Commit ec2671d16b

Jakub Konka <kubkon@jakubkonka.com>
2023-11-01 22:51:18
elf: update .rela section sizes; skip .got.zig when emitting object
1 parent 21853bc
Changed files (2)
src/link/Elf/ZigObject.zig
@@ -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;
src/link/Elf.zig
@@ -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);
     }