1//===- GlobalHandler.cpp - Target independent global & env. var handling --===//
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-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Target independent global handler and environment manager.
10//
11//===----------------------------------------------------------------------===//
12
13#include "GlobalHandler.h"
14#include "PluginInterface.h"
15#include "Utils/ELF.h"
16
17#include "Shared/Utils.h"
18
19#include "llvm/Support/Error.h"
20
21#include <cstring>
22
23using namespace llvm;
24using namespace omp;
25using namespace target;
26using namespace plugin;
27
28Expected<std::unique_ptr<ObjectFile>>
29GenericGlobalHandlerTy::getELFObjectFile(DeviceImageTy &Image) {
30 assert(utils::elf::isELF(Image.getMemoryBuffer().getBuffer()) &&
31 "Input is not an ELF file");
32
33 return ELFObjectFileBase::createELFObjectFile(Image.getMemoryBuffer());
34}
35
36Error GenericGlobalHandlerTy::moveGlobalBetweenDeviceAndHost(
37 GenericDeviceTy &Device, DeviceImageTy &Image, const GlobalTy &HostGlobal,
38 bool Device2Host) {
39
40 GlobalTy DeviceGlobal(HostGlobal.getName(), HostGlobal.getSize());
41
42 // Get the metadata from the global on the device.
43 if (auto Err = getGlobalMetadataFromDevice(Device, Image, DeviceGlobal))
44 return Err;
45
46 // Perform the actual transfer.
47 return moveGlobalBetweenDeviceAndHost(Device, HostGlobal, DeviceGlobal,
48 Device2Host);
49}
50
51/// Actually move memory between host and device. See readGlobalFromDevice and
52/// writeGlobalToDevice for the interface description.
53Error GenericGlobalHandlerTy::moveGlobalBetweenDeviceAndHost(
54 GenericDeviceTy &Device, const GlobalTy &HostGlobal,
55 const GlobalTy &DeviceGlobal, bool Device2Host) {
56
57 // Transfer the data from the source to the destination.
58 if (Device2Host) {
59 if (auto Err =
60 Device.dataRetrieve(HostGlobal.getPtr(), DeviceGlobal.getPtr(),
61 HostGlobal.getSize(), nullptr))
62 return Err;
63 } else {
64 if (auto Err = Device.dataSubmit(DeviceGlobal.getPtr(), HostGlobal.getPtr(),
65 HostGlobal.getSize(), nullptr))
66 return Err;
67 }
68
69 DP("Succesfully %s %u bytes associated with global symbol '%s' %s the "
70 "device "
71 "(%p -> %p).\n",
72 Device2Host ? "read" : "write", HostGlobal.getSize(),
73 HostGlobal.getName().data(), Device2Host ? "from" : "to",
74 DeviceGlobal.getPtr(), HostGlobal.getPtr());
75
76 return Plugin::success();
77}
78
79bool GenericGlobalHandlerTy::isSymbolInImage(GenericDeviceTy &Device,
80 DeviceImageTy &Image,
81 StringRef SymName) {
82 // Get the ELF object file for the image. Notice the ELF object may already
83 // be created in previous calls, so we can reuse it. If this is unsuccessful
84 // just return false as we couldn't find it.
85 auto ELFObjOrErr = getELFObjectFile(Image);
86 if (!ELFObjOrErr) {
87 consumeError(ELFObjOrErr.takeError());
88 return false;
89 }
90
91 // Search the ELF symbol using the symbol name.
92 auto SymOrErr = utils::elf::getSymbol(**ELFObjOrErr, SymName);
93 if (!SymOrErr) {
94 consumeError(SymOrErr.takeError());
95 return false;
96 }
97
98 return SymOrErr->has_value();
99}
100
101Error GenericGlobalHandlerTy::getGlobalMetadataFromImage(
102 GenericDeviceTy &Device, DeviceImageTy &Image, GlobalTy &ImageGlobal) {
103
104 // Get the ELF object file for the image. Notice the ELF object may already
105 // be created in previous calls, so we can reuse it.
106 auto ELFObj = getELFObjectFile(Image);
107 if (!ELFObj)
108 return ELFObj.takeError();
109
110 // Search the ELF symbol using the symbol name.
111 auto SymOrErr = utils::elf::getSymbol(**ELFObj, ImageGlobal.getName());
112 if (!SymOrErr)
113 return Plugin::error("Failed ELF lookup of global '%s': %s",
114 ImageGlobal.getName().data(),
115 toString(SymOrErr.takeError()).data());
116
117 if (!SymOrErr->has_value())
118 return Plugin::error("Failed to find global symbol '%s' in the ELF image",
119 ImageGlobal.getName().data());
120
121 auto AddrOrErr = utils::elf::getSymbolAddress(**SymOrErr);
122 // Get the section to which the symbol belongs.
123 if (!AddrOrErr)
124 return Plugin::error("Failed to get ELF symbol from global '%s': %s",
125 ImageGlobal.getName().data(),
126 toString(AddrOrErr.takeError()).data());
127
128 // Setup the global symbol's address and size.
129 ImageGlobal.setPtr(const_cast<void *>(*AddrOrErr));
130 ImageGlobal.setSize((*SymOrErr)->getSize());
131
132 return Plugin::success();
133}
134
135Error GenericGlobalHandlerTy::readGlobalFromImage(GenericDeviceTy &Device,
136 DeviceImageTy &Image,
137 const GlobalTy &HostGlobal) {
138
139 GlobalTy ImageGlobal(HostGlobal.getName(), -1);
140 if (auto Err = getGlobalMetadataFromImage(Device, Image, ImageGlobal))
141 return Err;
142
143 if (ImageGlobal.getSize() != HostGlobal.getSize())
144 return Plugin::error("Transfer failed because global symbol '%s' has "
145 "%u bytes in the ELF image but %u bytes on the host",
146 HostGlobal.getName().data(), ImageGlobal.getSize(),
147 HostGlobal.getSize());
148
149 DP("Global symbol '%s' was found in the ELF image and %u bytes will copied "
150 "from %p to %p.\n",
151 HostGlobal.getName().data(), HostGlobal.getSize(), ImageGlobal.getPtr(),
152 HostGlobal.getPtr());
153
154 assert(Image.getStart() <= ImageGlobal.getPtr() &&
155 advanceVoidPtr(ImageGlobal.getPtr(), ImageGlobal.getSize()) <
156 advanceVoidPtr(Image.getStart(), Image.getSize()) &&
157 "Attempting to read outside the image!");
158
159 // Perform the copy from the image to the host memory.
160 std::memcpy(HostGlobal.getPtr(), ImageGlobal.getPtr(), HostGlobal.getSize());
161
162 return Plugin::success();
163}
164

source code of offload/plugins-nextgen/common/src/GlobalHandler.cpp