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(...@@ -1108,7 +1108,7 @@ pub fn commitDeclState(
1108 switch (self.bin_file.tag) {1108 switch (self.bin_file.tag) {
1109 .elf => {1109 .elf => {
1110 const elf_file = self.bin_file.cast(File.Elf).?;1110 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.?];
1112 const file_pos = debug_line_sect.sh_offset + src_fn.off;1112 const file_pos = debug_line_sect.sh_offset + src_fn.off;
1113 try pwriteDbgLineNops(elf_file.base.file.?, file_pos, 0, &[0]u8{}, src_fn.len);1113 try pwriteDbgLineNops(elf_file.base.file.?, file_pos, 0, &[0]u8{}, src_fn.len);
1114 },1114 },
...@@ -1170,7 +1170,7 @@ pub fn commitDeclState(...@@ -1170,7 +1170,7 @@ pub fn commitDeclState(
1170 const elf_file = self.bin_file.cast(File.Elf).?;1170 const elf_file = self.bin_file.cast(File.Elf).?;
1171 const shdr_index = elf_file.debug_line_section_index.?;1171 const shdr_index = elf_file.debug_line_section_index.?;
1172 try elf_file.growNonAllocSection(shdr_index, needed_size, 1, true);1172 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];
1174 const file_pos = debug_line_sect.sh_offset + src_fn.off;1174 const file_pos = debug_line_sect.sh_offset + src_fn.off;
1175 try pwriteDbgLineNops(1175 try pwriteDbgLineNops(
1176 elf_file.base.file.?,1176 elf_file.base.file.?,
...@@ -1337,7 +1337,7 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, atom_index: Atom.Index, len: u32)...@@ -1337,7 +1337,7 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, atom_index: Atom.Index, len: u32)
1337 switch (self.bin_file.tag) {1337 switch (self.bin_file.tag) {
1338 .elf => {1338 .elf => {
1339 const elf_file = self.bin_file.cast(File.Elf).?;1339 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.?];
1341 const file_pos = debug_info_sect.sh_offset + atom.off;1341 const file_pos = debug_info_sect.sh_offset + atom.off;
1342 try pwriteDbgInfoNops(elf_file.base.file.?, file_pos, 0, &[0]u8{}, atom.len, false);1342 try pwriteDbgInfoNops(elf_file.base.file.?, file_pos, 0, &[0]u8{}, atom.len, false);
1343 },1343 },
...@@ -1415,7 +1415,7 @@ fn writeDeclDebugInfo(self: *Dwarf, atom_index: Atom.Index, dbg_info_buf: []cons...@@ -1415,7 +1415,7 @@ fn writeDeclDebugInfo(self: *Dwarf, atom_index: Atom.Index, dbg_info_buf: []cons
1415 const elf_file = self.bin_file.cast(File.Elf).?;1415 const elf_file = self.bin_file.cast(File.Elf).?;
1416 const shdr_index = elf_file.debug_info_section_index.?;1416 const shdr_index = elf_file.debug_info_section_index.?;
1417 try elf_file.growNonAllocSection(shdr_index, needed_size, 1, true);1417 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];
1419 const file_pos = debug_info_sect.sh_offset + atom.off;1419 const file_pos = debug_info_sect.sh_offset + atom.off;
1420 try pwriteDbgInfoNops(1420 try pwriteDbgInfoNops(
1421 elf_file.base.file.?,1421 elf_file.base.file.?,
...@@ -1496,7 +1496,7 @@ pub fn updateDeclLineNumber(self: *Dwarf, mod: *Module, decl_index: Module.Decl....@@ -1496,7 +1496,7 @@ pub fn updateDeclLineNumber(self: *Dwarf, mod: *Module, decl_index: Module.Decl.
1496 switch (self.bin_file.tag) {1496 switch (self.bin_file.tag) {
1497 .elf => {1497 .elf => {
1498 const elf_file = self.bin_file.cast(File.Elf).?;1498 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.?];
1500 const file_pos = shdr.sh_offset + atom.off + self.getRelocDbgLineOff();1500 const file_pos = shdr.sh_offset + atom.off + self.getRelocDbgLineOff();
1501 try elf_file.base.file.?.pwriteAll(&data, file_pos);1501 try elf_file.base.file.?.pwriteAll(&data, file_pos);
1502 },1502 },
...@@ -1713,7 +1713,7 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void {...@@ -1713,7 +1713,7 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void {
1713 const elf_file = self.bin_file.cast(File.Elf).?;1713 const elf_file = self.bin_file.cast(File.Elf).?;
1714 const shdr_index = elf_file.debug_abbrev_section_index.?;1714 const shdr_index = elf_file.debug_abbrev_section_index.?;
1715 try elf_file.growNonAllocSection(shdr_index, needed_size, 1, false);1715 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];
1717 const file_pos = debug_abbrev_sect.sh_offset + abbrev_offset;1717 const file_pos = debug_abbrev_sect.sh_offset + abbrev_offset;
1718 try elf_file.base.file.?.pwriteAll(&abbrev_buf, file_pos);1718 try elf_file.base.file.?.pwriteAll(&abbrev_buf, file_pos);
1719 },1719 },
...@@ -1828,7 +1828,7 @@ pub fn writeDbgInfoHeader(self: *Dwarf, module: *Module, low_pc: u64, high_pc: u...@@ -1828,7 +1828,7 @@ pub fn writeDbgInfoHeader(self: *Dwarf, module: *Module, low_pc: u64, high_pc: u
1828 switch (self.bin_file.tag) {1828 switch (self.bin_file.tag) {
1829 .elf => {1829 .elf => {
1830 const elf_file = self.bin_file.cast(File.Elf).?;1830 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.?];
1832 const file_pos = debug_info_sect.sh_offset;1832 const file_pos = debug_info_sect.sh_offset;
1833 try pwriteDbgInfoNops(elf_file.base.file.?, file_pos, 0, di_buf.items, jmp_amt, false);1833 try pwriteDbgInfoNops(elf_file.base.file.?, file_pos, 0, di_buf.items, jmp_amt, false);
1834 },1834 },
...@@ -2147,7 +2147,7 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void {...@@ -2147,7 +2147,7 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void {
2147 const elf_file = self.bin_file.cast(File.Elf).?;2147 const elf_file = self.bin_file.cast(File.Elf).?;
2148 const shdr_index = elf_file.debug_aranges_section_index.?;2148 const shdr_index = elf_file.debug_aranges_section_index.?;
2149 try elf_file.growNonAllocSection(shdr_index, needed_size, 16, false);2149 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];
2151 const file_pos = debug_aranges_sect.sh_offset;2151 const file_pos = debug_aranges_sect.sh_offset;
2152 try elf_file.base.file.?.pwriteAll(di_buf.items, file_pos);2152 try elf_file.base.file.?.pwriteAll(di_buf.items, file_pos);
2153 },2153 },
...@@ -2312,9 +2312,9 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {...@@ -2312,9 +2312,9 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {
2312 .elf => {2312 .elf => {
2313 const elf_file = self.bin_file.cast(File.Elf).?;2313 const elf_file = self.bin_file.cast(File.Elf).?;
2314 const shdr_index = elf_file.debug_line_section_index.?;2314 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;
2316 try elf_file.growNonAllocSection(shdr_index, needed_size, 1, true);2316 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
2319 const amt = try elf_file.base.file.?.preadAll(buffer, file_pos);2319 const amt = try elf_file.base.file.?.preadAll(buffer, file_pos);
2320 if (amt != buffer.len) return error.InputOutput;2320 if (amt != buffer.len) return error.InputOutput;
...@@ -2377,7 +2377,7 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {...@@ -2377,7 +2377,7 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {
2377 switch (self.bin_file.tag) {2377 switch (self.bin_file.tag) {
2378 .elf => {2378 .elf => {
2379 const elf_file = self.bin_file.cast(File.Elf).?;2379 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.?];
2381 const file_pos = debug_line_sect.sh_offset;2381 const file_pos = debug_line_sect.sh_offset;
2382 try pwriteDbgLineNops(elf_file.base.file.?, file_pos, 0, di_buf.items, jmp_amt);2382 try pwriteDbgLineNops(elf_file.base.file.?, file_pos, 0, di_buf.items, jmp_amt);
2383 },2383 },
...@@ -2500,7 +2500,7 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {...@@ -2500,7 +2500,7 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {
2500 switch (self.bin_file.tag) {2500 switch (self.bin_file.tag) {
2501 .elf => {2501 .elf => {
2502 const elf_file = self.bin_file.cast(File.Elf).?;2502 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.?];
2504 break :blk debug_info_sect.sh_offset;2504 break :blk debug_info_sect.sh_offset;
2505 },2505 },
2506 .macho => {2506 .macho => {
src/link/Elf.zig+229-267
...@@ -12,7 +12,10 @@ linker_defined_index: ?File.Index = null,...@@ -12,7 +12,10 @@ linker_defined_index: ?File.Index = null,
1212
13/// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write.13/// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write.
14/// Same order as in the file.14/// 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.
16shdr_table_offset: ?u64 = null,19shdr_table_offset: ?u64 = null,
1720
18/// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write.21/// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write.
...@@ -85,7 +88,6 @@ symbols: std.ArrayListUnmanaged(Symbol) = .{},...@@ -85,7 +88,6 @@ symbols: std.ArrayListUnmanaged(Symbol) = .{},
85symbols_extra: std.ArrayListUnmanaged(u32) = .{},88symbols_extra: std.ArrayListUnmanaged(u32) = .{},
86resolver: std.AutoArrayHashMapUnmanaged(u32, Symbol.Index) = .{},89resolver: std.AutoArrayHashMapUnmanaged(u32, Symbol.Index) = .{},
87unresolved: std.AutoArrayHashMapUnmanaged(u32, void) = .{},90unresolved: std.AutoArrayHashMapUnmanaged(u32, void) = .{},
88
89symbols_free_list: std.ArrayListUnmanaged(Symbol.Index) = .{},91symbols_free_list: std.ArrayListUnmanaged(Symbol.Index) = .{},
9092
91phdr_table_dirty: bool = false,93phdr_table_dirty: bool = false,
...@@ -109,6 +111,8 @@ decls: std.AutoHashMapUnmanaged(Module.Decl.Index, DeclMetadata) = .{},...@@ -109,6 +111,8 @@ decls: std.AutoHashMapUnmanaged(Module.Decl.Index, DeclMetadata) = .{},
109111
110/// List of atoms that are owned directly by the linker.112/// List of atoms that are owned directly by the linker.
111atoms: std.ArrayListUnmanaged(Atom) = .{},113atoms: 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
113/// Table of unnamed constants associated with a parent `Decl`.117/// Table of unnamed constants associated with a parent `Decl`.
114/// We store them here so that we can free the constants whenever the `Decl`118/// 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...@@ -176,21 +180,18 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
176 try self.atoms.append(allocator, .{});180 try self.atoms.append(allocator, .{});
177 // Append null file at index 0181 // Append null file at index 0
178 try self.files.append(allocator, .null);182 try self.files.append(allocator, .null);
179 // There must always be a null section in index 0183 // There must always be a null shdr in index 0
180 try self.sections.append(allocator, .{184 try self.shdrs.append(allocator, .{
181 .shdr = .{185 .sh_name = 0,
182 .sh_name = 0,186 .sh_type = elf.SHT_NULL,
183 .sh_type = elf.SHT_NULL,187 .sh_flags = 0,
184 .sh_flags = 0,188 .sh_addr = 0,
185 .sh_addr = 0,189 .sh_offset = 0,
186 .sh_offset = 0,190 .sh_size = 0,
187 .sh_size = 0,191 .sh_link = 0,
188 .sh_link = 0,192 .sh_info = 0,
189 .sh_info = 0,193 .sh_addralign = 0,
190 .sh_addralign = 0,194 .sh_entsize = 0,
191 .sh_entsize = 0,
192 },
193 .phdr_index = undefined,
194 });195 });
195196
196 try self.populateMissingMetadata();197 try self.populateMissingMetadata();
...@@ -256,11 +257,8 @@ pub fn deinit(self: *Elf) void {...@@ -256,11 +257,8 @@ pub fn deinit(self: *Elf) void {
256 };257 };
257 self.files.deinit(gpa);258 self.files.deinit(gpa);
258259
259 for (self.sections.items(.free_list)) |*free_list| {260 self.shdrs.deinit(gpa);
260 free_list.deinit(gpa);261 self.phdr_to_shdr_table.deinit(gpa);
261 }
262 self.sections.deinit(gpa);
263
264 self.phdrs.deinit(gpa);262 self.phdrs.deinit(gpa);
265 self.shstrtab.deinit(gpa);263 self.shstrtab.deinit(gpa);
266 self.strtab.deinit(gpa);264 self.strtab.deinit(gpa);
...@@ -281,6 +279,10 @@ pub fn deinit(self: *Elf) void {...@@ -281,6 +279,10 @@ pub fn deinit(self: *Elf) void {
281 }279 }
282280
283 self.atoms.deinit(gpa);281 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);
284 self.lazy_syms.deinit(gpa);286 self.lazy_syms.deinit(gpa);
285287
286 {288 {
...@@ -332,7 +334,7 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 {...@@ -332,7 +334,7 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 {
332334
333 if (self.shdr_table_offset) |off| {335 if (self.shdr_table_offset) |off| {
334 const shdr_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Shdr) else @sizeOf(elf.Elf64_Shdr);336 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;
336 const increased_size = padToIdeal(tight_size);338 const increased_size = padToIdeal(tight_size);
337 const test_end = off + increased_size;339 const test_end = off + increased_size;
338 if (end > off and start < test_end) {340 if (end > off and start < test_end) {
...@@ -340,7 +342,7 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 {...@@ -340,7 +342,7 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 {
340 }342 }
341 }343 }
342344
343 for (self.sections.items(.shdr)) |section| {345 for (self.shdrs.items) |section| {
344 const increased_size = padToIdeal(section.sh_size);346 const increased_size = padToIdeal(section.sh_size);
345 const test_end = section.sh_offset + increased_size;347 const test_end = section.sh_offset + increased_size;
346 if (end > section.sh_offset and start < test_end) {348 if (end > section.sh_offset and start < test_end) {
...@@ -364,7 +366,7 @@ pub fn allocatedSize(self: *Elf, start: u64) u64 {...@@ -364,7 +366,7 @@ pub fn allocatedSize(self: *Elf, start: u64) u64 {
364 if (self.shdr_table_offset) |off| {366 if (self.shdr_table_offset) |off| {
365 if (off > start and off < min_pos) min_pos = off;367 if (off > start and off < min_pos) min_pos = off;
366 }368 }
367 for (self.sections.items(.shdr)) |section| {369 for (self.shdrs.items) |section| {
368 if (section.sh_offset <= start) continue;370 if (section.sh_offset <= start) continue;
369 if (section.sh_offset < min_pos) min_pos = section.sh_offset;371 if (section.sh_offset < min_pos) min_pos = section.sh_offset;
370 }372 }
...@@ -522,197 +524,174 @@ pub fn populateMissingMetadata(self: *Elf) !void {...@@ -522,197 +524,174 @@ pub fn populateMissingMetadata(self: *Elf) !void {
522 }524 }
523525
524 if (self.shstrtab_section_index == null) {526 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));
526 assert(self.shstrtab.buffer.items.len == 0);528 assert(self.shstrtab.buffer.items.len == 0);
527 try self.shstrtab.buffer.append(gpa, 0); // need a 0 at position 0529 try self.shstrtab.buffer.append(gpa, 0); // need a 0 at position 0
528 const off = self.findFreeSpace(self.shstrtab.buffer.items.len, 1);530 const off = self.findFreeSpace(self.shstrtab.buffer.items.len, 1);
529 log.debug("found .shstrtab free space 0x{x} to 0x{x}", .{ off, off + self.shstrtab.buffer.items.len });531 log.debug("found .shstrtab free space 0x{x} to 0x{x}", .{ off, off + self.shstrtab.buffer.items.len });
530 try self.sections.append(gpa, .{532 try self.shdrs.append(gpa, .{
531 .shdr = .{533 .sh_name = try self.shstrtab.insert(gpa, ".shstrtab"),
532 .sh_name = try self.shstrtab.insert(gpa, ".shstrtab"),534 .sh_type = elf.SHT_STRTAB,
533 .sh_type = elf.SHT_STRTAB,535 .sh_flags = 0,
534 .sh_flags = 0,536 .sh_addr = 0,
535 .sh_addr = 0,537 .sh_offset = off,
536 .sh_offset = off,538 .sh_size = self.shstrtab.buffer.items.len,
537 .sh_size = self.shstrtab.buffer.items.len,539 .sh_link = 0,
538 .sh_link = 0,540 .sh_info = 0,
539 .sh_info = 0,541 .sh_addralign = 1,
540 .sh_addralign = 1,542 .sh_entsize = 0,
541 .sh_entsize = 0,
542 },
543 .phdr_index = undefined,
544 });543 });
545 self.shstrtab_dirty = true;544 self.shstrtab_dirty = true;
546 self.shdr_table_dirty = true;545 self.shdr_table_dirty = true;
547 }546 }
548547
549 if (self.strtab_section_index == null) {548 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));
551 assert(self.strtab.buffer.items.len == 0);550 assert(self.strtab.buffer.items.len == 0);
552 try self.strtab.buffer.append(gpa, 0); // need a 0 at position 0551 try self.strtab.buffer.append(gpa, 0); // need a 0 at position 0
553 const off = self.findFreeSpace(self.strtab.buffer.items.len, 1);552 const off = self.findFreeSpace(self.strtab.buffer.items.len, 1);
554 log.debug("found .strtab free space 0x{x} to 0x{x}", .{ off, off + self.strtab.buffer.items.len });553 log.debug("found .strtab free space 0x{x} to 0x{x}", .{ off, off + self.strtab.buffer.items.len });
555 try self.sections.append(gpa, .{554 try self.shdrs.append(gpa, .{
556 .shdr = .{555 .sh_name = try self.shstrtab.insert(gpa, ".strtab"),
557 .sh_name = try self.shstrtab.insert(gpa, ".strtab"),556 .sh_type = elf.SHT_STRTAB,
558 .sh_type = elf.SHT_STRTAB,557 .sh_flags = 0,
559 .sh_flags = 0,558 .sh_addr = 0,
560 .sh_addr = 0,559 .sh_offset = off,
561 .sh_offset = off,560 .sh_size = self.strtab.buffer.items.len,
562 .sh_size = self.strtab.buffer.items.len,561 .sh_link = 0,
563 .sh_link = 0,562 .sh_info = 0,
564 .sh_info = 0,563 .sh_addralign = 1,
565 .sh_addralign = 1,564 .sh_entsize = 0,
566 .sh_entsize = 0,
567 },
568 .phdr_index = undefined,
569 });565 });
570 self.strtab_dirty = true;566 self.strtab_dirty = true;
571 self.shdr_table_dirty = true;567 self.shdr_table_dirty = true;
572 }568 }
573569
574 if (self.text_section_index == null) {570 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));
576 const phdr = &self.phdrs.items[self.phdr_load_re_index.?];572 const phdr = &self.phdrs.items[self.phdr_load_re_index.?];
577573 try self.shdrs.append(gpa, .{
578 try self.sections.append(gpa, .{574 .sh_name = try self.shstrtab.insert(gpa, ".text"),
579 .shdr = .{575 .sh_type = elf.SHT_PROGBITS,
580 .sh_name = try self.shstrtab.insert(gpa, ".text"),576 .sh_flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
581 .sh_type = elf.SHT_PROGBITS,577 .sh_addr = phdr.p_vaddr,
582 .sh_flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,578 .sh_offset = phdr.p_offset,
583 .sh_addr = phdr.p_vaddr,579 .sh_size = phdr.p_filesz,
584 .sh_offset = phdr.p_offset,580 .sh_link = 0,
585 .sh_size = phdr.p_filesz,581 .sh_info = 0,
586 .sh_link = 0,582 .sh_addralign = 1,
587 .sh_info = 0,583 .sh_entsize = 0,
588 .sh_addralign = 1,
589 .sh_entsize = 0,
590 },
591 .phdr_index = self.phdr_load_re_index.?,
592 });584 });
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.?, .{});
593 self.shdr_table_dirty = true;587 self.shdr_table_dirty = true;
594 }588 }
595589
596 if (self.got_section_index == null) {590 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));
598 const phdr = &self.phdrs.items[self.phdr_got_index.?];592 const phdr = &self.phdrs.items[self.phdr_got_index.?];
599593 try self.shdrs.append(gpa, .{
600 try self.sections.append(gpa, .{594 .sh_name = try self.shstrtab.insert(gpa, ".got"),
601 .shdr = .{595 .sh_type = elf.SHT_PROGBITS,
602 .sh_name = try self.shstrtab.insert(gpa, ".got"),596 .sh_flags = elf.SHF_ALLOC,
603 .sh_type = elf.SHT_PROGBITS,597 .sh_addr = phdr.p_vaddr,
604 .sh_flags = elf.SHF_ALLOC,598 .sh_offset = phdr.p_offset,
605 .sh_addr = phdr.p_vaddr,599 .sh_size = phdr.p_filesz,
606 .sh_offset = phdr.p_offset,600 .sh_link = 0,
607 .sh_size = phdr.p_filesz,601 .sh_info = 0,
608 .sh_link = 0,602 .sh_addralign = @as(u16, ptr_size),
609 .sh_info = 0,603 .sh_entsize = 0,
610 .sh_addralign = @as(u16, ptr_size),
611 .sh_entsize = 0,
612 },
613 .phdr_index = self.phdr_got_index.?,
614 });604 });
605 try self.phdr_to_shdr_table.putNoClobber(gpa, self.got_section_index.?, self.phdr_got_index.?);
615 self.shdr_table_dirty = true;606 self.shdr_table_dirty = true;
616 }607 }
617608
618 if (self.rodata_section_index == null) {609 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));
620 const phdr = &self.phdrs.items[self.phdr_load_ro_index.?];611 const phdr = &self.phdrs.items[self.phdr_load_ro_index.?];
621612 try self.shdrs.append(gpa, .{
622 try self.sections.append(gpa, .{613 .sh_name = try self.shstrtab.insert(gpa, ".rodata"),
623 .shdr = .{614 .sh_type = elf.SHT_PROGBITS,
624 .sh_name = try self.shstrtab.insert(gpa, ".rodata"),615 .sh_flags = elf.SHF_ALLOC,
625 .sh_type = elf.SHT_PROGBITS,616 .sh_addr = phdr.p_vaddr,
626 .sh_flags = elf.SHF_ALLOC,617 .sh_offset = phdr.p_offset,
627 .sh_addr = phdr.p_vaddr,618 .sh_size = phdr.p_filesz,
628 .sh_offset = phdr.p_offset,619 .sh_link = 0,
629 .sh_size = phdr.p_filesz,620 .sh_info = 0,
630 .sh_link = 0,621 .sh_addralign = 1,
631 .sh_info = 0,622 .sh_entsize = 0,
632 .sh_addralign = 1,
633 .sh_entsize = 0,
634 },
635 .phdr_index = self.phdr_load_ro_index.?,
636 });623 });
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.?, .{});
637 self.shdr_table_dirty = true;626 self.shdr_table_dirty = true;
638 }627 }
639628
640 if (self.data_section_index == null) {629 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));
642 const phdr = &self.phdrs.items[self.phdr_load_rw_index.?];631 const phdr = &self.phdrs.items[self.phdr_load_rw_index.?];
643632 try self.shdrs.append(gpa, .{
644 try self.sections.append(gpa, .{633 .sh_name = try self.shstrtab.insert(gpa, ".data"),
645 .shdr = .{634 .sh_type = elf.SHT_PROGBITS,
646 .sh_name = try self.shstrtab.insert(gpa, ".data"),635 .sh_flags = elf.SHF_WRITE | elf.SHF_ALLOC,
647 .sh_type = elf.SHT_PROGBITS,636 .sh_addr = phdr.p_vaddr,
648 .sh_flags = elf.SHF_WRITE | elf.SHF_ALLOC,637 .sh_offset = phdr.p_offset,
649 .sh_addr = phdr.p_vaddr,638 .sh_size = phdr.p_filesz,
650 .sh_offset = phdr.p_offset,639 .sh_link = 0,
651 .sh_size = phdr.p_filesz,640 .sh_info = 0,
652 .sh_link = 0,641 .sh_addralign = @as(u16, ptr_size),
653 .sh_info = 0,642 .sh_entsize = 0,
654 .sh_addralign = @as(u16, ptr_size),
655 .sh_entsize = 0,
656 },
657 .phdr_index = self.phdr_load_rw_index.?,
658 });643 });
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.?, .{});
659 self.shdr_table_dirty = true;646 self.shdr_table_dirty = true;
660 }647 }
661648
662 if (self.symtab_section_index == null) {649 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));
664 const min_align: u16 = if (small_ptr) @alignOf(elf.Elf32_Sym) else @alignOf(elf.Elf64_Sym);651 const min_align: u16 = if (small_ptr) @alignOf(elf.Elf32_Sym) else @alignOf(elf.Elf64_Sym);
665 const each_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Sym) else @sizeOf(elf.Elf64_Sym);652 const each_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Sym) else @sizeOf(elf.Elf64_Sym);
666 const file_size = self.base.options.symbol_count_hint * each_size;653 const file_size = self.base.options.symbol_count_hint * each_size;
667 const off = self.findFreeSpace(file_size, min_align);654 const off = self.findFreeSpace(file_size, min_align);
668 log.debug("found symtab free space 0x{x} to 0x{x}", .{ off, off + file_size });655 log.debug("found symtab free space 0x{x} to 0x{x}", .{ off, off + file_size });
669656 try self.shdrs.append(gpa, .{
670 try self.sections.append(gpa, .{657 .sh_name = try self.shstrtab.insert(gpa, ".symtab"),
671 .shdr = .{658 .sh_type = elf.SHT_SYMTAB,
672 .sh_name = try self.shstrtab.insert(gpa, ".symtab"),659 .sh_flags = 0,
673 .sh_type = elf.SHT_SYMTAB,660 .sh_addr = 0,
674 .sh_flags = 0,661 .sh_offset = off,
675 .sh_addr = 0,662 .sh_size = file_size,
676 .sh_offset = off,663 // The section header index of the associated string table.
677 .sh_size = file_size,664 .sh_link = self.strtab_section_index.?,
678 // The section header index of the associated string table.665 .sh_info = @as(u32, @intCast(self.symbols.items.len)),
679 .sh_link = self.strtab_section_index.?,666 .sh_addralign = min_align,
680 .sh_info = @as(u32, @intCast(self.symbols.items.len)),667 .sh_entsize = each_size,
681 .sh_addralign = min_align,
682 .sh_entsize = each_size,
683 },
684 .phdr_index = undefined,
685 });668 });
686 self.shdr_table_dirty = true;669 self.shdr_table_dirty = true;
687 }670 }
688671
689 if (self.dwarf) |*dw| {672 if (self.dwarf) |*dw| {
690 if (self.debug_str_section_index == null) {673 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));
692 assert(dw.strtab.buffer.items.len == 0);675 assert(dw.strtab.buffer.items.len == 0);
693 try dw.strtab.buffer.append(gpa, 0);676 try dw.strtab.buffer.append(gpa, 0);
694 try self.sections.append(gpa, .{677 try self.shdrs.append(gpa, .{
695 .shdr = .{678 .sh_name = try self.shstrtab.insert(gpa, ".debug_str"),
696 .sh_name = try self.shstrtab.insert(gpa, ".debug_str"),679 .sh_type = elf.SHT_PROGBITS,
697 .sh_type = elf.SHT_PROGBITS,680 .sh_flags = elf.SHF_MERGE | elf.SHF_STRINGS,
698 .sh_flags = elf.SHF_MERGE | elf.SHF_STRINGS,681 .sh_addr = 0,
699 .sh_addr = 0,682 .sh_offset = 0,
700 .sh_offset = 0,683 .sh_size = 0,
701 .sh_size = 0,684 .sh_link = 0,
702 .sh_link = 0,685 .sh_info = 0,
703 .sh_info = 0,686 .sh_addralign = 1,
704 .sh_addralign = 1,687 .sh_entsize = 1,
705 .sh_entsize = 1,
706 },
707 .phdr_index = undefined,
708 });688 });
709 self.debug_strtab_dirty = true;689 self.debug_strtab_dirty = true;
710 self.shdr_table_dirty = true;690 self.shdr_table_dirty = true;
711 }691 }
712692
713 if (self.debug_info_section_index == null) {693 if (self.debug_info_section_index == null) {
714 self.debug_info_section_index = @as(u16, @intCast(self.sections.slice().len));694 self.debug_info_section_index = @as(u16, @intCast(self.shdrs.items.len));
715
716 const file_size_hint = 200;695 const file_size_hint = 200;
717 const p_align = 1;696 const p_align = 1;
718 const off = self.findFreeSpace(file_size_hint, p_align);697 const off = self.findFreeSpace(file_size_hint, p_align);
...@@ -720,28 +699,24 @@ pub fn populateMissingMetadata(self: *Elf) !void {...@@ -720,28 +699,24 @@ pub fn populateMissingMetadata(self: *Elf) !void {
720 off,699 off,
721 off + file_size_hint,700 off + file_size_hint,
722 });701 });
723 try self.sections.append(gpa, .{702 try self.shdrs.append(gpa, .{
724 .shdr = .{703 .sh_name = try self.shstrtab.insert(gpa, ".debug_info"),
725 .sh_name = try self.shstrtab.insert(gpa, ".debug_info"),704 .sh_type = elf.SHT_PROGBITS,
726 .sh_type = elf.SHT_PROGBITS,705 .sh_flags = 0,
727 .sh_flags = 0,706 .sh_addr = 0,
728 .sh_addr = 0,707 .sh_offset = off,
729 .sh_offset = off,708 .sh_size = file_size_hint,
730 .sh_size = file_size_hint,709 .sh_link = 0,
731 .sh_link = 0,710 .sh_info = 0,
732 .sh_info = 0,711 .sh_addralign = p_align,
733 .sh_addralign = p_align,712 .sh_entsize = 0,
734 .sh_entsize = 0,
735 },
736 .phdr_index = undefined,
737 });713 });
738 self.shdr_table_dirty = true;714 self.shdr_table_dirty = true;
739 self.debug_info_header_dirty = true;715 self.debug_info_header_dirty = true;
740 }716 }
741717
742 if (self.debug_abbrev_section_index == null) {718 if (self.debug_abbrev_section_index == null) {
743 self.debug_abbrev_section_index = @as(u16, @intCast(self.sections.slice().len));719 self.debug_abbrev_section_index = @as(u16, @intCast(self.shdrs.items.len));
744
745 const file_size_hint = 128;720 const file_size_hint = 128;
746 const p_align = 1;721 const p_align = 1;
747 const off = self.findFreeSpace(file_size_hint, p_align);722 const off = self.findFreeSpace(file_size_hint, p_align);
...@@ -749,28 +724,24 @@ pub fn populateMissingMetadata(self: *Elf) !void {...@@ -749,28 +724,24 @@ pub fn populateMissingMetadata(self: *Elf) !void {
749 off,724 off,
750 off + file_size_hint,725 off + file_size_hint,
751 });726 });
752 try self.sections.append(gpa, .{727 try self.shdrs.append(gpa, .{
753 .shdr = .{728 .sh_name = try self.shstrtab.insert(gpa, ".debug_abbrev"),
754 .sh_name = try self.shstrtab.insert(gpa, ".debug_abbrev"),729 .sh_type = elf.SHT_PROGBITS,
755 .sh_type = elf.SHT_PROGBITS,730 .sh_flags = 0,
756 .sh_flags = 0,731 .sh_addr = 0,
757 .sh_addr = 0,732 .sh_offset = off,
758 .sh_offset = off,733 .sh_size = file_size_hint,
759 .sh_size = file_size_hint,734 .sh_link = 0,
760 .sh_link = 0,735 .sh_info = 0,
761 .sh_info = 0,736 .sh_addralign = p_align,
762 .sh_addralign = p_align,737 .sh_entsize = 0,
763 .sh_entsize = 0,
764 },
765 .phdr_index = undefined,
766 });738 });
767 self.shdr_table_dirty = true;739 self.shdr_table_dirty = true;
768 self.debug_abbrev_section_dirty = true;740 self.debug_abbrev_section_dirty = true;
769 }741 }
770742
771 if (self.debug_aranges_section_index == null) {743 if (self.debug_aranges_section_index == null) {
772 self.debug_aranges_section_index = @as(u16, @intCast(self.sections.slice().len));744 self.debug_aranges_section_index = @as(u16, @intCast(self.shdrs.items.len));
773
774 const file_size_hint = 160;745 const file_size_hint = 160;
775 const p_align = 16;746 const p_align = 16;
776 const off = self.findFreeSpace(file_size_hint, p_align);747 const off = self.findFreeSpace(file_size_hint, p_align);
...@@ -778,28 +749,24 @@ pub fn populateMissingMetadata(self: *Elf) !void {...@@ -778,28 +749,24 @@ pub fn populateMissingMetadata(self: *Elf) !void {
778 off,749 off,
779 off + file_size_hint,750 off + file_size_hint,
780 });751 });
781 try self.sections.append(gpa, .{752 try self.shdrs.append(gpa, .{
782 .shdr = .{753 .sh_name = try self.shstrtab.insert(gpa, ".debug_aranges"),
783 .sh_name = try self.shstrtab.insert(gpa, ".debug_aranges"),754 .sh_type = elf.SHT_PROGBITS,
784 .sh_type = elf.SHT_PROGBITS,755 .sh_flags = 0,
785 .sh_flags = 0,756 .sh_addr = 0,
786 .sh_addr = 0,757 .sh_offset = off,
787 .sh_offset = off,758 .sh_size = file_size_hint,
788 .sh_size = file_size_hint,759 .sh_link = 0,
789 .sh_link = 0,760 .sh_info = 0,
790 .sh_info = 0,761 .sh_addralign = p_align,
791 .sh_addralign = p_align,762 .sh_entsize = 0,
792 .sh_entsize = 0,
793 },
794 .phdr_index = undefined,
795 });763 });
796 self.shdr_table_dirty = true;764 self.shdr_table_dirty = true;
797 self.debug_aranges_section_dirty = true;765 self.debug_aranges_section_dirty = true;
798 }766 }
799767
800 if (self.debug_line_section_index == null) {768 if (self.debug_line_section_index == null) {
801 self.debug_line_section_index = @as(u16, @intCast(self.sections.slice().len));769 self.debug_line_section_index = @as(u16, @intCast(self.shdrs.items.len));
802
803 const file_size_hint = 250;770 const file_size_hint = 250;
804 const p_align = 1;771 const p_align = 1;
805 const off = self.findFreeSpace(file_size_hint, p_align);772 const off = self.findFreeSpace(file_size_hint, p_align);
...@@ -807,20 +774,17 @@ pub fn populateMissingMetadata(self: *Elf) !void {...@@ -807,20 +774,17 @@ pub fn populateMissingMetadata(self: *Elf) !void {
807 off,774 off,
808 off + file_size_hint,775 off + file_size_hint,
809 });776 });
810 try self.sections.append(gpa, .{777 try self.shdrs.append(gpa, .{
811 .shdr = .{778 .sh_name = try self.shstrtab.insert(gpa, ".debug_line"),
812 .sh_name = try self.shstrtab.insert(gpa, ".debug_line"),779 .sh_type = elf.SHT_PROGBITS,
813 .sh_type = elf.SHT_PROGBITS,780 .sh_flags = 0,
814 .sh_flags = 0,781 .sh_addr = 0,
815 .sh_addr = 0,782 .sh_offset = off,
816 .sh_offset = off,783 .sh_size = file_size_hint,
817 .sh_size = file_size_hint,784 .sh_link = 0,
818 .sh_link = 0,785 .sh_info = 0,
819 .sh_info = 0,786 .sh_addralign = p_align,
820 .sh_addralign = p_align,787 .sh_entsize = 0,
821 .sh_entsize = 0,
822 },
823 .phdr_index = undefined,
824 });788 });
825 self.shdr_table_dirty = true;789 self.shdr_table_dirty = true;
826 self.debug_line_header_dirty = true;790 self.debug_line_header_dirty = true;
...@@ -836,7 +800,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {...@@ -836,7 +800,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
836 .p64 => @alignOf(elf.Elf64_Shdr),800 .p64 => @alignOf(elf.Elf64_Shdr),
837 };801 };
838 if (self.shdr_table_offset == null) {802 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);
840 self.shdr_table_dirty = true;804 self.shdr_table_dirty = true;
841 }805 }
842806
...@@ -854,7 +818,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {...@@ -854,7 +818,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
854 // offset + it's filesize.818 // offset + it's filesize.
855 var max_file_offset: u64 = 0;819 var max_file_offset: u64 = 0;
856820
857 for (self.sections.items(.shdr)) |shdr| {821 for (self.shdrs.items) |shdr| {
858 if (shdr.sh_offset + shdr.sh_size > max_file_offset) {822 if (shdr.sh_offset + shdr.sh_size > max_file_offset) {
859 max_file_offset = shdr.sh_offset + shdr.sh_size;823 max_file_offset = shdr.sh_offset + shdr.sh_size;
860 }824 }
...@@ -885,19 +849,17 @@ pub fn populateMissingMetadata(self: *Elf) !void {...@@ -885,19 +849,17 @@ pub fn populateMissingMetadata(self: *Elf) !void {
885849
886pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void {850pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void {
887 // TODO Also detect virtual address collisions.851 // TODO Also detect virtual address collisions.
888 const shdr = &self.sections.items(.shdr)[shdr_index];852 const shdr = &self.shdrs.items[shdr_index];
889 const phdr_index = self.sections.items(.phdr_index)[shdr_index];853 const phdr_index = self.phdr_to_shdr_table.get(shdr_index).?;
890 const phdr = &self.phdrs.items[phdr_index];854 const phdr = &self.phdrs.items[phdr_index];
891 const last_atom_index = self.sections.items(.last_atom_index)[shdr_index];
892855
893 if (needed_size > self.allocatedSize(shdr.sh_offset)) {856 if (needed_size > self.allocatedSize(shdr.sh_offset)) {
894 // Must move the entire section.857 // Must move the entire section.
895 const new_offset = self.findFreeSpace(needed_size, self.page_size);858 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;
897 break :blk (last.value + last.size) - phdr.p_vaddr;861 break :blk (last.value + last.size) - phdr.p_vaddr;
898 } else if (shdr_index == self.got_section_index.?) blk: {862 } else shdr.sh_size;
899 break :blk shdr.sh_size;
900 } else 0;
901 shdr.sh_size = 0;863 shdr.sh_size = 0;
902864
903 log.debug("new '{?s}' file offset 0x{x} to 0x{x}", .{865 log.debug("new '{?s}' file offset 0x{x} to 0x{x}", .{
...@@ -927,7 +889,7 @@ pub fn growNonAllocSection(...@@ -927,7 +889,7 @@ pub fn growNonAllocSection(
927 min_alignment: u32,889 min_alignment: u32,
928 requires_file_copy: bool,890 requires_file_copy: bool,
929) !void {891) !void {
930 const shdr = &self.sections.items(.shdr)[shdr_index];892 const shdr = &self.shdrs.items[shdr_index];
931893
932 if (needed_size > self.allocatedSize(shdr.sh_offset)) {894 if (needed_size > self.allocatedSize(shdr.sh_offset)) {
933 const existing_size = if (self.symtab_section_index.? == shdr_index) blk: {895 const existing_size = if (self.symtab_section_index.? == shdr_index) blk: {
...@@ -940,7 +902,12 @@ pub fn growNonAllocSection(...@@ -940,7 +902,12 @@ pub fn growNonAllocSection(
940 shdr.sh_size = 0;902 shdr.sh_size = 0;
941 // Move all the symbols to a new file location.903 // Move all the symbols to a new file location.
942 const new_offset = self.findFreeSpace(needed_size, min_alignment);904 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
945 if (requires_file_copy) {912 if (requires_file_copy) {
946 const amt = try self.base.file.?.copyRangeAll(913 const amt = try self.base.file.?.copyRangeAll(
...@@ -1071,7 +1038,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1071,7 +1038,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1071 const atom_index = entry.key_ptr.*;1038 const atom_index = entry.key_ptr.*;
1072 const relocs = entry.value_ptr.*;1039 const relocs = entry.value_ptr.*;
1073 const atom_ptr = self.atom(atom_index).?;1040 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
1076 log.debug("relocating '{s}'", .{atom_ptr.name(self)});1043 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...@@ -1209,9 +1176,9 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
12091176
1210 {1177 {
1211 const shdr_index = self.shstrtab_section_index.?;1178 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) {
1213 try self.growNonAllocSection(shdr_index, self.shstrtab.buffer.items.len, 1, false);1180 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];
1215 try self.base.file.?.pwriteAll(self.shstrtab.buffer.items, shstrtab_sect.sh_offset);1182 try self.base.file.?.pwriteAll(self.shstrtab.buffer.items, shstrtab_sect.sh_offset);
1216 self.shstrtab_dirty = false;1183 self.shstrtab_dirty = false;
1217 }1184 }
...@@ -1219,9 +1186,9 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1219,9 +1186,9 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
12191186
1220 {1187 {
1221 const shdr_index = self.strtab_section_index.?;1188 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) {
1223 try self.growNonAllocSection(shdr_index, self.strtab.buffer.items.len, 1, false);1190 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];
1225 try self.base.file.?.pwriteAll(self.strtab.buffer.items, strtab_sect.sh_offset);1192 try self.base.file.?.pwriteAll(self.strtab.buffer.items, strtab_sect.sh_offset);
1226 self.strtab_dirty = false;1193 self.strtab_dirty = false;
1227 }1194 }
...@@ -1229,9 +1196,9 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1229,9 +1196,9 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
12291196
1230 if (self.dwarf) |dwarf| {1197 if (self.dwarf) |dwarf| {
1231 const shdr_index = self.debug_str_section_index.?;1198 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) {
1233 try self.growNonAllocSection(shdr_index, dwarf.strtab.buffer.items.len, 1, false);1200 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];
1235 try self.base.file.?.pwriteAll(dwarf.strtab.buffer.items, debug_strtab_sect.sh_offset);1202 try self.base.file.?.pwriteAll(dwarf.strtab.buffer.items, debug_strtab_sect.sh_offset);
1236 self.debug_strtab_dirty = false;1203 self.debug_strtab_dirty = false;
1237 }1204 }
...@@ -1247,7 +1214,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1247,7 +1214,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1247 .p64 => @alignOf(elf.Elf64_Shdr),1214 .p64 => @alignOf(elf.Elf64_Shdr),
1248 };1215 };
1249 const allocated_size = self.allocatedSize(self.shdr_table_offset.?);1216 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
1252 if (needed_size > allocated_size) {1219 if (needed_size > allocated_size) {
1253 self.shdr_table_offset = null; // free the space1220 self.shdr_table_offset = null; // free the space
...@@ -1256,12 +1223,11 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1256,12 +1223,11 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
12561223
1257 switch (self.ptr_width) {1224 switch (self.ptr_width) {
1258 .p32 => {1225 .p32 => {
1259 const slice = self.sections.slice();1226 const buf = try gpa.alloc(elf.Elf32_Shdr, self.shdrs.items.len);
1260 const buf = try gpa.alloc(elf.Elf32_Shdr, slice.len);
1261 defer gpa.free(buf);1227 defer gpa.free(buf);
12621228
1263 for (buf, 0..) |*shdr, i| {1229 for (buf, 0..) |*shdr, i| {
1264 shdr.* = shdrTo32(slice.items(.shdr)[i]);1230 shdr.* = shdrTo32(self.shdrs.items[i]);
1265 log.debug("writing section {?s}: {}", .{ self.shstrtab.get(shdr.sh_name), shdr.* });1231 log.debug("writing section {?s}: {}", .{ self.shstrtab.get(shdr.sh_name), shdr.* });
1266 if (foreign_endian) {1232 if (foreign_endian) {
1267 mem.byteSwapAllFields(elf.Elf32_Shdr, shdr);1233 mem.byteSwapAllFields(elf.Elf32_Shdr, shdr);
...@@ -1270,12 +1236,11 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1270,12 +1236,11 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1270 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?);1236 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?);
1271 },1237 },
1272 .p64 => {1238 .p64 => {
1273 const slice = self.sections.slice();1239 const buf = try gpa.alloc(elf.Elf64_Shdr, self.shdrs.items.len);
1274 const buf = try gpa.alloc(elf.Elf64_Shdr, slice.len);
1275 defer gpa.free(buf);1240 defer gpa.free(buf);
12761241
1277 for (buf, 0..) |*shdr, i| {1242 for (buf, 0..) |*shdr, i| {
1278 shdr.* = slice.items(.shdr)[i];1243 shdr.* = self.shdrs.items[i];
1279 log.debug("writing section {?s}: {}", .{ self.shstrtab.get(shdr.sh_name), shdr.* });1244 log.debug("writing section {?s}: {}", .{ self.shstrtab.get(shdr.sh_name), shdr.* });
1280 if (foreign_endian) {1245 if (foreign_endian) {
1281 mem.byteSwapAllFields(elf.Elf64_Shdr, shdr);1246 mem.byteSwapAllFields(elf.Elf64_Shdr, shdr);
...@@ -2118,7 +2083,7 @@ fn writeElfHeader(self: *Elf) !void {...@@ -2118,7 +2083,7 @@ fn writeElfHeader(self: *Elf) !void {
2118 mem.writeInt(u16, hdr_buf[index..][0..2], e_shentsize, endian);2083 mem.writeInt(u16, hdr_buf[index..][0..2], e_shentsize, endian);
2119 index += 2;2084 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));
2122 mem.writeInt(u16, hdr_buf[index..][0..2], e_shnum, endian);2087 mem.writeInt(u16, hdr_buf[index..][0..2], e_shnum, endian);
2123 index += 2;2088 index += 2;
21242089
...@@ -2305,9 +2270,9 @@ fn updateDeclCode(...@@ -2305,9 +2270,9 @@ fn updateDeclCode(
2305 try self.got.writeEntry(self, got_index);2270 try self.got.writeEntry(self, got_index);
2306 }2271 }
23072272
2308 const phdr_index = self.sections.items(.phdr_index)[shdr_index];2273 const phdr_index = self.phdr_to_shdr_table.get(shdr_index).?;
2309 const section_offset = sym.value - self.phdrs.items[phdr_index].p_vaddr;2274 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
2312 if (self.base.child_pid) |pid| {2277 if (self.base.child_pid) |pid| {
2313 switch (builtin.os.tag) {2278 switch (builtin.os.tag) {
...@@ -2510,7 +2475,7 @@ fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol....@@ -2510,7 +2475,7 @@ fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol.
2510 };2475 };
25112476
2512 const local_sym = self.symbol(symbol_index);2477 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).?;
2514 local_sym.name_offset = name_str_index;2479 local_sym.name_offset = name_str_index;
2515 const local_esym = local_sym.sourceSymbol(self);2480 const local_esym = local_sym.sourceSymbol(self);
2516 local_esym.st_name = name_str_index;2481 local_esym.st_name = name_str_index;
...@@ -2537,7 +2502,7 @@ fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol....@@ -2537,7 +2502,7 @@ fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol.
2537 try self.got.writeEntry(self, got_index);2502 try self.got.writeEntry(self, got_index);
25382503
2539 const section_offset = atom_ptr.value - self.phdrs.items[phdr_index].p_vaddr;2504 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;
2541 try self.base.file.?.pwriteAll(code, file_offset);2506 try self.base.file.?.pwriteAll(code, file_offset);
2542}2507}
25432508
...@@ -2584,7 +2549,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module...@@ -2584,7 +2549,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module
25842549
2585 const required_alignment = typed_value.ty.abiAlignment(mod);2550 const required_alignment = typed_value.ty.abiAlignment(mod);
2586 const shdr_index = self.rodata_section_index.?;2551 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).?;
2588 const local_sym = self.symbol(sym_index);2553 const local_sym = self.symbol(sym_index);
2589 local_sym.name_offset = name_str_index;2554 local_sym.name_offset = name_str_index;
2590 const local_esym = local_sym.sourceSymbol(self);2555 const local_esym = local_sym.sourceSymbol(self);
...@@ -2607,7 +2572,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module...@@ -2607,7 +2572,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module
2607 try unnamed_consts.append(gpa, atom_ptr.atom_index);2572 try unnamed_consts.append(gpa, atom_ptr.atom_index);
26082573
2609 const section_offset = atom_ptr.value - self.phdrs.items[phdr_index].p_vaddr;2574 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;
2611 try self.base.file.?.pwriteAll(code, file_offset);2576 try self.base.file.?.pwriteAll(code, file_offset);
26122577
2613 return sym_index;2578 return sym_index;
...@@ -2775,7 +2740,7 @@ fn addLinkerDefinedSymbols(self: *Elf) !void {...@@ -2775,7 +2740,7 @@ fn addLinkerDefinedSymbols(self: *Elf) !void {
2775fn allocateLinkerDefinedSymbols(self: *Elf) void {2740fn allocateLinkerDefinedSymbols(self: *Elf) void {
2776 // _DYNAMIC2741 // _DYNAMIC
2777 if (self.dynamic_section_index) |shndx| {2742 if (self.dynamic_section_index) |shndx| {
2778 const shdr = self.sections.items(.shdr)[shndx];2743 const shdr = &self.shdrs.items[shndx];
2779 const symbol_ptr = self.symbol(self.dynamic_index.?);2744 const symbol_ptr = self.symbol(self.dynamic_index.?);
2780 symbol_ptr.value = shdr.sh_addr;2745 symbol_ptr.value = shdr.sh_addr;
2781 symbol_ptr.output_section_index = shndx;2746 symbol_ptr.output_section_index = shndx;
...@@ -2792,7 +2757,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {...@@ -2792,7 +2757,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
2792 if (self.sectionByName(".init_array")) |shndx| {2757 if (self.sectionByName(".init_array")) |shndx| {
2793 const start_sym = self.symbol(self.init_array_start_index.?);2758 const start_sym = self.symbol(self.init_array_start_index.?);
2794 const end_sym = self.symbol(self.init_array_end_index.?);2759 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];
2796 start_sym.output_section_index = shndx;2761 start_sym.output_section_index = shndx;
2797 start_sym.value = shdr.sh_addr;2762 start_sym.value = shdr.sh_addr;
2798 end_sym.output_section_index = shndx;2763 end_sym.output_section_index = shndx;
...@@ -2803,7 +2768,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {...@@ -2803,7 +2768,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
2803 if (self.sectionByName(".fini_array")) |shndx| {2768 if (self.sectionByName(".fini_array")) |shndx| {
2804 const start_sym = self.symbol(self.fini_array_start_index.?);2769 const start_sym = self.symbol(self.fini_array_start_index.?);
2805 const end_sym = self.symbol(self.fini_array_end_index.?);2770 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];
2807 start_sym.output_section_index = shndx;2772 start_sym.output_section_index = shndx;
2808 start_sym.value = shdr.sh_addr;2773 start_sym.value = shdr.sh_addr;
2809 end_sym.output_section_index = shndx;2774 end_sym.output_section_index = shndx;
...@@ -2814,7 +2779,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {...@@ -2814,7 +2779,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
2814 if (self.sectionByName(".preinit_array")) |shndx| {2779 if (self.sectionByName(".preinit_array")) |shndx| {
2815 const start_sym = self.symbol(self.preinit_array_start_index.?);2780 const start_sym = self.symbol(self.preinit_array_start_index.?);
2816 const end_sym = self.symbol(self.preinit_array_end_index.?);2781 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];
2818 start_sym.output_section_index = shndx;2783 start_sym.output_section_index = shndx;
2819 start_sym.value = shdr.sh_addr;2784 start_sym.value = shdr.sh_addr;
2820 end_sym.output_section_index = shndx;2785 end_sym.output_section_index = shndx;
...@@ -2823,7 +2788,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {...@@ -2823,7 +2788,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
28232788
2824 // _GLOBAL_OFFSET_TABLE_2789 // _GLOBAL_OFFSET_TABLE_
2825 if (self.got_plt_section_index) |shndx| {2790 if (self.got_plt_section_index) |shndx| {
2826 const shdr = &self.sections.items(.shdr)[shndx];2791 const shdr = &self.shdrs.items[shndx];
2827 const symbol_ptr = self.symbol(self.got_index.?);2792 const symbol_ptr = self.symbol(self.got_index.?);
2828 symbol_ptr.value = shdr.sh_addr;2793 symbol_ptr.value = shdr.sh_addr;
2829 symbol_ptr.output_section_index = shndx;2794 symbol_ptr.output_section_index = shndx;
...@@ -2831,7 +2796,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {...@@ -2831,7 +2796,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
28312796
2832 // _PROCEDURE_LINKAGE_TABLE_2797 // _PROCEDURE_LINKAGE_TABLE_
2833 if (self.plt_section_index) |shndx| {2798 if (self.plt_section_index) |shndx| {
2834 const shdr = &self.sections.items(.shdr)[shndx];2799 const shdr = &self.shdrs.items[shndx];
2835 const symbol_ptr = self.symbol(self.plt_index.?);2800 const symbol_ptr = self.symbol(self.plt_index.?);
2836 symbol_ptr.value = shdr.sh_addr;2801 symbol_ptr.value = shdr.sh_addr;
2837 symbol_ptr.output_section_index = shndx;2802 symbol_ptr.output_section_index = shndx;
...@@ -2839,7 +2804,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {...@@ -2839,7 +2804,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
28392804
2840 // __dso_handle2805 // __dso_handle
2841 if (self.dso_handle_index) |index| {2806 if (self.dso_handle_index) |index| {
2842 const shdr = &self.sections.items(.shdr)[1];2807 const shdr = &self.shdrs.items[1];
2843 const symbol_ptr = self.symbol(index);2808 const symbol_ptr = self.symbol(index);
2844 symbol_ptr.value = shdr.sh_addr;2809 symbol_ptr.value = shdr.sh_addr;
2845 symbol_ptr.output_section_index = 0;2810 symbol_ptr.output_section_index = 0;
...@@ -2847,7 +2812,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {...@@ -2847,7 +2812,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
28472812
2848 // __GNU_EH_FRAME_HDR2813 // __GNU_EH_FRAME_HDR
2849 if (self.eh_frame_hdr_section_index) |shndx| {2814 if (self.eh_frame_hdr_section_index) |shndx| {
2850 const shdr = &self.sections.items(.shdr)[shndx];2815 const shdr = &self.shdrs.items[shndx];
2851 const symbol_ptr = self.symbol(self.gnu_eh_frame_hdr_index.?);2816 const symbol_ptr = self.symbol(self.gnu_eh_frame_hdr_index.?);
2852 symbol_ptr.value = shdr.sh_addr;2817 symbol_ptr.value = shdr.sh_addr;
2853 symbol_ptr.output_section_index = shndx;2818 symbol_ptr.output_section_index = shndx;
...@@ -2856,7 +2821,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {...@@ -2856,7 +2821,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
2856 // __rela_iplt_start, __rela_iplt_end2821 // __rela_iplt_start, __rela_iplt_end
2857 if (self.rela_dyn_section_index) |shndx| blk: {2822 if (self.rela_dyn_section_index) |shndx| blk: {
2858 if (self.base.options.link_mode != .Static or self.base.options.pie) break :blk;2823 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];
2860 const end_addr = shdr.sh_addr + shdr.sh_size;2825 const end_addr = shdr.sh_addr + shdr.sh_size;
2861 const start_addr = end_addr - self.calcNumIRelativeRelocs() * @sizeOf(elf.Elf64_Rela);2826 const start_addr = end_addr - self.calcNumIRelativeRelocs() * @sizeOf(elf.Elf64_Rela);
2862 const start_sym = self.symbol(self.rela_iplt_start_index.?);2827 const start_sym = self.symbol(self.rela_iplt_start_index.?);
...@@ -2870,7 +2835,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {...@@ -2870,7 +2835,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
2870 // _end2835 // _end
2871 {2836 {
2872 const end_symbol = self.symbol(self.end_index.?);2837 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| {
2874 if (shdr.sh_flags & elf.SHF_ALLOC != 0) {2839 if (shdr.sh_flags & elf.SHF_ALLOC != 0) {
2875 end_symbol.value = shdr.sh_addr + shdr.sh_size;2840 end_symbol.value = shdr.sh_addr + shdr.sh_size;
2876 end_symbol.output_section_index = @intCast(shndx);2841 end_symbol.output_section_index = @intCast(shndx);
...@@ -2886,7 +2851,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {...@@ -2886,7 +2851,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
2886 const name = start.name(self);2851 const name = start.name(self);
2887 const stop = self.symbol(self.start_stop_indexes.items[index + 1]);2852 const stop = self.symbol(self.start_stop_indexes.items[index + 1]);
2888 const shndx = self.sectionByName(name["__start_".len..]).?;2853 const shndx = self.sectionByName(name["__start_".len..]).?;
2889 const shdr = self.sections.items(.shdr)[shndx];2854 const shdr = &self.shdrs.items[shndx];
2890 start.value = shdr.sh_addr;2855 start.value = shdr.sh_addr;
2891 start.output_section_index = shndx;2856 start.output_section_index = shndx;
2892 stop.value = shdr.sh_addr + shdr.sh_size;2857 stop.value = shdr.sh_addr + shdr.sh_size;
...@@ -2916,7 +2881,7 @@ fn updateSymtabSize(self: *Elf) !void {...@@ -2916,7 +2881,7 @@ fn updateSymtabSize(self: *Elf) !void {
2916 sizes.nlocals += linker_defined.output_symtab_size.nlocals;2881 sizes.nlocals += linker_defined.output_symtab_size.nlocals;
2917 }2882 }
29182883
2919 const shdr = &self.sections.items(.shdr)[self.symtab_section_index.?];2884 const shdr = &self.shdrs.items[self.symtab_section_index.?];
2920 shdr.sh_info = sizes.nlocals + 1;2885 shdr.sh_info = sizes.nlocals + 1;
2921 self.markDirty(self.symtab_section_index.?, null);2886 self.markDirty(self.symtab_section_index.?, null);
29222887
...@@ -2934,7 +2899,7 @@ fn updateSymtabSize(self: *Elf) !void {...@@ -2934,7 +2899,7 @@ fn updateSymtabSize(self: *Elf) !void {
29342899
2935fn writeSymtab(self: *Elf) !void {2900fn writeSymtab(self: *Elf) !void {
2936 const gpa = self.base.allocator;2901 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.?];
2938 const sym_size: u64 = switch (self.ptr_width) {2903 const sym_size: u64 = switch (self.ptr_width) {
2939 .p32 => @sizeOf(elf.Elf32_Sym),2904 .p32 => @sizeOf(elf.Elf32_Sym),
2940 .p64 => @sizeOf(elf.Elf64_Sym),2905 .p64 => @sizeOf(elf.Elf64_Sym),
...@@ -3031,7 +2996,7 @@ fn writeShdr(self: *Elf, index: usize) !void {...@@ -3031,7 +2996,7 @@ fn writeShdr(self: *Elf, index: usize) !void {
3031 switch (self.ptr_width) {2996 switch (self.ptr_width) {
3032 .p32 => {2997 .p32 => {
3033 var shdr: [1]elf.Elf32_Shdr = undefined;2998 var shdr: [1]elf.Elf32_Shdr = undefined;
3034 shdr[0] = shdrTo32(self.sections.items(.shdr)[index]);2999 shdr[0] = shdrTo32(self.shdrs.items[index]);
3035 if (foreign_endian) {3000 if (foreign_endian) {
3036 mem.byteSwapAllFields(elf.Elf32_Shdr, &shdr[0]);3001 mem.byteSwapAllFields(elf.Elf32_Shdr, &shdr[0]);
3037 }3002 }
...@@ -3039,7 +3004,7 @@ fn writeShdr(self: *Elf, index: usize) !void {...@@ -3039,7 +3004,7 @@ fn writeShdr(self: *Elf, index: usize) !void {
3039 return self.base.file.?.pwriteAll(mem.sliceAsBytes(&shdr), offset);3004 return self.base.file.?.pwriteAll(mem.sliceAsBytes(&shdr), offset);
3040 },3005 },
3041 .p64 => {3006 .p64 => {
3042 var shdr = [1]elf.Elf64_Shdr{self.sections.items(.shdr)[index]};3007 var shdr = [1]elf.Elf64_Shdr{self.shdrs.items[index]};
3043 if (foreign_endian) {3008 if (foreign_endian) {
3044 mem.byteSwapAllFields(elf.Elf64_Shdr, &shdr[0]);3009 mem.byteSwapAllFields(elf.Elf64_Shdr, &shdr[0]);
3045 }3010 }
...@@ -3327,7 +3292,7 @@ pub fn defaultEntryAddress(self: Elf) u64 {...@@ -3327,7 +3292,7 @@ pub fn defaultEntryAddress(self: Elf) u64 {
3327}3292}
33283293
3329pub fn sectionByName(self: *Elf, name: [:0]const u8) ?u16 {3294pub 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| {
3331 const this_name = self.shstrtab.getAssumeExists(shdr.sh_name);3296 const this_name = self.shstrtab.getAssumeExists(shdr.sh_name);
3332 if (mem.eql(u8, this_name, name)) return @as(u16, @intCast(i));3297 if (mem.eql(u8, this_name, name)) return @as(u16, @intCast(i));
3333 } else return null;3298 } else return null;
...@@ -3481,10 +3446,7 @@ const default_entry_addr = 0x8000000;...@@ -3481,10 +3446,7 @@ const default_entry_addr = 0x8000000;
34813446
3482pub const base_tag: link.File.Tag = .elf;3447pub const base_tag: link.File.Tag = .elf;
34833448
3484const Section = struct {3449const LastAtomAndFreeList = struct {
3485 shdr: elf.Elf64_Shdr,
3486 phdr_index: u16,
3487
3488 /// Index of the last allocated atom in this section.3450 /// Index of the last allocated atom in this section.
3489 last_atom_index: Atom.Index = 0,3451 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 {...@@ -79,9 +79,10 @@ pub fn freeRelocations(elf_file: *Elf, atom_index: Index) void {
79}79}
8080
81pub fn allocate(self: *Atom, elf_file: *Elf) !void {81pub fn allocate(self: *Atom, elf_file: *Elf) !void {
82 const shdr = &elf_file.sections.items(.shdr)[self.output_section_index];82 const shdr = &elf_file.shdrs.items[self.output_section_index];
83 const free_list = &elf_file.sections.items(.free_list)[self.output_section_index];83 const meta = elf_file.last_atom_and_free_list_table.getPtr(self.output_section_index).?;
84 const last_atom_index = &elf_file.sections.items(.last_atom_index)[self.output_section_index];84 const free_list = &meta.free_list;
85 const last_atom_index = &meta.last_atom_index;
85 const new_atom_ideal_capacity = Elf.padToIdeal(self.size);86 const new_atom_ideal_capacity = Elf.padToIdeal(self.size);
86 const alignment = try std.math.powi(u64, 2, self.alignment);87 const alignment = try std.math.powi(u64, 2, self.alignment);
8788
...@@ -208,7 +209,9 @@ pub fn free(self: *Atom, elf_file: *Elf) void {...@@ -208,7 +209,9 @@ pub fn free(self: *Atom, elf_file: *Elf) void {
208209
209 const gpa = elf_file.base.allocator;210 const gpa = elf_file.base.allocator;
210 const shndx = self.output_section_index;211 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;
212 var already_have_free_list_node = false;215 var already_have_free_list_node = false;
213 {216 {
214 var i: usize = 0;217 var i: usize = 0;
...@@ -225,7 +228,6 @@ pub fn free(self: *Atom, elf_file: *Elf) void {...@@ -225,7 +228,6 @@ pub fn free(self: *Atom, elf_file: *Elf) void {
225 }228 }
226 }229 }
227230
228 const last_atom_index = &elf_file.sections.items(.last_atom_index)[shndx];
229 if (elf_file.atom(last_atom_index.*)) |last_atom| {231 if (elf_file.atom(last_atom_index.*)) |last_atom| {
230 if (last_atom.atom_index == self.atom_index) {232 if (last_atom.atom_index == self.atom_index) {
231 if (elf_file.atom(self.prev_index)) |_| {233 if (elf_file.atom(self.prev_index)) |_| {
src/link/Elf/synthetic_sections.zig+2-2
...@@ -29,7 +29,7 @@ pub const GotSection = struct {...@@ -29,7 +29,7 @@ pub const GotSection = struct {
2929
30 pub fn address(entry: Entry, elf_file: *Elf) u64 {30 pub fn address(entry: Entry, elf_file: *Elf) u64 {
31 const ptr_bytes = @as(u64, elf_file.archPtrWidthBytes());31 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.?];
33 return shdr.sh_addr + @as(u64, entry.cell_index) * ptr_bytes;33 return shdr.sh_addr + @as(u64, entry.cell_index) * ptr_bytes;
34 }34 }
35 };35 };
...@@ -124,7 +124,7 @@ pub const GotSection = struct {...@@ -124,7 +124,7 @@ pub const GotSection = struct {
124 }124 }
125 const endian = elf_file.base.options.target.cpu.arch.endian();125 const endian = elf_file.base.options.target.cpu.arch.endian();
126 const entry = got.entries.items[index];126 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.?];
128 const off = shdr.sh_offset + @as(u64, entry_size) * entry.cell_index;128 const off = shdr.sh_offset + @as(u64, entry_size) * entry.cell_index;
129 const vaddr = shdr.sh_addr + @as(u64, entry_size) * entry.cell_index;129 const vaddr = shdr.sh_addr + @as(u64, entry_size) * entry.cell_index;
130 const value = elf_file.symbol(entry.symbol_index).value;130 const value = elf_file.symbol(entry.symbol_index).value;