authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-05 21:11:44+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-16 19:33:04+02:00
log5fa90afb646bfba4ca3b23a354ef171708e002e9
tree279a86d1b46d21a1cb3124a9dbbe10e2becbdf16
parentd1446565a1449d1f79edb848bbd8db21ce05c70b

elf: fix synthetic section handling and actually parse DSOs


4 files changed, 68 insertions(+), 20 deletions(-)

src/link/Elf.zig+56-17
...@@ -1678,6 +1678,8 @@ fn parseLibrary(...@@ -1678,6 +1678,8 @@ fn parseLibrary(
16781678
1679 if (Archive.isArchive(in_file)) {1679 if (Archive.isArchive(in_file)) {
1680 try self.parseArchive(in_file, lib.path, must_link, ctx);1680 try self.parseArchive(in_file, lib.path, must_link, ctx);
1681 } else if (SharedObject.isSharedObject(in_file)) {
1682 try self.parseSharedObject(in_file, lib, ctx);
1681 } else return error.UnknownFileType;1683 } else return error.UnknownFileType;
1682}1684}
16831685
...@@ -1732,6 +1734,34 @@ fn parseArchive(...@@ -1732,6 +1734,34 @@ fn parseArchive(
1732 }1734 }
1733}1735}
17341736
1737fn parseSharedObject(
1738 self: *Elf,
1739 in_file: std.fs.File,
1740 lib: SystemLib,
1741 ctx: *ParseErrorCtx,
1742) ParseError!void {
1743 const tracy = trace(@src());
1744 defer tracy.end();
1745
1746 const gpa = self.base.allocator;
1747 const data = try in_file.readToEndAlloc(gpa, std.math.maxInt(u32));
1748 const index = @as(File.Index, @intCast(try self.files.addOne(gpa)));
1749 self.files.set(index, .{ .shared_object = .{
1750 .path = lib.path,
1751 .data = data,
1752 .index = index,
1753 .needed = lib.needed,
1754 .alive = lib.needed,
1755 } });
1756 try self.shared_objects.append(gpa, index);
1757
1758 const shared_object = self.file(index).?.shared_object;
1759 try shared_object.parse(self);
1760
1761 ctx.detected_cpu_arch = shared_object.header.?.e_machine.toTargetCpuArch().?;
1762 if (ctx.detected_cpu_arch != self.base.options.target.cpu.arch) return error.InvalidCpuArch;
1763}
1764
1735/// When resolving symbols, we approach the problem similarly to `mold`.1765/// When resolving symbols, we approach the problem similarly to `mold`.
1736/// 1. Resolve symbols across all objects (including those preemptively extracted archives).1766/// 1. Resolve symbols across all objects (including those preemptively extracted archives).
1737/// 2. Resolve symbols across all shared objects.1767/// 2. Resolve symbols across all shared objects.
...@@ -3437,23 +3467,23 @@ fn addLinkerDefinedSymbols(self: *Elf) !void {...@@ -3437,23 +3467,23 @@ fn addLinkerDefinedSymbols(self: *Elf) !void {
3437 self.rela_iplt_start_index = try linker_defined.addGlobal("__rela_iplt_start", self);3467 self.rela_iplt_start_index = try linker_defined.addGlobal("__rela_iplt_start", self);
3438 self.rela_iplt_end_index = try linker_defined.addGlobal("__rela_iplt_end", self);3468 self.rela_iplt_end_index = try linker_defined.addGlobal("__rela_iplt_end", self);
34393469
3440 // for (self.objects.items) |index| {3470 for (self.objects.items) |index| {
3441 // const object = self.getFile(index).?.object;3471 const object = self.file(index).?.object;
3442 // for (object.atoms.items) |atom_index| {3472 for (object.atoms.items) |atom_index| {
3443 // if (self.getStartStopBasename(atom_index)) |name| {3473 if (self.getStartStopBasename(atom_index)) |name| {
3444 // const gpa = self.base.allocator;3474 const gpa = self.base.allocator;
3445 // try self.start_stop_indexes.ensureUnusedCapacity(gpa, 2);3475 try self.start_stop_indexes.ensureUnusedCapacity(gpa, 2);
34463476
3447 // const start = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name});3477 const start = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name});
3448 // defer gpa.free(start);3478 defer gpa.free(start);
3449 // const stop = try std.fmt.allocPrintZ(gpa, "__stop_{s}", .{name});3479 const stop = try std.fmt.allocPrintZ(gpa, "__stop_{s}", .{name});
3450 // defer gpa.free(stop);3480 defer gpa.free(stop);
34513481
3452 // self.start_stop_indexes.appendAssumeCapacity(try internal.addSyntheticGlobal(start, self));3482 self.start_stop_indexes.appendAssumeCapacity(try linker_defined.addGlobal(start, self));
3453 // self.start_stop_indexes.appendAssumeCapacity(try internal.addSyntheticGlobal(stop, self));3483 self.start_stop_indexes.appendAssumeCapacity(try linker_defined.addGlobal(stop, self));
3454 // }3484 }
3455 // }3485 }
3456 // }3486 }
34573487
3458 linker_defined.resolveSymbols(self);3488 linker_defined.resolveSymbols(self);
3459}3489}
...@@ -5199,6 +5229,15 @@ pub fn isCIdentifier(name: []const u8) bool {...@@ -5199,6 +5229,15 @@ pub fn isCIdentifier(name: []const u8) bool {
5199 return true;5229 return true;
5200}5230}
52015231
5232fn getStartStopBasename(self: *Elf, atom_index: Atom.Index) ?[]const u8 {
5233 const atom_ptr = self.atom(atom_index) orelse return null;
5234 const name = atom_ptr.name(self);
5235 if (atom_ptr.inputShdr(self).sh_flags & elf.SHF_ALLOC != 0 and name.len > 0) {
5236 if (isCIdentifier(name)) return name;
5237 }
5238 return null;
5239}
5240
5202pub fn atom(self: *Elf, atom_index: Atom.Index) ?*Atom {5241pub fn atom(self: *Elf, atom_index: Atom.Index) ?*Atom {
5203 if (atom_index == 0) return null;5242 if (atom_index == 0) return null;
5204 assert(atom_index < self.atoms.items.len);5243 assert(atom_index < self.atoms.items.len);
src/link/Elf/Object.zig+1-1
...@@ -970,7 +970,7 @@ pub const ElfShdr = struct {...@@ -970,7 +970,7 @@ pub const ElfShdr = struct {
970 sh_addralign: u64,970 sh_addralign: u64,
971 sh_entsize: u64,971 sh_entsize: u64,
972972
973 fn fromElf64Shdr(shdr: elf.Elf64_Shdr) error{Overflow}!ElfShdr {973 pub fn fromElf64Shdr(shdr: elf.Elf64_Shdr) error{Overflow}!ElfShdr {
974 return .{974 return .{
975 .sh_name = shdr.sh_name,975 .sh_name = shdr.sh_name,
976 .sh_type = shdr.sh_type,976 .sh_type = shdr.sh_type,
src/link/Elf/SharedObject.zig+2-1
...@@ -33,6 +33,7 @@ pub fn isSharedObject(file: std.fs.File) bool {...@@ -33,6 +33,7 @@ pub fn isSharedObject(file: std.fs.File) bool {
33}33}
3434
35pub fn deinit(self: *SharedObject, allocator: Allocator) void {35pub fn deinit(self: *SharedObject, allocator: Allocator) void {
36 allocator.free(self.data);
36 self.versyms.deinit(allocator);37 self.versyms.deinit(allocator);
37 self.verstrings.deinit(allocator);38 self.verstrings.deinit(allocator);
38 self.symbols.deinit(allocator);39 self.symbols.deinit(allocator);
...@@ -139,7 +140,7 @@ fn initSymtab(self: *SharedObject, elf_file: *Elf) !void {...@@ -139,7 +140,7 @@ fn initSymtab(self: *SharedObject, elf_file: *Elf) !void {
139 defer gpa.free(full_name);140 defer gpa.free(full_name);
140 break :blk try elf_file.strtab.insert(gpa, full_name);141 break :blk try elf_file.strtab.insert(gpa, full_name);
141 } else try elf_file.strtab.insert(gpa, name);142 } else try elf_file.strtab.insert(gpa, name);
142 const gop = try elf_file.getOrCreateGlobal(off);143 const gop = try elf_file.getOrPutGlobal(off);
143 self.symbols.addOneAssumeCapacity().* = gop.index;144 self.symbols.addOneAssumeCapacity().* = gop.index;
144 }145 }
145}146}
src/link/Elf/synthetic_sections.zig+9-1
...@@ -284,8 +284,12 @@ pub const GotSection = struct {...@@ -284,8 +284,12 @@ pub const GotSection = struct {
284 entry.tag = .got;284 entry.tag = .got;
285 entry.symbol_index = sym_index;285 entry.symbol_index = sym_index;
286 const symbol = elf_file.symbol(sym_index);286 const symbol = elf_file.symbol(sym_index);
287 if (symbol.flags.import or symbol.isIFunc(elf_file) or (elf_file.base.options.pic and !symbol.isAbs(elf_file)))287 symbol.flags.has_got = true;
288 if (symbol.flags.import or symbol.isIFunc(elf_file) or
289 (elf_file.base.options.pic and !symbol.isAbs(elf_file)))
290 {
288 got.flags.needs_rela = true;291 got.flags.needs_rela = true;
292 }
289 if (symbol.extra(elf_file)) |extra| {293 if (symbol.extra(elf_file)) |extra| {
290 var new_extra = extra;294 var new_extra = extra;
291 new_extra.got = index;295 new_extra.got = index;
...@@ -310,6 +314,7 @@ pub const GotSection = struct {...@@ -310,6 +314,7 @@ pub const GotSection = struct {
310 entry.tag = .tlsgd;314 entry.tag = .tlsgd;
311 entry.symbol_index = sym_index;315 entry.symbol_index = sym_index;
312 const symbol = elf_file.symbol(sym_index);316 const symbol = elf_file.symbol(sym_index);
317 symbol.flags.has_tlsgd = true;
313 if (symbol.flags.import or elf_file.isDynLib()) got.flags.needs_rela = true;318 if (symbol.flags.import or elf_file.isDynLib()) got.flags.needs_rela = true;
314 if (symbol.extra(elf_file)) |extra| {319 if (symbol.extra(elf_file)) |extra| {
315 var new_extra = extra;320 var new_extra = extra;
...@@ -324,6 +329,7 @@ pub const GotSection = struct {...@@ -324,6 +329,7 @@ pub const GotSection = struct {
324 entry.tag = .gottp;329 entry.tag = .gottp;
325 entry.symbol_index = sym_index;330 entry.symbol_index = sym_index;
326 const symbol = elf_file.symbol(sym_index);331 const symbol = elf_file.symbol(sym_index);
332 symbol.flags.has_gottp = true;
327 if (symbol.flags.import or elf_file.isDynLib()) got.flags.needs_rela = true;333 if (symbol.flags.import or elf_file.isDynLib()) got.flags.needs_rela = true;
328 if (symbol.extra(elf_file)) |extra| {334 if (symbol.extra(elf_file)) |extra| {
329 var new_extra = extra;335 var new_extra = extra;
...@@ -338,6 +344,7 @@ pub const GotSection = struct {...@@ -338,6 +344,7 @@ pub const GotSection = struct {
338 entry.tag = .tlsdesc;344 entry.tag = .tlsdesc;
339 entry.symbol_index = sym_index;345 entry.symbol_index = sym_index;
340 const symbol = elf_file.symbol(sym_index);346 const symbol = elf_file.symbol(sym_index);
347 symbol.flags.has_tlsdesc = true;
341 got.flags.needs_rela = true;348 got.flags.needs_rela = true;
342 if (symbol.extra(elf_file)) |extra| {349 if (symbol.extra(elf_file)) |extra| {
343 var new_extra = extra;350 var new_extra = extra;
...@@ -645,6 +652,7 @@ pub const PltSection = struct {...@@ -645,6 +652,7 @@ pub const PltSection = struct {
645 pub fn addSymbol(plt: *PltSection, sym_index: Symbol.Index, elf_file: *Elf) !void {652 pub fn addSymbol(plt: *PltSection, sym_index: Symbol.Index, elf_file: *Elf) !void {
646 const index = @as(u32, @intCast(plt.symbols.items.len));653 const index = @as(u32, @intCast(plt.symbols.items.len));
647 const symbol = elf_file.symbol(sym_index);654 const symbol = elf_file.symbol(sym_index);
655 symbol.flags.has_plt = true;
648 if (symbol.extra(elf_file)) |extra| {656 if (symbol.extra(elf_file)) |extra| {
649 var new_extra = extra;657 var new_extra = extra;
650 new_extra.plt = index;658 new_extra.plt = index;