InstrProfReader.cpp 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228
  1. //===- InstrProfReader.cpp - Instrumented profiling reader ----------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file contains support for reading profiling data for clang's
  10. // instrumentation based PGO and coverage.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "llvm/ProfileData/InstrProfReader.h"
  14. #include "llvm/ADT/ArrayRef.h"
  15. #include "llvm/ADT/DenseMap.h"
  16. #include "llvm/ADT/StringExtras.h"
  17. #include "llvm/ADT/StringRef.h"
  18. #include "llvm/IR/ProfileSummary.h"
  19. #include "llvm/ProfileData/InstrProf.h"
  20. #include "llvm/ProfileData/MemProf.h"
  21. #include "llvm/ProfileData/ProfileCommon.h"
  22. #include "llvm/Support/Endian.h"
  23. #include "llvm/Support/Error.h"
  24. #include "llvm/Support/ErrorOr.h"
  25. #include "llvm/Support/MemoryBuffer.h"
  26. #include "llvm/Support/SwapByteOrder.h"
  27. #include "llvm/Support/SymbolRemappingReader.h"
  28. #include <algorithm>
  29. #include <cstddef>
  30. #include <cstdint>
  31. #include <limits>
  32. #include <memory>
  33. #include <system_error>
  34. #include <utility>
  35. #include <vector>
  36. using namespace llvm;
  37. // Extracts the variant information from the top 8 bits in the version and
  38. // returns an enum specifying the variants present.
  39. static InstrProfKind getProfileKindFromVersion(uint64_t Version) {
  40. InstrProfKind ProfileKind = InstrProfKind::Unknown;
  41. if (Version & VARIANT_MASK_IR_PROF) {
  42. ProfileKind |= InstrProfKind::IRInstrumentation;
  43. }
  44. if (Version & VARIANT_MASK_CSIR_PROF) {
  45. ProfileKind |= InstrProfKind::ContextSensitive;
  46. }
  47. if (Version & VARIANT_MASK_INSTR_ENTRY) {
  48. ProfileKind |= InstrProfKind::FunctionEntryInstrumentation;
  49. }
  50. if (Version & VARIANT_MASK_BYTE_COVERAGE) {
  51. ProfileKind |= InstrProfKind::SingleByteCoverage;
  52. }
  53. if (Version & VARIANT_MASK_FUNCTION_ENTRY_ONLY) {
  54. ProfileKind |= InstrProfKind::FunctionEntryOnly;
  55. }
  56. if (Version & VARIANT_MASK_MEMPROF) {
  57. ProfileKind |= InstrProfKind::MemProf;
  58. }
  59. return ProfileKind;
  60. }
  61. static Expected<std::unique_ptr<MemoryBuffer>>
  62. setupMemoryBuffer(const Twine &Path) {
  63. ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
  64. MemoryBuffer::getFileOrSTDIN(Path, /*IsText=*/true);
  65. if (std::error_code EC = BufferOrErr.getError())
  66. return errorCodeToError(EC);
  67. return std::move(BufferOrErr.get());
  68. }
  69. static Error initializeReader(InstrProfReader &Reader) {
  70. return Reader.readHeader();
  71. }
  72. /// Read a list of binary ids from a profile that consist of
  73. /// a. uint64_t binary id length
  74. /// b. uint8_t binary id data
  75. /// c. uint8_t padding (if necessary)
  76. /// This function is shared between raw and indexed profiles.
  77. /// Raw profiles are in host-endian format, and indexed profiles are in
  78. /// little-endian format. So, this function takes an argument indicating the
  79. /// associated endian format to read the binary ids correctly.
  80. static Error
  81. readBinaryIdsInternal(const MemoryBuffer &DataBuffer,
  82. const uint64_t BinaryIdsSize,
  83. const uint8_t *BinaryIdsStart,
  84. std::vector<llvm::object::BuildID> &BinaryIds,
  85. const llvm::support::endianness Endian) {
  86. using namespace support;
  87. if (BinaryIdsSize == 0)
  88. return Error::success();
  89. const uint8_t *BI = BinaryIdsStart;
  90. const uint8_t *BIEnd = BinaryIdsStart + BinaryIdsSize;
  91. const uint8_t *End =
  92. reinterpret_cast<const uint8_t *>(DataBuffer.getBufferEnd());
  93. while (BI < BIEnd) {
  94. size_t Remaining = BIEnd - BI;
  95. // There should be enough left to read the binary id length.
  96. if (Remaining < sizeof(uint64_t))
  97. return make_error<InstrProfError>(
  98. instrprof_error::malformed,
  99. "not enough data to read binary id length");
  100. uint64_t BILen = 0;
  101. if (Endian == little)
  102. BILen = endian::readNext<uint64_t, little, unaligned>(BI);
  103. else
  104. BILen = endian::readNext<uint64_t, big, unaligned>(BI);
  105. if (BILen == 0)
  106. return make_error<InstrProfError>(instrprof_error::malformed,
  107. "binary id length is 0");
  108. Remaining = BIEnd - BI;
  109. // There should be enough left to read the binary id data.
  110. if (Remaining < alignToPowerOf2(BILen, sizeof(uint64_t)))
  111. return make_error<InstrProfError>(
  112. instrprof_error::malformed, "not enough data to read binary id data");
  113. // Add binary id to the binary ids list.
  114. BinaryIds.push_back(object::BuildID(BI, BI + BILen));
  115. // Increment by binary id data length, which aligned to the size of uint64.
  116. BI += alignToPowerOf2(BILen, sizeof(uint64_t));
  117. if (BI > End)
  118. return make_error<InstrProfError>(
  119. instrprof_error::malformed,
  120. "binary id section is greater than buffer size");
  121. }
  122. return Error::success();
  123. }
  124. static Error printBinaryIdsInternal(raw_ostream &OS,
  125. const MemoryBuffer &DataBuffer,
  126. uint64_t BinaryIdsSize,
  127. const uint8_t *BinaryIdsStart,
  128. llvm::support::endianness Endian) {
  129. if (BinaryIdsSize == 0)
  130. return Error::success();
  131. std::vector<llvm::object::BuildID> BinaryIds;
  132. if (Error E = readBinaryIdsInternal(DataBuffer, BinaryIdsSize, BinaryIdsStart,
  133. BinaryIds, Endian))
  134. return E;
  135. OS << "Binary IDs: \n";
  136. for (auto BI : BinaryIds) {
  137. for (uint64_t I = 0; I < BI.size(); I++)
  138. OS << format("%02x", BI[I]);
  139. OS << "\n";
  140. }
  141. return Error::success();
  142. }
  143. Expected<std::unique_ptr<InstrProfReader>>
  144. InstrProfReader::create(const Twine &Path,
  145. const InstrProfCorrelator *Correlator) {
  146. // Set up the buffer to read.
  147. auto BufferOrError = setupMemoryBuffer(Path);
  148. if (Error E = BufferOrError.takeError())
  149. return std::move(E);
  150. return InstrProfReader::create(std::move(BufferOrError.get()), Correlator);
  151. }
  152. Expected<std::unique_ptr<InstrProfReader>>
  153. InstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer,
  154. const InstrProfCorrelator *Correlator) {
  155. // Sanity check the buffer.
  156. if (uint64_t(Buffer->getBufferSize()) > std::numeric_limits<uint64_t>::max())
  157. return make_error<InstrProfError>(instrprof_error::too_large);
  158. if (Buffer->getBufferSize() == 0)
  159. return make_error<InstrProfError>(instrprof_error::empty_raw_profile);
  160. std::unique_ptr<InstrProfReader> Result;
  161. // Create the reader.
  162. if (IndexedInstrProfReader::hasFormat(*Buffer))
  163. Result.reset(new IndexedInstrProfReader(std::move(Buffer)));
  164. else if (RawInstrProfReader64::hasFormat(*Buffer))
  165. Result.reset(new RawInstrProfReader64(std::move(Buffer), Correlator));
  166. else if (RawInstrProfReader32::hasFormat(*Buffer))
  167. Result.reset(new RawInstrProfReader32(std::move(Buffer), Correlator));
  168. else if (TextInstrProfReader::hasFormat(*Buffer))
  169. Result.reset(new TextInstrProfReader(std::move(Buffer)));
  170. else
  171. return make_error<InstrProfError>(instrprof_error::unrecognized_format);
  172. // Initialize the reader and return the result.
  173. if (Error E = initializeReader(*Result))
  174. return std::move(E);
  175. return std::move(Result);
  176. }
  177. Expected<std::unique_ptr<IndexedInstrProfReader>>
  178. IndexedInstrProfReader::create(const Twine &Path, const Twine &RemappingPath) {
  179. // Set up the buffer to read.
  180. auto BufferOrError = setupMemoryBuffer(Path);
  181. if (Error E = BufferOrError.takeError())
  182. return std::move(E);
  183. // Set up the remapping buffer if requested.
  184. std::unique_ptr<MemoryBuffer> RemappingBuffer;
  185. std::string RemappingPathStr = RemappingPath.str();
  186. if (!RemappingPathStr.empty()) {
  187. auto RemappingBufferOrError = setupMemoryBuffer(RemappingPathStr);
  188. if (Error E = RemappingBufferOrError.takeError())
  189. return std::move(E);
  190. RemappingBuffer = std::move(RemappingBufferOrError.get());
  191. }
  192. return IndexedInstrProfReader::create(std::move(BufferOrError.get()),
  193. std::move(RemappingBuffer));
  194. }
  195. Expected<std::unique_ptr<IndexedInstrProfReader>>
  196. IndexedInstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer,
  197. std::unique_ptr<MemoryBuffer> RemappingBuffer) {
  198. if (uint64_t(Buffer->getBufferSize()) > std::numeric_limits<uint64_t>::max())
  199. return make_error<InstrProfError>(instrprof_error::too_large);
  200. // Create the reader.
  201. if (!IndexedInstrProfReader::hasFormat(*Buffer))
  202. return make_error<InstrProfError>(instrprof_error::bad_magic);
  203. auto Result = std::make_unique<IndexedInstrProfReader>(
  204. std::move(Buffer), std::move(RemappingBuffer));
  205. // Initialize the reader and return the result.
  206. if (Error E = initializeReader(*Result))
  207. return std::move(E);
  208. return std::move(Result);
  209. }
  210. bool TextInstrProfReader::hasFormat(const MemoryBuffer &Buffer) {
  211. // Verify that this really looks like plain ASCII text by checking a
  212. // 'reasonable' number of characters (up to profile magic size).
  213. size_t count = std::min(Buffer.getBufferSize(), sizeof(uint64_t));
  214. StringRef buffer = Buffer.getBufferStart();
  215. return count == 0 ||
  216. std::all_of(buffer.begin(), buffer.begin() + count,
  217. [](char c) { return isPrint(c) || isSpace(c); });
  218. }
  219. // Read the profile variant flag from the header: ":FE" means this is a FE
  220. // generated profile. ":IR" means this is an IR level profile. Other strings
  221. // with a leading ':' will be reported an error format.
  222. Error TextInstrProfReader::readHeader() {
  223. Symtab.reset(new InstrProfSymtab());
  224. while (Line->startswith(":")) {
  225. StringRef Str = Line->substr(1);
  226. if (Str.equals_insensitive("ir"))
  227. ProfileKind |= InstrProfKind::IRInstrumentation;
  228. else if (Str.equals_insensitive("fe"))
  229. ProfileKind |= InstrProfKind::FrontendInstrumentation;
  230. else if (Str.equals_insensitive("csir")) {
  231. ProfileKind |= InstrProfKind::IRInstrumentation;
  232. ProfileKind |= InstrProfKind::ContextSensitive;
  233. } else if (Str.equals_insensitive("entry_first"))
  234. ProfileKind |= InstrProfKind::FunctionEntryInstrumentation;
  235. else if (Str.equals_insensitive("not_entry_first"))
  236. ProfileKind &= ~InstrProfKind::FunctionEntryInstrumentation;
  237. else
  238. return error(instrprof_error::bad_header);
  239. ++Line;
  240. }
  241. return success();
  242. }
  243. Error
  244. TextInstrProfReader::readValueProfileData(InstrProfRecord &Record) {
  245. #define CHECK_LINE_END(Line) \
  246. if (Line.is_at_end()) \
  247. return error(instrprof_error::truncated);
  248. #define READ_NUM(Str, Dst) \
  249. if ((Str).getAsInteger(10, (Dst))) \
  250. return error(instrprof_error::malformed);
  251. #define VP_READ_ADVANCE(Val) \
  252. CHECK_LINE_END(Line); \
  253. uint32_t Val; \
  254. READ_NUM((*Line), (Val)); \
  255. Line++;
  256. if (Line.is_at_end())
  257. return success();
  258. uint32_t NumValueKinds;
  259. if (Line->getAsInteger(10, NumValueKinds)) {
  260. // No value profile data
  261. return success();
  262. }
  263. if (NumValueKinds == 0 || NumValueKinds > IPVK_Last + 1)
  264. return error(instrprof_error::malformed,
  265. "number of value kinds is invalid");
  266. Line++;
  267. for (uint32_t VK = 0; VK < NumValueKinds; VK++) {
  268. VP_READ_ADVANCE(ValueKind);
  269. if (ValueKind > IPVK_Last)
  270. return error(instrprof_error::malformed, "value kind is invalid");
  271. ;
  272. VP_READ_ADVANCE(NumValueSites);
  273. if (!NumValueSites)
  274. continue;
  275. Record.reserveSites(VK, NumValueSites);
  276. for (uint32_t S = 0; S < NumValueSites; S++) {
  277. VP_READ_ADVANCE(NumValueData);
  278. std::vector<InstrProfValueData> CurrentValues;
  279. for (uint32_t V = 0; V < NumValueData; V++) {
  280. CHECK_LINE_END(Line);
  281. std::pair<StringRef, StringRef> VD = Line->rsplit(':');
  282. uint64_t TakenCount, Value;
  283. if (ValueKind == IPVK_IndirectCallTarget) {
  284. if (InstrProfSymtab::isExternalSymbol(VD.first)) {
  285. Value = 0;
  286. } else {
  287. if (Error E = Symtab->addFuncName(VD.first))
  288. return E;
  289. Value = IndexedInstrProf::ComputeHash(VD.first);
  290. }
  291. } else {
  292. READ_NUM(VD.first, Value);
  293. }
  294. READ_NUM(VD.second, TakenCount);
  295. CurrentValues.push_back({Value, TakenCount});
  296. Line++;
  297. }
  298. Record.addValueData(ValueKind, S, CurrentValues.data(), NumValueData,
  299. nullptr);
  300. }
  301. }
  302. return success();
  303. #undef CHECK_LINE_END
  304. #undef READ_NUM
  305. #undef VP_READ_ADVANCE
  306. }
  307. Error TextInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) {
  308. // Skip empty lines and comments.
  309. while (!Line.is_at_end() && (Line->empty() || Line->startswith("#")))
  310. ++Line;
  311. // If we hit EOF while looking for a name, we're done.
  312. if (Line.is_at_end()) {
  313. return error(instrprof_error::eof);
  314. }
  315. // Read the function name.
  316. Record.Name = *Line++;
  317. if (Error E = Symtab->addFuncName(Record.Name))
  318. return error(std::move(E));
  319. // Read the function hash.
  320. if (Line.is_at_end())
  321. return error(instrprof_error::truncated);
  322. if ((Line++)->getAsInteger(0, Record.Hash))
  323. return error(instrprof_error::malformed,
  324. "function hash is not a valid integer");
  325. // Read the number of counters.
  326. uint64_t NumCounters;
  327. if (Line.is_at_end())
  328. return error(instrprof_error::truncated);
  329. if ((Line++)->getAsInteger(10, NumCounters))
  330. return error(instrprof_error::malformed,
  331. "number of counters is not a valid integer");
  332. if (NumCounters == 0)
  333. return error(instrprof_error::malformed, "number of counters is zero");
  334. // Read each counter and fill our internal storage with the values.
  335. Record.Clear();
  336. Record.Counts.reserve(NumCounters);
  337. for (uint64_t I = 0; I < NumCounters; ++I) {
  338. if (Line.is_at_end())
  339. return error(instrprof_error::truncated);
  340. uint64_t Count;
  341. if ((Line++)->getAsInteger(10, Count))
  342. return error(instrprof_error::malformed, "count is invalid");
  343. Record.Counts.push_back(Count);
  344. }
  345. // Check if value profile data exists and read it if so.
  346. if (Error E = readValueProfileData(Record))
  347. return error(std::move(E));
  348. return success();
  349. }
  350. template <class IntPtrT>
  351. InstrProfKind RawInstrProfReader<IntPtrT>::getProfileKind() const {
  352. return getProfileKindFromVersion(Version);
  353. }
  354. template <class IntPtrT>
  355. bool RawInstrProfReader<IntPtrT>::hasFormat(const MemoryBuffer &DataBuffer) {
  356. if (DataBuffer.getBufferSize() < sizeof(uint64_t))
  357. return false;
  358. uint64_t Magic =
  359. *reinterpret_cast<const uint64_t *>(DataBuffer.getBufferStart());
  360. return RawInstrProf::getMagic<IntPtrT>() == Magic ||
  361. sys::getSwappedBytes(RawInstrProf::getMagic<IntPtrT>()) == Magic;
  362. }
  363. template <class IntPtrT>
  364. Error RawInstrProfReader<IntPtrT>::readHeader() {
  365. if (!hasFormat(*DataBuffer))
  366. return error(instrprof_error::bad_magic);
  367. if (DataBuffer->getBufferSize() < sizeof(RawInstrProf::Header))
  368. return error(instrprof_error::bad_header);
  369. auto *Header = reinterpret_cast<const RawInstrProf::Header *>(
  370. DataBuffer->getBufferStart());
  371. ShouldSwapBytes = Header->Magic != RawInstrProf::getMagic<IntPtrT>();
  372. return readHeader(*Header);
  373. }
  374. template <class IntPtrT>
  375. Error RawInstrProfReader<IntPtrT>::readNextHeader(const char *CurrentPos) {
  376. const char *End = DataBuffer->getBufferEnd();
  377. // Skip zero padding between profiles.
  378. while (CurrentPos != End && *CurrentPos == 0)
  379. ++CurrentPos;
  380. // If there's nothing left, we're done.
  381. if (CurrentPos == End)
  382. return make_error<InstrProfError>(instrprof_error::eof);
  383. // If there isn't enough space for another header, this is probably just
  384. // garbage at the end of the file.
  385. if (CurrentPos + sizeof(RawInstrProf::Header) > End)
  386. return make_error<InstrProfError>(instrprof_error::malformed,
  387. "not enough space for another header");
  388. // The writer ensures each profile is padded to start at an aligned address.
  389. if (reinterpret_cast<size_t>(CurrentPos) % alignof(uint64_t))
  390. return make_error<InstrProfError>(instrprof_error::malformed,
  391. "insufficient padding");
  392. // The magic should have the same byte order as in the previous header.
  393. uint64_t Magic = *reinterpret_cast<const uint64_t *>(CurrentPos);
  394. if (Magic != swap(RawInstrProf::getMagic<IntPtrT>()))
  395. return make_error<InstrProfError>(instrprof_error::bad_magic);
  396. // There's another profile to read, so we need to process the header.
  397. auto *Header = reinterpret_cast<const RawInstrProf::Header *>(CurrentPos);
  398. return readHeader(*Header);
  399. }
  400. template <class IntPtrT>
  401. Error RawInstrProfReader<IntPtrT>::createSymtab(InstrProfSymtab &Symtab) {
  402. if (Error E = Symtab.create(StringRef(NamesStart, NamesEnd - NamesStart)))
  403. return error(std::move(E));
  404. for (const RawInstrProf::ProfileData<IntPtrT> *I = Data; I != DataEnd; ++I) {
  405. const IntPtrT FPtr = swap(I->FunctionPointer);
  406. if (!FPtr)
  407. continue;
  408. Symtab.mapAddress(FPtr, I->NameRef);
  409. }
  410. return success();
  411. }
  412. template <class IntPtrT>
  413. Error RawInstrProfReader<IntPtrT>::readHeader(
  414. const RawInstrProf::Header &Header) {
  415. Version = swap(Header.Version);
  416. if (GET_VERSION(Version) != RawInstrProf::Version)
  417. return error(instrprof_error::unsupported_version);
  418. if (useDebugInfoCorrelate() && !Correlator)
  419. return error(instrprof_error::missing_debug_info_for_correlation);
  420. if (!useDebugInfoCorrelate() && Correlator)
  421. return error(instrprof_error::unexpected_debug_info_for_correlation);
  422. BinaryIdsSize = swap(Header.BinaryIdsSize);
  423. if (BinaryIdsSize % sizeof(uint64_t))
  424. return error(instrprof_error::bad_header);
  425. CountersDelta = swap(Header.CountersDelta);
  426. NamesDelta = swap(Header.NamesDelta);
  427. auto NumData = swap(Header.DataSize);
  428. auto PaddingBytesBeforeCounters = swap(Header.PaddingBytesBeforeCounters);
  429. auto CountersSize = swap(Header.CountersSize) * getCounterTypeSize();
  430. auto PaddingBytesAfterCounters = swap(Header.PaddingBytesAfterCounters);
  431. auto NamesSize = swap(Header.NamesSize);
  432. ValueKindLast = swap(Header.ValueKindLast);
  433. auto DataSize = NumData * sizeof(RawInstrProf::ProfileData<IntPtrT>);
  434. auto PaddingSize = getNumPaddingBytes(NamesSize);
  435. // Profile data starts after profile header and binary ids if exist.
  436. ptrdiff_t DataOffset = sizeof(RawInstrProf::Header) + BinaryIdsSize;
  437. ptrdiff_t CountersOffset = DataOffset + DataSize + PaddingBytesBeforeCounters;
  438. ptrdiff_t NamesOffset =
  439. CountersOffset + CountersSize + PaddingBytesAfterCounters;
  440. ptrdiff_t ValueDataOffset = NamesOffset + NamesSize + PaddingSize;
  441. auto *Start = reinterpret_cast<const char *>(&Header);
  442. if (Start + ValueDataOffset > DataBuffer->getBufferEnd())
  443. return error(instrprof_error::bad_header);
  444. if (Correlator) {
  445. // These sizes in the raw file are zero because we constructed them in the
  446. // Correlator.
  447. assert(DataSize == 0 && NamesSize == 0);
  448. assert(CountersDelta == 0 && NamesDelta == 0);
  449. Data = Correlator->getDataPointer();
  450. DataEnd = Data + Correlator->getDataSize();
  451. NamesStart = Correlator->getNamesPointer();
  452. NamesEnd = NamesStart + Correlator->getNamesSize();
  453. } else {
  454. Data = reinterpret_cast<const RawInstrProf::ProfileData<IntPtrT> *>(
  455. Start + DataOffset);
  456. DataEnd = Data + NumData;
  457. NamesStart = Start + NamesOffset;
  458. NamesEnd = NamesStart + NamesSize;
  459. }
  460. // Binary ids start just after the header.
  461. BinaryIdsStart =
  462. reinterpret_cast<const uint8_t *>(&Header) + sizeof(RawInstrProf::Header);
  463. CountersStart = Start + CountersOffset;
  464. CountersEnd = CountersStart + CountersSize;
  465. ValueDataStart = reinterpret_cast<const uint8_t *>(Start + ValueDataOffset);
  466. const uint8_t *BufferEnd = (const uint8_t *)DataBuffer->getBufferEnd();
  467. if (BinaryIdsStart + BinaryIdsSize > BufferEnd)
  468. return error(instrprof_error::bad_header);
  469. std::unique_ptr<InstrProfSymtab> NewSymtab = std::make_unique<InstrProfSymtab>();
  470. if (Error E = createSymtab(*NewSymtab))
  471. return E;
  472. Symtab = std::move(NewSymtab);
  473. return success();
  474. }
  475. template <class IntPtrT>
  476. Error RawInstrProfReader<IntPtrT>::readName(NamedInstrProfRecord &Record) {
  477. Record.Name = getName(Data->NameRef);
  478. return success();
  479. }
  480. template <class IntPtrT>
  481. Error RawInstrProfReader<IntPtrT>::readFuncHash(NamedInstrProfRecord &Record) {
  482. Record.Hash = swap(Data->FuncHash);
  483. return success();
  484. }
  485. template <class IntPtrT>
  486. Error RawInstrProfReader<IntPtrT>::readRawCounts(
  487. InstrProfRecord &Record) {
  488. uint32_t NumCounters = swap(Data->NumCounters);
  489. if (NumCounters == 0)
  490. return error(instrprof_error::malformed, "number of counters is zero");
  491. ptrdiff_t CounterBaseOffset = swap(Data->CounterPtr) - CountersDelta;
  492. if (CounterBaseOffset < 0)
  493. return error(
  494. instrprof_error::malformed,
  495. ("counter offset " + Twine(CounterBaseOffset) + " is negative").str());
  496. if (CounterBaseOffset >= CountersEnd - CountersStart)
  497. return error(instrprof_error::malformed,
  498. ("counter offset " + Twine(CounterBaseOffset) +
  499. " is greater than the maximum counter offset " +
  500. Twine(CountersEnd - CountersStart - 1))
  501. .str());
  502. uint64_t MaxNumCounters =
  503. (CountersEnd - (CountersStart + CounterBaseOffset)) /
  504. getCounterTypeSize();
  505. if (NumCounters > MaxNumCounters)
  506. return error(instrprof_error::malformed,
  507. ("number of counters " + Twine(NumCounters) +
  508. " is greater than the maximum number of counters " +
  509. Twine(MaxNumCounters))
  510. .str());
  511. Record.Counts.clear();
  512. Record.Counts.reserve(NumCounters);
  513. for (uint32_t I = 0; I < NumCounters; I++) {
  514. const char *Ptr =
  515. CountersStart + CounterBaseOffset + I * getCounterTypeSize();
  516. if (hasSingleByteCoverage()) {
  517. // A value of zero signifies the block is covered.
  518. Record.Counts.push_back(*Ptr == 0 ? 1 : 0);
  519. } else {
  520. const auto *CounterValue = reinterpret_cast<const uint64_t *>(Ptr);
  521. Record.Counts.push_back(swap(*CounterValue));
  522. }
  523. }
  524. return success();
  525. }
  526. template <class IntPtrT>
  527. Error RawInstrProfReader<IntPtrT>::readValueProfilingData(
  528. InstrProfRecord &Record) {
  529. Record.clearValueData();
  530. CurValueDataSize = 0;
  531. // Need to match the logic in value profile dumper code in compiler-rt:
  532. uint32_t NumValueKinds = 0;
  533. for (uint32_t I = 0; I < IPVK_Last + 1; I++)
  534. NumValueKinds += (Data->NumValueSites[I] != 0);
  535. if (!NumValueKinds)
  536. return success();
  537. Expected<std::unique_ptr<ValueProfData>> VDataPtrOrErr =
  538. ValueProfData::getValueProfData(
  539. ValueDataStart, (const unsigned char *)DataBuffer->getBufferEnd(),
  540. getDataEndianness());
  541. if (Error E = VDataPtrOrErr.takeError())
  542. return E;
  543. // Note that besides deserialization, this also performs the conversion for
  544. // indirect call targets. The function pointers from the raw profile are
  545. // remapped into function name hashes.
  546. VDataPtrOrErr.get()->deserializeTo(Record, Symtab.get());
  547. CurValueDataSize = VDataPtrOrErr.get()->getSize();
  548. return success();
  549. }
  550. template <class IntPtrT>
  551. Error RawInstrProfReader<IntPtrT>::readNextRecord(NamedInstrProfRecord &Record) {
  552. // Keep reading profiles that consist of only headers and no profile data and
  553. // counters.
  554. while (atEnd())
  555. // At this point, ValueDataStart field points to the next header.
  556. if (Error E = readNextHeader(getNextHeaderPos()))
  557. return error(std::move(E));
  558. // Read name ad set it in Record.
  559. if (Error E = readName(Record))
  560. return error(std::move(E));
  561. // Read FuncHash and set it in Record.
  562. if (Error E = readFuncHash(Record))
  563. return error(std::move(E));
  564. // Read raw counts and set Record.
  565. if (Error E = readRawCounts(Record))
  566. return error(std::move(E));
  567. // Read value data and set Record.
  568. if (Error E = readValueProfilingData(Record))
  569. return error(std::move(E));
  570. // Iterate.
  571. advanceData();
  572. return success();
  573. }
  574. template <class IntPtrT>
  575. Error RawInstrProfReader<IntPtrT>::readBinaryIds(
  576. std::vector<llvm::object::BuildID> &BinaryIds) {
  577. return readBinaryIdsInternal(*DataBuffer, BinaryIdsSize, BinaryIdsStart,
  578. BinaryIds, getDataEndianness());
  579. }
  580. template <class IntPtrT>
  581. Error RawInstrProfReader<IntPtrT>::printBinaryIds(raw_ostream &OS) {
  582. return printBinaryIdsInternal(OS, *DataBuffer, BinaryIdsSize, BinaryIdsStart,
  583. getDataEndianness());
  584. }
  585. namespace llvm {
  586. template class RawInstrProfReader<uint32_t>;
  587. template class RawInstrProfReader<uint64_t>;
  588. } // end namespace llvm
  589. InstrProfLookupTrait::hash_value_type
  590. InstrProfLookupTrait::ComputeHash(StringRef K) {
  591. return IndexedInstrProf::ComputeHash(HashType, K);
  592. }
  593. using data_type = InstrProfLookupTrait::data_type;
  594. using offset_type = InstrProfLookupTrait::offset_type;
  595. bool InstrProfLookupTrait::readValueProfilingData(
  596. const unsigned char *&D, const unsigned char *const End) {
  597. Expected<std::unique_ptr<ValueProfData>> VDataPtrOrErr =
  598. ValueProfData::getValueProfData(D, End, ValueProfDataEndianness);
  599. if (VDataPtrOrErr.takeError())
  600. return false;
  601. VDataPtrOrErr.get()->deserializeTo(DataBuffer.back(), nullptr);
  602. D += VDataPtrOrErr.get()->TotalSize;
  603. return true;
  604. }
  605. data_type InstrProfLookupTrait::ReadData(StringRef K, const unsigned char *D,
  606. offset_type N) {
  607. using namespace support;
  608. // Check if the data is corrupt. If so, don't try to read it.
  609. if (N % sizeof(uint64_t))
  610. return data_type();
  611. DataBuffer.clear();
  612. std::vector<uint64_t> CounterBuffer;
  613. const unsigned char *End = D + N;
  614. while (D < End) {
  615. // Read hash.
  616. if (D + sizeof(uint64_t) >= End)
  617. return data_type();
  618. uint64_t Hash = endian::readNext<uint64_t, little, unaligned>(D);
  619. // Initialize number of counters for GET_VERSION(FormatVersion) == 1.
  620. uint64_t CountsSize = N / sizeof(uint64_t) - 1;
  621. // If format version is different then read the number of counters.
  622. if (GET_VERSION(FormatVersion) != IndexedInstrProf::ProfVersion::Version1) {
  623. if (D + sizeof(uint64_t) > End)
  624. return data_type();
  625. CountsSize = endian::readNext<uint64_t, little, unaligned>(D);
  626. }
  627. // Read counter values.
  628. if (D + CountsSize * sizeof(uint64_t) > End)
  629. return data_type();
  630. CounterBuffer.clear();
  631. CounterBuffer.reserve(CountsSize);
  632. for (uint64_t J = 0; J < CountsSize; ++J)
  633. CounterBuffer.push_back(endian::readNext<uint64_t, little, unaligned>(D));
  634. DataBuffer.emplace_back(K, Hash, std::move(CounterBuffer));
  635. // Read value profiling data.
  636. if (GET_VERSION(FormatVersion) > IndexedInstrProf::ProfVersion::Version2 &&
  637. !readValueProfilingData(D, End)) {
  638. DataBuffer.clear();
  639. return data_type();
  640. }
  641. }
  642. return DataBuffer;
  643. }
  644. template <typename HashTableImpl>
  645. Error InstrProfReaderIndex<HashTableImpl>::getRecords(
  646. StringRef FuncName, ArrayRef<NamedInstrProfRecord> &Data) {
  647. auto Iter = HashTable->find(FuncName);
  648. if (Iter == HashTable->end())
  649. return make_error<InstrProfError>(instrprof_error::unknown_function);
  650. Data = (*Iter);
  651. if (Data.empty())
  652. return make_error<InstrProfError>(instrprof_error::malformed,
  653. "profile data is empty");
  654. return Error::success();
  655. }
  656. template <typename HashTableImpl>
  657. Error InstrProfReaderIndex<HashTableImpl>::getRecords(
  658. ArrayRef<NamedInstrProfRecord> &Data) {
  659. if (atEnd())
  660. return make_error<InstrProfError>(instrprof_error::eof);
  661. Data = *RecordIterator;
  662. if (Data.empty())
  663. return make_error<InstrProfError>(instrprof_error::malformed,
  664. "profile data is empty");
  665. return Error::success();
  666. }
  667. template <typename HashTableImpl>
  668. InstrProfReaderIndex<HashTableImpl>::InstrProfReaderIndex(
  669. const unsigned char *Buckets, const unsigned char *const Payload,
  670. const unsigned char *const Base, IndexedInstrProf::HashT HashType,
  671. uint64_t Version) {
  672. FormatVersion = Version;
  673. HashTable.reset(HashTableImpl::Create(
  674. Buckets, Payload, Base,
  675. typename HashTableImpl::InfoType(HashType, Version)));
  676. RecordIterator = HashTable->data_begin();
  677. }
  678. template <typename HashTableImpl>
  679. InstrProfKind InstrProfReaderIndex<HashTableImpl>::getProfileKind() const {
  680. return getProfileKindFromVersion(FormatVersion);
  681. }
  682. namespace {
  683. /// A remapper that does not apply any remappings.
  684. class InstrProfReaderNullRemapper : public InstrProfReaderRemapper {
  685. InstrProfReaderIndexBase &Underlying;
  686. public:
  687. InstrProfReaderNullRemapper(InstrProfReaderIndexBase &Underlying)
  688. : Underlying(Underlying) {}
  689. Error getRecords(StringRef FuncName,
  690. ArrayRef<NamedInstrProfRecord> &Data) override {
  691. return Underlying.getRecords(FuncName, Data);
  692. }
  693. };
  694. } // namespace
  695. /// A remapper that applies remappings based on a symbol remapping file.
  696. template <typename HashTableImpl>
  697. class llvm::InstrProfReaderItaniumRemapper
  698. : public InstrProfReaderRemapper {
  699. public:
  700. InstrProfReaderItaniumRemapper(
  701. std::unique_ptr<MemoryBuffer> RemapBuffer,
  702. InstrProfReaderIndex<HashTableImpl> &Underlying)
  703. : RemapBuffer(std::move(RemapBuffer)), Underlying(Underlying) {
  704. }
  705. /// Extract the original function name from a PGO function name.
  706. static StringRef extractName(StringRef Name) {
  707. // We can have multiple :-separated pieces; there can be pieces both
  708. // before and after the mangled name. Find the first part that starts
  709. // with '_Z'; we'll assume that's the mangled name we want.
  710. std::pair<StringRef, StringRef> Parts = {StringRef(), Name};
  711. while (true) {
  712. Parts = Parts.second.split(':');
  713. if (Parts.first.startswith("_Z"))
  714. return Parts.first;
  715. if (Parts.second.empty())
  716. return Name;
  717. }
  718. }
  719. /// Given a mangled name extracted from a PGO function name, and a new
  720. /// form for that mangled name, reconstitute the name.
  721. static void reconstituteName(StringRef OrigName, StringRef ExtractedName,
  722. StringRef Replacement,
  723. SmallVectorImpl<char> &Out) {
  724. Out.reserve(OrigName.size() + Replacement.size() - ExtractedName.size());
  725. Out.insert(Out.end(), OrigName.begin(), ExtractedName.begin());
  726. Out.insert(Out.end(), Replacement.begin(), Replacement.end());
  727. Out.insert(Out.end(), ExtractedName.end(), OrigName.end());
  728. }
  729. Error populateRemappings() override {
  730. if (Error E = Remappings.read(*RemapBuffer))
  731. return E;
  732. for (StringRef Name : Underlying.HashTable->keys()) {
  733. StringRef RealName = extractName(Name);
  734. if (auto Key = Remappings.insert(RealName)) {
  735. // FIXME: We could theoretically map the same equivalence class to
  736. // multiple names in the profile data. If that happens, we should
  737. // return NamedInstrProfRecords from all of them.
  738. MappedNames.insert({Key, RealName});
  739. }
  740. }
  741. return Error::success();
  742. }
  743. Error getRecords(StringRef FuncName,
  744. ArrayRef<NamedInstrProfRecord> &Data) override {
  745. StringRef RealName = extractName(FuncName);
  746. if (auto Key = Remappings.lookup(RealName)) {
  747. StringRef Remapped = MappedNames.lookup(Key);
  748. if (!Remapped.empty()) {
  749. if (RealName.begin() == FuncName.begin() &&
  750. RealName.end() == FuncName.end())
  751. FuncName = Remapped;
  752. else {
  753. // Try rebuilding the name from the given remapping.
  754. SmallString<256> Reconstituted;
  755. reconstituteName(FuncName, RealName, Remapped, Reconstituted);
  756. Error E = Underlying.getRecords(Reconstituted, Data);
  757. if (!E)
  758. return E;
  759. // If we failed because the name doesn't exist, fall back to asking
  760. // about the original name.
  761. if (Error Unhandled = handleErrors(
  762. std::move(E), [](std::unique_ptr<InstrProfError> Err) {
  763. return Err->get() == instrprof_error::unknown_function
  764. ? Error::success()
  765. : Error(std::move(Err));
  766. }))
  767. return Unhandled;
  768. }
  769. }
  770. }
  771. return Underlying.getRecords(FuncName, Data);
  772. }
  773. private:
  774. /// The memory buffer containing the remapping configuration. Remappings
  775. /// holds pointers into this buffer.
  776. std::unique_ptr<MemoryBuffer> RemapBuffer;
  777. /// The mangling remapper.
  778. SymbolRemappingReader Remappings;
  779. /// Mapping from mangled name keys to the name used for the key in the
  780. /// profile data.
  781. /// FIXME: Can we store a location within the on-disk hash table instead of
  782. /// redoing lookup?
  783. DenseMap<SymbolRemappingReader::Key, StringRef> MappedNames;
  784. /// The real profile data reader.
  785. InstrProfReaderIndex<HashTableImpl> &Underlying;
  786. };
  787. bool IndexedInstrProfReader::hasFormat(const MemoryBuffer &DataBuffer) {
  788. using namespace support;
  789. if (DataBuffer.getBufferSize() < 8)
  790. return false;
  791. uint64_t Magic =
  792. endian::read<uint64_t, little, aligned>(DataBuffer.getBufferStart());
  793. // Verify that it's magical.
  794. return Magic == IndexedInstrProf::Magic;
  795. }
  796. const unsigned char *
  797. IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version,
  798. const unsigned char *Cur, bool UseCS) {
  799. using namespace IndexedInstrProf;
  800. using namespace support;
  801. if (Version >= IndexedInstrProf::Version4) {
  802. const IndexedInstrProf::Summary *SummaryInLE =
  803. reinterpret_cast<const IndexedInstrProf::Summary *>(Cur);
  804. uint64_t NFields =
  805. endian::byte_swap<uint64_t, little>(SummaryInLE->NumSummaryFields);
  806. uint64_t NEntries =
  807. endian::byte_swap<uint64_t, little>(SummaryInLE->NumCutoffEntries);
  808. uint32_t SummarySize =
  809. IndexedInstrProf::Summary::getSize(NFields, NEntries);
  810. std::unique_ptr<IndexedInstrProf::Summary> SummaryData =
  811. IndexedInstrProf::allocSummary(SummarySize);
  812. const uint64_t *Src = reinterpret_cast<const uint64_t *>(SummaryInLE);
  813. uint64_t *Dst = reinterpret_cast<uint64_t *>(SummaryData.get());
  814. for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++)
  815. Dst[I] = endian::byte_swap<uint64_t, little>(Src[I]);
  816. SummaryEntryVector DetailedSummary;
  817. for (unsigned I = 0; I < SummaryData->NumCutoffEntries; I++) {
  818. const IndexedInstrProf::Summary::Entry &Ent = SummaryData->getEntry(I);
  819. DetailedSummary.emplace_back((uint32_t)Ent.Cutoff, Ent.MinBlockCount,
  820. Ent.NumBlocks);
  821. }
  822. std::unique_ptr<llvm::ProfileSummary> &Summary =
  823. UseCS ? this->CS_Summary : this->Summary;
  824. // initialize InstrProfSummary using the SummaryData from disk.
  825. Summary = std::make_unique<ProfileSummary>(
  826. UseCS ? ProfileSummary::PSK_CSInstr : ProfileSummary::PSK_Instr,
  827. DetailedSummary, SummaryData->get(Summary::TotalBlockCount),
  828. SummaryData->get(Summary::MaxBlockCount),
  829. SummaryData->get(Summary::MaxInternalBlockCount),
  830. SummaryData->get(Summary::MaxFunctionCount),
  831. SummaryData->get(Summary::TotalNumBlocks),
  832. SummaryData->get(Summary::TotalNumFunctions));
  833. return Cur + SummarySize;
  834. } else {
  835. // The older versions do not support a profile summary. This just computes
  836. // an empty summary, which will not result in accurate hot/cold detection.
  837. // We would need to call addRecord for all NamedInstrProfRecords to get the
  838. // correct summary. However, this version is old (prior to early 2016) and
  839. // has not been supporting an accurate summary for several years.
  840. InstrProfSummaryBuilder Builder(ProfileSummaryBuilder::DefaultCutoffs);
  841. Summary = Builder.getSummary();
  842. return Cur;
  843. }
  844. }
  845. Error IndexedInstrProfReader::readHeader() {
  846. using namespace support;
  847. const unsigned char *Start =
  848. (const unsigned char *)DataBuffer->getBufferStart();
  849. const unsigned char *Cur = Start;
  850. if ((const unsigned char *)DataBuffer->getBufferEnd() - Cur < 24)
  851. return error(instrprof_error::truncated);
  852. auto HeaderOr = IndexedInstrProf::Header::readFromBuffer(Start);
  853. if (!HeaderOr)
  854. return HeaderOr.takeError();
  855. const IndexedInstrProf::Header *Header = &HeaderOr.get();
  856. Cur += Header->size();
  857. Cur = readSummary((IndexedInstrProf::ProfVersion)Header->formatVersion(), Cur,
  858. /* UseCS */ false);
  859. if (Header->formatVersion() & VARIANT_MASK_CSIR_PROF)
  860. Cur =
  861. readSummary((IndexedInstrProf::ProfVersion)Header->formatVersion(), Cur,
  862. /* UseCS */ true);
  863. // Read the hash type and start offset.
  864. IndexedInstrProf::HashT HashType = static_cast<IndexedInstrProf::HashT>(
  865. endian::byte_swap<uint64_t, little>(Header->HashType));
  866. if (HashType > IndexedInstrProf::HashT::Last)
  867. return error(instrprof_error::unsupported_hash_type);
  868. uint64_t HashOffset = endian::byte_swap<uint64_t, little>(Header->HashOffset);
  869. // The hash table with profile counts comes next.
  870. auto IndexPtr = std::make_unique<InstrProfReaderIndex<OnDiskHashTableImplV3>>(
  871. Start + HashOffset, Cur, Start, HashType, Header->formatVersion());
  872. // The MemProfOffset field in the header is only valid when the format
  873. // version is higher than 8 (when it was introduced).
  874. if (GET_VERSION(Header->formatVersion()) >= 8 &&
  875. Header->formatVersion() & VARIANT_MASK_MEMPROF) {
  876. uint64_t MemProfOffset =
  877. endian::byte_swap<uint64_t, little>(Header->MemProfOffset);
  878. const unsigned char *Ptr = Start + MemProfOffset;
  879. // The value returned from RecordTableGenerator.Emit.
  880. const uint64_t RecordTableOffset =
  881. support::endian::readNext<uint64_t, little, unaligned>(Ptr);
  882. // The offset in the stream right before invoking
  883. // FrameTableGenerator.Emit.
  884. const uint64_t FramePayloadOffset =
  885. support::endian::readNext<uint64_t, little, unaligned>(Ptr);
  886. // The value returned from FrameTableGenerator.Emit.
  887. const uint64_t FrameTableOffset =
  888. support::endian::readNext<uint64_t, little, unaligned>(Ptr);
  889. // Read the schema.
  890. auto SchemaOr = memprof::readMemProfSchema(Ptr);
  891. if (!SchemaOr)
  892. return SchemaOr.takeError();
  893. Schema = SchemaOr.get();
  894. // Now initialize the table reader with a pointer into data buffer.
  895. MemProfRecordTable.reset(MemProfRecordHashTable::Create(
  896. /*Buckets=*/Start + RecordTableOffset,
  897. /*Payload=*/Ptr,
  898. /*Base=*/Start, memprof::RecordLookupTrait(Schema)));
  899. // Initialize the frame table reader with the payload and bucket offsets.
  900. MemProfFrameTable.reset(MemProfFrameHashTable::Create(
  901. /*Buckets=*/Start + FrameTableOffset,
  902. /*Payload=*/Start + FramePayloadOffset,
  903. /*Base=*/Start, memprof::FrameLookupTrait()));
  904. }
  905. // BinaryIdOffset field in the header is only valid when the format version
  906. // is higher than 9 (when it was introduced).
  907. if (GET_VERSION(Header->formatVersion()) >= 9) {
  908. uint64_t BinaryIdOffset =
  909. endian::byte_swap<uint64_t, little>(Header->BinaryIdOffset);
  910. const unsigned char *Ptr = Start + BinaryIdOffset;
  911. // Read binary ids size.
  912. BinaryIdsSize = support::endian::readNext<uint64_t, little, unaligned>(Ptr);
  913. if (BinaryIdsSize % sizeof(uint64_t))
  914. return error(instrprof_error::bad_header);
  915. // Set the binary ids start.
  916. BinaryIdsStart = Ptr;
  917. if (BinaryIdsStart > (const unsigned char *)DataBuffer->getBufferEnd())
  918. return make_error<InstrProfError>(instrprof_error::malformed,
  919. "corrupted binary ids");
  920. }
  921. // Load the remapping table now if requested.
  922. if (RemappingBuffer) {
  923. Remapper =
  924. std::make_unique<InstrProfReaderItaniumRemapper<OnDiskHashTableImplV3>>(
  925. std::move(RemappingBuffer), *IndexPtr);
  926. if (Error E = Remapper->populateRemappings())
  927. return E;
  928. } else {
  929. Remapper = std::make_unique<InstrProfReaderNullRemapper>(*IndexPtr);
  930. }
  931. Index = std::move(IndexPtr);
  932. return success();
  933. }
  934. InstrProfSymtab &IndexedInstrProfReader::getSymtab() {
  935. if (Symtab)
  936. return *Symtab;
  937. std::unique_ptr<InstrProfSymtab> NewSymtab = std::make_unique<InstrProfSymtab>();
  938. if (Error E = Index->populateSymtab(*NewSymtab)) {
  939. consumeError(error(InstrProfError::take(std::move(E))));
  940. }
  941. Symtab = std::move(NewSymtab);
  942. return *Symtab;
  943. }
  944. Expected<InstrProfRecord> IndexedInstrProfReader::getInstrProfRecord(
  945. StringRef FuncName, uint64_t FuncHash, uint64_t *MismatchedFuncSum) {
  946. ArrayRef<NamedInstrProfRecord> Data;
  947. uint64_t FuncSum = 0;
  948. Error Err = Remapper->getRecords(FuncName, Data);
  949. if (Err)
  950. return std::move(Err);
  951. // Found it. Look for counters with the right hash.
  952. // A flag to indicate if the records are from the same type
  953. // of profile (i.e cs vs nocs).
  954. bool CSBitMatch = false;
  955. auto getFuncSum = [](const std::vector<uint64_t> &Counts) {
  956. uint64_t ValueSum = 0;
  957. for (uint64_t CountValue : Counts) {
  958. if (CountValue == (uint64_t)-1)
  959. continue;
  960. // Handle overflow -- if that happens, return max.
  961. if (std::numeric_limits<uint64_t>::max() - CountValue <= ValueSum)
  962. return std::numeric_limits<uint64_t>::max();
  963. ValueSum += CountValue;
  964. }
  965. return ValueSum;
  966. };
  967. for (const NamedInstrProfRecord &I : Data) {
  968. // Check for a match and fill the vector if there is one.
  969. if (I.Hash == FuncHash)
  970. return std::move(I);
  971. if (NamedInstrProfRecord::hasCSFlagInHash(I.Hash) ==
  972. NamedInstrProfRecord::hasCSFlagInHash(FuncHash)) {
  973. CSBitMatch = true;
  974. if (MismatchedFuncSum == nullptr)
  975. continue;
  976. FuncSum = std::max(FuncSum, getFuncSum(I.Counts));
  977. }
  978. }
  979. if (CSBitMatch) {
  980. if (MismatchedFuncSum != nullptr)
  981. *MismatchedFuncSum = FuncSum;
  982. return error(instrprof_error::hash_mismatch);
  983. }
  984. return error(instrprof_error::unknown_function);
  985. }
  986. Expected<memprof::MemProfRecord>
  987. IndexedInstrProfReader::getMemProfRecord(const uint64_t FuncNameHash) {
  988. // TODO: Add memprof specific errors.
  989. if (MemProfRecordTable == nullptr)
  990. return make_error<InstrProfError>(instrprof_error::invalid_prof,
  991. "no memprof data available in profile");
  992. auto Iter = MemProfRecordTable->find(FuncNameHash);
  993. if (Iter == MemProfRecordTable->end())
  994. return make_error<InstrProfError>(
  995. instrprof_error::unknown_function,
  996. "memprof record not found for function hash " + Twine(FuncNameHash));
  997. // Setup a callback to convert from frame ids to frame using the on-disk
  998. // FrameData hash table.
  999. memprof::FrameId LastUnmappedFrameId = 0;
  1000. bool HasFrameMappingError = false;
  1001. auto IdToFrameCallback = [&](const memprof::FrameId Id) {
  1002. auto FrIter = MemProfFrameTable->find(Id);
  1003. if (FrIter == MemProfFrameTable->end()) {
  1004. LastUnmappedFrameId = Id;
  1005. HasFrameMappingError = true;
  1006. return memprof::Frame(0, 0, 0, false);
  1007. }
  1008. return *FrIter;
  1009. };
  1010. memprof::MemProfRecord Record(*Iter, IdToFrameCallback);
  1011. // Check that all frame ids were successfully converted to frames.
  1012. if (HasFrameMappingError) {
  1013. return make_error<InstrProfError>(instrprof_error::hash_mismatch,
  1014. "memprof frame not found for frame id " +
  1015. Twine(LastUnmappedFrameId));
  1016. }
  1017. return Record;
  1018. }
  1019. Error IndexedInstrProfReader::getFunctionCounts(StringRef FuncName,
  1020. uint64_t FuncHash,
  1021. std::vector<uint64_t> &Counts) {
  1022. Expected<InstrProfRecord> Record = getInstrProfRecord(FuncName, FuncHash);
  1023. if (Error E = Record.takeError())
  1024. return error(std::move(E));
  1025. Counts = Record.get().Counts;
  1026. return success();
  1027. }
  1028. Error IndexedInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) {
  1029. ArrayRef<NamedInstrProfRecord> Data;
  1030. Error E = Index->getRecords(Data);
  1031. if (E)
  1032. return error(std::move(E));
  1033. Record = Data[RecordIndex++];
  1034. if (RecordIndex >= Data.size()) {
  1035. Index->advanceToNextKey();
  1036. RecordIndex = 0;
  1037. }
  1038. return success();
  1039. }
  1040. Error IndexedInstrProfReader::readBinaryIds(
  1041. std::vector<llvm::object::BuildID> &BinaryIds) {
  1042. return readBinaryIdsInternal(*DataBuffer, BinaryIdsSize, BinaryIdsStart,
  1043. BinaryIds, llvm::support::little);
  1044. }
  1045. Error IndexedInstrProfReader::printBinaryIds(raw_ostream &OS) {
  1046. return printBinaryIdsInternal(OS, *DataBuffer, BinaryIdsSize, BinaryIdsStart,
  1047. llvm::support::little);
  1048. }
  1049. void InstrProfReader::accumulateCounts(CountSumOrPercent &Sum, bool IsCS) {
  1050. uint64_t NumFuncs = 0;
  1051. for (const auto &Func : *this) {
  1052. if (isIRLevelProfile()) {
  1053. bool FuncIsCS = NamedInstrProfRecord::hasCSFlagInHash(Func.Hash);
  1054. if (FuncIsCS != IsCS)
  1055. continue;
  1056. }
  1057. Func.accumulateCounts(Sum);
  1058. ++NumFuncs;
  1059. }
  1060. Sum.NumEntries = NumFuncs;
  1061. }