1 //===- GlobalHandler.cpp - Target independent global & env. var handling --===//
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 // Target independent global handler and environment manager.
11 //===----------------------------------------------------------------------===//
13 #include "GlobalHandler.h"
14 #include "ELFSymbols.h"
15 #include "PluginInterface.h"
16 #include "Utilities.h"
22 using namespace target
;
23 using namespace plugin
;
25 const ELF64LEObjectFile
*
26 GenericGlobalHandlerTy::getOrCreateELFObjectFile(const GenericDeviceTy
&Device
,
27 DeviceImageTy
&Image
) {
29 auto Search
= ELFObjectFiles
.find(Image
.getId());
30 if (Search
!= ELFObjectFiles
.end())
31 // The ELF object file was already there.
32 return &Search
->second
;
34 // The ELF object file we are checking is not created yet.
35 Expected
<ELF64LEObjectFile
> ElfOrErr
=
36 ELF64LEObjectFile::create(Image
.getMemoryBuffer());
38 consumeError(ElfOrErr
.takeError());
43 ELFObjectFiles
.try_emplace(Image
.getId(), std::move(ElfOrErr
.get()));
44 assert(Result
.second
&& "Map insertion failed");
45 assert(Result
.first
!= ELFObjectFiles
.end() && "Map insertion failed");
47 return &Result
.first
->second
;
50 Error
GenericGlobalHandlerTy::getGlobalMetadataFromELF(
51 const DeviceImageTy
&Image
, const ELF64LE::Sym
&Symbol
,
52 const ELF64LE::Shdr
&Section
, GlobalTy
&ImageGlobal
) {
54 // The global's address is computed as the image begin + the ELF section
55 // offset + the ELF symbol value.
56 ImageGlobal
.setPtr(advanceVoidPtr(
57 Image
.getStart(), Section
.sh_offset
- Section
.sh_addr
+ Symbol
.st_value
));
59 // Set the global's size.
60 ImageGlobal
.setSize(Symbol
.st_size
);
62 return Plugin::success();
65 Error
GenericGlobalHandlerTy::moveGlobalBetweenDeviceAndHost(
66 GenericDeviceTy
&Device
, DeviceImageTy
&Image
, const GlobalTy
&HostGlobal
,
69 GlobalTy
DeviceGlobal(HostGlobal
.getName(), HostGlobal
.getSize());
71 // Get the metadata from the global on the device.
72 if (auto Err
= getGlobalMetadataFromDevice(Device
, Image
, DeviceGlobal
))
75 // Perform the actual transfer.
76 return moveGlobalBetweenDeviceAndHost(Device
, HostGlobal
, DeviceGlobal
,
80 /// Actually move memory between host and device. See readGlobalFromDevice and
81 /// writeGlobalToDevice for the interface description.
82 Error
GenericGlobalHandlerTy::moveGlobalBetweenDeviceAndHost(
83 GenericDeviceTy
&Device
, const GlobalTy
&HostGlobal
,
84 const GlobalTy
&DeviceGlobal
, bool Device2Host
) {
86 // Transfer the data from the source to the destination.
89 Device
.dataRetrieve(HostGlobal
.getPtr(), DeviceGlobal
.getPtr(),
90 HostGlobal
.getSize(), nullptr))
93 if (auto Err
= Device
.dataSubmit(DeviceGlobal
.getPtr(), HostGlobal
.getPtr(),
94 HostGlobal
.getSize(), nullptr))
98 DP("Succesfully %s %u bytes associated with global symbol '%s' %s the device "
100 Device2Host
? "read" : "write", HostGlobal
.getSize(),
101 HostGlobal
.getName().data(), Device2Host
? "from" : "to",
102 DeviceGlobal
.getPtr(), HostGlobal
.getPtr());
104 return Plugin::success();
107 Error
GenericGlobalHandlerTy::getGlobalMetadataFromImage(
108 GenericDeviceTy
&Device
, DeviceImageTy
&Image
, GlobalTy
&ImageGlobal
) {
110 // Get the ELF object file for the image. Notice the ELF object may already
111 // be created in previous calls, so we can reuse it.
112 const ELF64LEObjectFile
*ELFObj
= getOrCreateELFObjectFile(Device
, Image
);
114 return Plugin::error("Unable to create ELF object for image %p",
117 // Search the ELF symbol using the symbol name.
118 auto SymOrErr
= getELFSymbol(*ELFObj
, ImageGlobal
.getName());
120 return Plugin::error("Failed ELF lookup of global '%s': %s",
121 ImageGlobal
.getName().data(),
122 toString(SymOrErr
.takeError()).data());
125 return Plugin::error("Failed to find global symbol '%s' in the ELF image",
126 ImageGlobal
.getName().data());
128 // Get the section to which the symbol belongs.
129 auto SecOrErr
= ELFObj
->getELFFile().getSection((*SymOrErr
)->st_shndx
);
131 return Plugin::error("Failed to get ELF section from global '%s': %s",
132 ImageGlobal
.getName().data(),
133 toString(SecOrErr
.takeError()).data());
135 // Setup the global symbol's address and size.
136 return getGlobalMetadataFromELF(Image
, **SymOrErr
, **SecOrErr
, ImageGlobal
);
139 Error
GenericGlobalHandlerTy::readGlobalFromImage(GenericDeviceTy
&Device
,
140 DeviceImageTy
&Image
,
141 const GlobalTy
&HostGlobal
) {
143 GlobalTy
ImageGlobal(HostGlobal
.getName(), -1);
144 if (auto Err
= getGlobalMetadataFromImage(Device
, Image
, ImageGlobal
))
147 if (ImageGlobal
.getSize() != HostGlobal
.getSize())
148 return Plugin::error("Transfer failed because global symbol '%s' has "
149 "%u bytes in the ELF image but %u bytes on the host",
150 HostGlobal
.getName().data(), ImageGlobal
.getSize(),
151 HostGlobal
.getSize());
153 DP("Global symbol '%s' was found in the ELF image and %u bytes will copied "
155 HostGlobal
.getName().data(), HostGlobal
.getSize(), ImageGlobal
.getPtr(),
156 HostGlobal
.getPtr());
158 // Perform the copy from the image to the host memory.
159 std::memcpy(HostGlobal
.getPtr(), ImageGlobal
.getPtr(), HostGlobal
.getSize());
161 return Plugin::success();