InstrProfilingPlatformLinux.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. /*===- InstrProfilingPlatformLinux.c - Profile data Linux platform ------===*\
  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(__linux__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \
  9. (defined(__sun__) && defined(__svr4__)) || defined(__NetBSD__) || \
  10. defined(_AIX)
  11. #if !defined(_AIX)
  12. #include <elf.h>
  13. #include <link.h>
  14. #endif
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include "InstrProfiling.h"
  18. #include "InstrProfilingInternal.h"
  19. #if defined(__FreeBSD__) && !defined(ElfW)
  20. /*
  21. * FreeBSD's elf.h and link.h headers do not define the ElfW(type) macro yet.
  22. * If this is added to all supported FreeBSD versions in the future, this
  23. * compatibility macro can be removed.
  24. */
  25. #define ElfW(type) __ElfN(type)
  26. #endif
  27. #define PROF_DATA_START INSTR_PROF_SECT_START(INSTR_PROF_DATA_COMMON)
  28. #define PROF_DATA_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_DATA_COMMON)
  29. #define PROF_NAME_START INSTR_PROF_SECT_START(INSTR_PROF_NAME_COMMON)
  30. #define PROF_NAME_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_NAME_COMMON)
  31. #define PROF_CNTS_START INSTR_PROF_SECT_START(INSTR_PROF_CNTS_COMMON)
  32. #define PROF_CNTS_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_CNTS_COMMON)
  33. #define PROF_ORDERFILE_START INSTR_PROF_SECT_START(INSTR_PROF_ORDERFILE_COMMON)
  34. #define PROF_VNODES_START INSTR_PROF_SECT_START(INSTR_PROF_VNODES_COMMON)
  35. #define PROF_VNODES_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_VNODES_COMMON)
  36. /* Declare section start and stop symbols for various sections
  37. * generated by compiler instrumentation.
  38. */
  39. extern __llvm_profile_data PROF_DATA_START COMPILER_RT_VISIBILITY
  40. COMPILER_RT_WEAK;
  41. extern __llvm_profile_data PROF_DATA_STOP COMPILER_RT_VISIBILITY
  42. COMPILER_RT_WEAK;
  43. extern char PROF_CNTS_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
  44. extern char PROF_CNTS_STOP COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
  45. extern uint32_t PROF_ORDERFILE_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
  46. extern char PROF_NAME_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
  47. extern char PROF_NAME_STOP COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
  48. extern ValueProfNode PROF_VNODES_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
  49. extern ValueProfNode PROF_VNODES_STOP COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
  50. COMPILER_RT_VISIBILITY const __llvm_profile_data *
  51. __llvm_profile_begin_data(void) {
  52. return &PROF_DATA_START;
  53. }
  54. COMPILER_RT_VISIBILITY const __llvm_profile_data *
  55. __llvm_profile_end_data(void) {
  56. return &PROF_DATA_STOP;
  57. }
  58. COMPILER_RT_VISIBILITY const char *__llvm_profile_begin_names(void) {
  59. return &PROF_NAME_START;
  60. }
  61. COMPILER_RT_VISIBILITY const char *__llvm_profile_end_names(void) {
  62. return &PROF_NAME_STOP;
  63. }
  64. COMPILER_RT_VISIBILITY char *__llvm_profile_begin_counters(void) {
  65. return &PROF_CNTS_START;
  66. }
  67. COMPILER_RT_VISIBILITY char *__llvm_profile_end_counters(void) {
  68. return &PROF_CNTS_STOP;
  69. }
  70. COMPILER_RT_VISIBILITY uint32_t *__llvm_profile_begin_orderfile(void) {
  71. return &PROF_ORDERFILE_START;
  72. }
  73. COMPILER_RT_VISIBILITY ValueProfNode *
  74. __llvm_profile_begin_vnodes(void) {
  75. return &PROF_VNODES_START;
  76. }
  77. COMPILER_RT_VISIBILITY ValueProfNode *__llvm_profile_end_vnodes(void) {
  78. return &PROF_VNODES_STOP;
  79. }
  80. COMPILER_RT_VISIBILITY ValueProfNode *CurrentVNode = &PROF_VNODES_START;
  81. COMPILER_RT_VISIBILITY ValueProfNode *EndVNode = &PROF_VNODES_STOP;
  82. #ifdef NT_GNU_BUILD_ID
  83. static size_t RoundUp(size_t size, size_t align) {
  84. return (size + align - 1) & ~(align - 1);
  85. }
  86. /*
  87. * Write binary id length and then its data, because binary id does not
  88. * have a fixed length.
  89. */
  90. static int WriteOneBinaryId(ProfDataWriter *Writer, uint64_t BinaryIdLen,
  91. const uint8_t *BinaryIdData,
  92. uint64_t BinaryIdPadding) {
  93. ProfDataIOVec BinaryIdIOVec[] = {
  94. {&BinaryIdLen, sizeof(uint64_t), 1, 0},
  95. {BinaryIdData, sizeof(uint8_t), BinaryIdLen, 0},
  96. {NULL, sizeof(uint8_t), BinaryIdPadding, 1},
  97. };
  98. if (Writer->Write(Writer, BinaryIdIOVec,
  99. sizeof(BinaryIdIOVec) / sizeof(*BinaryIdIOVec)))
  100. return -1;
  101. /* Successfully wrote binary id, report success. */
  102. return 0;
  103. }
  104. /*
  105. * Look for the note that has the name "GNU\0" and type NT_GNU_BUILD_ID
  106. * that contains build id. If build id exists, write binary id.
  107. *
  108. * Each note in notes section starts with a struct which includes
  109. * n_namesz, n_descsz, and n_type members. It is followed by the name
  110. * (whose length is defined in n_namesz) and then by the descriptor
  111. * (whose length is defined in n_descsz).
  112. *
  113. * Note sections like .note.ABI-tag and .note.gnu.build-id are aligned
  114. * to 4 bytes, so round n_namesz and n_descsz to the nearest 4 bytes.
  115. */
  116. static int WriteBinaryIdForNote(ProfDataWriter *Writer,
  117. const ElfW(Nhdr) * Note) {
  118. int BinaryIdSize = 0;
  119. const char *NoteName = (const char *)Note + sizeof(ElfW(Nhdr));
  120. if (Note->n_type == NT_GNU_BUILD_ID && Note->n_namesz == 4 &&
  121. memcmp(NoteName, "GNU\0", 4) == 0) {
  122. uint64_t BinaryIdLen = Note->n_descsz;
  123. const uint8_t *BinaryIdData =
  124. (const uint8_t *)(NoteName + RoundUp(Note->n_namesz, 4));
  125. uint8_t BinaryIdPadding = __llvm_profile_get_num_padding_bytes(BinaryIdLen);
  126. if (Writer != NULL && WriteOneBinaryId(Writer, BinaryIdLen, BinaryIdData,
  127. BinaryIdPadding) == -1)
  128. return -1;
  129. BinaryIdSize = sizeof(BinaryIdLen) + BinaryIdLen + BinaryIdPadding;
  130. }
  131. return BinaryIdSize;
  132. }
  133. /*
  134. * Helper function that iterates through notes section and find build ids.
  135. * If writer is given, write binary ids into profiles.
  136. * If an error happens while writing, return -1.
  137. */
  138. static int WriteBinaryIds(ProfDataWriter *Writer, const ElfW(Nhdr) * Note,
  139. const ElfW(Nhdr) * NotesEnd) {
  140. int BinaryIdsSize = 0;
  141. while (Note < NotesEnd) {
  142. int OneBinaryIdSize = WriteBinaryIdForNote(Writer, Note);
  143. if (OneBinaryIdSize == -1)
  144. return -1;
  145. BinaryIdsSize += OneBinaryIdSize;
  146. /* Calculate the offset of the next note in notes section. */
  147. size_t NoteOffset = sizeof(ElfW(Nhdr)) + RoundUp(Note->n_namesz, 4) +
  148. RoundUp(Note->n_descsz, 4);
  149. Note = (const ElfW(Nhdr) *)((const char *)(Note) + NoteOffset);
  150. }
  151. return BinaryIdsSize;
  152. }
  153. /*
  154. * Write binary ids into profiles if writer is given.
  155. * Return the total size of binary ids.
  156. * If an error happens while writing, return -1.
  157. */
  158. COMPILER_RT_VISIBILITY int __llvm_write_binary_ids(ProfDataWriter *Writer) {
  159. extern const ElfW(Ehdr) __ehdr_start __attribute__((visibility("hidden")));
  160. const ElfW(Ehdr) *ElfHeader = &__ehdr_start;
  161. const ElfW(Phdr) *ProgramHeader =
  162. (const ElfW(Phdr) *)((uintptr_t)ElfHeader + ElfHeader->e_phoff);
  163. int TotalBinaryIdsSize = 0;
  164. uint32_t I;
  165. /* Iterate through entries in the program header. */
  166. for (I = 0; I < ElfHeader->e_phnum; I++) {
  167. /* Look for the notes segment in program header entries. */
  168. if (ProgramHeader[I].p_type != PT_NOTE)
  169. continue;
  170. /* There can be multiple notes segment, and examine each of them. */
  171. const ElfW(Nhdr) * Note;
  172. const ElfW(Nhdr) * NotesEnd;
  173. /*
  174. * When examining notes in file, use p_offset, which is the offset within
  175. * the elf file, to find the start of notes.
  176. */
  177. if (ProgramHeader[I].p_memsz == 0 ||
  178. ProgramHeader[I].p_memsz == ProgramHeader[I].p_filesz) {
  179. Note = (const ElfW(Nhdr) *)((uintptr_t)ElfHeader +
  180. ProgramHeader[I].p_offset);
  181. NotesEnd = (const ElfW(Nhdr) *)((const char *)(Note) +
  182. ProgramHeader[I].p_filesz);
  183. } else {
  184. /*
  185. * When examining notes in memory, use p_vaddr, which is the address of
  186. * section after loaded to memory, to find the start of notes.
  187. */
  188. Note =
  189. (const ElfW(Nhdr) *)((uintptr_t)ElfHeader + ProgramHeader[I].p_vaddr);
  190. NotesEnd =
  191. (const ElfW(Nhdr) *)((const char *)(Note) + ProgramHeader[I].p_memsz);
  192. }
  193. int BinaryIdsSize = WriteBinaryIds(Writer, Note, NotesEnd);
  194. if (TotalBinaryIdsSize == -1)
  195. return -1;
  196. TotalBinaryIdsSize += BinaryIdsSize;
  197. }
  198. return TotalBinaryIdsSize;
  199. }
  200. #else /* !NT_GNU_BUILD_ID */
  201. /*
  202. * Fallback implementation for targets that don't support the GNU
  203. * extensions NT_GNU_BUILD_ID and __ehdr_start.
  204. */
  205. COMPILER_RT_VISIBILITY int __llvm_write_binary_ids(ProfDataWriter *Writer) {
  206. return 0;
  207. }
  208. #endif
  209. #if defined(_AIX)
  210. // Empty stubs to allow linking object files using the registration-based scheme
  211. COMPILER_RT_VISIBILITY
  212. void __llvm_profile_register_function(void *Data_) {}
  213. COMPILER_RT_VISIBILITY
  214. void __llvm_profile_register_names_function(void *NamesStart,
  215. uint64_t NamesSize) {}
  216. // The __start_SECNAME and __stop_SECNAME symbols (for SECNAME \in
  217. // {"__llvm_prf_cnts", "__llvm_prf_data", "__llvm_prf_name", "__llvm_prf_vnds"})
  218. // are always live when linking on AIX, regardless if the .o's being linked
  219. // reference symbols from the profile library (for example when no files were
  220. // compiled with -fprofile-generate). That's because these symbols are kept
  221. // alive through references in constructor functions that are always live in the
  222. // default linking model on AIX (-bcdtors:all). The __start_SECNAME and
  223. // __stop_SECNAME symbols are only resolved by the linker when the SECNAME
  224. // section exists. So for the scenario where the user objects have no such
  225. // section (i.e. when they are compiled with -fno-profile-generate), we always
  226. // define these zero length variables in each of the above 4 sections.
  227. static int dummy_cnts[0] COMPILER_RT_SECTION(
  228. COMPILER_RT_SEG INSTR_PROF_CNTS_SECT_NAME);
  229. static int dummy_data[0] COMPILER_RT_SECTION(
  230. COMPILER_RT_SEG INSTR_PROF_DATA_SECT_NAME);
  231. static const int dummy_name[0] COMPILER_RT_SECTION(
  232. COMPILER_RT_SEG INSTR_PROF_NAME_SECT_NAME);
  233. static int dummy_vnds[0] COMPILER_RT_SECTION(
  234. COMPILER_RT_SEG INSTR_PROF_VNODES_SECT_NAME);
  235. // To avoid GC'ing of the dummy variables by the linker, reference them in an
  236. // array and reference the array in the runtime registration code
  237. // (InstrProfilingRuntime.cpp)
  238. COMPILER_RT_VISIBILITY
  239. void *__llvm_profile_keep[] = {(void *)&dummy_cnts, (void *)&dummy_data,
  240. (void *)&dummy_name, (void *)&dummy_vnds};
  241. #endif
  242. #endif