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) = .{},...@@ -111,7 +111,7 @@ symbols_free_list: std.ArrayListUnmanaged(Symbol.Index) = .{},
111111
112phdr_table_dirty: bool = false,112phdr_table_dirty: bool = false,
113shdr_table_dirty: bool = false,113shdr_table_dirty: bool = false,
114got_dirty: bool = false,114got_addresses_dirty: bool = false,
115115
116debug_strtab_dirty: bool = false,116debug_strtab_dirty: bool = false,
117debug_abbrev_section_dirty: bool = false,117debug_abbrev_section_dirty: bool = false,
...@@ -942,7 +942,7 @@ pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void {...@@ -942,7 +942,7 @@ pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void {
942 // and grow.942 // and grow.
943 {943 {
944 const dirty_addr = phdr.p_vaddr + phdr.p_memsz;944 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| {
946 if (self.symbol(entry.symbol_index).value >= dirty_addr) break true;946 if (self.symbol(entry.symbol_index).value >= dirty_addr) break true;
947 } else false;947 } else false;
948948
...@@ -1333,15 +1333,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1333,15 +1333,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1333 }1333 }
1334 try self.writeObjects();1334 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
1345 // Look for entry address in objects if not set by the incremental compiler.1336 // Look for entry address in objects if not set by the incremental compiler.
1346 if (self.entry_addr == null) {1337 if (self.entry_addr == null) {
1347 const entry: ?[]const u8 = entry: {1338 const entry: ?[]const u8 = entry: {
...@@ -1541,6 +1532,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1541,6 +1532,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1541 assert(!self.shdr_table_dirty);1532 assert(!self.shdr_table_dirty);
1542 assert(!self.debug_strtab_dirty);1533 assert(!self.debug_strtab_dirty);
1543 assert(!self.got.dirty);1534 assert(!self.got.dirty);
1535 assert(!self.got_addresses_dirty);
1544}1536}
15451537
1546const ParseError = error{1538const ParseError = error{
...@@ -1789,8 +1781,7 @@ fn scanRelocs(self: *Elf) !void {...@@ -1789,8 +1781,7 @@ fn scanRelocs(self: *Elf) !void {
1789 if (sym.flags.needs_got) {1781 if (sym.flags.needs_got) {
1790 log.debug("'{s}' needs GOT", .{sym.name(self)});1782 log.debug("'{s}' needs GOT", .{sym.name(self)});
1791 // TODO how can we tell we need to write it again, aka the entry is dirty?1783 // 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);1784 _ = try sym.getOrCreateGotEntry(@intCast(sym_index), self);
1793 try self.got.writeEntry(self, gop.index);
1794 }1785 }
1795 }1786 }
1796}1787}
...@@ -3472,6 +3463,15 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -3472,6 +3463,15 @@ fn initSyntheticSections(self: *Elf) !void {
3472 .p64 => false,3463 .p64 => false,
3473 };3464 };
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
3475 if (self.symtab_section_index == null) {3475 if (self.symtab_section_index == null) {
3476 self.symtab_section_index = try self.addSection(.{3476 self.symtab_section_index = try self.addSection(.{
3477 .name = ".symtab",3477 .name = ".symtab",
...@@ -3499,9 +3499,18 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -3499,9 +3499,18 @@ fn initSyntheticSections(self: *Elf) !void {
3499}3499}
35003500
3501fn updateSyntheticSectionSizes(self: *Elf) !void {3501fn 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
3502 if (self.symtab_section_index != null) {3510 if (self.symtab_section_index != null) {
3503 try self.updateSymtabSize();3511 try self.updateSymtabSize();
3504 }3512 }
3513
3505 if (self.strtab_section_index) |index| {3514 if (self.strtab_section_index) |index| {
3506 // TODO I don't really this here but we need it to add symbol names from GOT and other synthetic3515 // TODO I don't really this here but we need it to add symbol names from GOT and other synthetic
3507 // sections into .strtab for easier debugging.3516 // sections into .strtab for easier debugging.
...@@ -3510,6 +3519,7 @@ fn updateSyntheticSectionSizes(self: *Elf) !void {...@@ -3510,6 +3519,7 @@ fn updateSyntheticSectionSizes(self: *Elf) !void {
3510 }3519 }
3511 try self.growNonAllocSection(index, self.strtab.buffer.items.len, 1, false);3520 try self.growNonAllocSection(index, self.strtab.buffer.items.len, 1, false);
3512 }3521 }
3522
3513 if (self.shstrtab_section_index) |index| {3523 if (self.shstrtab_section_index) |index| {
3514 try self.growNonAllocSection(index, self.shstrtab.buffer.items.len, 1, false);3524 try self.growNonAllocSection(index, self.shstrtab.buffer.items.len, 1, false);
3515 }3525 }
...@@ -3560,14 +3570,25 @@ fn updateSymtabSize(self: *Elf) !void {...@@ -3560,14 +3570,25 @@ fn updateSymtabSize(self: *Elf) !void {
3560}3570}
35613571
3562fn writeSyntheticSections(self: *Elf) !void {3572fn 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
3563 if (self.shstrtab_section_index) |index| {3582 if (self.shstrtab_section_index) |index| {
3564 const shdr = self.shdrs.items[index];3583 const shdr = self.shdrs.items[index];
3565 try self.base.file.?.pwriteAll(self.shstrtab.buffer.items, shdr.sh_offset);3584 try self.base.file.?.pwriteAll(self.shstrtab.buffer.items, shdr.sh_offset);
3566 }3585 }
3586
3567 if (self.strtab_section_index) |index| {3587 if (self.strtab_section_index) |index| {
3568 const shdr = self.shdrs.items[index];3588 const shdr = self.shdrs.items[index];
3569 try self.base.file.?.pwriteAll(self.strtab.buffer.items, shdr.sh_offset);3589 try self.base.file.?.pwriteAll(self.strtab.buffer.items, shdr.sh_offset);
3570 }3590 }
3591
3571 if (self.symtab_section_index) |_| {3592 if (self.symtab_section_index) |_| {
3572 try self.writeSymtab();3593 try self.writeSymtab();
3573 }3594 }