Skip to content

Commit

Permalink
Merge pull request #24 from Amanieu/v10
Browse files Browse the repository at this point in the history
  • Loading branch information
Amanieu authored Oct 23, 2024
2 parents 6db9ae0 + 8b3c9fb commit 41b5d55
Show file tree
Hide file tree
Showing 10 changed files with 292 additions and 56 deletions.
37 changes: 29 additions & 8 deletions minicov/c/InstrProfiling.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ typedef struct ValueProfNode {
#include "profile/InstrProfData.inc"
} ValueProfNode;

typedef struct COMPILER_RT_ALIGNAS(INSTR_PROF_DATA_ALIGNMENT) VTableProfData {
#define INSTR_PROF_VTABLE_DATA(Type, LLVMType, Name, Initializer) Type Name;
#include "profile/InstrProfData.inc"
} VTableProfData;

/*!
* \brief Return 1 if profile counters are continuously synced to the raw
* profile via an mmap(). This is in contrast to the default mode, in which
Expand Down Expand Up @@ -102,12 +107,16 @@ const __llvm_profile_data *__llvm_profile_begin_data(void);
const __llvm_profile_data *__llvm_profile_end_data(void);
const char *__llvm_profile_begin_names(void);
const char *__llvm_profile_end_names(void);
const char *__llvm_profile_begin_vtabnames(void);
const char *__llvm_profile_end_vtabnames(void);
char *__llvm_profile_begin_counters(void);
char *__llvm_profile_end_counters(void);
char *__llvm_profile_begin_bitmap(void);
char *__llvm_profile_end_bitmap(void);
ValueProfNode *__llvm_profile_begin_vnodes();
ValueProfNode *__llvm_profile_end_vnodes();
const VTableProfData *__llvm_profile_begin_vtables();
const VTableProfData *__llvm_profile_end_vtables();
uint32_t *__llvm_profile_begin_orderfile();

/*!
Expand Down Expand Up @@ -251,20 +260,31 @@ uint64_t __llvm_profile_get_num_bitmap_bytes(const char *Begin,
/*! \brief Get the size of the profile name section in bytes. */
uint64_t __llvm_profile_get_name_size(const char *Begin, const char *End);

/* ! \brief Given the sizes of the data and counter information, return the
* number of padding bytes before and after the counters, and after the names,
* in the raw profile.
/*! \brief Get the number of virtual table profile data entries */
uint64_t __llvm_profile_get_num_vtable(const VTableProfData *Begin,
const VTableProfData *End);

/*! \brief Get the size of virtual table profile data in bytes. */
uint64_t __llvm_profile_get_vtable_section_size(const VTableProfData *Begin,
const VTableProfData *End);

/* ! \brief Given the sizes of the data and counter information, computes the
* number of padding bytes before and after the counter section, as well as the
* number of padding bytes after other setions in the raw profile.
* Returns -1 upon errors and 0 upon success. Output parameters should be used
* iff return value is 0.
*
* Note: When mmap() mode is disabled, no padding bytes before/after counters
* are needed. However, in mmap() mode, the counter section in the raw profile
* must be page-aligned: this API computes the number of padding bytes
* needed to achieve that.
*/
void __llvm_profile_get_padding_sizes_for_counters(
int __llvm_profile_get_padding_sizes_for_counters(
uint64_t DataSize, uint64_t CountersSize, uint64_t NumBitmapBytes,
uint64_t NamesSize, uint64_t *PaddingBytesBeforeCounters,
uint64_t *PaddingBytesAfterCounters, uint64_t *PaddingBytesAfterBitmap,
uint64_t *PaddingBytesAfterNames);
uint64_t NamesSize, uint64_t VTableSize, uint64_t VNameSize,
uint64_t *PaddingBytesBeforeCounters, uint64_t *PaddingBytesAfterCounters,
uint64_t *PaddingBytesAfterBitmap, uint64_t *PaddingBytesAfterNames,
uint64_t *PaddingBytesAfterVTable, uint64_t *PaddingBytesAfterVNames);

/*!
* \brief Set the flag that profile data has been dumped to the file.
Expand Down Expand Up @@ -293,7 +313,8 @@ COMPILER_RT_VISIBILITY extern int INSTR_PROF_PROFILE_RUNTIME_VAR;
* variable is defined as weak so that compiler can emit an overriding
* definition depending on user option.
*/
extern uint64_t INSTR_PROF_RAW_VERSION_VAR; /* __llvm_profile_raw_version */
COMPILER_RT_VISIBILITY extern uint64_t
INSTR_PROF_RAW_VERSION_VAR; /* __llvm_profile_raw_version */

/*!
* This variable is a weak symbol defined in InstrProfiling.c. It allows
Expand Down
89 changes: 74 additions & 15 deletions minicov/c/InstrProfilingBuffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,18 @@ uint64_t __llvm_profile_get_size_for_buffer(void) {
const char *BitmapEnd = __llvm_profile_end_bitmap();
const char *NamesBegin = __llvm_profile_begin_names();
const char *NamesEnd = __llvm_profile_end_names();
const VTableProfData *VTableBegin = __llvm_profile_begin_vtables();
const VTableProfData *VTableEnd = __llvm_profile_end_vtables();
const char *VNamesBegin = __llvm_profile_begin_vtabnames();
const char *VNamesEnd = __llvm_profile_end_vtabnames();

return __llvm_profile_get_size_for_buffer_internal(
DataBegin, DataEnd, CountersBegin, CountersEnd, BitmapBegin, BitmapEnd,
NamesBegin, NamesEnd);
NamesBegin, NamesEnd, VTableBegin, VTableEnd, VNamesBegin, VNamesEnd);
}

// NOTE: Caller should guarantee that `Begin` and `End` specifies a half-open
// interval [Begin, End). Namely, `End` is one-byte past the end of the array.
COMPILER_RT_VISIBILITY
uint64_t __llvm_profile_get_num_data(const __llvm_profile_data *Begin,
const __llvm_profile_data *End) {
Expand All @@ -71,6 +77,26 @@ uint64_t __llvm_profile_get_data_size(const __llvm_profile_data *Begin,
return __llvm_profile_get_num_data(Begin, End) * sizeof(__llvm_profile_data);
}

// Counts the number of `VTableProfData` elements within the range of [Begin,
// End). Caller should guarantee that End points to one byte past the inclusive
// range.
// FIXME: Add a compiler-rt test to make sure the number of vtables in the
// raw profile is the same as the number of vtable elements in the instrumented
// binary.
COMPILER_RT_VISIBILITY
uint64_t __llvm_profile_get_num_vtable(const VTableProfData *Begin,
const VTableProfData *End) {
// Convert pointers to intptr_t to use integer arithmetic.
intptr_t EndI = (intptr_t)End, BeginI = (intptr_t)Begin;
return (EndI - BeginI) / sizeof(VTableProfData);
}

COMPILER_RT_VISIBILITY
uint64_t __llvm_profile_get_vtable_section_size(const VTableProfData *Begin,
const VTableProfData *End) {
return (intptr_t)(End) - (intptr_t)(Begin);
}

COMPILER_RT_VISIBILITY size_t __llvm_profile_counter_entry_size(void) {
if (__llvm_profile_get_version() & VARIANT_MASK_BYTE_COVERAGE)
return sizeof(uint8_t);
Expand Down Expand Up @@ -119,21 +145,33 @@ static int needsCounterPadding(void) {
}

COMPILER_RT_VISIBILITY
void __llvm_profile_get_padding_sizes_for_counters(
int __llvm_profile_get_padding_sizes_for_counters(
uint64_t DataSize, uint64_t CountersSize, uint64_t NumBitmapBytes,
uint64_t NamesSize, uint64_t *PaddingBytesBeforeCounters,
uint64_t *PaddingBytesAfterCounters, uint64_t *PaddingBytesAfterBitmapBytes,
uint64_t *PaddingBytesAfterNames) {
uint64_t NamesSize, uint64_t VTableSize, uint64_t VNameSize,
uint64_t *PaddingBytesBeforeCounters, uint64_t *PaddingBytesAfterCounters,
uint64_t *PaddingBytesAfterBitmapBytes, uint64_t *PaddingBytesAfterNames,
uint64_t *PaddingBytesAfterVTable, uint64_t *PaddingBytesAfterVName) {
// Counter padding is needed only if continuous mode is enabled.
if (!needsCounterPadding()) {
*PaddingBytesBeforeCounters = 0;
*PaddingBytesAfterCounters =
__llvm_profile_get_num_padding_bytes(CountersSize);
*PaddingBytesAfterBitmapBytes =
__llvm_profile_get_num_padding_bytes(NumBitmapBytes);
*PaddingBytesAfterNames = __llvm_profile_get_num_padding_bytes(NamesSize);
return;
if (PaddingBytesAfterVTable != NULL)
*PaddingBytesAfterVTable =
__llvm_profile_get_num_padding_bytes(VTableSize);
if (PaddingBytesAfterVName != NULL)
*PaddingBytesAfterVName = __llvm_profile_get_num_padding_bytes(VNameSize);
return 0;
}

// Value profiling not supported in continuous mode at profile-write time.
// Return -1 to alert the incompatibility.
if (VTableSize != 0 || VNameSize != 0)
return -1;

// In continuous mode, the file offsets for headers and for the start of
// counter sections need to be page-aligned.
*PaddingBytesBeforeCounters =
Expand All @@ -142,34 +180,52 @@ void __llvm_profile_get_padding_sizes_for_counters(
*PaddingBytesAfterBitmapBytes =
calculateBytesNeededToPageAlign(NumBitmapBytes);
*PaddingBytesAfterNames = calculateBytesNeededToPageAlign(NamesSize);
// Set these two variables to zero to avoid uninitialized variables
// even if VTableSize and VNameSize are known to be zero.
if (PaddingBytesAfterVTable != NULL)
*PaddingBytesAfterVTable = 0;
if (PaddingBytesAfterVName != NULL)
*PaddingBytesAfterVName = 0;
return 0;
}

COMPILER_RT_VISIBILITY
uint64_t __llvm_profile_get_size_for_buffer_internal(
const __llvm_profile_data *DataBegin, const __llvm_profile_data *DataEnd,
const char *CountersBegin, const char *CountersEnd, const char *BitmapBegin,
const char *BitmapEnd, const char *NamesBegin, const char *NamesEnd) {
const char *BitmapEnd, const char *NamesBegin, const char *NamesEnd,
const VTableProfData *VTableBegin, const VTableProfData *VTableEnd,
const char *VNamesBegin, const char *VNamesEnd) {
/* Match logic in __llvm_profile_write_buffer(). */
const uint64_t NamesSize = (NamesEnd - NamesBegin) * sizeof(char);
uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd);
uint64_t CountersSize =
__llvm_profile_get_counters_size(CountersBegin, CountersEnd);
const uint64_t NumBitmapBytes =
__llvm_profile_get_num_bitmap_bytes(BitmapBegin, BitmapEnd);
const uint64_t VTableSize =
__llvm_profile_get_vtable_section_size(VTableBegin, VTableEnd);
const uint64_t VNameSize =
__llvm_profile_get_name_size(VNamesBegin, VNamesEnd);

/* Determine how much padding is needed before/after the counters and after
* the names. */
uint64_t PaddingBytesBeforeCounters, PaddingBytesAfterCounters,
PaddingBytesAfterNames, PaddingBytesAfterBitmapBytes;
PaddingBytesAfterNames, PaddingBytesAfterBitmapBytes,
PaddingBytesAfterVTable, PaddingBytesAfterVNames;
__llvm_profile_get_padding_sizes_for_counters(
DataSize, CountersSize, NumBitmapBytes, NamesSize,
&PaddingBytesBeforeCounters, &PaddingBytesAfterCounters,
&PaddingBytesAfterBitmapBytes, &PaddingBytesAfterNames);
DataSize, CountersSize, NumBitmapBytes, NamesSize, 0 /* VTableSize */,
0 /* VNameSize */, &PaddingBytesBeforeCounters,
&PaddingBytesAfterCounters, &PaddingBytesAfterBitmapBytes,
&PaddingBytesAfterNames, &PaddingBytesAfterVTable,
&PaddingBytesAfterVNames);

return sizeof(__llvm_profile_header) + __llvm_write_binary_ids(NULL) +
DataSize + PaddingBytesBeforeCounters + CountersSize +
PaddingBytesAfterCounters + NumBitmapBytes +
PaddingBytesAfterBitmapBytes + NamesSize + PaddingBytesAfterNames;
PaddingBytesAfterBitmapBytes + NamesSize + PaddingBytesAfterNames +
VTableSize + PaddingBytesAfterVTable + VNameSize +
PaddingBytesAfterVNames;
}

COMPILER_RT_VISIBILITY
Expand All @@ -191,7 +247,10 @@ COMPILER_RT_VISIBILITY int __llvm_profile_write_buffer_internal(
const char *NamesBegin, const char *NamesEnd) {
ProfDataWriter BufferWriter;
initBufferWriter(&BufferWriter, Buffer);
return lprofWriteDataImpl(&BufferWriter, DataBegin, DataEnd, CountersBegin,
CountersEnd, BitmapBegin, BitmapEnd, 0, NamesBegin,
NamesEnd, 0);
// Set virtual table arguments to NULL since they are not supported yet.
return lprofWriteDataImpl(
&BufferWriter, DataBegin, DataEnd, CountersBegin, CountersEnd,
BitmapBegin, BitmapEnd, /*VPDataReader=*/0, NamesBegin, NamesEnd,
/*VTableBegin=*/NULL, /*VTableEnd=*/NULL, /*VNamesBegin=*/NULL,
/*VNamesEnd=*/NULL, /*SkipNameDataWrite=*/0);
}
8 changes: 6 additions & 2 deletions minicov/c/InstrProfilingInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
uint64_t __llvm_profile_get_size_for_buffer_internal(
const __llvm_profile_data *DataBegin, const __llvm_profile_data *DataEnd,
const char *CountersBegin, const char *CountersEnd, const char *BitmapBegin,
const char *BitmapEnd, const char *NamesBegin, const char *NamesEnd);
const char *BitmapEnd, const char *NamesBegin, const char *NamesEnd,
const VTableProfData *VTableBegin, const VTableProfData *VTableEnd,
const char *VNamesBegin, const char *VNamesEnd);

/*!
* \brief Write instrumentation data to the given buffer, given explicit
Expand Down Expand Up @@ -156,7 +158,9 @@ int lprofWriteDataImpl(ProfDataWriter *Writer,
const char *CountersBegin, const char *CountersEnd,
const char *BitmapBegin, const char *BitmapEnd,
VPDataReaderType *VPDataReader, const char *NamesBegin,
const char *NamesEnd, int SkipNameDataWrite);
const char *NamesEnd, const VTableProfData *VTableBegin,
const VTableProfData *VTableEnd, const char *VNamesBegin,
const char *VNamesEnd, int SkipNameDataWrite);

/* Merge value profile data pointed to by SrcValueProfData into
* in-memory profile counters pointed by to DstData. */
Expand Down
23 changes: 21 additions & 2 deletions minicov/c/InstrProfilingMerge.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,26 @@ static uintptr_t signextIfWin64(void *V) {
#endif
}

// Skip names section, vtable profile data section and vtable names section
// for runtime profile merge. To merge runtime addresses from multiple
// profiles collected from the same instrumented binary, the binary should be
// loaded at fixed base address (e.g., build with -no-pie, or run with ASLR
// disabled). In this set-up these three sections remain unchanged.
static uint64_t
getDistanceFromCounterToValueProf(const __llvm_profile_header *const Header) {
const uint64_t VTableSectionSize =
Header->NumVTables * sizeof(VTableProfData);
const uint64_t PaddingBytesAfterVTableSection =
__llvm_profile_get_num_padding_bytes(VTableSectionSize);
const uint64_t VNamesSize = Header->VNamesSize;
const uint64_t PaddingBytesAfterVNamesSize =
__llvm_profile_get_num_padding_bytes(VNamesSize);
return Header->NamesSize +
__llvm_profile_get_num_padding_bytes(Header->NamesSize) +
VTableSectionSize + PaddingBytesAfterVTableSection + VNamesSize +
PaddingBytesAfterVNamesSize;
}

COMPILER_RT_VISIBILITY
int __llvm_profile_merge_from_buffer(const char *ProfileData,
uint64_t ProfileSize) {
Expand Down Expand Up @@ -136,8 +156,7 @@ int __llvm_profile_merge_from_buffer(const char *ProfileData,
SrcBitmapStart = SrcCountersEnd;
SrcNameStart = SrcBitmapStart + Header->NumBitmapBytes;
SrcValueProfDataStart =
SrcNameStart + Header->NamesSize +
__llvm_profile_get_num_padding_bytes(Header->NamesSize);
SrcNameStart + getDistanceFromCounterToValueProf(Header);
if (SrcNameStart < SrcCountersStart || SrcNameStart < SrcBitmapStart)
return 1;

Expand Down
21 changes: 21 additions & 0 deletions minicov/c/InstrProfilingPlatformLinux.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@
#define PROF_DATA_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_DATA_COMMON)
#define PROF_NAME_START INSTR_PROF_SECT_START(INSTR_PROF_NAME_COMMON)
#define PROF_NAME_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_NAME_COMMON)
#define PROF_VNAME_START INSTR_PROF_SECT_START(INSTR_PROF_VNAME_COMMON)
#define PROF_VNAME_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_VNAME_COMMON)
#define PROF_CNTS_START INSTR_PROF_SECT_START(INSTR_PROF_CNTS_COMMON)
#define PROF_CNTS_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_CNTS_COMMON)
#define PROF_VTABLE_START INSTR_PROF_SECT_START(INSTR_PROF_VTAB_COMMON)
#define PROF_VTABLE_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_VTAB_COMMON)
#define PROF_BITS_START INSTR_PROF_SECT_START(INSTR_PROF_BITS_COMMON)
#define PROF_BITS_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_BITS_COMMON)
#define PROF_ORDERFILE_START INSTR_PROF_SECT_START(INSTR_PROF_ORDERFILE_COMMON)
Expand All @@ -34,6 +38,10 @@ extern __llvm_profile_data PROF_DATA_STOP COMPILER_RT_VISIBILITY
COMPILER_RT_WEAK;
extern char PROF_CNTS_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
extern char PROF_CNTS_STOP COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
extern VTableProfData PROF_VTABLE_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
extern VTableProfData PROF_VTABLE_STOP COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
extern char PROF_VNAME_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
extern char PROF_VNAME_STOP COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
extern char PROF_BITS_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
extern char PROF_BITS_STOP COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
extern uint32_t PROF_ORDERFILE_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
Expand All @@ -56,6 +64,19 @@ COMPILER_RT_VISIBILITY const char *__llvm_profile_begin_names(void) {
COMPILER_RT_VISIBILITY const char *__llvm_profile_end_names(void) {
return &PROF_NAME_STOP;
}
COMPILER_RT_VISIBILITY const char *__llvm_profile_begin_vtabnames(void) {
return &PROF_VNAME_START;
}
COMPILER_RT_VISIBILITY const char *__llvm_profile_end_vtabnames(void) {
return &PROF_VNAME_STOP;
}
COMPILER_RT_VISIBILITY const VTableProfData *
__llvm_profile_begin_vtables(void) {
return &PROF_VTABLE_START;
}
COMPILER_RT_VISIBILITY const VTableProfData *__llvm_profile_end_vtables(void) {
return &PROF_VTABLE_STOP;
}
COMPILER_RT_VISIBILITY char *__llvm_profile_begin_counters(void) {
return &PROF_CNTS_START;
}
Expand Down
15 changes: 15 additions & 0 deletions minicov/c/InstrProfilingPlatformOther.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@

static const __llvm_profile_data *DataFirst = NULL;
static const __llvm_profile_data *DataLast = NULL;
static const VTableProfData *VTableProfDataFirst = NULL;
static const VTableProfData *VTableProfDataLast = NULL;
static const char *NamesFirst = NULL;
static const char *NamesLast = NULL;
static const char *VNamesFirst = NULL;
static const char *VNamesLast = NULL;
static const char *BitmapFirst = NULL;
static const char *BitmapLast = NULL;
static char *CountersFirst = NULL;
Expand Down Expand Up @@ -81,11 +85,22 @@ COMPILER_RT_VISIBILITY
const __llvm_profile_data *__llvm_profile_begin_data(void) { return DataFirst; }
COMPILER_RT_VISIBILITY
const __llvm_profile_data *__llvm_profile_end_data(void) { return DataLast; }
COMPILER_RT_VISIBILITY const VTableProfData *
__llvm_profile_begin_vtables(void) {
return VTableProfDataFirst;
}
COMPILER_RT_VISIBILITY const VTableProfData *__llvm_profile_end_vtables(void) {
return VTableProfDataLast;
}
COMPILER_RT_VISIBILITY
const char *__llvm_profile_begin_names(void) { return NamesFirst; }
COMPILER_RT_VISIBILITY
const char *__llvm_profile_end_names(void) { return NamesLast; }
COMPILER_RT_VISIBILITY
const char *__llvm_profile_begin_vtabnames(void) { return VNamesFirst; }
COMPILER_RT_VISIBILITY
const char *__llvm_profile_end_vtabnames(void) { return VNamesLast; }
COMPILER_RT_VISIBILITY
char *__llvm_profile_begin_counters(void) { return CountersFirst; }
COMPILER_RT_VISIBILITY
char *__llvm_profile_end_counters(void) { return CountersLast; }
Expand Down
Loading

0 comments on commit 41b5d55

Please sign in to comment.