authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-08-11 06:19:10-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-08-11 06:19:10-04:00
log44a6172edbf6c99f4ebfeabb530756ed2a40c3c2
treefb158886b71bc3e1a19d09aea13b4e3d19b164ea
parent9f1f60fd4311b37493a5297ccaac167d0270f521
parentfa620ef710bbbf7f642fd1d6d24a188d02902988
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #12405 from ziglang/macho-aligned-ptrs

link.MachO: use accurate alignment attribute on pointers

4 files changed, 79 insertions(+), 16 deletions(-)

lib/std/array_list.zig+63
...@@ -221,6 +221,30 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {...@@ -221,6 +221,30 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
221 mem.copy(T, self.items[old_len..], items);221 mem.copy(T, self.items[old_len..], items);
222 }222 }
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
224 pub const Writer = if (T != u8)248 pub const Writer = if (T != u8)
225 @compileError("The Writer interface is only defined for ArrayList(u8) " ++249 @compileError("The Writer interface is only defined for ArrayList(u8) " ++
226 "but the given type is ArrayList(" ++ @typeName(T) ++ ")")250 "but the given type is ArrayList(" ++ @typeName(T) ++ ")")
...@@ -592,6 +616,29 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ...@@ -592,6 +616,29 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
592 mem.copy(T, self.items[old_len..], items);616 mem.copy(T, self.items[old_len..], items);
593 }617 }
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
595 pub const WriterContext = struct {642 pub const WriterContext = struct {
596 self: *Self,643 self: *Self,
597 allocator: Allocator,644 allocator: Allocator,
...@@ -899,6 +946,14 @@ test "std.ArrayList/ArrayListUnmanaged.basic" {...@@ -899,6 +946,14 @@ test "std.ArrayList/ArrayListUnmanaged.basic" {
899 try testing.expect(list.pop() == 1);946 try testing.expect(list.pop() == 1);
900 try testing.expect(list.items.len == 9);947 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
902 list.appendSlice(&[_]i32{}) catch unreachable;957 list.appendSlice(&[_]i32{}) catch unreachable;
903 try testing.expect(list.items.len == 9);958 try testing.expect(list.items.len == 9);
904959
...@@ -941,6 +996,14 @@ test "std.ArrayList/ArrayListUnmanaged.basic" {...@@ -941,6 +996,14 @@ test "std.ArrayList/ArrayListUnmanaged.basic" {
941 try testing.expect(list.pop() == 1);996 try testing.expect(list.pop() == 1);
942 try testing.expect(list.items.len == 9);997 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
944 list.appendSlice(a, &[_]i32{}) catch unreachable;1007 list.appendSlice(a, &[_]i32{}) catch unreachable;
945 try testing.expect(list.items.len == 9);1008 try testing.expect(list.items.len == 9);
9461009
src/link/MachO.zig+3-3
...@@ -5315,10 +5315,10 @@ fn writeFunctionStarts(self: *MachO, ncmds: *u32, lc_writer: anytype) !void {...@@ -5315,10 +5315,10 @@ fn writeFunctionStarts(self: *MachO, ncmds: *u32, lc_writer: anytype) !void {
5315}5315}
53165316
5317fn filterDataInCode(5317fn filterDataInCode(
5318 dices: []const macho.data_in_code_entry,5318 dices: []align(1) const macho.data_in_code_entry,
5319 start_addr: u64,5319 start_addr: u64,
5320 end_addr: u64,5320 end_addr: u64,
5321) []const macho.data_in_code_entry {5321) []align(1) const macho.data_in_code_entry {
5322 const Predicate = struct {5322 const Predicate = struct {
5323 addr: u64,5323 addr: u64,
53245324
...@@ -5825,7 +5825,7 @@ pub fn getEntryPoint(self: MachO) error{MissingMainEntrypoint}!SymbolWithLoc {...@@ -5825,7 +5825,7 @@ pub fn getEntryPoint(self: MachO) error{MissingMainEntrypoint}!SymbolWithLoc {
5825 return global;5825 return global;
5826}5826}
58275827
5828pub fn findFirst(comptime T: type, haystack: []const T, start: usize, predicate: anytype) usize {5828pub fn findFirst(comptime T: type, haystack: []align(1) const T, start: usize, predicate: anytype) usize {
5829 if (!@hasDecl(@TypeOf(predicate), "predicate"))5829 if (!@hasDecl(@TypeOf(predicate), "predicate"))
5830 @compileError("Predicate is required to define fn predicate(@This(), T) bool");5830 @compileError("Predicate is required to define fn predicate(@This(), T) bool");
58315831
src/link/MachO/Atom.zig+1-1
...@@ -218,7 +218,7 @@ const RelocContext = struct {...@@ -218,7 +218,7 @@ const RelocContext = struct {
218 base_offset: i32 = 0,218 base_offset: i32 = 0,
219};219};
220220
221pub fn parseRelocs(self: *Atom, relocs: []const macho.relocation_info, context: RelocContext) !void {221pub fn parseRelocs(self: *Atom, relocs: []align(1) const macho.relocation_info, context: RelocContext) !void {
222 const tracy = trace(@src());222 const tracy = trace(@src());
223 defer tracy.end();223 defer tracy.end();
224224
src/link/MachO/Object.zig+12-12
...@@ -24,7 +24,7 @@ mtime: u64,...@@ -24,7 +24,7 @@ mtime: u64,
24contents: []align(@alignOf(u64)) const u8,24contents: []align(@alignOf(u64)) const u8,
2525
26header: macho.mach_header_64 = undefined,26header: macho.mach_header_64 = undefined,
27in_symtab: []const macho.nlist_64 = undefined,27in_symtab: []align(1) const macho.nlist_64 = undefined,
28in_strtab: []const u8 = undefined,28in_strtab: []const u8 = undefined,
2929
30symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{},30symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{},
...@@ -100,12 +100,12 @@ pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch)...@@ -100,12 +100,12 @@ pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch)
100 .SYMTAB => {100 .SYMTAB => {
101 const symtab = cmd.cast(macho.symtab_command).?;101 const symtab = cmd.cast(macho.symtab_command).?;
102 // Sadly, SYMTAB may be at an unaligned offset within the object file.102 // 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(
104 [*]align(1) const macho.nlist_64,104 [*]align(1) const macho.nlist_64,
105 self.contents.ptr + symtab.symoff,105 self.contents.ptr + symtab.symoff,
106 ))[0..symtab.nsyms];106 )[0..symtab.nsyms];
107 self.in_strtab = self.contents[symtab.stroff..][0..symtab.strsize];107 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);
109 },109 },
110 else => {},110 else => {},
111 }111 }
...@@ -197,10 +197,10 @@ fn filterSymbolsByAddress(...@@ -197,10 +197,10 @@ fn filterSymbolsByAddress(
197}197}
198198
199fn filterRelocs(199fn filterRelocs(
200 relocs: []const macho.relocation_info,200 relocs: []align(1) const macho.relocation_info,
201 start_addr: u64,201 start_addr: u64,
202 end_addr: u64,202 end_addr: u64,
203) []const macho.relocation_info {203) []align(1) const macho.relocation_info {
204 const Predicate = struct {204 const Predicate = struct {
205 addr: u64,205 addr: u64,
206206
...@@ -303,10 +303,10 @@ pub fn splitIntoAtomsOneShot(self: *Object, macho_file: *MachO, object_id: u32)...@@ -303,10 +303,10 @@ pub fn splitIntoAtomsOneShot(self: *Object, macho_file: *MachO, object_id: u32)
303 const code: ?[]const u8 = if (!sect.isZerofill()) try self.getSectionContents(sect) else null;303 const code: ?[]const u8 = if (!sect.isZerofill()) try self.getSectionContents(sect) else null;
304304
305 // Read section's list of relocations305 // Read section's list of relocations
306 const relocs = @alignCast(@alignOf(macho.relocation_info), @ptrCast(306 const relocs = @ptrCast(
307 [*]align(1) const macho.relocation_info,307 [*]align(1) const macho.relocation_info,
308 self.contents.ptr + sect.reloff,308 self.contents.ptr + sect.reloff,
309 ))[0..sect.nreloc];309 )[0..sect.nreloc];
310310
311 // Symbols within this section only.311 // Symbols within this section only.
312 const filtered_syms = filterSymbolsByAddress(312 const filtered_syms = filterSymbolsByAddress(
...@@ -473,7 +473,7 @@ fn createAtomFromSubsection(...@@ -473,7 +473,7 @@ fn createAtomFromSubsection(
473 size: u64,473 size: u64,
474 alignment: u32,474 alignment: u32,
475 code: ?[]const u8,475 code: ?[]const u8,
476 relocs: []const macho.relocation_info,476 relocs: []align(1) const macho.relocation_info,
477 indexes: []const SymbolAtIndex,477 indexes: []const SymbolAtIndex,
478 match: u8,478 match: u8,
479 sect: macho.section_64,479 sect: macho.section_64,
...@@ -539,7 +539,7 @@ pub fn getSourceSection(self: Object, index: u16) macho.section_64 {...@@ -539,7 +539,7 @@ pub fn getSourceSection(self: Object, index: u16) macho.section_64 {
539 return self.sections.items[index];539 return self.sections.items[index];
540}540}
541541
542pub fn parseDataInCode(self: Object) ?[]const macho.data_in_code_entry {542pub fn parseDataInCode(self: Object) ?[]align(1) const macho.data_in_code_entry {
543 var it = LoadCommandIterator{543 var it = LoadCommandIterator{
544 .ncmds = self.header.ncmds,544 .ncmds = self.header.ncmds,
545 .buffer = self.contents[@sizeOf(macho.mach_header_64)..][0..self.header.sizeofcmds],545 .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 {...@@ -549,10 +549,10 @@ pub fn parseDataInCode(self: Object) ?[]const macho.data_in_code_entry {
549 .DATA_IN_CODE => {549 .DATA_IN_CODE => {
550 const dice = cmd.cast(macho.linkedit_data_command).?;550 const dice = cmd.cast(macho.linkedit_data_command).?;
551 const ndice = @divExact(dice.datasize, @sizeOf(macho.data_in_code_entry));551 const ndice = @divExact(dice.datasize, @sizeOf(macho.data_in_code_entry));
552 return @alignCast(@alignOf(macho.data_in_code_entry), @ptrCast(552 return @ptrCast(
553 [*]align(1) const macho.data_in_code_entry,553 [*]align(1) const macho.data_in_code_entry,
554 self.contents.ptr + dice.dataoff,554 self.contents.ptr + dice.dataoff,
555 ))[0..ndice];555 )[0..ndice];
556 },556 },
557 else => {},557 else => {},
558 }558 }