mirror of
https://github.com/ThatGuySam/doesitarm.git
synced 2026-05-18 06:44:46 -07:00
141 lines
4.5 KiB
JavaScript
141 lines
4.5 KiB
JavaScript
import { Buffer } from 'buffer/'
|
|
|
|
import { Parser as MachoNodeParser } from './macho-node/parser.js'
|
|
|
|
function makeFileBuffer ( buffer ) {
|
|
const fileBuffer = new Buffer.alloc( buffer.byteLength )
|
|
|
|
for (var i = 0; i < buffer.length; i++)
|
|
fileBuffer[i] = buffer[i];
|
|
|
|
return fileBuffer
|
|
}
|
|
|
|
const machoNodeParser = new MachoNodeParser()
|
|
|
|
// Tends to not support universal architecture
|
|
// but support some MachoManiac doesn't and fails faster
|
|
// so we run it first
|
|
// https://github.com/indutny/macho
|
|
export class MachoNode {
|
|
constructor ({ machoFileInstance, FileApi }) {
|
|
this.machoFileInstance = machoFileInstance
|
|
this.FileApi = FileApi
|
|
}
|
|
|
|
// MachNode cpu types mapped to MachoManiac cpu types
|
|
// MachoNode types - https://github.com/indutny/macho/blob/c9d02419b36a468ebb4dcef66d0f9b98b6f22dbd/lib/macho/constants.js#L9
|
|
// MachoManiac types - https://github.com/MTJailed/MachoManiac/blob/98d2d31d38d3ea3c911468181eed6e5f445eb556/macho.cpu.js#L13
|
|
cpuMap = new Map([
|
|
['vax', 'VAX'],
|
|
['mc680x0', 'MC680'],
|
|
// https://superuser.com/a/74354/412612
|
|
['i386', 'X86'],
|
|
['x86_64', 'X86'],
|
|
['mc98000', 'MC98000'],
|
|
['hppa', 'HPPA'],
|
|
['arm', 'ARM'],
|
|
['arm64', 'ARM64'],
|
|
// arm64_32 is a variant of arm64 with 32-bit pointer sizes, used on Apple Watch Series 4 and later.
|
|
// https://stackoverflow.com/a/68248923/1397641
|
|
['arm64_32', 'ARM64'],
|
|
['mc88000', 'MC88000'],
|
|
['sparc', 'SPARC'],
|
|
['i860', 'I860'],
|
|
// ['alpha', '???']
|
|
['powerpc', 'POWERPC'],
|
|
['powerpc64', 'POWERPC64']
|
|
])
|
|
|
|
mapNodeMetaTOManiacMeta ( machoNodeMeta ) {
|
|
|
|
return {
|
|
// Single entry since MachoNode doesn't support universal architectures
|
|
architectures: [{
|
|
bits: machoNodeMeta.bits,
|
|
fileType: machoNodeMeta.filetype,
|
|
// header: architecture.header,
|
|
// loadCommandsInfo: architecture.loadCommandsInfo,
|
|
magic: machoNodeMeta.magic,
|
|
// offset: architecture.offset,
|
|
processorSubType: machoNodeMeta.subtype,
|
|
processorType: this.cpuMap.get( machoNodeMeta.cpu.type ),
|
|
}]
|
|
}
|
|
}
|
|
|
|
async run () {
|
|
|
|
// console.log( 'this.machoFileInstance.buffer.readUInt32LE(0)', this.machoFileInstance.buffer.readUInt32LE(0).toString(16), 4277009103 )
|
|
|
|
const machoNodeMeta = machoNodeParser.execute( this.machoFileInstance.buffer )
|
|
|
|
return this.mapNodeMetaTOManiacMeta( machoNodeMeta )
|
|
}
|
|
}
|
|
|
|
|
|
// https://github.com/MTJailed/MachoManiac
|
|
export class MachoManiac {
|
|
constructor ({ machoFileInstance, FileApi }) {
|
|
this.machoFileInstance = machoFileInstance
|
|
this.FileApi = FileApi
|
|
}
|
|
|
|
async run () {
|
|
// import parseMacho from '~/helpers/macho/index.js'
|
|
const { default: parseMacho } = await import( '~/helpers/macho/index.js' )
|
|
|
|
const contextHasFileGlobal = typeof File === 'function'
|
|
|
|
// In the Browser, MachManiac uses the File API to read the file
|
|
// so we check if the global File API is available and convert our machoFileInstance to File API
|
|
//
|
|
// In the NodeJS environment, MachManiac uses the FileApi module to read the file
|
|
// so we pass through the machoFileInstance as is
|
|
const fileInstance = contextHasFileGlobal ? (new File( [this.machoFileInstance.blob], 'App' )) : this.machoFileInstance
|
|
|
|
return await parseMacho( fileInstance, this.FileApi )
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function extractMachoMeta ({ machoFileInstance, FileApi = null }) {
|
|
const parsers = [
|
|
MachoNode,
|
|
MachoManiac
|
|
]
|
|
|
|
// Run through each parser
|
|
for ( const Parser of parsers ) {
|
|
console.log( 'Trying parser', Parser.name )
|
|
|
|
try {
|
|
const parserTimeout = setTimeout(() => {
|
|
throw new Error( 'Timed out' )
|
|
}, 60 * 1000 )
|
|
|
|
// Run the parser
|
|
const parserInstance = new Parser({
|
|
machoFileInstance,
|
|
FileApi
|
|
})
|
|
const meta = await parserInstance.run()
|
|
|
|
// Clear the timeout
|
|
clearTimeout( parserTimeout )
|
|
|
|
return meta
|
|
} catch ( err ) {
|
|
console.log( 'Macho parser failed', Parser, err.message.substring(0,100) )
|
|
|
|
continue
|
|
|
|
// throw new Error( 'Macho parser failed' )
|
|
}
|
|
}
|
|
|
|
return null
|
|
}
|