1 /* 2 * Semihosting System HEAPINFO Test 3 * 4 * Copyright (c) 2021 Linaro Ltd 5 * 6 * SPDX-License-Identifier: GPL-2.0-or-later 7 */ 8 9 #include <stdint.h> 10 #include <stddef.h> 11 #include <minilib.h> 12 13 #define SYS_HEAPINFO 0x16 14 15 uintptr_t __semi_call(uintptr_t type, uintptr_t arg0) 16 { 17 register uintptr_t t asm("x0") = type; 18 register uintptr_t a0 asm("x1") = arg0; 19 asm("hlt 0xf000" 20 : "=r" (t) 21 : "r" (t), "r" (a0) 22 : "memory" ); 23 24 return t; 25 } 26 27 int main(int argc, char *argv[argc]) 28 { 29 struct { 30 void *heap_base; 31 void *heap_limit; 32 void *stack_base; 33 void *stack_limit; 34 } info = { }; 35 void *ptr_to_info = (void *) &info; 36 uint32_t *ptr_to_heap; 37 int i; 38 39 ml_printf("Semihosting Heap Info Test\n"); 40 41 __semi_call(SYS_HEAPINFO, (uintptr_t) &ptr_to_info); 42 43 if (info.heap_base == NULL || info.heap_limit == NULL) { 44 ml_printf("null heap: %p -> %p\n", info.heap_base, info.heap_limit); 45 return -1; 46 } 47 48 /* Error if heap base is above limit */ 49 if ((uintptr_t) info.heap_base >= (uintptr_t) info.heap_limit) { 50 ml_printf("heap base %p >= heap_limit %p\n", 51 info.heap_base, info.heap_limit); 52 return -2; 53 } 54 55 if (info.stack_base == NULL) { 56 ml_printf("null stack: %p -> %p\n", info.stack_base, info.stack_limit); 57 return -3; 58 } 59 60 /* 61 * boot.S put our stack somewhere inside the data segment of the 62 * ELF file, and we know that SYS_HEAPINFO won't pick a range 63 * that overlaps with part of a loaded ELF file. So the info 64 * struct (on the stack) should not be inside the reported heap. 65 */ 66 if (ptr_to_info > info.heap_base && ptr_to_info < info.heap_limit) { 67 ml_printf("info appears to be inside the heap: %p in %p:%p\n", 68 ptr_to_info, info.heap_base, info.heap_limit); 69 return -4; 70 } 71 72 ml_printf("heap: %p -> %p\n", info.heap_base, info.heap_limit); 73 ml_printf("stack: %p <- %p\n", info.stack_limit, info.stack_base); 74 75 /* finally can we read/write the heap */ 76 ptr_to_heap = info.heap_base; 77 for (i = 0; i < 512; i++) { 78 *ptr_to_heap++ = i; 79 } 80 ptr_to_heap = info.heap_base; 81 for (i = 0; i < 512; i++) { 82 uint32_t tmp = *ptr_to_heap; 83 if (tmp != i) { 84 ml_printf("unexpected value in heap: %d @ %p", tmp, ptr_to_heap); 85 return -5; 86 } 87 ptr_to_heap++; 88 } 89 ml_printf("r/w to heap up to %p\n", ptr_to_heap); 90 91 ml_printf("Passed HeapInfo checks\n"); 92 return 0; 93 } 94