mirror of
https://github.com/ziglang/zig.git
synced 2025-12-28 17:13:19 +00:00
elf: decouple notion of atom free list from shdrs
Not every section will have the need for such a free list.
This commit is contained in:
parent
a3ce011408
commit
4b082d89c9
@ -1108,7 +1108,7 @@ pub fn commitDeclState(
|
||||
switch (self.bin_file.tag) {
|
||||
.elf => {
|
||||
const elf_file = self.bin_file.cast(File.Elf).?;
|
||||
const debug_line_sect = &elf_file.sections.items(.shdr)[elf_file.debug_line_section_index.?];
|
||||
const debug_line_sect = &elf_file.shdrs.items[elf_file.debug_line_section_index.?];
|
||||
const file_pos = debug_line_sect.sh_offset + src_fn.off;
|
||||
try pwriteDbgLineNops(elf_file.base.file.?, file_pos, 0, &[0]u8{}, src_fn.len);
|
||||
},
|
||||
@ -1170,7 +1170,7 @@ pub fn commitDeclState(
|
||||
const elf_file = self.bin_file.cast(File.Elf).?;
|
||||
const shdr_index = elf_file.debug_line_section_index.?;
|
||||
try elf_file.growNonAllocSection(shdr_index, needed_size, 1, true);
|
||||
const debug_line_sect = elf_file.sections.items(.shdr)[shdr_index];
|
||||
const debug_line_sect = elf_file.shdrs.items[shdr_index];
|
||||
const file_pos = debug_line_sect.sh_offset + src_fn.off;
|
||||
try pwriteDbgLineNops(
|
||||
elf_file.base.file.?,
|
||||
@ -1337,7 +1337,7 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, atom_index: Atom.Index, len: u32)
|
||||
switch (self.bin_file.tag) {
|
||||
.elf => {
|
||||
const elf_file = self.bin_file.cast(File.Elf).?;
|
||||
const debug_info_sect = &elf_file.sections.items(.shdr)[elf_file.debug_info_section_index.?];
|
||||
const debug_info_sect = &elf_file.shdrs.items[elf_file.debug_info_section_index.?];
|
||||
const file_pos = debug_info_sect.sh_offset + atom.off;
|
||||
try pwriteDbgInfoNops(elf_file.base.file.?, file_pos, 0, &[0]u8{}, atom.len, false);
|
||||
},
|
||||
@ -1415,7 +1415,7 @@ fn writeDeclDebugInfo(self: *Dwarf, atom_index: Atom.Index, dbg_info_buf: []cons
|
||||
const elf_file = self.bin_file.cast(File.Elf).?;
|
||||
const shdr_index = elf_file.debug_info_section_index.?;
|
||||
try elf_file.growNonAllocSection(shdr_index, needed_size, 1, true);
|
||||
const debug_info_sect = elf_file.sections.items(.shdr)[shdr_index];
|
||||
const debug_info_sect = &elf_file.shdrs.items[shdr_index];
|
||||
const file_pos = debug_info_sect.sh_offset + atom.off;
|
||||
try pwriteDbgInfoNops(
|
||||
elf_file.base.file.?,
|
||||
@ -1496,7 +1496,7 @@ pub fn updateDeclLineNumber(self: *Dwarf, mod: *Module, decl_index: Module.Decl.
|
||||
switch (self.bin_file.tag) {
|
||||
.elf => {
|
||||
const elf_file = self.bin_file.cast(File.Elf).?;
|
||||
const shdr = elf_file.sections.items(.shdr)[elf_file.debug_line_section_index.?];
|
||||
const shdr = elf_file.shdrs.items[elf_file.debug_line_section_index.?];
|
||||
const file_pos = shdr.sh_offset + atom.off + self.getRelocDbgLineOff();
|
||||
try elf_file.base.file.?.pwriteAll(&data, file_pos);
|
||||
},
|
||||
@ -1713,7 +1713,7 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void {
|
||||
const elf_file = self.bin_file.cast(File.Elf).?;
|
||||
const shdr_index = elf_file.debug_abbrev_section_index.?;
|
||||
try elf_file.growNonAllocSection(shdr_index, needed_size, 1, false);
|
||||
const debug_abbrev_sect = elf_file.sections.items(.shdr)[shdr_index];
|
||||
const debug_abbrev_sect = &elf_file.shdrs.items[shdr_index];
|
||||
const file_pos = debug_abbrev_sect.sh_offset + abbrev_offset;
|
||||
try elf_file.base.file.?.pwriteAll(&abbrev_buf, file_pos);
|
||||
},
|
||||
@ -1828,7 +1828,7 @@ pub fn writeDbgInfoHeader(self: *Dwarf, module: *Module, low_pc: u64, high_pc: u
|
||||
switch (self.bin_file.tag) {
|
||||
.elf => {
|
||||
const elf_file = self.bin_file.cast(File.Elf).?;
|
||||
const debug_info_sect = elf_file.sections.items(.shdr)[elf_file.debug_info_section_index.?];
|
||||
const debug_info_sect = &elf_file.shdrs.items[elf_file.debug_info_section_index.?];
|
||||
const file_pos = debug_info_sect.sh_offset;
|
||||
try pwriteDbgInfoNops(elf_file.base.file.?, file_pos, 0, di_buf.items, jmp_amt, false);
|
||||
},
|
||||
@ -2147,7 +2147,7 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void {
|
||||
const elf_file = self.bin_file.cast(File.Elf).?;
|
||||
const shdr_index = elf_file.debug_aranges_section_index.?;
|
||||
try elf_file.growNonAllocSection(shdr_index, needed_size, 16, false);
|
||||
const debug_aranges_sect = elf_file.sections.items(.shdr)[shdr_index];
|
||||
const debug_aranges_sect = &elf_file.shdrs.items[shdr_index];
|
||||
const file_pos = debug_aranges_sect.sh_offset;
|
||||
try elf_file.base.file.?.pwriteAll(di_buf.items, file_pos);
|
||||
},
|
||||
@ -2312,9 +2312,9 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {
|
||||
.elf => {
|
||||
const elf_file = self.bin_file.cast(File.Elf).?;
|
||||
const shdr_index = elf_file.debug_line_section_index.?;
|
||||
const needed_size = elf_file.sections.items(.shdr)[shdr_index].sh_size + delta;
|
||||
const needed_size = elf_file.shdrs.items[shdr_index].sh_size + delta;
|
||||
try elf_file.growNonAllocSection(shdr_index, needed_size, 1, true);
|
||||
const file_pos = elf_file.sections.items(.shdr)[shdr_index].sh_offset + first_fn.off;
|
||||
const file_pos = elf_file.shdrs.items[shdr_index].sh_offset + first_fn.off;
|
||||
|
||||
const amt = try elf_file.base.file.?.preadAll(buffer, file_pos);
|
||||
if (amt != buffer.len) return error.InputOutput;
|
||||
@ -2377,7 +2377,7 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void {
|
||||
switch (self.bin_file.tag) {
|
||||
.elf => {
|
||||
const elf_file = self.bin_file.cast(File.Elf).?;
|
||||
const debug_line_sect = elf_file.sections.items(.shdr)[elf_file.debug_line_section_index.?];
|
||||
const debug_line_sect = &elf_file.shdrs.items[elf_file.debug_line_section_index.?];
|
||||
const file_pos = debug_line_sect.sh_offset;
|
||||
try pwriteDbgLineNops(elf_file.base.file.?, file_pos, 0, di_buf.items, jmp_amt);
|
||||
},
|
||||
@ -2500,7 +2500,7 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {
|
||||
switch (self.bin_file.tag) {
|
||||
.elf => {
|
||||
const elf_file = self.bin_file.cast(File.Elf).?;
|
||||
const debug_info_sect = &elf_file.sections.items(.shdr)[elf_file.debug_info_section_index.?];
|
||||
const debug_info_sect = &elf_file.shdrs.items[elf_file.debug_info_section_index.?];
|
||||
break :blk debug_info_sect.sh_offset;
|
||||
},
|
||||
.macho => {
|
||||
|
||||
496
src/link/Elf.zig
496
src/link/Elf.zig
@ -12,7 +12,10 @@ linker_defined_index: ?File.Index = null,
|
||||
|
||||
/// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write.
|
||||
/// Same order as in the file.
|
||||
sections: std.MultiArrayList(Section) = .{},
|
||||
shdrs: std.ArrayListUnmanaged(elf.Elf64_Shdr) = .{},
|
||||
/// Given index to a section, pulls index of containing phdr if any.
|
||||
phdr_to_shdr_table: std.AutoHashMapUnmanaged(u16, u16) = .{},
|
||||
/// File offset into the shdr table.
|
||||
shdr_table_offset: ?u64 = null,
|
||||
|
||||
/// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write.
|
||||
@ -85,7 +88,6 @@ symbols: std.ArrayListUnmanaged(Symbol) = .{},
|
||||
symbols_extra: std.ArrayListUnmanaged(u32) = .{},
|
||||
resolver: std.AutoArrayHashMapUnmanaged(u32, Symbol.Index) = .{},
|
||||
unresolved: std.AutoArrayHashMapUnmanaged(u32, void) = .{},
|
||||
|
||||
symbols_free_list: std.ArrayListUnmanaged(Symbol.Index) = .{},
|
||||
|
||||
phdr_table_dirty: bool = false,
|
||||
@ -109,6 +111,8 @@ decls: std.AutoHashMapUnmanaged(Module.Decl.Index, DeclMetadata) = .{},
|
||||
|
||||
/// List of atoms that are owned directly by the linker.
|
||||
atoms: std.ArrayListUnmanaged(Atom) = .{},
|
||||
/// Table of last atom index in a section and matching atom free list if any.
|
||||
last_atom_and_free_list_table: std.AutoArrayHashMapUnmanaged(u16, LastAtomAndFreeList) = .{},
|
||||
|
||||
/// Table of unnamed constants associated with a parent `Decl`.
|
||||
/// 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
|
||||
try self.atoms.append(allocator, .{});
|
||||
// Append null file at index 0
|
||||
try self.files.append(allocator, .null);
|
||||
// There must always be a null section in index 0
|
||||
try self.sections.append(allocator, .{
|
||||
.shdr = .{
|
||||
.sh_name = 0,
|
||||
.sh_type = elf.SHT_NULL,
|
||||
.sh_flags = 0,
|
||||
.sh_addr = 0,
|
||||
.sh_offset = 0,
|
||||
.sh_size = 0,
|
||||
.sh_link = 0,
|
||||
.sh_info = 0,
|
||||
.sh_addralign = 0,
|
||||
.sh_entsize = 0,
|
||||
},
|
||||
.phdr_index = undefined,
|
||||
// There must always be a null shdr in index 0
|
||||
try self.shdrs.append(allocator, .{
|
||||
.sh_name = 0,
|
||||
.sh_type = elf.SHT_NULL,
|
||||
.sh_flags = 0,
|
||||
.sh_addr = 0,
|
||||
.sh_offset = 0,
|
||||
.sh_size = 0,
|
||||
.sh_link = 0,
|
||||
.sh_info = 0,
|
||||
.sh_addralign = 0,
|
||||
.sh_entsize = 0,
|
||||
});
|
||||
|
||||
try self.populateMissingMetadata();
|
||||
@ -256,11 +257,8 @@ pub fn deinit(self: *Elf) void {
|
||||
};
|
||||
self.files.deinit(gpa);
|
||||
|
||||
for (self.sections.items(.free_list)) |*free_list| {
|
||||
free_list.deinit(gpa);
|
||||
}
|
||||
self.sections.deinit(gpa);
|
||||
|
||||
self.shdrs.deinit(gpa);
|
||||
self.phdr_to_shdr_table.deinit(gpa);
|
||||
self.phdrs.deinit(gpa);
|
||||
self.shstrtab.deinit(gpa);
|
||||
self.strtab.deinit(gpa);
|
||||
@ -281,6 +279,10 @@ pub fn deinit(self: *Elf) void {
|
||||
}
|
||||
|
||||
self.atoms.deinit(gpa);
|
||||
for (self.last_atom_and_free_list_table.values()) |*value| {
|
||||
value.free_list.deinit(gpa);
|
||||
}
|
||||
self.last_atom_and_free_list_table.deinit(gpa);
|
||||
self.lazy_syms.deinit(gpa);
|
||||
|
||||
{
|
||||
@ -332,7 +334,7 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 {
|
||||
|
||||
if (self.shdr_table_offset) |off| {
|
||||
const shdr_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Shdr) else @sizeOf(elf.Elf64_Shdr);
|
||||
const tight_size = self.sections.slice().len * shdr_size;
|
||||
const tight_size = self.shdrs.items.len * shdr_size;
|
||||
const increased_size = padToIdeal(tight_size);
|
||||
const test_end = off + increased_size;
|
||||
if (end > off and start < test_end) {
|
||||
@ -340,7 +342,7 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 {
|
||||
}
|
||||
}
|
||||
|
||||
for (self.sections.items(.shdr)) |section| {
|
||||
for (self.shdrs.items) |section| {
|
||||
const increased_size = padToIdeal(section.sh_size);
|
||||
const test_end = section.sh_offset + increased_size;
|
||||
if (end > section.sh_offset and start < test_end) {
|
||||
@ -364,7 +366,7 @@ pub fn allocatedSize(self: *Elf, start: u64) u64 {
|
||||
if (self.shdr_table_offset) |off| {
|
||||
if (off > start and off < min_pos) min_pos = off;
|
||||
}
|
||||
for (self.sections.items(.shdr)) |section| {
|
||||
for (self.shdrs.items) |section| {
|
||||
if (section.sh_offset <= start) continue;
|
||||
if (section.sh_offset < min_pos) min_pos = section.sh_offset;
|
||||
}
|
||||
@ -522,197 +524,174 @@ pub fn populateMissingMetadata(self: *Elf) !void {
|
||||
}
|
||||
|
||||
if (self.shstrtab_section_index == null) {
|
||||
self.shstrtab_section_index = @as(u16, @intCast(self.sections.slice().len));
|
||||
self.shstrtab_section_index = @as(u16, @intCast(self.shdrs.items.len));
|
||||
assert(self.shstrtab.buffer.items.len == 0);
|
||||
try self.shstrtab.buffer.append(gpa, 0); // need a 0 at position 0
|
||||
const off = self.findFreeSpace(self.shstrtab.buffer.items.len, 1);
|
||||
log.debug("found .shstrtab free space 0x{x} to 0x{x}", .{ off, off + self.shstrtab.buffer.items.len });
|
||||
try self.sections.append(gpa, .{
|
||||
.shdr = .{
|
||||
.sh_name = try self.shstrtab.insert(gpa, ".shstrtab"),
|
||||
.sh_type = elf.SHT_STRTAB,
|
||||
.sh_flags = 0,
|
||||
.sh_addr = 0,
|
||||
.sh_offset = off,
|
||||
.sh_size = self.shstrtab.buffer.items.len,
|
||||
.sh_link = 0,
|
||||
.sh_info = 0,
|
||||
.sh_addralign = 1,
|
||||
.sh_entsize = 0,
|
||||
},
|
||||
.phdr_index = undefined,
|
||||
try self.shdrs.append(gpa, .{
|
||||
.sh_name = try self.shstrtab.insert(gpa, ".shstrtab"),
|
||||
.sh_type = elf.SHT_STRTAB,
|
||||
.sh_flags = 0,
|
||||
.sh_addr = 0,
|
||||
.sh_offset = off,
|
||||
.sh_size = self.shstrtab.buffer.items.len,
|
||||
.sh_link = 0,
|
||||
.sh_info = 0,
|
||||
.sh_addralign = 1,
|
||||
.sh_entsize = 0,
|
||||
});
|
||||
self.shstrtab_dirty = true;
|
||||
self.shdr_table_dirty = true;
|
||||
}
|
||||
|
||||
if (self.strtab_section_index == null) {
|
||||
self.strtab_section_index = @as(u16, @intCast(self.sections.slice().len));
|
||||
self.strtab_section_index = @as(u16, @intCast(self.shdrs.items.len));
|
||||
assert(self.strtab.buffer.items.len == 0);
|
||||
try self.strtab.buffer.append(gpa, 0); // need a 0 at position 0
|
||||
const off = self.findFreeSpace(self.strtab.buffer.items.len, 1);
|
||||
log.debug("found .strtab free space 0x{x} to 0x{x}", .{ off, off + self.strtab.buffer.items.len });
|
||||
try self.sections.append(gpa, .{
|
||||
.shdr = .{
|
||||
.sh_name = try self.shstrtab.insert(gpa, ".strtab"),
|
||||
.sh_type = elf.SHT_STRTAB,
|
||||
.sh_flags = 0,
|
||||
.sh_addr = 0,
|
||||
.sh_offset = off,
|
||||
.sh_size = self.strtab.buffer.items.len,
|
||||
.sh_link = 0,
|
||||
.sh_info = 0,
|
||||
.sh_addralign = 1,
|
||||
.sh_entsize = 0,
|
||||
},
|
||||
.phdr_index = undefined,
|
||||
try self.shdrs.append(gpa, .{
|
||||
.sh_name = try self.shstrtab.insert(gpa, ".strtab"),
|
||||
.sh_type = elf.SHT_STRTAB,
|
||||
.sh_flags = 0,
|
||||
.sh_addr = 0,
|
||||
.sh_offset = off,
|
||||
.sh_size = self.strtab.buffer.items.len,
|
||||
.sh_link = 0,
|
||||
.sh_info = 0,
|
||||
.sh_addralign = 1,
|
||||
.sh_entsize = 0,
|
||||
});
|
||||
self.strtab_dirty = true;
|
||||
self.shdr_table_dirty = true;
|
||||
}
|
||||
|
||||
if (self.text_section_index == null) {
|
||||
self.text_section_index = @as(u16, @intCast(self.sections.slice().len));
|
||||
self.text_section_index = @as(u16, @intCast(self.shdrs.items.len));
|
||||
const phdr = &self.phdrs.items[self.phdr_load_re_index.?];
|
||||
|
||||
try self.sections.append(gpa, .{
|
||||
.shdr = .{
|
||||
.sh_name = try self.shstrtab.insert(gpa, ".text"),
|
||||
.sh_type = elf.SHT_PROGBITS,
|
||||
.sh_flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
|
||||
.sh_addr = phdr.p_vaddr,
|
||||
.sh_offset = phdr.p_offset,
|
||||
.sh_size = phdr.p_filesz,
|
||||
.sh_link = 0,
|
||||
.sh_info = 0,
|
||||
.sh_addralign = 1,
|
||||
.sh_entsize = 0,
|
||||
},
|
||||
.phdr_index = self.phdr_load_re_index.?,
|
||||
try self.shdrs.append(gpa, .{
|
||||
.sh_name = try self.shstrtab.insert(gpa, ".text"),
|
||||
.sh_type = elf.SHT_PROGBITS,
|
||||
.sh_flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
|
||||
.sh_addr = phdr.p_vaddr,
|
||||
.sh_offset = phdr.p_offset,
|
||||
.sh_size = phdr.p_filesz,
|
||||
.sh_link = 0,
|
||||
.sh_info = 0,
|
||||
.sh_addralign = 1,
|
||||
.sh_entsize = 0,
|
||||
});
|
||||
try self.phdr_to_shdr_table.putNoClobber(gpa, self.text_section_index.?, self.phdr_load_re_index.?);
|
||||
try self.last_atom_and_free_list_table.putNoClobber(gpa, self.text_section_index.?, .{});
|
||||
self.shdr_table_dirty = true;
|
||||
}
|
||||
|
||||
if (self.got_section_index == null) {
|
||||
self.got_section_index = @as(u16, @intCast(self.sections.slice().len));
|
||||
self.got_section_index = @as(u16, @intCast(self.shdrs.items.len));
|
||||
const phdr = &self.phdrs.items[self.phdr_got_index.?];
|
||||
|
||||
try self.sections.append(gpa, .{
|
||||
.shdr = .{
|
||||
.sh_name = try self.shstrtab.insert(gpa, ".got"),
|
||||
.sh_type = elf.SHT_PROGBITS,
|
||||
.sh_flags = elf.SHF_ALLOC,
|
||||
.sh_addr = phdr.p_vaddr,
|
||||
.sh_offset = phdr.p_offset,
|
||||
.sh_size = phdr.p_filesz,
|
||||
.sh_link = 0,
|
||||
.sh_info = 0,
|
||||
.sh_addralign = @as(u16, ptr_size),
|
||||
.sh_entsize = 0,
|
||||
},
|
||||
.phdr_index = self.phdr_got_index.?,
|
||||
try self.shdrs.append(gpa, .{
|
||||
.sh_name = try self.shstrtab.insert(gpa, ".got"),
|
||||
.sh_type = elf.SHT_PROGBITS,
|
||||
.sh_flags = elf.SHF_ALLOC,
|
||||
.sh_addr = phdr.p_vaddr,
|
||||
.sh_offset = phdr.p_offset,
|
||||
.sh_size = phdr.p_filesz,
|
||||
.sh_link = 0,
|
||||
.sh_info = 0,
|
||||
.sh_addralign = @as(u16, ptr_size),
|
||||
.sh_entsize = 0,
|
||||
});
|
||||
try self.phdr_to_shdr_table.putNoClobber(gpa, self.got_section_index.?, self.phdr_got_index.?);
|
||||
self.shdr_table_dirty = true;
|
||||
}
|
||||
|
||||
if (self.rodata_section_index == null) {
|
||||
self.rodata_section_index = @as(u16, @intCast(self.sections.slice().len));
|
||||
self.rodata_section_index = @as(u16, @intCast(self.shdrs.items.len));
|
||||
const phdr = &self.phdrs.items[self.phdr_load_ro_index.?];
|
||||
|
||||
try self.sections.append(gpa, .{
|
||||
.shdr = .{
|
||||
.sh_name = try self.shstrtab.insert(gpa, ".rodata"),
|
||||
.sh_type = elf.SHT_PROGBITS,
|
||||
.sh_flags = elf.SHF_ALLOC,
|
||||
.sh_addr = phdr.p_vaddr,
|
||||
.sh_offset = phdr.p_offset,
|
||||
.sh_size = phdr.p_filesz,
|
||||
.sh_link = 0,
|
||||
.sh_info = 0,
|
||||
.sh_addralign = 1,
|
||||
.sh_entsize = 0,
|
||||
},
|
||||
.phdr_index = self.phdr_load_ro_index.?,
|
||||
try self.shdrs.append(gpa, .{
|
||||
.sh_name = try self.shstrtab.insert(gpa, ".rodata"),
|
||||
.sh_type = elf.SHT_PROGBITS,
|
||||
.sh_flags = elf.SHF_ALLOC,
|
||||
.sh_addr = phdr.p_vaddr,
|
||||
.sh_offset = phdr.p_offset,
|
||||
.sh_size = phdr.p_filesz,
|
||||
.sh_link = 0,
|
||||
.sh_info = 0,
|
||||
.sh_addralign = 1,
|
||||
.sh_entsize = 0,
|
||||
});
|
||||
try self.phdr_to_shdr_table.putNoClobber(gpa, self.rodata_section_index.?, self.phdr_load_ro_index.?);
|
||||
try self.last_atom_and_free_list_table.putNoClobber(gpa, self.rodata_section_index.?, .{});
|
||||
self.shdr_table_dirty = true;
|
||||
}
|
||||
|
||||
if (self.data_section_index == null) {
|
||||
self.data_section_index = @as(u16, @intCast(self.sections.slice().len));
|
||||
self.data_section_index = @as(u16, @intCast(self.shdrs.items.len));
|
||||
const phdr = &self.phdrs.items[self.phdr_load_rw_index.?];
|
||||
|
||||
try self.sections.append(gpa, .{
|
||||
.shdr = .{
|
||||
.sh_name = try self.shstrtab.insert(gpa, ".data"),
|
||||
.sh_type = elf.SHT_PROGBITS,
|
||||
.sh_flags = elf.SHF_WRITE | elf.SHF_ALLOC,
|
||||
.sh_addr = phdr.p_vaddr,
|
||||
.sh_offset = phdr.p_offset,
|
||||
.sh_size = phdr.p_filesz,
|
||||
.sh_link = 0,
|
||||
.sh_info = 0,
|
||||
.sh_addralign = @as(u16, ptr_size),
|
||||
.sh_entsize = 0,
|
||||
},
|
||||
.phdr_index = self.phdr_load_rw_index.?,
|
||||
try self.shdrs.append(gpa, .{
|
||||
.sh_name = try self.shstrtab.insert(gpa, ".data"),
|
||||
.sh_type = elf.SHT_PROGBITS,
|
||||
.sh_flags = elf.SHF_WRITE | elf.SHF_ALLOC,
|
||||
.sh_addr = phdr.p_vaddr,
|
||||
.sh_offset = phdr.p_offset,
|
||||
.sh_size = phdr.p_filesz,
|
||||
.sh_link = 0,
|
||||
.sh_info = 0,
|
||||
.sh_addralign = @as(u16, ptr_size),
|
||||
.sh_entsize = 0,
|
||||
});
|
||||
try self.phdr_to_shdr_table.putNoClobber(gpa, self.data_section_index.?, self.phdr_load_rw_index.?);
|
||||
try self.last_atom_and_free_list_table.putNoClobber(gpa, self.data_section_index.?, .{});
|
||||
self.shdr_table_dirty = true;
|
||||
}
|
||||
|
||||
if (self.symtab_section_index == null) {
|
||||
self.symtab_section_index = @as(u16, @intCast(self.sections.slice().len));
|
||||
self.symtab_section_index = @as(u16, @intCast(self.shdrs.items.len));
|
||||
const min_align: u16 = if (small_ptr) @alignOf(elf.Elf32_Sym) else @alignOf(elf.Elf64_Sym);
|
||||
const each_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Sym) else @sizeOf(elf.Elf64_Sym);
|
||||
const file_size = self.base.options.symbol_count_hint * each_size;
|
||||
const off = self.findFreeSpace(file_size, min_align);
|
||||
log.debug("found symtab free space 0x{x} to 0x{x}", .{ off, off + file_size });
|
||||
|
||||
try self.sections.append(gpa, .{
|
||||
.shdr = .{
|
||||
.sh_name = try self.shstrtab.insert(gpa, ".symtab"),
|
||||
.sh_type = elf.SHT_SYMTAB,
|
||||
.sh_flags = 0,
|
||||
.sh_addr = 0,
|
||||
.sh_offset = off,
|
||||
.sh_size = file_size,
|
||||
// The section header index of the associated string table.
|
||||
.sh_link = self.strtab_section_index.?,
|
||||
.sh_info = @as(u32, @intCast(self.symbols.items.len)),
|
||||
.sh_addralign = min_align,
|
||||
.sh_entsize = each_size,
|
||||
},
|
||||
.phdr_index = undefined,
|
||||
try self.shdrs.append(gpa, .{
|
||||
.sh_name = try self.shstrtab.insert(gpa, ".symtab"),
|
||||
.sh_type = elf.SHT_SYMTAB,
|
||||
.sh_flags = 0,
|
||||
.sh_addr = 0,
|
||||
.sh_offset = off,
|
||||
.sh_size = file_size,
|
||||
// The section header index of the associated string table.
|
||||
.sh_link = self.strtab_section_index.?,
|
||||
.sh_info = @as(u32, @intCast(self.symbols.items.len)),
|
||||
.sh_addralign = min_align,
|
||||
.sh_entsize = each_size,
|
||||
});
|
||||
self.shdr_table_dirty = true;
|
||||
}
|
||||
|
||||
if (self.dwarf) |*dw| {
|
||||
if (self.debug_str_section_index == null) {
|
||||
self.debug_str_section_index = @as(u16, @intCast(self.sections.slice().len));
|
||||
self.debug_str_section_index = @as(u16, @intCast(self.shdrs.items.len));
|
||||
assert(dw.strtab.buffer.items.len == 0);
|
||||
try dw.strtab.buffer.append(gpa, 0);
|
||||
try self.sections.append(gpa, .{
|
||||
.shdr = .{
|
||||
.sh_name = try self.shstrtab.insert(gpa, ".debug_str"),
|
||||
.sh_type = elf.SHT_PROGBITS,
|
||||
.sh_flags = elf.SHF_MERGE | elf.SHF_STRINGS,
|
||||
.sh_addr = 0,
|
||||
.sh_offset = 0,
|
||||
.sh_size = 0,
|
||||
.sh_link = 0,
|
||||
.sh_info = 0,
|
||||
.sh_addralign = 1,
|
||||
.sh_entsize = 1,
|
||||
},
|
||||
.phdr_index = undefined,
|
||||
try self.shdrs.append(gpa, .{
|
||||
.sh_name = try self.shstrtab.insert(gpa, ".debug_str"),
|
||||
.sh_type = elf.SHT_PROGBITS,
|
||||
.sh_flags = elf.SHF_MERGE | elf.SHF_STRINGS,
|
||||
.sh_addr = 0,
|
||||
.sh_offset = 0,
|
||||
.sh_size = 0,
|
||||
.sh_link = 0,
|
||||
.sh_info = 0,
|
||||
.sh_addralign = 1,
|
||||
.sh_entsize = 1,
|
||||
});
|
||||
self.debug_strtab_dirty = true;
|
||||
self.shdr_table_dirty = true;
|
||||
}
|
||||
|
||||
if (self.debug_info_section_index == null) {
|
||||
self.debug_info_section_index = @as(u16, @intCast(self.sections.slice().len));
|
||||
|
||||
self.debug_info_section_index = @as(u16, @intCast(self.shdrs.items.len));
|
||||
const file_size_hint = 200;
|
||||
const p_align = 1;
|
||||
const off = self.findFreeSpace(file_size_hint, p_align);
|
||||
@ -720,28 +699,24 @@ pub fn populateMissingMetadata(self: *Elf) !void {
|
||||
off,
|
||||
off + file_size_hint,
|
||||
});
|
||||
try self.sections.append(gpa, .{
|
||||
.shdr = .{
|
||||
.sh_name = try self.shstrtab.insert(gpa, ".debug_info"),
|
||||
.sh_type = elf.SHT_PROGBITS,
|
||||
.sh_flags = 0,
|
||||
.sh_addr = 0,
|
||||
.sh_offset = off,
|
||||
.sh_size = file_size_hint,
|
||||
.sh_link = 0,
|
||||
.sh_info = 0,
|
||||
.sh_addralign = p_align,
|
||||
.sh_entsize = 0,
|
||||
},
|
||||
.phdr_index = undefined,
|
||||
try self.shdrs.append(gpa, .{
|
||||
.sh_name = try self.shstrtab.insert(gpa, ".debug_info"),
|
||||
.sh_type = elf.SHT_PROGBITS,
|
||||
.sh_flags = 0,
|
||||
.sh_addr = 0,
|
||||
.sh_offset = off,
|
||||
.sh_size = file_size_hint,
|
||||
.sh_link = 0,
|
||||
.sh_info = 0,
|
||||
.sh_addralign = p_align,
|
||||
.sh_entsize = 0,
|
||||
});
|
||||
self.shdr_table_dirty = true;
|
||||
self.debug_info_header_dirty = true;
|
||||
}
|
||||
|
||||
if (self.debug_abbrev_section_index == null) {
|
||||
self.debug_abbrev_section_index = @as(u16, @intCast(self.sections.slice().len));
|
||||
|
||||
self.debug_abbrev_section_index = @as(u16, @intCast(self.shdrs.items.len));
|
||||
const file_size_hint = 128;
|
||||
const p_align = 1;
|
||||
const off = self.findFreeSpace(file_size_hint, p_align);
|
||||
@ -749,28 +724,24 @@ pub fn populateMissingMetadata(self: *Elf) !void {
|
||||
off,
|
||||
off + file_size_hint,
|
||||
});
|
||||
try self.sections.append(gpa, .{
|
||||
.shdr = .{
|
||||
.sh_name = try self.shstrtab.insert(gpa, ".debug_abbrev"),
|
||||
.sh_type = elf.SHT_PROGBITS,
|
||||
.sh_flags = 0,
|
||||
.sh_addr = 0,
|
||||
.sh_offset = off,
|
||||
.sh_size = file_size_hint,
|
||||
.sh_link = 0,
|
||||
.sh_info = 0,
|
||||
.sh_addralign = p_align,
|
||||
.sh_entsize = 0,
|
||||
},
|
||||
.phdr_index = undefined,
|
||||
try self.shdrs.append(gpa, .{
|
||||
.sh_name = try self.shstrtab.insert(gpa, ".debug_abbrev"),
|
||||
.sh_type = elf.SHT_PROGBITS,
|
||||
.sh_flags = 0,
|
||||
.sh_addr = 0,
|
||||
.sh_offset = off,
|
||||
.sh_size = file_size_hint,
|
||||
.sh_link = 0,
|
||||
.sh_info = 0,
|
||||
.sh_addralign = p_align,
|
||||
.sh_entsize = 0,
|
||||
});
|
||||
self.shdr_table_dirty = true;
|
||||
self.debug_abbrev_section_dirty = true;
|
||||
}
|
||||
|
||||
if (self.debug_aranges_section_index == null) {
|
||||
self.debug_aranges_section_index = @as(u16, @intCast(self.sections.slice().len));
|
||||
|
||||
self.debug_aranges_section_index = @as(u16, @intCast(self.shdrs.items.len));
|
||||
const file_size_hint = 160;
|
||||
const p_align = 16;
|
||||
const off = self.findFreeSpace(file_size_hint, p_align);
|
||||
@ -778,28 +749,24 @@ pub fn populateMissingMetadata(self: *Elf) !void {
|
||||
off,
|
||||
off + file_size_hint,
|
||||
});
|
||||
try self.sections.append(gpa, .{
|
||||
.shdr = .{
|
||||
.sh_name = try self.shstrtab.insert(gpa, ".debug_aranges"),
|
||||
.sh_type = elf.SHT_PROGBITS,
|
||||
.sh_flags = 0,
|
||||
.sh_addr = 0,
|
||||
.sh_offset = off,
|
||||
.sh_size = file_size_hint,
|
||||
.sh_link = 0,
|
||||
.sh_info = 0,
|
||||
.sh_addralign = p_align,
|
||||
.sh_entsize = 0,
|
||||
},
|
||||
.phdr_index = undefined,
|
||||
try self.shdrs.append(gpa, .{
|
||||
.sh_name = try self.shstrtab.insert(gpa, ".debug_aranges"),
|
||||
.sh_type = elf.SHT_PROGBITS,
|
||||
.sh_flags = 0,
|
||||
.sh_addr = 0,
|
||||
.sh_offset = off,
|
||||
.sh_size = file_size_hint,
|
||||
.sh_link = 0,
|
||||
.sh_info = 0,
|
||||
.sh_addralign = p_align,
|
||||
.sh_entsize = 0,
|
||||
});
|
||||
self.shdr_table_dirty = true;
|
||||
self.debug_aranges_section_dirty = true;
|
||||
}
|
||||
|
||||
if (self.debug_line_section_index == null) {
|
||||
self.debug_line_section_index = @as(u16, @intCast(self.sections.slice().len));
|
||||
|
||||
self.debug_line_section_index = @as(u16, @intCast(self.shdrs.items.len));
|
||||
const file_size_hint = 250;
|
||||
const p_align = 1;
|
||||
const off = self.findFreeSpace(file_size_hint, p_align);
|
||||
@ -807,20 +774,17 @@ pub fn populateMissingMetadata(self: *Elf) !void {
|
||||
off,
|
||||
off + file_size_hint,
|
||||
});
|
||||
try self.sections.append(gpa, .{
|
||||
.shdr = .{
|
||||
.sh_name = try self.shstrtab.insert(gpa, ".debug_line"),
|
||||
.sh_type = elf.SHT_PROGBITS,
|
||||
.sh_flags = 0,
|
||||
.sh_addr = 0,
|
||||
.sh_offset = off,
|
||||
.sh_size = file_size_hint,
|
||||
.sh_link = 0,
|
||||
.sh_info = 0,
|
||||
.sh_addralign = p_align,
|
||||
.sh_entsize = 0,
|
||||
},
|
||||
.phdr_index = undefined,
|
||||
try self.shdrs.append(gpa, .{
|
||||
.sh_name = try self.shstrtab.insert(gpa, ".debug_line"),
|
||||
.sh_type = elf.SHT_PROGBITS,
|
||||
.sh_flags = 0,
|
||||
.sh_addr = 0,
|
||||
.sh_offset = off,
|
||||
.sh_size = file_size_hint,
|
||||
.sh_link = 0,
|
||||
.sh_info = 0,
|
||||
.sh_addralign = p_align,
|
||||
.sh_entsize = 0,
|
||||
});
|
||||
self.shdr_table_dirty = true;
|
||||
self.debug_line_header_dirty = true;
|
||||
@ -836,7 +800,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
|
||||
.p64 => @alignOf(elf.Elf64_Shdr),
|
||||
};
|
||||
if (self.shdr_table_offset == null) {
|
||||
self.shdr_table_offset = self.findFreeSpace(self.sections.slice().len * shsize, shalign);
|
||||
self.shdr_table_offset = self.findFreeSpace(self.shdrs.items.len * shsize, shalign);
|
||||
self.shdr_table_dirty = true;
|
||||
}
|
||||
|
||||
@ -854,7 +818,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
|
||||
// offset + it's filesize.
|
||||
var max_file_offset: u64 = 0;
|
||||
|
||||
for (self.sections.items(.shdr)) |shdr| {
|
||||
for (self.shdrs.items) |shdr| {
|
||||
if (shdr.sh_offset + shdr.sh_size > max_file_offset) {
|
||||
max_file_offset = shdr.sh_offset + shdr.sh_size;
|
||||
}
|
||||
@ -885,19 +849,17 @@ pub fn populateMissingMetadata(self: *Elf) !void {
|
||||
|
||||
pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void {
|
||||
// TODO Also detect virtual address collisions.
|
||||
const shdr = &self.sections.items(.shdr)[shdr_index];
|
||||
const phdr_index = self.sections.items(.phdr_index)[shdr_index];
|
||||
const shdr = &self.shdrs.items[shdr_index];
|
||||
const phdr_index = self.phdr_to_shdr_table.get(shdr_index).?;
|
||||
const phdr = &self.phdrs.items[phdr_index];
|
||||
const last_atom_index = self.sections.items(.last_atom_index)[shdr_index];
|
||||
|
||||
if (needed_size > self.allocatedSize(shdr.sh_offset)) {
|
||||
// Must move the entire section.
|
||||
const new_offset = self.findFreeSpace(needed_size, self.page_size);
|
||||
const existing_size = if (self.atom(last_atom_index)) |last| blk: {
|
||||
const existing_size = if (self.last_atom_and_free_list_table.get(shdr_index)) |meta| blk: {
|
||||
const last = self.atom(meta.last_atom_index) orelse break :blk 0;
|
||||
break :blk (last.value + last.size) - phdr.p_vaddr;
|
||||
} else if (shdr_index == self.got_section_index.?) blk: {
|
||||
break :blk shdr.sh_size;
|
||||
} else 0;
|
||||
} else shdr.sh_size;
|
||||
shdr.sh_size = 0;
|
||||
|
||||
log.debug("new '{?s}' file offset 0x{x} to 0x{x}", .{
|
||||
@ -927,7 +889,7 @@ pub fn growNonAllocSection(
|
||||
min_alignment: u32,
|
||||
requires_file_copy: bool,
|
||||
) !void {
|
||||
const shdr = &self.sections.items(.shdr)[shdr_index];
|
||||
const shdr = &self.shdrs.items[shdr_index];
|
||||
|
||||
if (needed_size > self.allocatedSize(shdr.sh_offset)) {
|
||||
const existing_size = if (self.symtab_section_index.? == shdr_index) blk: {
|
||||
@ -940,7 +902,12 @@ pub fn growNonAllocSection(
|
||||
shdr.sh_size = 0;
|
||||
// Move all the symbols to a new file location.
|
||||
const new_offset = self.findFreeSpace(needed_size, min_alignment);
|
||||
log.debug("moving '{?s}' from 0x{x} to 0x{x}", .{ self.shstrtab.get(shdr.sh_name), shdr.sh_offset, new_offset });
|
||||
|
||||
log.debug("moving '{?s}' from 0x{x} to 0x{x}", .{
|
||||
self.shstrtab.get(shdr.sh_name),
|
||||
shdr.sh_offset,
|
||||
new_offset,
|
||||
});
|
||||
|
||||
if (requires_file_copy) {
|
||||
const amt = try self.base.file.?.copyRangeAll(
|
||||
@ -1071,7 +1038,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
|
||||
const atom_index = entry.key_ptr.*;
|
||||
const relocs = entry.value_ptr.*;
|
||||
const atom_ptr = self.atom(atom_index).?;
|
||||
const source_shdr = self.sections.items(.shdr)[atom_ptr.output_section_index];
|
||||
const source_shdr = &self.shdrs.items[atom_ptr.output_section_index];
|
||||
|
||||
log.debug("relocating '{s}'", .{atom_ptr.name(self)});
|
||||
|
||||
@ -1209,9 +1176,9 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
|
||||
|
||||
{
|
||||
const shdr_index = self.shstrtab_section_index.?;
|
||||
if (self.shstrtab_dirty or self.shstrtab.buffer.items.len != self.sections.items(.shdr)[shdr_index].sh_size) {
|
||||
if (self.shstrtab_dirty or self.shstrtab.buffer.items.len != self.shdrs.items[shdr_index].sh_size) {
|
||||
try self.growNonAllocSection(shdr_index, self.shstrtab.buffer.items.len, 1, false);
|
||||
const shstrtab_sect = self.sections.items(.shdr)[shdr_index];
|
||||
const shstrtab_sect = &self.shdrs.items[shdr_index];
|
||||
try self.base.file.?.pwriteAll(self.shstrtab.buffer.items, shstrtab_sect.sh_offset);
|
||||
self.shstrtab_dirty = false;
|
||||
}
|
||||
@ -1219,9 +1186,9 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
|
||||
|
||||
{
|
||||
const shdr_index = self.strtab_section_index.?;
|
||||
if (self.strtab_dirty or self.strtab.buffer.items.len != self.sections.items(.shdr)[shdr_index].sh_size) {
|
||||
if (self.strtab_dirty or self.strtab.buffer.items.len != self.shdrs.items[shdr_index].sh_size) {
|
||||
try self.growNonAllocSection(shdr_index, self.strtab.buffer.items.len, 1, false);
|
||||
const strtab_sect = self.sections.items(.shdr)[shdr_index];
|
||||
const strtab_sect = self.shdrs.items[shdr_index];
|
||||
try self.base.file.?.pwriteAll(self.strtab.buffer.items, strtab_sect.sh_offset);
|
||||
self.strtab_dirty = false;
|
||||
}
|
||||
@ -1229,9 +1196,9 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
|
||||
|
||||
if (self.dwarf) |dwarf| {
|
||||
const shdr_index = self.debug_str_section_index.?;
|
||||
if (self.debug_strtab_dirty or dwarf.strtab.buffer.items.len != self.sections.items(.shdr)[shdr_index].sh_size) {
|
||||
if (self.debug_strtab_dirty or dwarf.strtab.buffer.items.len != self.shdrs.items[shdr_index].sh_size) {
|
||||
try self.growNonAllocSection(shdr_index, dwarf.strtab.buffer.items.len, 1, false);
|
||||
const debug_strtab_sect = self.sections.items(.shdr)[shdr_index];
|
||||
const debug_strtab_sect = self.shdrs.items[shdr_index];
|
||||
try self.base.file.?.pwriteAll(dwarf.strtab.buffer.items, debug_strtab_sect.sh_offset);
|
||||
self.debug_strtab_dirty = false;
|
||||
}
|
||||
@ -1247,7 +1214,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
|
||||
.p64 => @alignOf(elf.Elf64_Shdr),
|
||||
};
|
||||
const allocated_size = self.allocatedSize(self.shdr_table_offset.?);
|
||||
const needed_size = self.sections.slice().len * shsize;
|
||||
const needed_size = self.shdrs.items.len * shsize;
|
||||
|
||||
if (needed_size > allocated_size) {
|
||||
self.shdr_table_offset = null; // free the space
|
||||
@ -1256,12 +1223,11 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
|
||||
|
||||
switch (self.ptr_width) {
|
||||
.p32 => {
|
||||
const slice = self.sections.slice();
|
||||
const buf = try gpa.alloc(elf.Elf32_Shdr, slice.len);
|
||||
const buf = try gpa.alloc(elf.Elf32_Shdr, self.shdrs.items.len);
|
||||
defer gpa.free(buf);
|
||||
|
||||
for (buf, 0..) |*shdr, i| {
|
||||
shdr.* = shdrTo32(slice.items(.shdr)[i]);
|
||||
shdr.* = shdrTo32(self.shdrs.items[i]);
|
||||
log.debug("writing section {?s}: {}", .{ self.shstrtab.get(shdr.sh_name), shdr.* });
|
||||
if (foreign_endian) {
|
||||
mem.byteSwapAllFields(elf.Elf32_Shdr, shdr);
|
||||
@ -1270,12 +1236,11 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
|
||||
try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?);
|
||||
},
|
||||
.p64 => {
|
||||
const slice = self.sections.slice();
|
||||
const buf = try gpa.alloc(elf.Elf64_Shdr, slice.len);
|
||||
const buf = try gpa.alloc(elf.Elf64_Shdr, self.shdrs.items.len);
|
||||
defer gpa.free(buf);
|
||||
|
||||
for (buf, 0..) |*shdr, i| {
|
||||
shdr.* = slice.items(.shdr)[i];
|
||||
shdr.* = self.shdrs.items[i];
|
||||
log.debug("writing section {?s}: {}", .{ self.shstrtab.get(shdr.sh_name), shdr.* });
|
||||
if (foreign_endian) {
|
||||
mem.byteSwapAllFields(elf.Elf64_Shdr, shdr);
|
||||
@ -2118,7 +2083,7 @@ fn writeElfHeader(self: *Elf) !void {
|
||||
mem.writeInt(u16, hdr_buf[index..][0..2], e_shentsize, endian);
|
||||
index += 2;
|
||||
|
||||
const e_shnum = @as(u16, @intCast(self.sections.slice().len));
|
||||
const e_shnum = @as(u16, @intCast(self.shdrs.items.len));
|
||||
mem.writeInt(u16, hdr_buf[index..][0..2], e_shnum, endian);
|
||||
index += 2;
|
||||
|
||||
@ -2305,9 +2270,9 @@ fn updateDeclCode(
|
||||
try self.got.writeEntry(self, got_index);
|
||||
}
|
||||
|
||||
const phdr_index = self.sections.items(.phdr_index)[shdr_index];
|
||||
const phdr_index = self.phdr_to_shdr_table.get(shdr_index).?;
|
||||
const section_offset = sym.value - self.phdrs.items[phdr_index].p_vaddr;
|
||||
const file_offset = self.sections.items(.shdr)[shdr_index].sh_offset + section_offset;
|
||||
const file_offset = self.shdrs.items[shdr_index].sh_offset + section_offset;
|
||||
|
||||
if (self.base.child_pid) |pid| {
|
||||
switch (builtin.os.tag) {
|
||||
@ -2510,7 +2475,7 @@ fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol.
|
||||
};
|
||||
|
||||
const local_sym = self.symbol(symbol_index);
|
||||
const phdr_index = self.sections.items(.phdr_index)[local_sym.output_section_index];
|
||||
const phdr_index = self.phdr_to_shdr_table.get(local_sym.output_section_index).?;
|
||||
local_sym.name_offset = name_str_index;
|
||||
const local_esym = local_sym.sourceSymbol(self);
|
||||
local_esym.st_name = name_str_index;
|
||||
@ -2537,7 +2502,7 @@ fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol.
|
||||
try self.got.writeEntry(self, got_index);
|
||||
|
||||
const section_offset = atom_ptr.value - self.phdrs.items[phdr_index].p_vaddr;
|
||||
const file_offset = self.sections.items(.shdr)[local_sym.output_section_index].sh_offset + section_offset;
|
||||
const file_offset = self.shdrs.items[local_sym.output_section_index].sh_offset + section_offset;
|
||||
try self.base.file.?.pwriteAll(code, file_offset);
|
||||
}
|
||||
|
||||
@ -2584,7 +2549,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module
|
||||
|
||||
const required_alignment = typed_value.ty.abiAlignment(mod);
|
||||
const shdr_index = self.rodata_section_index.?;
|
||||
const phdr_index = self.sections.items(.phdr_index)[shdr_index];
|
||||
const phdr_index = self.phdr_to_shdr_table.get(shdr_index).?;
|
||||
const local_sym = self.symbol(sym_index);
|
||||
local_sym.name_offset = name_str_index;
|
||||
const local_esym = local_sym.sourceSymbol(self);
|
||||
@ -2607,7 +2572,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module
|
||||
try unnamed_consts.append(gpa, atom_ptr.atom_index);
|
||||
|
||||
const section_offset = atom_ptr.value - self.phdrs.items[phdr_index].p_vaddr;
|
||||
const file_offset = self.sections.items(.shdr)[shdr_index].sh_offset + section_offset;
|
||||
const file_offset = self.shdrs.items[shdr_index].sh_offset + section_offset;
|
||||
try self.base.file.?.pwriteAll(code, file_offset);
|
||||
|
||||
return sym_index;
|
||||
@ -2775,7 +2740,7 @@ fn addLinkerDefinedSymbols(self: *Elf) !void {
|
||||
fn allocateLinkerDefinedSymbols(self: *Elf) void {
|
||||
// _DYNAMIC
|
||||
if (self.dynamic_section_index) |shndx| {
|
||||
const shdr = self.sections.items(.shdr)[shndx];
|
||||
const shdr = &self.shdrs.items[shndx];
|
||||
const symbol_ptr = self.symbol(self.dynamic_index.?);
|
||||
symbol_ptr.value = shdr.sh_addr;
|
||||
symbol_ptr.output_section_index = shndx;
|
||||
@ -2792,7 +2757,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
|
||||
if (self.sectionByName(".init_array")) |shndx| {
|
||||
const start_sym = self.symbol(self.init_array_start_index.?);
|
||||
const end_sym = self.symbol(self.init_array_end_index.?);
|
||||
const shdr = &self.sections.items(.shdr)[shndx];
|
||||
const shdr = &self.shdrs.items[shndx];
|
||||
start_sym.output_section_index = shndx;
|
||||
start_sym.value = shdr.sh_addr;
|
||||
end_sym.output_section_index = shndx;
|
||||
@ -2803,7 +2768,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
|
||||
if (self.sectionByName(".fini_array")) |shndx| {
|
||||
const start_sym = self.symbol(self.fini_array_start_index.?);
|
||||
const end_sym = self.symbol(self.fini_array_end_index.?);
|
||||
const shdr = &self.sections.items(.shdr)[shndx];
|
||||
const shdr = &self.shdrs.items[shndx];
|
||||
start_sym.output_section_index = shndx;
|
||||
start_sym.value = shdr.sh_addr;
|
||||
end_sym.output_section_index = shndx;
|
||||
@ -2814,7 +2779,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
|
||||
if (self.sectionByName(".preinit_array")) |shndx| {
|
||||
const start_sym = self.symbol(self.preinit_array_start_index.?);
|
||||
const end_sym = self.symbol(self.preinit_array_end_index.?);
|
||||
const shdr = &self.sections.items(.shdr)[shndx];
|
||||
const shdr = &self.shdrs.items[shndx];
|
||||
start_sym.output_section_index = shndx;
|
||||
start_sym.value = shdr.sh_addr;
|
||||
end_sym.output_section_index = shndx;
|
||||
@ -2823,7 +2788,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
|
||||
|
||||
// _GLOBAL_OFFSET_TABLE_
|
||||
if (self.got_plt_section_index) |shndx| {
|
||||
const shdr = &self.sections.items(.shdr)[shndx];
|
||||
const shdr = &self.shdrs.items[shndx];
|
||||
const symbol_ptr = self.symbol(self.got_index.?);
|
||||
symbol_ptr.value = shdr.sh_addr;
|
||||
symbol_ptr.output_section_index = shndx;
|
||||
@ -2831,7 +2796,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
|
||||
|
||||
// _PROCEDURE_LINKAGE_TABLE_
|
||||
if (self.plt_section_index) |shndx| {
|
||||
const shdr = &self.sections.items(.shdr)[shndx];
|
||||
const shdr = &self.shdrs.items[shndx];
|
||||
const symbol_ptr = self.symbol(self.plt_index.?);
|
||||
symbol_ptr.value = shdr.sh_addr;
|
||||
symbol_ptr.output_section_index = shndx;
|
||||
@ -2839,7 +2804,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
|
||||
|
||||
// __dso_handle
|
||||
if (self.dso_handle_index) |index| {
|
||||
const shdr = &self.sections.items(.shdr)[1];
|
||||
const shdr = &self.shdrs.items[1];
|
||||
const symbol_ptr = self.symbol(index);
|
||||
symbol_ptr.value = shdr.sh_addr;
|
||||
symbol_ptr.output_section_index = 0;
|
||||
@ -2847,7 +2812,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
|
||||
|
||||
// __GNU_EH_FRAME_HDR
|
||||
if (self.eh_frame_hdr_section_index) |shndx| {
|
||||
const shdr = &self.sections.items(.shdr)[shndx];
|
||||
const shdr = &self.shdrs.items[shndx];
|
||||
const symbol_ptr = self.symbol(self.gnu_eh_frame_hdr_index.?);
|
||||
symbol_ptr.value = shdr.sh_addr;
|
||||
symbol_ptr.output_section_index = shndx;
|
||||
@ -2856,7 +2821,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
|
||||
// __rela_iplt_start, __rela_iplt_end
|
||||
if (self.rela_dyn_section_index) |shndx| blk: {
|
||||
if (self.base.options.link_mode != .Static or self.base.options.pie) break :blk;
|
||||
const shdr = &self.sections.items(.shdr)[shndx];
|
||||
const shdr = &self.shdrs.items[shndx];
|
||||
const end_addr = shdr.sh_addr + shdr.sh_size;
|
||||
const start_addr = end_addr - self.calcNumIRelativeRelocs() * @sizeOf(elf.Elf64_Rela);
|
||||
const start_sym = self.symbol(self.rela_iplt_start_index.?);
|
||||
@ -2870,7 +2835,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
|
||||
// _end
|
||||
{
|
||||
const end_symbol = self.symbol(self.end_index.?);
|
||||
for (self.sections.items(.shdr), 0..) |shdr, shndx| {
|
||||
for (self.shdrs.items, 0..) |*shdr, shndx| {
|
||||
if (shdr.sh_flags & elf.SHF_ALLOC != 0) {
|
||||
end_symbol.value = shdr.sh_addr + shdr.sh_size;
|
||||
end_symbol.output_section_index = @intCast(shndx);
|
||||
@ -2886,7 +2851,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
|
||||
const name = start.name(self);
|
||||
const stop = self.symbol(self.start_stop_indexes.items[index + 1]);
|
||||
const shndx = self.sectionByName(name["__start_".len..]).?;
|
||||
const shdr = self.sections.items(.shdr)[shndx];
|
||||
const shdr = &self.shdrs.items[shndx];
|
||||
start.value = shdr.sh_addr;
|
||||
start.output_section_index = shndx;
|
||||
stop.value = shdr.sh_addr + shdr.sh_size;
|
||||
@ -2916,7 +2881,7 @@ fn updateSymtabSize(self: *Elf) !void {
|
||||
sizes.nlocals += linker_defined.output_symtab_size.nlocals;
|
||||
}
|
||||
|
||||
const shdr = &self.sections.items(.shdr)[self.symtab_section_index.?];
|
||||
const shdr = &self.shdrs.items[self.symtab_section_index.?];
|
||||
shdr.sh_info = sizes.nlocals + 1;
|
||||
self.markDirty(self.symtab_section_index.?, null);
|
||||
|
||||
@ -2934,7 +2899,7 @@ fn updateSymtabSize(self: *Elf) !void {
|
||||
|
||||
fn writeSymtab(self: *Elf) !void {
|
||||
const gpa = self.base.allocator;
|
||||
const shdr = &self.sections.items(.shdr)[self.symtab_section_index.?];
|
||||
const shdr = &self.shdrs.items[self.symtab_section_index.?];
|
||||
const sym_size: u64 = switch (self.ptr_width) {
|
||||
.p32 => @sizeOf(elf.Elf32_Sym),
|
||||
.p64 => @sizeOf(elf.Elf64_Sym),
|
||||
@ -3031,7 +2996,7 @@ fn writeShdr(self: *Elf, index: usize) !void {
|
||||
switch (self.ptr_width) {
|
||||
.p32 => {
|
||||
var shdr: [1]elf.Elf32_Shdr = undefined;
|
||||
shdr[0] = shdrTo32(self.sections.items(.shdr)[index]);
|
||||
shdr[0] = shdrTo32(self.shdrs.items[index]);
|
||||
if (foreign_endian) {
|
||||
mem.byteSwapAllFields(elf.Elf32_Shdr, &shdr[0]);
|
||||
}
|
||||
@ -3039,7 +3004,7 @@ fn writeShdr(self: *Elf, index: usize) !void {
|
||||
return self.base.file.?.pwriteAll(mem.sliceAsBytes(&shdr), offset);
|
||||
},
|
||||
.p64 => {
|
||||
var shdr = [1]elf.Elf64_Shdr{self.sections.items(.shdr)[index]};
|
||||
var shdr = [1]elf.Elf64_Shdr{self.shdrs.items[index]};
|
||||
if (foreign_endian) {
|
||||
mem.byteSwapAllFields(elf.Elf64_Shdr, &shdr[0]);
|
||||
}
|
||||
@ -3327,7 +3292,7 @@ pub fn defaultEntryAddress(self: Elf) u64 {
|
||||
}
|
||||
|
||||
pub fn sectionByName(self: *Elf, name: [:0]const u8) ?u16 {
|
||||
for (self.sections.items(.shdr), 0..) |shdr, i| {
|
||||
for (self.shdrs.items, 0..) |*shdr, i| {
|
||||
const this_name = self.shstrtab.getAssumeExists(shdr.sh_name);
|
||||
if (mem.eql(u8, this_name, name)) return @as(u16, @intCast(i));
|
||||
} else return null;
|
||||
@ -3481,10 +3446,7 @@ const default_entry_addr = 0x8000000;
|
||||
|
||||
pub const base_tag: link.File.Tag = .elf;
|
||||
|
||||
const Section = struct {
|
||||
shdr: elf.Elf64_Shdr,
|
||||
phdr_index: u16,
|
||||
|
||||
const LastAtomAndFreeList = struct {
|
||||
/// Index of the last allocated atom in this section.
|
||||
last_atom_index: Atom.Index = 0,
|
||||
|
||||
|
||||
@ -79,9 +79,10 @@ pub fn freeRelocations(elf_file: *Elf, atom_index: Index) void {
|
||||
}
|
||||
|
||||
pub fn allocate(self: *Atom, elf_file: *Elf) !void {
|
||||
const shdr = &elf_file.sections.items(.shdr)[self.output_section_index];
|
||||
const free_list = &elf_file.sections.items(.free_list)[self.output_section_index];
|
||||
const last_atom_index = &elf_file.sections.items(.last_atom_index)[self.output_section_index];
|
||||
const shdr = &elf_file.shdrs.items[self.output_section_index];
|
||||
const meta = elf_file.last_atom_and_free_list_table.getPtr(self.output_section_index).?;
|
||||
const free_list = &meta.free_list;
|
||||
const last_atom_index = &meta.last_atom_index;
|
||||
const new_atom_ideal_capacity = Elf.padToIdeal(self.size);
|
||||
const alignment = try std.math.powi(u64, 2, self.alignment);
|
||||
|
||||
@ -208,7 +209,9 @@ pub fn free(self: *Atom, elf_file: *Elf) void {
|
||||
|
||||
const gpa = elf_file.base.allocator;
|
||||
const shndx = self.output_section_index;
|
||||
const free_list = &elf_file.sections.items(.free_list)[shndx];
|
||||
const meta = elf_file.last_atom_and_free_list_table.getPtr(shndx).?;
|
||||
const free_list = &meta.free_list;
|
||||
const last_atom_index = &meta.last_atom_index;
|
||||
var already_have_free_list_node = false;
|
||||
{
|
||||
var i: usize = 0;
|
||||
@ -225,7 +228,6 @@ pub fn free(self: *Atom, elf_file: *Elf) void {
|
||||
}
|
||||
}
|
||||
|
||||
const last_atom_index = &elf_file.sections.items(.last_atom_index)[shndx];
|
||||
if (elf_file.atom(last_atom_index.*)) |last_atom| {
|
||||
if (last_atom.atom_index == self.atom_index) {
|
||||
if (elf_file.atom(self.prev_index)) |_| {
|
||||
|
||||
@ -29,7 +29,7 @@ pub const GotSection = struct {
|
||||
|
||||
pub fn address(entry: Entry, elf_file: *Elf) u64 {
|
||||
const ptr_bytes = @as(u64, elf_file.archPtrWidthBytes());
|
||||
const shdr = &elf_file.sections.items(.shdr)[elf_file.got_section_index.?];
|
||||
const shdr = &elf_file.shdrs.items[elf_file.got_section_index.?];
|
||||
return shdr.sh_addr + @as(u64, entry.cell_index) * ptr_bytes;
|
||||
}
|
||||
};
|
||||
@ -124,7 +124,7 @@ pub const GotSection = struct {
|
||||
}
|
||||
const endian = elf_file.base.options.target.cpu.arch.endian();
|
||||
const entry = got.entries.items[index];
|
||||
const shdr = &elf_file.sections.items(.shdr)[elf_file.got_section_index.?];
|
||||
const shdr = &elf_file.shdrs.items[elf_file.got_section_index.?];
|
||||
const off = shdr.sh_offset + @as(u64, entry_size) * entry.cell_index;
|
||||
const vaddr = shdr.sh_addr + @as(u64, entry_size) * entry.cell_index;
|
||||
const value = elf_file.symbol(entry.symbol_index).value;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user