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 "signfile.hpp"
00031 #include "module.h"
00032 #include "code.h"
00033 #include "codeglob.h"
00034 #include "x86istr.h"
00035 #include "heuristic.h"
00036 #include "codescan.h"
00037 #ifdef DEBUG
00038 #include <cctype>
00039 #endif
00040 #include "utils/f77auto_ptr"
00041
00042 using namespace std;
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 void CodeParser::_ReverseScan(IScanning* scanning,vma_t address,IMachineStatus* status)
00054 {
00055 _PRG_ASSERT(scanning != NULL);
00056 _PRG_ASSERT(status != NULL);
00057 _PRG_ASSERT(&*module != NULL);
00058 vma_t addr = address;
00059
00060 for(;;)
00061 {
00062
00063 IstrReferences::iterator i =
00064 istrReferences.beginReferenceTo(addr);
00065 IstrReferences::iterator end =
00066 istrReferences.endReferenceTo(addr);
00067 for(;i != end; ++i)
00068 {
00069 if ( !(*i).direct )
00070 {
00071 IMachineStatus* newStatus = status->Clone();
00072 _ReverseScan(scanning,(*i).to,newStatus);
00073 delete newStatus;
00074 }
00075 }
00076
00077
00078 if (!byteInfo[addr].IsPrevInstruction())
00079 break;
00080
00081
00082 _DEBUG_(vma_t debug_temp_addr = addr);
00083 while (byteInfo.GetIstrLen(--addr) == 0);
00084
00085
00086 _PRG_ASSERT(byteInfo.GetIstrLen(addr) == (debug_temp_addr-addr));
00087
00088
00089 Instruction currInstruction;
00090 int result = GetInstruction(*module,addr,currInstruction);
00091 if (!result)
00092 {
00093 _PRG_ASSERT(0);
00094 return;
00095 }
00096
00097
00098 if (!scanning->ProcessInstruction(addr,currInstruction,status,*this))
00099 break;
00100 }
00101 }
00102
00103 void CodeParser::ReverseScan(IScanning* scanning,vma_t address)
00104 {
00105 _PRG_ASSERT(scanning != NULL);
00106 IMachineStatus* status = scanning->CreateMachineStatus();
00107 _PRG_ASSERT(status != NULL);
00108 _PRG_ASSERT(&*module != NULL);
00109 _ReverseScan(scanning,address,status);
00110 delete status;
00111 }
00112
00113 class ScanningComplexReg;
00114 class MachineStatusReg: public IMachineStatus
00115 {
00116 public:
00117 IMachineStatus* Clone() const { return new MachineStatusReg(*this); };
00118 };
00119
00120 class ScanningComplexReg: public IScanning
00121 {
00122 public:
00123 ScanningComplexReg(vma_t _address,reg_t _reg):
00124 reg(_reg),address(_address),bResult(true)
00125 {};
00126 bool GetResult() const;
00127 IMachineStatus* CreateMachineStatus() const
00128 { return new MachineStatusReg(); };
00129 bool ProcessInstruction(vma_t address,const Instruction& instr,
00130 IMachineStatus* status,CodeParser& codeInfo);
00131 private:
00132 reg_t reg;
00133 vma_t address;
00134 bool bResult;
00135
00136 bool CheckLoop(vma_t address) { return IsPresent(story,address); };
00137 void AddLabel(vma_t address) { story.insert(address); };
00138 std::set<vma_t, std::less<vma_t> > story;
00139 };
00140
00141 bool ScanningComplexReg::GetResult() const
00142 {
00143 return bResult;
00144 }
00145
00146 #ifdef __BORLANDC__
00147 #pragma argsused
00148 #endif
00149 bool ScanningComplexReg::ProcessInstruction(vma_t address,
00150 const Instruction& instr,IMachineStatus* status,CodeParser& codeInfo)
00151 {
00152
00153 if ( codeInfo.byteInfo[address].IsLabel() )
00154 {
00155
00156
00157 if (CheckLoop(address))
00158 return false;
00159 AddLabel(address);
00160 }
00161
00162
00163 enum FlowTypes flow = instr.GetFlowType();
00164 _PRG_ASSERT( flow != FLOW_JUMP);
00165 if ( flow == FLOW_CALL )
00166 {
00167
00168
00169 if ( REG(esi)!=reg && REG(edi)!=reg && REG(ebx)!=reg && REG(ebp)!=reg)
00170 if ( REG(si)!=reg && REG(di)!=reg && REG(bx)!=reg && REG(bp)!=reg )
00171 {
00172 bResult = false;
00173 return false;
00174 }
00175 }
00176
00177
00178
00179
00180 enum Instruction::UseType useType;
00181 try
00182 {
00183 useType = instr.GetUseType(reg);
00184 }
00185 catch (const Instruction::UseTypeUnimplemented&)
00186 {
00187 return (bResult = false);
00188 }
00189 #ifdef DEBUG
00190
00191 if (useType == 32) return (bResult = false);
00192 #endif
00193 _PRG_ASSERT(useType != 32);
00194
00195 if ( (useType&Instruction::useMaskChange) == Instruction::useModify )
00196 {
00197 bResult = false;
00198 return false;
00199 }
00200
00201 if ( (useType&Instruction::useMaskChange) == Instruction::useOverwrite )
00202 {
00203 Instruction currInstruction;
00204 _DEBUG_(int res =) GetInstruction(*codeInfo.module,this->address,currInstruction);
00205 _PRG_ASSERT(res != 0);
00206
00207
00208 _PRG_ASSERT(currInstruction.numArg == 1);
00209 instr.GetUseType(reg,&currInstruction.Args[0]);
00210
00211
00212 if (currInstruction.Args[0].type == Param::t_literal)
00213 {
00214 if (IsNullAddress(currInstruction.Args[0].literal))
00215 return false;
00216 if (!codeInfo.module->GetSection(currInstruction.Args[0].literal)->IsCode())
00217 {
00218
00219 return false;
00220 }
00221 }
00222
00223
00224 if (currInstruction.Args[0].type == Param::t_memory)
00225 {
00226 bResult = codeInfo.ExecuteComplexReferenceMemory(this->address,currInstruction);
00227 return false;
00228 }
00229
00230
00231 if (!codeInfo.AddTempFlow(currInstruction.GetFlowType(),this->address,
00232 currInstruction,address,
00233 codeInfo.byteInfo[this->address].GetPriority(),false))
00234 {
00235
00236
00237 #ifdef DEBUG
00238
00239 #endif
00240 bResult = false;
00241 }
00242 return false;
00243 }
00244
00245 return true;
00246 }
00247
00248 bool CodeParser::ExecuteComplexReferenceReg(vma_t address,const Instruction& instruction)
00249 {
00250 _PRG_ASSERT(instruction.numArg == 1);
00251 _PRG_ASSERT(instruction.Args[0].type == Param::t_registry);
00252 reg_t reg = instruction.Args[0].mem_reg1;
00253 ScanningComplexReg scan(address,reg);
00254 ReverseScan(&scan,address);
00255 return scan.GetResult();
00256 }
00257
00258 bool IsCodePointer(const ByteInfos& byteInfo,vma_t address)
00259 {
00260 const ByteInfo& info = byteInfo[address];
00261 if (info.len != addr_bytes)
00262 return false;
00263 if (info.GetType() != ByteInfo::typePointer)
00264 return false;
00265 return true;
00266 }
00267
00268 bool CodeParser::ExecuteComplexReferenceMemory(vma_t address,const Instruction& instruction)
00269 {
00270 _PRG_ASSERT(instruction.numArg == 1);
00271 _PRG_ASSERT(instruction.Args[0].type == Param::t_memory);
00272 _PRG_ASSERT(&*module != NULL);
00273 const Param& arg = instruction.Args[0];
00274
00275
00276
00277 if (arg.mem_reg1 == null_reg && arg.mem_reg2 != null_reg && arg.factor == addr_bytes)
00278 {
00279
00280 if (ContainValidAddress(arg))
00281 {
00282 unsigned count = 0;
00283 bool isFirstValid = true;
00284
00285 try
00286 {
00287 ObjectModule::DataReader reader = module->GetDataReader(arg.literal);
00288 for(;;)
00289 {
00290 for(;;)
00291 {
00292 vma_t addr;
00293
00294 if (byteInfo.IsOccupied(reader.Tell(),addr_bytes))
00295 {
00296 if (!IsCodePointer(byteInfo,reader.Tell()))
00297 break;
00298 }
00299 if (module->HasRelocation() && !module->GetRelocationInfos().GetRelocation(reader.Tell()))
00300 break;
00301 addr = reader.ReadDword();
00302 if (!module->GetSection(addr)->IsCode())
00303 break;
00304 ++count;
00305 }
00306 if (count !=0)
00307 break;
00308
00309 ++count;
00310 isFirstValid = false;
00311
00312 reader = reader = module->GetDataReader(arg.literal+addr_bytes);
00313 }
00314 }
00315 catch(const ObjectModule::OutOfAddress&) {}
00316 if (!isFirstValid)
00317 --count;
00318 if (count<=2)
00319 return false;
00320
00321
00322 enum ByteInfo::TPriority priority = byteInfo[address].GetPriority();
00323 vma_t tableAddress = arg.literal + (isFirstValid ? 0 : addr_bytes);
00324 ObjectModule::DataReader reader = module->GetDataReader(tableAddress);
00325 for(; count != 0 ; --count)
00326 {
00327 ByteInfo& info = byteInfo[reader.Tell()];
00328 info.len = addr_bytes;
00329 info.SetType(ByteInfo::typePointer);
00330 info.SetPriority(priority);
00331 vma_t pointer = reader.ReadDword();
00332 AddTempFlow(instruction.GetFlowType(),address,pointer,priority);
00333 }
00334 byteInfo[tableAddress].SetIsLabel();
00335 return true;
00336 }
00337 }
00338
00339 if (arg.mem_reg1 == null_reg && arg.mem_reg2 == null_reg && arg.GetMemSize() == (unsigned int)addr_bytes)
00340 {
00341
00342 if (!ContainValidAddress(arg))
00343 return false;
00344
00345
00346 if (!module->HasRelocation() || module->GetRelocationInfos().GetRelocation(arg.literal))
00347 {
00348 vma_t addr;
00349 ObjectModule::DataReader reader = module->GetDataReader(arg.literal);
00350 addr = reader.ReadDword();
00351 if (!IsNullAddress(addr) && module->GetSection(addr)->IsCode())
00352 {
00353 AddTempFlow(instruction.GetFlowType(),address,addr,
00354 byteInfo[address].GetPriority());
00355 }
00356 }
00357
00358
00359 IstrReferences::iterator i =
00360 varReferences.beginReferenceTo(arg.literal);
00361 IstrReferences::iterator end =
00362 varReferences.endReferenceTo(arg.literal);
00363
00364 const ByteInfo& info = byteInfo[arg.literal];
00365
00366 for(;i != end; ++i)
00367 {
00368 if ( !(*i).direct )
00369 {
00370
00371 enum ByteInfo::TPriority priority =
00372 f77_min(byteInfo[address].GetPriority(),info.GetPriority());
00373
00374
00375 Instruction instruction;
00376 int result = GetInstruction(*module,(*i).to,instruction);
00377 if (!result)
00378 return false;
00379
00380
00381 if (instruction.instruction == istr_mov && instruction.Args[0].type == Param::t_memory && instruction.Args[1].type == Param::t_literal)
00382 {
00383 _PRG_ASSERT(instruction.Args[0].mem_reg1 == null_reg);
00384 _PRG_ASSERT(instruction.Args[0].mem_reg2 == null_reg);
00385 _PRG_ASSERT(instruction.Args[0].literal == arg.literal);
00386 if (ContainValidAddress(instruction.Args[1]))
00387 AddTempFlow(instruction.GetFlowType(),address,
00388 instruction.Args[1].literal,
00389 priority);
00390 }
00391 }
00392 }
00393 return true;
00394 }
00395
00396 return false;
00397 }
00398
00399
00400 bool CodeParser::ExecuteComplexReference(vma_t address)
00401 {
00402 _PRG_ASSERT(&*module != NULL);
00403
00404
00405 Instruction currInstruction;
00406 int result = GetInstruction(*module,address,currInstruction);
00407 if (!result || currInstruction.numArg != 1)
00408 {
00409
00410 _PRG_ASSERT(0);
00411 return false;
00412 }
00413
00414 if ( currInstruction.Args[0].type == Param::t_registry )
00415 return ExecuteComplexReferenceReg(address,currInstruction);
00416
00417 if ( currInstruction.Args[0].type == Param::t_memory )
00418 return ExecuteComplexReferenceMemory(address,currInstruction);
00419
00420 return false;
00421 }
00422
00423