mirror of
https://github.com/ziglang/zig.git
synced 2026-01-19 13:55:20 +00:00
macho: parse archives
This commit is contained in:
parent
d05e9c3792
commit
c5e509595a
@ -845,11 +845,48 @@ fn parseFatLibrary(self: *MachO, path: []const u8) !fat.Arch {
|
||||
}
|
||||
|
||||
fn parseArchive(self: *MachO, lib: SystemLib, must_link: bool, fat_arch: ?fat.Arch) ParseError!void {
|
||||
_ = self;
|
||||
_ = lib;
|
||||
_ = must_link;
|
||||
_ = fat_arch;
|
||||
return error.Unhandled;
|
||||
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));
|
||||
|
||||
var archive = Archive{ .path = try gpa.dupe(u8, lib.path), .data = data };
|
||||
defer archive.deinit(gpa);
|
||||
try archive.parse(self);
|
||||
|
||||
var has_parse_error = false;
|
||||
for (archive.objects.items) |extracted| {
|
||||
const index = @as(File.Index, @intCast(try self.files.addOne(gpa)));
|
||||
self.files.set(index, .{ .object = extracted });
|
||||
const object = &self.files.items(.data)[index].object;
|
||||
object.index = index;
|
||||
object.alive = must_link or lib.needed; // TODO: or self.options.all_load;
|
||||
object.hidden = lib.hidden;
|
||||
object.parse(self) catch |err| switch (err) {
|
||||
error.MalformedObject,
|
||||
error.InvalidCpuArch,
|
||||
error.InvalidTarget,
|
||||
=> has_parse_error = true,
|
||||
else => |e| return e,
|
||||
};
|
||||
try self.objects.append(gpa, index);
|
||||
|
||||
// Finally, we do a post-parse check for -ObjC to see if we need to force load this member
|
||||
// anyhow.
|
||||
// TODO: object.alive = object.alive or (self.options.force_load_objc and object.hasObjc());
|
||||
}
|
||||
if (has_parse_error) return error.MalformedArchive;
|
||||
}
|
||||
|
||||
fn parseDylib(self: *MachO, lib: SystemLib, explicit: bool, fat_arch: ?fat.Arch) ParseError!void {
|
||||
|
||||
@ -73,14 +73,20 @@ pub fn isArchive(path: []const u8, fat_arch: ?fat.Arch) !bool {
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Archive, allocator: Allocator) void {
|
||||
allocator.free(self.data);
|
||||
allocator.free(self.path);
|
||||
self.objects.deinit(allocator);
|
||||
}
|
||||
|
||||
pub fn parse(self: *Archive, arena: Allocator, macho_file: *MachO) !void {
|
||||
const gpa = macho_file.base.allocator;
|
||||
pub fn parse(self: *Archive, macho_file: *MachO) !void {
|
||||
const gpa = macho_file.base.comp.gpa;
|
||||
|
||||
var arena = std.heap.ArenaAllocator.init(gpa);
|
||||
defer arena.deinit();
|
||||
|
||||
var stream = std.io.fixedBufferStream(self.data);
|
||||
const reader = stream.reader();
|
||||
_ = try reader.readBytesNoEof(SARMAG);
|
||||
|
||||
while (true) {
|
||||
if (stream.pos >= self.data.len) break;
|
||||
@ -89,18 +95,18 @@ pub fn parse(self: *Archive, arena: Allocator, macho_file: *MachO) !void {
|
||||
const hdr = try reader.readStruct(ar_hdr);
|
||||
|
||||
if (!mem.eql(u8, &hdr.ar_fmag, ARFMAG)) {
|
||||
macho_file.base.fatal("{s}: invalid header delimiter: expected '{s}', found '{s}'", .{
|
||||
self.path, std.fmt.fmtSliceEscapeLower(ARFMAG), std.fmt.fmtSliceEscapeLower(&hdr.ar_fmag),
|
||||
try macho_file.reportParseError(self.path, "invalid header delimiter: expected '{s}', found '{s}'", .{
|
||||
std.fmt.fmtSliceEscapeLower(ARFMAG), std.fmt.fmtSliceEscapeLower(&hdr.ar_fmag),
|
||||
});
|
||||
return error.ParseFailed;
|
||||
return error.MalformedArchive;
|
||||
}
|
||||
|
||||
var size = try hdr.size();
|
||||
const name = name: {
|
||||
if (hdr.name()) |n| break :name try arena.dupe(u8, n);
|
||||
if (hdr.name()) |n| break :name n;
|
||||
if (try hdr.nameLength()) |len| {
|
||||
size -= len;
|
||||
const buf = try arena.alloc(u8, len);
|
||||
const buf = try arena.allocator().alloc(u8, len);
|
||||
try reader.readNoEof(buf);
|
||||
const actual_len = mem.indexOfScalar(u8, buf, @as(u8, 0)) orelse len;
|
||||
break :name buf[0..actual_len];
|
||||
@ -114,9 +120,9 @@ pub fn parse(self: *Archive, arena: Allocator, macho_file: *MachO) !void {
|
||||
if (mem.eql(u8, name, "__.SYMDEF") or mem.eql(u8, name, "__.SYMDEF SORTED")) continue;
|
||||
|
||||
const object = Object{
|
||||
.archive = self.path,
|
||||
.path = name,
|
||||
.data = self.data[stream.pos..][0..size],
|
||||
.archive = try gpa.dupe(u8, self.path),
|
||||
.path = try gpa.dupe(u8, name),
|
||||
.data = try gpa.dupe(u8, self.data[stream.pos..][0..size]),
|
||||
.index = undefined,
|
||||
.alive = false,
|
||||
.mtime = hdr.date() catch 0,
|
||||
|
||||
@ -56,6 +56,7 @@ pub fn deinit(self: *Object, allocator: Allocator) void {
|
||||
sf.stabs.deinit(allocator);
|
||||
}
|
||||
self.stab_files.deinit(allocator);
|
||||
allocator.free(self.data);
|
||||
}
|
||||
|
||||
pub fn parse(self: *Object, macho_file: *MachO) !void {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user