| author | |
| committer | |
| log | ae74a36af0aa8c876b118973969aec1a10c25665 |
| tree | b9f478c3f66e11af43924f40033380cc0fa6fd0a |
| parent | 652ebf3b6a62007d37fb7fd4def393f11bb6159f |
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(); | ||
| 1075 | 1076 | ||
| 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 | } |
| 1416 | 1417 | ||
| 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 | } |
| 1425 | 1433 | ||
| 1434 | fn 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 | |||
| 1426 | fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void { | 1454 | fn 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 { |
| 366 | pub fn resolveRelocs(self: Atom, elf_file: *Elf, code: []u8) !void { | 367 | pub 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) }); |
| 368 | 369 | ||
| 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(); |
| 371 | 373 | ||
| ... | @@ -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; |
| 375 | 377 | ||
| 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 | }; | ||
| 377 | 383 | ||
| 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 { |
| 414 | 420 | ||
| 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 | } |
| 274 | 278 | ||
| 275 | for (self.symtab[first_global..]) |sym| { | 279 | for (self.symtab[first_global..]) |sym| { |