From d026202a26e56e7e2ea20ca49509fdcf8b937020 Mon Sep 17 00:00:00 2001 From: David Gonzalez Martin Date: Thu, 6 Apr 2023 10:16:20 +0200 Subject: [PATCH 1/2] Expose an option for producing 64-bit DWARF format This commit enables producing 64-bit DWARF format for Zig executables that are produced through the LLVM backend. This is achieved by exposing both command-line flags and CompileStep flags. The production of the 64-bit format only affects binaries that use the DWARF format and it is disabled on MacOS due to it being problematic. This commit, despite generating the interface for the Zig user to be able to tell the compile which format is wanted, is just implemented for the LLVM backend, so clang and the self-hosted backends will need this to be implemented in a future commit. This is an effort to work around #7962, since the emission of the 64-bit format automatically produces 64-bit relocations. Further investigation will be needed to make DWARF 32-bit format to emit bigger relocations when needed and not make the linker angry. --- lib/std/Build/CompileStep.zig | 9 +++++++++ lib/std/dwarf.zig | 5 +++++ src/Compilation.zig | 2 ++ src/codegen/llvm.zig | 9 ++++++++- src/codegen/llvm/bindings.zig | 2 +- src/link.zig | 2 ++ src/main.zig | 6 ++++++ src/zig_llvm.cpp | 6 +++++- src/zig_llvm.h | 2 +- 9 files changed, 39 insertions(+), 4 deletions(-) diff --git a/lib/std/Build/CompileStep.zig b/lib/std/Build/CompileStep.zig index 9340ec8d99ffc9cab281b45bf9855cd94d62886d..2c51d5885250cdf0654b0fe944d361e5ddeadbb6 100644 --- a/lib/std/Build/CompileStep.zig +++ b/lib/std/Build/CompileStep.zig @@ -69,6 +69,7 @@ disable_stack_probing: bool, disable_sanitize_c: bool, sanitize_thread: bool, rdynamic: bool, +dwarf_format: ?std.dwarf.Format = null, import_memory: bool = false, /// For WebAssembly targets, this will allow for undefined symbols to /// be imported from the host environment. @@ -1449,6 +1450,14 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { try addFlag(&zig_args, "strip", self.strip); try addFlag(&zig_args, "unwind-tables", self.unwind_tables); + if (!self.producesPdbFile()) { + if (self.dwarf_format) |dwarf_format| { + try zig_args.append(switch (dwarf_format) { + .dwarf32 => "-gdwarf32", + .dwarf64 => "-gdwarf64", + }); + } + } switch (self.compress_debug_sections) { .none => {}, diff --git a/lib/std/dwarf.zig b/lib/std/dwarf.zig index 99dff14c3615c906383a754ded3e2ad5966245e7..505a5cb886ce74aea15890609bdf484112e5da1f 100644 --- a/lib/std/dwarf.zig +++ b/lib/std/dwarf.zig @@ -147,6 +147,11 @@ pub const CC = enum(u8) { GNU_borland_fastcall_i386 = 0x41, }; +pub const Format = enum { + dwarf32, + dwarf64, +}; + const PcRange = struct { start: u64, end: u64, diff --git a/src/Compilation.zig b/src/Compilation.zig index 48a0412b2395ead63c4c9888ebd6c36bbef2fdf5..848b1594fa193ba644378f25f875998c0d56f1b6 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -620,6 +620,7 @@ pub const InitOptions = struct { test_name_prefix: ?[]const u8 = null, test_runner_path: ?[]const u8 = null, subsystem: ?std.Target.SubSystem = null, + dwarf_format: ?std.dwarf.Format = null, /// WASI-only. Type of WASI execution model ("command" or "reactor"). wasi_exec_model: ?std.builtin.WasiExecModel = null, /// (Zig compiler development) Enable dumping linker's state as JSON. @@ -1517,6 +1518,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .disable_lld_caching = options.disable_lld_caching or cache_mode == .whole, .subsystem = options.subsystem, .is_test = options.is_test, + .dwarf_format = options.dwarf_format, .wasi_exec_model = wasi_exec_model, .hash_style = options.hash_style, .enable_link_snapshots = options.enable_link_snapshots, diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 47b47cc80744ba4b8dfdf6f642a6009392c97128..23d9af39e06db364f3a203b47f21447f2115d246 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -433,7 +433,14 @@ pub const Object = struct { if (!options.strip) { switch (options.target.ofmt) { .coff => llvm_module.addModuleCodeViewFlag(), - else => llvm_module.addModuleDebugInfoFlag(), + else => { + const dwarf_format = options.dwarf_format orelse .dwarf32; + const produce_dwarf64 = switch (dwarf_format) { + .dwarf32 => false, + .dwarf64 => true, + }; + llvm_module.addModuleDebugInfoFlag(produce_dwarf64); + }, } const di_builder = llvm_module.createDIBuilder(true); opt_di_builder = di_builder; diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig index 63cac80db8853a481b066a493d5a36e429696ff4..55f0ba896355ea78b9eb29744efce95253a24030 100644 --- a/src/codegen/llvm/bindings.zig +++ b/src/codegen/llvm/bindings.zig @@ -409,7 +409,7 @@ pub const Module = opaque { extern fn LLVMSetTarget(M: *Module, Triple: [*:0]const u8) void; pub const addModuleDebugInfoFlag = ZigLLVMAddModuleDebugInfoFlag; - extern fn ZigLLVMAddModuleDebugInfoFlag(module: *Module) void; + extern fn ZigLLVMAddModuleDebugInfoFlag(module: *Module, dwarf64: bool) void; pub const addModuleCodeViewFlag = ZigLLVMAddModuleCodeViewFlag; extern fn ZigLLVMAddModuleCodeViewFlag(module: *Module) void; diff --git a/src/link.zig b/src/link.zig index c8999cee4764cd5ed73f3c1bd861695cec56c9d7..a0a1bdad949e067ca6ea9c151a5785f5e9593d56 100644 --- a/src/link.zig +++ b/src/link.zig @@ -200,6 +200,8 @@ pub const Options = struct { compatibility_version: ?std.builtin.Version, libc_installation: ?*const LibCInstallation, + dwarf_format: ?std.dwarf.Format = null, + /// WASI-only. Type of WASI execution model ("command" or "reactor"). wasi_exec_model: std.builtin.WasiExecModel = undefined, diff --git a/src/main.zig b/src/main.zig index 2bc4961cba939aaa4fb4bbb0663455a258f7fa56..81a83d580d80dbb43b875f2725513b042c0b57e0 100644 --- a/src/main.zig +++ b/src/main.zig @@ -844,6 +844,7 @@ fn buildOutputType( var reference_trace: ?u32 = null; var error_tracing: ?bool = null; var pdb_out_path: ?[]const u8 = null; + var dwarf_format: ?std.dwarf.Format = null; // e.g. -m3dnow or -mno-outline-atomics. They correspond to std.Target llvm cpu feature names. // This array is populated by zig cc frontend and then has to be converted to zig-style @@ -1355,6 +1356,10 @@ fn buildOutputType( strip = true; } else if (mem.eql(u8, arg, "-fno-strip")) { strip = false; + } else if (mem.eql(u8, arg, "-gdwarf32")) { + dwarf_format = .dwarf32; + } else if (mem.eql(u8, arg, "-gdwarf64")) { + dwarf_format = .dwarf64; } else if (mem.eql(u8, arg, "-fformatted-panics")) { formatted_panics = true; } else if (mem.eql(u8, arg, "-fno-formatted-panics")) { @@ -3145,6 +3150,7 @@ fn buildOutputType( .test_runner_path = test_runner_path, .disable_lld_caching = !output_to_cache, .subsystem = subsystem, + .dwarf_format = dwarf_format, .wasi_exec_model = wasi_exec_model, .debug_compile_errors = debug_compile_errors, .enable_link_snapshots = enable_link_snapshots, diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index a88442042203a9cd6fba78afae392b69d76e9387..af53bd1d27a2b8870b730be767730465fee055e3 100644 --- a/src/zig_llvm.cpp +++ b/src/zig_llvm.cpp @@ -1163,9 +1163,13 @@ void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type, free(native_triple); } -void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module) { +void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module, bool produce_dwarf64) { unwrap(module)->addModuleFlag(Module::Warning, "Debug Info Version", DEBUG_METADATA_VERSION); unwrap(module)->addModuleFlag(Module::Warning, "Dwarf Version", 4); + + if (produce_dwarf64) { + unwrap(module)->addModuleFlag(Module::Warning, "DWARF64", 1); + } } void ZigLLVMAddModuleCodeViewFlag(LLVMModuleRef module) { diff --git a/src/zig_llvm.h b/src/zig_llvm.h index e466be9e8c27f7179b0f5f1ca76ca6b1d93a00d1..8f24d045a2b8b62564051b54d0834d5098159ad8 100644 --- a/src/zig_llvm.h +++ b/src/zig_llvm.h @@ -238,7 +238,7 @@ ZIG_EXTERN_C unsigned ZigLLVMTag_DW_union_type(void); ZIG_EXTERN_C struct ZigLLVMDIBuilder *ZigLLVMCreateDIBuilder(LLVMModuleRef module, bool allow_unresolved); ZIG_EXTERN_C void ZigLLVMDisposeDIBuilder(struct ZigLLVMDIBuilder *dbuilder); -ZIG_EXTERN_C void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module); +ZIG_EXTERN_C void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module, bool produce_dwarf64); ZIG_EXTERN_C void ZigLLVMAddModuleCodeViewFlag(LLVMModuleRef module); ZIG_EXTERN_C void ZigLLVMSetModulePICLevel(LLVMModuleRef module); ZIG_EXTERN_C void ZigLLVMSetModulePIELevel(LLVMModuleRef module); -- 2.54.0 From ceff2782029672714ac2e04a7b3e25af23eb9a9b Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 20 Apr 2023 15:09:33 -0700 Subject: [PATCH 2/2] fixes to the previous commit * CompileStep: Avoid calling producesPdbFile() to determine whether the option should be respected. If the user asks for it, put it on the command line and let the Zig CLI deal with it appropriately. * Make the namespace of `std.dwarf.Format.dwarf32` no longer have a redundant "dwarf" in it. * Add `zig cc` integration for `-gdwarf32` and `-gdwarf64`. * Toss in a bonus bug fix for `-gdwarf-2`, `-gdwarf-3`, etc. * Avoid using default init values for struct fields unnecessarily. * Add missing cache hash addition for the new option. --- lib/std/Build/CompileStep.zig | 13 ++++--- lib/std/dwarf.zig | 5 +-- src/Compilation.zig | 9 ++++- src/clang_options_data.zig | 63 ++++++++++++++++++++++++++++++---- src/codegen/llvm.zig | 9 +---- src/link.zig | 2 +- src/main.zig | 14 ++++++-- tools/update_clang_options.zig | 18 +++++++--- 8 files changed, 98 insertions(+), 35 deletions(-) diff --git a/lib/std/Build/CompileStep.zig b/lib/std/Build/CompileStep.zig index 2c51d5885250cdf0654b0fe944d361e5ddeadbb6..b71298ce6a813f39d4a60693dc324b63e1bc08e0 100644 --- a/lib/std/Build/CompileStep.zig +++ b/lib/std/Build/CompileStep.zig @@ -1450,13 +1450,12 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { try addFlag(&zig_args, "strip", self.strip); try addFlag(&zig_args, "unwind-tables", self.unwind_tables); - if (!self.producesPdbFile()) { - if (self.dwarf_format) |dwarf_format| { - try zig_args.append(switch (dwarf_format) { - .dwarf32 => "-gdwarf32", - .dwarf64 => "-gdwarf64", - }); - } + + if (self.dwarf_format) |dwarf_format| { + try zig_args.append(switch (dwarf_format) { + .@"32" => "-gdwarf32", + .@"64" => "-gdwarf64", + }); } switch (self.compress_debug_sections) { diff --git a/lib/std/dwarf.zig b/lib/std/dwarf.zig index 505a5cb886ce74aea15890609bdf484112e5da1f..d7b4e29947b75ad8c5501be3a48fd307af1b9c62 100644 --- a/lib/std/dwarf.zig +++ b/lib/std/dwarf.zig @@ -147,10 +147,7 @@ pub const CC = enum(u8) { GNU_borland_fastcall_i386 = 0x41, }; -pub const Format = enum { - dwarf32, - dwarf64, -}; +pub const Format = enum { @"32", @"64" }; const PcRange = struct { start: u64, diff --git a/src/Compilation.zig b/src/Compilation.zig index 848b1594fa193ba644378f25f875998c0d56f1b6..a07ac417e3fa41b96ac448eb6c92d90eed1bddec 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1112,6 +1112,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { cache.hash.add(link_libunwind); cache.hash.add(options.output_mode); cache.hash.add(options.machine_code_model); + cache.hash.addOptional(options.dwarf_format); cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_bin); cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_implib); cache.hash.addBytes(options.root_name); @@ -4490,7 +4491,13 @@ pub fn addCCArgs( // generation, it only changes the type of information generated. try argv.appendSlice(&.{ "-g", "-gcodeview" }); }, - .elf, .macho => try argv.append("-gdwarf-4"), + .elf, .macho => { + try argv.append("-gdwarf-4"); + if (comp.bin_file.options.dwarf_format) |f| switch (f) { + .@"32" => try argv.append("-gdwarf32"), + .@"64" => try argv.append("-gdwarf64"), + }; + }, else => try argv.append("-g"), } } diff --git a/src/clang_options_data.zig b/src/clang_options_data.zig index fc23d8696449fe5c25769533aaf6095f49a9d5fb..c342cf7777465d020e127dac441a568ff6ca0861 100644 --- a/src/clang_options_data.zig +++ b/src/clang_options_data.zig @@ -3870,13 +3870,62 @@ flagpd1("gcodeview-command-line"), flagpd1("gcodeview-ghash"), flagpd1("gcolumn-info"), flagpd1("gdbx"), -flagpd1("gdwarf"), -flagpd1("gdwarf32"), -flagpd1("gdwarf64"), -flagpd1("gdwarf-2"), -flagpd1("gdwarf-3"), -flagpd1("gdwarf-4"), -flagpd1("gdwarf-5"), +.{ + .name = "gdwarf", + .syntax = .flag, + .zig_equivalent = .debug, + .pd1 = true, + .pd2 = false, + .psl = false, +}, +.{ + .name = "gdwarf32", + .syntax = .flag, + .zig_equivalent = .gdwarf32, + .pd1 = true, + .pd2 = false, + .psl = false, +}, +.{ + .name = "gdwarf64", + .syntax = .flag, + .zig_equivalent = .gdwarf64, + .pd1 = true, + .pd2 = false, + .psl = false, +}, +.{ + .name = "gdwarf-2", + .syntax = .flag, + .zig_equivalent = .debug, + .pd1 = true, + .pd2 = false, + .psl = false, +}, +.{ + .name = "gdwarf-3", + .syntax = .flag, + .zig_equivalent = .debug, + .pd1 = true, + .pd2 = false, + .psl = false, +}, +.{ + .name = "gdwarf-4", + .syntax = .flag, + .zig_equivalent = .debug, + .pd1 = true, + .pd2 = false, + .psl = false, +}, +.{ + .name = "gdwarf-5", + .syntax = .flag, + .zig_equivalent = .debug, + .pd1 = true, + .pd2 = false, + .psl = false, +}, flagpd1("gdwarf-aranges"), flagpd1("gembed-source"), sepd1("gen-cdb-fragment-path"), diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 23d9af39e06db364f3a203b47f21447f2115d246..a081448155b0ae66a4ee9745f2ee0d0bdfc4f55a 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -433,14 +433,7 @@ pub const Object = struct { if (!options.strip) { switch (options.target.ofmt) { .coff => llvm_module.addModuleCodeViewFlag(), - else => { - const dwarf_format = options.dwarf_format orelse .dwarf32; - const produce_dwarf64 = switch (dwarf_format) { - .dwarf32 => false, - .dwarf64 => true, - }; - llvm_module.addModuleDebugInfoFlag(produce_dwarf64); - }, + else => llvm_module.addModuleDebugInfoFlag(options.dwarf_format == std.dwarf.Format.@"64"), } const di_builder = llvm_module.createDIBuilder(true); opt_di_builder = di_builder; diff --git a/src/link.zig b/src/link.zig index a0a1bdad949e067ca6ea9c151a5785f5e9593d56..672a53999f5bf1455632f556e5fc99ba27c5bccc 100644 --- a/src/link.zig +++ b/src/link.zig @@ -200,7 +200,7 @@ pub const Options = struct { compatibility_version: ?std.builtin.Version, libc_installation: ?*const LibCInstallation, - dwarf_format: ?std.dwarf.Format = null, + dwarf_format: ?std.dwarf.Format, /// WASI-only. Type of WASI execution model ("command" or "reactor"). wasi_exec_model: std.builtin.WasiExecModel = undefined, diff --git a/src/main.zig b/src/main.zig index 81a83d580d80dbb43b875f2725513b042c0b57e0..6a83791ca38fe4f8d2ef40abcb173f38529ffb52 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1357,9 +1357,9 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "-fno-strip")) { strip = false; } else if (mem.eql(u8, arg, "-gdwarf32")) { - dwarf_format = .dwarf32; + dwarf_format = .@"32"; } else if (mem.eql(u8, arg, "-gdwarf64")) { - dwarf_format = .dwarf64; + dwarf_format = .@"64"; } else if (mem.eql(u8, arg, "-fformatted-panics")) { formatted_panics = true; } else if (mem.eql(u8, arg, "-fno-formatted-panics")) { @@ -1767,6 +1767,14 @@ fn buildOutputType( try clang_argv.appendSlice(it.other_args); } }, + .gdwarf32 => { + strip = false; + dwarf_format = .@"32"; + }, + .gdwarf64 => { + strip = false; + dwarf_format = .@"64"; + }, .sanitize => { if (mem.eql(u8, it.only_arg, "undefined")) { want_sanitize_c = true; @@ -5108,6 +5116,8 @@ pub const ClangArgIterator = struct { asm_only, optimize, debug, + gdwarf32, + gdwarf64, sanitize, linker_script, dry_run, diff --git a/tools/update_clang_options.zig b/tools/update_clang_options.zig index cf7d72595bfc9bd916862a50e69eb23b2ce3cb34..7639d08ce3cf4302fddd35a5fe81fbc360224774 100644 --- a/tools/update_clang_options.zig +++ b/tools/update_clang_options.zig @@ -241,23 +241,31 @@ const known_options = [_]KnownOpt{ .ident = "debug", }, .{ - .name = "g-dwarf", + .name = "gdwarf32", + .ident = "gdwarf32", + }, + .{ + .name = "gdwarf64", + .ident = "gdwarf64", + }, + .{ + .name = "gdwarf", .ident = "debug", }, .{ - .name = "g-dwarf-2", + .name = "gdwarf-2", .ident = "debug", }, .{ - .name = "g-dwarf-3", + .name = "gdwarf-3", .ident = "debug", }, .{ - .name = "g-dwarf-4", + .name = "gdwarf-4", .ident = "debug", }, .{ - .name = "g-dwarf-5", + .name = "gdwarf-5", .ident = "debug", }, .{ -- 2.54.0