Skip to content

zig cc: add linker -Map flag #18358

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions lib/std/Build/Step/Compile.zig
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ version: ?std.SemanticVersion,
kind: Kind,
major_only_filename: ?[]const u8,
name_only_filename: ?[]const u8,
linker_map_file: ?[]const u8,
// keep in sync with src/link.zig:CompressDebugSections
compress_debug_sections: enum { none, zlib, zstd } = .none,
verbose_link: bool,
Expand Down Expand Up @@ -310,6 +311,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
.rdynamic = false,
.installed_path = null,
.force_undefined_symbols = StringHashMap(void).init(owner.allocator),
.linker_map_file = null,

.emit_directory = null,
.generated_docs = null,
Expand Down Expand Up @@ -1432,6 +1434,9 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
if (self.global_base) |global_base| {
try zig_args.append(b.fmt("--global-base={d}", .{global_base}));
}
if (self.linker_map_file) |map_file| {
try zig_args.append(b.fmt("-Map={s}", .{map_file}));
}

if (self.wasi_exec_model) |model| {
try zig_args.append(b.fmt("-mexec-model={s}", .{@tagName(model)}));
Expand Down
2 changes: 2 additions & 0 deletions src/Compilation.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1048,6 +1048,7 @@ pub const CreateOptions = struct {
linker_print_icf_sections: bool = false,
linker_print_map: bool = false,
llvm_opt_bisect_limit: i32 = -1,
linker_map_file: ?[]const u8 = null,
each_lib_rpath: ?bool = null,
build_id: ?std.zig.BuildId = null,
disable_c_depfile: bool = false,
Expand Down Expand Up @@ -1591,6 +1592,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
.pdb_source_path = options.pdb_source_path,
.pdb_out_path = options.pdb_out_path,
.entry_addr = null, // CLI does not expose this option (yet?)
.map_file = options.linker_map_file,
};

switch (options.cache_mode) {
Expand Down
3 changes: 3 additions & 0 deletions src/link.zig
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,10 @@ pub const File = struct {
soname: ?[]const u8,
print_gc_sections: bool,
print_icf_sections: bool,
/// Print a link map to the standard output
print_map: bool,
/// Print a link map to the specified file
map_file: ?[]const u8,

/// Use a wrapper function for symbol. Any undefined reference to symbol
/// will be resolved to __wrap_symbol. Any undefined reference to
Expand Down
5 changes: 5 additions & 0 deletions src/link/Elf.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2472,6 +2472,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) !voi
man.hash.add(self.compress_debug_sections);
man.hash.add(comp.config.any_sanitize_thread);
man.hash.addOptionalBytes(comp.sysroot);
man.hash.addOptionalBytes(self.base.options.map_file);

// We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.
_ = try man.hit();
Expand Down Expand Up @@ -2732,6 +2733,10 @@ fn linkWithLLD(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) !voi
}
}

if (self.base.options.map_file) |map_file| {
try argv.appendSlice(&.{ "-Map", map_file });
}

for (self.symbol_wrap_set.keys()) |symbol_name| {
try argv.appendSlice(&.{ "-wrap", symbol_name });
}
Expand Down
4 changes: 4 additions & 0 deletions src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -856,6 +856,7 @@ fn buildOutputType(
var linker_dynamicbase = true;
var linker_optimization: ?[]const u8 = null;
var linker_module_definition_file: ?[]const u8 = null;
var linker_map_file: ?[]const u8 = null;
var test_no_exec = false;
var entry: Compilation.CreateOptions.Entry = .default;
var force_undefined_symbols: std.StringArrayHashMapUnmanaged(void) = .{};
Expand Down Expand Up @@ -2440,6 +2441,8 @@ fn buildOutputType(
} else if (mem.eql(u8, arg, "--version")) {
try std.io.getStdOut().writeAll("zig ld " ++ build_options.version ++ "\n");
process.exit(0);
} else if (mem.startsWith(u8, arg, "-Map=")) {
linker_map_file = arg["-Map=".len..];
Comment on lines +2444 to +2445
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This handles -Map=file which is enough for me. Should -Map file be handled as well?

} else {
fatal("unsupported linker arg: {s}", .{arg});
}
Expand Down Expand Up @@ -3197,6 +3200,7 @@ fn buildOutputType(
.linker_dynamicbase = linker_dynamicbase,
.linker_compress_debug_sections = linker_compress_debug_sections,
.linker_module_definition_file = linker_module_definition_file,
.linker_map_file = linker_map_file,
.major_subsystem_version = major_subsystem_version,
.minor_subsystem_version = minor_subsystem_version,
.link_eh_frame_hdr = link_eh_frame_hdr,
Expand Down
23 changes: 23 additions & 0 deletions test/link/elf.zig
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ pub fn testAll(b: *Build) *Step {
elf_step.dependOn(testLinkOrder(b, .{ .target = glibc_target }));
elf_step.dependOn(testLdScript(b, .{ .target = glibc_target }));
elf_step.dependOn(testLdScriptPathError(b, .{ .target = glibc_target }));
elf_step.dependOn(testMapFlag(b, .{ .use_llvm = false, .target = glibc_target }));
elf_step.dependOn(testMapFlag(b, .{ .use_llvm = true, .target = glibc_target }));
elf_step.dependOn(testMismatchedCpuArchitectureError(b, .{ .target = glibc_target }));
// https://github.com/ziglang/zig/issues/17451
// elf_step.dependOn(testNoEhFrameHdr(b, .{ .target = glibc_target }));
Expand Down Expand Up @@ -2008,6 +2010,27 @@ fn testLdScriptPathError(b: *Build, opts: Options) *Step {
return test_step;
}

fn testMapFlag(b: *Build, opts: Options) *Step {
const test_step = addTestStep(b, "map-flag", opts);

var tmp = std.testing.tmpDir(.{});
defer tmp.cleanup();

const tmp_dir_path = tmp.dir.realpathAlloc(b.allocator, ".")
catch @panic("failed to get tmpdir path");
const map_file_path = b.pathJoin(&.{tmp_dir_path, "linkermap.map"});

const exe = addExecutable(b, "main", opts);
addCSourceBytes(exe, "int main() { return 0; }", &.{});
exe.linker_map_file = map_file_path;
exe.linkLibC();

const run = addRunArtifact(exe);
run.expectExitCode(0);

return test_step;
}

fn testMismatchedCpuArchitectureError(b: *Build, opts: Options) *Step {
const test_step = addTestStep(b, "mismatched-cpu-architecture-error", opts);

Expand Down