brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.3 KiB · 3461f8c Raw
354 lines · c
1//===- bolt/runtime/common.h ------------------------------------*- C++ -*-===//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-exception6//7//===----------------------------------------------------------------------===//8 9#if defined(__linux__)10 11#include <cstddef>12#include <cstdint>13 14#include "config.h"15 16#ifdef HAVE_ELF_H17#include <elf.h>18#endif19 20#elif defined(__APPLE__)21 22typedef __SIZE_TYPE__ size_t;23#define __SSIZE_TYPE__                                                         \24  __typeof__(_Generic((__SIZE_TYPE__)0, unsigned long long int                 \25                      : (long long int)0, unsigned long int                    \26                      : (long int)0, unsigned int                              \27                      : (int)0, unsigned short                                 \28                      : (short)0, unsigned char                                \29                      : (signed char)0))30typedef __SSIZE_TYPE__ ssize_t;31 32typedef unsigned long long uint64_t;33typedef unsigned uint32_t;34typedef unsigned char uint8_t;35 36typedef long long int64_t;37typedef int int32_t;38 39#else40#error "For Linux or MacOS only"41#endif42 43#define PROT_READ 0x1  /* Page can be read.  */44#define PROT_WRITE 0x2 /* Page can be written.  */45#define PROT_EXEC 0x4  /* Page can be executed.  */46#define PROT_NONE 0x0  /* Page can not be accessed.  */47#define PROT_GROWSDOWN                                                         \48  0x01000000 /* Extend change to start of                                      \49                growsdown vma (mprotect only).  */50#define PROT_GROWSUP                                                           \51  0x02000000 /* Extend change to start of                                      \52                growsup vma (mprotect only).  */53 54/* Sharing types (must choose one and only one of these).  */55#define MAP_SHARED 0x01  /* Share changes.  */56#define MAP_PRIVATE 0x02 /* Changes are private.  */57#define MAP_FIXED 0x10   /* Interpret addr exactly.  */58 59#if defined(__APPLE__)60#define MAP_ANONYMOUS 0x100061#else62#define MAP_ANONYMOUS 0x2063#endif64 65#define MAP_FAILED ((void *)-1)66 67#define SEEK_SET 0 /* Seek from beginning of file.  */68#define SEEK_CUR 1 /* Seek from current position.  */69#define SEEK_END 2 /* Seek from end of file.  */70 71#define O_RDONLY 072#define O_WRONLY 173#define O_RDWR 274#define O_CREAT 6475#define O_TRUNC 51276#define O_APPEND 102477 78// Functions that are required by freestanding environment. Compiler may79// generate calls to these implicitly.80extern "C" {81void *memcpy(void *Dest, const void *Src, size_t Len) {82  uint8_t *d = static_cast<uint8_t *>(Dest);83  const uint8_t *s = static_cast<const uint8_t *>(Src);84  while (Len--)85    *d++ = *s++;86  return Dest;87}88 89void *memmove(void *Dest, const void *Src, size_t Len) {90  uint8_t *d = static_cast<uint8_t *>(Dest);91  const uint8_t *s = static_cast<const uint8_t *>(Src);92  if (d < s) {93    while (Len--)94      *d++ = *s++;95  } else {96    s += Len - 1;97    d += Len - 1;98    while (Len--)99      *d-- = *s--;100  }101 102  return Dest;103}104 105void *memset(void *Buf, int C, size_t Size) {106  char *S = (char *)Buf;107  for (size_t I = 0; I < Size; ++I)108    *S++ = C;109  return Buf;110}111 112int memcmp(const void *s1, const void *s2, size_t n) {113  const uint8_t *c1 = static_cast<const uint8_t *>(s1);114  const uint8_t *c2 = static_cast<const uint8_t *>(s2);115  for (; n--; c1++, c2++) {116    if (*c1 != *c2)117      return *c1 < *c2 ? -1 : 1;118  }119  return 0;120}121} // extern "C"122 123// Anonymous namespace covering everything but our library entry point124namespace {125 126struct dirent64 {127  uint64_t d_ino;          /* Inode number */128  int64_t d_off;           /* Offset to next linux_dirent */129  unsigned short d_reclen; /* Length of this linux_dirent */130  unsigned char d_type;131  char d_name[]; /* Filename (null-terminated) */132                 /* length is actually (d_reclen - 2 -133                   offsetof(struct linux_dirent, d_name)) */134};135 136/* Length of the entries in `struct utsname' is 65.  */137#define _UTSNAME_LENGTH 65138 139struct UtsNameTy {140  char sysname[_UTSNAME_LENGTH];  /* Operating system name (e.g., "Linux") */141  char nodename[_UTSNAME_LENGTH]; /* Name within "some implementation-defined142                      network" */143  char release[_UTSNAME_LENGTH]; /* Operating system release (e.g., "2.6.28") */144  char version[_UTSNAME_LENGTH]; /* Operating system version */145  char machine[_UTSNAME_LENGTH]; /* Hardware identifier */146  char domainname[_UTSNAME_LENGTH]; /* NIS or YP domain name */147};148 149struct timespec {150  uint64_t tv_sec;  /* seconds */151  uint64_t tv_nsec; /* nanoseconds */152};153 154#if defined(__aarch64__) || defined(__arm64__)155#include "sys_aarch64.h"156#elif defined(__riscv)157#include "sys_riscv64.h"158#elif defined(__x86_64__)159#include "sys_x86_64.h"160#else161#error "For AArch64/ARM64,X86_64 AND RISCV64 only."162#endif163 164constexpr uint32_t BufSize = 10240;165 166// Helper functions for writing strings to the .fdata file. We intentionally167// avoid using libc names to make it clear it is our impl.168 169/// Write number Num using Base to the buffer in OutBuf, returns a pointer to170/// the end of the string.171char *intToStr(char *OutBuf, uint64_t Num, uint32_t Base) {172  const char *Chars = "0123456789abcdef";173  char Buf[21];174  char *Ptr = Buf;175  while (Num) {176    *Ptr++ = *(Chars + (Num % Base));177    Num /= Base;178  }179  if (Ptr == Buf) {180    *OutBuf++ = '0';181    return OutBuf;182  }183  while (Ptr != Buf)184    *OutBuf++ = *--Ptr;185 186  return OutBuf;187}188 189/// Copy Str to OutBuf, returns a pointer to the end of the copied string190char *strCopy(char *OutBuf, const char *Str, int32_t Size = BufSize) {191  while (*Str) {192    *OutBuf++ = *Str++;193    if (--Size <= 0)194      return OutBuf;195  }196  return OutBuf;197}198 199/// Compare two strings, at most Num bytes.200int strnCmp(const char *Str1, const char *Str2, size_t Num) {201  while (Num && *Str1 && (*Str1 == *Str2)) {202    Num--;203    Str1++;204    Str2++;205  }206  if (Num == 0)207    return 0;208  return *(unsigned char *)Str1 - *(unsigned char *)Str2;209}210 211uint32_t strLen(const char *Str) {212  uint32_t Size = 0;213  while (*Str++)214    ++Size;215  return Size;216}217 218void *strStr(const char *const Haystack, const char *const Needle) {219  int j = 0;220 221  for (int i = 0; i < strLen(Haystack); i++) {222    if (Haystack[i] == Needle[0]) {223      for (j = 1; j < strLen(Needle); j++) {224        if (Haystack[i + j] != Needle[j])225          break;226      }227      if (j == strLen(Needle))228        return (void *)&Haystack[i];229    }230  }231  return nullptr;232}233 234void reportNumber(const char *Msg, uint64_t Num, uint32_t Base) {235  char Buf[BufSize];236  char *Ptr = Buf;237  Ptr = strCopy(Ptr, Msg, BufSize - 23);238  Ptr = intToStr(Ptr, Num, Base);239  Ptr = strCopy(Ptr, "\n");240  __write(2, Buf, Ptr - Buf);241}242 243void report(const char *Msg) { __write(2, Msg, strLen(Msg)); }244 245unsigned long hexToLong(const char *Str, char Terminator = '\0') {246  unsigned long Res = 0;247  while (*Str != Terminator) {248    Res <<= 4;249    if ('0' <= *Str && *Str <= '9')250      Res += *Str++ - '0';251    else if ('a' <= *Str && *Str <= 'f')252      Res += *Str++ - 'a' + 10;253    else if ('A' <= *Str && *Str <= 'F')254      Res += *Str++ - 'A' + 10;255    else256      return 0;257  }258  return Res;259}260 261/// Starting from character at \p buf, find the longest consecutive sequence262/// of digits (0-9) and convert it to uint32_t. The converted value263/// is put into \p ret. \p end marks the end of the buffer to avoid buffer264/// overflow. The function \returns whether a valid uint32_t value is found.265/// \p buf will be updated to the next character right after the digits.266static bool scanUInt32(const char *&Buf, const char *End, uint32_t &Ret) {267  uint64_t Result = 0;268  const char *OldBuf = Buf;269  while (Buf < End && ((*Buf) >= '0' && (*Buf) <= '9')) {270    Result = Result * 10 + (*Buf) - '0';271    ++Buf;272  }273  if (OldBuf != Buf && Result <= 0xFFFFFFFFu) {274    Ret = static_cast<uint32_t>(Result);275    return true;276  }277  return false;278}279 280void reportError(const char *Msg, uint64_t Size) {281  __write(2, Msg, Size);282  __exit(1);283}284 285void assert(bool Assertion, const char *Msg) {286  if (Assertion)287    return;288  char Buf[BufSize];289  char *Ptr = Buf;290  Ptr = strCopy(Ptr, "Assertion failed: ");291  Ptr = strCopy(Ptr, Msg, BufSize - 40);292  Ptr = strCopy(Ptr, "\n");293  reportError(Buf, Ptr - Buf);294}295 296#define SIG_BLOCK 0297#define SIG_UNBLOCK 1298#define SIG_SETMASK 2299 300static const uint64_t MaskAllSignals[] = {-1ULL};301 302class Mutex {303  volatile bool InUse{false};304 305public:306  bool acquire() { return !__atomic_test_and_set(&InUse, __ATOMIC_ACQUIRE); }307  void release() { __atomic_clear(&InUse, __ATOMIC_RELEASE); }308};309 310/// RAII wrapper for Mutex311class Lock {312  Mutex &M;313  uint64_t SignalMask[1] = {};314 315public:316  Lock(Mutex &M) : M(M) {317    __sigprocmask(SIG_BLOCK, MaskAllSignals, SignalMask);318    while (!M.acquire()) {319    }320  }321 322  ~Lock() {323    M.release();324    __sigprocmask(SIG_SETMASK, SignalMask, nullptr);325  }326};327 328/// RAII wrapper for Mutex329class TryLock {330  Mutex &M;331  bool Locked = false;332 333public:334  TryLock(Mutex &M) : M(M) {335    int Retry = 100;336    while (--Retry && !M.acquire())337      ;338    if (Retry)339      Locked = true;340  }341  bool isLocked() { return Locked; }342 343  ~TryLock() {344    if (isLocked())345      M.release();346  }347};348 349inline uint64_t alignTo(uint64_t Value, uint64_t Align) {350  return (Value + Align - 1) / Align * Align;351}352 353} // anonymous namespace354