@isopodlabs/binary_libs 0.1.1 → 0.1.2
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/CompoundDocument.d.ts +129 -0
- package/dist/CompoundDocument.js +300 -0
- package/dist/arch.d.ts +26 -0
- package/dist/arch.js +96 -0
- package/dist/clr.d.ts +286 -0
- package/dist/clr.js +658 -0
- package/dist/elf.d.ts +112 -0
- package/dist/elf.js +778 -0
- package/dist/mach.d.ts +394 -0
- package/dist/mach.js +1027 -0
- package/dist/pe.d.ts +151 -0
- package/dist/pe.js +484 -0
- package/package.json +5 -1
- package/.gitmodules +0 -3
- package/.vscode/launch.json +0 -16
- package/.vscode/settings.json +0 -3
- package/.vscode/tasks.json +0 -39
- package/eslint.config.mjs +0 -32
- package/src/CompoundDocument.ts +0 -314
- package/src/arch.ts +0 -79
- package/src/clr.ts +0 -646
- package/src/elf.ts +0 -802
- package/src/mach.ts +0 -1140
- package/src/pe.ts +0 -506
- package/transform.ts +0 -369
- package/tsconfig.json +0 -27
- package/tsconfig.tsbuildinfo +0 -1
package/src/mach.ts
DELETED
|
@@ -1,1140 +0,0 @@
|
|
|
1
|
-
import * as binary from '@isopodlabs/binary';
|
|
2
|
-
|
|
3
|
-
class mach_stream extends binary.endianStream {
|
|
4
|
-
constructor(public base: Uint8Array, data: Uint8Array, be: boolean, public mem?: binary.memory) { super(data, be); }
|
|
5
|
-
subdata(offset: number, size?: number) {
|
|
6
|
-
return this.base.subarray(offset, size && offset + size);
|
|
7
|
-
}
|
|
8
|
-
substream(offset: number, size?: number) {
|
|
9
|
-
return new mach_stream(this.base, this.subdata(offset, size), this.be, this.mem);
|
|
10
|
-
}
|
|
11
|
-
getmem(address: bigint, size: number) {
|
|
12
|
-
return this.mem?.get(address, size);
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const uint16 = binary.UINT16;
|
|
17
|
-
const uint32 = binary.UINT32;
|
|
18
|
-
const uint64 = binary.UINT64;
|
|
19
|
-
const int32 = binary.INT32;
|
|
20
|
-
const xint32 = binary.asHex(uint32);
|
|
21
|
-
const xint64 = binary.asHex(uint64);
|
|
22
|
-
|
|
23
|
-
const FILETYPE = {
|
|
24
|
-
OBJECT: 1, // Relocatable object file
|
|
25
|
-
EXECUTE: 2, // Executable file
|
|
26
|
-
FVMLIB: 3, // Fixed VM shared library file
|
|
27
|
-
CORE: 4, // Core file
|
|
28
|
-
PRELOAD: 5, // Preloaded executable file
|
|
29
|
-
DYLIB: 6, // Dynamically bound shared library
|
|
30
|
-
DYLINKER: 7, // Dynamic link editor
|
|
31
|
-
BUNDLE: 8, // Dynamically bound bundle file
|
|
32
|
-
DYLIB_STUB: 9, // Shared library stub for static linking
|
|
33
|
-
DSYM: 10, // Companion file with only debug sections
|
|
34
|
-
KEXT_BUNDLE: 11, // x86_64 kexts
|
|
35
|
-
FILESET: 12
|
|
36
|
-
} as const;
|
|
37
|
-
|
|
38
|
-
// Machine types known by all
|
|
39
|
-
enum CPU_TYPE {
|
|
40
|
-
ANY = -1,
|
|
41
|
-
ARCH_MASK = 0xff000000, // mask for architecture bits
|
|
42
|
-
ARCH_64 = 0x01000000, // 64 bit ABI
|
|
43
|
-
|
|
44
|
-
VAX = 1,
|
|
45
|
-
MC680x0 = 6,
|
|
46
|
-
X86 = 7,
|
|
47
|
-
MIPS = 8,
|
|
48
|
-
MC98000 = 10,
|
|
49
|
-
HPPA = 11,
|
|
50
|
-
ARM = 12,
|
|
51
|
-
MC88000 = 13,
|
|
52
|
-
SPARC = 14,
|
|
53
|
-
I860 = 15,
|
|
54
|
-
ALPHA = 16,
|
|
55
|
-
POWERPC = 18,
|
|
56
|
-
|
|
57
|
-
X86_64 = X86 | ARCH_64,
|
|
58
|
-
POWERPC_64 = POWERPC | ARCH_64,
|
|
59
|
-
ARM_64 = ARM | ARCH_64,
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
const CPU_SUBTYPES: {[K in CPU_TYPE]?: any} = {
|
|
63
|
-
[CPU_TYPE.VAX] : {
|
|
64
|
-
VAX_ALL: 0,
|
|
65
|
-
VAX780: 1,
|
|
66
|
-
VAX785: 2,
|
|
67
|
-
VAX750: 3,
|
|
68
|
-
VAX730: 4,
|
|
69
|
-
UVAXI: 5,
|
|
70
|
-
UVAXII: 6,
|
|
71
|
-
VAX8200: 7,
|
|
72
|
-
VAX8500: 8,
|
|
73
|
-
VAX8600: 9,
|
|
74
|
-
VAX8650: 10,
|
|
75
|
-
VAX8800: 11,
|
|
76
|
-
UVAXIII: 12,
|
|
77
|
-
},
|
|
78
|
-
[CPU_TYPE.MC680x0] : {
|
|
79
|
-
MC680x0_ALL: 1,
|
|
80
|
-
MC68030: 1, // compat
|
|
81
|
-
MC68040: 2,
|
|
82
|
-
MC68030_ONLY: 3,
|
|
83
|
-
},
|
|
84
|
-
[CPU_TYPE.X86] : {
|
|
85
|
-
X86_ALL: 3,
|
|
86
|
-
X86_64_ALL: 3,
|
|
87
|
-
X86_ARCH1: 4,
|
|
88
|
-
},
|
|
89
|
-
[CPU_TYPE.MIPS] : {
|
|
90
|
-
MIPS_ALL: 0,
|
|
91
|
-
MIPS_R2300: 1,
|
|
92
|
-
MIPS_R2600: 2,
|
|
93
|
-
MIPS_R2800: 3,
|
|
94
|
-
MIPS_R2000a: 4, // pmax
|
|
95
|
-
MIPS_R2000: 5,
|
|
96
|
-
MIPS_R3000a: 6, // 3max
|
|
97
|
-
MIPS_R3000: 7,
|
|
98
|
-
|
|
99
|
-
},
|
|
100
|
-
[CPU_TYPE.MC98000] : {
|
|
101
|
-
MC98000_ALL: 0,
|
|
102
|
-
MC98601: 1,
|
|
103
|
-
|
|
104
|
-
},
|
|
105
|
-
[CPU_TYPE.HPPA] : {
|
|
106
|
-
HPPA_ALL: 0,
|
|
107
|
-
HPPA_7100: 0, // compat
|
|
108
|
-
HPPA_7100LC: 1,
|
|
109
|
-
},
|
|
110
|
-
[CPU_TYPE.ARM] : {
|
|
111
|
-
ARM_ALL: 0,
|
|
112
|
-
ARM_V4T: 5,
|
|
113
|
-
ARM_V6: 6,
|
|
114
|
-
ARM_V5TEJ: 7,
|
|
115
|
-
ARM_XSCALE: 8,
|
|
116
|
-
ARM_V7: 9,
|
|
117
|
-
ARM_V7S: 11,
|
|
118
|
-
ARM_V7K: 12,
|
|
119
|
-
ARM_V6M: 14,
|
|
120
|
-
ARM_V7M: 15,
|
|
121
|
-
ARM_V7EM: 16,
|
|
122
|
-
|
|
123
|
-
},
|
|
124
|
-
[CPU_TYPE.MC88000] : {
|
|
125
|
-
MC88000_ALL: 0,
|
|
126
|
-
MC88100: 1,
|
|
127
|
-
MC88110: 2,
|
|
128
|
-
|
|
129
|
-
},
|
|
130
|
-
[CPU_TYPE.SPARC] : {
|
|
131
|
-
SPARC_ALL: 0,
|
|
132
|
-
},
|
|
133
|
-
[CPU_TYPE.I860] : {
|
|
134
|
-
I860_ALL: 0,
|
|
135
|
-
I860_860: 1,
|
|
136
|
-
},
|
|
137
|
-
[CPU_TYPE.ALPHA] : {
|
|
138
|
-
|
|
139
|
-
},
|
|
140
|
-
[CPU_TYPE.POWERPC] : {
|
|
141
|
-
POWERPC_ALL: 0,
|
|
142
|
-
POWERPC_601: 1,
|
|
143
|
-
POWERPC_602: 2,
|
|
144
|
-
POWERPC_603: 3,
|
|
145
|
-
POWERPC_603e: 4,
|
|
146
|
-
POWERPC_603ev: 5,
|
|
147
|
-
POWERPC_604: 6,
|
|
148
|
-
POWERPC_604e: 7,
|
|
149
|
-
POWERPC_620: 8,
|
|
150
|
-
POWERPC_750: 9,
|
|
151
|
-
POWERPC_7400: 10,
|
|
152
|
-
POWERPC_7450: 11,
|
|
153
|
-
POWERPC_970: 100,
|
|
154
|
-
},
|
|
155
|
-
[CPU_TYPE.X86_64] : {
|
|
156
|
-
I386_ALL: 0x03,
|
|
157
|
-
I386: 0x03,
|
|
158
|
-
I486: 0x04,
|
|
159
|
-
I486SX: 0x84,
|
|
160
|
-
I586: 0x05,
|
|
161
|
-
PENT: 0x05,
|
|
162
|
-
PENTPRO: 0x16,
|
|
163
|
-
PENTII_M3: 0x36,
|
|
164
|
-
PENTII_M5: 0x56,
|
|
165
|
-
CELERON: 0x67,
|
|
166
|
-
CELERON_MOBILE: 0x77,
|
|
167
|
-
PENTIUM_3: 0x08,
|
|
168
|
-
PENTIUM_3_M: 0x18,
|
|
169
|
-
PENTIUM_3_XEON: 0x28,
|
|
170
|
-
PENTIUM_M: 0x09,
|
|
171
|
-
PENTIUM_4: 0x0a,
|
|
172
|
-
PENTIUM_4_M: 0x1a,
|
|
173
|
-
ITANIUM: 0x0b,
|
|
174
|
-
ITANIUM_2: 0x1b,
|
|
175
|
-
XEON: 0x0c,
|
|
176
|
-
XEON_MP: 0x1c,
|
|
177
|
-
},
|
|
178
|
-
[CPU_TYPE.POWERPC_64] : {
|
|
179
|
-
|
|
180
|
-
},
|
|
181
|
-
[CPU_TYPE.ARM_64] : {
|
|
182
|
-
FEATURE: 0x01000000, // mask for feature flags
|
|
183
|
-
LIB64: 0x80000000, // 64 bit libraries
|
|
184
|
-
ARM64_ALL: 0,
|
|
185
|
-
ARM64_V8: 1,
|
|
186
|
-
ARM64E: 2,
|
|
187
|
-
},
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
// Constants for the flags field of the header
|
|
191
|
-
const HEADER_FLAGS = {
|
|
192
|
-
NOUNDEFS: 0x1, // the object file has no undefinedreferences
|
|
193
|
-
INCRLINK: 0x2, // the object file is the output of an incremental link against a base file and can't be link edited again
|
|
194
|
-
DYLDLINK: 0x4, // the object file is input for the dynamic linker and can't be staticly link edited again
|
|
195
|
-
BINDATLOAD: 0x8, // the object file's undefined references are bound by the dynamic linker when loaded.
|
|
196
|
-
PREBOUND: 0x10, // the file has its dynamic undefined references prebound.
|
|
197
|
-
SPLIT_SEGS: 0x20, // the file has its read-only and read-write segments split
|
|
198
|
-
LAZY_INIT: 0x40, // the shared library init routine is to be run lazily via catching memory faults to its writeable segments (obsolete)
|
|
199
|
-
TWOLEVEL: 0x80, // the image is using two-level name space bindings
|
|
200
|
-
FORCE_FLAT: 0x100, // the executable is forcing all images to use flat name space bindings
|
|
201
|
-
NOMULTIDEFS: 0x200, // this umbrella guarantees no multiple defintions of symbols in its sub-images so the two-level namespace hints can always be used.
|
|
202
|
-
NOFIXPREBINDING: 0x400, // do not have dyld notify the prebinding agent about this executable
|
|
203
|
-
PREBINDABLE: 0x800, // the binary is not prebound but can have its prebinding redone. only used when MH_PREBOUND is not set.
|
|
204
|
-
ALLMODSBOUND: 0x1000, // indicates that this binary binds to all two-level namespace modules of its dependent libraries. only used when MH_PREBINDABLE and MH_TWOLEVELare both set.
|
|
205
|
-
SUBSECTIONS_VIA_SYMBOLS:0x2000, // safe to divide up the sections into sub-sections via symbols for dead code stripping
|
|
206
|
-
CANONICAL: 0x4000, // the binary has been canonicalized via the unprebind operation
|
|
207
|
-
WEAK_DEFINES: 0x8000, // the final linked image contains external weak symbols
|
|
208
|
-
BINDS_TO_WEAK: 0x10000, // the final linked image uses weak symbols
|
|
209
|
-
ALLOW_STACK_EXECUTION: 0x20000, // When this bit is set, all stacks in the task will be given stack execution privilege. Only used in MH_EXECUTE filetypes.
|
|
210
|
-
ROOT_SAFE: 0x40000, // When this bit is set, the binary declares it is safe for use in processes with uid zero
|
|
211
|
-
SETUID_SAFE: 0x80000, // When this bit is set, the binary declares it is safe for use in processes when issetugid() is true
|
|
212
|
-
NO_REEXPORTED_DYLIBS: 0x100000, // When this bit is set on a dylib, the static linker does not need to examine dependent dylibs to see if any are re-exported
|
|
213
|
-
PIE: 0x200000, // When this bit is set, the OS will load the main executable at a random address.Only used in MH_EXECUTE filetypes.
|
|
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
|
-
HAS_TLV_DESCRIPTORS: 0x800000, // Contains a section of type S_THREAD_LOCAL_VARIABLES
|
|
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
|
-
} as const;
|
|
218
|
-
|
|
219
|
-
const header = {
|
|
220
|
-
magic: uint32, // mach magic number identifier
|
|
221
|
-
cputype: binary.as(uint32, binary.Enum(CPU_TYPE)),
|
|
222
|
-
cpusubtype: binary.as(uint32, (x: number): number|string => x),//binary.Enum(CPU_SUBTYPE)),
|
|
223
|
-
filetype: binary.as(uint32, binary.Enum(FILETYPE)),
|
|
224
|
-
ncmds: uint32, // number of load commands
|
|
225
|
-
sizeofcmds: uint32, // the size of all the load commands
|
|
226
|
-
flags: binary.as(uint32, binary.Flags(HEADER_FLAGS, true))
|
|
227
|
-
};
|
|
228
|
-
|
|
229
|
-
const fat_arch = {
|
|
230
|
-
cputype: binary.as(uint32, binary.Enum(CPU_TYPE)),
|
|
231
|
-
cpusubtype: binary.as(uint32, (x: number): number|string => x),//binary.Enum(CPU_SUBTYPE)),
|
|
232
|
-
offset: binary.UINT32_BE, // file offset to this object file
|
|
233
|
-
size: binary.UINT32_BE, // size of this object file
|
|
234
|
-
align: binary.UINT32_BE, // alignment as a power of 2
|
|
235
|
-
contents: binary.DontRead<MachFile>(),
|
|
236
|
-
};
|
|
237
|
-
|
|
238
|
-
const fat_header = {
|
|
239
|
-
magic: uint32, // FAT_MAGIC
|
|
240
|
-
archs: binary.ArrayType(uint32, fat_arch)
|
|
241
|
-
};
|
|
242
|
-
|
|
243
|
-
const REQ_DYLD = 0x80000000;
|
|
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
|
-
};
|
|
299
|
-
|
|
300
|
-
const str = {
|
|
301
|
-
get(s: binary.stream) {
|
|
302
|
-
const off = uint32.get(s); // offset to the string
|
|
303
|
-
return binary.utils.decodeTextTo0(s.buffer_at(off - 8), 'utf8');
|
|
304
|
-
}
|
|
305
|
-
};
|
|
306
|
-
|
|
307
|
-
const index_table = {
|
|
308
|
-
first: uint32,
|
|
309
|
-
count: uint32,
|
|
310
|
-
};
|
|
311
|
-
|
|
312
|
-
const blob = {
|
|
313
|
-
get(s: mach_stream) {
|
|
314
|
-
const offset = uint32.get(s);
|
|
315
|
-
const size = uint32.get(s);
|
|
316
|
-
if (size)
|
|
317
|
-
return s.subdata(offset, size);//.buffer_at(offset, size);
|
|
318
|
-
}
|
|
319
|
-
};
|
|
320
|
-
|
|
321
|
-
function blobT<T extends binary.TypeReader>(type: T) {
|
|
322
|
-
return {
|
|
323
|
-
get(s: mach_stream) {
|
|
324
|
-
const offset = uint32.get(s);
|
|
325
|
-
const size = uint32.get(s);
|
|
326
|
-
return {
|
|
327
|
-
data: s.subdata(offset, size),
|
|
328
|
-
contents: binary.read(s.substream(offset, size), type)
|
|
329
|
-
};
|
|
330
|
-
}
|
|
331
|
-
};
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
function blobArray<T extends binary.Type>(type: T) {
|
|
335
|
-
return blobT(binary.RemainingArrayType(type));
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
function count_table<T extends binary.TypeReader>(type: T) {
|
|
340
|
-
return {
|
|
341
|
-
get(s: mach_stream) {
|
|
342
|
-
const offset = uint32.get(s);
|
|
343
|
-
const count = uint32.get(s);
|
|
344
|
-
if (count)
|
|
345
|
-
return binary.readn(s.substream(offset), type, count);
|
|
346
|
-
}
|
|
347
|
-
};
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
const fixed_string16 = binary.StringType(16);
|
|
351
|
-
const version = binary.asFlags(uint32, {major: 0xffff0000, minor: 0xff00, patch: 0xff}, false);
|
|
352
|
-
|
|
353
|
-
const command = {
|
|
354
|
-
cmd: binary.as(uint32, v => v as CMD),
|
|
355
|
-
cmdsize: uint32,
|
|
356
|
-
};
|
|
357
|
-
|
|
358
|
-
const SECTION_FLAGS = binary.BitFields({
|
|
359
|
-
TYPE: [8, binary.Enum({
|
|
360
|
-
REGULAR: 0x0, // regular section
|
|
361
|
-
ZEROFILL: 0x1, // zero fill on demand section
|
|
362
|
-
CSTRING_LITERALS: 0x2, // section with only literal C strings
|
|
363
|
-
LITERALS4: 0x3, // section with only 4 byte literals
|
|
364
|
-
LITERALS8: 0x4, // section with only 8 byte literals
|
|
365
|
-
LITERAL_POINTERS: 0x5, // section with only pointers to literals
|
|
366
|
-
NON_LAZY_SYMBOL_POINTERS: 0x6, // section with only non-lazy symbol pointers
|
|
367
|
-
LAZY_SYMBOL_POINTERS: 0x7, // section with only lazy symbol pointers
|
|
368
|
-
SYMBOL_STUBS: 0x8, // section with only symbol stubs, byte size of stub in the reserved2 field
|
|
369
|
-
MOD_INIT_FUNC_POINTERS: 0x9, // section with only function pointers for initialization
|
|
370
|
-
MOD_TERM_FUNC_POINTERS: 0xa, // section with only function pointers for termination
|
|
371
|
-
COALESCED: 0xb, // section contains symbols that are to be coalesced
|
|
372
|
-
GB_ZEROFILL: 0xc, // zero fill on demand section (that can be larger than 4 gigabytes)
|
|
373
|
-
INTERPOSING: 0xd, // section with only pairs of function pointers for interposing
|
|
374
|
-
LITERALS16: 0xe, // section with only 16 byte literals
|
|
375
|
-
DTRACE_DOF: 0xf, // section contains DTrace Object Format
|
|
376
|
-
LAZY_DYLIB_SYMBOL_POINTERS: 0x10, // section with only lazy symbol pointers to lazy loaded dylibs
|
|
377
|
-
// Section types to support thread local variables
|
|
378
|
-
THREAD_LOCAL_REGULAR: 0x11, // template of initial values for TLVs
|
|
379
|
-
THREAD_LOCAL_ZEROFILL: 0x12, // template of initial values for TLVs
|
|
380
|
-
THREAD_LOCAL_VARIABLES: 0x13, // TLV descriptors
|
|
381
|
-
THREAD_LOCAL_VARIABLE_POINTERS: 0x14, // pointers to TLV descriptors
|
|
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, // section contains some machine instructions
|
|
387
|
-
EXT_RELOC: 0x0002, // section has external relocation entries
|
|
388
|
-
LOC_RELOC: 0x0001, // section has local relocation entries
|
|
389
|
-
}, true)],
|
|
390
|
-
USR: [8, binary.Flags({
|
|
391
|
-
PURE_INSTRUCTIONS: 0x80, // section contains only true machine instructions
|
|
392
|
-
NO_TOC: 0x40, // section contains coalesced symbols that are not to be in a ranlib table of contents
|
|
393
|
-
STRIP_STATIC_SYMS: 0x20, // ok to strip static symbols in this section in files with the MH_DYLDLINK flag
|
|
394
|
-
NO_DEAD_STRIP: 0x10, // no dead stripping
|
|
395
|
-
LIVE_SUPPORT: 0x08, // blocks are live if they reference live blocks
|
|
396
|
-
SELF_MODIFYING_CODE: 0x04, // Used with i386 code stubs written on by dyld
|
|
397
|
-
DEBUG: 0x02, // a debug section
|
|
398
|
-
}, true)],
|
|
399
|
-
})],
|
|
400
|
-
});
|
|
401
|
-
|
|
402
|
-
function section(bits: 32|64) {
|
|
403
|
-
const type = binary.UINT(bits);
|
|
404
|
-
|
|
405
|
-
class Section extends binary.Class({
|
|
406
|
-
//data: binary.DontRead<binary.utils.MappedMemory>(),
|
|
407
|
-
sectname: fixed_string16,
|
|
408
|
-
segname: fixed_string16,
|
|
409
|
-
addr: type, // memory address of this section
|
|
410
|
-
size: type, // size in bytes of this section
|
|
411
|
-
offset: xint32, // file offset of this section
|
|
412
|
-
align: uint32, // section alignment (power of 2)
|
|
413
|
-
reloff: xint32, // file offset of relocation entries
|
|
414
|
-
nreloc: uint32, // number of relocation entries
|
|
415
|
-
flags: binary.as(uint32, SECTION_FLAGS), // flags (section type and attributes)
|
|
416
|
-
reserved1: uint32, // reserved (for offset or index)
|
|
417
|
-
reserved2: uint32, // reserved (for count or sizeof)
|
|
418
|
-
_: binary.AlignType(bits / 8)
|
|
419
|
-
}) {
|
|
420
|
-
data: Promise<binary.MappedMemory>;
|
|
421
|
-
constructor(s: mach_stream) {
|
|
422
|
-
super(s);
|
|
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
|
-
)();
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
return Section;
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
const SEGMENT_FLAGS = {
|
|
434
|
-
HIGHVM: 0x1, // the file contents for this segment is for the high part of the VM space, the low part is zero filled (for stacks in core files)
|
|
435
|
-
FVMLIB: 0x2, // this segment is the VM that is allocated by a fixed VM library, for overlap checking in the link editor
|
|
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
|
|
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.
|
|
438
|
-
};
|
|
439
|
-
|
|
440
|
-
function segment<T extends 32|64>(bits: T) {
|
|
441
|
-
const type = binary.UINT(bits);
|
|
442
|
-
const fields = {
|
|
443
|
-
data: binary.DontRead<binary.MappedMemory>(),
|
|
444
|
-
segname: fixed_string16, // segment name
|
|
445
|
-
vmaddr: type, // memory address of this segment
|
|
446
|
-
vmsize: type, // memory size of this segment
|
|
447
|
-
fileoff: type, // file offset of this segment
|
|
448
|
-
filesize: type, // amount to map from the file
|
|
449
|
-
maxprot: uint32, // maximum VM protection
|
|
450
|
-
initprot: uint32, // initial VM protection
|
|
451
|
-
nsects: uint32, // number of sections in segment
|
|
452
|
-
flags: binary.as(uint32, binary.Flags(SEGMENT_FLAGS,true)), // flags
|
|
453
|
-
sections: binary.DontRead<Record<string, any>>(),//binary.ReadType<typeof section(bits)>)),
|
|
454
|
-
};
|
|
455
|
-
return {
|
|
456
|
-
get(s: mach_stream) {
|
|
457
|
-
const o = binary.read(s, fields);
|
|
458
|
-
|
|
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
|
-
}
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
load();
|
|
471
|
-
return o;
|
|
472
|
-
}
|
|
473
|
-
};
|
|
474
|
-
}
|
|
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
|
-
|
|
512
|
-
const fvmlib = {
|
|
513
|
-
name: str, // library's target pathname
|
|
514
|
-
minor_version: xint32, // library's minor version number
|
|
515
|
-
header_addr: xint32, // library's header address
|
|
516
|
-
};
|
|
517
|
-
|
|
518
|
-
const dylib = {
|
|
519
|
-
name: str,
|
|
520
|
-
timestamp: uint32,
|
|
521
|
-
current_version: version,
|
|
522
|
-
compatibility_version: version,
|
|
523
|
-
};
|
|
524
|
-
|
|
525
|
-
const thread_command = {
|
|
526
|
-
flavor: uint32, // flavor of thread state
|
|
527
|
-
count: uint32, // count of longs in thread state
|
|
528
|
-
// struct XXX_thread_state state thread state for this flavor
|
|
529
|
-
// ...
|
|
530
|
-
};
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
// SYMTAB
|
|
534
|
-
const nlist_flags = binary.BitFields({
|
|
535
|
-
ext: 1,
|
|
536
|
-
type: [3, binary.Enum({
|
|
537
|
-
UNDF: 0, // undefined, n_sect == NO_SECT
|
|
538
|
-
ABS: 1, // absolute, n_sect == NO_SECT
|
|
539
|
-
INDR: 5, // indirect
|
|
540
|
-
PBUD: 6, // prebound undefined (defined in a dylib)
|
|
541
|
-
SECT: 7, // defined in section number n_sect
|
|
542
|
-
})],
|
|
543
|
-
pext: 1,
|
|
544
|
-
stab: [3, binary.Enum({
|
|
545
|
-
|
|
546
|
-
})],
|
|
547
|
-
});
|
|
548
|
-
/*
|
|
549
|
-
//masks
|
|
550
|
-
//STAB = 0xe0, // if any of these bits set, a symbolic debugging entry
|
|
551
|
-
PEXT = 0x10, // private external symbol bit
|
|
552
|
-
//TYPE = 0x0e, // mask for the type bits
|
|
553
|
-
EXT = 0x01, // external symbol bit, set for external symbols
|
|
554
|
-
|
|
555
|
-
UNDF = 0x00, // undefined, n_sect == NO_SECT
|
|
556
|
-
ABS = 0x02, // absolute, n_sect == NO_SECT
|
|
557
|
-
INDR = 0x0a, // indirect
|
|
558
|
-
PBUD = 0x0c, // prebound undefined (defined in a dylib)
|
|
559
|
-
SECT = 0x0e, // defined in section number n_sect
|
|
560
|
-
// STAB values
|
|
561
|
-
GSYM = 0x20, // global symbol: name,,NO_SECT,type,0
|
|
562
|
-
FNAME = 0x22, // procedure name (f77 kludge): name,,NO_SECT,0,0
|
|
563
|
-
FUN = 0x24, // procedure: name,,n_sect,linenumber,address
|
|
564
|
-
STSYM = 0x26, // static symbol: name,,n_sect,type,address
|
|
565
|
-
LCSYM = 0x28, // .lcomm symbol: name,,n_sect,type,address
|
|
566
|
-
BNSYM = 0x2e, // begin nsect sym: 0,,n_sect,0,address
|
|
567
|
-
OPT = 0x3c, // emitted with gcc2_compiled and in gcc source
|
|
568
|
-
RSYM = 0x40, // register sym: name,,NO_SECT,type,register
|
|
569
|
-
SLINE = 0x44, // src line: 0,,n_sect,linenumber,address
|
|
570
|
-
ENSYM = 0x4e, // end nsect sym: 0,,n_sect,0,address
|
|
571
|
-
SSYM = 0x60, // structure elt: name,,NO_SECT,type,struct_offset
|
|
572
|
-
SO = 0x64, // source file name: name,,n_sect,0,address
|
|
573
|
-
OSO = 0x66, // object file name: name,,0,0,st_mtime
|
|
574
|
-
LSYM = 0x80, // local sym: name,,NO_SECT,type,offset
|
|
575
|
-
BINCL = 0x82, // include file beginning: name,,NO_SECT,0,sum
|
|
576
|
-
SOL = 0x84, // #included file name: name,,n_sect,0,address
|
|
577
|
-
PARAMS = 0x86, // compiler parameters: name,,NO_SECT,0,0
|
|
578
|
-
VERSION = 0x88, // compiler version: name,,NO_SECT,0,0
|
|
579
|
-
OLEVEL = 0x8A, // compiler -O level: name,,NO_SECT,0,0
|
|
580
|
-
PSYM = 0xa0, // parameter: name,,NO_SECT,type,offset
|
|
581
|
-
EINCL = 0xa2, // include file end: name,,NO_SECT,0,0
|
|
582
|
-
ENTRY = 0xa4, // alternate entry: name,,n_sect,linenumber,address
|
|
583
|
-
LBRAC = 0xc0, // left bracket: 0,,NO_SECT,nesting level,address
|
|
584
|
-
EXCL = 0xc2, // deleted include file: name,,NO_SECT,0,sum
|
|
585
|
-
RBRAC = 0xe0, // right bracket: 0,,NO_SECT,nesting level,address
|
|
586
|
-
BCOMM = 0xe2, // begin common: name,,NO_SECT,0,0
|
|
587
|
-
ECOMM = 0xe4, // end common: name,,n_sect,0,0
|
|
588
|
-
ECOML = 0xe8, // end common (local name): 0,,n_sect,0,address
|
|
589
|
-
LENG = 0xfe, // second stab entry with length information
|
|
590
|
-
}
|
|
591
|
-
*/
|
|
592
|
-
const nlist_desc = binary.BitFields({
|
|
593
|
-
ref: [3, binary.Enum({
|
|
594
|
-
UNDEFINED_NON_LAZY: 0,
|
|
595
|
-
UNDEFINED_LAZY: 1,
|
|
596
|
-
DEFINED: 2,
|
|
597
|
-
PRIVATE_DEFINED: 3,
|
|
598
|
-
PRIVATE_UNDEFINED_NON_LAZY: 4,
|
|
599
|
-
PRIVATE_UNDEFINED_LAZY: 5,
|
|
600
|
-
})],
|
|
601
|
-
flags: [5, binary.Flags({
|
|
602
|
-
ARM_THUMB_DEF: 1 << 0, // symbol is a Thumb function (ARM)
|
|
603
|
-
REF_DYNAMIC: 1 << 1,
|
|
604
|
-
NO_DEAD_STRIP: 1 << 2, // symbol is not to be dead stripped
|
|
605
|
-
//DESC_DISCARDE: 1 << 2, // symbol is discarded
|
|
606
|
-
WEAK_REF: 1 << 3, // symbol is weak referenced
|
|
607
|
-
WEAK_DEF: 1 << 4, // coalesed symbol is a weak definition
|
|
608
|
-
//REF_TO_WEA 1 << 4, // reference to a weak symbol
|
|
609
|
-
//SYMBOL_RESOLVER: 0x0100,
|
|
610
|
-
}, true)],
|
|
611
|
-
align: 8
|
|
612
|
-
//MAX_LIBRARY_ORDINAL = 0xfd << 8,
|
|
613
|
-
//DYNAMIC_LOOKUP_ORDINAL = 0xfe << 8,
|
|
614
|
-
//EXECUTABLE_ORDINAL = 0xff << 8,
|
|
615
|
-
});
|
|
616
|
-
|
|
617
|
-
function nlist(bits:32|64) { return {
|
|
618
|
-
strx: uint32, // index into the string table
|
|
619
|
-
flags: binary.as(binary.UINT8, nlist_flags),
|
|
620
|
-
sect: binary.UINT8,// section number or NO_SECT
|
|
621
|
-
desc: binary.as(uint16, nlist_desc),
|
|
622
|
-
value: binary.UINT(bits),
|
|
623
|
-
|
|
624
|
-
//const char *name(const char *s) const { return s ? s + strx : ""; }
|
|
625
|
-
//FLAGS type() const { return FLAGS(flags & TYPE); }
|
|
626
|
-
//FLAGS stab() const { return FLAGS(flags & STAB); }
|
|
627
|
-
}; }
|
|
628
|
-
|
|
629
|
-
const symtab = {
|
|
630
|
-
get(s: binary._stream) {
|
|
631
|
-
const sym = binary.read(s, count_table(nlist(64)));
|
|
632
|
-
const str = binary.read(s, blob) as Uint8Array;
|
|
633
|
-
return sym?.map(v => [binary.utils.decodeTextTo0(str.subarray(v.strx), 'utf8'), v]);
|
|
634
|
-
}
|
|
635
|
-
};
|
|
636
|
-
|
|
637
|
-
// DYSYMTAB
|
|
638
|
-
|
|
639
|
-
const INDIRECT = {
|
|
640
|
-
INDIRECT_SYMBOL_LOCAL: 0x80000000, // non-lazy symbol pointer section for a defined symbol which strip(1) has removed
|
|
641
|
-
INDIRECT_SYMBOL_ABS: 0x40000000,
|
|
642
|
-
} as const;
|
|
643
|
-
|
|
644
|
-
const toc_entry = {
|
|
645
|
-
symbol_index: uint32, // the defined external symbol (index into the symbol table)
|
|
646
|
-
module_index: uint32, // index into the module table this symbol is defined in
|
|
647
|
-
};
|
|
648
|
-
|
|
649
|
-
function module(bits:32|64) {
|
|
650
|
-
const fields = {
|
|
651
|
-
module_name: uint32, // the module name (index into string table)
|
|
652
|
-
extdefsym: index_table, // index into externally defined symbols
|
|
653
|
-
refsym: index_table, // index into reference symbol table
|
|
654
|
-
localsym: index_table, // index into symbols for local symbols
|
|
655
|
-
extrel: index_table, // index into external relocation entries
|
|
656
|
-
init_iterm: index_table, // low 16 bits are the index into the init section, high 16 bits are the index into the term section
|
|
657
|
-
};
|
|
658
|
-
return bits == 32 ? {...fields,
|
|
659
|
-
objc_module_info_addr: uint32, // for this module address of the start of the (__OBJC,__module_info) section
|
|
660
|
-
objc_module_info_size: uint32, // for this module size of the (__OBJC,__module_info) section
|
|
661
|
-
} : {...fields,
|
|
662
|
-
objc_module_info_size: uint32, // for this module size of the (__OBJC, __module_info) section
|
|
663
|
-
objc_module_info_addr: uint64, // for this module address of the start of the (__OBJC, __module_info) section
|
|
664
|
-
};
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
const symbol_ref = binary.as(uint32, binary.BitFields({
|
|
668
|
-
symbol_index: 24, // index into the symbol table
|
|
669
|
-
flags: 8
|
|
670
|
-
}));
|
|
671
|
-
|
|
672
|
-
const hint = binary.as(uint32, binary.BitFields({
|
|
673
|
-
sub_image: 8, // index into the sub images
|
|
674
|
-
toc: 24 // index into the table of contents
|
|
675
|
-
}));
|
|
676
|
-
|
|
677
|
-
const version_min = {
|
|
678
|
-
version,
|
|
679
|
-
reserved: uint32, // zero
|
|
680
|
-
};
|
|
681
|
-
|
|
682
|
-
const REBASE = binary.BitFields({
|
|
683
|
-
immediate: 4,
|
|
684
|
-
opcode: [4, binary.Enum({
|
|
685
|
-
DONE: 0,
|
|
686
|
-
SET_TYPE_IMM: 1,
|
|
687
|
-
SET_SEGMENT_AND_OFFSET_ULEB: 2,
|
|
688
|
-
ADD_ADDR_ULEB: 3,
|
|
689
|
-
ADD_ADDR_IMM_SCALED: 4,
|
|
690
|
-
DO_REBASE_IMM_TIMES: 5,
|
|
691
|
-
DO_REBASE_ULEB_TIMES: 6,
|
|
692
|
-
DO_REBASE_ADD_ADDR_ULEB: 7,
|
|
693
|
-
DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: 8,
|
|
694
|
-
})]
|
|
695
|
-
//TYPE_POINTER = 1,
|
|
696
|
-
//TYPE_TEXT_ABSOLUTE32 = 2,
|
|
697
|
-
//TYPE_TEXT_PCREL32 = 3,
|
|
698
|
-
});
|
|
699
|
-
|
|
700
|
-
const BIND = binary.BitFields({
|
|
701
|
-
immediate: 4,
|
|
702
|
-
opcode: [4, binary.Enum({
|
|
703
|
-
DONE: 0,
|
|
704
|
-
SET_DYLIB_ORDINAL_IMM: 1,
|
|
705
|
-
SET_DYLIB_ORDINAL_ULEB: 2,
|
|
706
|
-
SET_DYLIB_SPECIAL_IMM: 3,
|
|
707
|
-
SET_SYMBOL_TRAILING_FLAGS_IMM: 4,
|
|
708
|
-
SET_TYPE_IMM: 5,
|
|
709
|
-
SET_ADDEND_SLEB: 6,
|
|
710
|
-
SET_SEGMENT_AND_OFFSET_ULEB: 7,
|
|
711
|
-
ADD_ADDR_ULEB: 8,
|
|
712
|
-
DO_BIND: 9,
|
|
713
|
-
DO_BIND_ADD_ADDR_ULEB: 10,
|
|
714
|
-
DO_BIND_ADD_ADDR_IMM_SCALED: 11,
|
|
715
|
-
DO_BIND_ULEB_TIMES_SKIPPING_ULEB: 12,
|
|
716
|
-
})]
|
|
717
|
-
//TYPE_POINTER = 1,
|
|
718
|
-
//TYPE_TEXT_ABSOLUTE32 = 2,
|
|
719
|
-
//TYPE_TEXT_PCREL32 = 3,
|
|
720
|
-
//SPECIAL_DYLIB_SELF = 0,
|
|
721
|
-
//SPECIAL_DYLIB_MAIN_EXECUTABLE = -1,
|
|
722
|
-
//SPECIAL_DYLIB_FLAT_LOOKUP = -2,
|
|
723
|
-
//SYMBOL_FLAGS_WEAK_IMPORT = 0x1,
|
|
724
|
-
//SYMBOL_FLAGS_NON_WEAK_DEFINITION = 0x8,
|
|
725
|
-
});
|
|
726
|
-
|
|
727
|
-
const dyld_kind = {
|
|
728
|
-
KIND_MASK: 0x03,
|
|
729
|
-
KIND_REGULAR: 0x00,
|
|
730
|
-
KIND_THREAD_LOCAL: 0x01,
|
|
731
|
-
KIND_ABSOLUTE: 0x02,
|
|
732
|
-
WEAK_DEFINITION: 0x04,
|
|
733
|
-
REEXPORT: 0x08,
|
|
734
|
-
STUB_AND_RESOLVER: 0x10,
|
|
735
|
-
} as const;
|
|
736
|
-
|
|
737
|
-
const dyldinfo = {
|
|
738
|
-
rebase: blob,
|
|
739
|
-
bind: blob,
|
|
740
|
-
weak_bind: blob,
|
|
741
|
-
lazy_bind: blob,
|
|
742
|
-
exprt: blob,
|
|
743
|
-
};
|
|
744
|
-
|
|
745
|
-
//BUILD_VERSION
|
|
746
|
-
const TOOL = {
|
|
747
|
-
CLANG: 1,
|
|
748
|
-
SWIFT: 2,
|
|
749
|
-
LD: 3,
|
|
750
|
-
LLD: 4,
|
|
751
|
-
} as const;
|
|
752
|
-
|
|
753
|
-
const PLATFORM = {
|
|
754
|
-
MACOS: 1,
|
|
755
|
-
IOS: 2,
|
|
756
|
-
TVOS: 3,
|
|
757
|
-
WATCHOS: 4,
|
|
758
|
-
BRIDGEOS: 5,
|
|
759
|
-
MACCATALYST: 6,
|
|
760
|
-
IOSSIMULATOR: 7,
|
|
761
|
-
TVOSSIMULATOR: 8,
|
|
762
|
-
WATCHOSSIMULATOR: 9,
|
|
763
|
-
DRIVERKIT: 10,
|
|
764
|
-
} as const;
|
|
765
|
-
|
|
766
|
-
//DYLD_CHAINED_FIXUPS
|
|
767
|
-
|
|
768
|
-
const dyld_chained_starts_in_segment = {
|
|
769
|
-
size: uint32, ///< Size of this, including chain_starts entries
|
|
770
|
-
page_size: uint16, ///< Page size in bytes (0x1000 or 0x4000)
|
|
771
|
-
pointer_format: binary.asEnum(uint16, {
|
|
772
|
-
ARM64E: 1,
|
|
773
|
-
'64': 2,
|
|
774
|
-
'32': 3,
|
|
775
|
-
'32_CACHE': 4,
|
|
776
|
-
'32_FIRMWARE': 5,
|
|
777
|
-
'64_OFFSET': 6,
|
|
778
|
-
ARM64E_KERNEL: 7,
|
|
779
|
-
'64_KERNEL_CACHE': 8,
|
|
780
|
-
ARM64E_USERLAND: 9,
|
|
781
|
-
ARM64E_FIRMWARE: 10,
|
|
782
|
-
X86_64_KERNEL_CACHE: 11,
|
|
783
|
-
ARM64E_USERLAND24: 12,
|
|
784
|
-
}),
|
|
785
|
-
segment_offset: xint64, // VM offset from the __TEXT segment
|
|
786
|
-
max_valid_pointer: xint32, // Values beyond this are not pointers on 32-bit
|
|
787
|
-
pages: binary.ArrayType(uint16, binary.asEnum(uint16, {
|
|
788
|
-
NONE: 0xFFFF,
|
|
789
|
-
MULTI: 0x8000, // page which has multiple starts
|
|
790
|
-
LAST: 0x8000, // last chain_start for a given page
|
|
791
|
-
}))
|
|
792
|
-
};
|
|
793
|
-
|
|
794
|
-
const dyld_chained_starts_in_image = binary.ArrayType(uint32, binary.OffsetType(uint32, dyld_chained_starts_in_segment));
|
|
795
|
-
|
|
796
|
-
const dyld_chained_import = binary.as(uint32, binary.BitFields({
|
|
797
|
-
lib_ordinal : 8,
|
|
798
|
-
weak_import : 1,
|
|
799
|
-
name_offset : 23,
|
|
800
|
-
}));
|
|
801
|
-
|
|
802
|
-
const dyld_chained_import_addend = {
|
|
803
|
-
import: dyld_chained_import,
|
|
804
|
-
addend: int32,
|
|
805
|
-
};
|
|
806
|
-
|
|
807
|
-
const dyld_chained_import_addend64 = {
|
|
808
|
-
import: binary.as(uint64, binary.BitFields({
|
|
809
|
-
lib_ordinal : 16,
|
|
810
|
-
weak_import : 1,
|
|
811
|
-
reserved : 15,
|
|
812
|
-
name_offset : 32,
|
|
813
|
-
})),
|
|
814
|
-
addend: uint64,
|
|
815
|
-
};
|
|
816
|
-
|
|
817
|
-
class dyld_chained_fixups extends binary.ReadClass({
|
|
818
|
-
fixups_version: uint32, // currently 0
|
|
819
|
-
starts: binary.OffsetType(uint32, dyld_chained_starts_in_image),
|
|
820
|
-
imports: binary.OffsetType(uint32, binary.Remainder), // offset of imports table in chain_data
|
|
821
|
-
symbols: binary.OffsetType(uint32, binary.Remainder), // offset of symbol strings in chain_data
|
|
822
|
-
imports_count: uint32, // number of imported symbol names
|
|
823
|
-
imports_format: binary.asEnum(uint32, {
|
|
824
|
-
IMPORT: 1,
|
|
825
|
-
IMPORT_ADDEND: 2,
|
|
826
|
-
IMPORT_ADDEND64: 3
|
|
827
|
-
}),
|
|
828
|
-
symbols_format: binary.asEnum(uint32, {
|
|
829
|
-
UNCOMPRESSED: 0,
|
|
830
|
-
ZLIB: 1,
|
|
831
|
-
}),
|
|
832
|
-
}) {
|
|
833
|
-
imports2;
|
|
834
|
-
constructor(s: binary.endianStream) {
|
|
835
|
-
super(s);
|
|
836
|
-
const imports = new binary.endianStream(this.imports, s.be);
|
|
837
|
-
switch (this.imports_format) {
|
|
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))));
|
|
840
|
-
break;
|
|
841
|
-
}
|
|
842
|
-
case 'IMPORT_ADDEND':
|
|
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))));
|
|
844
|
-
break;
|
|
845
|
-
case 'IMPORT_ADDEND64':
|
|
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))));
|
|
847
|
-
break;
|
|
848
|
-
}
|
|
849
|
-
}
|
|
850
|
-
}
|
|
851
|
-
|
|
852
|
-
const dyld_chained_ptr_64_bind = binary.as(uint64, binary.BitFields({
|
|
853
|
-
ordinal : 24,
|
|
854
|
-
addend : 8,
|
|
855
|
-
reserved : 19,
|
|
856
|
-
next : 12,
|
|
857
|
-
bind : 1, // set to 1
|
|
858
|
-
}));
|
|
859
|
-
|
|
860
|
-
const dyld_chained_ptr_64_rebase = binary.as(uint64, binary.BitFields({
|
|
861
|
-
target : 36,
|
|
862
|
-
high8 : 8,
|
|
863
|
-
reserved : 7,
|
|
864
|
-
next : 12,
|
|
865
|
-
bind : 1, // set to 0
|
|
866
|
-
}));
|
|
867
|
-
|
|
868
|
-
//DATA_IN_CODE
|
|
869
|
-
|
|
870
|
-
const data_in_code_entry = {
|
|
871
|
-
offset: xint32, // from header to start of data range
|
|
872
|
-
length: uint16, // number of bytes in data range
|
|
873
|
-
kind: binary.as(uint16, binary.Enum({
|
|
874
|
-
DATA: 0x0001,
|
|
875
|
-
JUMP_TABLE8: 0x0002,
|
|
876
|
-
JUMP_TABLE16: 0x0003,
|
|
877
|
-
JUMP_TABLE32: 0x0004,
|
|
878
|
-
ABS_JUMP_TABLE32: 0x0005,
|
|
879
|
-
})),
|
|
880
|
-
};
|
|
881
|
-
|
|
882
|
-
// Sections of type S_THREAD_LOCAL_VARIABLES contain an array of tlv_descriptor structures.
|
|
883
|
-
/*
|
|
884
|
-
const tlv_descriptor = {
|
|
885
|
-
void* (*thunk)(tlv_descriptor*);
|
|
886
|
-
unsigned long key;
|
|
887
|
-
unsigned long offset;
|
|
888
|
-
};
|
|
889
|
-
*/
|
|
890
|
-
|
|
891
|
-
function routines(bits:32|64) {
|
|
892
|
-
const type = binary.UINT(bits);
|
|
893
|
-
return {
|
|
894
|
-
init_address: type, // address of initialization routine
|
|
895
|
-
init_module: type, // index into the module table that the init routine is defined in
|
|
896
|
-
reserved1: type,
|
|
897
|
-
reserved2: type,
|
|
898
|
-
reserved3: type,
|
|
899
|
-
reserved4: type,
|
|
900
|
-
reserved5: type,
|
|
901
|
-
reserved6: type,
|
|
902
|
-
};
|
|
903
|
-
}
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
//const cmd_table : {[K in CMD]?: binary.TypeReader2} = {
|
|
908
|
-
const cmd_table = {//: Record<CMD, binary.TypeReader2> = {
|
|
909
|
-
[CMD.SEGMENT]: segment(32),
|
|
910
|
-
[CMD.SEGMENT_64]: segment(64),
|
|
911
|
-
[CMD.LOADFVMLIB]: fvmlib,
|
|
912
|
-
[CMD.IDFVMLIB]: fvmlib,
|
|
913
|
-
|
|
914
|
-
[CMD.LOAD_DYLIB]: dylib,
|
|
915
|
-
[CMD.ID_DYLIB]: dylib,
|
|
916
|
-
[CMD.LOAD_WEAK_DYLIB]: dylib,
|
|
917
|
-
[CMD.REEXPORT_DYLIB]: dylib,
|
|
918
|
-
[CMD.LAZY_LOAD_DYLIB]: dylib,
|
|
919
|
-
[CMD.LOAD_UPWARD_DYLIB]: dylib,
|
|
920
|
-
|
|
921
|
-
[CMD.SUB_FRAMEWORK]: str,
|
|
922
|
-
[CMD.SUB_UMBRELLA]: str,
|
|
923
|
-
[CMD.SUB_CLIENT]: str,
|
|
924
|
-
[CMD.SUB_LIBRARY]: str,
|
|
925
|
-
[CMD.LOAD_DYLINKER]: str,
|
|
926
|
-
[CMD.ID_DYLINKER]: str,
|
|
927
|
-
[CMD.DYLD_ENVIRONMENT]: str,
|
|
928
|
-
[CMD.RPATH]: str,
|
|
929
|
-
|
|
930
|
-
[CMD.PREBOUND_DYLIB]: {
|
|
931
|
-
name: str,
|
|
932
|
-
nmodules: uint32,
|
|
933
|
-
linked_modules: str,
|
|
934
|
-
},
|
|
935
|
-
|
|
936
|
-
[CMD.THREAD]: thread_command,
|
|
937
|
-
[CMD.UNIXTHREAD]: thread_command,
|
|
938
|
-
|
|
939
|
-
[CMD.ROUTINES]: routines(32),
|
|
940
|
-
[CMD.ROUTINES_64]: routines(64),
|
|
941
|
-
|
|
942
|
-
[CMD.SYMTAB]: symtab,
|
|
943
|
-
|
|
944
|
-
[CMD.TWOLEVEL_HINTS]: count_table(hint),
|
|
945
|
-
|
|
946
|
-
[CMD.PREBIND_CKSUM]: {
|
|
947
|
-
cksum: uint32,
|
|
948
|
-
},
|
|
949
|
-
|
|
950
|
-
[CMD.UUID]: {
|
|
951
|
-
uuid: binary.Buffer(16),
|
|
952
|
-
},
|
|
953
|
-
|
|
954
|
-
[CMD.CODE_SIGNATURE]: blob,
|
|
955
|
-
[CMD.SEGMENT_SPLIT_INFO]: blob,
|
|
956
|
-
[CMD.FUNCTION_STARTS]: blobArray(binary.ULEB128),
|
|
957
|
-
[CMD.DATA_IN_CODE]: blobArray(data_in_code_entry),
|
|
958
|
-
[CMD.DYLIB_CODE_SIGN_DRS]: blob,
|
|
959
|
-
[CMD.LINKER_OPTIMIZATION_HINT]: blob,
|
|
960
|
-
[CMD.DYLD_EXPORTS_TRIE]: blob,
|
|
961
|
-
[CMD.DYLD_CHAINED_FIXUPS]: blob,//blobT(dyld_chained_fixups),
|
|
962
|
-
|
|
963
|
-
[CMD.ENCRYPTION_INFO]: {
|
|
964
|
-
cryptoff: uint32, // file offset of encrypted range
|
|
965
|
-
cryptsize: uint32, // file size of encrypted range
|
|
966
|
-
cryptid: uint32, // which enryption system, 0 means not-encrypted yet
|
|
967
|
-
},
|
|
968
|
-
[CMD.ENCRYPTION_INFO_64]: {
|
|
969
|
-
cryptoff: uint32, // file offset of encrypted range
|
|
970
|
-
cryptsize: uint32, // file size of encrypted range
|
|
971
|
-
cryptid: uint32, // which enryption system, 0 means not-encrypted yet
|
|
972
|
-
pad: uint32, // must be zero
|
|
973
|
-
},
|
|
974
|
-
|
|
975
|
-
[CMD.VERSION_MIN_MACOSX]: version_min,
|
|
976
|
-
[CMD.VERSION_MIN_IPHONEOS]: version_min,
|
|
977
|
-
[CMD.VERSION_MIN_TVOS]: version_min,
|
|
978
|
-
[CMD.VERSION_MIN_WATCHOS]: version_min,
|
|
979
|
-
|
|
980
|
-
[CMD.DYLD_INFO]: dyldinfo,
|
|
981
|
-
[CMD.DYLD_INFO_ONLY]: dyldinfo,
|
|
982
|
-
|
|
983
|
-
[CMD.SYMSEG]: blob,//OBSOLETE
|
|
984
|
-
|
|
985
|
-
// [CMD.IDENT]: {},//OBSOLETE
|
|
986
|
-
|
|
987
|
-
[CMD.FVMFILE]: {//OBSOLETE
|
|
988
|
-
name: str,
|
|
989
|
-
header_addr: uint32,
|
|
990
|
-
},
|
|
991
|
-
|
|
992
|
-
[CMD.MAIN]: {
|
|
993
|
-
entryoff: uint32, // file (__TEXT) offset of entry point
|
|
994
|
-
stacksize: uint32, // if not zero, initialize stack size
|
|
995
|
-
},
|
|
996
|
-
|
|
997
|
-
[CMD.SOURCE_VERSION]: {
|
|
998
|
-
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
|
|
999
|
-
},
|
|
1000
|
-
[CMD.BUILD_VERSION]: {
|
|
1001
|
-
platform: binary.asEnum(uint32, PLATFORM),
|
|
1002
|
-
minos: version,
|
|
1003
|
-
sdk: version,
|
|
1004
|
-
tools: binary.objectWithNames(binary.ArrayType(uint32, {tool: binary.as(uint32, binary.Enum(TOOL)), version}), binary.field('tool')),
|
|
1005
|
-
},
|
|
1006
|
-
[CMD.LINKER_OPTION]: {
|
|
1007
|
-
count: uint32, // number of strings following
|
|
1008
|
-
},
|
|
1009
|
-
[CMD.NOTE]: {
|
|
1010
|
-
data_owner: fixed_string16, // owner name for this LC_NOTE
|
|
1011
|
-
data: blob
|
|
1012
|
-
},
|
|
1013
|
-
// [CMD.PREPAGE]: {},
|
|
1014
|
-
[CMD.DYSYMTAB]: {
|
|
1015
|
-
localsym: index_table, // local symbols
|
|
1016
|
-
extdefsym: index_table, // externally defined symbols
|
|
1017
|
-
undefsym: index_table, // undefined symbols
|
|
1018
|
-
toc: count_table(toc_entry), // table of contents
|
|
1019
|
-
modtab: count_table(module(64)), // module table
|
|
1020
|
-
extrefsym: count_table(symbol_ref), // referenced symbol table
|
|
1021
|
-
indirectsym: count_table(symbol_ref), // indirect symbol table
|
|
1022
|
-
extrel: count_table({address:uint32, symbol_ref}), // external relocation entries
|
|
1023
|
-
locrel: count_table({address:uint32, symbol_ref}), // local relocation entries
|
|
1024
|
-
},
|
|
1025
|
-
};
|
|
1026
|
-
|
|
1027
|
-
export class MachFile {
|
|
1028
|
-
header: any;
|
|
1029
|
-
commands:{cmd:CMD, data:any}[] = [];
|
|
1030
|
-
ready: Promise<void>;
|
|
1031
|
-
|
|
1032
|
-
static check(data: Uint8Array): boolean {
|
|
1033
|
-
switch (binary.UINT32_BE.get(new binary.stream(data))) {
|
|
1034
|
-
case 0xfeedface:
|
|
1035
|
-
case 0xcefaedfe:
|
|
1036
|
-
case 0xfeedfacf:
|
|
1037
|
-
case 0xcffaedfe:
|
|
1038
|
-
return true;
|
|
1039
|
-
default:
|
|
1040
|
-
return false;
|
|
1041
|
-
}
|
|
1042
|
-
}
|
|
1043
|
-
|
|
1044
|
-
constructor(data: Uint8Array, mem?: binary.memory) {
|
|
1045
|
-
const magic = binary.UINT32_LE.get(new binary.stream(data));
|
|
1046
|
-
switch (magic) {
|
|
1047
|
-
case 0xfeedface: this.ready = this.load(data, false, 32, mem); break;
|
|
1048
|
-
case 0xcefaedfe: this.ready = this.load(data, true, 32, mem); break;
|
|
1049
|
-
case 0xfeedfacf: this.ready = this.load(data, false, 64, mem); break;
|
|
1050
|
-
case 0xcffaedfe: this.ready = this.load(data, true, 64, mem); break;
|
|
1051
|
-
default: throw new Error('not a mach file');
|
|
1052
|
-
}
|
|
1053
|
-
}
|
|
1054
|
-
|
|
1055
|
-
async load(data: Uint8Array, be: boolean, bits: 32|64, mem?: binary.memory) {
|
|
1056
|
-
const file = new binary.endianStream(data, be);
|
|
1057
|
-
const h = binary.read(file, header);
|
|
1058
|
-
const cpu = CPU_TYPE[h.cputype as keyof typeof CPU_TYPE];
|
|
1059
|
-
h.cpusubtype = binary.Enum(CPU_SUBTYPES[cpu])(+h.cpusubtype);
|
|
1060
|
-
if (bits === 64)
|
|
1061
|
-
file.skip(4);
|
|
1062
|
-
|
|
1063
|
-
for (let i = 0; i < h.ncmds; ++i) {
|
|
1064
|
-
const cmd = binary.read(file, command);
|
|
1065
|
-
const file2 = new mach_stream(data, file.read_buffer(cmd.cmdsize - 8), file.be, mem);
|
|
1066
|
-
const result = await binary.read(file2, cmd_table[cmd.cmd] ?? {});
|
|
1067
|
-
this.commands.push({cmd: cmd.cmd, data: result});
|
|
1068
|
-
}
|
|
1069
|
-
this.header = h;
|
|
1070
|
-
|
|
1071
|
-
const funcs = this.getCommand(CMD.FUNCTION_STARTS);
|
|
1072
|
-
if (funcs) {
|
|
1073
|
-
const array = funcs.contents;
|
|
1074
|
-
const text = await this.getSegment('__TEXT');
|
|
1075
|
-
let acc = BigInt(text?.vmaddr ?? 0);
|
|
1076
|
-
for (const i in array)
|
|
1077
|
-
array[i] = (acc += BigInt(array[i]));
|
|
1078
|
-
}
|
|
1079
|
-
}
|
|
1080
|
-
|
|
1081
|
-
getCommand<T extends CMD>(cmd: T) : binary.ReadType<typeof cmd_table[T]>;
|
|
1082
|
-
getCommand(cmd: CMD) {
|
|
1083
|
-
for (const i of this.commands) {
|
|
1084
|
-
if (i.cmd === cmd)
|
|
1085
|
-
return i.data;
|
|
1086
|
-
}
|
|
1087
|
-
}
|
|
1088
|
-
|
|
1089
|
-
getSegment(name: string) {
|
|
1090
|
-
for (const i of this.commands) {
|
|
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]>;;
|
|
1095
|
-
}
|
|
1096
|
-
}
|
|
1097
|
-
}
|
|
1098
|
-
|
|
1099
|
-
const FAT_MAGIC = 0xcafebabe;
|
|
1100
|
-
const FAT_CIGAM = 0xbebafeca;
|
|
1101
|
-
|
|
1102
|
-
export class FATMachFile {
|
|
1103
|
-
archs: binary.ReadType<typeof fat_arch>[] = [];
|
|
1104
|
-
|
|
1105
|
-
static check(data: Uint8Array): boolean {
|
|
1106
|
-
switch (binary.UINT32_BE.get(new binary.stream(data))) {
|
|
1107
|
-
case FAT_MAGIC:
|
|
1108
|
-
case FAT_CIGAM:
|
|
1109
|
-
return true;
|
|
1110
|
-
default:
|
|
1111
|
-
return false;
|
|
1112
|
-
}
|
|
1113
|
-
}
|
|
1114
|
-
|
|
1115
|
-
constructor(data: Uint8Array, mem?: binary.memory) {
|
|
1116
|
-
switch (binary.UINT32_BE.get(new binary.stream(data))) {
|
|
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;
|
|
1119
|
-
default:
|
|
1120
|
-
throw new Error('not a fat mach file');
|
|
1121
|
-
}
|
|
1122
|
-
}
|
|
1123
|
-
|
|
1124
|
-
load(file: binary.endianStream, mem?: binary.memory) {
|
|
1125
|
-
const header = binary.read(file, fat_header);
|
|
1126
|
-
this.archs = header.archs;
|
|
1127
|
-
for (const arch of header.archs) {
|
|
1128
|
-
const cpu = CPU_TYPE[arch.cputype as keyof typeof CPU_TYPE];
|
|
1129
|
-
const data = file.buffer_at(arch.offset, arch. size);
|
|
1130
|
-
arch.cpusubtype = binary.Enum(CPU_SUBTYPES[cpu])(+arch.cpusubtype);
|
|
1131
|
-
arch.contents = new MachFile(data, mem);
|
|
1132
|
-
}
|
|
1133
|
-
}
|
|
1134
|
-
}
|
|
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
|
-
*/
|