InstrProfilingFile.c 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274
  1. /*===- InstrProfilingFile.c - Write instrumentation to a file -------------===*\
  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. #if !defined(__Fuchsia__)
  9. #include <assert.h>
  10. #include <errno.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #ifdef _MSC_VER
  15. /* For _alloca. */
  16. #include <malloc.h>
  17. #endif
  18. #if defined(_WIN32)
  19. #include "WindowsMMap.h"
  20. /* For _chsize_s */
  21. #include <io.h>
  22. #include <process.h>
  23. #else
  24. #include <sys/file.h>
  25. #include <sys/mman.h>
  26. #include <unistd.h>
  27. #if defined(__linux__)
  28. #include <sys/types.h>
  29. #endif
  30. #endif
  31. #include "InstrProfiling.h"
  32. #include "InstrProfilingInternal.h"
  33. #include "InstrProfilingPort.h"
  34. #include "InstrProfilingUtil.h"
  35. /* From where is profile name specified.
  36. * The order the enumerators define their
  37. * precedence. Re-order them may lead to
  38. * runtime behavior change. */
  39. typedef enum ProfileNameSpecifier {
  40. PNS_unknown = 0,
  41. PNS_default,
  42. PNS_command_line,
  43. PNS_environment,
  44. PNS_runtime_api
  45. } ProfileNameSpecifier;
  46. static const char *getPNSStr(ProfileNameSpecifier PNS) {
  47. switch (PNS) {
  48. case PNS_default:
  49. return "default setting";
  50. case PNS_command_line:
  51. return "command line";
  52. case PNS_environment:
  53. return "environment variable";
  54. case PNS_runtime_api:
  55. return "runtime API";
  56. default:
  57. return "Unknown";
  58. }
  59. }
  60. #define MAX_PID_SIZE 16
  61. /* Data structure holding the result of parsed filename pattern. */
  62. typedef struct lprofFilename {
  63. /* File name string possibly with %p or %h specifiers. */
  64. const char *FilenamePat;
  65. /* A flag indicating if FilenamePat's memory is allocated
  66. * by runtime. */
  67. unsigned OwnsFilenamePat;
  68. const char *ProfilePathPrefix;
  69. char PidChars[MAX_PID_SIZE];
  70. char *TmpDir;
  71. char Hostname[COMPILER_RT_MAX_HOSTLEN];
  72. unsigned NumPids;
  73. unsigned NumHosts;
  74. /* When in-process merging is enabled, this parameter specifies
  75. * the total number of profile data files shared by all the processes
  76. * spawned from the same binary. By default the value is 1. If merging
  77. * is not enabled, its value should be 0. This parameter is specified
  78. * by the %[0-9]m specifier. For instance %2m enables merging using
  79. * 2 profile data files. %1m is equivalent to %m. Also %m specifier
  80. * can only appear once at the end of the name pattern. */
  81. unsigned MergePoolSize;
  82. ProfileNameSpecifier PNS;
  83. } lprofFilename;
  84. static lprofFilename lprofCurFilename = {0, 0, 0, {0}, NULL,
  85. {0}, 0, 0, 0, PNS_unknown};
  86. static int ProfileMergeRequested = 0;
  87. static int getProfileFileSizeForMerging(FILE *ProfileFile,
  88. uint64_t *ProfileFileSize);
  89. #if defined(__APPLE__)
  90. static const int ContinuousModeSupported = 1;
  91. static const int UseBiasVar = 0;
  92. static const char *FileOpenMode = "a+b";
  93. static void *BiasAddr = NULL;
  94. static void *BiasDefaultAddr = NULL;
  95. static int mmapForContinuousMode(uint64_t CurrentFileOffset, FILE *File) {
  96. /* Get the sizes of various profile data sections. Taken from
  97. * __llvm_profile_get_size_for_buffer(). */
  98. const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
  99. const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
  100. const char *CountersBegin = __llvm_profile_begin_counters();
  101. const char *CountersEnd = __llvm_profile_end_counters();
  102. const char *BitmapBegin = __llvm_profile_begin_bitmap();
  103. const char *BitmapEnd = __llvm_profile_end_bitmap();
  104. const char *NamesBegin = __llvm_profile_begin_names();
  105. const char *NamesEnd = __llvm_profile_end_names();
  106. const uint64_t NamesSize = (NamesEnd - NamesBegin) * sizeof(char);
  107. uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd);
  108. uint64_t CountersSize =
  109. __llvm_profile_get_counters_size(CountersBegin, CountersEnd);
  110. uint64_t NumBitmapBytes =
  111. __llvm_profile_get_num_bitmap_bytes(BitmapBegin, BitmapEnd);
  112. /* Check that the counter, bitmap, and data sections in this image are
  113. * page-aligned. */
  114. unsigned PageSize = getpagesize();
  115. if ((intptr_t)CountersBegin % PageSize != 0) {
  116. PROF_ERR("Counters section not page-aligned (start = %p, pagesz = %u).\n",
  117. CountersBegin, PageSize);
  118. return 1;
  119. }
  120. if ((intptr_t)BitmapBegin % PageSize != 0) {
  121. PROF_ERR("Bitmap section not page-aligned (start = %p, pagesz = %u).\n",
  122. BitmapBegin, PageSize);
  123. return 1;
  124. }
  125. if ((intptr_t)DataBegin % PageSize != 0) {
  126. PROF_ERR("Data section not page-aligned (start = %p, pagesz = %u).\n",
  127. DataBegin, PageSize);
  128. return 1;
  129. }
  130. int Fileno = fileno(File);
  131. /* Determine how much padding is needed before/after the counters and
  132. * after the names. */
  133. uint64_t PaddingBytesBeforeCounters, PaddingBytesAfterCounters,
  134. PaddingBytesAfterNames, PaddingBytesAfterBitmapBytes;
  135. __llvm_profile_get_padding_sizes_for_counters(
  136. DataSize, CountersSize, NumBitmapBytes, NamesSize,
  137. &PaddingBytesBeforeCounters, &PaddingBytesAfterCounters,
  138. &PaddingBytesAfterBitmapBytes, &PaddingBytesAfterNames);
  139. uint64_t PageAlignedCountersLength = CountersSize + PaddingBytesAfterCounters;
  140. uint64_t FileOffsetToCounters = CurrentFileOffset +
  141. sizeof(__llvm_profile_header) + DataSize +
  142. PaddingBytesBeforeCounters;
  143. void *CounterMmap = mmap((void *)CountersBegin, PageAlignedCountersLength,
  144. PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED,
  145. Fileno, FileOffsetToCounters);
  146. if (CounterMmap != CountersBegin) {
  147. PROF_ERR(
  148. "Continuous counter sync mode is enabled, but mmap() failed (%s).\n"
  149. " - CountersBegin: %p\n"
  150. " - PageAlignedCountersLength: %" PRIu64 "\n"
  151. " - Fileno: %d\n"
  152. " - FileOffsetToCounters: %" PRIu64 "\n",
  153. strerror(errno), CountersBegin, PageAlignedCountersLength, Fileno,
  154. FileOffsetToCounters);
  155. return 1;
  156. }
  157. /* Also mmap MCDC bitmap bytes. If there aren't any bitmap bytes, mmap()
  158. * will fail with EINVAL. */
  159. if (NumBitmapBytes == 0)
  160. return 0;
  161. uint64_t PageAlignedBitmapLength =
  162. NumBitmapBytes + PaddingBytesAfterBitmapBytes;
  163. uint64_t FileOffsetToBitmap =
  164. CurrentFileOffset + sizeof(__llvm_profile_header) + DataSize +
  165. PaddingBytesBeforeCounters + CountersSize + PaddingBytesAfterCounters;
  166. void *BitmapMmap =
  167. mmap((void *)BitmapBegin, PageAlignedBitmapLength, PROT_READ | PROT_WRITE,
  168. MAP_FIXED | MAP_SHARED, Fileno, FileOffsetToBitmap);
  169. if (BitmapMmap != BitmapBegin) {
  170. PROF_ERR(
  171. "Continuous counter sync mode is enabled, but mmap() failed (%s).\n"
  172. " - BitmapBegin: %p\n"
  173. " - PageAlignedBitmapLength: %" PRIu64 "\n"
  174. " - Fileno: %d\n"
  175. " - FileOffsetToBitmap: %" PRIu64 "\n",
  176. strerror(errno), BitmapBegin, PageAlignedBitmapLength, Fileno,
  177. FileOffsetToBitmap);
  178. return 1;
  179. }
  180. return 0;
  181. }
  182. #elif defined(__ELF__) || defined(_WIN32)
  183. #define INSTR_PROF_PROFILE_COUNTER_BIAS_DEFAULT_VAR \
  184. INSTR_PROF_CONCAT(INSTR_PROF_PROFILE_COUNTER_BIAS_VAR, _default)
  185. COMPILER_RT_VISIBILITY intptr_t INSTR_PROF_PROFILE_COUNTER_BIAS_DEFAULT_VAR = 0;
  186. /* This variable is a weak external reference which could be used to detect
  187. * whether or not the compiler defined this symbol. */
  188. #if defined(_MSC_VER)
  189. COMPILER_RT_VISIBILITY extern intptr_t INSTR_PROF_PROFILE_COUNTER_BIAS_VAR;
  190. #if defined(_M_IX86) || defined(__i386__)
  191. #define WIN_SYM_PREFIX "_"
  192. #else
  193. #define WIN_SYM_PREFIX
  194. #endif
  195. #pragma comment( \
  196. linker, "/alternatename:" WIN_SYM_PREFIX INSTR_PROF_QUOTE( \
  197. INSTR_PROF_PROFILE_COUNTER_BIAS_VAR) "=" WIN_SYM_PREFIX \
  198. INSTR_PROF_QUOTE(INSTR_PROF_PROFILE_COUNTER_BIAS_DEFAULT_VAR))
  199. #else
  200. COMPILER_RT_VISIBILITY extern intptr_t INSTR_PROF_PROFILE_COUNTER_BIAS_VAR
  201. __attribute__((weak, alias(INSTR_PROF_QUOTE(
  202. INSTR_PROF_PROFILE_COUNTER_BIAS_DEFAULT_VAR))));
  203. #endif
  204. static const int ContinuousModeSupported = 1;
  205. static const int UseBiasVar = 1;
  206. /* TODO: If there are two DSOs, the second DSO initilization will truncate the
  207. * first profile file. */
  208. static const char *FileOpenMode = "w+b";
  209. /* This symbol is defined by the compiler when runtime counter relocation is
  210. * used and runtime provides a weak alias so we can check if it's defined. */
  211. static void *BiasAddr = &INSTR_PROF_PROFILE_COUNTER_BIAS_VAR;
  212. static void *BiasDefaultAddr = &INSTR_PROF_PROFILE_COUNTER_BIAS_DEFAULT_VAR;
  213. static int mmapForContinuousMode(uint64_t CurrentFileOffset, FILE *File) {
  214. /* Get the sizes of various profile data sections. Taken from
  215. * __llvm_profile_get_size_for_buffer(). */
  216. const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
  217. const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
  218. const char *CountersBegin = __llvm_profile_begin_counters();
  219. const char *CountersEnd = __llvm_profile_end_counters();
  220. const char *BitmapBegin = __llvm_profile_begin_bitmap();
  221. const char *BitmapEnd = __llvm_profile_end_bitmap();
  222. uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd);
  223. /* Get the file size. */
  224. uint64_t FileSize = 0;
  225. if (getProfileFileSizeForMerging(File, &FileSize))
  226. return 1;
  227. /* Map the profile. */
  228. char *Profile = (char *)mmap(NULL, FileSize, PROT_READ | PROT_WRITE,
  229. MAP_SHARED, fileno(File), 0);
  230. if (Profile == MAP_FAILED) {
  231. PROF_ERR("Unable to mmap profile: %s\n", strerror(errno));
  232. return 1;
  233. }
  234. const uint64_t CountersOffsetInBiasMode =
  235. sizeof(__llvm_profile_header) + __llvm_write_binary_ids(NULL) + DataSize;
  236. /* Update the profile fields based on the current mapping. */
  237. INSTR_PROF_PROFILE_COUNTER_BIAS_VAR =
  238. (intptr_t)Profile - (uintptr_t)CountersBegin + CountersOffsetInBiasMode;
  239. /* Return the memory allocated for counters to OS. */
  240. lprofReleaseMemoryPagesToOS((uintptr_t)CountersBegin, (uintptr_t)CountersEnd);
  241. /* BIAS MODE not supported yet for Bitmap (MCDC). */
  242. /* Return the memory allocated for counters to OS. */
  243. lprofReleaseMemoryPagesToOS((uintptr_t)BitmapBegin, (uintptr_t)BitmapEnd);
  244. return 0;
  245. }
  246. #else
  247. static const int ContinuousModeSupported = 0;
  248. static const int UseBiasVar = 0;
  249. static const char *FileOpenMode = "a+b";
  250. static void *BiasAddr = NULL;
  251. static void *BiasDefaultAddr = NULL;
  252. static int mmapForContinuousMode(uint64_t CurrentFileOffset, FILE *File) {
  253. return 0;
  254. }
  255. #endif
  256. static int isProfileMergeRequested(void) { return ProfileMergeRequested; }
  257. static void setProfileMergeRequested(int EnableMerge) {
  258. ProfileMergeRequested = EnableMerge;
  259. }
  260. static FILE *ProfileFile = NULL;
  261. static FILE *getProfileFile(void) { return ProfileFile; }
  262. static void setProfileFile(FILE *File) { ProfileFile = File; }
  263. static int getCurFilenameLength(void);
  264. static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf);
  265. static unsigned doMerging(void) {
  266. return lprofCurFilename.MergePoolSize || isProfileMergeRequested();
  267. }
  268. /* Return 1 if there is an error, otherwise return 0. */
  269. static uint32_t fileWriter(ProfDataWriter *This, ProfDataIOVec *IOVecs,
  270. uint32_t NumIOVecs) {
  271. uint32_t I;
  272. FILE *File = (FILE *)This->WriterCtx;
  273. char Zeroes[sizeof(uint64_t)] = {0};
  274. for (I = 0; I < NumIOVecs; I++) {
  275. if (IOVecs[I].Data) {
  276. if (fwrite(IOVecs[I].Data, IOVecs[I].ElmSize, IOVecs[I].NumElm, File) !=
  277. IOVecs[I].NumElm)
  278. return 1;
  279. } else if (IOVecs[I].UseZeroPadding) {
  280. size_t BytesToWrite = IOVecs[I].ElmSize * IOVecs[I].NumElm;
  281. while (BytesToWrite > 0) {
  282. size_t PartialWriteLen =
  283. (sizeof(uint64_t) > BytesToWrite) ? BytesToWrite : sizeof(uint64_t);
  284. if (fwrite(Zeroes, sizeof(uint8_t), PartialWriteLen, File) !=
  285. PartialWriteLen) {
  286. return 1;
  287. }
  288. BytesToWrite -= PartialWriteLen;
  289. }
  290. } else {
  291. if (fseek(File, IOVecs[I].ElmSize * IOVecs[I].NumElm, SEEK_CUR) == -1)
  292. return 1;
  293. }
  294. }
  295. return 0;
  296. }
  297. /* TODO: make buffer size controllable by an internal option, and compiler can pass the size
  298. to runtime via a variable. */
  299. static uint32_t orderFileWriter(FILE *File, const uint32_t *DataStart) {
  300. if (fwrite(DataStart, sizeof(uint32_t), INSTR_ORDER_FILE_BUFFER_SIZE, File) !=
  301. INSTR_ORDER_FILE_BUFFER_SIZE)
  302. return 1;
  303. return 0;
  304. }
  305. static void initFileWriter(ProfDataWriter *This, FILE *File) {
  306. This->Write = fileWriter;
  307. This->WriterCtx = File;
  308. }
  309. COMPILER_RT_VISIBILITY ProfBufferIO *
  310. lprofCreateBufferIOInternal(void *File, uint32_t BufferSz) {
  311. FreeHook = &free;
  312. DynamicBufferIOBuffer = (uint8_t *)calloc(1, BufferSz);
  313. VPBufferSize = BufferSz;
  314. ProfDataWriter *fileWriter =
  315. (ProfDataWriter *)calloc(1, sizeof(ProfDataWriter));
  316. initFileWriter(fileWriter, File);
  317. ProfBufferIO *IO = lprofCreateBufferIO(fileWriter);
  318. IO->OwnFileWriter = 1;
  319. return IO;
  320. }
  321. static void setupIOBuffer(void) {
  322. const char *BufferSzStr = 0;
  323. BufferSzStr = getenv("LLVM_VP_BUFFER_SIZE");
  324. if (BufferSzStr && BufferSzStr[0]) {
  325. VPBufferSize = atoi(BufferSzStr);
  326. DynamicBufferIOBuffer = (uint8_t *)calloc(VPBufferSize, 1);
  327. }
  328. }
  329. /* Get the size of the profile file. If there are any errors, print the
  330. * message under the assumption that the profile is being read for merging
  331. * purposes, and return -1. Otherwise return the file size in the inout param
  332. * \p ProfileFileSize. */
  333. static int getProfileFileSizeForMerging(FILE *ProfileFile,
  334. uint64_t *ProfileFileSize) {
  335. if (fseek(ProfileFile, 0L, SEEK_END) == -1) {
  336. PROF_ERR("Unable to merge profile data, unable to get size: %s\n",
  337. strerror(errno));
  338. return -1;
  339. }
  340. *ProfileFileSize = ftell(ProfileFile);
  341. /* Restore file offset. */
  342. if (fseek(ProfileFile, 0L, SEEK_SET) == -1) {
  343. PROF_ERR("Unable to merge profile data, unable to rewind: %s\n",
  344. strerror(errno));
  345. return -1;
  346. }
  347. if (*ProfileFileSize > 0 &&
  348. *ProfileFileSize < sizeof(__llvm_profile_header)) {
  349. PROF_WARN("Unable to merge profile data: %s\n",
  350. "source profile file is too small.");
  351. return -1;
  352. }
  353. return 0;
  354. }
  355. /* mmap() \p ProfileFile for profile merging purposes, assuming that an
  356. * exclusive lock is held on the file and that \p ProfileFileSize is the
  357. * length of the file. Return the mmap'd buffer in the inout variable
  358. * \p ProfileBuffer. Returns -1 on failure. On success, the caller is
  359. * responsible for unmapping the mmap'd buffer in \p ProfileBuffer. */
  360. static int mmapProfileForMerging(FILE *ProfileFile, uint64_t ProfileFileSize,
  361. char **ProfileBuffer) {
  362. *ProfileBuffer = mmap(NULL, ProfileFileSize, PROT_READ, MAP_SHARED | MAP_FILE,
  363. fileno(ProfileFile), 0);
  364. if (*ProfileBuffer == MAP_FAILED) {
  365. PROF_ERR("Unable to merge profile data, mmap failed: %s\n",
  366. strerror(errno));
  367. return -1;
  368. }
  369. if (__llvm_profile_check_compatibility(*ProfileBuffer, ProfileFileSize)) {
  370. (void)munmap(*ProfileBuffer, ProfileFileSize);
  371. PROF_WARN("Unable to merge profile data: %s\n",
  372. "source profile file is not compatible.");
  373. return -1;
  374. }
  375. return 0;
  376. }
  377. /* Read profile data in \c ProfileFile and merge with in-memory
  378. profile counters. Returns -1 if there is fatal error, otheriwse
  379. 0 is returned. Returning 0 does not mean merge is actually
  380. performed. If merge is actually done, *MergeDone is set to 1.
  381. */
  382. static int doProfileMerging(FILE *ProfileFile, int *MergeDone) {
  383. uint64_t ProfileFileSize;
  384. char *ProfileBuffer;
  385. /* Get the size of the profile on disk. */
  386. if (getProfileFileSizeForMerging(ProfileFile, &ProfileFileSize) == -1)
  387. return -1;
  388. /* Nothing to merge. */
  389. if (!ProfileFileSize)
  390. return 0;
  391. /* mmap() the profile and check that it is compatible with the data in
  392. * the current image. */
  393. if (mmapProfileForMerging(ProfileFile, ProfileFileSize, &ProfileBuffer) == -1)
  394. return -1;
  395. /* Now start merging */
  396. if (__llvm_profile_merge_from_buffer(ProfileBuffer, ProfileFileSize)) {
  397. PROF_ERR("%s\n", "Invalid profile data to merge");
  398. (void)munmap(ProfileBuffer, ProfileFileSize);
  399. return -1;
  400. }
  401. // Truncate the file in case merging of value profile did not happen to
  402. // prevent from leaving garbage data at the end of the profile file.
  403. (void)COMPILER_RT_FTRUNCATE(ProfileFile,
  404. __llvm_profile_get_size_for_buffer());
  405. (void)munmap(ProfileBuffer, ProfileFileSize);
  406. *MergeDone = 1;
  407. return 0;
  408. }
  409. /* Create the directory holding the file, if needed. */
  410. static void createProfileDir(const char *Filename) {
  411. size_t Length = strlen(Filename);
  412. if (lprofFindFirstDirSeparator(Filename)) {
  413. char *Copy = (char *)COMPILER_RT_ALLOCA(Length + 1);
  414. strncpy(Copy, Filename, Length + 1);
  415. __llvm_profile_recursive_mkdir(Copy);
  416. }
  417. }
  418. /* Open the profile data for merging. It opens the file in r+b mode with
  419. * file locking. If the file has content which is compatible with the
  420. * current process, it also reads in the profile data in the file and merge
  421. * it with in-memory counters. After the profile data is merged in memory,
  422. * the original profile data is truncated and gets ready for the profile
  423. * dumper. With profile merging enabled, each executable as well as any of
  424. * its instrumented shared libraries dump profile data into their own data file.
  425. */
  426. static FILE *openFileForMerging(const char *ProfileFileName, int *MergeDone) {
  427. FILE *ProfileFile = getProfileFile();
  428. int rc;
  429. // initializeProfileForContinuousMode will lock the profile, but if
  430. // ProfileFile is set by user via __llvm_profile_set_file_object, it's assumed
  431. // unlocked at this point.
  432. if (ProfileFile && !__llvm_profile_is_continuous_mode_enabled()) {
  433. lprofLockFileHandle(ProfileFile);
  434. }
  435. if (!ProfileFile) {
  436. createProfileDir(ProfileFileName);
  437. ProfileFile = lprofOpenFileEx(ProfileFileName);
  438. }
  439. if (!ProfileFile)
  440. return NULL;
  441. rc = doProfileMerging(ProfileFile, MergeDone);
  442. if (rc || (!*MergeDone && COMPILER_RT_FTRUNCATE(ProfileFile, 0L)) ||
  443. fseek(ProfileFile, 0L, SEEK_SET) == -1) {
  444. PROF_ERR("Profile Merging of file %s failed: %s\n", ProfileFileName,
  445. strerror(errno));
  446. fclose(ProfileFile);
  447. return NULL;
  448. }
  449. return ProfileFile;
  450. }
  451. static FILE *getFileObject(const char *OutputName) {
  452. FILE *File;
  453. File = getProfileFile();
  454. if (File != NULL) {
  455. return File;
  456. }
  457. return fopen(OutputName, "ab");
  458. }
  459. /* Write profile data to file \c OutputName. */
  460. static int writeFile(const char *OutputName) {
  461. int RetVal;
  462. FILE *OutputFile;
  463. int MergeDone = 0;
  464. VPMergeHook = &lprofMergeValueProfData;
  465. if (doMerging())
  466. OutputFile = openFileForMerging(OutputName, &MergeDone);
  467. else
  468. OutputFile = getFileObject(OutputName);
  469. if (!OutputFile)
  470. return -1;
  471. FreeHook = &free;
  472. setupIOBuffer();
  473. ProfDataWriter fileWriter;
  474. initFileWriter(&fileWriter, OutputFile);
  475. RetVal = lprofWriteData(&fileWriter, lprofGetVPDataReader(), MergeDone);
  476. if (OutputFile == getProfileFile()) {
  477. fflush(OutputFile);
  478. if (doMerging() && !__llvm_profile_is_continuous_mode_enabled()) {
  479. lprofUnlockFileHandle(OutputFile);
  480. }
  481. } else {
  482. fclose(OutputFile);
  483. }
  484. return RetVal;
  485. }
  486. /* Write order data to file \c OutputName. */
  487. static int writeOrderFile(const char *OutputName) {
  488. int RetVal;
  489. FILE *OutputFile;
  490. OutputFile = fopen(OutputName, "w");
  491. if (!OutputFile) {
  492. PROF_WARN("can't open file with mode ab: %s\n", OutputName);
  493. return -1;
  494. }
  495. FreeHook = &free;
  496. setupIOBuffer();
  497. const uint32_t *DataBegin = __llvm_profile_begin_orderfile();
  498. RetVal = orderFileWriter(OutputFile, DataBegin);
  499. fclose(OutputFile);
  500. return RetVal;
  501. }
  502. #define LPROF_INIT_ONCE_ENV "__LLVM_PROFILE_RT_INIT_ONCE"
  503. static void truncateCurrentFile(void) {
  504. const char *Filename;
  505. char *FilenameBuf;
  506. FILE *File;
  507. int Length;
  508. Length = getCurFilenameLength();
  509. FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
  510. Filename = getCurFilename(FilenameBuf, 0);
  511. if (!Filename)
  512. return;
  513. /* Only create the profile directory and truncate an existing profile once.
  514. * In continuous mode, this is necessary, as the profile is written-to by the
  515. * runtime initializer. */
  516. int initialized = getenv(LPROF_INIT_ONCE_ENV) != NULL;
  517. if (initialized)
  518. return;
  519. #if defined(_WIN32)
  520. _putenv(LPROF_INIT_ONCE_ENV "=" LPROF_INIT_ONCE_ENV);
  521. #else
  522. setenv(LPROF_INIT_ONCE_ENV, LPROF_INIT_ONCE_ENV, 1);
  523. #endif
  524. /* Create the profile dir (even if online merging is enabled), so that
  525. * the profile file can be set up if continuous mode is enabled. */
  526. createProfileDir(Filename);
  527. /* By pass file truncation to allow online raw profile merging. */
  528. if (lprofCurFilename.MergePoolSize)
  529. return;
  530. /* Truncate the file. Later we'll reopen and append. */
  531. File = fopen(Filename, "w");
  532. if (!File)
  533. return;
  534. fclose(File);
  535. }
  536. /* Write a partial profile to \p Filename, which is required to be backed by
  537. * the open file object \p File. */
  538. static int writeProfileWithFileObject(const char *Filename, FILE *File) {
  539. setProfileFile(File);
  540. int rc = writeFile(Filename);
  541. if (rc)
  542. PROF_ERR("Failed to write file \"%s\": %s\n", Filename, strerror(errno));
  543. setProfileFile(NULL);
  544. return rc;
  545. }
  546. static void initializeProfileForContinuousMode(void) {
  547. if (!__llvm_profile_is_continuous_mode_enabled())
  548. return;
  549. if (!ContinuousModeSupported) {
  550. PROF_ERR("%s\n", "continuous mode is unsupported on this platform");
  551. return;
  552. }
  553. if (UseBiasVar && BiasAddr == BiasDefaultAddr) {
  554. PROF_ERR("%s\n", "__llvm_profile_counter_bias is undefined");
  555. return;
  556. }
  557. /* Get the sizes of counter section. */
  558. uint64_t CountersSize = __llvm_profile_get_counters_size(
  559. __llvm_profile_begin_counters(), __llvm_profile_end_counters());
  560. int Length = getCurFilenameLength();
  561. char *FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
  562. const char *Filename = getCurFilename(FilenameBuf, 0);
  563. if (!Filename)
  564. return;
  565. FILE *File = NULL;
  566. uint64_t CurrentFileOffset = 0;
  567. if (doMerging()) {
  568. /* We are merging profiles. Map the counter section as shared memory into
  569. * the profile, i.e. into each participating process. An increment in one
  570. * process should be visible to every other process with the same counter
  571. * section mapped. */
  572. File = lprofOpenFileEx(Filename);
  573. if (!File)
  574. return;
  575. uint64_t ProfileFileSize = 0;
  576. if (getProfileFileSizeForMerging(File, &ProfileFileSize) == -1) {
  577. lprofUnlockFileHandle(File);
  578. fclose(File);
  579. return;
  580. }
  581. if (ProfileFileSize == 0) {
  582. /* Grow the profile so that mmap() can succeed. Leak the file handle, as
  583. * the file should stay open. */
  584. if (writeProfileWithFileObject(Filename, File) != 0) {
  585. lprofUnlockFileHandle(File);
  586. fclose(File);
  587. return;
  588. }
  589. } else {
  590. /* The merged profile has a non-zero length. Check that it is compatible
  591. * with the data in this process. */
  592. char *ProfileBuffer;
  593. if (mmapProfileForMerging(File, ProfileFileSize, &ProfileBuffer) == -1) {
  594. lprofUnlockFileHandle(File);
  595. fclose(File);
  596. return;
  597. }
  598. (void)munmap(ProfileBuffer, ProfileFileSize);
  599. }
  600. } else {
  601. File = fopen(Filename, FileOpenMode);
  602. if (!File)
  603. return;
  604. /* Check that the offset within the file is page-aligned. */
  605. CurrentFileOffset = ftell(File);
  606. unsigned PageSize = getpagesize();
  607. if (CurrentFileOffset % PageSize != 0) {
  608. PROF_ERR("Continuous counter sync mode is enabled, but raw profile is not"
  609. "page-aligned. CurrentFileOffset = %" PRIu64 ", pagesz = %u.\n",
  610. (uint64_t)CurrentFileOffset, PageSize);
  611. fclose(File);
  612. return;
  613. }
  614. if (writeProfileWithFileObject(Filename, File) != 0) {
  615. fclose(File);
  616. return;
  617. }
  618. }
  619. /* mmap() the profile counters so long as there is at least one counter.
  620. * If there aren't any counters, mmap() would fail with EINVAL. */
  621. if (CountersSize > 0)
  622. mmapForContinuousMode(CurrentFileOffset, File);
  623. if (doMerging()) {
  624. lprofUnlockFileHandle(File);
  625. }
  626. if (File != NULL) {
  627. fclose(File);
  628. }
  629. }
  630. static const char *DefaultProfileName = "default.profraw";
  631. static void resetFilenameToDefault(void) {
  632. if (lprofCurFilename.FilenamePat && lprofCurFilename.OwnsFilenamePat) {
  633. #ifdef __GNUC__
  634. #pragma GCC diagnostic push
  635. #pragma GCC diagnostic ignored "-Wcast-qual"
  636. #elif defined(__clang__)
  637. #pragma clang diagnostic push
  638. #pragma clang diagnostic ignored "-Wcast-qual"
  639. #endif
  640. free((void *)lprofCurFilename.FilenamePat);
  641. #ifdef __GNUC__
  642. #pragma GCC diagnostic pop
  643. #elif defined(__clang__)
  644. #pragma clang diagnostic pop
  645. #endif
  646. }
  647. memset(&lprofCurFilename, 0, sizeof(lprofCurFilename));
  648. lprofCurFilename.FilenamePat = DefaultProfileName;
  649. lprofCurFilename.PNS = PNS_default;
  650. }
  651. static unsigned getMergePoolSize(const char *FilenamePat, int *I) {
  652. unsigned J = 0, Num = 0;
  653. for (;; ++J) {
  654. char C = FilenamePat[*I + J];
  655. if (C == 'm') {
  656. *I += J;
  657. return Num ? Num : 1;
  658. }
  659. if (C < '0' || C > '9')
  660. break;
  661. Num = Num * 10 + C - '0';
  662. /* If FilenamePat[*I+J] is between '0' and '9', the next byte is guaranteed
  663. * to be in-bound as the string is null terminated. */
  664. }
  665. return 0;
  666. }
  667. /* Assert that Idx does index past a string null terminator. Return the
  668. * result of the check. */
  669. static int checkBounds(int Idx, int Strlen) {
  670. assert(Idx <= Strlen && "Indexing past string null terminator");
  671. return Idx <= Strlen;
  672. }
  673. /* Parses the pattern string \p FilenamePat and stores the result to
  674. * lprofcurFilename structure. */
  675. static int parseFilenamePattern(const char *FilenamePat,
  676. unsigned CopyFilenamePat) {
  677. int NumPids = 0, NumHosts = 0, I;
  678. char *PidChars = &lprofCurFilename.PidChars[0];
  679. char *Hostname = &lprofCurFilename.Hostname[0];
  680. int MergingEnabled = 0;
  681. int FilenamePatLen = strlen(FilenamePat);
  682. #ifdef __GNUC__
  683. #pragma GCC diagnostic push
  684. #pragma GCC diagnostic ignored "-Wcast-qual"
  685. #elif defined(__clang__)
  686. #pragma clang diagnostic push
  687. #pragma clang diagnostic ignored "-Wcast-qual"
  688. #endif
  689. /* Clean up cached prefix and filename. */
  690. if (lprofCurFilename.ProfilePathPrefix)
  691. free((void *)lprofCurFilename.ProfilePathPrefix);
  692. if (lprofCurFilename.FilenamePat && lprofCurFilename.OwnsFilenamePat) {
  693. free((void *)lprofCurFilename.FilenamePat);
  694. }
  695. #ifdef __GNUC__
  696. #pragma GCC diagnostic pop
  697. #elif defined(__clang__)
  698. #pragma clang diagnostic pop
  699. #endif
  700. memset(&lprofCurFilename, 0, sizeof(lprofCurFilename));
  701. if (!CopyFilenamePat)
  702. lprofCurFilename.FilenamePat = FilenamePat;
  703. else {
  704. lprofCurFilename.FilenamePat = strdup(FilenamePat);
  705. lprofCurFilename.OwnsFilenamePat = 1;
  706. }
  707. /* Check the filename for "%p", which indicates a pid-substitution. */
  708. for (I = 0; checkBounds(I, FilenamePatLen) && FilenamePat[I]; ++I) {
  709. if (FilenamePat[I] == '%') {
  710. ++I; /* Advance to the next character. */
  711. if (!checkBounds(I, FilenamePatLen))
  712. break;
  713. if (FilenamePat[I] == 'p') {
  714. if (!NumPids++) {
  715. if (snprintf(PidChars, MAX_PID_SIZE, "%ld", (long)getpid()) <= 0) {
  716. PROF_WARN("Unable to get pid for filename pattern %s. Using the "
  717. "default name.",
  718. FilenamePat);
  719. return -1;
  720. }
  721. }
  722. } else if (FilenamePat[I] == 'h') {
  723. if (!NumHosts++)
  724. if (COMPILER_RT_GETHOSTNAME(Hostname, COMPILER_RT_MAX_HOSTLEN)) {
  725. PROF_WARN("Unable to get hostname for filename pattern %s. Using "
  726. "the default name.",
  727. FilenamePat);
  728. return -1;
  729. }
  730. } else if (FilenamePat[I] == 't') {
  731. lprofCurFilename.TmpDir = getenv("TMPDIR");
  732. if (!lprofCurFilename.TmpDir) {
  733. PROF_WARN("Unable to get the TMPDIR environment variable, referenced "
  734. "in %s. Using the default path.",
  735. FilenamePat);
  736. return -1;
  737. }
  738. } else if (FilenamePat[I] == 'c') {
  739. if (__llvm_profile_is_continuous_mode_enabled()) {
  740. PROF_WARN("%%c specifier can only be specified once in %s.\n",
  741. FilenamePat);
  742. __llvm_profile_disable_continuous_mode();
  743. return -1;
  744. }
  745. #if defined(__APPLE__) || defined(__ELF__) || defined(_WIN32)
  746. __llvm_profile_set_page_size(getpagesize());
  747. __llvm_profile_enable_continuous_mode();
  748. #else
  749. PROF_WARN("%s", "Continous mode is currently only supported for Mach-O,"
  750. " ELF and COFF formats.");
  751. return -1;
  752. #endif
  753. } else {
  754. unsigned MergePoolSize = getMergePoolSize(FilenamePat, &I);
  755. if (!MergePoolSize)
  756. continue;
  757. if (MergingEnabled) {
  758. PROF_WARN("%%m specifier can only be specified once in %s.\n",
  759. FilenamePat);
  760. return -1;
  761. }
  762. MergingEnabled = 1;
  763. lprofCurFilename.MergePoolSize = MergePoolSize;
  764. }
  765. }
  766. }
  767. lprofCurFilename.NumPids = NumPids;
  768. lprofCurFilename.NumHosts = NumHosts;
  769. return 0;
  770. }
  771. static void parseAndSetFilename(const char *FilenamePat,
  772. ProfileNameSpecifier PNS,
  773. unsigned CopyFilenamePat) {
  774. const char *OldFilenamePat = lprofCurFilename.FilenamePat;
  775. ProfileNameSpecifier OldPNS = lprofCurFilename.PNS;
  776. /* The old profile name specifier takes precedence over the old one. */
  777. if (PNS < OldPNS)
  778. return;
  779. if (!FilenamePat)
  780. FilenamePat = DefaultProfileName;
  781. if (OldFilenamePat && !strcmp(OldFilenamePat, FilenamePat)) {
  782. lprofCurFilename.PNS = PNS;
  783. return;
  784. }
  785. /* When PNS >= OldPNS, the last one wins. */
  786. if (!FilenamePat || parseFilenamePattern(FilenamePat, CopyFilenamePat))
  787. resetFilenameToDefault();
  788. lprofCurFilename.PNS = PNS;
  789. if (!OldFilenamePat) {
  790. if (getenv("LLVM_PROFILE_VERBOSE"))
  791. PROF_NOTE("Set profile file path to \"%s\" via %s.\n",
  792. lprofCurFilename.FilenamePat, getPNSStr(PNS));
  793. } else {
  794. if (getenv("LLVM_PROFILE_VERBOSE"))
  795. PROF_NOTE("Override old profile path \"%s\" via %s to \"%s\" via %s.\n",
  796. OldFilenamePat, getPNSStr(OldPNS), lprofCurFilename.FilenamePat,
  797. getPNSStr(PNS));
  798. }
  799. truncateCurrentFile();
  800. if (__llvm_profile_is_continuous_mode_enabled())
  801. initializeProfileForContinuousMode();
  802. }
  803. /* Return buffer length that is required to store the current profile
  804. * filename with PID and hostname substitutions. */
  805. /* The length to hold uint64_t followed by 3 digits pool id including '_' */
  806. #define SIGLEN 24
  807. static int getCurFilenameLength(void) {
  808. int Len;
  809. if (!lprofCurFilename.FilenamePat || !lprofCurFilename.FilenamePat[0])
  810. return 0;
  811. if (!(lprofCurFilename.NumPids || lprofCurFilename.NumHosts ||
  812. lprofCurFilename.TmpDir || lprofCurFilename.MergePoolSize))
  813. return strlen(lprofCurFilename.FilenamePat);
  814. Len = strlen(lprofCurFilename.FilenamePat) +
  815. lprofCurFilename.NumPids * (strlen(lprofCurFilename.PidChars) - 2) +
  816. lprofCurFilename.NumHosts * (strlen(lprofCurFilename.Hostname) - 2) +
  817. (lprofCurFilename.TmpDir ? (strlen(lprofCurFilename.TmpDir) - 1) : 0);
  818. if (lprofCurFilename.MergePoolSize)
  819. Len += SIGLEN;
  820. return Len;
  821. }
  822. /* Return the pointer to the current profile file name (after substituting
  823. * PIDs and Hostnames in filename pattern. \p FilenameBuf is the buffer
  824. * to store the resulting filename. If no substitution is needed, the
  825. * current filename pattern string is directly returned, unless ForceUseBuf
  826. * is enabled. */
  827. static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf) {
  828. int I, J, PidLength, HostNameLength, TmpDirLength, FilenamePatLength;
  829. const char *FilenamePat = lprofCurFilename.FilenamePat;
  830. if (!lprofCurFilename.FilenamePat || !lprofCurFilename.FilenamePat[0])
  831. return 0;
  832. if (!(lprofCurFilename.NumPids || lprofCurFilename.NumHosts ||
  833. lprofCurFilename.TmpDir || lprofCurFilename.MergePoolSize ||
  834. __llvm_profile_is_continuous_mode_enabled())) {
  835. if (!ForceUseBuf)
  836. return lprofCurFilename.FilenamePat;
  837. FilenamePatLength = strlen(lprofCurFilename.FilenamePat);
  838. memcpy(FilenameBuf, lprofCurFilename.FilenamePat, FilenamePatLength);
  839. FilenameBuf[FilenamePatLength] = '\0';
  840. return FilenameBuf;
  841. }
  842. PidLength = strlen(lprofCurFilename.PidChars);
  843. HostNameLength = strlen(lprofCurFilename.Hostname);
  844. TmpDirLength = lprofCurFilename.TmpDir ? strlen(lprofCurFilename.TmpDir) : 0;
  845. /* Construct the new filename. */
  846. for (I = 0, J = 0; FilenamePat[I]; ++I)
  847. if (FilenamePat[I] == '%') {
  848. if (FilenamePat[++I] == 'p') {
  849. memcpy(FilenameBuf + J, lprofCurFilename.PidChars, PidLength);
  850. J += PidLength;
  851. } else if (FilenamePat[I] == 'h') {
  852. memcpy(FilenameBuf + J, lprofCurFilename.Hostname, HostNameLength);
  853. J += HostNameLength;
  854. } else if (FilenamePat[I] == 't') {
  855. memcpy(FilenameBuf + J, lprofCurFilename.TmpDir, TmpDirLength);
  856. FilenameBuf[J + TmpDirLength] = DIR_SEPARATOR;
  857. J += TmpDirLength + 1;
  858. } else {
  859. if (!getMergePoolSize(FilenamePat, &I))
  860. continue;
  861. char LoadModuleSignature[SIGLEN + 1];
  862. int S;
  863. int ProfilePoolId = getpid() % lprofCurFilename.MergePoolSize;
  864. S = snprintf(LoadModuleSignature, SIGLEN + 1, "%" PRIu64 "_%d",
  865. lprofGetLoadModuleSignature(), ProfilePoolId);
  866. if (S == -1 || S > SIGLEN)
  867. S = SIGLEN;
  868. memcpy(FilenameBuf + J, LoadModuleSignature, S);
  869. J += S;
  870. }
  871. /* Drop any unknown substitutions. */
  872. } else
  873. FilenameBuf[J++] = FilenamePat[I];
  874. FilenameBuf[J] = 0;
  875. return FilenameBuf;
  876. }
  877. /* Returns the pointer to the environment variable
  878. * string. Returns null if the env var is not set. */
  879. static const char *getFilenamePatFromEnv(void) {
  880. const char *Filename = getenv("LLVM_PROFILE_FILE");
  881. if (!Filename || !Filename[0])
  882. return 0;
  883. return Filename;
  884. }
  885. COMPILER_RT_VISIBILITY
  886. const char *__llvm_profile_get_path_prefix(void) {
  887. int Length;
  888. char *FilenameBuf, *Prefix;
  889. const char *Filename, *PrefixEnd;
  890. if (lprofCurFilename.ProfilePathPrefix)
  891. return lprofCurFilename.ProfilePathPrefix;
  892. Length = getCurFilenameLength();
  893. FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
  894. Filename = getCurFilename(FilenameBuf, 0);
  895. if (!Filename)
  896. return "\0";
  897. PrefixEnd = lprofFindLastDirSeparator(Filename);
  898. if (!PrefixEnd)
  899. return "\0";
  900. Length = PrefixEnd - Filename + 1;
  901. Prefix = (char *)malloc(Length + 1);
  902. if (!Prefix) {
  903. PROF_ERR("Failed to %s\n", "allocate memory.");
  904. return "\0";
  905. }
  906. memcpy(Prefix, Filename, Length);
  907. Prefix[Length] = '\0';
  908. lprofCurFilename.ProfilePathPrefix = Prefix;
  909. return Prefix;
  910. }
  911. COMPILER_RT_VISIBILITY
  912. const char *__llvm_profile_get_filename(void) {
  913. int Length;
  914. char *FilenameBuf;
  915. const char *Filename;
  916. Length = getCurFilenameLength();
  917. FilenameBuf = (char *)malloc(Length + 1);
  918. if (!FilenameBuf) {
  919. PROF_ERR("Failed to %s\n", "allocate memory.");
  920. return "\0";
  921. }
  922. Filename = getCurFilename(FilenameBuf, 1);
  923. if (!Filename)
  924. return "\0";
  925. return FilenameBuf;
  926. }
  927. /* This API initializes the file handling, both user specified
  928. * profile path via -fprofile-instr-generate= and LLVM_PROFILE_FILE
  929. * environment variable can override this default value.
  930. */
  931. COMPILER_RT_VISIBILITY
  932. void __llvm_profile_initialize_file(void) {
  933. const char *EnvFilenamePat;
  934. const char *SelectedPat = NULL;
  935. ProfileNameSpecifier PNS = PNS_unknown;
  936. int hasCommandLineOverrider = (INSTR_PROF_PROFILE_NAME_VAR[0] != 0);
  937. EnvFilenamePat = getFilenamePatFromEnv();
  938. if (EnvFilenamePat) {
  939. /* Pass CopyFilenamePat = 1, to ensure that the filename would be valid
  940. at the moment when __llvm_profile_write_file() gets executed. */
  941. parseAndSetFilename(EnvFilenamePat, PNS_environment, 1);
  942. return;
  943. } else if (hasCommandLineOverrider) {
  944. SelectedPat = INSTR_PROF_PROFILE_NAME_VAR;
  945. PNS = PNS_command_line;
  946. } else {
  947. SelectedPat = NULL;
  948. PNS = PNS_default;
  949. }
  950. parseAndSetFilename(SelectedPat, PNS, 0);
  951. }
  952. /* This method is invoked by the runtime initialization hook
  953. * InstrProfilingRuntime.o if it is linked in.
  954. */
  955. COMPILER_RT_VISIBILITY
  956. void __llvm_profile_initialize(void) {
  957. __llvm_profile_initialize_file();
  958. if (!__llvm_profile_is_continuous_mode_enabled())
  959. __llvm_profile_register_write_file_atexit();
  960. }
  961. /* This API is directly called by the user application code. It has the
  962. * highest precedence compared with LLVM_PROFILE_FILE environment variable
  963. * and command line option -fprofile-instr-generate=<profile_name>.
  964. */
  965. COMPILER_RT_VISIBILITY
  966. void __llvm_profile_set_filename(const char *FilenamePat) {
  967. if (__llvm_profile_is_continuous_mode_enabled())
  968. return;
  969. parseAndSetFilename(FilenamePat, PNS_runtime_api, 1);
  970. }
  971. /* The public API for writing profile data into the file with name
  972. * set by previous calls to __llvm_profile_set_filename or
  973. * __llvm_profile_override_default_filename or
  974. * __llvm_profile_initialize_file. */
  975. COMPILER_RT_VISIBILITY
  976. int __llvm_profile_write_file(void) {
  977. int rc, Length;
  978. const char *Filename;
  979. char *FilenameBuf;
  980. // Temporarily suspend getting SIGKILL when the parent exits.
  981. int PDeathSig = lprofSuspendSigKill();
  982. if (lprofProfileDumped() || __llvm_profile_is_continuous_mode_enabled()) {
  983. PROF_NOTE("Profile data not written to file: %s.\n", "already written");
  984. if (PDeathSig == 1)
  985. lprofRestoreSigKill();
  986. return 0;
  987. }
  988. Length = getCurFilenameLength();
  989. FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
  990. Filename = getCurFilename(FilenameBuf, 0);
  991. /* Check the filename. */
  992. if (!Filename) {
  993. PROF_ERR("Failed to write file : %s\n", "Filename not set");
  994. if (PDeathSig == 1)
  995. lprofRestoreSigKill();
  996. return -1;
  997. }
  998. /* Check if there is llvm/runtime version mismatch. */
  999. if (GET_VERSION(__llvm_profile_get_version()) != INSTR_PROF_RAW_VERSION) {
  1000. PROF_ERR("Runtime and instrumentation version mismatch : "
  1001. "expected %d, but get %d\n",
  1002. INSTR_PROF_RAW_VERSION,
  1003. (int)GET_VERSION(__llvm_profile_get_version()));
  1004. if (PDeathSig == 1)
  1005. lprofRestoreSigKill();
  1006. return -1;
  1007. }
  1008. /* Write profile data to the file. */
  1009. rc = writeFile(Filename);
  1010. if (rc)
  1011. PROF_ERR("Failed to write file \"%s\": %s\n", Filename, strerror(errno));
  1012. // Restore SIGKILL.
  1013. if (PDeathSig == 1)
  1014. lprofRestoreSigKill();
  1015. return rc;
  1016. }
  1017. COMPILER_RT_VISIBILITY
  1018. int __llvm_profile_dump(void) {
  1019. if (!doMerging())
  1020. PROF_WARN("Later invocation of __llvm_profile_dump can lead to clobbering "
  1021. " of previously dumped profile data : %s. Either use %%m "
  1022. "in profile name or change profile name before dumping.\n",
  1023. "online profile merging is not on");
  1024. int rc = __llvm_profile_write_file();
  1025. lprofSetProfileDumped(1);
  1026. return rc;
  1027. }
  1028. /* Order file data will be saved in a file with suffx .order. */
  1029. static const char *OrderFileSuffix = ".order";
  1030. COMPILER_RT_VISIBILITY
  1031. int __llvm_orderfile_write_file(void) {
  1032. int rc, Length, LengthBeforeAppend, SuffixLength;
  1033. const char *Filename;
  1034. char *FilenameBuf;
  1035. // Temporarily suspend getting SIGKILL when the parent exits.
  1036. int PDeathSig = lprofSuspendSigKill();
  1037. SuffixLength = strlen(OrderFileSuffix);
  1038. Length = getCurFilenameLength() + SuffixLength;
  1039. FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1);
  1040. Filename = getCurFilename(FilenameBuf, 1);
  1041. /* Check the filename. */
  1042. if (!Filename) {
  1043. PROF_ERR("Failed to write file : %s\n", "Filename not set");
  1044. if (PDeathSig == 1)
  1045. lprofRestoreSigKill();
  1046. return -1;
  1047. }
  1048. /* Append order file suffix */
  1049. LengthBeforeAppend = strlen(Filename);
  1050. memcpy(FilenameBuf + LengthBeforeAppend, OrderFileSuffix, SuffixLength);
  1051. FilenameBuf[LengthBeforeAppend + SuffixLength] = '\0';
  1052. /* Check if there is llvm/runtime version mismatch. */
  1053. if (GET_VERSION(__llvm_profile_get_version()) != INSTR_PROF_RAW_VERSION) {
  1054. PROF_ERR("Runtime and instrumentation version mismatch : "
  1055. "expected %d, but get %d\n",
  1056. INSTR_PROF_RAW_VERSION,
  1057. (int)GET_VERSION(__llvm_profile_get_version()));
  1058. if (PDeathSig == 1)
  1059. lprofRestoreSigKill();
  1060. return -1;
  1061. }
  1062. /* Write order data to the file. */
  1063. rc = writeOrderFile(Filename);
  1064. if (rc)
  1065. PROF_ERR("Failed to write file \"%s\": %s\n", Filename, strerror(errno));
  1066. // Restore SIGKILL.
  1067. if (PDeathSig == 1)
  1068. lprofRestoreSigKill();
  1069. return rc;
  1070. }
  1071. COMPILER_RT_VISIBILITY
  1072. int __llvm_orderfile_dump(void) {
  1073. int rc = __llvm_orderfile_write_file();
  1074. return rc;
  1075. }
  1076. static void writeFileWithoutReturn(void) { __llvm_profile_write_file(); }
  1077. COMPILER_RT_VISIBILITY
  1078. int __llvm_profile_register_write_file_atexit(void) {
  1079. static int HasBeenRegistered = 0;
  1080. if (HasBeenRegistered)
  1081. return 0;
  1082. lprofSetupValueProfiler();
  1083. HasBeenRegistered = 1;
  1084. return atexit(writeFileWithoutReturn);
  1085. }
  1086. COMPILER_RT_VISIBILITY int __llvm_profile_set_file_object(FILE *File,
  1087. int EnableMerge) {
  1088. if (__llvm_profile_is_continuous_mode_enabled()) {
  1089. if (!EnableMerge) {
  1090. PROF_WARN("__llvm_profile_set_file_object(fd=%d) not supported in "
  1091. "continuous sync mode when merging is disabled\n",
  1092. fileno(File));
  1093. return 1;
  1094. }
  1095. if (lprofLockFileHandle(File) != 0) {
  1096. PROF_WARN("Data may be corrupted during profile merging : %s\n",
  1097. "Fail to obtain file lock due to system limit.");
  1098. }
  1099. uint64_t ProfileFileSize = 0;
  1100. if (getProfileFileSizeForMerging(File, &ProfileFileSize) == -1) {
  1101. lprofUnlockFileHandle(File);
  1102. return 1;
  1103. }
  1104. if (ProfileFileSize == 0) {
  1105. FreeHook = &free;
  1106. setupIOBuffer();
  1107. ProfDataWriter fileWriter;
  1108. initFileWriter(&fileWriter, File);
  1109. if (lprofWriteData(&fileWriter, 0, 0)) {
  1110. lprofUnlockFileHandle(File);
  1111. PROF_ERR("Failed to write file \"%d\": %s\n", fileno(File),
  1112. strerror(errno));
  1113. return 1;
  1114. }
  1115. fflush(File);
  1116. } else {
  1117. /* The merged profile has a non-zero length. Check that it is compatible
  1118. * with the data in this process. */
  1119. char *ProfileBuffer;
  1120. if (mmapProfileForMerging(File, ProfileFileSize, &ProfileBuffer) == -1) {
  1121. lprofUnlockFileHandle(File);
  1122. return 1;
  1123. }
  1124. (void)munmap(ProfileBuffer, ProfileFileSize);
  1125. }
  1126. mmapForContinuousMode(0, File);
  1127. lprofUnlockFileHandle(File);
  1128. } else {
  1129. setProfileFile(File);
  1130. setProfileMergeRequested(EnableMerge);
  1131. }
  1132. return 0;
  1133. }
  1134. #endif