authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-09-13 17:00:36+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-09-13 17:00:36+02:00
log4c36da1047a83019ce7af653a32938c9d1ea616d
tree7f5c1d0bd42379172c700c0edfb9355c93082767
parent1965465ced82dc9c0fb93ea9182f196e6d6f4409

macho: fix incremental compilation


3 files changed, 251 insertions(+), 192 deletions(-)

src/link/MachO.zig+238-192
......@@ -170,6 +170,8 @@ sections_order_dirty: bool = false,
170170has_dices: bool = false,
171171has_stabs: bool = false,
172172
173args_digest: [Cache.hex_digest_len]u8 = undefined,
174
173175section_ordinals: std.AutoArrayHashMapUnmanaged(MatchingSection, void) = .{},
174176
175177/// A list of atoms that have surplus capacity. This list can have false
......@@ -334,31 +336,31 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
334336 return self;
335337 }
336338
337 if (!options.strip and options.module != null) {
338 // Create dSYM bundle.
339 const dir = options.module.?.zig_cache_artifact_directory;
340 log.debug("creating {s}.dSYM bundle in {s}", .{ sub_path, dir.path });
339 // if (!options.strip and options.module != null) {
340 // // Create dSYM bundle.
341 // const dir = options.module.?.zig_cache_artifact_directory;
342 // log.debug("creating {s}.dSYM bundle in {s}", .{ sub_path, dir.path });
341343
342 const d_sym_path = try fmt.allocPrint(
343 allocator,
344 "{s}.dSYM" ++ fs.path.sep_str ++ "Contents" ++ fs.path.sep_str ++ "Resources" ++ fs.path.sep_str ++ "DWARF",
345 .{sub_path},
346 );
347 defer allocator.free(d_sym_path);
344 // const d_sym_path = try fmt.allocPrint(
345 // allocator,
346 // "{s}.dSYM" ++ fs.path.sep_str ++ "Contents" ++ fs.path.sep_str ++ "Resources" ++ fs.path.sep_str ++ "DWARF",
347 // .{sub_path},
348 // );
349 // defer allocator.free(d_sym_path);
348350
349 var d_sym_bundle = try dir.handle.makeOpenPath(d_sym_path, .{});
350 defer d_sym_bundle.close();
351 // var d_sym_bundle = try dir.handle.makeOpenPath(d_sym_path, .{});
352 // defer d_sym_bundle.close();
351353
352 const d_sym_file = try d_sym_bundle.createFile(sub_path, .{
353 .truncate = false,
354 .read = true,
355 });
354 // const d_sym_file = try d_sym_bundle.createFile(sub_path, .{
355 // .truncate = false,
356 // .read = true,
357 // });
356358
357 self.d_sym = .{
358 .base = self,
359 .file = d_sym_file,
360 };
361 }
359 // self.d_sym = .{
360 // .base = self,
361 // .file = d_sym_file,
362 // };
363 // }
362364
363365 // Index 0 is always a null symbol.
364366 try self.locals.append(allocator, .{
......@@ -555,218 +557,256 @@ pub fn flush(self: *MachO, comp: *Compilation) !void {
555557 try self.strtab.append(self.base.allocator, 0);
556558 }
557559
558 // Positional arguments to the linker such as object files and static archives.
559 var positionals = std.ArrayList([]const u8).init(arena);
560 const needs_full_relink = blk: {
561 if (use_stage1) break :blk true;
560562
561 try positionals.appendSlice(self.base.options.objects);
563 var hh: Cache.HashHelper = .{};
564 hh.addListOfBytes(self.base.options.objects);
565 for (comp.c_object_table.keys()) |key| {
566 hh.addBytes(key.status.success.object_path);
567 }
568 hh.addOptionalBytes(module_obj_path);
569 if (comp.compiler_rt_static_lib) |lib| {
570 hh.addBytes(lib.full_object_path);
571 }
572 if (self.base.options.link_libcpp) {
573 hh.addBytes(comp.libcxxabi_static_lib.?.full_object_path);
574 hh.addBytes(comp.libcxx_static_lib.?.full_object_path);
575 }
576 hh.addListOfBytes(self.base.options.lib_dirs);
577 hh.addListOfBytes(self.base.options.framework_dirs);
578 hh.addListOfBytes(self.base.options.frameworks);
579 hh.addListOfBytes(self.base.options.rpath_list);
580 hh.addStringSet(self.base.options.system_libs);
581 hh.addOptionalBytes(self.base.options.sysroot);
582 const new_digest = hh.final();
583 const needs_full_relink = !mem.eql(u8, &new_digest, &self.args_digest);
584 mem.copy(u8, &self.args_digest, &new_digest);
585 break :blk needs_full_relink;
586 };
562587
563 for (comp.c_object_table.keys()) |key| {
564 try positionals.append(key.status.success.object_path);
565 }
588 if (needs_full_relink) {
589 self.objects.clearRetainingCapacity();
590 self.archives.clearRetainingCapacity();
591 self.dylibs.clearRetainingCapacity();
592 self.dylibs_map.clearRetainingCapacity();
593 self.referenced_dylibs.clearRetainingCapacity();
566594
567 if (module_obj_path) |p| {
568 try positionals.append(p);
569 }
595 // TODO figure out how to clear atoms from objects, etc.
570596
571 if (comp.compiler_rt_static_lib) |lib| {
572 try positionals.append(lib.full_object_path);
573 }
597 // Positional arguments to the linker such as object files and static archives.
598 var positionals = std.ArrayList([]const u8).init(arena);
574599
575 // libc++ dep
576 if (self.base.options.link_libcpp) {
577 try positionals.append(comp.libcxxabi_static_lib.?.full_object_path);
578 try positionals.append(comp.libcxx_static_lib.?.full_object_path);
579 }
600 try positionals.appendSlice(self.base.options.objects);
580601
581 // Shared and static libraries passed via `-l` flag.
582 var search_lib_names = std.ArrayList([]const u8).init(arena);
602 for (comp.c_object_table.keys()) |key| {
603 try positionals.append(key.status.success.object_path);
604 }
583605
584 const system_libs = self.base.options.system_libs.keys();
585 for (system_libs) |link_lib| {
586 // By this time, we depend on these libs being dynamically linked libraries and not static libraries
587 // (the check for that needs to be earlier), but they could be full paths to .dylib files, in which
588 // case we want to avoid prepending "-l".
589 if (Compilation.classifyFileExt(link_lib) == .shared_library) {
590 try positionals.append(link_lib);
591 continue;
606 if (module_obj_path) |p| {
607 try positionals.append(p);
592608 }
593609
594 try search_lib_names.append(link_lib);
595 }
610 if (comp.compiler_rt_static_lib) |lib| {
611 try positionals.append(lib.full_object_path);
612 }
596613
597 var lib_dirs = std.ArrayList([]const u8).init(arena);
598 for (self.base.options.lib_dirs) |dir| {
599 if (try resolveSearchDir(arena, dir, self.base.options.sysroot)) |search_dir| {
600 try lib_dirs.append(search_dir);
601 } else {
602 log.warn("directory not found for '-L{s}'", .{dir});
614 // libc++ dep
615 if (self.base.options.link_libcpp) {
616 try positionals.append(comp.libcxxabi_static_lib.?.full_object_path);
617 try positionals.append(comp.libcxx_static_lib.?.full_object_path);
603618 }
604 }
605619
606 var libs = std.ArrayList([]const u8).init(arena);
607 var lib_not_found = false;
608 for (search_lib_names.items) |lib_name| {
609 // Assume ld64 default: -search_paths_first
610 // Look in each directory for a dylib (stub first), and then for archive
611 // TODO implement alternative: -search_dylibs_first
612 for (&[_][]const u8{ ".tbd", ".dylib", ".a" }) |ext| {
613 if (try resolveLib(arena, lib_dirs.items, lib_name, ext)) |full_path| {
614 try libs.append(full_path);
615 break;
620 // Shared and static libraries passed via `-l` flag.
621 var search_lib_names = std.ArrayList([]const u8).init(arena);
622
623 const system_libs = self.base.options.system_libs.keys();
624 for (system_libs) |link_lib| {
625 // By this time, we depend on these libs being dynamically linked libraries and not static libraries
626 // (the check for that needs to be earlier), but they could be full paths to .dylib files, in which
627 // case we want to avoid prepending "-l".
628 if (Compilation.classifyFileExt(link_lib) == .shared_library) {
629 try positionals.append(link_lib);
630 continue;
616631 }
617 } else {
618 log.warn("library not found for '-l{s}'", .{lib_name});
619 lib_not_found = true;
632
633 try search_lib_names.append(link_lib);
620634 }
621 }
622635
623 if (lib_not_found) {
624 log.warn("Library search paths:", .{});
625 for (lib_dirs.items) |dir| {
626 log.warn(" {s}", .{dir});
636 var lib_dirs = std.ArrayList([]const u8).init(arena);
637 for (self.base.options.lib_dirs) |dir| {
638 if (try resolveSearchDir(arena, dir, self.base.options.sysroot)) |search_dir| {
639 try lib_dirs.append(search_dir);
640 } else {
641 log.warn("directory not found for '-L{s}'", .{dir});
642 }
627643 }
628 }
629644
630 // If we were given the sysroot, try to look there first for libSystem.B.{dylib, tbd}.
631 var libsystem_available = false;
632 if (self.base.options.sysroot != null) blk: {
633 // Try stub file first. If we hit it, then we're done as the stub file
634 // re-exports every single symbol definition.
635 if (try resolveLib(arena, lib_dirs.items, "System", ".tbd")) |full_path| {
636 try libs.append(full_path);
637 libsystem_available = true;
638 break :blk;
645 var libs = std.ArrayList([]const u8).init(arena);
646 var lib_not_found = false;
647 for (search_lib_names.items) |lib_name| {
648 // Assume ld64 default: -search_paths_first
649 // Look in each directory for a dylib (stub first), and then for archive
650 // TODO implement alternative: -search_dylibs_first
651 for (&[_][]const u8{ ".tbd", ".dylib", ".a" }) |ext| {
652 if (try resolveLib(arena, lib_dirs.items, lib_name, ext)) |full_path| {
653 try libs.append(full_path);
654 break;
655 }
656 } else {
657 log.warn("library not found for '-l{s}'", .{lib_name});
658 lib_not_found = true;
659 }
639660 }
640 // If we didn't hit the stub file, try .dylib next. However, libSystem.dylib
641 // doesn't export libc.dylib which we'll need to resolve subsequently also.
642 if (try resolveLib(arena, lib_dirs.items, "System", ".dylib")) |libsystem_path| {
643 if (try resolveLib(arena, lib_dirs.items, "c", ".dylib")) |libc_path| {
644 try libs.append(libsystem_path);
645 try libs.append(libc_path);
661
662 if (lib_not_found) {
663 log.warn("Library search paths:", .{});
664 for (lib_dirs.items) |dir| {
665 log.warn(" {s}", .{dir});
666 }
667 }
668
669 // If we were given the sysroot, try to look there first for libSystem.B.{dylib, tbd}.
670 var libsystem_available = false;
671 if (self.base.options.sysroot != null) blk: {
672 // Try stub file first. If we hit it, then we're done as the stub file
673 // re-exports every single symbol definition.
674 if (try resolveLib(arena, lib_dirs.items, "System", ".tbd")) |full_path| {
675 try libs.append(full_path);
646676 libsystem_available = true;
647677 break :blk;
648678 }
679 // If we didn't hit the stub file, try .dylib next. However, libSystem.dylib
680 // doesn't export libc.dylib which we'll need to resolve subsequently also.
681 if (try resolveLib(arena, lib_dirs.items, "System", ".dylib")) |libsystem_path| {
682 if (try resolveLib(arena, lib_dirs.items, "c", ".dylib")) |libc_path| {
683 try libs.append(libsystem_path);
684 try libs.append(libc_path);
685 libsystem_available = true;
686 break :blk;
687 }
688 }
689 }
690 if (!libsystem_available) {
691 const full_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
692 "libc", "darwin", "libSystem.B.tbd",
693 });
694 try libs.append(full_path);
649695 }
650 }
651 if (!libsystem_available) {
652 const full_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
653 "libc", "darwin", "libSystem.B.tbd",
654 });
655 try libs.append(full_path);
656 }
657696
658 // frameworks
659 var framework_dirs = std.ArrayList([]const u8).init(arena);
660 for (self.base.options.framework_dirs) |dir| {
661 if (try resolveSearchDir(arena, dir, self.base.options.sysroot)) |search_dir| {
662 try framework_dirs.append(search_dir);
663 } else {
664 log.warn("directory not found for '-F{s}'", .{dir});
697 // frameworks
698 var framework_dirs = std.ArrayList([]const u8).init(arena);
699 for (self.base.options.framework_dirs) |dir| {
700 if (try resolveSearchDir(arena, dir, self.base.options.sysroot)) |search_dir| {
701 try framework_dirs.append(search_dir);
702 } else {
703 log.warn("directory not found for '-F{s}'", .{dir});
704 }
665705 }
666 }
667706
668 var framework_not_found = false;
669 for (self.base.options.frameworks) |framework| {
670 for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| {
671 if (try resolveFramework(arena, framework_dirs.items, framework, ext)) |full_path| {
672 try libs.append(full_path);
673 break;
707 var framework_not_found = false;
708 for (self.base.options.frameworks) |framework| {
709 for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| {
710 if (try resolveFramework(arena, framework_dirs.items, framework, ext)) |full_path| {
711 try libs.append(full_path);
712 break;
713 }
714 } else {
715 log.warn("framework not found for '-framework {s}'", .{framework});
716 framework_not_found = true;
674717 }
675 } else {
676 log.warn("framework not found for '-framework {s}'", .{framework});
677 framework_not_found = true;
678718 }
679 }
680719
681 if (framework_not_found) {
682 log.warn("Framework search paths:", .{});
683 for (framework_dirs.items) |dir| {
684 log.warn(" {s}", .{dir});
720 if (framework_not_found) {
721 log.warn("Framework search paths:", .{});
722 for (framework_dirs.items) |dir| {
723 log.warn(" {s}", .{dir});
724 }
685725 }
686 }
687726
688 // rpaths
689 var rpath_table = std.StringArrayHashMap(void).init(arena);
690 for (self.base.options.rpath_list) |rpath| {
691 if (rpath_table.contains(rpath)) continue;
692 const cmdsize = @intCast(u32, mem.alignForwardGeneric(
693 u64,
694 @sizeOf(macho.rpath_command) + rpath.len + 1,
695 @sizeOf(u64),
696 ));
697 var rpath_cmd = commands.emptyGenericCommandWithData(macho.rpath_command{
698 .cmd = macho.LC_RPATH,
699 .cmdsize = cmdsize,
700 .path = @sizeOf(macho.rpath_command),
701 });
702 rpath_cmd.data = try self.base.allocator.alloc(u8, cmdsize - rpath_cmd.inner.path);
703 mem.set(u8, rpath_cmd.data, 0);
704 mem.copy(u8, rpath_cmd.data, rpath);
705 try self.load_commands.append(self.base.allocator, .{ .Rpath = rpath_cmd });
706 try rpath_table.putNoClobber(rpath, {});
707 self.load_commands_dirty = true;
708 }
727 // rpaths
728 var rpath_table = std.StringArrayHashMap(void).init(arena);
729 for (self.base.options.rpath_list) |rpath| {
730 if (rpath_table.contains(rpath)) continue;
731 const cmdsize = @intCast(u32, mem.alignForwardGeneric(
732 u64,
733 @sizeOf(macho.rpath_command) + rpath.len + 1,
734 @sizeOf(u64),
735 ));
736 var rpath_cmd = commands.emptyGenericCommandWithData(macho.rpath_command{
737 .cmd = macho.LC_RPATH,
738 .cmdsize = cmdsize,
739 .path = @sizeOf(macho.rpath_command),
740 });
741 rpath_cmd.data = try self.base.allocator.alloc(u8, cmdsize - rpath_cmd.inner.path);
742 mem.set(u8, rpath_cmd.data, 0);
743 mem.copy(u8, rpath_cmd.data, rpath);
744 try self.load_commands.append(self.base.allocator, .{ .Rpath = rpath_cmd });
745 try rpath_table.putNoClobber(rpath, {});
746 self.load_commands_dirty = true;
747 }
709748
710 if (self.base.options.verbose_link) {
711 var argv = std.ArrayList([]const u8).init(arena);
749 if (self.base.options.verbose_link) {
750 var argv = std.ArrayList([]const u8).init(arena);
712751
713 try argv.append("zig");
714 try argv.append("ld");
752 try argv.append("zig");
753 try argv.append("ld");
715754
716 if (is_exe_or_dyn_lib) {
717 try argv.append("-dynamic");
718 }
755 if (is_exe_or_dyn_lib) {
756 try argv.append("-dynamic");
757 }
719758
720 if (is_dyn_lib) {
721 try argv.append("-dylib");
759 if (is_dyn_lib) {
760 try argv.append("-dylib");
722761
723 const install_name = try std.fmt.allocPrint(arena, "@rpath/{s}", .{
724 self.base.options.emit.?.sub_path,
725 });
726 try argv.append("-install_name");
727 try argv.append(install_name);
728 }
762 const install_name = try std.fmt.allocPrint(arena, "@rpath/{s}", .{
763 self.base.options.emit.?.sub_path,
764 });
765 try argv.append("-install_name");
766 try argv.append(install_name);
767 }
729768
730 if (self.base.options.sysroot) |syslibroot| {
731 try argv.append("-syslibroot");
732 try argv.append(syslibroot);
733 }
769 if (self.base.options.sysroot) |syslibroot| {
770 try argv.append("-syslibroot");
771 try argv.append(syslibroot);
772 }
734773
735 for (rpath_table.keys()) |rpath| {
736 try argv.append("-rpath");
737 try argv.append(rpath);
738 }
774 for (rpath_table.keys()) |rpath| {
775 try argv.append("-rpath");
776 try argv.append(rpath);
777 }
739778
740 try argv.appendSlice(positionals.items);
779 try argv.appendSlice(positionals.items);
741780
742 try argv.append("-o");
743 try argv.append(full_out_path);
781 try argv.append("-o");
782 try argv.append(full_out_path);
744783
745 try argv.append("-lSystem");
746 try argv.append("-lc");
784 try argv.append("-lSystem");
785 try argv.append("-lc");
747786
748 for (search_lib_names.items) |l_name| {
749 try argv.append(try std.fmt.allocPrint(arena, "-l{s}", .{l_name}));
750 }
787 for (search_lib_names.items) |l_name| {
788 try argv.append(try std.fmt.allocPrint(arena, "-l{s}", .{l_name}));
789 }
751790
752 for (self.base.options.lib_dirs) |lib_dir| {
753 try argv.append(try std.fmt.allocPrint(arena, "-L{s}", .{lib_dir}));
754 }
791 for (self.base.options.lib_dirs) |lib_dir| {
792 try argv.append(try std.fmt.allocPrint(arena, "-L{s}", .{lib_dir}));
793 }
755794
756 for (self.base.options.frameworks) |framework| {
757 try argv.append(try std.fmt.allocPrint(arena, "-framework {s}", .{framework}));
758 }
795 for (self.base.options.frameworks) |framework| {
796 try argv.append(try std.fmt.allocPrint(arena, "-framework {s}", .{framework}));
797 }
759798
760 for (self.base.options.framework_dirs) |framework_dir| {
761 try argv.append(try std.fmt.allocPrint(arena, "-F{s}", .{framework_dir}));
799 for (self.base.options.framework_dirs) |framework_dir| {
800 try argv.append(try std.fmt.allocPrint(arena, "-F{s}", .{framework_dir}));
801 }
802
803 Compilation.dump_argv(argv.items);
762804 }
763805
764 Compilation.dump_argv(argv.items);
806 try self.parseInputFiles(positionals.items, self.base.options.sysroot);
807 try self.parseLibs(libs.items, self.base.options.sysroot);
765808 }
766809
767 try self.parseInputFiles(positionals.items, self.base.options.sysroot);
768 try self.parseLibs(libs.items, self.base.options.sysroot);
769
770810 if (self.bss_section_index) |idx| {
771811 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
772812 const sect = &seg.sections.items[idx];
......@@ -778,7 +818,8 @@ pub fn flush(self: *MachO, comp: *Compilation) !void {
778818 sect.offset = self.tlv_bss_file_offset;
779819 }
780820
781 for (self.objects.items) |_, object_id| {
821 for (self.objects.items) |*object, object_id| {
822 if (object.analyzed) continue;
782823 try self.resolveSymbolsInObject(@intCast(u16, object_id));
783824 }
784825
......@@ -2617,6 +2658,8 @@ fn parseObjectsIntoAtoms(self: *MachO) !void {
26172658 defer section_metadata.deinit();
26182659
26192660 for (self.objects.items) |*object, object_id| {
2661 if (object.analyzed) continue;
2662
26202663 var atoms_in_objects = try object.parseIntoAtoms(self.base.allocator, @intCast(u16, object_id), self);
26212664 defer atoms_in_objects.deinit();
26222665
......@@ -2663,6 +2706,8 @@ fn parseObjectsIntoAtoms(self: *MachO) !void {
26632706 try first_atoms.putNoClobber(match, atom);
26642707 }
26652708 }
2709
2710 object.analyzed = true;
26662711 }
26672712
26682713 var it = section_metadata.iterator();
......@@ -3003,6 +3048,12 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv
30033048 defer tracy.end();
30043049
30053050 const decl = func.owner_decl;
3051 // TODO clearing the code and relocs buffer should probably be orchestrated
3052 // in a different, smarter, more automatic way somewhere else, in a more centralised
3053 // way than this.
3054 // If we don't clear the buffers here, we are up for some nasty surprises when
3055 // this atom is reused later on and was not freed by freeAtom().
3056 decl.link.macho.clearRetainingCapacity();
30063057
30073058 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
30083059 defer code_buffer.deinit();
......@@ -3038,12 +3089,6 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv
30383089 try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .none);
30393090 switch (res) {
30403091 .appended => {
3041 // TODO clearing the code and relocs buffer should probably be orchestrated
3042 // in a different, smarter, more automatic way somewhere else, in a more centralised
3043 // way than this.
3044 // If we don't clear the buffers here, we are up for some nasty surprises when
3045 // this atom is reused later on and was not freed by freeAtom().
3046 decl.link.macho.code.clearAndFree(self.base.allocator);
30473092 try decl.link.macho.code.appendSlice(self.base.allocator, code_buffer.items);
30483093 },
30493094 .fail => |em| {
......@@ -3194,6 +3239,7 @@ fn placeDecl(self: *MachO, decl: *Module.Decl, code_len: usize) !*macho.nlist_64
31943239 });
31953240 }
31963241 decl.link.macho.size = code_len;
3242 decl.link.macho.dirty = true;
31973243
31983244 const new_name = try std.fmt.allocPrint(self.base.allocator, "_{s}", .{mem.spanZ(decl.name)});
31993245 defer self.base.allocator.free(new_name);
src/link/MachO/Atom.zig+11
......@@ -600,6 +600,17 @@ pub fn deinit(self: *Atom, allocator: *Allocator) void {
600600 self.code.deinit(allocator);
601601}
602602
603pub fn clearRetainingCapacity(self: *Atom) void {
604 self.dices.clearRetainingCapacity();
605 self.lazy_bindings.clearRetainingCapacity();
606 self.bindings.clearRetainingCapacity();
607 self.rebases.clearRetainingCapacity();
608 self.relocs.clearRetainingCapacity();
609 self.contained.clearRetainingCapacity();
610 self.aliases.clearRetainingCapacity();
611 self.code.clearRetainingCapacity();
612}
613
603614/// Returns how much room there is to grow in virtual address space.
604615/// File offset relocation happens transparently, so it is not included in
605616/// this calculation.
src/link/MachO/Object.zig+2
......@@ -64,6 +64,8 @@ sections_as_symbols: std.AutoHashMapUnmanaged(u16, u32) = .{},
6464symbol_mapping: std.AutoHashMapUnmanaged(u32, u32) = .{},
6565reverse_symbol_mapping: std.AutoHashMapUnmanaged(u32, u32) = .{},
6666
67analyzed: bool = false,
68
6769const DebugInfo = struct {
6870 inner: dwarf.DwarfInfo,
6971 debug_info: []u8,