| ... | ... | @@ -214,10 +214,21 @@ pub const TextBlock = struct { |
| 214 | 214 | /// Unlike in Elf, we need to store the size of this symbol as part of |
| 215 | 215 | /// the TextBlock since macho.nlist_64 lacks this information. |
| 216 | 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 | 222 | /// Points to the previous and next neighbours |
| 218 | 223 | prev: ?*TextBlock, |
| 219 | 224 | next: ?*TextBlock, |
| 220 | 225 | |
| 226 | pub const RipPosition = struct { |
| 227 | address: u64, |
| 228 | start: usize, |
| 229 | len: usize, |
| 230 | }; |
| 231 | |
| 221 | 232 | pub const empty = TextBlock{ |
| 222 | 233 | .local_sym_index = 0, |
| 223 | 234 | .offset_table_index = undefined, |
| ... | ... | @@ -226,6 +237,15 @@ pub const TextBlock = struct { |
| 226 | 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 | 249 | /// Returns how much room there is to grow in virtual address space. |
| 230 | 250 | /// File offset relocation happens transparently, so it is not included in |
| 231 | 251 | /// this calculation. |
| ... | ... | @@ -993,6 +1013,20 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { |
| 993 | 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 | 1030 | const text_section = self.sections.items[self.text_section_index.?]; |
| 997 | 1031 | const section_offset = symbol.n_value - text_section.addr; |
| 998 | 1032 | const file_offset = text_section.offset + section_offset; |