aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2021-06-10 11:03:14 +0200
committerJakub Konka <kubkon@jakubkonka.com>2021-06-10 11:03:14 +0200
commit03cda80a634d82e02e641fe04fa2abda4455966a (patch)
tree43593edce0f5c9d4e76725908eccc0efaa8653c3
parent66ff56c58f3ef71f5cc3b8392632b3ec8abec43f (diff)
downloadzig-03cda80a634d82e02e641fe04fa2abda4455966a.tar.gz
zig-03cda80a634d82e02e641fe04fa2abda4455966a.zip
zld: handle aliasing of tentative into regular global
-rw-r--r--src/link/MachO/Object.zig10
-rw-r--r--src/link/MachO/Zld.zig32
2 files changed, 36 insertions, 6 deletions
diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig
index 12ce918a36..4501d63fff 100644
--- a/src/link/MachO/Object.zig
+++ b/src/link/MachO/Object.zig
@@ -351,15 +351,15 @@ pub fn parseSymbols(self: *Object) !void {
const sym_name = mem.spanZ(@ptrCast([*:0]const u8, strtab.ptr + sym.n_strx));
if (Symbol.isStab(sym)) {
- log.err("stab {s} in {s}", .{ sym_name, self.name.? });
+ log.err("unhandled symbol type: stab {s} in {s}", .{ sym_name, self.name.? });
return error.UnhandledSymbolType;
}
if (Symbol.isIndr(sym)) {
- log.err("indirect symbol {s} in {s}", .{ sym_name, self.name.? });
+ log.err("unhandled symbol type: indirect {s} in {s}", .{ sym_name, self.name.? });
return error.UnhandledSymbolType;
}
if (Symbol.isAbs(sym)) {
- log.err("absolute symbol {s} in {s}", .{ sym_name, self.name.? });
+ log.err("unhandled symbol type: absolute {s} in {s}", .{ sym_name, self.name.? });
return error.UnhandledSymbolType;
}
@@ -399,9 +399,7 @@ pub fn parseSymbols(self: *Object) !void {
.alignment = (sym.n_desc >> 8) & 0x0f,
.file = self,
};
-
- log.err("Common symbol {s} in {s}: {}", .{ sym_name, self.name.?, tentative });
- return error.UnhandledSymbolType;
+ break :symbol &tentative.base;
}
const undef = try self.allocator.create(Symbol.Unresolved);
diff --git a/src/link/MachO/Zld.zig b/src/link/MachO/Zld.zig
index 9f676f3fc2..017b3f7d4e 100644
--- a/src/link/MachO/Zld.zig
+++ b/src/link/MachO/Zld.zig
@@ -84,6 +84,11 @@ common_section_index: ?u16 = null,
globals: std.StringArrayHashMapUnmanaged(*Symbol) = .{},
imports: std.StringArrayHashMapUnmanaged(*Symbol) = .{},
unresolved: std.StringArrayHashMapUnmanaged(*Symbol) = .{},
+tentatives: std.StringArrayHashMapUnmanaged(*Symbol) = .{},
+
+// /// Offset into __DATA,__common section.
+// /// Set if the linker found tentative definitions in any of the objects.
+// tentative_defs_offset: u32 = 0,
strtab: std.ArrayListUnmanaged(u8) = .{},
strtab_dir: std.StringHashMapUnmanaged(u32) = .{},
@@ -144,6 +149,7 @@ pub fn deinit(self: *Zld) void {
}
self.dylibs.deinit(self.allocator);
+ self.tentatives.deinit(self.allocator);
self.globals.deinit(self.allocator);
self.imports.deinit(self.allocator);
self.unresolved.deinit(self.allocator);
@@ -1379,6 +1385,10 @@ fn resolveSymbolsInObject(self: *Zld, object: *Object) !void {
if (sym.cast(Symbol.Regular)) |reg| {
if (reg.linkage == .translation_unit) continue; // Symbol local to TU.
+ if (self.tentatives.fetchSwapRemove(sym.name)) |kv| {
+ // Create link to the global.
+ kv.value.alias = sym;
+ }
if (self.unresolved.fetchSwapRemove(sym.name)) |kv| {
// Create link to the global.
kv.value.alias = sym;
@@ -1412,11 +1422,33 @@ fn resolveSymbolsInObject(self: *Zld, object: *Object) !void {
g_sym.alias = sym;
sym_ptr.* = sym;
+ } else if (sym.cast(Symbol.Tentative)) |tent| {
+ if (self.globals.get(sym.name)) |g_sym| {
+ sym.alias = g_sym;
+ continue;
+ }
+
+ if (self.unresolved.fetchSwapRemove(sym.name)) |kv| {
+ kv.value.alias = sym;
+ }
+
+ const t_sym = self.tentatives.get(sym.name) orelse {
+ // Put new tentative definition symbol into symbol table.
+ try self.tentatives.putNoClobber(self.allocator, sym.name, sym);
+ continue;
+ };
+
+ // TODO compare by size and pick the largest.
+ return error.TODOResolveTentatives;
} else if (sym.cast(Symbol.Unresolved)) |und| {
if (self.globals.get(sym.name)) |g_sym| {
sym.alias = g_sym;
continue;
}
+ if (self.tentatives.get(sym.name)) |t_sym| {
+ sym.alias = t_sym;
+ continue;
+ }
if (self.unresolved.get(sym.name)) |u_sym| {
sym.alias = u_sym;
continue;