diff --git a/src/link/Dwarf2.zig b/src/link/Dwarf2.zig index bea17968b46b9a51fc250168fc84517fb908124b..657a07821d49a195e5057bf2e472c1984596a438 100644 --- a/src/link/Dwarf2.zig +++ b/src/link/Dwarf2.zig @@ -4,7 +4,7 @@ endian: std.lang.Endian, address_size: AddressSize, const_pool: link.ConstPool, -units: std.array_hash_map.Auto(*Module, Unit), +units: []Unit, /// Indices are `link.ConstPool.Index`. consts: std.ArrayList(Const), globals: std.array_hash_map.Auto(InternPool.Nav.Index, Global), @@ -23,6 +23,7 @@ debug_str_offsets: StrOffsets, pub const AddressSize = enum(u8) { @"32" = 4, @"64" = 8, _ }; pub const Unit = struct { + alive: bool, dirs: std.array_hash_map.Auto(Unit.Index, void), files: std.array_hash_map.Auto(Zcu.File.Index, void), frame_ni: MappedFile.Node.Index.Optional, @@ -40,11 +41,11 @@ pub const Unit = struct { _, pub fn mod(ui: Unit.Index, dwarf: *Dwarf) *Module { - return dwarf.units.keys()[@backingInt(ui)]; + return dwarf.lf.comp.zcu.?.module_roots.keys()[@backingInt(ui)]; } pub fn get(ui: Unit.Index, dwarf: *Dwarf) *Unit { - return &dwarf.units.values()[@backingInt(ui)]; + return &dwarf.units[@backingInt(ui)]; } }; @@ -221,7 +222,11 @@ pub const Str = struct { }; }; -pub const Rnglists = struct {}; +pub const Rnglists = struct { + fn offsetsTableOffset(dwarf: *Dwarf) usize { + return dwarf.unitLengthSize() + 2 + 1 + 1 + 4; + } +}; pub const StrOffsets = struct { ni: MappedFile.Node.Index.Optional, @@ -630,8 +635,7 @@ pub const WipNav = struct { const zcu = debug.pt.zcu; const ip = &zcu.intern_pool; const func = zcu.funcInfo(debug.wip_nav.func); - const src_inst = ip.getNav(func.owner_nav).srcInst(ip); - const inst_info = src_inst.resolveFull(ip).?; + const inst_info = ip.getNav(func.owner_nav).srcInst(ip).resolveFull(ip).?; const decl = zcu.fileByIndex(inst_info.file).zir.?.getDeclaration(inst_info.inst); const nav = ip.getNav(func.owner_nav); const diw = &debug.info_writer.interface; @@ -1087,7 +1091,7 @@ pub const WipNav = struct { fn strpFmt(debug: *Debug, comptime fmt: []const u8, args: anytype) link.EmitError!void { const gpa = debug.pt.zcu.gpa; - const str = try std.fmt.allocPrint(gpa, fmt, args); + const str = try gpa.print(fmt, args); defer gpa.free(str); try debug.strp(str); } @@ -1341,7 +1345,7 @@ pub fn init(lf: *link.File, format: DW.Format) Dwarf { .endian = target.cpu.arch.endian(), .const_pool = .empty, - .units = .empty, + .units = &.{}, .consts = .empty, .globals = .empty, .funcs = .empty, @@ -1414,8 +1418,8 @@ pub fn init(lf: *link.File, format: DW.Format) Dwarf { pub fn deinit(dwarf: *Dwarf) void { const gpa = dwarf.lf.comp.gpa; dwarf.const_pool.deinit(gpa); - for (dwarf.units.values()) |*unit| unit.deinit(gpa); - dwarf.units.deinit(gpa); + for (dwarf.units) |*unit| unit.deinit(gpa); + gpa.free(dwarf.units); dwarf.consts.deinit(gpa); dwarf.globals.deinit(gpa); dwarf.funcs.deinit(gpa); @@ -1425,38 +1429,47 @@ pub fn deinit(dwarf: *Dwarf) void { dwarf.* = undefined; } -pub fn updateUnits(dwarf: *Dwarf, zcu: *Zcu) std.mem.Allocator.Error!void { - try dwarf.units.ensureTotalCapacity(zcu.gpa, zcu.module_roots.count() - dwarf.units.count()); - for (zcu.module_roots.keys(), zcu.module_roots.values()) |mod, root| if (root.unwrap()) |root_zfi| { - if (!zcu.alive_files.contains(root_zfi)) continue; +pub fn initUnits(dwarf: *Dwarf, gpa: std.mem.Allocator, units_len: usize) std.mem.Allocator.Error!void { + assert(dwarf.units.len == 0); + dwarf.units = try gpa.alloc(Unit, units_len); + @memset(dwarf.units, .{ + .alive = false, + .dirs = .empty, + .files = .empty, + .frame_ni = .none, + .cie_ni = .none, + .debug_info_ni = .none, + .debug_info_header_ni = .none, + .debug_line_ni = .none, + .debug_line_header_ni = .none, + .debug_line_header_changed = false, + .debug_rnglists_ni = .none, + .debug_rnglists_offsets_table_offset = undefined, + .debug_rnglists_end = undefined, + }); +} +pub fn updateUnits(dwarf: *Dwarf, zcu: *Zcu) std.mem.Allocator.Error!bool { + var units_changed = false; + for (zcu.module_roots.values(), dwarf.units, 0..) |root, *unit, ui| { + const root_zfi = root.unwrap() orelse continue; // non-zig + const alive = zcu.alive_files.contains(root_zfi); + if (unit.alive == alive) continue; // unchanged + unit.alive = alive; + units_changed = true; + if (!alive) continue; // unreferenced assert(zcu.fileByIndex(root_zfi).mod != null); - const unit_gop = dwarf.units.getOrPutAssumeCapacity(mod); - if (unit_gop.found_existing) continue; - unit_gop.value_ptr.* = .{ - .dirs = .empty, - .files = .empty, - .frame_ni = .none, - .cie_ni = .none, - .debug_info_ni = .none, - .debug_info_header_ni = .none, - .debug_line_ni = .none, - .debug_line_header_ni = .none, - .debug_line_header_changed = true, - .debug_rnglists_ni = .none, - .debug_rnglists_offsets_table_offset = undefined, - .debug_rnglists_end = undefined, - }; - const root_di, const root_fi = try unit_gop.value_ptr.getFile( + const root_di, const root_fi = try unit.getFile( zcu.gpa, - @fromBackingInt(@intCast(unit_gop.index)), + @fromBackingInt(@intCast(ui)), root_zfi, ); assert(root_di == .root and root_fi == .root); - }; + } + return units_changed; } pub fn getUnit(dwarf: *Dwarf, mod: *Module) Unit.Index { - return @fromBackingInt(@intCast(dwarf.units.getIndex(mod).?)); + return @fromBackingInt(@intCast(dwarf.lf.comp.zcu.?.module_roots.getIndex(mod).?)); } pub fn getConst(dwarf: *Dwarf, pt: Zcu.PerThread, val: Value) link.Error!link.ConstPool.Index { @@ -1678,10 +1691,10 @@ pub fn genDebugInfoHeader( mod: *Module, unit: *Unit, dih_nw: *MappedFile.Node.Writer, - debug_rnglists_offsets_table_offset: usize, ) link.EmitError!void { const comp = zcu.comp; const dihw = &dih_nw.interface; + if (!unit.alive) return dwarf.genUnitPadding(dihw); try dwarf.genUnitLength(dihw); try dihw.writeInt(u16, 5, dwarf.endian); try dihw.writeByte(DW.UT.compile); @@ -1704,7 +1717,7 @@ pub fn genDebugInfoHeader( try dwarf.sectionOffset( dih_nw, unit.debug_rnglists_ni.unwrap().?, - debug_rnglists_offsets_table_offset, + Rnglists.offsetsTableOffset(dwarf), ); try dihw.writeUleb128(0); const module_offset = dihw.end; @@ -1715,31 +1728,27 @@ pub fn genDebugInfoHeader( zcu.builtin_modules.get(mod.getBuiltinOptions(comp.config).hash()).?, zcu.root_mod, zcu.std_mod, - }) |name, dep| try dwarf.genModuleDependency(zcu, dih_nw, name, dep, module_offset); + }) |name, dep| try dwarf.genModuleDependency(dih_nw, name, dep, module_offset); for (mod.deps.keys(), mod.deps.values()) |name, dep| - try dwarf.genModuleDependency(zcu, dih_nw, name, dep, module_offset); + try dwarf.genModuleDependency(dih_nw, name, dep, module_offset); for ([2]AbbrevCode{ .pad_1, .pad_n }) |pad| _ = try dwarf.refAbbrevCode(pad); try dwarf.genDebugInfoPadding(dihw, dihw.unusedCapacityLen()); } fn genModuleDependency( dwarf: *Dwarf, - zcu: *Zcu, nw: *MappedFile.Node.Writer, name: []const u8, dep: *Module, module_offset: usize, ) link.EmitError!void { - if (!zcu.alive_files.contains(zcu.module_roots.get(dep).?.unwrap() orelse return)) return; + const dep_unit = dwarf.getUnit(dep).get(dwarf); + if (!dep_unit.alive) return; const diw = &nw.interface; try diw.writeUleb128(try dwarf.refAbbrevCode(.module_dependency)); try diw.writeAll(name); try diw.writeByte(0); - try dwarf.sectionOffset( - nw, - dwarf.getUnit(dep).get(dwarf).debug_info_header_ni.unwrap().?, - module_offset, - ); + try dwarf.sectionOffset(nw, dep_unit.debug_info_header_ni.unwrap().?, module_offset); } pub fn genDebugInfoPadding(dwarf: *Dwarf, diw: *Writer, size: u64) Writer.Error!void { @@ -1899,21 +1908,20 @@ pub fn genDebugRnglistsHeader( dwarf: *Dwarf, unit: *Unit, drh_nw: *MappedFile.Node.Writer, -) Writer.Error!usize { +) Writer.Error!void { const drhw = &drh_nw.interface; try dwarf.genUnitLength(drhw); try drhw.writeInt(u16, 5, dwarf.endian); try drhw.writeByte(@backingInt(dwarf.address_size)); try drhw.writeByte(0); try drhw.writeInt(u32, 1, dwarf.endian); - const offsets_table_offset = drhw.end; + assert(drhw.end == Rnglists.offsetsTableOffset(dwarf)); switch (dwarf.format) { .@"32" => try drhw.writeInt(u32, 4, dwarf.endian), .@"64" => try drhw.writeInt(u64, 8, dwarf.endian), } unit.debug_rnglists_end = drhw.end; try drhw.writeByte(DW.RLE.end_of_list); - return offsets_table_offset; } pub fn genDebugRnglists( @@ -2097,16 +2105,18 @@ pub fn updateConst(dwarf: *Dwarf, cpi: link.ConstPool.Index, val: InternPool.Ind pub fn updateConstIncomplete( dwarf: *Dwarf, + pt: Zcu.PerThread, di_nw: *MappedFile.Node.Writer, val: InternPool.Index, ) link.Error!void { - dwarf.updateConstIncompleteInner(di_nw, val) catch |err| switch (err) { + dwarf.updateConstIncompleteInner(pt, di_nw, val) catch |err| switch (err) { else => |e| return e, error.WriteFailed => return dwarf.reportWriteError(di_nw), }; } fn updateConstIncompleteInner( dwarf: *Dwarf, + pt: Zcu.PerThread, di_nw: *MappedFile.Node.Writer, val: InternPool.Index, ) link.EmitError!void { @@ -2114,23 +2124,87 @@ fn updateConstIncompleteInner( const zcu = comp.zcu.?; const ip = &zcu.intern_pool; const diw = &di_nw.interface; - emit: switch (ip.indexToKey(val)) { - .struct_type => { - const loaded_struct = ip.loadStructType(val); - if (loaded_struct.zir_index.resolveFull(ip)) |src_inst| switch (src_inst.inst) { - .main_struct_inst => { - const ui = dwarf.getUnit(comp.zcu.?.fileByIndex(src_inst.file).mod.?); - _, const fi = try ui.get(dwarf).getFile(comp.gpa, ui, src_inst.file); - try diw.writeUleb128(try dwarf.refAbbrevCode(.empty_file)); - try diw.writeUleb128(@backingInt(fi)); - try dwarf.strp(&dwarf.debug_str, di_nw, loaded_struct.name.toSlice(ip)); - break :emit; + done: { + const zir_index, const name, const maybe_name_nav = container: switch (ip.indexToKey(val)) { + .struct_type => { + const loaded_struct = ip.loadStructType(val); + if (loaded_struct.zir_index.resolveFull(ip)) |src_inst| switch (src_inst.inst) { + .main_struct_inst => { + const ui = dwarf.getUnit(comp.zcu.?.fileByIndex(src_inst.file).mod.?); + _, const fi = try ui.get(dwarf).getFile(comp.gpa, ui, src_inst.file); + try diw.writeUleb128(try dwarf.refAbbrevCode(.empty_file)); + try diw.writeUleb128(@backingInt(fi)); + try dwarf.strp(&dwarf.debug_str, di_nw, loaded_struct.name.toSlice(ip)); + break :done; + }, + else => {}, + }; + break :container .{ + loaded_struct.zir_index, + loaded_struct.name, + loaded_struct.name_nav, + }; + }, + .union_type => { + const loaded_union = ip.loadUnionType(val); + break :container .{ loaded_union.zir_index, loaded_union.name, loaded_union.name_nav }; + }, + .enum_type => { + const loaded_enum = ip.loadEnumType(val); + if (loaded_enum.zir_index.unwrap()) |zir_index| + break :container .{ zir_index, loaded_enum.name, loaded_enum.name_nav }; + try diw.writeUleb128(try dwarf.refAbbrevCode(.generated_empty_struct_type)); + try dwarf.strp(&dwarf.debug_str, di_nw, loaded_enum.name.toSlice(ip)); + try diw.writeByte(@intFromBool(true)); + break :done; + }, + .opaque_type => { + const loaded_opaque = ip.loadOpaqueType(val); + break :container .{ + loaded_opaque.zir_index, + loaded_opaque.name, + loaded_opaque.name_nav, + }; + }, + else => |val_key| break :done switch (val_key.typeOf()) { + .type_type => { + const name = try comp.gpa.print("{f}", .{Type.fromInterned(val).fmt(pt)}); + defer comp.gpa.free(name); + try diw.writeUleb128(try dwarf.refAbbrevCode(.generated_empty_struct_type)); + try dwarf.strp(&dwarf.debug_str, di_nw, name); + try diw.writeByte(@intFromBool(true)); }, - else => return, - }; - return; - }, - else => return, + else => |ty| { + const ty_cpi = try dwarf.getConst(pt, Value.fromInterned(ty)); + try diw.writeUleb128(try dwarf.refAbbrevCode(.undefined_comptime_value)); + try dwarf.sectionOffset( + di_nw, + Const.get(ty_cpi, dwarf).debug_info_ni.unwrap().?, + 0, + ); + }, + }, + }; + if (maybe_name_nav.unwrap()) |name_nav| { + const src_inst = ip.getNav(name_nav).srcInst(ip).resolveFull(ip).?; + const decl = zcu.fileByIndex(src_inst.file).zir.?.getDeclaration(src_inst.inst); + const parent_cpi = try dwarf.getConst(pt, .fromInterned(zcu.fileRootType(src_inst.file))); + try diw.writeUleb128(try dwarf.refAbbrevCode(.decl_func_generic)); + try dwarf.sectionOffset(di_nw, Const.get(parent_cpi, dwarf).debug_info_ni.unwrap().?, 0); + try diw.writeInt(u32, decl.src_line + 1, dwarf.endian); + try diw.writeUleb128(decl.src_column + 1); + try diw.writeByte(if (decl.is_pub) DW.ACCESS.public else DW.ACCESS.private); + try dwarf.strp(&dwarf.debug_str, di_nw, name.toSlice(ip)); + try diw.writeUleb128(@backingInt(AbbrevCode.null)); + } else { + const zfi = zir_index.resolveFile(ip); + const ui = dwarf.getUnit(zcu.fileByIndex(zfi).mod.?); + _, const fi = try ui.get(dwarf).getFile(comp.gpa, ui, zfi); + try diw.writeUleb128(try dwarf.refAbbrevCode(.empty_struct_type)); + try diw.writeUleb128(@backingInt(fi)); + try dwarf.strp(&dwarf.debug_str, di_nw, name.toSlice(ip)); + } + try diw.writeByte(@intFromBool(true)); } try dwarf.genDebugInfoPadding(diw, diw.unusedCapacityLen()); } diff --git a/src/link/Elf2.zig b/src/link/Elf2.zig index 1388fbcf4cf5be95b3c1a83341f05cd5289eeffc..183560e4f64d41cfacfb574facf630a9366770d2 100644 --- a/src/link/Elf2.zig +++ b/src/link/Elf2.zig @@ -212,37 +212,11 @@ changed_symtab_index: std.array_hash_map.Auto(String(.strtab), void), textrel_count: u32, dwarf: Dwarf, -dwarf_shared: std.enums.EnumArray(Dwarf.SharedSection, struct { - first_target_reloc: NodeReloc.Index, -}), -dwarf_units: std.ArrayList(struct { - frame_cie_first_target_reloc: NodeReloc.Index, - debug_info_header_first_target_reloc: NodeReloc.Index, - debug_info_header_first_node_reloc: NodeReloc.Index, - debug_line_header_first_target_reloc: NodeReloc.Index, - debug_line_header_first_node_reloc: NodeReloc.Index, - debug_rnglists_first_target_reloc: NodeReloc.Index, - debug_rnglists_symbol_relocs: std.array_hash_map.Auto(SymbolReloc.Index, void), -}), -dwarf_consts: std.array_hash_map.Auto(link.ConstPool.Index, struct { - debug_info_first_target_reloc: NodeReloc.Index, - debug_info_first_symbol_reloc: SymbolReloc.Index, - debug_info_first_node_reloc: NodeReloc.Index, -}), -dwarf_globals: std.ArrayList(struct { - debug_info_first_target_reloc: NodeReloc.Index, - debug_info_first_symbol_reloc: SymbolReloc.Index, - debug_info_first_node_reloc: NodeReloc.Index, -}), -dwarf_funcs: std.ArrayList(struct { - frame_fde_first_symbol_reloc: SymbolReloc.Index, - frame_fde_first_node_reloc: NodeReloc.Index, - debug_info_first_target_reloc: NodeReloc.Index, - debug_info_first_symbol_reloc: SymbolReloc.Index, - debug_info_first_node_reloc: NodeReloc.Index, - debug_line_first_symbol_reloc: SymbolReloc.Index, - debug_line_first_node_reloc: NodeReloc.Index, -}), +dwarf_shared: std.enums.EnumArray(Dwarf.SharedSection, dwarf_relocs.Shared), +dwarf_units: []dwarf_relocs.Unit, +dwarf_consts: std.array_hash_map.Auto(link.ConstPool.Index, dwarf_relocs.Const), +dwarf_globals: std.ArrayList(dwarf_relocs.Global), +dwarf_funcs: std.ArrayList(dwarf_relocs.Func), overflowed_reloc_count: u32, misaligned_reloc_count: u32, @@ -878,6 +852,40 @@ const Section = struct { }; }; +const dwarf_relocs = struct { + const Shared = struct { + first_target_reloc: NodeReloc.Index, + }; + const Unit = struct { + frame_cie_first_target_reloc: NodeReloc.Index, + debug_info_header_first_target_reloc: NodeReloc.Index, + debug_info_header_first_node_reloc: NodeReloc.Index, + debug_line_header_first_target_reloc: NodeReloc.Index, + debug_line_header_first_node_reloc: NodeReloc.Index, + debug_rnglists_first_target_reloc: NodeReloc.Index, + debug_rnglists_symbol_relocs: std.array_hash_map.Auto(SymbolReloc.Index, void), + }; + const Const = struct { + debug_info_first_target_reloc: NodeReloc.Index, + debug_info_first_symbol_reloc: SymbolReloc.Index, + debug_info_first_node_reloc: NodeReloc.Index, + }; + const Global = struct { + debug_info_first_target_reloc: NodeReloc.Index, + debug_info_first_symbol_reloc: SymbolReloc.Index, + debug_info_first_node_reloc: NodeReloc.Index, + }; + const Func = struct { + frame_fde_first_symbol_reloc: SymbolReloc.Index, + frame_fde_first_node_reloc: NodeReloc.Index, + debug_info_first_target_reloc: NodeReloc.Index, + debug_info_first_symbol_reloc: SymbolReloc.Index, + debug_info_first_node_reloc: NodeReloc.Index, + debug_line_first_symbol_reloc: SymbolReloc.Index, + debug_line_first_node_reloc: NodeReloc.Index, + }; +}; + pub const MachineRelocType = union { AARCH64: std.elf.R_AARCH64, LARCH: std.elf.R_LARCH, @@ -1859,10 +1867,10 @@ const NodeReloc = struct { const first_target_reloc = switch (elf.getNode(reloc.target)) { else => unreachable, .debug_shared => |ss| &elf.dwarf_shared.getPtr(ss).first_target_reloc, - .unit_frame_cie => |ui| &elf.dwarf_units.items[@backingInt(ui)].frame_cie_first_target_reloc, - .unit_debug_info_header => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_info_header_first_target_reloc, - .unit_debug_line_header => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_line_header_first_target_reloc, - .unit_debug_rnglists => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_rnglists_first_target_reloc, + .unit_frame_cie => |ui| &elf.dwarf_units[@backingInt(ui)].frame_cie_first_target_reloc, + .unit_debug_info_header => |ui| &elf.dwarf_units[@backingInt(ui)].debug_info_header_first_target_reloc, + .unit_debug_line_header => |ui| &elf.dwarf_units[@backingInt(ui)].debug_line_header_first_target_reloc, + .unit_debug_rnglists => |ui| &elf.dwarf_units[@backingInt(ui)].debug_rnglists_first_target_reloc, .const_debug_info => |cpi| &elf.dwarf_consts.getPtr(cpi).?.debug_info_first_target_reloc, .global_debug_info => |gi| &elf.dwarf_globals.items[@backingInt(gi)].debug_info_first_target_reloc, .func_debug_info => |fi| &elf.dwarf_funcs.items[@backingInt(fi)].debug_info_first_target_reloc, @@ -3829,7 +3837,7 @@ fn create( .dwarf_shared = comptime .initFill(.{ .first_target_reloc = .none, }), - .dwarf_units = .empty, + .dwarf_units = &.{}, .dwarf_consts = .empty, .dwarf_globals = .empty, .dwarf_funcs = .empty, @@ -3883,8 +3891,8 @@ pub fn deinit(elf: *Elf) void { elf.changed_symtab_index.deinit(gpa); elf.dwarf.deinit(); - for (elf.dwarf_units.items) |*dwarf_unit| dwarf_unit.debug_rnglists_symbol_relocs.deinit(gpa); - elf.dwarf_units.deinit(gpa); + for (elf.dwarf_units) |*dwarf_unit| dwarf_unit.debug_rnglists_symbol_relocs.deinit(gpa); + gpa.free(elf.dwarf_units); elf.dwarf_consts.deinit(gpa); elf.dwarf_globals.deinit(gpa); elf.dwarf_funcs.deinit(gpa); @@ -4286,8 +4294,8 @@ fn initHeaders( } elf.ni.shdr = elf.addNodeAssumeCapacity(try elf.ni.elf.addFloatingChild(gpa, &elf.mf, .{ - .size = node_block_align.forward(1 * entsize.sh), // as above, only the SHN_UNDEF initially - .alignment = addr_align.max(node_block_align), + .size = 1 * entsize.sh, // as above, only the null shdr initially + .alignment = addr_align, .moved = true, .resized = true, }), .shdr); @@ -5357,10 +5365,10 @@ fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void { .first_got_reloc = &elf.lazy.getPtr(lmi.ref().kind).values()[lmi.ref().index].first_got_reloc, }, .unit_debug_info_header => |ui| .{ - .first_node_reloc = &elf.dwarf_units.items[@backingInt(ui)].debug_info_header_first_node_reloc, + .first_node_reloc = &elf.dwarf_units[@backingInt(ui)].debug_info_header_first_node_reloc, }, .unit_debug_line_header => |ui| .{ - .first_node_reloc = &elf.dwarf_units.items[@backingInt(ui)].debug_line_header_first_node_reloc, + .first_node_reloc = &elf.dwarf_units[@backingInt(ui)].debug_line_header_first_node_reloc, }, .unit_debug_rnglists => unreachable, // unsupported .const_debug_info => |cpi| .{ @@ -5744,13 +5752,12 @@ const ShdrPtr = union(std.elf.CLASS) { @"64": *std.elf.Elf64.Shdr, }; fn shdrPtr(elf: *Elf, shndx: Section.Index) ShdrPtr { - const raw_slice = elf.ni.shdr.slice(&elf.mf); + const slice = elf.ni.shdr.slice(&elf.mf); switch (elf.identClass()) { .NONE, _ => unreachable, inline else => |class| { - const shdrs_len = elf.shdrs.items.len + 1; // +1 for SHN_UNDEF const shdr_slice: []class.ElfN().Shdr = @ptrCast(@alignCast( - raw_slice[0 .. shdrs_len * @sizeOf(class.ElfN().Shdr)], + slice[0 .. @sizeOf(class.ElfN().Shdr) * (1 + elf.shdrs.items.len)], )); const shdr_ptr = &shdr_slice[@backingInt(shndx)]; return @unionInit(ShdrPtr, @tagName(class), shdr_ptr); @@ -7196,104 +7203,110 @@ pub fn zcuFilesReady(elf: *Elf, zcu: *Zcu) link.Error!void { } fn zcuFilesReadyInner(elf: *Elf, zcu: *Zcu) Error!void { const gpa = zcu.gpa; - - try elf.dwarf.updateUnits(zcu); - const old_units_len = elf.dwarf_units.items.len; - const new_units_len = elf.dwarf.units.count(); - try elf.dwarf_units.appendNTimes(gpa, .{ - .frame_cie_first_target_reloc = .none, - .debug_info_header_first_target_reloc = .none, - .debug_info_header_first_node_reloc = .none, - .debug_line_header_first_target_reloc = .none, - .debug_line_header_first_node_reloc = .none, - .debug_rnglists_first_target_reloc = .none, - .debug_rnglists_symbol_relocs = .empty, - }, new_units_len - old_units_len); - try elf.nodes.ensureUnusedCapacity(gpa, 5 * (new_units_len - old_units_len)); - - for (old_units_len.., elf.dwarf.units.values()[old_units_len..]) |unit_index, *unit| { + const units_len = zcu.module_roots.count(); + if (elf.dwarf_units.len == 0) { + @branchHint(.unlikely); + try elf.dwarf.initUnits(gpa, units_len); + elf.dwarf_units = try gpa.alloc(dwarf_relocs.Unit, zcu.module_roots.count()); + @memset(elf.dwarf_units, .{ + .frame_cie_first_target_reloc = .none, + .debug_info_header_first_target_reloc = .none, + .debug_info_header_first_node_reloc = .none, + .debug_line_header_first_target_reloc = .none, + .debug_line_header_first_node_reloc = .none, + .debug_rnglists_first_target_reloc = .none, + .debug_rnglists_symbol_relocs = .empty, + }); + } + if (!try elf.dwarf.updateUnits(zcu)) return; + try elf.nodes.ensureUnusedCapacity(gpa, 5 * units_len); + for (0..units_len) |unit_index| { const ui: Dwarf.Unit.Index = @fromBackingInt(@intCast(unit_index)); + const unit = ui.get(&elf.dwarf); + if (!unit.alive) continue; switch (elf.shndx.debug_info) { .UNDEF => {}, else => |debug_info_shndx| { - const debug_info_ni = elf.addNodeAssumeCapacity( - try debug_info_shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{ - .alignment = elf.mf.flags.block_size, - .enable_next_moved = true, - }), - .{ .unit_debug_info = ui }, - ); - unit.debug_info_ni = .wrap(debug_info_ni); + const debug_info_ni = unit.debug_info_ni.unwrap() orelse debug_info_ni: { + const debug_info_ni = elf.addNodeAssumeCapacity( + try debug_info_shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{ + .alignment = elf.mf.flags.block_size, + .enable_next_moved = true, + }), + .{ .unit_debug_info = ui }, + ); + unit.debug_info_ni = .wrap(debug_info_ni); + break :debug_info_ni debug_info_ni; + }; - unit.debug_info_header_ni = .wrap(elf.addNodeAssumeCapacity( - try debug_info_ni.addOnlyHeaderChild(gpa, &elf.mf, .{ + if (unit.debug_info_header_ni == .none) unit.debug_info_header_ni = .wrap( + elf.addNodeAssumeCapacity(try debug_info_ni.addOnlyHeaderChild(gpa, &elf.mf, .{ .next_moved = true, .enable_next_moved = true, - }), - .{ .unit_debug_info_header = ui }, - )); + }), .{ .unit_debug_info_header = ui }), + ); }, } switch (elf.shndx.debug_line) { .UNDEF => {}, else => |debug_line_shndx| { - const debug_line_ni = elf.addNodeAssumeCapacity( - try debug_line_shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{ - .alignment = elf.mf.flags.block_size, - .enable_next_moved = true, - }), - .{ .unit_debug_line = ui }, - ); - unit.debug_line_ni = .wrap(debug_line_ni); + const debug_line_ni = unit.debug_line_ni.unwrap() orelse debug_line_ni: { + const debug_line_ni = elf.addNodeAssumeCapacity( + try debug_line_shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{ + .alignment = elf.mf.flags.block_size, + .enable_next_moved = true, + }), + .{ .unit_debug_line = ui }, + ); + unit.debug_line_ni = .wrap(debug_line_ni); + break :debug_line_ni debug_line_ni; + }; - unit.debug_line_header_ni = .wrap(elf.addNodeAssumeCapacity( - try debug_line_ni.addOnlyHeaderChild(gpa, &elf.mf, .{ + if (unit.debug_line_header_ni == .none) unit.debug_line_header_ni = .wrap( + elf.addNodeAssumeCapacity(try debug_line_ni.addOnlyHeaderChild(gpa, &elf.mf, .{ // Idle tasks are going to try to keep this up to date before we are able to // write out the full header, so just reserve space for them to do so. .size = elf.dwarf.unitLengthSize(), .enable_next_moved = true, - }), - .{ .unit_debug_line_header = ui }, - )); + }), .{ .unit_debug_line_header = ui }), + ); }, } switch (elf.shndx.debug_rnglists) { .UNDEF => {}, - else => |debug_rnglists_shndx| unit.debug_rnglists_ni = .wrap(elf.addNodeAssumeCapacity( - try debug_rnglists_shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{ - .next_moved = true, - .enable_next_moved = true, - }), - .{ .unit_debug_rnglists = ui }, - )), + else => |debug_rnglists_shndx| { + const debug_rnglists_ni = unit.debug_rnglists_ni.unwrap() orelse debug_rnglists_ni: { + const debug_rnglists_ni = elf.addNodeAssumeCapacity( + try debug_rnglists_shndx.get(elf).ni.addFloatingChild(gpa, &elf.mf, .{ + .next_moved = true, + .enable_next_moved = true, + }), + .{ .unit_debug_rnglists = ui }, + ); + unit.debug_rnglists_ni = .wrap(debug_rnglists_ni); + break :debug_rnglists_ni debug_rnglists_ni; + }; + + var drh_nw: MappedFile.Node.Writer = undefined; + debug_rnglists_ni.writer(gpa, &elf.mf, &drh_nw); + defer drh_nw.deinit(); + elf.dwarf.genDebugRnglistsHeader(unit, &drh_nw) catch |err| switch (err) { + else => |e| return e, + error.WriteFailed => return drh_nw.err.?, + }; + }, } } - - for ( - elf.dwarf.units.keys()[old_units_len..], - elf.dwarf.units.values()[old_units_len..], - ) |mod, *unit| { - var drh_nw: MappedFile.Node.Writer = undefined; - unit.debug_rnglists_ni.unwrap().?.writer(gpa, &elf.mf, &drh_nw); - defer drh_nw.deinit(); - const debug_rnglists_offsets_table_offset = - elf.dwarf.genDebugRnglistsHeader(unit, &drh_nw) catch |err| switch (err) { - else => |e| return e, - error.WriteFailed => return drh_nw.err.?, - }; - + for (0..units_len) |unit_index| { + const ui: Dwarf.Unit.Index = @fromBackingInt(@intCast(unit_index)); + const unit = ui.get(&elf.dwarf); + if (unit.debug_info_header_ni == .none) continue; var dih_nw: MappedFile.Node.Writer = undefined; const debug_info_header_ni = unit.debug_info_header_ni.unwrap().?; debug_info_header_ni.writer(gpa, &elf.mf, &dih_nw); defer dih_nw.deinit(); elf.resetNodeRelocs(debug_info_header_ni); - elf.dwarf.genDebugInfoHeader( - zcu, - mod, - unit, - &dih_nw, - debug_rnglists_offsets_table_offset, - ) catch |err| switch (err) { + elf.dwarf.genDebugInfoHeader(zcu, ui.mod(&elf.dwarf), unit, &dih_nw) catch |err| switch (err) { else => |e| return e, error.WriteFailed => return dih_nw.err.?, }; @@ -7302,8 +7315,9 @@ fn zcuFilesReadyInner(elf: *Elf, zcu: *Zcu) Error!void { fn flushFiles(elf: *Elf) Error!void { const gpa = elf.base.comp.gpa; - if (elf.shndx.debug_line != .UNDEF) for (elf.dwarf.units.values()) |*unit| { + if (elf.shndx.debug_line != .UNDEF) for (elf.dwarf.units) |*unit| { if (!unit.cleanDebugLineHeaderChanged()) continue; + assert(unit.alive); const debug_line_header_ni = unit.debug_line_header_ni.unwrap().?; try debug_line_header_ni.parent(&elf.mf).unwrap().?.nextMoved(gpa, &elf.mf); try debug_line_header_ni.moved(gpa, &elf.mf); @@ -8122,10 +8136,10 @@ fn addNodeRelocAssumeCapacity( const first_target_reloc = switch (elf.getNode(target)) { else => unreachable, .debug_shared => |ss| &elf.dwarf_shared.getPtr(ss).first_target_reloc, - .unit_frame_cie => |ui| &elf.dwarf_units.items[@backingInt(ui)].frame_cie_first_target_reloc, - .unit_debug_info_header => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_info_header_first_target_reloc, - .unit_debug_line_header => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_line_header_first_target_reloc, - .unit_debug_rnglists => |ui| &elf.dwarf_units.items[@backingInt(ui)].debug_rnglists_first_target_reloc, + .unit_frame_cie => |ui| &elf.dwarf_units[@backingInt(ui)].frame_cie_first_target_reloc, + .unit_debug_info_header => |ui| &elf.dwarf_units[@backingInt(ui)].debug_info_header_first_target_reloc, + .unit_debug_line_header => |ui| &elf.dwarf_units[@backingInt(ui)].debug_line_header_first_target_reloc, + .unit_debug_rnglists => |ui| &elf.dwarf_units[@backingInt(ui)].debug_rnglists_first_target_reloc, .const_debug_info => |cpi| &elf.dwarf_consts.getPtr(cpi).?.debug_info_first_target_reloc, .global_debug_info => |gi| &elf.dwarf_globals.items[@backingInt(gi)].debug_info_first_target_reloc, .func_debug_info => |fi| &elf.dwarf_funcs.items[@backingInt(fi)].debug_info_first_target_reloc, @@ -8621,7 +8635,7 @@ fn updateConstInner( pub fn updateConstIncomplete( elf: *Elf, - _: Zcu.PerThread, + pt: Zcu.PerThread, cpi: link.ConstPool.Index, val: InternPool.Index, ) link.Error!void { @@ -8629,7 +8643,7 @@ pub fn updateConstIncomplete( var di_nw: MappedFile.Node.Writer = undefined; debug_info_ni.writer(elf.base.comp.gpa, &elf.mf, &di_nw); defer di_nw.deinit(); - try elf.dwarf.updateConstIncomplete(&di_nw, val); + try elf.dwarf.updateConstIncomplete(pt, &di_nw, val); } pub fn updateFunc( @@ -8717,7 +8731,7 @@ fn updateFuncInner( unit.frame_ni = .wrap(frame_ni); break :frame_ni frame_ni; }; - _ = unit.cie_ni.unwrap() orelse { + if (unit.cie_ni == .none) { const cie_ni = elf.addNodeAssumeCapacity( try frame_ni.addOnlyHeaderChild(gpa, &elf.mf, .{ .alignment = frame_align, @@ -8736,19 +8750,19 @@ fn updateFuncInner( }, wip_nav.frame_format) catch |err| switch (err) { error.WriteFailed => return cie_nw.err.?, }; - }; + } const dwarf_func = dwarf_fi.get(dwarf); const fde_ni = if (dwarf_func.fde_ni.unwrap()) |fde_ni| fde_ni: { try fde_ni.moved(gpa, &elf.mf); try fde_ni.nextMoved(gpa, &elf.mf); break :fde_ni fde_ni; } else fde_ni: { - const fde_ni = try frame_ni.addFloatingChild(gpa, &elf.mf, .{ + const fde_ni = elf.addNodeAssumeCapacity(try frame_ni.addFloatingChild(gpa, &elf.mf, .{ .alignment = frame_align, .moved = true, .next_moved = true, .enable_next_moved = true, - }); + }), .{ .func_frame_fde = dwarf_fi }); dwarf_func.fde_ni = .wrap(fde_ni); break :fde_ni fde_ni; }; @@ -8868,7 +8882,7 @@ fn updateFuncInner( else => |e| return e, error.WriteFailed => return dr_nw.err.?, }; - const symbol_relocs = &elf.dwarf_units.items[@backingInt(debug.wip_nav.unit)] + const symbol_relocs = &elf.dwarf_units[@backingInt(debug.wip_nav.unit)] .debug_rnglists_symbol_relocs; try symbol_relocs.ensureUnusedCapacity(gpa, elf.symbol_relocs.items.len - first_symbol_reloc); @@ -9629,7 +9643,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void .unit_padding, .unit_frame, .unit_debug_info, .unit_debug_line => {}, .unit_frame_cie => |ui| { const target_section_offset = elf.computeNodeSectionOffset(ni); - var target_ri = elf.dwarf_units.items[@backingInt(ui)].frame_cie_first_target_reloc; + var target_ri = elf.dwarf_units[@backingInt(ui)].frame_cie_first_target_reloc; while (target_ri != .none) { const target_reloc = target_ri.get(elf); assert(target_reloc.target == ni); @@ -9638,7 +9652,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void } }, .unit_debug_info_header => |ui| { - const dwarf_unit = &elf.dwarf_units.items[@backingInt(ui)]; + const dwarf_unit = &elf.dwarf_units[@backingInt(ui)]; const target_section_offset = elf.computeNodeSectionOffset(ni); var target_ri = dwarf_unit.debug_info_header_first_target_reloc; while (target_ri != .none) { @@ -9652,7 +9666,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void }); }, .unit_debug_line_header => |ui| { - const dwarf_unit = &elf.dwarf_units.items[@backingInt(ui)]; + const dwarf_unit = &elf.dwarf_units[@backingInt(ui)]; const target_section_offset = elf.computeNodeSectionOffset(ni); var target_ri = dwarf_unit.debug_line_header_first_target_reloc; while (target_ri != .none) { @@ -9666,7 +9680,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void }); }, .unit_debug_rnglists => |ui| { - const dwarf_unit = &elf.dwarf_units.items[@backingInt(ui)]; + const dwarf_unit = &elf.dwarf_units[@backingInt(ui)]; const target_section_offset = elf.computeNodeSectionOffset(ni); var target_ri = dwarf_unit.debug_rnglists_first_target_reloc; while (target_ri != .none) {