diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2024-08-05 07:44:35 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2024-08-07 10:21:02 +0200 |
| commit | 137d43c0ea77d5cc21040eadbd38fdfd945a3216 (patch) | |
| tree | d0317c251f8fbd503e8c35d441123200fb16b186 /src | |
| parent | 26da7c8207ff73927bcc8d5608703175074e266f (diff) | |
| download | zig-137d43c0ea77d5cc21040eadbd38fdfd945a3216.tar.gz zig-137d43c0ea77d5cc21040eadbd38fdfd945a3216.zip | |
elf: get hello-world glibc working again
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/Elf.zig | 19 | ||||
| -rw-r--r-- | src/link/Elf/Object.zig | 45 | ||||
| -rw-r--r-- | src/link/Elf/SharedObject.zig | 13 | ||||
| -rw-r--r-- | src/link/Elf/ZigObject.zig | 58 | ||||
| -rw-r--r-- | src/link/Elf/file.zig | 73 |
5 files changed, 92 insertions, 116 deletions
diff --git a/src/link/Elf.zig b/src/link/Elf.zig index ac2bff0882..0c0cec630f 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -2060,6 +2060,9 @@ fn scanRelocs(self: *Elf) !void { for (self.objects.items) |index| { try self.file(index).?.createSymbolIndirection(self); } + for (self.shared_objects.items) |index| { + try self.file(index).?.createSymbolIndirection(self); + } if (self.got.flags.needs_tlsld) { log.debug("program needs TLSLD", .{}); try self.got.addTlsLdSymbol(self); @@ -4431,11 +4434,13 @@ pub fn updateSymtabSize(self: *Elf) !void { strsize += ctx.strsize; } - if (self.zig_got_section_index) |_| { - self.zig_got.output_symtab_ctx.ilocal = nlocals + 1; - self.zig_got.updateSymtabSize(self); - nlocals += self.zig_got.output_symtab_ctx.nlocals; - strsize += self.zig_got.output_symtab_ctx.strsize; + if (self.zigObjectPtr()) |_| { + if (self.zig_got_section_index) |_| { + self.zig_got.output_symtab_ctx.ilocal = nlocals + 1; + self.zig_got.updateSymtabSize(self); + nlocals += self.zig_got.output_symtab_ctx.nlocals; + strsize += self.zig_got.output_symtab_ctx.strsize; + } } if (self.got_section_index) |_| { @@ -4574,7 +4579,9 @@ fn writeSyntheticSections(self: *Elf) !void { const shdr = self.shdrs.items[shndx]; try self.got.addRela(self); try self.copy_rel.addRela(self); - try self.zig_got.addRela(self); + if (self.zigObjectPtr()) |_| { + try self.zig_got.addRela(self); + } self.sortRelaDyn(); try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.rela_dyn.items), shdr.sh_offset); } diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index ef327dc9fb..30324e1e21 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -561,51 +561,6 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void { } } -pub fn createSymbolIndirection(self: *Object, elf_file: *Elf) !void { - for (self.symbols.items, 0..) |*sym, i| { - const ref = self.resolveSymbol(@intCast(i), elf_file); - const ref_sym = elf_file.symbol(ref) orelse continue; - if (ref_sym.file(elf_file).?.index() != self.index) continue; - if (!sym.isLocal(elf_file) and !sym.flags.has_dynamic) { - log.debug("'{s}' is non-local", .{sym.name(elf_file)}); - try elf_file.dynsym.addSymbol(ref, elf_file); - } - if (sym.flags.needs_got) { - log.debug("'{s}' needs GOT", .{sym.name(elf_file)}); - _ = try elf_file.got.addGotSymbol(ref, elf_file); - } - if (sym.flags.needs_plt) { - if (sym.flags.is_canonical) { - log.debug("'{s}' needs CPLT", .{sym.name(elf_file)}); - sym.flags.@"export" = true; - try elf_file.plt.addSymbol(ref, elf_file); - } else if (sym.flags.needs_got) { - log.debug("'{s}' needs PLTGOT", .{sym.name(elf_file)}); - try elf_file.plt_got.addSymbol(ref, elf_file); - } else { - log.debug("'{s}' needs PLT", .{sym.name(elf_file)}); - try elf_file.plt.addSymbol(ref, elf_file); - } - } - if (sym.flags.needs_copy_rel and !sym.flags.has_copy_rel) { - log.debug("'{s}' needs COPYREL", .{sym.name(elf_file)}); - try elf_file.copy_rel.addSymbol(ref, elf_file); - } - if (sym.flags.needs_tlsgd) { - log.debug("'{s}' needs TLSGD", .{sym.name(elf_file)}); - try elf_file.got.addTlsGdSymbol(ref, elf_file); - } - if (sym.flags.needs_gottp) { - log.debug("'{s}' needs GOTTP", .{sym.name(elf_file)}); - try elf_file.got.addGotTpSymbol(ref, elf_file); - } - if (sym.flags.needs_tlsdesc) { - log.debug("'{s}' needs TLSDESC", .{sym.name(elf_file)}); - try elf_file.got.addTlsDescSymbol(ref, elf_file); - } - } -} - pub fn resolveSymbols(self: *Object, elf_file: *Elf) !void { const gpa = elf_file.base.comp.gpa; diff --git a/src/link/Elf/SharedObject.zig b/src/link/Elf/SharedObject.zig index c4d84e29c9..b33853d23c 100644 --- a/src/link/Elf/SharedObject.zig +++ b/src/link/Elf/SharedObject.zig @@ -219,9 +219,7 @@ fn initSymbols(self: *SharedObject, elf_file: *Elf, opts: struct { self.versionString(self.versyms.items[i]), }); defer gpa.free(mangled); - const name_off = @as(u32, @intCast(self.strtab.items.len)); - try self.strtab.writer(gpa).print("{s}\x00", .{mangled}); - break :blk name_off; + break :blk try self.addString(gpa, mangled); } else sym.st_name; const out_esym_index: u32 = @intCast(self.symtab.items.len); const out_esym = self.symtab.addOneAssumeCapacity(); @@ -230,6 +228,7 @@ fn initSymbols(self: *SharedObject, elf_file: *Elf, opts: struct { const out_sym_index = self.addSymbolAssumeCapacity(); const out_sym = &self.symbols.items[out_sym_index]; out_sym.value = @intCast(out_esym.st_value); + out_sym.name_offset = name_off; out_sym.ref = .{ .index = 0, .file = 0 }; out_sym.esym_index = out_esym_index; out_sym.version_index = self.versyms.items[out_esym_index]; @@ -394,6 +393,14 @@ pub fn symbolAliases(self: *SharedObject, index: u32, elf_file: *Elf) []const u3 return aliases.items[start..end]; } +fn addString(self: *SharedObject, allocator: Allocator, str: []const u8) !u32 { + const off: u32 = @intCast(self.strtab.items.len); + try self.strtab.ensureUnusedCapacity(allocator, str.len + 1); + self.strtab.appendSliceAssumeCapacity(str); + self.strtab.appendAssumeCapacity(0); + return off; +} + pub fn getString(self: SharedObject, off: u32) [:0]const u8 { assert(off < self.strtab.items.len); return mem.sliceTo(@as([*:0]const u8, @ptrCast(self.strtab.items.ptr + off)), 0); diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index 1970ab5701..4544320c71 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -442,64 +442,6 @@ pub fn scanRelocs(self: *ZigObject, elf_file: *Elf, undefs: anytype) !void { } } -pub fn createSymbolIndirection(self: *ZigObject, elf_file: *Elf) !void { - const impl = struct { - fn impl(sym: *Symbol, ref: Elf.Ref, ef: *Elf) !void { - if (!sym.isLocal(ef) and !sym.flags.has_dynamic) { - log.debug("'{s}' is non-local", .{sym.name(ef)}); - try ef.dynsym.addSymbol(ref, ef); - } - if (sym.flags.needs_got) { - log.debug("'{s}' needs GOT", .{sym.name(ef)}); - _ = try ef.got.addGotSymbol(ref, ef); - } - if (sym.flags.needs_plt) { - if (sym.flags.is_canonical) { - log.debug("'{s}' needs CPLT", .{sym.name(ef)}); - sym.flags.@"export" = true; - try ef.plt.addSymbol(ref, ef); - } else if (sym.flags.needs_got) { - log.debug("'{s}' needs PLTGOT", .{sym.name(ef)}); - try ef.plt_got.addSymbol(ref, ef); - } else { - log.debug("'{s}' needs PLT", .{sym.name(ef)}); - try ef.plt.addSymbol(ref, ef); - } - } - if (sym.flags.needs_copy_rel and !sym.flags.has_copy_rel) { - log.debug("'{s}' needs COPYREL", .{sym.name(ef)}); - try ef.copy_rel.addSymbol(ref, ef); - } - if (sym.flags.needs_tlsgd) { - log.debug("'{s}' needs TLSGD", .{sym.name(ef)}); - try ef.got.addTlsGdSymbol(ref, ef); - } - if (sym.flags.needs_gottp) { - log.debug("'{s}' needs GOTTP", .{sym.name(ef)}); - try ef.got.addGotTpSymbol(ref, ef); - } - if (sym.flags.needs_tlsdesc) { - log.debug("'{s}' needs TLSDESC", .{sym.name(ef)}); - try ef.got.addTlsDescSymbol(ref, ef); - } - } - }.impl; - for (self.local_symbols.items, 0..) |index, i| { - const sym = &self.symbols.items[index]; - const ref = self.resolveSymbol(@intCast(i), elf_file); - const ref_sym = elf_file.symbol(ref) orelse continue; - if (ref_sym.file(elf_file).?.index() != self.index) continue; - try impl(sym, ref, elf_file); - } - for (self.global_symbols.items, 0..) |index, i| { - const sym = &self.symbols.items[index]; - const ref = self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file); - const ref_sym = elf_file.symbol(ref) orelse continue; - if (ref_sym.file(elf_file).?.index() != self.index) continue; - try impl(sym, ref, elf_file); - } -} - pub fn markLive(self: *ZigObject, elf_file: *Elf) void { for (self.global_symbols.items, 0..) |index, i| { const global = self.symbols.items[index]; diff --git a/src/link/Elf/file.zig b/src/link/Elf/file.zig index 32a540ce39..2c3b953523 100644 --- a/src/link/Elf/file.zig +++ b/src/link/Elf/file.zig @@ -101,10 +101,74 @@ pub const File = union(enum) { } pub fn createSymbolIndirection(file: File, elf_file: *Elf) !void { - return switch (file) { - .linker_defined, .shared_object => unreachable, - inline else => |x| x.createSymbolIndirection(elf_file), - }; + const impl = struct { + fn impl(sym: *Symbol, ref: Elf.Ref, ef: *Elf) !void { + if (!sym.isLocal(ef) and !sym.flags.has_dynamic) { + log.debug("'{s}' is non-local", .{sym.name(ef)}); + try ef.dynsym.addSymbol(ref, ef); + } + if (sym.flags.needs_got) { + log.debug("'{s}' needs GOT", .{sym.name(ef)}); + _ = try ef.got.addGotSymbol(ref, ef); + } + if (sym.flags.needs_plt) { + if (sym.flags.is_canonical) { + log.debug("'{s}' needs CPLT", .{sym.name(ef)}); + sym.flags.@"export" = true; + try ef.plt.addSymbol(ref, ef); + } else if (sym.flags.needs_got) { + log.debug("'{s}' needs PLTGOT", .{sym.name(ef)}); + try ef.plt_got.addSymbol(ref, ef); + } else { + log.debug("'{s}' needs PLT", .{sym.name(ef)}); + try ef.plt.addSymbol(ref, ef); + } + } + if (sym.flags.needs_copy_rel and !sym.flags.has_copy_rel) { + log.debug("'{s}' needs COPYREL", .{sym.name(ef)}); + try ef.copy_rel.addSymbol(ref, ef); + } + if (sym.flags.needs_tlsgd) { + log.debug("'{s}' needs TLSGD", .{sym.name(ef)}); + try ef.got.addTlsGdSymbol(ref, ef); + } + if (sym.flags.needs_gottp) { + log.debug("'{s}' needs GOTTP", .{sym.name(ef)}); + try ef.got.addGotTpSymbol(ref, ef); + } + if (sym.flags.needs_tlsdesc) { + log.debug("'{s}' needs TLSDESC", .{sym.name(ef)}); + try ef.got.addTlsDescSymbol(ref, ef); + } + } + }.impl; + + switch (file) { + .zig_object => |x| { + for (x.local_symbols.items, 0..) |idx, i| { + const sym = &x.symbols.items[idx]; + const ref = x.resolveSymbol(@intCast(i), elf_file); + const ref_sym = elf_file.symbol(ref) orelse continue; + if (ref_sym.file(elf_file).?.index() != x.index) continue; + try impl(sym, ref, elf_file); + } + for (x.global_symbols.items, 0..) |idx, i| { + const sym = &x.symbols.items[idx]; + const ref = x.resolveSymbol(@intCast(i | ZigObject.global_symbol_bit), elf_file); + const ref_sym = elf_file.symbol(ref) orelse continue; + if (ref_sym.file(elf_file).?.index() != x.index) continue; + try impl(sym, ref, elf_file); + } + }, + inline else => |x| { + for (x.symbols.items, 0..) |*sym, i| { + const ref = x.resolveSymbol(@intCast(i), elf_file); + const ref_sym = elf_file.symbol(ref) orelse continue; + if (ref_sym.file(elf_file).?.index() != x.index) continue; + try impl(sym, ref, elf_file); + } + }, + } } pub fn atom(file: File, atom_index: Atom.Index) ?*Atom { @@ -239,6 +303,7 @@ pub const File = union(enum) { const std = @import("std"); const elf = std.elf; +const log = std.log.scoped(.link); const Allocator = std.mem.Allocator; const Archive = @import("Archive.zig"); |
