mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 05:20:34 +00:00
elf: resolve and write objects to file
This commit is contained in:
parent
652ebf3b6a
commit
ae74a36af0
@ -45,7 +45,7 @@ pub fn emitMir(emit: *Emit) Error!void {
|
||||
// Add relocation to the decl.
|
||||
const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?;
|
||||
try atom_ptr.addReloc(elf_file, .{
|
||||
.r_offset = end_offset,
|
||||
.r_offset = end_offset - 4,
|
||||
.r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | std.elf.R_X86_64_PLT32,
|
||||
.r_addend = -4,
|
||||
});
|
||||
|
||||
@ -1072,6 +1072,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
|
||||
try self.base.file.?.pwriteAll(code, file_offset);
|
||||
}
|
||||
}
|
||||
try self.writeObjects();
|
||||
|
||||
try self.updateSymtabSize();
|
||||
try self.writeSymtab();
|
||||
@ -1414,6 +1415,13 @@ fn allocateObjects(self: *Elf) !void {
|
||||
try atom_ptr.allocate(self);
|
||||
}
|
||||
|
||||
for (object.locals()) |local_index| {
|
||||
const local = self.symbol(local_index);
|
||||
const atom_ptr = local.atom(self) orelse continue;
|
||||
if (!atom_ptr.alive) continue;
|
||||
local.value = atom_ptr.value;
|
||||
}
|
||||
|
||||
for (object.globals()) |global_index| {
|
||||
const global = self.symbol(global_index);
|
||||
if (global.file_index == index) {
|
||||
@ -1423,6 +1431,26 @@ fn allocateObjects(self: *Elf) !void {
|
||||
}
|
||||
}
|
||||
|
||||
fn writeObjects(self: *Elf) !void {
|
||||
const gpa = self.base.allocator;
|
||||
|
||||
for (self.objects.items) |index| {
|
||||
const object = self.file(index).?.object;
|
||||
for (object.atoms.items) |atom_index| {
|
||||
const atom_ptr = self.atom(atom_index) orelse continue;
|
||||
if (!atom_ptr.alive) continue;
|
||||
|
||||
const shdr = &self.shdrs.items[atom_ptr.output_section_index];
|
||||
const file_offset = shdr.sh_offset + atom_ptr.value - shdr.sh_addr;
|
||||
const code = try atom_ptr.codeInObjectUncompressAlloc(self);
|
||||
defer gpa.free(code);
|
||||
|
||||
try atom_ptr.resolveRelocs(self, code);
|
||||
try self.base.file.?.pwriteAll(code, file_offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
@ -67,12 +67,13 @@ pub fn codeInObjectUncompressAlloc(self: Atom, elf_file: *Elf) ![]u8 {
|
||||
switch (chdr.ch_type) {
|
||||
.ZLIB => {
|
||||
var stream = std.io.fixedBufferStream(data[@sizeOf(elf.Elf64_Chdr)..]);
|
||||
var zlib_stream = try std.compress.zlib.decompressStream(gpa, stream.reader());
|
||||
var zlib_stream = std.compress.zlib.decompressStream(gpa, stream.reader()) catch
|
||||
return error.InputOutput;
|
||||
defer zlib_stream.deinit();
|
||||
const decomp = try gpa.alloc(u8, chdr.ch_size);
|
||||
const nread = try zlib_stream.reader().readAll(decomp);
|
||||
const nread = zlib_stream.reader().readAll(decomp) catch return error.InputOutput;
|
||||
if (nread != decomp.len) {
|
||||
return error.Io;
|
||||
return error.InputOutput;
|
||||
}
|
||||
return decomp;
|
||||
},
|
||||
@ -366,6 +367,7 @@ pub fn scanRelocs(self: Atom, elf_file: *Elf) !void {
|
||||
pub fn resolveRelocs(self: Atom, elf_file: *Elf, code: []u8) !void {
|
||||
relocs_log.debug("0x{x}: {s}", .{ self.value, self.name(elf_file) });
|
||||
|
||||
const file_ptr = elf_file.file(self.file_index).?;
|
||||
var stream = std.io.fixedBufferStream(code);
|
||||
const cwriter = stream.writer();
|
||||
|
||||
@ -373,7 +375,11 @@ pub fn resolveRelocs(self: Atom, elf_file: *Elf, code: []u8) !void {
|
||||
const r_type = rel.r_type();
|
||||
if (r_type == elf.R_X86_64_NONE) continue;
|
||||
|
||||
const target = elf_file.symbol(rel.r_sym());
|
||||
const target = switch (file_ptr) {
|
||||
.zig_module => elf_file.symbol(rel.r_sym()),
|
||||
.object => |x| elf_file.symbol(x.symbols.items[rel.r_sym()]),
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
// We will use equation format to resolve relocations:
|
||||
// https://intezer.com/blog/malware-analysis/executable-and-linkable-format-101-part-3-relocations/
|
||||
@ -414,9 +420,17 @@ pub fn resolveRelocs(self: Atom, elf_file: *Elf, code: []u8) !void {
|
||||
|
||||
switch (rel.r_type()) {
|
||||
elf.R_X86_64_NONE => unreachable,
|
||||
|
||||
elf.R_X86_64_64 => try cwriter.writeIntLittle(i64, S + A),
|
||||
elf.R_X86_64_PLT32 => try cwriter.writeIntLittle(i32, @as(i32, @intCast(S + A - P))),
|
||||
else => @panic("TODO"),
|
||||
|
||||
elf.R_X86_64_PLT32,
|
||||
elf.R_X86_64_PC32,
|
||||
=> try cwriter.writeIntLittle(i32, @as(i32, @intCast(S + A - P))),
|
||||
|
||||
else => {
|
||||
log.err("TODO: unhandled relocation type {}", .{fmtRelocType(rel.r_type())});
|
||||
@panic("TODO unhandled relocation type");
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -270,6 +270,10 @@ fn initSymtab(self: *Object, elf_file: *Elf) !void {
|
||||
sym_ptr.esym_index = @as(u32, @intCast(i));
|
||||
sym_ptr.atom_index = if (sym.st_shndx == elf.SHN_ABS) 0 else self.atoms.items[sym.st_shndx];
|
||||
sym_ptr.file_index = self.index;
|
||||
sym_ptr.output_section_index = if (sym_ptr.atom(elf_file)) |atom_ptr|
|
||||
atom_ptr.output_section_index
|
||||
else
|
||||
0;
|
||||
}
|
||||
|
||||
for (self.symtab[first_global..]) |sym| {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user