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