1 //===-- SubprocessMemory.cpp ------------------------------------*- C++ -*-===//
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-exception
7 //===----------------------------------------------------------------------===//
9 #include "SubprocessMemory.h"
11 #include "llvm/Support/Error.h"
23 #if defined(__linux__) && !defined(__ANDROID__)
25 Error
SubprocessMemory::initializeSubprocessMemory(pid_t ProcessID
) {
26 // Add the PID to the shared memory name so that if we're running multiple
27 // processes at the same time, they won't interfere with each other.
28 // This comes up particularly often when running the exegesis tests with
30 std::string AuxiliaryMemoryName
= "/auxmem" + std::to_string(ProcessID
);
31 int AuxiliaryMemoryFD
= shm_open(AuxiliaryMemoryName
.c_str(),
32 O_RDWR
| O_CREAT
, S_IRUSR
| S_IWUSR
);
33 if (AuxiliaryMemoryFD
== -1)
34 return make_error
<Failure
>(
35 "Failed to create shared memory object for auxiliary memory: " +
36 Twine(strerror(errno
)));
37 if (ftruncate(AuxiliaryMemoryFD
, AuxiliaryMemorySize
) != 0) {
38 return make_error
<Failure
>("Truncating the auxiliary memory failed: " +
39 Twine(strerror(errno
)));
41 SharedMemoryNames
.push_back(AuxiliaryMemoryName
);
42 return Error::success();
45 Error
SubprocessMemory::addMemoryDefinition(
46 std::unordered_map
<std::string
, MemoryValue
> MemoryDefinitions
,
48 SharedMemoryNames
.reserve(MemoryDefinitions
.size());
49 for (auto &[Name
, MemVal
] : MemoryDefinitions
) {
50 std::string SharedMemoryName
= "/" + std::to_string(ProcessPID
) + "memdef" +
51 std::to_string(MemVal
.Index
);
52 SharedMemoryNames
.push_back(SharedMemoryName
);
54 shm_open(SharedMemoryName
.c_str(), O_RDWR
| O_CREAT
, S_IRUSR
| S_IWUSR
);
55 if (ftruncate(SharedMemoryFD
, MemVal
.SizeBytes
) != 0) {
56 return make_error
<Failure
>("Truncating a memory definiton failed: " +
57 Twine(strerror(errno
)));
60 char *SharedMemoryMapping
=
61 (char *)mmap(NULL
, MemVal
.SizeBytes
, PROT_READ
| PROT_WRITE
, MAP_SHARED
,
63 // fill the buffer with the specified value
64 size_t CurrentByte
= 0;
65 const size_t ValueWidthBytes
= MemVal
.Value
.getBitWidth() / 8;
66 while (CurrentByte
< MemVal
.SizeBytes
- ValueWidthBytes
) {
67 memcpy(SharedMemoryMapping
+ CurrentByte
, MemVal
.Value
.getRawData(),
69 CurrentByte
+= ValueWidthBytes
;
71 // fill the last section
72 memcpy(SharedMemoryMapping
+ CurrentByte
, MemVal
.Value
.getRawData(),
73 MemVal
.SizeBytes
- CurrentByte
);
74 if (munmap(SharedMemoryMapping
, MemVal
.SizeBytes
) != 0) {
75 return make_error
<Failure
>(
76 "Unmapping a memory definition in the parent failed: " +
77 Twine(strerror(errno
)));
80 return Error::success();
83 Expected
<int> SubprocessMemory::setupAuxiliaryMemoryInSubprocess(
84 std::unordered_map
<std::string
, MemoryValue
> MemoryDefinitions
,
85 pid_t ParentPID
, int CounterFileDescriptor
) {
86 std::string AuxiliaryMemoryName
= "/auxmem" + std::to_string(ParentPID
);
87 int AuxiliaryMemoryFileDescriptor
=
88 shm_open(AuxiliaryMemoryName
.c_str(), O_RDWR
, S_IRUSR
| S_IWUSR
);
89 if (AuxiliaryMemoryFileDescriptor
== -1)
90 return make_error
<Failure
>(
91 "Getting file descriptor for auxiliary memory failed");
92 // set up memory value file descriptors
93 int *AuxiliaryMemoryMapping
=
94 (int *)mmap(NULL
, 4096, PROT_READ
| PROT_WRITE
, MAP_SHARED
,
95 AuxiliaryMemoryFileDescriptor
, 0);
96 if ((intptr_t)AuxiliaryMemoryMapping
== -1)
97 return make_error
<Failure
>("Mapping auxiliary memory failed");
98 AuxiliaryMemoryMapping
[0] = CounterFileDescriptor
;
99 for (auto &[Name
, MemVal
] : MemoryDefinitions
) {
100 std::string MemoryValueName
= "/" + std::to_string(ParentPID
) + "memdef" +
101 std::to_string(MemVal
.Index
);
102 AuxiliaryMemoryMapping
[AuxiliaryMemoryOffset
+ MemVal
.Index
] =
103 shm_open(MemoryValueName
.c_str(), O_RDWR
, S_IRUSR
| S_IWUSR
);
104 if (AuxiliaryMemoryMapping
[AuxiliaryMemoryOffset
+ MemVal
.Index
] == -1)
105 return make_error
<Failure
>("Mapping shared memory failed");
107 if (munmap(AuxiliaryMemoryMapping
, 4096) == -1)
108 return make_error
<Failure
>("Unmapping auxiliary memory failed");
109 return AuxiliaryMemoryFileDescriptor
;
112 SubprocessMemory::~SubprocessMemory() {
113 for (std::string SharedMemoryName
: SharedMemoryNames
) {
114 if (shm_unlink(SharedMemoryName
.c_str()) != 0) {
115 errs() << "Failed to unlink shared memory section: " << strerror(errno
)
123 Error
SubprocessMemory::initializeSubprocessMemory(pid_t ProcessPID
) {
124 return make_error
<Failure
>(
125 "initializeSubprocessMemory is only supported on Linux");
128 Error
SubprocessMemory::addMemoryDefinition(
129 std::unordered_map
<std::string
, MemoryValue
> MemoryDefinitions
,
131 return make_error
<Failure
>("addMemoryDefinitions is only supported on Linux");
134 Expected
<int> SubprocessMemory::setupAuxiliaryMemoryInSubprocess(
135 std::unordered_map
<std::string
, MemoryValue
> MemoryDefinitions
,
136 pid_t ParentPID
, int CounterFileDescriptor
) {
137 return make_error
<Failure
>(
138 "setupAuxiliaryMemoryInSubprocess is only supported on Linux");
141 SubprocessMemory::~SubprocessMemory() {}
143 #endif // defined(__linux__) && !defined(__ANDROID__)
145 } // namespace exegesis