diff --git a/llvm-15.0.3/llvm-crash-analyzer/include/Analysis/TaintAnalysis.h b/llvm-15.0.3/llvm-crash-analyzer/include/Analysis/TaintAnalysis.h index ed65d73855..974ddb41d6 100644 --- a/llvm-15.0.3/llvm-crash-analyzer/include/Analysis/TaintAnalysis.h +++ b/llvm-15.0.3/llvm-crash-analyzer/include/Analysis/TaintAnalysis.h @@ -92,6 +92,7 @@ class TaintAnalysis { void resetTaintList(SmallVectorImpl &TL); void mergeTaintList(SmallVectorImpl &Dest_TL, SmallVectorImpl &Src_TL); + bool handleGlobalVar(TaintInfo &Ti); bool propagateTaint(DestSourcePair &DS, SmallVectorImpl &TL, const MachineInstr &MI, TaintDataFlowGraph &TaintDFG, RegisterEquivalence &REAnalysis, diff --git a/llvm-15.0.3/llvm-crash-analyzer/include/Decompiler/Decompiler.h b/llvm-15.0.3/llvm-crash-analyzer/include/Decompiler/Decompiler.h index d608c2192a..a49af077c8 100644 --- a/llvm-15.0.3/llvm-crash-analyzer/include/Decompiler/Decompiler.h +++ b/llvm-15.0.3/llvm-crash-analyzer/include/Decompiler/Decompiler.h @@ -80,6 +80,7 @@ class Decompiler { SmallVector FunctionsThatAreNotInBT; lldb::SBTarget *DecTarget = nullptr; + lldb::SBModule *DecModule = nullptr; // Store debug info compile units for coresponding files. std::unordered_map> CUs; @@ -148,6 +149,9 @@ class Decompiler { void setTarget(lldb::SBTarget *T) { DecTarget = T; } lldb::SBTarget *getTarget() { return DecTarget; } + void setSBModule(lldb::SBModule *M) { DecModule = M; } + lldb::SBModule *getSBModule() { return DecModule; } + class Module &getModule() { return *Module.get(); } diff --git a/llvm-15.0.3/llvm-crash-analyzer/lib/Analysis/TaintAnalysis.cpp b/llvm-15.0.3/llvm-crash-analyzer/lib/Analysis/TaintAnalysis.cpp index 6dc0e9fdcd..f75364c293 100644 --- a/llvm-15.0.3/llvm-crash-analyzer/lib/Analysis/TaintAnalysis.cpp +++ b/llvm-15.0.3/llvm-crash-analyzer/lib/Analysis/TaintAnalysis.cpp @@ -556,6 +556,62 @@ void crash_analyzer::TaintAnalysis::insertTaint( printTaintList(TL); } +// Check if Ti represents a global variable and convert Ti into expected form. +// Expected form is $noreg plus offset, which is the global variable symbol +// address. +bool crash_analyzer::TaintAnalysis::handleGlobalVar(TaintInfo &Ti) { + + if (!Dec) + return false; + + auto LLDBModule = Dec->getSBModule(); + if (!LLDBModule) + return false; + + if (!Ti.Op) + return false; + + Optional ImmVal = llvm::None; + // Get symbol address from Ti ({reg:$noreg; off:ADDR}). + if (Ti.Op->isReg() && Ti.Op->getReg() == 0 && Ti.Offset) + ImmVal = *Ti.Offset; + + // Get symbol address from Ti ({imm:ADDR}). + if (Ti.Op->isImm()) + ImmVal = Ti.Op->getImm(); + + if (!ImmVal) + return false; + + if (*ImmVal < 0) + return false; + + uint64_t VarAddr = static_cast(*ImmVal); + + // Search symbols for global var with the matching address. + int NumSym = static_cast(LLDBModule->GetNumSymbols()); + for (int i = 0; i < NumSym; i++) { + auto SBSym = LLDBModule->GetSymbolAtIndex(i); + auto SymAddr = SBSym.GetStartAddress().GetLoadAddress(*Dec->getTarget()); + // Check symbol address and if it is a global variable. + if (SymAddr == VarAddr && + Dec->getTarget()->FindFirstGlobalVariable(SBSym.GetName())) { + LLVM_DEBUG(dbgs() << "Handle global variable \"" << SBSym.GetName() + << "\"\n"); + // Convert Ti from {imm:ADDR} to {reg:$noreg; off:ADDR}. + if (Ti.Op->isImm()) { + Ti.Offset = VarAddr; + MachineOperand *MO2 = new MachineOperand(*Ti.Op); + MO2->ChangeToRegister(0, false); + Ti.Op = MO2; + LLVM_DEBUG(dbgs() << "Update Taint Info to " << Ti << "\n"); + } + return true; + } + } + return false; +} + void crash_analyzer::TaintAnalysis::startTaint( DestSourcePair &DS, SmallVectorImpl &TL, const MachineInstr &MI, TaintDataFlowGraph &TaintDFG, RegisterEquivalence &REAnalysis) { @@ -687,6 +743,8 @@ bool llvm::crash_analyzer::TaintAnalysis::propagateTaint( if (SrcTi.Offset) calculateMemAddr(SrcTi); + bool SrcGlobalVar = handleGlobalVar(SrcTi); + Src2Ti.Op = DS.Source2; Src2Ti.Offset = DS.Src2Offset; if (Src2Ti.Offset) @@ -750,6 +808,10 @@ bool llvm::crash_analyzer::TaintAnalysis::propagateTaint( SrcTi = ZeroTi; ConstantFound = true; } + // Immediate operand, which is a symbol address for the global variable, + // should not be treated as a constant. + if (SrcGlobalVar) + ConstantFound = false; // FIXME: Since now we have corefile content we can check if this constant // is the same from the crash point, and by doing that we avoid FALSE diff --git a/llvm-15.0.3/llvm-crash-analyzer/llvm-crash-analyzer.cpp b/llvm-15.0.3/llvm-crash-analyzer/llvm-crash-analyzer.cpp index 178d5e71b2..c67417ede8 100644 --- a/llvm-15.0.3/llvm-crash-analyzer/llvm-crash-analyzer.cpp +++ b/llvm-15.0.3/llvm-crash-analyzer/llvm-crash-analyzer.cpp @@ -215,6 +215,12 @@ int main(int argc, char **argv) { crash_analyzer::TaintAnalysis TA(TaintDotFileName, MirDotFileName, PrintPotentialCrashCauseLocation); Dec->setTarget(&coreFile.getTarget()); + + // Set SBModule for Decompiler, so we can access the symbol table. + auto FileSpec = lldb::SBFileSpec(InputFilename.c_str()); + auto LLDBModule = coreFile.getTarget().FindModule(FileSpec); + Dec->setSBModule(new lldb::SBModule(LLDBModule)); + TA.setDecompiler(Dec); TA.runOnBlameModule(BlameTrace); diff --git a/llvm-15.0.3/llvm-crash-analyzer/test/Analysis/Inputs/core.global-var-immediate b/llvm-15.0.3/llvm-crash-analyzer/test/Analysis/Inputs/core.global-var-immediate new file mode 100644 index 0000000000..bbffc97ab7 Binary files /dev/null and b/llvm-15.0.3/llvm-crash-analyzer/test/Analysis/Inputs/core.global-var-immediate differ diff --git a/llvm-15.0.3/llvm-crash-analyzer/test/Analysis/Inputs/global-var-immediate.out b/llvm-15.0.3/llvm-crash-analyzer/test/Analysis/Inputs/global-var-immediate.out new file mode 100755 index 0000000000..84be9c4a5f Binary files /dev/null and b/llvm-15.0.3/llvm-crash-analyzer/test/Analysis/Inputs/global-var-immediate.out differ diff --git a/llvm-15.0.3/llvm-crash-analyzer/test/Analysis/global-var-immediate.test b/llvm-15.0.3/llvm-crash-analyzer/test/Analysis/global-var-immediate.test new file mode 100644 index 0000000000..ca470d656d --- /dev/null +++ b/llvm-15.0.3/llvm-crash-analyzer/test/Analysis/global-var-immediate.test @@ -0,0 +1,33 @@ +##include +## typedef struct node { +## int *fn; +## } T; +## +## T p; +## T q2; +## void h(int *r) { +## *r = 0; // crash +## } +## +## void g (T*q) { +## int *t = q->fn; +## h(t); +## } +## +## void f() { +## p.fn = NULL; // blame point - line 18 +## q2.fn = NULL; +## g(&p); +## } +## +## int main() { +## f(); +## return 0; +## } + + +# RUN: %llvm-crash-analyzer --core-file=%S/Inputs/core.global-var-immediate \ +# RUN: %S/Inputs/global-var-immediate.out --print-potential-crash-cause-loc < %s 2>&1 | FileCheck %s + +# CHECK: Blame Function is f +# CHECK-NOT: From File {{.*}}/m.c:18:8 \ No newline at end of file