|
54 | 54 | #define ENTRY_SIZE 2
|
55 | 55 |
|
56 | 56 | // Callback for malloc_iterate. Because this function is meant to be copied to
|
57 |
| -// a different process for execution, it must not make any function calls. It |
58 |
| -// could be written as asm, but simple C is more readable/maintainable and |
59 |
| -// should consistently compile to movable, position-independent code. |
| 57 | +// a different process for execution, it must not make any function calls to |
| 58 | +// ensure compiles to simple, position-independent code. It is implemented in C |
| 59 | +// for readability/maintainability. It is placed in its own code section to |
| 60 | +// simplify calculating its size. |
| 61 | +__attribute__((noinline, used, section(".text.remote"))) |
60 | 62 | static void heap_iterate_callback(unsigned long base, unsigned long size, void *arg) {
|
61 | 63 | volatile uint64_t *data = (uint64_t*)arg;
|
62 | 64 | while (data[NEXT_FREE_IDX] >= data[MAX_VALID_IDX]) {
|
63 | 65 | // SIGTRAP indicates the buffer is full and needs to be drained before more
|
64 | 66 | // entries can be written.
|
65 | 67 | __builtin_debugtrap();
|
| 68 | + |
| 69 | + // After the SIGTRAP, the signal handler advances the instruction pointer |
| 70 | + // (PC) to the next instruction. Inserting a nop instruction here ensures |
| 71 | + // the CPU has a clear, executable instruction to process, which avoids |
| 72 | + // potential speculative execution or pipeline issues that could arise if |
| 73 | + // the next instruction were a control transfer like a branch or jump. |
66 | 74 | __asm__ __volatile__("nop");
|
67 | 75 | }
|
68 | 76 | data[data[NEXT_FREE_IDX]++] = base;
|
69 | 77 | data[data[NEXT_FREE_IDX]++] = size;
|
70 |
| - __asm__ __volatile__(".align 8"); |
71 |
| - __asm__ __volatile__(".local heap_iterate_callback_end"); |
72 |
| - __asm__ __volatile__("heap_iterate_callback_end:"); |
73 | 78 | }
|
74 | 79 |
|
| 80 | +// Linker-populated symbol defined in section-text-remote.ld. Used to calculate |
| 81 | +// the size of the heap_iterate_callback function when copying it to a remote |
| 82 | +// process for execution. |
| 83 | +extern char _remote_code_section_end; |
| 84 | + |
75 | 85 | void* heap_iterate_callback_start() {
|
76 | 86 | return (void*)heap_iterate_callback;
|
77 | 87 | }
|
78 | 88 |
|
79 | 89 | size_t heap_iterate_callback_len() {
|
80 |
| - extern char heap_iterate_callback_end; |
81 |
| - return (uintptr_t)&heap_iterate_callback_end - (uintptr_t)heap_iterate_callback |
82 |
| - + sizeof(uintptr_t); |
| 90 | + return (uintptr_t)&_remote_code_section_end - (uintptr_t)heap_iterate_callback; |
83 | 91 | }
|
84 | 92 |
|
85 | 93 | bool heap_iterate_metadata_init(void* data, size_t len) {
|
|
0 commit comments