| author | |
| committer | |
| log | 1a2c47a504c7f549328689201305514831de7513 |
| tree | bd19a368134a85388b8b23f1f94513a92aa03cd6 |
| parent | ec735f62e461952c47f997ab6199cd89abbb20c2 |
| parent | 2b8a05b8d9125b7465f0d3bd44e90d82a06dd5fa |
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/32138
Reviewed-by: Andrew Kelley <andrew@ziglang.org>5 files changed, 128 insertions(+), 15 deletions(-)
lib/std/debug/SelfInfo/MachO.zig+42-15| ... | ... | @@ -93,12 +93,28 @@ pub fn getSymbols( |
| 93 | 93 | pub fn getModuleName(si: *SelfInfo, io: Io, address: usize) Error![]const u8 { |
| 94 | 94 | _ = si; |
| 95 | 95 | _ = io; |
| 96 | // This function is marked as deprecated; however, it is significantly more | |
| 97 | // performant than `dladdr` (since the latter also does a very slow symbol | |
| 98 | // lookup), so let's use it since it's still available. | |
| 99 | return std.mem.span(std.c.dyld_image_path_containing_address( | |
| 100 | @ptrFromInt(address), | |
| 101 | ) orelse return error.MissingDebugInfo); | |
| 96 | return getModuleNameInner(address) orelse return error.MissingDebugInfo; | |
| 97 | } | |
| 98 | fn getModuleNameInner(address: usize) ?[]const u8 { | |
| 99 | switch (builtin.target.os.tag) { | |
| 100 | .macos => { | |
| 101 | // This function is marked as deprecated; however, it is significantly more performant | |
| 102 | // than `dladdr` (since the latter also does a very slow symbol lookup), so let's just | |
| 103 | // use it for the better performance since it's still available. | |
| 104 | return std.mem.span(std.c.dyld_image_path_containing_address( | |
| 105 | @ptrFromInt(address), | |
| 106 | ) orelse return null); | |
| 107 | }, | |
| 108 | else => { | |
| 109 | // On other Darwin systems, the function used above is entirely unavailable, so we have | |
| 110 | // no choice but to use the slow `dladdr`. | |
| 111 | var info: std.c.dl_info = undefined; | |
| 112 | if (std.c.dladdr(@ptrFromInt(address), &info) == 0) { | |
| 113 | return null; | |
| 114 | } | |
| 115 | return std.mem.span(info.fname); | |
| 116 | }, | |
| 117 | } | |
| 102 | 118 | } |
| 103 | 119 | pub fn getModuleSlide(si: *SelfInfo, io: Io, address: usize) Error!usize { |
| 104 | 120 | const gpa = std.debug.getDebugInfoAllocator(); |
| ... | ... | @@ -446,12 +462,25 @@ fn unwindFrameInner(si: *SelfInfo, io: Io, context: *UnwindContext) !usize { |
| 446 | 462 | |
| 447 | 463 | /// Acquires the mutex on success. |
| 448 | 464 | fn findModule(si: *SelfInfo, gpa: Allocator, io: Io, address: usize) Error!*Module { |
| 449 | // This function is marked as deprecated; however, it is significantly more | |
| 450 | // performant than `dladdr` (since the latter also does a very slow symbol | |
| 451 | // lookup), so let's use it since it's still available. | |
| 452 | const text_base = std.c._dyld_get_image_header_containing_address( | |
| 453 | @ptrFromInt(address), | |
| 454 | ) orelse return error.MissingDebugInfo; | |
| 465 | const text_base: *anyopaque = switch (builtin.target.os.tag) { | |
| 466 | .macos => base: { | |
| 467 | // This function is marked as deprecated; however, it is significantly more performant | |
| 468 | // than `dladdr` (since the latter also does a very slow symbol lookup), so let's just | |
| 469 | // use it for the better performance since it's still available. | |
| 470 | break :base std.c._dyld_get_image_header_containing_address( | |
| 471 | @ptrFromInt(address), | |
| 472 | ) orelse return error.MissingDebugInfo; | |
| 473 | }, | |
| 474 | else => base: { | |
| 475 | // On other Darwin systems, the function used above is entirely unavailable, so we have | |
| 476 | // no choice but to use the slow `dladdr`. | |
| 477 | var info: std.c.dl_info = undefined; | |
| 478 | if (std.c.dladdr(@ptrFromInt(address), &info) == 0) { | |
| 479 | return error.MissingDebugInfo; | |
| 480 | } | |
| 481 | break :base info.fbase; | |
| 482 | }, | |
| 483 | }; | |
| 455 | 484 | try si.mutex.lock(io); |
| 456 | 485 | errdefer si.mutex.unlock(io); |
| 457 | 486 | const gop = try si.modules.getOrPutAdapted(gpa, @intFromPtr(text_base), Module.Adapter{}); |
| ... | ... | @@ -563,9 +592,7 @@ const Module = struct { |
| 563 | 592 | |
| 564 | 593 | fn getFile(module: *Module, gpa: Allocator, io: Io) Error!*MachOFile { |
| 565 | 594 | if (module.file == null) { |
| 566 | const path = std.mem.span( | |
| 567 | std.c.dyld_image_path_containing_address(@ptrFromInt(module.text_base)).?, | |
| 568 | ); | |
| 595 | const path = getModuleNameInner(module.text_base).?; | |
| 569 | 596 | module.file = MachOFile.load(gpa, io, path, builtin.cpu.arch) catch |err| switch (err) { |
| 570 | 597 | error.InvalidMachO, error.InvalidDwarf => error.InvalidDebugInfo, |
| 571 | 598 | error.MissingDebugInfo, error.OutOfMemory, error.UnsupportedDebugInfo, error.ReadFailed => |e| e, |
test/standalone/build.zig.zon+3| ... | ... | @@ -153,6 +153,9 @@ |
| 153 | 153 | .compiler_rt_panic = .{ |
| 154 | 154 | .path = "compiler_rt_panic", |
| 155 | 155 | }, |
| 156 | .ios = .{ | |
| 157 | .path = "ios", | |
| 158 | }, | |
| 156 | 159 | .depend_on_main_mod = .{ |
| 157 | 160 | .path = "depend_on_main_mod", |
| 158 | 161 | }, |
test/standalone/ios/build.zig created+41| ... | ... | @@ -0,0 +1,41 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | pub const requires_symlinks = true; | |
| 4 | pub const requires_ios_sdk = true; | |
| 5 | ||
| 6 | pub fn build(b: *std.Build) void { | |
| 7 | const test_step = b.step("test", "Test it"); | |
| 8 | b.default_step = test_step; | |
| 9 | ||
| 10 | const target = b.resolveTargetQuery(.{ | |
| 11 | .cpu_arch = .aarch64, | |
| 12 | .os_tag = .ios, | |
| 13 | }); | |
| 14 | ||
| 15 | const exe = b.addExecutable(.{ | |
| 16 | .name = "main", | |
| 17 | .root_module = b.createModule(.{ | |
| 18 | .root_source_file = b.path("panic.zig"), | |
| 19 | .optimize = .Debug, | |
| 20 | .target = target, | |
| 21 | .link_libc = true, | |
| 22 | }), | |
| 23 | }); | |
| 24 | ||
| 25 | const io = b.graph.io; | |
| 26 | ||
| 27 | if (std.zig.system.darwin.getSdk(b.allocator, io, &target.result)) |sdk| { | |
| 28 | exe.root_module.addSystemIncludePath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "/usr/include" }) }); | |
| 29 | exe.root_module.addSystemFrameworkPath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "/System/Library/Frameworks" }) }); | |
| 30 | exe.root_module.addSystemFrameworkPath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "/System/Library/SubFrameworks" }) }); | |
| 31 | exe.root_module.addLibraryPath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "/usr/lib" }) }); | |
| 32 | } else { | |
| 33 | exe.step.dependOn(&b.addFail("no iOS SDK found").step); | |
| 34 | } | |
| 35 | ||
| 36 | exe.root_module.addCSourceFile(.{ .file = b.path("main.m"), .flags = &.{} }); | |
| 37 | exe.root_module.linkFramework("Foundation", .{}); | |
| 38 | exe.root_module.linkFramework("UIKit", .{}); | |
| 39 | ||
| 40 | test_step.dependOn(&b.addInstallArtifact(exe, .{}).step); | |
| 41 | } |
test/standalone/ios/main.m created+38| ... | ... | @@ -0,0 +1,38 @@ |
| 1 | #import <UIKit/UIKit.h> | |
| 2 | ||
| 3 | @interface AppDelegate : UIResponder <UIApplicationDelegate> | |
| 4 | @property (strong, nonatomic) UIWindow *window; | |
| 5 | @end | |
| 6 | ||
| 7 | extern void zig_panic(); | |
| 8 | ||
| 9 | int main() { | |
| 10 | @autoreleasepool { | |
| 11 | return UIApplicationMain(0, nil, nil, NSStringFromClass([AppDelegate class])); | |
| 12 | } | |
| 13 | } | |
| 14 | ||
| 15 | @implementation AppDelegate | |
| 16 | ||
| 17 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(id)options { | |
| 18 | CGRect mainScreenBounds = [[UIScreen mainScreen] bounds]; | |
| 19 | self.window = [[UIWindow alloc] initWithFrame:mainScreenBounds]; | |
| 20 | UIViewController *viewController = [[UIViewController alloc] init]; | |
| 21 | viewController.view.frame = mainScreenBounds; | |
| 22 | ||
| 23 | NSString* msg = @"Hello world"; | |
| 24 | ||
| 25 | UILabel *label = [[UILabel alloc] initWithFrame:mainScreenBounds]; | |
| 26 | [label setText:msg]; | |
| 27 | [viewController.view addSubview: label]; | |
| 28 | ||
| 29 | self.window.rootViewController = viewController; | |
| 30 | ||
| 31 | [self.window makeKeyAndVisible]; | |
| 32 | ||
| 33 | zig_panic(); | |
| 34 | ||
| 35 | return YES; | |
| 36 | } | |
| 37 | ||
| 38 | @end |
test/standalone/ios/panic.zig created+4| ... | ... | @@ -0,0 +1,4 @@ |
| 1 | export fn zig_panic() void { | |
| 2 | @panic("called zig_panic"); | |
| 3 | } | |
| 4 | pub const _start = {}; // entry point is in main.m |