xref: /haiku/src/system/runtime_loader/pe.cpp (revision 13581b3d2a71545960b98fefebc5225b5bf29072)
1 /*
2  * Copyright 2013-2014, Haiku, Inc.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *	Alexander von Gluck IV, <kallisti5@unixzen.com>
7  */
8 
9 
10 #include "pe.h"
11 
12 #include <ctype.h>
13 #include <dlfcn.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 
18 
19 static status_t
20 parse_mz_header(MzHeader* mzHeader, off_t* peOffset)
21 {
22 	if (memcmp(&mzHeader->magic, MZ_MAGIC, 2) != 0)
23 		return B_NOT_AN_EXECUTABLE;
24 
25 	*peOffset = (off_t)mzHeader->lfaNew;
26 	return B_OK;
27 }
28 
29 
30 static status_t
31 parse_pe_header(PeHeader* peHeader)
32 {
33 	if (memcmp(&peHeader->magic, PE_MAGIC, 2) != 0)
34 		return B_NOT_AN_EXECUTABLE;
35 
36 	// Looks like an old BeOS R3 x86 program
37 	if (peHeader->characteristics == 0x10E)
38 		return B_LEGACY_EXECUTABLE;
39 
40 	return B_OK;
41 }
42 
43 
44 /*! Read and verify the PE header */
45 status_t
46 pe_verify_header(void *header, size_t length)
47 {
48 	if (length < sizeof(MzHeader))
49 		return B_NOT_AN_EXECUTABLE;
50 
51 	// Verify MZ header, pull PE header offset
52 	off_t peOffset = 0;
53 	if (parse_mz_header((MzHeader*)header, &peOffset) != B_OK)
54 		return B_NOT_AN_EXECUTABLE;
55 
56 	// MS-DOS program
57 	if (peOffset == 0)
58 		return B_UNKNOWN_EXECUTABLE;
59 
60 	// Something is wrong with the binary
61 	if (peOffset + sizeof(PeHeader) > length)
62 		return B_UNKNOWN_EXECUTABLE;
63 
64 	// Find the PE header based on MZ provided offset
65 	uint8* pePtr = (uint8*)header;
66 	pePtr += peOffset;
67 
68 	// Win32 program or old BeOS R3 x86 program
69 	return parse_pe_header((PeHeader*)pePtr);
70 }
71