| ... | @@ -214,10 +214,21 @@ pub const TextBlock = struct { | ... | @@ -214,10 +214,21 @@ pub const TextBlock = struct { |
| 214 | /// Unlike in Elf, we need to store the size of this symbol as part of | 214 | /// Unlike in Elf, we need to store the size of this symbol as part of |
| 215 | /// the TextBlock since macho.nlist_64 lacks this information. | 215 | /// the TextBlock since macho.nlist_64 lacks this information. |
| 216 | size: u64, | 216 | size: u64, |
| | 217 | /// List of RIP-relative positions in the code |
| | 218 | /// This is a table of all RIP-relative positions that will need fixups |
| | 219 | /// after codegen when linker assigns addresses to GOT entries. |
| | 220 | /// TODO handle freeing, shrinking and re-allocs |
| | 221 | rip_positions: std.ArrayListUnmanaged(RipPosition) = .{}, |
| 217 | /// Points to the previous and next neighbours | 222 | /// Points to the previous and next neighbours |
| 218 | prev: ?*TextBlock, | 223 | prev: ?*TextBlock, |
| 219 | next: ?*TextBlock, | 224 | next: ?*TextBlock, |
| 220 | | 225 | |
| | 226 | pub const RipPosition = struct { |
| | 227 | address: u64, |
| | 228 | start: usize, |
| | 229 | len: usize, |
| | 230 | }; |
| | 231 | |
| 221 | pub const empty = TextBlock{ | 232 | pub const empty = TextBlock{ |
| 222 | .local_sym_index = 0, | 233 | .local_sym_index = 0, |
| 223 | .offset_table_index = undefined, | 234 | .offset_table_index = undefined, |
| ... | @@ -226,6 +237,15 @@ pub const TextBlock = struct { | ... | @@ -226,6 +237,15 @@ pub const TextBlock = struct { |
| 226 | .next = null, | 237 | .next = null, |
| 227 | }; | 238 | }; |
| 228 | | 239 | |
| | 240 | pub fn addRipPosition(self: *TextBlock, alloc: *Allocator, rip: RipPosition) !void { |
| | 241 | std.debug.print("text_block={}, rip={}\n", .{ self.local_sym_index, rip }); |
| | 242 | return self.rip_positions.append(alloc, rip); |
| | 243 | } |
| | 244 | |
| | 245 | fn deinit(self: *TextBlock, alloc: *Allocator) void { |
| | 246 | self.rip_positions.deinit(alloc); |
| | 247 | } |
| | 248 | |
| 229 | /// Returns how much room there is to grow in virtual address space. | 249 | /// Returns how much room there is to grow in virtual address space. |
| 230 | /// File offset relocation happens transparently, so it is not included in | 250 | /// File offset relocation happens transparently, so it is not included in |
| 231 | /// this calculation. | 251 | /// this calculation. |
| ... | @@ -993,6 +1013,20 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { | ... | @@ -993,6 +1013,20 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { |
| 993 | try self.writeOffsetTableEntry(decl.link.macho.offset_table_index); | 1013 | try self.writeOffsetTableEntry(decl.link.macho.offset_table_index); |
| 994 | } | 1014 | } |
| 995 | | 1015 | |
| | 1016 | // Perform RIP-relative fixups (if any) |
| | 1017 | const got_section = self.sections.items[self.got_section_index.?]; |
| | 1018 | for (decl.link.macho.rip_positions.items) |rip| { |
| | 1019 | std.debug.print("rip={}\n", .{rip}); |
| | 1020 | const target_addr = rip.address; |
| | 1021 | // const got_addr = got_section.addr + decl.link.macho.offset_table_index * @sizeOf(u64); |
| | 1022 | const this_addr = symbol.n_value + rip.start; |
| | 1023 | std.debug.print("target_addr=0x{x},this_addr=0x{x}\n", .{target_addr, this_addr}); |
| | 1024 | const displacement = @intCast(u32, target_addr - this_addr + rip.len); |
| | 1025 | std.debug.print("displacement=0x{x}\n", .{displacement}); |
| | 1026 | var placeholder = code_buffer.items[rip.start + rip.len - @sizeOf(u32) ..][0..@sizeOf(u32)]; |
| | 1027 | mem.writeIntSliceLittle(u32, placeholder, displacement); |
| | 1028 | } |
| | 1029 | |
| 996 | const text_section = self.sections.items[self.text_section_index.?]; | 1030 | const text_section = self.sections.items[self.text_section_index.?]; |
| 997 | const section_offset = symbol.n_value - text_section.addr; | 1031 | const section_offset = symbol.n_value - text_section.addr; |
| 998 | const file_offset = text_section.offset + section_offset; | 1032 | const file_offset = text_section.offset + section_offset; |