diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2021-04-20 16:55:08 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2021-04-20 16:55:32 +0200 |
| commit | d64c76e8f1faf493d5fa6f3c0d9324f05f99d68f (patch) | |
| tree | c8ca7fb3acc4047d00dc60096e8856c99d98efa6 /src/link/MachO | |
| parent | 7bc6554a58274730f762bffb1f031af8dcfdb1fb (diff) | |
| download | zig-d64c76e8f1faf493d5fa6f3c0d9324f05f99d68f.tar.gz zig-d64c76e8f1faf493d5fa6f3c0d9324f05f99d68f.zip | |
zld: fix parsing of weak symbols
Diffstat (limited to 'src/link/MachO')
| -rw-r--r-- | src/link/MachO/Symbol.zig | 2 | ||||
| -rw-r--r-- | src/link/MachO/Zld.zig | 71 |
2 files changed, 37 insertions, 36 deletions
diff --git a/src/link/MachO/Symbol.zig b/src/link/MachO/Symbol.zig index f65a694f75..9e6c2bf68a 100644 --- a/src/link/MachO/Symbol.zig +++ b/src/link/MachO/Symbol.zig @@ -52,7 +52,7 @@ pub fn isUndf(sym: macho.nlist_64) bool { } pub fn isWeakDef(sym: macho.nlist_64) bool { - return sym.n_desc == macho.N_WEAK_DEF; + return (sym.n_desc & macho.N_WEAK_DEF) != 0; } /// Symbol is local if it is defined and not an extern. diff --git a/src/link/MachO/Zld.zig b/src/link/MachO/Zld.zig index 4a3c307806..6831251966 100644 --- a/src/link/MachO/Zld.zig +++ b/src/link/MachO/Zld.zig @@ -1340,13 +1340,14 @@ fn resolveSymbolsInObject(self: *Zld, object_id: u16) !void { .strong => { if (!is_weak) { log.debug("strong symbol '{s}' defined multiple times", .{sym_name}); + return error.MultipleSymbolDefinitions; } continue; }, else => {}, } - global.value.tag = .strong; + global.value.tag = if (is_weak) .weak else .strong; global.value.file = object_id; global.value.index = @intCast(u32, sym_id); } else if (Symbol.isUndef(sym)) { @@ -1428,20 +1429,20 @@ fn resolveSymbols(self: *Zld) !void { .file = 0, }); - // { - // log.warn("symtab", .{}); - // for (self.symtab.items()) |sym| { - // switch (sym.value.tag) { - // .weak, .strong => { - // log.warn(" | {s} => {s}", .{ sym.key, self.objects.items[sym.value.file.?].name.? }); - // }, - // .import => { - // log.warn(" | {s} => libSystem.B.dylib", .{sym.key}); - // }, - // else => unreachable, - // } - // } - // } + { + log.debug("symtab", .{}); + for (self.symtab.items()) |sym| { + switch (sym.value.tag) { + .weak, .strong => { + log.debug(" | {s} => {s}", .{ sym.key, self.objects.items[sym.value.file.?].name.? }); + }, + .import => { + log.debug(" | {s} => libSystem.B.dylib", .{sym.key}); + }, + else => unreachable, + } + } + } } fn resolveStubsAndGotEntries(self: *Zld) !void { @@ -1687,7 +1688,26 @@ fn relocTargetAddr(self: *Zld, object_id: u16, target: reloc.Relocation.Target) const sym = object.symtab.items[sym_id]; const sym_name = object.getString(sym.n_strx); - if (self.symtab.get(sym_name)) |global| { + if (Symbol.isSect(sym)) { + log.debug(" | local symbol '{s}'", .{sym_name}); + if (object.locals.get(sym_name)) |local| { + break :blk local.address; + } + // For temp locals, i.e., symbols prefixed with l... we relocate + // based on section addressing. + const source_sect_id = sym.n_sect - 1; + const target_mapping = self.mappings.get(.{ + .object_id = object_id, + .source_sect_id = source_sect_id, + }) orelse unreachable; + + const source_seg = object.load_commands.items[object.segment_cmd_index.?].Segment; + const source_sect = source_seg.sections.items[source_sect_id]; + const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment; + const target_sect = target_seg.sections.items[target_mapping.target_sect_id]; + const target_addr = target_sect.addr + target_mapping.offset; + break :blk sym.n_value - source_sect.addr + target_addr; + } else if (self.symtab.get(sym_name)) |global| { switch (global.tag) { .weak, .strong => { log.debug(" | global symbol '{s}'", .{sym_name}); @@ -1711,25 +1731,6 @@ fn relocTargetAddr(self: *Zld, object_id: u16, target: reloc.Relocation.Target) }, else => unreachable, } - } else if (Symbol.isSect(sym)) { - log.debug(" | local symbol '{s}'", .{sym_name}); - if (object.locals.get(sym_name)) |local| { - break :blk local.address; - } - // For temp locals, i.e., symbols prefixed with l... we relocate - // based on section addressing. - const source_sect_id = sym.n_sect - 1; - const target_mapping = self.mappings.get(.{ - .object_id = object_id, - .source_sect_id = source_sect_id, - }) orelse unreachable; - - const source_seg = object.load_commands.items[object.segment_cmd_index.?].Segment; - const source_sect = source_seg.sections.items[source_sect_id]; - const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment; - const target_sect = target_seg.sections.items[target_mapping.target_sect_id]; - const target_addr = target_sect.addr + target_mapping.offset; - break :blk sym.n_value - source_sect.addr + target_addr; } else { log.err("failed to resolve symbol '{s}' as a relocation target", .{sym_name}); return error.FailedToResolveRelocationTarget; |
