authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-09-12 19:17:57+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-09-12 19:17:57+02:00
logae74a36af0aa8c876b118973969aec1a10c25665
treeb9f478c3f66e11af43924f40033380cc0fa6fd0a
parent652ebf3b6a62007d37fb7fd4def393f11bb6159f

elf: resolve and write objects to file


4 files changed, 53 insertions(+), 7 deletions(-)

src/arch/x86_64/Emit.zig+1-1
...@@ -45,7 +45,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -45,7 +45,7 @@ pub fn emitMir(emit: *Emit) Error!void {
45 // Add relocation to the decl.45 // Add relocation to the decl.
46 const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?;46 const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?;
47 try atom_ptr.addReloc(elf_file, .{47 try atom_ptr.addReloc(elf_file, .{
48 .r_offset = end_offset,48 .r_offset = end_offset - 4,
49 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | std.elf.R_X86_64_PLT32,49 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | std.elf.R_X86_64_PLT32,
50 .r_addend = -4,50 .r_addend = -4,
51 });51 });
src/link/Elf.zig+28
...@@ -1072,6 +1072,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1072,6 +1072,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1072 try self.base.file.?.pwriteAll(code, file_offset);1072 try self.base.file.?.pwriteAll(code, file_offset);
1073 }1073 }
1074 }1074 }
1075 try self.writeObjects();
10751076
1076 try self.updateSymtabSize();1077 try self.updateSymtabSize();
1077 try self.writeSymtab();1078 try self.writeSymtab();
...@@ -1414,6 +1415,13 @@ fn allocateObjects(self: *Elf) !void {...@@ -1414,6 +1415,13 @@ fn allocateObjects(self: *Elf) !void {
1414 try atom_ptr.allocate(self);1415 try atom_ptr.allocate(self);
1415 }1416 }
14161417
1418 for (object.locals()) |local_index| {
1419 const local = self.symbol(local_index);
1420 const atom_ptr = local.atom(self) orelse continue;
1421 if (!atom_ptr.alive) continue;
1422 local.value = atom_ptr.value;
1423 }
1424
1417 for (object.globals()) |global_index| {1425 for (object.globals()) |global_index| {
1418 const global = self.symbol(global_index);1426 const global = self.symbol(global_index);
1419 if (global.file_index == index) {1427 if (global.file_index == index) {
...@@ -1423,6 +1431,26 @@ fn allocateObjects(self: *Elf) !void {...@@ -1423,6 +1431,26 @@ fn allocateObjects(self: *Elf) !void {
1423 }1431 }
1424}1432}
14251433
1434fn writeObjects(self: *Elf) !void {
1435 const gpa = self.base.allocator;
1436
1437 for (self.objects.items) |index| {
1438 const object = self.file(index).?.object;
1439 for (object.atoms.items) |atom_index| {
1440 const atom_ptr = self.atom(atom_index) orelse continue;
1441 if (!atom_ptr.alive) continue;
1442
1443 const shdr = &self.shdrs.items[atom_ptr.output_section_index];
1444 const file_offset = shdr.sh_offset + atom_ptr.value - shdr.sh_addr;
1445 const code = try atom_ptr.codeInObjectUncompressAlloc(self);
1446 defer gpa.free(code);
1447
1448 try atom_ptr.resolveRelocs(self, code);
1449 try self.base.file.?.pwriteAll(code, file_offset);
1450 }
1451 }
1452}
1453
1426fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void {1454fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void {
1427 const tracy = trace(@src());1455 const tracy = trace(@src());
1428 defer tracy.end();1456 defer tracy.end();
src/link/Elf/Atom.zig+20-6
...@@ -67,12 +67,13 @@ pub fn codeInObjectUncompressAlloc(self: Atom, elf_file: *Elf) ![]u8 {...@@ -67,12 +67,13 @@ pub fn codeInObjectUncompressAlloc(self: Atom, elf_file: *Elf) ![]u8 {
67 switch (chdr.ch_type) {67 switch (chdr.ch_type) {
68 .ZLIB => {68 .ZLIB => {
69 var stream = std.io.fixedBufferStream(data[@sizeOf(elf.Elf64_Chdr)..]);69 var stream = std.io.fixedBufferStream(data[@sizeOf(elf.Elf64_Chdr)..]);
70 var zlib_stream = try std.compress.zlib.decompressStream(gpa, stream.reader());70 var zlib_stream = std.compress.zlib.decompressStream(gpa, stream.reader()) catch
71 return error.InputOutput;
71 defer zlib_stream.deinit();72 defer zlib_stream.deinit();
72 const decomp = try gpa.alloc(u8, chdr.ch_size);73 const decomp = try gpa.alloc(u8, chdr.ch_size);
73 const nread = try zlib_stream.reader().readAll(decomp);74 const nread = zlib_stream.reader().readAll(decomp) catch return error.InputOutput;
74 if (nread != decomp.len) {75 if (nread != decomp.len) {
75 return error.Io;76 return error.InputOutput;
76 }77 }
77 return decomp;78 return decomp;
78 },79 },
...@@ -366,6 +367,7 @@ pub fn scanRelocs(self: Atom, elf_file: *Elf) !void {...@@ -366,6 +367,7 @@ pub fn scanRelocs(self: Atom, elf_file: *Elf) !void {
366pub fn resolveRelocs(self: Atom, elf_file: *Elf, code: []u8) !void {367pub fn resolveRelocs(self: Atom, elf_file: *Elf, code: []u8) !void {
367 relocs_log.debug("0x{x}: {s}", .{ self.value, self.name(elf_file) });368 relocs_log.debug("0x{x}: {s}", .{ self.value, self.name(elf_file) });
368369
370 const file_ptr = elf_file.file(self.file_index).?;
369 var stream = std.io.fixedBufferStream(code);371 var stream = std.io.fixedBufferStream(code);
370 const cwriter = stream.writer();372 const cwriter = stream.writer();
371373
...@@ -373,7 +375,11 @@ pub fn resolveRelocs(self: Atom, elf_file: *Elf, code: []u8) !void {...@@ -373,7 +375,11 @@ pub fn resolveRelocs(self: Atom, elf_file: *Elf, code: []u8) !void {
373 const r_type = rel.r_type();375 const r_type = rel.r_type();
374 if (r_type == elf.R_X86_64_NONE) continue;376 if (r_type == elf.R_X86_64_NONE) continue;
375377
376 const target = elf_file.symbol(rel.r_sym());378 const target = switch (file_ptr) {
379 .zig_module => elf_file.symbol(rel.r_sym()),
380 .object => |x| elf_file.symbol(x.symbols.items[rel.r_sym()]),
381 else => unreachable,
382 };
377383
378 // We will use equation format to resolve relocations:384 // We will use equation format to resolve relocations:
379 // https://intezer.com/blog/malware-analysis/executable-and-linkable-format-101-part-3-relocations/385 // 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 {...@@ -414,9 +420,17 @@ pub fn resolveRelocs(self: Atom, elf_file: *Elf, code: []u8) !void {
414420
415 switch (rel.r_type()) {421 switch (rel.r_type()) {
416 elf.R_X86_64_NONE => unreachable,422 elf.R_X86_64_NONE => unreachable,
423
417 elf.R_X86_64_64 => try cwriter.writeIntLittle(i64, S + A),424 elf.R_X86_64_64 => try cwriter.writeIntLittle(i64, S + A),
418 elf.R_X86_64_PLT32 => try cwriter.writeIntLittle(i32, @as(i32, @intCast(S + A - P))),425
419 else => @panic("TODO"),426 elf.R_X86_64_PLT32,
427 elf.R_X86_64_PC32,
428 => try cwriter.writeIntLittle(i32, @as(i32, @intCast(S + A - P))),
429
430 else => {
431 log.err("TODO: unhandled relocation type {}", .{fmtRelocType(rel.r_type())});
432 @panic("TODO unhandled relocation type");
433 },
420 }434 }
421 }435 }
422}436}
src/link/Elf/Object.zig+4
...@@ -270,6 +270,10 @@ fn initSymtab(self: *Object, elf_file: *Elf) !void {...@@ -270,6 +270,10 @@ fn initSymtab(self: *Object, elf_file: *Elf) !void {
270 sym_ptr.esym_index = @as(u32, @intCast(i));270 sym_ptr.esym_index = @as(u32, @intCast(i));
271 sym_ptr.atom_index = if (sym.st_shndx == elf.SHN_ABS) 0 else self.atoms.items[sym.st_shndx];271 sym_ptr.atom_index = if (sym.st_shndx == elf.SHN_ABS) 0 else self.atoms.items[sym.st_shndx];
272 sym_ptr.file_index = self.index;272 sym_ptr.file_index = self.index;
273 sym_ptr.output_section_index = if (sym_ptr.atom(elf_file)) |atom_ptr|
274 atom_ptr.output_section_index
275 else
276 0;
273 }277 }
274278
275 for (self.symtab[first_global..]) |sym| {279 for (self.symtab[first_global..]) |sym| {