00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024
00025 #include "analy.h"
00026 #include "analy_alpha.h"
00027 #include "analy_names.h"
00028 #include "analy_register.h"
00029 #include "analy_ppc.h"
00030 #include "analy_x86.h"
00031 #include "coff_analy.h"
00032 #include "coff_s.h"
00033 #include "global.h"
00034
00035 #include "htctrl.h"
00036 #include "htdebug.h"
00037 #include "htiobox.h"
00038 #include "htcoff.h"
00039 #include "htstring.h"
00040 #include "snprintf.h"
00041 #include "x86asm.h"
00042
00043
00044
00045
00046 void CoffAnalyser::init(ht_coff_shared_data *Coff_shared, ht_streamfile *File)
00047 {
00048 coff_shared = Coff_shared;
00049 file = File;
00050
00051 validarea = new Area();
00052 validarea->init();
00053
00054 Analyser::init();
00055
00057
00058 setLocationTreeOptimizeThreshold(100);
00059 setSymbolTreeOptimizeThreshold(100);
00060 }
00061
00062
00063
00064
00065
00066 int CoffAnalyser::load(ht_object_stream *f)
00067 {
00068
00069
00070
00071
00072
00073 GET_OBJECT(f, validarea);
00074 return Analyser::load(f);
00075 }
00076
00077
00078
00079
00080 void CoffAnalyser::done()
00081 {
00082 validarea->done();
00083 delete validarea;
00084 Analyser::done();
00085 }
00086
00087
00088
00089
00090 void CoffAnalyser::beginAnalysis()
00091 {
00092
00093
00094
00095
00096
00097 Address *entry=createAddress32(coff_shared->coff32header.entrypoint_address);
00098 pushAddress(entry, entry);
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116 COFF_SECTION_HEADER *s=coff_shared->sections.sections;
00117 char blub[100];
00118 for (UINT i=0; i<coff_shared->sections.section_count; i++) {
00119 Address *secaddr = createAddress32(s->data_address);
00120 sprintf(blub, "; section %d <%s>", i+1, getSegmentNameByAddress(secaddr));
00121 addComment(secaddr, 0, "");
00122 addComment(secaddr, 0, ";******************************************************************");
00123 addComment(secaddr, 0, blub);
00124 sprintf(blub, "; virtual address %08x size %08x", s->data_address, s->data_size);
00125 addComment(secaddr, 0, blub);
00126 sprintf(blub, "; file offset %08x", s->data_offset+coff_shared->hdr_ofs);
00127 addComment(secaddr, 0, blub);
00128 addComment(secaddr, 0, ";******************************************************************");
00129
00130
00131 sprintf(blub, "; end of section <%s>", getSegmentNameByAddress(secaddr));
00132 Address *secend_addr = (Address*)secaddr->duplicate();
00133 secend_addr->add(MAX(s->data_size, s->data_vsize));
00134 newLocation(secend_addr)->flags |= AF_FUNCTION_END;
00135 addComment(secend_addr, 0, "");
00136 addComment(secend_addr, 0, ";******************************************************************");
00137 addComment(secend_addr, 0, blub);
00138 addComment(secend_addr, 0, ";******************************************************************");
00139
00140 validarea->add(secaddr, secend_addr);
00141 Address *secini_addr = (Address *)secaddr->duplicate();
00142 secini_addr->add(MIN(s->data_size, s->data_vsize));
00143 if (validAddress(secaddr, scinitialized) && validAddress(secini_addr, scinitialized)) {
00144 initialized->add(secaddr, secini_addr);
00145 }
00146 s++;
00147 delete secaddr;
00148 delete secend_addr;
00149 delete secini_addr;
00150 }
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 addComment(entry, 0, "");
00207 addComment(entry, 0, ";****************************");
00208 if (coff_shared->coffheader.characteristics & COFF_DLL) {
00209 addComment(entry, 0, "; library entry point");
00210 } else {
00211 addComment(entry, 0, "; program entry point");
00212 }
00213 addComment(entry, 0, ";****************************");
00214 assignSymbol(entry, "entrypoint", label_func);
00215
00216 setLocationTreeOptimizeThreshold(1000);
00217 setSymbolTreeOptimizeThreshold(1000);
00218 delete entry;
00219
00220 Analyser::beginAnalysis();
00221 }
00222
00223
00224
00225
00226 OBJECT_ID CoffAnalyser::object_id() const
00227 {
00228 return ATOM_COFF_ANALYSER;
00229 }
00230
00231
00232
00233
00234 UINT CoffAnalyser::bufPtr(Address *Addr, byte *buf, int size)
00235 {
00236 FILEOFS ofs = addressToFileofs(Addr);
00237 assert(ofs != INVALID_FILE_OFS);
00238 file->seek(ofs);
00239 return file->read(buf, size);
00240 }
00241
00242 bool CoffAnalyser::convertAddressToRVA(Address *addr, RVA *r)
00243 {
00244 if (addr->object_id()==ATOM_ADDRESS_X86_FLAT_32) {
00245 *r = ((AddressX86Flat32*)addr)->addr;
00246 } else if (addr->object_id()==ATOM_ADDRESS_FLAT_32) {
00247 *r = ((AddressFlat32*)addr)->addr;
00248 } else {
00249 return false;
00250 }
00251 return true;
00252 }
00253
00254 Address *CoffAnalyser::createAddress()
00255 {
00256 switch (coff_shared->coffheader.machine) {
00257 case COFF_MACHINE_I386:
00258 case COFF_MACHINE_I486:
00259 case COFF_MACHINE_I586:
00260 return new AddressX86Flat32(0);
00261 default:
00262 return new AddressFlat32(0);
00263 }
00264 }
00265
00266 Address *CoffAnalyser::createAddress32(dword addr)
00267 {
00268 switch (coff_shared->coffheader.machine) {
00269 case COFF_MACHINE_I386:
00270 case COFF_MACHINE_I486:
00271 case COFF_MACHINE_I586:
00272 return new AddressX86Flat32(addr);
00273 default:
00274 return new AddressFlat32(addr);
00275 }
00276 }
00277
00278
00279
00280
00281 Assembler *CoffAnalyser::createAssembler()
00282 {
00283 switch (coff_shared->coffheader.machine) {
00284 case COFF_MACHINE_I386:
00285 case COFF_MACHINE_I486:
00286 case COFF_MACHINE_I586:
00287 Assembler *a = new x86asm(X86_OPSIZE32, X86_ADDRSIZE32);
00288 a->init();
00289 return a;
00290 }
00291 return NULL;
00292 }
00293
00294
00295
00296
00297
00298 FILEOFS CoffAnalyser::addressToFileofs(Address *Addr)
00299 {
00300 if (validAddress(Addr, scinitialized)) {
00301 FILEOFS ofs;
00302
00303 RVA rva;
00304 if (!convertAddressToRVA(Addr, &rva)) return INVALID_FILE_OFS;
00305 if (!coff_rva_to_ofs(&coff_shared->sections, rva, &ofs)) return INVALID_FILE_OFS;
00306 return ofs;
00307 } else {
00308 return INVALID_FILE_OFS;
00309 }
00310 }
00311
00312
00313
00314
00315 char *CoffAnalyser::getSegmentNameByAddress(Address *Addr)
00316 {
00317 static char sectionname[9];
00318 coff_section_headers *sections=&coff_shared->sections;
00319 int i;
00320 RVA rva;
00321 if (!convertAddressToRVA(Addr, &rva)) return NULL;
00322 coff_rva_to_section(sections, rva, &i);
00323 COFF_SECTION_HEADER *s=sections->sections+i;
00324 if (!coff_rva_is_valid(sections, rva)) return NULL;
00325 memmove(sectionname, s->name, 8);
00326 sectionname[8]=0;
00327 return sectionname;
00328 }
00329
00330
00331
00332
00333 const char *CoffAnalyser::getName()
00334 {
00335 return file->get_desc();
00336 }
00337
00338
00339
00340
00341 const char *CoffAnalyser::getType()
00342 {
00343 return "COFF/Analyser";
00344 }
00345
00346
00347
00348
00349 void CoffAnalyser::initCodeAnalyser()
00350 {
00351 Analyser::initCodeAnalyser();
00352 }
00353
00354
00355
00356
00357 void CoffAnalyser::initUnasm()
00358 {
00359 DPRINTF("coff_analy: ");
00360 switch (coff_shared->coffheader.machine) {
00361 case COFF_MACHINE_I386:
00362 case COFF_MACHINE_I486:
00363 case COFF_MACHINE_I586:
00364 DPRINTF("initing analy_x86_disassembler\n");
00365 analy_disasm = new AnalyX86Disassembler();
00366 ((AnalyX86Disassembler*)analy_disasm)->init(this, 0);
00367 break;
00368 case COFF_MACHINE_R3000:
00369 DPRINTF("no apropriate disassembler for MIPS\n");
00370 warnbox("No disassembler for MIPS!");
00371 break;
00372 case COFF_MACHINE_R4000:
00373 DPRINTF("no apropriate disassembler for MIPS\n");
00374 warnbox("No disassembler for MIPS!");
00375 break;
00376 case COFF_MACHINE_R10000:
00377 DPRINTF("no apropriate disassembler for MIPS\n");
00378 warnbox("No disassembler for MIPS!");
00379 break;
00380 case COFF_MACHINE_ALPHA:
00381 DPRINTF("initing alpha_axp_disassembler\n");
00382 analy_disasm = new AnalyAlphaDisassembler();
00383 ((AnalyAlphaDisassembler *)analy_disasm)->init(this);
00384 break;
00385 case COFF_MACHINE_POWERPC_LE:
00386 DPRINTF("no apropriate disassembler for POWER PC\n");
00387 warnbox("No disassembler for POWER PC!");
00388 break;
00389 case COFF_MACHINE_POWERPC_BE:
00390 analy_disasm = new AnalyPPCDisassembler();
00391 ((AnalyPPCDisassembler*)analy_disasm)->init(this);
00392 break;
00393 case COFF_MACHINE_UNKNOWN:
00394 default:
00395 DPRINTF("no apropriate disassembler for machine %04x\n", coff_shared->coffheader.machine);
00396 warnbox("No disassembler for unknown machine type %04x!", coff_shared->coffheader.machine);
00397 }
00398 }
00399
00400
00401
00402
00403 void CoffAnalyser::log(const char *msg)
00404 {
00405
00406
00407
00408
00409
00410
00411 }
00412
00413
00414
00415
00416 Address *CoffAnalyser::nextValid(Address *Addr)
00417 {
00418 return (Address *)validarea->findNext(Addr);
00419 }
00420
00421
00422
00423
00424 void CoffAnalyser::store(ht_object_stream *st)
00425 {
00426
00427
00428
00429
00430
00431 PUT_OBJECT(st, validarea);
00432 Analyser::store(st);
00433 }
00434
00435
00436
00437
00438 int CoffAnalyser::queryConfig(int mode)
00439 {
00440 switch (mode) {
00441 case Q_DO_ANALYSIS:
00442 case Q_ENGAGE_CODE_ANALYSER:
00443 case Q_ENGAGE_DATA_ANALYSER:
00444 return true;
00445 default:
00446 return 0;
00447 }
00448 }
00449
00450
00451
00452
00453 Address *CoffAnalyser::fileofsToAddress(FILEOFS fileofs)
00454 {
00455 RVA a;
00456 if (coff_ofs_to_rva(&coff_shared->sections, fileofs, &a)) {
00457 return createAddress32(a);
00458 } else {
00459 return new InvalidAddress();
00460 }
00461 }
00462
00463
00464
00465
00466 bool CoffAnalyser::validAddress(Address *Addr, tsectype action)
00467 {
00468 coff_section_headers *sections=&coff_shared->sections;
00469 int sec;
00470 RVA rva;
00471 if (!convertAddressToRVA(Addr, &rva)) return false;
00472 if (!coff_rva_to_section(sections, rva, &sec)) return false;
00473 COFF_SECTION_HEADER *s=sections->sections+sec;
00474 switch (action) {
00475 case scvalid:
00476 return true;
00477 case scread:
00478 return s->characteristics & COFF_SCN_MEM_READ;
00479 case scwrite:
00480 return s->characteristics & COFF_SCN_MEM_WRITE;
00481 case screadwrite:
00482 return s->characteristics & COFF_SCN_MEM_WRITE;
00483 case sccode:
00484
00485 if (!coff_rva_is_physical(sections, rva)) return false;
00486 return (s->characteristics & (COFF_SCN_MEM_EXECUTE | COFF_SCN_CNT_CODE));
00487 case scinitialized:
00488 if (!coff_rva_is_physical(sections, rva)) return false;
00489 return !(s->characteristics & COFF_SCN_CNT_UNINITIALIZED_DATA);
00490 }
00491 return false;
00492 }
00493
00494