authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-05-14 19:20:21+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-05-16 08:12:29+02:00
log6461b9516371d22d347c27b5fcd2e8c22fafd03d
tree4d11bd6cfeca70ff1f82b1318ef75c8722695278
parentd98e39fa6864f287bc50f265f98b7195849afa68

macho: fix DWARF in dSYM and sym naming more consistent

* Advance line and PC prior to ending sequence in debug line program for a fn_decl. This is equivalent to closing scope in the debugger and without it, the debugger will not map source-to-address info as a result will not print the source when breaking at a symbol. * Fix debug aranges sentinels to be of the size as the actual tuple descriptor (assuming segment selector to be ommitted). In summary, the sentinels were 32bit 0s, whereas they ought to be 64bit 0s. * Make naming of symbols in the binary more consistent by prefixing each symbol name with an underscore '_'.

3 files changed, 53 insertions(+), 15 deletions(-)

src/link/MachO.zig+18-6
......@@ -362,8 +362,8 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
362362
363363 self.base.file = file;
364364
365 // Create dSYM bundle.
366365 if (!options.strip and options.module != null) {
366 // Create dSYM bundle.
367367 const dir = options.module.?.zig_cache_artifact_directory;
368368 log.debug("creating {s}.dSYM bundle in {s}", .{ sub_path, dir.path });
369369
......@@ -1223,7 +1223,11 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
12231223 self.shrinkTextBlock(&decl.link.macho, code.len);
12241224 }
12251225 decl.link.macho.size = code.len;
1226 symbol.n_strx = try self.updateString(symbol.n_strx, mem.spanZ(decl.name));
1226
1227 const new_name = try std.fmt.allocPrint(self.base.allocator, "_{s}", .{mem.spanZ(decl.name)});
1228 defer self.base.allocator.free(new_name);
1229
1230 symbol.n_strx = try self.updateString(symbol.n_strx, new_name);
12271231 symbol.n_type = macho.N_SECT;
12281232 symbol.n_sect = @intCast(u8, self.text_section_index.?) + 1;
12291233 symbol.n_desc = 0;
......@@ -1232,7 +1236,9 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
12321236 if (self.d_sym) |*ds|
12331237 try ds.writeLocalSymbol(decl.link.macho.local_sym_index);
12341238 } else {
1235 const decl_name = mem.spanZ(decl.name);
1239 const decl_name = try std.fmt.allocPrint(self.base.allocator, "_{s}", .{mem.spanZ(decl.name)});
1240 defer self.base.allocator.free(decl_name);
1241
12361242 const name_str_index = try self.makeString(decl_name);
12371243 const addr = try self.allocateTextBlock(&decl.link.macho, code.len, required_alignment);
12381244
......@@ -1371,6 +1377,9 @@ pub fn updateDeclExports(
13711377 const decl_sym = &self.locals.items[decl.link.macho.local_sym_index];
13721378
13731379 for (exports) |exp| {
1380 const exp_name = try std.fmt.allocPrint(self.base.allocator, "_{s}", .{exp.options.name});
1381 defer self.base.allocator.free(exp_name);
1382
13741383 if (exp.options.section) |section_name| {
13751384 if (!mem.eql(u8, section_name, "__text")) {
13761385 try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1);
......@@ -1398,7 +1407,7 @@ pub fn updateDeclExports(
13981407 // Otherwise, don't do anything since we already have all the flags
13991408 // set that we need for global (strong) linkage.
14001409 // n_type == N_SECT | N_EXT
1401 if (mem.eql(u8, exp.options.name, "_main")) {
1410 if (mem.eql(u8, exp_name, "_main")) {
14021411 self.entry_addr = decl_sym.n_value;
14031412 }
14041413 },
......@@ -1420,14 +1429,14 @@ pub fn updateDeclExports(
14201429 if (exp.link.macho.sym_index) |i| {
14211430 const sym = &self.globals.items[i];
14221431 sym.* = .{
1423 .n_strx = try self.updateString(sym.n_strx, exp.options.name),
1432 .n_strx = try self.updateString(sym.n_strx, exp_name),
14241433 .n_type = n_type,
14251434 .n_sect = @intCast(u8, self.text_section_index.?) + 1,
14261435 .n_desc = n_desc,
14271436 .n_value = decl_sym.n_value,
14281437 };
14291438 } else {
1430 const name_str_index = try self.makeString(exp.options.name);
1439 const name_str_index = try self.makeString(exp_name);
14311440 const i = if (self.globals_free_list.popOrNull()) |i| i else blk: {
14321441 _ = self.globals.addOneAssumeCapacity();
14331442 self.export_info_dirty = true;
......@@ -2230,9 +2239,12 @@ fn makeString(self: *MachO, bytes: []const u8) !u32 {
22302239
22312240 try self.string_table.ensureCapacity(self.base.allocator, self.string_table.items.len + bytes.len + 1);
22322241 const offset = @intCast(u32, self.string_table.items.len);
2242
22332243 log.debug("writing new string '{s}' into string table at offset 0x{x}", .{ bytes, offset });
2244
22342245 self.string_table.appendSliceAssumeCapacity(bytes);
22352246 self.string_table.appendAssumeCapacity(0);
2247
22362248 try self.string_table_directory.putNoClobber(
22372249 self.base.allocator,
22382250 try self.base.allocator.dupe(u8, bytes),
src/link/MachO/DebugSymbols.zig+28-2
......@@ -534,8 +534,8 @@ pub fn flushModule(self: *DebugSymbols, allocator: *Allocator, options: link.Opt
534534 mem.writeIntLittle(u64, di_buf.addManyAsArrayAssumeCapacity(8), text_section.size);
535535
536536 // Sentinel.
537 mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), 0);
538 mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), 0);
537 mem.writeIntLittle(u64, di_buf.addManyAsArrayAssumeCapacity(8), 0);
538 mem.writeIntLittle(u64, di_buf.addManyAsArrayAssumeCapacity(8), 0);
539539
540540 // Go back and populate the initial length.
541541 const init_len = di_buf.items.len - after_init_len;
......@@ -1075,6 +1075,32 @@ pub fn commitDeclDebugInfo(
10751075 mem.writeIntLittle(u32, ptr, @intCast(u32, text_block.size));
10761076 }
10771077
1078 {
1079 // Advance line and PC.
1080 // TODO encapsulate logic in a helper function.
1081 try dbg_line_buffer.append(DW.LNS_advance_pc);
1082 try leb.writeULEB128(dbg_line_buffer.writer(), text_block.size);
1083
1084 try dbg_line_buffer.append(DW.LNS_advance_line);
1085 const line_off: u28 = blk: {
1086 const tree = decl.container.file_scope.tree;
1087 const node_tags = tree.nodes.items(.tag);
1088 const node_datas = tree.nodes.items(.data);
1089 const token_starts = tree.tokens.items(.start);
1090
1091 // TODO Look into improving the performance here by adding a token-index-to-line
1092 // lookup table. Currently this involves scanning over the source code for newlines.
1093 const fn_decl = decl.src_node;
1094 assert(node_tags[fn_decl] == .fn_decl);
1095 const block = node_datas[fn_decl].rhs;
1096 const lbrace = tree.firstToken(block);
1097 const rbrace = tree.lastToken(block);
1098 const line_delta = std.zig.lineDelta(tree.source, token_starts[lbrace], token_starts[rbrace]);
1099 break :blk @intCast(u28, line_delta);
1100 };
1101 try leb.writeULEB128(dbg_line_buffer.writer(), line_off);
1102 }
1103
10781104 try dbg_line_buffer.appendSlice(&[_]u8{ DW.LNS_extended_op, 1, DW.LNE_end_sequence });
10791105
10801106 // Now we have the full contents and may allocate a region to store it.
test/stage2/darwin.zig+7-7
......@@ -17,7 +17,7 @@ pub fn addCases(ctx: *TestContext) !void {
1717
1818 // Incorrect return type
1919 case.addError(
20 \\export fn _main() noreturn {
20 \\export fn main() noreturn {
2121 \\}
2222 , &[_][]const u8{":2:1: error: expected noreturn, found void"});
2323
......@@ -26,7 +26,7 @@ pub fn addCases(ctx: *TestContext) !void {
2626 \\extern "c" fn write(usize, usize, usize) usize;
2727 \\extern "c" fn exit(usize) noreturn;
2828 \\
29 \\export fn _main() noreturn {
29 \\export fn main() noreturn {
3030 \\ print();
3131 \\
3232 \\ exit(0);
......@@ -46,7 +46,7 @@ pub fn addCases(ctx: *TestContext) !void {
4646 \\extern "c" fn write(usize, usize, usize) usize;
4747 \\extern "c" fn exit(usize) noreturn;
4848 \\
49 \\export fn _main() noreturn {
49 \\export fn main() noreturn {
5050 \\ print();
5151 \\ print();
5252 \\ print();
......@@ -73,7 +73,7 @@ pub fn addCases(ctx: *TestContext) !void {
7373 \\extern "c" fn write(usize, usize, usize) usize;
7474 \\extern "c" fn exit(usize) noreturn;
7575 \\
76 \\export fn _main() noreturn {
76 \\export fn main() noreturn {
7777 \\ print();
7878 \\
7979 \\ exit(0);
......@@ -93,7 +93,7 @@ pub fn addCases(ctx: *TestContext) !void {
9393 \\extern "c" fn write(usize, usize, usize) usize;
9494 \\extern "c" fn exit(usize) noreturn;
9595 \\
96 \\export fn _main() noreturn {
96 \\export fn main() noreturn {
9797 \\ print();
9898 \\ print();
9999 \\
......@@ -119,7 +119,7 @@ pub fn addCases(ctx: *TestContext) !void {
119119 case.addCompareOutput(
120120 \\extern "c" fn exit(usize) noreturn;
121121 \\
122 \\export fn _main() noreturn {
122 \\export fn main() noreturn {
123123 \\ exit(0);
124124 \\}
125125 ,
......@@ -130,7 +130,7 @@ pub fn addCases(ctx: *TestContext) !void {
130130 \\extern "c" fn exit(usize) noreturn;
131131 \\extern "c" fn write(usize, usize, usize) usize;
132132 \\
133 \\export fn _main() noreturn {
133 \\export fn main() noreturn {
134134 \\ _ = write(1, @ptrToInt("Hey!\n"), 5);
135135 \\ exit(0);
136136 \\}