authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-08-23 07:11:55+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-08-25 10:20:15+02:00
log95c30fb4864ddde2f8d8da7fc64f6f90baa42325
tree10e8268f34fc0d1ac2240719b52c46768d4cead0
parenta9d3885ac7529e3b1dde3def42ac3da2874dd774

elf: fix shdr-to-phdr links


2 files changed, 16 insertions(+), 10 deletions(-)

src/link/Elf.zig+15-9
...@@ -559,7 +559,7 @@ pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64) !void {...@@ -559,7 +559,7 @@ pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64) !void {
559 const shdr = &slice.items(.shdr)[shdr_index];559 const shdr = &slice.items(.shdr)[shdr_index];
560 assert(shdr.sh_flags & elf.SHF_ALLOC != 0);560 assert(shdr.sh_flags & elf.SHF_ALLOC != 0);
561 const phndx = slice.items(.phndx)[shdr_index];561 const phndx = slice.items(.phndx)[shdr_index];
562 const phdr = &self.phdrs.items[phndx];562 const maybe_phdr = if (phndx) |ndx| &self.phdrs.items[ndx] else null;
563563
564 log.debug("allocated size {x} of {s}, needed size {x}", .{564 log.debug("allocated size {x} of {s}, needed size {x}", .{
565 self.allocatedSize(shdr.sh_offset),565 self.allocatedSize(shdr.sh_offset),
...@@ -575,7 +575,7 @@ pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64) !void {...@@ -575,7 +575,7 @@ pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64) !void {
575 const existing_size = shdr.sh_size;575 const existing_size = shdr.sh_size;
576 shdr.sh_size = 0;576 shdr.sh_size = 0;
577 // Must move the entire section.577 // Must move the entire section.
578 const alignment = if (phdr.p_type == elf.PT_NULL) shdr.sh_addralign else phdr.p_align;578 const alignment = if (maybe_phdr) |phdr| phdr.p_align else shdr.sh_addralign;
579 const new_offset = try self.findFreeSpace(needed_size, alignment);579 const new_offset = try self.findFreeSpace(needed_size, alignment);
580580
581 log.debug("new '{s}' file offset 0x{x} to 0x{x}", .{581 log.debug("new '{s}' file offset 0x{x} to 0x{x}", .{
...@@ -589,17 +589,17 @@ pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64) !void {...@@ -589,17 +589,17 @@ pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64) !void {
589 if (amt != existing_size) return error.InputOutput;589 if (amt != existing_size) return error.InputOutput;
590590
591 shdr.sh_offset = new_offset;591 shdr.sh_offset = new_offset;
592 if (phdr.p_type != elf.PT_NULL) phdr.p_offset = new_offset;592 if (maybe_phdr) |phdr| phdr.p_offset = new_offset;
593 }593 }
594 if (phdr.p_type != elf.PT_NULL) phdr.p_filesz = needed_size;594 if (maybe_phdr) |phdr| phdr.p_filesz = needed_size;
595 }595 }
596 shdr.sh_size = needed_size;596 shdr.sh_size = needed_size;
597597
598 if (phdr.p_type != elf.PT_NULL) {598 if (maybe_phdr) |phdr| {
599 const mem_capacity = self.allocatedVirtualSize(phdr.p_vaddr);599 const mem_capacity = self.allocatedVirtualSize(phdr.p_vaddr);
600 if (needed_size > mem_capacity) {600 if (needed_size > mem_capacity) {
601 var err = try self.base.addErrorWithNotes(2);601 var err = try self.base.addErrorWithNotes(2);
602 try err.addMsg("fatal linker error: cannot expand load segment phdr({d}) in virtual memory", .{phndx});602 try err.addMsg("fatal linker error: cannot expand load segment phdr({d}) in virtual memory", .{phndx.?});
603 try err.addNote("TODO: emit relocations to memory locations in self-hosted backends", .{});603 try err.addNote("TODO: emit relocations to memory locations in self-hosted backends", .{});
604 try err.addNote("as a workaround, try increasing pre-allocated virtual memory of each segment", .{});604 try err.addNote("as a workaround, try increasing pre-allocated virtual memory of each segment", .{});
605 }605 }
...@@ -3235,6 +3235,12 @@ fn sortPhdrs(self: *Elf) error{OutOfMemory}!void {...@@ -3235,6 +3235,12 @@ fn sortPhdrs(self: *Elf) error{OutOfMemory}!void {
3235 index.* = backlinks[index.*];3235 index.* = backlinks[index.*];
3236 }3236 }
3237 }3237 }
3238
3239 for (self.sections.items(.phndx)) |*maybe_phndx| {
3240 if (maybe_phndx.*) |*index| {
3241 index.* = backlinks[index.*];
3242 }
3243 }
3238}3244}
32393245
3240fn shdrRank(self: *Elf, shndx: u32) u8 {3246fn shdrRank(self: *Elf, shndx: u32) u8 {
...@@ -3763,6 +3769,7 @@ pub fn allocateAllocSections(self: *Elf) !void {...@@ -3763,6 +3769,7 @@ pub fn allocateAllocSections(self: *Elf) !void {
37633769
3764 for (cover.items) |shndx| {3770 for (cover.items) |shndx| {
3765 const shdr = &slice.items(.shdr)[shndx];3771 const shdr = &slice.items(.shdr)[shndx];
3772 slice.items(.phndx)[shndx] = phndx;
3766 if (shdr.sh_type == elf.SHT_NOBITS) {3773 if (shdr.sh_type == elf.SHT_NOBITS) {
3767 shdr.sh_offset = 0;3774 shdr.sh_offset = 0;
3768 continue;3775 continue;
...@@ -3770,7 +3777,6 @@ pub fn allocateAllocSections(self: *Elf) !void {...@@ -3770,7 +3777,6 @@ pub fn allocateAllocSections(self: *Elf) !void {
3770 off = alignment.@"align"(shndx, shdr.sh_addralign, off);3777 off = alignment.@"align"(shndx, shdr.sh_addralign, off);
3771 shdr.sh_offset = off;3778 shdr.sh_offset = off;
3772 off += shdr.sh_size;3779 off += shdr.sh_size;
3773 slice.items(.phndx)[shndx] = phndx;
3774 }3780 }
37753781
3776 addr = mem.alignForward(u64, addr, self.page_size);3782 addr = mem.alignForward(u64, addr, self.page_size);
...@@ -5282,7 +5288,7 @@ fn fmtDumpState(...@@ -5282,7 +5288,7 @@ fn fmtDumpState(
52825288
5283 try writer.writeAll("\nOutput shdrs\n");5289 try writer.writeAll("\nOutput shdrs\n");
5284 for (self.sections.items(.shdr), self.sections.items(.phndx), 0..) |shdr, phndx, shndx| {5290 for (self.sections.items(.shdr), self.sections.items(.phndx), 0..) |shdr, phndx, shndx| {
5285 try writer.print(" shdr({d}) : phdr({d}) : {}\n", .{5291 try writer.print(" shdr({d}) : phdr({?d}) : {}\n", .{
5286 shndx,5292 shndx,
5287 phndx,5293 phndx,
5288 self.fmtShdr(shdr),5294 self.fmtShdr(shdr),
...@@ -5530,7 +5536,7 @@ pub const SymbolResolver = struct {...@@ -5530,7 +5536,7 @@ pub const SymbolResolver = struct {
55305536
5531const Section = struct {5537const Section = struct {
5532 shdr: elf.Elf64_Shdr,5538 shdr: elf.Elf64_Shdr,
5533 phndx: u32 = 0,5539 phndx: ?u32 = null,
5534 atom_list: std.ArrayListUnmanaged(Ref) = .{},5540 atom_list: std.ArrayListUnmanaged(Ref) = .{},
55355541
5536 /// Index of the last allocated atom in this section.5542 /// Index of the last allocated atom in this section.
src/link/Elf/ZigObject.zig+1-1
...@@ -239,7 +239,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {...@@ -239,7 +239,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
239 shdr.sh_size = 1024;239 shdr.sh_size = 1024;
240 } else {240 } else {
241 phndx.* = elf_file.phdr_zig_load_zerofill_index.?;241 phndx.* = elf_file.phdr_zig_load_zerofill_index.?;
242 const phdr = elf_file.phdrs.items[phndx.*];242 const phdr = elf_file.phdrs.items[phndx.*.?];
243 shdr.sh_addr = phdr.p_vaddr;243 shdr.sh_addr = phdr.p_vaddr;
244 shdr.sh_size = phdr.p_memsz;244 shdr.sh_size = phdr.p_memsz;
245 }245 }