Skip to content

Commit

Permalink
bru h
Browse files Browse the repository at this point in the history
  • Loading branch information
paperclover committed Apr 13, 2024
1 parent cbd5103 commit 2d1c830
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 83 deletions.
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -738,7 +738,7 @@ if(NOT NO_CODEGEN)
OUTPUT ${BUN_IDENTIFIER_CACHE_OUT}
MAIN_DEPENDENCY "${BUN_SRC}/js_lexer/identifier_data.zig"
DEPENDS "${BUN_SRC}/js_lexer/identifier_cache.zig"
COMMAND ${ZIG_COMPILER} run "${BUN_SRC}/js_lexer/identifier_data.zig"
COMMAND ${ZIG_COMPILER} run "--zig-lib-dir" "${ZIG_LIB_DIR}" "${BUN_SRC}/js_lexer/identifier_data.zig"
VERBATIM
COMMENT "Building Identifier Cache"
)
Expand Down Expand Up @@ -1015,7 +1015,7 @@ endif()
# --- clang and linker flags ---
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
if(NOT WIN32)
target_compile_options(${bun} PUBLIC -g3 -O0 -gdwarf-4
target_compile_options(${bun} PUBLIC -O0 -g -g3 -ggdb -gdwarf-4
-Werror=return-type
-Werror=return-stack-address
-Werror=implicit-function-declaration
Expand Down
40 changes: 0 additions & 40 deletions src/bun.js/api/BunObject.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3325,11 +3325,6 @@ const UnsafeObject = struct {
const object = JSValue.createEmptyObject(globalThis, 3);
const fields = comptime .{
.gcAggressionLevel = &gcAggressionLevel,
.crashBySegfault = &crashBySegfault,
.crashByPanic = &crashByPanic,
.crashByUnreachable = &crashByUnreachable,
.crashBySafetyCheck = &crashBySafetyCheck,
.crashByCallGlobalError = &crashByCallGlobalError,
.arrayBufferToString = &arrayBufferToString,
.mimallocDump = &dump_mimalloc,
};
Expand Down Expand Up @@ -3361,41 +3356,6 @@ const UnsafeObject = struct {
return ret;
}

pub fn crashBySegfault(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue {
@setRuntimeSafety(false);
const ptr: [*]align(1) u64 = @ptrFromInt(0xDEADBEEF);
ptr[0] = 0xDEADBEEF;
std.mem.doNotOptimizeAway(&ptr);
return .undefined;
}

pub fn crashByPanic(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue {
// std.debug.panic("invoked crashByPanic() handler", .{});
bun.crash_handler.panicImpl("invoked crashByPanic() handler", null, null);
}

pub fn crashByUnreachable(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue {
@setRuntimeSafety(true);
unreachable;
}

pub fn crashBySafetyCheck(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue {
@setRuntimeSafety(true);
const Y = enum(u8) { a };
var a: u8 = 2;
const x: Y = @enumFromInt((&a).*);
_ = x;
return .undefined;
}

pub fn crashByCallGlobalError(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue {
bun.crash_handler.handleRootError(error.Test, null);
}

pub fn crashOutOfMemory(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue {
bun.outOfMemory();
}

pub fn arrayBufferToString(
globalThis: *JSC.JSGlobalObject,
callframe: *JSC.CallFrame,
Expand Down
100 changes: 73 additions & 27 deletions src/crash_handler.zig
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const debug = std.debug;

/// Set this to false if you want to disable all uses of this panic handler.
/// This is useful for testing as a crash in here will not 'panicked during a panic'.
pub const enabled = true;
pub const enable = true;

const report_base_url = "https://bun.report/";

Expand Down Expand Up @@ -194,27 +194,29 @@ pub fn crashHandler(
if (debug_trace) {
dumpStackTrace(trace.*);
} else {
writer.writeAll("Please report this panic as a GitHub issue using this link:\n") catch std.os.abort();
writer.writeAll("tracestr:\n") catch std.os.abort();

if (Output.enable_ansi_colors) {
writer.print(Output.prettyFmt("<cyan>", true), .{}) catch std.os.abort();
}
encodeTraceString(
.{
.trace = trace,
.reason = reason,
.action = .open_issue,
},
writer,
) catch std.os.abort();
}

encodeTraceString(
.{
.trace = trace,
.reason = reason,
.action = .open_issue,
},
writer,
) catch std.os.abort();

if (Output.enable_ansi_colors) {
writer.writeAll(Output.prettyFmt("<r>\n", true)) catch std.os.abort();
} else {
writer.writeAll("\n") catch std.os.abort();
}

writer.print("\nSearch GitHub issues https://bun.sh/issues or ask for #help in https://bun.sh/discord\n\n", .{}) catch std.os.abort();

Output.flush();
}

Expand All @@ -234,7 +236,7 @@ pub fn crashHandler(
});
Output.flush();

// It is important to be aware that this function *can* panic.
comptime std.debug.assert(void == @TypeOf(bun.reloadProcess(bun.default_allocator, false, true)));
bun.reloadProcess(bun.default_allocator, false, true);
}
},
Expand All @@ -251,8 +253,6 @@ pub fn crashHandler(
const stderr = std.io.getStdErr().writer();
stderr.print("\npanic: {s}\n", .{reason}) catch std.os.abort();
stderr.print("panicked during a panic. Aborting.\n", .{}) catch std.os.abort();

std.debug.dumpCurrentStackTrace(@returnAddress());
},
3 => {
// Panicked while printing "Panicked during a panic."
Expand Down Expand Up @@ -541,7 +541,7 @@ fn panicBuiltin(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace, b
std.debug.panicImpl(error_return_trace, begin_addr, msg);
}

pub const panic = if (enabled) panicImpl else panicBuiltin;
pub const panic = if (enable) panicImpl else panicBuiltin;

const arch_display_string = if (bun.Environment.isAarch64)
if (bun.Environment.isMac) "Silicon" else "arm64"
Expand Down Expand Up @@ -592,7 +592,7 @@ pub fn updatePosixSegfaultHandler(act: ?*const std.os.Sigaction) !void {
var windows_segfault_handle: ?windows.HANDLE = null;

pub fn init() void {
if (!enabled) return;
if (!enable) return;
switch (bun.Environment.os) {
.windows => {
windows_segfault_handle = windows.kernel32.AddVectoredExceptionHandler(0, handleSegfaultWindows);
Expand Down Expand Up @@ -869,8 +869,10 @@ const StackLine = union(enum) {
const seg_start = info.dlpi_addr +% phdr.p_vaddr;
const seg_end = seg_start + phdr.p_memsz;
if (context.address >= seg_start and context.address < seg_end) {
const name = bun.sliceTo(info.dlpi_name, 0) orelse "";
std.debug.print("\nhi {d}, {s}, base = 0x{x}, ptr = 0x{x}", .{ context.i, name, info.dlpi_addr, context.address });
// const name = bun.sliceTo(info.dlpi_name, 0) orelse "";
{
@compileError("TODO");
}
return error.Found;
}
}
Expand Down Expand Up @@ -901,8 +903,12 @@ const StackLine = union(enum) {

pub fn format(self: StackLine, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
switch (self) {
.unknown => try writer.print("unknown address", .{}),
.known => |known| try writer.print("0x{x} @ {s}", .{ known.address, known.object orelse "bun" }),
.unknown => try writer.print("???", .{}),
.known => |known| try writer.print("0x{x}{s}{s}", .{
if (bun.Environment.isMac) @as(u64, known.address) + 0x100000000 else known.address,
if (known.object != null) " @ " else "",
known.object orelse "bun",
}),
.javascript => try writer.print("javascript address", .{}),
}
}
Expand Down Expand Up @@ -1128,12 +1134,52 @@ pub fn dumpStackTrace(trace: std.builtin.StackTrace) void {
stdDumpStackTrace(trace);
}

pub fn jsGetMachOImageZeroOffset(_: *bun.JSC.JSGlobalObject, _: *bun.JSC.CallFrame) bun.JSC.JSValue {
if (!bun.Environment.isMac) return .undefined;
pub const js_bindings = struct {
const JSC = bun.JSC;
const JSValue = JSC.JSValue;

pub fn generate(global: *JSC.JSGlobalObject) JSC.JSValue {
const obj = JSC.JSValue.createEmptyObject(global, 3);
inline for (.{
.{ "getMachOImageZeroOffset", jsGetMachOImageZeroOffset },
.{ "segfault", jsSegfault },
.{ "panic", jsPanic },
.{ "rootError", jsRootError },
.{ "outOfMemory", jsOutOfMemory },
}) |tuple| {
const name = JSC.ZigString.static(tuple[0]);
obj.put(global, name, JSC.createCallback(global, name, 1, tuple[1]));
}
return obj;
}

const header = std.c._dyld_get_image_header(0) orelse return .undefined;
const base_address = @intFromPtr(header);
const vmaddr_slide = std.c._dyld_get_image_vmaddr_slide(0);
pub fn jsGetMachOImageZeroOffset(_: *bun.JSC.JSGlobalObject, _: *bun.JSC.CallFrame) callconv(.C) bun.JSC.JSValue {
if (!bun.Environment.isMac) return .undefined;

return bun.JSC.JSValue.jsNumber(base_address - vmaddr_slide);
}
const header = std.c._dyld_get_image_header(0) orelse return .undefined;
const base_address = @intFromPtr(header);
const vmaddr_slide = std.c._dyld_get_image_vmaddr_slide(0);

return bun.JSC.JSValue.jsNumber(base_address - vmaddr_slide);
}

pub fn jsSegfault(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue {
@setRuntimeSafety(false);
const ptr: [*]align(1) u64 = @ptrFromInt(0xDEADBEEF);
ptr[0] = 0xDEADBEEF;
std.mem.doNotOptimizeAway(&ptr);
return .undefined;
}

pub fn jsPanic(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue {
bun.crash_handler.panicImpl("invoked crashByPanic() handler", null, null);
}

pub fn jsRootError(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue {
bun.crash_handler.handleRootError(error.Test, null);
}

pub fn jsOutOfMemory(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue {
bun.outOfMemory();
}
};
12 changes: 7 additions & 5 deletions src/js/internal-for-testing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ export const shellInternals = {
parse: $newZigFunction("shell.zig", "TestingAPIs.shellParse", 1),
};

export const getMachOImageZeroOffset = $newZigFunction(
"crash_handler.zig",
"jsGetMachOImageZeroOffset",
0,
) as () => number;
export const crash_handler = $zig("crash_handler.zig", "js_bindings.generate") as {
getMachOImageZeroOffset: () => number;
segfault: () => void;
panic: () => void;
rootError: () => void;
outOfMemory: () => void;
};
2 changes: 1 addition & 1 deletion src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const Environment = bun.Environment;

pub const panic = bun.crash_handler.panic;
pub const std_options = struct {
pub const enable_segfault_handler = !bun.crash_handler.enabled;
pub const enable_segfault_handler = !bun.crash_handler.enable;
};

pub const io_mode = .blocking;
Expand Down
8 changes: 0 additions & 8 deletions test/cli/crash-handler.test.ts

This file was deleted.

8 changes: 8 additions & 0 deletions test/cli/run/fixture-crash.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { crash_handler } from "bun:internal-for-testing";

const approach = process.argv[2];
if (approach in crash_handler) {
crash_handler[approach]();
} else {
console.error("usage: bun fixture-crash.js <segfault|panic|rootError|outOfMemory>");
}
19 changes: 19 additions & 0 deletions test/cli/run/run-crash-handler.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { crash_handler } from "bun:internal-for-testing";
import { test, expect } from "bun:test";
import { bunExe, bunEnv } from "harness";
import path from "path";
const { getMachOImageZeroOffset } = crash_handler;

test.if(process.platform === "darwin")("macOS has the assumed image offset", () => {
// If this fails, then https://bun.report will be incorrect and the stack
// trace remappings will stop working.
expect(getMachOImageZeroOffset()).toBe(0x100000000);
});

test("a panic dumps a trace string", async () => {
const result = Bun.spawnSync([bunExe(), path.join(import.meta.dir, "fixture-crash.js"), "panic"], {
env: {
...bunEnv,
},
});
});

0 comments on commit 2d1c830

Please sign in to comment.