From 1dcf7c2eaae9d44395d725828ed45e009875e3f5 Mon Sep 17 00:00:00 2001 From: clc5q <clc5q@git.zephyr-software.com> Date: Sat, 12 Jan 2008 16:43:01 +0000 Subject: [PATCH] Restructure IDB fixup code to use a work list for code that needs reanalysis. --- SMPStaticAnalyzer.cpp | 196 +++++++++++++++++++++++++++++++----------- 1 file changed, 146 insertions(+), 50 deletions(-) diff --git a/SMPStaticAnalyzer.cpp b/SMPStaticAnalyzer.cpp index 2c499e65..13313ce8 100644 --- a/SMPStaticAnalyzer.cpp +++ b/SMPStaticAnalyzer.cpp @@ -44,7 +44,7 @@ int FuncsProcessed = 0; #define SMP_FIXUP_IDB 1 // Try to fix the IDA database? -#define SMP_DEBUG_FIXUP_IDB 0 // debugging output for FixupIDB chain +#define SMP_DEBUG_FIXUP_IDB 1 // debugging output for FixupIDB chain // Define optimization categories for instructions. int OptCategory[NN_last+1]; @@ -97,7 +97,31 @@ vector<SMP_bounds_t> FuncBounds; // List of functions that need to be reanalyzed after all the code fixup // and code discovery is complete. Kept as a list of addresses; any address // within the function is good enough to designate it. -list<ea_t> ReanalyzeList; +list<ea_t> FuncReanalyzeList; + +// A code region that has been converted from data but has code addresses that +// need to be reanalyzed. This is usually because a former data address is +// now a jump to a code target that is still a data address. We have to wait +// until the target has become code before IDA will accept the jump as valid. +class FixupRegion { +public: + FixupRegion(SMP_bounds_t); + inline ea_t GetStart(void) const { return CodeRegion.startEA; }; + inline ea_t GetEnd(void) const { return CodeRegion.endEA; }; + inline void SetStart(ea_t addr) { CodeRegion.startEA = addr; }; + list<ea_t> FixupInstrs; // easier to expose than to encapsulate +private: + SMP_bounds_t CodeRegion; +}; + +FixupRegion::FixupRegion(SMP_bounds_t Range) { + this->CodeRegion = Range; + return; +} + +// List of code regions that were not completely analysed because of jump to +// data considerations. +list<FixupRegion> CodeReanalyzeList; void IDAP_run(int); @@ -107,6 +131,7 @@ void FindDataInCode(void); void AuditTailChunkOwnership(void); void FindOrphanedCode(segment_t *, FILE *); void FixCodeIdentification(void); +int FixupNewCodeChunks(void); void AuditCodeTargets(void); ea_t FindNewFuncLimit(ea_t); void SpecialDebugOutput(void); @@ -541,6 +566,7 @@ void FixupIDB(void) { FindDataInCode(); AuditTailChunkOwnership(); FixCodeIdentification(); + int fixes = FixupNewCodeChunks(); #if SMP_DEBUG_FIXUP_IDB SpecialDebugOutput(); #endif @@ -1048,6 +1074,11 @@ void FixCodeIdentification(void) { msg("Found data to convert: %x to %x\n", AreaStart, AreaEnd); #endif do_unknown_range(AreaStart, AreaSize, DOUNK_SIMPLE); + SMP_bounds_t ConvertRegion; + ConvertRegion.startEA = AreaStart; + ConvertRegion.endEA = AreaEnd; + FixupRegion CurrRegion(ConvertRegion); + CodeReanalyzeList.push_back(CurrRegion); bool AllConverted = true; do { flags_t InstrFlags = getFlags(CurrDisasmAddr); @@ -1071,6 +1102,7 @@ void FixCodeIdentification(void) { msg(" Patched bytes at %x\n", CurrDisasmAddr); } else { + CurrRegion.FixupInstrs.push_back(CurrDisasmAddr); AllConverted = false; msg("FixCodeID failure at %x\n", CurrDisasmAddr); } @@ -1085,54 +1117,6 @@ void FixCodeIdentification(void) { ++DisasmIndex; // skip cleanup loop } } while (CurrDisasmAddr < CurrAddr); - if (AllConverted) { - if (IsFunctionPrologue(AreaStart, AreaEnd)) { - // Create a new function entry chunk here. - // **!!** TODO - ; - } - else { - // Extend the previous chunk to include the - // converted code. - ea_t PrevIDAAddr = IDAProLocs[IDAProIndex - 2]; - func_t *PrevChunk = get_fchunk(PrevIDAAddr); -#if SMP_DEBUG_FIXUP_IDB - msg(" addr in chunk to extend: %x\n", PrevIDAAddr); - msg(" func_t pointer for chunk: %x\n", PrevChunk); -#endif -#if 0 // temporary for debugging - if (is_func_entry(PrevChunk)) { - // Extend the func entry to contain the new code. - if (func_setend(PrevIDAAddr, AreaEnd)) { - msg("Func extended to include code from %x to %x\n", - AreaStart, AreaEnd); - ReanalyzeList.push_back(PrevIDAAddr); - } - else { - msg("Failed to extend func from %x to %x\n", - AreaStart, AreaEnd); - } - } - else { // tail - // See if this works for function tails, also. - // Extend the func entry to contain the new code. - if (func_setend(PrevIDAAddr, AreaEnd)) { - msg("Tail extended to include code from %x to %x\n", - AreaStart, AreaEnd); - func_t *TailOwner = get_func(PrevChunk->owner); - ReanalyzeList.push_back(PrevIDAAddr); - } - else { - msg("Failed to extend tail from %x to %x\n", - AreaStart, AreaEnd); - } - } // end if (is_func_entry()) ... else ... -#endif - } // end if (IsFunctionPrologue()) ... else ... - } // end if (AllConverted) - else { - msg("not AllConverted; cannot include new code in previous chunk.\n"); - } } // end if (SkipArea) ... else ... } // end if (addr < CurrDisasmAddr) .. else if ... else ... } // end while (DisasmIndex <= DisasmLocs.size() @@ -1182,6 +1166,118 @@ void FixCodeIdentification(void) { return; } // end of FixCodeIdentification() +// Analyze instructions that could not be analyzed earlier and were placed on the CodeReanalyzeList. +// Earlier failures are usually because the instruction branches to an address that has not +// yet been converted from data to code, so ua_code() failed. Now that all data to code +// conversions have completed, ua_code() should succeed. +// Return the number of instructions successfully analyzed. +int FixupNewCodeChunks(void) { + list<FixupRegion>::iterator CurrRegion; + int changes = 0; + for (CurrRegion = CodeReanalyzeList.begin(); CurrRegion != CodeReanalyzeList.end(); ++CurrRegion) { + bool AllConverted = true; + list<ea_t>::iterator CurrInstr; + for (CurrInstr = CurrRegion->FixupInstrs.begin(); CurrInstr != CurrRegion->FixupInstrs.end(); ++CurrInstr) { + int InstrLen = ua_code(*CurrInstr); + if (InstrLen > 0) { // Successfully converted to code + SMPInstr NewInstr(*CurrInstr); + NewInstr.Analyze(); +#if SMP_DEBUG_FIXUP_IDB + msg("FixupNewCodeChunks success at %x: len: %d\n", *CurrInstr, InstrLen); +#endif + *CurrInstr = BADADDR; // mark for removal + } + else { + AllConverted = false; +#if SMP_DEBUG_FIXUP_IDB + msg("FixupNewCodeChunks failure at %x\n", *CurrInstr); +#endif + } + } // end for all instrs in CurrRegion + if (AllConverted) { +#if SMP_DEBUG_FIXUP_IDB + msg("FixupNewCodeChunks success for region from %x to %x\n", + CurrRegion->GetStart(), CurrRegion->GetEnd()); +#endif + CurrRegion->SetStart(BADADDR); // mark for removal + } + else { + // Remove only the instructions that were fixed up. + CurrInstr = CurrRegion->FixupInstrs.begin(); + while (CurrInstr != CurrRegion->FixupInstrs.end()) { + if (BADADDR == *CurrInstr) { + CurrInstr = CurrRegion->FixupInstrs.erase(CurrInstr); + } + else { + ++CurrInstr; + } + } + } + } // end for all regions in the CodeReanalyzeList + + // Remove completed regions from the CodeReanalyzeList + CurrRegion = CodeReanalyzeList.begin(); + while (CurrRegion != CodeReanalyzeList.end()) { + if (BADADDR == CurrRegion->GetStart()) + CurrRegion = CodeReanalyzeList.erase(CurrRegion); + else + ++CurrRegion; + } + +#if 0 + if (AllConverted) { + if (IsFunctionPrologue(AreaStart, AreaEnd)) { + // Create a new function entry chunk here. + // **!!** TODO + ; + } + else { + // Extend the previous chunk to include the + // converted code. + ea_t PrevIDAAddr = IDAProLocs[IDAProIndex - 2]; + func_t *PrevChunk = get_fchunk(PrevIDAAddr); +#if SMP_DEBUG_FIXUP_IDB + msg(" addr in chunk to extend: %x\n", PrevIDAAddr); + msg(" func_t pointer for chunk: %x\n", PrevChunk); +#endif +#if 0 // temporary for debugging + if (is_func_entry(PrevChunk)) { + // Extend the func entry to contain the new code. + if (func_setend(PrevIDAAddr, AreaEnd)) { + msg("Func extended to include code from %x to %x\n", + AreaStart, AreaEnd); + FuncReanalyzeList.push_back(PrevIDAAddr); + } + else { + msg("Failed to extend func from %x to %x\n", + AreaStart, AreaEnd); + } + } + else { // tail + // See if this works for function tails, also. + // Extend the func entry to contain the new code. + if (func_setend(PrevIDAAddr, AreaEnd)) { + msg("Tail extended to include code from %x to %x\n", + AreaStart, AreaEnd); + func_t *TailOwner = get_func(PrevChunk->owner); + FuncReanalyzeList.push_back(PrevIDAAddr); + } + else { + msg("Failed to extend tail from %x to %x\n", + AreaStart, AreaEnd); + } + } // end if (is_func_entry()) ... else ... +#endif + } // end if (IsFunctionPrologue()) ... else ... + } // end if (AllConverted) + else { + msg("not AllConverted; cannot include new code in previous chunk.\n"); + } +#endif + + return changes; +} // end of FixupNewCodeChunnks() + // Audit the IDA code database by looking at all instructions in the // code segment and printing all those that are not contained in a // function. Emit the context-free annotations that we are able to -- GitLab