1 //===- RemarkLinker.cpp ---------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file provides an implementation of the remark linker.
11 //===----------------------------------------------------------------------===//
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"
22 using namespace llvm::remarks
;
28 static Expected
<StringRef
>
29 getRemarksSectionName(const object::ObjectFile
&Obj
) {
31 return StringRef("__remarks");
32 // ELF -> .remarks, but there is no ELF support at this point.
33 return createStringError(std::errc::illegal_byte_sequence
,
34 "Unsupported file format.");
37 Expected
<Optional
<StringRef
>>
38 llvm::remarks::getRemarksSectionContents(const object::ObjectFile
&Obj
) {
39 Expected
<StringRef
> SectionName
= getRemarksSectionName(Obj
);
41 return SectionName
.takeError();
43 for (const object::SectionRef
&Section
: Obj
.sections()) {
44 Expected
<StringRef
> MaybeName
= Section
.getName();
46 return MaybeName
.takeError();
47 if (*MaybeName
!= *SectionName
)
50 if (Expected
<StringRef
> Contents
= Section
.getContents())
53 return Contents
.takeError();
55 return Optional
<StringRef
>{};
58 Remark
&RemarkLinker::keep(std::unique_ptr
<Remark
> Remark
) {
59 StrTab
.internalize(*Remark
);
60 auto Inserted
= Remarks
.insert(std::move(Remark
));
61 return **Inserted
.first
;
64 void RemarkLinker::setExternalFilePrependPath(StringRef PrependPathIn
) {
65 PrependPath
= std::string(PrependPathIn
);
68 // Discard remarks with no source location.
69 static bool shouldKeepRemark(const Remark
&R
) { return R
.Loc
.has_value(); }
71 Error
RemarkLinker::link(StringRef Buffer
, Optional
<Format
> RemarkFormat
) {
73 Expected
<Format
> ParserFormat
= magicToFormat(Buffer
);
75 return ParserFormat
.takeError();
76 RemarkFormat
= *ParserFormat
;
79 Expected
<std::unique_ptr
<RemarkParser
>> MaybeParser
=
80 createRemarkParserFromMeta(
81 *RemarkFormat
, Buffer
, /*StrTab=*/None
,
82 PrependPath
? Optional
<StringRef
>(StringRef(*PrependPath
))
83 : Optional
<StringRef
>(None
));
85 return MaybeParser
.takeError();
87 RemarkParser
&Parser
= **MaybeParser
;
90 Expected
<std::unique_ptr
<Remark
>> Next
= Parser
.next();
91 if (Error E
= Next
.takeError()) {
92 if (E
.isA
<EndOfFileError
>()) {
93 consumeError(std::move(E
));
99 assert(*Next
!= nullptr);
101 if (shouldKeepRemark(**Next
))
102 keep(std::move(*Next
));
104 return Error::success();
107 Error
RemarkLinker::link(const object::ObjectFile
&Obj
,
108 Optional
<Format
> RemarkFormat
) {
109 Expected
<Optional
<StringRef
>> SectionOrErr
= getRemarksSectionContents(Obj
);
111 return SectionOrErr
.takeError();
113 if (Optional
<StringRef
> Section
= *SectionOrErr
)
114 return link(*Section
, RemarkFormat
);
115 return Error::success();
118 Error
RemarkLinker::serialize(raw_ostream
&OS
, Format RemarksFormat
) const {
119 Expected
<std::unique_ptr
<RemarkSerializer
>> MaybeSerializer
=
120 createRemarkSerializer(RemarksFormat
, SerializerMode::Standalone
, OS
,
121 std::move(const_cast<StringTable
&>(StrTab
)));
122 if (!MaybeSerializer
)
123 return MaybeSerializer
.takeError();
125 std::unique_ptr
<remarks::RemarkSerializer
> Serializer
=
126 std::move(*MaybeSerializer
);
128 for (const Remark
&R
: remarks())
130 return Error::success();