authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-02 17:16:27+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-16 19:33:04+02:00
log87602092fa21029c872c217a6544a2c0ced2f34f
tree6609531f38c4eec0f3dbaf18aabcf7da6dccbc8a
parentd565f8bef2b606649e805586cf305ea0da9a8fb2

elf: write .got in bulk after scanning objects


1 files changed, 34 insertions(+), 13 deletions(-)

src/link/Elf.zig+34-13
......@@ -111,7 +111,7 @@ symbols_free_list: std.ArrayListUnmanaged(Symbol.Index) = .{},
111111
112112phdr_table_dirty: bool = false,
113113shdr_table_dirty: bool = false,
114got_dirty: bool = false,
114got_addresses_dirty: bool = false,
115115
116116debug_strtab_dirty: bool = false,
117117debug_abbrev_section_dirty: bool = false,
......@@ -942,7 +942,7 @@ pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void {
942942 // and grow.
943943 {
944944 const dirty_addr = phdr.p_vaddr + phdr.p_memsz;
945 self.got_dirty = for (self.got.entries.items) |entry| {
945 self.got_addresses_dirty = for (self.got.entries.items) |entry| {
946946 if (self.symbol(entry.symbol_index).value >= dirty_addr) break true;
947947 } else false;
948948
......@@ -1333,15 +1333,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
13331333 }
13341334 try self.writeObjects();
13351335
1336 if (self.got_dirty) {
1337 const shdr = &self.shdrs.items[self.got_section_index.?];
1338 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.got.size(self));
1339 defer buffer.deinit();
1340 try self.got.writeAllEntries(self, buffer.writer());
1341 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
1342 self.got_dirty = false;
1343 }
1344
13451336 // Look for entry address in objects if not set by the incremental compiler.
13461337 if (self.entry_addr == null) {
13471338 const entry: ?[]const u8 = entry: {
......@@ -1541,6 +1532,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
15411532 assert(!self.shdr_table_dirty);
15421533 assert(!self.debug_strtab_dirty);
15431534 assert(!self.got.dirty);
1535 assert(!self.got_addresses_dirty);
15441536}
15451537
15461538const ParseError = error{
......@@ -1789,8 +1781,7 @@ fn scanRelocs(self: *Elf) !void {
17891781 if (sym.flags.needs_got) {
17901782 log.debug("'{s}' needs GOT", .{sym.name(self)});
17911783 // TODO how can we tell we need to write it again, aka the entry is dirty?
1792 const gop = try sym.getOrCreateGotEntry(@intCast(sym_index), self);
1793 try self.got.writeEntry(self, gop.index);
1784 _ = try sym.getOrCreateGotEntry(@intCast(sym_index), self);
17941785 }
17951786 }
17961787}
......@@ -3472,6 +3463,15 @@ fn initSyntheticSections(self: *Elf) !void {
34723463 .p64 => false,
34733464 };
34743465
3466 if (self.got.entries.items.len > 0 and self.got_section_index == null) {
3467 self.got_section_index = try self.addSection(.{
3468 .name = ".got",
3469 .type = elf.SHT_PROGBITS,
3470 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
3471 .addralign = self.ptrWidthBytes(),
3472 });
3473 }
3474
34753475 if (self.symtab_section_index == null) {
34763476 self.symtab_section_index = try self.addSection(.{
34773477 .name = ".symtab",
......@@ -3499,9 +3499,18 @@ fn initSyntheticSections(self: *Elf) !void {
34993499}
35003500
35013501fn updateSyntheticSectionSizes(self: *Elf) !void {
3502 if (self.got_section_index) |index| {
3503 if (self.got.dirty) {
3504 try self.growAllocSection(index, self.got.size(self));
3505 self.got.dirty = false;
3506 self.got_addresses_dirty = true;
3507 }
3508 }
3509
35023510 if (self.symtab_section_index != null) {
35033511 try self.updateSymtabSize();
35043512 }
3513
35053514 if (self.strtab_section_index) |index| {
35063515 // TODO I don't really this here but we need it to add symbol names from GOT and other synthetic
35073516 // sections into .strtab for easier debugging.
......@@ -3510,6 +3519,7 @@ fn updateSyntheticSectionSizes(self: *Elf) !void {
35103519 }
35113520 try self.growNonAllocSection(index, self.strtab.buffer.items.len, 1, false);
35123521 }
3522
35133523 if (self.shstrtab_section_index) |index| {
35143524 try self.growNonAllocSection(index, self.shstrtab.buffer.items.len, 1, false);
35153525 }
......@@ -3560,14 +3570,25 @@ fn updateSymtabSize(self: *Elf) !void {
35603570}
35613571
35623572fn writeSyntheticSections(self: *Elf) !void {
3573 if (self.got_addresses_dirty) {
3574 const shdr = &self.shdrs.items[self.got_section_index.?];
3575 var buffer = try std.ArrayList(u8).initCapacity(self.base.allocator, self.got.size(self));
3576 defer buffer.deinit();
3577 try self.got.writeAllEntries(self, buffer.writer());
3578 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
3579 self.got_addresses_dirty = false;
3580 }
3581
35633582 if (self.shstrtab_section_index) |index| {
35643583 const shdr = self.shdrs.items[index];
35653584 try self.base.file.?.pwriteAll(self.shstrtab.buffer.items, shdr.sh_offset);
35663585 }
3586
35673587 if (self.strtab_section_index) |index| {
35683588 const shdr = self.shdrs.items[index];
35693589 try self.base.file.?.pwriteAll(self.strtab.buffer.items, shdr.sh_offset);
35703590 }
3591
35713592 if (self.symtab_section_index) |_| {
35723593 try self.writeSymtab();
35733594 }