| ... | ... | @@ -461,6 +461,135 @@ const Node = union(enum) { |
| 461 | 461 | fn fromAtom(atom: link.File.AtomId) MappedFile.Node.Index { |
| 462 | 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 | 595 | const InputSection = struct { |
| ... | ... | @@ -2985,10 +3114,15 @@ fn addGlobalSymbol(elf: *Elf, opts: Symbol.Global.AddOptions) (error{ |
| 2985 | 3114 | /// some operation which requires relocations to be re-applied, it can pass `force_apply_relocs` as |
| 2986 | 3115 | /// `true` to guarantee this function to do so. |
| 2987 | 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 | 3120 | const gpa = elf.base.comp.gpa; |
| 2989 | 3121 | |
| 2990 | 3122 | const gsi = orig_gsi.resolveAlias(elf); |
| 2991 | 3123 | |
| 3124 | trace.addText(gsi.rawName(elf).slice(elf)); |
| 3125 | |
| 2992 | 3126 | const maybe_alias_gsi = gsi.findAliaser(elf); |
| 2993 | 3127 | |
| 2994 | 3128 | var apply_relocs: bool = force_apply_relocs; |
| ... | ... | @@ -4132,7 +4266,20 @@ const Symbol = struct { |
| 4132 | 4266 | } |
| 4133 | 4267 | |
| 4134 | 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 | 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 | 4283 | switch (elf.symPtr(sym_index)) { |
| 4137 | 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 | 10864 | elf.mf.nodes_lock.lock(); |
| 10718 | 10865 | defer elf.mf.nodes_lock.unlock(); |
| 10719 | 10866 | |
| 10867 | const trace = tracy.trace(@src()); |
| 10868 | defer trace.end(); |
| 10869 | |
| 10720 | 10870 | const comp = elf.base.comp; |
| 10721 | 10871 | const diags = &comp.link_diags; |
| 10722 | 10872 | |
| ... | ... | @@ -11285,6 +11435,7 @@ fn flushElfOffset(elf: *Elf, ni: MappedFile.Node.Index) void { |
| 11285 | 11435 | fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void { |
| 11286 | 11436 | const trace = tracy.trace(@src()); |
| 11287 | 11437 | defer trace.end(); |
| 11438 | trace.addTextFmt("{f}", .{Node.fmtDebug(ni, elf)}); |
| 11288 | 11439 | |
| 11289 | 11440 | switch (elf.getNode(ni)) { |
| 11290 | 11441 | .deleted => unreachable, |
| ... | ... | @@ -11904,6 +12055,7 @@ fn allocateSegmentLoadAddress(elf: *Elf, orig_phndx: u32) std.mem.Allocator.Erro |
| 11904 | 12055 | fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void { |
| 11905 | 12056 | const trace = tracy.trace(@src()); |
| 11906 | 12057 | defer trace.end(); |
| 12058 | trace.addTextFmt("{f}", .{Node.fmtDebug(ni, elf)}); |
| 11907 | 12059 | |
| 11908 | 12060 | _, const size = ni.location(&elf.mf).resolve(&elf.mf); |
| 11909 | 12061 | switch (elf.getNode(ni)) { |
| ... | ... | @@ -12039,6 +12191,7 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo |
| 12039 | 12191 | fn flushPadding(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void { |
| 12040 | 12192 | const trace = tracy.trace(@src()); |
| 12041 | 12193 | defer trace.end(); |
| 12194 | trace.addTextFmt("{f}", .{Node.fmtDebug(ni, elf)}); |
| 12042 | 12195 | |
| 12043 | 12196 | const node = elf.getNode(ni); |
| 12044 | 12197 | switch (node) { |
| ... | ... | @@ -12798,111 +12951,8 @@ pub fn printNode( |
| 12798 | 12951 | ni: MappedFile.Node.Index, |
| 12799 | 12952 | indent: usize, |
| 12800 | 12953 | ) Io.Writer.Error!void { |
| 12801 | | const node = elf.getNode(ni); |
| 12802 | 12954 | try w.splatByteAll(' ', indent); |
| 12803 | | try w.writeAll(@tagName(node)); |
| 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 | | } |
| 12955 | try w.print("{f}", .{Node.fmtDebug(ni, elf)}); |
| 12906 | 12956 | { |
| 12907 | 12957 | const mf_node = &elf.mf.nodes.items[@backingInt(ni)]; |
| 12908 | 12958 | const off, const size = mf_node.location().resolve(&elf.mf); |