authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-05-17 13:40:35+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-05-18 09:28:00+02:00
log17b25885989d5f4f0e87de69f5eb3173553de4bc
tree87e1378ce887b74715ed5d24925d1e9313faae63
parent138cecc0283fdc3ec1b4343c15001e2802ed29de

zld: refactor out logic for dylib LC creation


3 files changed, 49 insertions(+), 63 deletions(-)

src/link/MachO.zig+5-21
......@@ -2096,28 +2096,12 @@ pub fn populateMissingMetadata(self: *MachO) !void {
20962096 }
20972097 if (self.libsystem_cmd_index == null) {
20982098 self.libsystem_cmd_index = @intCast(u16, self.load_commands.items.len);
2099 const cmdsize = @intCast(u32, mem.alignForwardGeneric(
2100 u64,
2101 @sizeOf(macho.dylib_command) + mem.lenZ(LIB_SYSTEM_PATH),
2102 @sizeOf(u64),
2103 ));
2104 // TODO Find a way to work out runtime version from the OS version triple stored in std.Target.
2105 // In the meantime, we're gonna hardcode to the minimum compatibility version of 0.0.0.
2106 const min_version = 0x0;
2107 var dylib_cmd = emptyGenericCommandWithData(macho.dylib_command{
2108 .cmd = macho.LC_LOAD_DYLIB,
2109 .cmdsize = cmdsize,
2110 .dylib = .{
2111 .name = @sizeOf(macho.dylib_command),
2112 .timestamp = 2, // not sure why not simply 0; this is reverse engineered from Mach-O files
2113 .current_version = min_version,
2114 .compatibility_version = min_version,
2115 },
2116 });
2117 dylib_cmd.data = try self.base.allocator.alloc(u8, cmdsize - dylib_cmd.inner.dylib.name);
2118 mem.set(u8, dylib_cmd.data, 0);
2119 mem.copy(u8, dylib_cmd.data, mem.spanZ(LIB_SYSTEM_PATH));
2099
2100 var dylib_cmd = try createLoadDylibCommand(self.base.allocator, mem.spanZ(LIB_SYSTEM_PATH), 2, 0, 0);
2101 errdefer dylib_cmd.deinit(self.base.allocator);
2102
21202103 try self.load_commands.append(self.base.allocator, .{ .Dylib = dylib_cmd });
2104
21212105 self.header_dirty = true;
21222106 self.load_commands_dirty = true;
21232107 }
src/link/MachO/Zld.zig+13-42
......@@ -339,26 +339,10 @@ 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 const cmdsize = @intCast(u32, mem.alignForwardGeneric(
343 u64,
344 @sizeOf(macho.dylib_command) + dylib.name.?.len,
345 @sizeOf(u64),
346 ));
347 // TODO Read the min version from the dylib itself.
348 const min_version = 0x0;
349 var dylib_cmd = emptyGenericCommandWithData(macho.dylib_command{
350 .cmd = macho.LC_LOAD_DYLIB,
351 .cmdsize = cmdsize,
352 .dylib = .{
353 .name = @sizeOf(macho.dylib_command),
354 .timestamp = 2, // TODO parse from the dylib.
355 .current_version = min_version,
356 .compatibility_version = min_version,
357 },
358 });
359 dylib_cmd.data = try self.allocator.alloc(u8, cmdsize - dylib_cmd.inner.dylib.name);
360 mem.set(u8, dylib_cmd.data, 0);
361 mem.copy(u8, dylib_cmd.data, dylib.name.?);
342 // TODO Read the timestamp and versions from the dylib itself.
343 var dylib_cmd = try createLoadDylibCommand(self.allocator, dylib.name.?, 2, 0, 0);
344 errdefer dylib_cmd.deinit(self.allocator);
345
362346 try self.load_commands.append(self.allocator, .{ .Dylib = dylib_cmd });
363347 }
364348}
......@@ -2061,27 +2045,10 @@ fn populateMetadata(self: *Zld) !void {
20612045
20622046 if (self.libsystem_cmd_index == null) {
20632047 self.libsystem_cmd_index = @intCast(u16, self.load_commands.items.len);
2064 const cmdsize = @intCast(u32, mem.alignForwardGeneric(
2065 u64,
2066 @sizeOf(macho.dylib_command) + mem.lenZ(LIB_SYSTEM_PATH),
2067 @sizeOf(u64),
2068 ));
2069 // TODO Find a way to work out runtime version from the OS version triple stored in std.Target.
2070 // In the meantime, we're gonna hardcode to the minimum compatibility version of 0.0.0.
2071 const min_version = 0x0;
2072 var dylib_cmd = emptyGenericCommandWithData(macho.dylib_command{
2073 .cmd = macho.LC_LOAD_DYLIB,
2074 .cmdsize = cmdsize,
2075 .dylib = .{
2076 .name = @sizeOf(macho.dylib_command),
2077 .timestamp = 2, // not sure why not simply 0; this is reverse engineered from Mach-O files
2078 .current_version = min_version,
2079 .compatibility_version = min_version,
2080 },
2081 });
2082 dylib_cmd.data = try self.allocator.alloc(u8, cmdsize - dylib_cmd.inner.dylib.name);
2083 mem.set(u8, dylib_cmd.data, 0);
2084 mem.copy(u8, dylib_cmd.data, mem.spanZ(LIB_SYSTEM_PATH));
2048
2049 var dylib_cmd = try createLoadDylibCommand(self.allocator, mem.spanZ(LIB_SYSTEM_PATH), 2, 0, 0);
2050 errdefer dylib_cmd.deinit(self.allocator);
2051
20852052 try self.load_commands.append(self.allocator, .{ .Dylib = dylib_cmd });
20862053 }
20872054
......@@ -2738,11 +2705,15 @@ fn writeSymbolTable(self: *Zld) !void {
27382705
27392706 for (self.imports.items()) |entry| {
27402707 const sym = entry.value;
2708 const ordinal = ordinal: {
2709 const dylib = sym.cast(Symbol.Proxy).?.dylib orelse break :ordinal 1; // TODO handle libSystem
2710 break :ordinal dylib.ordinal.?;
2711 };
27412712 try undefs.append(.{
27422713 .n_strx = try self.makeString(sym.name),
27432714 .n_type = macho.N_UNDF | macho.N_EXT,
27442715 .n_sect = 0,
2745 .n_desc = macho.N_SYMBOL_RESOLVER | macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY,
2716 .n_desc = (ordinal * macho.N_SYMBOL_RESOLVER) | macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY,
27462717 .n_value = 0,
27472718 });
27482719 }
src/link/MachO/commands.zig+31
......@@ -298,6 +298,37 @@ pub fn GenericCommandWithData(comptime Cmd: type) type {
298298 };
299299}
300300
301pub fn createLoadDylibCommand(
302 allocator: *Allocator,
303 name: []const u8,
304 timestamp: u32,
305 current_version: u32,
306 compatibility_version: u32,
307) !GenericCommandWithData(macho.dylib_command) {
308 const cmdsize = @intCast(u32, mem.alignForwardGeneric(
309 u64,
310 @sizeOf(macho.dylib_command) + name.len,
311 @sizeOf(u64),
312 ));
313
314 var dylib_cmd = emptyGenericCommandWithData(macho.dylib_command{
315 .cmd = macho.LC_LOAD_DYLIB,
316 .cmdsize = cmdsize,
317 .dylib = .{
318 .name = @sizeOf(macho.dylib_command),
319 .timestamp = timestamp,
320 .current_version = current_version,
321 .compatibility_version = compatibility_version,
322 },
323 });
324 dylib_cmd.data = try allocator.alloc(u8, cmdsize - dylib_cmd.inner.dylib.name);
325
326 mem.set(u8, dylib_cmd.data, 0);
327 mem.copy(u8, dylib_cmd.data, name);
328
329 return dylib_cmd;
330}
331
301332fn testRead(allocator: *Allocator, buffer: []const u8, expected: anytype) !void {
302333 var stream = io.fixedBufferStream(buffer);
303334 var given = try LoadCommand.read(allocator, stream.reader());