Skip to content

Commit 44a6172

Browse files
authored
Merge pull request #12405 from ziglang/macho-aligned-ptrs
link.MachO: use accurate alignment attribute on pointers
2 parents 9f1f60f + fa620ef commit 44a6172

File tree

4 files changed

+79
-16
lines changed

4 files changed

+79
-16
lines changed

lib/std/array_list.zig

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,30 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
221221
mem.copy(T, self.items[old_len..], items);
222222
}
223223

224+
/// Append an unaligned slice of items to the list. Allocates more
225+
/// memory as necessary. Only call this function if calling
226+
/// `appendSlice` instead would be a compile error.
227+
pub fn appendUnalignedSlice(self: *Self, items: []align(1) const T) Allocator.Error!void {
228+
try self.ensureUnusedCapacity(items.len);
229+
self.appendUnalignedSliceAssumeCapacity(items);
230+
}
231+
232+
/// Append the slice of items to the list, asserting the capacity is already
233+
/// enough to store the new items. **Does not** invalidate pointers.
234+
/// Only call this function if calling `appendSliceAssumeCapacity` instead
235+
/// would be a compile error.
236+
pub fn appendUnalignedSliceAssumeCapacity(self: *Self, items: []align(1) const T) void {
237+
const old_len = self.items.len;
238+
const new_len = old_len + items.len;
239+
assert(new_len <= self.capacity);
240+
self.items.len = new_len;
241+
@memcpy(
242+
@ptrCast([*]align(@alignOf(T)) u8, self.items.ptr + old_len),
243+
@ptrCast([*]const u8, items.ptr),
244+
items.len * @sizeOf(T),
245+
);
246+
}
247+
224248
pub const Writer = if (T != u8)
225249
@compileError("The Writer interface is only defined for ArrayList(u8) " ++
226250
"but the given type is ArrayList(" ++ @typeName(T) ++ ")")
@@ -592,6 +616,29 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
592616
mem.copy(T, self.items[old_len..], items);
593617
}
594618

619+
/// Append the slice of items to the list. Allocates more
620+
/// memory as necessary. Only call this function if a call to `appendSlice` instead would
621+
/// be a compile error.
622+
pub fn appendUnalignedSlice(self: *Self, allocator: Allocator, items: []align(1) const T) Allocator.Error!void {
623+
try self.ensureUnusedCapacity(allocator, items.len);
624+
self.appendUnalignedSliceAssumeCapacity(items);
625+
}
626+
627+
/// Append an unaligned slice of items to the list, asserting the capacity is enough
628+
/// to store the new items. Only call this function if a call to `appendSliceAssumeCapacity`
629+
/// instead would be a compile error.
630+
pub fn appendUnalignedSliceAssumeCapacity(self: *Self, items: []align(1) const T) void {
631+
const old_len = self.items.len;
632+
const new_len = old_len + items.len;
633+
assert(new_len <= self.capacity);
634+
self.items.len = new_len;
635+
@memcpy(
636+
@ptrCast([*]align(@alignOf(T)) u8, self.items.ptr + old_len),
637+
@ptrCast([*]const u8, items.ptr),
638+
items.len * @sizeOf(T),
639+
);
640+
}
641+
595642
pub const WriterContext = struct {
596643
self: *Self,
597644
allocator: Allocator,
@@ -899,6 +946,14 @@ test "std.ArrayList/ArrayListUnmanaged.basic" {
899946
try testing.expect(list.pop() == 1);
900947
try testing.expect(list.items.len == 9);
901948

949+
var unaligned: [3]i32 align(1) = [_]i32{ 4, 5, 6 };
950+
list.appendUnalignedSlice(&unaligned) catch unreachable;
951+
try testing.expect(list.items.len == 12);
952+
try testing.expect(list.pop() == 6);
953+
try testing.expect(list.pop() == 5);
954+
try testing.expect(list.pop() == 4);
955+
try testing.expect(list.items.len == 9);
956+
902957
list.appendSlice(&[_]i32{}) catch unreachable;
903958
try testing.expect(list.items.len == 9);
904959

@@ -941,6 +996,14 @@ test "std.ArrayList/ArrayListUnmanaged.basic" {
941996
try testing.expect(list.pop() == 1);
942997
try testing.expect(list.items.len == 9);
943998

999+
var unaligned: [3]i32 align(1) = [_]i32{ 4, 5, 6 };
1000+
list.appendUnalignedSlice(a, &unaligned) catch unreachable;
1001+
try testing.expect(list.items.len == 12);
1002+
try testing.expect(list.pop() == 6);
1003+
try testing.expect(list.pop() == 5);
1004+
try testing.expect(list.pop() == 4);
1005+
try testing.expect(list.items.len == 9);
1006+
9441007
list.appendSlice(a, &[_]i32{}) catch unreachable;
9451008
try testing.expect(list.items.len == 9);
9461009

src/link/MachO.zig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5315,10 +5315,10 @@ fn writeFunctionStarts(self: *MachO, ncmds: *u32, lc_writer: anytype) !void {
53155315
}
53165316

53175317
fn filterDataInCode(
5318-
dices: []const macho.data_in_code_entry,
5318+
dices: []align(1) const macho.data_in_code_entry,
53195319
start_addr: u64,
53205320
end_addr: u64,
5321-
) []const macho.data_in_code_entry {
5321+
) []align(1) const macho.data_in_code_entry {
53225322
const Predicate = struct {
53235323
addr: u64,
53245324

@@ -5825,7 +5825,7 @@ pub fn getEntryPoint(self: MachO) error{MissingMainEntrypoint}!SymbolWithLoc {
58255825
return global;
58265826
}
58275827

5828-
pub fn findFirst(comptime T: type, haystack: []const T, start: usize, predicate: anytype) usize {
5828+
pub fn findFirst(comptime T: type, haystack: []align(1) const T, start: usize, predicate: anytype) usize {
58295829
if (!@hasDecl(@TypeOf(predicate), "predicate"))
58305830
@compileError("Predicate is required to define fn predicate(@This(), T) bool");
58315831

src/link/MachO/Atom.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ const RelocContext = struct {
218218
base_offset: i32 = 0,
219219
};
220220

221-
pub fn parseRelocs(self: *Atom, relocs: []const macho.relocation_info, context: RelocContext) !void {
221+
pub fn parseRelocs(self: *Atom, relocs: []align(1) const macho.relocation_info, context: RelocContext) !void {
222222
const tracy = trace(@src());
223223
defer tracy.end();
224224

src/link/MachO/Object.zig

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ mtime: u64,
2424
contents: []align(@alignOf(u64)) const u8,
2525

2626
header: macho.mach_header_64 = undefined,
27-
in_symtab: []const macho.nlist_64 = undefined,
27+
in_symtab: []align(1) const macho.nlist_64 = undefined,
2828
in_strtab: []const u8 = undefined,
2929

3030
symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{},
@@ -100,12 +100,12 @@ pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch)
100100
.SYMTAB => {
101101
const symtab = cmd.cast(macho.symtab_command).?;
102102
// Sadly, SYMTAB may be at an unaligned offset within the object file.
103-
self.in_symtab = @alignCast(@alignOf(macho.nlist_64), @ptrCast(
103+
self.in_symtab = @ptrCast(
104104
[*]align(1) const macho.nlist_64,
105105
self.contents.ptr + symtab.symoff,
106-
))[0..symtab.nsyms];
106+
)[0..symtab.nsyms];
107107
self.in_strtab = self.contents[symtab.stroff..][0..symtab.strsize];
108-
try self.symtab.appendSlice(allocator, self.in_symtab);
108+
try self.symtab.appendUnalignedSlice(allocator, self.in_symtab);
109109
},
110110
else => {},
111111
}
@@ -197,10 +197,10 @@ fn filterSymbolsByAddress(
197197
}
198198

199199
fn filterRelocs(
200-
relocs: []const macho.relocation_info,
200+
relocs: []align(1) const macho.relocation_info,
201201
start_addr: u64,
202202
end_addr: u64,
203-
) []const macho.relocation_info {
203+
) []align(1) const macho.relocation_info {
204204
const Predicate = struct {
205205
addr: u64,
206206

@@ -303,10 +303,10 @@ pub fn splitIntoAtomsOneShot(self: *Object, macho_file: *MachO, object_id: u32)
303303
const code: ?[]const u8 = if (!sect.isZerofill()) try self.getSectionContents(sect) else null;
304304

305305
// Read section's list of relocations
306-
const relocs = @alignCast(@alignOf(macho.relocation_info), @ptrCast(
306+
const relocs = @ptrCast(
307307
[*]align(1) const macho.relocation_info,
308308
self.contents.ptr + sect.reloff,
309-
))[0..sect.nreloc];
309+
)[0..sect.nreloc];
310310

311311
// Symbols within this section only.
312312
const filtered_syms = filterSymbolsByAddress(
@@ -473,7 +473,7 @@ fn createAtomFromSubsection(
473473
size: u64,
474474
alignment: u32,
475475
code: ?[]const u8,
476-
relocs: []const macho.relocation_info,
476+
relocs: []align(1) const macho.relocation_info,
477477
indexes: []const SymbolAtIndex,
478478
match: u8,
479479
sect: macho.section_64,
@@ -539,7 +539,7 @@ pub fn getSourceSection(self: Object, index: u16) macho.section_64 {
539539
return self.sections.items[index];
540540
}
541541

542-
pub fn parseDataInCode(self: Object) ?[]const macho.data_in_code_entry {
542+
pub fn parseDataInCode(self: Object) ?[]align(1) const macho.data_in_code_entry {
543543
var it = LoadCommandIterator{
544544
.ncmds = self.header.ncmds,
545545
.buffer = self.contents[@sizeOf(macho.mach_header_64)..][0..self.header.sizeofcmds],
@@ -549,10 +549,10 @@ pub fn parseDataInCode(self: Object) ?[]const macho.data_in_code_entry {
549549
.DATA_IN_CODE => {
550550
const dice = cmd.cast(macho.linkedit_data_command).?;
551551
const ndice = @divExact(dice.datasize, @sizeOf(macho.data_in_code_entry));
552-
return @alignCast(@alignOf(macho.data_in_code_entry), @ptrCast(
552+
return @ptrCast(
553553
[*]align(1) const macho.data_in_code_entry,
554554
self.contents.ptr + dice.dataoff,
555-
))[0..ndice];
555+
)[0..ndice];
556556
},
557557
else => {},
558558
}

0 commit comments

Comments
 (0)