mirror of
https://github.com/ziglang/zig.git
synced 2026-02-19 07:48:31 +00:00
Merge pull request #18918 from ziglang/elf-better-addr-mgmt
elf: store relative offsets in atom and symbol
This commit is contained in:
commit
3f5593205d
124
src/link/Elf.zig
124
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,
|
||||
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: ?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,
|
||||
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: ?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,
|
||||
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: ?u16 = null,
|
||||
strtab_section_index: ?u16 = null,
|
||||
symtab_section_index: ?u16 = 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) {
|
||||
@ -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 => {
|
||||
@ -2970,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);
|
||||
@ -3710,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;
|
||||
@ -3760,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);
|
||||
@ -3771,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);
|
||||
@ -3793,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,
|
||||
@ -4192,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| {
|
||||
@ -4348,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 },
|
||||
@ -4371,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) {
|
||||
@ -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;
|
||||
|
||||
@ -5148,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,
|
||||
@ -5163,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,
|
||||
@ -5202,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),
|
||||
@ -5233,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),
|
||||
@ -5252,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;
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
@ -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);
|
||||
}
|
||||
@ -71,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;
|
||||
}
|
||||
@ -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) {
|
||||
|
||||
@ -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.* = .{
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -234,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);
|
||||
@ -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) {
|
||||
|
||||
@ -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,
|
||||
@ -853,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;
|
||||
@ -907,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 {
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -1006,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;
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -1345,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;
|
||||
@ -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 };
|
||||
|
||||
@ -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 => {
|
||||
|
||||
@ -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()});
|
||||
|
||||
@ -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;
|
||||
@ -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,
|
||||
};
|
||||
@ -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
|
||||
@ -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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user