| author | |
| committer | |
| log | 5fa90afb646bfba4ca3b23a354ef171708e002e9 |
| tree | 279a86d1b46d21a1cb3124a9dbbe10e2becbdf16 |
| parent | d1446565a1449d1f79edb848bbd8db21ce05c70b |
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( |
| 1678 | 1678 | ||
| 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 | } |
| 1683 | 1685 | ||
| ... | @@ -1732,6 +1734,34 @@ fn parseArchive( | ... | @@ -1732,6 +1734,34 @@ fn parseArchive( |
| 1732 | } | 1734 | } |
| 1733 | } | 1735 | } |
| 1734 | 1736 | ||
| 1737 | fn 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); |
| 3439 | 3469 | ||
| 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); |
| 3446 | 3476 | ||
| 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); |
| 3451 | 3481 | ||
| 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 | } |
| 3457 | 3487 | ||
| 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 | } |
| 5201 | 5231 | ||
| 5232 | fn 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 | |||
| 5202 | pub fn atom(self: *Elf, atom_index: Atom.Index) ?*Atom { | 5241 | pub 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, |
| 972 | 972 | ||
| 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 | } |
| 34 | 34 | ||
| 35 | pub fn deinit(self: *SharedObject, allocator: Allocator) void { | 35 | pub 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; |