21 #define DEBUG_TYPE "correlator"
31 return make_error<InstrProfError>(
33 "could not find counter section (" INSTR_PROF_CNTS_SECT_NAME
")");
44 if (
auto Err = CountersSection.takeError())
46 auto C = std::make_unique<Context>();
48 C->CountersSectionStart = CountersSection->getAddress();
49 C->CountersSectionEnd =
C->CountersSectionStart + CountersSection->getSize();
56 auto DsymObjectsOrErr =
58 if (
auto Err = DsymObjectsOrErr.takeError())
60 if (!DsymObjectsOrErr->empty()) {
63 if (DsymObjectsOrErr->size() > 1)
64 return make_error<InstrProfError>(
66 "using multiple objects is not yet supported");
67 DebugInfoFilename = *DsymObjectsOrErr->
begin();
71 if (
auto Err = BufferOrErr.takeError())
80 if (
auto Err = BinOrErr.takeError())
83 if (
auto *Obj = dyn_cast<object::ObjectFile>(BinOrErr->get())) {
85 if (
auto Err = CtxOrErr.takeError())
87 auto T = Obj->makeTriple();
93 return make_error<InstrProfError>(
99 return C->getDataSize();
101 return C->getDataSize();
110 std::unique_ptr<InstrProfCorrelator::Context>
Ctx)
115 std::unique_ptr<InstrProfCorrelator::Context> Ctx)
120 return C->getKind() == InstrProfCorrelatorKind::CK_32Bit;
124 return C->getKind() == InstrProfCorrelatorKind::CK_64Bit;
129 template <
class IntPtrT>
132 std::unique_ptr<InstrProfCorrelator::Context> Ctx,
135 auto DICtx = DWARFContext::create(Obj);
136 return std::make_unique<DwarfInstrProfCorrelator<IntPtrT>>(
std::move(DICtx),
139 return make_error<InstrProfError>(
140 instrprof_error::unable_to_correlate_profile,
141 "unsupported debug info format (only DWARF is supported)");
144 template <
class IntPtrT>
146 assert(
Data.empty() && Names.empty() && NamesVec.empty());
147 correlateProfileDataImpl();
148 if (
Data.empty() || NamesVec.empty())
149 return make_error<InstrProfError>(
150 instrprof_error::unable_to_correlate_profile,
151 "could not find any profile metadata in debug info");
154 CounterOffsets.clear();
162 io.mapRequired(
"Probes",
Data.Probes);
168 io.mapRequired(
"Function Name",
P.FunctionName);
169 io.mapOptional(
"Linkage Name",
P.LinkageName);
170 io.mapRequired(
"CFG Hash",
P.CFGHash);
171 io.mapRequired(
"Counter Offset",
P.CounterOffset);
172 io.mapRequired(
"Num Counters",
P.NumCounters);
173 io.mapOptional(
"File",
P.FilePath);
174 io.mapOptional(
"Line",
P.LineNumber);
179 static const bool flow =
false;
182 template <
class IntPtrT>
185 correlateProfileDataImpl(&
Data);
186 if (
Data.Probes.empty())
187 return make_error<InstrProfError>(
188 instrprof_error::unable_to_correlate_profile,
189 "could not find any profile metadata in debug info");
190 yaml::Output YamlOS(OS);
192 return Error::success();
195 template <
class IntPtrT>
198 IntPtrT CounterOffset,
202 if (!CounterOffsets.insert(CounterOffset).second)
206 maybeSwap<uint64_t>(CFGHash),
209 maybeSwap<IntPtrT>(CounterOffset),
210 maybeSwap<IntPtrT>(FunctionPtr),
212 maybeSwap<IntPtrT>(0),
213 maybeSwap<uint32_t>(NumCounters),
214 {maybeSwap<uint16_t>(0), maybeSwap<uint16_t>(0)},
216 NamesVec.push_back(FunctionName.
str());
219 template <
class IntPtrT>
220 std::optional<uint64_t>
222 auto Locations = Die.
getLocations(dwarf::DW_AT_location);
229 for (
auto &Location : *Locations) {
232 for (
auto &
Op : Expr) {
233 if (
Op.getCode() == dwarf::DW_OP_addr) {
234 return Op.getRawOperand(0);
235 }
else if (
Op.getCode() == dwarf::DW_OP_addrx) {
237 if (
auto SA = DU.getAddrOffsetSectionItem(
Index))
245 template <
class IntPtrT>
250 if (Die.
getTag() != dwarf::DW_TAG_variable)
252 if (!ParentDie.isSubprogramDIE())
256 if (
const char *
Name = Die.
getName(DINameKind::ShortName))
261 template <
class IntPtrT>
264 auto maybeAddProbe = [&](
DWARFDie Die) {
265 if (!isDIEOfProbe(Die))
267 std::optional<const char *> FunctionName;
268 std::optional<uint64_t> CFGHash;
269 std::optional<uint64_t> CounterPtr =
getLocation(Die);
272 std::optional<uint64_t> NumCounters;
274 if (Child.getTag() != dwarf::DW_TAG_LLVM_annotation)
276 auto AnnotationFormName = Child.find(dwarf::DW_AT_name);
277 auto AnnotationFormValue = Child.find(dwarf::DW_AT_const_value);
278 if (!AnnotationFormName || !AnnotationFormValue)
280 auto AnnotationNameOrErr = AnnotationFormName->getAsCString();
281 if (
auto Err = AnnotationNameOrErr.takeError()) {
285 StringRef AnnotationName = *AnnotationNameOrErr;
287 InstrProfCorrelator::FunctionNameAttributeName) == 0) {
289 AnnotationFormValue->getAsCString().moveInto(FunctionName))
291 }
else if (AnnotationName.
compare(
292 InstrProfCorrelator::CFGHashAttributeName) == 0) {
293 CFGHash = AnnotationFormValue->getAsUnsignedConstant();
294 }
else if (AnnotationName.
compare(
295 InstrProfCorrelator::NumCountersAttributeName) == 0) {
296 NumCounters = AnnotationFormValue->getAsUnsignedConstant();
299 if (!FunctionName || !CFGHash || !CounterPtr || !NumCounters) {
301 << FunctionName <<
"\n\tCFGHash: " << CFGHash
302 <<
"\n\tCounterPtr: " << CounterPtr
303 <<
"\n\tNumCounters: " << NumCounters);
307 uint64_t CountersStart = this->Ctx->CountersSectionStart;
308 uint64_t CountersEnd = this->Ctx->CountersSectionEnd;
309 if (*CounterPtr < CountersStart || *CounterPtr >= CountersEnd) {
311 dbgs() <<
"CounterPtr out of range for probe\n\tFunction Name: "
312 << FunctionName <<
"\n\tExpected: [0x"
313 << Twine::utohexstr(CountersStart) <<
", 0x"
314 << Twine::utohexstr(CountersEnd) <<
")\n\tActual: 0x"
315 << Twine::utohexstr(*CounterPtr));
320 LLVM_DEBUG(
dbgs() <<
"Could not find address of " << *FunctionName
324 IntPtrT CounterOffset = *CounterPtr - CountersStart;
327 P.FunctionName = *FunctionName;
328 if (
auto Name = FnDie.getName(DINameKind::LinkageName))
329 P.LinkageName =
Name;
330 P.CFGHash = *CFGHash;
331 P.CounterOffset = CounterOffset;
332 P.NumCounters = *NumCounters;
333 auto FilePath = FnDie.getDeclFile(
334 DILineInfoSpecifier::FileLineInfoKind::RelativeFilePath);
335 if (!FilePath.empty())
336 P.FilePath = FilePath;
337 if (
auto LineNumber = FnDie.getDeclLine())
338 P.LineNumber = LineNumber;
339 Data->Probes.push_back(
P);
341 this->addProbe(*FunctionName, *CFGHash, CounterOffset,
342 FunctionPtr.value_or(0), *NumCounters);
345 for (
auto &
CU : DICtx->normal_units())
346 for (
const auto &Entry :
CU->dies())
348 for (
auto &
CU : DICtx->dwo_units())
349 for (
const auto &Entry :
CU->dies())