Commit 6461b95163
Changed files (3)
src
link
test
stage2
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.
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),
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);
\\}