mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
Elf2: implement object relocs
This commit is contained in:
parent
80c961159b
commit
b1d46339b5
1 changed files with 402 additions and 214 deletions
|
|
@ -3,6 +3,7 @@ options: link.File.OpenOptions,
|
|||
mf: MappedFile,
|
||||
ni: Node.Known,
|
||||
nodes: std.MultiArrayList(Node),
|
||||
shdrs: std.ArrayList(Section),
|
||||
phdrs: std.ArrayList(MappedFile.Node.Index),
|
||||
si: Symbol.Known,
|
||||
symtab: std.ArrayList(Symbol),
|
||||
|
|
@ -163,9 +164,10 @@ pub const Node = union(enum) {
|
|||
}
|
||||
};
|
||||
|
||||
pub const Section = struct { si: Symbol.Index, rela_si: Symbol.Index };
|
||||
|
||||
pub const StringTable = struct {
|
||||
map: std.HashMapUnmanaged(u32, void, StringTable.Context, std.hash_map.default_max_load_percentage),
|
||||
size: u32,
|
||||
|
||||
const Context = struct {
|
||||
slice: []const u8,
|
||||
|
|
@ -193,14 +195,10 @@ pub const StringTable = struct {
|
|||
}
|
||||
};
|
||||
|
||||
pub fn get(
|
||||
st: *StringTable,
|
||||
gpa: std.mem.Allocator,
|
||||
mf: *MappedFile,
|
||||
ni: MappedFile.Node.Index,
|
||||
key: []const u8,
|
||||
) !u32 {
|
||||
const slice_const = ni.sliceConst(mf);
|
||||
pub fn get(st: *StringTable, elf: *Elf, si: Symbol.Index, key: []const u8) !u32 {
|
||||
const gpa = elf.base.comp.gpa;
|
||||
const ni = si.node(elf);
|
||||
const slice_const = ni.sliceConst(&elf.mf);
|
||||
const gop = try st.map.getOrPutContextAdapted(
|
||||
gpa,
|
||||
key,
|
||||
|
|
@ -208,11 +206,18 @@ pub const StringTable = struct {
|
|||
.{ .slice = slice_const },
|
||||
);
|
||||
if (gop.found_existing) return gop.key_ptr.*;
|
||||
const old_size = st.size;
|
||||
const old_size, const new_size = size: switch (elf.shdrPtr(si.shndx(elf))) {
|
||||
inline else => |shdr| {
|
||||
const old_size: u32 = @intCast(elf.targetLoad(&shdr.size));
|
||||
const new_size: u32 = @intCast(old_size + key.len + 1);
|
||||
st.size = new_size;
|
||||
try ni.resize(mf, gpa, new_size);
|
||||
const slice = ni.slice(mf)[old_size..];
|
||||
elf.targetStore(&shdr.size, new_size);
|
||||
break :size .{ old_size, new_size };
|
||||
},
|
||||
};
|
||||
_, const node_size = ni.location(&elf.mf).resolve(&elf.mf);
|
||||
if (new_size > node_size)
|
||||
try ni.resize(&elf.mf, gpa, new_size +| new_size / MappedFile.growth_factor);
|
||||
const slice = ni.slice(&elf.mf)[old_size..];
|
||||
@memcpy(slice[0..key.len], key);
|
||||
slice[key.len] = 0;
|
||||
gop.key_ptr.* = old_size;
|
||||
|
|
@ -226,7 +231,7 @@ pub const Symbol = struct {
|
|||
loc_relocs: Reloc.Index,
|
||||
/// Relocations targeting this symbol
|
||||
target_relocs: Reloc.Index,
|
||||
unused: u32 = 0,
|
||||
unused: u32,
|
||||
|
||||
pub const Index = enum(u32) {
|
||||
null,
|
||||
|
|
@ -252,6 +257,52 @@ pub const Symbol = struct {
|
|||
return @enumFromInt(@intFromEnum(si) + 1);
|
||||
}
|
||||
|
||||
pub const Shndx = enum(Tag) {
|
||||
UNDEF = std.elf.SHN_UNDEF,
|
||||
LIVEPATCH = reserve(std.elf.SHN_LIVEPATCH),
|
||||
ABS = reserve(std.elf.SHN_ABS),
|
||||
COMMON = reserve(std.elf.SHN_COMMON),
|
||||
_,
|
||||
|
||||
pub const Tag = u32;
|
||||
|
||||
pub const LORESERVE: Shndx = .fromSection(std.elf.SHN_LORESERVE);
|
||||
pub const HIRESERVE: Shndx = .fromSection(std.elf.SHN_HIRESERVE);
|
||||
comptime {
|
||||
assert(@intFromEnum(HIRESERVE) == std.math.maxInt(Tag));
|
||||
}
|
||||
|
||||
fn reserve(sec: std.elf.Section) Tag {
|
||||
assert(sec >= std.elf.SHN_LORESERVE and sec <= std.elf.SHN_HIRESERVE);
|
||||
return @as(Tag, std.math.maxInt(Tag) - std.elf.SHN_HIRESERVE) + sec;
|
||||
}
|
||||
|
||||
pub fn fromSection(sec: std.elf.Section) Shndx {
|
||||
return switch (sec) {
|
||||
std.elf.SHN_UNDEF...std.elf.SHN_LORESERVE - 1 => @enumFromInt(sec),
|
||||
std.elf.SHN_LORESERVE...std.elf.SHN_HIRESERVE => @enumFromInt(reserve(sec)),
|
||||
};
|
||||
}
|
||||
pub fn toSection(s: Shndx) ?std.elf.Section {
|
||||
return switch (@intFromEnum(s)) {
|
||||
std.elf.SHN_UNDEF...std.elf.SHN_LORESERVE - 1 => |sec| @intCast(sec),
|
||||
std.elf.SHN_LORESERVE...reserve(std.elf.SHN_LORESERVE) - 1 => null,
|
||||
reserve(std.elf.SHN_LORESERVE)...reserve(std.elf.SHN_HIRESERVE) => |sec| @intCast(
|
||||
sec - reserve(std.elf.SHN_LORESERVE) + std.elf.SHN_LORESERVE,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn get(s: Shndx, elf: *Elf) *Section {
|
||||
return &elf.shdrs.items[@intFromEnum(s)];
|
||||
}
|
||||
};
|
||||
pub fn shndx(si: Symbol.Index, elf: *Elf) Shndx {
|
||||
return .fromSection(switch (elf.symPtr(si)) {
|
||||
inline else => |sym| elf.targetLoad(&sym.shndx),
|
||||
});
|
||||
}
|
||||
|
||||
pub const InitOptions = struct {
|
||||
name: []const u8 = "",
|
||||
lib_name: ?[]const u8 = null,
|
||||
|
|
@ -260,48 +311,83 @@ pub const Symbol = struct {
|
|||
type: std.elf.STT,
|
||||
bind: std.elf.STB = .LOCAL,
|
||||
visibility: std.elf.STV = .DEFAULT,
|
||||
shndx: std.elf.Section = std.elf.SHN_UNDEF,
|
||||
shndx: Shndx = .UNDEF,
|
||||
};
|
||||
pub fn init(si: Symbol.Index, elf: *Elf, opts: InitOptions) !void {
|
||||
const gpa = elf.base.comp.gpa;
|
||||
const target_endian = elf.targetEndian();
|
||||
const sym_size: usize = switch (elf.identClass()) {
|
||||
.NONE, _ => unreachable,
|
||||
inline else => |class| @sizeOf(class.ElfN().Sym),
|
||||
};
|
||||
const name_strtab_entry = try elf.string(.strtab, opts.name);
|
||||
try elf.si.symtab.node(elf).resize(&elf.mf, gpa, sym_size * elf.symtab.items.len);
|
||||
switch (elf.shdrPtr(elf.si.symtab.shndx(elf))) {
|
||||
inline else => |shdr| {
|
||||
const old_size = elf.targetLoad(&shdr.size);
|
||||
const ent_size = elf.targetLoad(&shdr.entsize);
|
||||
const new_size = ent_size * elf.symtab.items.len;
|
||||
if (new_size > old_size) {
|
||||
elf.targetStore(&shdr.size, @intCast(new_size));
|
||||
const symtab_ni = elf.si.symtab.node(elf);
|
||||
_, const node_size = symtab_ni.location(&elf.mf).resolve(&elf.mf);
|
||||
if (new_size > node_size) try symtab_ni.resize(
|
||||
&elf.mf,
|
||||
gpa,
|
||||
new_size +| new_size / MappedFile.growth_factor,
|
||||
);
|
||||
}
|
||||
},
|
||||
}
|
||||
switch (elf.symPtr(si)) {
|
||||
inline else => |sym, class| {
|
||||
const Sym = class.ElfN().Sym;
|
||||
sym.* = .{
|
||||
.name = name_strtab_entry,
|
||||
.value = @intCast(opts.value),
|
||||
.size = @intCast(opts.size),
|
||||
.info = .{ .type = opts.type, .bind = opts.bind },
|
||||
.other = .{ .visibility = opts.visibility },
|
||||
.shndx = opts.shndx,
|
||||
.shndx = opts.shndx.toSection().?,
|
||||
};
|
||||
if (target_endian != native_endian) std.mem.byteSwapAllFields(class.ElfN().Sym, sym);
|
||||
if (target_endian != native_endian) std.mem.byteSwapAllFields(Sym, sym);
|
||||
},
|
||||
}
|
||||
switch (elf.shdrPtr(elf.si.symtab.shndx(elf))) {
|
||||
inline else => |shdr| elf.targetStore(&shdr.info, @max(
|
||||
elf.targetLoad(&shdr.info),
|
||||
@intFromEnum(si) + 1,
|
||||
)),
|
||||
}
|
||||
if (opts.bind == .LOCAL or elf.si.dynsym == .null) return;
|
||||
const dsi = elf.dynsym.items.len;
|
||||
try elf.dynsym.append(gpa, si);
|
||||
const dynsym_ni = elf.si.dynsym.node(elf);
|
||||
const name_dynstr_entry = try elf.string(.dynstr, opts.name);
|
||||
try dynsym_ni.resize(&elf.mf, gpa, sym_size * elf.dynsym.items.len);
|
||||
switch (elf.shdrPtr(elf.si.dynsym.shndx(elf))) {
|
||||
inline else => |shdr| {
|
||||
const old_size = elf.targetLoad(&shdr.size);
|
||||
const ent_size = elf.targetLoad(&shdr.entsize);
|
||||
const new_size = ent_size * elf.dynsym.items.len;
|
||||
if (new_size > old_size) {
|
||||
elf.targetStore(&shdr.size, @intCast(new_size));
|
||||
const dynsym_ni = elf.si.dynsym.node(elf);
|
||||
_, const node_size = dynsym_ni.location(&elf.mf).resolve(&elf.mf);
|
||||
if (new_size > node_size) try dynsym_ni.resize(
|
||||
&elf.mf,
|
||||
gpa,
|
||||
new_size +| new_size / MappedFile.growth_factor,
|
||||
);
|
||||
}
|
||||
},
|
||||
}
|
||||
switch (elf.dynsymSlice()) {
|
||||
inline else => |dynsym, class| {
|
||||
const dsym = &dynsym[dsi];
|
||||
dsym.* = .{
|
||||
inline else => |dynsyms, class| {
|
||||
const Sym = class.ElfN().Sym;
|
||||
const dynsym = &dynsyms[dsi];
|
||||
dynsym.* = .{
|
||||
.name = name_dynstr_entry,
|
||||
.value = @intCast(opts.value),
|
||||
.size = @intCast(opts.size),
|
||||
.info = .{ .type = opts.type, .bind = opts.bind },
|
||||
.other = .{ .visibility = opts.visibility },
|
||||
.shndx = opts.shndx,
|
||||
.shndx = opts.shndx.toSection().?,
|
||||
};
|
||||
if (target_endian != native_endian) std.mem.byteSwapAllFields(class.ElfN().Sym, dsym);
|
||||
if (target_endian != native_endian) std.mem.byteSwapAllFields(Sym, dynsym);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -321,6 +407,7 @@ pub const Symbol = struct {
|
|||
}
|
||||
|
||||
pub fn applyLocationRelocs(si: Symbol.Index, elf: *Elf) void {
|
||||
if (elf.ehdrField(.type) == .REL) return;
|
||||
switch (si.get(elf).loc_relocs) {
|
||||
.none => {},
|
||||
else => |loc_relocs| for (elf.relocs.items[@intFromEnum(loc_relocs)..]) |*reloc| {
|
||||
|
|
@ -331,6 +418,7 @@ pub const Symbol = struct {
|
|||
}
|
||||
|
||||
pub fn applyTargetRelocs(si: Symbol.Index, elf: *Elf) void {
|
||||
if (elf.ehdrField(.type) == .REL) return;
|
||||
var ri = si.get(elf).target_relocs;
|
||||
while (ri != .none) {
|
||||
const reloc = ri.get(elf);
|
||||
|
|
@ -374,7 +462,7 @@ pub const Reloc = extern struct {
|
|||
next: Reloc.Index,
|
||||
loc: Symbol.Index,
|
||||
target: Symbol.Index,
|
||||
unused: u32,
|
||||
rel_index: u32,
|
||||
offset: u64,
|
||||
addend: i64,
|
||||
|
||||
|
|
@ -411,6 +499,7 @@ pub const Reloc = extern struct {
|
|||
};
|
||||
|
||||
pub fn apply(reloc: *const Reloc, elf: *Elf) void {
|
||||
assert(elf.ehdrField(.type) != .REL);
|
||||
const loc_ni = reloc.loc.get(elf).ni;
|
||||
switch (loc_ni) {
|
||||
.none => return,
|
||||
|
|
@ -601,6 +690,7 @@ fn create(
|
|||
.tls = .none,
|
||||
},
|
||||
.nodes = .empty,
|
||||
.shdrs = .empty,
|
||||
.phdrs = .empty,
|
||||
.si = .{
|
||||
.dynsym = .null,
|
||||
|
|
@ -611,16 +701,13 @@ fn create(
|
|||
.symtab = .empty,
|
||||
.shstrtab = .{
|
||||
.map = .empty,
|
||||
.size = 1,
|
||||
},
|
||||
.strtab = .{
|
||||
.map = .empty,
|
||||
.size = 1,
|
||||
},
|
||||
.dynsym = .empty,
|
||||
.dynstr = .{
|
||||
.map = .empty,
|
||||
.size = 1,
|
||||
},
|
||||
.needed = .empty,
|
||||
.inputs = .empty,
|
||||
|
|
@ -650,6 +737,7 @@ pub fn deinit(elf: *Elf) void {
|
|||
const gpa = elf.base.comp.gpa;
|
||||
elf.mf.deinit(gpa);
|
||||
elf.nodes.deinit(gpa);
|
||||
elf.shdrs.deinit(gpa);
|
||||
elf.phdrs.deinit(gpa);
|
||||
elf.symtab.deinit(gpa);
|
||||
elf.shstrtab.map.deinit(gpa);
|
||||
|
|
@ -681,11 +769,10 @@ fn initHeaders(
|
|||
const comp = elf.base.comp;
|
||||
const gpa = comp.gpa;
|
||||
const have_dynamic_section = switch (@"type") {
|
||||
.NONE => unreachable,
|
||||
.NONE, .CORE, _ => unreachable,
|
||||
.REL => false,
|
||||
.EXEC => comp.config.link_mode == .dynamic,
|
||||
.DYN => true,
|
||||
.CORE, _ => unreachable,
|
||||
};
|
||||
const addr_align: std.mem.Alignment = switch (class) {
|
||||
.NONE, _ => unreachable,
|
||||
|
|
@ -693,6 +780,7 @@ fn initHeaders(
|
|||
.@"64" => .@"8",
|
||||
};
|
||||
|
||||
const shnum: u32 = 1;
|
||||
var phnum: u32 = 0;
|
||||
const phdr_phndx = phnum;
|
||||
phnum += 1;
|
||||
|
|
@ -716,16 +804,16 @@ fn initHeaders(
|
|||
} else undefined;
|
||||
|
||||
const expected_nodes_len = expected_nodes_len: switch (@"type") {
|
||||
.NONE => unreachable,
|
||||
.NONE, .CORE, _ => unreachable,
|
||||
.REL => {
|
||||
defer phnum = 0;
|
||||
break :expected_nodes_len 5 + phnum;
|
||||
},
|
||||
.EXEC, .DYN => break :expected_nodes_len 5 + phnum * 2 +
|
||||
@as(usize, 2) * @intFromBool(have_dynamic_section),
|
||||
.CORE, _ => unreachable,
|
||||
};
|
||||
try elf.nodes.ensureTotalCapacity(gpa, expected_nodes_len);
|
||||
try elf.shdrs.ensureTotalCapacity(gpa, shnum);
|
||||
try elf.phdrs.resize(gpa, phnum);
|
||||
elf.nodes.appendAssumeCapacity(.file);
|
||||
|
||||
|
|
@ -760,7 +848,7 @@ fn initHeaders(
|
|||
ehdr.phentsize = @sizeOf(ElfN.Phdr);
|
||||
ehdr.phnum = @min(phnum, std.elf.PN_XNUM);
|
||||
ehdr.shentsize = @sizeOf(ElfN.Shdr);
|
||||
ehdr.shnum = 1;
|
||||
ehdr.shnum = if (shnum < std.elf.SHN_LORESERVE) shnum else 0;
|
||||
ehdr.shstrndx = std.elf.SHN_UNDEF;
|
||||
if (elf.targetEndian() != native_endian) std.mem.byteSwapAllFields(ElfN.Ehdr, ehdr);
|
||||
},
|
||||
|
|
@ -768,7 +856,7 @@ fn initHeaders(
|
|||
|
||||
assert(elf.ni.shdr == try elf.mf.addLastChildNode(gpa, elf.ni.file, .{
|
||||
.size = elf.ehdrField(.shentsize) * elf.ehdrField(.shnum),
|
||||
.alignment = addr_align,
|
||||
.alignment = elf.mf.flags.block_size,
|
||||
.moved = true,
|
||||
.resized = true,
|
||||
}));
|
||||
|
|
@ -810,7 +898,8 @@ fn initHeaders(
|
|||
elf.phdrs.items[data_phndx] = elf.ni.data;
|
||||
|
||||
break :ph_vaddr switch (elf.ehdrField(.type)) {
|
||||
else => 0,
|
||||
.NONE, .CORE, _ => unreachable,
|
||||
.REL, .DYN => 0,
|
||||
.EXEC => switch (elf.ehdrField(.machine)) {
|
||||
.@"386" => 0x400000,
|
||||
.AARCH64, .X86_64 => 0x200000,
|
||||
|
|
@ -933,20 +1022,21 @@ fn initHeaders(
|
|||
}
|
||||
}
|
||||
|
||||
const sh_null: *ElfN.Shdr = @ptrCast(@alignCast(elf.ni.shdr.slice(&elf.mf)));
|
||||
sh_null.* = .{
|
||||
const sh_undef: *ElfN.Shdr = @ptrCast(@alignCast(elf.ni.shdr.slice(&elf.mf)));
|
||||
sh_undef.* = .{
|
||||
.name = try elf.string(.shstrtab, ""),
|
||||
.type = .NULL,
|
||||
.flags = .{ .shf = .{} },
|
||||
.addr = 0,
|
||||
.offset = 0,
|
||||
.size = 0,
|
||||
.size = if (shnum < std.elf.SHN_LORESERVE) 0 else shnum,
|
||||
.link = 0,
|
||||
.info = if (phnum >= std.elf.PN_XNUM) phnum else 0,
|
||||
.info = if (phnum < std.elf.PN_XNUM) 0 else phnum,
|
||||
.addralign = 0,
|
||||
.entsize = 0,
|
||||
};
|
||||
if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Shdr, sh_null);
|
||||
if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Shdr, sh_undef);
|
||||
elf.shdrs.appendAssumeCapacity(.{ .si = .null, .rela_si = .null });
|
||||
|
||||
try elf.symtab.ensureTotalCapacity(gpa, 1);
|
||||
elf.symtab.addOneAssumeCapacity().* = .{
|
||||
|
|
@ -960,6 +1050,7 @@ fn initHeaders(
|
|||
.size = @sizeOf(ElfN.Sym) * 1,
|
||||
.addralign = addr_align,
|
||||
.entsize = @sizeOf(ElfN.Sym),
|
||||
.node_align = elf.mf.flags.block_size,
|
||||
}));
|
||||
const symtab_null = @field(elf.symPtr(.null), @tagName(ct_class));
|
||||
symtab_null.* = .{
|
||||
|
|
@ -973,13 +1064,14 @@ fn initHeaders(
|
|||
if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Sym, symtab_null);
|
||||
|
||||
const ehdr = @field(elf.ehdrPtr(), @tagName(ct_class));
|
||||
ehdr.shstrndx = ehdr.shnum;
|
||||
elf.targetStore(&ehdr.shstrndx, ehdr.shnum);
|
||||
},
|
||||
}
|
||||
assert(elf.si.shstrtab == try elf.addSection(elf.ni.file, .{
|
||||
.type = .STRTAB,
|
||||
.addralign = elf.mf.flags.block_size,
|
||||
.size = 1,
|
||||
.entsize = 1,
|
||||
.node_align = elf.mf.flags.block_size,
|
||||
}));
|
||||
try elf.renameSection(.symtab, ".symtab");
|
||||
try elf.renameSection(.shstrtab, ".shstrtab");
|
||||
|
|
@ -989,27 +1081,28 @@ fn initHeaders(
|
|||
.name = ".strtab",
|
||||
.type = .STRTAB,
|
||||
.size = 1,
|
||||
.addralign = elf.mf.flags.block_size,
|
||||
.entsize = 1,
|
||||
.node_align = elf.mf.flags.block_size,
|
||||
}));
|
||||
try elf.linkSections(.symtab, .strtab);
|
||||
elf.si.strtab.node(elf).slice(&elf.mf)[0] = 0;
|
||||
|
||||
assert(elf.si.rodata == try elf.addSection(if (@"type" != .REL) elf.ni.rodata else elf.ni.file, .{
|
||||
assert(elf.si.rodata == try elf.addSection(elf.ni.rodata, .{
|
||||
.name = ".rodata",
|
||||
.flags = .{ .ALLOC = true },
|
||||
.addralign = elf.mf.flags.block_size,
|
||||
}));
|
||||
assert(elf.si.text == try elf.addSection(if (@"type" != .REL) elf.ni.text else elf.ni.file, .{
|
||||
assert(elf.si.text == try elf.addSection(elf.ni.text, .{
|
||||
.name = ".text",
|
||||
.flags = .{ .ALLOC = true, .EXECINSTR = true },
|
||||
.addralign = elf.mf.flags.block_size,
|
||||
}));
|
||||
assert(elf.si.data == try elf.addSection(if (@"type" != .REL) elf.ni.data else elf.ni.file, .{
|
||||
assert(elf.si.data == try elf.addSection(elf.ni.data, .{
|
||||
.name = ".data",
|
||||
.flags = .{ .WRITE = true, .ALLOC = true },
|
||||
.addralign = elf.mf.flags.block_size,
|
||||
}));
|
||||
if (@"type" != .REL) {
|
||||
if (maybe_interp) |interp| {
|
||||
const interp_ni = try elf.mf.addLastChildNode(gpa, elf.ni.rodata, .{
|
||||
.size = interp.len + 1,
|
||||
|
|
@ -1041,13 +1134,14 @@ fn initHeaders(
|
|||
switch (class) {
|
||||
.NONE, _ => unreachable,
|
||||
inline else => |ct_class| {
|
||||
const ElfN = ct_class.ElfN();
|
||||
const Sym = ct_class.ElfN().Sym;
|
||||
elf.si.dynsym = try elf.addSection(elf.ni.rodata, .{
|
||||
.name = ".dynsym",
|
||||
.type = .DYNSYM,
|
||||
.size = @sizeOf(ElfN.Sym) * 1,
|
||||
.size = @sizeOf(Sym) * 1,
|
||||
.addralign = addr_align,
|
||||
.entsize = @sizeOf(ElfN.Sym),
|
||||
.entsize = @sizeOf(Sym),
|
||||
.node_align = elf.mf.flags.block_size,
|
||||
});
|
||||
const dynsym_null = &@field(elf.dynsymSlice(), @tagName(ct_class))[0];
|
||||
dynsym_null.* = .{
|
||||
|
|
@ -1058,27 +1152,29 @@ fn initHeaders(
|
|||
.other = .{ .visibility = .DEFAULT },
|
||||
.shndx = std.elf.SHN_UNDEF,
|
||||
};
|
||||
if (elf.targetEndian() != native_endian) std.mem.byteSwapAllFields(ElfN.Sym, dynsym_null);
|
||||
if (elf.targetEndian() != native_endian) std.mem.byteSwapAllFields(
|
||||
Sym,
|
||||
dynsym_null,
|
||||
);
|
||||
},
|
||||
}
|
||||
elf.si.dynstr = try elf.addSection(elf.ni.rodata, .{
|
||||
.name = ".dynstr",
|
||||
.type = .STRTAB,
|
||||
.size = 1,
|
||||
.addralign = elf.mf.flags.block_size,
|
||||
.entsize = 1,
|
||||
.node_align = elf.mf.flags.block_size,
|
||||
});
|
||||
elf.si.dynamic = try elf.addSection(dynamic_ni, .{
|
||||
.name = ".dynamic",
|
||||
.type = .DYNAMIC,
|
||||
.flags = .{ .ALLOC = true, .WRITE = true },
|
||||
.addralign = addr_align,
|
||||
.node_align = addr_align,
|
||||
});
|
||||
try elf.linkSections(elf.si.dynamic, elf.si.dynstr);
|
||||
try elf.linkSections(elf.si.dynsym, elf.si.dynstr);
|
||||
}
|
||||
if (comp.config.any_non_single_threaded) {
|
||||
if (@"type" != .REL) {
|
||||
elf.ni.tls = try elf.mf.addLastChildNode(gpa, elf.ni.rodata, .{
|
||||
.alignment = elf.mf.flags.block_size,
|
||||
.moved = true,
|
||||
|
|
@ -1087,13 +1183,15 @@ fn initHeaders(
|
|||
elf.nodes.appendAssumeCapacity(.{ .segment = tls_phndx });
|
||||
elf.phdrs.items[tls_phndx] = elf.ni.tls;
|
||||
}
|
||||
|
||||
elf.si.tdata = try elf.addSection(if (@"type" != .REL) elf.ni.tls else elf.ni.file, .{
|
||||
} else {
|
||||
assert(maybe_interp == null);
|
||||
assert(!have_dynamic_section);
|
||||
}
|
||||
if (comp.config.any_non_single_threaded) elf.si.tdata = try elf.addSection(elf.ni.tls, .{
|
||||
.name = ".tdata",
|
||||
.flags = .{ .WRITE = true, .ALLOC = true, .TLS = true },
|
||||
.addralign = elf.mf.flags.block_size,
|
||||
});
|
||||
}
|
||||
assert(elf.nodes.len == expected_nodes_len);
|
||||
}
|
||||
|
||||
|
|
@ -1218,6 +1316,7 @@ pub const PhdrSlice = union(std.elf.CLASS) {
|
|||
@"64": []std.elf.Elf64.Phdr,
|
||||
};
|
||||
pub fn phdrSlice(elf: *Elf) PhdrSlice {
|
||||
assert(elf.ehdrField(.type) != .REL);
|
||||
const slice = elf.ni.phdr.slice(&elf.mf);
|
||||
return switch (elf.identClass()) {
|
||||
.NONE, _ => unreachable,
|
||||
|
|
@ -1246,6 +1345,17 @@ pub fn shdrSlice(elf: *Elf) ShdrSlice {
|
|||
};
|
||||
}
|
||||
|
||||
pub const ShdrPtr = union(std.elf.CLASS) {
|
||||
NONE: noreturn,
|
||||
@"32": *std.elf.Elf32.Shdr,
|
||||
@"64": *std.elf.Elf64.Shdr,
|
||||
};
|
||||
pub fn shdrPtr(elf: *Elf, shndx: Symbol.Index.Shndx) ShdrPtr {
|
||||
return switch (elf.shdrSlice()) {
|
||||
inline else => |shdrs, class| @unionInit(ShdrPtr, @tagName(class), &shdrs[@intFromEnum(shndx)]),
|
||||
};
|
||||
}
|
||||
|
||||
pub const SymtabSlice = union(std.elf.CLASS) {
|
||||
NONE: noreturn,
|
||||
@"32": []std.elf.Elf32.Sym,
|
||||
|
|
@ -1258,7 +1368,11 @@ pub fn symtabSlice(elf: *Elf) SymtabSlice {
|
|||
inline else => |class| @unionInit(
|
||||
SymtabSlice,
|
||||
@tagName(class),
|
||||
@ptrCast(@alignCast(slice)),
|
||||
@ptrCast(@alignCast(slice[0..std.mem.alignBackwardAnyAlign(
|
||||
usize,
|
||||
slice.len,
|
||||
@sizeOf(class.ElfN().Sym),
|
||||
)])),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
|
@ -1270,7 +1384,7 @@ pub const SymPtr = union(std.elf.CLASS) {
|
|||
};
|
||||
pub fn symPtr(elf: *Elf, si: Symbol.Index) SymPtr {
|
||||
return switch (elf.symtabSlice()) {
|
||||
inline else => |sym, class| @unionInit(SymPtr, @tagName(class), &sym[@intFromEnum(si)]),
|
||||
inline else => |syms, class| @unionInit(SymPtr, @tagName(class), &syms[@intFromEnum(si)]),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -1560,7 +1674,7 @@ fn loadObject(
|
|||
.si = try elf.initSymbolAssumeCapacity(.{
|
||||
.name = std.fs.path.stem(member orelse path.sub_path),
|
||||
.type = .FILE,
|
||||
.shndx = std.elf.SHN_ABS,
|
||||
.shndx = .ABS,
|
||||
}),
|
||||
};
|
||||
const target_endian = elf.targetEndian();
|
||||
|
|
@ -1626,7 +1740,7 @@ fn loadObject(
|
|||
});
|
||||
section.si = try elf.initSymbolAssumeCapacity(.{
|
||||
.type = .SECTION,
|
||||
.shndx = elf.targetLoad(&@field(elf.symPtr(parent_si), @tagName(class)).shndx),
|
||||
.shndx = parent_si.shndx(elf),
|
||||
});
|
||||
section.si.get(elf).ni = ni;
|
||||
elf.input_sections.addOneAssumeCapacity().* = .{
|
||||
|
|
@ -1698,9 +1812,7 @@ fn loadObject(
|
|||
.type = input_sym.info.type,
|
||||
.bind = input_sym.info.bind,
|
||||
.visibility = input_sym.other.visibility,
|
||||
.shndx = elf.targetLoad(switch (elf.symPtr(parent_si)) {
|
||||
inline else => |parent_sym| &parent_sym.shndx,
|
||||
}),
|
||||
.shndx = parent_si.shndx(elf),
|
||||
});
|
||||
si.get(elf).ni = parent_si.get(elf).ni;
|
||||
switch (input_sym.info.bind) {
|
||||
|
|
@ -1755,7 +1867,7 @@ fn loadObject(
|
|||
"relocation section size (0x{x}) is not a multiple of entsize (0x{x})",
|
||||
.{ rels.shdr.size, rels.shdr.entsize },
|
||||
);
|
||||
try elf.relocs.ensureUnusedCapacity(gpa, relnum);
|
||||
try elf.ensureUnusedRelocCapacity(loc_sec.si, relnum);
|
||||
try fr.seekTo(fl.offset + rels.shdr.offset);
|
||||
for (0..relnum) |_| {
|
||||
const rel = try r.peekStruct(Rel, target_endian);
|
||||
|
|
@ -1832,13 +1944,13 @@ fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *std.Io.File.Reader) !void
|
|||
var soname: ?ElfN.Addr = null;
|
||||
try fr.seekTo(dynamic_ph.offset);
|
||||
for (0..dynnum) |_| {
|
||||
const key = try r.takeInt(ElfN.Addr, target_endian);
|
||||
const value = try r.takeInt(ElfN.Addr, target_endian);
|
||||
switch (key) {
|
||||
const tag = try r.takeInt(ElfN.Addr, target_endian);
|
||||
const val = try r.takeInt(ElfN.Addr, target_endian);
|
||||
switch (tag) {
|
||||
else => {},
|
||||
std.elf.DT_STRTAB => strtab = value,
|
||||
std.elf.DT_STRSZ => strsz = value,
|
||||
std.elf.DT_SONAME => soname = value,
|
||||
std.elf.DT_STRTAB => strtab = val,
|
||||
std.elf.DT_STRSZ => strsz = val,
|
||||
std.elf.DT_SONAME => soname = val,
|
||||
}
|
||||
}
|
||||
if (strtab == null or soname == null)
|
||||
|
|
@ -1883,11 +1995,7 @@ fn prelinkInner(elf: *Elf) !void {
|
|||
std.fs.path.stem(elf.base.emit.sub_path),
|
||||
});
|
||||
defer gpa.free(zcu_name);
|
||||
const si = try elf.initSymbolAssumeCapacity(.{
|
||||
.name = zcu_name,
|
||||
.type = .FILE,
|
||||
.shndx = std.elf.SHN_ABS,
|
||||
});
|
||||
const si = try elf.initSymbolAssumeCapacity(.{ .name = zcu_name, .type = .FILE, .shndx = .ABS });
|
||||
elf.inputs.addOneAssumeCapacity().* = .{
|
||||
.path = elf.base.emit,
|
||||
.member = null,
|
||||
|
|
@ -1989,9 +2097,12 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {
|
|||
name: []const u8 = "",
|
||||
type: std.elf.SHT = .NULL,
|
||||
flags: std.elf.SHF = .{},
|
||||
size: std.elf.Word = 0,
|
||||
size: std.elf.Xword = 0,
|
||||
link: std.elf.Word = 0,
|
||||
info: std.elf.Word = 0,
|
||||
addralign: std.mem.Alignment = .@"1",
|
||||
entsize: std.elf.Word = 0,
|
||||
node_align: std.mem.Alignment = .@"1",
|
||||
}) !Symbol.Index {
|
||||
switch (opts.type) {
|
||||
.NULL => assert(opts.size == 0),
|
||||
|
|
@ -2000,50 +2111,71 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {
|
|||
}
|
||||
const gpa = elf.base.comp.gpa;
|
||||
try elf.nodes.ensureUnusedCapacity(gpa, 1);
|
||||
try elf.shdrs.ensureUnusedCapacity(gpa, 1);
|
||||
try elf.symtab.ensureUnusedCapacity(gpa, 1);
|
||||
|
||||
const shstrtab_entry = try elf.string(.shstrtab, opts.name);
|
||||
const shndx, const shdr_size = shndx: switch (elf.ehdrPtr()) {
|
||||
inline else => |ehdr| {
|
||||
const shndx = elf.targetLoad(&ehdr.shnum);
|
||||
const shndx: Symbol.Index.Shndx, const new_shdr_size = shndx: switch (elf.ehdrPtr()) {
|
||||
inline else => |ehdr, class| {
|
||||
const shndx, const shnum = alloc_shndx: switch (elf.targetLoad(&ehdr.shnum)) {
|
||||
1...std.elf.SHN_LORESERVE - 2 => |shndx| {
|
||||
const shnum = shndx + 1;
|
||||
elf.targetStore(&ehdr.shnum, shnum);
|
||||
break :shndx .{ shndx, elf.targetLoad(&ehdr.shentsize) * shnum };
|
||||
break :alloc_shndx .{ shndx, shnum };
|
||||
},
|
||||
std.elf.SHN_LORESERVE - 1 => |shndx| {
|
||||
const shnum = shndx + 1;
|
||||
elf.targetStore(&ehdr.shnum, 0);
|
||||
elf.targetStore(&@field(elf.shdrPtr(.UNDEF), @tagName(class)).size, shnum);
|
||||
break :alloc_shndx .{ shndx, shnum };
|
||||
},
|
||||
std.elf.SHN_LORESERVE...std.elf.SHN_HIRESERVE => unreachable,
|
||||
0 => {
|
||||
const shnum_ptr = &@field(elf.shdrPtr(.UNDEF), @tagName(class)).size;
|
||||
const shndx: u32 = @intCast(elf.targetLoad(shnum_ptr));
|
||||
const shnum = shndx + 1;
|
||||
elf.targetStore(shnum_ptr, shnum);
|
||||
break :alloc_shndx .{ shndx, shnum };
|
||||
},
|
||||
};
|
||||
try elf.ni.shdr.resize(&elf.mf, gpa, shdr_size);
|
||||
const ni = try elf.mf.addLastChildNode(gpa, segment_ni, .{
|
||||
.alignment = opts.addralign,
|
||||
assert(shndx < @intFromEnum(Symbol.Index.Shndx.LORESERVE));
|
||||
break :shndx .{ @enumFromInt(shndx), elf.targetLoad(&ehdr.shentsize) * shnum };
|
||||
},
|
||||
};
|
||||
_, const shdr_node_size = elf.ni.shdr.location(&elf.mf).resolve(&elf.mf);
|
||||
if (new_shdr_size > shdr_node_size)
|
||||
try elf.ni.shdr.resize(&elf.mf, gpa, new_shdr_size +| new_shdr_size / MappedFile.growth_factor);
|
||||
const ni = try elf.mf.addLastChildNode(gpa, switch (elf.ehdrField(.type)) {
|
||||
.NONE, .CORE, _ => unreachable,
|
||||
.REL => elf.ni.file,
|
||||
.EXEC, .DYN => segment_ni,
|
||||
}, .{
|
||||
.alignment = opts.addralign.max(opts.node_align),
|
||||
.size = opts.size,
|
||||
.resized = opts.size > 0,
|
||||
});
|
||||
const si = elf.addSymbolAssumeCapacity();
|
||||
elf.nodes.appendAssumeCapacity(.{ .section = si });
|
||||
elf.shdrs.appendAssumeCapacity(.{ .si = si, .rela_si = .null });
|
||||
si.get(elf).ni = ni;
|
||||
const addr = elf.computeNodeVAddr(ni);
|
||||
const offset = ni.fileLocation(&elf.mf, false).offset;
|
||||
try si.init(elf, .{
|
||||
.value = addr,
|
||||
.size = opts.size,
|
||||
.type = .SECTION,
|
||||
.shndx = shndx,
|
||||
});
|
||||
switch (elf.shdrSlice()) {
|
||||
inline else => |shdr| {
|
||||
const sh = &shdr[shndx];
|
||||
sh.* = .{
|
||||
try si.init(elf, .{ .value = addr, .type = .SECTION, .shndx = shndx });
|
||||
switch (elf.shdrPtr(shndx)) {
|
||||
inline else => |shdr, class| {
|
||||
shdr.* = .{
|
||||
.name = shstrtab_entry,
|
||||
.type = opts.type,
|
||||
.flags = .{ .shf = opts.flags },
|
||||
.addr = @intCast(addr),
|
||||
.offset = @intCast(offset),
|
||||
.size = opts.size,
|
||||
.link = 0,
|
||||
.info = 0,
|
||||
.size = @intCast(opts.size),
|
||||
.link = opts.link,
|
||||
.info = opts.info,
|
||||
.addralign = @intCast(opts.addralign.toByteUnits()),
|
||||
.entsize = opts.entsize,
|
||||
};
|
||||
if (elf.targetEndian() != native_endian) std.mem.byteSwapAllFields(@TypeOf(sh.*), sh);
|
||||
if (elf.targetEndian() != native_endian) std.mem.byteSwapAllFields(class.ElfN().Shdr, shdr);
|
||||
},
|
||||
}
|
||||
return si;
|
||||
|
|
@ -2051,39 +2183,27 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {
|
|||
|
||||
fn renameSection(elf: *Elf, si: Symbol.Index, name: []const u8) !void {
|
||||
const shstrtab_entry = try elf.string(.shstrtab, name);
|
||||
switch (elf.shdrSlice()) {
|
||||
inline else => |shdr, class| elf.targetStore(
|
||||
&shdr[elf.targetLoad(&@field(elf.symPtr(si), @tagName(class)).shndx)].name,
|
||||
shstrtab_entry,
|
||||
),
|
||||
switch (elf.shdrPtr(si.shndx(elf))) {
|
||||
inline else => |shdr| elf.targetStore(&shdr.name, shstrtab_entry),
|
||||
}
|
||||
}
|
||||
|
||||
fn linkSections(elf: *Elf, si: Symbol.Index, link_si: Symbol.Index) !void {
|
||||
switch (elf.shdrSlice()) {
|
||||
inline else => |shdr, class| shdr[
|
||||
elf.targetLoad(&@field(elf.symPtr(si), @tagName(class)).shndx)
|
||||
].link = @field(elf.symPtr(link_si), @tagName(class)).shndx,
|
||||
switch (elf.shdrPtr(si.shndx(elf))) {
|
||||
inline else => |shdr| elf.targetStore(&shdr.link, @intFromEnum(link_si.shndx(elf))),
|
||||
}
|
||||
}
|
||||
|
||||
fn sectionName(elf: *Elf, si: Symbol.Index) [:0]const u8 {
|
||||
const name = elf.si.shstrtab.node(elf).slice(&elf.mf)[switch (elf.shdrSlice()) {
|
||||
inline else => |shndx, class| elf.targetLoad(
|
||||
&shndx[elf.targetLoad(&@field(elf.symPtr(si), @tagName(class)).shndx)].name,
|
||||
),
|
||||
const name = elf.si.shstrtab.node(elf).slice(&elf.mf)[switch (elf.shdrPtr(si.shndx(elf))) {
|
||||
inline else => |shdr| elf.targetLoad(&shdr.name),
|
||||
}..];
|
||||
return name[0..std.mem.indexOfScalar(u8, name, 0).? :0];
|
||||
}
|
||||
|
||||
fn string(elf: *Elf, comptime section: enum { shstrtab, strtab, dynstr }, key: []const u8) !u32 {
|
||||
if (key.len == 0) return 0;
|
||||
return @field(elf, @tagName(section)).get(
|
||||
elf.base.comp.gpa,
|
||||
&elf.mf,
|
||||
@field(elf.si, @tagName(section)).node(elf),
|
||||
key,
|
||||
);
|
||||
return @field(elf, @tagName(section)).get(elf, @field(elf.si, @tagName(section)), key);
|
||||
}
|
||||
|
||||
pub fn addReloc(
|
||||
|
|
@ -2094,9 +2214,51 @@ pub fn addReloc(
|
|||
addend: i64,
|
||||
@"type": Reloc.Type,
|
||||
) !void {
|
||||
try elf.relocs.ensureUnusedCapacity(elf.base.comp.gpa, 1);
|
||||
try elf.ensureUnusedRelocCapacity(loc_si, 1);
|
||||
elf.addRelocAssumeCapacity(loc_si, offset, target_si, addend, @"type");
|
||||
}
|
||||
pub fn ensureUnusedRelocCapacity(elf: *Elf, loc_si: Symbol.Index, len: usize) !void {
|
||||
if (len == 0) return;
|
||||
const gpa = elf.base.comp.gpa;
|
||||
|
||||
try elf.relocs.ensureUnusedCapacity(gpa, len);
|
||||
if (elf.ehdrField(.type) != .REL) return;
|
||||
|
||||
const shndx = loc_si.shndx(elf);
|
||||
const sh = shndx.get(elf);
|
||||
if (sh.rela_si == .null) {
|
||||
var stack = std.heap.stackFallback(32, gpa);
|
||||
const allocator = stack.get();
|
||||
|
||||
const rela_name = try std.fmt.allocPrint(allocator, ".rela{s}", .{elf.sectionName(sh.si)});
|
||||
defer allocator.free(rela_name);
|
||||
|
||||
const class = elf.identClass();
|
||||
sh.rela_si = try elf.addSection(.none, .{
|
||||
.name = rela_name,
|
||||
.type = .RELA,
|
||||
.link = @intFromEnum(elf.si.symtab.shndx(elf)),
|
||||
.info = @intFromEnum(shndx),
|
||||
.addralign = switch (class) {
|
||||
.NONE, _ => unreachable,
|
||||
.@"32" => .@"4",
|
||||
.@"64" => .@"8",
|
||||
},
|
||||
.entsize = switch (class) {
|
||||
.NONE, _ => unreachable,
|
||||
inline else => |ct_class| @sizeOf(ct_class.ElfN().Rela),
|
||||
},
|
||||
.node_align = elf.mf.flags.block_size,
|
||||
});
|
||||
}
|
||||
const rela_ni = sh.rela_si.node(elf);
|
||||
_, const rela_node_size = rela_ni.location(&elf.mf).resolve(&elf.mf);
|
||||
const rela_size = switch (elf.shdrPtr(sh.rela_si.shndx(elf))) {
|
||||
inline else => |shdr| elf.targetLoad(&shdr.size) + elf.targetLoad(&shdr.entsize) * len,
|
||||
};
|
||||
if (rela_size > rela_node_size)
|
||||
try rela_ni.resize(&elf.mf, gpa, rela_size +| rela_size / MappedFile.growth_factor);
|
||||
}
|
||||
pub fn addRelocAssumeCapacity(
|
||||
elf: *Elf,
|
||||
loc_si: Symbol.Index,
|
||||
|
|
@ -2113,7 +2275,40 @@ pub fn addRelocAssumeCapacity(
|
|||
.next = target.target_relocs,
|
||||
.loc = loc_si,
|
||||
.target = target_si,
|
||||
.unused = 0,
|
||||
.rel_index = switch (elf.ehdrField(.type)) {
|
||||
.NONE, .CORE, _ => unreachable,
|
||||
.REL => rel_index: {
|
||||
const rela_si = loc_si.shndx(elf).get(elf).rela_si;
|
||||
switch (elf.shdrPtr(rela_si.shndx(elf))) {
|
||||
inline else => |shdr, class| {
|
||||
const Rela = class.ElfN().Rela;
|
||||
const old_size = elf.targetLoad(&shdr.size);
|
||||
const ent_size = elf.targetLoad(&shdr.entsize);
|
||||
const new_size = old_size + ent_size;
|
||||
elf.targetStore(&shdr.size, @intCast(new_size));
|
||||
const rela: *Rela = @ptrCast(@alignCast(
|
||||
rela_si.node(elf).slice(&elf.mf)[@intCast(old_size)..@intCast(new_size)],
|
||||
));
|
||||
rela.* = .{
|
||||
.offset = @intCast(offset),
|
||||
.info = .{
|
||||
.type = switch (elf.ehdrField(.machine)) {
|
||||
else => |machine| @panic(@tagName(machine)),
|
||||
inline .X86_64, .AARCH64, .RISCV, .PPC64 => |machine| @intCast(
|
||||
@intFromEnum(@field(@"type", @tagName(machine))),
|
||||
),
|
||||
},
|
||||
.sym = @intCast(@intFromEnum(target_si)),
|
||||
},
|
||||
.addend = @intCast(addend),
|
||||
};
|
||||
if (elf.targetEndian() != native_endian) std.mem.byteSwapAllFields(Rela, rela);
|
||||
break :rel_index @intCast(@divExact(old_size, ent_size));
|
||||
},
|
||||
}
|
||||
},
|
||||
.EXEC, .DYN => 0,
|
||||
},
|
||||
.offset = offset,
|
||||
.addend = addend,
|
||||
};
|
||||
|
|
@ -2479,7 +2674,8 @@ fn flushUav(
|
|||
switch (sym.ni) {
|
||||
.none => {
|
||||
try elf.nodes.ensureUnusedCapacity(gpa, 1);
|
||||
const ni = try elf.mf.addLastChildNode(gpa, elf.si.data.node(elf), .{
|
||||
const sec_si = elf.si.data;
|
||||
const ni = try elf.mf.addLastChildNode(gpa, sec_si.node(elf), .{
|
||||
.alignment = uav_align.toStdMem(),
|
||||
.moved = true,
|
||||
});
|
||||
|
|
@ -2487,7 +2683,7 @@ fn flushUav(
|
|||
sym.ni = ni;
|
||||
switch (elf.symPtr(si)) {
|
||||
inline else => |sym_ptr, class| sym_ptr.shndx =
|
||||
@field(elf.symPtr(.data), @tagName(class)).shndx,
|
||||
@field(elf.symPtr(sec_si), @tagName(class)).shndx,
|
||||
}
|
||||
},
|
||||
else => {
|
||||
|
|
@ -2611,11 +2807,10 @@ fn flushFileOffset(elf: *Elf, ni: MappedFile.Node.Index) !void {
|
|||
var child_it = ni.children(&elf.mf);
|
||||
while (child_it.next()) |child_ni| try elf.flushFileOffset(child_ni);
|
||||
},
|
||||
.section => |si| switch (elf.shdrSlice()) {
|
||||
inline else => |shdr, class| elf.targetStore(
|
||||
&shdr[elf.targetLoad(&@field(elf.symPtr(si), @tagName(class)).shndx)].offset,
|
||||
@intCast(ni.fileLocation(&elf.mf, false).offset),
|
||||
),
|
||||
.section => |si| switch (elf.shdrPtr(si.shndx(elf))) {
|
||||
inline else => |shdr| elf.targetStore(&shdr.offset, @intCast(
|
||||
ni.fileLocation(&elf.mf, false).offset,
|
||||
)),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -2644,14 +2839,12 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void {
|
|||
.section => |si| {
|
||||
try elf.flushFileOffset(ni);
|
||||
const addr = elf.computeNodeVAddr(ni);
|
||||
switch (elf.shdrSlice()) {
|
||||
switch (elf.shdrPtr(si.shndx(elf))) {
|
||||
inline else => |shdr, class| {
|
||||
const sym = @field(elf.symPtr(si), @tagName(class));
|
||||
const sh = &shdr[elf.targetLoad(&sym.shndx)];
|
||||
const flags = elf.targetLoad(&sh.flags).shf;
|
||||
const flags = elf.targetLoad(&shdr.flags).shf;
|
||||
if (flags.ALLOC) {
|
||||
elf.targetStore(&sh.addr, @intCast(addr));
|
||||
sym.value = sh.addr;
|
||||
elf.targetStore(&shdr.addr, @intCast(addr));
|
||||
@field(elf.symPtr(si), @tagName(class)).value = shdr.addr;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
@ -2732,20 +2925,15 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) !void {
|
|||
}
|
||||
},
|
||||
},
|
||||
.section => |si| switch (elf.symPtr(si)) {
|
||||
inline else => |sym, class| {
|
||||
const sh = &@field(elf.shdrSlice(), @tagName(class))[elf.targetLoad(&sym.shndx)];
|
||||
elf.targetStore(&sh.size, @intCast(size));
|
||||
switch (elf.targetLoad(&sh.type)) {
|
||||
.section => |si| switch (elf.shdrPtr(si.shndx(elf))) {
|
||||
inline else => |shdr| {
|
||||
switch (elf.targetLoad(&shdr.type)) {
|
||||
else => unreachable,
|
||||
.NULL => if (size > 0) elf.targetStore(&sh.type, .PROGBITS),
|
||||
.PROGBITS => if (size == 0) elf.targetStore(&sh.type, .NULL),
|
||||
.SYMTAB, .DYNSYM => elf.targetStore(
|
||||
&sh.info,
|
||||
@intCast(@divExact(size, elf.targetLoad(&sh.entsize))),
|
||||
),
|
||||
.STRTAB, .DYNAMIC => {},
|
||||
.NULL => if (size > 0) elf.targetStore(&shdr.type, .PROGBITS),
|
||||
.PROGBITS => if (size == 0) elf.targetStore(&shdr.type, .NULL),
|
||||
.SYMTAB, .STRTAB, .RELA, .DYNAMIC, .REL, .DYNSYM => return,
|
||||
}
|
||||
elf.targetStore(&shdr.size, @intCast(size));
|
||||
},
|
||||
},
|
||||
.input_section => {},
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue