|
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"
|
@@ -492,22 +494,29 @@ Expected<bool> RawCoverageMappingDummyChecker::isDummy() {
|
492 | 494 | return Tag == Counter::Zero;
|
493 | 495 | }
|
494 | 496 |
|
495 |
| -Error InstrProfSymtab::create(SectionRef &Section) { |
496 |
| - Expected<StringRef> DataOrErr = Section.getContents(); |
497 |
| - if (!DataOrErr) |
498 |
| - return DataOrErr.takeError(); |
499 |
| - Data = *DataOrErr; |
500 |
| - Address = Section.getAddress(); |
501 |
| - |
| 497 | +/// Determine if we should skip the first byte of the section content |
| 498 | +static bool shouldSkipSectionFirstByte(SectionRef &Section) { |
| 499 | + const ObjectFile *Obj = Section.getObject(); |
502 | 500 | // If this is a linked PE/COFF file, then we have to skip over the null byte
|
503 | 501 | // that is allocated in the .lprfn$A section in the LLVM profiling runtime.
|
504 | 502 | // If the name section is .lprfcovnames, it doesn't have the null byte at the
|
505 | 503 | // beginning.
|
506 |
| - const ObjectFile *Obj = Section.getObject(); |
507 | 504 | if (isa<COFFObjectFile>(Obj) && !Obj->isRelocatableObject())
|
508 | 505 | if (Expected<StringRef> NameOrErr = Section.getName())
|
509 | 506 | if (*NameOrErr != getInstrProfSectionName(IPSK_covname, Triple::COFF))
|
510 |
| - Data = Data.drop_front(1); |
| 507 | + return true; |
| 508 | + return false; |
| 509 | +} |
| 510 | + |
| 511 | +Error InstrProfSymtab::create(SectionRef &Section) { |
| 512 | + Expected<StringRef> DataOrErr = Section.getContents(); |
| 513 | + if (!DataOrErr) |
| 514 | + return DataOrErr.takeError(); |
| 515 | + Data = *DataOrErr; |
| 516 | + Address = Section.getAddress(); |
| 517 | + |
| 518 | + if (shouldSkipSectionFirstByte(Section)) |
| 519 | + Data = Data.substr(1); |
511 | 520 |
|
512 | 521 | return Error::success();
|
513 | 522 | }
|
@@ -1077,6 +1086,56 @@ lookupSections(ObjectFile &OF, InstrProfSectKind IPSK) {
|
1077 | 1086 | return Sections;
|
1078 | 1087 | }
|
1079 | 1088 |
|
| 1089 | +/// Find a section that matches \p Name and is allocatable at runtime. |
| 1090 | +/// |
| 1091 | +/// Returns the contents of the section and its start offset in the object file. |
| 1092 | +static Expected<std::pair<StringRef, uint64_t>> |
| 1093 | +lookupAllocatableSection(ObjectFile &OF, InstrProfSectKind IPSK) { |
| 1094 | + // On Wasm, allocatable sections can live only in data segments. |
| 1095 | + if (auto *WOF = dyn_cast<WasmObjectFile>(&OF)) { |
| 1096 | + std::vector<const WasmSegment *> Segments; |
| 1097 | + auto ObjFormat = OF.getTripleObjectFormat(); |
| 1098 | + auto Name = |
| 1099 | + getInstrProfSectionName(IPSK, ObjFormat, /*AddSegmentInfo=*/false); |
| 1100 | + for (const auto &DebugName : WOF->debugNames()) { |
| 1101 | + if (DebugName.Type != wasm::NameType::DATA_SEGMENT || |
| 1102 | + DebugName.Name != Name) |
| 1103 | + continue; |
| 1104 | + if (DebugName.Index >= WOF->dataSegments().size()) |
| 1105 | + return make_error<CoverageMapError>(coveragemap_error::malformed); |
| 1106 | + auto &Segment = WOF->dataSegments()[DebugName.Index]; |
| 1107 | + Segments.push_back(&Segment); |
| 1108 | + } |
| 1109 | + if (Segments.empty()) |
| 1110 | + return make_error<CoverageMapError>(coveragemap_error::no_data_found); |
| 1111 | + if (Segments.size() != 1) |
| 1112 | + return make_error<CoverageMapError>(coveragemap_error::malformed); |
| 1113 | + |
| 1114 | + const auto &Segment = *Segments.front(); |
| 1115 | + auto &Data = Segment.Data; |
| 1116 | + StringRef Content(reinterpret_cast<const char *>(Data.Content.data()), |
| 1117 | + Data.Content.size()); |
| 1118 | + return std::make_pair(Content, Segment.SectionOffset); |
| 1119 | + } |
| 1120 | + |
| 1121 | + // On other object file types, delegate to lookupSections to find the section. |
| 1122 | + auto Sections = lookupSections(OF, IPSK); |
| 1123 | + if (!Sections) |
| 1124 | + return Sections.takeError(); |
| 1125 | + if (Sections->size() != 1) |
| 1126 | + return make_error<CoverageMapError>( |
| 1127 | + coveragemap_error::malformed, |
| 1128 | + "the size of coverage mapping section is not one"); |
| 1129 | + auto &Section = Sections->front(); |
| 1130 | + auto ContentsOrErr = Section.getContents(); |
| 1131 | + if (!ContentsOrErr) |
| 1132 | + return ContentsOrErr.takeError(); |
| 1133 | + auto Content = *ContentsOrErr; |
| 1134 | + if (shouldSkipSectionFirstByte(Section)) |
| 1135 | + Content = Content.drop_front(1); |
| 1136 | + return std::make_pair(Content, Section.getAddress()); |
| 1137 | +} |
| 1138 | + |
1080 | 1139 | static Expected<std::unique_ptr<BinaryCoverageReader>>
|
1081 | 1140 | loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch,
|
1082 | 1141 | StringRef CompilationDir = "",
|
@@ -1107,23 +1166,20 @@ loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch,
|
1107 | 1166 |
|
1108 | 1167 | // Look for the sections that we are interested in.
|
1109 | 1168 | auto ProfileNames = std::make_unique<InstrProfSymtab>();
|
1110 |
| - std::vector<SectionRef> NamesSectionRefs; |
1111 | 1169 | // If IPSK_name is not found, fallback to search for IPK_covname, which is
|
1112 | 1170 | // used when binary correlation is enabled.
|
1113 |
| - auto NamesSection = lookupSections(*OF, IPSK_name); |
| 1171 | + auto NamesSection = lookupAllocatableSection(*OF, IPSK_name); |
1114 | 1172 | if (auto E = NamesSection.takeError()) {
|
1115 | 1173 | consumeError(std::move(E));
|
1116 |
| - NamesSection = lookupSections(*OF, IPSK_covname); |
| 1174 | + NamesSection = lookupAllocatableSection(*OF, IPSK_covname); |
1117 | 1175 | if (auto E = NamesSection.takeError())
|
1118 | 1176 | return std::move(E);
|
1119 | 1177 | }
|
1120 |
| - NamesSectionRefs = *NamesSection; |
1121 | 1178 |
|
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())) |
| 1179 | + uint64_t NamesAddress; |
| 1180 | + StringRef NamesContent; |
| 1181 | + std::tie(NamesContent, NamesAddress) = *NamesSection; |
| 1182 | + if (Error E = ProfileNames->create(NamesContent, NamesAddress)) |
1127 | 1183 | return std::move(E);
|
1128 | 1184 |
|
1129 | 1185 | auto CoverageSection = lookupSections(*OF, IPSK_covmap);
|
|
0 commit comments