bool llvm::StripDebugInfo(Module &M) { bool Changed = false; for (Module::named_metadata_iterator NMI = M.named_metadata_begin(), NME = M.named_metadata_end(); NMI != NME;) { NamedMDNode *NMD = &*NMI; ++NMI; // We're stripping debug info, and without them, coverage information // doesn't quite make sense. if (NMD->getName().startswith("llvm.dbg.") || NMD->getName() == "llvm.gcov") { NMD->eraseFromParent(); Changed = true; } } for (Function &F : M) Changed |= stripDebugInfo(F); for (auto &GV : M.globals()) { SmallVector<MDNode *, 1> MDs; GV.getMetadata(LLVMContext::MD_dbg, MDs); if (!MDs.empty()) { GV.eraseMetadata(LLVMContext::MD_dbg); Changed = true; } } if (GVMaterializer *Materializer = M.getMaterializer()) Materializer->setStripDebugInfo(); return Changed; }
// StripDebugInfo - Strip debug info in the module if it exists. // To do this, we remove llvm.dbg.func.start, llvm.dbg.stoppoint, and // llvm.dbg.region.end calls, and any globals they point to if now dead. static bool StripDebugInfo(Module &M) { bool Changed = false; // Remove all of the calls to the debugger intrinsics, and remove them from // the module. if (Function *Declare = M.getFunction("llvm.dbg.declare")) { while (!Declare->use_empty()) { CallInst *CI = cast<CallInst>(Declare->use_back()); CI->eraseFromParent(); } Declare->eraseFromParent(); Changed = true; } if (Function *DbgVal = M.getFunction("llvm.dbg.value")) { while (!DbgVal->use_empty()) { CallInst *CI = cast<CallInst>(DbgVal->use_back()); CI->eraseFromParent(); } DbgVal->eraseFromParent(); Changed = true; } for (Module::named_metadata_iterator NMI = M.named_metadata_begin(), NME = M.named_metadata_end(); NMI != NME;) { NamedMDNode *NMD = NMI; ++NMI; if (NMD->getName().startswith("llvm.dbg.")) { NMD->eraseFromParent(); Changed = true; } } for (Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) for (Function::iterator FI = MI->begin(), FE = MI->end(); FI != FE; ++FI) for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ++BI) { if (!BI->getDebugLoc().isUnknown()) { Changed = true; BI->setDebugLoc(DebugLoc()); } } return Changed; }
bool llvm::StripDebugInfo(Module &M) { bool Changed = false; // Remove all of the calls to the debugger intrinsics, and remove them from // the module. if (Function *Declare = M.getFunction("llvm.dbg.declare")) { while (!Declare->use_empty()) { CallInst *CI = cast<CallInst>(Declare->user_back()); CI->eraseFromParent(); } Declare->eraseFromParent(); Changed = true; } if (Function *DbgVal = M.getFunction("llvm.dbg.value")) { while (!DbgVal->use_empty()) { CallInst *CI = cast<CallInst>(DbgVal->user_back()); CI->eraseFromParent(); } DbgVal->eraseFromParent(); Changed = true; } for (Module::named_metadata_iterator NMI = M.named_metadata_begin(), NME = M.named_metadata_end(); NMI != NME;) { NamedMDNode *NMD = NMI; ++NMI; if (NMD->getName().startswith("llvm.dbg.")) { NMD->eraseFromParent(); Changed = true; } } for (Function &F : M) Changed |= stripDebugInfo(F); if (GVMaterializer *Materializer = M.getMaterializer()) Materializer->setStripDebugInfo(); return Changed; }
bool llvm::stripNonLineTableDebugInfo(Module &M) { bool Changed = false; // First off, delete the debug intrinsics. auto RemoveUses = [&](StringRef Name) { if (auto *DbgVal = M.getFunction(Name)) { while (!DbgVal->use_empty()) cast<Instruction>(DbgVal->user_back())->eraseFromParent(); DbgVal->eraseFromParent(); Changed = true; } }; RemoveUses("llvm.dbg.declare"); RemoveUses("llvm.dbg.value"); // Delete non-CU debug info named metadata nodes. for (auto NMI = M.named_metadata_begin(), NME = M.named_metadata_end(); NMI != NME;) { NamedMDNode *NMD = &*NMI; ++NMI; // Specifically keep dbg.cu around. if (NMD->getName() == "llvm.dbg.cu") continue; } // Drop all dbg attachments from global variables. for (auto &GV : M.globals()) GV.eraseMetadata(LLVMContext::MD_dbg); DebugTypeInfoRemoval Mapper(M.getContext()); auto remap = [&](llvm::MDNode *Node) -> llvm::MDNode * { if (!Node) return nullptr; Mapper.traverseAndRemap(Node); auto *NewNode = Mapper.mapNode(Node); Changed |= Node != NewNode; Node = NewNode; return NewNode; }; // Rewrite the DebugLocs to be equivalent to what // -gline-tables-only would have created. for (auto &F : M) { if (auto *SP = F.getSubprogram()) { Mapper.traverseAndRemap(SP); auto *NewSP = cast<DISubprogram>(Mapper.mapNode(SP)); Changed |= SP != NewSP; F.setSubprogram(NewSP); } for (auto &BB : F) { for (auto &I : BB) { if (I.getDebugLoc() == DebugLoc()) continue; // Make a replacement. auto &DL = I.getDebugLoc(); auto *Scope = DL.getScope(); MDNode *InlinedAt = DL.getInlinedAt(); Scope = remap(Scope); InlinedAt = remap(InlinedAt); I.setDebugLoc( DebugLoc::get(DL.getLine(), DL.getCol(), Scope, InlinedAt)); } } } // Create a new llvm.dbg.cu, which is equivalent to the one // -gline-tables-only would have created. for (auto &NMD : M.getNamedMDList()) { SmallVector<MDNode *, 8> Ops; for (MDNode *Op : NMD.operands()) Ops.push_back(remap(Op)); if (!Changed) continue; NMD.clearOperands(); for (auto *Op : Ops) if (Op) NMD.addOperand(Op); } return Changed; }
void SDBuildCHA::buildClouds(Module &M) { // this set is used for checking if a parent class is defined or not std::set<vtbl_t> build_undefinedVtables; for(auto itr = M.getNamedMDList().begin(); itr != M.getNamedMDList().end(); itr++) { NamedMDNode* md = itr; // check if this is a metadata that we've added if(! md->getName().startswith(SD_MD_CLASSINFO)) continue; //sd_print("GOT METADATA: %s\n", md->getName().data()); std::vector<nmd_t> infoVec = extractMetadata(md); for (const nmd_t& info : infoVec) { // record the old vtable array GlobalVariable* oldVtable = M.getGlobalVariable(info.className, true); //sd_print("class %s with %d subtables\n", info.className.c_str(), info.subVTables.size()); /* sd_print("oldvtables: %p, %d, class %s\n", oldVtable, oldVtable ? oldVtable->hasInitializer() : -1, info.className.c_str()); */ if (oldVtable && oldVtable->hasInitializer()) { ConstantArray* vtable = dyn_cast<ConstantArray>(oldVtable->getInitializer()); assert(vtable); oldVTables[info.className] = vtable; } else { undefinedVTables.insert(info.className); } for(unsigned ind = 0; ind < info.subVTables.size(); ind++) { const nmd_sub_t* subInfo = & info.subVTables[ind]; vtbl_t name(info.className, ind); /* sd_print("SubVtable[%d] Order: %d Parents[%d]: %s [%d-%d] AddrPt: %d\n", ind, subInfo->order, subInfo->parents.size(), "NYI", subInfo->start, subInfo->end, subInfo->addressPoint); */ if (build_undefinedVtables.find(name) != build_undefinedVtables.end()) { //sd_print("Removing %s,%d from build_udnefinedVtables\n", name.first.c_str(), name.second); build_undefinedVtables.erase(name); } if (cloudMap.find(name) == cloudMap.end()){ //sd_print("Inserting %s, %d in cloudMap\n", name.first.c_str(), name.second); cloudMap[name] = std::set<vtbl_t>(); } vtbl_set_t parents; for (auto it : subInfo->parents) { if (it.first != "") { vtbl_t &parent = it; parents.insert(parent); // if the parent class is not defined yet, add it to the // undefined vtable set if (cloudMap.find(parent) == cloudMap.end()) { //sd_print("Inserting %s, %d in cloudMap - undefined parent\n", parent.first.c_str(), parent.second); cloudMap[parent] = std::set<vtbl_t>(); build_undefinedVtables.insert(parent); } // add the current class to the parent's children set cloudMap[parent].insert(name); } else { assert(ind == 0); // make sure secondary vtables have a direct parent // add the class to the root set roots.insert(info.className); } } parentMap[info.className].push_back(parents); // record the original address points addrPtMap[info.className].push_back(subInfo->addressPoint); // record the sub-vtable ends rangeMap[info.className].push_back(range_t(subInfo->start, subInfo->end)); } } } if (build_undefinedVtables.size() != 0) { sd_print("Build Undefined vtables:\n"); for (auto n : build_undefinedVtables) { sd_print("%s,%d\n", n.first.c_str(), n.second); } } assert(build_undefinedVtables.size() == 0); for (auto rootName : roots) { vtbl_t root(rootName, 0); for (auto child : preorder(root)) { if (ancestorMap.find(child) == ancestorMap.end()) { ancestorMap[child] = rootName; } } } for (auto it : parentMap) { const vtbl_name_t &className = it.first; const std::vector<vtbl_set_t> &parentSetV = it.second; for (int ind = 0; ind < parentSetV.size(); ind++) { vtbl_name_t layoutClass = "none"; // Check that all possible parents are in the same layout cloud for (auto ptIt : parentSetV[ind]) { if (layoutClass != "none") assert(layoutClass == ancestorMap[ptIt] && "All parents of a primitive vtable should have the same root layout."); else layoutClass = ancestorMap[ptIt]; } // No parents - then our "layout class" is ourselves. if (layoutClass == "none") layoutClass = className; // record the class name of the sub-object subObjNameMap[className].push_back(layoutClass); } } }