1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
//===- GlobalHandler.cpp - Target independent global & env. var handling --===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Target independent global handler and environment manager.
//
//===----------------------------------------------------------------------===//
#include "GlobalHandler.h"
#include "ELFSymbols.h"
#include "PluginInterface.h"
#include "Utilities.h"
#include <cstring>
using namespace llvm;
using namespace omp;
using namespace target;
using namespace plugin;
const ELF64LEObjectFile *
GenericGlobalHandlerTy::getOrCreateELFObjectFile(const GenericDeviceTy &Device,
DeviceImageTy &Image) {
auto Search = ELFObjectFiles.find(Image.getId());
if (Search != ELFObjectFiles.end())
// The ELF object file was already there.
return &Search->second;
// The ELF object file we are checking is not created yet.
Expected<ELF64LEObjectFile> ElfOrErr =
ELF64LEObjectFile::create(Image.getMemoryBuffer());
if (!ElfOrErr) {
consumeError(ElfOrErr.takeError());
return nullptr;
}
auto Result =
ELFObjectFiles.try_emplace(Image.getId(), std::move(ElfOrErr.get()));
assert(Result.second && "Map insertion failed");
assert(Result.first != ELFObjectFiles.end() && "Map insertion failed");
return &Result.first->second;
}
Error GenericGlobalHandlerTy::getGlobalMetadataFromELF(
const DeviceImageTy &Image, const ELF64LE::Sym &Symbol,
const ELF64LE::Shdr &Section, GlobalTy &ImageGlobal) {
// The global's address is computed as the image begin + the ELF section
// offset + the ELF symbol value.
ImageGlobal.setPtr(
advanceVoidPtr(Image.getStart(), Section.sh_offset + Symbol.st_value));
// Set the global's size.
ImageGlobal.setSize(Symbol.st_size);
return Plugin::success();
}
Error GenericGlobalHandlerTy::moveGlobalBetweenDeviceAndHost(
GenericDeviceTy &Device, DeviceImageTy &Image, const GlobalTy &HostGlobal,
bool Device2Host) {
GlobalTy DeviceGlobal(HostGlobal.getName(), HostGlobal.getSize());
// Get the metadata from the global on the device.
if (auto Err = getGlobalMetadataFromDevice(Device, Image, DeviceGlobal))
return Err;
// Perform the actual transfer.
return moveGlobalBetweenDeviceAndHost(Device, Image, HostGlobal, DeviceGlobal,
Device2Host);
}
/// Actually move memory between host and device. See readGlobalFromDevice and
/// writeGlobalToDevice for the interface description.
Error GenericGlobalHandlerTy::moveGlobalBetweenDeviceAndHost(
GenericDeviceTy &Device, DeviceImageTy &DeviceImage,
const GlobalTy &HostGlobal, const GlobalTy &DeviceGlobal,
bool Device2Host) {
// Transfer the data from the source to the destination.
if (Device2Host) {
if (auto Err =
Device.dataRetrieve(HostGlobal.getPtr(), DeviceGlobal.getPtr(),
HostGlobal.getSize(), nullptr))
return Err;
} else {
if (auto Err = Device.dataSubmit(DeviceGlobal.getPtr(), HostGlobal.getPtr(),
HostGlobal.getSize(), nullptr))
return Err;
}
DP("Succesfully %s %u bytes associated with global symbol '%s' %s the device "
"(%p -> %p).\n",
Device2Host ? "read" : "write", HostGlobal.getSize(),
HostGlobal.getName().data(), Device2Host ? "from" : "to",
DeviceGlobal.getPtr(), HostGlobal.getPtr());
return Plugin::success();
}
Error GenericGlobalHandlerTy::getGlobalMetadataFromImage(
GenericDeviceTy &Device, DeviceImageTy &Image, GlobalTy &ImageGlobal) {
// Get the ELF object file for the image. Notice the ELF object may already
// be created in previous calls, so we can reuse it.
const ELF64LEObjectFile *ELFObj = getOrCreateELFObjectFile(Device, Image);
if (!ELFObj)
return Plugin::error("Unable to create ELF object for image %p",
Image.getStart());
// Search the ELF symbol using the the symbol name.
auto SymOrErr = getELFSymbol(*ELFObj, ImageGlobal.getName());
if (!SymOrErr)
return Plugin::error("Failed ELF lookup of global '%s': %s",
ImageGlobal.getName().data(),
toString(SymOrErr.takeError()).data());
if (!*SymOrErr)
return Plugin::error("Failed to find global symbol '%s' in the ELF image",
ImageGlobal.getName().data());
// Get the section to which the symbol belongs.
auto SecOrErr = ELFObj->getELFFile().getSection((*SymOrErr)->st_shndx);
if (!SecOrErr)
return Plugin::error("Failed to get ELF section from global '%s': %s",
ImageGlobal.getName().data(),
toString(SecOrErr.takeError()).data());
// Setup the global symbol's address and size.
return getGlobalMetadataFromELF(Image, **SymOrErr, **SecOrErr, ImageGlobal);
}
Error GenericGlobalHandlerTy::readGlobalFromImage(GenericDeviceTy &Device,
DeviceImageTy &Image,
const GlobalTy &HostGlobal) {
GlobalTy ImageGlobal(HostGlobal.getName(), -1);
if (auto Err = getGlobalMetadataFromImage(Device, Image, ImageGlobal))
return Err;
if (ImageGlobal.getSize() != HostGlobal.getSize())
return Plugin::error("Transfer failed because global symbol '%s' has "
"%u bytes in the ELF image but %u bytes on the host",
HostGlobal.getName().data(), ImageGlobal.getSize(),
HostGlobal.getSize());
DP("Global symbol '%s' was found in the ELF image and %u bytes will copied "
"from %p to %p.\n",
HostGlobal.getName().data(), HostGlobal.getSize(), ImageGlobal.getPtr(),
HostGlobal.getPtr());
// Perform the copy from the image to the host memory.
std::memcpy(HostGlobal.getPtr(), ImageGlobal.getPtr(), HostGlobal.getSize());
return Plugin::success();
}
|