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