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 {...@@ -425,7 +425,8 @@ const TextBlockParser = struct {
425 }425 }
426426
427 try block.parseRelocs(self.relocs, .{427 try block.parseRelocs(self.relocs, .{
428 .base_addr = start_addr,428 .base_addr = self.section.addr,
429 .base_offset = start_addr,
429 .allocator = context.allocator,430 .allocator = context.allocator,
430 .object = context.object,431 .object = context.object,
431 .macho_file = context.macho_file,432 .macho_file = context.macho_file,
...@@ -583,7 +584,8 @@ pub fn parseTextBlocks(...@@ -583,7 +584,8 @@ pub fn parseTextBlocks(
583 }584 }
584585
585 try block.parseRelocs(relocs, .{586 try block.parseRelocs(relocs, .{
586 .base_addr = 0,587 .base_addr = sect.addr,
588 .base_offset = 0,
587 .allocator = allocator,589 .allocator = allocator,
588 .object = self,590 .object = self,
589 .macho_file = macho_file,591 .macho_file = macho_file,
...@@ -689,7 +691,8 @@ pub fn parseTextBlocks(...@@ -689,7 +691,8 @@ pub fn parseTextBlocks(
689 }691 }
690692
691 try block.parseRelocs(relocs, .{693 try block.parseRelocs(relocs, .{
692 .base_addr = 0,694 .base_addr = sect.addr,
695 .base_offset = 0,
693 .allocator = allocator,696 .allocator = allocator,
694 .object = self,697 .object = self,
695 .macho_file = macho_file,698 .macho_file = macho_file,
src/link/MachO/TextBlock.zig+12-11
...@@ -479,13 +479,13 @@ pub const Relocation = struct {...@@ -479,13 +479,13 @@ pub const Relocation = struct {
479479
480 pub const Signed = struct {480 pub const Signed = struct {
481 addend: i64,481 addend: i64,
482 correction: i4,482 correction: u3,
483483
484 pub fn resolve(self: Signed, args: ResolveArgs) !void {484 pub fn resolve(self: Signed, args: ResolveArgs) !void {
485 const target_addr = @intCast(i64, args.target_addr) + self.addend;485 const target_addr = @intCast(i64, args.target_addr) + self.addend;
486 const displacement = try math.cast(486 const displacement = try math.cast(
487 i32,487 i32,
488 target_addr - @intCast(i64, args.source_addr) - self.correction - 4,488 target_addr - @intCast(i64, args.source_addr + self.correction + 4),
489 );489 );
490 mem.writeIntLittle(u32, args.block.code.items[args.offset..][0..4], @bitCast(u32, displacement));490 mem.writeIntLittle(u32, args.block.code.items[args.offset..][0..4], @bitCast(u32, displacement));
491 }491 }
...@@ -613,6 +613,7 @@ pub fn freeListEligible(self: TextBlock, macho_file: MachO) bool {...@@ -613,6 +613,7 @@ pub fn freeListEligible(self: TextBlock, macho_file: MachO) bool {
613613
614const RelocContext = struct {614const RelocContext = struct {
615 base_addr: u64 = 0,615 base_addr: u64 = 0,
616 base_offset: u64 = 0,
616 allocator: *Allocator,617 allocator: *Allocator,
617 object: *Object,618 object: *Object,
618 macho_file: *MachO,619 macho_file: *MachO,
...@@ -620,7 +621,7 @@ const RelocContext = struct {...@@ -620,7 +621,7 @@ const RelocContext = struct {
620621
621fn initRelocFromObject(rel: macho.relocation_info, context: RelocContext) !Relocation {622fn initRelocFromObject(rel: macho.relocation_info, context: RelocContext) !Relocation {
622 var parsed_rel = Relocation{623 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),
624 .where = undefined,625 .where = undefined,
625 .where_index = undefined,626 .where_index = undefined,
626 .payload = undefined,627 .payload = undefined,
...@@ -684,7 +685,7 @@ fn initRelocFromObject(rel: macho.relocation_info, context: RelocContext) !Reloc...@@ -684,7 +685,7 @@ fn initRelocFromObject(rel: macho.relocation_info, context: RelocContext) !Reloc
684}685}
685686
686pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: RelocContext) !void {687pub 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);
688 var it = RelocIterator{689 var it = RelocIterator{
689 .buffer = filtered_relocs,690 .buffer = filtered_relocs,
690 };691 };
...@@ -956,9 +957,9 @@ fn parseUnsigned(...@@ -956,9 +957,9 @@ fn parseUnsigned(
956 mem.readIntLittle(i32, self.code.items[out.offset..][0..4]);957 mem.readIntLittle(i32, self.code.items[out.offset..][0..4]);
957958
958 if (rel.r_extern == 0) {959 if (rel.r_extern == 0) {
959 const source_seg = context.object.load_commands.items[context.object.segment_cmd_index.?].Segment;960 const 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 const target_sect_base_addr = seg.sections.items[rel.r_symbolnum - 1].addr;
961 addend -= @intCast(i64, source_sect_base_addr);962 addend -= @intCast(i64, target_sect_base_addr);
962 }963 }
963964
964 out.payload = .{965 out.payload = .{
...@@ -1043,7 +1044,7 @@ fn parseSigned(self: TextBlock, rel: macho.relocation_info, out: *Relocation, co...@@ -1043,7 +1044,7 @@ fn parseSigned(self: TextBlock, rel: macho.relocation_info, out: *Relocation, co
1043 assert(rel.r_length == 2);1044 assert(rel.r_length == 2);
10441045
1045 const rel_type = @intToEnum(macho.reloc_type_x86_64, rel.r_type);1046 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) {
1047 .X86_64_RELOC_SIGNED => 0,1048 .X86_64_RELOC_SIGNED => 0,
1048 .X86_64_RELOC_SIGNED_1 => 1,1049 .X86_64_RELOC_SIGNED_1 => 1,
1049 .X86_64_RELOC_SIGNED_2 => 2,1050 .X86_64_RELOC_SIGNED_2 => 2,
...@@ -1053,9 +1054,9 @@ fn parseSigned(self: TextBlock, rel: macho.relocation_info, out: *Relocation, co...@@ -1053,9 +1054,9 @@ fn parseSigned(self: TextBlock, rel: macho.relocation_info, out: *Relocation, co
1053 var addend: i64 = mem.readIntLittle(i32, self.code.items[out.offset..][0..4]) + correction;1054 var addend: i64 = mem.readIntLittle(i32, self.code.items[out.offset..][0..4]) + correction;
10541055
1055 if (rel.r_extern == 0) {1056 if (rel.r_extern == 0) {
1056 const source_seg = context.object.load_commands.items[context.object.segment_cmd_index.?].Segment;1057 const 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 const target_sect_base_addr = seg.sections.items[rel.r_symbolnum - 1].addr;
1058 addend = @intCast(i64, out.offset) + addend - @intCast(i64, source_sect_base_addr) + 4 + correction;1059 addend += @intCast(i64, context.base_addr + out.offset + correction + 4) - @intCast(i64, target_sect_base_addr);
1059 }1060 }
10601061
1061 out.payload = .{1062 out.payload = .{