infix
A JIT-Powered FFI Library for C
Loading...
Searching...
No Matches
utility.c
Go to the documentation of this file.
1
28// This file is only compiled if debugging is enabled.
29#if defined(INFIX_DEBUG_ENABLED) && INFIX_DEBUG_ENABLED
30// Use the double-tap test harness's `note` macro for debug printing if available.
31// This integrates the debug output seamlessly into the TAP test logs.
32#if defined(DBLTAP_ENABLE) && defined(DBLTAP_IMPLEMENTATION)
33#include "common/double_tap.h"
34#else
35// If not building as part of a test, fall back to a standard printf implementation.
36#include <stdio.h>
37#ifndef note
38#define note(...) \
39 do { \
40 printf("# " __VA_ARGS__); \
41 printf("\n"); \
42 } while (0)
43#endif
44#endif // DBLTAP_ENABLE
45#include "common/utility.h"
46#include <inttypes.h>
62void infix_dump_hex(const void * data, size_t size, const char * title) {
63 const uint8_t * byte = (const uint8_t *)data;
64 char line_buf[256];
65 char * buf_ptr;
66 size_t remaining_len;
67 int written;
68 note("%s (size: %llu bytes at %p)", title, (unsigned long long)size, data);
69 for (size_t i = 0; i < size; i += 16) {
70 buf_ptr = line_buf;
71 remaining_len = sizeof(line_buf);
72 // Print the address offset for the current line.
73 written = snprintf(buf_ptr, remaining_len, "0x%04llx: ", (unsigned long long)i);
74 if (written < 0 || (size_t)written >= remaining_len)
75 goto print_line;
76 buf_ptr += written;
77 remaining_len -= written;
78 // Print the hexadecimal representation of the bytes.
79 for (size_t j = 0; j < 16; ++j) {
80 if (i + j < size)
81 written = snprintf(buf_ptr, remaining_len, "%02x ", byte[i + j]);
82 else
83 written = snprintf(buf_ptr, remaining_len, " "); // Pad if at the end of the data.
84 if (written < 0 || (size_t)written >= remaining_len)
85 goto print_line;
86 buf_ptr += written;
87 remaining_len -= written;
88 if (j == 7) { // Add an extra space in the middle for readability.
89 written = snprintf(buf_ptr, remaining_len, " ");
90 if (written < 0 || (size_t)written >= remaining_len)
91 goto print_line;
92 buf_ptr += written;
93 remaining_len -= written;
94 }
95 }
96 written = snprintf(buf_ptr, remaining_len, "| ");
97 if (written < 0 || (size_t)written >= remaining_len)
98 goto print_line;
99 buf_ptr += written;
100 remaining_len -= written;
101 // Print the ASCII representation of the bytes.
102 for (size_t j = 0; j < 16; ++j) {
103 if (i + j < size) {
104 if (byte[i + j] >= 32 && byte[i + j] <= 126) // Printable ASCII characters
105 written = snprintf(buf_ptr, remaining_len, "%c", byte[i + j]);
106 else
107 written = snprintf(buf_ptr, remaining_len, "."); // Non-printable characters
108 if (written < 0 || (size_t)written >= remaining_len)
109 goto print_line;
110 buf_ptr += written;
111 remaining_len -= written;
112 }
113 }
114print_line:
115 note(" %s", line_buf);
116 }
117 note("End of %s", title);
118}
129void infix_dump_state(const char * file, int line) {
130#if defined(__x86_64__) || defined(_M_X64)
131 printf("# Dumping x64 Register State at %s:%d\n", file, line);
132 volatile unsigned long long stack_dump[16];
133 register long long rsp __asm__("rsp");
134
135 __asm__ __volatile__(
136 "movq %%rax, %%r15\n\t"
137 "movq %%rbx, %%r14\n\t"
138 "movq %%rcx, %%r13\n\t"
139 "movq %%rdx, %%r12\n\t"
140 "movq %%rsi, %%r11\n\t"
141 "movq %%rdi, %%r10\n\t"
142 "movq %%rbp, %%r9\n\t"
143 :
144 :
145 : "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15");
146 register long long rax __asm__("r15");
147 register long long rbx __asm__("r14");
148 register long long rcx __asm__("r13");
149 register long long rdx __asm__("r12");
150 register long long rsi __asm__("r11");
151 register long long rdi __asm__("r10");
152 register long long rbp __asm__("r9");
153
154 for (int i = 0; i < 16; ++i)
155 stack_dump[i] = ((unsigned long long *)rsp)[i];
156
157 printf("# RAX: %016llx RBX: %016llx\n", rax, rbx);
158 printf("# RCX: %016llx RDX: %016llx\n", rcx, rdx);
159 printf("# RSI: %016llx RDI: %016llx\n", rsi, rdi);
160 printf("# RBP: %016llx RSP: %016llx\n", rbp, rsp);
161 fflush(stdout);
162
163 printf("# Stack Dump (128 bytes) ---\n");
164 for (int i = 0; i < 16; i += 2)
165 printf("%016llx: %016llx %016llx\n", rsp + i * 8, stack_dump[i], stack_dump[i + 1]);
166#elif defined(__aarch64__) || defined(_M_ARM64)
167 printf("# Dumping AArch64 Register State at %s:%d\n", file, line);
168 volatile unsigned long long stack_dump[16];
169 register long long sp __asm__("sp");
170
171 long long x0, x1, x2, x3, x4, x5, x6, x7;
172 __asm__ __volatile__(
173 "mov %0, x0\n\t"
174 "mov %1, x1\n\t"
175 "mov %2, x2\n\t"
176 "mov %3, x3\n\t"
177 "mov %4, x4\n\t"
178 "mov %5, x5\n\t"
179 "mov %6, x6\n\t"
180 "mov %7, x7\n\t"
181 : "=r"(x0), "=r"(x1), "=r"(x2), "=r"(x3), "=r"(x4), "=r"(x5), "=r"(x6), "=r"(x7));
182 printf("# x0: %016llx x1: %016llx\n", x0, x1);
183 printf("# x2: %016llx x3: %016llx\n", x2, x3);
184 printf("# x4: %016llx x5: %016llx\n", x4, x5);
185 printf("# x6: %016llx x7: %016llx\n", x6, x7);
186
187 printf("# SP: %016llx\n", sp);
188
189 for (int i = 0; i < 16; ++i)
190 stack_dump[i] = ((unsigned long long *)sp)[i];
191
192 printf("# Stack Dump (128 bytes)\n");
193 fflush(stdout);
194
195 for (int i = 0; i < 16; i += 2)
196 printf("# %016llx: %016llx %016llx\n", sp + i * 8, stack_dump[i], stack_dump[i + 1]);
197#else
198 printf("# infix_dump_state() not implemented for this architecture\n");
199#endif
200 fflush(stdout);
201}
202#endif // INFIX_DEBUG_ENABLED
A lightweight, single-header TAP (Test Anything Protocol) library.
#define note(...)
Definition double_tap.h:210
A header for conditionally compiled debugging utilities.
static void infix_dump_state(c23_maybe_unused const char *file, c23_maybe_unused int line)
Definition utility.h:149
static void infix_dump_hex(c23_maybe_unused const void *data, c23_maybe_unused size_t size, c23_maybe_unused const char *title)
Definition utility.h:131