1480093f4SDimitry Andric //===- RemarkLinker.cpp ---------------------------------------------------===// 2480093f4SDimitry Andric // 3480093f4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4480093f4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5480093f4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6480093f4SDimitry Andric // 7480093f4SDimitry Andric //===----------------------------------------------------------------------===// 8480093f4SDimitry Andric // 9480093f4SDimitry Andric // This file provides an implementation of the remark linker. 10480093f4SDimitry Andric // 11480093f4SDimitry Andric //===----------------------------------------------------------------------===// 12480093f4SDimitry Andric 13480093f4SDimitry Andric #include "llvm/Remarks/RemarkLinker.h" 14480093f4SDimitry Andric #include "llvm/ADT/StringRef.h" 151fd87a68SDimitry Andric #include "llvm/Object/ObjectFile.h" 161fd87a68SDimitry Andric #include "llvm/Object/SymbolicFile.h" 17480093f4SDimitry Andric #include "llvm/Remarks/RemarkParser.h" 18480093f4SDimitry Andric #include "llvm/Remarks/RemarkSerializer.h" 19480093f4SDimitry Andric #include "llvm/Support/Error.h" 20480093f4SDimitry Andric 21480093f4SDimitry Andric using namespace llvm; 22480093f4SDimitry Andric using namespace llvm::remarks; 23480093f4SDimitry Andric 24*81ad6265SDimitry Andric namespace llvm { 25*81ad6265SDimitry Andric class raw_ostream; 26*81ad6265SDimitry Andric } 27*81ad6265SDimitry Andric 28480093f4SDimitry Andric static Expected<StringRef> 29480093f4SDimitry Andric getRemarksSectionName(const object::ObjectFile &Obj) { 30480093f4SDimitry Andric if (Obj.isMachO()) 31480093f4SDimitry Andric return StringRef("__remarks"); 32480093f4SDimitry Andric // ELF -> .remarks, but there is no ELF support at this point. 33480093f4SDimitry Andric return createStringError(std::errc::illegal_byte_sequence, 34480093f4SDimitry Andric "Unsupported file format."); 35480093f4SDimitry Andric } 36480093f4SDimitry Andric 37480093f4SDimitry Andric Expected<Optional<StringRef>> 38480093f4SDimitry Andric llvm::remarks::getRemarksSectionContents(const object::ObjectFile &Obj) { 39480093f4SDimitry Andric Expected<StringRef> SectionName = getRemarksSectionName(Obj); 40480093f4SDimitry Andric if (!SectionName) 41480093f4SDimitry Andric return SectionName.takeError(); 42480093f4SDimitry Andric 43480093f4SDimitry Andric for (const object::SectionRef &Section : Obj.sections()) { 44480093f4SDimitry Andric Expected<StringRef> MaybeName = Section.getName(); 45480093f4SDimitry Andric if (!MaybeName) 46480093f4SDimitry Andric return MaybeName.takeError(); 47480093f4SDimitry Andric if (*MaybeName != *SectionName) 48480093f4SDimitry Andric continue; 49480093f4SDimitry Andric 50480093f4SDimitry Andric if (Expected<StringRef> Contents = Section.getContents()) 51480093f4SDimitry Andric return *Contents; 52480093f4SDimitry Andric else 53480093f4SDimitry Andric return Contents.takeError(); 54480093f4SDimitry Andric } 55480093f4SDimitry Andric return Optional<StringRef>{}; 56480093f4SDimitry Andric } 57480093f4SDimitry Andric 58480093f4SDimitry Andric Remark &RemarkLinker::keep(std::unique_ptr<Remark> Remark) { 59480093f4SDimitry Andric StrTab.internalize(*Remark); 60480093f4SDimitry Andric auto Inserted = Remarks.insert(std::move(Remark)); 61480093f4SDimitry Andric return **Inserted.first; 62480093f4SDimitry Andric } 63480093f4SDimitry Andric 64480093f4SDimitry Andric void RemarkLinker::setExternalFilePrependPath(StringRef PrependPathIn) { 655ffd83dbSDimitry Andric PrependPath = std::string(PrependPathIn); 66480093f4SDimitry Andric } 67480093f4SDimitry Andric 68480093f4SDimitry Andric // Discard remarks with no source location. 69*81ad6265SDimitry Andric static bool shouldKeepRemark(const Remark &R) { return R.Loc.has_value(); } 70480093f4SDimitry Andric 71480093f4SDimitry Andric Error RemarkLinker::link(StringRef Buffer, Optional<Format> RemarkFormat) { 72480093f4SDimitry Andric if (!RemarkFormat) { 73480093f4SDimitry Andric Expected<Format> ParserFormat = magicToFormat(Buffer); 74480093f4SDimitry Andric if (!ParserFormat) 75480093f4SDimitry Andric return ParserFormat.takeError(); 76480093f4SDimitry Andric RemarkFormat = *ParserFormat; 77480093f4SDimitry Andric } 78480093f4SDimitry Andric 79480093f4SDimitry Andric Expected<std::unique_ptr<RemarkParser>> MaybeParser = 80480093f4SDimitry Andric createRemarkParserFromMeta( 81480093f4SDimitry Andric *RemarkFormat, Buffer, /*StrTab=*/None, 82480093f4SDimitry Andric PrependPath ? Optional<StringRef>(StringRef(*PrependPath)) 83480093f4SDimitry Andric : Optional<StringRef>(None)); 84480093f4SDimitry Andric if (!MaybeParser) 85480093f4SDimitry Andric return MaybeParser.takeError(); 86480093f4SDimitry Andric 87480093f4SDimitry Andric RemarkParser &Parser = **MaybeParser; 88480093f4SDimitry Andric 89480093f4SDimitry Andric while (true) { 90480093f4SDimitry Andric Expected<std::unique_ptr<Remark>> Next = Parser.next(); 91480093f4SDimitry Andric if (Error E = Next.takeError()) { 92480093f4SDimitry Andric if (E.isA<EndOfFileError>()) { 93480093f4SDimitry Andric consumeError(std::move(E)); 94480093f4SDimitry Andric break; 95480093f4SDimitry Andric } 96480093f4SDimitry Andric return E; 97480093f4SDimitry Andric } 98480093f4SDimitry Andric 99480093f4SDimitry Andric assert(*Next != nullptr); 100480093f4SDimitry Andric 101480093f4SDimitry Andric if (shouldKeepRemark(**Next)) 102480093f4SDimitry Andric keep(std::move(*Next)); 103480093f4SDimitry Andric } 104480093f4SDimitry Andric return Error::success(); 105480093f4SDimitry Andric } 106480093f4SDimitry Andric 107480093f4SDimitry Andric Error RemarkLinker::link(const object::ObjectFile &Obj, 108480093f4SDimitry Andric Optional<Format> RemarkFormat) { 109480093f4SDimitry Andric Expected<Optional<StringRef>> SectionOrErr = getRemarksSectionContents(Obj); 110480093f4SDimitry Andric if (!SectionOrErr) 111480093f4SDimitry Andric return SectionOrErr.takeError(); 112480093f4SDimitry Andric 113480093f4SDimitry Andric if (Optional<StringRef> Section = *SectionOrErr) 114480093f4SDimitry Andric return link(*Section, RemarkFormat); 115480093f4SDimitry Andric return Error::success(); 116480093f4SDimitry Andric } 117480093f4SDimitry Andric 118480093f4SDimitry Andric Error RemarkLinker::serialize(raw_ostream &OS, Format RemarksFormat) const { 119480093f4SDimitry Andric Expected<std::unique_ptr<RemarkSerializer>> MaybeSerializer = 120480093f4SDimitry Andric createRemarkSerializer(RemarksFormat, SerializerMode::Standalone, OS, 121480093f4SDimitry Andric std::move(const_cast<StringTable &>(StrTab))); 122480093f4SDimitry Andric if (!MaybeSerializer) 123480093f4SDimitry Andric return MaybeSerializer.takeError(); 124480093f4SDimitry Andric 125480093f4SDimitry Andric std::unique_ptr<remarks::RemarkSerializer> Serializer = 126480093f4SDimitry Andric std::move(*MaybeSerializer); 127480093f4SDimitry Andric 128480093f4SDimitry Andric for (const Remark &R : remarks()) 129480093f4SDimitry Andric Serializer->emit(R); 130480093f4SDimitry Andric return Error::success(); 131480093f4SDimitry Andric } 132