1 /*
2 * HT Editor
3 * xex_analy.cc
4 *
5 * Copyright (C) 2006 Sebastian Biallas (sb@biallas.net)
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include "analy.h"
26 #include "analy_names.h"
27 #include "analy_register.h"
28 #include "analy_ppc.h"
29 #include "htctrl.h"
30 #include "htdebug.h"
31 #include "htiobox.h"
32 #include "htxex.h"
33 #include "strtools.h"
34 #include "xex_analy.h"
35 #include "xexstruct.h"
36 #include "snprintf.h"
37
init(ht_xex_shared_data * XEX_shared,File * File)38 void XEXAnalyser::init(ht_xex_shared_data *XEX_shared, File *File)
39 {
40 xex_shared = XEX_shared;
41 file = File;
42
43 validarea = new Area();
44 validarea->init();
45
46 Analyser::init();
47 }
48
49 /*
50 *
51 */
load(ObjectStream & f)52 void XEXAnalyser::load(ObjectStream &f)
53 {
54 GET_OBJECT(f, validarea);
55 Analyser::load(f);
56 }
57
58 /*
59 *
60 */
done()61 void XEXAnalyser::done()
62 {
63 validarea->done();
64 delete validarea;
65 Analyser::done();
66 }
67
68 /*
69 *
70 */
beginAnalysis()71 void XEXAnalyser::beginAnalysis()
72 {
73 char buffer[1024];
74
75 Address *entry = createAddress32(xex_shared->entrypoint);
76 pushAddress(entry, entry);
77
78 int lib_count=xex_shared->imports.lib_count;
79 for (int i=0; i < lib_count; i++) {
80 XexImportLib *lib = xex_shared->imports.libs + i;
81 for (int j = 0; j < lib->func_count; j++) {
82 XexImportFunc *func = lib->funcs + j;
83 uint32 ord = func->ord;
84 if (ord & 0xff000000) {
85 int libidx = (ord & 0x00ff0000) >> 16;
86 ord &= 0x7fff;
87 if (libidx != i) {
88 continue;
89 }
90 char s[200];
91 ht_snprintf(s, sizeof s, "wrapper_import_%s_%d", lib->name, ord);
92 Address *faddr = createAddress32(func->patch);
93 addComment(faddr, 0, "");
94 assignSymbol(faddr, s, label_func);
95 delete faddr;
96 faddr = createAddress32(func->patch+12);
97 Address *faddr2 = createAddress32(func->ia);
98 addXRef(faddr2, faddr, xrefijump);
99 delete faddr;
100 delete faddr2;
101 // printf("xref 0x%08x -> 0x%08x\n", ia, imports[i].func[j].patch + 12);
102
103 } else {
104 char s[200];
105 ord &= 0x7fff;
106 ht_snprintf(s, sizeof s, "import_%s_%d", lib->name, ord);
107 Address *faddr = createAddress32(func->patch);
108 addComment(faddr, 0, "");
109 assignSymbol(faddr, s, label_func);
110 data->setIntAddressType(faddr, dst_idword, 4);
111 delete faddr;
112 // printf("function_ptr 0x%08x name '%s'\n", imports[i].func[j].patch, s);
113 }
114
115 }
116 }
117
118 #if 0
119 int dimport_count=xex_shared->dimports.funcs->count();
120 entropy = random_permutation(dimport_count);
121 for (int i=0; i<dimport_count; i++) {
122 // FIXME: delay imports need work (push addr)
123 ht_pe_import_function *f=(ht_pe_import_function *)(*xex_shared->dimports.funcs)[entropy[i]];
124 ht_pe_import_library *d=(ht_pe_import_library *)(*xex_shared->dimports.libs)[f->libidx];
125 if (f->byname) {
126 ht_snprintf(buffer, sizeof buffer, "; delay import function loader for %s, ordinal %04x", f->name.name, f->ordinal);
127 } else {
128 ht_snprintf(buffer, sizeof buffer, "; delay import function loader for ordinal %04x", f->ordinal);
129 }
130 char *label;
131 label = import_func_name(d->name, f->byname ? f->name.name : NULL, f->ordinal);
132 Address *faddr;
133 if (pe32) {
134 faddr = createAddress32(f->address);
135 } else {
136 faddr = createAddress64(f->address);
137 }
138 addComment(faddr, 0, "");
139 addComment(faddr, 0, ";********************************************************");
140 addComment(faddr, 0, buffer);
141 addComment(faddr, 0, ";********************************************************");
142 assignSymbol(faddr, label, label_func);
143 free(label);
144 delete faddr;
145 }
146 if (entropy) free(entropy);
147 #endif
148
149 addComment(entry, 0, "");
150 addComment(entry, 0, ";****************************");
151 addComment(entry, 0, "; program entry point");
152 addComment(entry, 0, ";****************************");
153 assignSymbol(entry, "entrypoint", label_func);
154
155 setLocationTreeOptimizeThreshold(1000);
156 setSymbolTreeOptimizeThreshold(1000);
157 delete entry;
158
159 Analyser::beginAnalysis();
160 }
161
162 /*
163 *
164 */
getObjectID() const165 ObjectID XEXAnalyser::getObjectID() const
166 {
167 return ATOM_XEX_ANALYSER;
168 }
169
170 /*
171 *
172 */
bufPtr(Address * Addr,byte * buf,int size)173 uint XEXAnalyser::bufPtr(Address *Addr, byte *buf, int size)
174 {
175 FileOfs ofs = addressToFileofs(Addr);
176 /* if (ofs == INVALID_FILE_OFS) {
177 int as=0;
178 }*/
179 assert(ofs != INVALID_FILE_OFS);
180 file->seek(ofs);
181 return file->read(buf, size);
182 }
183
convertAddressToRVA(Address * addr,RVA * r)184 bool XEXAnalyser::convertAddressToRVA(Address *addr, RVA *r)
185 {
186 ObjectID oid = addr->getObjectID();
187 if (oid == ATOM_ADDRESS_FLAT_32) {
188 *r = ((AddressFlat32*)addr)->addr - xex_shared->image_base;
189 return true;
190 }
191 return false;
192 }
193
194 /*
195 *
196 */
createAddress32(uint32 addr)197 Address *XEXAnalyser::createAddress32(uint32 addr)
198 {
199 return new AddressFlat32(addr);
200 }
201
202
createAddress()203 Address *XEXAnalyser::createAddress()
204 {
205 return new AddressFlat32();
206 }
207
208 /*
209 *
210 */
addressToFileofs(Address * Addr)211 FileOfs XEXAnalyser::addressToFileofs(Address *Addr)
212 {
213 if (validAddress(Addr, scinitialized)) {
214 FileOfs ofs;
215 RVA r;
216 if (!convertAddressToRVA(Addr, &r)) return INVALID_FILE_OFS;
217 if (!xex_rva_to_ofs(xex_shared, r, ofs)) return INVALID_FILE_OFS;
218 return ofs;
219 } else {
220 return INVALID_FILE_OFS;
221 }
222 }
223
224 /*
225 *
226 */
getSegmentNameByAddress(Address * Addr)227 const char *XEXAnalyser::getSegmentNameByAddress(Address *Addr)
228 {
229 return "";
230 }
231
232 /*
233 *
234 */
getName(String & s)235 String &XEXAnalyser::getName(String &s)
236 {
237 return file->getDesc(s);
238 }
239
240 /*
241 *
242 */
getType()243 const char *XEXAnalyser::getType()
244 {
245 return "XEX/Analyser";
246 }
247
248 /*
249 *
250 */
initUnasm()251 void XEXAnalyser::initUnasm()
252 {
253 analy_disasm = new AnalyPPCDisassembler();
254 ((AnalyPPCDisassembler*)analy_disasm)->init(this, ANALY_PPC_32);
255 }
256
257 /*
258 *
259 */
nextValid(Address * Addr)260 Address *XEXAnalyser::nextValid(Address *Addr)
261 {
262 return (Address *)validarea->findNext(Addr);
263 }
264
265 /*
266 *
267 */
store(ObjectStream & st) const268 void XEXAnalyser::store(ObjectStream &st) const
269 {
270 PUT_OBJECT(st, validarea);
271 Analyser::store(st);
272 }
273
274
275 /*
276 *
277 */
fileofsToAddress(FileOfs fileofs)278 Address *XEXAnalyser::fileofsToAddress(FileOfs fileofs)
279 {
280 RVA r;
281 if (xex_ofs_to_rva(xex_shared, fileofs, r)) {
282 return createAddress32(r + xex_shared->image_base);
283 } else {
284 return new InvalidAddress();
285 }
286 }
287
288 /*
289 *
290 */
validAddress(Address * Addr,tsectype action)291 bool XEXAnalyser::validAddress(Address *Addr, tsectype action)
292 {
293 // e_section_headers *sections=&xex_shared->sections;
294 int sec;
295 RVA r;
296 FileOfs ofs;
297 if (!convertAddressToRVA(Addr, &r)) return false;
298 // if (!pe_rva_to_section(sections, r, &sec)) return false;
299 if (!xex_rva_to_ofs(xex_shared, r, ofs)) return false;
300 uint32 flags = xex_get_rva_flags(xex_shared, r);
301 switch (action) {
302 case scvalid:
303 case scinitialized:
304 case scread:
305 return true;
306 return true;
307 case scwrite:
308 case screadwrite:
309 return !(flags & 1);
310 case sccode:
311 return !(flags & 2);
312 }
313 return true;
314 }
315