Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1882 | clevermous | 1 | /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */ |
2 | /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */ |
||
3 | #include |
||
4 | #include |
||
5 | #include |
||
6 | #include |
||
7 | #include |
||
8 | #include |
||
9 | |||
10 | #define STUB_INFO_MAGIC "StubInfoMagic!!" |
||
11 | |||
12 | static _v2_prog_type type; |
||
13 | static int type_initialized = 0; |
||
14 | |||
15 | static |
||
16 | const _v2_prog_type *_check_v2_prog_internal (int pf); |
||
17 | |||
18 | const _v2_prog_type *_check_v2_prog(const char *program, int pf) |
||
19 | { |
||
20 | const _v2_prog_type *prog_type; |
||
21 | |||
22 | if (type_initialized && type.stubinfo) |
||
23 | free(type.stubinfo); |
||
24 | type_initialized = 1; |
||
25 | |||
26 | memset(&type, 0, sizeof(type)); |
||
27 | |||
28 | if (program) |
||
29 | { |
||
30 | pf = open(program, O_RDONLY|O_BINARY); |
||
31 | if (pf < 0) |
||
32 | return &type; |
||
33 | } |
||
34 | |||
35 | prog_type = _check_v2_prog_internal(pf); |
||
36 | |||
37 | if (program) |
||
38 | close(pf); |
||
39 | |||
40 | if (prog_type) |
||
41 | type.valid = 1; |
||
42 | return &type; |
||
43 | } |
||
44 | |||
45 | static |
||
46 | const _v2_prog_type *_check_v2_prog_internal (int pf) |
||
47 | { |
||
48 | unsigned short header[5]; |
||
49 | lseek(pf, 0, SEEK_SET); |
||
50 | if (read(pf, header, sizeof(header)) != sizeof(header)) |
||
51 | return NULL; |
||
52 | if (header[0] == 0x010b || header[0] == 0x014c) |
||
53 | { |
||
54 | unsigned char firstbytes[1]; |
||
55 | unsigned long coffhdr[40]; |
||
56 | |||
57 | /* Seems to be an unstubbed COFF. See what the first opcode |
||
58 | is to determine if it's v1.x or v2 COFF (or an impostor). |
||
59 | |||
60 | FIXME: the code here assumes that any COFF that's not a V1 |
||
61 | can only be V2. What about other compilers that use COFF? */ |
||
62 | type.object_format = _V2_OBJECT_FORMAT_COFF; |
||
63 | if (lseek(pf, 2, 1) < 0 |
||
64 | || read(pf, coffhdr, sizeof(coffhdr)) != sizeof(coffhdr) |
||
65 | || lseek(pf, coffhdr[10 + 5], 0) < 0 |
||
66 | || read(pf, firstbytes, 1) != 1) /* scnptr */ |
||
67 | /* "Aha! An impostor!" (The Adventure game) */ |
||
68 | type.object_format = _V2_OBJECT_FORMAT_UNKNOWN; |
||
69 | else if (firstbytes[0] != 0xa3) /* opcode of movl %eax, 0x12345678 (V1) */ |
||
70 | type.version.v.major = 2; |
||
71 | else |
||
72 | type.version.v.major = 1; |
||
73 | type.exec_format = _V2_EXEC_FORMAT_COFF; |
||
74 | } |
||
75 | else if (header[0] == 0x5a4d) /* "MZ" */ |
||
76 | { |
||
77 | char go32stub[9]; |
||
78 | unsigned long coff_start = (unsigned long)header[2]*512L; |
||
79 | unsigned long exe_start; |
||
80 | type.exec_format = _V2_EXEC_FORMAT_EXE; |
||
81 | if (header[1]) |
||
82 | coff_start += (long)header[1] - 512L; |
||
83 | exe_start = (unsigned long)header[4]*16L; |
||
84 | if (lseek(pf, exe_start, SEEK_SET) != exe_start) |
||
85 | return NULL; |
||
86 | if (read(pf, go32stub, 8) != 8) |
||
87 | return NULL; |
||
88 | go32stub[8] = 0; |
||
89 | if (strcmp(go32stub, "go32stub") == 0) |
||
90 | { |
||
91 | type.version.v.major = 2; |
||
92 | type.object_format = _V2_OBJECT_FORMAT_COFF; |
||
93 | type.exec_format = _V2_EXEC_FORMAT_STUBCOFF; |
||
94 | } |
||
95 | else |
||
96 | { |
||
97 | int stub_offset; |
||
98 | char magic[16]; |
||
99 | int struct_length; |
||
100 | unsigned short coff_id; |
||
101 | type.version.v.major = 1; |
||
102 | if (lseek(pf, coff_start - 4, SEEK_SET) != coff_start-4) |
||
103 | return NULL; |
||
104 | if (read(pf, &stub_offset, 4) != 4) |
||
105 | return NULL; |
||
106 | if (read(pf, &coff_id, 2) != 2) |
||
107 | return NULL; |
||
108 | if (coff_id == 0x010b || coff_id == 0x014c) |
||
109 | { |
||
110 | type.object_format = _V2_OBJECT_FORMAT_COFF; |
||
111 | type.exec_format = _V2_EXEC_FORMAT_STUBCOFF; |
||
112 | } |
||
113 | if (lseek(pf, stub_offset, 0) != stub_offset) |
||
114 | return NULL; |
||
115 | if (read(pf, magic, 16) != 16) |
||
116 | return NULL; |
||
117 | if (memcmp(STUB_INFO_MAGIC, magic, 16) == 0) |
||
118 | { |
||
119 | if (read(pf, &struct_length, 4) != 4) |
||
120 | return NULL; |
||
121 | type.stubinfo = (_v1_stubinfo *)malloc(struct_length); |
||
122 | memcpy(type.stubinfo->magic, magic, 16); |
||
123 | type.stubinfo->struct_length = struct_length; |
||
124 | if (read(pf, type.stubinfo->go32, struct_length - 20) |
||
125 | != struct_length - 20) |
||
126 | return NULL; |
||
127 | type.has_stubinfo = 1; |
||
128 | } |
||
129 | } |
||
130 | } |
||
131 | else if (header[0] == 0x2123) /* "#!" */ |
||
132 | { |
||
133 | type.exec_format = _V2_EXEC_FORMAT_UNIXSCRIPT; |
||
134 | } |
||
135 | return &type; |
||
136 | }>>> |
||
137 |