Skip to content

Commit 588162d

Browse files
committed
Use clang-format, apply suggestions, credit author, add rule for js build
1 parent 87fcef5 commit 588162d

File tree

3 files changed

+119
-127
lines changed

3 files changed

+119
-127
lines changed

src/alcotest-engine/dune

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
%{target}
1616
"let get ?__FUNCTION__ () =\n ignore __FUNCTION__;\n None\n")))
1717

18-
1918
(rule
2019
(target c_library_flags.sexp)
2120
(enabled_if (= %{os_type} Win32))
@@ -24,7 +23,7 @@
2423

2524
(rule
2625
(target c_library_flags.sexp)
27-
(enabled_if (<> %{os_type} Win32))
26+
(enabled_if (or (<> %{os_type} Win32) (= %{architecture} "js")))
2827
(action
2928
(write-file %{target} "()")))
3029

src/alcotest-engine/stack_error_reporter.c

Lines changed: 117 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,20 @@ typedef struct {
2121
size_t offset;
2222
} StackTraceBuffer;
2323

24-
bool finit_stack_trace_buffer(StackTraceBuffer* pStackTraceBuffer, size_t size)
25-
{
24+
static bool finit_stack_trace_buffer(StackTraceBuffer *pStackTraceBuffer,
25+
size_t size) {
2626
char *error_buffer = (char *)malloc(size);
2727
if (error_buffer == NULL) {
2828
return false;
2929
}
3030
pStackTraceBuffer->capacity = size;
3131
pStackTraceBuffer->offset = 0;
3232
pStackTraceBuffer->buffer = error_buffer;
33-
pStackTraceBuffer->buffer[0] = '0';
33+
pStackTraceBuffer->buffer[0] = '\0';
3434
return true;
3535
}
3636

37-
void append_to_buffer(StackTraceBuffer *sb, const char *format, ...) {
37+
static void append_to_buffer(StackTraceBuffer *sb, const char *format, ...) {
3838
if (sb->offset >= sb->capacity)
3939
return; // Buffer full
4040

@@ -59,156 +59,151 @@ void append_to_buffer(StackTraceBuffer *sb, const char *format, ...) {
5959

6060
static const char *CAML_ERROR_ID = "segfault exception";
6161

62-
#if defined(_WIN32) || defined(_WIN64)
62+
#if defined(_WIN32)
6363
#define PLATFORM_WINDOWS
64+
#include <dbghelp.h>
6465
#include <excpt.h>
6566
#include <windows.h>
66-
#include <dbghelp.h>
6767

68-
void create_stacktrace(StackTraceBuffer* pStackTraceBuffer)
69-
{
70-
HANDLE process = GetCurrentProcess();
71-
HANDLE thread = GetCurrentThread();
72-
CONTEXT context;
73-
STACKFRAME64 stack;
74-
DWORD machine_type;
75-
76-
RtlCaptureContext(&context);
77-
78-
ZeroMemory(&stack, sizeof(STACKFRAME64));
79-
80-
#ifdef _M_IX86
81-
machine_type = IMAGE_FILE_MACHINE_I386;
82-
stack.AddrPC.Offset = context.Eip;
83-
stack.AddrFrame.Offset = context.Ebp;
84-
stack.AddrStack.Offset = context.Esp;
85-
#elif _M_X64
86-
machine_type = IMAGE_FILE_MACHINE_AMD64;
87-
stack.AddrPC.Offset = context.Rip;
88-
stack.AddrFrame.Offset = context.Rsp;
89-
stack.AddrStack.Offset = context.Rsp;
90-
#elif _M_ARM64
91-
machine_type = IMAGE_FILE_MACHINE_ARM64;
92-
stack.AddrPC.Offset = context.Pc;
93-
stack.AddrFrame.Offset = context.Fp;
94-
stack.AddrStack.Offset = context.Sp;
68+
// Stacktrace collection inspired by
69+
// https://smhk.net/note/2025/03/c-stack-trace-in-windows/
70+
static void create_stacktrace(StackTraceBuffer *pStackTraceBuffer) {
71+
HANDLE process = GetCurrentProcess();
72+
HANDLE thread = GetCurrentThread();
73+
CONTEXT context;
74+
STACKFRAME64 stack;
75+
DWORD machine_type;
76+
77+
RtlCaptureContext(&context);
78+
79+
ZeroMemory(&stack, sizeof(STACKFRAME64));
80+
81+
#if defined(_M_IX86) || defined(__i386__)
82+
machine_type = IMAGE_FILE_MACHINE_I386;
83+
stack.AddrPC.Offset = context.Eip;
84+
stack.AddrFrame.Offset = context.Ebp;
85+
stack.AddrStack.Offset = context.Esp;
86+
#elif defined(_M_X64) || defined(__x86_64__)
87+
machine_type = IMAGE_FILE_MACHINE_AMD64;
88+
stack.AddrPC.Offset = context.Rip;
89+
stack.AddrFrame.Offset = context.Rsp;
90+
stack.AddrStack.Offset = context.Rsp;
91+
#elif defined(_M_ARM64) || defined(__aarch64__)
92+
machine_type = IMAGE_FILE_MACHINE_ARM64;
93+
stack.AddrPC.Offset = context.Pc;
94+
stack.AddrFrame.Offset = context.Fp;
95+
stack.AddrStack.Offset = context.Sp;
9596
#else
9697
#error "Unsupported platform"
9798
#endif
9899

99-
stack.AddrPC.Mode = AddrModeFlat;
100-
stack.AddrFrame.Mode = AddrModeFlat;
101-
stack.AddrStack.Mode = AddrModeFlat;
102-
103-
SymInitialize(process, NULL, TRUE);
104-
SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME);
105-
106-
append_to_buffer(pStackTraceBuffer, "Stack trace:\n");
107-
append_to_buffer(pStackTraceBuffer, " %-40s %-18s %s\n", "Function", "Address", "Line");
108-
append_to_buffer(pStackTraceBuffer, " %-40s %-18s %s\n", "--------", "-------", "----");
109-
110-
while (StackWalk64(
111-
machine_type,
112-
process,
113-
thread,
114-
&stack,
115-
&context,
116-
NULL,
117-
SymFunctionTableAccess64,
118-
SymGetModuleBase64,
119-
NULL)) {
120-
if (stack.AddrPC.Offset == 0)
121-
break;
122-
123-
DWORD64 symbol_addr = stack.AddrPC.Offset;
124-
DWORD64 displacement = 0;
125-
char symbol_buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)] = {0};
126-
SYMBOL_INFO *symbol = (SYMBOL_INFO *)symbol_buffer;
127-
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
128-
symbol->MaxNameLen = MAX_SYM_NAME;
129-
130-
// Get line information
131-
IMAGEHLP_LINE64 line = {0};
132-
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
133-
DWORD line_displacement = 0;
134-
BOOL has_line = SymGetLineFromAddr64(process, symbol_addr, &line_displacement, &line);
135-
136-
char function_name[MAX_SYM_NAME] = "Unknown";
137-
if (SymFromAddr(process, symbol_addr, &displacement, symbol)) {
138-
strncpy(function_name, symbol->Name, MAX_SYM_NAME - 1);
139-
function_name[MAX_SYM_NAME - 1] = '\0'; // Ensure null termination
140-
}
141-
// Format line information
142-
char line_info[256] = "Unknown";
143-
if (has_line) {
144-
snprintf(line_info, sizeof(line_info), "%s:%lu", line.FileName, line.LineNumber);
145-
}
146-
147-
// Print with better alignment using format specifiers
148-
append_to_buffer(pStackTraceBuffer,
149-
" %-40.40s 0x%016llX %s\n",
150-
function_name,
151-
symbol_addr,
152-
line_info);
153-
append_to_buffer(pStackTraceBuffer, "\0");
154-
100+
stack.AddrPC.Mode = AddrModeFlat;
101+
stack.AddrFrame.Mode = AddrModeFlat;
102+
stack.AddrStack.Mode = AddrModeFlat;
103+
104+
SymInitialize(process, NULL, TRUE);
105+
SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME);
106+
107+
append_to_buffer(pStackTraceBuffer, "Stack trace:\n");
108+
append_to_buffer(pStackTraceBuffer, " %-40s %-18s %s\n", "Function",
109+
"Address", "Line");
110+
append_to_buffer(pStackTraceBuffer, " %-40s %-18s %s\n", "--------",
111+
"-------", "----");
112+
113+
while (StackWalk64(machine_type, process, thread, &stack, &context, NULL,
114+
SymFunctionTableAccess64, SymGetModuleBase64, NULL)) {
115+
if (stack.AddrPC.Offset == 0)
116+
break;
117+
118+
DWORD64 symbol_addr = stack.AddrPC.Offset;
119+
DWORD64 displacement = 0;
120+
_Alignas(SYMBOL_INFO *)
121+
symbol_buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)] = {0};
122+
SYMBOL_INFO *symbol = (SYMBOL_INFO *)symbol_buffer;
123+
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
124+
symbol->MaxNameLen = MAX_SYM_NAME;
125+
126+
// Get line information
127+
IMAGEHLP_LINE64 line = {0};
128+
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
129+
DWORD line_displacement = 0;
130+
BOOL has_line =
131+
SymGetLineFromAddr64(process, symbol_addr, &line_displacement, &line);
132+
133+
char function_name[MAX_SYM_NAME] = "Unknown";
134+
if (SymFromAddr(process, symbol_addr, &displacement, symbol)) {
135+
strncpy(function_name, symbol->Name, MAX_SYM_NAME - 1);
136+
function_name[MAX_SYM_NAME - 1] = '\0'; // Ensure null termination
137+
}
138+
// Format line information
139+
char line_info[256] = "Unknown";
140+
if (has_line) {
141+
snprintf(line_info, sizeof(line_info), "%s:%lu", line.FileName,
142+
line.LineNumber);
155143
}
156144

157-
SymCleanup(process);
158-
}
145+
// Print with better alignment using format specifiers
146+
append_to_buffer(pStackTraceBuffer, " %-40.40s 0x%016llX %s\n",
147+
function_name, symbol_addr, line_info);
148+
append_to_buffer(pStackTraceBuffer, "\0");
149+
}
159150

151+
SymCleanup(process);
152+
}
160153

161154
LONG WINAPI windows_exception_handler(PEXCEPTION_POINTERS pExceptionInfo) {
162-
const DWORD exceptionCode = pExceptionInfo->ExceptionRecord->ExceptionCode;
163-
switch(exceptionCode) {
164-
case EXCEPTION_ACCESS_VIOLATION:
165-
{
166-
void* faulting_address = (void*)pExceptionInfo->ExceptionRecord->ExceptionInformation[1];
167-
StackTraceBuffer stack_trace_buffer;
168-
if(!finit_stack_trace_buffer(&stack_trace_buffer, buffer_size))
169-
{
170-
caml_failwith("Can't create stack trace buffer");
171-
return EXCEPTION_CONTINUE_SEARCH;
172-
}
173-
create_stacktrace(&stack_trace_buffer);
174-
175-
caml_raise_with_string(*caml_named_value(CAML_ERROR_ID), stack_trace_buffer.buffer);
176-
free(stack_trace_buffer.buffer);
177-
ExitProcess(STATUS_ACCESS_VIOLATION);
178-
}
179-
default: break;
155+
const DWORD exceptionCode = pExceptionInfo->ExceptionRecord->ExceptionCode;
156+
switch (exceptionCode) {
157+
case EXCEPTION_ACCESS_VIOLATION: {
158+
void *faulting_address =
159+
(void *)pExceptionInfo->ExceptionRecord->ExceptionInformation[1];
160+
StackTraceBuffer stack_trace_buffer;
161+
if (!finit_stack_trace_buffer(&stack_trace_buffer, buffer_size)) {
162+
caml_failwith("Can't create stack trace buffer");
163+
return EXCEPTION_CONTINUE_SEARCH;
180164
}
181-
return EXCEPTION_CONTINUE_SEARCH;
165+
create_stacktrace(&stack_trace_buffer);
166+
167+
caml_raise_with_string(*caml_named_value(CAML_ERROR_ID),
168+
stack_trace_buffer.buffer);
169+
free(stack_trace_buffer.buffer);
170+
ExitProcess(STATUS_ACCESS_VIOLATION);
171+
}
172+
default:
173+
break;
174+
}
175+
return EXCEPTION_CONTINUE_SEARCH;
182176
}
183177
#else
184178
#define PLATFORM_UNIX
185-
#include <signal.h>
186179
#include <execinfo.h>
180+
#include <signal.h>
187181
#include <stdlib.h>
188182
#include <unistd.h>
189183

190-
void unix_signal_handler(int sig, siginfo_t *si, void *unused) {
184+
#define STACK_TRACE_LENGTH 20
185+
186+
static void unix_signal_handler(int sig, siginfo_t *si, void *unused) {
191187

192188
StackTraceBuffer stack_trace_buffer;
193189
if (!finit_stack_trace_buffer(&stack_trace_buffer, buffer_size)) {
194190
caml_failwith("Can't create stack trace buffer");
195191
return;
196192
}
197193

198-
void* trace[20];
199-
size_t trace_size = backtrace(trace, 20);
194+
void *trace[STACK_TRACE_LENGTH];
195+
size_t trace_size = backtrace(trace, STACK_TRACE_LENGTH);
200196

201-
if(trace_size == 0)
202-
{
197+
if (trace_size == 0) {
203198
caml_failwith("Couldn't get backtrace");
204199
return;
205200
}
206201

207-
append_to_buffer(&stack_trace_buffer, "Caught Violation access, here's stack trace:\n");
208-
209-
char** pSymbols = backtrace_symbols(trace, trace_size);
210-
for(int i = 0; i < trace_size; ++i)
211-
{
202+
append_to_buffer(&stack_trace_buffer,
203+
"Caught Violation access, here's stack trace:\n");
204+
205+
char **pSymbols = backtrace_symbols(trace, trace_size);
206+
for (int i = 0; i < trace_size; ++i) {
212207
append_to_buffer(&stack_trace_buffer, "%s\n", pSymbols[i]);
213208
}
214209
free(pSymbols);
@@ -219,9 +214,7 @@ void unix_signal_handler(int sig, siginfo_t *si, void *unused) {
219214
}
220215
#endif
221216

222-
223-
CAMLprim value caml_setup_stub_exception_handler()
224-
{
217+
CAMLprim value caml_setup_stub_exception_handler(void) {
225218
CAMLparam0();
226219
#ifdef PLATFORM_WINDOWS
227220
AddVectoredExceptionHandler(1, windows_exception_handler);

test/e2e/alcotest/stubs/nullexceptionstub.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#include <caml/misc.h>
99
#include <caml/mlvalues.h>
1010

11-
value caml_segfault_call()
11+
value caml_segfault_call(void)
1212
{
1313
CAMLparam0();
1414
int* someVal = NULL;

0 commit comments

Comments
 (0)