authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-08-10 22:26:29-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-08-10 22:28:05-07:00
logfa620ef710bbbf7f642fd1d6d24a188d02902988
tree3831b8ef6ef96938dd9f3d678dd3e353e6e92cf6
parentcc56400e62ae7d59cccf78d0cfe2e4b990d53abc

link.MachO: use accurate alignment attribute on pointers

Also adds a new method to ArrayList: appendUnalignedSlice

4 files changed, 80 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+13-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) = .{},
...@@ -99,12 +99,13 @@ pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch)...@@ -99,12 +99,13 @@ pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch)
99 },99 },
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 self.in_symtab = @ptrCast(103 self.in_symtab = @ptrCast(
103 [*]const macho.nlist_64,104 [*]align(1) const macho.nlist_64,
104 @alignCast(@alignOf(macho.nlist_64), &self.contents[symtab.symoff]),105 self.contents.ptr + symtab.symoff,
105 )[0..symtab.nsyms];106 )[0..symtab.nsyms];
106 self.in_strtab = self.contents[symtab.stroff..][0..symtab.strsize];107 self.in_strtab = self.contents[symtab.stroff..][0..symtab.strsize];
107 try self.symtab.appendSlice(allocator, self.in_symtab);108 try self.symtab.appendUnalignedSlice(allocator, self.in_symtab);
108 },109 },
109 else => {},110 else => {},
110 }111 }
...@@ -196,10 +197,10 @@ fn filterSymbolsByAddress(...@@ -196,10 +197,10 @@ fn filterSymbolsByAddress(
196}197}
197198
198fn filterRelocs(199fn filterRelocs(
199 relocs: []const macho.relocation_info,200 relocs: []align(1) const macho.relocation_info,
200 start_addr: u64,201 start_addr: u64,
201 end_addr: u64,202 end_addr: u64,
202) []const macho.relocation_info {203) []align(1) const macho.relocation_info {
203 const Predicate = struct {204 const Predicate = struct {
204 addr: u64,205 addr: u64,
205206
...@@ -303,8 +304,8 @@ pub fn splitIntoAtomsOneShot(self: *Object, macho_file: *MachO, object_id: u32)...@@ -303,8 +304,8 @@ pub fn splitIntoAtomsOneShot(self: *Object, macho_file: *MachO, object_id: u32)
303304
304 // Read section's list of relocations305 // Read section's list of relocations
305 const relocs = @ptrCast(306 const relocs = @ptrCast(
306 [*]const macho.relocation_info,307 [*]align(1) const macho.relocation_info,
307 @alignCast(@alignOf(macho.relocation_info), &self.contents[sect.reloff]),308 self.contents.ptr + sect.reloff,
308 )[0..sect.nreloc];309 )[0..sect.nreloc];
309310
310 // Symbols within this section only.311 // Symbols within this section only.
...@@ -472,7 +473,7 @@ fn createAtomFromSubsection(...@@ -472,7 +473,7 @@ fn createAtomFromSubsection(
472 size: u64,473 size: u64,
473 alignment: u32,474 alignment: u32,
474 code: ?[]const u8,475 code: ?[]const u8,
475 relocs: []const macho.relocation_info,476 relocs: []align(1) const macho.relocation_info,
476 indexes: []const SymbolAtIndex,477 indexes: []const SymbolAtIndex,
477 match: u8,478 match: u8,
478 sect: macho.section_64,479 sect: macho.section_64,
...@@ -538,7 +539,7 @@ pub fn getSourceSection(self: Object, index: u16) macho.section_64 {...@@ -538,7 +539,7 @@ pub fn getSourceSection(self: Object, index: u16) macho.section_64 {
538 return self.sections.items[index];539 return self.sections.items[index];
539}540}
540541
541pub fn parseDataInCode(self: Object) ?[]const macho.data_in_code_entry {542pub fn parseDataInCode(self: Object) ?[]align(1) const macho.data_in_code_entry {
542 var it = LoadCommandIterator{543 var it = LoadCommandIterator{
543 .ncmds = self.header.ncmds,544 .ncmds = self.header.ncmds,
544 .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,8 +550,8 @@ pub fn parseDataInCode(self: Object) ?[]const macho.data_in_code_entry {...@@ -549,8 +550,8 @@ pub fn parseDataInCode(self: Object) ?[]const macho.data_in_code_entry {
549 const dice = cmd.cast(macho.linkedit_data_command).?;550 const dice = cmd.cast(macho.linkedit_data_command).?;
550 const ndice = @divExact(dice.datasize, @sizeOf(macho.data_in_code_entry));551 const ndice = @divExact(dice.datasize, @sizeOf(macho.data_in_code_entry));
551 return @ptrCast(552 return @ptrCast(
552 [*]const macho.data_in_code_entry,553 [*]align(1) const macho.data_in_code_entry,
553 @alignCast(@alignOf(macho.data_in_code_entry), &self.contents[dice.dataoff]),554 self.contents.ptr + dice.dataoff,
554 )[0..ndice];555 )[0..ndice];
555 },556 },
556 else => {},557 else => {},