如何用Python 3.1.1获取dll的目标平台信息?
我有很多dll文件,我想把它们分到两个不同的文件夹里(一个是PC,一个是PPC)。为此,我需要知道每个dll文件的目标平台或者其他一些关于它们平台的详细信息。
我使用的是Python 3.1.1。我尝试过使用win32api,但这个版本的Python不支持它。所以,我试着用ctypes.windll配合try-except的方法:如果try成功了,说明加载的dll是“PC”的;如果失败了,就说明是“PPC”的。但是,这个想法遇到了一些问题。
有些dll文件我知道是“PC”的,但却无法加载到内存中。对于这些文件,try-except的方法不起作用。所以,我需要从dll文件中请求关于它自身目标平台的信息。
你对这个问题有什么想法吗?
非常感谢。
1 个回答
1
我找到了一种基于dll文件结构的解决方案。下面是我代码的一部分:
def DLLIdentifier( self ):
'''
Microsoft Portable Executable and Common Object File Format Specification
http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx
After the MS DOS stub, at the file offset specified at offset 0x3c,
is a 4-byte signature that identifies the file as a PE format image file.
This signature is "PE\0\0" (the letters "P" and "E" followed by two null bytes).
At the beginning of an object file, or immediately after the signature of an image file,
is a standard COFF file header in the following format.
Note that the Windows loader limits the number of sections to 96.
The Machine field has one of the following values that specifies its CPU type.
An image file can be run only on the specified machine or on a system that emulates the specified machine.
'''
Platform = 'UNKNOWN'
for Row in codecs.open( os.path.join( self.Root, self.File ), 'rb' ):
if b'\x00PE\x00\x00' in Row:
# IMAGE_FILE_MACHINE_UNKNOWN 0x0 The contents of this field are assumed to be applicable to any machine type
if b'\x00PE\x00\x00\x00\x00' in Row:
Platform = 'UNKNOWN'
break
# IMAGE_FILE_MACHINE_AM33 0x1d3 Matsushita AM33
elif b'\x00PE\x00\x00\xD3\x01' in Row:
Platform = 'AM33'
break
# IMAGE_FILE_MACHINE_AMD64 0x8664 x64
elif b'\x00PE\x00\x00\x664\x08' in Row:
Platform = 'AMD64'
break
# IMAGE_FILE_MACHINE_ARM 0x1c0 ARM little endian
elif b'\x00PE\x00\x00\xC0\x01' in Row:
Platform = 'ARM'
break
# IMAGE_FILE_MACHINE_EBC 0xebc EFI byte code
elif b'\x00PE\x00\x00\xBC\x0E' in Row:
Platform = 'EBC'
break
# IMAGE_FILE_MACHINE_I386 0x14c Intel 386 or later processors and compatible processors
elif b'\x00PE\x00\x00\x4C\x01' in Row:
Platform = 'I386'
break
# IMAGE_FILE_MACHINE_IA64 0x200 Intel Itanium processor family
elif b'\x00PE\x00\x00\x00\x02' in Row:
Platform = 'IA64'
break
# IMAGE_FILE_MACHINE_M32R 0x9041 Mitsubishi M32R little endian
elif b'\x00PE\x00\x00\x041\x09' in Row:
Platform = 'M32R'
break
# IMAGE_FILE_MACHINE_MIPS16 0x266 MIPS16
elif b'\x00PE\x00\x00\x66\x02' in Row:
Platform = 'MIPS16'
break
# IMAGE_FILE_MACHINE_MIPSFPU 0x366 MIPS with FPU
elif b'\x00PE\x00\x00\x66\x03' in Row:
Platform = 'MIPSFPU'
break
# IMAGE_FILE_MACHINE_MIPSFPU16 0x466 MIPS16 with FPU
elif b'\x00PE\x00\x00\x66\x04' in Row:
Platform = 'MIPSFPU16'
break
# IMAGE_FILE_MACHINE_POWERPC 0x1f0 Power PC little endian
elif b'\x00PE\x00\x00\xF0\x01' in Row:
Platform = 'POWERPC'
break
# IMAGE_FILE_MACHINE_POWERPCFP 0x1f1 Power PC with floating point support
elif b'\x00PE\x00\x00\xF1\x01' in Row:
Platform = 'POWERPCFP'
break
# IMAGE_FILE_MACHINE_R4000 0x166 MIPS little endian
elif b'\x00PE\x00\x00\x66\x01' in Row:
Platform = 'R4000'
break
# IMAGE_FILE_MACHINE_SH3 0x1a2 Hitachi SH3
elif b'\x00PE\x00\x00\xA2\x01' in Row:
Platform = 'SH3'
break
# IMAGE_FILE_MACHINE_SH3DSP 0x1a3 Hitachi SH3 DSP
elif b'\x00PE\x00\x00\xA3\x01' in Row:
Platform = 'SH3DSP'
break
# IMAGE_FILE_MACHINE_SH4 0x1a6 Hitachi SH4
elif b'\x00PE\x00\x00\xA6\x01' in Row:
Platform = 'SH4'
break
# IMAGE_FILE_MACHINE_SH5 0x1a8 Hitachi SH5
elif b'\x00PE\x00\x00\xA8\x01' in Row:
Platform = 'SH5'
break
# IMAGE_FILE_MACHINE_THUMB 0x1c2 Thumb
elif b'\x00PE\x00\x00\xC2\x01' in Row:
Platform = 'THUMB'
break
# IMAGE_FILE_MACHINE_WCEMIPSV2 0x169 MIPS little - endian WCE v2
elif b'\x00PE\x00\x00\x69\x01' in Row:
Platform = 'WCEMIPSV2'
break
else:
StartIndex = Row.find( b'\x00PE\x00\x00' )
EndIndex = StartIndex + 7
PlatformCode = Row[StartIndex:EndIndex]
self.ErrorState = False
self.oLogger.critical( 'The unknown platform code is "{}".'.format( PlatformCode ) )
assert Platform != 'UNKNOWN', 'Unknown .dll file "{}" at\n{}'.format( self.File, os.path.join( self.Root, self.File ) )
if Platform == 'I386':
self.PlatformType = 'PC'
elif Platform in ( 'ARM', 'THUMB' ):
self.PlatformType = 'PPC'
else:
self.ErrorState = False
self.oLogger.critical( 'The unknown dll file with "{}" platform code.'.format( Platform ) )