authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-05-17 14:28:49+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-05-18 09:28:00+02:00
log73c015b956909d9e28392c858e7c9ecf6827e919
treeba983eeecdd5aac80b2939dedb9cf32860d31cac
parent17b25885989d5f4f0e87de69f5eb3173553de4bc

zld: parse dylib id


3 files changed, 88 insertions(+), 2 deletions(-)

lib/std/macho.zig+32
......@@ -71,6 +71,38 @@ pub const source_version_command = extern struct {
7171 version: u64,
7272};
7373
74/// The build_version_command contains the min OS version on which this
75/// binary was built to run for its platform. The list of known platforms and
76/// tool values following it.
77pub const build_version_command = extern struct {
78 /// LC_BUILD_VERSION
79 cmd: u32,
80
81 /// sizeof(struct build_version_command) plus
82 /// ntools * sizeof(struct build_version_command)
83 cmdsize: u32,
84
85 /// platform
86 platform: u32,
87
88 /// X.Y.Z is encoded in nibbles xxxx.yy.zz
89 minos: u32,
90
91 /// X.Y.Z is encoded in nibbles xxxx.yy.zz
92 sdk: u32,
93
94 /// number of tool entries following this
95 ntools: u32,
96};
97
98pub const build_tool_version = extern struct {
99 /// enum for the tool
100 tool: u32,
101
102 /// version number of the tool
103 version: u32,
104};
105
74106/// The entry_point_command is a replacement for thread_command.
75107/// It is used for main executables to specify the location (file offset)
76108/// of main(). If -stack_size was used at link time, the stacksize
src/link/MachO/Dylib.zig+48
......@@ -23,9 +23,23 @@ load_commands: std.ArrayListUnmanaged(LoadCommand) = .{},
2323
2424symtab_cmd_index: ?u16 = null,
2525dysymtab_cmd_index: ?u16 = null,
26id_cmd_index: ?u16 = null,
27
28id: ?Id = null,
2629
2730symbols: std.StringArrayHashMapUnmanaged(*Symbol) = .{},
2831
32pub const Id = struct {
33 name: []const u8,
34 timestamp: u32,
35 current_version: u32,
36 compatibility_version: u32,
37
38 pub fn deinit(id: *Id, allocator: *Allocator) void {
39 allocator.free(id.name);
40 }
41};
42
2943pub fn init(allocator: *Allocator) Dylib {
3044 return .{ .allocator = allocator };
3145}
......@@ -45,6 +59,10 @@ pub fn deinit(self: *Dylib) void {
4559 if (self.name) |name| {
4660 self.allocator.free(name);
4761 }
62
63 if (self.id) |*id| {
64 id.deinit(self.allocator);
65 }
4866}
4967
5068pub fn closeFile(self: Dylib) void {
......@@ -78,6 +96,7 @@ pub fn parse(self: *Dylib) !void {
7896 }
7997
8098 try self.readLoadCommands(reader);
99 try self.parseId();
81100 try self.parseSymbols();
82101}
83102
......@@ -94,6 +113,9 @@ pub fn readLoadCommands(self: *Dylib, reader: anytype) !void {
94113 macho.LC_DYSYMTAB => {
95114 self.dysymtab_cmd_index = i;
96115 },
116 macho.LC_ID_DYLIB => {
117 self.id_cmd_index = i;
118 },
97119 else => {
98120 log.debug("Unknown load command detected: 0x{x}.", .{cmd.cmd()});
99121 },
......@@ -102,6 +124,32 @@ pub fn readLoadCommands(self: *Dylib, reader: anytype) !void {
102124 }
103125}
104126
127pub fn parseId(self: *Dylib) !void {
128 const index = self.id_cmd_index orelse {
129 log.debug("no LC_ID_DYLIB load command found; using hard-coded defaults...", .{});
130 self.id = .{
131 .name = try self.allocator.dupe(u8, self.name.?),
132 .timestamp = 2,
133 .current_version = 0,
134 .compatibility_version = 0,
135 };
136 return;
137 };
138 const id_cmd = self.load_commands.items[index].Dylib;
139 const dylib = id_cmd.inner.dylib;
140
141 // TODO should we compare the name from the dylib's id with the user-specified one?
142 const dylib_name = @ptrCast([*:0]const u8, id_cmd.data[dylib.name - @sizeOf(macho.dylib_command) ..]);
143 const name = try self.allocator.dupe(u8, mem.spanZ(dylib_name));
144
145 self.id = .{
146 .name = name,
147 .timestamp = dylib.timestamp,
148 .current_version = dylib.current_version,
149 .compatibility_version = dylib.compatibility_version,
150 };
151}
152
105153pub fn parseSymbols(self: *Dylib) !void {
106154 const index = self.symtab_cmd_index orelse return;
107155 const symtab_cmd = self.load_commands.items[index].Symtab;
src/link/MachO/Zld.zig+8-2
......@@ -339,8 +339,14 @@ fn parseDylibs(self: *Zld, shared_libs: []const []const u8) !void {
339339 try self.dylibs.append(self.allocator, dylib);
340340
341341 // Add LC_LOAD_DYLIB command
342 // TODO Read the timestamp and versions from the dylib itself.
343 var dylib_cmd = try createLoadDylibCommand(self.allocator, dylib.name.?, 2, 0, 0);
342 const dylib_id = dylib.id orelse unreachable;
343 var dylib_cmd = try createLoadDylibCommand(
344 self.allocator,
345 dylib_id.name,
346 dylib_id.timestamp,
347 dylib_id.current_version,
348 dylib_id.compatibility_version,
349 );
344350 errdefer dylib_cmd.deinit(self.allocator);
345351
346352 try self.load_commands.append(self.allocator, .{ .Dylib = dylib_cmd });