Commit 6ec5df3898

Jakub Konka <kubkon@jakubkonka.com>
2024-08-30 22:40:27
elf: allocate .tdata and .tbss using allocateAtom mechanics
1 parent 3e100c5
Changed files (2)
src/link/Elf/ZigObject.zig
@@ -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;
 
-    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
 
-    {
-        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 };
+    try self.allocateAtom(atom_ptr, elf_file);
+    sym.value = 0;
+    esym.st_value = 0;
 
-        // 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);
-        }
-    }
+    self.navs.getPtr(nav_index).?.allocated = true;
 
-    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 });
+    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,
+        });
+    }
 }
 
 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 {
src/link/Elf.zig
@@ -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,