Expand Up
@@ -10,20 +10,27 @@
//
// ===----------------------------------------------------------------------===//
#include " llvm/ADT/StringMap.h"
#include " llvm/ADT/StringRef.h"
#include " llvm/Frontend/OpenMP/OMPConstants.h"
#include " llvm/Frontend/OpenMP/OMPGridValues.h"
#include " llvm/Object/ELF.h"
#include " llvm/Object/ELFObjectFile.h"
#include < algorithm>
#include < assert.h>
#include < cstdio>
#include < cstdlib>
#include < cstring>
#include < functional>
#include < libelf.h>
#include < list>
#include < memory>
#include < mutex>
#include < shared_mutex>
#include < unordered_map>
#include < vector>
#include " ELFSymbols.h"
#include " impl_runtime.h"
#include " interop_hsa.h"
Expand All
@@ -35,12 +42,9 @@
#include " omptargetplugin.h"
#include " print_tracing.h"
#include " llvm/ADT/StringMap.h"
#include " llvm/ADT/StringRef.h"
#include " llvm/Frontend/OpenMP/OMPConstants.h"
#include " llvm/Frontend/OpenMP/OMPGridValues.h"
using namespace llvm ;
using namespace llvm ::object;
using namespace llvm ::ELF;
// hostrpc interface, FIXME: consider moving to its own include these are
// statically linked into amdgpu/plugin if present from hostrpc_services.a,
Expand Down
Expand Up
@@ -1559,37 +1563,29 @@ int32_t runRegionLocked(int32_t DeviceId, void *TgtEntryPtr, void **TgtArgs,
}
bool elfMachineIdIsAmdgcn (__tgt_device_image *Image) {
const uint16_t AmdgcnMachineID = 224 ; // EM_AMDGPU may not be in system elf.h
int32_t R = elf_check_machine (Image, AmdgcnMachineID);
const uint16_t AmdgcnMachineID = EM_AMDGPU;
const int32_t R = elf_check_machine (Image, AmdgcnMachineID);
if (!R) {
DP (" Supported machine ID not found\n " );
}
return R;
}
uint32_t elfEFlags (__tgt_device_image *Image) {
char *ImgBegin = (char *)Image->ImageStart ;
const char *ImgBegin = (char *)Image->ImageStart ;
size_t ImgSize = (char *)Image->ImageEnd - ImgBegin;
Elf *E = elf_memory (ImgBegin, ImgSize);
if (!E) {
DP (" Unable to get ELF handle: %s!\n " , elf_errmsg (-1 ));
StringRef Buffer = StringRef (ImgBegin, ImgSize);
auto ElfOrErr = ObjectFile::createELFObjectFile (MemoryBufferRef (Buffer, " " ),
/* InitContent=*/ false );
if (!ElfOrErr) {
consumeError (ElfOrErr.takeError ());
return 0 ;
}
Elf64_Ehdr *Eh64 = elf64_getehdr (E);
if (!Eh64) {
DP (" Unable to get machine ID from ELF file!\n " );
elf_end (E);
return 0 ;
}
uint32_t Flags = Eh64->e_flags ;
elf_end (E);
DP (" ELF Flags: 0x%x\n " , Flags);
return Flags;
if (const auto *ELFObj = dyn_cast<ELF64LEObjectFile>(ElfOrErr->get ()))
return ELFObj->getPlatformFlags ();
return 0 ;
}
template <typename T> bool enforceUpperBound (T *Value, T Upper) {
Expand All
@@ -1600,128 +1596,53 @@ template <typename T> bool enforceUpperBound(T *Value, T Upper) {
return Changed;
}
Elf64_Shdr *findOnlyShtHash (Elf *Elf) {
size_t N;
int Rc = elf_getshdrnum (Elf, &N);
if (Rc != 0 ) {
return nullptr ;
}
Elf64_Shdr *Result = nullptr ;
for (size_t I = 0 ; I < N; I++) {
Elf_Scn *Scn = elf_getscn (Elf, I);
if (Scn) {
Elf64_Shdr *Shdr = elf64_getshdr (Scn);
if (Shdr) {
if (Shdr->sh_type == SHT_HASH) {
if (Result == nullptr ) {
Result = Shdr;
} else {
// multiple SHT_HASH sections not handled
return nullptr ;
}
}
}
}
}
return Result;
}
const Elf64_Sym *elfLookup (Elf *Elf, char *Base, Elf64_Shdr *SectionHash,
const char *Symname) {
assert (SectionHash);
size_t SectionSymtabIndex = SectionHash->sh_link ;
Elf64_Shdr *SectionSymtab =
elf64_getshdr (elf_getscn (Elf, SectionSymtabIndex));
size_t SectionStrtabIndex = SectionSymtab->sh_link ;
const Elf64_Sym *Symtab =
reinterpret_cast <const Elf64_Sym *>(Base + SectionSymtab->sh_offset );
const uint32_t *Hashtab =
reinterpret_cast <const uint32_t *>(Base + SectionHash->sh_offset );
// Layout:
// nbucket
// nchain
// bucket[nbucket]
// chain[nchain]
uint32_t Nbucket = Hashtab[0 ];
const uint32_t *Bucket = &Hashtab[2 ];
const uint32_t *Chain = &Hashtab[Nbucket + 2 ];
const size_t Max = strlen (Symname) + 1 ;
const uint32_t Hash = elf_hash (Symname);
for (uint32_t I = Bucket[Hash % Nbucket]; I != 0 ; I = Chain[I]) {
char *N = elf_strptr (Elf, SectionStrtabIndex, Symtab[I].st_name );
if (strncmp (Symname, N, Max) == 0 ) {
return &Symtab[I];
}
}
return nullptr ;
}
struct SymbolInfo {
void *Addr = nullptr ;
const void *Addr = nullptr ;
uint32_t Size = UINT32_MAX;
uint32_t ShType = SHT_NULL;
};
int getSymbolInfoWithoutLoading (Elf *Elf, char *Base, const char *Symname,
SymbolInfo *Res) {
if (elf_kind (Elf) != ELF_K_ELF) {
return 1 ;
}
Elf64_Shdr *SectionHash = findOnlyShtHash (Elf);
if (!SectionHash) {
int getSymbolInfoWithoutLoading (const ELFObjectFile<ELF64LE> &ELFObj,
StringRef SymName, SymbolInfo *Res) {
auto SymOrErr = getELFSymbol (ELFObj, SymName);
if (!SymOrErr) {
std::string ErrorString = toString (SymOrErr.takeError ());
DP (" Failed ELF lookup: %s\n " , ErrorString.c_str ());
return 1 ;
}
const Elf64_Sym *Sym = elfLookup (Elf, Base, SectionHash, Symname);
if (!Sym) {
if (!*SymOrErr)
return 1 ;
}
if (Sym->st_size > UINT32_MAX) {
auto SymSecOrErr = ELFObj.getELFFile ().getSection ((*SymOrErr)->st_shndx );
if (!SymSecOrErr) {
std::string ErrorString = toString (SymOrErr.takeError ());
DP (" Failed ELF lookup: %s\n " , ErrorString.c_str ());
return 1 ;
}
if (Sym->st_shndx == SHN_UNDEF) {
return 1 ;
}
Elf_Scn *Section = elf_getscn (Elf, Sym->st_shndx );
if (!Section) {
return 1 ;
}
Elf64_Shdr *Header = elf64_getshdr (Section);
if (!Header) {
return 1 ;
}
Res->Addr = Sym->st_value + Base;
Res->Size = static_cast <uint32_t >(Sym->st_size );
Res->ShType = Header->sh_type ;
Res->Addr = (*SymOrErr)->st_value + ELFObj.getELFFile ().base ();
Res->Size = static_cast <uint32_t >((*SymOrErr)->st_size );
Res->ShType = static_cast <uint32_t >((*SymSecOrErr)->sh_type );
return 0 ;
}
int getSymbolInfoWithoutLoading (char *Base, size_t ImgSize, const char *Symname ,
int getSymbolInfoWithoutLoading (char *Base, size_t ImgSize, const char *SymName ,
SymbolInfo *Res) {
Elf *Elf = elf_memory (Base, ImgSize);
if (Elf) {
int Rc = getSymbolInfoWithoutLoading (Elf, Base, Symname, Res);
elf_end (Elf);
return Rc;
StringRef Buffer = StringRef (Base, ImgSize);
auto ElfOrErr = ObjectFile::createELFObjectFile (MemoryBufferRef (Buffer, " " ),
/* InitContent=*/ false );
if (!ElfOrErr) {
REPORT (" Failed to load ELF: %s\n " , toString (ElfOrErr.takeError ()).c_str ());
return 1 ;
}
if (const auto *ELFObj = dyn_cast<ELF64LEObjectFile>(ElfOrErr->get ()))
return getSymbolInfoWithoutLoading (*ELFObj, SymName, Res);
return 1 ;
}
hsa_status_t interopGetSymbolInfo (char *Base, size_t ImgSize,
const char *SymName, void **VarAddr,
const char *SymName, const void **VarAddr,
uint32_t *VarSize) {
SymbolInfo SI;
int Rc = getSymbolInfoWithoutLoading (Base, ImgSize, SymName, &SI);
Expand Down
Expand Up
@@ -2492,7 +2413,7 @@ __tgt_target_table *__tgt_rtl_load_binary_locked(int32_t DeviceId,
KernDescNameStr += " _kern_desc" ;
const char *KernDescName = KernDescNameStr.c_str ();
void *KernDescPtr;
const void *KernDescPtr;
uint32_t KernDescSize;
void *CallStackAddr = nullptr ;
Err = interopGetSymbolInfo ((char *)Image->ImageStart , ImgSize, KernDescName,
Expand Down
Expand Up
@@ -2531,7 +2452,7 @@ __tgt_target_table *__tgt_rtl_load_binary_locked(int32_t DeviceId,
WGSizeNameStr += " _wg_size" ;
const char *WGSizeName = WGSizeNameStr.c_str ();
void *WGSizePtr;
const void *WGSizePtr;
uint32_t WGSize;
Err = interopGetSymbolInfo ((char *)Image->ImageStart , ImgSize, WGSizeName,
&WGSizePtr, &WGSize);
Expand Down
Expand Up
@@ -2570,7 +2491,7 @@ __tgt_target_table *__tgt_rtl_load_binary_locked(int32_t DeviceId,
ExecModeNameStr += " _exec_mode" ;
const char *ExecModeName = ExecModeNameStr.c_str ();
void *ExecModePtr;
const void *ExecModePtr;
uint32_t VarSize;
Err = interopGetSymbolInfo ((char *)Image->ImageStart , ImgSize, ExecModeName,
&ExecModePtr, &VarSize);
Expand Down