| ... | ... | @@ -146,11 +146,8 @@ const MCValue = union(enum) { |
| 146 | 146 | /// If the type is a pointer, it means the pointer address is at |
| 147 | 147 | /// this memory location. |
| 148 | 148 | memory: u64, |
| 149 | | /// The value is in memory but requires a linker relocation fixup: |
| 150 | | /// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc) |
| 151 | | /// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc) |
| 152 | | /// * import - the value is referenced indirectly via import entry index (the linker emits an import-type reloc) |
| 153 | | linker_load: struct { type: enum { got, direct, import }, sym_index: u32 }, |
| 149 | /// The value is in memory but requires a linker relocation fixup. |
| 150 | linker_load: codegen.LinkerLoad, |
| 154 | 151 | /// The value is one of the stack variables. |
| 155 | 152 | /// |
| 156 | 153 | /// If the type is a pointer, it means the pointer address is in |
| ... | ... | @@ -217,33 +214,23 @@ const DbgInfoReloc = struct { |
| 217 | 214 | } |
| 218 | 215 | |
| 219 | 216 | fn genVarDbgInfo(reloc: DbgInfoReloc, function: Self) !void { |
| 220 | | const name_with_null = reloc.name.ptr[0 .. reloc.name.len + 1]; |
| 221 | | const ty = switch (reloc.tag) { |
| 222 | | .dbg_var_ptr => reloc.ty.childType(), |
| 223 | | .dbg_var_val => reloc.ty, |
| 217 | const is_ptr = switch (reloc.tag) { |
| 218 | .dbg_var_ptr => true, |
| 219 | .dbg_var_val => false, |
| 224 | 220 | else => unreachable, |
| 225 | 221 | }; |
| 226 | | // const atom= function.getDbgInfoAtomPtr(); |
| 222 | const atom = function.getDbgInfoAtomPtr(); |
| 227 | 223 | |
| 228 | 224 | switch (function.debug_output) { |
| 229 | 225 | .dwarf => |dw| { |
| 230 | | const dbg_info = &dw.dbg_info; |
| 231 | | try dbg_info.append(@enumToInt(link.File.Dwarf.AbbrevKind.variable)); |
| 232 | | const endian = function.target.cpu.arch.endian(); |
| 233 | | |
| 234 | | switch (reloc.mcv) { |
| 235 | | .register => |reg| { |
| 236 | | try dbg_info.ensureUnusedCapacity(2); |
| 237 | | dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc |
| 238 | | 1, // ULEB128 dwarf expression length |
| 239 | | reg.dwarfLocOp(), |
| 240 | | }); |
| 226 | const loc: link.File.Dwarf.DeclState.VarArgDbgInfoLoc = switch (reloc.mcv) { |
| 227 | .register => |reg| .{ |
| 228 | .register = reg.dwarfLocOp(), |
| 241 | 229 | }, |
| 242 | | |
| 243 | 230 | .ptr_stack_offset, |
| 244 | 231 | .stack_offset, |
| 245 | 232 | .stack_argument_offset, |
| 246 | | => |offset| { |
| 233 | => |offset| blk: { |
| 247 | 234 | const adjusted_offset = switch (reloc.mcv) { |
| 248 | 235 | .ptr_stack_offset, |
| 249 | 236 | .stack_offset, |
| ... | ... | @@ -251,110 +238,31 @@ const DbgInfoReloc = struct { |
| 251 | 238 | .stack_argument_offset => @intCast(i32, function.saved_regs_stack_space + offset), |
| 252 | 239 | else => unreachable, |
| 253 | 240 | }; |
| 254 | | |
| 255 | | try dbg_info.ensureUnusedCapacity(7); |
| 256 | | const fixup = dbg_info.items.len; |
| 257 | | dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc |
| 258 | | 1, // we will backpatch it after we encode the displacement in LEB128 |
| 259 | | Register.x29.dwarfLocOpDeref(), // frame pointer |
| 260 | | }); |
| 261 | | leb128.writeILEB128(dbg_info.writer(), adjusted_offset) catch unreachable; |
| 262 | | dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2); |
| 263 | | }, |
| 264 | | |
| 265 | | .memory, |
| 266 | | .linker_load, |
| 267 | | => { |
| 268 | | const ptr_width = @intCast(u8, @divExact(function.target.cpu.arch.ptrBitWidth(), 8)); |
| 269 | | const is_ptr = switch (reloc.tag) { |
| 270 | | .dbg_var_ptr => true, |
| 271 | | .dbg_var_val => false, |
| 272 | | else => unreachable, |
| 273 | | }; |
| 274 | | try dbg_info.ensureUnusedCapacity(2 + ptr_width); |
| 275 | | dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc |
| 276 | | 1 + ptr_width + @boolToInt(is_ptr), |
| 277 | | DW.OP.addr, // literal address |
| 278 | | }); |
| 279 | | const offset = @intCast(u32, dbg_info.items.len); |
| 280 | | const addr = switch (reloc.mcv) { |
| 281 | | .memory => |addr| addr, |
| 282 | | else => 0, |
| 283 | | }; |
| 284 | | switch (ptr_width) { |
| 285 | | 0...4 => { |
| 286 | | try dbg_info.writer().writeInt(u32, @intCast(u32, addr), endian); |
| 241 | break :blk .{ |
| 242 | .stack = .{ |
| 243 | .fp_register = Register.x29.dwarfLocOpDeref(), |
| 244 | .offset = adjusted_offset, |
| 287 | 245 | }, |
| 288 | | 5...8 => { |
| 289 | | try dbg_info.writer().writeInt(u64, addr, endian); |
| 290 | | }, |
| 291 | | else => unreachable, |
| 292 | | } |
| 293 | | if (is_ptr) { |
| 294 | | // We need deref the address as we point to the value via GOT entry. |
| 295 | | try dbg_info.append(DW.OP.deref); |
| 296 | | } |
| 297 | | switch (reloc.mcv) { |
| 298 | | .linker_load => |load_struct| try dw.addExprlocReloc( |
| 299 | | load_struct.sym_index, |
| 300 | | offset, |
| 301 | | is_ptr, |
| 302 | | ), |
| 303 | | else => {}, |
| 304 | | } |
| 305 | | }, |
| 306 | | |
| 307 | | .immediate => |x| { |
| 308 | | try dbg_info.ensureUnusedCapacity(2); |
| 309 | | const fixup = dbg_info.items.len; |
| 310 | | dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc |
| 311 | | 1, |
| 312 | | if (ty.isSignedInt()) DW.OP.consts else DW.OP.constu, |
| 313 | | }); |
| 314 | | if (ty.isSignedInt()) { |
| 315 | | try leb128.writeILEB128(dbg_info.writer(), @bitCast(i64, x)); |
| 316 | | } else { |
| 317 | | try leb128.writeULEB128(dbg_info.writer(), x); |
| 318 | | } |
| 319 | | try dbg_info.append(DW.OP.stack_value); |
| 320 | | dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2); |
| 321 | | }, |
| 322 | | |
| 323 | | .undef => { |
| 324 | | // DW.AT.location, DW.FORM.exprloc |
| 325 | | // uleb128(exprloc_len) |
| 326 | | // DW.OP.implicit_value uleb128(len_of_bytes) bytes |
| 327 | | const abi_size = @intCast(u32, ty.abiSize(function.target.*)); |
| 328 | | var implicit_value_len = std.ArrayList(u8).init(function.gpa); |
| 329 | | defer implicit_value_len.deinit(); |
| 330 | | try leb128.writeULEB128(implicit_value_len.writer(), abi_size); |
| 331 | | const total_exprloc_len = 1 + implicit_value_len.items.len + abi_size; |
| 332 | | try leb128.writeULEB128(dbg_info.writer(), total_exprloc_len); |
| 333 | | try dbg_info.ensureUnusedCapacity(total_exprloc_len); |
| 334 | | dbg_info.appendAssumeCapacity(DW.OP.implicit_value); |
| 335 | | dbg_info.appendSliceAssumeCapacity(implicit_value_len.items); |
| 336 | | dbg_info.appendNTimesAssumeCapacity(0xaa, abi_size); |
| 337 | | }, |
| 338 | | |
| 339 | | .none => { |
| 340 | | try dbg_info.ensureUnusedCapacity(3); |
| 341 | | dbg_info.appendSliceAssumeCapacity(&[3]u8{ // DW.AT.location, DW.FORM.exprloc |
| 342 | | 2, DW.OP.lit0, DW.OP.stack_value, |
| 343 | | }); |
| 246 | }; |
| 344 | 247 | }, |
| 345 | | |
| 346 | | else => { |
| 347 | | try dbg_info.ensureUnusedCapacity(2); |
| 348 | | dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc |
| 349 | | 1, DW.OP.nop, |
| 350 | | }); |
| 248 | .memory => |address| .{ .memory = .{ |
| 249 | .address = address, |
| 250 | .is_ptr = is_ptr, |
| 251 | } }, |
| 252 | .linker_load => |linker_load| .{ .memory = .{ |
| 253 | .address = 0, |
| 254 | .is_ptr = is_ptr, |
| 255 | .linker_load = linker_load, |
| 256 | } }, |
| 257 | .immediate => |x| .{ .immediate = x }, |
| 258 | .undef => .undef, |
| 259 | .none => .none, |
| 260 | else => blk: { |
| 351 | 261 | log.debug("TODO generate debug info for {}", .{reloc.mcv}); |
| 262 | break :blk .nop; |
| 352 | 263 | }, |
| 353 | | } |
| 354 | | |
| 355 | | try dbg_info.ensureUnusedCapacity(5 + name_with_null.len); |
| 356 | | try function.addDbgInfoTypeReloc(ty); // DW.AT.type, DW.FORM.ref4 |
| 357 | | dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT.name, DW.FORM.string |
| 264 | }; |
| 265 | try dw.genVarDbgInfo(reloc.name, reloc.ty, atom, loc); |
| 358 | 266 | }, |
| 359 | 267 | .plan9 => {}, |
| 360 | 268 | .none => {}, |
| ... | ... | @@ -1071,28 +979,6 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void { |
| 1071 | 979 | try table.ensureUnusedCapacity(self.gpa, additional_count); |
| 1072 | 980 | } |
| 1073 | 981 | |
| 1074 | | /// Adds a Type to the .debug_info at the current position. The bytes will be populated later, |
| 1075 | | /// after codegen for this symbol is done. |
| 1076 | | fn addDbgInfoTypeReloc(self: Self, ty: Type) !void { |
| 1077 | | switch (self.debug_output) { |
| 1078 | | .dwarf => |dw| { |
| 1079 | | const dbg_info = &dw.dbg_info; |
| 1080 | | const index = dbg_info.items.len; |
| 1081 | | try dbg_info.resize(index + 4); // DW.AT.type, DW.FORM.ref4 |
| 1082 | | const mod = self.bin_file.options.module.?; |
| 1083 | | const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl); |
| 1084 | | const atom = switch (self.bin_file.tag) { |
| 1085 | | .elf => &fn_owner_decl.link.elf.dbg_info_atom, |
| 1086 | | .macho => &fn_owner_decl.link.macho.dbg_info_atom, |
| 1087 | | else => unreachable, |
| 1088 | | }; |
| 1089 | | try dw.addTypeRelocGlobal(atom, ty, @intCast(u32, index)); |
| 1090 | | }, |
| 1091 | | .plan9 => {}, |
| 1092 | | .none => {}, |
| 1093 | | } |
| 1094 | | } |
| 1095 | | |
| 1096 | 982 | fn allocMem( |
| 1097 | 983 | self: *Self, |
| 1098 | 984 | abi_size: u32, |