mirror of
https://github.com/ziglang/zig.git
synced 2026-01-19 13:55:20 +00:00
macho: parse dylibs
This commit is contained in:
parent
c5e509595a
commit
d153bc2f0c
@ -382,6 +382,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node
|
||||
self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) {
|
||||
error.MalformedObject,
|
||||
error.MalformedArchive,
|
||||
error.MalformedDylib,
|
||||
error.InvalidCpuArch,
|
||||
error.InvalidTarget,
|
||||
error.UnknownFileType,
|
||||
@ -432,8 +433,8 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node
|
||||
|
||||
for (system_libs.items) |lib| {
|
||||
self.parseLibrary(lib, false) catch |err| switch (err) {
|
||||
error.MalformedDylib,
|
||||
error.MalformedArchive,
|
||||
error.MalformedDylib,
|
||||
error.InvalidCpuArch,
|
||||
error.UnknownFileType,
|
||||
=> continue, // already reported
|
||||
@ -794,7 +795,7 @@ fn parseLibrary(self: *MachO, lib: SystemLib, must_link: bool) ParseError!void {
|
||||
if (try Archive.isArchive(lib.path, fat_arch)) {
|
||||
try self.parseArchive(lib, must_link, fat_arch);
|
||||
} else if (try Dylib.isDylib(lib.path, fat_arch)) {
|
||||
try self.parseDylib(lib, true, fat_arch);
|
||||
_ = try self.parseDylib(lib, true, fat_arch);
|
||||
} else {
|
||||
try self.reportParseError(lib.path, "unknown file type for a library", .{});
|
||||
return error.UnknownFileType;
|
||||
@ -802,7 +803,7 @@ fn parseLibrary(self: *MachO, lib: SystemLib, must_link: bool) ParseError!void {
|
||||
} else if (try Archive.isArchive(lib.path, null)) {
|
||||
try self.parseArchive(lib, must_link, null);
|
||||
} else if (try Dylib.isDylib(lib.path, null)) {
|
||||
try self.parseDylib(lib, true, null);
|
||||
_ = try self.parseDylib(lib, true, null);
|
||||
} else {
|
||||
try self.parseTbd(lib, true);
|
||||
}
|
||||
@ -889,12 +890,39 @@ fn parseArchive(self: *MachO, lib: SystemLib, must_link: bool, fat_arch: ?fat.Ar
|
||||
if (has_parse_error) return error.MalformedArchive;
|
||||
}
|
||||
|
||||
fn parseDylib(self: *MachO, lib: SystemLib, explicit: bool, fat_arch: ?fat.Arch) ParseError!void {
|
||||
_ = self;
|
||||
_ = lib;
|
||||
_ = explicit;
|
||||
_ = fat_arch;
|
||||
return error.Unhandled;
|
||||
fn parseDylib(self: *MachO, lib: SystemLib, explicit: bool, fat_arch: ?fat.Arch) ParseError!File.Index {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const gpa = self.base.comp.gpa;
|
||||
|
||||
const file = try std.fs.cwd().openFile(lib.path, .{});
|
||||
defer file.close();
|
||||
|
||||
const data = if (fat_arch) |arch| blk: {
|
||||
try file.seekTo(arch.offset);
|
||||
const data = try gpa.alloc(u8, arch.size);
|
||||
const nread = try file.readAll(data);
|
||||
if (nread != arch.size) return error.InputOutput;
|
||||
break :blk data;
|
||||
} else try file.readToEndAlloc(gpa, std.math.maxInt(u32));
|
||||
|
||||
const index = @as(File.Index, @intCast(try self.files.addOne(gpa)));
|
||||
self.files.set(index, .{ .dylib = .{
|
||||
.path = try gpa.dupe(u8, lib.path),
|
||||
.data = data,
|
||||
.index = index,
|
||||
.needed = lib.needed,
|
||||
.weak = lib.weak,
|
||||
.reexport = lib.reexport,
|
||||
.explicit = explicit,
|
||||
} });
|
||||
const dylib = &self.files.items(.data)[index].dylib;
|
||||
try dylib.parse(self);
|
||||
|
||||
try self.dylibs.append(gpa, index);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
fn parseTbd(self: *MachO, lib: SystemLib, explicit: bool) ParseError!void {
|
||||
|
||||
@ -34,6 +34,8 @@ pub fn isDylib(path: []const u8, fat_arch: ?fat.Arch) !bool {
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Dylib, allocator: Allocator) void {
|
||||
allocator.free(self.data);
|
||||
allocator.free(self.path);
|
||||
self.exports.deinit(allocator);
|
||||
self.strtab.deinit(allocator);
|
||||
if (self.id) |*id| id.deinit(allocator);
|
||||
@ -49,7 +51,7 @@ pub fn parse(self: *Dylib, macho_file: *MachO) !void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const gpa = macho_file.base.allocator;
|
||||
const gpa = macho_file.base.comp.gpa;
|
||||
var stream = std.io.fixedBufferStream(self.data);
|
||||
const reader = stream.reader();
|
||||
|
||||
@ -57,9 +59,22 @@ pub fn parse(self: *Dylib, macho_file: *MachO) !void {
|
||||
|
||||
self.header = try reader.readStruct(macho.mach_header_64);
|
||||
|
||||
const this_cpu_arch: std.Target.Cpu.Arch = switch (self.header.?.cputype) {
|
||||
macho.CPU_TYPE_ARM64 => .aarch64,
|
||||
macho.CPU_TYPE_X86_64 => .x86_64,
|
||||
else => |x| {
|
||||
try macho_file.reportParseError2(self.index, "unknown cpu architecture: {d}", .{x});
|
||||
return error.InvalidCpuArch;
|
||||
},
|
||||
};
|
||||
if (macho_file.getTarget().cpu.arch != this_cpu_arch) {
|
||||
try macho_file.reportParseError2(self.index, "invalid cpu architecture: {s}", .{@tagName(this_cpu_arch)});
|
||||
return error.InvalidCpuArch;
|
||||
}
|
||||
|
||||
const lc_id = self.getLoadCommand(.ID_DYLIB) orelse {
|
||||
macho_file.base.fatal("{s}: missing LC_ID_DYLIB load command", .{self.path});
|
||||
return error.ParseFailed;
|
||||
try macho_file.reportParseError2(self.index, "missing LC_ID_DYLIB load command", .{});
|
||||
return error.MalformedDylib;
|
||||
};
|
||||
self.id = try Id.fromLoadCommand(gpa, lc_id.cast(macho.dylib_command).?, lc_id.getDylibPathName());
|
||||
|
||||
@ -90,6 +105,23 @@ pub fn parse(self: *Dylib, macho_file: *MachO) !void {
|
||||
};
|
||||
|
||||
self.initPlatform();
|
||||
|
||||
if (self.platform) |platform| {
|
||||
if (!macho_file.platform.eqlTarget(platform)) {
|
||||
try macho_file.reportParseError2(self.index, "invalid platform: {}", .{
|
||||
platform.fmtTarget(macho_file.getTarget().cpu.arch),
|
||||
});
|
||||
return error.InvalidTarget;
|
||||
}
|
||||
if (macho_file.platform.version.order(platform.version) == .lt) {
|
||||
try macho_file.reportParseError2(self.index, "object file built for newer platform: {}: {} < {}", .{
|
||||
macho_file.platform.fmtTarget(macho_file.getTarget().cpu.arch),
|
||||
macho_file.platform.version,
|
||||
platform.version,
|
||||
});
|
||||
return error.InvalidTarget;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const TrieIterator = struct {
|
||||
@ -187,7 +219,7 @@ fn parseTrieNode(
|
||||
fn parseTrie(self: *Dylib, data: []const u8, macho_file: *MachO) !void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
const gpa = macho_file.base.allocator;
|
||||
const gpa = macho_file.base.comp.gpa;
|
||||
var arena = std.heap.ArenaAllocator.init(gpa);
|
||||
defer arena.deinit();
|
||||
|
||||
@ -204,7 +236,7 @@ pub fn parseTbd(
|
||||
) !void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
const gpa = macho_file.base.allocator;
|
||||
const gpa = macho_file.base.comp.gpa;
|
||||
|
||||
log.debug("parsing dylib from stub", .{});
|
||||
|
||||
@ -435,7 +467,7 @@ fn addObjCExport(
|
||||
}
|
||||
|
||||
pub fn initSymbols(self: *Dylib, macho_file: *MachO) !void {
|
||||
const gpa = macho_file.base.allocator;
|
||||
const gpa = macho_file.base.comp.gpa;
|
||||
|
||||
try self.symbols.ensureTotalCapacityPrecise(gpa, self.exports.items(.name).len);
|
||||
|
||||
@ -459,7 +491,7 @@ fn initPlatform(self: *Dylib) void {
|
||||
.VERSION_MIN_IPHONEOS,
|
||||
.VERSION_MIN_TVOS,
|
||||
.VERSION_MIN_WATCHOS,
|
||||
=> break MachO.Options.Platform.fromLoadCommand(cmd),
|
||||
=> break MachO.Platform.fromLoadCommand(cmd),
|
||||
else => {},
|
||||
}
|
||||
} else null;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user