Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

pef_analy.cc

Go to the documentation of this file.
00001 /* 
00002  *      HT Editor
00003  *      pef_analy.cc
00004  *
00005  *      Copyright (C) 1999-2002 Sebastian Biallas (sb@web-productions.de)
00006  *
00007  *      This program is free software; you can redistribute it and/or modify
00008  *      it under the terms of the GNU General Public License version 2 as
00009  *      published by the Free Software Foundation.
00010  *
00011  *      This program is distributed in the hope that it will be useful,
00012  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *      GNU General Public License for more details.
00015  *
00016  *      You should have received a copy of the GNU General Public License
00017  *      along with this program; if not, write to the Free Software
00018  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  */
00020 
00021 #include "analy.h"
00022 #include "analy_names.h"
00023 #include "analy_ppc.h"
00024 #include "analy_register.h"
00025 #include "global.h"
00026 #include "pef_analy.h"
00027 
00028 #include "htctrl.h"
00029 #include "htdebug.h"
00030 #include "htiobox.h"
00031 #include "htpef.h"
00032 #include "htstring.h"
00033 #include "pestruct.h"
00034 #include "snprintf.h"
00035 #include "x86asm.h"
00036 
00037 extern "C" {
00038 #include "demangle.h"
00039 }
00040 
00041 #include <stdio.h>
00042 #include <stdlib.h>
00043 #include <string.h>
00044 
00045 /*
00046  *
00047  */
00048 
00049 void PEFAnalyser::init(ht_pef_shared_data *Pef_shared, ht_streamfile *File)
00050 {
00051         pef_shared = Pef_shared;
00052         file = File;
00053 
00054         validarea = new Area();
00055         validarea->init();
00056 
00057         Analyser::init();
00058 }
00059 
00060 void PEFAnalyser::beginAnalysis()
00061 {
00062 //      Address *entry = NULL;
00063 
00064 //      entry = createAddress32(pef_shared->header32.e_entry);
00065 
00066         setLocationTreeOptimizeThreshold(100);
00067         setSymbolTreeOptimizeThreshold(100);
00068 
00069         /*
00070          *      entrypoint
00071          */
00072 //      pushAddress(entry, entry);
00073         
00074         /*
00075          *      give all sections a descriptive comment:
00076          */
00077 
00078         PEF_SECTION_HEADER *s32=pef_shared->sheaders.sheaders;
00079         char blub[100];
00080         for (UINT i=0; i < pef_shared->sheaders.count; i++) {
00081                 Address *secaddr;
00082                 secaddr = createAddress32(s32->defaultAddress);
00083                 if (validAddress(secaddr, scvalid)) {
00084                         ht_snprintf(blub, sizeof blub, ";  section %d <%s>", i, getSegmentNameByAddress(secaddr));
00085                         addComment(secaddr, 0, "");
00086                         addComment(secaddr, 0, ";******************************************************************");
00087                         addComment(secaddr, 0, blub);
00088                         ht_snprintf(blub, sizeof blub, ";  virtual address  %08x  virtual size   %08x", s32->defaultAddress, s32->totalSize);
00089                         addComment(secaddr, 0, blub);
00090                         ht_snprintf(blub, sizeof blub, ";  file offset      %08x  file size      %08x", s32->containerOffset, s32->packedSize);
00091                         addComment(secaddr, 0, blub);
00092                         addComment(secaddr, 0, ";******************************************************************");
00093 
00094                         // mark end of sections
00095                         ht_snprintf(blub, sizeof blub, ";  end of section <%s>", getSegmentNameByAddress(secaddr));
00096                         Address *secend_addr = (Address *)secaddr->duplicate();
00097                         secend_addr->add(s32->totalSize);
00098                         newLocation(secend_addr)->flags |= AF_FUNCTION_END;
00099                         addComment(secend_addr, 0, "");
00100                         addComment(secend_addr, 0, ";******************************************************************");
00101                         addComment(secend_addr, 0, blub);
00102                         addComment(secend_addr, 0, ";******************************************************************");
00103 
00104                         validarea->add(secaddr, secend_addr);
00105 
00106                         delete secend_addr;
00107                 }
00108                 delete secaddr;
00109                 s32++;
00110         }
00111 
00112 /* symbols */
00113 /*      for (UINT i=1; i<pef_shared->sheaders.count; i++) {
00114                 if ((pef_shared->sheaders.sheaders32[i].sh_type==PEF_SHT_SYMTAB) || (pef_shared->sheaders.sheaders32[i].sh_type==PEF_SHT_DYNSYM)) {
00115                         initInsertSymbols(i);
00116                 }
00117         }*/
00118 /*      assignSymbol(entry, "entrypoint", label_func);
00119         addComment(entry, 0, "");
00120         addComment(entry, 0, ";****************************");
00121         addComment(entry, 0, ";  executable entry point");
00122         addComment(entry, 0, ";****************************");*/
00123 
00124         setLocationTreeOptimizeThreshold(1000);
00125         setSymbolTreeOptimizeThreshold(1000);
00126 //      delete entry;
00127         
00128         Analyser::beginAnalysis();
00129 }
00130 
00131 /*
00132  *
00133  */
00134 void PEFAnalyser::initInsertSymbols(int shidx)
00135 {
00136 /*      char pef_buffer[1024];
00137         if (pef_shared->ident.e_ident[PEF_EI_CLASS] == PEFCLASS32) {
00138 
00139                 FILEOFS h=pef_shared->sheaders.sheaders32[shidx].sh_offset;
00140                 FILEOFS sto=pef_shared->sheaders.sheaders32[pef_shared->sheaders.sheaders32[shidx].sh_link].sh_offset;
00141                 UINT symnum=pef_shared->sheaders.sheaders32[shidx].sh_size / sizeof (PEF_SYMBOL32);
00142 
00143                 int *entropy = random_permutation(symnum);
00144                 for (UINT i=0; i<symnum; i++) {
00145                         PEF_SYMBOL32 sym;
00146                         if (entropy[i] == 0) continue;
00147                         file->seek(h+entropy[i]*sizeof (PEF_SYMBOL32));
00148                         file->read(&sym, sizeof sym);
00149                         create_host_struct(&sym, PEF_SYMBOL32_struct, pef_shared->byte_order);
00150 
00151                         file->seek(sto+sym.st_name);
00152                         char *name = fgetstrz(file);
00153                         if (!name) continue;
00154 
00155                         switch (sym.st_shndx) {
00156                                 case PEF_SHN_UNDEF:
00157                                         break;
00158                                 case PEF_SHN_ABS:
00159                                         break;
00160                                 case PEF_SHN_COMMON:
00161                                         break;
00162                                 default: {
00163                                         // sym.st_shndx
00164                                         break;
00165                                 }
00166                         }
00167 
00168                         char *bind;
00169                         switch (PEF32_ST_BIND(sym.st_info)) {
00170                                 case PEF_STB_LOCAL:
00171                                         bind="local";
00172                                         break;
00173                                 case PEF_STB_GLOBAL:
00174                                         bind="global";
00175                                         break;
00176                                 case PEF_STB_WEAK:
00177                                         bind="weak";
00178                                         break;
00179                                 default:
00180                                         bind="?";
00181                                         break;
00182                         }
00183 
00184                         switch (PEF32_ST_TYPE(sym.st_info)) {
00185                                 case PEF_STT_NOTYPE:
00186                                 case PEF_STT_FUNC: {
00187                                 char *label = name;
00188                                         if (!getSymbolByName(label)) {
00189                                                 Address *address = createAddress32(sym.st_value);
00190                                                 if (validAddress(address, scvalid)) {
00191                                                         char *demangled = cplus_demangle(label, DMGL_PARAMS | DMGL_ANSI);
00192 
00193                                                         make_valid_name(label, label);
00194 
00195                                                         ht_snprintf(pef_buffer, sizeof pef_buffer, "; function %s (%s)", (demangled) ? demangled : label, bind);
00196 
00197                                                         if (demangled) free(demangled);
00198 
00199                                                         addComment(address, 0, "");
00200                                                         addComment(address, 0, ";********************************************************");
00201                                                         addComment(address, 0, pef_buffer);
00202                                                         addComment(address, 0, ";********************************************************");
00203                                                         pushAddress(address, address);
00204                                                         assignSymbol(address, label, label_func);
00205                                                 }
00206                                                 delete address;
00207                                         }
00208                                         break;
00209                                 }
00210                                 case PEF_STT_OBJECT: {
00211                                         char *label = name;
00212                                         if (!getSymbolByName(label)) {
00213                                                 Address *address = createAddress32(sym.st_value);
00214                                                 if (validAddress(address, scvalid)) {
00215 
00216                                                         char *demangled = cplus_demangle(label, DMGL_PARAMS | DMGL_ANSI);
00217                                         
00218                                                         make_valid_name(label, label);
00219                                         
00220                                                         ht_snprintf(pef_buffer, sizeof pef_buffer, "; data object %s, size %d (%s)", (demangled) ? demangled : label, sym.st_size, bind);
00221 
00222                                                         if (demangled) free(demangled);
00223 
00224                                                         addComment(address, 0, "");
00225                                                         addComment(address, 0, ";********************************************************");
00226                                                         addComment(address, 0, pef_buffer);
00227                                                         addComment(address, 0, ";********************************************************");
00228                                                         assignSymbol(address, label, label_data);
00229                                                 }
00230                                                 delete address;
00231                                         }
00232                                         break;
00233                                 }
00234                                 case PEF_STT_SECTION:
00235                                 case PEF_STT_FILE:
00236                                         break;
00237                         }
00238                         free(name);
00239                 }
00240                 if (entropy) free(entropy);
00241         } else {
00242                 // FIXME: 64 bit
00243                 FILEOFS h=pef_shared->sheaders.sheaders64[shidx].sh_offset.lo;
00244                 FILEOFS sto=pef_shared->sheaders.sheaders64[pef_shared->sheaders.sheaders64[shidx].sh_link].sh_offset.lo;
00245                 UINT symnum=pef_shared->sheaders.sheaders64[shidx].sh_size.lo / sizeof (PEF_SYMBOL64);
00246 
00247                 int *entropy = random_permutation(symnum);
00248                 for (UINT i=0; i<symnum; i++) {
00249                         PEF_SYMBOL64 sym;
00250                         if (entropy[i] == 0) continue;
00251                         file->seek(h+entropy[i]*sizeof (PEF_SYMBOL64));
00252                         file->read(&sym, sizeof sym);
00253                         create_host_struct(&sym, PEF_SYMBOL64_struct, pef_shared->byte_order);
00254 
00255                         file->seek(sto+sym.st_name);
00256                         char *name = fgetstrz(file);
00257                         if (!name) continue;
00258 
00259                         switch (sym.st_shndx) {
00260                                 case PEF_SHN_UNDEF:
00261                                         break;
00262                                 case PEF_SHN_ABS:
00263                                         break;
00264                                 case PEF_SHN_COMMON:
00265                                         break;
00266                                 default: {
00267                                         // sym.st_shndx
00268                                         break;
00269                                 }
00270                         }
00271 
00272                         char *bind;
00273                         switch (PEF64_ST_BIND(sym.st_info)) {
00274                                 case PEF_STB_LOCAL:
00275                                         bind="local";
00276                                         break;
00277                                 case PEF_STB_GLOBAL:
00278                                         bind="global";
00279                                         break;
00280                                 case PEF_STB_WEAK:
00281                                         bind="weak";
00282                                         break;
00283                                 default:
00284                                         bind="?";
00285                                         break;
00286                         }
00287 
00288                         switch (PEF64_ST_TYPE(sym.st_info)) {
00289                                 case PEF_STT_NOTYPE:
00290                                 case PEF_STT_FUNC: {
00291                                         char *label = name;
00292                                         if (!getSymbolByName(label)) {
00293                                                 Address *address = createAddress64(sym.st_value);
00294 
00295                                                 char *demangled = cplus_demangle(label, DMGL_PARAMS | DMGL_ANSI);
00296 
00297                                                 make_valid_name(label, label);
00298 
00299                                                 ht_snprintf(pef_buffer, sizeof pef_buffer, "; function %s (%s)", (demangled) ? demangled : label, bind);
00300 
00301                                                 if (demangled) free(demangled);
00302 
00303                                                 addComment(address, 0, "");
00304                                                 addComment(address, 0, ";********************************************************");
00305                                                 addComment(address, 0, pef_buffer);
00306                                                 addComment(address, 0, ";********************************************************");
00307                                                 pushAddress(address, address);
00308                                                 assignSymbol(address, label, label_func);
00309                                                 
00310                                                 delete address;
00311                                         }
00312                                         break;
00313                                 }
00314                                 case PEF_STT_OBJECT: {
00315                                         char *label = name;
00316                                         if (!getSymbolByName(label)) {
00317                                                 Address *address = createAddress64(sym.st_value);
00318 
00319                                                 char *demangled = cplus_demangle(label, DMGL_PARAMS | DMGL_ANSI);
00320                                         
00321                                                 make_valid_name(label, label);
00322                                         
00323                                                 ht_snprintf(pef_buffer, sizeof pef_buffer, "; data object %s, size %d (%s)", (demangled) ? demangled : label, sym.st_size.lo, bind);
00324 
00325                                                 if (demangled) free(demangled);
00326 
00327                                                 addComment(address, 0, "");
00328                                                 addComment(address, 0, ";********************************************************");
00329                                                 addComment(address, 0, pef_buffer);
00330                                                 addComment(address, 0, ";********************************************************");
00331                                                 assignSymbol(address, label, label_data);
00332                                                 
00333                                                 delete address;
00334                                         }
00335                                         break;
00336                                 }
00337                                 case PEF_STT_SECTION:
00338                                 case PEF_STT_FILE:
00339                                         break;
00340                         }
00341                         free(name);
00342                 }
00343                 if (entropy) free(entropy);
00344         }*/
00345 }
00346 
00347 /*
00348  *
00349  */
00350 int PEFAnalyser::load(ht_object_stream *f)
00351 {
00352         GET_OBJECT(f, validarea);
00353         return Analyser::load(f);
00354 }
00355 
00356 /*
00357  *
00358  */
00359 void PEFAnalyser::done()
00360 {
00361         validarea->done();
00362         delete validarea;
00363         Analyser::done();
00364 }
00365 
00366 OBJECT_ID PEFAnalyser::object_id() const
00367 {
00368         return ATOM_PEF_ANALYSER;
00369 }
00370 
00371 /*
00372  *
00373  */
00374 UINT PEFAnalyser::bufPtr(Address *Addr, byte *buf, int size)
00375 {
00376         FILEOFS ofs = addressToFileofs(Addr);
00377 /*     if (ofs == INVALID_FILE_OFS) {
00378                 int as = 1;
00379         }*/
00380         assert(ofs != INVALID_FILE_OFS);
00381         file->seek(ofs);
00382         return file->read(buf, size);;
00383 }
00384 
00385 bool PEFAnalyser::convertAddressToPEFAddress(Address *addr, PEFAddress *r)
00386 {
00387         if (addr->object_id()==ATOM_ADDRESS_FLAT_32) {
00388                 r->a32 = ((AddressFlat32*)addr)->addr;
00389                 return true;
00390         } else {
00391                 return false;
00392         }
00393 }
00394 
00395 Address *PEFAnalyser::createAddress()
00396 {
00397         return new AddressFlat32();
00398 }
00399 
00400 Address *PEFAnalyser::createAddress32(dword addr)
00401 {
00402         return new AddressFlat32(addr);
00403 }
00404 
00405 Address *PEFAnalyser::createAddress64(qword addr)
00406 {
00407         return new AddressFlat64(addr);
00408 }
00409 
00410 /*
00411  *
00412  */
00413 Assembler *PEFAnalyser::createAssembler()
00414 {
00415         return NULL;
00416 }
00417 
00418 /*
00419  *
00420  */
00421 FILEOFS PEFAnalyser::addressToFileofs(Address *Addr)
00422 {
00423         if (validAddress(Addr, scinitialized)) {
00424                 dword ofs;
00425                 PEFAddress ea;
00426                 if (!convertAddressToPEFAddress(Addr, &ea)) return INVALID_FILE_OFS;
00427                 if (!pef_addr_to_ofs(&pef_shared->sheaders, ea, &ofs)) return INVALID_FILE_OFS;
00428                 return ofs;
00429         } else {
00430                 return INVALID_FILE_OFS;
00431         }
00432 }
00433 
00434 /*
00435  *
00436  */
00437 char *PEFAnalyser::getSegmentNameByAddress(Address *Addr)
00438 {
00439         static char pef_sectionname[33];
00440         pef_section_headers *sections=&pef_shared->sheaders;
00441         int i;
00442         PEFAddress ea;
00443         if (!convertAddressToPEFAddress(Addr, &ea)) return NULL;
00444         if (!pef_addr_to_section(sections, ea, &i)) return NULL;
00445         if ((uint32)pef_shared->sheaders.sheaders[i].nameOffset == 0xffffffff) {
00446                 ht_snprintf(pef_sectionname, sizeof pef_sectionname, "unnamed%d", i);
00447         } else {
00448 //              strncpy(pef_sectionname, pef_shared->shnames[i], 32);
00449 //              pef_sectionname[32]=0;
00450                 strcpy(pef_sectionname, "nyi");
00451         }
00452         return pef_sectionname;
00453 }
00454 
00455 /*
00456  *
00457  */
00458 const char *PEFAnalyser::getName()
00459 {
00460         return file->get_desc();
00461 }
00462 
00463 /*
00464  *
00465  */
00466 const char *PEFAnalyser::getType()
00467 {
00468         return "PEF/Analyser";
00469 }
00470 
00471 /*
00472  *
00473  */
00474 void PEFAnalyser::initCodeAnalyser()
00475 {
00476         Analyser::initCodeAnalyser();
00477 }
00478 
00479 /*
00480  *
00481  */
00482 void PEFAnalyser::initUnasm()
00483 {
00484         DPRINTF("pef_analy: ");
00485         switch (pef_shared->arch) {
00486                 case PEFARCH_PowerPC:
00487                         DPRINTF("initing analy_ppc_disassembler\n");
00488                         analy_disasm = new AnalyPPCDisassembler();
00489                         ((AnalyPPCDisassembler*)analy_disasm)->init(this);
00490                         break;
00491                 case PEFARCH_M68K:
00492                         DPRINTF("no disassembler for machine 'm68k'\n");
00493                         warnbox("No disassembler for machine 'm68k'!");
00494                         break;
00495                 default:
00496                         break;
00497         }
00498 }
00499 
00500 /*
00501  *
00502  */
00503 void PEFAnalyser::log(const char *msg)
00504 {
00505         /*
00506          *      log() does to much traffic so dont log
00507          *   perhaps we reactivate this later
00508          *
00509          */
00510 /*      LOG(msg);*/
00511 }
00512 
00513 /*
00514  *
00515  */
00516 Address *PEFAnalyser::nextValid(Address *Addr)
00517 {
00518         return (Address *)validarea->findNext(Addr);
00519 }
00520 
00521 /*
00522  *
00523  */
00524 void PEFAnalyser::store(ht_object_stream *f)
00525 {
00526         PUT_OBJECT(f, validarea);
00527         Analyser::store(f);
00528 }
00529 
00530 /*
00531  *
00532  */
00533 int PEFAnalyser::queryConfig(int mode)
00534 {
00535         switch (mode) {
00536                 case Q_DO_ANALYSIS:
00537                 case Q_ENGAGE_CODE_ANALYSER:
00538                 case Q_ENGAGE_DATA_ANALYSER:
00539                         return true;
00540                 default:
00541                         return 0;
00542         }
00543 }
00544 
00545 /*
00546  *
00547  */
00548 Address *PEFAnalyser::fileofsToAddress(FILEOFS fileofs)
00549 {
00550         PEFAddress ea;
00551         if (pef_ofs_to_addr(&pef_shared->sheaders, fileofs, &ea)) {
00552                 return createAddress32(ea.a32);
00553         } else {
00554                 return new InvalidAddress();
00555         }
00556 }
00557 
00558 /*
00559  *
00560  */
00561 bool PEFAnalyser::validAddress(Address *Addr, tsectype action)
00562 {
00563         pef_section_headers *sections=&pef_shared->sheaders;
00564         int sec;
00565         PEFAddress ea;
00566         if (!convertAddressToPEFAddress(Addr, &ea)) return false;
00567         if (!pef_addr_to_section(sections, ea, &sec)) return false;
00568         PEF_SECTION_HEADER *s = sections->sheaders + sec;
00569         switch (action) {
00570                 case scvalid:
00571                         return true;
00572                 case scread:
00573                         return true;
00574                 case scwrite:
00575                 case screadwrite:
00576                         return (s->sectionKind == 1) ||
00577                                 (s->sectionKind == 2) ||
00578                                 (s->sectionKind == 6);
00579                 case sccode:
00580                         return (s->sectionKind == 0);
00581                 case scinitialized:
00582                         return (s->sectionKind == 0) ||
00583                                 (s->sectionKind == 1) ||
00584                                 (s->sectionKind == 3) ||
00585                                 (s->sectionKind == 6)   /* FIXME: is 6 really initialized ? */;
00586         }
00587         return false;
00588 }

Generated on Fri May 7 21:15:42 2004 by doxygen 1.3.5