| ... | @@ -461,6 +461,135 @@ const Node = union(enum) { | ... | @@ -461,6 +461,135 @@ const Node = union(enum) { |
| 461 | fn fromAtom(atom: link.File.AtomId) MappedFile.Node.Index { | 461 | fn fromAtom(atom: link.File.AtomId) MappedFile.Node.Index { |
| 462 | return @fromBackingInt(@backingInt(atom)); | 462 | return @fromBackingInt(@backingInt(atom)); |
| 463 | } | 463 | } |
| | 464 | |
| | 465 | fn fmtDebug(ni: MappedFile.Node.Index, elf: *Elf) FormatDebug { |
| | 466 | return .{ .ni = ni, .elf = elf }; |
| | 467 | } |
| | 468 | const FormatDebug = struct { |
| | 469 | ni: MappedFile.Node.Index, |
| | 470 | elf: *Elf, |
| | 471 | pub fn format(ctx: FormatDebug, w: *Io.Writer) Io.Writer.Error!void { |
| | 472 | const elf = ctx.elf; |
| | 473 | const node = elf.getNode(ctx.ni); |
| | 474 | try w.writeAll(@tagName(node)); |
| | 475 | switch (node) { |
| | 476 | // nodes with no payload |
| | 477 | .deleted, |
| | 478 | .archive, |
| | 479 | .archive_header, |
| | 480 | .elf, |
| | 481 | .ehdr, |
| | 482 | .shdr, |
| | 483 | .debug_addr, |
| | 484 | .eh_frame_footer, |
| | 485 | .debug_str_offsets, |
| | 486 | .unit_padding, |
| | 487 | .archive_elf_member_header, |
| | 488 | => |tag| comptime assert(@TypeOf(tag) == void), |
| | 489 | |
| | 490 | .archive_input_member => |ii| try w.print("({f}{f})", .{ |
| | 491 | ii.path(elf).fmtEscapeString(), |
| | 492 | fmtMemberString(ii.member(elf)), |
| | 493 | }), |
| | 494 | .segment => |phndx| switch (elf.phdrSlice()) { |
| | 495 | inline else => |phdr| { |
| | 496 | const ph = &phdr[phndx]; |
| | 497 | try w.writeByte('('); |
| | 498 | const pt = elf.targetLoad(&ph.type); |
| | 499 | if (std.enums.tagName(std.elf.PT, pt)) |pt_name| |
| | 500 | try w.writeAll(pt_name) |
| | 501 | else inline for (@typeInfo(std.elf.PT).@"enum".decl_names) |decl_name| { |
| | 502 | const decl_val = @field(std.elf.PT, decl_name); |
| | 503 | if (@TypeOf(decl_val) != std.elf.PT) continue; |
| | 504 | if (pt == @field(std.elf.PT, decl_name)) break try w.writeAll(decl_name); |
| | 505 | } else try w.print("0x{x}", .{pt}); |
| | 506 | try w.writeAll(", "); |
| | 507 | const pf = elf.targetLoad(&ph.flags); |
| | 508 | if (pf.R) try w.writeByte('R'); |
| | 509 | if (pf.W) try w.writeByte('W'); |
| | 510 | if (pf.X) try w.writeByte('X'); |
| | 511 | try w.writeByte(')'); |
| | 512 | }, |
| | 513 | }, |
| | 514 | .section, .section_manual_size => |shndx| try w.print("({q})", .{ |
| | 515 | shndx.name(elf).slice(elf), |
| | 516 | }), |
| | 517 | .input_section => |isi| { |
| | 518 | const ii = isi.input(elf); |
| | 519 | try w.print("({f}{f}, {q})", .{ |
| | 520 | ii.path(elf).fmtEscapeString(), |
| | 521 | fmtMemberString(ii.member(elf)), |
| | 522 | elf.getNodeShndx(isi.node(elf)).name(elf).slice(elf), |
| | 523 | }); |
| | 524 | }, |
| | 525 | .copied_global => |gsi| try w.print("({q})", .{ |
| | 526 | gsi.rawName(elf).slice(elf), |
| | 527 | }), |
| | 528 | .nav => |nmi| { |
| | 529 | const ip = &elf.base.comp.zcu.?.intern_pool; |
| | 530 | try w.print("({qf})", .{ |
| | 531 | ip.getNav(nmi.nav(elf)).fqn.fmt(ip), |
| | 532 | }); |
| | 533 | }, |
| | 534 | .uav => |umi| { |
| | 535 | const zcu = elf.base.comp.zcu.?; |
| | 536 | const val: Value = .fromInterned(umi.uavValue(elf)); |
| | 537 | try w.print("({f}, {f})", .{ |
| | 538 | val.typeOf(zcu).fmt(zcu), |
| | 539 | val.fmtValue(zcu), |
| | 540 | }); |
| | 541 | }, |
| | 542 | inline .lazy_code, .lazy_const_data => |lmi| try w.print("({f})", .{ |
| | 543 | Type.fromInterned(lmi.lazySymbol(elf).ty).fmt(elf.base.comp.zcu.?), |
| | 544 | }), |
| | 545 | |
| | 546 | .debug_shared => |ss| try w.print("({t})", .{ss}), |
| | 547 | |
| | 548 | .unit_frame, |
| | 549 | .unit_frame_cie, |
| | 550 | .unit_debug_info, |
| | 551 | .unit_debug_info_header, |
| | 552 | .unit_debug_info_footer, |
| | 553 | .unit_debug_line, |
| | 554 | .unit_debug_line_header, |
| | 555 | .unit_debug_rnglists, |
| | 556 | => |ui| try w.print("({q})", .{ |
| | 557 | ui.mod(&elf.dwarf).fully_qualified_name, |
| | 558 | }), |
| | 559 | |
| | 560 | .const_debug_info => |cpi| switch (cpi.val(&elf.dwarf.const_pool)) { |
| | 561 | .generic_poison_type => try w.writeAll("(anytype)"), |
| | 562 | else => |val| try w.print("({f})", .{ |
| | 563 | Value.fromInterned(val).fmtValue(elf.base.comp.zcu.?), |
| | 564 | }), |
| | 565 | }, |
| | 566 | .global_debug_info => |gi| { |
| | 567 | const ip = &elf.base.comp.zcu.?.intern_pool; |
| | 568 | try w.print("({qf})", .{ |
| | 569 | ip.getNav(gi.nav(&elf.dwarf)).fqn.fmt(ip), |
| | 570 | }); |
| | 571 | }, |
| | 572 | .func_frame_fde, .func_debug_info, .func_debug_line => |fi| { |
| | 573 | const ip = &elf.base.comp.zcu.?.intern_pool; |
| | 574 | try w.print("({qf})", .{ |
| | 575 | ip.getNav(fi.nav(&elf.dwarf)).fqn.fmt(ip), |
| | 576 | }); |
| | 577 | }, |
| | 578 | .decl_debug_info => |di| { |
| | 579 | const comp = elf.base.comp; |
| | 580 | const zcu = comp.zcu.?; |
| | 581 | const ip = &zcu.intern_pool; |
| | 582 | const src_inst = di.srcInst(&elf.dwarf); |
| | 583 | const path = zcu.fileByIndex(src_inst.resolveFile(ip)).path; |
| | 584 | if (src_inst.resolve(ip)) |inst| { |
| | 585 | try w.print("({f}, %{d})", .{ path.fmt(comp), inst }); |
| | 586 | } else { |
| | 587 | try w.print("({f}, lost)", .{path.fmt(comp)}); |
| | 588 | } |
| | 589 | }, |
| | 590 | } |
| | 591 | } |
| | 592 | }; |
| 464 | }; | 593 | }; |
| 465 | | 594 | |
| 466 | const InputSection = struct { | 595 | const InputSection = struct { |
| ... | @@ -2985,10 +3114,15 @@ fn addGlobalSymbol(elf: *Elf, opts: Symbol.Global.AddOptions) (error{ | ... | @@ -2985,10 +3114,15 @@ fn addGlobalSymbol(elf: *Elf, opts: Symbol.Global.AddOptions) (error{ |
| 2985 | /// some operation which requires relocations to be re-applied, it can pass `force_apply_relocs` as | 3114 | /// some operation which requires relocations to be re-applied, it can pass `force_apply_relocs` as |
| 2986 | /// `true` to guarantee this function to do so. | 3115 | /// `true` to guarantee this function to do so. |
| 2987 | fn updateGlobalDynamic(elf: *Elf, orig_gsi: Symbol.Global.Index, force_apply_relocs: bool) Error!void { | 3116 | fn updateGlobalDynamic(elf: *Elf, orig_gsi: Symbol.Global.Index, force_apply_relocs: bool) Error!void { |
| | 3117 | const trace = tracy.trace(@src()); |
| | 3118 | defer trace.end(); |
| | 3119 | |
| 2988 | const gpa = elf.base.comp.gpa; | 3120 | const gpa = elf.base.comp.gpa; |
| 2989 | | 3121 | |
| 2990 | const gsi = orig_gsi.resolveAlias(elf); | 3122 | const gsi = orig_gsi.resolveAlias(elf); |
| 2991 | | 3123 | |
| | 3124 | trace.addText(gsi.rawName(elf).slice(elf)); |
| | 3125 | |
| 2992 | const maybe_alias_gsi = gsi.findAliaser(elf); | 3126 | const maybe_alias_gsi = gsi.findAliaser(elf); |
| 2993 | | 3127 | |
| 2994 | var apply_relocs: bool = force_apply_relocs; | 3128 | var apply_relocs: bool = force_apply_relocs; |
| ... | @@ -4132,7 +4266,20 @@ const Symbol = struct { | ... | @@ -4132,7 +4266,20 @@ const Symbol = struct { |
| 4132 | } | 4266 | } |
| 4133 | | 4267 | |
| 4134 | fn flushMoved(sym_id: Symbol.Id, elf: *Elf, new_value: u64) void { | 4268 | fn flushMoved(sym_id: Symbol.Id, elf: *Elf, new_value: u64) void { |
| | 4269 | const trace = tracy.trace(@src()); |
| | 4270 | defer trace.end(); |
| | 4271 | |
| 4135 | const sym_index = sym_id.index(elf); | 4272 | const sym_index = sym_id.index(elf); |
| | 4273 | |
| | 4274 | trace.addText(name: { |
| | 4275 | // There isn't a general `name` method on `Symbol.Id` because it would be incorrect |
| | 4276 | // to ever actually care about the name of a local symbol. |
| | 4277 | const name: String(.strtab) = switch (elf.symPtr(sym_index)) { |
| | 4278 | inline else => |sym| @fromBackingInt(elf.targetLoad(&sym.name)), |
| | 4279 | }; |
| | 4280 | break :name name.slice(elf); |
| | 4281 | }); |
| | 4282 | |
| 4136 | switch (elf.symPtr(sym_index)) { | 4283 | switch (elf.symPtr(sym_index)) { |
| 4137 | inline else => |sym| elf.targetStore(&sym.value, @intCast(new_value)), | 4284 | inline else => |sym| elf.targetStore(&sym.value, @intCast(new_value)), |
| 4138 | } | 4285 | } |
| ... | @@ -10717,6 +10864,9 @@ pub fn idle(elf: *Elf) link.Error!bool { | ... | @@ -10717,6 +10864,9 @@ pub fn idle(elf: *Elf) link.Error!bool { |
| 10717 | elf.mf.nodes_lock.lock(); | 10864 | elf.mf.nodes_lock.lock(); |
| 10718 | defer elf.mf.nodes_lock.unlock(); | 10865 | defer elf.mf.nodes_lock.unlock(); |
| 10719 | | 10866 | |
| | 10867 | const trace = tracy.trace(@src()); |
| | 10868 | defer trace.end(); |
| | 10869 | |
| 10720 | const comp = elf.base.comp; | 10870 | const comp = elf.base.comp; |
| 10721 | const diags = &comp.link_diags; | 10871 | const diags = &comp.link_diags; |
| 10722 | | 10872 | |
| ... | @@ -11285,6 +11435,7 @@ fn flushElfOffset(elf: *Elf, ni: MappedFile.Node.Index) void { | ... | @@ -11285,6 +11435,7 @@ fn flushElfOffset(elf: *Elf, ni: MappedFile.Node.Index) void { |
| 11285 | fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void { | 11435 | fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void { |
| 11286 | const trace = tracy.trace(@src()); | 11436 | const trace = tracy.trace(@src()); |
| 11287 | defer trace.end(); | 11437 | defer trace.end(); |
| | 11438 | trace.addTextFmt("{f}", .{Node.fmtDebug(ni, elf)}); |
| 11288 | | 11439 | |
| 11289 | switch (elf.getNode(ni)) { | 11440 | switch (elf.getNode(ni)) { |
| 11290 | .deleted => unreachable, | 11441 | .deleted => unreachable, |
| ... | @@ -11904,6 +12055,7 @@ fn allocateSegmentLoadAddress(elf: *Elf, orig_phndx: u32) std.mem.Allocator.Erro | ... | @@ -11904,6 +12055,7 @@ fn allocateSegmentLoadAddress(elf: *Elf, orig_phndx: u32) std.mem.Allocator.Erro |
| 11904 | fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void { | 12055 | fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void { |
| 11905 | const trace = tracy.trace(@src()); | 12056 | const trace = tracy.trace(@src()); |
| 11906 | defer trace.end(); | 12057 | defer trace.end(); |
| | 12058 | trace.addTextFmt("{f}", .{Node.fmtDebug(ni, elf)}); |
| 11907 | | 12059 | |
| 11908 | _, const size = ni.location(&elf.mf).resolve(&elf.mf); | 12060 | _, const size = ni.location(&elf.mf).resolve(&elf.mf); |
| 11909 | switch (elf.getNode(ni)) { | 12061 | switch (elf.getNode(ni)) { |
| ... | @@ -12039,6 +12191,7 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo | ... | @@ -12039,6 +12191,7 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo |
| 12039 | fn flushPadding(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void { | 12191 | fn flushPadding(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void { |
| 12040 | const trace = tracy.trace(@src()); | 12192 | const trace = tracy.trace(@src()); |
| 12041 | defer trace.end(); | 12193 | defer trace.end(); |
| | 12194 | trace.addTextFmt("{f}", .{Node.fmtDebug(ni, elf)}); |
| 12042 | | 12195 | |
| 12043 | const node = elf.getNode(ni); | 12196 | const node = elf.getNode(ni); |
| 12044 | switch (node) { | 12197 | switch (node) { |
| ... | @@ -12798,111 +12951,8 @@ pub fn printNode( | ... | @@ -12798,111 +12951,8 @@ pub fn printNode( |
| 12798 | ni: MappedFile.Node.Index, | 12951 | ni: MappedFile.Node.Index, |
| 12799 | indent: usize, | 12952 | indent: usize, |
| 12800 | ) Io.Writer.Error!void { | 12953 | ) Io.Writer.Error!void { |
| 12801 | const node = elf.getNode(ni); | | |
| 12802 | try w.splatByteAll(' ', indent); | 12954 | try w.splatByteAll(' ', indent); |
| 12803 | try w.writeAll(@tagName(node)); | 12955 | try w.print("{f}", .{Node.fmtDebug(ni, elf)}); |
| 12804 | switch (node) { | | |
| 12805 | else => {}, | | |
| 12806 | .segment => |phndx| switch (elf.phdrSlice()) { | | |
| 12807 | inline else => |phdr| { | | |
| 12808 | const ph = &phdr[phndx]; | | |
| 12809 | try w.writeByte('('); | | |
| 12810 | const pt = elf.targetLoad(&ph.type); | | |
| 12811 | if (std.enums.tagName(std.elf.PT, pt)) |pt_name| | | |
| 12812 | try w.writeAll(pt_name) | | |
| 12813 | else inline for (@typeInfo(std.elf.PT).@"enum".decl_names) |decl_name| { | | |
| 12814 | const decl_val = @field(std.elf.PT, decl_name); | | |
| 12815 | if (@TypeOf(decl_val) != std.elf.PT) continue; | | |
| 12816 | if (pt == @field(std.elf.PT, decl_name)) break try w.writeAll(decl_name); | | |
| 12817 | } else try w.print("0x{x}", .{pt}); | | |
| 12818 | try w.writeAll(", "); | | |
| 12819 | const pf = elf.targetLoad(&ph.flags); | | |
| 12820 | if (pf.R) try w.writeByte('R'); | | |
| 12821 | if (pf.W) try w.writeByte('W'); | | |
| 12822 | if (pf.X) try w.writeByte('X'); | | |
| 12823 | try w.writeByte(')'); | | |
| 12824 | }, | | |
| 12825 | }, | | |
| 12826 | .section, .section_manual_size => |shndx| try w.print("({s})", .{shndx.name(elf).slice(elf)}), | | |
| 12827 | .input_section => |isi| { | | |
| 12828 | const ii = isi.input(elf); | | |
| 12829 | try w.print("({f}{f}, {s})", .{ | | |
| 12830 | ii.path(elf).fmtEscapeString(), | | |
| 12831 | fmtMemberString(ii.member(elf)), | | |
| 12832 | elf.getNodeShndx(isi.node(elf)).name(elf).slice(elf), | | |
| 12833 | }); | | |
| 12834 | }, | | |
| 12835 | .copied_global => |gsi| try w.print("(copy:{s})", .{gsi.rawName(elf).slice(elf)}), | | |
| 12836 | .nav => |nmi| { | | |
| 12837 | const zcu = elf.base.comp.zcu.?; | | |
| 12838 | const ip = &zcu.intern_pool; | | |
| 12839 | const nav = ip.getNav(nmi.nav(elf)); | | |
| 12840 | try w.print("({f}, {f})", .{ | | |
| 12841 | Type.fromInterned(nav.resolved.?.type).fmt(zcu), | | |
| 12842 | nav.fqn.fmt(ip), | | |
| 12843 | }); | | |
| 12844 | }, | | |
| 12845 | .uav => |umi| { | | |
| 12846 | const zcu = elf.base.comp.zcu.?; | | |
| 12847 | const val: Value = .fromInterned(umi.uavValue(elf)); | | |
| 12848 | try w.print("({f}, {f})", .{ | | |
| 12849 | val.typeOf(zcu).fmt(zcu), | | |
| 12850 | val.fmtValue(zcu), | | |
| 12851 | }); | | |
| 12852 | }, | | |
| 12853 | inline .lazy_code, .lazy_const_data => |lmi| try w.print("({f})", .{ | | |
| 12854 | Type.fromInterned(lmi.lazySymbol(elf).ty).fmt(elf.base.comp.zcu.?), | | |
| 12855 | }), | | |
| 12856 | .debug_shared => |ss| try w.print("({})", .{ss}), | | |
| 12857 | .unit_frame, | | |
| 12858 | .unit_frame_cie, | | |
| 12859 | .unit_debug_info, | | |
| 12860 | .unit_debug_info_header, | | |
| 12861 | .unit_debug_info_footer, | | |
| 12862 | .unit_debug_line, | | |
| 12863 | .unit_debug_line_header, | | |
| 12864 | .unit_debug_rnglists, | | |
| 12865 | => |ui| try w.print("({s})", .{ui.mod(&elf.dwarf).fully_qualified_name}), | | |
| 12866 | .const_debug_info => |cpi| switch (cpi.val(&elf.dwarf.const_pool)) { | | |
| 12867 | .generic_poison_type => try w.writeAll("(anytype)"), | | |
| 12868 | else => |val| try w.print("({f})", .{ | | |
| 12869 | Value.fromInterned(val).fmtValue(elf.base.comp.zcu.?), | | |
| 12870 | }), | | |
| 12871 | }, | | |
| 12872 | .global_debug_info => |gi| { | | |
| 12873 | const zcu = elf.base.comp.zcu.?; | | |
| 12874 | const ip = &zcu.intern_pool; | | |
| 12875 | const nav = ip.getNav(gi.nav(&elf.dwarf)); | | |
| 12876 | try w.writeByte('('); | | |
| 12877 | if (nav.resolved) |resolved| try w.print("{f}, ", .{ | | |
| 12878 | Type.fromInterned(resolved.type).fmt(zcu), | | |
| 12879 | }); | | |
| 12880 | try w.print("{f}", .{nav.fqn.fmt(ip)}); | | |
| 12881 | if (nav.resolved) |resolved| try w.print(", {f}", .{ | | |
| 12882 | Value.fromInterned(resolved.value).fmtValue(zcu), | | |
| 12883 | }); | | |
| 12884 | try w.writeByte(')'); | | |
| 12885 | }, | | |
| 12886 | .func_frame_fde, .func_debug_info, .func_debug_line => |fi| { | | |
| 12887 | const zcu = elf.base.comp.zcu.?; | | |
| 12888 | const ip = &zcu.intern_pool; | | |
| 12889 | const nav = ip.getNav(fi.nav(&elf.dwarf)); | | |
| 12890 | try w.writeByte('('); | | |
| 12891 | if (nav.resolved) |resolved| try w.print("{f}, ", .{ | | |
| 12892 | Type.fromInterned(resolved.type).fmt(zcu), | | |
| 12893 | }); | | |
| 12894 | try w.print("{f})", .{nav.fqn.fmt(ip)}); | | |
| 12895 | }, | | |
| 12896 | .decl_debug_info => |di| { | | |
| 12897 | const comp = elf.base.comp; | | |
| 12898 | const zcu = comp.zcu.?; | | |
| 12899 | const ip = &zcu.intern_pool; | | |
| 12900 | const src_inst = di.srcInst(&elf.dwarf); | | |
| 12901 | try w.print("({f}, ", .{zcu.fileByIndex(src_inst.resolveFile(ip)).path.fmt(comp)}); | | |
| 12902 | if (src_inst.resolve(ip)) |inst| try w.print("%{d}", .{inst}) else try w.writeAll("lost"); | | |
| 12903 | try w.writeByte(')'); | | |
| 12904 | }, | | |
| 12905 | } | | |
| 12906 | { | 12956 | { |
| 12907 | const mf_node = &elf.mf.nodes.items[@backingInt(ni)]; | 12957 | const mf_node = &elf.mf.nodes.items[@backingInt(ni)]; |
| 12908 | const off, const size = mf_node.location().resolve(&elf.mf); | 12958 | const off, const size = mf_node.location().resolve(&elf.mf); |