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");...@@ -34,6 +34,7 @@ const std = @import("std");
34const mem = std.mem;34const mem = std.mem;
35const leb = std.leb;35const leb = std.leb;
36const log = std.log.scoped(.link);36const log = std.log.scoped(.link);
37const macho = std.macho;
37const testing = std.testing;38const testing = std.testing;
38const assert = std.debug.assert;39const assert = std.debug.assert;
39const Allocator = mem.Allocator;40const Allocator = mem.Allocator;
...@@ -61,10 +62,14 @@ pub const Edge = struct {...@@ -61,10 +62,14 @@ pub const Edge = struct {
6162
62pub const Node = struct {63pub const Node = struct {
63 base: *Trie,64 base: *Trie,
64 /// Export flags associated with this exported symbol (if any).65 /// Terminal info associated with this node.
65 export_flags: ?u64 = null,66 /// If this node is not a terminal node, info is null.
66 /// VM address offset wrt to the section this symbol is defined against (if any).67 terminal_info: ?struct {
67 vmaddr_offset: ?u64 = null,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,
68 /// Offset of this node in the trie output byte stream.73 /// Offset of this node in the trie output byte stream.
69 trie_offset: ?usize = null,74 trie_offset: ?usize = null,
70 /// List of all edges originating from this node.75 /// List of all edges originating from this node.
...@@ -125,9 +130,15 @@ pub const Node = struct {...@@ -125,9 +130,15 @@ pub const Node = struct {
125 var reader = stream.reader();130 var reader = stream.reader();
126 const node_size = try leb.readULEB128(u64, reader);131 const node_size = try leb.readULEB128(u64, reader);
127 if (node_size > 0) {132 if (node_size > 0) {
128 self.export_flags = try leb.readULEB128(u64, reader);133 const export_flags = try leb.readULEB128(u64, reader);
129 // TODO Parse flags.134 // TODO Parse special flags.
130 self.vmaddr_offset = try leb.readULEB128(u64, reader);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 };
131 }142 }
132 const nedges = try reader.readByte();143 const nedges = try reader.readByte();
133 self.base.node_count += nedges;144 self.base.node_count += nedges;
...@@ -162,13 +173,16 @@ pub const Node = struct {...@@ -162,13 +173,16 @@ pub const Node = struct {
162 /// In case this is not upheld, this method will panic.173 /// In case this is not upheld, this method will panic.
163 fn writeULEB128Mem(self: Node, buffer: *std.ArrayList(u8)) !void {174 fn writeULEB128Mem(self: Node, buffer: *std.ArrayList(u8)) !void {
164 assert(self.trie_offset != null); // You need to call updateOffset first.175 assert(self.trie_offset != null); // You need to call updateOffset first.
165 if (self.vmaddr_offset) |offset| {176 if (self.terminal_info) |info| {
166 // Terminal node info: encode export flags and vmaddr offset of this symbol.177 // Terminal node info: encode export flags and vmaddr offset of this symbol.
167 var info_buf_len: usize = 0;178 var info_buf_len: usize = 0;
168 var info_buf: [@sizeOf(u64) * 2]u8 = undefined;179 var info_buf: [@sizeOf(u64) * 2]u8 = undefined;
169 var info_stream = std.io.fixedBufferStream(&info_buf);180 var info_stream = std.io.fixedBufferStream(&info_buf);
170 try leb.writeULEB128(info_stream.writer(), self.export_flags.?);181 // TODO Implement for special flags.
171 try leb.writeULEB128(info_stream.writer(), offset);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
173 // Encode the size of the terminal node info.187 // Encode the size of the terminal node info.
174 var size_buf: [@sizeOf(u64)]u8 = undefined;188 var size_buf: [@sizeOf(u64)]u8 = undefined;
...@@ -208,9 +222,9 @@ pub const Node = struct {...@@ -208,9 +222,9 @@ pub const Node = struct {
208 /// Updates offset of this node in the output byte stream.222 /// Updates offset of this node in the output byte stream.
209 fn updateOffset(self: *Node, offset: usize) UpdateResult {223 fn updateOffset(self: *Node, offset: usize) UpdateResult {
210 var node_size: usize = 0;224 var node_size: usize = 0;
211 if (self.vmaddr_offset) |vmaddr| {225 if (self.terminal_info) |info| {
212 node_size += sizeULEB128Mem(self.export_flags.?);226 node_size += sizeULEB128Mem(info.export_flags);
213 node_size += sizeULEB128Mem(vmaddr);227 node_size += sizeULEB128Mem(info.vmaddr_offset);
214 node_size += sizeULEB128Mem(node_size);228 node_size += sizeULEB128Mem(node_size);
215 } else {229 } else {
216 node_size += 1; // 0x0 for non-terminal nodes230 node_size += 1; // 0x0 for non-terminal nodes
...@@ -263,8 +277,10 @@ pub fn put(self: *Trie, symbol: Symbol) !void {...@@ -263,8 +277,10 @@ pub fn put(self: *Trie, symbol: Symbol) !void {
263 self.root = .{ .base = self };277 self.root = .{ .base = self };
264 }278 }
265 const node = try self.root.?.put(symbol.name);279 const node = try self.root.?.put(symbol.name);
266 node.vmaddr_offset = symbol.vmaddr_offset;280 node.terminal_info = .{
267 node.export_flags = symbol.export_flags;281 .vmaddr_offset = symbol.vmaddr_offset,
282 .export_flags = symbol.export_flags,
283 };
268}284}
269285
270const FromByteStreamError = error{286const FromByteStreamError = error{