diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 09658cfd7a..c4bd3d4c10 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -768,15 +768,15 @@ pub fn initMetadata(self: *Elf) !void { pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void { const shdr = &self.shdrs.items[shdr_index]; - const phdr_index = self.phdr_to_shdr_table.get(shdr_index).?; - const phdr = &self.phdrs.items[phdr_index]; + const maybe_phdr = if (self.phdr_to_shdr_table.get(shdr_index)) |phndx| &self.phdrs.items[phndx] else null; const is_zerofill = shdr.sh_type == elf.SHT_NOBITS; if (needed_size > self.allocatedSize(shdr.sh_offset) and !is_zerofill) { const existing_size = shdr.sh_size; shdr.sh_size = 0; // Must move the entire section. - const new_offset = self.findFreeSpace(needed_size, self.page_size); + const alignment = if (maybe_phdr) |phdr| phdr.p_align else shdr.sh_addralign; + const new_offset = self.findFreeSpace(needed_size, alignment); log.debug("new '{s}' file offset 0x{x} to 0x{x}", .{ self.getShString(shdr.sh_name), @@ -789,25 +789,27 @@ pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void { if (amt != existing_size) return error.InputOutput; shdr.sh_offset = new_offset; - phdr.p_offset = new_offset; + if (maybe_phdr) |phdr| phdr.p_offset = new_offset; } shdr.sh_size = needed_size; if (!is_zerofill) { - phdr.p_filesz = needed_size; + if (maybe_phdr) |phdr| phdr.p_filesz = needed_size; } - const mem_capacity = self.allocatedVirtualSize(phdr.p_vaddr); - if (needed_size > mem_capacity) { - var err = try self.addErrorWithNotes(2); - try err.addMsg(self, "fatal linker error: cannot expand load segment phdr({d}) in virtual memory", .{ - phdr_index, - }); - try err.addNote(self, "TODO: emit relocations to memory locations in self-hosted backends", .{}); - try err.addNote(self, "as a workaround, try increasing pre-allocated virtual memory of each segment", .{}); - } + if (maybe_phdr) |phdr| { + const mem_capacity = self.allocatedVirtualSize(phdr.p_vaddr); + if (needed_size > mem_capacity) { + var err = try self.addErrorWithNotes(2); + try err.addMsg(self, "fatal linker error: cannot expand load segment phdr({d}) in virtual memory", .{ + self.phdr_to_shdr_table.get(shdr_index).?, + }); + try err.addNote(self, "TODO: emit relocations to memory locations in self-hosted backends", .{}); + try err.addNote(self, "as a workaround, try increasing pre-allocated virtual memory of each segment", .{}); + } - phdr.p_memsz = needed_size; + phdr.p_memsz = needed_size; + } self.markDirty(shdr_index); } @@ -1499,7 +1501,17 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node pub fn flushObject(self: *Elf, comp: *Compilation) link.File.FlushError!void { _ = comp; try self.initSections(); + try self.sortShdrs(); + try self.updateSectionSizes(); + + try self.allocateNonAllocSections(); + + if (build_options.enable_logging) { + state_log.debug("{}", .{self.dumpState()}); + } + try self.writeShdrTable(); + try self.writeSyntheticSections(); try self.writeHeader(); } diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index 4cb1da9407..82c3fe45f8 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -180,16 +180,16 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf) !void { } if (self.debug_info_header_dirty) { - const text_phdr = &elf_file.phdrs.items[elf_file.phdr_zig_load_re_index.?]; - const low_pc = text_phdr.p_vaddr; - const high_pc = text_phdr.p_vaddr + text_phdr.p_memsz; + const text_shdr = elf_file.shdrs.items[elf_file.zig_text_section_index.?]; + const low_pc = text_shdr.sh_addr; + const high_pc = text_shdr.sh_addr + text_shdr.sh_size; try dw.writeDbgInfoHeader(elf_file.base.options.module.?, low_pc, high_pc); self.debug_info_header_dirty = false; } if (self.debug_aranges_section_dirty) { - const text_phdr = &elf_file.phdrs.items[elf_file.phdr_zig_load_re_index.?]; - try dw.writeDbgAranges(text_phdr.p_vaddr, text_phdr.p_memsz); + const text_shdr = elf_file.shdrs.items[elf_file.zig_text_section_index.?]; + try dw.writeDbgAranges(text_shdr.sh_addr, text_shdr.sh_size); self.debug_aranges_section_dirty = false; } @@ -731,9 +731,7 @@ fn updateDeclCode( const shdr = elf_file.shdrs.items[shdr_index]; if (shdr.sh_type != elf.SHT_NOBITS) { - const phdr_index = elf_file.phdr_to_shdr_table.get(shdr_index).?; - const section_offset = sym.value - elf_file.phdrs.items[phdr_index].p_vaddr; - const file_offset = shdr.sh_offset + section_offset; + const file_offset = shdr.sh_offset + sym.value - shdr.sh_addr; try elf_file.base.file.?.pwriteAll(code, file_offset); } } @@ -940,7 +938,6 @@ fn updateLazySymbol( .const_data => elf_file.zig_data_rel_ro_section_index.?, }; const local_sym = elf_file.symbol(symbol_index); - const phdr_index = elf_file.phdr_to_shdr_table.get(output_section_index).?; local_sym.name_offset = name_str_index; local_sym.output_section_index = output_section_index; const local_esym = &self.local_esyms.items(.elf_sym)[local_sym.esym_index]; @@ -963,8 +960,8 @@ fn updateLazySymbol( const gop = try local_sym.getOrCreateZigGotEntry(symbol_index, elf_file); try elf_file.zig_got.writeOne(elf_file, gop.index); - const section_offset = atom_ptr.value - elf_file.phdrs.items[phdr_index].p_vaddr; - const file_offset = elf_file.shdrs.items[output_section_index].sh_offset + section_offset; + const shdr = elf_file.shdrs.items[output_section_index]; + const file_offset = shdr.sh_offset + atom_ptr.value - shdr.sh_addr; try elf_file.base.file.?.pwriteAll(code, file_offset); } @@ -1038,7 +1035,6 @@ fn lowerConst( .fail => |em| return .{ .fail = em }, }; - const phdr_index = elf_file.phdr_to_shdr_table.get(output_section_index).?; const local_sym = elf_file.symbol(sym_index); const name_str_index = try self.insertString(gpa, name); local_sym.name_offset = name_str_index; @@ -1061,8 +1057,8 @@ fn lowerConst( local_sym.value = atom_ptr.value; local_esym.st_value = atom_ptr.value; - const section_offset = atom_ptr.value - elf_file.phdrs.items[phdr_index].p_vaddr; - const file_offset = elf_file.shdrs.items[output_section_index].sh_offset + section_offset; + const shdr = elf_file.shdrs.items[output_section_index]; + const file_offset = shdr.sh_offset + atom_ptr.value - shdr.sh_addr; try elf_file.base.file.?.pwriteAll(code, file_offset); return .{ .ok = sym_index };