llvm.org GIT mirror llvm / b945463
[ProfileData] PR33517: Check for failure of symtab creation With PR33517, it became apparent that symbol table creation can fail when presented with malformed inputs. This patch makes that sort of error detectable, so llvm-cov etc. can fail more gracefully. Specifically, we now check that function names within the symbol table aren't empty. Testing: check-{llvm,clang,profile}, some unit test updates. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305765 91177308-0d34-0410-b5e6-96231b3b80d8 Vedant Kumar 2 years ago
10 changed file(s) with 58 addition(s) and 28 deletion(s). Raw diff Collapse all Expand all
449449 /// decls from module \c M. This interface is used by transformation
450450 /// passes such as indirect function call promotion. Variable \c InLTO
451451 /// indicates if this is called from LTO optimization passes.
452 void create(Module &M, bool InLTO = false);
452 Error create(Module &M, bool InLTO = false);
453453
454454 /// Create InstrProfSymtab from a set of names iteratable from
455455 /// \p IterRange. This interface is used by IndexedProfReader.
456 template void create(const NameIterRange &IterRange);
456 template Error create(const NameIterRange &IterRange);
457457
458458 // If the symtab is created by a series of calls to \c addFuncName, \c
459459 // finalizeSymtab needs to be called before looking up function names.
463463
464464 /// Update the symtab by adding \p FuncName to the table. This interface
465465 /// is used by the raw and text profile readers.
466 void addFuncName(StringRef FuncName) {
466 Error addFuncName(StringRef FuncName) {
467 if (FuncName.empty())
468 return make_error(instrprof_error::malformed);
467469 auto Ins = NameTab.insert(FuncName);
468470 if (Ins.second)
469471 MD5NameMap.push_back(std::make_pair(
470472 IndexedInstrProf::ComputeHash(FuncName), Ins.first->getKey()));
473 return Error::success();
471474 }
472475
473476 /// Map a function address to its name's MD5 hash. This interface
510513 }
511514
512515 template
513 void InstrProfSymtab::create(const NameIterRange &IterRange) {
516 Error InstrProfSymtab::create(const NameIterRange &IterRange) {
514517 for (auto Name : IterRange)
515 addFuncName(Name);
518 if (Error E = addFuncName(Name))
519 return E;
516520
517521 finalizeSymtab();
522 return Error::success();
518523 }
519524
520525 void InstrProfSymtab::finalizeSymtab() {
342342 virtual void setValueProfDataEndianness(support::endianness Endianness) = 0;
343343 virtual uint64_t getVersion() const = 0;
344344 virtual bool isIRLevelProfile() const = 0;
345 virtual void populateSymtab(InstrProfSymtab &) = 0;
345 virtual Error populateSymtab(InstrProfSymtab &) = 0;
346346 };
347347
348348 typedef OnDiskIterableChainedHashTable
382382 return (FormatVersion & VARIANT_MASK_IR_PROF) != 0;
383383 }
384384
385 void populateSymtab(InstrProfSymtab &Symtab) override {
386 Symtab.create(HashTable->keys());
385 Error populateSymtab(InstrProfSymtab &Symtab) override {
386 return Symtab.create(HashTable->keys());
387387 }
388388 };
389389
5757 void write(raw_fd_ostream &OS);
5858
5959 /// Write the profile in text format to \c OS
60 void writeText(raw_fd_ostream &OS);
60 Error writeText(raw_fd_ostream &OS);
6161
6262 /// Write \c Record in text format to \c OS
6363 static void writeRecordInText(const InstrProfRecord &Record,
418418 StringRef FuncName;
419419 if (Error Err = CFR->template getFuncName(ProfileNames, FuncName))
420420 return Err;
421 if (FuncName.empty())
422 return make_error(instrprof_error::malformed);
421423 Records.emplace_back(Version, FuncName, FuncHash, Mapping, FilenamesBegin,
422424 Filenames.size() - FilenamesBegin);
423425 return Error::success();
329329 return createPGOFuncNameVar(*F.getParent(), F.getLinkage(), PGOFuncName);
330330 }
331331
332 void InstrProfSymtab::create(Module &M, bool InLTO) {
332 Error InstrProfSymtab::create(Module &M, bool InLTO) {
333333 for (Function &F : M) {
334334 // Function may not have a name: like using asm("") to overwrite the name.
335335 // Ignore in this case.
336336 if (!F.hasName())
337337 continue;
338338 const std::string &PGOFuncName = getPGOFuncName(F, InLTO);
339 addFuncName(PGOFuncName);
339 if (Error E = addFuncName(PGOFuncName))
340 return E;
340341 MD5FuncMap.emplace_back(Function::getGUID(PGOFuncName), &F);
341342 // In ThinLTO, local function may have been promoted to global and have
342343 // suffix added to the function name. We need to add the stripped function
345346 auto pos = PGOFuncName.find('.');
346347 if (pos != std::string::npos) {
347348 const std::string &OtherFuncName = PGOFuncName.substr(0, pos);
348 addFuncName(OtherFuncName);
349 if (Error E = addFuncName(OtherFuncName))
350 return E;
349351 MD5FuncMap.emplace_back(Function::getGUID(OtherFuncName), &F);
350352 }
351353 }
352354 }
353355
354356 finalizeSymtab();
357 return Error::success();
355358 }
356359
357360 Error collectPGOFuncNameStrings(ArrayRef NameStrs,
446449 SmallVector Names;
447450 NameStrings.split(Names, getInstrProfNameSeparator());
448451 for (StringRef &Name : Names)
449 Symtab.addFuncName(Name);
452 if (Error E = Symtab.addFuncName(Name))
453 return E;
450454
451455 while (P < EndP && *P == 0)
452456 P++;
199199 std::pair VD = Line->rsplit(':');
200200 uint64_t TakenCount, Value;
201201 if (ValueKind == IPVK_IndirectCallTarget) {
202 Symtab->addFuncName(VD.first);
202 if (Error E = Symtab->addFuncName(VD.first))
203 return E;
203204 Value = IndexedInstrProf::ComputeHash(VD.first);
204205 } else {
205206 READ_NUM(VD.first, Value);
231232
232233 // Read the function name.
233234 Record.Name = *Line++;
234 Symtab->addFuncName(Record.Name);
235 if (Error E = Symtab->addFuncName(Record.Name))
236 return E;
235237
236238 // Read the function hash.
237239 if (Line.is_at_end())
693695 return *Symtab.get();
694696
695697 std::unique_ptr NewSymtab = make_unique();
696 Index->populateSymtab(*NewSymtab.get());
698 if (Error E = Index->populateSymtab(*NewSymtab.get())) {
699 consumeError(error(InstrProfError::take(std::move(E))));
700 }
697701
698702 Symtab = std::move(NewSymtab);
699703 return *Symtab.get();
362362 OS << "\n";
363363 }
364364
365 void InstrProfWriter::writeText(raw_fd_ostream &OS) {
365 Error InstrProfWriter::writeText(raw_fd_ostream &OS) {
366366 if (ProfileKind == PF_IRLevel)
367367 OS << "# IR level Instrumentation Flag\n:ir\n";
368368 InstrProfSymtab Symtab;
369369 for (const auto &I : FunctionData)
370370 if (shouldEncodeData(I.getValue()))
371 Symtab.addFuncName(I.getKey());
371 if (Error E = Symtab.addFuncName(I.getKey()))
372 return E;
372373 Symtab.finalizeSymtab();
373374
374375 for (const auto &I : FunctionData)
375376 if (shouldEncodeData(I.getValue()))
376377 for (const auto &Func : I.getValue())
377378 writeRecordInText(Func.second, Symtab, OS);
378 }
379 return Error::success();
380 }
641641 if (DisableICP)
642642 return false;
643643 InstrProfSymtab Symtab;
644 Symtab.create(M, InLTO);
644 if (Error E = Symtab.create(M, InLTO)) {
645 std::string SymtabFailure = toString(std::move(E));
646 DEBUG(dbgs() << "Failed to create symtab: " << SymtabFailure << "\n");
647 (void)SymtabFailure;
648 return false;
649 }
645650 bool Changed = false;
646651 for (auto &F : M) {
647652 if (F.isDeclaration())
245245 exitWithError(std::move(WC->Err), WC->ErrWhence);
246246
247247 InstrProfWriter &Writer = Contexts[0]->Writer;
248 if (OutputFormat == PF_Text)
249 Writer.writeText(Output);
250 else
248 if (OutputFormat == PF_Text) {
249 if (Error E = Writer.writeText(Output))
250 exitWithError(std::move(E));
251 } else {
251252 Writer.write(Output);
253 }
252254 }
253255
254256 static sampleprof::SampleProfileFormat FormatMap[] = {
858858 FuncNames.push_back("bar2");
859859 FuncNames.push_back("bar3");
860860 InstrProfSymtab Symtab;
861 Symtab.create(FuncNames);
861 NoError(Symtab.create(FuncNames));
862862 StringRef R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func1"));
863863 ASSERT_EQ(StringRef("func1"), R);
864864 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func2"));
879879 ASSERT_EQ(StringRef(), R);
880880
881881 // Now incrementally update the symtab
882 Symtab.addFuncName("blah_1");
883 Symtab.addFuncName("blah_2");
884 Symtab.addFuncName("blah_3");
882 NoError(Symtab.addFuncName("blah_1"));
883 NoError(Symtab.addFuncName("blah_2"));
884 NoError(Symtab.addFuncName("blah_3"));
885885 // Finalize it
886886 Symtab.finalizeSymtab();
887887
906906 ASSERT_EQ(StringRef("bar3"), R);
907907 }
908908
909 // Test that we get an error when creating a bogus symtab.
910 TEST_P(MaybeSparseInstrProfTest, instr_prof_bogus_symtab_empty_func_name) {
911 InstrProfSymtab Symtab;
912 ErrorEquals(instrprof_error::malformed, Symtab.addFuncName(""));
913 }
914
909915 // Testing symtab creator interface used by value profile transformer.
910916 TEST_P(MaybeSparseInstrProfTest, instr_prof_symtab_module_test) {
911917 LLVMContext Ctx;
926932 Function::Create(FTy, Function::WeakODRLinkage, "Wbar", M.get());
927933
928934 InstrProfSymtab ProfSymtab;
929 ProfSymtab.create(*M);
935 NoError(ProfSymtab.create(*M));
930936
931937 StringRef Funcs[] = {"Gfoo", "Gblah", "Gbar", "Ifoo", "Iblah", "Ibar",
932938 "Pfoo", "Pblah", "Pbar", "Wfoo", "Wblah", "Wbar"};