00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
00041 static void StartBeginComment()
00042 {
00043
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
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
00105 if (address == module->GetEntryPoint())
00106 {
00107 StartBeginComment();
00108 printf("Program entry point");
00109 }
00110
00111
00112
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
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
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
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
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
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
00173
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
00196 memset(buffer,' ',sizeof(buffer));
00197 }
00198 if (n<(unsigned int)len)
00199 {
00200 uint8_t car = reader.ReadByte();
00201
00202
00203 sprintf(buffer+part*3,"%02X",car);
00204 buffer[part*3+2] = part==(nCarInRow/2-1)?'-':' ';
00205
00206 buffer[nCarInRow*3+1+part] = isprint(car)?car:'.';
00207 }
00208 }
00209 }
00210
00211
00212
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
00276 FOR_EACH_SECTION_CODE_BEGIN(module,p)
00277
00278 InstructionDecoder decoder(module->GetRelocationInfos());
00279
00280
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
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
00303 CheckReference(pc);
00304
00305
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
00338
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
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
00387 WriteBegin(pc,result);
00388 WriteInstruction(currInstruction);
00389
00390 pc += result;
00391 }
00392 }
00393 }
00394 FOR_EACH_SECTION_CODE_END(module,p)
00395 }
00396
00397