authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-01-11 18:23:54+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-01-24 12:34:39+01:00
log8c7a34ae68bbc87e67692e280350f8f825a59230
treee57710e2d5230555219d3d7ae576286c7179adb4
parentc023b762cd2898e6d2f5cb3c1f6f188ebeb00069

macho: prep for dylib deps (no resolution yet)


1 files changed, 158 insertions(+), 0 deletions(-)

src/link/MachO.zig+158
......@@ -470,6 +470,18 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node
470470
471471 if (comp.link_errors.items.len > 0) return error.FlushFailure;
472472
473 for (self.dylibs.items) |index| {
474 self.getFile(index).?.dylib.umbrella = index;
475 }
476
477 // try self.parseDependentDylibs();
478
479 for (self.dylibs.items) |index| {
480 const dylib = self.getFile(index).?.dylib;
481 if (!dylib.explicit and !dylib.hoisted) continue;
482 try dylib.initSymbols(self);
483 }
484
473485 state_log.debug("{}", .{self.dumpState()});
474486
475487 @panic("TODO");
......@@ -954,6 +966,152 @@ fn parseTbd(self: *MachO, lib: SystemLib, explicit: bool) ParseError!File.Index
954966 return index;
955967}
956968
969// /// According to ld64's manual, public (i.e., system) dylibs/frameworks are hoisted into the final
970// /// image unless overriden by -no_implicit_dylibs.
971// fn isHoisted(self: *MachO, install_name: []const u8) bool {
972// _ = self;
973// // TODO: if (self.options.no_implicit_dylibs) return true;
974// if (std.fs.path.dirname(install_name)) |dirname| {
975// if (mem.startsWith(u8, dirname, "/usr/lib")) return true;
976// if (eatPrefix(dirname, "/System/Library/Frameworks/")) |path| {
977// const basename = std.fs.path.basename(install_name);
978// if (mem.indexOfScalar(u8, path, '.')) |index| {
979// if (mem.eql(u8, basename, path[0..index])) return true;
980// }
981// }
982// }
983// return false;
984// }
985
986// fn parseDependentDylibs(
987// self: *MachO
988// ) !void {
989// const tracy = trace(@src());
990// defer tracy.end();
991
992// const gpa = self.base.comp.gpa;
993// const lib_dirs = self.base.comp.lib_dirs;
994// const framework_dirs = self.base.comp.framework_dirs;
995
996// if (self.dylibs.items.len == 0) return;
997
998// var arena = std.heap.ArenaAllocator.init(gpa);
999// defer arena.deinit();
1000
1001// // TODO handle duplicate dylibs - it is not uncommon to have the same dylib loaded multiple times
1002// // in which case we should track that and return File.Index immediately instead re-parsing paths.
1003
1004// var index: usize = 0;
1005// while (index < self.dylibs.items.len) : (index += 1) {
1006// const dylib_index = self.dylibs.items[index];
1007
1008// var dependents = std.ArrayList(File.Index).init(gpa);
1009// defer dependents.deinit();
1010// try dependents.ensureTotalCapacityPrecise(self.getFile(dylib_index).?.dylib.dependents.items.len);
1011
1012// const is_weak = self.getFile(dylib_index).?.dylib.weak;
1013// for (self.getFile(dylib_index).?.dylib.dependents.items) |id| {
1014// // We will search for the dependent dylibs in the following order:
1015// // 1. Basename is in search lib directories or framework directories
1016// // 2. If name is an absolute path, search as-is optionally prepending a syslibroot
1017// // if specified.
1018// // 3. If name is a relative path, substitute @rpath, @loader_path, @executable_path with
1019// // dependees list of rpaths, and search there.
1020// // 4. Finally, just search the provided relative path directly in CWD.
1021// const full_path = full_path: {
1022// fail: {
1023// const stem = std.fs.path.stem(id.name);
1024// const framework_name = try std.fmt.allocPrint(gpa, "{s}.framework" ++ std.fs.path.sep_str ++ "{s}", .{
1025// stem,
1026// stem,
1027// });
1028// defer gpa.free(framework_name);
1029
1030// if (mem.endsWith(u8, id.name, framework_name)) {
1031// // Framework
1032// const full_path = (try self.resolveFramework(arena, framework_dirs, stem)) orelse break :fail;
1033// break :full_path full_path;
1034// }
1035
1036// // Library
1037// const lib_name = eatPrefix(stem, "lib") orelse stem;
1038// const full_path = (try self.resolveLib(arena, lib_dirs, lib_name)) orelse break :fail;
1039// break :full_path full_path;
1040// }
1041
1042// if (std.fs.path.isAbsolute(id.name)) {
1043// const path = if (self.options.syslibroot) |root|
1044// try std.fs.path.join(arena, &.{ root, id.name })
1045// else
1046// id.name;
1047// for (&[_][]const u8{ "", ".tbd", ".dylib" }) |ext| {
1048// const full_path = try std.fmt.allocPrint(arena, "{s}{s}", .{ path, ext });
1049// if (try accessLibPath(full_path)) break :full_path full_path;
1050// }
1051// }
1052
1053// if (eatPrefix(id.name, "@rpath/")) |path| {
1054// const dylib = self.getFile(dylib_index).?.dylib;
1055// for (self.getFile(dylib.umbrella).?.dylib.rpaths.keys()) |rpath| {
1056// const prefix = eatPrefix(rpath, "@loader_path/") orelse rpath;
1057// const rel_path = try std.fs.path.join(arena, &.{ prefix, path });
1058// var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
1059// const full_path = std.fs.realpath(rel_path, &buffer) catch continue;
1060// break :full_path full_path;
1061// }
1062// } else if (eatPrefix(id.name, "@loader_path/")) |_| {
1063// return self.base.fatal("{s}: TODO handle install_name '{s}'", .{
1064// self.getFile(dylib_index).?.dylib.path, id.name,
1065// });
1066// } else if (eatPrefix(id.name, "@executable_path/")) |_| {
1067// return self.base.fatal("{s}: TODO handle install_name '{s}'", .{
1068// self.getFile(dylib_index).?.dylib.path, id.name,
1069// });
1070// }
1071
1072// var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
1073// const full_path = std.fs.realpath(id.name, &buffer) catch {
1074// dependents.appendAssumeCapacity(0);
1075// continue;
1076// };
1077// break :full_path full_path;
1078// };
1079// const link_obj = LinkObject{
1080// .path = full_path,
1081// .tag = .obj,
1082// .weak = is_weak,
1083// };
1084// const file_index = file_index: {
1085// if (try self.parseDylib(arena, link_obj, false)) |file| break :file_index file;
1086// if (try self.parseTbd(link_obj, false)) |file| break :file_index file;
1087// break :file_index @as(File.Index, 0);
1088// };
1089// dependents.appendAssumeCapacity(file_index);
1090// }
1091
1092// const dylib = self.getFile(dylib_index).?.dylib;
1093// for (dylib.dependents.items, dependents.items) |id, file_index| {
1094// if (self.getFile(file_index)) |file| {
1095// const dep_dylib = file.dylib;
1096// dep_dylib.hoisted = self.isHoisted(id.name);
1097// if (self.getFile(dep_dylib.umbrella) == null) {
1098// dep_dylib.umbrella = dylib.umbrella;
1099// }
1100// if (!dep_dylib.hoisted) {
1101// const umbrella = dep_dylib.getUmbrella(self);
1102// for (dep_dylib.exports.items(.name), dep_dylib.exports.items(.flags)) |off, flags| {
1103// try umbrella.addExport(gpa, dep_dylib.getString(off), flags);
1104// }
1105// try umbrella.rpaths.ensureUnusedCapacity(gpa, dep_dylib.rpaths.keys().len);
1106// for (dep_dylib.rpaths.keys()) |rpath| {
1107// umbrella.rpaths.putAssumeCapacity(rpath, {});
1108// }
1109// }
1110// } else self.base.fatal("{s}: unable to resolve dependency {s}", .{ dylib.getUmbrella(self).path, id.name });
1111// }
1112// }
1113// }
1114
9571115fn shrinkAtom(self: *MachO, atom_index: Atom.Index, new_block_size: u64) void {
9581116 _ = self;
9591117 _ = atom_index;