mirror of
https://github.com/ziglang/zig.git
synced 2026-02-05 06:03:38 +00:00
macho: parsing Trie now takes a reader and returns bytes read
This commit is contained in:
parent
a283404053
commit
601600dec9
@ -1806,7 +1806,7 @@ fn writeExportTrie(self: *MachO) !void {
|
||||
try trie.put(.{
|
||||
.name = name,
|
||||
.vmaddr_offset = symbol.n_value - text_segment.inner.vmaddr,
|
||||
.export_flags = 0, // TODO workout creation of export flags
|
||||
.export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -39,27 +39,6 @@ const testing = std.testing;
|
||||
const assert = std.debug.assert;
|
||||
const Allocator = mem.Allocator;
|
||||
|
||||
pub const Symbol = struct {
|
||||
name: []const u8,
|
||||
vmaddr_offset: u64,
|
||||
export_flags: u64,
|
||||
};
|
||||
|
||||
pub const Edge = struct {
|
||||
from: *Node,
|
||||
to: *Node,
|
||||
label: []u8,
|
||||
|
||||
fn deinit(self: *Edge, allocator: *Allocator) void {
|
||||
self.to.deinit(allocator);
|
||||
allocator.destroy(self.to);
|
||||
allocator.free(self.label);
|
||||
self.from = undefined;
|
||||
self.to = undefined;
|
||||
self.label = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
pub const Node = struct {
|
||||
base: *Trie,
|
||||
|
||||
@ -80,6 +59,22 @@ pub const Node = struct {
|
||||
|
||||
node_dirty: bool = true,
|
||||
|
||||
/// Edge connecting to nodes in the trie.
|
||||
pub const Edge = struct {
|
||||
from: *Node,
|
||||
to: *Node,
|
||||
label: []u8,
|
||||
|
||||
fn deinit(self: *Edge, allocator: *Allocator) void {
|
||||
self.to.deinit(allocator);
|
||||
allocator.destroy(self.to);
|
||||
allocator.free(self.label);
|
||||
self.from = undefined;
|
||||
self.to = undefined;
|
||||
self.label = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
fn deinit(self: *Node, allocator: *Allocator) void {
|
||||
for (self.edges.items) |*edge| {
|
||||
edge.deinit(allocator);
|
||||
@ -131,10 +126,12 @@ pub const Node = struct {
|
||||
}
|
||||
|
||||
/// Recursively parses the node from the input byte stream.
|
||||
fn read(self: *Node, allocator: *Allocator, reader: anytype) Trie.ReadError!void {
|
||||
fn read(self: *Node, allocator: *Allocator, reader: anytype) Trie.ReadError!usize {
|
||||
self.node_dirty = true;
|
||||
const trie_offset = try reader.context.getPos();
|
||||
self.trie_offset = trie_offset;
|
||||
|
||||
self.trie_offset = try reader.context.getPos();
|
||||
var nread: usize = 0;
|
||||
|
||||
const node_size = try leb.readULEB128(u64, reader);
|
||||
if (node_size > 0) {
|
||||
@ -154,9 +151,13 @@ pub const Node = struct {
|
||||
const nedges = try reader.readByte();
|
||||
self.base.node_count += nedges;
|
||||
|
||||
nread += (try reader.context.getPos()) - trie_offset;
|
||||
|
||||
var i: usize = 0;
|
||||
while (i < nedges) : (i += 1) {
|
||||
var label = blk: {
|
||||
const edge_start_pos = try reader.context.getPos();
|
||||
|
||||
const label = blk: {
|
||||
var label_buf = std.ArrayList(u8).init(allocator);
|
||||
while (true) {
|
||||
const next = try reader.readByte();
|
||||
@ -168,20 +169,24 @@ pub const Node = struct {
|
||||
};
|
||||
|
||||
const seek_to = try leb.readULEB128(u64, reader);
|
||||
const cur_pos = try reader.context.getPos();
|
||||
const return_pos = try reader.context.getPos();
|
||||
|
||||
nread += return_pos - edge_start_pos;
|
||||
try reader.context.seekTo(seek_to);
|
||||
|
||||
const node = try allocator.create(Node);
|
||||
node.* = .{ .base = self.base };
|
||||
|
||||
try node.read(allocator, reader);
|
||||
nread += try node.read(allocator, reader);
|
||||
try self.edges.append(allocator, .{
|
||||
.from = self,
|
||||
.to = node,
|
||||
.label = label,
|
||||
});
|
||||
try reader.context.seekTo(cur_pos);
|
||||
try reader.context.seekTo(return_pos);
|
||||
}
|
||||
|
||||
return nread;
|
||||
}
|
||||
|
||||
/// Writes this node to a byte stream.
|
||||
@ -301,10 +306,23 @@ pub fn init(allocator: *Allocator) Trie {
|
||||
return .{ .allocator = allocator };
|
||||
}
|
||||
|
||||
/// Export symbol that is to be placed in the trie.
|
||||
pub const ExportSymbol = struct {
|
||||
/// Name of the symbol.
|
||||
name: []const u8,
|
||||
|
||||
/// Offset of this symbol's virtual memory address from the beginning
|
||||
/// of the __TEXT segment.
|
||||
vmaddr_offset: u64,
|
||||
|
||||
/// Export flags of this exported symbol.
|
||||
export_flags: u64,
|
||||
};
|
||||
|
||||
/// Insert a symbol into the trie, updating the prefixes in the process.
|
||||
/// This operation may change the layout of the trie by splicing edges in
|
||||
/// certain circumstances.
|
||||
pub fn put(self: *Trie, symbol: Symbol) !void {
|
||||
pub fn put(self: *Trie, symbol: ExportSymbol) !void {
|
||||
try self.createRoot();
|
||||
const node = try self.root.?.put(self.allocator, symbol.name);
|
||||
node.terminal_info = .{
|
||||
@ -356,7 +374,7 @@ const ReadError = error{
|
||||
};
|
||||
|
||||
/// Parse the trie from a byte stream.
|
||||
pub fn read(self: *Trie, reader: anytype) ReadError!void {
|
||||
pub fn read(self: *Trie, reader: anytype) ReadError!usize {
|
||||
try self.createRoot();
|
||||
return self.root.?.read(self.allocator, reader);
|
||||
}
|
||||
@ -533,60 +551,34 @@ test "write Trie to a byte stream" {
|
||||
}
|
||||
}
|
||||
|
||||
// test "parse Trie from byte stream" {
|
||||
// var gpa = testing.allocator;
|
||||
test "parse Trie from byte stream" {
|
||||
var gpa = testing.allocator;
|
||||
|
||||
// const in_buffer = [_]u8{
|
||||
// 0x0,
|
||||
// 0x1,
|
||||
// 0x5f,
|
||||
// 0x0,
|
||||
// 0x5,
|
||||
// 0x0,
|
||||
// 0x2,
|
||||
// 0x5f,
|
||||
// 0x6d,
|
||||
// 0x68,
|
||||
// 0x5f,
|
||||
// 0x65,
|
||||
// 0x78,
|
||||
// 0x65,
|
||||
// 0x63,
|
||||
// 0x75,
|
||||
// 0x74,
|
||||
// 0x65,
|
||||
// 0x5f,
|
||||
// 0x68,
|
||||
// 0x65,
|
||||
// 0x61,
|
||||
// 0x64,
|
||||
// 0x65,
|
||||
// 0x72,
|
||||
// 0x0,
|
||||
// 0x21,
|
||||
// 0x6d,
|
||||
// 0x61,
|
||||
// 0x69,
|
||||
// 0x6e,
|
||||
// 0x0,
|
||||
// 0x25,
|
||||
// 0x2,
|
||||
// 0x0,
|
||||
// 0x0,
|
||||
// 0x0,
|
||||
// 0x3,
|
||||
// 0x0,
|
||||
// 0x80,
|
||||
// 0x20,
|
||||
// 0x0,
|
||||
// };
|
||||
// var stream = std.io.fixedBufferStream(in_buffer[0..]);
|
||||
// var trie = Trie.init(gpa);
|
||||
// defer trie.deinit();
|
||||
// try trie.fromByteStream(&stream);
|
||||
const in_buffer = [_]u8{
|
||||
0x0, 0x1, // node root
|
||||
0x5f, 0x0, 0x5, // edge '_'
|
||||
0x0, 0x2, // non-terminal node
|
||||
0x5f, 0x6d, 0x68, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, // edge '_mh_execute_header'
|
||||
0x65, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x0, 0x21, // edge '_mh_execute_header'
|
||||
0x6d, 0x61, 0x69, 0x6e, 0x0, 0x25, // edge 'main'
|
||||
0x2, 0x0, 0x0, 0x0, // terminal node
|
||||
0x3, 0x0, 0x80, 0x20, 0x0, // terminal node
|
||||
};
|
||||
|
||||
// var out_buffer = try trie.writeULEB128Mem();
|
||||
// defer gpa.free(out_buffer);
|
||||
var in_stream = std.io.fixedBufferStream(in_buffer[0..]);
|
||||
var trie = Trie.init(gpa);
|
||||
defer trie.deinit();
|
||||
const nread = try trie.read(in_stream.reader());
|
||||
|
||||
// testing.expect(mem.eql(u8, in_buffer[0..], out_buffer));
|
||||
// }
|
||||
testing.expect(nread == in_buffer.len);
|
||||
|
||||
try trie.finalize();
|
||||
|
||||
var out_buffer = try gpa.alloc(u8, trie.size);
|
||||
defer gpa.free(out_buffer);
|
||||
var out_stream = std.io.fixedBufferStream(out_buffer);
|
||||
const nwritten = try trie.write(out_stream.writer());
|
||||
|
||||
testing.expect(nwritten == trie.size);
|
||||
testing.expect(mem.eql(u8, in_buffer[0..], out_buffer));
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user