| ... | ... | @@ -5,7 +5,6 @@ const mem = std.mem; |
| 5 | 5 | |
| 6 | 6 | const assert = std.debug.assert; |
| 7 | 7 | const Allocator = mem.Allocator; |
| 8 | | const sizeLEB128 = @import("../MachO.zig").sizeLEB128; |
| 9 | 8 | |
| 10 | 9 | /// Table of binding info entries used to tell the dyld which |
| 11 | 10 | /// symbols to bind at loading time. |
| ... | ... | @@ -27,6 +26,9 @@ pub const BindingInfoTable = struct { |
| 27 | 26 | |
| 28 | 27 | /// Offset of this symbol wrt to the segment id encoded in `segment`. |
| 29 | 28 | offset: i64, |
| 29 | |
| 30 | /// Addend value (if any). |
| 31 | addend: ?i64 = null, |
| 30 | 32 | }; |
| 31 | 33 | |
| 32 | 34 | pub fn deinit(self: *BindingInfoTable, allocator: *Allocator) void { |
| ... | ... | @@ -91,6 +93,9 @@ pub const BindingInfoTable = struct { |
| 91 | 93 | macho.BIND_OPCODE_SET_TYPE_IMM => { |
| 92 | 94 | self.binding_type = imm; |
| 93 | 95 | }, |
| 96 | macho.BIND_OPCODE_SET_ADDEND_SLEB => { |
| 97 | symbol.addend = try leb.readILEB128(i64, reader); |
| 98 | }, |
| 94 | 99 | else => { |
| 95 | 100 | std.log.warn("unhandled BIND_OPCODE_: 0x{x}", .{opcode}); |
| 96 | 101 | }, |
| ... | ... | @@ -121,6 +126,11 @@ pub const BindingInfoTable = struct { |
| 121 | 126 | try writer.writeByte(macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | @truncate(u4, symbol.segment)); |
| 122 | 127 | try leb.writeILEB128(writer, symbol.offset); |
| 123 | 128 | |
| 129 | if (symbol.addend) |addend| { |
| 130 | try writer.writeByte(macho.BIND_OPCODE_SET_ADDEND_SLEB); |
| 131 | try leb.writeILEB128(writer, addend); |
| 132 | } |
| 133 | |
| 124 | 134 | try writer.writeByte(macho.BIND_OPCODE_DO_BIND); |
| 125 | 135 | } |
| 126 | 136 | |
| ... | ... | @@ -128,10 +138,13 @@ pub const BindingInfoTable = struct { |
| 128 | 138 | } |
| 129 | 139 | |
| 130 | 140 | /// Calculate size in bytes of this binding info table. |
| 131 | | pub fn calcSize(self: *BindingInfoTable) usize { |
| 141 | pub fn calcSize(self: *BindingInfoTable) !usize { |
| 142 | var stream = std.io.countingWriter(std.io.null_writer); |
| 143 | var writer = stream.writer(); |
| 132 | 144 | var size: usize = 1; |
| 145 | |
| 133 | 146 | if (self.dylib_ordinal > 15) { |
| 134 | | size += sizeLEB128(self.dylib_ordinal); |
| 147 | try leb.writeULEB128(writer, @bitCast(u64, self.dylib_ordinal)); |
| 135 | 148 | } |
| 136 | 149 | |
| 137 | 150 | size += 1; |
| ... | ... | @@ -144,12 +157,17 @@ pub const BindingInfoTable = struct { |
| 144 | 157 | } |
| 145 | 158 | |
| 146 | 159 | size += 1; |
| 147 | | size += sizeLEB128(symbol.offset); |
| 160 | try leb.writeILEB128(writer, symbol.offset); |
| 161 | |
| 162 | if (symbol.addend) |addend| { |
| 163 | size += 1; |
| 164 | try leb.writeILEB128(writer, addend); |
| 165 | } |
| 148 | 166 | |
| 149 | 167 | size += 1; |
| 150 | 168 | } |
| 151 | 169 | |
| 152 | | size += 1; |
| 170 | size += 1 + stream.bytes_written; |
| 153 | 171 | return size; |
| 154 | 172 | } |
| 155 | 173 | }; |
| ... | ... | @@ -173,6 +191,9 @@ pub const LazyBindingInfoTable = struct { |
| 173 | 191 | |
| 174 | 192 | /// Id of the segment where to bind this symbol to. |
| 175 | 193 | segment: u8, |
| 194 | |
| 195 | /// Addend value (if any). |
| 196 | addend: ?i64 = null, |
| 176 | 197 | }; |
| 177 | 198 | |
| 178 | 199 | pub fn deinit(self: *LazyBindingInfoTable, allocator: *Allocator) void { |
| ... | ... | @@ -232,6 +253,9 @@ pub const LazyBindingInfoTable = struct { |
| 232 | 253 | macho.BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB => { |
| 233 | 254 | symbol.dylib_ordinal = try leb.readILEB128(i64, reader); |
| 234 | 255 | }, |
| 256 | macho.BIND_OPCODE_SET_ADDEND_SLEB => { |
| 257 | symbol.addend = try leb.readILEB128(i64, reader); |
| 258 | }, |
| 235 | 259 | else => { |
| 236 | 260 | std.log.warn("unhandled BIND_OPCODE_: 0x{x}", .{opcode}); |
| 237 | 261 | }, |
| ... | ... | @@ -246,6 +270,11 @@ pub const LazyBindingInfoTable = struct { |
| 246 | 270 | try writer.writeByte(macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | @truncate(u4, symbol.segment)); |
| 247 | 271 | try leb.writeILEB128(writer, symbol.offset); |
| 248 | 272 | |
| 273 | if (symbol.addend) |addend| { |
| 274 | try writer.writeByte(macho.BIND_OPCODE_SET_ADDEND_SLEB); |
| 275 | try leb.writeILEB128(writer, addend); |
| 276 | } |
| 277 | |
| 249 | 278 | if (symbol.dylib_ordinal > 15) { |
| 250 | 279 | try writer.writeByte(macho.BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB); |
| 251 | 280 | try leb.writeULEB128(writer, @bitCast(u64, symbol.dylib_ordinal)); |
| ... | ... | @@ -267,15 +296,23 @@ pub const LazyBindingInfoTable = struct { |
| 267 | 296 | } |
| 268 | 297 | |
| 269 | 298 | /// Calculate size in bytes of this binding info table. |
| 270 | | pub fn calcSize(self: *LazyBindingInfoTable) usize { |
| 299 | pub fn calcSize(self: *LazyBindingInfoTable) !usize { |
| 300 | var stream = std.io.countingWriter(std.io.null_writer); |
| 301 | var writer = stream.writer(); |
| 271 | 302 | var size: usize = 0; |
| 272 | 303 | |
| 273 | 304 | for (self.symbols.items) |symbol| { |
| 274 | 305 | size += 1; |
| 275 | | size += sizeLEB128(symbol.offset); |
| 306 | try leb.writeILEB128(writer, symbol.offset); |
| 307 | |
| 308 | if (symbol.addend) |addend| { |
| 309 | size += 1; |
| 310 | try leb.writeILEB128(writer, addend); |
| 311 | } |
| 312 | |
| 276 | 313 | size += 1; |
| 277 | 314 | if (symbol.dylib_ordinal > 15) { |
| 278 | | size += sizeLEB128(symbol.dylib_ordinal); |
| 315 | try leb.writeULEB128(writer, @bitCast(u64, symbol.dylib_ordinal)); |
| 279 | 316 | } |
| 280 | 317 | if (symbol.name) |name| { |
| 281 | 318 | size += 1; |
| ... | ... | @@ -285,6 +322,7 @@ pub const LazyBindingInfoTable = struct { |
| 285 | 322 | size += 2; |
| 286 | 323 | } |
| 287 | 324 | |
| 325 | size += stream.bytes_written; |
| 288 | 326 | return size; |
| 289 | 327 | } |
| 290 | 328 | }; |