source: gs2-extensions/parallel-building/trunk/src/perllib/cpan/Image/ExifTool/EXE.pm@ 24626

Last change on this file since 24626 was 24626, checked in by jmt12, 13 years ago

An (almost) complete copy of the perllib directory from a (circa SEP2011) head checkout from Greenstone 2 trunk - in order to try and make merging in this extension a little easier later on (as there have been some major changes to buildcol.pl commited in the main trunk but not in the x64 branch)

  • Property svn:executable set to *
File size: 41.7 KB
Line 
1#------------------------------------------------------------------------------
2# File: EXE.pm
3#
4# Description: Read meta information of various executable file formats
5#
6# Revisions: 2008/08/28 - P. Harvey Created
7#
8# References: 1) http://www.openwatcom.org/ftp/devel/docs/pecoff.pdf
9# 2) http://support.microsoft.com/kb/65122
10# 3) http://www.opensource.apple.com
11# 4) http://www.skyfree.org/linux/references/ELF_Format.pdf
12# 5) http://msdn.microsoft.com/en-us/library/ms809762.aspx
13# 6) http://code.google.com/p/pefile/
14# 7) http://www.codeproject.com/KB/DLL/showver.aspx
15#------------------------------------------------------------------------------
16
17package Image::ExifTool::EXE;
18
19use strict;
20use vars qw($VERSION);
21use Image::ExifTool qw(:DataAccess :Utils);
22
23$VERSION = '1.04';
24
25sub ProcessPEResources($$);
26sub ProcessPEVersion($$);
27
28# PE file resource types (ref 6)
29my %resourceType = (
30 1 => 'Cursor',
31 2 => 'Bitmap',
32 3 => 'Icon',
33 4 => 'Menu',
34 5 => 'Dialog',
35 6 => 'String',
36 7 => 'Font Dir',
37 8 => 'Font',
38 9 => 'Accelerator',
39 10 => 'RC Data',
40 11 => 'Message Table',
41 12 => 'Group Cursor',
42 14 => 'Group Icon',
43 16 => 'Version',
44 17 => 'Dialog Include',
45 19 => 'Plug-n-Play',
46 20 => 'VxD',
47 21 => 'Animated Cursor',
48 22 => 'Animated Icon',
49 23 => 'HTML',
50 24 => 'Manifest',
51);
52
53# Information extracted from PE COFF (Windows EXE) file header
54%Image::ExifTool::EXE::Main = (
55 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
56 GROUPS => { 2 => 'Other' },
57 FORMAT => 'int16u',
58 NOTES => q{
59 This module extracts information from various types of Windows, MacOS and
60 Unix executable and library files. The first table below lists information
61 extracted from the header of Windows PE (Portable Executable) EXE files and
62 DLL libraries.
63 },
64 0 => {
65 Name => 'MachineType',
66 PrintHex => 1,
67 PrintConv => {
68 0x014c => 'Intel 386 or later, and compatibles',
69 0x014d => 'Intel i860', #5
70 0x0162 => 'MIPS R3000',
71 0x0166 => 'MIPS little endian (R4000)',
72 0x0168 => 'MIPS R10000',
73 0x0169 => 'MIPS little endian WCI v2',
74 0x0183 => 'Alpha AXP (old)', #5
75 0x0184 => 'Alpha AXP',
76 0x01a2 => 'Hitachi SH3',
77 0x01a3 => 'Hitachi SH3 DSP',
78 0x01a6 => 'Hitachi SH4',
79 0x01a8 => 'Hitachi SH5',
80 0x01c0 => 'ARM little endian',
81 0x01c2 => 'Thumb',
82 0x01d3 => 'Matsushita AM33',
83 0x01f0 => 'PowerPC little endian',
84 0x01f1 => 'PowerPC with floating point support',
85 0x0200 => 'Intel IA64',
86 0x0266 => 'MIPS16',
87 0x0268 => 'Motorola 68000 series',
88 0x0284 => 'Alpha AXP 64-bit',
89 0x0366 => 'MIPS with FPU',
90 0x0466 => 'MIPS16 with FPU',
91 0x0ebc => 'EFI Byte Code',
92 0x8664 => 'AMD AMD64',
93 0x9041 => 'Mitsubishi M32R little endian',
94 0xc0ee => 'clr pure MSIL',
95 },
96 },
97 2 => {
98 Name => 'TimeStamp',
99 Format => 'int32u',
100 Groups => { 2 => 'Time' },
101 ValueConv => 'ConvertUnixTime($val,1)',
102 PrintConv => '$self->ConvertDateTime($val)',
103 },
104 10 => {
105 Name => 'PEType',
106 PrintHex => 1,
107 PrintConv => {
108 0x10b => 'PE32',
109 0x20b => 'PE32+',
110 },
111 },
112 11 => {
113 Name => 'LinkerVersion',
114 Format => 'int8u[2]',
115 ValueConv => '$val=~tr/ /./; $val',
116 },
117 12 => {
118 Name => 'CodeSize',
119 Format => 'int32u',
120 },
121 14 => {
122 Name => 'InitializedDataSize',
123 Format => 'int32u',
124 },
125 16 => {
126 Name => 'UninitializedDataSize',
127 Format => 'int32u',
128 },
129 18 => {
130 Name => 'EntryPoint',
131 Format => 'int32u',
132 PrintConv => 'sprintf("0x%.4x", $val)',
133 },
134 30 => {
135 Name => 'OSVersion',
136 Format => 'int16u[2]',
137 ValueConv => '$val=~tr/ /./; $val',
138 },
139 32 => {
140 Name => 'ImageVersion',
141 Format => 'int16u[2]',
142 ValueConv => '$val=~tr/ /./; $val',
143 },
144 34 => {
145 Name => 'SubsystemVersion',
146 Format => 'int16u[2]',
147 ValueConv => '$val=~tr/ /./; $val',
148 },
149 44 => {
150 Name => 'Subsystem',
151 PrintConv => {
152 0 => 'Unknown',
153 1 => 'Native',
154 2 => 'Windows GUI',
155 3 => 'Windows command line',
156 5 => 'OS/2 Command line', #5
157 7 => 'POSIX command line',
158 9 => 'Windows CE GUI',
159 10 => 'EFI application',
160 11 => 'EFI boot service',
161 12 => 'EFI runtime driver',
162 13 => 'EFI ROM', #6
163 14 => 'XBOX', #6
164 },
165 },
166);
167
168# PE file version information (ref 6)
169%Image::ExifTool::EXE::PEVersion = (
170 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
171 GROUPS => { 2 => 'Other' },
172 FORMAT => 'int32u',
173 NOTES => q{
174 Information extracted from the VS_VERSION_INFO structure of Windows PE
175 files.
176 },
177 # (boring -- always 0xfeef04bd)
178 #0 => {
179 # Name => 'Signature',
180 # PrintConv => 'sprintf("0x%.4x",$val)',
181 #},
182 # (boring -- always 1.0)
183 #1 => {
184 # Name => 'StructVersion',
185 # Format => 'int16u[2]',
186 # ValueConv => 'my @a=split(" ",$val); "$a[1].$a[0]"',
187 #},
188 2 => {
189 Name => 'FileVersionNumber',
190 Format => 'int16u[4]',
191 ValueConv => 'my @a=split(" ",$val); "$a[1].$a[0].$a[3].$a[2]"',
192 },
193 4 => {
194 Name => 'ProductVersionNumber',
195 Format => 'int16u[4]',
196 ValueConv => 'my @a=split(" ",$val); "$a[1].$a[0].$a[3].$a[2]"',
197 },
198 6 => {
199 Name => 'FileFlagsMask',
200 PrintConv => 'sprintf("0x%.4x",$val)',
201 },
202 7 => { # ref Cygwin /usr/include/w32api/winver.h
203 Name => 'FileFlags',
204 PrintConv => { BITMASK => {
205 0 => 'Debug',
206 1 => 'Pre-release',
207 2 => 'Patched',
208 3 => 'Private build',
209 4 => 'Info inferred',
210 5 => 'Special build',
211 }},
212 },
213 8 => {
214 Name => 'FileOS',
215 PrintHex => 1,
216 PrintConv => { # ref Cygwin /usr/include/w32api/winver.h
217 0x00001 => 'Win16',
218 0x00002 => 'PM-16',
219 0x00003 => 'PM-32',
220 0x00004 => 'Win32',
221 0x10000 => 'DOS',
222 0x20000 => 'OS/2 16-bit',
223 0x30000 => 'OS/2 32-bit',
224 0x40000 => 'Windows NT',
225 0x10001 => 'Windows 16-bit',
226 0x10004 => 'Windows 32-bit',
227 0x20002 => 'OS/2 16-bit PM-16',
228 0x30003 => 'OS/2 32-bit PM-32',
229 0x40004 => 'Windows NT 32-bit',
230 },
231 },
232 9 => { # ref Cygwin /usr/include/w32api/winver.h
233 Name => 'ObjectFileType',
234 PrintConv => {
235 0 => 'Unknown',
236 1 => 'Executable application',
237 2 => 'Dynamic link library',
238 3 => 'Driver',
239 4 => 'Font',
240 5 => 'VxD',
241 7 => 'Static library',
242 },
243 },
244 10 => 'FileSubtype',
245 # (these are usually zero, so ignore them)
246 # 11 => 'FileDateMS',
247 # 12 => 'FileDateLS',
248);
249
250# Windows PE StringFileInfo resource strings
251# (see http://msdn.microsoft.com/en-us/library/aa381049.aspx)
252%Image::ExifTool::EXE::PEString = (
253 GROUPS => { 2 => 'Other' },
254 VARS => { NO_ID => 1 },
255 NOTES => q{
256 Resource strings found in Windows PE files. The B<TagID>'s are not shown
257 because they are the same as the B<Tag Name>. ExifTool will extract any
258 existing StringFileInfo tags even if not listed in this table.
259 },
260 LanguageCode => {
261 Notes => 'extracted from the StringFileInfo value',
262 # ref http://techsupt.winbatch.com/TS/T000001050F49.html
263 # (also see http://support.bigfix.com/fixlet/documents/WinInspectors-2006-08-10.pdf)
264 # (also see ftp://ftp.dyu.edu.tw/pub/cpatch/faq/tech/tech_nlsnt.txt)
265 # (not a complete set)
266 PrintString => 1,
267 PrintConv => {
268 '0000' => 'Neutral',
269 '007F' => 'Invariant',
270 '0400' => 'Process default',
271 '0401' => 'Arabic',
272 '0402' => 'Bulgarian',
273 '0403' => 'Catalan',
274 '0404' => 'Chinese (Traditional)',
275 '0405' => 'Czech',
276 '0406' => 'Danish',
277 '0407' => 'German',
278 '0408' => 'Greek',
279 '0409' => 'English (U.S.)',
280 '040A' => 'Spanish (Castilian)',
281 '040B' => 'Finnish',
282 '040C' => 'French',
283 '040D' => 'Hebrew',
284 '040E' => 'Hungarian',
285 '040F' => 'Icelandic',
286 '0410' => 'Italian',
287 '0411' => 'Japanese',
288 '0412' => 'Korean',
289 '0413' => 'Dutch',
290 '0414' => 'Norwegian (Bokml)',
291 '0415' => 'Polish',
292 '0416' => 'Portuguese (Brazilian)',
293 '0417' => 'Rhaeto-Romanic',
294 '0418' => 'Romanian',
295 '0419' => 'Russian',
296 '041A' => 'Croato-Serbian (Latin)',
297 '041B' => 'Slovak',
298 '041C' => 'Albanian',
299 '041D' => 'Swedish',
300 '041E' => 'Thai',
301 '041F' => 'Turkish',
302 '0420' => 'Urdu',
303 # 0421-0493 ref 6
304 '0421' => 'Indonesian',
305 '0422' => 'Ukrainian',
306 '0423' => 'Belarusian',
307 '0424' => 'Slovenian',
308 '0425' => 'Estonian',
309 '0426' => 'Latvian',
310 '0427' => 'Lithuanian',
311 '0428' => 'Maori',
312 '0429' => 'Farsi',
313 '042a' => 'Vietnamese',
314 '042b' => 'Armenian',
315 '042c' => 'Azeri',
316 '042d' => 'Basque',
317 '042e' => 'Sorbian',
318 '042f' => 'Macedonian',
319 '0430' => 'Sutu',
320 '0431' => 'Tsonga',
321 '0432' => 'Tswana',
322 '0433' => 'Venda',
323 '0434' => 'Xhosa',
324 '0435' => 'Zulu',
325 '0436' => 'Afrikaans',
326 '0437' => 'Georgian',
327 '0438' => 'Faeroese',
328 '0439' => 'Hindi',
329 '043a' => 'Maltese',
330 '043b' => 'Saami',
331 '043c' => 'Gaelic',
332 '043e' => 'Malay',
333 '043f' => 'Kazak',
334 '0440' => 'Kyrgyz',
335 '0441' => 'Swahili',
336 '0443' => 'Uzbek',
337 '0444' => 'Tatar',
338 '0445' => 'Bengali',
339 '0446' => 'Punjabi',
340 '0447' => 'Gujarati',
341 '0448' => 'Oriya',
342 '0449' => 'Tamil',
343 '044a' => 'Telugu',
344 '044b' => 'Kannada',
345 '044c' => 'Malayalam',
346 '044d' => 'Assamese',
347 '044e' => 'Marathi',
348 '044f' => 'Sanskrit',
349 '0450' => 'Mongolian',
350 '0456' => 'Galician',
351 '0457' => 'Konkani',
352 '0458' => 'Manipuri',
353 '0459' => 'Sindhi',
354 '045a' => 'Syriac',
355 '0460' => 'Kashmiri',
356 '0461' => 'Nepali',
357 '0465' => 'Divehi',
358 '047f' => 'Invariant',
359 '048f' => 'Esperanto',
360 '0490' => 'Walon',
361 '0491' => 'Cornish',
362 '0492' => 'Welsh',
363 '0493' => 'Breton',
364 '0800' => 'Neutral 2',
365 '0804' => 'Chinese (Simplified)',
366 '0807' => 'German (Swiss)',
367 '0809' => 'English (British)',
368 '080A' => 'Spanish (Mexican)',
369 '080C' => 'French (Belgian)',
370 '0810' => 'Italian (Swiss)',
371 '0813' => 'Dutch (Belgian)',
372 '0814' => 'Norwegian (Nynorsk)',
373 '0816' => 'Portuguese',
374 '081A' => 'Serbo-Croatian (Cyrillic)',
375 '0C07' => 'German (Austrian)',
376 '0C09' => 'English (Australian)',
377 '0C0A' => 'Spanish (Modern)',
378 '0C0C' => 'French (Canadian)',
379 '1009' => 'English (Canadian)',
380 '100C' => 'French (Swiss)',
381 },
382 },
383 CharacterSet => {
384 Notes => 'extracted from the StringFileInfo value',
385 # ref http://techsupt.winbatch.com/TS/T000001050F49.html
386 # (also see http://blog.chinaunix.net/u1/41189/showart_345768.html)
387 PrintString => 1,
388 PrintConv => {
389 '0000' => 'ASCII',
390 '03A4' => 'Windows, Japan (Shift - JIS X-0208)', # cp932
391 '03A8' => 'Windows, Chinese (Simplified)', # cp936
392 '03B5' => 'Windows, Korea (Shift - KSC 5601)', # cp949
393 '03B6' => 'Windows, Taiwan (Big5)', # cp950
394 '04B0' => 'Unicode', # UCS-2
395 '04E2' => 'Windows, Latin2 (Eastern European)',
396 '04E3' => 'Windows, Cyrillic',
397 '04E4' => 'Windows, Latin1',
398 '04E5' => 'Windows, Greek',
399 '04E6' => 'Windows, Turkish',
400 '04E7' => 'Windows, Hebrew',
401 '04E8' => 'Windows, Arabic',
402 },
403 },
404 BuildDate => { Groups => { 2 => 'Time' } }, # (non-standard)
405 BuildVersion => { }, # (non-standard)
406 Comments => { },
407 CompanyName => { },
408 Copyright => { }, # (non-standard)
409 FileDescription => { },
410 FileVersion => { },
411 InternalName => { },
412 LegalCopyright => { },
413 LegalTrademarks => { },
414 OriginalFilename=> { },
415 PrivateBuild => { },
416 ProductName => { },
417 ProductVersion => { },
418 SpecialBuild => { },
419);
420
421# Information extracted from Mach-O (Mac OS X) file header
422%Image::ExifTool::EXE::MachO = (
423 GROUPS => { 2 => 'Other' },
424 VARS => { ID_LABEL => 'Index' },
425 NOTES => q{
426 Information extracted from Mach-O (Mac OS X) executable files and DYLIB
427 libraries.
428 },
429 # ref http://www.opensource.apple.com/darwinsource/DevToolsOct2007/cctools-622.9/include/mach/machine.h
430 0 => 'CPUArchitecture',
431 1 => 'CPUByteOrder',
432 2 => 'CPUCount',
433 # ref /System/Library/Frameworks/Kernel.framework/Versions/A/Headers/mach/machine.h
434 3 => {
435 Name => 'CPUType',
436 List => 1,
437 PrintConv => {
438 # handle 64-bit flag (0x1000000)
439 OTHER => sub {
440 my ($val, $inv, $conv) = @_;
441 my $v = $val & 0xfeffffff;
442 return $$conv{$v} ? "$$conv{$v} 64-bit" : "Unknown ($val)";
443 },
444 -1 => 'Any',
445 1 => 'VAX',
446 2 => 'ROMP',
447 4 => 'NS32032',
448 5 => 'NS32332',
449 6 => 'MC680x0',
450 7 => 'x86',
451 8 => 'MIPS',
452 9 => 'NS32532',
453 10 => 'MC98000',
454 11 => 'HPPA',
455 12 => 'ARM',
456 13 => 'MC88000',
457 14 => 'SPARC',
458 15 => 'i860 big endian',
459 16 => 'i860 little endian',
460 17 => 'RS6000',
461 18 => 'PowerPC',
462 255 => 'VEO',
463 },
464 },
465 # ref /System/Library/Frameworks/Kernel.framework/Versions/A/Headers/mach/machine.h
466 4 => {
467 Name => 'CPUSubtype',
468 List => 1,
469 PrintConv => {
470 # handle 64-bit flags on CPUType (0x1000000) and CPUSubtype (0x80000000)
471 OTHER => sub {
472 my ($val, $inv, $conv) = @_;
473 my @v = split ' ', $val;
474 my $v = ($v[0] & 0xfeffffff) . ' ' . ($v[1] & 0x7fffffff);
475 return $$conv{$v} ? "$$conv{$v} 64-bit" : "Unknown ($val)";
476 },
477 # in theory, subtype can be -1 for multiple CPU types,
478 # but in practice I'm not sure anyone uses this - PH
479 '1 0' => 'VAX (all)',
480 '1 1' => 'VAX780',
481 '1 2' => 'VAX785',
482 '1 3' => 'VAX750',
483 '1 4' => 'VAX730',
484 '1 5' => 'UVAXI',
485 '1 6' => 'UVAXII',
486 '1 7' => 'VAX8200',
487 '1 8' => 'VAX8500',
488 '1 9' => 'VAX8600',
489 '1 10' => 'VAX8650',
490 '1 11' => 'VAX8800',
491 '1 12' => 'UVAXIII',
492 '2 0' => 'RT (all)',
493 '2 1' => 'RT PC',
494 '2 2' => 'RT APC',
495 '2 3' => 'RT 135',
496 # 32032/32332/32532 subtypes.
497 '4 0' => 'NS32032 (all)',
498 '4 1' => 'NS32032 DPC (032 CPU)',
499 '4 2' => 'NS32032 SQT',
500 '4 3' => 'NS32032 APC FPU (32081)',
501 '4 4' => 'NS32032 APC FPA (Weitek)',
502 '4 5' => 'NS32032 XPC (532)',
503 '5 0' => 'NS32332 (all)',
504 '5 1' => 'NS32332 DPC (032 CPU)',
505 '5 2' => 'NS32332 SQT',
506 '5 3' => 'NS32332 APC FPU (32081)',
507 '5 4' => 'NS32332 APC FPA (Weitek)',
508 '5 5' => 'NS32332 XPC (532)',
509 '6 1' => 'MC680x0 (all)',
510 '6 2' => 'MC68040',
511 '6 3' => 'MC68030',
512 '7 3' => 'i386 (all)',
513 '7 4' => 'i486',
514 '7 132' => 'i486SX',
515 '7 5' => 'i586',
516 '7 22' => 'Pentium Pro',
517 '7 54' => 'Pentium II M3',
518 '7 86' => 'Pentium II M5',
519 '7 103' => 'Celeron',
520 '7 119' => 'Celeron Mobile',
521 '7 8' => 'Pentium III',
522 '7 24' => 'Pentium III M',
523 '7 40' => 'Pentium III Xeon',
524 '7 9' => 'Pentium M',
525 '7 10' => 'Pentium 4',
526 '7 26' => 'Pentium 4 M',
527 '7 11' => 'Itanium',
528 '7 27' => 'Itanium 2',
529 '7 12' => 'Xeon',
530 '7 28' => 'Xeon MP',
531 '8 0' => 'MIPS (all)',
532 '8 1' => 'MIPS R2300',
533 '8 2' => 'MIPS R2600',
534 '8 3' => 'MIPS R2800',
535 '8 4' => 'MIPS R2000a',
536 '8 5' => 'MIPS R2000',
537 '8 6' => 'MIPS R3000a',
538 '8 7' => 'MIPS R3000',
539 '10 0' => 'MC98000 (all)',
540 '10 1' => 'MC98601',
541 '11 0' => 'HPPA (all)',
542 '11 1' => 'HPPA 7100LC',
543 '12 0' => 'ARM (all)',
544 '12 1' => 'ARM A500 ARCH',
545 '12 2' => 'ARM A500',
546 '12 3' => 'ARM A440',
547 '12 4' => 'ARM M4',
548 '12 5' => 'ARM A680/V4T',
549 '12 6' => 'ARM V6',
550 '12 7' => 'ARM V5TEJ',
551 '12 8' => 'ARM XSCALE',
552 '12 9' => 'ARM V7',
553 '13 0' => 'MC88000 (all)',
554 '13 1' => 'MC88100',
555 '13 2' => 'MC88110',
556 '14 0' => 'SPARC (all)',
557 '14 1' => 'SUN 4/260',
558 '14 2' => 'SUN 4/110',
559 '15 0' => 'i860 (all)',
560 '15 1' => 'i860 860',
561 '16 0' => 'i860 little (all)',
562 '16 1' => 'i860 little',
563 '17 0' => 'RS6000 (all)',
564 '17 1' => 'RS6000',
565 '18 0' => 'PowerPC (all)',
566 '18 1' => 'PowerPC 601',
567 '18 2' => 'PowerPC 602',
568 '18 3' => 'PowerPC 603',
569 '18 4' => 'PowerPC 603e',
570 '18 5' => 'PowerPC 603ev',
571 '18 6' => 'PowerPC 604',
572 '18 7' => 'PowerPC 604e',
573 '18 8' => 'PowerPC 620',
574 '18 9' => 'PowerPC 750',
575 '18 10' => 'PowerPC 7400',
576 '18 11' => 'PowerPC 7450',
577 '18 100' => 'PowerPC 970',
578 '255 1' => 'VEO 1',
579 '255 2' => 'VEO 2',
580 },
581 },
582 5 => {
583 Name => 'ObjectFileType',
584 PrintHex => 1,
585 # ref https://svn.red-bean.com/pyobjc/branches/pyobjc-20x-branch/macholib/macholib/mach_o.py
586 PrintConv => {
587 -1 => 'Static library', #PH (internal use only)
588 1 => 'Relocatable object',
589 2 => 'Demand paged executable',
590 3 => 'Fixed VM shared library',
591 4 => 'Core',
592 5 => 'Preloaded executable',
593 6 => 'Dynamically bound shared library',
594 7 => 'Dynamic link editor',
595 8 => 'Dynamically bound bundle',
596 9 => 'Shared library stub for static linking',
597 },
598 },
599);
600
601# Information extracted from PEF (Classic MacOS executable) file header
602%Image::ExifTool::EXE::PEF = (
603 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
604 GROUPS => { 2 => 'Other' },
605 NOTES => q{
606 Information extracted from PEF (Classic MacOS) executable files and
607 libraries.
608 },
609 FORMAT => 'int32u',
610 2 => {
611 Name => 'CPUArchitecture',
612 Format => 'undef[4]',
613 PrintConv => {
614 pwpc => 'PowerPC',
615 m68k => '68000',
616 },
617 },
618 3 => 'PEFVersion',
619 4 => {
620 Name => 'TimeStamp',
621 Groups => { 2 => 'Time' },
622 # timestamp is relative to Jan 1, 1904
623 ValueConv => 'ConvertUnixTime($val - ((66 * 365 + 17) * 24 * 3600))',
624 PrintConv => '$self->ConvertDateTime($val)',
625 },
626 #5 => 'OldDefVersion',
627 #6 => 'OldImpVersion',
628 #7 => 'CurrentVersion',
629);
630
631# Information extracted from ELF (Unix executable) file header
632%Image::ExifTool::EXE::ELF = (
633 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
634 GROUPS => { 2 => 'Other' },
635 NOTES => q{
636 Information extracted from ELF (Unix) executable files and SO libraries.
637 },
638 4 => {
639 Name => 'CPUArchitecture',
640 PrintConv => {
641 1 => '32 bit',
642 2 => '64 bit',
643 },
644 },
645 5 => {
646 Name => 'CPUByteOrder',
647 PrintConv => {
648 1 => 'Little endian',
649 2 => 'Big endian',
650 },
651 },
652 16 => {
653 Name => 'ObjectFileType',
654 Format => 'int16u',
655 PrintConv => {
656 0 => 'None',
657 1 => 'Relocatable file',
658 2 => 'Executable file',
659 3 => 'Shared object file',
660 4 => 'Core file',
661 },
662 },
663 18 => {
664 Name => 'CPUType',
665 Format => 'int16u',
666 # ref /usr/include/linux/elf-em.h
667 PrintConv => {
668 0 => 'None',
669 1 => 'AT&T WE 32100',
670 2 => 'SPARC',
671 3 => 'i386',
672 4 => 'Motorola 68000',
673 5 => 'Motorola 88000',
674 6 => 'i486',
675 7 => 'i860',
676 8 => 'MIPS R3000',
677 10 => 'MIPS R4000',
678 15 => 'HPPA',
679 18 => 'Sun v8plus',
680 20 => 'PowerPC',
681 21 => 'PowerPC 64-bit',
682 22 => 'IBM S/390',
683 23 => 'Cell BE SPU',
684 42 => 'SuperH',
685 43 => 'SPARC v9 64-bit',
686 46 => 'Renesas H8/300,300H,H8S',
687 50 => 'HP/Intel IA-64',
688 62 => 'AMD x86-64',
689 76 => 'Axis Communications 32-bit embedded processor',
690 87 => 'NEC v850',
691 88 => 'Renesas M32R',
692 0x5441 => 'Fujitsu FR-V',
693 0x9026 => 'Alpha', # (interim value)
694 0x9041 => 'm32r (old)',
695 0x9080 => 'v850 (old)',
696 0xa390 => 'S/390 (old)',
697 },
698 },
699);
700
701#------------------------------------------------------------------------------
702# Read Unicode string (null terminated) from resource
703# Inputs: 0) data ref, 1) start offset, 2) optional ExifTool object ref
704# Returns: 0) Unicode string translated to UTF8, or current CharSet with ExifTool ref
705# 1) end pos (rounded up to nearest 4 bytes)
706sub ReadUnicodeStr($$;$)
707{
708 my ($dataPt, $pos, $exifTool) = @_;
709 my $len = length $$dataPt;
710 my $str = '';
711 while ($pos + 2 <= $len) {
712 my $ch = substr($$dataPt, $pos, 2);
713 $pos += 2;
714 last if $ch eq "\0\0";
715 $str .= $ch;
716 }
717 $pos += 2 if $pos & 0x03;
718 my $to = $exifTool ? $exifTool->Options('Charset') : 'UTF8';
719 return (Image::ExifTool::Decode(undef,$str,'UCS2','II',$to), $pos);
720}
721
722#------------------------------------------------------------------------------
723# Process Windows PE Version Resource
724# Inputs: 0) ExifTool object ref, 1) dirInfo ref
725# Returns: true on success
726sub ProcessPEVersion($$)
727{
728 my ($exifTool, $dirInfo) = @_;
729 my $dataPt = $$dirInfo{DataPt};
730 my $pos = $$dirInfo{DirStart};
731 my $end = $pos + $$dirInfo{DirLen};
732 my ($index, $len, $valLen, $type, $string, $strEnd);
733
734 # get VS_VERSION_INFO
735 for ($index = 0; ; ++$index) {
736 $pos = ($pos + 3) & 0xfffffffc; # align on a 4-byte boundary
737 last if $pos + 6 > $end;
738 $len = Get16u($dataPt, $pos);
739 $valLen = Get16u($dataPt, $pos + 2);
740 $type = Get16u($dataPt, $pos + 4);
741 return 0 unless $len or $valLen; # prevent possible infinite loop
742 ($string, $strEnd) = ReadUnicodeStr($dataPt, $pos + 6);
743 return 0 if $strEnd + $valLen > $end;
744 unless ($index or $string eq 'VS_VERSION_INFO') {
745 $exifTool->Warn('Invalid Version Info block');
746 return 0;
747 }
748 if ($string eq 'VS_VERSION_INFO') {
749 # parse the fixed version info
750 $$dirInfo{DirStart} = $strEnd;
751 $$dirInfo{DirLen} = $valLen;
752 my $subTablePtr = GetTagTable('Image::ExifTool::EXE::PEVersion');
753 $exifTool->ProcessDirectory($dirInfo, $subTablePtr);
754 $pos = $strEnd + $valLen;
755 } elsif ($string eq 'StringFileInfo' and $valLen == 0) {
756 $pos += $len;
757 my $pt = $strEnd;
758 # parse string table
759 my $tagTablePtr = GetTagTable('Image::ExifTool::EXE::PEString');
760 for ($index = 0; $pt + 6 < $pos; ++$index) {
761 $len = Get16u($dataPt, $pt);
762 $valLen = Get16u($dataPt, $pt + 2);
763 # $type = Get16u($dataPt, $pt + 4);
764 # get tag ID (converted to UTF8)
765 ($string, $pt) = ReadUnicodeStr($dataPt, $pt + 6);
766 unless ($index) {
767 # separate the language code and character set
768 # (not sure what the CharacterSet tag is for, but the string
769 # values stored here are UCS-2 in all my files even if the
770 # CharacterSet is otherwise)
771 my $char;
772 if (length($string) > 4) {
773 $char = substr($string, 4);
774 $string = substr($string, 0, 4);
775 }
776 $exifTool->HandleTag($tagTablePtr, 'LanguageCode', uc $string);
777 $exifTool->HandleTag($tagTablePtr, 'CharacterSet', uc $char) if $char;
778 next;
779 }
780 my $tag = $string;
781 # create entry in tag table if it doesn't already exist
782 unless ($$tagTablePtr{$tag}) {
783 my $name = $tag;
784 $name =~ tr/-_a-zA-Z0-9//dc; # remove illegal characters
785 next unless length $name;
786 Image::ExifTool::AddTagToTable($tagTablePtr, $tag, { Name => $name });
787 }
788 # get tag value (converted to current Charset)
789 if ($valLen) {
790 ($string, $pt) = ReadUnicodeStr($dataPt, $pt, $exifTool);
791 } else {
792 $string = '';
793 }
794 $exifTool->HandleTag($tagTablePtr, $tag, $string);
795 }
796 } else {
797 $pos += $len + $valLen;
798 # ignore other information (for now)
799 }
800 }
801 return 1;
802}
803
804#------------------------------------------------------------------------------
805# Process Windows PE Resources
806# Inputs: 0) ExifTool object ref, 1) dirInfo ref
807# Returns: true on success
808sub ProcessPEResources($$)
809{
810 my ($exifTool, $dirInfo) = @_;
811 my $raf = $$dirInfo{RAF};
812 my $base = $$dirInfo{Base};
813 my $dirStart = $$dirInfo{DirStart} + $base;
814 my $level = $$dirInfo{Level} || 0;
815 my $verbose = $exifTool->Options('Verbose');
816 my ($buff, $buf2, $item);
817
818 return 0 if $level > 10; # protect against deep recursion
819 # read the resource header
820 $raf->Seek($dirStart, 0) and $raf->Read($buff, 16) == 16 or return 0;
821 my $nameEntries = Get16u(\$buff, 12);
822 my $idEntries = Get16u(\$buff, 14);
823 my $count = $nameEntries + $idEntries;
824 $raf->Read($buff, $count * 8) == $count * 8 or return 0;
825 # loop through all resource entries
826 for ($item=0; $item<$count; ++$item) {
827 my $pos = $item * 8;
828 my $name = Get32u(\$buff, $pos);
829 my $entryPos = Get32u(\$buff, $pos + 4);
830 unless ($level) {
831 # set resource type if this is the 0th level directory
832 my $resType = $resourceType{$name} || sprintf('Unknown (0x%x)', $name);
833 # ignore everything but the Version resource unless verbose
834 if ($verbose) {
835 $exifTool->VPrint(0, "$resType resource:\n");
836 } else {
837 next unless $resType eq 'Version';
838 }
839 $$dirInfo{ResType} = $resType;
840 }
841 if ($entryPos & 0x80000000) { # is this a directory?
842 # descend into next directory level
843 $$dirInfo{DirStart} = $entryPos & 0x7fffffff;
844 $$dirInfo{Level} = $level + 1;
845 ProcessPEResources($exifTool, $dirInfo) or return 0;
846 --$$dirInfo{Level};
847 } elsif ($$dirInfo{ResType} eq 'Version' and $level == 2 and
848 not $$dirInfo{GotVersion}) # (only process first Version resource)
849 {
850 # get position of this resource in the file
851 my $buf2;
852 $raf->Seek($entryPos + $base, 0) and $raf->Read($buf2, 16) == 16 or return 0;
853 my $off = Get32u(\$buf2, 0);
854 my $len = Get32u(\$buf2, 4);
855 # determine which section this is in so we can convert the virtual address
856 my ($section, $filePos);
857 foreach $section (@{$$dirInfo{Sections}}) {
858 next unless $off >= $$section{VirtualAddress} and
859 $off < $$section{VirtualAddress} + $$section{Size};
860 $filePos = $off + $$section{Base} - $$section{VirtualAddress};
861 last;
862 }
863 return 0 unless $filePos;
864 $raf->Seek($filePos, 0) and $raf->Read($buf2, $len) == $len or return 0;
865 ProcessPEVersion($exifTool, {
866 DataPt => \$buf2,
867 DataLen => $len,
868 DirStart => 0,
869 DirLen => $len,
870 }) or $exifTool->Warn('Possibly corrupt Version resource');
871 $$dirInfo{GotVersion} = 1; # set flag so we don't do this again
872 }
873 }
874 return 1;
875}
876
877#------------------------------------------------------------------------------
878# Process Windows PE file data dictionary
879# Inputs: 0) ExifTool object ref, 1) dirInfo ref
880# Returns: true on success
881sub ProcessPEDict($$)
882{
883 my ($exifTool, $dirInfo) = @_;
884 my $raf = $$dirInfo{RAF};
885 my $dataPt = $$dirInfo{DataPt};
886 my $dirLen = length($$dataPt);
887 my ($pos, @sections, %dirInfo);
888
889 # loop through all sections
890 for ($pos=0; $pos+40<=$dirLen; $pos+=40) {
891 my $name = substr($$dataPt, $pos, 8);
892 my $va = Get32u($dataPt, $pos + 12);
893 my $size = Get32u($dataPt, $pos + 16);
894 my $offset = Get32u($dataPt, $pos + 20);
895 # remember the section offsets for the VirtualAddress lookup later
896 push @sections, { Base => $offset, Size => $size, VirtualAddress => $va };
897 # save details of the first resource section
898 %dirInfo = (
899 RAF => $raf,
900 Base => $offset,
901 DirStart => 0, # (relative to Base)
902 DirLen => $size,
903 Sections => \@sections,
904 ) if $name eq ".rsrc\0\0\0" and not %dirInfo;
905 }
906 # process the first resource section
907 ProcessPEResources($exifTool, \%dirInfo) or return 0 if %dirInfo;
908 return 1;
909}
910
911#------------------------------------------------------------------------------
912# Extract information from an EXE file
913# Inputs: 0) ExifTool object reference, 1) dirInfo reference
914# Returns: 1 on success, 0 if this wasn't a valid EXE file
915sub ProcessEXE($$)
916{
917 my ($exifTool, $dirInfo) = @_;
918 my $raf = $$dirInfo{RAF};
919 my ($buff, $buf2, $type, $tagTablePtr, %dirInfo);
920
921 my $size = $raf->Read($buff, 0x40) or return 0;
922#
923# DOS and Windows EXE
924#
925 if ($buff =~ /^MZ/ and $size == 0x40) {
926 # DOS/Windows executable
927 # validate DOS header
928 # (ref http://www.delphidabbler.com/articles?article=8&part=2)
929 # 0 magic : int16u # Magic number ("MZ")
930 # 2 cblp : int16u # Bytes on last page of file
931 # 4 cp : int16u # Pages in file
932 # 6 crlc : int16u # Relocations
933 # 8 cparhdr : int16u # Size of header in paragraphs
934 # 10 minalloc: int16u # Minimum extra paragraphs needed
935 # 12 maxalloc: int16u # Maximum extra paragraphs needed
936 # 14 ss : int16u # Initial (relative) SS value
937 # 16 sp : int16u # Initial SP value
938 # 18 csum : int16u # Checksum
939 # 20 ip : int16u # Initial IP value
940 # 22 cs : int16u # Initial (relative) CS value
941 # 24 lfarlc : int16u # Address of relocation table
942 # 26 ovno : int16u # Overlay number
943 # 28 res : int16u[4] # Reserved words
944 # 36 oemid : int16u # OEM identifier (for oeminfo)
945 # 38 oeminfo : int16u # OEM info; oemid specific
946 # 40 res2 : int16u[10]# Reserved words
947 # 60 lfanew : int32u; # File address of new exe header
948 SetByteOrder('II');
949 my ($cblp, $cp, $lfarlc, $lfanew) = unpack('x2v2x18vx34V', $buff);
950 my $fileSize = ($cp - ($cblp ? 1 : 0)) * 512 + $cblp;
951 return 0 if $fileSize < 0x40 or $fileSize < $lfarlc;
952 # read the Windows PE header
953 if ($lfarlc == 0x40 and $fileSize > $lfanew + 2 and
954 # read the Windows NE, PE or LE (virtual device driver) header
955 $raf->Seek($lfanew, 0) and $raf->Read($buff, 0x40) and
956 $buff =~ /^(NE|PE|LE)/)
957 {
958 if ($1 eq 'NE') {
959 if ($size >= 0x40) { # NE header is 64 bytes (ref 2)
960 # check for DLL
961 my $appFlags = Get16u(\$buff, 0x0c);
962 $type = 'Win16 ' . ($appFlags & 0x80 ? 'DLL' : 'EXE');
963 # offset 0x02 is 2 bytes with linker version and revision numbers
964 # offset 0x36 is executable type (2 = Windows)
965 }
966 } elsif ($1 eq 'PE') {
967 # PE header comes at byte 4 in buff:
968 # 4 int16u Machine
969 # 6 int16u NumberOfSections
970 # 8 int32u TimeDateStamp
971 # 12 int32u PointerToSymbolTable
972 # 16 int32u NumberOfSymbols
973 # 20 int16u SizeOfOptionalHeader
974 # 22 int16u Characteristics
975 if ($size >= 24) { # PE header is 24 bytes (plus optional header)
976 my $flags = Get16u(\$buff, 22);
977 $exifTool->SetFileType('Win32 ' . ($flags & 0x2000 ? 'DLL' : 'EXE'));
978 # read the rest of the optional header if necessary
979 my $optSize = Get16u(\$buff, 20);
980 my $more = $optSize + 24 - $size;
981 if ($more > 0) {
982 if ($raf->Read($buf2, $more) == $more) {
983 $buff .= $buf2;
984 $size += $more;
985 my $magic = Get16u(\$buff, 24);
986 # verify PE32/PE32+ magic number
987 unless ($magic == 0x10b or $magic == 0x20b) {
988 $exifTool->Warn('Unknown PE magic number');
989 return 1;
990 }
991 } else {
992 $exifTool->Warn('Error reading optional header');
993 }
994 }
995 # process PE COFF file header
996 $tagTablePtr = GetTagTable('Image::ExifTool::EXE::Main');
997 %dirInfo = (
998 DataPt => \$buff,
999 DataPos => $raf->Tell() - $size,
1000 DataLen => $size,
1001 DirStart => 4,
1002 DirLen => $size,
1003 );
1004 $exifTool->ProcessDirectory(\%dirInfo, $tagTablePtr);
1005 # process data dictionary
1006 my $num = Get16u(\$buff, 6); # NumberOfSections
1007 if ($raf->Read($buff, 40 * $num) == 40 * $num) {
1008 %dirInfo = (
1009 RAF => $raf,
1010 DataPt => \$buff,
1011 );
1012 ProcessPEDict($exifTool, \%dirInfo) or $exifTool->Warn('Error processing PE data dictionary');
1013 }
1014 return 1;
1015 }
1016 } else {
1017 $type = 'Virtual Device Driver';
1018 }
1019 } else {
1020 $type = 'DOS EXE';
1021 }
1022#
1023# Mach-O (Mac OS X)
1024#
1025 } elsif ($buff =~ /^(\xca\xfe\xba\xbe|\xfe\xed\xfa(\xce|\xcf)|(\xce|\xcf)\xfa\xed\xfe)/ and $size > 12) {
1026 # Mach-O executable
1027 # (ref http://developer.apple.com/documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html)
1028 $tagTablePtr = GetTagTable('Image::ExifTool::EXE::MachO');
1029 if ($1 eq "\xca\xfe\xba\xbe") {
1030 SetByteOrder('MM');
1031 $exifTool->SetFileType('Mach-O fat binary executable');
1032 my $count = Get32u(\$buff, 4); # get architecture count
1033 my $more = $count * 20 - ($size - 8);
1034 if ($more > 0) {
1035 unless ($raf->Read($buf2, $more) == $more) {
1036 $exifTool->Warn('Error reading fat-arch headers');
1037 return 1;
1038 }
1039 $buff .= $buf2;
1040 $size += $more;
1041 }
1042 $exifTool->HandleTag($tagTablePtr, 2, $count);
1043 my $i;
1044 for ($i=0; $i<$count; ++$i) {
1045 my $cpuType = Get32s(\$buff, 8 + $i * 20);
1046 my $cpuSubtype = Get32u(\$buff, 12 + $i * 20);
1047 $exifTool->HandleTag($tagTablePtr, 3, $cpuType);
1048 $exifTool->HandleTag($tagTablePtr, 4, "$cpuType $cpuSubtype");
1049 }
1050 # load first Mach-O header to get the object file type
1051 my $offset = Get32u(\$buff, 16);
1052 if ($raf->Seek($offset, 0) and $raf->Read($buf2, 16) == 16) {
1053 if ($buf2 =~ /^(\xfe\xed\xfa(\xce|\xcf)|(\xce|\xcf)\xfa\xed\xfe)/) {
1054 SetByteOrder($buf2 =~ /^\xfe\xed/ ? 'MM' : 'II');
1055 my $objType = Get32s(\$buf2, 12);
1056 $exifTool->HandleTag($tagTablePtr, 5, $objType);
1057 } elsif ($buf2 =~ /^!<arch>\x0a/) {
1058 # .a libraries use this magic number
1059 $exifTool->HandleTag($tagTablePtr, 5, -1);
1060 } else {
1061 $exifTool->Warn('Unrecognized object file type');
1062 }
1063 } else {
1064 $exifTool->Warn('Error reading file');
1065 }
1066 } elsif ($size >= 16) {
1067 $exifTool->SetFileType('Mach-O executable');
1068 my $info = {
1069 "\xfe\xed\xfa\xce" => ['32 bit', 'Big endian'],
1070 "\xce\xfa\xed\xfe" => ['32 bit', 'Little endian'],
1071 "\xfe\xed\xfa\xcf" => ['64 bit', 'Big endian'],
1072 "\xcf\xfa\xed\xfe" => ['64 bit', 'Little endian'],
1073 }->{substr($buff, 0, 4)};
1074 my $byteOrder = ($buff =~ /^\xfe/) ? 'MM' : 'II';
1075 SetByteOrder($byteOrder);
1076 my $cpuType = Get32s(\$buff, 4);
1077 my $cpuSubtype = Get32s(\$buff, 8);
1078 my $objType = Get32s(\$buff, 12);
1079 $exifTool->HandleTag($tagTablePtr, 0, $$info[0]);
1080 $exifTool->HandleTag($tagTablePtr, 1, $$info[1]);
1081 $exifTool->HandleTag($tagTablePtr, 3, $cpuType);
1082 $exifTool->HandleTag($tagTablePtr, 4, "$cpuType $cpuSubtype");
1083 $exifTool->HandleTag($tagTablePtr, 5, $objType);
1084 }
1085 return 1;
1086#
1087# PEF (classic MacOS)
1088#
1089 } elsif ($buff =~ /^Joy!peff/ and $size > 12) {
1090 # ref http://developer.apple.com/documentation/mac/pdf/MacOS_RT_Architectures.pdf
1091 $exifTool->SetFileType('Classic MacOS executable');
1092 SetByteOrder('MM');
1093 $tagTablePtr = GetTagTable('Image::ExifTool::EXE::PEF');
1094 %dirInfo = (
1095 DataPt => \$buff,
1096 DataPos => 0,
1097 DataLen => $size,
1098 DirStart => 0,
1099 DirLen => $size,
1100 );
1101 $exifTool->ProcessDirectory(\%dirInfo, $tagTablePtr);
1102 return 1;
1103#
1104# ELF (Unix)
1105#
1106 } elsif ($buff =~ /^\x7fELF/ and $size >= 16) {
1107 $exifTool->SetFileType("ELF executable");
1108 SetByteOrder(Get8u(\$buff,5) == 1 ? 'II' : 'MM');
1109 $tagTablePtr = GetTagTable('Image::ExifTool::EXE::ELF');
1110 %dirInfo = (
1111 DataPt => \$buff,
1112 DataPos => 0,
1113 DataLen => $size,
1114 DirStart => 0,
1115 DirLen => $size,
1116 );
1117 $exifTool->ProcessDirectory(\%dirInfo, $tagTablePtr);
1118 return 1;
1119#
1120# various scripts (perl, sh, etc...)
1121#
1122 } elsif ($buff =~ m{^#!\s*/\S*bin/(\w+)}) {
1123 $type = "$1 script";
1124#
1125# .a libraries
1126#
1127 } elsif ($buff =~ /^!<arch>\x0a/) {
1128 $type = 'Static library',
1129 }
1130 return 0 unless $type;
1131 $exifTool->SetFileType($type);
1132 return 1;
1133}
1134
11351; # end
1136
1137__END__
1138
1139=head1 NAME
1140
1141Image::ExifTool::EXE - Read executable file meta information
1142
1143=head1 SYNOPSIS
1144
1145This module is used by Image::ExifTool
1146
1147=head1 DESCRIPTION
1148
1149This module contains definitions required by Image::ExifTool to extract meta
1150information from various types of Windows, MacOS and Unix executable and
1151library files.
1152
1153=head1 AUTHOR
1154
1155Copyright 2003-2011, Phil Harvey (phil at owl.phy.queensu.ca)
1156
1157This library is free software; you can redistribute it and/or modify it
1158under the same terms as Perl itself.
1159
1160=head1 REFERENCES
1161
1162=over 4
1163
1164=item L<http://www.openwatcom.org/ftp/devel/docs/pecoff.pdf>
1165
1166=item L<http://support.microsoft.com/kb/65122>
1167
1168=item L<http://www.opensource.apple.com>
1169
1170=item L<http://www.skyfree.org/linux/references/ELF_Format.pdf>
1171
1172=item L<http://msdn.microsoft.com/en-us/library/ms809762.aspx>
1173
1174=item L<http://code.google.com/p/pefile/>
1175
1176=item L<http://www.codeproject.com/KB/DLL/showver.aspx>
1177
1178=back
1179
1180=head1 SEE ALSO
1181
1182L<Image::ExifTool::TagNames/EXE Tags>,
1183L<Image::ExifTool(3pm)|Image::ExifTool>
1184
1185=cut
1186
Note: See TracBrowser for help on using the repository browser.