authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-09-07 23:21:08+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-09-07 23:21:08+02:00
loge229202cb87a895401f2813f0f12227a0d715c09
treeaa8f679dbdd4e492b71978439ee75e67fe662aa2
parent159e55dfd9b03a11f5eb1c79ec5d56cdfd6f7707

macho: store source section address of relocs in context

This is particularly relevant for x86_64 and C++ when relocating StaticInit sections containing static initializers machine code. Then, in case of SIGNED_X relocations, it is necessary to have the full image of the VM address layout of the sections in the object file as this is how the addend needs to be adjusted for non-extern relocations.

2 files changed, 18 insertions(+), 14 deletions(-)

src/link/MachO/Object.zig+6-3
......@@ -425,7 +425,8 @@ const TextBlockParser = struct {
425425 }
426426
427427 try block.parseRelocs(self.relocs, .{
428 .base_addr = start_addr,
428 .base_addr = self.section.addr,
429 .base_offset = start_addr,
429430 .allocator = context.allocator,
430431 .object = context.object,
431432 .macho_file = context.macho_file,
......@@ -583,7 +584,8 @@ pub fn parseTextBlocks(
583584 }
584585
585586 try block.parseRelocs(relocs, .{
586 .base_addr = 0,
587 .base_addr = sect.addr,
588 .base_offset = 0,
587589 .allocator = allocator,
588590 .object = self,
589591 .macho_file = macho_file,
......@@ -689,7 +691,8 @@ pub fn parseTextBlocks(
689691 }
690692
691693 try block.parseRelocs(relocs, .{
692 .base_addr = 0,
694 .base_addr = sect.addr,
695 .base_offset = 0,
693696 .allocator = allocator,
694697 .object = self,
695698 .macho_file = macho_file,
src/link/MachO/TextBlock.zig+12-11
......@@ -479,13 +479,13 @@ pub const Relocation = struct {
479479
480480 pub const Signed = struct {
481481 addend: i64,
482 correction: i4,
482 correction: u3,
483483
484484 pub fn resolve(self: Signed, args: ResolveArgs) !void {
485485 const target_addr = @intCast(i64, args.target_addr) + self.addend;
486486 const displacement = try math.cast(
487487 i32,
488 target_addr - @intCast(i64, args.source_addr) - self.correction - 4,
488 target_addr - @intCast(i64, args.source_addr + self.correction + 4),
489489 );
490490 mem.writeIntLittle(u32, args.block.code.items[args.offset..][0..4], @bitCast(u32, displacement));
491491 }
......@@ -613,6 +613,7 @@ pub fn freeListEligible(self: TextBlock, macho_file: MachO) bool {
613613
614614const RelocContext = struct {
615615 base_addr: u64 = 0,
616 base_offset: u64 = 0,
616617 allocator: *Allocator,
617618 object: *Object,
618619 macho_file: *MachO,
......@@ -620,7 +621,7 @@ const RelocContext = struct {
620621
621622fn initRelocFromObject(rel: macho.relocation_info, context: RelocContext) !Relocation {
622623 var parsed_rel = Relocation{
623 .offset = @intCast(u32, @intCast(u64, rel.r_address) - context.base_addr),
624 .offset = @intCast(u32, @intCast(u64, rel.r_address) - context.base_offset),
624625 .where = undefined,
625626 .where_index = undefined,
626627 .payload = undefined,
......@@ -684,7 +685,7 @@ fn initRelocFromObject(rel: macho.relocation_info, context: RelocContext) !Reloc
684685}
685686
686687pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: RelocContext) !void {
687 const filtered_relocs = filterRelocs(relocs, context.base_addr, context.base_addr + self.size);
688 const filtered_relocs = filterRelocs(relocs, context.base_offset, context.base_offset + self.size);
688689 var it = RelocIterator{
689690 .buffer = filtered_relocs,
690691 };
......@@ -956,9 +957,9 @@ fn parseUnsigned(
956957 mem.readIntLittle(i32, self.code.items[out.offset..][0..4]);
957958
958959 if (rel.r_extern == 0) {
959 const source_seg = context.object.load_commands.items[context.object.segment_cmd_index.?].Segment;
960 const source_sect_base_addr = source_seg.sections.items[rel.r_symbolnum - 1].addr;
961 addend -= @intCast(i64, source_sect_base_addr);
960 const seg = context.object.load_commands.items[context.object.segment_cmd_index.?].Segment;
961 const target_sect_base_addr = seg.sections.items[rel.r_symbolnum - 1].addr;
962 addend -= @intCast(i64, target_sect_base_addr);
962963 }
963964
964965 out.payload = .{
......@@ -1043,7 +1044,7 @@ fn parseSigned(self: TextBlock, rel: macho.relocation_info, out: *Relocation, co
10431044 assert(rel.r_length == 2);
10441045
10451046 const rel_type = @intToEnum(macho.reloc_type_x86_64, rel.r_type);
1046 const correction: i4 = switch (rel_type) {
1047 const correction: u3 = switch (rel_type) {
10471048 .X86_64_RELOC_SIGNED => 0,
10481049 .X86_64_RELOC_SIGNED_1 => 1,
10491050 .X86_64_RELOC_SIGNED_2 => 2,
......@@ -1053,9 +1054,9 @@ fn parseSigned(self: TextBlock, rel: macho.relocation_info, out: *Relocation, co
10531054 var addend: i64 = mem.readIntLittle(i32, self.code.items[out.offset..][0..4]) + correction;
10541055
10551056 if (rel.r_extern == 0) {
1056 const source_seg = context.object.load_commands.items[context.object.segment_cmd_index.?].Segment;
1057 const source_sect_base_addr = source_seg.sections.items[rel.r_symbolnum - 1].addr;
1058 addend = @intCast(i64, out.offset) + addend - @intCast(i64, source_sect_base_addr) + 4 + correction;
1057 const seg = context.object.load_commands.items[context.object.segment_cmd_index.?].Segment;
1058 const target_sect_base_addr = seg.sections.items[rel.r_symbolnum - 1].addr;
1059 addend += @intCast(i64, context.base_addr + out.offset + correction + 4) - @intCast(i64, target_sect_base_addr);
10591060 }
10601061
10611062 out.payload = .{