brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.0 KiB · ce0ce91 Raw
181 lines · cpp
1//===-- SubprocessMemory.cpp ------------------------------------*- 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#include "SubprocessMemory.h"10#include "Error.h"11#include "llvm/ADT/ScopeExit.h"12#include "llvm/Support/Error.h"13#include "llvm/Support/FormatVariadic.h"14#include <cerrno>15 16#ifdef __linux__17#include <fcntl.h>18#include <sys/mman.h>19#include <sys/syscall.h>20#include <unistd.h>21#endif22 23namespace llvm {24namespace exegesis {25 26#if defined(__linux__)27 28// The SYS_* macros for system calls are provided by the libc whereas the29// __NR_* macros are from the linux headers. This means that sometimes30// SYS_* macros might not be available for certain system calls depending31// upon the libc. This happens with the gettid syscall and bionic for32// example, so we use __NR_gettid when no SYS_gettid is available.33#ifndef SYS_gettid34#define SYS_gettid __NR_gettid35#endif36 37long SubprocessMemory::getCurrentTID() {38  // We're using the raw syscall here rather than the gettid() function provided39  // by most libcs for compatibility as gettid() was only added to glibc in40  // version 2.30.41  return syscall(SYS_gettid);42}43 44#if !defined(__ANDROID__)45 46Error SubprocessMemory::initializeSubprocessMemory(pid_t ProcessID) {47  // Add the PID to the shared memory name so that if we're running multiple48  // processes at the same time, they won't interfere with each other.49  // This comes up particularly often when running the exegesis tests with50  // llvm-lit. Additionally add the TID so that downstream consumers51  // using multiple threads don't run into conflicts.52  std::string AuxiliaryMemoryName =53      formatv("/{0}auxmem{1}", getCurrentTID(), ProcessID);54  int AuxiliaryMemoryFD = shm_open(AuxiliaryMemoryName.c_str(),55                                   O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);56  if (AuxiliaryMemoryFD == -1)57    return make_error<Failure>(58        "Failed to create shared memory object for auxiliary memory: " +59        Twine(strerror(errno)));60  auto AuxiliaryMemoryFDClose =61      make_scope_exit([AuxiliaryMemoryFD]() { close(AuxiliaryMemoryFD); });62  if (ftruncate(AuxiliaryMemoryFD, AuxiliaryMemorySize) != 0) {63    return make_error<Failure>("Truncating the auxiliary memory failed: " +64                               Twine(strerror(errno)));65  }66  SharedMemoryNames.push_back(AuxiliaryMemoryName);67  return Error::success();68}69 70Error SubprocessMemory::addMemoryDefinition(71    std::unordered_map<std::string, MemoryValue> MemoryDefinitions,72    pid_t ProcessPID) {73  SharedMemoryNames.reserve(MemoryDefinitions.size());74  for (auto &[Name, MemVal] : MemoryDefinitions) {75    std::string SharedMemoryName =76        formatv("/{0}t{1}memdef{2}", ProcessPID, getCurrentTID(), MemVal.Index);77    SharedMemoryNames.push_back(SharedMemoryName);78    int SharedMemoryFD =79        shm_open(SharedMemoryName.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);80    if (SharedMemoryFD == -1)81      return make_error<Failure>(82          "Failed to create shared memory object for memory definition: " +83          Twine(strerror(errno)));84    auto SharedMemoryFDClose =85        make_scope_exit([SharedMemoryFD]() { close(SharedMemoryFD); });86    if (ftruncate(SharedMemoryFD, MemVal.SizeBytes) != 0) {87      return make_error<Failure>("Truncating a memory definiton failed: " +88                                 Twine(strerror(errno)));89    }90 91    char *SharedMemoryMapping =92        (char *)mmap(NULL, MemVal.SizeBytes, PROT_READ | PROT_WRITE, MAP_SHARED,93                     SharedMemoryFD, 0);94    // fill the buffer with the specified value95    size_t CurrentByte = 0;96    const size_t ValueWidthBytes = MemVal.Value.getBitWidth() / 8;97    while (CurrentByte < MemVal.SizeBytes - ValueWidthBytes) {98      memcpy(SharedMemoryMapping + CurrentByte, MemVal.Value.getRawData(),99             ValueWidthBytes);100      CurrentByte += ValueWidthBytes;101    }102    // fill the last section103    memcpy(SharedMemoryMapping + CurrentByte, MemVal.Value.getRawData(),104           MemVal.SizeBytes - CurrentByte);105    if (munmap(SharedMemoryMapping, MemVal.SizeBytes) != 0) {106      return make_error<Failure>(107          "Unmapping a memory definition in the parent failed: " +108          Twine(strerror(errno)));109    }110  }111  return Error::success();112}113 114Expected<int> SubprocessMemory::setupAuxiliaryMemoryInSubprocess(115    std::unordered_map<std::string, MemoryValue> MemoryDefinitions,116    pid_t ParentPID, long ParentTID, int CounterFileDescriptor) {117  std::string AuxiliaryMemoryName =118      formatv("/{0}auxmem{1}", ParentTID, ParentPID);119  int AuxiliaryMemoryFileDescriptor =120      shm_open(AuxiliaryMemoryName.c_str(), O_RDWR, S_IRUSR | S_IWUSR);121  if (AuxiliaryMemoryFileDescriptor == -1)122    return make_error<Failure>(123        "Getting file descriptor for auxiliary memory failed: " +124        Twine(strerror(errno)));125  // set up memory value file descriptors126  int *AuxiliaryMemoryMapping =127      (int *)mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED,128                  AuxiliaryMemoryFileDescriptor, 0);129  if (reinterpret_cast<intptr_t>(AuxiliaryMemoryMapping) == -1)130    return make_error<Failure>("Mapping auxiliary memory failed");131  AuxiliaryMemoryMapping[0] = CounterFileDescriptor;132  for (auto &[Name, MemVal] : MemoryDefinitions) {133    std::string MemoryValueName =134        formatv("/{0}t{1}memdef{2}", ParentPID, ParentTID, MemVal.Index);135    AuxiliaryMemoryMapping[AuxiliaryMemoryOffset + MemVal.Index] =136        shm_open(MemoryValueName.c_str(), O_RDWR, S_IRUSR | S_IWUSR);137    if (AuxiliaryMemoryMapping[AuxiliaryMemoryOffset + MemVal.Index] == -1)138      return make_error<Failure>("Mapping shared memory failed");139  }140  if (munmap(AuxiliaryMemoryMapping, 4096) == -1)141    return make_error<Failure>("Unmapping auxiliary memory failed");142  return AuxiliaryMemoryFileDescriptor;143}144 145SubprocessMemory::~SubprocessMemory() {146  for (const std::string &SharedMemoryName : SharedMemoryNames) {147    if (shm_unlink(SharedMemoryName.c_str()) != 0) {148      errs() << "Failed to unlink shared memory section: " << strerror(errno)149             << "\n";150    }151  }152}153 154#else155 156Error SubprocessMemory::initializeSubprocessMemory(pid_t ProcessPID) {157  return make_error<Failure>(158      "initializeSubprocessMemory is only supported on Linux");159}160 161Error SubprocessMemory::addMemoryDefinition(162    std::unordered_map<std::string, MemoryValue> MemoryDefinitions,163    pid_t ProcessPID) {164  return make_error<Failure>("addMemoryDefinitions is only supported on Linux");165}166 167Expected<int> SubprocessMemory::setupAuxiliaryMemoryInSubprocess(168    std::unordered_map<std::string, MemoryValue> MemoryDefinitions,169    pid_t ParentPID, long ParentTID, int CounterFileDescriptor) {170  return make_error<Failure>(171      "setupAuxiliaryMemoryInSubprocess is only supported on Linux");172}173 174SubprocessMemory::~SubprocessMemory() {}175 176#endif // !defined(__ANDROID__)177#endif // defined(__linux__)178 179} // namespace exegesis180} // namespace llvm181