1 //===- RemarkLinker.cpp ---------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file provides an implementation of the remark linker. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/Remarks/RemarkLinker.h" 14 #include "llvm/ADT/StringRef.h" 15 #include "llvm/Object/ObjectFile.h" 16 #include "llvm/Object/SymbolicFile.h" 17 #include "llvm/Remarks/RemarkParser.h" 18 #include "llvm/Remarks/RemarkSerializer.h" 19 #include "llvm/Support/Error.h" 20 #include "llvm/Support/raw_ostream.h" 21 22 using namespace llvm; 23 using namespace llvm::remarks; 24 25 static Expected<StringRef> 26 getRemarksSectionName(const object::ObjectFile &Obj) { 27 if (Obj.isMachO()) 28 return StringRef("__remarks"); 29 // ELF -> .remarks, but there is no ELF support at this point. 30 return createStringError(std::errc::illegal_byte_sequence, 31 "Unsupported file format."); 32 } 33 34 Expected<Optional<StringRef>> 35 llvm::remarks::getRemarksSectionContents(const object::ObjectFile &Obj) { 36 Expected<StringRef> SectionName = getRemarksSectionName(Obj); 37 if (!SectionName) 38 return SectionName.takeError(); 39 40 for (const object::SectionRef &Section : Obj.sections()) { 41 Expected<StringRef> MaybeName = Section.getName(); 42 if (!MaybeName) 43 return MaybeName.takeError(); 44 if (*MaybeName != *SectionName) 45 continue; 46 47 if (Expected<StringRef> Contents = Section.getContents()) 48 return *Contents; 49 else 50 return Contents.takeError(); 51 } 52 return Optional<StringRef>{}; 53 } 54 55 Remark &RemarkLinker::keep(std::unique_ptr<Remark> Remark) { 56 StrTab.internalize(*Remark); 57 auto Inserted = Remarks.insert(std::move(Remark)); 58 return **Inserted.first; 59 } 60 61 void RemarkLinker::setExternalFilePrependPath(StringRef PrependPathIn) { 62 PrependPath = std::string(PrependPathIn); 63 } 64 65 // Discard remarks with no source location. 66 static bool shouldKeepRemark(const Remark &R) { return R.Loc.hasValue(); } 67 68 Error RemarkLinker::link(StringRef Buffer, Optional<Format> RemarkFormat) { 69 if (!RemarkFormat) { 70 Expected<Format> ParserFormat = magicToFormat(Buffer); 71 if (!ParserFormat) 72 return ParserFormat.takeError(); 73 RemarkFormat = *ParserFormat; 74 } 75 76 Expected<std::unique_ptr<RemarkParser>> MaybeParser = 77 createRemarkParserFromMeta( 78 *RemarkFormat, Buffer, /*StrTab=*/None, 79 PrependPath ? Optional<StringRef>(StringRef(*PrependPath)) 80 : Optional<StringRef>(None)); 81 if (!MaybeParser) 82 return MaybeParser.takeError(); 83 84 RemarkParser &Parser = **MaybeParser; 85 86 while (true) { 87 Expected<std::unique_ptr<Remark>> Next = Parser.next(); 88 if (Error E = Next.takeError()) { 89 if (E.isA<EndOfFileError>()) { 90 consumeError(std::move(E)); 91 break; 92 } 93 return E; 94 } 95 96 assert(*Next != nullptr); 97 98 if (shouldKeepRemark(**Next)) 99 keep(std::move(*Next)); 100 } 101 return Error::success(); 102 } 103 104 Error RemarkLinker::link(const object::ObjectFile &Obj, 105 Optional<Format> RemarkFormat) { 106 Expected<Optional<StringRef>> SectionOrErr = getRemarksSectionContents(Obj); 107 if (!SectionOrErr) 108 return SectionOrErr.takeError(); 109 110 if (Optional<StringRef> Section = *SectionOrErr) 111 return link(*Section, RemarkFormat); 112 return Error::success(); 113 } 114 115 Error RemarkLinker::serialize(raw_ostream &OS, Format RemarksFormat) const { 116 Expected<std::unique_ptr<RemarkSerializer>> MaybeSerializer = 117 createRemarkSerializer(RemarksFormat, SerializerMode::Standalone, OS, 118 std::move(const_cast<StringTable &>(StrTab))); 119 if (!MaybeSerializer) 120 return MaybeSerializer.takeError(); 121 122 std::unique_ptr<remarks::RemarkSerializer> Serializer = 123 std::move(*MaybeSerializer); 124 125 for (const Remark &R : remarks()) 126 Serializer->emit(R); 127 return Error::success(); 128 } 129