|
18 | 18 | #include "llvm/ADT/SmallVector.h"
|
19 | 19 | #include "llvm/ADT/Statistic.h"
|
20 | 20 | #include "llvm/ADT/StringRef.h"
|
| 21 | +#include "llvm/BinaryFormat/Wasm.h" |
21 | 22 | #include "llvm/Object/Archive.h"
|
22 | 23 | #include "llvm/Object/Binary.h"
|
23 | 24 | #include "llvm/Object/COFF.h"
|
24 | 25 | #include "llvm/Object/Error.h"
|
25 | 26 | #include "llvm/Object/MachOUniversal.h"
|
26 | 27 | #include "llvm/Object/ObjectFile.h"
|
| 28 | +#include "llvm/Object/Wasm.h" |
27 | 29 | #include "llvm/ProfileData/InstrProf.h"
|
28 | 30 | #include "llvm/Support/Casting.h"
|
29 | 31 | #include "llvm/Support/Compression.h"
|
@@ -1075,6 +1077,53 @@ lookupSections(ObjectFile &OF, InstrProfSectKind IPSK) {
|
1075 | 1077 | return Sections;
|
1076 | 1078 | }
|
1077 | 1079 |
|
| 1080 | +/// Find a section that matches \p Name and is allocatable at runtime. |
| 1081 | +/// |
| 1082 | +/// Returns the contents of the section and its start offset in the object file. |
| 1083 | +static Expected<std::pair<StringRef, uint64_t>> |
| 1084 | +lookupAllocatableSection(ObjectFile &OF, InstrProfSectKind IPSK) { |
| 1085 | + // On Wasm, allocatable sections can live only in data segments. |
| 1086 | + if (auto *WOF = dyn_cast<WasmObjectFile>(&OF)) { |
| 1087 | + std::vector<const WasmSegment *> Segments; |
| 1088 | + auto ObjFormat = OF.getTripleObjectFormat(); |
| 1089 | + auto Name = |
| 1090 | + getInstrProfSectionName(IPSK, ObjFormat, /*AddSegmentInfo=*/false); |
| 1091 | + for (const auto &DebugName : WOF->debugNames()) { |
| 1092 | + if (DebugName.Type != wasm::NameType::DATA_SEGMENT || |
| 1093 | + DebugName.Name != Name) |
| 1094 | + continue; |
| 1095 | + if (DebugName.Index >= WOF->dataSegments().size()) |
| 1096 | + return make_error<CoverageMapError>(coveragemap_error::malformed); |
| 1097 | + auto &Segment = WOF->dataSegments()[DebugName.Index]; |
| 1098 | + Segments.push_back(&Segment); |
| 1099 | + } |
| 1100 | + if (Segments.empty()) |
| 1101 | + return make_error<CoverageMapError>(coveragemap_error::no_data_found); |
| 1102 | + if (Segments.size() != 1) |
| 1103 | + return make_error<CoverageMapError>(coveragemap_error::malformed); |
| 1104 | + |
| 1105 | + const auto &Segment = *Segments.front(); |
| 1106 | + auto &Data = Segment.Data; |
| 1107 | + StringRef Content(reinterpret_cast<const char *>(Data.Content.data()), |
| 1108 | + Data.Content.size()); |
| 1109 | + return std::make_pair(Content, Segment.SectionOffset); |
| 1110 | + } |
| 1111 | + |
| 1112 | + // On other object file types, delegate to lookupSections to find the section. |
| 1113 | + auto Sections = lookupSections(OF, IPSK); |
| 1114 | + if (!Sections) |
| 1115 | + return Sections.takeError(); |
| 1116 | + if (Sections->size() != 1) |
| 1117 | + return make_error<CoverageMapError>( |
| 1118 | + coveragemap_error::malformed, |
| 1119 | + "the size of coverage mapping section is not one"); |
| 1120 | + auto &Section = Sections->front(); |
| 1121 | + auto ContentsOrErr = Section.getContents(); |
| 1122 | + if (!ContentsOrErr) |
| 1123 | + return ContentsOrErr.takeError(); |
| 1124 | + return std::make_pair(*ContentsOrErr, Section.getAddress()); |
| 1125 | +} |
| 1126 | + |
1078 | 1127 | static Expected<std::unique_ptr<BinaryCoverageReader>>
|
1079 | 1128 | loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch,
|
1080 | 1129 | StringRef CompilationDir = "",
|
@@ -1105,23 +1154,20 @@ loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch,
|
1105 | 1154 |
|
1106 | 1155 | // Look for the sections that we are interested in.
|
1107 | 1156 | auto ProfileNames = std::make_unique<InstrProfSymtab>();
|
1108 |
| - std::vector<SectionRef> NamesSectionRefs; |
1109 | 1157 | // If IPSK_name is not found, fallback to search for IPK_covname, which is
|
1110 | 1158 | // used when binary correlation is enabled.
|
1111 |
| - auto NamesSection = lookupSections(*OF, IPSK_name); |
| 1159 | + auto NamesSection = lookupAllocatableSection(*OF, IPSK_name); |
1112 | 1160 | if (auto E = NamesSection.takeError()) {
|
1113 | 1161 | consumeError(std::move(E));
|
1114 |
| - NamesSection = lookupSections(*OF, IPSK_covname); |
| 1162 | + NamesSection = lookupAllocatableSection(*OF, IPSK_covname); |
1115 | 1163 | if (auto E = NamesSection.takeError())
|
1116 | 1164 | return std::move(E);
|
1117 | 1165 | }
|
1118 |
| - NamesSectionRefs = *NamesSection; |
1119 | 1166 |
|
1120 |
| - if (NamesSectionRefs.size() != 1) |
1121 |
| - return make_error<CoverageMapError>( |
1122 |
| - coveragemap_error::malformed, |
1123 |
| - "the size of coverage mapping section is not one"); |
1124 |
| - if (Error E = ProfileNames->create(NamesSectionRefs.back())) |
| 1167 | + uint64_t NamesAddress; |
| 1168 | + StringRef NamesContent; |
| 1169 | + std::tie(NamesContent, NamesAddress) = *NamesSection; |
| 1170 | + if (Error E = ProfileNames->create(NamesContent, NamesAddress)) |
1125 | 1171 | return std::move(E);
|
1126 | 1172 |
|
1127 | 1173 | auto CoverageSection = lookupSections(*OF, IPSK_covmap);
|
|
0 commit comments