1356843Sdim//===- RemarkLinker.cpp ---------------------------------------------------===// 2356843Sdim// 3356843Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4356843Sdim// See https://llvm.org/LICENSE.txt for license information. 5356843Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6356843Sdim// 7356843Sdim//===----------------------------------------------------------------------===// 8356843Sdim// 9356843Sdim// This file provides an implementation of the remark linker. 10356843Sdim// 11356843Sdim//===----------------------------------------------------------------------===// 12356843Sdim 13356843Sdim#include "llvm/Remarks/RemarkLinker.h" 14356843Sdim#include "llvm/ADT/StringRef.h" 15356843Sdim#include "llvm/Remarks/BitstreamRemarkContainer.h" 16356843Sdim#include "llvm/Remarks/RemarkParser.h" 17356843Sdim#include "llvm/Remarks/RemarkSerializer.h" 18356843Sdim#include "llvm/Support/Error.h" 19356843Sdim 20356843Sdimusing namespace llvm; 21356843Sdimusing namespace llvm::remarks; 22356843Sdim 23356843Sdimstatic Expected<StringRef> 24356843SdimgetRemarksSectionName(const object::ObjectFile &Obj) { 25356843Sdim if (Obj.isMachO()) 26356843Sdim return StringRef("__remarks"); 27356843Sdim // ELF -> .remarks, but there is no ELF support at this point. 28356843Sdim return createStringError(std::errc::illegal_byte_sequence, 29356843Sdim "Unsupported file format."); 30356843Sdim} 31356843Sdim 32356843SdimExpected<Optional<StringRef>> 33356843Sdimllvm::remarks::getRemarksSectionContents(const object::ObjectFile &Obj) { 34356843Sdim Expected<StringRef> SectionName = getRemarksSectionName(Obj); 35356843Sdim if (!SectionName) 36356843Sdim return SectionName.takeError(); 37356843Sdim 38356843Sdim for (const object::SectionRef &Section : Obj.sections()) { 39356843Sdim Expected<StringRef> MaybeName = Section.getName(); 40356843Sdim if (!MaybeName) 41356843Sdim return MaybeName.takeError(); 42356843Sdim if (*MaybeName != *SectionName) 43356843Sdim continue; 44356843Sdim 45356843Sdim if (Expected<StringRef> Contents = Section.getContents()) 46356843Sdim return *Contents; 47356843Sdim else 48356843Sdim return Contents.takeError(); 49356843Sdim } 50356843Sdim return Optional<StringRef>{}; 51356843Sdim} 52356843Sdim 53356843SdimRemark &RemarkLinker::keep(std::unique_ptr<Remark> Remark) { 54356843Sdim StrTab.internalize(*Remark); 55356843Sdim auto Inserted = Remarks.insert(std::move(Remark)); 56356843Sdim return **Inserted.first; 57356843Sdim} 58356843Sdim 59356843Sdimvoid RemarkLinker::setExternalFilePrependPath(StringRef PrependPathIn) { 60356843Sdim PrependPath = PrependPathIn; 61356843Sdim} 62356843Sdim 63356843Sdim// Discard remarks with no source location. 64356843Sdimstatic bool shouldKeepRemark(const Remark &R) { return R.Loc.hasValue(); } 65356843Sdim 66356843SdimError RemarkLinker::link(StringRef Buffer, Optional<Format> RemarkFormat) { 67356843Sdim if (!RemarkFormat) { 68356843Sdim Expected<Format> ParserFormat = magicToFormat(Buffer); 69356843Sdim if (!ParserFormat) 70356843Sdim return ParserFormat.takeError(); 71356843Sdim RemarkFormat = *ParserFormat; 72356843Sdim } 73356843Sdim 74356843Sdim Expected<std::unique_ptr<RemarkParser>> MaybeParser = 75356843Sdim createRemarkParserFromMeta( 76356843Sdim *RemarkFormat, Buffer, /*StrTab=*/None, 77356843Sdim PrependPath ? Optional<StringRef>(StringRef(*PrependPath)) 78356843Sdim : Optional<StringRef>(None)); 79356843Sdim if (!MaybeParser) 80356843Sdim return MaybeParser.takeError(); 81356843Sdim 82356843Sdim RemarkParser &Parser = **MaybeParser; 83356843Sdim 84356843Sdim while (true) { 85356843Sdim Expected<std::unique_ptr<Remark>> Next = Parser.next(); 86356843Sdim if (Error E = Next.takeError()) { 87356843Sdim if (E.isA<EndOfFileError>()) { 88356843Sdim consumeError(std::move(E)); 89356843Sdim break; 90356843Sdim } 91356843Sdim return E; 92356843Sdim } 93356843Sdim 94356843Sdim assert(*Next != nullptr); 95356843Sdim 96356843Sdim if (shouldKeepRemark(**Next)) 97356843Sdim keep(std::move(*Next)); 98356843Sdim } 99356843Sdim return Error::success(); 100356843Sdim} 101356843Sdim 102356843SdimError RemarkLinker::link(const object::ObjectFile &Obj, 103356843Sdim Optional<Format> RemarkFormat) { 104356843Sdim Expected<Optional<StringRef>> SectionOrErr = getRemarksSectionContents(Obj); 105356843Sdim if (!SectionOrErr) 106356843Sdim return SectionOrErr.takeError(); 107356843Sdim 108356843Sdim if (Optional<StringRef> Section = *SectionOrErr) 109356843Sdim return link(*Section, RemarkFormat); 110356843Sdim return Error::success(); 111356843Sdim} 112356843Sdim 113356843SdimError RemarkLinker::serialize(raw_ostream &OS, Format RemarksFormat) const { 114356843Sdim Expected<std::unique_ptr<RemarkSerializer>> MaybeSerializer = 115356843Sdim createRemarkSerializer(RemarksFormat, SerializerMode::Standalone, OS, 116356843Sdim std::move(const_cast<StringTable &>(StrTab))); 117356843Sdim if (!MaybeSerializer) 118356843Sdim return MaybeSerializer.takeError(); 119356843Sdim 120356843Sdim std::unique_ptr<remarks::RemarkSerializer> Serializer = 121356843Sdim std::move(*MaybeSerializer); 122356843Sdim 123356843Sdim for (const Remark &R : remarks()) 124356843Sdim Serializer->emit(R); 125356843Sdim return Error::success(); 126356843Sdim} 127