| ... | ... | @@ -470,6 +470,18 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node |
| 470 | 470 | |
| 471 | 471 | if (comp.link_errors.items.len > 0) return error.FlushFailure; |
| 472 | 472 | |
| 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 | |
| 473 | 485 | state_log.debug("{}", .{self.dumpState()}); |
| 474 | 486 | |
| 475 | 487 | @panic("TODO"); |
| ... | ... | @@ -954,6 +966,152 @@ fn parseTbd(self: *MachO, lib: SystemLib, explicit: bool) ParseError!File.Index |
| 954 | 966 | return index; |
| 955 | 967 | } |
| 956 | 968 | |
| 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 | |
| 957 | 1115 | fn shrinkAtom(self: *MachO, atom_index: Atom.Index, new_block_size: u64) void { |
| 958 | 1116 | _ = self; |
| 959 | 1117 | _ = atom_index; |