1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
|
#
# Copyright © 2022 pastdue ( https://github.com/past-due/ ) and contributors
# License: MIT License ( https://opensource.org/licenses/MIT )
#
# Script Version: 2022-10-12a
#
function(get_pe_file_machine_raw_bytes filename outputvar)
set(_dos_header_length_bytes 64)
# read the only bytes from IMAGE_DOS_HEADER we care about
file(READ "${filename}" _dos_header LIMIT ${_dos_header_length_bytes} HEX)
# magic - "MZ"
string(SUBSTRING "${_dos_header}" 0 4 _dos_magic_hex)
if (NOT _dos_magic_hex STREQUAL "4d5a") # "MZ"
message(WARNING "Missing \"MZ\" start to dos header: ${filename}")
set(${outputvar} FALSE)
return()
endif()
# pe offset
string(SUBSTRING "${_dos_header}" 120 2 _offset_hex_nib1)
string(SUBSTRING "${_dos_header}" 122 2 _offset_hex_nib2)
string(SUBSTRING "${_dos_header}" 124 2 _offset_hex_nib3)
string(SUBSTRING "${_dos_header}" 126 2 _offset_hex_nib4)
set(_offset_hex "${_offset_hex_nib4}${_offset_hex_nib3}${_offset_hex_nib2}${_offset_hex_nib1}")
math(EXPR _pe_offset "0x${_offset_hex}" OUTPUT_FORMAT DECIMAL)
# read the first 6 bytes of the PE header (DWORD Signature + WORD Machine)
file(READ "${filename}" _pe_header_start OFFSET ${_pe_offset} LIMIT 6 HEX)
string(SUBSTRING "${_pe_header_start}" 0 4 _pe_sig_hex)
if (NOT _pe_sig_hex STREQUAL "5045") # "PE"
message(WARNING "Missing \"PE\" signature to start PE header (got: ${_pe_sig_hex}): ${filename}")
set(${outputvar} FALSE)
return()
endif()
# get the bytes of the machine word (as hex)
string(SUBSTRING "${_pe_header_start}" 8 4 _machine_bytes_hex)
set(${outputvar} "${_machine_bytes_hex}" PARENT_SCOPE)
endfunction()
function(pe_file_machine_raw_bytes_to_arch machine_bytes_hex outputvar)
# See: https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#machine-types
if (machine_bytes_hex STREQUAL "4c01")
set(${outputvar} "i386" PARENT_SCOPE)
elseif (machine_bytes_hex STREQUAL "6486")
set(${outputvar} "amd64" PARENT_SCOPE)
elseif (machine_bytes_hex STREQUAL "64aa")
set(${outputvar} "arm64" PARENT_SCOPE)
else()
message(STATUS "Unknown arch: machine_bytes_hex (raw bytes as hex)")
set(${outputvar} "unknown" PARENT_SCOPE)
endif()
endfunction()
# GET_PE_FILE_ARCH( <filename> <outputvar> )
#
# Read and parse the Machine field of the PE file header to get a "pretty" machine type.
#
# Currently supports:
# - "i386"
# - "amd64"
# - "arm64"
#
# or "unknown"
#
function(get_pe_file_arch filename outputvar)
# get the bytes of the machine word (as hex)
get_pe_file_machine_raw_bytes("${filename}" _machine_bytes_hex)
pe_file_machine_raw_bytes_to_arch("${_machine_bytes_hex}" ${outputvar})
endfunction()
|