elf: allocate .tdata and .tbss using allocateAtom mechanics

This commit is contained in:
Jakub Konka 2024-08-30 22:40:27 +02:00
parent 3e100c5dab
commit 6ec5df3898
2 changed files with 43 additions and 54 deletions

View File

@ -3556,24 +3556,9 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void {
fn updateSectionSizes(self: *Elf) !void {
const slice = self.sections.slice();
for (slice.items(.shdr), slice.items(.atom_list), 0..) |*shdr, atom_list, shndx| {
for (slice.items(.shdr), slice.items(.atom_list)) |*shdr, atom_list| {
if (atom_list.items.len == 0) continue;
if (self.requiresThunks() and shdr.sh_flags & elf.SHF_EXECINSTR != 0) continue;
if (self.zigObjectPtr()) |zo| blk: {
const sym_index = for ([_]?Symbol.Index{
zo.text_index,
zo.rodata_index,
zo.data_relro_index,
zo.data_index,
zo.bss_index,
}) |maybe_idx| {
if (maybe_idx) |idx| break idx;
} else break :blk;
const atom_ptr = zo.symbol(sym_index).atom(self).?;
if (shndx == atom_ptr.output_section_index) {
shdr.sh_size = atom_ptr.size;
}
}
for (atom_list.items) |ref| {
const atom_ptr = self.atom(ref) orelse continue;
if (!atom_ptr.alive) continue;
@ -3908,6 +3893,7 @@ pub fn allocateAllocSections(self: *Elf) !void {
zo.rodata_index,
zo.data_relro_index,
zo.data_index,
zo.tdata_index,
zo.eh_frame_index,
}) |maybe_sym_index| {
const sect_sym_index = maybe_sym_index orelse continue;
@ -4067,6 +4053,7 @@ fn writeAtoms(self: *Elf) !void {
zo.rodata_index,
zo.data_relro_index,
zo.data_index,
zo.tdata_index,
zo.eh_frame_index,
zo.debug_info_index,
zo.debug_abbrev_index,

View File

@ -56,6 +56,8 @@ rodata_index: ?Symbol.Index = null,
data_relro_index: ?Symbol.Index = null,
data_index: ?Symbol.Index = null,
bss_index: ?Symbol.Index = null,
tdata_index: ?Symbol.Index = null,
tbss_index: ?Symbol.Index = null,
eh_frame_index: ?Symbol.Index = null,
debug_info_index: ?Symbol.Index = null,
debug_abbrev_index: ?Symbol.Index = null,
@ -233,10 +235,6 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void {
meta.exports.deinit(allocator);
}
self.uavs.deinit(allocator);
for (self.tls_variables.values()) |*tlv| {
tlv.deinit(allocator);
}
self.tls_variables.deinit(allocator);
if (self.dwarf) |*dwarf| {
@ -898,14 +896,6 @@ pub fn writeSymtab(self: ZigObject, elf_file: *Elf) void {
pub fn codeAlloc(self: *ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8 {
const gpa = elf_file.base.comp.gpa;
const atom_ptr = self.atom(atom_index).?;
const shdr = &elf_file.sections.items(.shdr)[atom_ptr.output_section_index];
if (shdr.sh_flags & elf.SHF_TLS != 0) {
const tlv = self.tls_variables.get(atom_index).?;
const code = try gpa.dupe(u8, tlv.code);
return code;
}
const file_offset = atom_ptr.offset(elf_file);
const size = std.math.cast(usize, atom_ptr.size) orelse return error.Overflow;
const code = try gpa.alloc(u8, size);
@ -1161,18 +1151,29 @@ fn getNavShdrIndex(
const is_bss = !has_relocs and for (code) |byte| {
if (byte != 0) break false;
} else true;
if (is_bss) return elf_file.sectionByName(".tbss") orelse try elf_file.addSection(.{
.type = elf.SHT_NOBITS,
.flags = elf.SHF_ALLOC | elf.SHF_WRITE | elf.SHF_TLS,
.name = try elf_file.insertShString(".tbss"),
.offset = std.math.maxInt(u64),
});
return elf_file.sectionByName(".tdata") orelse try elf_file.addSection(.{
if (is_bss) {
if (self.tbss_index) |symbol_index|
return self.symbol(symbol_index).atom(elf_file).?.output_section_index;
const osec = try elf_file.addSection(.{
.name = try elf_file.insertShString(".tbss"),
.flags = elf.SHF_ALLOC | elf.SHF_WRITE | elf.SHF_TLS,
.type = elf.SHT_NOBITS,
.addralign = 1,
});
self.tbss_index = try self.addSectionSymbol(gpa, ".tbss", .@"1", osec);
return osec;
}
if (self.tdata_index) |symbol_index|
return self.symbol(symbol_index).atom(elf_file).?.output_section_index;
const osec = try elf_file.addSection(.{
.type = elf.SHT_PROGBITS,
.flags = elf.SHF_ALLOC | elf.SHF_WRITE | elf.SHF_TLS,
.name = try elf_file.insertShString(".tdata"),
.addralign = 1,
.offset = std.math.maxInt(u64),
});
self.tdata_index = try self.addSectionSymbol(gpa, ".tdata", .@"1", osec);
return osec;
}
if (is_const) {
if (self.data_relro_index) |symbol_index|
@ -1367,15 +1368,11 @@ fn updateTlv(
const atom_ptr = sym.atom(elf_file).?;
const name_offset = try self.strtab.insert(gpa, nav.fqn.toSlice(ip));
sym.value = 0;
sym.name_offset = name_offset;
atom_ptr.output_section_index = shndx;
atom_ptr.alive = true;
atom_ptr.name_offset = name_offset;
atom_ptr.output_section_index = shndx;
sym.name_offset = name_offset;
esym.st_value = 0;
esym.st_name = name_offset;
esym.st_info = elf.STT_TLS;
esym.st_size = code.len;
@ -1383,21 +1380,25 @@ fn updateTlv(
atom_ptr.alignment = required_alignment;
atom_ptr.size = code.len;
const gop = try self.tls_variables.getOrPut(gpa, atom_ptr.atom_index);
assert(!gop.found_existing); // TODO incremental updates
try self.allocateAtom(atom_ptr, elf_file);
sym.value = 0;
esym.st_value = 0;
self.navs.getPtr(nav_index).?.allocated = true;
{
const gop = try self.tls_variables.getOrPut(gpa, atom_ptr.atom_index);
assert(!gop.found_existing); // TODO incremental updates
gop.value_ptr.* = .{ .symbol_index = sym_index };
// We only store the data for the TLV if it's non-zerofill.
if (elf_file.sections.items(.shdr)[shndx].sh_type != elf.SHT_NOBITS) {
gop.value_ptr.code = try gpa.dupe(u8, code);
}
const shdr = elf_file.sections.items(.shdr)[shndx];
if (shdr.sh_type != elf.SHT_NOBITS) {
const file_offset = atom_ptr.offset(elf_file);
try elf_file.base.file.?.pwriteAll(code, file_offset);
log.debug("writing TLV {s} from 0x{x} to 0x{x}", .{
atom_ptr.name(elf_file),
file_offset,
file_offset + code.len,
});
}
const atom_list = &elf_file.sections.items(.atom_list)[atom_ptr.output_section_index];
try atom_list.append(gpa, .{ .index = atom_ptr.atom_index, .file = self.index });
}
pub fn updateFunc(
@ -1994,8 +1995,9 @@ fn allocateAtom(self: *ZigObject, atom_ptr: *Atom, elf_file: *Elf) !void {
const sect_atom_ptr = for ([_]?Symbol.Index{
self.text_index,
self.rodata_index,
self.data_index,
self.data_relro_index,
self.data_index,
self.tdata_index,
}) |maybe_sym_index| {
const sect_sym_index = maybe_sym_index orelse continue;
const sect_atom_ptr = self.symbol(sect_sym_index).atom(elf_file).?;
@ -2305,7 +2307,7 @@ const AtomList = std.ArrayListUnmanaged(Atom.Index);
const NavTable = std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, AvMetadata);
const UavTable = std.AutoArrayHashMapUnmanaged(InternPool.Index, AvMetadata);
const LazySymbolTable = std.AutoArrayHashMapUnmanaged(InternPool.Index, LazySymbolMetadata);
const TlsTable = std.AutoArrayHashMapUnmanaged(Atom.Index, TlsVariable);
const TlsTable = std.AutoArrayHashMapUnmanaged(Atom.Index, void);
const x86_64 = struct {
fn writeTrampolineCode(source_addr: i64, target_addr: i64, buf: *[max_trampoline_len]u8) ![]u8 {