Commit 2d0f4fc9c0

Jakub Konka <kubkon@jakubkonka.com>
2024-08-29 21:14:46
elf: allocate .text in ZigObject similarly to .eh_frame
1 parent 8485355
Changed files (2)
src/link/Elf/ZigObject.zig
@@ -51,6 +51,12 @@ debug_loclists_section_dirty: bool = false,
 debug_rnglists_section_dirty: bool = false,
 eh_frame_section_dirty: bool = false,
 
+text_index: ?Symbol.Index = null,
+data_relro_index: ?Symbol.Index = null,
+rodata_index: ?Symbol.Index = null,
+data_index: ?Symbol.Index = null,
+bss_index: ?Symbol.Index = null,
+eh_frame_index: ?Symbol.Index = null,
 debug_info_index: ?Symbol.Index = null,
 debug_abbrev_index: ?Symbol.Index = null,
 debug_aranges_index: ?Symbol.Index = null,
@@ -59,11 +65,6 @@ debug_line_index: ?Symbol.Index = null,
 debug_line_str_index: ?Symbol.Index = null,
 debug_loclists_index: ?Symbol.Index = null,
 debug_rnglists_index: ?Symbol.Index = null,
-eh_frame_index: ?Symbol.Index = null,
-bss_index: ?Symbol.Index = null,
-data_index: ?Symbol.Index = null,
-data_relro_index: ?Symbol.Index = null,
-rodata_index: ?Symbol.Index = null,
 
 pub const global_symbol_bit: u32 = 0x80000000;
 pub const symbol_mask: u32 = 0x7fffffff;
@@ -75,6 +76,7 @@ const InitOptions = struct {
 };
 
 pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
+    _ = options;
     const comp = elf_file.base.comp;
     const gpa = comp.gpa;
     const ptr_size = elf_file.ptrWidthBytes();
@@ -92,60 +94,6 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
         esym.st_shndx = elf.SHN_ABS;
     }
 
-    const fillSection = struct {
-        fn fillSection(ef: *Elf, shdr: *elf.Elf64_Shdr, size: u64, phndx: ?u16) !void {
-            if (ef.base.isRelocatable()) {
-                const off = try ef.findFreeSpace(size, shdr.sh_addralign);
-                shdr.sh_offset = off;
-                shdr.sh_size = size;
-            } else {
-                const phdr = ef.phdrs.items[phndx.?];
-                shdr.sh_addr = phdr.p_vaddr;
-                shdr.sh_offset = phdr.p_offset;
-                shdr.sh_size = phdr.p_memsz;
-            }
-        }
-    }.fillSection;
-
-    comptime assert(Elf.number_of_zig_segments == 2);
-
-    if (!elf_file.base.isRelocatable()) {
-        if (elf_file.phdr_zig_load_re_index == null) {
-            const filesz = options.program_code_size_hint;
-            const off = try elf_file.findFreeSpace(filesz, elf_file.page_size);
-            elf_file.phdr_zig_load_re_index = try elf_file.addPhdr(.{
-                .type = elf.PT_LOAD,
-                .offset = off,
-                .filesz = filesz,
-                .addr = if (ptr_size >= 4) 0x4000000 else 0x4000,
-                .memsz = filesz,
-                .@"align" = elf_file.page_size,
-                .flags = elf.PF_X | elf.PF_R | elf.PF_W,
-            });
-        }
-    }
-
-    if (elf_file.zig_text_section_index == null) {
-        elf_file.zig_text_section_index = try elf_file.addSection(.{
-            .name = try elf_file.insertShString(".text.zig"),
-            .type = elf.SHT_PROGBITS,
-            .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
-            .addralign = 1,
-            .offset = std.math.maxInt(u64),
-        });
-        const shdr = &elf_file.sections.items(.shdr)[elf_file.zig_text_section_index.?];
-        const phndx = &elf_file.sections.items(.phndx)[elf_file.zig_text_section_index.?];
-        try fillSection(elf_file, shdr, options.program_code_size_hint, elf_file.phdr_zig_load_re_index);
-        if (elf_file.base.isRelocatable()) {
-            _ = try elf_file.addRelaShdr(
-                try elf_file.insertShString(".rela.text.zig"),
-                elf_file.zig_text_section_index.?,
-            );
-        } else {
-            phndx.* = elf_file.phdr_zig_load_re_index.?;
-        }
-    }
-
     switch (comp.config.debug_format) {
         .strip => {},
         .dwarf => |v| {
@@ -1196,7 +1144,19 @@ fn getNavShdrIndex(
     const ip = &zcu.intern_pool;
     const any_non_single_threaded = elf_file.base.comp.config.any_non_single_threaded;
     const nav_val = zcu.navValue(nav_index);
-    if (ip.isFunctionType(nav_val.typeOf(zcu).toIntern())) return elf_file.zig_text_section_index.?;
+    if (ip.isFunctionType(nav_val.typeOf(zcu).toIntern())) {
+        if (self.text_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_EXECINSTR,
+            .name = try elf_file.insertShString(".text"),
+            .addralign = 1,
+            .offset = std.math.maxInt(u64),
+        });
+        self.text_index = try self.addSectionSymbol(gpa, ".text", .@"1", osec);
+        return osec;
+    }
     const is_const, const is_threadlocal, const nav_init = switch (ip.indexToKey(nav_val.toIntern())) {
         .variable => |variable| .{ false, variable.is_threadlocal, variable.init },
         .@"extern" => |@"extern"| .{ @"extern".is_const, @"extern".is_threadlocal, .none },
@@ -1538,6 +1498,19 @@ pub fn updateFunc(
                 self.symbol(sym_index).name(elf_file),
             });
             defer gpa.free(name);
+            const osec = if (self.text_index) |sect_sym_index|
+                self.symbol(sect_sym_index).atom(elf_file).?.output_section_index
+            else osec: {
+                const osec = try elf_file.addSection(.{
+                    .name = try elf_file.insertShString(".text"),
+                    .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
+                    .type = elf.SHT_PROGBITS,
+                    .addralign = 1,
+                    .offset = std.math.maxInt(u64),
+                });
+                self.text_index = try self.addSectionSymbol(gpa, ".text", .@"1", osec);
+                break :osec osec;
+            };
             const name_off = try self.addString(gpa, name);
             const tr_size = trampolineSize(elf_file.getTarget().cpu.arch);
             const tr_sym_index = try self.newSymbolWithAtom(gpa, name_off);
@@ -1549,7 +1522,7 @@ pub fn updateFunc(
             tr_atom_ptr.value = old_rva;
             tr_atom_ptr.alive = true;
             tr_atom_ptr.alignment = old_alignment;
-            tr_atom_ptr.output_section_index = elf_file.zig_text_section_index.?;
+            tr_atom_ptr.output_section_index = osec;
             tr_atom_ptr.size = tr_size;
             const target_sym = self.symbol(sym_index);
             target_sym.addExtra(.{ .trampoline = tr_sym_index }, elf_file);
@@ -1703,7 +1676,19 @@ fn updateLazySymbol(
     };
 
     const output_section_index = switch (sym.kind) {
-        .code => elf_file.zig_text_section_index.?,
+        .code => if (self.text_index) |sym_index|
+            self.symbol(sym_index).atom(elf_file).?.output_section_index
+        else osec: {
+            const osec = try elf_file.addSection(.{
+                .name = try elf_file.insertShString(".text"),
+                .type = elf.SHT_PROGBITS,
+                .addralign = 1,
+                .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
+                .offset = std.math.maxInt(u64),
+            });
+            self.text_index = try self.addSectionSymbol(gpa, ".text", .@"1", osec);
+            break :osec osec;
+        },
         .const_data => if (self.rodata_index) |sym_index|
             self.symbol(sym_index).atom(elf_file).?.output_section_index
         else osec: {
src/link/Elf.zig
@@ -54,10 +54,6 @@ shdr_table_offset: ?u64 = null,
 /// Same order as in the file.
 phdrs: std.ArrayListUnmanaged(elf.Elf64_Phdr) = .{},
 
-/// Tracked loadable segments during incremental linking.
-/// The index into the program headers of a PT_LOAD program header with Read and Execute flags
-phdr_zig_load_re_index: ?u16 = null,
-
 /// Special program headers
 /// PT_PHDR
 phdr_table_index: ?u16 = null,
@@ -118,10 +114,6 @@ rela_plt: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{},
 /// Applies only to a relocatable.
 comdat_group_sections: std.ArrayListUnmanaged(ComdatGroupSection) = .{},
 
-/// Tracked section headers with incremental updates to Zig object.
-/// .rela.* sections are only used when emitting a relocatable object file.
-zig_text_section_index: ?u32 = null,
-
 debug_info_section_index: ?u32 = null,
 debug_abbrev_section_index: ?u32 = null,
 debug_str_section_index: ?u32 = null,
@@ -3356,7 +3348,6 @@ fn sortPhdrs(self: *Elf) error{OutOfMemory}!void {
     }
 
     for (&[_]*?u16{
-        &self.phdr_zig_load_re_index,
         &self.phdr_table_index,
         &self.phdr_table_load_index,
         &self.phdr_interp_index,
@@ -3482,7 +3473,6 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void {
         &self.copy_rel_section_index,
         &self.versym_section_index,
         &self.verneed_section_index,
-        &self.zig_text_section_index,
         &self.debug_info_section_index,
         &self.debug_abbrev_section_index,
         &self.debug_str_section_index,
@@ -3734,10 +3724,9 @@ fn getMaxNumberOfPhdrs() u64 {
 /// We permit a maximum of 3**2 number of segments.
 fn calcNumberOfSegments(self: *Elf) usize {
     var covers: [9]bool = [_]bool{false} ** 9;
-    for (self.sections.items(.shdr), 0..) |shdr, shndx| {
+    for (self.sections.items(.shdr)) |shdr| {
         if (shdr.sh_type == elf.SHT_NULL) continue;
         if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;
-        if (self.isZigSection(@intCast(shndx))) continue;
         const flags = shdrToPhdrFlags(shdr.sh_flags);
         covers[flags - 1] = true;
     }
@@ -3835,7 +3824,6 @@ pub fn allocateAllocSections(self: *Elf) !void {
     for (slice.items(.shdr), 0..) |shdr, shndx| {
         if (shdr.sh_type == elf.SHT_NULL) continue;
         if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;
-        if (self.isZigSection(@intCast(shndx))) continue;
         const flags = shdrToPhdrFlags(shdr.sh_flags);
         try covers[flags - 1].append(@intCast(shndx));
     }
@@ -4813,15 +4801,6 @@ pub fn isEffectivelyDynLib(self: Elf) bool {
     };
 }
 
-pub fn isZigSection(self: Elf, shndx: u32) bool {
-    inline for (&[_]?u32{
-        self.zig_text_section_index,
-    }) |index| {
-        if (index == shndx) return true;
-    }
-    return false;
-}
-
 pub fn isDebugSection(self: Elf, shndx: u32) bool {
     inline for (&[_]?u32{
         self.debug_info_section_index,