#if defined(_AIX)
#ifdef __64BIT__
#define __XCOFF64__
#endif
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ldr.h>
#include <xcoff.h>
#include "InstrProfiling.h"
#include "InstrProfilingInternal.h"
#define BIN_ID_PREFIX …
static size_t FindBinaryId(char *Result, size_t Size) {
unsigned long EntryAddr = (unsigned long)__builtin_return_address(0);
char Buf[1024];
size_t BufSize = sizeof(Buf);
char *BufPtr = Buf;
int RC = -1;
errno = 0;
RC = loadquery(L_GETXINFO | L_IGNOREUNLOAD, BufPtr, (unsigned int)BufSize);
if (RC == -1 && errno == ENOMEM) {
BufSize = 64000;
BufPtr = malloc(BufSize);
if (BufPtr != 0)
RC = loadquery(L_GETXINFO | L_IGNOREUNLOAD, BufPtr, (unsigned int)BufSize);
}
if (RC == -1)
goto done;
struct ld_xinfo *CurInfo = (struct ld_xinfo *)BufPtr;
while (1) {
unsigned long CurTextStart = (uint64_t)CurInfo->ldinfo_textorg;
unsigned long CurTextEnd = CurTextStart + CurInfo->ldinfo_textsize;
if (CurTextStart <= EntryAddr && EntryAddr < CurTextEnd) {
char *p = (char *)CurInfo->ldinfo_textorg;
FILHDR *f = (FILHDR *)p;
AOUTHDR *a = (AOUTHDR *)(p + FILHSZ);
SCNHDR *s =
(SCNHDR *)(p + FILHSZ + f->f_opthdr + SCNHSZ * (a->o_snloader - 1));
LDHDR *ldhdr = (LDHDR *)(p + s->s_scnptr);
char *lstr = (char *)ldhdr + ldhdr->l_stoff;
size_t len = *(short *)lstr;
char *str = (char *)(lstr + 2);
size_t PrefixLen = sizeof(BIN_ID_PREFIX) - 1;
if (len > PrefixLen && (len - PrefixLen) <= Size &&
strncmp(str, BIN_ID_PREFIX, PrefixLen) == 0) {
memcpy(Result, str + PrefixLen, len - PrefixLen);
RC = len - PrefixLen;
goto done;
}
break;
}
if (CurInfo->ldinfo_next == 0u)
break;
CurInfo = (struct ld_xinfo *)((char *)CurInfo + CurInfo->ldinfo_next);
}
done:
if (BufSize != sizeof(Buf) && BufPtr != 0)
free(BufPtr);
return RC;
}
static int StrToHexError = 0;
static uint8_t StrToHex(char c) {
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'a' && c <= 'f')
return c - 'a' + 0xa;
if (c >= 'A' && c <= 'F')
return c - 'A' + 0xa;
StrToHexError = 1;
return 0;
}
COMPILER_RT_VISIBILITY int __llvm_write_binary_ids(ProfDataWriter *Writer) {
static char Buf[200];
static int64_t BinaryIdLen = 0;
static uint8_t *BinaryIdData = 0;
if (BinaryIdLen == -1)
return 0;
if (BinaryIdLen == 0) {
if (getenv("LLVM_PROFILE_NO_BUILD_ID"))
goto fail;
int BuildIdLen = FindBinaryId(Buf, sizeof(Buf));
if (BuildIdLen <= 0)
goto fail;
if (Buf[BuildIdLen - 1] == '\0')
BuildIdLen--;
if ((BuildIdLen % 2) != 0 || BuildIdLen == 0)
goto fail;
BinaryIdLen = BuildIdLen / 2;
BinaryIdData = (uint8_t *)Buf;
if (Buf[0] == '0' && Buf[1] == 'x') {
BinaryIdLen -= 1;
BinaryIdData += 2;
}
StrToHexError = 0;
for (int i = 0; i < BinaryIdLen; i++)
BinaryIdData[i] = (StrToHex(BinaryIdData[2 * i]) << 4) +
StrToHex(BinaryIdData[2 * i + 1]);
if (StrToHexError)
goto fail;
if (getenv("LLVM_PROFILE_VERBOSE")) {
char *StrBuf = (char *)COMPILER_RT_ALLOCA(2 * BinaryIdLen + 1);
for (int i = 0; i < (int)BinaryIdLen; i++)
sprintf(&StrBuf[2 * i], "%02x", BinaryIdData[i]);
PROF_NOTE("Writing binary id: %s\n", StrBuf);
}
}
uint8_t BinaryIdPadding = __llvm_profile_get_num_padding_bytes(BinaryIdLen);
if (Writer && lprofWriteOneBinaryId(Writer, BinaryIdLen, BinaryIdData,
BinaryIdPadding) == -1)
return -1;
return sizeof(BinaryIdLen) + BinaryIdLen + BinaryIdPadding;
fail:
if (getenv("LLVM_PROFILE_VERBOSE"))
fprintf(stderr, "no or invalid binary id: %.*s\n", (int)sizeof(Buf), Buf);
BinaryIdLen = -1;
return 0;
}
COMPILER_RT_VISIBILITY
void __llvm_profile_register_function(void *Data_) {}
COMPILER_RT_VISIBILITY
void __llvm_profile_register_names_function(void *NamesStart,
uint64_t NamesSize) {}
static int dummy_cnts[0] COMPILER_RT_SECTION(
COMPILER_RT_SEG INSTR_PROF_CNTS_SECT_NAME);
static int dummy_bits[0] COMPILER_RT_SECTION(
COMPILER_RT_SEG INSTR_PROF_BITS_SECT_NAME);
static int dummy_data[0] COMPILER_RT_SECTION(
COMPILER_RT_SEG INSTR_PROF_DATA_SECT_NAME);
static const int dummy_name[0] COMPILER_RT_SECTION(
COMPILER_RT_SEG INSTR_PROF_NAME_SECT_NAME);
static int dummy_vnds[0] COMPILER_RT_SECTION(
COMPILER_RT_SEG INSTR_PROF_VNODES_SECT_NAME);
static int dummy_orderfile[0] COMPILER_RT_SECTION(
COMPILER_RT_SEG INSTR_PROF_ORDERFILE_SECT_NAME);
static int dummy_vname[0] COMPILER_RT_SECTION(
COMPILER_RT_SEG INSTR_PROF_VNAME_SECT_NAME);
static int dummy_vtab[0] COMPILER_RT_SECTION(
COMPILER_RT_SEG INSTR_PROF_VTAB_SECT_NAME);
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-qual"
#endif
COMPILER_RT_VISIBILITY
void *__llvm_profile_keep[] = {(void *)&dummy_cnts, (void *)&dummy_bits,
(void *)&dummy_data, (void *)&dummy_name,
(void *)&dummy_vnds, (void *)&dummy_orderfile,
(void *)&dummy_vname, (void *)&dummy_vtab};
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#endif