Make your own free website on Tripod.com
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

codeprn.cpp

Go to the documentation of this file.
00001 /*
00002 PeRdr - PE file disassembler
00003 Copyright (C) 1999-2003 Frediano Ziglio
00004 -----
00005 
00006 This program is free software; you can redistribute it and/or modify
00007 it under the terms of the GNU General Public License as published by
00008 the Free Software Foundation; either version 2 of the License, or
00009 (at your option) any later version.
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 INFORMATION
00022   www: http://freddy77.tripod.com/perdr/
00023   e-mail: freddy77@angelfire.com
00024 */
00025 #include "global.h"
00026 #ifdef HAVE_HDRSTOP
00027 #pragma hdrstop
00028 #endif
00029 
00030 #include "module.h"
00031 #include "code.h"
00032 #include "codeglob.h"
00033 #include "perdroptions.h"
00034 
00035 using namespace std;
00036 
00037 // !!!
00038 static bool commentBeginned = false;
00039 
00040 // scrittura commenti
00041 static void StartBeginComment()
00042 {
00043   // scrivi inizio commento
00044   if (!commentBeginned)
00045     printf("\n");
00046   else
00047     printf("\n|\n");
00048   commentBeginned = true;
00049 
00050   printf("* ");
00051 }
00052 
00053 static void StartComment()
00054 {
00055   if (!commentBeginned)
00056     StartBeginComment();
00057   else
00058     printf("\n|");
00059 }
00060 
00061 static void EndComment()
00062 {
00063   if (commentBeginned)
00064   {
00065     printf("\n|\n");
00066     commentBeginned = false;
00067   }
00068 }
00069 
00070 // testa vari riferimenti
00071 struct CheckRef
00072 {
00073   CheckRef():count(0) {};
00074   void operator()(const IstrReference& ref)
00075   {
00076     if (!ref.direct)
00077     {
00078       if (count==0)
00079       {
00080         StartBeginComment();
00081         printf("Referenced by a (U)nconditional or (C)onditional Jump "
00082                "or (c)all at Address:");
00083       }
00084       char type = '?';
00085       switch(ref.type)
00086       {
00087       case FLOW_CALL:  type = 'c'; break;
00088       case FLOW_JUMP:  type = 'U'; break;
00089       case FLOW_CJUMP: type = 'C'; break;
00090       }
00091       if ( (count%4) == 0 )
00092         StartComment();
00093       else
00094         printf(",");
00095       printf(" %08X(%c)",ref.to,type);
00096           ++count;
00097     }
00098   }
00099   int count;
00100 };
00101 
00102 void CodeParser::CheckReference(vma_t address)
00103 {
00104   // entry point
00105   if (address == module->GetEntryPoint())
00106   {
00107     StartBeginComment();
00108     printf("Program entry point");
00109   }
00110 
00111   // export
00112   // !!! manca ordinal
00113   pair<Symbols::iterator,Symbols::iterator> sym = module->GetExportSymbols()[address];
00114   for(;sym.first != sym.second;++sym.first)
00115   {
00116     StartBeginComment();
00117     printf("Exported function %s",(*sym.first).name.c_str());
00118   }
00119 
00120         // testa presenza riferimento
00121   std::for_each(istrReferences.beginReferenceTo(address),
00122       istrReferences.endReferenceTo(address),
00123       CheckRef());
00124 }
00125 
00126 #ifdef __BORLANDC__
00127 #pragma argsused
00128 #endif
00129 void CodeParser::CheckJumpReference(vma_t address,const Instruction& instruction)
00130 {
00131         // check for api reference
00132   for (int i=0; i<instruction.numArg; ++i)
00133   {
00134     const Param &arg = instruction.Args[i];
00135     if (arg.type == Param::t_memory)
00136     {
00137       // call/jmp dword ptr [constant]
00138                         if (arg.mem_reg1 == null_reg && arg.mem_reg2 == null_reg)
00139       {
00140         pair<Symbols::iterator,Symbols::iterator> sym = module->GetSymbols()[arg.literal];
00141         for(;sym.first != sym.second;++sym.first)
00142         {
00143           StartBeginComment();
00144           printf("Reference to %s",(*sym.first).name.c_str());
00145         }
00146       }
00147     }
00148     if (arg.type == Param::t_literal)
00149     {
00150       // salti a jmp ad api
00151                         if (IsPresent(apiAlias,arg.literal))
00152       {
00153         pair<Symbols::iterator,Symbols::iterator> sym = module->GetSymbols()[apiAlias[arg.literal]];
00154         for(;sym.first != sym.second;++sym.first)
00155         {
00156           StartBeginComment();
00157           printf("Reference to %s",(*sym.first).name.c_str());
00158         }
00159       }
00160 
00161       // salti a funzioni esportate
00162       pair<Symbols::iterator,Symbols::iterator> sym = module->GetExportSymbols()[arg.literal];
00163       for(;sym.first != sym.second;++sym.first)
00164       {
00165         StartBeginComment();
00166         printf("Reference to %s",(*sym.first).name.c_str());
00167       }
00168     }
00169   }
00170 }
00171 
00172 // stampa una stringa
00173 // !!! usa funzione WriteBinary (da fare copiando questa)
00174 void CodeParser::WriteString(vma_t address,int len) const
00175 {
00176   EndComment();
00177 
00178   _PRG_ASSERT(&*module != NULL);
00179   _PRG_ASSERT(len>0);
00180         ObjectModule::DataReader reader = module->GetDataReader(address);
00181   const unsigned nCarInRow = 16;
00182   char buffer[3*nCarInRow+nCarInRow+10];
00183   for(unsigned n=0;;++n)
00184   {
00185     unsigned part = n%nCarInRow;
00186     if (part==0)
00187     {
00188       if (n>=nCarInRow)
00189       {
00190         buffer[nCarInRow*3+nCarInRow+1] = '\0';
00191         printf("%08X %s\n",address+n-nCarInRow,buffer);
00192         if (n>=(unsigned int)len)
00193           return;
00194       }
00195       // inizializza buffer
00196       memset(buffer,' ',sizeof(buffer));
00197     }
00198     if (n<(unsigned int)len)
00199     {
00200       uint8_t car = reader.ReadByte();
00201 
00202       // scrive il carattere in esadecimale e carattere relativo
00203       sprintf(buffer+part*3,"%02X",car);
00204       buffer[part*3+2] = part==(nCarInRow/2-1)?'-':' ';
00205       // !!! settare come opzione carattere ?
00206       buffer[nCarInRow*3+1+part] = isprint(car)?car:'.';
00207     }
00208   }
00209 }
00210 
00211 // scrive inizio istruzione/BYTE/DWORD come da inizio
00212 // legge da ::module
00213 void CodeParser::WriteBegin(vma_t address,int num_bytes) const
00214 {
00215   int x=0,c;
00216   EndComment();
00217   printf("%08lX ",(long int)address);
00218   if (::options.showBytes)
00219   {
00220                 ObjectModule::DataReader reader = module->GetDataReader(address);
00221     for (int i=0;i<num_bytes;++i)
00222     {
00223       if ( i%10 == 0 )
00224       {
00225         x = 0;
00226         if (i != 0)
00227           printf("\n         ");
00228       }
00229       c = reader.ReadByte();
00230       printf("%02X",c);
00231       x += 2;
00232     }
00233 
00234     for (;x!=20;x+=2)
00235       printf("  ");
00236   }
00237 
00238   printf("\t");
00239 }
00240 
00241 static void WritePriority(ByteInfo::TPriority priority)
00242 {
00243   const char *s = "unknown";
00244   switch (priority)
00245   {
00246   case ByteInfo::priNone:
00247     s = "none"; break;
00248   case ByteInfo::priCheckOnly:
00249     s = "check only"; break;
00250   case ByteInfo::priFiller:
00251     s = "filler"; break;
00252   case ByteInfo::priConstant:
00253     s = "constant"; break;
00254   case ByteInfo::priApi:
00255     s = "api"; break;
00256   case ByteInfo::priExport:
00257     s = "export"; break;
00258   case ByteInfo::priHeuristics:
00259     s = "heuristics"; break;
00260   case ByteInfo::priSafeHeuristics:
00261     s = "safe heuristics"; break;
00262   case ByteInfo::priSafeExport:
00263     s = "safe export"; break;
00264   case ByteInfo::priEntryPoint:
00265     s = "entry point"; break;
00266   }
00267   StartBeginComment();
00268   printf("Current priority: %s",s);
00269 }
00270 
00271 void CodeParser::WriteCode()
00272 {
00273         vma_t end;
00274 
00275   // disassembly vero e proprio
00276   FOR_EACH_SECTION_CODE_BEGIN(module,p)
00277 
00278     InstructionDecoder decoder(module->GetRelocationInfos());
00279 
00280     // init as invalid priority
00281     ByteInfo::TPriority priority = ByteInfo::TPriority(-1);
00282 
00283     vma_t pc = (*p).begin;
00284     end      = (*p).end;
00285     for(; pc<end; )
00286     {
00287                         ObjectModule::DataReader reader = module->GetDataReader(pc);
00288           int c;
00289           Instruction currInstruction;
00290 
00291       // testa cambio priorita
00292       if (options.showPriority)
00293       {
00294         ByteInfo::TPriority currPriority = byteInfo[pc].GetPriority();
00295         if (currPriority != priority)
00296         {
00297           WritePriority(currPriority);
00298           priority = currPriority;
00299         }
00300       }
00301 
00302       // test for reference
00303       CheckReference(pc);
00304 
00305       // testa se tipo conosciuto
00306       unsigned len = byteInfo.GetLen(pc);
00307       bool isInstruction = true;
00308 
00309       if (len != 0)
00310       {
00311         isInstruction = false;
00312         const ByteInfo& info = byteInfo[pc];
00313         switch (info.GetType())
00314         {
00315         case ByteInfo::typeInteger:
00316           {
00317             uint32_t i;
00318             switch (len)
00319             {
00320             case 1:
00321               i = reader.ReadByte();
00322               WriteBegin(pc,len);
00323               printf("BYTE %02X\n",i);
00324               break;
00325             case 2:
00326               i = reader.ReadWord();
00327               WriteBegin(pc,len);
00328               printf("WORD %04X\n",i);
00329               break;
00330             case 4:
00331               i = reader.ReadDword();
00332               WriteBegin(pc,len);
00333               printf("DWORD %08X\n",i);
00334               break;
00335 
00336             default:
00337               // !!! scrive come bytes normali
00338               //_PRG_ASSERT(0);
00339               WriteString(pc,len);
00340             }
00341             pc += len;
00342           }
00343           break;
00344         case ByteInfo::typePointer:
00345           {
00346             _PRG_ASSERT(len == (unsigned int)addr_bytes);
00347             vma_t address = reader.ReadDword();
00348             WriteBegin(pc,len);
00349             printf("DWORD %08lX\n",(long int)address);
00350             pc += len;
00351           }
00352           break;
00353         case ByteInfo::typeLoader:
00354           StartBeginComment();
00355           printf("Loader bytes");
00356           WriteString(pc,len);
00357           pc += len;
00358           break;
00359         case ByteInfo::typeASCIIZ:
00360           _DEBUG_(fprintf(stderr,"Debug: (String) reached\n"));
00361           WriteString(pc,len);
00362           pc += len;
00363           break;
00364         default:
00365           isInstruction = true;
00366         }
00367       }
00368 
00369       if (isInstruction)
00370       {
00371         // leggi successiva istruzione
00372         int result = decoder.Decode(currInstruction,reader);
00373 
00374         if ( !result || (byteInfo.GetIstrLen(pc)==0 &&
00375              byteInfo.IsOccupied(pc,result)) )
00376         {
00377                                         reader = module->GetDataReader(pc);
00378           c = reader.ReadByte();
00379           WriteBegin(pc,1);
00380             printf("BYTE\t%02X\n",c);
00381           pc += 1;
00382         }
00383         else
00384         {
00385             CheckJumpReference(pc,currInstruction);
00386           // !!! aggiungere codice per reference a stringhe o altro
00387           WriteBegin(pc,result);
00388                             WriteInstruction(currInstruction);
00389             // va avanti
00390             pc += result;
00391         }
00392       }
00393     }
00394   FOR_EACH_SECTION_CODE_END(module,p)
00395 }
00396 
00397 // vim:tabstop=2:mouse=a:

Generated on Mon Jan 13 22:20:34 2003 for perdr by doxygen1.2.15