elf: update .rela section sizes; skip .got.zig when emitting object

This commit is contained in:
Jakub Konka 2023-11-01 22:51:18 +01:00
parent 21853bc310
commit ec2671d16b
2 changed files with 72 additions and 25 deletions

View File

@ -112,7 +112,6 @@ zig_data_section_index: ?u16 = null,
zig_data_rela_section_index: ?u16 = null,
zig_bss_section_index: ?u16 = null,
zig_got_section_index: ?u16 = null,
zig_got_rela_section_index: ?u16 = null,
debug_info_section_index: ?u16 = null,
debug_abbrev_section_index: ?u16 = null,
@ -612,8 +611,7 @@ pub fn initMetadata(self: *Elf) !void {
try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_text_section_index.?, .{});
}
if (self.zig_got_section_index == null) {
// TODO we don't actually need this section in a relocatable object file
if (self.zig_got_section_index == null and !self.isObject()) {
self.zig_got_section_index = try self.addSection(.{
.name = ".got.zig",
.type = elf.SHT_PROGBITS,
@ -622,18 +620,11 @@ pub fn initMetadata(self: *Elf) !void {
.offset = std.math.maxInt(u64),
});
const shdr = &self.shdrs.items[self.zig_got_section_index.?];
fillSection(
self,
shdr,
@as(u64, ptr_size) * self.base.options.symbol_count_hint,
self.phdr_zig_got_index,
);
if (self.isObject()) {
self.zig_got_rela_section_index = try self.addRelaShdr(
".rela.got.zig",
self.zig_got_section_index.?,
);
}
const phndx = self.phdr_zig_got_index.?;
const phdr = self.phdrs.items[phndx];
shdr.sh_addr = phdr.p_vaddr;
shdr.sh_offset = phdr.p_offset;
shdr.sh_size = phdr.p_memsz;
}
if (self.zig_data_rel_ro_section_index == null) {
@ -3701,7 +3692,6 @@ fn sortShdrs(self: *Elf) !void {
&self.zig_text_section_index,
&self.zig_text_rela_section_index,
&self.zig_got_section_index,
&self.zig_got_rela_section_index,
&self.zig_data_rel_ro_section_index,
&self.zig_data_rel_ro_rela_section_index,
&self.zig_data_section_index,
@ -3766,7 +3756,6 @@ fn sortShdrs(self: *Elf) !void {
for (&[_]?u16{
self.zig_text_rela_section_index,
self.zig_got_rela_section_index,
self.zig_data_rel_ro_rela_section_index,
self.zig_data_rela_section_index,
}) |maybe_index| {
@ -3776,6 +3765,20 @@ fn sortShdrs(self: *Elf) !void {
shdr.sh_info = backlinks[shdr.sh_info];
}
{
var last_atom_and_free_list_table = try self.last_atom_and_free_list_table.clone(gpa);
defer last_atom_and_free_list_table.deinit(gpa);
self.last_atom_and_free_list_table.clearRetainingCapacity();
var it = last_atom_and_free_list_table.iterator();
while (it.next()) |entry| {
const shndx = entry.key_ptr.*;
const meta = entry.value_ptr.*;
self.last_atom_and_free_list_table.putAssumeCapacityNoClobber(backlinks[shndx], meta);
}
}
{
var phdr_to_shdr_table = try self.phdr_to_shdr_table.clone(gpa);
defer phdr_to_shdr_table.deinit(gpa);
@ -3832,6 +3835,10 @@ fn updateSectionSizes(self: *Elf) !void {
}
}
if (self.zigObjectPtr()) |zig_object| {
zig_object.updateRelaSectionSizes(self);
}
if (self.eh_frame_section_index) |index| {
self.shdrs.items[index].sh_size = try eh_frame.calcEhFrameSize(self);
}

View File

@ -398,6 +398,40 @@ pub fn markLive(self: *ZigObject, elf_file: *Elf) void {
}
}
pub fn updateRelaSectionSizes(self: ZigObject, elf_file: *Elf) void {
_ = self;
for (&[_]?u16{
elf_file.zig_text_rela_section_index,
elf_file.zig_data_rel_ro_rela_section_index,
elf_file.zig_data_rela_section_index,
}) |maybe_index| {
const index = maybe_index orelse continue;
const shdr = &elf_file.shdrs.items[index];
const meta = elf_file.last_atom_and_free_list_table.get(@intCast(shdr.sh_info)).?;
const last_atom_index = meta.last_atom_index;
var atom = elf_file.atom(last_atom_index) orelse continue;
while (true) {
const relocs = atom.relocs(elf_file);
shdr.sh_size += relocs.len * shdr.sh_entsize;
if (elf_file.atom(atom.prev_index)) |prev| {
atom = prev;
} else break;
}
}
for (&[_]?u16{
elf_file.zig_text_rela_section_index,
elf_file.zig_data_rel_ro_rela_section_index,
elf_file.zig_data_rela_section_index,
}) |maybe_index| {
const index = maybe_index orelse continue;
const shdr = &elf_file.shdrs.items[index];
if (shdr.sh_size == 0) shdr.sh_offset = 0;
}
}
pub fn symbol(self: *ZigObject, index: Symbol.Index) Symbol.Index {
const is_global = index & global_symbol_bit != 0;
const actual_index = index & symbol_mask;
@ -689,10 +723,12 @@ fn updateDeclCode(
sym.value = atom_ptr.value;
esym.st_value = atom_ptr.value;
log.debug(" (writing new offset table entry)", .{});
assert(sym.flags.has_zig_got);
const extra = sym.extra(elf_file).?;
try elf_file.zig_got.writeOne(elf_file, extra.zig_got);
if (!elf_file.isObject()) {
log.debug(" (writing new offset table entry)", .{});
assert(sym.flags.has_zig_got);
const extra = sym.extra(elf_file).?;
try elf_file.zig_got.writeOne(elf_file, extra.zig_got);
}
}
} else if (code.len < old_size) {
atom_ptr.shrink(elf_file);
@ -704,8 +740,10 @@ fn updateDeclCode(
sym.value = atom_ptr.value;
esym.st_value = atom_ptr.value;
const gop = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
try elf_file.zig_got.writeOne(elf_file, gop.index);
if (!elf_file.isObject()) {
const gop = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
try elf_file.zig_got.writeOne(elf_file, gop.index);
}
}
if (elf_file.base.child_pid) |pid| {
@ -957,8 +995,10 @@ fn updateLazySymbol(
local_sym.value = atom_ptr.value;
local_esym.st_value = atom_ptr.value;
const gop = try local_sym.getOrCreateZigGotEntry(symbol_index, elf_file);
try elf_file.zig_got.writeOne(elf_file, gop.index);
if (!elf_file.isObject()) {
const gop = try local_sym.getOrCreateZigGotEntry(symbol_index, elf_file);
try elf_file.zig_got.writeOne(elf_file, gop.index);
}
const shdr = elf_file.shdrs.items[output_section_index];
const file_offset = shdr.sh_offset + atom_ptr.value - shdr.sh_addr;