From e401930fa862e3b9b3eedc8eb405c501fbf3de30 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Tue, 13 Feb 2024 16:42:28 +0100 Subject: [PATCH 1/2] elf: store relative offsets in atom and symbol --- src/link/Elf.zig | 16 ++------- src/link/Elf/Atom.zig | 39 +++++++++++++--------- src/link/Elf/Object.zig | 11 ------- src/link/Elf/Symbol.zig | 15 ++++++--- src/link/Elf/ZigObject.zig | 51 +++++++++++------------------ src/link/Elf/eh_frame.zig | 2 +- src/link/Elf/relocatable.zig | 1 - src/link/Elf/synthetic_sections.zig | 4 +-- 8 files changed, 61 insertions(+), 78 deletions(-) diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 7f421d5d2695..7ef4684765c4 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1332,7 +1332,6 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) try self.sortPhdrs(); try self.allocateNonAllocSections(); self.allocateSpecialPhdrs(); - self.allocateAtoms(); self.allocateLinkerDefinedSymbols(); // Dump the state for easy debugging. @@ -1352,7 +1351,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) if (shdr.sh_type == elf.SHT_NOBITS) continue; const code = try zig_object.codeAlloc(self, atom_index); defer gpa.free(code); - const file_offset = shdr.sh_offset + atom_ptr.value - shdr.sh_addr; + const file_offset = shdr.sh_offset + atom_ptr.value; atom_ptr.resolveRelocsAlloc(self, code) catch |err| switch (err) { // TODO error.RelaxFail, error.InvalidInstruction, error.CannotEncode => { @@ -2907,7 +2906,7 @@ pub fn writeElfHeader(self: *Elf) !void { mem.writeInt(u32, hdr_buf[index..][0..4], 1, endian); index += 4; - const e_entry = if (self.entry_index) |entry_index| self.symbol(entry_index).value else 0; + const e_entry = if (self.entry_index) |entry_index| self.symbol(entry_index).address(.{}, self) else 0; const phdr_table_offset = if (self.phdr_table_index) |phndx| self.phdrs.items[phndx].p_offset else 0; switch (self.ptr_width) { .p32 => { @@ -4402,15 +4401,6 @@ fn allocateSpecialPhdrs(self: *Elf) void { } } -pub fn allocateAtoms(self: *Elf) void { - if (self.zigObjectPtr()) |zig_object| { - zig_object.allocateTlvAtoms(self); - } - for (self.objects.items) |index| { - self.file(index).?.object.allocateAtoms(self); - } -} - fn writeAtoms(self: *Elf) !void { const gpa = self.base.comp.gpa; @@ -4464,7 +4454,7 @@ fn writeAtoms(self: *Elf) !void { const atom_ptr = self.atom(atom_index).?; assert(atom_ptr.flags.alive); - const offset = math.cast(usize, atom_ptr.value - shdr.sh_addr - base_offset) orelse + const offset = math.cast(usize, atom_ptr.value - base_offset) orelse return error.Overflow; const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow; diff --git a/src/link/Elf/Atom.zig b/src/link/Elf/Atom.zig index cb3e7718b272..b1b07e569f1b 100644 --- a/src/link/Elf/Atom.zig +++ b/src/link/Elf/Atom.zig @@ -54,6 +54,12 @@ pub fn name(self: Atom, elf_file: *Elf) []const u8 { }; } +pub fn address(self: Atom, elf_file: *Elf) u64 { + const shndx = self.outputShndx() orelse return self.value; + const shdr = elf_file.shdrs.items[shndx]; + return shdr.sh_addr + self.value; +} + pub fn file(self: Atom, elf_file: *Elf) ?File { return elf_file.file(self.file_index); } @@ -85,14 +91,17 @@ pub fn priority(self: Atom, elf_file: *Elf) u64 { /// File offset relocation happens transparently, so it is not included in /// this calculation. pub fn capacity(self: Atom, elf_file: *Elf) u64 { - const next_value = if (elf_file.atom(self.next_index)) |next| next.value else std.math.maxInt(u32); - return next_value - self.value; + const next_addr = if (elf_file.atom(self.next_index)) |next| + next.address(elf_file) + else + std.math.maxInt(u32); + return next_addr - self.address(elf_file); } pub fn freeListEligible(self: Atom, elf_file: *Elf) bool { // No need to keep a free list node for the last block. const next = elf_file.atom(self.next_index) orelse return false; - const cap = next.value - self.value; + const cap = next.address(elf_file) - self.address(elf_file); const ideal_cap = Elf.padToIdeal(self.size); if (cap <= ideal_cap) return false; const surplus = cap - ideal_cap; @@ -160,15 +169,15 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void { atom_placement = last.atom_index; break :blk new_start_vaddr; } else { - break :blk shdr.sh_addr; + break :blk 0; } }; log.debug("allocated atom({d}) : '{s}' at 0x{x} to 0x{x}", .{ self.atom_index, self.name(elf_file), - self.value, - self.value + self.size, + self.address(elf_file), + self.address(elf_file) + self.size, }); const expand_section = if (atom_placement) |placement_index| @@ -176,7 +185,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void { else true; if (expand_section) { - const needed_size = (self.value + self.size) - shdr.sh_addr; + const needed_size = self.value + self.size; try elf_file.growAllocSection(self.outputShndx().?, needed_size); last_atom_index.* = self.atom_index; @@ -301,7 +310,7 @@ pub fn relocs(self: Atom, elf_file: *Elf) []align(1) const elf.Elf64_Rela { } pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.Elf64_Rela)) !void { - relocs_log.debug("0x{x}: {s}", .{ self.value, self.name(elf_file) }); + relocs_log.debug("0x{x}: {s}", .{ self.address(elf_file), self.name(elf_file) }); const file_ptr = self.file(elf_file).?; for (self.relocs(elf_file)) |rel| { @@ -322,7 +331,7 @@ pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.El var r_sym: u32 = 0; switch (target.type(elf_file)) { elf.STT_SECTION => { - r_addend += @intCast(target.value); + r_addend += @intCast(target.address(.{}, elf_file)); r_sym = elf_file.sectionSymbolOutputSymtabIndex(target.outputShndx().?); }, else => { @@ -778,7 +787,7 @@ fn reportUndefined( } pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) !void { - relocs_log.debug("0x{x}: {s}", .{ self.value, self.name(elf_file) }); + relocs_log.debug("0x{x}: {s}", .{ self.address(elf_file), self.name(elf_file) }); const file_ptr = self.file(elf_file).?; var stream = std.io.fixedBufferStream(code); @@ -802,7 +811,7 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) !void { // https://intezer.com/blog/malware-analysis/executable-and-linkable-format-101-part-3-relocations/ // // Address of the source atom. - const P = @as(i64, @intCast(self.value + rel.r_offset)); + const P = @as(i64, @intCast(self.address(elf_file) + rel.r_offset)); // Addend from the relocation. const A = rel.r_addend; // Address of the target symbol - can be address of the symbol within an atom or address of PLT stub. @@ -969,7 +978,7 @@ fn resolveDynAbsReloc( ) !void { const comp = elf_file.base.comp; const gpa = comp.gpa; - const P = self.value + rel.r_offset; + const P = self.address(elf_file) + rel.r_offset; const A = rel.r_addend; const S = @as(i64, @intCast(target.address(.{}, elf_file))); const is_writeable = self.inputShdr(elf_file).sh_flags & elf.SHF_WRITE != 0; @@ -1058,7 +1067,7 @@ fn applyDynamicReloc(value: i64, elf_file: *Elf, writer: anytype) !void { } pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: anytype) !void { - relocs_log.debug("0x{x}: {s}", .{ self.value, self.name(elf_file) }); + relocs_log.debug("0x{x}: {s}", .{ self.address(elf_file), self.name(elf_file) }); const file_ptr = self.file(elf_file).?; var stream = std.io.fixedBufferStream(code); @@ -1097,7 +1106,7 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any // We will use equation format to resolve relocations: // https://intezer.com/blog/malware-analysis/executable-and-linkable-format-101-part-3-relocations/ // - const P = @as(i64, @intCast(self.value + rel.r_offset)); + const P = @as(i64, @intCast(self.address(elf_file) + rel.r_offset)); // Addend from the relocation. const A = rel.r_addend; // Address of the target symbol - can be address of the symbol within an atom or address of PLT stub. @@ -1248,7 +1257,7 @@ fn format2( const atom = ctx.atom; const elf_file = ctx.elf_file; try writer.print("atom({d}) : {s} : @{x} : shdr({d}) : align({x}) : size({x})", .{ - atom.atom_index, atom.name(elf_file), atom.value, + atom.atom_index, atom.name(elf_file), atom.address(elf_file), atom.output_section_index, atom.alignment, atom.size, }); if (atom.fde_start != atom.fde_end) { diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index 882025ab8c22..246fd9a1552c 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -718,21 +718,11 @@ pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void { if (!gop.found_existing) gop.value_ptr.* = .{}; try gop.value_ptr.append(gpa, atom_index); } -} - -pub fn allocateAtoms(self: Object, elf_file: *Elf) void { - for (self.atoms.items) |atom_index| { - const atom = elf_file.atom(atom_index) orelse continue; - if (!atom.flags.alive) continue; - const shdr = elf_file.shdrs.items[atom.output_section_index]; - atom.value += shdr.sh_addr; - } for (self.locals()) |local_index| { const local = elf_file.symbol(local_index); const atom = local.atom(elf_file) orelse continue; if (!atom.flags.alive) continue; - local.value += atom.value; local.output_section_index = atom.output_section_index; } @@ -741,7 +731,6 @@ pub fn allocateAtoms(self: Object, elf_file: *Elf) void { const atom = global.atom(elf_file) orelse continue; if (!atom.flags.alive) continue; if (global.file(elf_file).?.index() != self.index) continue; - global.value += atom.value; global.output_section_index = atom.output_section_index; } } diff --git a/src/link/Elf/Symbol.zig b/src/link/Elf/Symbol.zig index 7c7d3fd17c95..b2eee739ed77 100644 --- a/src/link/Elf/Symbol.zig +++ b/src/link/Elf/Symbol.zig @@ -104,6 +104,9 @@ pub fn address(symbol: Symbol, opts: struct { plt: bool = true }, elf_file: *Elf // Lazy-bound function it is! return symbol.pltAddress(elf_file); } + if (symbol.atom(elf_file)) |atom_ptr| { + return atom_ptr.address(elf_file) + symbol.value; + } return symbol.value; } @@ -247,11 +250,11 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void { if (symbol.flags.is_canonical) break :blk symbol.address(.{}, elf_file); break :blk 0; } - if (st_shndx == elf.SHN_ABS or st_shndx == elf.SHN_COMMON) break :blk symbol.value; + if (st_shndx == elf.SHN_ABS or st_shndx == elf.SHN_COMMON) break :blk symbol.address(.{ .plt = false }, elf_file); const shdr = &elf_file.shdrs.items[st_shndx]; if (shdr.sh_flags & elf.SHF_TLS != 0 and file_ptr != .linker_defined) - break :blk symbol.value - elf_file.tlsAddress(); - break :blk symbol.value; + break :blk symbol.address(.{ .plt = false }, elf_file) - elf_file.tlsAddress(); + break :blk symbol.address(.{ .plt = false }, elf_file); }; out.st_info = (st_bind << 4) | st_type; out.st_other = esym.st_other; @@ -323,7 +326,11 @@ fn format2( _ = options; _ = unused_fmt_string; const symbol = ctx.symbol; - try writer.print("%{d} : {s} : @{x}", .{ symbol.esym_index, symbol.fmtName(ctx.elf_file), symbol.value }); + try writer.print("%{d} : {s} : @{x}", .{ + symbol.esym_index, + symbol.fmtName(ctx.elf_file), + symbol.address(.{}, ctx.elf_file), + }); if (symbol.file(ctx.elf_file)) |file_ptr| { if (symbol.isAbs(ctx.elf_file)) { if (symbol.elfSym(ctx.elf_file).st_shndx == elf.SHN_UNDEF) { diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index a132b1d453c2..6febd30fc4cf 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -401,19 +401,6 @@ pub fn claimUnresolvedObject(self: ZigObject, elf_file: *Elf) void { } } -pub fn allocateTlvAtoms(self: ZigObject, elf_file: *Elf) void { - for (self.tls_variables.keys(), self.tls_variables.values()) |atom_index, tlv| { - const atom = elf_file.atom(atom_index) orelse continue; - if (!atom.flags.alive) continue; - const local = elf_file.symbol(tlv.symbol_index); - const shdr = elf_file.shdrs.items[atom.output_section_index]; - atom.value += shdr.sh_addr; - local.value = atom.value; - - // TODO exported TLS vars - } -} - pub fn scanRelocs(self: *ZigObject, elf_file: *Elf, undefs: anytype) !void { const gpa = elf_file.base.comp.gpa; for (self.atoms.items) |atom_index| { @@ -644,7 +631,7 @@ pub fn codeAlloc(self: ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8 return code; } - const file_offset = shdr.sh_offset + atom.value - shdr.sh_addr; + const file_offset = shdr.sh_offset + atom.value; const size = std.math.cast(usize, atom.size) orelse return error.Overflow; const code = try gpa.alloc(u8, size); errdefer gpa.free(code); @@ -664,7 +651,7 @@ pub fn getDeclVAddr( ) !u64 { const this_sym_index = try self.getOrCreateMetadataForDecl(elf_file, decl_index); const this_sym = elf_file.symbol(this_sym_index); - const vaddr = this_sym.value; + const vaddr = this_sym.address(.{}, elf_file); const parent_atom = elf_file.symbol(reloc_info.parent_atom_index).atom(elf_file).?; try parent_atom.addReloc(elf_file, .{ .r_offset = reloc_info.offset, @@ -682,7 +669,7 @@ pub fn getAnonDeclVAddr( ) !u64 { const sym_index = self.anon_decls.get(decl_val).?.symbol_index; const sym = elf_file.symbol(sym_index); - const vaddr = sym.value; + const vaddr = sym.address(.{}, elf_file); const parent_atom = elf_file.symbol(reloc_info.parent_atom_index).atom(elf_file).?; try parent_atom.addReloc(elf_file, .{ .r_offset = reloc_info.offset, @@ -941,13 +928,13 @@ fn updateDeclCode( if (old_size > 0 and elf_file.base.child_pid == null) { const capacity = atom_ptr.capacity(elf_file); - const need_realloc = code.len > capacity or !required_alignment.check(sym.value); + const need_realloc = code.len > capacity or !required_alignment.check(atom_ptr.value); if (need_realloc) { try atom_ptr.grow(elf_file); log.debug("growing {s} from 0x{x} to 0x{x}", .{ decl_name, old_vaddr, atom_ptr.value }); if (old_vaddr != atom_ptr.value) { - sym.value = atom_ptr.value; - esym.st_value = atom_ptr.value; + sym.value = 0; + esym.st_value = 0; if (!elf_file.base.isRelocatable()) { log.debug(" (writing new offset table entry)", .{}); @@ -963,9 +950,9 @@ fn updateDeclCode( try atom_ptr.allocate(elf_file); errdefer self.freeDeclMetadata(elf_file, sym_index); - sym.value = atom_ptr.value; + sym.value = 0; sym.flags.needs_zig_got = true; - esym.st_value = atom_ptr.value; + esym.st_value = 0; if (!elf_file.base.isRelocatable()) { const gop = try sym.getOrCreateZigGotEntry(sym_index, elf_file); @@ -981,7 +968,7 @@ fn updateDeclCode( .iov_len = code.len, }}; var remote_vec: [1]std.os.iovec_const = .{.{ - .iov_base = @as([*]u8, @ptrFromInt(@as(usize, @intCast(sym.value)))), + .iov_base = @as([*]u8, @ptrFromInt(@as(usize, @intCast(sym.address(.{}, elf_file))))), .iov_len = code.len, }}; const rc = std.os.linux.process_vm_writev(pid, &code_vec, &remote_vec, 0); @@ -996,7 +983,7 @@ fn updateDeclCode( const shdr = elf_file.shdrs.items[shdr_index]; if (shdr.sh_type != elf.SHT_NOBITS) { - const file_offset = shdr.sh_offset + sym.value - shdr.sh_addr; + const file_offset = shdr.sh_offset + atom_ptr.value; try elf_file.base.file.?.pwriteAll(code, file_offset); } } @@ -1022,12 +1009,14 @@ fn updateTlv( const esym = &self.local_esyms.items(.elf_sym)[sym.esym_index]; const atom_ptr = sym.atom(elf_file).?; + sym.value = 0; sym.output_section_index = shndx; atom_ptr.output_section_index = shndx; sym.name_offset = try self.strtab.insert(gpa, decl_name); atom_ptr.flags.alive = true; atom_ptr.name_offset = sym.name_offset; + esym.st_value = 0; esym.st_name = sym.name_offset; esym.st_info = elf.STT_TLS; esym.st_size = code.len; @@ -1117,7 +1106,7 @@ pub fn updateFunc( try self.dwarf.?.commitDeclState( mod, decl_index, - sym.value, + sym.address(.{}, elf_file), sym.atom(elf_file).?.size, ds, ); @@ -1202,7 +1191,7 @@ pub fn updateDecl( try self.dwarf.?.commitDeclState( mod, decl_index, - sym.value, + sym.address(.{}, elf_file), sym.atom(elf_file).?.size, ds, ); @@ -1281,9 +1270,9 @@ fn updateLazySymbol( try atom_ptr.allocate(elf_file); errdefer self.freeDeclMetadata(elf_file, symbol_index); - local_sym.value = atom_ptr.value; + local_sym.value = 0; local_sym.flags.needs_zig_got = true; - local_esym.st_value = atom_ptr.value; + local_esym.st_value = 0; if (!elf_file.base.isRelocatable()) { const gop = try local_sym.getOrCreateZigGotEntry(symbol_index, elf_file); @@ -1291,7 +1280,7 @@ fn updateLazySymbol( } const shdr = elf_file.shdrs.items[output_section_index]; - const file_offset = shdr.sh_offset + atom_ptr.value - shdr.sh_addr; + const file_offset = shdr.sh_offset + atom_ptr.value; try elf_file.base.file.?.pwriteAll(code, file_offset); } @@ -1384,11 +1373,11 @@ fn lowerConst( // TODO rename and re-audit this method errdefer self.freeDeclMetadata(elf_file, sym_index); - local_sym.value = atom_ptr.value; - local_esym.st_value = atom_ptr.value; + local_sym.value = 0; + local_esym.st_value = 0; const shdr = elf_file.shdrs.items[output_section_index]; - const file_offset = shdr.sh_offset + atom_ptr.value - shdr.sh_addr; + const file_offset = shdr.sh_offset + atom_ptr.value; try elf_file.base.file.?.pwriteAll(code, file_offset); return .{ .ok = sym_index }; diff --git a/src/link/Elf/eh_frame.zig b/src/link/Elf/eh_frame.zig index 4825ddb4764d..648c3d45f390 100644 --- a/src/link/Elf/eh_frame.zig +++ b/src/link/Elf/eh_frame.zig @@ -409,7 +409,7 @@ fn emitReloc(elf_file: *Elf, rec: anytype, sym: *const Symbol, rel: elf.Elf64_Re var r_sym: u32 = 0; switch (sym.type(elf_file)) { elf.STT_SECTION => { - r_addend += @intCast(sym.value); + r_addend += @intCast(sym.address(.{}, elf_file)); r_sym = elf_file.sectionSymbolOutputSymtabIndex(sym.outputShndx().?); }, else => { diff --git a/src/link/Elf/relocatable.zig b/src/link/Elf/relocatable.zig index 9492c30ab8e5..017329dde773 100644 --- a/src/link/Elf/relocatable.zig +++ b/src/link/Elf/relocatable.zig @@ -195,7 +195,6 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const try allocateAllocSections(elf_file); try elf_file.allocateNonAllocSections(); - elf_file.allocateAtoms(); if (build_options.enable_logging) { state_log.debug("{}", .{elf_file.dumpState()}); diff --git a/src/link/Elf/synthetic_sections.zig b/src/link/Elf/synthetic_sections.zig index 6f76605e3126..47e10281fa74 100644 --- a/src/link/Elf/synthetic_sections.zig +++ b/src/link/Elf/synthetic_sections.zig @@ -297,7 +297,7 @@ pub const ZigGotSection = struct { const off = zig_got.entryOffset(index, elf_file); const vaddr = zig_got.entryAddress(index, elf_file); const entry = zig_got.entries.items[index]; - const value = elf_file.symbol(entry).value; + const value = elf_file.symbol(entry).address(.{}, elf_file); switch (entry_size) { 2 => { var buf: [2]u8 = undefined; @@ -1004,7 +1004,7 @@ pub const GotPltSection = struct { { // [0]: _DYNAMIC const symbol = elf_file.symbol(elf_file.dynamic_index.?); - try writer.writeInt(u64, symbol.value, .little); + try writer.writeInt(u64, symbol.address(.{}, elf_file), .little); } // [1]: 0x0 // [2]: 0x0 From 216a5594f62aca7524012e0a2bbf226c4064fae4 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Tue, 13 Feb 2024 17:24:46 +0100 Subject: [PATCH 2/2] elf: use u32 for all section indexes --- src/link/Elf.zig | 114 ++++++++++++++-------------- src/link/Elf/Atom.zig | 4 +- src/link/Elf/Object.zig | 10 +-- src/link/Elf/Symbol.zig | 10 +-- src/link/Elf/ZigObject.zig | 8 +- src/link/Elf/synthetic_sections.zig | 10 +-- 6 files changed, 78 insertions(+), 78 deletions(-) diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 7ef4684765c4..248db26b0167 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -138,40 +138,40 @@ 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: ?u16 = null, -zig_data_rel_ro_section_index: ?u16 = null, -zig_data_section_index: ?u16 = null, -zig_bss_section_index: ?u16 = null, -zig_got_section_index: ?u16 = null, - -debug_info_section_index: ?u16 = null, -debug_abbrev_section_index: ?u16 = null, -debug_str_section_index: ?u16 = null, -debug_aranges_section_index: ?u16 = null, -debug_line_section_index: ?u16 = null, - -copy_rel_section_index: ?u16 = null, -dynamic_section_index: ?u16 = null, -dynstrtab_section_index: ?u16 = null, -dynsymtab_section_index: ?u16 = null, -eh_frame_section_index: ?u16 = null, -eh_frame_rela_section_index: ?u16 = null, -eh_frame_hdr_section_index: ?u16 = null, -hash_section_index: ?u16 = null, -gnu_hash_section_index: ?u16 = null, -got_section_index: ?u16 = null, -got_plt_section_index: ?u16 = null, -interp_section_index: ?u16 = null, -plt_section_index: ?u16 = null, -plt_got_section_index: ?u16 = null, -rela_dyn_section_index: ?u16 = null, -rela_plt_section_index: ?u16 = null, -versym_section_index: ?u16 = null, -verneed_section_index: ?u16 = null, - -shstrtab_section_index: ?u16 = null, -strtab_section_index: ?u16 = null, -symtab_section_index: ?u16 = null, +zig_text_section_index: ?u32 = null, +zig_data_rel_ro_section_index: ?u32 = null, +zig_data_section_index: ?u32 = null, +zig_bss_section_index: ?u32 = null, +zig_got_section_index: ?u32 = null, + +debug_info_section_index: ?u32 = null, +debug_abbrev_section_index: ?u32 = null, +debug_str_section_index: ?u32 = null, +debug_aranges_section_index: ?u32 = null, +debug_line_section_index: ?u32 = null, + +copy_rel_section_index: ?u32 = null, +dynamic_section_index: ?u32 = null, +dynstrtab_section_index: ?u32 = null, +dynsymtab_section_index: ?u32 = null, +eh_frame_section_index: ?u32 = null, +eh_frame_rela_section_index: ?u32 = null, +eh_frame_hdr_section_index: ?u32 = null, +hash_section_index: ?u32 = null, +gnu_hash_section_index: ?u32 = null, +got_section_index: ?u32 = null, +got_plt_section_index: ?u32 = null, +interp_section_index: ?u32 = null, +plt_section_index: ?u32 = null, +plt_got_section_index: ?u32 = null, +rela_dyn_section_index: ?u32 = null, +rela_plt_section_index: ?u32 = null, +versym_section_index: ?u32 = null, +verneed_section_index: ?u32 = null, + +shstrtab_section_index: ?u32 = null, +strtab_section_index: ?u32 = null, +symtab_section_index: ?u32 = null, // Linker-defined symbols dynamic_index: ?Symbol.Index = null, @@ -931,7 +931,7 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void { try self.base.file.?.pwriteAll(&[1]u8{0}, end_pos); } -pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void { +pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64) !void { const shdr = &self.shdrs.items[shdr_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; @@ -981,7 +981,7 @@ pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void { pub fn growNonAllocSection( self: *Elf, - shdr_index: u16, + shdr_index: u32, needed_size: u64, min_alignment: u32, requires_file_copy: bool, @@ -1018,7 +1018,7 @@ pub fn growNonAllocSection( self.markDirty(shdr_index); } -pub fn markDirty(self: *Elf, shdr_index: u16) void { +pub fn markDirty(self: *Elf, shdr_index: u32) void { const zig_object = self.zigObjectPtr().?; if (zig_object.dwarf) |_| { if (self.debug_info_section_index.? == shdr_index) { @@ -2969,7 +2969,7 @@ pub fn writeElfHeader(self: *Elf) !void { mem.writeInt(u16, hdr_buf[index..][0..2], e_shnum, endian); index += 2; - mem.writeInt(u16, hdr_buf[index..][0..2], self.shstrtab_section_index.?, endian); + mem.writeInt(u16, hdr_buf[index..][0..2], @intCast(self.shstrtab_section_index.?), endian); index += 2; assert(index == e_ehsize); @@ -3709,7 +3709,7 @@ fn sortPhdrs(self: *Elf) error{OutOfMemory}!void { } } -fn shdrRank(self: *Elf, shndx: u16) u8 { +fn shdrRank(self: *Elf, shndx: u32) u8 { const shdr = self.shdrs.items[shndx]; const name = self.getShString(shdr.sh_name); const flags = shdr.sh_flags; @@ -3759,7 +3759,7 @@ fn shdrRank(self: *Elf, shndx: u16) u8 { pub fn sortShdrs(self: *Elf) !void { const Entry = struct { - shndx: u16, + shndx: u32, pub fn lessThan(elf_file: *Elf, lhs: @This(), rhs: @This()) bool { return elf_file.shdrRank(lhs.shndx) < elf_file.shdrRank(rhs.shndx); @@ -3770,15 +3770,15 @@ pub fn sortShdrs(self: *Elf) !void { var entries = try std.ArrayList(Entry).initCapacity(gpa, self.shdrs.items.len); defer entries.deinit(); for (0..self.shdrs.items.len) |shndx| { - entries.appendAssumeCapacity(.{ .shndx = @as(u16, @intCast(shndx)) }); + entries.appendAssumeCapacity(.{ .shndx = @intCast(shndx) }); } mem.sort(Entry, entries.items, self, Entry.lessThan); - const backlinks = try gpa.alloc(u16, entries.items.len); + const backlinks = try gpa.alloc(u32, entries.items.len); defer gpa.free(backlinks); for (entries.items, 0..) |entry, i| { - backlinks[entry.shndx] = @as(u16, @intCast(i)); + backlinks[entry.shndx] = @intCast(i); } const slice = try self.shdrs.toOwnedSlice(gpa); @@ -3792,10 +3792,10 @@ pub fn sortShdrs(self: *Elf) !void { try self.resetShdrIndexes(backlinks); } -fn resetShdrIndexes(self: *Elf, backlinks: []const u16) !void { +fn resetShdrIndexes(self: *Elf, backlinks: []const u32) !void { const gpa = self.base.comp.gpa; - for (&[_]*?u16{ + for (&[_]*?u32{ &self.eh_frame_section_index, &self.eh_frame_rela_section_index, &self.eh_frame_hdr_section_index, @@ -4191,7 +4191,7 @@ pub fn allocateAllocSections(self: *Elf) error{OutOfMemory}!void { // virtual and file offsets. However, the simple one will do for one // as we are more interested in quick turnaround and compatibility // with `findFreeSpace` mechanics than anything else. - const Cover = std.ArrayList(u16); + const Cover = std.ArrayList(u32); const gpa = self.base.comp.gpa; var covers: [max_number_of_object_segments]Cover = undefined; for (&covers) |*cover| { @@ -4347,7 +4347,7 @@ pub fn allocateNonAllocSections(self: *Elf) !void { } fn allocateSpecialPhdrs(self: *Elf) void { - for (&[_]struct { ?u16, ?u16 }{ + for (&[_]struct { ?u16, ?u32 }{ .{ self.phdr_interp_index, self.interp_section_index }, .{ self.phdr_dynamic_index, self.dynamic_section_index }, .{ self.phdr_gnu_eh_frame_index, self.eh_frame_hdr_section_index }, @@ -4370,7 +4370,7 @@ fn allocateSpecialPhdrs(self: *Elf) void { if (self.phdr_tls_index) |index| { const slice = self.shdrs.items; const phdr = &self.phdrs.items[index]; - var shndx: u16 = 0; + var shndx: u32 = 0; while (shndx < slice.len) { const shdr = slice[shndx]; if (shdr.sh_flags & elf.SHF_TLS == 0) { @@ -5138,8 +5138,8 @@ const CsuObjects = struct { } }; -pub fn isZigSection(self: Elf, shndx: u16) bool { - inline for (&[_]?u16{ +pub fn isZigSection(self: Elf, shndx: u32) bool { + inline for (&[_]?u32{ self.zig_text_section_index, self.zig_data_rel_ro_section_index, self.zig_data_section_index, @@ -5153,8 +5153,8 @@ pub fn isZigSection(self: Elf, shndx: u16) bool { return false; } -pub fn isDebugSection(self: Elf, shndx: u16) bool { - inline for (&[_]?u16{ +pub fn isDebugSection(self: Elf, shndx: u32) bool { + inline for (&[_]?u32{ self.debug_info_section_index, self.debug_abbrev_section_index, self.debug_str_section_index, @@ -5192,7 +5192,7 @@ fn addPhdr(self: *Elf, opts: struct { return index; } -pub fn addRelaShdr(self: *Elf, name: [:0]const u8, shndx: u16) !u16 { +pub fn addRelaShdr(self: *Elf, name: [:0]const u8, shndx: u32) !u32 { const entsize: u64 = switch (self.ptr_width) { .p32 => @sizeOf(elf.Elf32_Rela), .p64 => @sizeOf(elf.Elf64_Rela), @@ -5223,9 +5223,9 @@ pub const AddSectionOpts = struct { offset: u64 = 0, }; -pub fn addSection(self: *Elf, opts: AddSectionOpts) !u16 { +pub fn addSection(self: *Elf, opts: AddSectionOpts) !u32 { const gpa = self.base.comp.gpa; - const index = @as(u16, @intCast(self.shdrs.items.len)); + const index = @as(u32, @intCast(self.shdrs.items.len)); const shdr = try self.shdrs.addOne(gpa); shdr.* = .{ .sh_name = try self.insertShString(opts.name), @@ -5242,10 +5242,10 @@ pub fn addSection(self: *Elf, opts: AddSectionOpts) !u16 { return index; } -pub fn sectionByName(self: *Elf, name: [:0]const u8) ?u16 { +pub fn sectionByName(self: *Elf, name: [:0]const u8) ?u32 { for (self.shdrs.items, 0..) |*shdr, i| { const this_name = self.getShString(shdr.sh_name); - if (mem.eql(u8, this_name, name)) return @as(u16, @intCast(i)); + if (mem.eql(u8, this_name, name)) return @intCast(i); } else return null; } diff --git a/src/link/Elf/Atom.zig b/src/link/Elf/Atom.zig index b1b07e569f1b..330544d8bbfd 100644 --- a/src/link/Elf/Atom.zig +++ b/src/link/Elf/Atom.zig @@ -17,7 +17,7 @@ alignment: Alignment = .@"1", input_section_index: u32 = 0, /// Index of the output section. -output_section_index: u16 = 0, +output_section_index: u32 = 0, /// Index of the input section containing this atom's relocs. relocs_section_index: u32 = 0, @@ -77,7 +77,7 @@ pub fn relocsShndx(self: Atom) ?u32 { return self.relocs_section_index; } -pub fn outputShndx(self: Atom) ?u16 { +pub fn outputShndx(self: Atom) ?u32 { if (self.output_section_index == 0) return null; return self.output_section_index; } diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index 246fd9a1552c..395e6680a121 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -126,7 +126,7 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil try self.strtab.appendSlice(allocator, shstrtab); const symtab_index = for (self.shdrs.items, 0..) |shdr, i| switch (shdr.sh_type) { - elf.SHT_SYMTAB => break @as(u16, @intCast(i)), + elf.SHT_SYMTAB => break @as(u32, @intCast(i)), else => {}, } else null; @@ -223,7 +223,7 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file: => {}, else => { - const shndx = @as(u16, @intCast(i)); + const shndx = @as(u32, @intCast(i)); if (self.skipShdr(shndx, elf_file)) continue; try self.addAtom(allocator, handle, shdr, shndx, elf_file); }, @@ -268,7 +268,7 @@ fn addAtom(self: *Object, allocator: Allocator, handle: std.fs.File, shdr: elf.E } } -fn initOutputSection(self: Object, elf_file: *Elf, shdr: elf.Elf64_Shdr) error{OutOfMemory}!u16 { +fn initOutputSection(self: Object, elf_file: *Elf, shdr: elf.Elf64_Shdr) error{OutOfMemory}!u32 { const name = blk: { const name = self.getString(shdr.sh_name); if (elf_file.base.isRelocatable()) break :blk name; @@ -316,7 +316,7 @@ fn initOutputSection(self: Object, elf_file: *Elf, shdr: elf.Elf64_Shdr) error{O return out_shndx; } -fn skipShdr(self: *Object, index: u16, elf_file: *Elf) bool { +fn skipShdr(self: *Object, index: u32, elf_file: *Elf) bool { const comp = elf_file.base.comp; const shdr = self.shdrs.items[index]; const name = self.getString(shdr.sh_name); @@ -673,7 +673,7 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void { var sh_flags: u32 = elf.SHF_ALLOC | elf.SHF_WRITE; if (is_tls) sh_flags |= elf.SHF_TLS; - const shndx = @as(u16, @intCast(self.shdrs.items.len)); + const shndx = @as(u32, @intCast(self.shdrs.items.len)); const shdr = try self.shdrs.addOne(gpa); const sh_size = math.cast(usize, this_sym.st_size) orelse return error.Overflow; shdr.* = .{ diff --git a/src/link/Elf/Symbol.zig b/src/link/Elf/Symbol.zig index b2eee739ed77..ea1b4f4b6b3d 100644 --- a/src/link/Elf/Symbol.zig +++ b/src/link/Elf/Symbol.zig @@ -15,7 +15,7 @@ file_index: File.Index = 0, atom_index: Atom.Index = 0, /// Assigned output section index for this atom. -output_section_index: u16 = 0, +output_section_index: u32 = 0, /// Index of the source symbol this symbol references. /// Use `elfSym` to pull the source symbol from the relevant file. @@ -37,7 +37,7 @@ pub fn isAbs(symbol: Symbol, elf_file: *Elf) bool { file_ptr != .linker_defined; } -pub fn outputShndx(symbol: Symbol) ?u16 { +pub fn outputShndx(symbol: Symbol) ?u32 { if (symbol.output_section_index == 0) return null; return symbol.output_section_index; } @@ -237,12 +237,12 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void { if (file_ptr == .shared_object) break :blk elf.STB_GLOBAL; break :blk esym.st_bind(); }; - const st_shndx = blk: { - if (symbol.flags.has_copy_rel) break :blk elf_file.copy_rel_section_index.?; + const st_shndx: u16 = blk: { + if (symbol.flags.has_copy_rel) break :blk @intCast(elf_file.copy_rel_section_index.?); if (file_ptr == .shared_object or esym.st_shndx == elf.SHN_UNDEF) break :blk elf.SHN_UNDEF; if (elf_file.base.isRelocatable() and esym.st_shndx == elf.SHN_COMMON) break :blk elf.SHN_COMMON; if (symbol.atom(elf_file) == null and file_ptr != .linker_defined) break :blk elf.SHN_ABS; - break :blk symbol.outputShndx() orelse elf.SHN_UNDEF; + break :blk @intCast(symbol.outputShndx() orelse elf.SHN_UNDEF); }; const st_value = blk: { if (symbol.flags.has_copy_rel) break :blk symbol.address(.{}, elf_file); diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index 6febd30fc4cf..93673954604f 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -840,7 +840,7 @@ fn getDeclShdrIndex( elf_file: *Elf, decl: *const Module.Decl, code: []const u8, -) error{OutOfMemory}!u16 { +) error{OutOfMemory}!u32 { _ = self; const mod = elf_file.base.comp.module.?; const any_non_single_threaded = elf_file.base.comp.config.any_non_single_threaded; @@ -894,7 +894,7 @@ fn updateDeclCode( elf_file: *Elf, decl_index: InternPool.DeclIndex, sym_index: Symbol.Index, - shdr_index: u16, + shdr_index: u32, code: []const u8, stt_bits: u8, ) !void { @@ -993,7 +993,7 @@ fn updateTlv( elf_file: *Elf, decl_index: InternPool.DeclIndex, sym_index: Symbol.Index, - shndx: u16, + shndx: u32, code: []const u8, ) !void { const gpa = elf_file.base.comp.gpa; @@ -1334,7 +1334,7 @@ fn lowerConst( name: []const u8, tv: TypedValue, required_alignment: InternPool.Alignment, - output_section_index: u16, + output_section_index: u32, src_loc: Module.SrcLoc, ) !LowerConstResult { const gpa = elf_file.base.comp.gpa; diff --git a/src/link/Elf/synthetic_sections.zig b/src/link/Elf/synthetic_sections.zig index 47e10281fa74..93516764bc51 100644 --- a/src/link/Elf/synthetic_sections.zig +++ b/src/link/Elf/synthetic_sections.zig @@ -388,7 +388,7 @@ pub const ZigGotSection = struct { .st_name = st_name, .st_info = elf.STT_OBJECT, .st_other = 0, - .st_shndx = elf_file.zig_got_section_index.?, + .st_shndx = @intCast(elf_file.zig_got_section_index.?), .st_value = st_value, .st_size = st_size, }; @@ -813,7 +813,7 @@ pub const GotSection = struct { .st_name = st_name, .st_info = elf.STT_OBJECT, .st_other = 0, - .st_shndx = elf_file.got_section_index.?, + .st_shndx = @intCast(elf_file.got_section_index.?), .st_value = st_value, .st_size = st_size, }; @@ -953,7 +953,7 @@ pub const PltSection = struct { .st_name = st_name, .st_info = elf.STT_FUNC, .st_other = 0, - .st_shndx = elf_file.plt_section_index.?, + .st_shndx = @intCast(elf_file.plt_section_index.?), .st_value = sym.pltAddress(elf_file), .st_size = 16, }; @@ -1082,7 +1082,7 @@ pub const PltGotSection = struct { .st_name = st_name, .st_info = elf.STT_FUNC, .st_other = 0, - .st_shndx = elf_file.plt_got_section_index.?, + .st_shndx = @intCast(elf_file.plt_got_section_index.?), .st_value = sym.pltGotAddress(elf_file), .st_size = 16, }; @@ -1132,7 +1132,7 @@ pub const CopyRelSection = struct { } } - pub fn updateSectionSize(copy_rel: CopyRelSection, shndx: u16, elf_file: *Elf) !void { + pub fn updateSectionSize(copy_rel: CopyRelSection, shndx: u32, elf_file: *Elf) !void { const shdr = &elf_file.shdrs.items[shndx]; for (copy_rel.symbols.items) |sym_index| { const symbol = elf_file.symbol(sym_index);