diff --git a/src/link/MachO.zig b/src/link/MachO.zig index c6628149c3e3..2d2b4dbca124 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -362,8 +362,8 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio self.base.file = file; - // Create dSYM bundle. if (!options.strip and options.module != null) { + // Create dSYM bundle. const dir = options.module.?.zig_cache_artifact_directory; log.debug("creating {s}.dSYM bundle in {s}", .{ sub_path, dir.path }); @@ -1223,7 +1223,11 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { self.shrinkTextBlock(&decl.link.macho, code.len); } decl.link.macho.size = code.len; - symbol.n_strx = try self.updateString(symbol.n_strx, mem.spanZ(decl.name)); + + const new_name = try std.fmt.allocPrint(self.base.allocator, "_{s}", .{mem.spanZ(decl.name)}); + defer self.base.allocator.free(new_name); + + symbol.n_strx = try self.updateString(symbol.n_strx, new_name); symbol.n_type = macho.N_SECT; symbol.n_sect = @intCast(u8, self.text_section_index.?) + 1; symbol.n_desc = 0; @@ -1232,7 +1236,9 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { if (self.d_sym) |*ds| try ds.writeLocalSymbol(decl.link.macho.local_sym_index); } else { - const decl_name = mem.spanZ(decl.name); + const decl_name = try std.fmt.allocPrint(self.base.allocator, "_{s}", .{mem.spanZ(decl.name)}); + defer self.base.allocator.free(decl_name); + const name_str_index = try self.makeString(decl_name); const addr = try self.allocateTextBlock(&decl.link.macho, code.len, required_alignment); @@ -1371,6 +1377,9 @@ pub fn updateDeclExports( const decl_sym = &self.locals.items[decl.link.macho.local_sym_index]; for (exports) |exp| { + const exp_name = try std.fmt.allocPrint(self.base.allocator, "_{s}", .{exp.options.name}); + defer self.base.allocator.free(exp_name); + if (exp.options.section) |section_name| { if (!mem.eql(u8, section_name, "__text")) { try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1); @@ -1398,7 +1407,7 @@ pub fn updateDeclExports( // Otherwise, don't do anything since we already have all the flags // set that we need for global (strong) linkage. // n_type == N_SECT | N_EXT - if (mem.eql(u8, exp.options.name, "_main")) { + if (mem.eql(u8, exp_name, "_main")) { self.entry_addr = decl_sym.n_value; } }, @@ -1420,14 +1429,14 @@ pub fn updateDeclExports( if (exp.link.macho.sym_index) |i| { const sym = &self.globals.items[i]; sym.* = .{ - .n_strx = try self.updateString(sym.n_strx, exp.options.name), + .n_strx = try self.updateString(sym.n_strx, exp_name), .n_type = n_type, .n_sect = @intCast(u8, self.text_section_index.?) + 1, .n_desc = n_desc, .n_value = decl_sym.n_value, }; } else { - const name_str_index = try self.makeString(exp.options.name); + const name_str_index = try self.makeString(exp_name); const i = if (self.globals_free_list.popOrNull()) |i| i else blk: { _ = self.globals.addOneAssumeCapacity(); self.export_info_dirty = true; @@ -2230,9 +2239,12 @@ fn makeString(self: *MachO, bytes: []const u8) !u32 { try self.string_table.ensureCapacity(self.base.allocator, self.string_table.items.len + bytes.len + 1); const offset = @intCast(u32, self.string_table.items.len); + log.debug("writing new string '{s}' into string table at offset 0x{x}", .{ bytes, offset }); + self.string_table.appendSliceAssumeCapacity(bytes); self.string_table.appendAssumeCapacity(0); + try self.string_table_directory.putNoClobber( self.base.allocator, try self.base.allocator.dupe(u8, bytes), diff --git a/src/link/MachO/DebugSymbols.zig b/src/link/MachO/DebugSymbols.zig index b05f0e1a7753..17f24f7cd8e3 100644 --- a/src/link/MachO/DebugSymbols.zig +++ b/src/link/MachO/DebugSymbols.zig @@ -534,8 +534,8 @@ pub fn flushModule(self: *DebugSymbols, allocator: *Allocator, options: link.Opt mem.writeIntLittle(u64, di_buf.addManyAsArrayAssumeCapacity(8), text_section.size); // Sentinel. - mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), 0); - mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), 0); + mem.writeIntLittle(u64, di_buf.addManyAsArrayAssumeCapacity(8), 0); + mem.writeIntLittle(u64, di_buf.addManyAsArrayAssumeCapacity(8), 0); // Go back and populate the initial length. const init_len = di_buf.items.len - after_init_len; @@ -1075,6 +1075,32 @@ pub fn commitDeclDebugInfo( mem.writeIntLittle(u32, ptr, @intCast(u32, text_block.size)); } + { + // Advance line and PC. + // TODO encapsulate logic in a helper function. + try dbg_line_buffer.append(DW.LNS_advance_pc); + try leb.writeULEB128(dbg_line_buffer.writer(), text_block.size); + + try dbg_line_buffer.append(DW.LNS_advance_line); + const line_off: u28 = blk: { + const tree = decl.container.file_scope.tree; + const node_tags = tree.nodes.items(.tag); + const node_datas = tree.nodes.items(.data); + const token_starts = tree.tokens.items(.start); + + // TODO Look into improving the performance here by adding a token-index-to-line + // lookup table. Currently this involves scanning over the source code for newlines. + const fn_decl = decl.src_node; + assert(node_tags[fn_decl] == .fn_decl); + const block = node_datas[fn_decl].rhs; + const lbrace = tree.firstToken(block); + const rbrace = tree.lastToken(block); + const line_delta = std.zig.lineDelta(tree.source, token_starts[lbrace], token_starts[rbrace]); + break :blk @intCast(u28, line_delta); + }; + try leb.writeULEB128(dbg_line_buffer.writer(), line_off); + } + try dbg_line_buffer.appendSlice(&[_]u8{ DW.LNS_extended_op, 1, DW.LNE_end_sequence }); // Now we have the full contents and may allocate a region to store it. diff --git a/test/stage2/darwin.zig b/test/stage2/darwin.zig index 4f708729a29e..f62a61a6bc74 100644 --- a/test/stage2/darwin.zig +++ b/test/stage2/darwin.zig @@ -17,7 +17,7 @@ pub fn addCases(ctx: *TestContext) !void { // Incorrect return type case.addError( - \\export fn _main() noreturn { + \\export fn main() noreturn { \\} , &[_][]const u8{":2:1: error: expected noreturn, found void"}); @@ -26,7 +26,7 @@ pub fn addCases(ctx: *TestContext) !void { \\extern "c" fn write(usize, usize, usize) usize; \\extern "c" fn exit(usize) noreturn; \\ - \\export fn _main() noreturn { + \\export fn main() noreturn { \\ print(); \\ \\ exit(0); @@ -46,7 +46,7 @@ pub fn addCases(ctx: *TestContext) !void { \\extern "c" fn write(usize, usize, usize) usize; \\extern "c" fn exit(usize) noreturn; \\ - \\export fn _main() noreturn { + \\export fn main() noreturn { \\ print(); \\ print(); \\ print(); @@ -73,7 +73,7 @@ pub fn addCases(ctx: *TestContext) !void { \\extern "c" fn write(usize, usize, usize) usize; \\extern "c" fn exit(usize) noreturn; \\ - \\export fn _main() noreturn { + \\export fn main() noreturn { \\ print(); \\ \\ exit(0); @@ -93,7 +93,7 @@ pub fn addCases(ctx: *TestContext) !void { \\extern "c" fn write(usize, usize, usize) usize; \\extern "c" fn exit(usize) noreturn; \\ - \\export fn _main() noreturn { + \\export fn main() noreturn { \\ print(); \\ print(); \\ @@ -119,7 +119,7 @@ pub fn addCases(ctx: *TestContext) !void { case.addCompareOutput( \\extern "c" fn exit(usize) noreturn; \\ - \\export fn _main() noreturn { + \\export fn main() noreturn { \\ exit(0); \\} , @@ -130,7 +130,7 @@ pub fn addCases(ctx: *TestContext) !void { \\extern "c" fn exit(usize) noreturn; \\extern "c" fn write(usize, usize, usize) usize; \\ - \\export fn _main() noreturn { + \\export fn main() noreturn { \\ _ = write(1, @ptrToInt("Hey!\n"), 5); \\ exit(0); \\}