authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-09-10 21:58:42+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-09-10 21:58:45+02:00
log4b082d89c9cd6e40259701f21344d55eef2a8d2e
tree6ec2c1c6f9b906f843f9279e11e43acde0db413c
parenta3ce011408802ba81cb52753c65dbcd2254b9e75

elf: decouple notion of atom free list from shdrs

Not every section will have the need for such a free list.

4 files changed, 250 insertions(+), 286 deletions(-)

src/link/Dwarf.zig+12-12
......@@ -1108,7 +1108,7 @@ pub fn commitDeclState(
11081108 switch (self.bin_file.tag) {
11091109 .elf => {
11101110 const elf_file = self.bin_file.cast(File.Elf).?;
1111 const debug_line_sect = &elf_file.sections.items(.shdr)[elf_file.debug_line_section_index.?];
1111 const debug_line_sect = &elf_file.shdrs.items[elf_file.debug_line_section_index.?];
11121112 const file_pos = debug_line_sect.sh_offset + src_fn.off;
11131113 try pwriteDbgLineNops(elf_file.base.file.?, file_pos, 0, &[0]u8{}, src_fn.len);
11141114 },
......@@ -1170,7 +1170,7 @@ pub fn commitDeclState(
11701170 const elf_file = self.bin_file.cast(File.Elf).?;
11711171 const shdr_index = elf_file.debug_line_section_index.?;
11721172 try elf_file.growNonAllocSection(shdr_index, needed_size, 1, true);
1173 const debug_line_sect = elf_file.sections.items(.shdr)[shdr_index];
1173 const debug_line_sect = elf_file.shdrs.items[shdr_index];
11741174 const file_pos = debug_line_sect.sh_offset + src_fn.off;
11751175 try pwriteDbgLineNops(
11761176 elf_file.base.file.?,
......@@ -1337,7 +1337,7 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, atom_index: Atom.Index, len: u32)
13371337 switch (self.bin_file.tag) {
13381338 .elf => {
13391339 const elf_file = self.bin_file.cast(File.Elf).?;
1340 const debug_info_sect = &elf_file.sections.items(.shdr)[elf_file.debug_info_section_index.?];
1340 const debug_info_sect = &elf_file.shdrs.items[elf_file.debug_info_section_index.?];
13411341 const file_pos = debug_info_sect.sh_offset + atom.off;
13421342 try pwriteDbgInfoNops(elf_file.base.file.?, file_pos, 0, &[0]u8{}, atom.len, false);
13431343 },
......@@ -1415,7 +1415,7 @@ fn writeDeclDebugInfo(self: *Dwarf, atom_index: Atom.Index, dbg_info_buf: []cons
14151415 const elf_file = self.bin_file.cast(File.Elf).?;
14161416 const shdr_index = elf_file.debug_info_section_index.?;
14171417 try elf_file.growNonAllocSection(shdr_index, needed_size, 1, true);
1418 const debug_info_sect = elf_file.sections.items(.shdr)[shdr_index];
1418 const debug_info_sect = &elf_file.shdrs.items[shdr_index];
14191419 const file_pos = debug_info_sect.sh_offset + atom.off;
14201420 try pwriteDbgInfoNops(
14211421 elf_file.base.file.?,
......@@ -1496,7 +1496,7 @@ pub fn updateDeclLineNumber(self: *Dwarf, mod: *Module, decl_index: Module.Decl.
14961496 switch (self.bin_file.tag) {
14971497 .elf => {
14981498 const elf_file = self.bin_file.cast(File.Elf).?;
1499 const shdr = elf_file.sections.items(.shdr)[elf_file.debug_line_section_index.?];
1499 const shdr = elf_file.shdrs.items[elf_file.debug_line_section_index.?];
15001500 const file_pos = shdr.sh_offset + atom.off + self.getRelocDbgLineOff();
15011501 try elf_file.base.file.?.pwriteAll(&data, file_pos);
15021502 },
......@@ -1713,7 +1713,7 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void {
17131713 const elf_file = self.bin_file.cast(File.Elf).?;
17141714 const shdr_index = elf_file.debug_abbrev_section_index.?;
17151715 try elf_file.growNonAllocSection(shdr_index, needed_size, 1, false);
1716 const debug_abbrev_sect = elf_file.sections.items(.shdr)[shdr_index];
1716 const debug_abbrev_sect = &elf_file.shdrs.items[shdr_index];
17171717 const file_pos = debug_abbrev_sect.sh_offset + abbrev_offset;
17181718 try elf_file.base.file.?.pwriteAll(&abbrev_buf, file_pos);
17191719 },
......@@ -1828,7 +1828,7 @@ pub fn writeDbgInfoHeader(self: *Dwarf, module: *Module, low_pc: u64, high_pc: u
18281828 switch (self.bin_file.tag) {
18291829 .elf => {
18301830 const elf_file = self.bin_file.cast(File.Elf).?;
1831 const debug_info_sect = elf_file.sections.items(.shdr)[elf_file.debug_info_section_index.?];
1831 const debug_info_sect = &elf_file.shdrs.items[elf_file.debug_info_section_index.?];
18321832 const file_pos = debug_info_sect.sh_offset;
18331833 try pwriteDbgInfoNops(elf_file.base.file.?, file_pos, 0, di_buf.items, jmp_amt, false);
18341834 },
......@@ -2147,7 +2147,7 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void {
21472147 const elf_file = self.bin_file.cast(File.Elf).?;
21482148 const shdr_index = elf_file.debug_aranges_section_index.?;
21492149 try elf_file.growNonAllocSection(shdr_index, needed_size, 16, false);
2150 const debug_aranges_sect = elf_file.sections.items(.shdr)[shdr_index];
2150 const debug_aranges_sect = &elf_file.shdrs.items[shdr_index];
21512151 const file_pos = debug_aranges_sect.sh_offset;
21522152 try elf_file.base.file.?.pwriteAll(di_buf.items, file_pos);
21532153 },
......@@ -2312,9 +2312,9 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {
23122312 .elf => {
23132313 const elf_file = self.bin_file.cast(File.Elf).?;
23142314 const shdr_index = elf_file.debug_line_section_index.?;
2315 const needed_size = elf_file.sections.items(.shdr)[shdr_index].sh_size + delta;
2315 const needed_size = elf_file.shdrs.items[shdr_index].sh_size + delta;
23162316 try elf_file.growNonAllocSection(shdr_index, needed_size, 1, true);
2317 const file_pos = elf_file.sections.items(.shdr)[shdr_index].sh_offset + first_fn.off;
2317 const file_pos = elf_file.shdrs.items[shdr_index].sh_offset + first_fn.off;
23182318
23192319 const amt = try elf_file.base.file.?.preadAll(buffer, file_pos);
23202320 if (amt != buffer.len) return error.InputOutput;
......@@ -2377,7 +2377,7 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {
23772377 switch (self.bin_file.tag) {
23782378 .elf => {
23792379 const elf_file = self.bin_file.cast(File.Elf).?;
2380 const debug_line_sect = elf_file.sections.items(.shdr)[elf_file.debug_line_section_index.?];
2380 const debug_line_sect = &elf_file.shdrs.items[elf_file.debug_line_section_index.?];
23812381 const file_pos = debug_line_sect.sh_offset;
23822382 try pwriteDbgLineNops(elf_file.base.file.?, file_pos, 0, di_buf.items, jmp_amt);
23832383 },
......@@ -2500,7 +2500,7 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {
25002500 switch (self.bin_file.tag) {
25012501 .elf => {
25022502 const elf_file = self.bin_file.cast(File.Elf).?;
2503 const debug_info_sect = &elf_file.sections.items(.shdr)[elf_file.debug_info_section_index.?];
2503 const debug_info_sect = &elf_file.shdrs.items[elf_file.debug_info_section_index.?];
25042504 break :blk debug_info_sect.sh_offset;
25052505 },
25062506 .macho => {
src/link/Elf.zig+229-267
......@@ -12,7 +12,10 @@ linker_defined_index: ?File.Index = null,
1212
1313/// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write.
1414/// Same order as in the file.
15sections: std.MultiArrayList(Section) = .{},
15shdrs: std.ArrayListUnmanaged(elf.Elf64_Shdr) = .{},
16/// Given index to a section, pulls index of containing phdr if any.
17phdr_to_shdr_table: std.AutoHashMapUnmanaged(u16, u16) = .{},
18/// File offset into the shdr table.
1619shdr_table_offset: ?u64 = null,
1720
1821/// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write.
......@@ -85,7 +88,6 @@ symbols: std.ArrayListUnmanaged(Symbol) = .{},
8588symbols_extra: std.ArrayListUnmanaged(u32) = .{},
8689resolver: std.AutoArrayHashMapUnmanaged(u32, Symbol.Index) = .{},
8790unresolved: std.AutoArrayHashMapUnmanaged(u32, void) = .{},
88
8991symbols_free_list: std.ArrayListUnmanaged(Symbol.Index) = .{},
9092
9193phdr_table_dirty: bool = false,
......@@ -109,6 +111,8 @@ decls: std.AutoHashMapUnmanaged(Module.Decl.Index, DeclMetadata) = .{},
109111
110112/// List of atoms that are owned directly by the linker.
111113atoms: std.ArrayListUnmanaged(Atom) = .{},
114/// Table of last atom index in a section and matching atom free list if any.
115last_atom_and_free_list_table: std.AutoArrayHashMapUnmanaged(u16, LastAtomAndFreeList) = .{},
112116
113117/// Table of unnamed constants associated with a parent `Decl`.
114118/// We store them here so that we can free the constants whenever the `Decl`
......@@ -176,21 +180,18 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
176180 try self.atoms.append(allocator, .{});
177181 // Append null file at index 0
178182 try self.files.append(allocator, .null);
179 // There must always be a null section in index 0
180 try self.sections.append(allocator, .{
181 .shdr = .{
182 .sh_name = 0,
183 .sh_type = elf.SHT_NULL,
184 .sh_flags = 0,
185 .sh_addr = 0,
186 .sh_offset = 0,
187 .sh_size = 0,
188 .sh_link = 0,
189 .sh_info = 0,
190 .sh_addralign = 0,
191 .sh_entsize = 0,
192 },
193 .phdr_index = undefined,
183 // There must always be a null shdr in index 0
184 try self.shdrs.append(allocator, .{
185 .sh_name = 0,
186 .sh_type = elf.SHT_NULL,
187 .sh_flags = 0,
188 .sh_addr = 0,
189 .sh_offset = 0,
190 .sh_size = 0,
191 .sh_link = 0,
192 .sh_info = 0,
193 .sh_addralign = 0,
194 .sh_entsize = 0,
194195 });
195196
196197 try self.populateMissingMetadata();
......@@ -256,11 +257,8 @@ pub fn deinit(self: *Elf) void {
256257 };
257258 self.files.deinit(gpa);
258259
259 for (self.sections.items(.free_list)) |*free_list| {
260 free_list.deinit(gpa);
261 }
262 self.sections.deinit(gpa);
263
260 self.shdrs.deinit(gpa);
261 self.phdr_to_shdr_table.deinit(gpa);
264262 self.phdrs.deinit(gpa);
265263 self.shstrtab.deinit(gpa);
266264 self.strtab.deinit(gpa);
......@@ -281,6 +279,10 @@ pub fn deinit(self: *Elf) void {
281279 }
282280
283281 self.atoms.deinit(gpa);
282 for (self.last_atom_and_free_list_table.values()) |*value| {
283 value.free_list.deinit(gpa);
284 }
285 self.last_atom_and_free_list_table.deinit(gpa);
284286 self.lazy_syms.deinit(gpa);
285287
286288 {
......@@ -332,7 +334,7 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 {
332334
333335 if (self.shdr_table_offset) |off| {
334336 const shdr_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Shdr) else @sizeOf(elf.Elf64_Shdr);
335 const tight_size = self.sections.slice().len * shdr_size;
337 const tight_size = self.shdrs.items.len * shdr_size;
336338 const increased_size = padToIdeal(tight_size);
337339 const test_end = off + increased_size;
338340 if (end > off and start < test_end) {
......@@ -340,7 +342,7 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 {
340342 }
341343 }
342344
343 for (self.sections.items(.shdr)) |section| {
345 for (self.shdrs.items) |section| {
344346 const increased_size = padToIdeal(section.sh_size);
345347 const test_end = section.sh_offset + increased_size;
346348 if (end > section.sh_offset and start < test_end) {
......@@ -364,7 +366,7 @@ pub fn allocatedSize(self: *Elf, start: u64) u64 {
364366 if (self.shdr_table_offset) |off| {
365367 if (off > start and off < min_pos) min_pos = off;
366368 }
367 for (self.sections.items(.shdr)) |section| {
369 for (self.shdrs.items) |section| {
368370 if (section.sh_offset <= start) continue;
369371 if (section.sh_offset < min_pos) min_pos = section.sh_offset;
370372 }
......@@ -522,197 +524,174 @@ pub fn populateMissingMetadata(self: *Elf) !void {
522524 }
523525
524526 if (self.shstrtab_section_index == null) {
525 self.shstrtab_section_index = @as(u16, @intCast(self.sections.slice().len));
527 self.shstrtab_section_index = @as(u16, @intCast(self.shdrs.items.len));
526528 assert(self.shstrtab.buffer.items.len == 0);
527529 try self.shstrtab.buffer.append(gpa, 0); // need a 0 at position 0
528530 const off = self.findFreeSpace(self.shstrtab.buffer.items.len, 1);
529531 log.debug("found .shstrtab free space 0x{x} to 0x{x}", .{ off, off + self.shstrtab.buffer.items.len });
530 try self.sections.append(gpa, .{
531 .shdr = .{
532 .sh_name = try self.shstrtab.insert(gpa, ".shstrtab"),
533 .sh_type = elf.SHT_STRTAB,
534 .sh_flags = 0,
535 .sh_addr = 0,
536 .sh_offset = off,
537 .sh_size = self.shstrtab.buffer.items.len,
538 .sh_link = 0,
539 .sh_info = 0,
540 .sh_addralign = 1,
541 .sh_entsize = 0,
542 },
543 .phdr_index = undefined,
532 try self.shdrs.append(gpa, .{
533 .sh_name = try self.shstrtab.insert(gpa, ".shstrtab"),
534 .sh_type = elf.SHT_STRTAB,
535 .sh_flags = 0,
536 .sh_addr = 0,
537 .sh_offset = off,
538 .sh_size = self.shstrtab.buffer.items.len,
539 .sh_link = 0,
540 .sh_info = 0,
541 .sh_addralign = 1,
542 .sh_entsize = 0,
544543 });
545544 self.shstrtab_dirty = true;
546545 self.shdr_table_dirty = true;
547546 }
548547
549548 if (self.strtab_section_index == null) {
550 self.strtab_section_index = @as(u16, @intCast(self.sections.slice().len));
549 self.strtab_section_index = @as(u16, @intCast(self.shdrs.items.len));
551550 assert(self.strtab.buffer.items.len == 0);
552551 try self.strtab.buffer.append(gpa, 0); // need a 0 at position 0
553552 const off = self.findFreeSpace(self.strtab.buffer.items.len, 1);
554553 log.debug("found .strtab free space 0x{x} to 0x{x}", .{ off, off + self.strtab.buffer.items.len });
555 try self.sections.append(gpa, .{
556 .shdr = .{
557 .sh_name = try self.shstrtab.insert(gpa, ".strtab"),
558 .sh_type = elf.SHT_STRTAB,
559 .sh_flags = 0,
560 .sh_addr = 0,
561 .sh_offset = off,
562 .sh_size = self.strtab.buffer.items.len,
563 .sh_link = 0,
564 .sh_info = 0,
565 .sh_addralign = 1,
566 .sh_entsize = 0,
567 },
568 .phdr_index = undefined,
554 try self.shdrs.append(gpa, .{
555 .sh_name = try self.shstrtab.insert(gpa, ".strtab"),
556 .sh_type = elf.SHT_STRTAB,
557 .sh_flags = 0,
558 .sh_addr = 0,
559 .sh_offset = off,
560 .sh_size = self.strtab.buffer.items.len,
561 .sh_link = 0,
562 .sh_info = 0,
563 .sh_addralign = 1,
564 .sh_entsize = 0,
569565 });
570566 self.strtab_dirty = true;
571567 self.shdr_table_dirty = true;
572568 }
573569
574570 if (self.text_section_index == null) {
575 self.text_section_index = @as(u16, @intCast(self.sections.slice().len));
571 self.text_section_index = @as(u16, @intCast(self.shdrs.items.len));
576572 const phdr = &self.phdrs.items[self.phdr_load_re_index.?];
577
578 try self.sections.append(gpa, .{
579 .shdr = .{
580 .sh_name = try self.shstrtab.insert(gpa, ".text"),
581 .sh_type = elf.SHT_PROGBITS,
582 .sh_flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
583 .sh_addr = phdr.p_vaddr,
584 .sh_offset = phdr.p_offset,
585 .sh_size = phdr.p_filesz,
586 .sh_link = 0,
587 .sh_info = 0,
588 .sh_addralign = 1,
589 .sh_entsize = 0,
590 },
591 .phdr_index = self.phdr_load_re_index.?,
573 try self.shdrs.append(gpa, .{
574 .sh_name = try self.shstrtab.insert(gpa, ".text"),
575 .sh_type = elf.SHT_PROGBITS,
576 .sh_flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
577 .sh_addr = phdr.p_vaddr,
578 .sh_offset = phdr.p_offset,
579 .sh_size = phdr.p_filesz,
580 .sh_link = 0,
581 .sh_info = 0,
582 .sh_addralign = 1,
583 .sh_entsize = 0,
592584 });
585 try self.phdr_to_shdr_table.putNoClobber(gpa, self.text_section_index.?, self.phdr_load_re_index.?);
586 try self.last_atom_and_free_list_table.putNoClobber(gpa, self.text_section_index.?, .{});
593587 self.shdr_table_dirty = true;
594588 }
595589
596590 if (self.got_section_index == null) {
597 self.got_section_index = @as(u16, @intCast(self.sections.slice().len));
591 self.got_section_index = @as(u16, @intCast(self.shdrs.items.len));
598592 const phdr = &self.phdrs.items[self.phdr_got_index.?];
599
600 try self.sections.append(gpa, .{
601 .shdr = .{
602 .sh_name = try self.shstrtab.insert(gpa, ".got"),
603 .sh_type = elf.SHT_PROGBITS,
604 .sh_flags = elf.SHF_ALLOC,
605 .sh_addr = phdr.p_vaddr,
606 .sh_offset = phdr.p_offset,
607 .sh_size = phdr.p_filesz,
608 .sh_link = 0,
609 .sh_info = 0,
610 .sh_addralign = @as(u16, ptr_size),
611 .sh_entsize = 0,
612 },
613 .phdr_index = self.phdr_got_index.?,
593 try self.shdrs.append(gpa, .{
594 .sh_name = try self.shstrtab.insert(gpa, ".got"),
595 .sh_type = elf.SHT_PROGBITS,
596 .sh_flags = elf.SHF_ALLOC,
597 .sh_addr = phdr.p_vaddr,
598 .sh_offset = phdr.p_offset,
599 .sh_size = phdr.p_filesz,
600 .sh_link = 0,
601 .sh_info = 0,
602 .sh_addralign = @as(u16, ptr_size),
603 .sh_entsize = 0,
614604 });
605 try self.phdr_to_shdr_table.putNoClobber(gpa, self.got_section_index.?, self.phdr_got_index.?);
615606 self.shdr_table_dirty = true;
616607 }
617608
618609 if (self.rodata_section_index == null) {
619 self.rodata_section_index = @as(u16, @intCast(self.sections.slice().len));
610 self.rodata_section_index = @as(u16, @intCast(self.shdrs.items.len));
620611 const phdr = &self.phdrs.items[self.phdr_load_ro_index.?];
621
622 try self.sections.append(gpa, .{
623 .shdr = .{
624 .sh_name = try self.shstrtab.insert(gpa, ".rodata"),
625 .sh_type = elf.SHT_PROGBITS,
626 .sh_flags = elf.SHF_ALLOC,
627 .sh_addr = phdr.p_vaddr,
628 .sh_offset = phdr.p_offset,
629 .sh_size = phdr.p_filesz,
630 .sh_link = 0,
631 .sh_info = 0,
632 .sh_addralign = 1,
633 .sh_entsize = 0,
634 },
635 .phdr_index = self.phdr_load_ro_index.?,
612 try self.shdrs.append(gpa, .{
613 .sh_name = try self.shstrtab.insert(gpa, ".rodata"),
614 .sh_type = elf.SHT_PROGBITS,
615 .sh_flags = elf.SHF_ALLOC,
616 .sh_addr = phdr.p_vaddr,
617 .sh_offset = phdr.p_offset,
618 .sh_size = phdr.p_filesz,
619 .sh_link = 0,
620 .sh_info = 0,
621 .sh_addralign = 1,
622 .sh_entsize = 0,
636623 });
624 try self.phdr_to_shdr_table.putNoClobber(gpa, self.rodata_section_index.?, self.phdr_load_ro_index.?);
625 try self.last_atom_and_free_list_table.putNoClobber(gpa, self.rodata_section_index.?, .{});
637626 self.shdr_table_dirty = true;
638627 }
639628
640629 if (self.data_section_index == null) {
641 self.data_section_index = @as(u16, @intCast(self.sections.slice().len));
630 self.data_section_index = @as(u16, @intCast(self.shdrs.items.len));
642631 const phdr = &self.phdrs.items[self.phdr_load_rw_index.?];
643
644 try self.sections.append(gpa, .{
645 .shdr = .{
646 .sh_name = try self.shstrtab.insert(gpa, ".data"),
647 .sh_type = elf.SHT_PROGBITS,
648 .sh_flags = elf.SHF_WRITE | elf.SHF_ALLOC,
649 .sh_addr = phdr.p_vaddr,
650 .sh_offset = phdr.p_offset,
651 .sh_size = phdr.p_filesz,
652 .sh_link = 0,
653 .sh_info = 0,
654 .sh_addralign = @as(u16, ptr_size),
655 .sh_entsize = 0,
656 },
657 .phdr_index = self.phdr_load_rw_index.?,
632 try self.shdrs.append(gpa, .{
633 .sh_name = try self.shstrtab.insert(gpa, ".data"),
634 .sh_type = elf.SHT_PROGBITS,
635 .sh_flags = elf.SHF_WRITE | elf.SHF_ALLOC,
636 .sh_addr = phdr.p_vaddr,
637 .sh_offset = phdr.p_offset,
638 .sh_size = phdr.p_filesz,
639 .sh_link = 0,
640 .sh_info = 0,
641 .sh_addralign = @as(u16, ptr_size),
642 .sh_entsize = 0,
658643 });
644 try self.phdr_to_shdr_table.putNoClobber(gpa, self.data_section_index.?, self.phdr_load_rw_index.?);
645 try self.last_atom_and_free_list_table.putNoClobber(gpa, self.data_section_index.?, .{});
659646 self.shdr_table_dirty = true;
660647 }
661648
662649 if (self.symtab_section_index == null) {
663 self.symtab_section_index = @as(u16, @intCast(self.sections.slice().len));
650 self.symtab_section_index = @as(u16, @intCast(self.shdrs.items.len));
664651 const min_align: u16 = if (small_ptr) @alignOf(elf.Elf32_Sym) else @alignOf(elf.Elf64_Sym);
665652 const each_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Sym) else @sizeOf(elf.Elf64_Sym);
666653 const file_size = self.base.options.symbol_count_hint * each_size;
667654 const off = self.findFreeSpace(file_size, min_align);
668655 log.debug("found symtab free space 0x{x} to 0x{x}", .{ off, off + file_size });
669
670 try self.sections.append(gpa, .{
671 .shdr = .{
672 .sh_name = try self.shstrtab.insert(gpa, ".symtab"),
673 .sh_type = elf.SHT_SYMTAB,
674 .sh_flags = 0,
675 .sh_addr = 0,
676 .sh_offset = off,
677 .sh_size = file_size,
678 // The section header index of the associated string table.
679 .sh_link = self.strtab_section_index.?,
680 .sh_info = @as(u32, @intCast(self.symbols.items.len)),
681 .sh_addralign = min_align,
682 .sh_entsize = each_size,
683 },
684 .phdr_index = undefined,
656 try self.shdrs.append(gpa, .{
657 .sh_name = try self.shstrtab.insert(gpa, ".symtab"),
658 .sh_type = elf.SHT_SYMTAB,
659 .sh_flags = 0,
660 .sh_addr = 0,
661 .sh_offset = off,
662 .sh_size = file_size,
663 // The section header index of the associated string table.
664 .sh_link = self.strtab_section_index.?,
665 .sh_info = @as(u32, @intCast(self.symbols.items.len)),
666 .sh_addralign = min_align,
667 .sh_entsize = each_size,
685668 });
686669 self.shdr_table_dirty = true;
687670 }
688671
689672 if (self.dwarf) |*dw| {
690673 if (self.debug_str_section_index == null) {
691 self.debug_str_section_index = @as(u16, @intCast(self.sections.slice().len));
674 self.debug_str_section_index = @as(u16, @intCast(self.shdrs.items.len));
692675 assert(dw.strtab.buffer.items.len == 0);
693676 try dw.strtab.buffer.append(gpa, 0);
694 try self.sections.append(gpa, .{
695 .shdr = .{
696 .sh_name = try self.shstrtab.insert(gpa, ".debug_str"),
697 .sh_type = elf.SHT_PROGBITS,
698 .sh_flags = elf.SHF_MERGE | elf.SHF_STRINGS,
699 .sh_addr = 0,
700 .sh_offset = 0,
701 .sh_size = 0,
702 .sh_link = 0,
703 .sh_info = 0,
704 .sh_addralign = 1,
705 .sh_entsize = 1,
706 },
707 .phdr_index = undefined,
677 try self.shdrs.append(gpa, .{
678 .sh_name = try self.shstrtab.insert(gpa, ".debug_str"),
679 .sh_type = elf.SHT_PROGBITS,
680 .sh_flags = elf.SHF_MERGE | elf.SHF_STRINGS,
681 .sh_addr = 0,
682 .sh_offset = 0,
683 .sh_size = 0,
684 .sh_link = 0,
685 .sh_info = 0,
686 .sh_addralign = 1,
687 .sh_entsize = 1,
708688 });
709689 self.debug_strtab_dirty = true;
710690 self.shdr_table_dirty = true;
711691 }
712692
713693 if (self.debug_info_section_index == null) {
714 self.debug_info_section_index = @as(u16, @intCast(self.sections.slice().len));
715
694 self.debug_info_section_index = @as(u16, @intCast(self.shdrs.items.len));
716695 const file_size_hint = 200;
717696 const p_align = 1;
718697 const off = self.findFreeSpace(file_size_hint, p_align);
......@@ -720,28 +699,24 @@ pub fn populateMissingMetadata(self: *Elf) !void {
720699 off,
721700 off + file_size_hint,
722701 });
723 try self.sections.append(gpa, .{
724 .shdr = .{
725 .sh_name = try self.shstrtab.insert(gpa, ".debug_info"),
726 .sh_type = elf.SHT_PROGBITS,
727 .sh_flags = 0,
728 .sh_addr = 0,
729 .sh_offset = off,
730 .sh_size = file_size_hint,
731 .sh_link = 0,
732 .sh_info = 0,
733 .sh_addralign = p_align,
734 .sh_entsize = 0,
735 },
736 .phdr_index = undefined,
702 try self.shdrs.append(gpa, .{
703 .sh_name = try self.shstrtab.insert(gpa, ".debug_info"),
704 .sh_type = elf.SHT_PROGBITS,
705 .sh_flags = 0,
706 .sh_addr = 0,
707 .sh_offset = off,
708 .sh_size = file_size_hint,
709 .sh_link = 0,
710 .sh_info = 0,
711 .sh_addralign = p_align,
712 .sh_entsize = 0,
737713 });
738714 self.shdr_table_dirty = true;
739715 self.debug_info_header_dirty = true;
740716 }
741717
742718 if (self.debug_abbrev_section_index == null) {
743 self.debug_abbrev_section_index = @as(u16, @intCast(self.sections.slice().len));
744
719 self.debug_abbrev_section_index = @as(u16, @intCast(self.shdrs.items.len));
745720 const file_size_hint = 128;
746721 const p_align = 1;
747722 const off = self.findFreeSpace(file_size_hint, p_align);
......@@ -749,28 +724,24 @@ pub fn populateMissingMetadata(self: *Elf) !void {
749724 off,
750725 off + file_size_hint,
751726 });
752 try self.sections.append(gpa, .{
753 .shdr = .{
754 .sh_name = try self.shstrtab.insert(gpa, ".debug_abbrev"),
755 .sh_type = elf.SHT_PROGBITS,
756 .sh_flags = 0,
757 .sh_addr = 0,
758 .sh_offset = off,
759 .sh_size = file_size_hint,
760 .sh_link = 0,
761 .sh_info = 0,
762 .sh_addralign = p_align,
763 .sh_entsize = 0,
764 },
765 .phdr_index = undefined,
727 try self.shdrs.append(gpa, .{
728 .sh_name = try self.shstrtab.insert(gpa, ".debug_abbrev"),
729 .sh_type = elf.SHT_PROGBITS,
730 .sh_flags = 0,
731 .sh_addr = 0,
732 .sh_offset = off,
733 .sh_size = file_size_hint,
734 .sh_link = 0,
735 .sh_info = 0,
736 .sh_addralign = p_align,
737 .sh_entsize = 0,
766738 });
767739 self.shdr_table_dirty = true;
768740 self.debug_abbrev_section_dirty = true;
769741 }
770742
771743 if (self.debug_aranges_section_index == null) {
772 self.debug_aranges_section_index = @as(u16, @intCast(self.sections.slice().len));
773
744 self.debug_aranges_section_index = @as(u16, @intCast(self.shdrs.items.len));
774745 const file_size_hint = 160;
775746 const p_align = 16;
776747 const off = self.findFreeSpace(file_size_hint, p_align);
......@@ -778,28 +749,24 @@ pub fn populateMissingMetadata(self: *Elf) !void {
778749 off,
779750 off + file_size_hint,
780751 });
781 try self.sections.append(gpa, .{
782 .shdr = .{
783 .sh_name = try self.shstrtab.insert(gpa, ".debug_aranges"),
784 .sh_type = elf.SHT_PROGBITS,
785 .sh_flags = 0,
786 .sh_addr = 0,
787 .sh_offset = off,
788 .sh_size = file_size_hint,
789 .sh_link = 0,
790 .sh_info = 0,
791 .sh_addralign = p_align,
792 .sh_entsize = 0,
793 },
794 .phdr_index = undefined,
752 try self.shdrs.append(gpa, .{
753 .sh_name = try self.shstrtab.insert(gpa, ".debug_aranges"),
754 .sh_type = elf.SHT_PROGBITS,
755 .sh_flags = 0,
756 .sh_addr = 0,
757 .sh_offset = off,
758 .sh_size = file_size_hint,
759 .sh_link = 0,
760 .sh_info = 0,
761 .sh_addralign = p_align,
762 .sh_entsize = 0,
795763 });
796764 self.shdr_table_dirty = true;
797765 self.debug_aranges_section_dirty = true;
798766 }
799767
800768 if (self.debug_line_section_index == null) {
801 self.debug_line_section_index = @as(u16, @intCast(self.sections.slice().len));
802
769 self.debug_line_section_index = @as(u16, @intCast(self.shdrs.items.len));
803770 const file_size_hint = 250;
804771 const p_align = 1;
805772 const off = self.findFreeSpace(file_size_hint, p_align);
......@@ -807,20 +774,17 @@ pub fn populateMissingMetadata(self: *Elf) !void {
807774 off,
808775 off + file_size_hint,
809776 });
810 try self.sections.append(gpa, .{
811 .shdr = .{
812 .sh_name = try self.shstrtab.insert(gpa, ".debug_line"),
813 .sh_type = elf.SHT_PROGBITS,
814 .sh_flags = 0,
815 .sh_addr = 0,
816 .sh_offset = off,
817 .sh_size = file_size_hint,
818 .sh_link = 0,
819 .sh_info = 0,
820 .sh_addralign = p_align,
821 .sh_entsize = 0,
822 },
823 .phdr_index = undefined,
777 try self.shdrs.append(gpa, .{
778 .sh_name = try self.shstrtab.insert(gpa, ".debug_line"),
779 .sh_type = elf.SHT_PROGBITS,
780 .sh_flags = 0,
781 .sh_addr = 0,
782 .sh_offset = off,
783 .sh_size = file_size_hint,
784 .sh_link = 0,
785 .sh_info = 0,
786 .sh_addralign = p_align,
787 .sh_entsize = 0,
824788 });
825789 self.shdr_table_dirty = true;
826790 self.debug_line_header_dirty = true;
......@@ -836,7 +800,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
836800 .p64 => @alignOf(elf.Elf64_Shdr),
837801 };
838802 if (self.shdr_table_offset == null) {
839 self.shdr_table_offset = self.findFreeSpace(self.sections.slice().len * shsize, shalign);
803 self.shdr_table_offset = self.findFreeSpace(self.shdrs.items.len * shsize, shalign);
840804 self.shdr_table_dirty = true;
841805 }
842806
......@@ -854,7 +818,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
854818 // offset + it's filesize.
855819 var max_file_offset: u64 = 0;
856820
857 for (self.sections.items(.shdr)) |shdr| {
821 for (self.shdrs.items) |shdr| {
858822 if (shdr.sh_offset + shdr.sh_size > max_file_offset) {
859823 max_file_offset = shdr.sh_offset + shdr.sh_size;
860824 }
......@@ -885,19 +849,17 @@ pub fn populateMissingMetadata(self: *Elf) !void {
885849
886850pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void {
887851 // TODO Also detect virtual address collisions.
888 const shdr = &self.sections.items(.shdr)[shdr_index];
889 const phdr_index = self.sections.items(.phdr_index)[shdr_index];
852 const shdr = &self.shdrs.items[shdr_index];
853 const phdr_index = self.phdr_to_shdr_table.get(shdr_index).?;
890854 const phdr = &self.phdrs.items[phdr_index];
891 const last_atom_index = self.sections.items(.last_atom_index)[shdr_index];
892855
893856 if (needed_size > self.allocatedSize(shdr.sh_offset)) {
894857 // Must move the entire section.
895858 const new_offset = self.findFreeSpace(needed_size, self.page_size);
896 const existing_size = if (self.atom(last_atom_index)) |last| blk: {
859 const existing_size = if (self.last_atom_and_free_list_table.get(shdr_index)) |meta| blk: {
860 const last = self.atom(meta.last_atom_index) orelse break :blk 0;
897861 break :blk (last.value + last.size) - phdr.p_vaddr;
898 } else if (shdr_index == self.got_section_index.?) blk: {
899 break :blk shdr.sh_size;
900 } else 0;
862 } else shdr.sh_size;
901863 shdr.sh_size = 0;
902864
903865 log.debug("new '{?s}' file offset 0x{x} to 0x{x}", .{
......@@ -927,7 +889,7 @@ pub fn growNonAllocSection(
927889 min_alignment: u32,
928890 requires_file_copy: bool,
929891) !void {
930 const shdr = &self.sections.items(.shdr)[shdr_index];
892 const shdr = &self.shdrs.items[shdr_index];
931893
932894 if (needed_size > self.allocatedSize(shdr.sh_offset)) {
933895 const existing_size = if (self.symtab_section_index.? == shdr_index) blk: {
......@@ -940,7 +902,12 @@ pub fn growNonAllocSection(
940902 shdr.sh_size = 0;
941903 // Move all the symbols to a new file location.
942904 const new_offset = self.findFreeSpace(needed_size, min_alignment);
943 log.debug("moving '{?s}' from 0x{x} to 0x{x}", .{ self.shstrtab.get(shdr.sh_name), shdr.sh_offset, new_offset });
905
906 log.debug("moving '{?s}' from 0x{x} to 0x{x}", .{
907 self.shstrtab.get(shdr.sh_name),
908 shdr.sh_offset,
909 new_offset,
910 });
944911
945912 if (requires_file_copy) {
946913 const amt = try self.base.file.?.copyRangeAll(
......@@ -1071,7 +1038,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
10711038 const atom_index = entry.key_ptr.*;
10721039 const relocs = entry.value_ptr.*;
10731040 const atom_ptr = self.atom(atom_index).?;
1074 const source_shdr = self.sections.items(.shdr)[atom_ptr.output_section_index];
1041 const source_shdr = &self.shdrs.items[atom_ptr.output_section_index];
10751042
10761043 log.debug("relocating '{s}'", .{atom_ptr.name(self)});
10771044
......@@ -1209,9 +1176,9 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
12091176
12101177 {
12111178 const shdr_index = self.shstrtab_section_index.?;
1212 if (self.shstrtab_dirty or self.shstrtab.buffer.items.len != self.sections.items(.shdr)[shdr_index].sh_size) {
1179 if (self.shstrtab_dirty or self.shstrtab.buffer.items.len != self.shdrs.items[shdr_index].sh_size) {
12131180 try self.growNonAllocSection(shdr_index, self.shstrtab.buffer.items.len, 1, false);
1214 const shstrtab_sect = self.sections.items(.shdr)[shdr_index];
1181 const shstrtab_sect = &self.shdrs.items[shdr_index];
12151182 try self.base.file.?.pwriteAll(self.shstrtab.buffer.items, shstrtab_sect.sh_offset);
12161183 self.shstrtab_dirty = false;
12171184 }
......@@ -1219,9 +1186,9 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
12191186
12201187 {
12211188 const shdr_index = self.strtab_section_index.?;
1222 if (self.strtab_dirty or self.strtab.buffer.items.len != self.sections.items(.shdr)[shdr_index].sh_size) {
1189 if (self.strtab_dirty or self.strtab.buffer.items.len != self.shdrs.items[shdr_index].sh_size) {
12231190 try self.growNonAllocSection(shdr_index, self.strtab.buffer.items.len, 1, false);
1224 const strtab_sect = self.sections.items(.shdr)[shdr_index];
1191 const strtab_sect = self.shdrs.items[shdr_index];
12251192 try self.base.file.?.pwriteAll(self.strtab.buffer.items, strtab_sect.sh_offset);
12261193 self.strtab_dirty = false;
12271194 }
......@@ -1229,9 +1196,9 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
12291196
12301197 if (self.dwarf) |dwarf| {
12311198 const shdr_index = self.debug_str_section_index.?;
1232 if (self.debug_strtab_dirty or dwarf.strtab.buffer.items.len != self.sections.items(.shdr)[shdr_index].sh_size) {
1199 if (self.debug_strtab_dirty or dwarf.strtab.buffer.items.len != self.shdrs.items[shdr_index].sh_size) {
12331200 try self.growNonAllocSection(shdr_index, dwarf.strtab.buffer.items.len, 1, false);
1234 const debug_strtab_sect = self.sections.items(.shdr)[shdr_index];
1201 const debug_strtab_sect = self.shdrs.items[shdr_index];
12351202 try self.base.file.?.pwriteAll(dwarf.strtab.buffer.items, debug_strtab_sect.sh_offset);
12361203 self.debug_strtab_dirty = false;
12371204 }
......@@ -1247,7 +1214,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
12471214 .p64 => @alignOf(elf.Elf64_Shdr),
12481215 };
12491216 const allocated_size = self.allocatedSize(self.shdr_table_offset.?);
1250 const needed_size = self.sections.slice().len * shsize;
1217 const needed_size = self.shdrs.items.len * shsize;
12511218
12521219 if (needed_size > allocated_size) {
12531220 self.shdr_table_offset = null; // free the space
......@@ -1256,12 +1223,11 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
12561223
12571224 switch (self.ptr_width) {
12581225 .p32 => {
1259 const slice = self.sections.slice();
1260 const buf = try gpa.alloc(elf.Elf32_Shdr, slice.len);
1226 const buf = try gpa.alloc(elf.Elf32_Shdr, self.shdrs.items.len);
12611227 defer gpa.free(buf);
12621228
12631229 for (buf, 0..) |*shdr, i| {
1264 shdr.* = shdrTo32(slice.items(.shdr)[i]);
1230 shdr.* = shdrTo32(self.shdrs.items[i]);
12651231 log.debug("writing section {?s}: {}", .{ self.shstrtab.get(shdr.sh_name), shdr.* });
12661232 if (foreign_endian) {
12671233 mem.byteSwapAllFields(elf.Elf32_Shdr, shdr);
......@@ -1270,12 +1236,11 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
12701236 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?);
12711237 },
12721238 .p64 => {
1273 const slice = self.sections.slice();
1274 const buf = try gpa.alloc(elf.Elf64_Shdr, slice.len);
1239 const buf = try gpa.alloc(elf.Elf64_Shdr, self.shdrs.items.len);
12751240 defer gpa.free(buf);
12761241
12771242 for (buf, 0..) |*shdr, i| {
1278 shdr.* = slice.items(.shdr)[i];
1243 shdr.* = self.shdrs.items[i];
12791244 log.debug("writing section {?s}: {}", .{ self.shstrtab.get(shdr.sh_name), shdr.* });
12801245 if (foreign_endian) {
12811246 mem.byteSwapAllFields(elf.Elf64_Shdr, shdr);
......@@ -2118,7 +2083,7 @@ fn writeElfHeader(self: *Elf) !void {
21182083 mem.writeInt(u16, hdr_buf[index..][0..2], e_shentsize, endian);
21192084 index += 2;
21202085
2121 const e_shnum = @as(u16, @intCast(self.sections.slice().len));
2086 const e_shnum = @as(u16, @intCast(self.shdrs.items.len));
21222087 mem.writeInt(u16, hdr_buf[index..][0..2], e_shnum, endian);
21232088 index += 2;
21242089
......@@ -2305,9 +2270,9 @@ fn updateDeclCode(
23052270 try self.got.writeEntry(self, got_index);
23062271 }
23072272
2308 const phdr_index = self.sections.items(.phdr_index)[shdr_index];
2273 const phdr_index = self.phdr_to_shdr_table.get(shdr_index).?;
23092274 const section_offset = sym.value - self.phdrs.items[phdr_index].p_vaddr;
2310 const file_offset = self.sections.items(.shdr)[shdr_index].sh_offset + section_offset;
2275 const file_offset = self.shdrs.items[shdr_index].sh_offset + section_offset;
23112276
23122277 if (self.base.child_pid) |pid| {
23132278 switch (builtin.os.tag) {
......@@ -2510,7 +2475,7 @@ fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol.
25102475 };
25112476
25122477 const local_sym = self.symbol(symbol_index);
2513 const phdr_index = self.sections.items(.phdr_index)[local_sym.output_section_index];
2478 const phdr_index = self.phdr_to_shdr_table.get(local_sym.output_section_index).?;
25142479 local_sym.name_offset = name_str_index;
25152480 const local_esym = local_sym.sourceSymbol(self);
25162481 local_esym.st_name = name_str_index;
......@@ -2537,7 +2502,7 @@ fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol.
25372502 try self.got.writeEntry(self, got_index);
25382503
25392504 const section_offset = atom_ptr.value - self.phdrs.items[phdr_index].p_vaddr;
2540 const file_offset = self.sections.items(.shdr)[local_sym.output_section_index].sh_offset + section_offset;
2505 const file_offset = self.shdrs.items[local_sym.output_section_index].sh_offset + section_offset;
25412506 try self.base.file.?.pwriteAll(code, file_offset);
25422507}
25432508
......@@ -2584,7 +2549,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module
25842549
25852550 const required_alignment = typed_value.ty.abiAlignment(mod);
25862551 const shdr_index = self.rodata_section_index.?;
2587 const phdr_index = self.sections.items(.phdr_index)[shdr_index];
2552 const phdr_index = self.phdr_to_shdr_table.get(shdr_index).?;
25882553 const local_sym = self.symbol(sym_index);
25892554 local_sym.name_offset = name_str_index;
25902555 const local_esym = local_sym.sourceSymbol(self);
......@@ -2607,7 +2572,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module
26072572 try unnamed_consts.append(gpa, atom_ptr.atom_index);
26082573
26092574 const section_offset = atom_ptr.value - self.phdrs.items[phdr_index].p_vaddr;
2610 const file_offset = self.sections.items(.shdr)[shdr_index].sh_offset + section_offset;
2575 const file_offset = self.shdrs.items[shdr_index].sh_offset + section_offset;
26112576 try self.base.file.?.pwriteAll(code, file_offset);
26122577
26132578 return sym_index;
......@@ -2775,7 +2740,7 @@ fn addLinkerDefinedSymbols(self: *Elf) !void {
27752740fn allocateLinkerDefinedSymbols(self: *Elf) void {
27762741 // _DYNAMIC
27772742 if (self.dynamic_section_index) |shndx| {
2778 const shdr = self.sections.items(.shdr)[shndx];
2743 const shdr = &self.shdrs.items[shndx];
27792744 const symbol_ptr = self.symbol(self.dynamic_index.?);
27802745 symbol_ptr.value = shdr.sh_addr;
27812746 symbol_ptr.output_section_index = shndx;
......@@ -2792,7 +2757,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
27922757 if (self.sectionByName(".init_array")) |shndx| {
27932758 const start_sym = self.symbol(self.init_array_start_index.?);
27942759 const end_sym = self.symbol(self.init_array_end_index.?);
2795 const shdr = &self.sections.items(.shdr)[shndx];
2760 const shdr = &self.shdrs.items[shndx];
27962761 start_sym.output_section_index = shndx;
27972762 start_sym.value = shdr.sh_addr;
27982763 end_sym.output_section_index = shndx;
......@@ -2803,7 +2768,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
28032768 if (self.sectionByName(".fini_array")) |shndx| {
28042769 const start_sym = self.symbol(self.fini_array_start_index.?);
28052770 const end_sym = self.symbol(self.fini_array_end_index.?);
2806 const shdr = &self.sections.items(.shdr)[shndx];
2771 const shdr = &self.shdrs.items[shndx];
28072772 start_sym.output_section_index = shndx;
28082773 start_sym.value = shdr.sh_addr;
28092774 end_sym.output_section_index = shndx;
......@@ -2814,7 +2779,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
28142779 if (self.sectionByName(".preinit_array")) |shndx| {
28152780 const start_sym = self.symbol(self.preinit_array_start_index.?);
28162781 const end_sym = self.symbol(self.preinit_array_end_index.?);
2817 const shdr = &self.sections.items(.shdr)[shndx];
2782 const shdr = &self.shdrs.items[shndx];
28182783 start_sym.output_section_index = shndx;
28192784 start_sym.value = shdr.sh_addr;
28202785 end_sym.output_section_index = shndx;
......@@ -2823,7 +2788,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
28232788
28242789 // _GLOBAL_OFFSET_TABLE_
28252790 if (self.got_plt_section_index) |shndx| {
2826 const shdr = &self.sections.items(.shdr)[shndx];
2791 const shdr = &self.shdrs.items[shndx];
28272792 const symbol_ptr = self.symbol(self.got_index.?);
28282793 symbol_ptr.value = shdr.sh_addr;
28292794 symbol_ptr.output_section_index = shndx;
......@@ -2831,7 +2796,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
28312796
28322797 // _PROCEDURE_LINKAGE_TABLE_
28332798 if (self.plt_section_index) |shndx| {
2834 const shdr = &self.sections.items(.shdr)[shndx];
2799 const shdr = &self.shdrs.items[shndx];
28352800 const symbol_ptr = self.symbol(self.plt_index.?);
28362801 symbol_ptr.value = shdr.sh_addr;
28372802 symbol_ptr.output_section_index = shndx;
......@@ -2839,7 +2804,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
28392804
28402805 // __dso_handle
28412806 if (self.dso_handle_index) |index| {
2842 const shdr = &self.sections.items(.shdr)[1];
2807 const shdr = &self.shdrs.items[1];
28432808 const symbol_ptr = self.symbol(index);
28442809 symbol_ptr.value = shdr.sh_addr;
28452810 symbol_ptr.output_section_index = 0;
......@@ -2847,7 +2812,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
28472812
28482813 // __GNU_EH_FRAME_HDR
28492814 if (self.eh_frame_hdr_section_index) |shndx| {
2850 const shdr = &self.sections.items(.shdr)[shndx];
2815 const shdr = &self.shdrs.items[shndx];
28512816 const symbol_ptr = self.symbol(self.gnu_eh_frame_hdr_index.?);
28522817 symbol_ptr.value = shdr.sh_addr;
28532818 symbol_ptr.output_section_index = shndx;
......@@ -2856,7 +2821,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
28562821 // __rela_iplt_start, __rela_iplt_end
28572822 if (self.rela_dyn_section_index) |shndx| blk: {
28582823 if (self.base.options.link_mode != .Static or self.base.options.pie) break :blk;
2859 const shdr = &self.sections.items(.shdr)[shndx];
2824 const shdr = &self.shdrs.items[shndx];
28602825 const end_addr = shdr.sh_addr + shdr.sh_size;
28612826 const start_addr = end_addr - self.calcNumIRelativeRelocs() * @sizeOf(elf.Elf64_Rela);
28622827 const start_sym = self.symbol(self.rela_iplt_start_index.?);
......@@ -2870,7 +2835,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
28702835 // _end
28712836 {
28722837 const end_symbol = self.symbol(self.end_index.?);
2873 for (self.sections.items(.shdr), 0..) |shdr, shndx| {
2838 for (self.shdrs.items, 0..) |*shdr, shndx| {
28742839 if (shdr.sh_flags & elf.SHF_ALLOC != 0) {
28752840 end_symbol.value = shdr.sh_addr + shdr.sh_size;
28762841 end_symbol.output_section_index = @intCast(shndx);
......@@ -2886,7 +2851,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
28862851 const name = start.name(self);
28872852 const stop = self.symbol(self.start_stop_indexes.items[index + 1]);
28882853 const shndx = self.sectionByName(name["__start_".len..]).?;
2889 const shdr = self.sections.items(.shdr)[shndx];
2854 const shdr = &self.shdrs.items[shndx];
28902855 start.value = shdr.sh_addr;
28912856 start.output_section_index = shndx;
28922857 stop.value = shdr.sh_addr + shdr.sh_size;
......@@ -2916,7 +2881,7 @@ fn updateSymtabSize(self: *Elf) !void {
29162881 sizes.nlocals += linker_defined.output_symtab_size.nlocals;
29172882 }
29182883
2919 const shdr = &self.sections.items(.shdr)[self.symtab_section_index.?];
2884 const shdr = &self.shdrs.items[self.symtab_section_index.?];
29202885 shdr.sh_info = sizes.nlocals + 1;
29212886 self.markDirty(self.symtab_section_index.?, null);
29222887
......@@ -2934,7 +2899,7 @@ fn updateSymtabSize(self: *Elf) !void {
29342899
29352900fn writeSymtab(self: *Elf) !void {
29362901 const gpa = self.base.allocator;
2937 const shdr = &self.sections.items(.shdr)[self.symtab_section_index.?];
2902 const shdr = &self.shdrs.items[self.symtab_section_index.?];
29382903 const sym_size: u64 = switch (self.ptr_width) {
29392904 .p32 => @sizeOf(elf.Elf32_Sym),
29402905 .p64 => @sizeOf(elf.Elf64_Sym),
......@@ -3031,7 +2996,7 @@ fn writeShdr(self: *Elf, index: usize) !void {
30312996 switch (self.ptr_width) {
30322997 .p32 => {
30332998 var shdr: [1]elf.Elf32_Shdr = undefined;
3034 shdr[0] = shdrTo32(self.sections.items(.shdr)[index]);
2999 shdr[0] = shdrTo32(self.shdrs.items[index]);
30353000 if (foreign_endian) {
30363001 mem.byteSwapAllFields(elf.Elf32_Shdr, &shdr[0]);
30373002 }
......@@ -3039,7 +3004,7 @@ fn writeShdr(self: *Elf, index: usize) !void {
30393004 return self.base.file.?.pwriteAll(mem.sliceAsBytes(&shdr), offset);
30403005 },
30413006 .p64 => {
3042 var shdr = [1]elf.Elf64_Shdr{self.sections.items(.shdr)[index]};
3007 var shdr = [1]elf.Elf64_Shdr{self.shdrs.items[index]};
30433008 if (foreign_endian) {
30443009 mem.byteSwapAllFields(elf.Elf64_Shdr, &shdr[0]);
30453010 }
......@@ -3327,7 +3292,7 @@ pub fn defaultEntryAddress(self: Elf) u64 {
33273292}
33283293
33293294pub fn sectionByName(self: *Elf, name: [:0]const u8) ?u16 {
3330 for (self.sections.items(.shdr), 0..) |shdr, i| {
3295 for (self.shdrs.items, 0..) |*shdr, i| {
33313296 const this_name = self.shstrtab.getAssumeExists(shdr.sh_name);
33323297 if (mem.eql(u8, this_name, name)) return @as(u16, @intCast(i));
33333298 } else return null;
......@@ -3481,10 +3446,7 @@ const default_entry_addr = 0x8000000;
34813446
34823447pub const base_tag: link.File.Tag = .elf;
34833448
3484const Section = struct {
3485 shdr: elf.Elf64_Shdr,
3486 phdr_index: u16,
3487
3449const LastAtomAndFreeList = struct {
34883450 /// Index of the last allocated atom in this section.
34893451 last_atom_index: Atom.Index = 0,
34903452
src/link/Elf/Atom.zig+7-5
......@@ -79,9 +79,10 @@ pub fn freeRelocations(elf_file: *Elf, atom_index: Index) void {
7979}
8080
8181pub fn allocate(self: *Atom, elf_file: *Elf) !void {
82 const shdr = &elf_file.sections.items(.shdr)[self.output_section_index];
83 const free_list = &elf_file.sections.items(.free_list)[self.output_section_index];
84 const last_atom_index = &elf_file.sections.items(.last_atom_index)[self.output_section_index];
82 const shdr = &elf_file.shdrs.items[self.output_section_index];
83 const meta = elf_file.last_atom_and_free_list_table.getPtr(self.output_section_index).?;
84 const free_list = &meta.free_list;
85 const last_atom_index = &meta.last_atom_index;
8586 const new_atom_ideal_capacity = Elf.padToIdeal(self.size);
8687 const alignment = try std.math.powi(u64, 2, self.alignment);
8788
......@@ -208,7 +209,9 @@ pub fn free(self: *Atom, elf_file: *Elf) void {
208209
209210 const gpa = elf_file.base.allocator;
210211 const shndx = self.output_section_index;
211 const free_list = &elf_file.sections.items(.free_list)[shndx];
212 const meta = elf_file.last_atom_and_free_list_table.getPtr(shndx).?;
213 const free_list = &meta.free_list;
214 const last_atom_index = &meta.last_atom_index;
212215 var already_have_free_list_node = false;
213216 {
214217 var i: usize = 0;
......@@ -225,7 +228,6 @@ pub fn free(self: *Atom, elf_file: *Elf) void {
225228 }
226229 }
227230
228 const last_atom_index = &elf_file.sections.items(.last_atom_index)[shndx];
229231 if (elf_file.atom(last_atom_index.*)) |last_atom| {
230232 if (last_atom.atom_index == self.atom_index) {
231233 if (elf_file.atom(self.prev_index)) |_| {
src/link/Elf/synthetic_sections.zig+2-2
......@@ -29,7 +29,7 @@ pub const GotSection = struct {
2929
3030 pub fn address(entry: Entry, elf_file: *Elf) u64 {
3131 const ptr_bytes = @as(u64, elf_file.archPtrWidthBytes());
32 const shdr = &elf_file.sections.items(.shdr)[elf_file.got_section_index.?];
32 const shdr = &elf_file.shdrs.items[elf_file.got_section_index.?];
3333 return shdr.sh_addr + @as(u64, entry.cell_index) * ptr_bytes;
3434 }
3535 };
......@@ -124,7 +124,7 @@ pub const GotSection = struct {
124124 }
125125 const endian = elf_file.base.options.target.cpu.arch.endian();
126126 const entry = got.entries.items[index];
127 const shdr = &elf_file.sections.items(.shdr)[elf_file.got_section_index.?];
127 const shdr = &elf_file.shdrs.items[elf_file.got_section_index.?];
128128 const off = shdr.sh_offset + @as(u64, entry_size) * entry.cell_index;
129129 const vaddr = shdr.sh_addr + @as(u64, entry_size) * entry.cell_index;
130130 const value = elf_file.symbol(entry.symbol_index).value;