| author | |
| committer | |
| log | 6461b9516371d22d347c27b5fcd2e8c22fafd03d |
| tree | 4d11bd6cfeca70ff1f82b1318ef75c8722695278 |
| parent | d98e39fa6864f287bc50f265f98b7195849afa68 |
* 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 | ... | @@ -362,8 +362,8 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio |
| 362 | 362 | ||
| 363 | self.base.file = file; | 363 | self.base.file = file; |
| 364 | 364 | ||
| 365 | // Create dSYM bundle. | ||
| 366 | if (!options.strip and options.module != null) { | 365 | if (!options.strip and options.module != null) { |
| 366 | // Create dSYM bundle. | ||
| 367 | const dir = options.module.?.zig_cache_artifact_directory; | 367 | const dir = options.module.?.zig_cache_artifact_directory; |
| 368 | log.debug("creating {s}.dSYM bundle in {s}", .{ sub_path, dir.path }); | 368 | log.debug("creating {s}.dSYM bundle in {s}", .{ sub_path, dir.path }); |
| 369 | 369 | ||
| ... | @@ -1223,7 +1223,11 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { | ... | @@ -1223,7 +1223,11 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { |
| 1223 | self.shrinkTextBlock(&decl.link.macho, code.len); | 1223 | self.shrinkTextBlock(&decl.link.macho, code.len); |
| 1224 | } | 1224 | } |
| 1225 | decl.link.macho.size = code.len; | 1225 | 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); | ||
| 1227 | symbol.n_type = macho.N_SECT; | 1231 | symbol.n_type = macho.N_SECT; |
| 1228 | symbol.n_sect = @intCast(u8, self.text_section_index.?) + 1; | 1232 | symbol.n_sect = @intCast(u8, self.text_section_index.?) + 1; |
| 1229 | symbol.n_desc = 0; | 1233 | symbol.n_desc = 0; |
| ... | @@ -1232,7 +1236,9 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { | ... | @@ -1232,7 +1236,9 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { |
| 1232 | if (self.d_sym) |*ds| | 1236 | if (self.d_sym) |*ds| |
| 1233 | try ds.writeLocalSymbol(decl.link.macho.local_sym_index); | 1237 | try ds.writeLocalSymbol(decl.link.macho.local_sym_index); |
| 1234 | } else { | 1238 | } 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 | |||
| 1236 | const name_str_index = try self.makeString(decl_name); | 1242 | const name_str_index = try self.makeString(decl_name); |
| 1237 | const addr = try self.allocateTextBlock(&decl.link.macho, code.len, required_alignment); | 1243 | const addr = try self.allocateTextBlock(&decl.link.macho, code.len, required_alignment); |
| 1238 | 1244 | ||
| ... | @@ -1371,6 +1377,9 @@ pub fn updateDeclExports( | ... | @@ -1371,6 +1377,9 @@ pub fn updateDeclExports( |
| 1371 | const decl_sym = &self.locals.items[decl.link.macho.local_sym_index]; | 1377 | const decl_sym = &self.locals.items[decl.link.macho.local_sym_index]; |
| 1372 | 1378 | ||
| 1373 | for (exports) |exp| { | 1379 | 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 | |||
| 1374 | if (exp.options.section) |section_name| { | 1383 | if (exp.options.section) |section_name| { |
| 1375 | if (!mem.eql(u8, section_name, "__text")) { | 1384 | if (!mem.eql(u8, section_name, "__text")) { |
| 1376 | try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1); | 1385 | try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1); |
| ... | @@ -1398,7 +1407,7 @@ pub fn updateDeclExports( | ... | @@ -1398,7 +1407,7 @@ pub fn updateDeclExports( |
| 1398 | // Otherwise, don't do anything since we already have all the flags | 1407 | // Otherwise, don't do anything since we already have all the flags |
| 1399 | // set that we need for global (strong) linkage. | 1408 | // set that we need for global (strong) linkage. |
| 1400 | // n_type == N_SECT | N_EXT | 1409 | // n_type == N_SECT | N_EXT |
| 1401 | if (mem.eql(u8, exp.options.name, "_main")) { | 1410 | if (mem.eql(u8, exp_name, "_main")) { |
| 1402 | self.entry_addr = decl_sym.n_value; | 1411 | self.entry_addr = decl_sym.n_value; |
| 1403 | } | 1412 | } |
| 1404 | }, | 1413 | }, |
| ... | @@ -1420,14 +1429,14 @@ pub fn updateDeclExports( | ... | @@ -1420,14 +1429,14 @@ pub fn updateDeclExports( |
| 1420 | if (exp.link.macho.sym_index) |i| { | 1429 | if (exp.link.macho.sym_index) |i| { |
| 1421 | const sym = &self.globals.items[i]; | 1430 | const sym = &self.globals.items[i]; |
| 1422 | sym.* = .{ | 1431 | sym.* = .{ |
| 1423 | .n_strx = try self.updateString(sym.n_strx, exp.options.name), | 1432 | .n_strx = try self.updateString(sym.n_strx, exp_name), |
| 1424 | .n_type = n_type, | 1433 | .n_type = n_type, |
| 1425 | .n_sect = @intCast(u8, self.text_section_index.?) + 1, | 1434 | .n_sect = @intCast(u8, self.text_section_index.?) + 1, |
| 1426 | .n_desc = n_desc, | 1435 | .n_desc = n_desc, |
| 1427 | .n_value = decl_sym.n_value, | 1436 | .n_value = decl_sym.n_value, |
| 1428 | }; | 1437 | }; |
| 1429 | } else { | 1438 | } else { |
| 1430 | const name_str_index = try self.makeString(exp.options.name); | 1439 | const name_str_index = try self.makeString(exp_name); |
| 1431 | const i = if (self.globals_free_list.popOrNull()) |i| i else blk: { | 1440 | const i = if (self.globals_free_list.popOrNull()) |i| i else blk: { |
| 1432 | _ = self.globals.addOneAssumeCapacity(); | 1441 | _ = self.globals.addOneAssumeCapacity(); |
| 1433 | self.export_info_dirty = true; | 1442 | self.export_info_dirty = true; |
| ... | @@ -2230,9 +2239,12 @@ fn makeString(self: *MachO, bytes: []const u8) !u32 { | ... | @@ -2230,9 +2239,12 @@ fn makeString(self: *MachO, bytes: []const u8) !u32 { |
| 2230 | 2239 | ||
| 2231 | try self.string_table.ensureCapacity(self.base.allocator, self.string_table.items.len + bytes.len + 1); | 2240 | try self.string_table.ensureCapacity(self.base.allocator, self.string_table.items.len + bytes.len + 1); |
| 2232 | const offset = @intCast(u32, self.string_table.items.len); | 2241 | const offset = @intCast(u32, self.string_table.items.len); |
| 2242 | |||
| 2233 | log.debug("writing new string '{s}' into string table at offset 0x{x}", .{ bytes, offset }); | 2243 | log.debug("writing new string '{s}' into string table at offset 0x{x}", .{ bytes, offset }); |
| 2244 | |||
| 2234 | self.string_table.appendSliceAssumeCapacity(bytes); | 2245 | self.string_table.appendSliceAssumeCapacity(bytes); |
| 2235 | self.string_table.appendAssumeCapacity(0); | 2246 | self.string_table.appendAssumeCapacity(0); |
| 2247 | |||
| 2236 | try self.string_table_directory.putNoClobber( | 2248 | try self.string_table_directory.putNoClobber( |
| 2237 | self.base.allocator, | 2249 | self.base.allocator, |
| 2238 | try self.base.allocator.dupe(u8, bytes), | 2250 | 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 | ... | @@ -534,8 +534,8 @@ pub fn flushModule(self: *DebugSymbols, allocator: *Allocator, options: link.Opt |
| 534 | mem.writeIntLittle(u64, di_buf.addManyAsArrayAssumeCapacity(8), text_section.size); | 534 | mem.writeIntLittle(u64, di_buf.addManyAsArrayAssumeCapacity(8), text_section.size); |
| 535 | 535 | ||
| 536 | // Sentinel. | 536 | // Sentinel. |
| 537 | mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), 0); | 537 | mem.writeIntLittle(u64, di_buf.addManyAsArrayAssumeCapacity(8), 0); |
| 538 | mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), 0); | 538 | mem.writeIntLittle(u64, di_buf.addManyAsArrayAssumeCapacity(8), 0); |
| 539 | 539 | ||
| 540 | // Go back and populate the initial length. | 540 | // Go back and populate the initial length. |
| 541 | const init_len = di_buf.items.len - after_init_len; | 541 | const init_len = di_buf.items.len - after_init_len; |
| ... | @@ -1075,6 +1075,32 @@ pub fn commitDeclDebugInfo( | ... | @@ -1075,6 +1075,32 @@ pub fn commitDeclDebugInfo( |
| 1075 | mem.writeIntLittle(u32, ptr, @intCast(u32, text_block.size)); | 1075 | mem.writeIntLittle(u32, ptr, @intCast(u32, text_block.size)); |
| 1076 | } | 1076 | } |
| 1077 | 1077 | ||
| 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 | |||
| 1078 | try dbg_line_buffer.appendSlice(&[_]u8{ DW.LNS_extended_op, 1, DW.LNE_end_sequence }); | 1104 | try dbg_line_buffer.appendSlice(&[_]u8{ DW.LNS_extended_op, 1, DW.LNE_end_sequence }); |
| 1079 | 1105 | ||
| 1080 | // Now we have the full contents and may allocate a region to store it. | 1106 | // 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 { | ... | @@ -17,7 +17,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 17 | 17 | ||
| 18 | // Incorrect return type | 18 | // Incorrect return type |
| 19 | case.addError( | 19 | case.addError( |
| 20 | \\export fn _main() noreturn { | 20 | \\export fn main() noreturn { |
| 21 | \\} | 21 | \\} |
| 22 | , &[_][]const u8{":2:1: error: expected noreturn, found void"}); | 22 | , &[_][]const u8{":2:1: error: expected noreturn, found void"}); |
| 23 | 23 | ||
| ... | @@ -26,7 +26,7 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -26,7 +26,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 26 | \\extern "c" fn write(usize, usize, usize) usize; | 26 | \\extern "c" fn write(usize, usize, usize) usize; |
| 27 | \\extern "c" fn exit(usize) noreturn; | 27 | \\extern "c" fn exit(usize) noreturn; |
| 28 | \\ | 28 | \\ |
| 29 | \\export fn _main() noreturn { | 29 | \\export fn main() noreturn { |
| 30 | \\ print(); | 30 | \\ print(); |
| 31 | \\ | 31 | \\ |
| 32 | \\ exit(0); | 32 | \\ exit(0); |
| ... | @@ -46,7 +46,7 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -46,7 +46,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 46 | \\extern "c" fn write(usize, usize, usize) usize; | 46 | \\extern "c" fn write(usize, usize, usize) usize; |
| 47 | \\extern "c" fn exit(usize) noreturn; | 47 | \\extern "c" fn exit(usize) noreturn; |
| 48 | \\ | 48 | \\ |
| 49 | \\export fn _main() noreturn { | 49 | \\export fn main() noreturn { |
| 50 | \\ print(); | 50 | \\ print(); |
| 51 | \\ print(); | 51 | \\ print(); |
| 52 | \\ print(); | 52 | \\ print(); |
| ... | @@ -73,7 +73,7 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -73,7 +73,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 73 | \\extern "c" fn write(usize, usize, usize) usize; | 73 | \\extern "c" fn write(usize, usize, usize) usize; |
| 74 | \\extern "c" fn exit(usize) noreturn; | 74 | \\extern "c" fn exit(usize) noreturn; |
| 75 | \\ | 75 | \\ |
| 76 | \\export fn _main() noreturn { | 76 | \\export fn main() noreturn { |
| 77 | \\ print(); | 77 | \\ print(); |
| 78 | \\ | 78 | \\ |
| 79 | \\ exit(0); | 79 | \\ exit(0); |
| ... | @@ -93,7 +93,7 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -93,7 +93,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 93 | \\extern "c" fn write(usize, usize, usize) usize; | 93 | \\extern "c" fn write(usize, usize, usize) usize; |
| 94 | \\extern "c" fn exit(usize) noreturn; | 94 | \\extern "c" fn exit(usize) noreturn; |
| 95 | \\ | 95 | \\ |
| 96 | \\export fn _main() noreturn { | 96 | \\export fn main() noreturn { |
| 97 | \\ print(); | 97 | \\ print(); |
| 98 | \\ print(); | 98 | \\ print(); |
| 99 | \\ | 99 | \\ |
| ... | @@ -119,7 +119,7 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -119,7 +119,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 119 | case.addCompareOutput( | 119 | case.addCompareOutput( |
| 120 | \\extern "c" fn exit(usize) noreturn; | 120 | \\extern "c" fn exit(usize) noreturn; |
| 121 | \\ | 121 | \\ |
| 122 | \\export fn _main() noreturn { | 122 | \\export fn main() noreturn { |
| 123 | \\ exit(0); | 123 | \\ exit(0); |
| 124 | \\} | 124 | \\} |
| 125 | , | 125 | , |
| ... | @@ -130,7 +130,7 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -130,7 +130,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 130 | \\extern "c" fn exit(usize) noreturn; | 130 | \\extern "c" fn exit(usize) noreturn; |
| 131 | \\extern "c" fn write(usize, usize, usize) usize; | 131 | \\extern "c" fn write(usize, usize, usize) usize; |
| 132 | \\ | 132 | \\ |
| 133 | \\export fn _main() noreturn { | 133 | \\export fn main() noreturn { |
| 134 | \\ _ = write(1, @ptrToInt("Hey!\n"), 5); | 134 | \\ _ = write(1, @ptrToInt("Hey!\n"), 5); |
| 135 | \\ exit(0); | 135 | \\ exit(0); |
| 136 | \\} | 136 | \\} |