aboutsummaryrefslogtreecommitdiff
path: root/src/link
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-05-08 10:53:22 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-05-08 10:53:22 -0700
commitb6bb0ee1acd6fb9e3360f35d7b63687f755785f6 (patch)
tree34f42b24cc683d13a9e78bd27f914dfee00c37b0 /src/link
parent28353b315935e54b497f4abb875fac387e20f65f (diff)
parent84d5cc31c560749eda1e36b7bc9e6cf542eee550 (diff)
downloadzig-b6bb0ee1acd6fb9e3360f35d7b63687f755785f6.tar.gz
zig-b6bb0ee1acd6fb9e3360f35d7b63687f755785f6.zip
Merge remote-tracking branch 'origin/master' into stage2-whole-file-astgen
Conflicts: * lib/std/os/linux/tls.zig * test/behavior/align.zig * test/behavior/atomics.zig * test/behavior/vector.zig
Diffstat (limited to 'src/link')
-rw-r--r--src/link/MachO/Archive.zig9
-rw-r--r--src/link/MachO/Object.zig26
-rw-r--r--src/link/MachO/Symbol.zig10
-rw-r--r--src/link/MachO/Zld.zig31
-rw-r--r--src/link/MachO/reloc/aarch64.zig2
5 files changed, 59 insertions, 19 deletions
diff --git a/src/link/MachO/Archive.zig b/src/link/MachO/Archive.zig
index 5a0b9609ad..702a807a4d 100644
--- a/src/link/MachO/Archive.zig
+++ b/src/link/MachO/Archive.zig
@@ -16,7 +16,7 @@ allocator: *Allocator,
arch: ?std.Target.Cpu.Arch = null,
file: ?fs.File = null,
header: ?ar_hdr = null,
-name: ?[]u8 = null,
+name: ?[]const u8 = null,
/// Parsed table of contents.
/// Each symbol name points to a list of all definition
@@ -195,7 +195,7 @@ fn parseTableOfContents(self: *Archive, reader: anytype) !void {
}
/// Caller owns the Object instance.
-pub fn parseObject(self: Archive, offset: u32) !Object {
+pub fn parseObject(self: Archive, offset: u32) !*Object {
var reader = self.file.?.reader();
try reader.context.seekTo(offset);
@@ -217,7 +217,10 @@ pub fn parseObject(self: Archive, offset: u32) !Object {
break :name try std.fmt.allocPrint(self.allocator, "{s}({s})", .{ path, object_name });
};
- var object = Object.init(self.allocator);
+ var object = try self.allocator.create(Object);
+ errdefer self.allocator.destroy(object);
+
+ object.* = Object.init(self.allocator);
object.arch = self.arch.?;
object.file = try fs.cwd().openFile(self.name.?, .{});
object.name = name;
diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig
index 31cc63cfe0..4d2ade7aad 100644
--- a/src/link/MachO/Object.zig
+++ b/src/link/MachO/Object.zig
@@ -22,7 +22,7 @@ arch: ?std.Target.Cpu.Arch = null,
header: ?macho.mach_header_64 = null,
file: ?fs.File = null,
file_offset: ?u32 = null,
-name: ?[]u8 = null,
+name: ?[]const u8 = null,
load_commands: std.ArrayListUnmanaged(LoadCommand) = .{},
sections: std.ArrayListUnmanaged(Section) = .{},
@@ -343,14 +343,22 @@ pub fn parseSymbols(self: *Object) !void {
_ = try self.file.?.preadAll(strtab, symtab_cmd.stroff);
for (slice) |sym| {
+ const sym_name = mem.spanZ(@ptrCast([*:0]const u8, strtab.ptr + sym.n_strx));
+
if (Symbol.isStab(sym)) {
- log.err("TODO handle stabs embedded within object files", .{});
- return error.HandleStabsInObjects;
+ log.err("stab {s} in {s}", .{ sym_name, self.name.? });
+ return error.UnhandledSymbolType;
+ }
+ if (Symbol.isIndr(sym)) {
+ log.err("indirect symbol {s} in {s}", .{ sym_name, self.name.? });
+ return error.UnhandledSymbolType;
+ }
+ if (Symbol.isAbs(sym)) {
+ log.err("absolute symbol {s} in {s}", .{ sym_name, self.name.? });
+ return error.UnhandledSymbolType;
}
- const sym_name = mem.spanZ(@ptrCast([*:0]const u8, strtab.ptr + sym.n_strx));
const name = try self.allocator.dupe(u8, sym_name);
-
const symbol: *Symbol = symbol: {
if (Symbol.isSect(sym)) {
const linkage: Symbol.Regular.Linkage = linkage: {
@@ -374,6 +382,14 @@ pub fn parseSymbols(self: *Object) !void {
break :symbol &regular.base;
}
+ if (sym.n_value != 0) {
+ log.err("common symbol {s} in {s}", .{ sym_name, self.name.? });
+ return error.UnhandledSymbolType;
+ // const comm_size = sym.n_value;
+ // const comm_align = (sym.n_desc >> 8) & 0x0f;
+ // log.warn("Common symbol: size 0x{x}, align 0x{x}", .{ comm_size, comm_align });
+ }
+
const undef = try self.allocator.create(Symbol.Unresolved);
errdefer self.allocator.destroy(undef);
undef.* = .{
diff --git a/src/link/MachO/Symbol.zig b/src/link/MachO/Symbol.zig
index 4b8ee3c77c..f928c807a3 100644
--- a/src/link/MachO/Symbol.zig
+++ b/src/link/MachO/Symbol.zig
@@ -133,6 +133,16 @@ pub fn isUndf(sym: macho.nlist_64) bool {
return type_ == macho.N_UNDF;
}
+pub fn isIndr(sym: macho.nlist_64) bool {
+ const type_ = macho.N_TYPE & sym.n_type;
+ return type_ == macho.N_INDR;
+}
+
+pub fn isAbs(sym: macho.nlist_64) bool {
+ const type_ = macho.N_TYPE & sym.n_type;
+ return type_ == macho.N_ABS;
+}
+
pub fn isWeakDef(sym: macho.nlist_64) bool {
return (sym.n_desc & macho.N_WEAK_DEF) != 0;
}
diff --git a/src/link/MachO/Zld.zig b/src/link/MachO/Zld.zig
index 1b343fad3f..4d19da1e97 100644
--- a/src/link/MachO/Zld.zig
+++ b/src/link/MachO/Zld.zig
@@ -82,7 +82,7 @@ unresolved: std.StringArrayHashMapUnmanaged(*Symbol) = .{},
strtab: std.ArrayListUnmanaged(u8) = .{},
strtab_dir: std.StringHashMapUnmanaged(u32) = .{},
-threadlocal_offsets: std.ArrayListUnmanaged(u64) = .{},
+threadlocal_offsets: std.ArrayListUnmanaged(TlvOffset) = .{}, // TODO merge with Symbol abstraction
local_rebases: std.ArrayListUnmanaged(Pointer) = .{},
stubs: std.ArrayListUnmanaged(*Symbol) = .{},
got_entries: std.ArrayListUnmanaged(*Symbol) = .{},
@@ -92,6 +92,15 @@ stub_helper_stubs_start_off: ?u64 = null,
mappings: std.AutoHashMapUnmanaged(MappingKey, SectionMapping) = .{},
unhandled_sections: std.AutoHashMapUnmanaged(MappingKey, u0) = .{},
+const TlvOffset = struct {
+ source_addr: u64,
+ offset: u64,
+
+ fn cmp(context: void, a: TlvOffset, b: TlvOffset) bool {
+ return a.source_addr < b.source_addr;
+ }
+};
+
const MappingKey = struct {
object_id: u16,
source_sect_id: u16,
@@ -277,7 +286,7 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void {
object.* = Object.init(self.allocator);
object.arch = self.arch.?;
- object.name = try self.allocator.dupe(u8, input.name);
+ object.name = input.name;
object.file = input.file;
try object.parse();
try self.objects.append(self.allocator, object);
@@ -288,7 +297,7 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void {
archive.* = Archive.init(self.allocator);
archive.arch = self.arch.?;
- archive.name = try self.allocator.dupe(u8, input.name);
+ archive.name = input.name;
archive.file = input.file;
try archive.parse();
try self.archives.append(self.allocator, archive);
@@ -1362,10 +1371,7 @@ fn resolveSymbols(self: *Zld) !void {
};
assert(offsets.items.len > 0);
- const object = try self.allocator.create(Object);
- errdefer self.allocator.destroy(object);
-
- object.* = try archive.parseObject(offsets.items[0]);
+ const object = try archive.parseObject(offsets.items[0]);
try self.objects.append(self.allocator, object);
try self.resolveSymbolsInObject(object);
@@ -1567,7 +1573,10 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
};
// Since we require TLV data to always preceed TLV bss section, we calculate
// offsets wrt to the former if it is defined; otherwise, wrt to the latter.
- try self.threadlocal_offsets.append(self.allocator, args.target_addr - base_addr);
+ try self.threadlocal_offsets.append(self.allocator, .{
+ .source_addr = args.source_addr,
+ .offset = args.target_addr - base_addr,
+ });
}
},
.got_page, .got_page_off, .got_load, .got => {
@@ -2093,10 +2102,12 @@ fn flush(self: *Zld) !void {
var stream = std.io.fixedBufferStream(buffer);
var writer = stream.writer();
+ std.sort.sort(TlvOffset, self.threadlocal_offsets.items, {}, TlvOffset.cmp);
+
const seek_amt = 2 * @sizeOf(u64);
- while (self.threadlocal_offsets.popOrNull()) |offset| {
+ for (self.threadlocal_offsets.items) |tlv| {
try writer.context.seekBy(seek_amt);
- try writer.writeIntLittle(u64, offset);
+ try writer.writeIntLittle(u64, tlv.offset);
}
try self.file.?.pwriteAll(buffer, sect.offset);
diff --git a/src/link/MachO/reloc/aarch64.zig b/src/link/MachO/reloc/aarch64.zig
index dbc233b3a5..c08934d84b 100644
--- a/src/link/MachO/reloc/aarch64.zig
+++ b/src/link/MachO/reloc/aarch64.zig
@@ -25,7 +25,7 @@ pub const Branch = struct {
log.debug(" | displacement 0x{x}", .{displacement});
var inst = branch.inst;
- inst.unconditional_branch_immediate.imm26 = @truncate(u26, @bitCast(u28, displacement) >> 2);
+ inst.unconditional_branch_immediate.imm26 = @truncate(u26, @bitCast(u28, displacement >> 2));
mem.writeIntLittle(u32, branch.base.code[0..4], inst.toU32());
}
};