authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-09-08 14:29:51+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-09-08 14:29:54+02:00
log0ae2ea671b867e5ecd0bc779405c175f33316559
treebe04082be44611973aa36b4d4ebaa260f310d6d9
parentb98b3252beea98522c25b88eb29b5e2d8a65adfe

wasm: temporarily save curr file pointer before pwriting on Win

This is a temporary workaround to an unclear platform-dependence behavior we have in libstd for `std.fs.File` abstraction. See https://github.com/ziglang/zig/issues/12783 for more information.

3 files changed, 37 insertions(+), 9 deletions(-)

lib/std/fs/file.zig+16
...@@ -990,6 +990,8 @@ pub const File = struct {...@@ -990,6 +990,8 @@ pub const File = struct {
990 return index;990 return index;
991 }991 }
992992
993 /// On Windows, this function currently does alter the file pointer.
994 /// https://github.com/ziglang/zig/issues/12783
993 pub fn pread(self: File, buffer: []u8, offset: u64) PReadError!usize {995 pub fn pread(self: File, buffer: []u8, offset: u64) PReadError!usize {
994 if (is_windows) {996 if (is_windows) {
995 return windows.ReadFile(self.handle, buffer, offset, self.intended_io_mode);997 return windows.ReadFile(self.handle, buffer, offset, self.intended_io_mode);
...@@ -1004,6 +1006,8 @@ pub const File = struct {...@@ -1004,6 +1006,8 @@ pub const File = struct {
10041006
1005 /// Returns the number of bytes read. If the number read is smaller than `buffer.len`, it1007 /// Returns the number of bytes read. If the number read is smaller than `buffer.len`, it
1006 /// means the file reached the end. Reaching the end of a file is not an error condition.1008 /// means the file reached the end. Reaching the end of a file is not an error condition.
1009 /// On Windows, this function currently does alter the file pointer.
1010 /// https://github.com/ziglang/zig/issues/12783
1007 pub fn preadAll(self: File, buffer: []u8, offset: u64) PReadError!usize {1011 pub fn preadAll(self: File, buffer: []u8, offset: u64) PReadError!usize {
1008 var index: usize = 0;1012 var index: usize = 0;
1009 while (index != buffer.len) {1013 while (index != buffer.len) {
...@@ -1058,6 +1062,8 @@ pub const File = struct {...@@ -1058,6 +1062,8 @@ pub const File = struct {
1058 }1062 }
10591063
1060 /// See https://github.com/ziglang/zig/issues/76991064 /// See https://github.com/ziglang/zig/issues/7699
1065 /// On Windows, this function currently does alter the file pointer.
1066 /// https://github.com/ziglang/zig/issues/12783
1061 pub fn preadv(self: File, iovecs: []const os.iovec, offset: u64) PReadError!usize {1067 pub fn preadv(self: File, iovecs: []const os.iovec, offset: u64) PReadError!usize {
1062 if (is_windows) {1068 if (is_windows) {
1063 // TODO improve this to use ReadFileScatter1069 // TODO improve this to use ReadFileScatter
...@@ -1079,6 +1085,8 @@ pub const File = struct {...@@ -1079,6 +1085,8 @@ pub const File = struct {
1079 /// The `iovecs` parameter is mutable because this function needs to mutate the fields in1085 /// The `iovecs` parameter is mutable because this function needs to mutate the fields in
1080 /// order to handle partial reads from the underlying OS layer.1086 /// order to handle partial reads from the underlying OS layer.
1081 /// See https://github.com/ziglang/zig/issues/76991087 /// See https://github.com/ziglang/zig/issues/7699
1088 /// On Windows, this function currently does alter the file pointer.
1089 /// https://github.com/ziglang/zig/issues/12783
1082 pub fn preadvAll(self: File, iovecs: []os.iovec, offset: u64) PReadError!usize {1090 pub fn preadvAll(self: File, iovecs: []os.iovec, offset: u64) PReadError!usize {
1083 if (iovecs.len == 0) return 0;1091 if (iovecs.len == 0) return 0;
10841092
...@@ -1122,6 +1130,8 @@ pub const File = struct {...@@ -1122,6 +1130,8 @@ pub const File = struct {
1122 }1130 }
1123 }1131 }
11241132
1133 /// On Windows, this function currently does alter the file pointer.
1134 /// https://github.com/ziglang/zig/issues/12783
1125 pub fn pwrite(self: File, bytes: []const u8, offset: u64) PWriteError!usize {1135 pub fn pwrite(self: File, bytes: []const u8, offset: u64) PWriteError!usize {
1126 if (is_windows) {1136 if (is_windows) {
1127 return windows.WriteFile(self.handle, bytes, offset, self.intended_io_mode);1137 return windows.WriteFile(self.handle, bytes, offset, self.intended_io_mode);
...@@ -1134,6 +1144,8 @@ pub const File = struct {...@@ -1134,6 +1144,8 @@ pub const File = struct {
1134 }1144 }
1135 }1145 }
11361146
1147 /// On Windows, this function currently does alter the file pointer.
1148 /// https://github.com/ziglang/zig/issues/12783
1137 pub fn pwriteAll(self: File, bytes: []const u8, offset: u64) PWriteError!void {1149 pub fn pwriteAll(self: File, bytes: []const u8, offset: u64) PWriteError!void {
1138 var index: usize = 0;1150 var index: usize = 0;
1139 while (index < bytes.len) {1151 while (index < bytes.len) {
...@@ -1179,6 +1191,8 @@ pub const File = struct {...@@ -1179,6 +1191,8 @@ pub const File = struct {
1179 }1191 }
11801192
1181 /// See https://github.com/ziglang/zig/issues/76991193 /// See https://github.com/ziglang/zig/issues/7699
1194 /// On Windows, this function currently does alter the file pointer.
1195 /// https://github.com/ziglang/zig/issues/12783
1182 pub fn pwritev(self: File, iovecs: []os.iovec_const, offset: u64) PWriteError!usize {1196 pub fn pwritev(self: File, iovecs: []os.iovec_const, offset: u64) PWriteError!usize {
1183 if (is_windows) {1197 if (is_windows) {
1184 // TODO improve this to use WriteFileScatter1198 // TODO improve this to use WriteFileScatter
...@@ -1197,6 +1211,8 @@ pub const File = struct {...@@ -1197,6 +1211,8 @@ pub const File = struct {
1197 /// The `iovecs` parameter is mutable because this function needs to mutate the fields in1211 /// The `iovecs` parameter is mutable because this function needs to mutate the fields in
1198 /// order to handle partial writes from the underlying OS layer.1212 /// order to handle partial writes from the underlying OS layer.
1199 /// See https://github.com/ziglang/zig/issues/76991213 /// See https://github.com/ziglang/zig/issues/7699
1214 /// On Windows, this function currently does alter the file pointer.
1215 /// https://github.com/ziglang/zig/issues/12783
1200 pub fn pwritevAll(self: File, iovecs: []os.iovec_const, offset: u64) PWriteError!void {1216 pub fn pwritevAll(self: File, iovecs: []os.iovec_const, offset: u64) PWriteError!void {
1201 if (iovecs.len == 0) return;1217 if (iovecs.len == 0) return;
12021218
src/link/Wasm.zig+14-2
...@@ -3055,14 +3055,26 @@ fn writeVecSectionHeader(file: fs.File, offset: u64, section: wasm.Section, size...@@ -3055,14 +3055,26 @@ fn writeVecSectionHeader(file: fs.File, offset: u64, section: wasm.Section, size
3055 buf[0] = @enumToInt(section);3055 buf[0] = @enumToInt(section);
3056 leb.writeUnsignedFixed(5, buf[1..6], size);3056 leb.writeUnsignedFixed(5, buf[1..6], size);
3057 leb.writeUnsignedFixed(5, buf[6..], items);3057 leb.writeUnsignedFixed(5, buf[6..], items);
3058 try file.pwriteAll(&buf, offset);3058
3059 if (builtin.target.os.tag == .windows) {
3060 // https://github.com/ziglang/zig/issues/12783
3061 const curr_pos = try file.getPos();
3062 try file.pwriteAll(&buf, offset);
3063 try file.seekTo(curr_pos);
3064 } else try file.pwriteAll(&buf, offset);
3059}3065}
30603066
3061fn writeCustomSectionHeader(file: fs.File, offset: u64, size: u32) !void {3067fn writeCustomSectionHeader(file: fs.File, offset: u64, size: u32) !void {
3062 var buf: [1 + 5]u8 = undefined;3068 var buf: [1 + 5]u8 = undefined;
3063 buf[0] = 0; // 0 = 'custom' section3069 buf[0] = 0; // 0 = 'custom' section
3064 leb.writeUnsignedFixed(5, buf[1..6], size);3070 leb.writeUnsignedFixed(5, buf[1..6], size);
3065 try file.pwriteAll(&buf, offset);3071
3072 if (builtin.target.os.tag == .windows) {
3073 // https://github.com/ziglang/zig/issues/12783
3074 const curr_pos = try file.getPos();
3075 try file.pwriteAll(&buf, offset);
3076 try file.seekTo(curr_pos);
3077 } else try file.pwriteAll(&buf, offset);
3066}3078}
30673079
3068fn emitLinkSection(self: *Wasm, file: fs.File, arena: Allocator, symbol_table: *std.AutoArrayHashMap(SymbolLoc, u32)) !void {3080fn emitLinkSection(self: *Wasm, file: fs.File, arena: Allocator, symbol_table: *std.AutoArrayHashMap(SymbolLoc, u32)) !void {
test/link.zig+7-7
...@@ -28,35 +28,35 @@ pub fn addCases(cases: *tests.StandaloneContext) void {...@@ -28,35 +28,35 @@ pub fn addCases(cases: *tests.StandaloneContext) void {
28}28}
2929
30fn addWasmCases(cases: *tests.StandaloneContext) void {30fn addWasmCases(cases: *tests.StandaloneContext) void {
31 cases.addBuildFile("test/link/wasm/bss/build.zig", .{31 cases.addBuildFile("test/link/wasm/archive/build.zig", .{
32 .build_modes = true,32 .build_modes = true,
33 .requires_stage2 = true,33 .requires_stage2 = true,
34 });34 });
3535
36 cases.addBuildFile("test/link/wasm/segments/build.zig", .{36 cases.addBuildFile("test/link/wasm/bss/build.zig", .{
37 .build_modes = true,37 .build_modes = true,
38 .requires_stage2 = true,38 .requires_stage2 = true,
39 });39 });
4040
41 cases.addBuildFile("test/link/wasm/stack_pointer/build.zig", .{41 cases.addBuildFile("test/link/wasm/extern/build.zig", .{
42 .build_modes = true,42 .build_modes = true,
43 .requires_stage2 = true,43 .requires_stage2 = true,
44 .use_emulation = true,
44 });45 });
4546
46 cases.addBuildFile("test/link/wasm/type/build.zig", .{47 cases.addBuildFile("test/link/wasm/segments/build.zig", .{
47 .build_modes = true,48 .build_modes = true,
48 .requires_stage2 = true,49 .requires_stage2 = true,
49 });50 });
5051
51 cases.addBuildFile("test/link/wasm/archive/build.zig", .{52 cases.addBuildFile("test/link/wasm/stack_pointer/build.zig", .{
52 .build_modes = true,53 .build_modes = true,
53 .requires_stage2 = true,54 .requires_stage2 = true,
54 });55 });
5556
56 cases.addBuildFile("test/link/wasm/extern/build.zig", .{57 cases.addBuildFile("test/link/wasm/type/build.zig", .{
57 .build_modes = true,58 .build_modes = true,
58 .requires_stage2 = true,59 .requires_stage2 = true,
59 .use_emulation = true,
60 });60 });
61}61}
6262