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"
20*bdd1243dSDimitry Andric #include <optional>
21480093f4SDimitry Andric
22480093f4SDimitry Andric using namespace llvm;
23480093f4SDimitry Andric using namespace llvm::remarks;
24480093f4SDimitry Andric
2581ad6265SDimitry Andric namespace llvm {
2681ad6265SDimitry Andric class raw_ostream;
2781ad6265SDimitry Andric }
2881ad6265SDimitry Andric
29480093f4SDimitry Andric static Expected<StringRef>
getRemarksSectionName(const object::ObjectFile & Obj)30480093f4SDimitry Andric getRemarksSectionName(const object::ObjectFile &Obj) {
31480093f4SDimitry Andric if (Obj.isMachO())
32480093f4SDimitry Andric return StringRef("__remarks");
33480093f4SDimitry Andric // ELF -> .remarks, but there is no ELF support at this point.
34480093f4SDimitry Andric return createStringError(std::errc::illegal_byte_sequence,
35480093f4SDimitry Andric "Unsupported file format.");
36480093f4SDimitry Andric }
37480093f4SDimitry Andric
38*bdd1243dSDimitry Andric Expected<std::optional<StringRef>>
getRemarksSectionContents(const object::ObjectFile & Obj)39480093f4SDimitry Andric llvm::remarks::getRemarksSectionContents(const object::ObjectFile &Obj) {
40480093f4SDimitry Andric Expected<StringRef> SectionName = getRemarksSectionName(Obj);
41480093f4SDimitry Andric if (!SectionName)
42480093f4SDimitry Andric return SectionName.takeError();
43480093f4SDimitry Andric
44480093f4SDimitry Andric for (const object::SectionRef &Section : Obj.sections()) {
45480093f4SDimitry Andric Expected<StringRef> MaybeName = Section.getName();
46480093f4SDimitry Andric if (!MaybeName)
47480093f4SDimitry Andric return MaybeName.takeError();
48480093f4SDimitry Andric if (*MaybeName != *SectionName)
49480093f4SDimitry Andric continue;
50480093f4SDimitry Andric
51480093f4SDimitry Andric if (Expected<StringRef> Contents = Section.getContents())
52480093f4SDimitry Andric return *Contents;
53480093f4SDimitry Andric else
54480093f4SDimitry Andric return Contents.takeError();
55480093f4SDimitry Andric }
56*bdd1243dSDimitry Andric return std::optional<StringRef>{};
57480093f4SDimitry Andric }
58480093f4SDimitry Andric
keep(std::unique_ptr<Remark> Remark)59480093f4SDimitry Andric Remark &RemarkLinker::keep(std::unique_ptr<Remark> Remark) {
60480093f4SDimitry Andric StrTab.internalize(*Remark);
61480093f4SDimitry Andric auto Inserted = Remarks.insert(std::move(Remark));
62480093f4SDimitry Andric return **Inserted.first;
63480093f4SDimitry Andric }
64480093f4SDimitry Andric
setExternalFilePrependPath(StringRef PrependPathIn)65480093f4SDimitry Andric void RemarkLinker::setExternalFilePrependPath(StringRef PrependPathIn) {
665ffd83dbSDimitry Andric PrependPath = std::string(PrependPathIn);
67480093f4SDimitry Andric }
68480093f4SDimitry Andric
link(StringRef Buffer,std::optional<Format> RemarkFormat)69*bdd1243dSDimitry Andric Error RemarkLinker::link(StringRef Buffer, std::optional<Format> RemarkFormat) {
70480093f4SDimitry Andric if (!RemarkFormat) {
71480093f4SDimitry Andric Expected<Format> ParserFormat = magicToFormat(Buffer);
72480093f4SDimitry Andric if (!ParserFormat)
73480093f4SDimitry Andric return ParserFormat.takeError();
74480093f4SDimitry Andric RemarkFormat = *ParserFormat;
75480093f4SDimitry Andric }
76480093f4SDimitry Andric
77480093f4SDimitry Andric Expected<std::unique_ptr<RemarkParser>> MaybeParser =
78480093f4SDimitry Andric createRemarkParserFromMeta(
79*bdd1243dSDimitry Andric *RemarkFormat, Buffer, /*StrTab=*/std::nullopt,
80*bdd1243dSDimitry Andric PrependPath ? std::optional<StringRef>(StringRef(*PrependPath))
81*bdd1243dSDimitry Andric : std::optional<StringRef>());
82480093f4SDimitry Andric if (!MaybeParser)
83480093f4SDimitry Andric return MaybeParser.takeError();
84480093f4SDimitry Andric
85480093f4SDimitry Andric RemarkParser &Parser = **MaybeParser;
86480093f4SDimitry Andric
87480093f4SDimitry Andric while (true) {
88480093f4SDimitry Andric Expected<std::unique_ptr<Remark>> Next = Parser.next();
89480093f4SDimitry Andric if (Error E = Next.takeError()) {
90480093f4SDimitry Andric if (E.isA<EndOfFileError>()) {
91480093f4SDimitry Andric consumeError(std::move(E));
92480093f4SDimitry Andric break;
93480093f4SDimitry Andric }
94480093f4SDimitry Andric return E;
95480093f4SDimitry Andric }
96480093f4SDimitry Andric
97480093f4SDimitry Andric assert(*Next != nullptr);
98480093f4SDimitry Andric
99480093f4SDimitry Andric if (shouldKeepRemark(**Next))
100480093f4SDimitry Andric keep(std::move(*Next));
101480093f4SDimitry Andric }
102480093f4SDimitry Andric return Error::success();
103480093f4SDimitry Andric }
104480093f4SDimitry Andric
link(const object::ObjectFile & Obj,std::optional<Format> RemarkFormat)105480093f4SDimitry Andric Error RemarkLinker::link(const object::ObjectFile &Obj,
106*bdd1243dSDimitry Andric std::optional<Format> RemarkFormat) {
107*bdd1243dSDimitry Andric Expected<std::optional<StringRef>> SectionOrErr =
108*bdd1243dSDimitry Andric getRemarksSectionContents(Obj);
109480093f4SDimitry Andric if (!SectionOrErr)
110480093f4SDimitry Andric return SectionOrErr.takeError();
111480093f4SDimitry Andric
112*bdd1243dSDimitry Andric if (std::optional<StringRef> Section = *SectionOrErr)
113480093f4SDimitry Andric return link(*Section, RemarkFormat);
114480093f4SDimitry Andric return Error::success();
115480093f4SDimitry Andric }
116480093f4SDimitry Andric
serialize(raw_ostream & OS,Format RemarksFormat) const117480093f4SDimitry Andric Error RemarkLinker::serialize(raw_ostream &OS, Format RemarksFormat) const {
118480093f4SDimitry Andric Expected<std::unique_ptr<RemarkSerializer>> MaybeSerializer =
119480093f4SDimitry Andric createRemarkSerializer(RemarksFormat, SerializerMode::Standalone, OS,
120480093f4SDimitry Andric std::move(const_cast<StringTable &>(StrTab)));
121480093f4SDimitry Andric if (!MaybeSerializer)
122480093f4SDimitry Andric return MaybeSerializer.takeError();
123480093f4SDimitry Andric
124480093f4SDimitry Andric std::unique_ptr<remarks::RemarkSerializer> Serializer =
125480093f4SDimitry Andric std::move(*MaybeSerializer);
126480093f4SDimitry Andric
127480093f4SDimitry Andric for (const Remark &R : remarks())
128480093f4SDimitry Andric Serializer->emit(R);
129480093f4SDimitry Andric return Error::success();
130480093f4SDimitry Andric }
131