authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-03-12 17:58:54+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-03-17 19:59:13+01:00
logac0c669473b20a1fdcb818b92381d5ac5d70b64e
treede811065ccbebb97e11e8d390522678711588120
parentde209afbba0984c66fc5c9d379192edec87f0681

zld: add/fix more issues

* fix debug info for static archives * allow handling of empty object files * fix some relocs for GOT loads

3 files changed, 55 insertions(+), 9 deletions(-)

src/link/MachO/Archive.zig+6-2
...@@ -202,13 +202,17 @@ fn readObject(self: *Archive, arch: std.Target.Cpu.Arch, ar_name: []const u8, re...@@ -202,13 +202,17 @@ fn readObject(self: *Archive, arch: std.Target.Cpu.Arch, ar_name: []const u8, re
202 var object = Object{202 var object = Object{
203 .allocator = self.allocator,203 .allocator = self.allocator,
204 .name = object_name,204 .name = object_name,
205 .ar_name = try mem.dupe(self.allocator, u8, ar_name),
205 .file = new_file,206 .file = new_file,
206 .header = header,207 .header = header,
207 };208 };
208209
209 try object.readLoadCommands(reader, .{ .offset = offset });210 try object.readLoadCommands(reader, .{ .offset = offset });
210 try object.readSymtab();211
211 try object.readStrtab();212 if (object.symtab_cmd.index != null) {
213 try object.readSymtab();
214 try object.readStrtab();
215 }
212216
213 if (object.data_in_code_cmd_index != null) try object.readDataInCode();217 if (object.data_in_code_cmd_index != null) try object.readDataInCode();
214218
src/link/MachO/Object.zig+9-2
...@@ -16,6 +16,7 @@ usingnamespace @import("commands.zig");...@@ -16,6 +16,7 @@ usingnamespace @import("commands.zig");
16allocator: *Allocator,16allocator: *Allocator,
17file: fs.File,17file: fs.File,
18name: []u8,18name: []u8,
19ar_name: ?[]u8 = null,
1920
20header: macho.mach_header_64,21header: macho.mach_header_64,
2122
...@@ -49,6 +50,9 @@ pub fn deinit(self: *Object) void {...@@ -49,6 +50,9 @@ pub fn deinit(self: *Object) void {
49 self.strtab.deinit(self.allocator);50 self.strtab.deinit(self.allocator);
50 self.data_in_code_entries.deinit(self.allocator);51 self.data_in_code_entries.deinit(self.allocator);
51 self.allocator.free(self.name);52 self.allocator.free(self.name);
53 if (self.ar_name) |v| {
54 self.allocator.free(v);
55 }
52 self.file.close();56 self.file.close();
53}57}
5458
...@@ -85,8 +89,11 @@ pub fn initFromFile(allocator: *Allocator, arch: std.Target.Cpu.Arch, name: []co...@@ -85,8 +89,11 @@ pub fn initFromFile(allocator: *Allocator, arch: std.Target.Cpu.Arch, name: []co
85 };89 };
8690
87 try self.readLoadCommands(reader, .{});91 try self.readLoadCommands(reader, .{});
88 try self.readSymtab();92
89 try self.readStrtab();93 if (self.symtab_cmd_index != null) {
94 try self.readSymtab();
95 try self.readStrtab();
96 }
9097
91 if (self.data_in_code_cmd_index != null) try self.readDataInCode();98 if (self.data_in_code_cmd_index != null) try self.readDataInCode();
9299
src/link/MachO/Zld.zig+40-5
...@@ -767,7 +767,9 @@ fn resolveImports(self: *Zld) !void {...@@ -767,7 +767,9 @@ fn resolveImports(self: *Zld) !void {
767 mem.eql(u8, sym_name, "___stderrp") or767 mem.eql(u8, sym_name, "___stderrp") or
768 mem.eql(u8, sym_name, "___stdinp") or768 mem.eql(u8, sym_name, "___stdinp") or
769 mem.eql(u8, sym_name, "___stack_chk_guard") or769 mem.eql(u8, sym_name, "___stack_chk_guard") or
770 mem.eql(u8, sym_name, "_environ"))770 mem.eql(u8, sym_name, "_environ") or
771 mem.eql(u8, sym_name, "__DefaultRuneLocale") or
772 mem.eql(u8, sym_name, "_mach_task_self_"))
771 {773 {
772 log.debug("writing nonlazy symbol '{s}'", .{sym_name});774 log.debug("writing nonlazy symbol '{s}'", .{sym_name});
773 const index = @intCast(u32, self.nonlazy_imports.items().len);775 const index = @intCast(u32, self.nonlazy_imports.items().len);
...@@ -1192,6 +1194,8 @@ fn writeStubInStubHelper(self: *Zld, index: u32) !void {...@@ -1192,6 +1194,8 @@ fn writeStubInStubHelper(self: *Zld, index: u32) !void {
1192fn resolveSymbols(self: *Zld) !void {1194fn resolveSymbols(self: *Zld) !void {
1193 for (self.objects.items) |object, object_id| {1195 for (self.objects.items) |object, object_id| {
1194 const seg = object.load_commands.items[object.segment_cmd_index.?].Segment;1196 const seg = object.load_commands.items[object.segment_cmd_index.?].Segment;
1197 log.debug("\n\n", .{});
1198 log.debug("resolving symbols in {s}", .{object.name});
11951199
1196 for (object.symtab.items) |sym| {1200 for (object.symtab.items) |sym| {
1197 if (isImport(&sym)) continue;1201 if (isImport(&sym)) continue;
...@@ -1219,8 +1223,10 @@ fn resolveSymbols(self: *Zld) !void {...@@ -1219,8 +1223,10 @@ fn resolveSymbols(self: *Zld) !void {
1219 if (tt == .Global) {1223 if (tt == .Global) {
1220 for (locs.entry.value.items) |ss| {1224 for (locs.entry.value.items) |ss| {
1221 if (ss.tt == .Global) {1225 if (ss.tt == .Global) {
1222 log.err("symbol '{s}' defined multiple times", .{sym_name});1226 log.debug("symbol already defined '{s}'", .{sym_name});
1223 return error.MultipleSymbolDefinitions;1227 continue;
1228 // log.err("symbol '{s}' defined multiple times: {}", .{ sym_name, sym });
1229 // return error.MultipleSymbolDefinitions;
1224 }1230 }
1225 }1231 }
1226 }1232 }
...@@ -1589,8 +1595,28 @@ fn doRelocs(self: *Zld) !void {...@@ -1589,8 +1595,28 @@ fn doRelocs(self: *Zld) !void {
1589 ),1595 ),
1590 inst,1596 inst,
1591 );1597 );
1598
1592 const ta = if (addend) |a| target_addr + a else target_addr;1599 const ta = if (addend) |a| target_addr + a else target_addr;
1593 const narrowed = @truncate(u12, ta);1600 const narrowed = @truncate(u12, ta);
1601 log.debug(" | narrowed 0x{x}", .{narrowed});
1602 log.debug(" | parsed.size 0x{x}", .{parsed.size});
1603
1604 if (rel_type == .ARM64_RELOC_GOT_LOAD_PAGEOFF12) blk: {
1605 const data_const_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
1606 const got = data_const_seg.sections.items[self.got_section_index.?];
1607 if (got.addr <= target_addr and target_addr < got.addr + got.size) break :blk;
1608
1609 log.debug(" | rewriting to add", .{});
1610 mem.writeIntLittle(u32, inst, aarch64.Instruction.add(
1611 @intToEnum(aarch64.Register, parsed.rt),
1612 @intToEnum(aarch64.Register, parsed.rn),
1613 narrowed,
1614 false,
1615 ).toU32());
1616 addend = null;
1617 continue;
1618 }
1619
1594 const offset: u12 = blk: {1620 const offset: u12 = blk: {
1595 if (parsed.size == 0) {1621 if (parsed.size == 0) {
1596 if (parsed.v == 1) {1622 if (parsed.v == 1) {
...@@ -2628,8 +2654,16 @@ fn writeDebugInfo(self: *Zld) !void {...@@ -2628,8 +2654,16 @@ fn writeDebugInfo(self: *Zld) !void {
2628 });2654 });
2629 // Path to object file with debug info2655 // Path to object file with debug info
2630 var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;2656 var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
2631 const path = object.name;2657 const full_path = blk: {
2632 const full_path = try std.os.realpath(path, &buffer);2658 if (object.ar_name) |prefix| {
2659 const path = try std.os.realpath(prefix, &buffer);
2660 break :blk try std.fmt.allocPrint(self.allocator, "{s}({s})", .{ path, object.name });
2661 } else {
2662 const path = try std.os.realpath(object.name, &buffer);
2663 break :blk try mem.dupe(self.allocator, u8, path);
2664 }
2665 };
2666 defer self.allocator.free(full_path);
2633 const stat = try object.file.stat();2667 const stat = try object.file.stat();
2634 const mtime = @intCast(u64, @divFloor(stat.mtime, 1_000_000_000));2668 const mtime = @intCast(u64, @divFloor(stat.mtime, 1_000_000_000));
2635 try stabs.append(.{2669 try stabs.append(.{
...@@ -2640,6 +2674,7 @@ fn writeDebugInfo(self: *Zld) !void {...@@ -2640,6 +2674,7 @@ fn writeDebugInfo(self: *Zld) !void {
2640 .n_value = mtime,2674 .n_value = mtime,
2641 });2675 });
2642 }2676 }
2677 log.debug("analyzing debug info in '{s}'", .{object.name});
26432678
2644 for (object.symtab.items) |source_sym| {2679 for (object.symtab.items) |source_sym| {
2645 const symname = object.getString(source_sym.n_strx);2680 const symname = object.getString(source_sym.n_strx);