| author | |
| committer | |
| log | 137d43c0ea77d5cc21040eadbd38fdfd945a3216 |
| tree | d0317c251f8fbd503e8c35d441123200fb16b186 |
| parent | 26da7c8207ff73927bcc8d5608703175074e266f |
5 files changed, 92 insertions(+), 116 deletions(-)
src/link/Elf.zig+13-6| ... | ... | @@ -2060,6 +2060,9 @@ fn scanRelocs(self: *Elf) !void { |
| 2060 | 2060 | for (self.objects.items) |index| { |
| 2061 | 2061 | try self.file(index).?.createSymbolIndirection(self); |
| 2062 | 2062 | } |
| 2063 | for (self.shared_objects.items) |index| { | |
| 2064 | try self.file(index).?.createSymbolIndirection(self); | |
| 2065 | } | |
| 2063 | 2066 | if (self.got.flags.needs_tlsld) { |
| 2064 | 2067 | log.debug("program needs TLSLD", .{}); |
| 2065 | 2068 | try self.got.addTlsLdSymbol(self); |
| ... | ... | @@ -4431,11 +4434,13 @@ pub fn updateSymtabSize(self: *Elf) !void { |
| 4431 | 4434 | strsize += ctx.strsize; |
| 4432 | 4435 | } |
| 4433 | 4436 | |
| 4434 | if (self.zig_got_section_index) |_| { | |
| 4435 | self.zig_got.output_symtab_ctx.ilocal = nlocals + 1; | |
| 4436 | self.zig_got.updateSymtabSize(self); | |
| 4437 | nlocals += self.zig_got.output_symtab_ctx.nlocals; | |
| 4438 | strsize += self.zig_got.output_symtab_ctx.strsize; | |
| 4437 | if (self.zigObjectPtr()) |_| { | |
| 4438 | if (self.zig_got_section_index) |_| { | |
| 4439 | self.zig_got.output_symtab_ctx.ilocal = nlocals + 1; | |
| 4440 | self.zig_got.updateSymtabSize(self); | |
| 4441 | nlocals += self.zig_got.output_symtab_ctx.nlocals; | |
| 4442 | strsize += self.zig_got.output_symtab_ctx.strsize; | |
| 4443 | } | |
| 4439 | 4444 | } |
| 4440 | 4445 | |
| 4441 | 4446 | if (self.got_section_index) |_| { |
| ... | ... | @@ -4574,7 +4579,9 @@ fn writeSyntheticSections(self: *Elf) !void { |
| 4574 | 4579 | const shdr = self.shdrs.items[shndx]; |
| 4575 | 4580 | try self.got.addRela(self); |
| 4576 | 4581 | try self.copy_rel.addRela(self); |
| 4577 | try self.zig_got.addRela(self); | |
| 4582 | if (self.zigObjectPtr()) |_| { | |
| 4583 | try self.zig_got.addRela(self); | |
| 4584 | } | |
| 4578 | 4585 | self.sortRelaDyn(); |
| 4579 | 4586 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.rela_dyn.items), shdr.sh_offset); |
| 4580 | 4587 | } |
src/link/Elf/Object.zig-45| ... | ... | @@ -561,51 +561,6 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void { |
| 561 | 561 | } |
| 562 | 562 | } |
| 563 | 563 | |
| 564 | pub fn createSymbolIndirection(self: *Object, elf_file: *Elf) !void { | |
| 565 | for (self.symbols.items, 0..) |*sym, i| { | |
| 566 | const ref = self.resolveSymbol(@intCast(i), elf_file); | |
| 567 | const ref_sym = elf_file.symbol(ref) orelse continue; | |
| 568 | if (ref_sym.file(elf_file).?.index() != self.index) continue; | |
| 569 | if (!sym.isLocal(elf_file) and !sym.flags.has_dynamic) { | |
| 570 | log.debug("'{s}' is non-local", .{sym.name(elf_file)}); | |
| 571 | try elf_file.dynsym.addSymbol(ref, elf_file); | |
| 572 | } | |
| 573 | if (sym.flags.needs_got) { | |
| 574 | log.debug("'{s}' needs GOT", .{sym.name(elf_file)}); | |
| 575 | _ = try elf_file.got.addGotSymbol(ref, elf_file); | |
| 576 | } | |
| 577 | if (sym.flags.needs_plt) { | |
| 578 | if (sym.flags.is_canonical) { | |
| 579 | log.debug("'{s}' needs CPLT", .{sym.name(elf_file)}); | |
| 580 | sym.flags.@"export" = true; | |
| 581 | try elf_file.plt.addSymbol(ref, elf_file); | |
| 582 | } else if (sym.flags.needs_got) { | |
| 583 | log.debug("'{s}' needs PLTGOT", .{sym.name(elf_file)}); | |
| 584 | try elf_file.plt_got.addSymbol(ref, elf_file); | |
| 585 | } else { | |
| 586 | log.debug("'{s}' needs PLT", .{sym.name(elf_file)}); | |
| 587 | try elf_file.plt.addSymbol(ref, elf_file); | |
| 588 | } | |
| 589 | } | |
| 590 | if (sym.flags.needs_copy_rel and !sym.flags.has_copy_rel) { | |
| 591 | log.debug("'{s}' needs COPYREL", .{sym.name(elf_file)}); | |
| 592 | try elf_file.copy_rel.addSymbol(ref, elf_file); | |
| 593 | } | |
| 594 | if (sym.flags.needs_tlsgd) { | |
| 595 | log.debug("'{s}' needs TLSGD", .{sym.name(elf_file)}); | |
| 596 | try elf_file.got.addTlsGdSymbol(ref, elf_file); | |
| 597 | } | |
| 598 | if (sym.flags.needs_gottp) { | |
| 599 | log.debug("'{s}' needs GOTTP", .{sym.name(elf_file)}); | |
| 600 | try elf_file.got.addGotTpSymbol(ref, elf_file); | |
| 601 | } | |
| 602 | if (sym.flags.needs_tlsdesc) { | |
| 603 | log.debug("'{s}' needs TLSDESC", .{sym.name(elf_file)}); | |
| 604 | try elf_file.got.addTlsDescSymbol(ref, elf_file); | |
| 605 | } | |
| 606 | } | |
| 607 | } | |
| 608 | ||
| 609 | 564 | pub fn resolveSymbols(self: *Object, elf_file: *Elf) !void { |
| 610 | 565 | const gpa = elf_file.base.comp.gpa; |
| 611 | 566 |
src/link/Elf/SharedObject.zig+10-3| ... | ... | @@ -219,9 +219,7 @@ fn initSymbols(self: *SharedObject, elf_file: *Elf, opts: struct { |
| 219 | 219 | self.versionString(self.versyms.items[i]), |
| 220 | 220 | }); |
| 221 | 221 | defer gpa.free(mangled); |
| 222 | const name_off = @as(u32, @intCast(self.strtab.items.len)); | |
| 223 | try self.strtab.writer(gpa).print("{s}\x00", .{mangled}); | |
| 224 | break :blk name_off; | |
| 222 | break :blk try self.addString(gpa, mangled); | |
| 225 | 223 | } else sym.st_name; |
| 226 | 224 | const out_esym_index: u32 = @intCast(self.symtab.items.len); |
| 227 | 225 | const out_esym = self.symtab.addOneAssumeCapacity(); |
| ... | ... | @@ -230,6 +228,7 @@ fn initSymbols(self: *SharedObject, elf_file: *Elf, opts: struct { |
| 230 | 228 | const out_sym_index = self.addSymbolAssumeCapacity(); |
| 231 | 229 | const out_sym = &self.symbols.items[out_sym_index]; |
| 232 | 230 | out_sym.value = @intCast(out_esym.st_value); |
| 231 | out_sym.name_offset = name_off; | |
| 233 | 232 | out_sym.ref = .{ .index = 0, .file = 0 }; |
| 234 | 233 | out_sym.esym_index = out_esym_index; |
| 235 | 234 | 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 |
| 394 | 393 | return aliases.items[start..end]; |
| 395 | 394 | } |
| 396 | 395 | |
| 396 | fn addString(self: *SharedObject, allocator: Allocator, str: []const u8) !u32 { | |
| 397 | const off: u32 = @intCast(self.strtab.items.len); | |
| 398 | try self.strtab.ensureUnusedCapacity(allocator, str.len + 1); | |
| 399 | self.strtab.appendSliceAssumeCapacity(str); | |
| 400 | self.strtab.appendAssumeCapacity(0); | |
| 401 | return off; | |
| 402 | } | |
| 403 | ||
| 397 | 404 | pub fn getString(self: SharedObject, off: u32) [:0]const u8 { |
| 398 | 405 | assert(off < self.strtab.items.len); |
| 399 | 406 | return mem.sliceTo(@as([*:0]const u8, @ptrCast(self.strtab.items.ptr + off)), 0); |
src/link/Elf/ZigObject.zig-58| ... | ... | @@ -442,64 +442,6 @@ pub fn scanRelocs(self: *ZigObject, elf_file: *Elf, undefs: anytype) !void { |
| 442 | 442 | } |
| 443 | 443 | } |
| 444 | 444 | |
| 445 | pub fn createSymbolIndirection(self: *ZigObject, elf_file: *Elf) !void { | |
| 446 | const impl = struct { | |
| 447 | fn impl(sym: *Symbol, ref: Elf.Ref, ef: *Elf) !void { | |
| 448 | if (!sym.isLocal(ef) and !sym.flags.has_dynamic) { | |
| 449 | log.debug("'{s}' is non-local", .{sym.name(ef)}); | |
| 450 | try ef.dynsym.addSymbol(ref, ef); | |
| 451 | } | |
| 452 | if (sym.flags.needs_got) { | |
| 453 | log.debug("'{s}' needs GOT", .{sym.name(ef)}); | |
| 454 | _ = try ef.got.addGotSymbol(ref, ef); | |
| 455 | } | |
| 456 | if (sym.flags.needs_plt) { | |
| 457 | if (sym.flags.is_canonical) { | |
| 458 | log.debug("'{s}' needs CPLT", .{sym.name(ef)}); | |
| 459 | sym.flags.@"export" = true; | |
| 460 | try ef.plt.addSymbol(ref, ef); | |
| 461 | } else if (sym.flags.needs_got) { | |
| 462 | log.debug("'{s}' needs PLTGOT", .{sym.name(ef)}); | |
| 463 | try ef.plt_got.addSymbol(ref, ef); | |
| 464 | } else { | |
| 465 | log.debug("'{s}' needs PLT", .{sym.name(ef)}); | |
| 466 | try ef.plt.addSymbol(ref, ef); | |
| 467 | } | |
| 468 | } | |
| 469 | if (sym.flags.needs_copy_rel and !sym.flags.has_copy_rel) { | |
| 470 | log.debug("'{s}' needs COPYREL", .{sym.name(ef)}); | |
| 471 | try ef.copy_rel.addSymbol(ref, ef); | |
| 472 | } | |
| 473 | if (sym.flags.needs_tlsgd) { | |
| 474 | log.debug("'{s}' needs TLSGD", .{sym.name(ef)}); | |
| 475 | try ef.got.addTlsGdSymbol(ref, ef); | |
| 476 | } | |
| 477 | if (sym.flags.needs_gottp) { | |
| 478 | log.debug("'{s}' needs GOTTP", .{sym.name(ef)}); | |
| 479 | try ef.got.addGotTpSymbol(ref, ef); | |
| 480 | } | |
| 481 | if (sym.flags.needs_tlsdesc) { | |
| 482 | log.debug("'{s}' needs TLSDESC", .{sym.name(ef)}); | |
| 483 | try ef.got.addTlsDescSymbol(ref, ef); | |
| 484 | } | |
| 485 | } | |
| 486 | }.impl; | |
| 487 | for (self.local_symbols.items, 0..) |index, i| { | |
| 488 | const sym = &self.symbols.items[index]; | |
| 489 | const ref = self.resolveSymbol(@intCast(i), elf_file); | |
| 490 | const ref_sym = elf_file.symbol(ref) orelse continue; | |
| 491 | if (ref_sym.file(elf_file).?.index() != self.index) continue; | |
| 492 | try impl(sym, ref, elf_file); | |
| 493 | } | |
| 494 | for (self.global_symbols.items, 0..) |index, i| { | |
| 495 | const sym = &self.symbols.items[index]; | |
| 496 | const ref = self.resolveSymbol(@intCast(i | global_symbol_bit), elf_file); | |
| 497 | const ref_sym = elf_file.symbol(ref) orelse continue; | |
| 498 | if (ref_sym.file(elf_file).?.index() != self.index) continue; | |
| 499 | try impl(sym, ref, elf_file); | |
| 500 | } | |
| 501 | } | |
| 502 | ||
| 503 | 445 | pub fn markLive(self: *ZigObject, elf_file: *Elf) void { |
| 504 | 446 | for (self.global_symbols.items, 0..) |index, i| { |
| 505 | 447 | const global = self.symbols.items[index]; |
src/link/Elf/file.zig+69-4| ... | ... | @@ -101,10 +101,74 @@ pub const File = union(enum) { |
| 101 | 101 | } |
| 102 | 102 | |
| 103 | 103 | pub fn createSymbolIndirection(file: File, elf_file: *Elf) !void { |
| 104 | return switch (file) { | |
| 105 | .linker_defined, .shared_object => unreachable, | |
| 106 | inline else => |x| x.createSymbolIndirection(elf_file), | |
| 107 | }; | |
| 104 | const impl = struct { | |
| 105 | fn impl(sym: *Symbol, ref: Elf.Ref, ef: *Elf) !void { | |
| 106 | if (!sym.isLocal(ef) and !sym.flags.has_dynamic) { | |
| 107 | log.debug("'{s}' is non-local", .{sym.name(ef)}); | |
| 108 | try ef.dynsym.addSymbol(ref, ef); | |
| 109 | } | |
| 110 | if (sym.flags.needs_got) { | |
| 111 | log.debug("'{s}' needs GOT", .{sym.name(ef)}); | |
| 112 | _ = try ef.got.addGotSymbol(ref, ef); | |
| 113 | } | |
| 114 | if (sym.flags.needs_plt) { | |
| 115 | if (sym.flags.is_canonical) { | |
| 116 | log.debug("'{s}' needs CPLT", .{sym.name(ef)}); | |
| 117 | sym.flags.@"export" = true; | |
| 118 | try ef.plt.addSymbol(ref, ef); | |
| 119 | } else if (sym.flags.needs_got) { | |
| 120 | log.debug("'{s}' needs PLTGOT", .{sym.name(ef)}); | |
| 121 | try ef.plt_got.addSymbol(ref, ef); | |
| 122 | } else { | |
| 123 | log.debug("'{s}' needs PLT", .{sym.name(ef)}); | |
| 124 | try ef.plt.addSymbol(ref, ef); | |
| 125 | } | |
| 126 | } | |
| 127 | if (sym.flags.needs_copy_rel and !sym.flags.has_copy_rel) { | |
| 128 | log.debug("'{s}' needs COPYREL", .{sym.name(ef)}); | |
| 129 | try ef.copy_rel.addSymbol(ref, ef); | |
| 130 | } | |
| 131 | if (sym.flags.needs_tlsgd) { | |
| 132 | log.debug("'{s}' needs TLSGD", .{sym.name(ef)}); | |
| 133 | try ef.got.addTlsGdSymbol(ref, ef); | |
| 134 | } | |
| 135 | if (sym.flags.needs_gottp) { | |
| 136 | log.debug("'{s}' needs GOTTP", .{sym.name(ef)}); | |
| 137 | try ef.got.addGotTpSymbol(ref, ef); | |
| 138 | } | |
| 139 | if (sym.flags.needs_tlsdesc) { | |
| 140 | log.debug("'{s}' needs TLSDESC", .{sym.name(ef)}); | |
| 141 | try ef.got.addTlsDescSymbol(ref, ef); | |
| 142 | } | |
| 143 | } | |
| 144 | }.impl; | |
| 145 | ||
| 146 | switch (file) { | |
| 147 | .zig_object => |x| { | |
| 148 | for (x.local_symbols.items, 0..) |idx, i| { | |
| 149 | const sym = &x.symbols.items[idx]; | |
| 150 | const ref = x.resolveSymbol(@intCast(i), elf_file); | |
| 151 | const ref_sym = elf_file.symbol(ref) orelse continue; | |
| 152 | if (ref_sym.file(elf_file).?.index() != x.index) continue; | |
| 153 | try impl(sym, ref, elf_file); | |
| 154 | } | |
| 155 | for (x.global_symbols.items, 0..) |idx, i| { | |
| 156 | const sym = &x.symbols.items[idx]; | |
| 157 | const ref = x.resolveSymbol(@intCast(i | ZigObject.global_symbol_bit), elf_file); | |
| 158 | const ref_sym = elf_file.symbol(ref) orelse continue; | |
| 159 | if (ref_sym.file(elf_file).?.index() != x.index) continue; | |
| 160 | try impl(sym, ref, elf_file); | |
| 161 | } | |
| 162 | }, | |
| 163 | inline else => |x| { | |
| 164 | for (x.symbols.items, 0..) |*sym, i| { | |
| 165 | const ref = x.resolveSymbol(@intCast(i), elf_file); | |
| 166 | const ref_sym = elf_file.symbol(ref) orelse continue; | |
| 167 | if (ref_sym.file(elf_file).?.index() != x.index) continue; | |
| 168 | try impl(sym, ref, elf_file); | |
| 169 | } | |
| 170 | }, | |
| 171 | } | |
| 108 | 172 | } |
| 109 | 173 | |
| 110 | 174 | pub fn atom(file: File, atom_index: Atom.Index) ?*Atom { |
| ... | ... | @@ -239,6 +303,7 @@ pub const File = union(enum) { |
| 239 | 303 | |
| 240 | 304 | const std = @import("std"); |
| 241 | 305 | const elf = std.elf; |
| 306 | const log = std.log.scoped(.link); | |
| 242 | 307 | |
| 243 | 308 | const Allocator = std.mem.Allocator; |
| 244 | 309 | const Archive = @import("Archive.zig"); |