authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-12-02 18:40:31+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-12-02 18:40:31+01:00
log5cba16c707fd4c46aeeabebdcc85d06b9149d6e4
tree4791d3480860b89a15840219440b3f22d6a466cb
parent0fba2f71758bd4230f5c6ff9a638e6b69a671a78

macho:use mem.asBytes and meta.eql in commands.zig

This commit addresses comments suggesting a cleaner approach at converting an `extern` struct to its byte representation using `mem.asBytes`, and to use `meta.eql` in place of more fragile `mem.eql(u8, ...)` for comparison of two `extern` structs. Thanks LemonBoy!

1 files changed, 17 insertions(+), 26 deletions(-)

src/link/MachO/commands.zig+17-26
...@@ -2,6 +2,7 @@ const std = @import("std");...@@ -2,6 +2,7 @@ const std = @import("std");
2const fs = std.fs;2const fs = std.fs;
3const io = std.io;3const io = std.io;
4const mem = std.mem;4const mem = std.mem;
5const meta = std.meta;
5const macho = std.macho;6const macho = std.macho;
6const testing = std.testing;7const testing = std.testing;
78
...@@ -25,8 +26,7 @@ pub const LoadCommand = union(enum) {...@@ -25,8 +26,7 @@ pub const LoadCommand = union(enum) {
25 const header = try reader.readStruct(macho.load_command);26 const header = try reader.readStruct(macho.load_command);
26 var buffer = try allocator.alloc(u8, header.cmdsize);27 var buffer = try allocator.alloc(u8, header.cmdsize);
27 defer allocator.free(buffer);28 defer allocator.free(buffer);
28 const slice = [1]macho.load_command{header};29 mem.copy(u8, buffer[0..], mem.asBytes(&header));
29 mem.copy(u8, buffer[0..], mem.sliceAsBytes(slice[0..1]));
30 try reader.readNoEof(buffer[@sizeOf(macho.load_command)..]);30 try reader.readNoEof(buffer[@sizeOf(macho.load_command)..]);
31 var stream = io.fixedBufferStream(buffer[0..]);31 var stream = io.fixedBufferStream(buffer[0..]);
3232
...@@ -126,30 +126,25 @@ pub const LoadCommand = union(enum) {...@@ -126,30 +126,25 @@ pub const LoadCommand = union(enum) {
126 }126 }
127127
128 fn writeStruct(command: anytype, writer: anytype) !void {128 fn writeStruct(command: anytype, writer: anytype) !void {
129 const slice = [1]@TypeOf(command){command};129 return writer.writeAll(mem.asBytes(&command));
130 return writer.writeAll(mem.sliceAsBytes(slice[0..1]));
131 }130 }
132131
133 fn eql(self: LoadCommand, other: LoadCommand) bool {132 fn eql(self: LoadCommand, other: LoadCommand) bool {
134 if (@as(@TagType(LoadCommand), self) != @as(@TagType(LoadCommand), other)) return false;133 if (@as(@TagType(LoadCommand), self) != @as(@TagType(LoadCommand), other)) return false;
135 return switch (self) {134 return switch (self) {
136 .DyldInfoOnly => |x| eqlStruct(x, other.DyldInfoOnly),135 .DyldInfoOnly => |x| meta.eql(x, other.DyldInfoOnly),
137 .Symtab => |x| eqlStruct(x, other.Symtab),136 .Symtab => |x| meta.eql(x, other.Symtab),
138 .Dysymtab => |x| eqlStruct(x, other.Dysymtab),137 .Dysymtab => |x| meta.eql(x, other.Dysymtab),
139 .Main => |x| eqlStruct(x, other.Main),138 .Main => |x| meta.eql(x, other.Main),
140 .VersionMin => |x| eqlStruct(x, other.VersionMin),139 .VersionMin => |x| meta.eql(x, other.VersionMin),
141 .SourceVersion => |x| eqlStruct(x, other.SourceVersion),140 .SourceVersion => |x| meta.eql(x, other.SourceVersion),
142 .LinkeditData => |x| eqlStruct(x, other.LinkeditData),141 .LinkeditData => |x| meta.eql(x, other.LinkeditData),
143 .Segment => |x| x.eql(other.Segment),142 .Segment => |x| x.eql(other.Segment),
144 .Dylinker => |x| x.eql(other.Dylinker),143 .Dylinker => |x| x.eql(other.Dylinker),
145 .Dylib => |x| x.eql(other.Dylib),144 .Dylib => |x| x.eql(other.Dylib),
146 .Unknown => |x| x.eql(other.Unknown),145 .Unknown => |x| x.eql(other.Unknown),
147 };146 };
148 }147 }
149
150 fn eqlStruct(lhs: anytype, rhs: anytype) bool {
151 return mem.eql(u8, mem.asBytes(&lhs), mem.asBytes(&rhs));
152 }
153};148};
154149
155pub const SegmentCommand = struct {150pub const SegmentCommand = struct {
...@@ -177,12 +172,9 @@ pub const SegmentCommand = struct {...@@ -177,12 +172,9 @@ pub const SegmentCommand = struct {
177 }172 }
178173
179 pub fn write(self: SegmentCommand, writer: anytype) !void {174 pub fn write(self: SegmentCommand, writer: anytype) !void {
180 const cmd = [1]macho.segment_command_64{self.inner};175 try writer.writeAll(mem.asBytes(&self.inner));
181 try writer.writeAll(mem.sliceAsBytes(cmd[0..1]));
182
183 for (self.sections.items) |sect| {176 for (self.sections.items) |sect| {
184 const section = [1]macho.section_64{sect};177 try writer.writeAll(mem.asBytes(&sect));
185 try writer.writeAll(mem.sliceAsBytes(section[0..1]));
186 }178 }
187 }179 }
188180
...@@ -191,12 +183,12 @@ pub const SegmentCommand = struct {...@@ -191,12 +183,12 @@ pub const SegmentCommand = struct {
191 }183 }
192184
193 fn eql(self: SegmentCommand, other: SegmentCommand) bool {185 fn eql(self: SegmentCommand, other: SegmentCommand) bool {
194 if (!mem.eql(u8, mem.asBytes(&self.inner), mem.asBytes(&other.inner))) return false;186 if (!meta.eql(self.inner, other.inner)) return false;
195 const lhs = self.sections.items;187 const lhs = self.sections.items;
196 const rhs = other.sections.items;188 const rhs = other.sections.items;
197 var i: usize = 0;189 var i: usize = 0;
198 while (i < self.inner.nsects) : (i += 1) {190 while (i < self.inner.nsects) : (i += 1) {
199 if (!mem.eql(u8, mem.asBytes(&lhs[i]), mem.asBytes(&rhs[i]))) return false;191 if (!meta.eql(lhs[i], rhs[i])) return false;
200 }192 }
201 return true;193 return true;
202 }194 }
...@@ -226,8 +218,7 @@ pub fn GenericCommandWithData(comptime Cmd: type) type {...@@ -226,8 +218,7 @@ pub fn GenericCommandWithData(comptime Cmd: type) type {
226 }218 }
227219
228 pub fn write(self: Self, writer: anytype) !void {220 pub fn write(self: Self, writer: anytype) !void {
229 const cmd = [1]Cmd{self.inner};221 try writer.writeAll(mem.asBytes(&self.inner));
230 try writer.writeAll(mem.sliceAsBytes(cmd[0..1]));
231 try writer.writeAll(self.data);222 try writer.writeAll(self.data);
232 }223 }
233224
...@@ -235,8 +226,8 @@ pub fn GenericCommandWithData(comptime Cmd: type) type {...@@ -235,8 +226,8 @@ pub fn GenericCommandWithData(comptime Cmd: type) type {
235 allocator.free(self.data);226 allocator.free(self.data);
236 }227 }
237228
238 pub fn eql(self: Self, other: Self) bool {229 fn eql(self: Self, other: Self) bool {
239 if (!mem.eql(u8, mem.asBytes(&self.inner), mem.asBytes(&other.inner))) return false;230 if (!meta.eql(self.inner, other.inner)) return false;
240 return mem.eql(u8, self.data, other.data);231 return mem.eql(u8, self.data, other.data);
241 }232 }
242 };233 };