Commit 5986bdf868

Jacob Young <jacobly0@users.noreply.github.com>
2025-06-04 07:42:40
Compilation: enable the x86_64 backend by default for debug builds
Closes #22257
1 parent e96d860
src/arch/x86_64/Emit.zig
@@ -378,9 +378,9 @@ pub fn emitMir(emit: *Emit) Error!void {
                                     };
                                     break :stack_value &loc_buf[0];
                                 } } },
-                                .pseudo_dbg_local_as => .{ mir_inst.data.as.air_inst, .{ .addr = .{
-                                    .sym = mir_inst.data.as.sym_index,
-                                } } },
+                                .pseudo_dbg_local_as => .{ mir_inst.data.as.air_inst, .{
+                                    .addr_reloc = mir_inst.data.as.sym_index,
+                                } },
                                 .pseudo_dbg_local_aso => loc: {
                                     const sym_off = emit.lower.mir.extraData(
                                         bits.SymbolOffset,
@@ -388,7 +388,7 @@ pub fn emitMir(emit: *Emit) Error!void {
                                     ).data;
                                     break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
                                         sym: {
-                                            loc_buf[0] = .{ .addr = .{ .sym = sym_off.sym_index } };
+                                            loc_buf[0] = .{ .addr_reloc = sym_off.sym_index };
                                             break :sym &loc_buf[0];
                                         },
                                         off: {
@@ -437,7 +437,7 @@ pub fn emitMir(emit: *Emit) Error!void {
                                                 .none => .{ .constu = 0 },
                                                 .reg => |reg| .{ .breg = reg.dwarfNum() },
                                                 .frame, .table, .rip_inst => unreachable,
-                                                .reloc => |sym_index| .{ .addr = .{ .sym = sym_index } },
+                                                .reloc => |sym_index| .{ .addr_reloc = sym_index },
                                             };
                                             break :base &loc_buf[0];
                                         },
src/Compilation/Config.zig
@@ -195,10 +195,7 @@ pub fn resolve(options: Options) ResolveError!Config {
     // Note that using the LLVM backend does not necessarily mean using LLVM libraries.
     // For example, Zig can emit .bc and .ll files directly, and this is still considered
     // using "the LLVM backend".
-    const use_llvm = b: {
-        // If we have no zig code to compile, no need for LLVM.
-        if (!options.have_zcu) break :b false;
-
+    const can_use_llvm = b: {
         // If emitting to LLVM bitcode object format, must use LLVM backend.
         if (options.emit_llvm_ir or options.emit_llvm_bc) {
             if (options.use_llvm == false)
@@ -237,6 +234,13 @@ pub fn resolve(options: Options) ResolveError!Config {
         break :b !target_util.selfHostedBackendIsAsRobustAsLlvm(target);
     };
 
+    const use_llvm = b: {
+        // If we have no zig code to compile, no need for LLVM.
+        if (!options.have_zcu) break :b false;
+
+        break :b can_use_llvm;
+    };
+
     if (options.emit_bin and options.have_zcu) {
         if (!use_lib_llvm and use_llvm) {
             // Explicit request to use LLVM to produce an object file, but without
@@ -273,7 +277,7 @@ pub fn resolve(options: Options) ResolveError!Config {
         }
 
         if (options.use_lld) |x| break :b x;
-        break :b true;
+        break :b can_use_llvm;
     };
 
     // Make a decision on whether to use Clang or Aro for translate-c and compiling C files.
src/libs/libcxx.zig
@@ -308,7 +308,7 @@ pub fn buildLibCxx(comp: *Compilation, prog_node: std.Progress.Node) BuildError!
     assert(comp.libcxx_static_lib == null);
     const crt_file = try sub_compilation.toCrtFile();
     comp.libcxx_static_lib = crt_file;
-    comp.queueLinkTaskMode(crt_file.full_object_path, output_mode);
+    comp.queueLinkTaskMode(crt_file.full_object_path, &config);
 }
 
 pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildError!void {
@@ -504,7 +504,7 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
     assert(comp.libcxxabi_static_lib == null);
     const crt_file = try sub_compilation.toCrtFile();
     comp.libcxxabi_static_lib = crt_file;
-    comp.queueLinkTaskMode(crt_file.full_object_path, output_mode);
+    comp.queueLinkTaskMode(crt_file.full_object_path, &config);
 }
 
 pub fn addCxxArgs(
src/libs/libtsan.zig
@@ -325,7 +325,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
     };
 
     const crt_file = try sub_compilation.toCrtFile();
-    comp.queueLinkTaskMode(crt_file.full_object_path, output_mode);
+    comp.queueLinkTaskMode(crt_file.full_object_path, &config);
     assert(comp.tsan_lib == null);
     comp.tsan_lib = crt_file;
 }
src/libs/libunwind.zig
@@ -195,7 +195,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr
     };
 
     const crt_file = try sub_compilation.toCrtFile();
-    comp.queueLinkTaskMode(crt_file.full_object_path, output_mode);
+    comp.queueLinkTaskMode(crt_file.full_object_path, &config);
     assert(comp.libunwind_static_lib == null);
     comp.libunwind_static_lib = crt_file;
 }
src/libs/musl.zig
@@ -278,7 +278,7 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro
             errdefer comp.gpa.free(basename);
 
             const crt_file = try sub_compilation.toCrtFile();
-            comp.queueLinkTaskMode(crt_file.full_object_path, output_mode);
+            comp.queueLinkTaskMode(crt_file.full_object_path, &config);
             {
                 comp.mutex.lock();
                 defer comp.mutex.unlock();
src/link/Elf/relocation.zig
@@ -108,12 +108,13 @@ pub const dwarf = struct {
 
     pub fn externalRelocType(
         target: Symbol,
+        is_got: bool,
         source_section: Dwarf.Section.Index,
         address_size: Dwarf.AddressSize,
         cpu_arch: std.Target.Cpu.Arch,
     ) u32 {
         return switch (cpu_arch) {
-            .x86_64 => @intFromEnum(@as(elf.R_X86_64, switch (source_section) {
+            .x86_64 => @intFromEnum(@as(elf.R_X86_64, if (is_got) .GOT32 else switch (source_section) {
                 else => switch (address_size) {
                     .@"32" => if (target.flags.is_tls) .DTPOFF32 else .@"32",
                     .@"64" => if (target.flags.is_tls) .DTPOFF64 else .@"64",
src/link/Elf/ZigObject.zig
@@ -463,8 +463,11 @@ pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !void {
                     for (entry.external_relocs.items) |reloc| {
                         const target_sym = self.symbol(reloc.target_sym);
                         const r_offset = entry_off + reloc.source_off;
-                        const r_addend: i64 = @intCast(reloc.target_off);
-                        const r_type = relocation.dwarf.externalRelocType(target_sym.*, sect_index, dwarf.address_size, cpu_arch);
+                        const r_addend: i64 = switch (reloc.target_off) {
+                            .none, .got => 0,
+                            else => |off| @intCast(@intFromEnum(off)),
+                        };
+                        const r_type = relocation.dwarf.externalRelocType(target_sym.*, reloc.target_off == .got, sect_index, dwarf.address_size, cpu_arch);
                         atom_ptr.addRelocAssumeCapacity(.{
                             .r_offset = r_offset,
                             .r_addend = r_addend,
@@ -947,7 +950,7 @@ pub fn getNavVAddr(
             .dwarf => |wip_nav| try wip_nav.infoExternalReloc(.{
                 .source_off = @intCast(reloc_info.offset),
                 .target_sym = this_sym_index,
-                .target_off = reloc_info.addend,
+                .target_off = .rel(reloc_info.addend),
             }),
             .plan9 => unreachable,
             .none => unreachable,
@@ -980,7 +983,7 @@ pub fn getUavVAddr(
             .dwarf => |wip_nav| try wip_nav.infoExternalReloc(.{
                 .source_off = @intCast(reloc_info.offset),
                 .target_sym = sym_index,
-                .target_off = reloc_info.addend,
+                .target_off = .rel(reloc_info.addend),
             }),
             .plan9 => unreachable,
             .none => unreachable,
src/link/MachO/ZigObject.zig
@@ -648,7 +648,7 @@ pub fn getNavVAddr(
             .dwarf => |wip_nav| try wip_nav.infoExternalReloc(.{
                 .source_off = @intCast(reloc_info.offset),
                 .target_sym = sym_index,
-                .target_off = reloc_info.addend,
+                .target_off = .rel(reloc_info.addend),
             }),
             .plan9 => unreachable,
             .none => unreachable,
@@ -688,7 +688,7 @@ pub fn getUavVAddr(
             .dwarf => |wip_nav| try wip_nav.infoExternalReloc(.{
                 .source_off = @intCast(reloc_info.offset),
                 .target_sym = sym_index,
-                .target_off = reloc_info.addend,
+                .target_off = .rel(reloc_info.addend),
             }),
             .plan9 => unreachable,
             .none => unreachable,
src/link/Dwarf.zig
@@ -785,6 +785,7 @@ const Entry = struct {
     }
 
     const Index = enum(u32) {
+        //got_proc,
         _,
 
         const Optional = enum(u32) {
@@ -1040,7 +1041,7 @@ const Entry = struct {
                 const symbol = zo.symbol(reloc.target_sym);
                 try dwarf.resolveReloc(
                     entry_off + reloc.source_off,
-                    @bitCast(symbol.address(.{}, elf_file) + @as(i64, @intCast(reloc.target_off)) -
+                    @bitCast(symbol.address(.{}, elf_file) + @as(i64, @intCast(@intFromEnum(reloc.target_off))) -
                         if (symbol.flags.is_tls) elf_file.dtpAddress() else 0),
                     @intFromEnum(dwarf.address_size),
                 );
@@ -1051,7 +1052,7 @@ const Entry = struct {
                 const ref = zo.getSymbolRef(reloc.target_sym, macho_file);
                 try dwarf.resolveReloc(
                     entry_off + reloc.source_off,
-                    ref.getSymbol(macho_file).?.getAddress(.{}, macho_file),
+                    ref.getSymbol(macho_file).?.getAddress(.{}, macho_file) + @as(i64, @intCast(@intFromEnum(reloc.target_off))),
                     @intFromEnum(dwarf.address_size),
                 );
             }
@@ -1080,18 +1081,39 @@ const CrossSectionReloc = struct {
 const ExternalReloc = struct {
     source_off: u32 = 0,
     target_sym: u32,
-    target_off: u64 = 0,
+    target_off: enum(u64) {
+        none = 0,
+        got = std.math.maxInt(i64) + 1,
+        _,
+
+        pub fn rel(off: u64) @This() {
+            const res: @This() = @enumFromInt(off);
+            switch (res) {
+                .none => {},
+                _ => {},
+                .got => unreachable, // assertion failure
+            }
+            return res;
+        }
+    } = .none,
 };
 
 pub const Loc = union(enum) {
     empty,
-    addr: union(enum) { sym: u32 },
+    addr_reloc: u32,
+    got_reloc: u32,
+    deref: *const Loc,
     constu: u64,
     consts: i64,
     plus: Bin,
     reg: u32,
     breg: u32,
     push_object_address,
+    call: struct {
+        args: []const Loc = &.{},
+        unit: Unit.Index,
+        entry: Entry.Index,
+    },
     form_tls_address: *const Loc,
     implicit_value: []const u8,
     stack_value: *const Loc,
@@ -1136,11 +1158,17 @@ pub const Loc = union(enum) {
         const writer = adapter.writer();
         switch (loc) {
             .empty => {},
-            .addr => |addr| {
+            .addr_reloc => |sym_index| {
                 try writer.writeByte(DW.OP.addr);
-                switch (addr) {
-                    .sym => |sym_index| try adapter.addrSym(sym_index),
-                }
+                try adapter.addrSym(sym_index);
+            },
+            .deref => |addr| {
+                try addr.write(adapter);
+                try writer.writeByte(DW.OP.deref);
+            },
+            .got_reloc => |sym_index| {
+                try writer.writeByte(DW.OP.const4s);
+                try adapter.gotSym(sym_index);
             },
             .constu => |constu| if (std.math.cast(u5, constu)) |lit| {
                 try writer.writeByte(@as(u8, DW.OP.lit0) + lit);
@@ -1225,6 +1253,11 @@ pub const Loc = union(enum) {
                 try sleb128(writer, 0);
             },
             .push_object_address => try writer.writeByte(DW.OP.push_object_address),
+            .call => |call| {
+                for (call.args) |arg| try arg.write(adapter);
+                try writer.writeByte(DW.OP.call_ref);
+                try adapter.infoEntry(call.unit, call.entry);
+            },
             .form_tls_address => |addr| {
                 try addr.write(adapter);
                 try writer.writeByte(DW.OP.form_tls_address);
@@ -1385,12 +1418,12 @@ pub const Cfa = union(enum) {
             },
             .def_cfa_expression => |expr| {
                 try writer.writeByte(DW.CFA.def_cfa_expression);
-                try wip_nav.frameExprloc(expr);
+                try wip_nav.frameExprLoc(expr);
             },
             .expression => |reg_expr| {
                 try writer.writeByte(DW.CFA.expression);
                 try uleb128(writer, reg_expr.reg);
-                try wip_nav.frameExprloc(reg_expr.expr);
+                try wip_nav.frameExprLoc(reg_expr.expr);
             },
             .val_offset => |reg_off| {
                 const factored_off = @divExact(reg_off.off, wip_nav.dwarf.debug_frame.header.data_alignment_factor);
@@ -1407,7 +1440,7 @@ pub const Cfa = union(enum) {
             .val_expression => |reg_expr| {
                 try writer.writeByte(DW.CFA.val_expression);
                 try uleb128(writer, reg_expr.reg);
-                try wip_nav.frameExprloc(reg_expr.expr);
+                try wip_nav.frameExprLoc(reg_expr.expr);
             },
             .escape => |bytes| try writer.writeAll(bytes),
         }
@@ -1471,7 +1504,7 @@ pub const WipNav = struct {
         });
         try wip_nav.strp(name);
         try wip_nav.refType(ty);
-        try wip_nav.infoExprloc(loc);
+        try wip_nav.infoExprLoc(loc);
         wip_nav.any_children = true;
     }
 
@@ -1733,6 +1766,9 @@ pub const WipNav = struct {
         fn endian(_: ExprLocCounter) std.builtin.Endian {
             return @import("builtin").cpu.arch.endian();
         }
+        fn gotSym(counter: *ExprLocCounter, _: u32) error{}!void {
+            counter.stream.bytes_written += 4;
+        }
         fn addrSym(counter: *ExprLocCounter, _: u32) error{}!void {
             counter.stream.bytes_written += @intFromEnum(counter.address_size);
         }
@@ -1741,7 +1777,7 @@ pub const WipNav = struct {
         }
     };
 
-    fn infoExprloc(wip_nav: *WipNav, loc: Loc) UpdateError!void {
+    fn infoExprLoc(wip_nav: *WipNav, loc: Loc) UpdateError!void {
         var counter: ExprLocCounter = .init(wip_nav.dwarf);
         try loc.write(&counter);
 
@@ -1753,6 +1789,14 @@ pub const WipNav = struct {
             fn endian(ctx: @This()) std.builtin.Endian {
                 return ctx.wip_nav.dwarf.endian;
             }
+            fn gotSym(ctx: @This(), sym_index: u32) UpdateError!void {
+                try ctx.wip_nav.infoExternalReloc(.{
+                    .source_off = @intCast(ctx.wip_nav.debug_info.items.len),
+                    .target_sym = sym_index,
+                    .target_off = .got,
+                });
+                try ctx.wip_nav.debug_info.appendNTimes(ctx.wip_nav.dwarf.gpa, 0, 4);
+            }
             fn addrSym(ctx: @This(), sym_index: u32) UpdateError!void {
                 try ctx.wip_nav.infoAddrSym(sym_index, 0);
             }
@@ -1768,12 +1812,12 @@ pub const WipNav = struct {
         try wip_nav.infoExternalReloc(.{
             .source_off = @intCast(wip_nav.debug_info.items.len),
             .target_sym = sym_index,
-            .target_off = sym_off,
+            .target_off = .rel(sym_off),
         });
         try wip_nav.debug_info.appendNTimes(wip_nav.dwarf.gpa, 0, @intFromEnum(wip_nav.dwarf.address_size));
     }
 
-    fn frameExprloc(wip_nav: *WipNav, loc: Loc) UpdateError!void {
+    fn frameExprLoc(wip_nav: *WipNav, loc: Loc) UpdateError!void {
         var counter: ExprLocCounter = .init(wip_nav.dwarf);
         try loc.write(&counter);
 
@@ -1785,6 +1829,14 @@ pub const WipNav = struct {
             fn endian(ctx: @This()) std.builtin.Endian {
                 return ctx.wip_nav.dwarf.endian;
             }
+            fn gotSym(ctx: @This(), sym_index: u32) UpdateError!void {
+                try ctx.wip_nav.frameExternalReloc(.{
+                    .source_off = @intCast(ctx.wip_nav.debug_frame.items.len),
+                    .target_sym = sym_index,
+                    .target_off = .got,
+                });
+                try ctx.wip_nav.debug_frame.appendNTimes(ctx.wip_nav.dwarf.gpa, 0, 4);
+            }
             fn addrSym(ctx: @This(), sym_index: u32) UpdateError!void {
                 try ctx.wip_nav.frameAddrSym(sym_index, 0);
             }
@@ -1800,7 +1852,7 @@ pub const WipNav = struct {
         try wip_nav.frameExternalReloc(.{
             .source_off = @intCast(wip_nav.debug_frame.items.len),
             .target_sym = sym_index,
-            .target_off = sym_off,
+            .target_off = .rel(sym_off),
         });
         try wip_nav.debug_frame.appendNTimes(wip_nav.dwarf.gpa, 0, @intFromEnum(wip_nav.dwarf.address_size));
     }
@@ -2286,50 +2338,81 @@ fn getUnit(dwarf: *Dwarf, mod: *Module) !Unit.Index {
     const mod_gop = try dwarf.mods.getOrPut(dwarf.gpa, mod);
     const unit: Unit.Index = @enumFromInt(mod_gop.index);
     if (!mod_gop.found_existing) {
-        errdefer _ = dwarf.mods.pop();
-        mod_gop.value_ptr.* = .{
-            .root_dir_path = undefined,
-            .dirs = .empty,
-            .files = .empty,
-        };
-        errdefer mod_gop.value_ptr.dirs.deinit(dwarf.gpa);
-        try mod_gop.value_ptr.dirs.putNoClobber(dwarf.gpa, unit, {});
-        assert(try dwarf.debug_aranges.section.addUnit(
-            DebugAranges.headerBytes(dwarf),
-            DebugAranges.trailerBytes(dwarf),
-            dwarf,
-        ) == unit);
-        errdefer dwarf.debug_aranges.section.popUnit(dwarf.gpa);
-        assert(try dwarf.debug_frame.section.addUnit(
-            DebugFrame.headerBytes(dwarf),
-            DebugFrame.trailerBytes(dwarf),
-            dwarf,
-        ) == unit);
-        errdefer dwarf.debug_frame.section.popUnit(dwarf.gpa);
-        assert(try dwarf.debug_info.section.addUnit(
-            DebugInfo.headerBytes(dwarf),
-            DebugInfo.trailer_bytes,
-            dwarf,
-        ) == unit);
-        errdefer dwarf.debug_info.section.popUnit(dwarf.gpa);
-        assert(try dwarf.debug_line.section.addUnit(
-            DebugLine.headerBytes(dwarf, 5, 25),
-            DebugLine.trailer_bytes,
-            dwarf,
-        ) == unit);
-        errdefer dwarf.debug_line.section.popUnit(dwarf.gpa);
-        assert(try dwarf.debug_loclists.section.addUnit(
-            DebugLocLists.headerBytes(dwarf),
-            DebugLocLists.trailer_bytes,
-            dwarf,
-        ) == unit);
-        errdefer dwarf.debug_loclists.section.popUnit(dwarf.gpa);
-        assert(try dwarf.debug_rnglists.section.addUnit(
-            DebugRngLists.headerBytes(dwarf),
-            DebugRngLists.trailer_bytes,
-            dwarf,
-        ) == unit);
-        errdefer dwarf.debug_rnglists.section.popUnit(dwarf.gpa);
+        {
+            errdefer _ = dwarf.mods.pop();
+            mod_gop.value_ptr.* = .{
+                .root_dir_path = undefined,
+                .dirs = .empty,
+                .files = .empty,
+            };
+            errdefer mod_gop.value_ptr.dirs.deinit(dwarf.gpa);
+            try mod_gop.value_ptr.dirs.putNoClobber(dwarf.gpa, unit, {});
+            assert(try dwarf.debug_aranges.section.addUnit(
+                DebugAranges.headerBytes(dwarf),
+                DebugAranges.trailerBytes(dwarf),
+                dwarf,
+            ) == unit);
+            errdefer dwarf.debug_aranges.section.popUnit(dwarf.gpa);
+            assert(try dwarf.debug_frame.section.addUnit(
+                DebugFrame.headerBytes(dwarf),
+                DebugFrame.trailerBytes(dwarf),
+                dwarf,
+            ) == unit);
+            errdefer dwarf.debug_frame.section.popUnit(dwarf.gpa);
+            assert(try dwarf.debug_info.section.addUnit(
+                DebugInfo.headerBytes(dwarf),
+                DebugInfo.trailer_bytes,
+                dwarf,
+            ) == unit);
+            errdefer dwarf.debug_info.section.popUnit(dwarf.gpa);
+            assert(try dwarf.debug_line.section.addUnit(
+                DebugLine.headerBytes(dwarf, 5, 25),
+                DebugLine.trailer_bytes,
+                dwarf,
+            ) == unit);
+            errdefer dwarf.debug_line.section.popUnit(dwarf.gpa);
+            assert(try dwarf.debug_loclists.section.addUnit(
+                DebugLocLists.headerBytes(dwarf),
+                DebugLocLists.trailer_bytes,
+                dwarf,
+            ) == unit);
+            errdefer dwarf.debug_loclists.section.popUnit(dwarf.gpa);
+            assert(try dwarf.debug_rnglists.section.addUnit(
+                DebugRngLists.headerBytes(dwarf),
+                DebugRngLists.trailer_bytes,
+                dwarf,
+            ) == unit);
+            errdefer dwarf.debug_rnglists.section.popUnit(dwarf.gpa);
+        }
+        //if (dwarf.bin_file.cast(.elf)) |elf_file| {
+        //    if (unit == .main) assert(try dwarf.addCommonEntry(unit) == .got_proc);
+        //    if (mod.pic and dwarf.debug_info.section.getUnit(.main).getEntry(.got_proc).len == 0) {
+        //        var wip_nav: WipNav = .{
+        //            .dwarf = dwarf,
+        //            .pt = undefined,
+        //            .unit = .main,
+        //            .entry = .got_proc,
+        //            .any_children = false,
+        //            .func = .none,
+        //            .func_sym_index = undefined,
+        //            .func_high_pc = undefined,
+        //            .blocks = undefined,
+        //            .cfi = undefined,
+        //            .debug_frame = .empty,
+        //            .debug_info = .empty,
+        //            .debug_line = .empty,
+        //            .debug_loclists = .empty,
+        //            .pending_lazy = .empty,
+        //        };
+        //        defer wip_nav.deinit();
+        //        try wip_nav.abbrevCode(.proc);
+        //        try wip_nav.infoExprLoc(.{ .deref = &.{ .plus = .{
+        //            &.empty,
+        //            &.{ .addr_reloc = try elf_file.zigObjectPtr().?.getGlobalSymbol(elf_file, "_GLOBAL_OFFSET_TABLE_", null) },
+        //        } } });
+        //        try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items);
+        //    }
+        //}
     }
     return unit;
 }
@@ -2384,7 +2467,8 @@ fn initWipNavInner(
         else => {},
     }
 
-    const unit = try dwarf.getUnit(file.mod.?);
+    const mod = file.mod.?;
+    const unit = try dwarf.getUnit(mod);
     const nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, nav_index);
     errdefer _ = if (!nav_gop.found_existing) dwarf.navs.pop();
     if (nav_gop.found_existing) {
@@ -2425,13 +2509,22 @@ fn initWipNavInner(
             }, &nav, inst_info.file, &decl);
             try wip_nav.strp(nav.fqn.toSlice(ip));
             const ty: Type = nav_val.typeOf(zcu);
-            const addr: Loc = .{ .addr = .{ .sym = sym_index } };
-            const loc: Loc = if (decl.is_threadlocal) .{ .form_tls_address = &addr } else addr;
+            const addr: Loc = .{ .addr_reloc = sym_index };
+            const loc: Loc = loc: {
+                if (dwarf.bin_file.cast(.elf)) |elf_file| if (decl.linkage == .@"extern" and mod.pic)
+                    // TODO: lldb doesn't support call :(
+                    //.{ .call = .{ .args = &.{.{ .got_reloc = sym_index }}, .unit = .main, .entry = .got_proc } }
+                    break :loc .{ .deref = &.{ .plus = .{
+                        &.{ .addr_reloc = try elf_file.zigObjectPtr().?.getGlobalSymbol(elf_file, "_GLOBAL_OFFSET_TABLE_", null) },
+                        &.{ .got_reloc = sym_index },
+                    } } };
+                break :loc if (decl.is_threadlocal) .{ .form_tls_address = &addr } else addr;
+            };
             switch (decl.kind) {
                 .unnamed_test, .@"test", .decltest, .@"comptime", .@"usingnamespace" => unreachable,
                 .@"const" => {
                     const const_ty_reloc_index = try wip_nav.refForward();
-                    try wip_nav.infoExprloc(loc);
+                    try wip_nav.infoExprLoc(loc);
                     try uleb128(diw, nav.status.fully_resolved.alignment.toByteUnits() orelse
                         ty.abiAlignment(zcu).toByteUnits().?);
                     try diw.writeByte(@intFromBool(decl.linkage != .normal));
@@ -2441,7 +2534,7 @@ fn initWipNavInner(
                 },
                 .@"var" => {
                     try wip_nav.refType(ty);
-                    try wip_nav.infoExprloc(loc);
+                    try wip_nav.infoExprLoc(loc);
                     try uleb128(diw, nav.status.fully_resolved.alignment.toByteUnits() orelse
                         ty.abiAlignment(zcu).toByteUnits().?);
                     try diw.writeByte(@intFromBool(decl.linkage != .normal));
@@ -2649,7 +2742,7 @@ pub fn finishWipNavFunc(
             .{
                 .source_off = 1 + @intFromEnum(dwarf.address_size),
                 .target_sym = wip_nav.func_sym_index,
-                .target_off = code_size,
+                .target_off = .rel(code_size),
             },
         });
         try dwarf.debug_rnglists.section.replaceEntry(
@@ -3838,7 +3931,7 @@ fn updateLazyValue(
                     byte_offset += base_ptr.byte_offset;
                 };
                 try wip_nav.abbrevCode(.location_comptime_value);
-                try wip_nav.infoExprloc(.{ .implicit_pointer = .{
+                try wip_nav.infoExprLoc(.{ .implicit_pointer = .{
                     .unit = base_unit,
                     .entry = base_entry,
                     .offset = byte_offset,
@@ -4360,7 +4453,7 @@ fn refAbbrevCode(dwarf: *Dwarf, abbrev_code: AbbrevCode) UpdateError!@typeInfo(A
     assert(abbrev_code != .null);
     const entry: Entry.Index = @enumFromInt(@intFromEnum(abbrev_code));
     if (dwarf.debug_abbrev.section.getUnit(DebugAbbrev.unit).getEntry(entry).len > 0) return @intFromEnum(abbrev_code);
-    var debug_abbrev = std.ArrayList(u8).init(dwarf.gpa);
+    var debug_abbrev: std.ArrayList(u8) = .init(dwarf.gpa);
     defer debug_abbrev.deinit();
     const daw = debug_abbrev.writer();
     const abbrev = AbbrevCode.abbrevs.get(abbrev_code);
@@ -4422,7 +4515,7 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
         mod_info.root_dir_path = try dwarf.debug_line_str.addString(dwarf, root_dir_path);
     }
 
-    var header = std.ArrayList(u8).init(dwarf.gpa);
+    var header: std.ArrayList(u8) = .init(dwarf.gpa);
     defer header.deinit();
     if (dwarf.debug_aranges.section.dirty) {
         for (dwarf.debug_aranges.section.units.items, 0..) |*unit_ptr, unit_index| {
@@ -4888,6 +4981,7 @@ const AbbrevCode = enum {
     comptime_value_field_comptime_state,
     comptime_value_elem_runtime_bits,
     comptime_value_elem_comptime_state,
+    //proc,
 
     const decl_bytes = uleb128Bytes(@intFromEnum(AbbrevCode.decl_instance_func_generic));
     comptime {
@@ -5757,6 +5851,12 @@ const AbbrevCode = enum {
                 .{ .ZIG_comptime_value, .ref_addr },
             },
         },
+        //.proc = .{
+        //    .tag = .dwarf_procedure,
+        //    .attrs = &.{
+        //        .{ .location, .exprloc },
+        //    },
+        //},
         .null = undefined,
     });
 };
src/Compilation.zig
@@ -7225,7 +7225,7 @@ fn buildOutputFromZig(
     assert(out.* == null);
     out.* = crt_file;
 
-    comp.queueLinkTaskMode(crt_file.full_object_path, output_mode);
+    comp.queueLinkTaskMode(crt_file.full_object_path, &config);
 }
 
 pub const CrtFileOptions = struct {
@@ -7349,7 +7349,7 @@ pub fn build_crt_file(
     try comp.updateSubCompilation(sub_compilation, misc_task_tag, prog_node);
 
     const crt_file = try sub_compilation.toCrtFile();
-    comp.queueLinkTaskMode(crt_file.full_object_path, output_mode);
+    comp.queueLinkTaskMode(crt_file.full_object_path, &config);
 
     {
         comp.mutex.lock();
@@ -7359,11 +7359,14 @@ pub fn build_crt_file(
     }
 }
 
-pub fn queueLinkTaskMode(comp: *Compilation, path: Cache.Path, output_mode: std.builtin.OutputMode) void {
-    comp.queueLinkTasks(switch (output_mode) {
+pub fn queueLinkTaskMode(comp: *Compilation, path: Cache.Path, config: *const Compilation.Config) void {
+    comp.queueLinkTasks(switch (config.output_mode) {
         .Exe => unreachable,
         .Obj => &.{.{ .load_object = path }},
-        .Lib => &.{.{ .load_archive = path }},
+        .Lib => &.{switch (config.link_mode) {
+            .static => .{ .load_archive = path },
+            .dynamic => .{ .load_dso = path },
+        }},
     });
 }
 
src/target.zig
@@ -223,6 +223,10 @@ pub fn hasLldSupport(ofmt: std.Target.ObjectFormat) bool {
 /// than or equal to the number of behavior tests as the respective LLVM backend.
 pub fn selfHostedBackendIsAsRobustAsLlvm(target: std.Target) bool {
     if (target.cpu.arch.isSpirV()) return true;
+    if (target.cpu.arch == .x86_64 and target.ptrBitWidth() == 64) return switch (target.ofmt) {
+        .elf, .macho => true,
+        else => false,
+    };
     return false;
 }
 
test/behavior/math.zig
@@ -1722,6 +1722,7 @@ test "signed zeros are represented properly" {
     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
+    if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
 
     const S = struct {
         fn doTheTest() !void {
test/tests.zig
@@ -1113,8 +1113,6 @@ const test_targets = blk: {
                 .os_tag = .linux,
                 .abi = .none,
             },
-            .use_llvm = false,
-            .use_lld = false,
         },
         .{
             .target = .{
@@ -1123,8 +1121,6 @@ const test_targets = blk: {
                 .os_tag = .linux,
                 .abi = .none,
             },
-            .use_llvm = false,
-            .use_lld = false,
             .pic = true,
         },
         .{
@@ -1134,8 +1130,6 @@ const test_targets = blk: {
                 .os_tag = .linux,
                 .abi = .none,
             },
-            .use_llvm = false,
-            .use_lld = false,
             .strip = true,
         },
         .{
@@ -1144,6 +1138,8 @@ const test_targets = blk: {
                 .os_tag = .linux,
                 .abi = .none,
             },
+            .use_llvm = true,
+            .use_lld = true,
         },
         .{
             .target = .{
build.zig
@@ -437,8 +437,8 @@ pub fn build(b: *std.Build) !void {
         .skip_non_native = skip_non_native,
         .skip_libc = skip_libc,
         .use_llvm = use_llvm,
-        // 2520100864 was observed on an x86_64-linux-gnu host.
-        .max_rss = 2772110950,
+        // 2923515904 was observed on an x86_64-linux-gnu host.
+        .max_rss = 3100000000,
     }));
 
     test_modules_step.dependOn(tests.addModuleTests(b, .{