/ lib / profile / InstrProfilingBuffer.c
InstrProfilingBuffer.c
  1  /*===- InstrProfilingBuffer.c - Write instrumentation to a memory buffer --===*\
  2  |*
  3  |*                     The LLVM Compiler Infrastructure
  4  |*
  5  |* This file is distributed under the University of Illinois Open Source
  6  |* License. See LICENSE.TXT for details.
  7  |*
  8  \*===----------------------------------------------------------------------===*/
  9  
 10  #include "InstrProfiling.h"
 11  #include "InstrProfilingInternal.h"
 12  
 13  #include <string.h>
 14  
 15  __attribute__((visibility("hidden")))
 16  uint64_t __llvm_profile_get_size_for_buffer(void) {
 17    const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
 18    const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
 19    const uint64_t *CountersBegin = __llvm_profile_begin_counters();
 20    const uint64_t *CountersEnd = __llvm_profile_end_counters();
 21    const char *NamesBegin = __llvm_profile_begin_names();
 22    const char *NamesEnd = __llvm_profile_end_names();
 23  
 24    return __llvm_profile_get_size_for_buffer_internal(
 25        DataBegin, DataEnd, CountersBegin, CountersEnd, NamesBegin, NamesEnd);
 26  }
 27  
 28  #define PROFILE_RANGE_SIZE(Range) (Range##End - Range##Begin)
 29  
 30  __attribute__((visibility("hidden")))
 31  uint64_t __llvm_profile_get_size_for_buffer_internal(
 32          const __llvm_profile_data *DataBegin,
 33          const __llvm_profile_data *DataEnd, const uint64_t *CountersBegin,
 34          const uint64_t *CountersEnd, const char *NamesBegin,
 35          const char *NamesEnd) {
 36    /* Match logic in __llvm_profile_write_buffer(). */
 37    const uint64_t NamesSize = PROFILE_RANGE_SIZE(Names) * sizeof(char);
 38    const uint64_t Padding = sizeof(uint64_t) - NamesSize % sizeof(uint64_t);
 39    return sizeof(__llvm_profile_header) +
 40        PROFILE_RANGE_SIZE(Data) * sizeof(__llvm_profile_data) +
 41        PROFILE_RANGE_SIZE(Counters) * sizeof(uint64_t) +
 42        NamesSize + Padding;
 43  }
 44  
 45  __attribute__((visibility("hidden")))
 46  int __llvm_profile_write_buffer(char *Buffer) {
 47    /* Match logic in __llvm_profile_get_size_for_buffer().
 48     * Match logic in __llvm_profile_write_file().
 49     */
 50    const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
 51    const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
 52    const uint64_t *CountersBegin = __llvm_profile_begin_counters();
 53    const uint64_t *CountersEnd   = __llvm_profile_end_counters();
 54    const char *NamesBegin = __llvm_profile_begin_names();
 55    const char *NamesEnd   = __llvm_profile_end_names();
 56  
 57    return __llvm_profile_write_buffer_internal(Buffer, DataBegin, DataEnd,
 58                                                CountersBegin, CountersEnd,
 59                                                NamesBegin, NamesEnd);
 60  }
 61  
 62  __attribute__((visibility("hidden")))
 63  int __llvm_profile_write_buffer_internal(
 64      char *Buffer, const __llvm_profile_data *DataBegin,
 65      const __llvm_profile_data *DataEnd, const uint64_t *CountersBegin,
 66      const uint64_t *CountersEnd, const char *NamesBegin, const char *NamesEnd) {
 67    /* Match logic in __llvm_profile_get_size_for_buffer().
 68     * Match logic in __llvm_profile_write_file().
 69     */
 70  
 71    /* Calculate size of sections. */
 72    const uint64_t DataSize = DataEnd - DataBegin;
 73    const uint64_t CountersSize = CountersEnd - CountersBegin;
 74    const uint64_t NamesSize = NamesEnd - NamesBegin;
 75    const uint64_t Padding = sizeof(uint64_t) - NamesSize % sizeof(uint64_t);
 76  
 77    /* Enough zeroes for padding. */
 78    const char Zeroes[sizeof(uint64_t)] = {0};
 79  
 80    /* Create the header. */
 81    __llvm_profile_header Header;
 82    Header.Magic = __llvm_profile_get_magic();
 83    Header.Version = __llvm_profile_get_version();
 84    Header.DataSize = DataSize;
 85    Header.CountersSize = CountersSize;
 86    Header.NamesSize = NamesSize;
 87    Header.CountersDelta = (uintptr_t)CountersBegin;
 88    Header.NamesDelta = (uintptr_t)NamesBegin;
 89  
 90    /* Write the data. */
 91  #define UPDATE_memcpy(Data, Size) \
 92    do {                            \
 93      memcpy(Buffer, Data, Size);   \
 94      Buffer += Size;               \
 95    } while (0)
 96    UPDATE_memcpy(&Header,  sizeof(__llvm_profile_header));
 97    UPDATE_memcpy(DataBegin,     DataSize      * sizeof(__llvm_profile_data));
 98    UPDATE_memcpy(CountersBegin, CountersSize  * sizeof(uint64_t));
 99    UPDATE_memcpy(NamesBegin,    NamesSize     * sizeof(char));
100    UPDATE_memcpy(Zeroes,        Padding       * sizeof(char));
101  #undef UPDATE_memcpy
102  
103    return 0;
104  }