1 /*
2  * linux-user semihosting checks
3  *
4  * Copyright (c) 2019, 2024
5  * Written by Alex Bennée <alex.bennee@linaro.org>
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  */
9 
10 #define SYS_WRITE0      0x04
11 #define SYS_HEAPINFO    0x16
12 #define SYS_REPORTEXC   0x18
13 
14 #include <stdint.h>
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include "semicall.h"
19 
20 int main(int argc, char *argv[argc])
21 {
22 #if UINTPTR_MAX == UINT32_MAX
23     uintptr_t exit_code = 0x20026;
24 #else
25     uintptr_t exit_block[2] = {0x20026, 0};
26     uintptr_t exit_code = (uintptr_t) &exit_block;
27 #endif
28     struct {
29         void *heap_base;
30         void *heap_limit;
31         void *stack_base;
32         void *stack_limit;
33     } info;
34     void *ptr_to_info = (void *) &info;
35 
36     __semi_call(SYS_WRITE0, (uintptr_t) "Checking HeapInfo\n");
37 
38     memset(&info, 0, sizeof(info));
39     __semi_call(SYS_HEAPINFO, (uintptr_t) &ptr_to_info);
40 
41     if (info.heap_base == NULL || info.heap_limit == NULL) {
42         printf("null heap: %p -> %p\n", info.heap_base, info.heap_limit);
43         exit(1);
44     }
45 
46     /* Error if heap base is above limit */
47     if ((uintptr_t) info.heap_base >= (uintptr_t) info.heap_limit) {
48         printf("heap base %p >= heap_limit %p\n",
49                info.heap_base, info.heap_limit);
50         exit(2);
51     }
52 
53     if (info.stack_base == NULL || info.stack_limit) {
54         printf("null stack: %p -> %p\n", info.stack_base, info.stack_limit);
55         exit(3);
56     }
57 
58     /* check our local variables are indeed inside the reported stack */
59     if (ptr_to_info > info.stack_base) {
60         printf("info appears to be above stack: %p > %p\n", ptr_to_info,
61                info.stack_base);
62         exit(4);
63     } else if (ptr_to_info < info.stack_limit) {
64         printf("info appears to be outside stack: %p < %p\n", ptr_to_info,
65                info.stack_limit);
66         exit(5);
67     }
68 
69     if (ptr_to_info > info.heap_base && ptr_to_info < info.heap_limit) {
70         printf("info appears to be inside the heap: %p in %p:%p\n",
71                ptr_to_info, info.heap_base, info.heap_limit);
72         exit(6);
73     }
74 
75     printf("heap: %p -> %p\n", info.heap_base, info.heap_limit);
76     printf("stack: %p -> %p\n", info.stack_base, info.stack_limit);
77 
78     __semi_call(SYS_WRITE0, (uintptr_t) "Passed HeapInfo checks");
79     __semi_call(SYS_REPORTEXC, exit_code);
80     /* if we get here we failed */
81     return -1;
82 }
83