|
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