| ... | ... | @@ -20,9 +20,6 @@ pub const Relocation = struct { |
| 20 | 20 | /// Note relocation size can be inferred by relocation's kind. |
| 21 | 21 | offset: u32, |
| 22 | 22 | |
| 23 | | /// Parent block containing this relocation. |
| 24 | | block: *TextBlock, |
| 25 | | |
| 26 | 23 | /// Target symbol: either a regular or a proxy. |
| 27 | 24 | target: *Symbol, |
| 28 | 25 | |
| ... | ... | @@ -36,6 +33,13 @@ pub const Relocation = struct { |
| 36 | 33 | load: Load, |
| 37 | 34 | }, |
| 38 | 35 | |
| 36 | const ResolveArgs = struct { |
| 37 | block: *TextBlock, |
| 38 | offset: u32, |
| 39 | source_addr: u64, |
| 40 | target_addr: u64, |
| 41 | }; |
| 42 | |
| 39 | 43 | pub const Unsigned = struct { |
| 40 | 44 | subtractor: ?*Symbol = null, |
| 41 | 45 | |
| ... | ... | @@ -48,16 +52,16 @@ pub const Relocation = struct { |
| 48 | 52 | /// => * is unreachable |
| 49 | 53 | is_64bit: bool, |
| 50 | 54 | |
| 51 | | pub fn resolve(self: Unsigned, base: Relocation, _: u64, target_addr: u64) !void { |
| 55 | pub fn resolve(self: Unsigned, args: ResolveArgs) !void { |
| 52 | 56 | const result = if (self.subtractor) |subtractor| |
| 53 | | @intCast(i64, target_addr) - @intCast(i64, subtractor.payload.regular.address) + self.addend |
| 57 | @intCast(i64, args.target_addr) - @intCast(i64, subtractor.payload.regular.address) + self.addend |
| 54 | 58 | else |
| 55 | | @intCast(i64, target_addr) + self.addend; |
| 59 | @intCast(i64, args.target_addr) + self.addend; |
| 56 | 60 | |
| 57 | 61 | if (self.is_64bit) { |
| 58 | | mem.writeIntLittle(u64, base.block.code[base.offset..][0..8], @bitCast(u64, result)); |
| 62 | mem.writeIntLittle(u64, args.block.code[args.offset..][0..8], @bitCast(u64, result)); |
| 59 | 63 | } else { |
| 60 | | mem.writeIntLittle(u32, base.block.code[base.offset..][0..4], @truncate(u32, @bitCast(u64, result))); |
| 64 | mem.writeIntLittle(u32, args.block.code[args.offset..][0..4], @truncate(u32, @bitCast(u64, result))); |
| 61 | 65 | } |
| 62 | 66 | } |
| 63 | 67 | |
| ... | ... | @@ -78,25 +82,29 @@ pub const Relocation = struct { |
| 78 | 82 | pub const Branch = struct { |
| 79 | 83 | arch: Arch, |
| 80 | 84 | |
| 81 | | pub fn resolve(self: Branch, base: Relocation, source_addr: u64, target_addr: u64) !void { |
| 85 | pub fn resolve(self: Branch, args: ResolveArgs) !void { |
| 82 | 86 | switch (self.arch) { |
| 83 | 87 | .aarch64 => { |
| 84 | | const displacement = try math.cast(i28, @intCast(i64, target_addr) - @intCast(i64, source_addr)); |
| 88 | const displacement = try math.cast( |
| 89 | i28, |
| 90 | @intCast(i64, args.target_addr) - @intCast(i64, args.source_addr), |
| 91 | ); |
| 92 | const code = args.block.code[args.offset..][0..4]; |
| 85 | 93 | var inst = aarch64.Instruction{ |
| 86 | | .unconditional_branch_immediate = mem.bytesToValue( |
| 87 | | meta.TagPayload( |
| 88 | | aarch64.Instruction, |
| 89 | | aarch64.Instruction.unconditional_branch_immediate, |
| 90 | | ), |
| 91 | | base.block.code[base.offset..][0..4], |
| 92 | | ), |
| 94 | .unconditional_branch_immediate = mem.bytesToValue(meta.TagPayload( |
| 95 | aarch64.Instruction, |
| 96 | aarch64.Instruction.unconditional_branch_immediate, |
| 97 | ), code), |
| 93 | 98 | }; |
| 94 | 99 | inst.unconditional_branch_immediate.imm26 = @truncate(u26, @bitCast(u28, displacement >> 2)); |
| 95 | | mem.writeIntLittle(u32, base.block.code[base.offset..][0..4], inst.toU32()); |
| 100 | mem.writeIntLittle(u32, code, inst.toU32()); |
| 96 | 101 | }, |
| 97 | 102 | .x86_64 => { |
| 98 | | const displacement = try math.cast(i32, @intCast(i64, target_addr) - @intCast(i64, source_addr) - 4); |
| 99 | | mem.writeIntLittle(u32, base.block.code[base.offset..][0..4], @bitCast(u32, displacement)); |
| 103 | const displacement = try math.cast( |
| 104 | i32, |
| 105 | @intCast(i64, args.target_addr) - @intCast(i64, args.source_addr) - 4, |
| 106 | ); |
| 107 | mem.writeIntLittle(u32, args.block.code[args.offset..][0..4], @bitCast(u32, displacement)); |
| 100 | 108 | }, |
| 101 | 109 | else => return error.UnsupportedCpuArchitecture, |
| 102 | 110 | } |
| ... | ... | @@ -118,25 +126,23 @@ pub const Relocation = struct { |
| 118 | 126 | }, |
| 119 | 127 | addend: ?u32 = null, |
| 120 | 128 | |
| 121 | | pub fn resolve(self: Page, base: Relocation, source_addr: u64, target_addr: u64) !void { |
| 122 | | const actual_target_addr = if (self.addend) |addend| target_addr + addend else target_addr; |
| 123 | | const source_page = @intCast(i32, source_addr >> 12); |
| 124 | | const target_page = @intCast(i32, actual_target_addr >> 12); |
| 129 | pub fn resolve(self: Page, args: ResolveArgs) !void { |
| 130 | const target_addr = if (self.addend) |addend| args.target_addr + addend else args.target_addr; |
| 131 | const source_page = @intCast(i32, args.source_addr >> 12); |
| 132 | const target_page = @intCast(i32, target_addr >> 12); |
| 125 | 133 | const pages = @bitCast(u21, @intCast(i21, target_page - source_page)); |
| 126 | 134 | |
| 135 | const code = args.block.code[args.offset..][0..4]; |
| 127 | 136 | var inst = aarch64.Instruction{ |
| 128 | | .pc_relative_address = mem.bytesToValue( |
| 129 | | meta.TagPayload( |
| 130 | | aarch64.Instruction, |
| 131 | | aarch64.Instruction.pc_relative_address, |
| 132 | | ), |
| 133 | | base.block.code[base.offset..][0..4], |
| 134 | | ), |
| 137 | .pc_relative_address = mem.bytesToValue(meta.TagPayload( |
| 138 | aarch64.Instruction, |
| 139 | aarch64.Instruction.pc_relative_address, |
| 140 | ), code), |
| 135 | 141 | }; |
| 136 | 142 | inst.pc_relative_address.immhi = @truncate(u19, pages >> 2); |
| 137 | 143 | inst.pc_relative_address.immlo = @truncate(u2, pages); |
| 138 | 144 | |
| 139 | | mem.writeIntLittle(u32, base.block.code[base.offset..][0..4], inst.toU32()); |
| 145 | mem.writeIntLittle(u32, code, inst.toU32()); |
| 140 | 146 | } |
| 141 | 147 | |
| 142 | 148 | pub fn format(self: Page, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { |
| ... | ... | @@ -173,35 +179,31 @@ pub const Relocation = struct { |
| 173 | 179 | load, |
| 174 | 180 | }; |
| 175 | 181 | |
| 176 | | pub fn resolve(self: PageOff, base: Relocation, _: u64, target_addr: u64) !void { |
| 182 | pub fn resolve(self: PageOff, args: ResolveArgs) !void { |
| 183 | const code = args.block.code[args.offset..][0..4]; |
| 184 | |
| 177 | 185 | switch (self.kind) { |
| 178 | 186 | .page => { |
| 179 | | const actual_target_addr = if (self.addend) |addend| target_addr + addend else target_addr; |
| 180 | | const narrowed = @truncate(u12, actual_target_addr); |
| 187 | const target_addr = if (self.addend) |addend| args.target_addr + addend else args.target_addr; |
| 188 | const narrowed = @truncate(u12, target_addr); |
| 181 | 189 | |
| 182 | 190 | const op_kind = self.op_kind orelse unreachable; |
| 183 | 191 | var inst: aarch64.Instruction = blk: { |
| 184 | 192 | switch (op_kind) { |
| 185 | 193 | .arithmetic => { |
| 186 | 194 | break :blk .{ |
| 187 | | .add_subtract_immediate = mem.bytesToValue( |
| 188 | | meta.TagPayload( |
| 189 | | aarch64.Instruction, |
| 190 | | aarch64.Instruction.add_subtract_immediate, |
| 191 | | ), |
| 192 | | base.block.code[base.offset..][0..4], |
| 193 | | ), |
| 195 | .add_subtract_immediate = mem.bytesToValue(meta.TagPayload( |
| 196 | aarch64.Instruction, |
| 197 | aarch64.Instruction.add_subtract_immediate, |
| 198 | ), code), |
| 194 | 199 | }; |
| 195 | 200 | }, |
| 196 | 201 | .load => { |
| 197 | 202 | break :blk .{ |
| 198 | | .load_store_register = mem.bytesToValue( |
| 199 | | meta.TagPayload( |
| 200 | | aarch64.Instruction, |
| 201 | | aarch64.Instruction.load_store_register, |
| 202 | | ), |
| 203 | | base.block.code[base.offset..][0..4], |
| 204 | | ), |
| 203 | .load_store_register = mem.bytesToValue(meta.TagPayload( |
| 204 | aarch64.Instruction, |
| 205 | aarch64.Instruction.load_store_register, |
| 206 | ), code), |
| 205 | 207 | }; |
| 206 | 208 | }, |
| 207 | 209 | } |
| ... | ... | @@ -226,22 +228,19 @@ pub const Relocation = struct { |
| 226 | 228 | inst.load_store_register.offset = offset; |
| 227 | 229 | } |
| 228 | 230 | |
| 229 | | mem.writeIntLittle(u32, base.block.code[base.offset..][0..4], inst.toU32()); |
| 231 | mem.writeIntLittle(u32, code, inst.toU32()); |
| 230 | 232 | }, |
| 231 | 233 | .got => { |
| 232 | | const narrowed = @truncate(u12, target_addr); |
| 234 | const narrowed = @truncate(u12, args.target_addr); |
| 233 | 235 | var inst: aarch64.Instruction = .{ |
| 234 | | .load_store_register = mem.bytesToValue( |
| 235 | | meta.TagPayload( |
| 236 | | aarch64.Instruction, |
| 237 | | aarch64.Instruction.load_store_register, |
| 238 | | ), |
| 239 | | base.block.code[base.offset..][0..4], |
| 240 | | ), |
| 236 | .load_store_register = mem.bytesToValue(meta.TagPayload( |
| 237 | aarch64.Instruction, |
| 238 | aarch64.Instruction.load_store_register, |
| 239 | ), code), |
| 241 | 240 | }; |
| 242 | 241 | const offset = try math.divExact(u12, narrowed, 8); |
| 243 | 242 | inst.load_store_register.offset = offset; |
| 244 | | mem.writeIntLittle(u32, base.block.code[base.offset..][0..4], inst.toU32()); |
| 243 | mem.writeIntLittle(u32, code, inst.toU32()); |
| 245 | 244 | }, |
| 246 | 245 | .tlvp => { |
| 247 | 246 | const RegInfo = struct { |
| ... | ... | @@ -250,27 +249,21 @@ pub const Relocation = struct { |
| 250 | 249 | size: u1, |
| 251 | 250 | }; |
| 252 | 251 | const reg_info: RegInfo = blk: { |
| 253 | | if (isArithmeticOp(base.block.code[base.offset..][0..4])) { |
| 254 | | const inst = mem.bytesToValue( |
| 255 | | meta.TagPayload( |
| 256 | | aarch64.Instruction, |
| 257 | | aarch64.Instruction.add_subtract_immediate, |
| 258 | | ), |
| 259 | | base.block.code[base.offset..][0..4], |
| 260 | | ); |
| 252 | if (isArithmeticOp(code)) { |
| 253 | const inst = mem.bytesToValue(meta.TagPayload( |
| 254 | aarch64.Instruction, |
| 255 | aarch64.Instruction.add_subtract_immediate, |
| 256 | ), code); |
| 261 | 257 | break :blk .{ |
| 262 | 258 | .rd = inst.rd, |
| 263 | 259 | .rn = inst.rn, |
| 264 | 260 | .size = inst.sf, |
| 265 | 261 | }; |
| 266 | 262 | } else { |
| 267 | | const inst = mem.bytesToValue( |
| 268 | | meta.TagPayload( |
| 269 | | aarch64.Instruction, |
| 270 | | aarch64.Instruction.load_store_register, |
| 271 | | ), |
| 272 | | base.block.code[base.offset..][0..4], |
| 273 | | ); |
| 263 | const inst = mem.bytesToValue(meta.TagPayload( |
| 264 | aarch64.Instruction, |
| 265 | aarch64.Instruction.load_store_register, |
| 266 | ), code); |
| 274 | 267 | break :blk .{ |
| 275 | 268 | .rd = inst.rt, |
| 276 | 269 | .rn = inst.rn, |
| ... | ... | @@ -278,7 +271,7 @@ pub const Relocation = struct { |
| 278 | 271 | }; |
| 279 | 272 | } |
| 280 | 273 | }; |
| 281 | | const narrowed = @truncate(u12, target_addr); |
| 274 | const narrowed = @truncate(u12, args.target_addr); |
| 282 | 275 | var inst = aarch64.Instruction{ |
| 283 | 276 | .add_subtract_immediate = .{ |
| 284 | 277 | .rd = reg_info.rd, |
| ... | ... | @@ -290,7 +283,7 @@ pub const Relocation = struct { |
| 290 | 283 | .sf = reg_info.size, |
| 291 | 284 | }, |
| 292 | 285 | }; |
| 293 | | mem.writeIntLittle(u32, base.block.code[base.offset..][0..4], inst.toU32()); |
| 286 | mem.writeIntLittle(u32, code, inst.toU32()); |
| 294 | 287 | }, |
| 295 | 288 | } |
| 296 | 289 | } |
| ... | ... | @@ -319,9 +312,9 @@ pub const Relocation = struct { |
| 319 | 312 | }; |
| 320 | 313 | |
| 321 | 314 | pub const PointerToGot = struct { |
| 322 | | pub fn resolve(_: PointerToGot, base: Relocation, source_addr: u64, target_addr: u64) !void { |
| 323 | | const result = try math.cast(i32, @intCast(i64, target_addr) - @intCast(i64, source_addr)); |
| 324 | | mem.writeIntLittle(u32, base.block.code[base.offset..][0..4], @bitCast(u32, result)); |
| 315 | pub fn resolve(_: PointerToGot, args: ResolveArgs) !void { |
| 316 | const result = try math.cast(i32, @intCast(i64, args.target_addr) - @intCast(i64, args.source_addr)); |
| 317 | mem.writeIntLittle(u32, args.block.code[args.offset..][0..4], @bitCast(u32, result)); |
| 325 | 318 | } |
| 326 | 319 | |
| 327 | 320 | pub fn format(self: PointerToGot, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { |
| ... | ... | @@ -336,13 +329,13 @@ pub const Relocation = struct { |
| 336 | 329 | addend: i64, |
| 337 | 330 | correction: i4, |
| 338 | 331 | |
| 339 | | pub fn resolve(self: Signed, base: Relocation, source_addr: u64, target_addr: u64) !void { |
| 340 | | const actual_target_addr = @intCast(i64, target_addr) + self.addend; |
| 332 | pub fn resolve(self: Signed, args: ResolveArgs) !void { |
| 333 | const target_addr = @intCast(i64, args.target_addr) + self.addend; |
| 341 | 334 | const displacement = try math.cast( |
| 342 | 335 | i32, |
| 343 | | actual_target_addr - @intCast(i64, source_addr) - self.correction - 4, |
| 336 | target_addr - @intCast(i64, args.source_addr) - self.correction - 4, |
| 344 | 337 | ); |
| 345 | | mem.writeIntLittle(u32, base.block.code[base.offset..][0..4], @bitCast(u32, displacement)); |
| 338 | mem.writeIntLittle(u32, args.block.code[args.offset..][0..4], @bitCast(u32, displacement)); |
| 346 | 339 | } |
| 347 | 340 | |
| 348 | 341 | pub fn format(self: Signed, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { |
| ... | ... | @@ -362,17 +355,17 @@ pub const Relocation = struct { |
| 362 | 355 | }, |
| 363 | 356 | addend: ?i32 = null, |
| 364 | 357 | |
| 365 | | pub fn resolve(self: Load, base: Relocation, source_addr: u64, target_addr: u64) !void { |
| 358 | pub fn resolve(self: Load, args: ResolveArgs) !void { |
| 366 | 359 | if (self.kind == .tlvp) { |
| 367 | 360 | // We need to rewrite the opcode from movq to leaq. |
| 368 | | base.block.code[base.offset - 2] = 0x8d; |
| 361 | args.block.code[args.offset - 2] = 0x8d; |
| 369 | 362 | } |
| 370 | 363 | const addend = if (self.addend) |addend| addend else 0; |
| 371 | 364 | const displacement = try math.cast( |
| 372 | 365 | i32, |
| 373 | | @intCast(i64, target_addr) - @intCast(i64, source_addr) - 4 + addend, |
| 366 | @intCast(i64, args.target_addr) - @intCast(i64, args.source_addr) - 4 + addend, |
| 374 | 367 | ); |
| 375 | | mem.writeIntLittle(u32, base.block.code[base.offset..][0..4], @bitCast(u32, displacement)); |
| 368 | mem.writeIntLittle(u32, args.block.code[args.offset..][0..4], @bitCast(u32, displacement)); |
| 376 | 369 | } |
| 377 | 370 | |
| 378 | 371 | pub fn format(self: Load, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { |
| ... | ... | @@ -387,106 +380,27 @@ pub const Relocation = struct { |
| 387 | 380 | } |
| 388 | 381 | }; |
| 389 | 382 | |
| 390 | | pub fn resolve(self: Relocation, zld: *Zld) !void { |
| 391 | | log.debug("relocating {}", .{self}); |
| 392 | | |
| 393 | | const source_addr = blk: { |
| 394 | | const sym = zld.locals.items[self.block.local_sym_index]; |
| 395 | | break :blk sym.payload.regular.address + self.offset; |
| 396 | | }; |
| 397 | | const target_addr = blk: { |
| 398 | | const is_via_got = switch (self.payload) { |
| 399 | | .pointer_to_got => true, |
| 400 | | .page => |page| page.kind == .got, |
| 401 | | .page_off => |page_off| page_off.kind == .got, |
| 402 | | .load => |load| load.kind == .got, |
| 403 | | else => false, |
| 404 | | }; |
| 405 | | |
| 406 | | if (is_via_got) { |
| 407 | | const dc_seg = zld.load_commands.items[zld.data_const_segment_cmd_index.?].Segment; |
| 408 | | const got = dc_seg.sections.items[zld.got_section_index.?]; |
| 409 | | const got_index = self.target.got_index orelse { |
| 410 | | log.err("expected GOT entry for symbol '{s}'", .{zld.getString(self.target.strx)}); |
| 411 | | log.err(" this is an internal linker error", .{}); |
| 412 | | return error.FailedToResolveRelocationTarget; |
| 413 | | }; |
| 414 | | break :blk got.addr + got_index * @sizeOf(u64); |
| 415 | | } |
| 416 | | |
| 417 | | switch (self.target.payload) { |
| 418 | | .regular => |reg| { |
| 419 | | const is_tlv = is_tlv: { |
| 420 | | const sym = zld.locals.items[self.block.local_sym_index]; |
| 421 | | const seg = zld.load_commands.items[sym.payload.regular.segment_id].Segment; |
| 422 | | const sect = seg.sections.items[sym.payload.regular.section_id]; |
| 423 | | break :is_tlv commands.sectionType(sect) == macho.S_THREAD_LOCAL_VARIABLES; |
| 424 | | }; |
| 425 | | if (is_tlv) { |
| 426 | | // For TLV relocations, the value specified as a relocation is the displacement from the |
| 427 | | // TLV initializer (either value in __thread_data or zero-init in __thread_bss) to the first |
| 428 | | // defined TLV template init section in the following order: |
| 429 | | // * wrt to __thread_data if defined, then |
| 430 | | // * wrt to __thread_bss |
| 431 | | const seg = zld.load_commands.items[zld.data_segment_cmd_index.?].Segment; |
| 432 | | const base_address = inner: { |
| 433 | | if (zld.tlv_data_section_index) |i| { |
| 434 | | break :inner seg.sections.items[i].addr; |
| 435 | | } else if (zld.tlv_bss_section_index) |i| { |
| 436 | | break :inner seg.sections.items[i].addr; |
| 437 | | } else { |
| 438 | | log.err("threadlocal variables present but no initializer sections found", .{}); |
| 439 | | log.err(" __thread_data not found", .{}); |
| 440 | | log.err(" __thread_bss not found", .{}); |
| 441 | | return error.FailedToResolveRelocationTarget; |
| 442 | | } |
| 443 | | }; |
| 444 | | break :blk reg.address - base_address; |
| 445 | | } |
| 446 | | |
| 447 | | break :blk reg.address; |
| 448 | | }, |
| 449 | | .proxy => { |
| 450 | | if (mem.eql(u8, zld.getString(self.target.strx), "__tlv_bootstrap")) { |
| 451 | | break :blk 0; // Dynamically bound by dyld. |
| 452 | | } |
| 453 | | |
| 454 | | const segment = zld.load_commands.items[zld.text_segment_cmd_index.?].Segment; |
| 455 | | const stubs = segment.sections.items[zld.stubs_section_index.?]; |
| 456 | | const stubs_index = self.target.stubs_index orelse { |
| 457 | | // TODO verify in TextBlock that the symbol is indeed dynamically bound. |
| 458 | | break :blk 0; // Dynamically bound by dyld. |
| 459 | | }; |
| 460 | | break :blk stubs.addr + stubs_index * stubs.reserved2; |
| 461 | | }, |
| 462 | | else => { |
| 463 | | log.err("failed to resolve symbol '{s}' as a relocation target", .{ |
| 464 | | zld.getString(self.target.strx), |
| 465 | | }); |
| 466 | | log.err(" this is an internal linker error", .{}); |
| 467 | | return error.FailedToResolveRelocationTarget; |
| 468 | | }, |
| 469 | | } |
| 383 | pub fn resolve(self: Relocation, block: *TextBlock, source_addr: u64, target_addr: u64) !void { |
| 384 | const args = ResolveArgs{ |
| 385 | .block = block, |
| 386 | .offset = self.offset, |
| 387 | .source_addr = source_addr, |
| 388 | .target_addr = target_addr, |
| 470 | 389 | }; |
| 471 | | |
| 472 | | log.debug(" | source_addr = 0x{x}", .{source_addr}); |
| 473 | | log.debug(" | target_addr = 0x{x}", .{target_addr}); |
| 474 | | |
| 475 | 390 | switch (self.payload) { |
| 476 | | .unsigned => |unsigned| try unsigned.resolve(self, source_addr, target_addr), |
| 477 | | .branch => |branch| try branch.resolve(self, source_addr, target_addr), |
| 478 | | .page => |page| try page.resolve(self, source_addr, target_addr), |
| 479 | | .page_off => |page_off| try page_off.resolve(self, source_addr, target_addr), |
| 480 | | .pointer_to_got => |pointer_to_got| try pointer_to_got.resolve(self, source_addr, target_addr), |
| 481 | | .signed => |signed| try signed.resolve(self, source_addr, target_addr), |
| 482 | | .load => |load| try load.resolve(self, source_addr, target_addr), |
| 391 | .unsigned => |unsigned| try unsigned.resolve(args), |
| 392 | .branch => |branch| try branch.resolve(args), |
| 393 | .page => |page| try page.resolve(args), |
| 394 | .page_off => |page_off| try page_off.resolve(args), |
| 395 | .pointer_to_got => |pointer_to_got| try pointer_to_got.resolve(args), |
| 396 | .signed => |signed| try signed.resolve(args), |
| 397 | .load => |load| try load.resolve(args), |
| 483 | 398 | } |
| 484 | 399 | } |
| 485 | 400 | |
| 486 | 401 | pub fn format(self: Relocation, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { |
| 487 | 402 | try std.fmt.format(writer, "Relocation {{ ", .{}); |
| 488 | 403 | try std.fmt.format(writer, ".offset = {}, ", .{self.offset}); |
| 489 | | try std.fmt.format(writer, ".block = {}", .{self.block.local_sym_index}); |
| 490 | 404 | try std.fmt.format(writer, ".target = {}, ", .{self.target}); |
| 491 | 405 | |
| 492 | 406 | switch (self.payload) { |
| ... | ... | @@ -713,7 +627,6 @@ pub const Parser = struct { |
| 713 | 627 | return Relocation{ |
| 714 | 628 | .offset = offset, |
| 715 | 629 | .target = target, |
| 716 | | .block = self.block, |
| 717 | 630 | .payload = undefined, |
| 718 | 631 | }; |
| 719 | 632 | } |