Commit f1af53f68e

Jakub Konka <kubkon@jakubkonka.com>
2024-07-23 10:33:00
macho: use pread syscall when loading tapi file
This avoids mixing preads with reads which do not mix well especially on Windows.
1 parent 7c37c55
Changed files (3)
src/link/MachO/Dylib.zig
@@ -270,7 +270,10 @@ fn parseTbd(self: *Dylib, macho_file: *MachO) !void {
     log.debug("parsing dylib from stub: {s}", .{self.path});
 
     const file = macho_file.getFileHandle(self.file_handle);
-    var lib_stub = LibStub.loadFromFile(gpa, file) catch return error.NotLibStub;
+    var lib_stub = LibStub.loadFromFile(gpa, file) catch |err| {
+        try macho_file.reportParseError2(self.index, "failed to parse TBD file: {s}", .{@errorName(err)});
+        return error.MalformedTbd;
+    };
     defer lib_stub.deinit();
     const umbrella_lib = lib_stub.inner[0];
 
src/link/MachO.zig
@@ -914,6 +914,7 @@ fn parseInputFileWorker(self: *MachO, file: File) void {
         switch (err) {
             error.MalformedObject,
             error.MalformedDylib,
+            error.MalformedTbd,
             error.InvalidCpuArch,
             error.InvalidTarget,
             => {}, // already reported
@@ -4637,7 +4638,6 @@ const ObjcStubsSection = synthetic.ObjcStubsSection;
 const Object = @import("MachO/Object.zig");
 const LazyBind = bind.LazyBind;
 const LaSymbolPtrSection = synthetic.LaSymbolPtrSection;
-const LibStub = tapi.LibStub;
 const Liveness = @import("../Liveness.zig");
 const LlvmObject = @import("../codegen/llvm.zig").Object;
 const Md5 = std.crypto.hash.Md5;
src/link/tapi.zig
@@ -129,8 +129,8 @@ pub const Tbd = union(enum) {
 
 pub const TapiError = error{
     NotLibStub,
-    FileTooBig,
-} || yaml.YamlError || std.fs.File.ReadError;
+    InputOutput,
+} || yaml.YamlError || std.fs.File.PReadError;
 
 pub const LibStub = struct {
     /// Underlying memory for stub's contents.
@@ -140,8 +140,14 @@ pub const LibStub = struct {
     inner: []Tbd,
 
     pub fn loadFromFile(allocator: Allocator, file: fs.File) TapiError!LibStub {
-        const source = try file.readToEndAlloc(allocator, std.math.maxInt(u32));
+        const filesize = blk: {
+            const stat = file.stat() catch break :blk std.math.maxInt(u32);
+            break :blk @min(stat.size, std.math.maxInt(u32));
+        };
+        const source = try allocator.alloc(u8, filesize);
         defer allocator.free(source);
+        const amt = try file.preadAll(source, 0);
+        if (amt != filesize) return error.InputOutput;
 
         var lib_stub = LibStub{
             .yaml = try Yaml.load(allocator, source),