authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-12-08 17:17:48+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-12-09 20:36:58+01:00
loga579f8ae8d6009d95ef22879bc725a233f838d6f
tree348e765217cfeb0998bb0241318a04f5b4b8f7e9
parent4c3e6c5bff967388dddc7ec352017c7b712d9f06

macho: add generic terminal info nullable struct to a node


1 files changed, 31 insertions(+), 15 deletions(-)

src/link/MachO/Trie.zig+31-15
......@@ -34,6 +34,7 @@ const std = @import("std");
3434const mem = std.mem;
3535const leb = std.leb;
3636const log = std.log.scoped(.link);
37const macho = std.macho;
3738const testing = std.testing;
3839const assert = std.debug.assert;
3940const Allocator = mem.Allocator;
......@@ -61,10 +62,14 @@ pub const Edge = struct {
6162
6263pub const Node = struct {
6364 base: *Trie,
64 /// Export flags associated with this exported symbol (if any).
65 export_flags: ?u64 = null,
66 /// VM address offset wrt to the section this symbol is defined against (if any).
67 vmaddr_offset: ?u64 = null,
65 /// Terminal info associated with this node.
66 /// If this node is not a terminal node, info is null.
67 terminal_info: ?struct {
68 /// Export flags associated with this exported symbol.
69 export_flags: u64,
70 /// VM address offset wrt to the section this symbol is defined against.
71 vmaddr_offset: u64,
72 } = null,
6873 /// Offset of this node in the trie output byte stream.
6974 trie_offset: ?usize = null,
7075 /// List of all edges originating from this node.
......@@ -125,9 +130,15 @@ pub const Node = struct {
125130 var reader = stream.reader();
126131 const node_size = try leb.readULEB128(u64, reader);
127132 if (node_size > 0) {
128 self.export_flags = try leb.readULEB128(u64, reader);
129 // TODO Parse flags.
130 self.vmaddr_offset = try leb.readULEB128(u64, reader);
133 const export_flags = try leb.readULEB128(u64, reader);
134 // TODO Parse special flags.
135 assert(export_flags & macho.EXPORT_SYMBOL_FLAGS_REEXPORT == 0 and
136 export_flags & macho.EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER == 0);
137 const vmaddr_offset = try leb.readULEB128(u64, reader);
138 self.terminal_info = .{
139 .export_flags = export_flags,
140 .vmaddr_offset = vmaddr_offset,
141 };
131142 }
132143 const nedges = try reader.readByte();
133144 self.base.node_count += nedges;
......@@ -162,13 +173,16 @@ pub const Node = struct {
162173 /// In case this is not upheld, this method will panic.
163174 fn writeULEB128Mem(self: Node, buffer: *std.ArrayList(u8)) !void {
164175 assert(self.trie_offset != null); // You need to call updateOffset first.
165 if (self.vmaddr_offset) |offset| {
176 if (self.terminal_info) |info| {
166177 // Terminal node info: encode export flags and vmaddr offset of this symbol.
167178 var info_buf_len: usize = 0;
168179 var info_buf: [@sizeOf(u64) * 2]u8 = undefined;
169180 var info_stream = std.io.fixedBufferStream(&info_buf);
170 try leb.writeULEB128(info_stream.writer(), self.export_flags.?);
171 try leb.writeULEB128(info_stream.writer(), offset);
181 // TODO Implement for special flags.
182 assert(info.export_flags & macho.EXPORT_SYMBOL_FLAGS_REEXPORT == 0 and
183 info.export_flags & macho.EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER == 0);
184 try leb.writeULEB128(info_stream.writer(), info.export_flags);
185 try leb.writeULEB128(info_stream.writer(), info.vmaddr_offset);
172186
173187 // Encode the size of the terminal node info.
174188 var size_buf: [@sizeOf(u64)]u8 = undefined;
......@@ -208,9 +222,9 @@ pub const Node = struct {
208222 /// Updates offset of this node in the output byte stream.
209223 fn updateOffset(self: *Node, offset: usize) UpdateResult {
210224 var node_size: usize = 0;
211 if (self.vmaddr_offset) |vmaddr| {
212 node_size += sizeULEB128Mem(self.export_flags.?);
213 node_size += sizeULEB128Mem(vmaddr);
225 if (self.terminal_info) |info| {
226 node_size += sizeULEB128Mem(info.export_flags);
227 node_size += sizeULEB128Mem(info.vmaddr_offset);
214228 node_size += sizeULEB128Mem(node_size);
215229 } else {
216230 node_size += 1; // 0x0 for non-terminal nodes
......@@ -263,8 +277,10 @@ pub fn put(self: *Trie, symbol: Symbol) !void {
263277 self.root = .{ .base = self };
264278 }
265279 const node = try self.root.?.put(symbol.name);
266 node.vmaddr_offset = symbol.vmaddr_offset;
267 node.export_flags = symbol.export_flags;
280 node.terminal_info = .{
281 .vmaddr_offset = symbol.vmaddr_offset,
282 .export_flags = symbol.export_flags,
283 };
268284}
269285
270286const FromByteStreamError = error{