@isopodlabs/binary_libs 0.0.1 → 0.1.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/.gitmodules +3 -0
- package/.vscode/launch.json +16 -0
- package/.vscode/settings.json +3 -0
- package/README.md +152 -44
- package/eslint.config.mjs +32 -0
- package/package.json +9 -2
- package/src/CompoundDocument.ts +5 -5
- package/src/arch.ts +16 -13
- package/src/clr.ts +53 -58
- package/src/elf.ts +544 -545
- package/src/mach.ts +172 -121
- package/src/pe.ts +209 -213
- package/transform.ts +369 -0
- package/tsconfig.json +10 -3
- package/tsconfig.tsbuildinfo +1 -0
- package/dist/CompoundDocument.d.ts +0 -129
- package/dist/CompoundDocument.js +0 -301
- package/dist/arch.d.ts +0 -41
- package/dist/arch.js +0 -94
- package/dist/binary.d.ts +0 -397
- package/dist/binary.js +0 -802
- package/dist/binary_helpers.d.ts +0 -69
- package/dist/binary_helpers.js +0 -328
- package/dist/clr.d.ts +0 -63
- package/dist/clr.js +0 -664
- package/dist/elf.d.ts +0 -11
- package/dist/elf.js +0 -791
- package/dist/mach.d.ts +0 -543
- package/dist/mach.js +0 -1034
- package/dist/pe.d.ts +0 -399
- package/dist/pe.js +0 -489
package/src/mach.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as binary from '@isopodlabs/binary';
|
|
2
2
|
|
|
3
|
-
class mach_stream extends binary.
|
|
4
|
-
constructor(public base: Uint8Array, data: Uint8Array, be: boolean, public mem?: binary.
|
|
3
|
+
class mach_stream extends binary.endianStream {
|
|
4
|
+
constructor(public base: Uint8Array, data: Uint8Array, be: boolean, public mem?: binary.memory) { super(data, be); }
|
|
5
5
|
subdata(offset: number, size?: number) {
|
|
6
6
|
return this.base.subarray(offset, size && offset + size);
|
|
7
7
|
}
|
|
@@ -17,8 +17,8 @@ const uint16 = binary.UINT16;
|
|
|
17
17
|
const uint32 = binary.UINT32;
|
|
18
18
|
const uint64 = binary.UINT64;
|
|
19
19
|
const int32 = binary.INT32;
|
|
20
|
-
const xint32 = binary.
|
|
21
|
-
const xint64 = binary.
|
|
20
|
+
const xint32 = binary.asHex(uint32);
|
|
21
|
+
const xint64 = binary.asHex(uint64);
|
|
22
22
|
|
|
23
23
|
const FILETYPE = {
|
|
24
24
|
OBJECT: 1, // Relocatable object file
|
|
@@ -33,7 +33,7 @@ const FILETYPE = {
|
|
|
33
33
|
DSYM: 10, // Companion file with only debug sections
|
|
34
34
|
KEXT_BUNDLE: 11, // x86_64 kexts
|
|
35
35
|
FILESET: 12
|
|
36
|
-
}
|
|
36
|
+
} as const;
|
|
37
37
|
|
|
38
38
|
// Machine types known by all
|
|
39
39
|
enum CPU_TYPE {
|
|
@@ -57,7 +57,7 @@ enum CPU_TYPE {
|
|
|
57
57
|
X86_64 = X86 | ARCH_64,
|
|
58
58
|
POWERPC_64 = POWERPC | ARCH_64,
|
|
59
59
|
ARM_64 = ARM | ARCH_64,
|
|
60
|
-
}
|
|
60
|
+
};
|
|
61
61
|
|
|
62
62
|
const CPU_SUBTYPES: {[K in CPU_TYPE]?: any} = {
|
|
63
63
|
[CPU_TYPE.VAX] : {
|
|
@@ -185,7 +185,7 @@ const CPU_SUBTYPES: {[K in CPU_TYPE]?: any} = {
|
|
|
185
185
|
ARM64_V8: 1,
|
|
186
186
|
ARM64E: 2,
|
|
187
187
|
},
|
|
188
|
-
}
|
|
188
|
+
};
|
|
189
189
|
|
|
190
190
|
// Constants for the flags field of the header
|
|
191
191
|
const HEADER_FLAGS = {
|
|
@@ -214,7 +214,7 @@ const HEADER_FLAGS = {
|
|
|
214
214
|
DEAD_STRIPPABLE_DYLIB: 0x400000, // Only for use on dylibs. When linking against a dylib that has this bit set, the static linker will automatically not create a LC_LOAD_DYLIBload command to the dylib if no symbols are being referenced from the dylib.
|
|
215
215
|
HAS_TLV_DESCRIPTORS: 0x800000, // Contains a section of type S_THREAD_LOCAL_VARIABLES
|
|
216
216
|
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.
|
|
217
|
-
}
|
|
217
|
+
} as const;
|
|
218
218
|
|
|
219
219
|
const header = {
|
|
220
220
|
magic: uint32, // mach magic number identifier
|
|
@@ -241,62 +241,61 @@ const fat_header = {
|
|
|
241
241
|
};
|
|
242
242
|
|
|
243
243
|
const REQ_DYLD = 0x80000000;
|
|
244
|
-
|
|
245
|
-
SEGMENT
|
|
246
|
-
SYMTAB
|
|
247
|
-
SYMSEG
|
|
248
|
-
THREAD
|
|
249
|
-
UNIXTHREAD
|
|
250
|
-
LOADFVMLIB
|
|
251
|
-
IDFVMLIB
|
|
252
|
-
IDENT
|
|
253
|
-
FVMFILE
|
|
254
|
-
PREPAGE
|
|
255
|
-
DYSYMTAB
|
|
256
|
-
LOAD_DYLIB
|
|
257
|
-
ID_DYLIB
|
|
258
|
-
LOAD_DYLINKER
|
|
259
|
-
ID_DYLINKER
|
|
260
|
-
PREBOUND_DYLIB
|
|
261
|
-
ROUTINES
|
|
262
|
-
SUB_FRAMEWORK
|
|
263
|
-
SUB_UMBRELLA
|
|
264
|
-
SUB_CLIENT
|
|
265
|
-
SUB_LIBRARY
|
|
266
|
-
TWOLEVEL_HINTS
|
|
267
|
-
PREBIND_CKSUM
|
|
268
|
-
LOAD_WEAK_DYLIB
|
|
269
|
-
SEGMENT_64
|
|
270
|
-
ROUTINES_64
|
|
271
|
-
UUID
|
|
272
|
-
RPATH
|
|
273
|
-
CODE_SIGNATURE
|
|
274
|
-
SEGMENT_SPLIT_INFO
|
|
275
|
-
REEXPORT_DYLIB
|
|
276
|
-
LAZY_LOAD_DYLIB
|
|
277
|
-
ENCRYPTION_INFO
|
|
278
|
-
DYLD_INFO
|
|
279
|
-
DYLD_INFO_ONLY
|
|
280
|
-
LOAD_UPWARD_DYLIB
|
|
281
|
-
VERSION_MIN_MACOSX
|
|
282
|
-
VERSION_MIN_IPHONEOS
|
|
283
|
-
FUNCTION_STARTS
|
|
284
|
-
DYLD_ENVIRONMENT
|
|
285
|
-
MAIN
|
|
286
|
-
DATA_IN_CODE
|
|
287
|
-
SOURCE_VERSION
|
|
288
|
-
DYLIB_CODE_SIGN_DRS
|
|
289
|
-
ENCRYPTION_INFO_64
|
|
290
|
-
LINKER_OPTION
|
|
291
|
-
LINKER_OPTIMIZATION_HINT
|
|
292
|
-
VERSION_MIN_TVOS
|
|
293
|
-
VERSION_MIN_WATCHOS
|
|
294
|
-
NOTE
|
|
295
|
-
BUILD_VERSION
|
|
296
|
-
DYLD_EXPORTS_TRIE
|
|
297
|
-
DYLD_CHAINED_FIXUPS
|
|
298
|
-
}
|
|
299
|
-
export type CMD = typeof CMD[keyof typeof CMD];
|
|
244
|
+
const enum CMD {
|
|
245
|
+
SEGMENT = 0x01, // segment of this file to be mapped
|
|
246
|
+
SYMTAB = 0x02, // link-edit stab symbol table info
|
|
247
|
+
SYMSEG = 0x03, // link-edit gdb symbol table info (obsolete)
|
|
248
|
+
THREAD = 0x04, // thread
|
|
249
|
+
UNIXTHREAD = 0x05, // unix thread (includes a stack)
|
|
250
|
+
LOADFVMLIB = 0x06, // load a specified fixed VM shared library
|
|
251
|
+
IDFVMLIB = 0x07, // fixed VM shared library identification
|
|
252
|
+
// IDENT = 0x08, // object identification info (obsolete)
|
|
253
|
+
FVMFILE = 0x09, // fixed VM file inclusion (internal use)
|
|
254
|
+
// PREPAGE = 0x0a, // prepage command (internal use)
|
|
255
|
+
DYSYMTAB = 0x0b, // dynamic link-edit symbol table info
|
|
256
|
+
LOAD_DYLIB = 0x0c, // load a dynamically linked shared library
|
|
257
|
+
ID_DYLIB = 0x0d, // dynamically linked shared lib ident
|
|
258
|
+
LOAD_DYLINKER = 0x0e, // load a dynamic linker
|
|
259
|
+
ID_DYLINKER = 0x0f, // dynamic linker identification
|
|
260
|
+
PREBOUND_DYLIB = 0x10, // modules prebound for a dynamically linked shared library
|
|
261
|
+
ROUTINES = 0x11, // image routines
|
|
262
|
+
SUB_FRAMEWORK = 0x12, // sub framework
|
|
263
|
+
SUB_UMBRELLA = 0x13, // sub umbrella
|
|
264
|
+
SUB_CLIENT = 0x14, // sub client
|
|
265
|
+
SUB_LIBRARY = 0x15, // sub library
|
|
266
|
+
TWOLEVEL_HINTS = 0x16, // two-level namespace lookup hints
|
|
267
|
+
PREBIND_CKSUM = 0x17, // prebind checksum
|
|
268
|
+
LOAD_WEAK_DYLIB = REQ_DYLD+0x18, // load a dynamically linked shared library that is allowed to be missing (all symbols are weak imported).
|
|
269
|
+
SEGMENT_64 = 0x19, // 64-bit segment of this file to be mapped
|
|
270
|
+
ROUTINES_64 = 0x1a, // 64-bit image routines
|
|
271
|
+
UUID = 0x1b, // the uuid
|
|
272
|
+
RPATH = REQ_DYLD+0x1c, // runpath additions
|
|
273
|
+
CODE_SIGNATURE = 0x1d, // local of code signature
|
|
274
|
+
SEGMENT_SPLIT_INFO = 0x1e, // local of info to split segments
|
|
275
|
+
REEXPORT_DYLIB = REQ_DYLD+0x1f, // load and re-export dylib
|
|
276
|
+
LAZY_LOAD_DYLIB = 0x20, // delay load of dylib until first use
|
|
277
|
+
ENCRYPTION_INFO = 0x21, // encrypted segment information
|
|
278
|
+
DYLD_INFO = 0x22, // compressed dyld information
|
|
279
|
+
DYLD_INFO_ONLY = REQ_DYLD+0x22, // compressed dyld information only
|
|
280
|
+
LOAD_UPWARD_DYLIB = REQ_DYLD+0x23, // load upward dylib
|
|
281
|
+
VERSION_MIN_MACOSX = 0x24, // build for MacOSX min OS version
|
|
282
|
+
VERSION_MIN_IPHONEOS = 0x25, // build for iPhoneOS min OS version
|
|
283
|
+
FUNCTION_STARTS = 0x26, // compressed table of function start addresses
|
|
284
|
+
DYLD_ENVIRONMENT = 0x27, // string for dyld to treat like environment variable
|
|
285
|
+
MAIN = REQ_DYLD+0x28, // replacement for LC_UNIXTHREAD
|
|
286
|
+
DATA_IN_CODE = 0x29, // table of non-instructions in __text
|
|
287
|
+
SOURCE_VERSION = 0x2A, // source version used to build binary
|
|
288
|
+
DYLIB_CODE_SIGN_DRS = 0x2B, // Code signing DRs copied from linked dylibs
|
|
289
|
+
ENCRYPTION_INFO_64 = 0x2C, // 64-bit encrypted segment information
|
|
290
|
+
LINKER_OPTION = 0x2D, // linker options in MH_OBJECT files
|
|
291
|
+
LINKER_OPTIMIZATION_HINT = 0x2E, // optimization hints in MH_OBJECT files
|
|
292
|
+
VERSION_MIN_TVOS = 0x2F, // build for AppleTV min OS version
|
|
293
|
+
VERSION_MIN_WATCHOS = 0x30, // build for Watch min OS version
|
|
294
|
+
NOTE = 0x31, // arbitrary data included within a Mach-O file
|
|
295
|
+
BUILD_VERSION = 0x32, // build for platform min OS version
|
|
296
|
+
DYLD_EXPORTS_TRIE = REQ_DYLD+0x33, // used with linkedit_data_command, payload is trie
|
|
297
|
+
DYLD_CHAINED_FIXUPS = REQ_DYLD+0x34, // used with linkedit_data_command
|
|
298
|
+
};
|
|
300
299
|
|
|
301
300
|
const str = {
|
|
302
301
|
get(s: binary.stream) {
|
|
@@ -308,7 +307,7 @@ const str = {
|
|
|
308
307
|
const index_table = {
|
|
309
308
|
first: uint32,
|
|
310
309
|
count: uint32,
|
|
311
|
-
}
|
|
310
|
+
};
|
|
312
311
|
|
|
313
312
|
const blob = {
|
|
314
313
|
get(s: mach_stream) {
|
|
@@ -327,11 +326,16 @@ function blobT<T extends binary.TypeReader>(type: T) {
|
|
|
327
326
|
return {
|
|
328
327
|
data: s.subdata(offset, size),
|
|
329
328
|
contents: binary.read(s.substream(offset, size), type)
|
|
330
|
-
}
|
|
329
|
+
};
|
|
331
330
|
}
|
|
332
331
|
};
|
|
333
332
|
}
|
|
334
333
|
|
|
334
|
+
function blobArray<T extends binary.Type>(type: T) {
|
|
335
|
+
return blobT(binary.RemainingArrayType(type));
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
|
|
335
339
|
function count_table<T extends binary.TypeReader>(type: T) {
|
|
336
340
|
return {
|
|
337
341
|
get(s: mach_stream) {
|
|
@@ -347,9 +351,9 @@ const fixed_string16 = binary.StringType(16);
|
|
|
347
351
|
const version = binary.asFlags(uint32, {major: 0xffff0000, minor: 0xff00, patch: 0xff}, false);
|
|
348
352
|
|
|
349
353
|
const command = {
|
|
350
|
-
cmd: binary.as(uint32,
|
|
354
|
+
cmd: binary.as(uint32, v => v as CMD),
|
|
351
355
|
cmdsize: uint32,
|
|
352
|
-
}
|
|
356
|
+
};
|
|
353
357
|
|
|
354
358
|
const SECTION_FLAGS = binary.BitFields({
|
|
355
359
|
TYPE: [8, binary.Enum({
|
|
@@ -398,7 +402,7 @@ const SECTION_FLAGS = binary.BitFields({
|
|
|
398
402
|
function section(bits: 32|64) {
|
|
399
403
|
const type = binary.UINT(bits);
|
|
400
404
|
|
|
401
|
-
class Section extends binary.
|
|
405
|
+
class Section extends binary.Class({
|
|
402
406
|
//data: binary.DontRead<binary.utils.MappedMemory>(),
|
|
403
407
|
sectname: fixed_string16,
|
|
404
408
|
segname: fixed_string16,
|
|
@@ -413,14 +417,14 @@ function section(bits: 32|64) {
|
|
|
413
417
|
reserved2: uint32, // reserved (for count or sizeof)
|
|
414
418
|
_: binary.AlignType(bits / 8)
|
|
415
419
|
}) {
|
|
416
|
-
data: Promise<binary.
|
|
420
|
+
data: Promise<binary.MappedMemory>;
|
|
417
421
|
constructor(s: mach_stream) {
|
|
418
422
|
super(s);
|
|
419
|
-
const prot = this.flags.ATTRIBUTES.SYS.SOME_INSTRUCTIONS ? binary.
|
|
420
|
-
this.data = (async () =>
|
|
421
|
-
//
|
|
422
|
-
|
|
423
|
-
|
|
423
|
+
const prot = this.flags.ATTRIBUTES.SYS.SOME_INSTRUCTIONS ? binary.MEM.EXECUTE : binary.MEM.NONE;
|
|
424
|
+
this.data = (async () =>
|
|
425
|
+
//new binary.utils.MappedMemory(await s.file.get(BigInt(this.addr), Number(this.size)), Number(this.addr), prot)
|
|
426
|
+
new binary.MappedMemory(s.subdata(+this.offset, Number(this.size)), Number(this.addr), prot)
|
|
427
|
+
)();
|
|
424
428
|
}
|
|
425
429
|
}
|
|
426
430
|
return Section;
|
|
@@ -431,12 +435,12 @@ const SEGMENT_FLAGS = {
|
|
|
431
435
|
FVMLIB: 0x2, // this segment is the VM that is allocated by a fixed VM library, for overlap checking in the link editor
|
|
432
436
|
NORELOC: 0x4, // this segment has nothing that was relocated in it and nothing relocated to it, that is it maybe safely replaced without relocation
|
|
433
437
|
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.
|
|
434
|
-
}
|
|
438
|
+
};
|
|
435
439
|
|
|
436
|
-
function segment(bits:
|
|
440
|
+
function segment<T extends 32|64>(bits: T) {
|
|
437
441
|
const type = binary.UINT(bits);
|
|
438
442
|
const fields = {
|
|
439
|
-
data: binary.DontRead<binary.
|
|
443
|
+
data: binary.DontRead<binary.MappedMemory>(),
|
|
440
444
|
segname: fixed_string16, // segment name
|
|
441
445
|
vmaddr: type, // memory address of this segment
|
|
442
446
|
vmsize: type, // memory size of this segment
|
|
@@ -449,21 +453,62 @@ function segment(bits: 32|64) {
|
|
|
449
453
|
sections: binary.DontRead<Record<string, any>>(),//binary.ReadType<typeof section(bits)>)),
|
|
450
454
|
};
|
|
451
455
|
return {
|
|
452
|
-
|
|
456
|
+
get(s: mach_stream) {
|
|
453
457
|
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
458
|
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
o.
|
|
460
|
-
|
|
459
|
+
async function load() {
|
|
460
|
+
const data = await s.getmem(BigInt(Number(o.vmaddr)), Number(o.filesize)) ?? s.subdata(Number(o.fileoff), Number(o.filesize));
|
|
461
|
+
o.data = new binary.MappedMemory(data, Number(o.vmaddr), o.initprot);
|
|
462
|
+
|
|
463
|
+
//const sect = section(bits);
|
|
464
|
+
if (o.nsects) {
|
|
465
|
+
o.sections = binary.objectWithNames(binary.ArrayType(o.nsects, section(bits)), binary.field('sectname')).get(s);
|
|
466
|
+
//o.sections = Object.fromEntries(Array.from({length: o.nsects}, (_,i)=>new sect(s)).map(s => [s.sectname, s]));
|
|
467
|
+
}
|
|
461
468
|
}
|
|
469
|
+
|
|
470
|
+
load();
|
|
462
471
|
return o;
|
|
463
472
|
}
|
|
464
473
|
};
|
|
465
474
|
}
|
|
466
475
|
|
|
476
|
+
/*
|
|
477
|
+
function segment(bits: 32|64) {
|
|
478
|
+
const type = binary.UINT(bits);
|
|
479
|
+
return class extends binary.ReadWriteStruct({
|
|
480
|
+
segname: fixed_string16, // segment name
|
|
481
|
+
vmaddr: type, // memory address of this segment
|
|
482
|
+
vmsize: type, // memory size of this segment
|
|
483
|
+
fileoff: type, // file offset of this segment
|
|
484
|
+
filesize: type, // amount to map from the file
|
|
485
|
+
maxprot: uint32, // maximum VM protection
|
|
486
|
+
initprot: uint32, // initial VM protection
|
|
487
|
+
nsects: uint32, // number of sections in segment
|
|
488
|
+
flags: binary.as(uint32, binary.Flags(SEGMENT_FLAGS,true)), // flags
|
|
489
|
+
}) {
|
|
490
|
+
data?: binary.MappedMemory;
|
|
491
|
+
sections: Record<string, any> = {};
|
|
492
|
+
|
|
493
|
+
constructor(s: mach_stream) {
|
|
494
|
+
super(s);
|
|
495
|
+
this.load(s);
|
|
496
|
+
}
|
|
497
|
+
async load(s: mach_stream) {
|
|
498
|
+
const data = await s.getmem(BigInt(this.vmaddr), Number(this.filesize)) ?? s.subdata(Number(this.fileoff), Number(this.filesize));
|
|
499
|
+
this.data = new binary.MappedMemory(data, Number(this.vmaddr), this.initprot);
|
|
500
|
+
|
|
501
|
+
//const sect = section(bits);
|
|
502
|
+
if (this.nsects) {
|
|
503
|
+
this.sections = binary.objectWithNames(binary.ArrayType(this.nsects, section(bits)), binary.field('sectname')).get(s);
|
|
504
|
+
//o.sections = Object.fromEntries(Array.from({length: o.nsects}, (_,i)=>new sect(s)).map(s => [s.sectname, s]));
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
}
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
*/
|
|
511
|
+
|
|
467
512
|
const fvmlib = {
|
|
468
513
|
name: str, // library's target pathname
|
|
469
514
|
minor_version: xint32, // library's minor version number
|
|
@@ -478,8 +523,8 @@ const dylib = {
|
|
|
478
523
|
};
|
|
479
524
|
|
|
480
525
|
const thread_command = {
|
|
481
|
-
//
|
|
482
|
-
//
|
|
526
|
+
flavor: uint32, // flavor of thread state
|
|
527
|
+
count: uint32, // count of longs in thread state
|
|
483
528
|
// struct XXX_thread_state state thread state for this flavor
|
|
484
529
|
// ...
|
|
485
530
|
};
|
|
@@ -594,7 +639,7 @@ const symtab = {
|
|
|
594
639
|
const INDIRECT = {
|
|
595
640
|
INDIRECT_SYMBOL_LOCAL: 0x80000000, // non-lazy symbol pointer section for a defined symbol which strip(1) has removed
|
|
596
641
|
INDIRECT_SYMBOL_ABS: 0x40000000,
|
|
597
|
-
}
|
|
642
|
+
} as const;
|
|
598
643
|
|
|
599
644
|
const toc_entry = {
|
|
600
645
|
symbol_index: uint32, // the defined external symbol (index into the symbol table)
|
|
@@ -687,7 +732,7 @@ const dyld_kind = {
|
|
|
687
732
|
WEAK_DEFINITION: 0x04,
|
|
688
733
|
REEXPORT: 0x08,
|
|
689
734
|
STUB_AND_RESOLVER: 0x10,
|
|
690
|
-
}
|
|
735
|
+
} as const;
|
|
691
736
|
|
|
692
737
|
const dyldinfo = {
|
|
693
738
|
rebase: blob,
|
|
@@ -703,7 +748,8 @@ const TOOL = {
|
|
|
703
748
|
SWIFT: 2,
|
|
704
749
|
LD: 3,
|
|
705
750
|
LLD: 4,
|
|
706
|
-
}
|
|
751
|
+
} as const;
|
|
752
|
+
|
|
707
753
|
const PLATFORM = {
|
|
708
754
|
MACOS: 1,
|
|
709
755
|
IOS: 2,
|
|
@@ -715,7 +761,7 @@ const PLATFORM = {
|
|
|
715
761
|
TVOSSIMULATOR: 8,
|
|
716
762
|
WATCHOSSIMULATOR: 9,
|
|
717
763
|
DRIVERKIT: 10,
|
|
718
|
-
}
|
|
764
|
+
} as const;
|
|
719
765
|
|
|
720
766
|
//DYLD_CHAINED_FIXUPS
|
|
721
767
|
|
|
@@ -768,7 +814,7 @@ const dyld_chained_import_addend64 = {
|
|
|
768
814
|
addend: uint64,
|
|
769
815
|
};
|
|
770
816
|
|
|
771
|
-
class dyld_chained_fixups extends binary.
|
|
817
|
+
class dyld_chained_fixups extends binary.ReadClass({
|
|
772
818
|
fixups_version: uint32, // currently 0
|
|
773
819
|
starts: binary.OffsetType(uint32, dyld_chained_starts_in_image),
|
|
774
820
|
imports: binary.OffsetType(uint32, binary.Remainder), // offset of imports table in chain_data
|
|
@@ -784,18 +830,20 @@ class dyld_chained_fixups extends binary.ReadStruct({
|
|
|
784
830
|
ZLIB: 1,
|
|
785
831
|
}),
|
|
786
832
|
}) {
|
|
787
|
-
|
|
833
|
+
imports2;
|
|
834
|
+
constructor(s: binary.endianStream) {
|
|
788
835
|
super(s);
|
|
789
|
-
const imports = new binary.
|
|
836
|
+
const imports = new binary.endianStream(this.imports, s.be);
|
|
790
837
|
switch (this.imports_format) {
|
|
791
|
-
case 'IMPORT':
|
|
792
|
-
this.
|
|
838
|
+
case 'IMPORT': {
|
|
839
|
+
this.imports2 = binary.withNames(binary.readn(imports, dyld_chained_import, this.imports_count), imp => binary.utils.decodeTextTo0(this.symbols.subarray(Number(imp.name_offset))));
|
|
793
840
|
break;
|
|
841
|
+
}
|
|
794
842
|
case 'IMPORT_ADDEND':
|
|
795
|
-
this.
|
|
843
|
+
this.imports2 = binary.withNames(binary.readn(imports, dyld_chained_import_addend, this.imports_count), imp => binary.utils.decodeTextTo0(this.symbols.subarray(Number(imp.import.name_offset))));
|
|
796
844
|
break;
|
|
797
845
|
case 'IMPORT_ADDEND64':
|
|
798
|
-
this.
|
|
846
|
+
this.imports2 = binary.withNames(binary.readn(imports, dyld_chained_import_addend64, this.imports_count), imp => binary.utils.decodeTextTo0(this.symbols.subarray(Number(imp.import.name_offset))));
|
|
799
847
|
break;
|
|
800
848
|
}
|
|
801
849
|
}
|
|
@@ -858,7 +906,6 @@ function routines(bits:32|64) {
|
|
|
858
906
|
|
|
859
907
|
//const cmd_table : {[K in CMD]?: binary.TypeReader2} = {
|
|
860
908
|
const cmd_table = {//: Record<CMD, binary.TypeReader2> = {
|
|
861
|
-
//const cmd_table = {
|
|
862
909
|
[CMD.SEGMENT]: segment(32),
|
|
863
910
|
[CMD.SEGMENT_64]: segment(64),
|
|
864
911
|
[CMD.LOADFVMLIB]: fvmlib,
|
|
@@ -906,8 +953,8 @@ const cmd_table = {//: Record<CMD, binary.TypeReader2> = {
|
|
|
906
953
|
|
|
907
954
|
[CMD.CODE_SIGNATURE]: blob,
|
|
908
955
|
[CMD.SEGMENT_SPLIT_INFO]: blob,
|
|
909
|
-
[CMD.FUNCTION_STARTS]:
|
|
910
|
-
[CMD.DATA_IN_CODE]:
|
|
956
|
+
[CMD.FUNCTION_STARTS]: blobArray(binary.ULEB128),
|
|
957
|
+
[CMD.DATA_IN_CODE]: blobArray(data_in_code_entry),
|
|
911
958
|
[CMD.DYLIB_CODE_SIGN_DRS]: blob,
|
|
912
959
|
[CMD.LINKER_OPTIMIZATION_HINT]: blob,
|
|
913
960
|
[CMD.DYLD_EXPORTS_TRIE]: blob,
|
|
@@ -935,7 +982,7 @@ const cmd_table = {//: Record<CMD, binary.TypeReader2> = {
|
|
|
935
982
|
|
|
936
983
|
[CMD.SYMSEG]: blob,//OBSOLETE
|
|
937
984
|
|
|
938
|
-
[CMD.IDENT]: {},//OBSOLETE
|
|
985
|
+
// [CMD.IDENT]: {},//OBSOLETE
|
|
939
986
|
|
|
940
987
|
[CMD.FVMFILE]: {//OBSOLETE
|
|
941
988
|
name: str,
|
|
@@ -963,7 +1010,7 @@ const cmd_table = {//: Record<CMD, binary.TypeReader2> = {
|
|
|
963
1010
|
data_owner: fixed_string16, // owner name for this LC_NOTE
|
|
964
1011
|
data: blob
|
|
965
1012
|
},
|
|
966
|
-
[CMD.PREPAGE]: {},
|
|
1013
|
+
// [CMD.PREPAGE]: {},
|
|
967
1014
|
[CMD.DYSYMTAB]: {
|
|
968
1015
|
localsym: index_table, // local symbols
|
|
969
1016
|
extdefsym: index_table, // externally defined symbols
|
|
@@ -994,7 +1041,7 @@ export class MachFile {
|
|
|
994
1041
|
}
|
|
995
1042
|
}
|
|
996
1043
|
|
|
997
|
-
constructor(data: Uint8Array, mem?: binary.
|
|
1044
|
+
constructor(data: Uint8Array, mem?: binary.memory) {
|
|
998
1045
|
const magic = binary.UINT32_LE.get(new binary.stream(data));
|
|
999
1046
|
switch (magic) {
|
|
1000
1047
|
case 0xfeedface: this.ready = this.load(data, false, 32, mem); break;
|
|
@@ -1005,8 +1052,8 @@ export class MachFile {
|
|
|
1005
1052
|
}
|
|
1006
1053
|
}
|
|
1007
1054
|
|
|
1008
|
-
async load(data: Uint8Array, be: boolean, bits: 32|64, mem?: binary.
|
|
1009
|
-
const file = new binary.
|
|
1055
|
+
async load(data: Uint8Array, be: boolean, bits: 32|64, mem?: binary.memory) {
|
|
1056
|
+
const file = new binary.endianStream(data, be);
|
|
1010
1057
|
const h = binary.read(file, header);
|
|
1011
1058
|
const cpu = CPU_TYPE[h.cputype as keyof typeof CPU_TYPE];
|
|
1012
1059
|
h.cpusubtype = binary.Enum(CPU_SUBTYPES[cpu])(+h.cpusubtype);
|
|
@@ -1021,7 +1068,7 @@ export class MachFile {
|
|
|
1021
1068
|
}
|
|
1022
1069
|
this.header = h;
|
|
1023
1070
|
|
|
1024
|
-
const funcs = this.
|
|
1071
|
+
const funcs = this.getCommand(CMD.FUNCTION_STARTS);
|
|
1025
1072
|
if (funcs) {
|
|
1026
1073
|
const array = funcs.contents;
|
|
1027
1074
|
const text = await this.getSegment('__TEXT');
|
|
@@ -1030,7 +1077,8 @@ export class MachFile {
|
|
|
1030
1077
|
array[i] = (acc += BigInt(array[i]));
|
|
1031
1078
|
}
|
|
1032
1079
|
}
|
|
1033
|
-
|
|
1080
|
+
|
|
1081
|
+
getCommand<T extends CMD>(cmd: T) : binary.ReadType<typeof cmd_table[T]>;
|
|
1034
1082
|
getCommand(cmd: CMD) {
|
|
1035
1083
|
for (const i of this.commands) {
|
|
1036
1084
|
if (i.cmd === cmd)
|
|
@@ -1038,14 +1086,12 @@ export class MachFile {
|
|
|
1038
1086
|
}
|
|
1039
1087
|
}
|
|
1040
1088
|
|
|
1041
|
-
|
|
1042
|
-
const c = this.getCommand(cmd);
|
|
1043
|
-
return c as binary.ReadType<typeof cmd_table[T]>;
|
|
1044
|
-
}
|
|
1045
|
-
getSegment(name: string) : binary.ReadType<ReturnType<typeof segment>> | undefined {
|
|
1089
|
+
getSegment(name: string) {
|
|
1046
1090
|
for (const i of this.commands) {
|
|
1047
|
-
if (
|
|
1048
|
-
return i.data
|
|
1091
|
+
if (i.cmd === CMD.SEGMENT && i.data.segname === name)
|
|
1092
|
+
return i.data as binary.ReadType<typeof cmd_table[CMD.SEGMENT]>;
|
|
1093
|
+
if (i.cmd === CMD.SEGMENT_64 && i.data.segname === name)
|
|
1094
|
+
return i.data as binary.ReadType<typeof cmd_table[CMD.SEGMENT_64]>;;
|
|
1049
1095
|
}
|
|
1050
1096
|
}
|
|
1051
1097
|
}
|
|
@@ -1066,24 +1112,29 @@ export class FATMachFile {
|
|
|
1066
1112
|
}
|
|
1067
1113
|
}
|
|
1068
1114
|
|
|
1069
|
-
constructor(data: Uint8Array, mem?: binary.
|
|
1115
|
+
constructor(data: Uint8Array, mem?: binary.memory) {
|
|
1070
1116
|
switch (binary.UINT32_BE.get(new binary.stream(data))) {
|
|
1071
|
-
case FAT_MAGIC: this.load(new binary.
|
|
1072
|
-
case FAT_CIGAM: this.load(new binary.
|
|
1117
|
+
case FAT_MAGIC: this.load(new binary.endianStream(data, false), mem); break;
|
|
1118
|
+
case FAT_CIGAM: this.load(new binary.endianStream(data, true), mem); break;
|
|
1073
1119
|
default:
|
|
1074
1120
|
throw new Error('not a fat mach file');
|
|
1075
1121
|
}
|
|
1076
1122
|
}
|
|
1077
1123
|
|
|
1078
|
-
load(file: binary.
|
|
1124
|
+
load(file: binary.endianStream, mem?: binary.memory) {
|
|
1079
1125
|
const header = binary.read(file, fat_header);
|
|
1080
1126
|
this.archs = header.archs;
|
|
1081
1127
|
for (const arch of header.archs) {
|
|
1082
1128
|
const cpu = CPU_TYPE[arch.cputype as keyof typeof CPU_TYPE];
|
|
1083
1129
|
const data = file.buffer_at(arch.offset, arch. size);
|
|
1084
1130
|
arch.cpusubtype = binary.Enum(CPU_SUBTYPES[cpu])(+arch.cpusubtype);
|
|
1085
|
-
arch.contents = new MachFile(data);
|
|
1131
|
+
arch.contents = new MachFile(data, mem);
|
|
1086
1132
|
}
|
|
1087
1133
|
}
|
|
1088
1134
|
}
|
|
1089
|
-
|
|
1135
|
+
/*
|
|
1136
|
+
export function freestanding<T extends CMD>(s: binary.stream, cmd: T) : binary.ReadType<typeof cmd_table[T]>;
|
|
1137
|
+
export function freestanding(s: binary.stream, cmd: CMD) {
|
|
1138
|
+
return binary.read(s, cmd_table[cmd]);
|
|
1139
|
+
}
|
|
1140
|
+
*/
|