authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-11-01 18:01:29+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-11-04 09:09:26+01:00
log0ee2ab413fd0370a8ced8d433c71d1d951dab41c
treeae75278dcaa46cc1413e300e3f373c60a36fbf08
parent74f12d0691292e9730327971bbf6c27a78095ae8

elf: emit valid section headers table when building an object file


2 files changed, 37 insertions(+), 29 deletions(-)

src/link/Elf.zig+27-15
...@@ -768,15 +768,15 @@ pub fn initMetadata(self: *Elf) !void {...@@ -768,15 +768,15 @@ pub fn initMetadata(self: *Elf) !void {
768768
769pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void {769pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void {
770 const shdr = &self.shdrs.items[shdr_index];770 const shdr = &self.shdrs.items[shdr_index];
771 const phdr_index = self.phdr_to_shdr_table.get(shdr_index).?;771 const maybe_phdr = if (self.phdr_to_shdr_table.get(shdr_index)) |phndx| &self.phdrs.items[phndx] else null;
772 const phdr = &self.phdrs.items[phdr_index];
773 const is_zerofill = shdr.sh_type == elf.SHT_NOBITS;772 const is_zerofill = shdr.sh_type == elf.SHT_NOBITS;
774773
775 if (needed_size > self.allocatedSize(shdr.sh_offset) and !is_zerofill) {774 if (needed_size > self.allocatedSize(shdr.sh_offset) and !is_zerofill) {
776 const existing_size = shdr.sh_size;775 const existing_size = shdr.sh_size;
777 shdr.sh_size = 0;776 shdr.sh_size = 0;
778 // Must move the entire section.777 // Must move the entire section.
779 const new_offset = self.findFreeSpace(needed_size, self.page_size);778 const alignment = if (maybe_phdr) |phdr| phdr.p_align else shdr.sh_addralign;
779 const new_offset = self.findFreeSpace(needed_size, alignment);
780780
781 log.debug("new '{s}' file offset 0x{x} to 0x{x}", .{781 log.debug("new '{s}' file offset 0x{x} to 0x{x}", .{
782 self.getShString(shdr.sh_name),782 self.getShString(shdr.sh_name),
...@@ -789,25 +789,27 @@ pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void {...@@ -789,25 +789,27 @@ pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void {
789 if (amt != existing_size) return error.InputOutput;789 if (amt != existing_size) return error.InputOutput;
790790
791 shdr.sh_offset = new_offset;791 shdr.sh_offset = new_offset;
792 phdr.p_offset = new_offset;792 if (maybe_phdr) |phdr| phdr.p_offset = new_offset;
793 }793 }
794794
795 shdr.sh_size = needed_size;795 shdr.sh_size = needed_size;
796 if (!is_zerofill) {796 if (!is_zerofill) {
797 phdr.p_filesz = needed_size;797 if (maybe_phdr) |phdr| phdr.p_filesz = needed_size;
798 }798 }
799799
800 const mem_capacity = self.allocatedVirtualSize(phdr.p_vaddr);800 if (maybe_phdr) |phdr| {
801 if (needed_size > mem_capacity) {801 const mem_capacity = self.allocatedVirtualSize(phdr.p_vaddr);
802 var err = try self.addErrorWithNotes(2);802 if (needed_size > mem_capacity) {
803 try err.addMsg(self, "fatal linker error: cannot expand load segment phdr({d}) in virtual memory", .{803 var err = try self.addErrorWithNotes(2);
804 phdr_index,804 try err.addMsg(self, "fatal linker error: cannot expand load segment phdr({d}) in virtual memory", .{
805 });805 self.phdr_to_shdr_table.get(shdr_index).?,
806 try err.addNote(self, "TODO: emit relocations to memory locations in self-hosted backends", .{});806 });
807 try err.addNote(self, "as a workaround, try increasing pre-allocated virtual memory of each segment", .{});807 try err.addNote(self, "TODO: emit relocations to memory locations in self-hosted backends", .{});
808 }808 try err.addNote(self, "as a workaround, try increasing pre-allocated virtual memory of each segment", .{});
809 }
809810
810 phdr.p_memsz = needed_size;811 phdr.p_memsz = needed_size;
812 }
811813
812 self.markDirty(shdr_index);814 self.markDirty(shdr_index);
813}815}
...@@ -1499,7 +1501,17 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1499,7 +1501,17 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1499pub fn flushObject(self: *Elf, comp: *Compilation) link.File.FlushError!void {1501pub fn flushObject(self: *Elf, comp: *Compilation) link.File.FlushError!void {
1500 _ = comp;1502 _ = comp;
1501 try self.initSections();1503 try self.initSections();
1504 try self.sortShdrs();
1505 try self.updateSectionSizes();
1506
1507 try self.allocateNonAllocSections();
1508
1509 if (build_options.enable_logging) {
1510 state_log.debug("{}", .{self.dumpState()});
1511 }
1512
1502 try self.writeShdrTable();1513 try self.writeShdrTable();
1514 try self.writeSyntheticSections();
1503 try self.writeHeader();1515 try self.writeHeader();
1504}1516}
15051517
src/link/Elf/ZigObject.zig+10-14
...@@ -180,16 +180,16 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf) !void {...@@ -180,16 +180,16 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf) !void {
180 }180 }
181181
182 if (self.debug_info_header_dirty) {182 if (self.debug_info_header_dirty) {
183 const text_phdr = &elf_file.phdrs.items[elf_file.phdr_zig_load_re_index.?];183 const text_shdr = elf_file.shdrs.items[elf_file.zig_text_section_index.?];
184 const low_pc = text_phdr.p_vaddr;184 const low_pc = text_shdr.sh_addr;
185 const high_pc = text_phdr.p_vaddr + text_phdr.p_memsz;185 const high_pc = text_shdr.sh_addr + text_shdr.sh_size;
186 try dw.writeDbgInfoHeader(elf_file.base.options.module.?, low_pc, high_pc);186 try dw.writeDbgInfoHeader(elf_file.base.options.module.?, low_pc, high_pc);
187 self.debug_info_header_dirty = false;187 self.debug_info_header_dirty = false;
188 }188 }
189189
190 if (self.debug_aranges_section_dirty) {190 if (self.debug_aranges_section_dirty) {
191 const text_phdr = &elf_file.phdrs.items[elf_file.phdr_zig_load_re_index.?];191 const text_shdr = elf_file.shdrs.items[elf_file.zig_text_section_index.?];
192 try dw.writeDbgAranges(text_phdr.p_vaddr, text_phdr.p_memsz);192 try dw.writeDbgAranges(text_shdr.sh_addr, text_shdr.sh_size);
193 self.debug_aranges_section_dirty = false;193 self.debug_aranges_section_dirty = false;
194 }194 }
195195
...@@ -731,9 +731,7 @@ fn updateDeclCode(...@@ -731,9 +731,7 @@ fn updateDeclCode(
731731
732 const shdr = elf_file.shdrs.items[shdr_index];732 const shdr = elf_file.shdrs.items[shdr_index];
733 if (shdr.sh_type != elf.SHT_NOBITS) {733 if (shdr.sh_type != elf.SHT_NOBITS) {
734 const phdr_index = elf_file.phdr_to_shdr_table.get(shdr_index).?;734 const file_offset = shdr.sh_offset + sym.value - shdr.sh_addr;
735 const section_offset = sym.value - elf_file.phdrs.items[phdr_index].p_vaddr;
736 const file_offset = shdr.sh_offset + section_offset;
737 try elf_file.base.file.?.pwriteAll(code, file_offset);735 try elf_file.base.file.?.pwriteAll(code, file_offset);
738 }736 }
739}737}
...@@ -940,7 +938,6 @@ fn updateLazySymbol(...@@ -940,7 +938,6 @@ fn updateLazySymbol(
940 .const_data => elf_file.zig_data_rel_ro_section_index.?,938 .const_data => elf_file.zig_data_rel_ro_section_index.?,
941 };939 };
942 const local_sym = elf_file.symbol(symbol_index);940 const local_sym = elf_file.symbol(symbol_index);
943 const phdr_index = elf_file.phdr_to_shdr_table.get(output_section_index).?;
944 local_sym.name_offset = name_str_index;941 local_sym.name_offset = name_str_index;
945 local_sym.output_section_index = output_section_index;942 local_sym.output_section_index = output_section_index;
946 const local_esym = &self.local_esyms.items(.elf_sym)[local_sym.esym_index];943 const local_esym = &self.local_esyms.items(.elf_sym)[local_sym.esym_index];
...@@ -963,8 +960,8 @@ fn updateLazySymbol(...@@ -963,8 +960,8 @@ fn updateLazySymbol(
963 const gop = try local_sym.getOrCreateZigGotEntry(symbol_index, elf_file);960 const gop = try local_sym.getOrCreateZigGotEntry(symbol_index, elf_file);
964 try elf_file.zig_got.writeOne(elf_file, gop.index);961 try elf_file.zig_got.writeOne(elf_file, gop.index);
965962
966 const section_offset = atom_ptr.value - elf_file.phdrs.items[phdr_index].p_vaddr;963 const shdr = elf_file.shdrs.items[output_section_index];
967 const file_offset = elf_file.shdrs.items[output_section_index].sh_offset + section_offset;964 const file_offset = shdr.sh_offset + atom_ptr.value - shdr.sh_addr;
968 try elf_file.base.file.?.pwriteAll(code, file_offset);965 try elf_file.base.file.?.pwriteAll(code, file_offset);
969}966}
970967
...@@ -1038,7 +1035,6 @@ fn lowerConst(...@@ -1038,7 +1035,6 @@ fn lowerConst(
1038 .fail => |em| return .{ .fail = em },1035 .fail => |em| return .{ .fail = em },
1039 };1036 };
10401037
1041 const phdr_index = elf_file.phdr_to_shdr_table.get(output_section_index).?;
1042 const local_sym = elf_file.symbol(sym_index);1038 const local_sym = elf_file.symbol(sym_index);
1043 const name_str_index = try self.insertString(gpa, name);1039 const name_str_index = try self.insertString(gpa, name);
1044 local_sym.name_offset = name_str_index;1040 local_sym.name_offset = name_str_index;
...@@ -1061,8 +1057,8 @@ fn lowerConst(...@@ -1061,8 +1057,8 @@ fn lowerConst(
1061 local_sym.value = atom_ptr.value;1057 local_sym.value = atom_ptr.value;
1062 local_esym.st_value = atom_ptr.value;1058 local_esym.st_value = atom_ptr.value;
10631059
1064 const section_offset = atom_ptr.value - elf_file.phdrs.items[phdr_index].p_vaddr;1060 const shdr = elf_file.shdrs.items[output_section_index];
1065 const file_offset = elf_file.shdrs.items[output_section_index].sh_offset + section_offset;1061 const file_offset = shdr.sh_offset + atom_ptr.value - shdr.sh_addr;
1066 try elf_file.base.file.?.pwriteAll(code, file_offset);1062 try elf_file.base.file.?.pwriteAll(code, file_offset);
10671063
1068 return .{ .ok = sym_index };1064 return .{ .ok = sym_index };