| author | |
| committer | |
| log | 59fa548be8944962d5882e2ac38f6013ac00e84a |
| tree | 767aa3d1d895975f7d162c07423ccf30b8bc39c1 |
| parent | 9c509f1526b4560b4e97367a18755a9d1ae6fcf7 |
| parent | edb428fae42ea82c49347fce6d48d80f1fed6ef1 |
| signature |
stage2: fix (recursively) marking decls as alive, and improve DWARF for local vars5 files changed, 218 insertions(+), 46 deletions(-)
src/arch/x86_64/CodeGen.zig+81-43| ... | ... | @@ -3903,17 +3903,17 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void { |
| 3903 | 3903 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 3904 | 3904 | const operand = pl_op.operand; |
| 3905 | 3905 | const ty = self.air.typeOf(operand); |
| 3906 | const mcv = try self.resolveInst(operand); | |
| 3906 | 3907 | |
| 3907 | if (!self.liveness.operandDies(inst, 0)) { | |
| 3908 | const mcv = try self.resolveInst(operand); | |
| 3909 | const name = self.air.nullTerminatedString(pl_op.payload); | |
| 3908 | log.debug("airDbgVar: %{d}: {}, {}", .{ inst, ty.fmtDebug(), mcv }); | |
| 3910 | 3909 | |
| 3911 | const tag = self.air.instructions.items(.tag)[inst]; | |
| 3912 | switch (tag) { | |
| 3913 | .dbg_var_ptr => try self.genVarDbgInfo(ty.childType(), mcv, name), | |
| 3914 | .dbg_var_val => try self.genVarDbgInfo(ty, mcv, name), | |
| 3915 | else => unreachable, | |
| 3916 | } | |
| 3910 | const name = self.air.nullTerminatedString(pl_op.payload); | |
| 3911 | ||
| 3912 | const tag = self.air.instructions.items(.tag)[inst]; | |
| 3913 | switch (tag) { | |
| 3914 | .dbg_var_ptr => try self.genVarDbgInfo(tag, ty.childType(), mcv, name), | |
| 3915 | .dbg_var_val => try self.genVarDbgInfo(tag, ty, mcv, name), | |
| 3916 | else => unreachable, | |
| 3917 | 3917 | } |
| 3918 | 3918 | |
| 3919 | 3919 | return self.finishAir(inst, .dead, .{ operand, .none, .none }); |
| ... | ... | @@ -3921,36 +3921,27 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void { |
| 3921 | 3921 | |
| 3922 | 3922 | fn genVarDbgInfo( |
| 3923 | 3923 | self: *Self, |
| 3924 | tag: Air.Inst.Tag, | |
| 3924 | 3925 | ty: Type, |
| 3925 | 3926 | mcv: MCValue, |
| 3926 | 3927 | name: [:0]const u8, |
| 3927 | 3928 | ) !void { |
| 3928 | 3929 | const name_with_null = name.ptr[0 .. name.len + 1]; |
| 3929 | switch (mcv) { | |
| 3930 | .register => |reg| { | |
| 3931 | switch (self.debug_output) { | |
| 3932 | .dwarf => |dw| { | |
| 3933 | const dbg_info = &dw.dbg_info; | |
| 3934 | try dbg_info.ensureUnusedCapacity(3); | |
| 3935 | dbg_info.appendAssumeCapacity(@enumToInt(link.File.Dwarf.AbbrevKind.variable)); | |
| 3930 | switch (self.debug_output) { | |
| 3931 | .dwarf => |dw| { | |
| 3932 | const dbg_info = &dw.dbg_info; | |
| 3933 | try dbg_info.append(@enumToInt(link.File.Dwarf.AbbrevKind.variable)); | |
| 3934 | ||
| 3935 | switch (mcv) { | |
| 3936 | .register => |reg| { | |
| 3937 | try dbg_info.ensureUnusedCapacity(2); | |
| 3936 | 3938 | dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc |
| 3937 | 3939 | 1, // ULEB128 dwarf expression length |
| 3938 | 3940 | reg.dwarfLocOp(), |
| 3939 | 3941 | }); |
| 3940 | try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); | |
| 3941 | try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 | |
| 3942 | dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string | |
| 3943 | 3942 | }, |
| 3944 | .plan9 => {}, | |
| 3945 | .none => {}, | |
| 3946 | } | |
| 3947 | }, | |
| 3948 | .ptr_stack_offset, .stack_offset => |off| { | |
| 3949 | switch (self.debug_output) { | |
| 3950 | .dwarf => |dw| { | |
| 3951 | const dbg_info = &dw.dbg_info; | |
| 3952 | try dbg_info.ensureUnusedCapacity(8); | |
| 3953 | dbg_info.appendAssumeCapacity(@enumToInt(link.File.Dwarf.AbbrevKind.variable)); | |
| 3943 | .ptr_stack_offset, .stack_offset => |off| { | |
| 3944 | try dbg_info.ensureUnusedCapacity(7); | |
| 3954 | 3945 | const fixup = dbg_info.items.len; |
| 3955 | 3946 | dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc |
| 3956 | 3947 | 1, // we will backpatch it after we encode the displacement in LEB128 |
| ... | ... | @@ -3958,18 +3949,54 @@ fn genVarDbgInfo( |
| 3958 | 3949 | }); |
| 3959 | 3950 | leb128.writeILEB128(dbg_info.writer(), -off) catch unreachable; |
| 3960 | 3951 | dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2); |
| 3961 | try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); | |
| 3962 | try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 | |
| 3963 | dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string | |
| 3964 | ||
| 3965 | 3952 | }, |
| 3966 | .plan9 => {}, | |
| 3967 | .none => {}, | |
| 3953 | .memory, .got_load, .direct_load => { | |
| 3954 | const endian = self.target.cpu.arch.endian(); | |
| 3955 | const ptr_width = @intCast(u8, @divExact(self.target.cpu.arch.ptrBitWidth(), 8)); | |
| 3956 | const is_ptr = switch (tag) { | |
| 3957 | .dbg_var_ptr => true, | |
| 3958 | .dbg_var_val => false, | |
| 3959 | else => unreachable, | |
| 3960 | }; | |
| 3961 | try dbg_info.ensureUnusedCapacity(2 + ptr_width); | |
| 3962 | dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc | |
| 3963 | 1 + ptr_width + @boolToInt(is_ptr), | |
| 3964 | DW.OP.addr, // literal address | |
| 3965 | }); | |
| 3966 | const offset = @intCast(u32, dbg_info.items.len); | |
| 3967 | const addr = switch (mcv) { | |
| 3968 | .memory => |addr| addr, | |
| 3969 | else => 0, | |
| 3970 | }; | |
| 3971 | switch (ptr_width) { | |
| 3972 | 0...4 => { | |
| 3973 | try dbg_info.writer().writeInt(u32, @intCast(u32, addr), endian); | |
| 3974 | }, | |
| 3975 | 5...8 => { | |
| 3976 | try dbg_info.writer().writeInt(u64, addr, endian); | |
| 3977 | }, | |
| 3978 | else => unreachable, | |
| 3979 | } | |
| 3980 | if (is_ptr) { | |
| 3981 | // We need deref the address as we point to the value via GOT entry. | |
| 3982 | try dbg_info.append(DW.OP.deref); | |
| 3983 | } | |
| 3984 | switch (mcv) { | |
| 3985 | .got_load, .direct_load => |index| try dw.addExprlocReloc(index, offset, is_ptr), | |
| 3986 | else => {}, | |
| 3987 | } | |
| 3988 | }, | |
| 3989 | else => { | |
| 3990 | log.debug("TODO generate debug info for {}", .{mcv}); | |
| 3991 | }, | |
| 3968 | 3992 | } |
| 3993 | ||
| 3994 | try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); | |
| 3995 | try self.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 | |
| 3996 | dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string | |
| 3969 | 3997 | }, |
| 3970 | else => { | |
| 3971 | log.debug("TODO generate debug info for {}", .{mcv}); | |
| 3972 | }, | |
| 3998 | .plan9 => {}, | |
| 3999 | .none => {}, | |
| 3973 | 4000 | } |
| 3974 | 4001 | } |
| 3975 | 4002 | |
| ... | ... | @@ -6089,6 +6116,7 @@ fn limitImmediateType(self: *Self, operand: Air.Inst.Ref, comptime T: type) !MCV |
| 6089 | 6116 | } |
| 6090 | 6117 | |
| 6091 | 6118 | fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCValue { |
| 6119 | log.debug("lowerDeclRef: ty = {}, val = {}", .{ tv.ty.fmtDebug(), tv.val.fmtDebug() }); | |
| 6092 | 6120 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 6093 | 6121 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 6094 | 6122 | |
| ... | ... | @@ -6100,7 +6128,8 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCVa |
| 6100 | 6128 | } |
| 6101 | 6129 | } |
| 6102 | 6130 | |
| 6103 | decl.alive = true; | |
| 6131 | decl.markAlive(); | |
| 6132 | ||
| 6104 | 6133 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { |
| 6105 | 6134 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; |
| 6106 | 6135 | const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes; |
| ... | ... | @@ -6120,8 +6149,6 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCVa |
| 6120 | 6149 | } else { |
| 6121 | 6150 | return self.fail("TODO codegen non-ELF const Decl pointer", .{}); |
| 6122 | 6151 | } |
| 6123 | ||
| 6124 | _ = tv; | |
| 6125 | 6152 | } |
| 6126 | 6153 | |
| 6127 | 6154 | fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue { |
| ... | ... | @@ -6144,6 +6171,7 @@ fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue { |
| 6144 | 6171 | } |
| 6145 | 6172 | |
| 6146 | 6173 | fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { |
| 6174 | log.debug("genTypedValue: ty = {}, val = {}", .{ typed_value.ty.fmtDebug(), typed_value.val.fmtDebug() }); | |
| 6147 | 6175 | if (typed_value.val.isUndef()) |
| 6148 | 6176 | return MCValue{ .undef = {} }; |
| 6149 | 6177 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| ... | ... | @@ -6181,8 +6209,6 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { |
| 6181 | 6209 | .Bool => { |
| 6182 | 6210 | return MCValue{ .immediate = @boolToInt(typed_value.val.toBool()) }; |
| 6183 | 6211 | }, |
| 6184 | .ComptimeInt => unreachable, // semantic analysis prevents this | |
| 6185 | .ComptimeFloat => unreachable, // semantic analysis prevents this | |
| 6186 | 6212 | .Optional => { |
| 6187 | 6213 | if (typed_value.ty.isPtrLikeOptional()) { |
| 6188 | 6214 | if (typed_value.val.isNull()) |
| ... | ... | @@ -6243,6 +6269,18 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { |
| 6243 | 6269 | } |
| 6244 | 6270 | } |
| 6245 | 6271 | }, |
| 6272 | ||
| 6273 | .ComptimeInt => unreachable, | |
| 6274 | .ComptimeFloat => unreachable, | |
| 6275 | .Type => unreachable, | |
| 6276 | .EnumLiteral => unreachable, | |
| 6277 | .Void => unreachable, | |
| 6278 | .NoReturn => unreachable, | |
| 6279 | .Undefined => unreachable, | |
| 6280 | .Null => unreachable, | |
| 6281 | .BoundFn => unreachable, | |
| 6282 | .Opaque => unreachable, | |
| 6283 | ||
| 6246 | 6284 | else => {}, |
| 6247 | 6285 | } |
| 6248 | 6286 |
src/codegen.zig-2| ... | ... | @@ -203,7 +203,6 @@ pub fn generateSymbol( |
| 203 | 203 | }, |
| 204 | 204 | .Array => switch (typed_value.val.tag()) { |
| 205 | 205 | .bytes => { |
| 206 | // TODO populate .debug_info for the array | |
| 207 | 206 | const payload = typed_value.val.castTag(.bytes).?; |
| 208 | 207 | const len = @intCast(usize, typed_value.ty.arrayLenIncludingSentinel()); |
| 209 | 208 | // The bytes payload already includes the sentinel, if any |
| ... | ... | @@ -212,7 +211,6 @@ pub fn generateSymbol( |
| 212 | 211 | return Result{ .appended = {} }; |
| 213 | 212 | }, |
| 214 | 213 | .aggregate => { |
| 215 | // TODO populate .debug_info for the array | |
| 216 | 214 | const elem_vals = typed_value.val.castTag(.aggregate).?.data; |
| 217 | 215 | const elem_ty = typed_value.ty.elemType(); |
| 218 | 216 | const len = @intCast(usize, typed_value.ty.arrayLenIncludingSentinel()); |
src/link/Dwarf.zig+78| ... | ... | @@ -79,6 +79,7 @@ pub const DeclState = struct { |
| 79 | 79 | std.hash_map.default_max_load_percentage, |
| 80 | 80 | ) = .{}, |
| 81 | 81 | abbrev_relocs: std.ArrayListUnmanaged(AbbrevRelocation) = .{}, |
| 82 | exprloc_relocs: std.ArrayListUnmanaged(ExprlocRelocation) = .{}, | |
| 82 | 83 | |
| 83 | 84 | fn init(gpa: Allocator, target: std.Target) DeclState { |
| 84 | 85 | return .{ |
| ... | ... | @@ -97,6 +98,16 @@ pub const DeclState = struct { |
| 97 | 98 | self.abbrev_table.deinit(self.gpa); |
| 98 | 99 | self.abbrev_resolver.deinit(self.gpa); |
| 99 | 100 | self.abbrev_relocs.deinit(self.gpa); |
| 101 | self.exprloc_relocs.deinit(self.gpa); | |
| 102 | } | |
| 103 | ||
| 104 | pub fn addExprlocReloc(self: *DeclState, target: u32, offset: u32, is_ptr: bool) !void { | |
| 105 | log.debug("{x}: target sym @{d}, via GOT {}", .{ offset, target, is_ptr }); | |
| 106 | try self.exprloc_relocs.append(self.gpa, .{ | |
| 107 | .@"type" = if (is_ptr) .got_load else .direct_load, | |
| 108 | .target = target, | |
| 109 | .offset = offset, | |
| 110 | }); | |
| 100 | 111 | } |
| 101 | 112 | |
| 102 | 113 | pub fn addTypeReloc( |
| ... | ... | @@ -270,6 +281,27 @@ pub const DeclState = struct { |
| 270 | 281 | try self.addTypeReloc(atom, ty.childType(), @intCast(u32, index), null); |
| 271 | 282 | } |
| 272 | 283 | }, |
| 284 | .Array => { | |
| 285 | // DW.AT.array_type | |
| 286 | try dbg_info_buffer.append(@enumToInt(AbbrevKind.array_type)); | |
| 287 | // DW.AT.name, DW.FORM.string | |
| 288 | try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(target)}); | |
| 289 | // DW.AT.type, DW.FORM.ref4 | |
| 290 | var index = dbg_info_buffer.items.len; | |
| 291 | try dbg_info_buffer.resize(index + 4); | |
| 292 | try self.addTypeReloc(atom, ty.childType(), @intCast(u32, index), null); | |
| 293 | // DW.AT.subrange_type | |
| 294 | try dbg_info_buffer.append(@enumToInt(AbbrevKind.array_dim)); | |
| 295 | // DW.AT.type, DW.FORM.ref4 | |
| 296 | index = dbg_info_buffer.items.len; | |
| 297 | try dbg_info_buffer.resize(index + 4); | |
| 298 | try self.addTypeReloc(atom, Type.usize, @intCast(u32, index), null); | |
| 299 | // DW.AT.count, DW.FORM.udata | |
| 300 | const len = ty.arrayLenIncludingSentinel(); | |
| 301 | try leb128.writeULEB128(dbg_info_buffer.writer(), len); | |
| 302 | // DW.AT.array_type delimit children | |
| 303 | try dbg_info_buffer.append(0); | |
| 304 | }, | |
| 273 | 305 | .Struct => blk: { |
| 274 | 306 | // DW.AT.structure_type |
| 275 | 307 | try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_type)); |
| ... | ... | @@ -528,6 +560,18 @@ pub const AbbrevRelocation = struct { |
| 528 | 560 | addend: u32, |
| 529 | 561 | }; |
| 530 | 562 | |
| 563 | pub const ExprlocRelocation = struct { | |
| 564 | /// Type of the relocation: direct load ref, or GOT load ref (via GOT table) | |
| 565 | @"type": enum { | |
| 566 | direct_load, | |
| 567 | got_load, | |
| 568 | }, | |
| 569 | /// Index of the target in the linker's locals symbol table. | |
| 570 | target: u32, | |
| 571 | /// Offset within the debug info buffer where to patch up the address value. | |
| 572 | offset: u32, | |
| 573 | }; | |
| 574 | ||
| 531 | 575 | pub const SrcFn = struct { |
| 532 | 576 | /// Offset from the beginning of the Debug Line Program header that contains this function. |
| 533 | 577 | off: u32, |
| ... | ... | @@ -564,6 +608,8 @@ pub const AbbrevKind = enum(u8) { |
| 564 | 608 | pad1, |
| 565 | 609 | parameter, |
| 566 | 610 | variable, |
| 611 | array_type, | |
| 612 | array_dim, | |
| 567 | 613 | }; |
| 568 | 614 | |
| 569 | 615 | /// The reloc offset for the virtual address of a function in its Line Number Program. |
| ... | ... | @@ -986,6 +1032,26 @@ pub fn commitDeclState( |
| 986 | 1032 | } |
| 987 | 1033 | } |
| 988 | 1034 | |
| 1035 | while (decl_state.exprloc_relocs.popOrNull()) |reloc| { | |
| 1036 | switch (self.tag) { | |
| 1037 | .macho => { | |
| 1038 | const macho_file = file.cast(File.MachO).?; | |
| 1039 | const d_sym = &macho_file.d_sym.?; | |
| 1040 | try d_sym.relocs.append(d_sym.base.base.allocator, .{ | |
| 1041 | .@"type" = switch (reloc.@"type") { | |
| 1042 | .direct_load => .direct_load, | |
| 1043 | .got_load => .got_load, | |
| 1044 | }, | |
| 1045 | .target = reloc.target, | |
| 1046 | .offset = reloc.offset + atom.off, | |
| 1047 | .addend = 0, | |
| 1048 | .prev_vaddr = 0, | |
| 1049 | }); | |
| 1050 | }, | |
| 1051 | else => unreachable, | |
| 1052 | } | |
| 1053 | } | |
| 1054 | ||
| 989 | 1055 | try self.writeDeclDebugInfo(file, atom, dbg_info_buffer.items); |
| 990 | 1056 | } |
| 991 | 1057 | |
| ... | ... | @@ -1357,6 +1423,18 @@ pub fn writeDbgAbbrev(self: *Dwarf, file: *File) !void { |
| 1357 | 1423 | DW.AT.name, DW.FORM.string, |
| 1358 | 1424 | 0, |
| 1359 | 1425 | 0, // table sentinel |
| 1426 | @enumToInt(AbbrevKind.array_type), | |
| 1427 | DW.TAG.array_type, DW.CHILDREN.yes, // header | |
| 1428 | DW.AT.name, DW.FORM.string, | |
| 1429 | DW.AT.type, DW.FORM.ref4, | |
| 1430 | 0, | |
| 1431 | 0, // table sentinel | |
| 1432 | @enumToInt(AbbrevKind.array_dim), | |
| 1433 | DW.TAG.subrange_type, DW.CHILDREN.no, // header | |
| 1434 | DW.AT.type, DW.FORM.ref4, | |
| 1435 | DW.AT.count, DW.FORM.udata, | |
| 1436 | 0, | |
| 1437 | 0, // table sentinel | |
| 1360 | 1438 | 0, |
| 1361 | 1439 | 0, |
| 1362 | 1440 | 0, // section sentinel |
src/link/MachO.zig+8| ... | ... | @@ -3472,6 +3472,9 @@ pub fn closeFiles(self: MachO) void { |
| 3472 | 3472 | for (self.dylibs.items) |dylib| { |
| 3473 | 3473 | dylib.file.close(); |
| 3474 | 3474 | } |
| 3475 | if (self.d_sym) |ds| { | |
| 3476 | ds.file.close(); | |
| 3477 | } | |
| 3475 | 3478 | } |
| 3476 | 3479 | |
| 3477 | 3480 | fn freeAtom(self: *MachO, atom: *Atom, match: MatchingSection, owns_atom: bool) void { |
| ... | ... | @@ -4274,6 +4277,11 @@ pub fn freeDecl(self: *MachO, decl: *Module.Decl) void { |
| 4274 | 4277 | self.got_entries_free_list.append(self.base.allocator, @intCast(u32, got_index)) catch {}; |
| 4275 | 4278 | self.got_entries.items[got_index] = .{ .target = .{ .local = 0 }, .atom = undefined }; |
| 4276 | 4279 | _ = self.got_entries_table.swapRemove(.{ .local = decl.link.macho.local_sym_index }); |
| 4280 | ||
| 4281 | if (self.d_sym) |*d_sym| { | |
| 4282 | d_sym.swapRemoveRelocs(decl.link.macho.local_sym_index); | |
| 4283 | } | |
| 4284 | ||
| 4277 | 4285 | log.debug(" adding GOT index {d} to free list (target local@{d})", .{ |
| 4278 | 4286 | got_index, |
| 4279 | 4287 | decl.link.macho.local_sym_index, |
src/link/MachO/DebugSymbols.zig+51-1| ... | ... | @@ -59,6 +59,19 @@ debug_aranges_section_dirty: bool = false, |
| 59 | 59 | debug_info_header_dirty: bool = false, |
| 60 | 60 | debug_line_header_dirty: bool = false, |
| 61 | 61 | |
| 62 | relocs: std.ArrayListUnmanaged(Reloc) = .{}, | |
| 63 | ||
| 64 | pub const Reloc = struct { | |
| 65 | @"type": enum { | |
| 66 | direct_load, | |
| 67 | got_load, | |
| 68 | }, | |
| 69 | target: u32, | |
| 70 | offset: u64, | |
| 71 | addend: u32, | |
| 72 | prev_vaddr: u64, | |
| 73 | }; | |
| 74 | ||
| 62 | 75 | /// You must call this function *after* `MachO.populateMissingMetadata()` |
| 63 | 76 | /// has been called to get a viable debug symbols output. |
| 64 | 77 | pub fn populateMissingMetadata(self: *DebugSymbols, allocator: Allocator) !void { |
| ... | ... | @@ -254,6 +267,30 @@ pub fn flushModule(self: *DebugSymbols, allocator: Allocator, options: link.Opti |
| 254 | 267 | // Zig source code. |
| 255 | 268 | const module = options.module orelse return error.LinkingWithoutZigSourceUnimplemented; |
| 256 | 269 | |
| 270 | for (self.relocs.items) |*reloc| { | |
| 271 | const sym = switch (reloc.@"type") { | |
| 272 | .direct_load => self.base.locals.items[reloc.target], | |
| 273 | .got_load => blk: { | |
| 274 | const got_index = self.base.got_entries_table.get(.{ .local = reloc.target }).?; | |
| 275 | const got_entry = self.base.got_entries.items[got_index]; | |
| 276 | break :blk self.base.locals.items[got_entry.atom.local_sym_index]; | |
| 277 | }, | |
| 278 | }; | |
| 279 | if (sym.n_value == reloc.prev_vaddr) continue; | |
| 280 | ||
| 281 | const seg = &self.load_commands.items[self.dwarf_segment_cmd_index.?].segment; | |
| 282 | const sect = &seg.sections.items[self.debug_info_section_index.?]; | |
| 283 | const file_offset = sect.offset + reloc.offset; | |
| 284 | log.debug("resolving relocation: {d}@{x} ('{s}') at offset {x}", .{ | |
| 285 | reloc.target, | |
| 286 | sym.n_value, | |
| 287 | self.base.getString(sym.n_strx), | |
| 288 | file_offset, | |
| 289 | }); | |
| 290 | try self.file.pwriteAll(mem.asBytes(&sym.n_value), file_offset); | |
| 291 | reloc.prev_vaddr = sym.n_value; | |
| 292 | } | |
| 293 | ||
| 257 | 294 | if (self.debug_abbrev_section_dirty) { |
| 258 | 295 | try self.dwarf.writeDbgAbbrev(&self.base.base); |
| 259 | 296 | self.load_commands_dirty = true; |
| ... | ... | @@ -330,7 +367,20 @@ pub fn deinit(self: *DebugSymbols, allocator: Allocator) void { |
| 330 | 367 | } |
| 331 | 368 | self.load_commands.deinit(allocator); |
| 332 | 369 | self.dwarf.deinit(); |
| 333 | self.file.close(); | |
| 370 | self.relocs.deinit(allocator); | |
| 371 | } | |
| 372 | ||
| 373 | pub fn swapRemoveRelocs(self: *DebugSymbols, target: u32) void { | |
| 374 | // TODO re-implement using a hashmap with free lists | |
| 375 | var last_index: usize = 0; | |
| 376 | while (last_index < self.relocs.items.len) { | |
| 377 | const reloc = self.relocs.items[last_index]; | |
| 378 | if (reloc.target == target) { | |
| 379 | _ = self.relocs.swapRemove(last_index); | |
| 380 | } else { | |
| 381 | last_index += 1; | |
| 382 | } | |
| 383 | } | |
| 334 | 384 | } |
| 335 | 385 | |
| 336 | 386 | fn copySegmentCommand( |