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: https://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