Skip to content

Commit f45264e

Browse files
committed
mapped_file: fix for 32bit targets; do not import munmap symbol on unsupported hosts
1 parent 4c4963d commit f45264e

File tree

2 files changed

+34
-7
lines changed

2 files changed

+34
-7
lines changed

src/link/MachO/Archive.zig

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const assert = std.debug.assert;
55
const fs = std.fs;
66
const log = std.log.scoped(.link);
77
const macho = std.macho;
8+
const math = std.math;
89
const mem = std.mem;
910

1011
const Allocator = mem.Allocator;
@@ -213,8 +214,9 @@ pub fn parseObject(
213214
.Name => 0,
214215
.Length => |len| len,
215216
};
217+
const object_off = math.cast(usize, try reader.context.getPos()) orelse return error.Overflow;
216218
const object_size = (try object_header.size()) - object_name_len;
217-
const data = try MappedFile.mapWithOptions(allocator, self.file, object_size, try reader.context.getPos());
219+
const data = try MappedFile.mapWithOptions(allocator, self.file, object_size, object_off);
218220
errdefer data.unmap(allocator);
219221

220222
var object = Object{

src/link/MappedFile.zig

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
1+
//! Memory mapping utility for large files.
2+
//! Its intended use is to map input object files into memory using `mmap` on supported
3+
//! hosts with a fallback to `malloc` in case the former fails or is unsupported (e.g.,
4+
//! on Windows).
5+
16
const MappedFile = @This();
27

38
const std = @import("std");
49
const builtin = @import("builtin");
10+
const assert = std.debug.assert;
511
const log = std.log.scoped(.mapped_file);
612
const fs = std.fs;
713
const math = std.math;
@@ -13,13 +19,19 @@ const File = fs.File;
1319

1420
tag: Tag,
1521
raw: union {
22+
/// Backing memory when mapped directly with `mmap`
1623
mmap: []align(mem.page_size) const u8,
24+
/// Backing memory when allocated with `malloc`
1725
malloc: []const u8,
1826
},
19-
offset: u64 = 0,
27+
/// Offset into `mmap`ed memory to account for the requirement for
28+
/// the mapped memory to be page size aligned
29+
offset: usize = 0,
2030

2131
const Tag = enum {
32+
/// Uses `mmap`
2233
mmap,
34+
/// Uses `malloc`
2335
malloc,
2436
};
2537

@@ -29,12 +41,17 @@ const Error = error{
2941
OutOfMemory,
3042
} || os.MMapError || os.SeekError || os.ReadError;
3143

44+
/// Maps the entire file using either `mmap` (preferred), or `malloc` (if the former
45+
/// fails and/or is unavailable).
46+
/// Needs to be free'd using `unmap`.
3247
pub fn map(gpa: Allocator, file: File) Error!MappedFile {
3348
const file_len = math.cast(usize, try file.getEndPos()) orelse return error.Overflow;
3449
return mapWithOptions(gpa, file, file_len, 0);
3550
}
3651

37-
pub fn mapWithOptions(gpa: Allocator, file: File, length: usize, offset: u64) Error!MappedFile {
52+
/// Same as `map` however allows to specify the requested mapped length as well as start offset.
53+
/// Note that offset is will be backwards aligned to the first available page boundary.
54+
pub fn mapWithOptions(gpa: Allocator, file: File, length: usize, offset: usize) Error!MappedFile {
3855
if (length == 0) {
3956
return error.InputOutput;
4057
}
@@ -48,7 +65,7 @@ pub fn mapWithOptions(gpa: Allocator, file: File, length: usize, offset: u64) Er
4865
};
4966
}
5067

51-
fn malloc(gpa: Allocator, file: File, length: usize, offset: u64) Error!MappedFile {
68+
fn malloc(gpa: Allocator, file: File, length: usize, offset: usize) Error!MappedFile {
5269
const reader = file.reader();
5370
if (offset > 0) {
5471
try file.seekTo(offset);
@@ -65,8 +82,9 @@ fn malloc(gpa: Allocator, file: File, length: usize, offset: u64) Error!MappedFi
6582
};
6683
}
6784

68-
fn mmap(file: File, length: usize, offset: u64) Error!MappedFile {
69-
const aligned_offset = mem.alignBackwardGeneric(u64, offset, mem.page_size);
85+
fn mmap(file: File, length: usize, offset: usize) Error!MappedFile {
86+
const aligned_offset = math.cast(usize, mem.alignBackwardGeneric(u64, offset, mem.page_size)) orelse
87+
return error.Overflow;
7088
const adjusted_length = length + (offset - aligned_offset);
7189
// Mold is using os.PROT.READ | os.PROT.WRITE together with os.MAP.PRIVATE most likely
7290
// because it is overwriting the mapped memory with some adjusted metadata when parsing
@@ -86,13 +104,20 @@ fn mmap(file: File, length: usize, offset: u64) Error!MappedFile {
86104
};
87105
}
88106

107+
/// Call to unmap/deallocate mapped memory.
89108
pub fn unmap(mf: MappedFile, gpa: Allocator) void {
90-
switch (mf.tag) {
109+
if (builtin.os.tag == .windows) {
110+
assert(mf.tag == .malloc);
111+
gpa.free(mf.raw.malloc);
112+
} else switch (mf.tag) {
91113
.mmap => os.munmap(mf.raw.mmap),
92114
.malloc => gpa.free(mf.raw.malloc),
93115
}
94116
}
95117

118+
/// Returns the mapped memory.
119+
/// In case of `mmap`, it takes into account backwards aligned `offset` and thus it is not required
120+
/// to adjust the slice as it is done automatically for the caller.
96121
pub fn slice(mf: MappedFile) []const u8 {
97122
return switch (mf.tag) {
98123
.mmap => mf.raw.mmap[mf.offset..],

0 commit comments

Comments
 (0)