authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-10-07 21:19:45+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-10-07 23:54:51+02:00
logea44d12d1be8eb17a1555f6ab794621da0212171
tree833ee5bbbe1f7a1d6cebe5ba2bed09ed6f9142db
parentb5b25d38a8fa4e66e54ff1279c1becee877793f6
signaturelock-open Commit is signed but in an unrecognized format.

Add writeULEB128Mem test and couple fixes

Signed-off-by: Jakub Konka <kubkon@jakubkonka.com>

1 files changed, 128 insertions(+), 51 deletions(-)

src/link/MachO/Trie.zig+128-51
...@@ -34,6 +34,7 @@ const std = @import("std");...@@ -34,6 +34,7 @@ const std = @import("std");
34const mem = std.mem;34const mem = std.mem;
35const leb = std.debug.leb;35const leb = std.debug.leb;
36const log = std.log.scoped(.link);36const log = std.log.scoped(.link);
37const testing = std.testing;
37const Allocator = mem.Allocator;38const Allocator = mem.Allocator;
3839
39pub const Symbol = struct {40pub const Symbol = struct {
...@@ -67,48 +68,33 @@ const Node = struct {...@@ -67,48 +68,33 @@ const Node = struct {
67 self.edges.deinit(alloc);68 self.edges.deinit(alloc);
68 }69 }
6970
70 fn put(self: *Node, alloc: *Allocator, fromEdge: ?*Edge, prefix: usize, label: []const u8) !*Node {71 fn put(self: *Node, alloc: *Allocator, label: []const u8) !*Node {
71 // Traverse all edges.72 // Check for match with edges from this node.
72 for (self.edges.items) |*edge| {73 for (self.edges.items) |*edge| {
73 const match = mem.indexOfDiff(u8, edge.label, label) orelse return self; // Got a full match, don't do anything.74 const match = mem.indexOfDiff(u8, edge.label, label) orelse return edge.to;
74 if (match - prefix > 0) {75 if (match == 0) continue;
75 // If we match, we advance further down the trie.76 if (match == edge.label.len) return edge.to.put(alloc, label[match..]);
76 return edge.to.put(alloc, edge, match, label);77
77 }78 // Found a match, need to splice up nodes.
78 }79 // From: A -> B
7980 // To: A -> C -> B
80 if (fromEdge) |from| {81 const mid = try alloc.create(Node);
81 if (mem.eql(u8, from.label, label[0..prefix])) {82 mid.* = .{};
82 if (prefix == label.len) return self;83 const to_label = edge.label;
84 const to_node = edge.to;
85 edge.to = mid;
86 edge.label = label[0..match];
87
88 try mid.edges.append(alloc, .{
89 .from = mid,
90 .to = to_node,
91 .label = to_label[match..],
92 });
93
94 if (match == label.len) {
95 return to_node;
83 } else {96 } else {
84 // Fixup nodes. We need to insert an intermediate node between97 return mid.put(alloc, label[match..]);
85 // from.to and self.
86 // Is: A -> B
87 // Should be: A -> C -> B
88 const mid = try alloc.create(Node);
89 mid.* = .{};
90 const to_label = from.label;
91 from.to = mid;
92 from.label = label[0..prefix];
93
94 try mid.edges.append(alloc, .{
95 .from = mid,
96 .to = self,
97 .label = to_label,
98 });
99
100 if (prefix == label.len) return self; // We're done.
101
102 const new_node = try alloc.create(Node);
103 new_node.* = .{};
104
105 try mid.edges.append(alloc, .{
106 .from = mid,
107 .to = new_node,
108 .label = label,
109 });
110
111 return new_node;
112 }98 }
113 }99 }
114100
...@@ -148,7 +134,7 @@ const Node = struct {...@@ -148,7 +134,7 @@ const Node = struct {
148 // Write number of edges (max legal number of edges is 256).134 // Write number of edges (max legal number of edges is 256).
149 try buffer.append(alloc, @intCast(u8, self.edges.items.len));135 try buffer.append(alloc, @intCast(u8, self.edges.items.len));
150136
151 var node_offset_info: [@sizeOf(u8)]u64 = undefined;137 var node_offset_info: [std.math.maxInt(u8)]u64 = undefined;
152 for (self.edges.items) |edge, i| {138 for (self.edges.items) |edge, i| {
153 // Write edges labels leaving out space in-between to later populate139 // Write edges labels leaving out space in-between to later populate
154 // with offsets to each node.140 // with offsets to each node.
...@@ -185,7 +171,7 @@ root: Node,...@@ -185,7 +171,7 @@ root: Node,
185/// This operation may change the layout of the trie by splicing edges in171/// This operation may change the layout of the trie by splicing edges in
186/// certain circumstances.172/// certain circumstances.
187pub fn put(self: *Trie, alloc: *Allocator, symbol: Symbol) !void {173pub fn put(self: *Trie, alloc: *Allocator, symbol: Symbol) !void {
188 const node = try self.root.put(alloc, null, 0, symbol.name);174 const node = try self.root.put(alloc, symbol.name);
189 node.offset = symbol.offset;175 node.offset = symbol.offset;
190 node.export_flags = symbol.export_flags;176 node.export_flags = symbol.export_flags;
191}177}
...@@ -202,9 +188,7 @@ pub fn deinit(self: *Trie, alloc: *Allocator) void {...@@ -202,9 +188,7 @@ pub fn deinit(self: *Trie, alloc: *Allocator) void {
202}188}
203189
204test "Trie basic" {190test "Trie basic" {
205 const testing = @import("std").testing;
206 var gpa = testing.allocator;191 var gpa = testing.allocator;
207
208 var trie: Trie = .{192 var trie: Trie = .{
209 .root = .{},193 .root = .{},
210 };194 };
...@@ -223,7 +207,7 @@ test "Trie basic" {...@@ -223,7 +207,7 @@ test "Trie basic" {
223 testing.expect(mem.eql(u8, trie.root.edges.items[0].label, "_st"));207 testing.expect(mem.eql(u8, trie.root.edges.items[0].label, "_st"));
224208
225 {209 {
226 // root --- _st ---> node --- _start ---> node210 // root --- _st ---> node --- art ---> node
227 try trie.put(gpa, .{211 try trie.put(gpa, .{
228 .name = "_start",212 .name = "_start",
229 .offset = 0,213 .offset = 0,
...@@ -234,12 +218,12 @@ test "Trie basic" {...@@ -234,12 +218,12 @@ test "Trie basic" {
234 const nextEdge = &trie.root.edges.items[0];218 const nextEdge = &trie.root.edges.items[0];
235 testing.expect(mem.eql(u8, nextEdge.label, "_st"));219 testing.expect(mem.eql(u8, nextEdge.label, "_st"));
236 testing.expect(nextEdge.to.edges.items.len == 1);220 testing.expect(nextEdge.to.edges.items.len == 1);
237 testing.expect(mem.eql(u8, nextEdge.to.edges.items[0].label, "_start"));221 testing.expect(mem.eql(u8, nextEdge.to.edges.items[0].label, "art"));
238 }222 }
239 {223 {
240 // root --- _ ---> node --- _st ---> node --- _start ---> node224 // root --- _ ---> node --- st ---> node --- art ---> node
241 // |225 // |
242 // | --- _main ---> node226 // | --- main ---> node
243 try trie.put(gpa, .{227 try trie.put(gpa, .{
244 .name = "_main",228 .name = "_main",
245 .offset = 0,229 .offset = 0,
...@@ -250,10 +234,103 @@ test "Trie basic" {...@@ -250,10 +234,103 @@ test "Trie basic" {
250 const nextEdge = &trie.root.edges.items[0];234 const nextEdge = &trie.root.edges.items[0];
251 testing.expect(mem.eql(u8, nextEdge.label, "_"));235 testing.expect(mem.eql(u8, nextEdge.label, "_"));
252 testing.expect(nextEdge.to.edges.items.len == 2);236 testing.expect(nextEdge.to.edges.items.len == 2);
253 testing.expect(mem.eql(u8, nextEdge.to.edges.items[0].label, "_st"));237 testing.expect(mem.eql(u8, nextEdge.to.edges.items[0].label, "st"));
254 testing.expect(mem.eql(u8, nextEdge.to.edges.items[1].label, "_main"));238 testing.expect(mem.eql(u8, nextEdge.to.edges.items[1].label, "main"));
255239
256 const nextNextEdge = &nextEdge.to.edges.items[0];240 const nextNextEdge = &nextEdge.to.edges.items[0];
257 testing.expect(mem.eql(u8, nextNextEdge.to.edges.items[0].label, "_start"));241 testing.expect(mem.eql(u8, nextNextEdge.to.edges.items[0].label, "art"));
258 }242 }
259}243}
244
245test "Trie.writeULEB128Mem" {
246 var gpa = testing.allocator;
247 var trie: Trie = .{
248 .root = .{},
249 };
250 defer trie.deinit(gpa);
251
252 try trie.put(gpa, .{
253 .name = "__mh_execute_header",
254 .offset = 0,
255 .export_flags = 0,
256 });
257 try trie.put(gpa, .{
258 .name = "_main",
259 .offset = 0x1000,
260 .export_flags = 0,
261 });
262
263 var buffer: std.ArrayListUnmanaged(u8) = .{};
264 defer buffer.deinit(gpa);
265
266 try trie.writeULEB128Mem(gpa, &buffer);
267
268 const exp_buffer = [_]u8{
269 0x0,
270 0x1,
271 0x5f,
272 0x0,
273 0xc,
274 0x0,
275 0x0,
276 0x0,
277 0x0,
278 0x0,
279 0x0,
280 0x0,
281 0x0,
282 0x2,
283 0x5f,
284 0x6d,
285 0x68,
286 0x5f,
287 0x65,
288 0x78,
289 0x65,
290 0x63,
291 0x75,
292 0x74,
293 0x65,
294 0x5f,
295 0x68,
296 0x65,
297 0x61,
298 0x64,
299 0x65,
300 0x72,
301 0x0,
302 0x36,
303 0x0,
304 0x0,
305 0x0,
306 0x0,
307 0x0,
308 0x0,
309 0x0,
310 0x6d,
311 0x61,
312 0x69,
313 0x6e,
314 0x0,
315 0x3a,
316 0x0,
317 0x0,
318 0x0,
319 0x0,
320 0x0,
321 0x0,
322 0x0,
323 0x2,
324 0x0,
325 0x0,
326 0x0,
327 0x3,
328 0x0,
329 0x80,
330 0x20,
331 0x0,
332 };
333
334 testing.expect(buffer.items.len == exp_buffer.len);
335 testing.expect(mem.eql(u8, buffer.items, exp_buffer[0..]));
336}