@isopodlabs/binary_libs 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/mach.js ADDED
@@ -0,0 +1,1034 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.FATMachFile = exports.MachFile = exports.CMD = void 0;
27
+ const binary = __importStar(require("@isopodlabs/binary"));
28
+ class mach_stream extends binary.stream_endian {
29
+ base;
30
+ mem;
31
+ constructor(base, data, be, mem) {
32
+ super(data, be);
33
+ this.base = base;
34
+ this.mem = mem;
35
+ }
36
+ subdata(offset, size) {
37
+ return this.base.subarray(offset, size && offset + size);
38
+ }
39
+ substream(offset, size) {
40
+ return new mach_stream(this.base, this.subdata(offset, size), this.be, this.mem);
41
+ }
42
+ getmem(address, size) {
43
+ return this.mem?.get(address, size);
44
+ }
45
+ }
46
+ const uint16 = binary.UINT16;
47
+ const uint32 = binary.UINT32;
48
+ const uint64 = binary.UINT64;
49
+ const int32 = binary.INT32;
50
+ const xint32 = binary.XINT32;
51
+ const xint64 = binary.XINT64;
52
+ const FILETYPE = {
53
+ OBJECT: 1,
54
+ EXECUTE: 2,
55
+ FVMLIB: 3,
56
+ CORE: 4,
57
+ PRELOAD: 5,
58
+ DYLIB: 6,
59
+ DYLINKER: 7,
60
+ BUNDLE: 8,
61
+ DYLIB_STUB: 9,
62
+ DSYM: 10,
63
+ KEXT_BUNDLE: 11,
64
+ FILESET: 12
65
+ };
66
+ // Machine types known by all
67
+ var CPU_TYPE;
68
+ (function (CPU_TYPE) {
69
+ CPU_TYPE[CPU_TYPE["ANY"] = -1] = "ANY";
70
+ CPU_TYPE[CPU_TYPE["ARCH_MASK"] = 4278190080] = "ARCH_MASK";
71
+ CPU_TYPE[CPU_TYPE["ARCH_64"] = 16777216] = "ARCH_64";
72
+ CPU_TYPE[CPU_TYPE["VAX"] = 1] = "VAX";
73
+ CPU_TYPE[CPU_TYPE["MC680x0"] = 6] = "MC680x0";
74
+ CPU_TYPE[CPU_TYPE["X86"] = 7] = "X86";
75
+ CPU_TYPE[CPU_TYPE["MIPS"] = 8] = "MIPS";
76
+ CPU_TYPE[CPU_TYPE["MC98000"] = 10] = "MC98000";
77
+ CPU_TYPE[CPU_TYPE["HPPA"] = 11] = "HPPA";
78
+ CPU_TYPE[CPU_TYPE["ARM"] = 12] = "ARM";
79
+ CPU_TYPE[CPU_TYPE["MC88000"] = 13] = "MC88000";
80
+ CPU_TYPE[CPU_TYPE["SPARC"] = 14] = "SPARC";
81
+ CPU_TYPE[CPU_TYPE["I860"] = 15] = "I860";
82
+ CPU_TYPE[CPU_TYPE["ALPHA"] = 16] = "ALPHA";
83
+ CPU_TYPE[CPU_TYPE["POWERPC"] = 18] = "POWERPC";
84
+ CPU_TYPE[CPU_TYPE["X86_64"] = 16777223] = "X86_64";
85
+ CPU_TYPE[CPU_TYPE["POWERPC_64"] = 16777234] = "POWERPC_64";
86
+ CPU_TYPE[CPU_TYPE["ARM_64"] = 16777228] = "ARM_64";
87
+ })(CPU_TYPE || (CPU_TYPE = {}));
88
+ const CPU_SUBTYPES = {
89
+ [CPU_TYPE.VAX]: {
90
+ VAX_ALL: 0,
91
+ VAX780: 1,
92
+ VAX785: 2,
93
+ VAX750: 3,
94
+ VAX730: 4,
95
+ UVAXI: 5,
96
+ UVAXII: 6,
97
+ VAX8200: 7,
98
+ VAX8500: 8,
99
+ VAX8600: 9,
100
+ VAX8650: 10,
101
+ VAX8800: 11,
102
+ UVAXIII: 12,
103
+ },
104
+ [CPU_TYPE.MC680x0]: {
105
+ MC680x0_ALL: 1,
106
+ MC68030: 1,
107
+ MC68040: 2,
108
+ MC68030_ONLY: 3,
109
+ },
110
+ [CPU_TYPE.X86]: {
111
+ X86_ALL: 3,
112
+ X86_64_ALL: 3,
113
+ X86_ARCH1: 4,
114
+ },
115
+ [CPU_TYPE.MIPS]: {
116
+ MIPS_ALL: 0,
117
+ MIPS_R2300: 1,
118
+ MIPS_R2600: 2,
119
+ MIPS_R2800: 3,
120
+ MIPS_R2000a: 4,
121
+ MIPS_R2000: 5,
122
+ MIPS_R3000a: 6,
123
+ MIPS_R3000: 7,
124
+ },
125
+ [CPU_TYPE.MC98000]: {
126
+ MC98000_ALL: 0,
127
+ MC98601: 1,
128
+ },
129
+ [CPU_TYPE.HPPA]: {
130
+ HPPA_ALL: 0,
131
+ HPPA_7100: 0,
132
+ HPPA_7100LC: 1,
133
+ },
134
+ [CPU_TYPE.ARM]: {
135
+ ARM_ALL: 0,
136
+ ARM_V4T: 5,
137
+ ARM_V6: 6,
138
+ ARM_V5TEJ: 7,
139
+ ARM_XSCALE: 8,
140
+ ARM_V7: 9,
141
+ ARM_V7S: 11,
142
+ ARM_V7K: 12,
143
+ ARM_V6M: 14,
144
+ ARM_V7M: 15,
145
+ ARM_V7EM: 16,
146
+ },
147
+ [CPU_TYPE.MC88000]: {
148
+ MC88000_ALL: 0,
149
+ MC88100: 1,
150
+ MC88110: 2,
151
+ },
152
+ [CPU_TYPE.SPARC]: {
153
+ SPARC_ALL: 0,
154
+ },
155
+ [CPU_TYPE.I860]: {
156
+ I860_ALL: 0,
157
+ I860_860: 1,
158
+ },
159
+ [CPU_TYPE.ALPHA]: {},
160
+ [CPU_TYPE.POWERPC]: {
161
+ POWERPC_ALL: 0,
162
+ POWERPC_601: 1,
163
+ POWERPC_602: 2,
164
+ POWERPC_603: 3,
165
+ POWERPC_603e: 4,
166
+ POWERPC_603ev: 5,
167
+ POWERPC_604: 6,
168
+ POWERPC_604e: 7,
169
+ POWERPC_620: 8,
170
+ POWERPC_750: 9,
171
+ POWERPC_7400: 10,
172
+ POWERPC_7450: 11,
173
+ POWERPC_970: 100,
174
+ },
175
+ [CPU_TYPE.X86_64]: {
176
+ I386_ALL: 0x03,
177
+ I386: 0x03,
178
+ I486: 0x04,
179
+ I486SX: 0x84,
180
+ I586: 0x05,
181
+ PENT: 0x05,
182
+ PENTPRO: 0x16,
183
+ PENTII_M3: 0x36,
184
+ PENTII_M5: 0x56,
185
+ CELERON: 0x67,
186
+ CELERON_MOBILE: 0x77,
187
+ PENTIUM_3: 0x08,
188
+ PENTIUM_3_M: 0x18,
189
+ PENTIUM_3_XEON: 0x28,
190
+ PENTIUM_M: 0x09,
191
+ PENTIUM_4: 0x0a,
192
+ PENTIUM_4_M: 0x1a,
193
+ ITANIUM: 0x0b,
194
+ ITANIUM_2: 0x1b,
195
+ XEON: 0x0c,
196
+ XEON_MP: 0x1c,
197
+ },
198
+ [CPU_TYPE.POWERPC_64]: {},
199
+ [CPU_TYPE.ARM_64]: {
200
+ FEATURE: 0x01000000,
201
+ LIB64: 0x80000000,
202
+ ARM64_ALL: 0,
203
+ ARM64_V8: 1,
204
+ ARM64E: 2,
205
+ },
206
+ };
207
+ // Constants for the flags field of the header
208
+ const HEADER_FLAGS = {
209
+ NOUNDEFS: 0x1,
210
+ INCRLINK: 0x2,
211
+ DYLDLINK: 0x4,
212
+ BINDATLOAD: 0x8,
213
+ PREBOUND: 0x10,
214
+ SPLIT_SEGS: 0x20,
215
+ LAZY_INIT: 0x40,
216
+ TWOLEVEL: 0x80,
217
+ FORCE_FLAT: 0x100,
218
+ NOMULTIDEFS: 0x200,
219
+ NOFIXPREBINDING: 0x400,
220
+ PREBINDABLE: 0x800,
221
+ ALLMODSBOUND: 0x1000,
222
+ SUBSECTIONS_VIA_SYMBOLS: 0x2000,
223
+ CANONICAL: 0x4000,
224
+ WEAK_DEFINES: 0x8000,
225
+ BINDS_TO_WEAK: 0x10000,
226
+ ALLOW_STACK_EXECUTION: 0x20000,
227
+ ROOT_SAFE: 0x40000,
228
+ SETUID_SAFE: 0x80000,
229
+ NO_REEXPORTED_DYLIBS: 0x100000,
230
+ PIE: 0x200000,
231
+ DEAD_STRIPPABLE_DYLIB: 0x400000,
232
+ HAS_TLV_DESCRIPTORS: 0x800000,
233
+ NO_HEAP_EXECUTION: 0x1000000, // When this bit is set, the OS will run the main executable with a non-executable heap even on platforms (e.g. i386) that don't require it.Only used in MH_EXECUTE filetypes.
234
+ };
235
+ const header = {
236
+ magic: uint32,
237
+ cputype: binary.as(uint32, binary.Enum(CPU_TYPE)),
238
+ cpusubtype: binary.as(uint32, (x) => x),
239
+ filetype: binary.as(uint32, binary.Enum(FILETYPE)),
240
+ ncmds: uint32,
241
+ sizeofcmds: uint32,
242
+ flags: binary.as(uint32, binary.Flags(HEADER_FLAGS, true))
243
+ };
244
+ const fat_arch = {
245
+ cputype: binary.as(uint32, binary.Enum(CPU_TYPE)),
246
+ cpusubtype: binary.as(uint32, (x) => x),
247
+ offset: binary.UINT32_BE,
248
+ size: binary.UINT32_BE,
249
+ align: binary.UINT32_BE,
250
+ contents: binary.DontRead(),
251
+ };
252
+ const fat_header = {
253
+ magic: uint32,
254
+ archs: binary.ArrayType(uint32, fat_arch)
255
+ };
256
+ const REQ_DYLD = 0x80000000;
257
+ exports.CMD = {
258
+ SEGMENT: 0x01,
259
+ SYMTAB: 0x02,
260
+ SYMSEG: 0x03,
261
+ THREAD: 0x04,
262
+ UNIXTHREAD: 0x05,
263
+ LOADFVMLIB: 0x06,
264
+ IDFVMLIB: 0x07,
265
+ IDENT: 0x08,
266
+ FVMFILE: 0x09,
267
+ PREPAGE: 0x0a,
268
+ DYSYMTAB: 0x0b,
269
+ LOAD_DYLIB: 0x0c,
270
+ ID_DYLIB: 0x0d,
271
+ LOAD_DYLINKER: 0x0e,
272
+ ID_DYLINKER: 0x0f,
273
+ PREBOUND_DYLIB: 0x10,
274
+ ROUTINES: 0x11,
275
+ SUB_FRAMEWORK: 0x12,
276
+ SUB_UMBRELLA: 0x13,
277
+ SUB_CLIENT: 0x14,
278
+ SUB_LIBRARY: 0x15,
279
+ TWOLEVEL_HINTS: 0x16,
280
+ PREBIND_CKSUM: 0x17,
281
+ LOAD_WEAK_DYLIB: 0x18 + REQ_DYLD,
282
+ SEGMENT_64: 0x19,
283
+ ROUTINES_64: 0x1a,
284
+ UUID: 0x1b,
285
+ RPATH: 0x1c + REQ_DYLD,
286
+ CODE_SIGNATURE: 0x1d,
287
+ SEGMENT_SPLIT_INFO: 0x1e,
288
+ REEXPORT_DYLIB: 0x1f + REQ_DYLD,
289
+ LAZY_LOAD_DYLIB: 0x20,
290
+ ENCRYPTION_INFO: 0x21,
291
+ DYLD_INFO: 0x22,
292
+ DYLD_INFO_ONLY: 0x22 + REQ_DYLD,
293
+ LOAD_UPWARD_DYLIB: 0x23 + REQ_DYLD,
294
+ VERSION_MIN_MACOSX: 0x24,
295
+ VERSION_MIN_IPHONEOS: 0x25,
296
+ FUNCTION_STARTS: 0x26,
297
+ DYLD_ENVIRONMENT: 0x27,
298
+ MAIN: 0x28 + REQ_DYLD,
299
+ DATA_IN_CODE: 0x29,
300
+ SOURCE_VERSION: 0x2A,
301
+ DYLIB_CODE_SIGN_DRS: 0x2B,
302
+ ENCRYPTION_INFO_64: 0x2C,
303
+ LINKER_OPTION: 0x2D,
304
+ LINKER_OPTIMIZATION_HINT: 0x2E,
305
+ VERSION_MIN_TVOS: 0x2F,
306
+ VERSION_MIN_WATCHOS: 0x30,
307
+ NOTE: 0x31,
308
+ BUILD_VERSION: 0x32,
309
+ DYLD_EXPORTS_TRIE: 0x33 + REQ_DYLD,
310
+ DYLD_CHAINED_FIXUPS: 0x34 + REQ_DYLD, // used with linkedit_data_command
311
+ };
312
+ const str = {
313
+ get(s) {
314
+ const off = uint32.get(s); // offset to the string
315
+ return binary.utils.decodeTextTo0(s.buffer_at(off - 8), 'utf8');
316
+ }
317
+ };
318
+ const index_table = {
319
+ first: uint32,
320
+ count: uint32,
321
+ };
322
+ const blob = {
323
+ get(s) {
324
+ const offset = uint32.get(s);
325
+ const size = uint32.get(s);
326
+ if (size)
327
+ return s.subdata(offset, size); //.buffer_at(offset, size);
328
+ }
329
+ };
330
+ function blobT(type) {
331
+ return {
332
+ get(s) {
333
+ const offset = uint32.get(s);
334
+ const size = uint32.get(s);
335
+ return {
336
+ data: s.subdata(offset, size),
337
+ contents: binary.read(s.substream(offset, size), type)
338
+ };
339
+ }
340
+ };
341
+ }
342
+ function count_table(type) {
343
+ return {
344
+ get(s) {
345
+ const offset = uint32.get(s);
346
+ const count = uint32.get(s);
347
+ if (count)
348
+ return binary.readn(s.substream(offset), type, count);
349
+ }
350
+ };
351
+ }
352
+ const fixed_string16 = binary.StringType(16);
353
+ const version = binary.asFlags(uint32, { major: 0xffff0000, minor: 0xff00, patch: 0xff }, false);
354
+ const command = {
355
+ cmd: binary.as(uint32, binary.EnumV(exports.CMD)),
356
+ cmdsize: uint32,
357
+ };
358
+ const SECTION_FLAGS = binary.BitFields({
359
+ TYPE: [8, binary.Enum({
360
+ REGULAR: 0x0,
361
+ ZEROFILL: 0x1,
362
+ CSTRING_LITERALS: 0x2,
363
+ LITERALS4: 0x3,
364
+ LITERALS8: 0x4,
365
+ LITERAL_POINTERS: 0x5,
366
+ NON_LAZY_SYMBOL_POINTERS: 0x6,
367
+ LAZY_SYMBOL_POINTERS: 0x7,
368
+ SYMBOL_STUBS: 0x8,
369
+ MOD_INIT_FUNC_POINTERS: 0x9,
370
+ MOD_TERM_FUNC_POINTERS: 0xa,
371
+ COALESCED: 0xb,
372
+ GB_ZEROFILL: 0xc,
373
+ INTERPOSING: 0xd,
374
+ LITERALS16: 0xe,
375
+ DTRACE_DOF: 0xf,
376
+ LAZY_DYLIB_SYMBOL_POINTERS: 0x10,
377
+ // Section types to support thread local variables
378
+ THREAD_LOCAL_REGULAR: 0x11,
379
+ THREAD_LOCAL_ZEROFILL: 0x12,
380
+ THREAD_LOCAL_VARIABLES: 0x13,
381
+ THREAD_LOCAL_VARIABLE_POINTERS: 0x14,
382
+ THREAD_LOCAL_INIT_FUNCTION_POINTERS: 0x15, // functions to call to initialize TLV values
383
+ })],
384
+ ATTRIBUTES: [24, binary.BitFields({
385
+ SYS: [16, binary.Flags({
386
+ SOME_INSTRUCTIONS: 0x0004,
387
+ EXT_RELOC: 0x0002,
388
+ LOC_RELOC: 0x0001, // section has local relocation entries
389
+ }, true)],
390
+ USR: [8, binary.Flags({
391
+ PURE_INSTRUCTIONS: 0x80,
392
+ NO_TOC: 0x40,
393
+ STRIP_STATIC_SYMS: 0x20,
394
+ NO_DEAD_STRIP: 0x10,
395
+ LIVE_SUPPORT: 0x08,
396
+ SELF_MODIFYING_CODE: 0x04,
397
+ DEBUG: 0x02, // a debug section
398
+ }, true)],
399
+ })],
400
+ });
401
+ function section(bits) {
402
+ const type = binary.UINT(bits);
403
+ class Section extends binary.ReadWriteStruct({
404
+ //data: binary.DontRead<binary.utils.MappedMemory>(),
405
+ sectname: fixed_string16,
406
+ segname: fixed_string16,
407
+ addr: type,
408
+ size: type,
409
+ offset: xint32,
410
+ align: uint32,
411
+ reloff: xint32,
412
+ nreloc: uint32,
413
+ flags: binary.as(uint32, SECTION_FLAGS),
414
+ reserved1: uint32,
415
+ reserved2: uint32,
416
+ _: binary.AlignType(bits / 8)
417
+ }) {
418
+ data;
419
+ constructor(s) {
420
+ super(s);
421
+ const prot = this.flags.ATTRIBUTES.SYS.SOME_INSTRUCTIONS ? 4 /* binary.utils.MEM.EXECUTE */ : 0 /* binary.utils.MEM.NONE */;
422
+ this.data = (async () => {
423
+ //return new binary.utils.MappedMemory(await s.file.get(BigInt(this.addr), Number(this.size)), Number(this.addr), prot)
424
+ return new binary.utils.MappedMemory(s.subdata(+this.offset, Number(this.size)), Number(this.addr), prot);
425
+ })();
426
+ }
427
+ }
428
+ return Section;
429
+ }
430
+ const SEGMENT_FLAGS = {
431
+ HIGHVM: 0x1,
432
+ FVMLIB: 0x2,
433
+ NORELOC: 0x4,
434
+ PROTECTED_VERSION_1: 0x8, // This segment is protected. If the segment starts at file offset 0, the first page of the segment is not protected. All other pages of the segment are protected.
435
+ };
436
+ function segment(bits) {
437
+ const type = binary.UINT(bits);
438
+ const fields = {
439
+ data: binary.DontRead(),
440
+ segname: fixed_string16,
441
+ vmaddr: type,
442
+ vmsize: type,
443
+ fileoff: type,
444
+ filesize: type,
445
+ maxprot: uint32,
446
+ initprot: uint32,
447
+ nsects: uint32,
448
+ flags: binary.as(uint32, binary.Flags(SEGMENT_FLAGS, true)),
449
+ sections: binary.DontRead(), //binary.ReadType<typeof section(bits)>)),
450
+ };
451
+ return {
452
+ async get(s) {
453
+ const o = binary.read(s, fields);
454
+ const data = await s.getmem(BigInt(o.vmaddr), Number(o.filesize)) ?? s.subdata(Number(o.fileoff), Number(o.filesize));
455
+ o.data = new binary.utils.MappedMemory(data, Number(o.vmaddr), o.initprot);
456
+ const sect = section(bits);
457
+ if (o.nsects) {
458
+ o.sections = binary.objectWithNames(binary.ArrayType(o.nsects, section(bits)), binary.field('sectname')).get(s);
459
+ //o.sections = Object.fromEntries(Array.from({length: o.nsects}, (_,i)=>new sect(s)).map(s => [s.sectname, s]));
460
+ }
461
+ return o;
462
+ }
463
+ };
464
+ }
465
+ const fvmlib = {
466
+ name: str,
467
+ minor_version: xint32,
468
+ header_addr: xint32, // library's header address
469
+ };
470
+ const dylib = {
471
+ name: str,
472
+ timestamp: uint32,
473
+ current_version: version,
474
+ compatibility_version: version,
475
+ };
476
+ const thread_command = {
477
+ // uint32 flavor flavor of thread state
478
+ // uint32 count count of longs in thread state
479
+ // struct XXX_thread_state state thread state for this flavor
480
+ // ...
481
+ };
482
+ // SYMTAB
483
+ const nlist_flags = binary.BitFields({
484
+ ext: 1,
485
+ type: [3, binary.Enum({
486
+ UNDF: 0,
487
+ ABS: 1,
488
+ INDR: 5,
489
+ PBUD: 6,
490
+ SECT: 7, // defined in section number n_sect
491
+ })],
492
+ pext: 1,
493
+ stab: [3, binary.Enum({})],
494
+ });
495
+ /*
496
+ //masks
497
+ //STAB = 0xe0, // if any of these bits set, a symbolic debugging entry
498
+ PEXT = 0x10, // private external symbol bit
499
+ //TYPE = 0x0e, // mask for the type bits
500
+ EXT = 0x01, // external symbol bit, set for external symbols
501
+
502
+ UNDF = 0x00, // undefined, n_sect == NO_SECT
503
+ ABS = 0x02, // absolute, n_sect == NO_SECT
504
+ INDR = 0x0a, // indirect
505
+ PBUD = 0x0c, // prebound undefined (defined in a dylib)
506
+ SECT = 0x0e, // defined in section number n_sect
507
+ // STAB values
508
+ GSYM = 0x20, // global symbol: name,,NO_SECT,type,0
509
+ FNAME = 0x22, // procedure name (f77 kludge): name,,NO_SECT,0,0
510
+ FUN = 0x24, // procedure: name,,n_sect,linenumber,address
511
+ STSYM = 0x26, // static symbol: name,,n_sect,type,address
512
+ LCSYM = 0x28, // .lcomm symbol: name,,n_sect,type,address
513
+ BNSYM = 0x2e, // begin nsect sym: 0,,n_sect,0,address
514
+ OPT = 0x3c, // emitted with gcc2_compiled and in gcc source
515
+ RSYM = 0x40, // register sym: name,,NO_SECT,type,register
516
+ SLINE = 0x44, // src line: 0,,n_sect,linenumber,address
517
+ ENSYM = 0x4e, // end nsect sym: 0,,n_sect,0,address
518
+ SSYM = 0x60, // structure elt: name,,NO_SECT,type,struct_offset
519
+ SO = 0x64, // source file name: name,,n_sect,0,address
520
+ OSO = 0x66, // object file name: name,,0,0,st_mtime
521
+ LSYM = 0x80, // local sym: name,,NO_SECT,type,offset
522
+ BINCL = 0x82, // include file beginning: name,,NO_SECT,0,sum
523
+ SOL = 0x84, // #included file name: name,,n_sect,0,address
524
+ PARAMS = 0x86, // compiler parameters: name,,NO_SECT,0,0
525
+ VERSION = 0x88, // compiler version: name,,NO_SECT,0,0
526
+ OLEVEL = 0x8A, // compiler -O level: name,,NO_SECT,0,0
527
+ PSYM = 0xa0, // parameter: name,,NO_SECT,type,offset
528
+ EINCL = 0xa2, // include file end: name,,NO_SECT,0,0
529
+ ENTRY = 0xa4, // alternate entry: name,,n_sect,linenumber,address
530
+ LBRAC = 0xc0, // left bracket: 0,,NO_SECT,nesting level,address
531
+ EXCL = 0xc2, // deleted include file: name,,NO_SECT,0,sum
532
+ RBRAC = 0xe0, // right bracket: 0,,NO_SECT,nesting level,address
533
+ BCOMM = 0xe2, // begin common: name,,NO_SECT,0,0
534
+ ECOMM = 0xe4, // end common: name,,n_sect,0,0
535
+ ECOML = 0xe8, // end common (local name): 0,,n_sect,0,address
536
+ LENG = 0xfe, // second stab entry with length information
537
+ }
538
+ */
539
+ const nlist_desc = binary.BitFields({
540
+ ref: [3, binary.Enum({
541
+ UNDEFINED_NON_LAZY: 0,
542
+ UNDEFINED_LAZY: 1,
543
+ DEFINED: 2,
544
+ PRIVATE_DEFINED: 3,
545
+ PRIVATE_UNDEFINED_NON_LAZY: 4,
546
+ PRIVATE_UNDEFINED_LAZY: 5,
547
+ })],
548
+ flags: [5, binary.Flags({
549
+ ARM_THUMB_DEF: 1 << 0,
550
+ REF_DYNAMIC: 1 << 1,
551
+ NO_DEAD_STRIP: 1 << 2,
552
+ //DESC_DISCARDE: 1 << 2, // symbol is discarded
553
+ WEAK_REF: 1 << 3,
554
+ WEAK_DEF: 1 << 4, // coalesed symbol is a weak definition
555
+ //REF_TO_WEA 1 << 4, // reference to a weak symbol
556
+ //SYMBOL_RESOLVER: 0x0100,
557
+ }, true)],
558
+ align: 8
559
+ //MAX_LIBRARY_ORDINAL = 0xfd << 8,
560
+ //DYNAMIC_LOOKUP_ORDINAL = 0xfe << 8,
561
+ //EXECUTABLE_ORDINAL = 0xff << 8,
562
+ });
563
+ function nlist(bits) {
564
+ return {
565
+ strx: uint32,
566
+ flags: binary.as(binary.UINT8, nlist_flags),
567
+ sect: binary.UINT8,
568
+ desc: binary.as(uint16, nlist_desc),
569
+ value: binary.UINT(bits),
570
+ //const char *name(const char *s) const { return s ? s + strx : ""; }
571
+ //FLAGS type() const { return FLAGS(flags & TYPE); }
572
+ //FLAGS stab() const { return FLAGS(flags & STAB); }
573
+ };
574
+ }
575
+ const symtab = {
576
+ get(s) {
577
+ const sym = binary.read(s, count_table(nlist(64)));
578
+ const str = binary.read(s, blob);
579
+ return sym?.map(v => [binary.utils.decodeTextTo0(str.subarray(v.strx), 'utf8'), v]);
580
+ }
581
+ };
582
+ // DYSYMTAB
583
+ const INDIRECT = {
584
+ INDIRECT_SYMBOL_LOCAL: 0x80000000,
585
+ INDIRECT_SYMBOL_ABS: 0x40000000,
586
+ };
587
+ const toc_entry = {
588
+ symbol_index: uint32,
589
+ module_index: uint32, // index into the module table this symbol is defined in
590
+ };
591
+ function module(bits) {
592
+ const fields = {
593
+ module_name: uint32,
594
+ extdefsym: index_table,
595
+ refsym: index_table,
596
+ localsym: index_table,
597
+ extrel: index_table,
598
+ init_iterm: index_table, // low 16 bits are the index into the init section, high 16 bits are the index into the term section
599
+ };
600
+ return bits == 32 ? { ...fields,
601
+ objc_module_info_addr: uint32,
602
+ objc_module_info_size: uint32, // for this module size of the (__OBJC,__module_info) section
603
+ } : { ...fields,
604
+ objc_module_info_size: uint32,
605
+ objc_module_info_addr: uint64, // for this module address of the start of the (__OBJC, __module_info) section
606
+ };
607
+ }
608
+ const symbol_ref = binary.as(uint32, binary.BitFields({
609
+ symbol_index: 24,
610
+ flags: 8
611
+ }));
612
+ const hint = binary.as(uint32, binary.BitFields({
613
+ sub_image: 8,
614
+ toc: 24 // index into the table of contents
615
+ }));
616
+ const version_min = {
617
+ version,
618
+ reserved: uint32, // zero
619
+ };
620
+ const REBASE = binary.BitFields({
621
+ immediate: 4,
622
+ opcode: [4, binary.Enum({
623
+ DONE: 0,
624
+ SET_TYPE_IMM: 1,
625
+ SET_SEGMENT_AND_OFFSET_ULEB: 2,
626
+ ADD_ADDR_ULEB: 3,
627
+ ADD_ADDR_IMM_SCALED: 4,
628
+ DO_REBASE_IMM_TIMES: 5,
629
+ DO_REBASE_ULEB_TIMES: 6,
630
+ DO_REBASE_ADD_ADDR_ULEB: 7,
631
+ DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: 8,
632
+ })]
633
+ //TYPE_POINTER = 1,
634
+ //TYPE_TEXT_ABSOLUTE32 = 2,
635
+ //TYPE_TEXT_PCREL32 = 3,
636
+ });
637
+ const BIND = binary.BitFields({
638
+ immediate: 4,
639
+ opcode: [4, binary.Enum({
640
+ DONE: 0,
641
+ SET_DYLIB_ORDINAL_IMM: 1,
642
+ SET_DYLIB_ORDINAL_ULEB: 2,
643
+ SET_DYLIB_SPECIAL_IMM: 3,
644
+ SET_SYMBOL_TRAILING_FLAGS_IMM: 4,
645
+ SET_TYPE_IMM: 5,
646
+ SET_ADDEND_SLEB: 6,
647
+ SET_SEGMENT_AND_OFFSET_ULEB: 7,
648
+ ADD_ADDR_ULEB: 8,
649
+ DO_BIND: 9,
650
+ DO_BIND_ADD_ADDR_ULEB: 10,
651
+ DO_BIND_ADD_ADDR_IMM_SCALED: 11,
652
+ DO_BIND_ULEB_TIMES_SKIPPING_ULEB: 12,
653
+ })]
654
+ //TYPE_POINTER = 1,
655
+ //TYPE_TEXT_ABSOLUTE32 = 2,
656
+ //TYPE_TEXT_PCREL32 = 3,
657
+ //SPECIAL_DYLIB_SELF = 0,
658
+ //SPECIAL_DYLIB_MAIN_EXECUTABLE = -1,
659
+ //SPECIAL_DYLIB_FLAT_LOOKUP = -2,
660
+ //SYMBOL_FLAGS_WEAK_IMPORT = 0x1,
661
+ //SYMBOL_FLAGS_NON_WEAK_DEFINITION = 0x8,
662
+ });
663
+ const dyld_kind = {
664
+ KIND_MASK: 0x03,
665
+ KIND_REGULAR: 0x00,
666
+ KIND_THREAD_LOCAL: 0x01,
667
+ KIND_ABSOLUTE: 0x02,
668
+ WEAK_DEFINITION: 0x04,
669
+ REEXPORT: 0x08,
670
+ STUB_AND_RESOLVER: 0x10,
671
+ };
672
+ const dyldinfo = {
673
+ rebase: blob,
674
+ bind: blob,
675
+ weak_bind: blob,
676
+ lazy_bind: blob,
677
+ exprt: blob,
678
+ };
679
+ //BUILD_VERSION
680
+ const TOOL = {
681
+ CLANG: 1,
682
+ SWIFT: 2,
683
+ LD: 3,
684
+ LLD: 4,
685
+ };
686
+ const PLATFORM = {
687
+ MACOS: 1,
688
+ IOS: 2,
689
+ TVOS: 3,
690
+ WATCHOS: 4,
691
+ BRIDGEOS: 5,
692
+ MACCATALYST: 6,
693
+ IOSSIMULATOR: 7,
694
+ TVOSSIMULATOR: 8,
695
+ WATCHOSSIMULATOR: 9,
696
+ DRIVERKIT: 10,
697
+ };
698
+ //DYLD_CHAINED_FIXUPS
699
+ const dyld_chained_starts_in_segment = {
700
+ size: uint32,
701
+ page_size: uint16,
702
+ pointer_format: binary.asEnum(uint16, {
703
+ ARM64E: 1,
704
+ '64': 2,
705
+ '32': 3,
706
+ '32_CACHE': 4,
707
+ '32_FIRMWARE': 5,
708
+ '64_OFFSET': 6,
709
+ ARM64E_KERNEL: 7,
710
+ '64_KERNEL_CACHE': 8,
711
+ ARM64E_USERLAND: 9,
712
+ ARM64E_FIRMWARE: 10,
713
+ X86_64_KERNEL_CACHE: 11,
714
+ ARM64E_USERLAND24: 12,
715
+ }),
716
+ segment_offset: xint64,
717
+ max_valid_pointer: xint32,
718
+ pages: binary.ArrayType(uint16, binary.asEnum(uint16, {
719
+ NONE: 0xFFFF,
720
+ MULTI: 0x8000,
721
+ LAST: 0x8000, // last chain_start for a given page
722
+ }))
723
+ };
724
+ const dyld_chained_starts_in_image = binary.ArrayType(uint32, binary.OffsetType(uint32, dyld_chained_starts_in_segment));
725
+ const dyld_chained_import = binary.as(uint32, binary.BitFields({
726
+ lib_ordinal: 8,
727
+ weak_import: 1,
728
+ name_offset: 23,
729
+ }));
730
+ const dyld_chained_import_addend = {
731
+ import: dyld_chained_import,
732
+ addend: int32,
733
+ };
734
+ const dyld_chained_import_addend64 = {
735
+ import: binary.as(uint64, binary.BitFields({
736
+ lib_ordinal: 16,
737
+ weak_import: 1,
738
+ reserved: 15,
739
+ name_offset: 32,
740
+ })),
741
+ addend: uint64,
742
+ };
743
+ class dyld_chained_fixups extends binary.ReadStruct({
744
+ fixups_version: uint32,
745
+ starts: binary.OffsetType(uint32, dyld_chained_starts_in_image),
746
+ imports: binary.OffsetType(uint32, binary.Remainder),
747
+ symbols: binary.OffsetType(uint32, binary.Remainder),
748
+ imports_count: uint32,
749
+ imports_format: binary.asEnum(uint32, {
750
+ IMPORT: 1,
751
+ IMPORT_ADDEND: 2,
752
+ IMPORT_ADDEND64: 3
753
+ }),
754
+ symbols_format: binary.asEnum(uint32, {
755
+ UNCOMPRESSED: 0,
756
+ ZLIB: 1,
757
+ }),
758
+ }) {
759
+ constructor(s) {
760
+ super(s);
761
+ const imports = new binary.stream_endian(this.imports, s.be);
762
+ switch (this.imports_format) {
763
+ case 'IMPORT':
764
+ this.imports = binary.withNames(binary.readn(imports, dyld_chained_import, this.imports_count), imp => binary.utils.decodeTextTo0(this.symbols.subarray(imp.name_offset)));
765
+ break;
766
+ case 'IMPORT_ADDEND':
767
+ this.imports = binary.withNames(binary.readn(imports, dyld_chained_import_addend, this.imports_count), imp => binary.utils.decodeTextTo0(this.symbols.subarray(imp.import.name_offset)));
768
+ break;
769
+ case 'IMPORT_ADDEND64':
770
+ this.imports = binary.withNames(binary.readn(imports, dyld_chained_import_addend64, this.imports_count), imp => binary.utils.decodeTextTo0(this.symbols.subarray(imp.import.name_offset)));
771
+ break;
772
+ }
773
+ }
774
+ }
775
+ const dyld_chained_ptr_64_bind = binary.as(uint64, binary.BitFields({
776
+ ordinal: 24,
777
+ addend: 8,
778
+ reserved: 19,
779
+ next: 12,
780
+ bind: 1, // set to 1
781
+ }));
782
+ const dyld_chained_ptr_64_rebase = binary.as(uint64, binary.BitFields({
783
+ target: 36,
784
+ high8: 8,
785
+ reserved: 7,
786
+ next: 12,
787
+ bind: 1, // set to 0
788
+ }));
789
+ //DATA_IN_CODE
790
+ const data_in_code_entry = {
791
+ offset: xint32,
792
+ length: uint16,
793
+ kind: binary.as(uint16, binary.Enum({
794
+ DATA: 0x0001,
795
+ JUMP_TABLE8: 0x0002,
796
+ JUMP_TABLE16: 0x0003,
797
+ JUMP_TABLE32: 0x0004,
798
+ ABS_JUMP_TABLE32: 0x0005,
799
+ })),
800
+ };
801
+ // Sections of type S_THREAD_LOCAL_VARIABLES contain an array of tlv_descriptor structures.
802
+ /*
803
+ const tlv_descriptor = {
804
+ void* (*thunk)(tlv_descriptor*);
805
+ unsigned long key;
806
+ unsigned long offset;
807
+ };
808
+ */
809
+ function routines(bits) {
810
+ const type = binary.UINT(bits);
811
+ return {
812
+ init_address: type,
813
+ init_module: type,
814
+ reserved1: type,
815
+ reserved2: type,
816
+ reserved3: type,
817
+ reserved4: type,
818
+ reserved5: type,
819
+ reserved6: type,
820
+ };
821
+ }
822
+ //const cmd_table : {[K in CMD]?: binary.TypeReader2} = {
823
+ const cmd_table = {
824
+ //const cmd_table = {
825
+ [exports.CMD.SEGMENT]: segment(32),
826
+ [exports.CMD.SEGMENT_64]: segment(64),
827
+ [exports.CMD.LOADFVMLIB]: fvmlib,
828
+ [exports.CMD.IDFVMLIB]: fvmlib,
829
+ [exports.CMD.LOAD_DYLIB]: dylib,
830
+ [exports.CMD.ID_DYLIB]: dylib,
831
+ [exports.CMD.LOAD_WEAK_DYLIB]: dylib,
832
+ [exports.CMD.REEXPORT_DYLIB]: dylib,
833
+ [exports.CMD.LAZY_LOAD_DYLIB]: dylib,
834
+ [exports.CMD.LOAD_UPWARD_DYLIB]: dylib,
835
+ [exports.CMD.SUB_FRAMEWORK]: str,
836
+ [exports.CMD.SUB_UMBRELLA]: str,
837
+ [exports.CMD.SUB_CLIENT]: str,
838
+ [exports.CMD.SUB_LIBRARY]: str,
839
+ [exports.CMD.LOAD_DYLINKER]: str,
840
+ [exports.CMD.ID_DYLINKER]: str,
841
+ [exports.CMD.DYLD_ENVIRONMENT]: str,
842
+ [exports.CMD.RPATH]: str,
843
+ [exports.CMD.PREBOUND_DYLIB]: {
844
+ name: str,
845
+ nmodules: uint32,
846
+ linked_modules: str,
847
+ },
848
+ [exports.CMD.THREAD]: thread_command,
849
+ [exports.CMD.UNIXTHREAD]: thread_command,
850
+ [exports.CMD.ROUTINES]: routines(32),
851
+ [exports.CMD.ROUTINES_64]: routines(64),
852
+ [exports.CMD.SYMTAB]: symtab,
853
+ [exports.CMD.TWOLEVEL_HINTS]: count_table(hint),
854
+ [exports.CMD.PREBIND_CKSUM]: {
855
+ cksum: uint32,
856
+ },
857
+ [exports.CMD.UUID]: {
858
+ uuid: binary.Buffer(16),
859
+ },
860
+ [exports.CMD.CODE_SIGNATURE]: blob,
861
+ [exports.CMD.SEGMENT_SPLIT_INFO]: blob,
862
+ [exports.CMD.FUNCTION_STARTS]: blobT(binary.RemainingArrayType(binary.ULEB128)),
863
+ [exports.CMD.DATA_IN_CODE]: blobT(binary.RemainingArrayType(data_in_code_entry)),
864
+ [exports.CMD.DYLIB_CODE_SIGN_DRS]: blob,
865
+ [exports.CMD.LINKER_OPTIMIZATION_HINT]: blob,
866
+ [exports.CMD.DYLD_EXPORTS_TRIE]: blob,
867
+ [exports.CMD.DYLD_CHAINED_FIXUPS]: blob,
868
+ [exports.CMD.ENCRYPTION_INFO]: {
869
+ cryptoff: uint32,
870
+ cryptsize: uint32,
871
+ cryptid: uint32, // which enryption system, 0 means not-encrypted yet
872
+ },
873
+ [exports.CMD.ENCRYPTION_INFO_64]: {
874
+ cryptoff: uint32,
875
+ cryptsize: uint32,
876
+ cryptid: uint32,
877
+ pad: uint32, // must be zero
878
+ },
879
+ [exports.CMD.VERSION_MIN_MACOSX]: version_min,
880
+ [exports.CMD.VERSION_MIN_IPHONEOS]: version_min,
881
+ [exports.CMD.VERSION_MIN_TVOS]: version_min,
882
+ [exports.CMD.VERSION_MIN_WATCHOS]: version_min,
883
+ [exports.CMD.DYLD_INFO]: dyldinfo,
884
+ [exports.CMD.DYLD_INFO_ONLY]: dyldinfo,
885
+ [exports.CMD.SYMSEG]: blob,
886
+ [exports.CMD.IDENT]: {},
887
+ [exports.CMD.FVMFILE]: {
888
+ name: str,
889
+ header_addr: uint32,
890
+ },
891
+ [exports.CMD.MAIN]: {
892
+ entryoff: uint32,
893
+ stacksize: uint32, // if not zero, initialize stack size
894
+ },
895
+ [exports.CMD.SOURCE_VERSION]: {
896
+ version: binary.as(binary.UINT64_BE, binary.BitFields({ a: 24, b: 10, c: 10, d: 10, e: 10 })) // A.B.C.D.E packed as a24.b10.c10.d10.e10
897
+ },
898
+ [exports.CMD.BUILD_VERSION]: {
899
+ platform: binary.asEnum(uint32, PLATFORM),
900
+ minos: version,
901
+ sdk: version,
902
+ tools: binary.objectWithNames(binary.ArrayType(uint32, { tool: binary.as(uint32, binary.Enum(TOOL)), version }), binary.field('tool')),
903
+ },
904
+ [exports.CMD.LINKER_OPTION]: {
905
+ count: uint32, // number of strings following
906
+ },
907
+ [exports.CMD.NOTE]: {
908
+ data_owner: fixed_string16,
909
+ data: blob
910
+ },
911
+ [exports.CMD.PREPAGE]: {},
912
+ [exports.CMD.DYSYMTAB]: {
913
+ localsym: index_table,
914
+ extdefsym: index_table,
915
+ undefsym: index_table,
916
+ toc: count_table(toc_entry),
917
+ modtab: count_table(module(64)),
918
+ extrefsym: count_table(symbol_ref),
919
+ indirectsym: count_table(symbol_ref),
920
+ extrel: count_table({ address: uint32, symbol_ref }),
921
+ locrel: count_table({ address: uint32, symbol_ref }), // local relocation entries
922
+ },
923
+ };
924
+ class MachFile {
925
+ header;
926
+ commands = [];
927
+ ready;
928
+ static check(data) {
929
+ switch (binary.UINT32_BE.get(new binary.stream(data))) {
930
+ case 0xfeedface:
931
+ case 0xcefaedfe:
932
+ case 0xfeedfacf:
933
+ case 0xcffaedfe:
934
+ return true;
935
+ default:
936
+ return false;
937
+ }
938
+ }
939
+ constructor(data, mem) {
940
+ const magic = binary.UINT32_LE.get(new binary.stream(data));
941
+ switch (magic) {
942
+ case 0xfeedface:
943
+ this.ready = this.load(data, false, 32, mem);
944
+ break;
945
+ case 0xcefaedfe:
946
+ this.ready = this.load(data, true, 32, mem);
947
+ break;
948
+ case 0xfeedfacf:
949
+ this.ready = this.load(data, false, 64, mem);
950
+ break;
951
+ case 0xcffaedfe:
952
+ this.ready = this.load(data, true, 64, mem);
953
+ break;
954
+ default: throw new Error('not a mach file');
955
+ }
956
+ }
957
+ async load(data, be, bits, mem) {
958
+ const file = new binary.stream_endian(data, be);
959
+ const h = binary.read(file, header);
960
+ const cpu = CPU_TYPE[h.cputype];
961
+ h.cpusubtype = binary.Enum(CPU_SUBTYPES[cpu])(+h.cpusubtype);
962
+ if (bits === 64)
963
+ file.skip(4);
964
+ for (let i = 0; i < h.ncmds; ++i) {
965
+ const cmd = binary.read(file, command);
966
+ const file2 = new mach_stream(data, file.read_buffer(cmd.cmdsize - 8), file.be, mem);
967
+ const result = await binary.read(file2, cmd_table[cmd.cmd] ?? {});
968
+ this.commands.push({ cmd: cmd.cmd, data: result });
969
+ }
970
+ this.header = h;
971
+ const funcs = this.getCommandT(exports.CMD.FUNCTION_STARTS);
972
+ if (funcs) {
973
+ const array = funcs.contents;
974
+ const text = await this.getSegment('__TEXT');
975
+ let acc = BigInt(text?.vmaddr ?? 0);
976
+ for (const i in array)
977
+ array[i] = (acc += BigInt(array[i]));
978
+ }
979
+ }
980
+ getCommand(cmd) {
981
+ for (const i of this.commands) {
982
+ if (i.cmd === cmd)
983
+ return i.data;
984
+ }
985
+ }
986
+ getCommandT(cmd) {
987
+ const c = this.getCommand(cmd);
988
+ return c;
989
+ }
990
+ getSegment(name) {
991
+ for (const i of this.commands) {
992
+ if ((i.cmd === exports.CMD.SEGMENT || i.cmd === exports.CMD.SEGMENT_64) && i.data.segname === name)
993
+ return i.data;
994
+ }
995
+ }
996
+ }
997
+ exports.MachFile = MachFile;
998
+ const FAT_MAGIC = 0xcafebabe;
999
+ const FAT_CIGAM = 0xbebafeca;
1000
+ class FATMachFile {
1001
+ archs = [];
1002
+ static check(data) {
1003
+ switch (binary.UINT32_BE.get(new binary.stream(data))) {
1004
+ case FAT_MAGIC:
1005
+ case FAT_CIGAM:
1006
+ return true;
1007
+ default:
1008
+ return false;
1009
+ }
1010
+ }
1011
+ constructor(data, mem) {
1012
+ switch (binary.UINT32_BE.get(new binary.stream(data))) {
1013
+ case FAT_MAGIC:
1014
+ this.load(new binary.stream_endian(data, false), mem);
1015
+ break;
1016
+ case FAT_CIGAM:
1017
+ this.load(new binary.stream_endian(data, true), mem);
1018
+ break;
1019
+ default:
1020
+ throw new Error('not a fat mach file');
1021
+ }
1022
+ }
1023
+ load(file, mem) {
1024
+ const header = binary.read(file, fat_header);
1025
+ this.archs = header.archs;
1026
+ for (const arch of header.archs) {
1027
+ const cpu = CPU_TYPE[arch.cputype];
1028
+ const data = file.buffer_at(arch.offset, arch.size);
1029
+ arch.cpusubtype = binary.Enum(CPU_SUBTYPES[cpu])(+arch.cpusubtype);
1030
+ arch.contents = new MachFile(data);
1031
+ }
1032
+ }
1033
+ }
1034
+ exports.FATMachFile = FATMachFile;