aboutsummaryrefslogtreecommitdiff
path: root/src/link/Elf.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-01-03 20:03:22 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-01-03 20:03:22 -0700
commitff66a18555dc6c00bd928f48462c3fc44f86ab6c (patch)
treee30f1af8d95b1e634d4076cbc521ee2b35d5c90c /src/link/Elf.zig
parent81fa31c05456facea1d1963a1e7f665351fb248d (diff)
downloadzig-ff66a18555dc6c00bd928f48462c3fc44f86ab6c.tar.gz
zig-ff66a18555dc6c00bd928f48462c3fc44f86ab6c.zip
linker: fix build-obj and -fno-emit-bin
This commit fixes two problems: * `zig build-obj` regressed from the cache-mode branch. It would crash because it assumed that dirname on the emit bin path would not be null. This assumption was invalid when outputting to the current working directory - a pretty common use case for `zig build-obj`. * When using the LLVM backend, `-fno-emit-bin` combined with any other kind of emitting, such as `-femit-asm`, emitted nothing. Both issues are now fixed.
Diffstat (limited to 'src/link/Elf.zig')
-rw-r--r--src/link/Elf.zig61
1 files changed, 36 insertions, 25 deletions
diff --git a/src/link/Elf.zig b/src/link/Elf.zig
index 105b012fbf..78a0b9d3a5 100644
--- a/src/link/Elf.zig
+++ b/src/link/Elf.zig
@@ -241,11 +241,7 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
assert(options.object_format == .elf);
if (build_options.have_llvm and options.use_llvm) {
- const self = try createEmpty(allocator, options);
- errdefer self.base.destroy();
-
- self.llvm_object = try LlvmObject.create(allocator, sub_path, options);
- return self;
+ return createEmpty(allocator, options);
}
const file = try options.emit.?.directory.handle.createFile(sub_path, .{
@@ -298,6 +294,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf {
};
const self = try gpa.create(Elf);
errdefer gpa.destroy(self);
+
self.* = .{
.base = .{
.tag = .elf,
@@ -307,9 +304,9 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Elf {
},
.ptr_width = ptr_width,
};
- // TODO get rid of the sub_path parameter to LlvmObject.create
- // and create the llvm_object here. Also openPath needs to
- // not override this field or there will be a memory leak.
+ if (build_options.have_llvm and options.use_llvm) {
+ self.llvm_object = try LlvmObject.create(gpa, options);
+ }
return self;
}
@@ -788,14 +785,21 @@ pub const abbrev_pad1 = 5;
pub const abbrev_parameter = 6;
pub fn flush(self: *Elf, comp: *Compilation) !void {
- if (build_options.have_llvm and self.base.options.use_lld) {
- return self.linkWithLLD(comp);
- } else {
- switch (self.base.options.effectiveOutputMode()) {
- .Exe, .Obj => {},
- .Lib => return error.TODOImplementWritingLibFiles,
+ if (self.base.options.emit == null) {
+ if (build_options.have_llvm) {
+ if (self.llvm_object) |llvm_object| {
+ return try llvm_object.flushModule(comp);
+ }
}
- return self.flushModule(comp);
+ return;
+ }
+ const use_lld = build_options.have_llvm and self.base.options.use_lld;
+ if (use_lld) {
+ return self.linkWithLLD(comp);
+ }
+ switch (self.base.options.output_mode) {
+ .Exe, .Obj => return self.flushModule(comp),
+ .Lib => return error.TODOImplementWritingLibFiles,
}
}
@@ -803,8 +807,11 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void {
const tracy = trace(@src());
defer tracy.end();
- if (build_options.have_llvm)
- if (self.llvm_object) |llvm_object| return try llvm_object.flushModule(comp);
+ if (build_options.have_llvm) {
+ if (self.llvm_object) |llvm_object| {
+ return try llvm_object.flushModule(comp);
+ }
+ }
// TODO This linker code currently assumes there is only 1 compilation unit and it
// corresponds to the Zig source code.
@@ -1327,9 +1334,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
try self.flushModule(comp);
- break :blk try fs.path.join(arena, &.{
- fs.path.dirname(full_out_path).?, self.base.intermediary_basename.?,
- });
+ if (fs.path.dirname(full_out_path)) |dirname| {
+ break :blk try fs.path.join(arena, &.{ dirname, self.base.intermediary_basename.? });
+ } else {
+ break :blk self.base.intermediary_basename.?;
+ }
} else null;
const is_obj = self.base.options.output_mode == .Obj;
@@ -1446,10 +1455,13 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
};
}
- // Due to a deficiency in LLD, we need to special-case BPF to a simple file copy when generating
- // relocatables. Normally, we would expect `lld -r` to work. However, because LLD wants to resolve
- // BPF relocations which it shouldn't, it fails before even generating the relocatable.
- if (self.base.options.output_mode == .Obj and (self.base.options.lto or target.isBpfFreestanding())) {
+ // Due to a deficiency in LLD, we need to special-case BPF to a simple file
+ // copy when generating relocatables. Normally, we would expect `lld -r` to work.
+ // However, because LLD wants to resolve BPF relocations which it shouldn't, it fails
+ // before even generating the relocatable.
+ if (self.base.options.output_mode == .Obj and
+ (self.base.options.lto or target.isBpfFreestanding()))
+ {
// In this case we must do a simple file copy
// here. TODO: think carefully about how we can avoid this redundant operation when doing
// build-obj. See also the corresponding TODO in linkAsArchive.
@@ -1473,7 +1485,6 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
try fs.cwd().copyFile(the_object_path, fs.cwd(), full_out_path, .{});
}
} else {
-
// Create an LLD command line and invoke it.
var argv = std.ArrayList([]const u8).init(self.base.allocator);
defer argv.deinit();