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