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 {
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+3-3
......@@ -5315,10 +5315,10 @@ fn writeFunctionStarts(self: *MachO, ncmds: *u32, lc_writer: anytype) !void {
53155315}
53165316
53175317fn 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
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 {
58295829 if (!@hasDecl(@TypeOf(predicate), "predicate"))
58305830 @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 {
218218 base_offset: i32 = 0,
219219};
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 {
222222 const tracy = trace(@src());
223223 defer tracy.end();
224224
src/link/MachO/Object.zig+12-12
......@@ -24,7 +24,7 @@ mtime: u64,
2424contents: []align(@alignOf(u64)) const u8,
2525
2626header: macho.mach_header_64 = undefined,
27in_symtab: []const macho.nlist_64 = undefined,
27in_symtab: []align(1) const macho.nlist_64 = undefined,
2828in_strtab: []const u8 = undefined,
2929
3030symtab: 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
199199fn 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
542pub fn parseDataInCode(self: Object) ?[]const macho.data_in_code_entry {
542pub 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 }