diff --git a/openmp/libomptarget/cmake/Modules/LibomptargetGetDependencies.cmake b/openmp/libomptarget/cmake/Modules/LibomptargetGetDependencies.cmake --- a/openmp/libomptarget/cmake/Modules/LibomptargetGetDependencies.cmake +++ b/openmp/libomptarget/cmake/Modules/LibomptargetGetDependencies.cmake @@ -11,7 +11,6 @@ # Try to detect in the system several dependencies required by the different # components of libomptarget. These are the dependencies we have: # -# libelf : required by some targets to handle the ELF files at runtime. # libffi : required to launch target kernels given function and argument # pointers. # CUDA : required to control offloading to NVIDIA GPUs. @@ -49,46 +48,6 @@ "Using LLVM include directories: ${LIBOMPTARGET_LLVM_INCLUDE_DIRS}") endif() -################################################################################ -# Looking for libelf... -################################################################################ - -find_path ( - LIBOMPTARGET_DEP_LIBELF_INCLUDE_DIR - NAMES - libelf.h - PATHS - /usr/include - /usr/local/include - /opt/local/include - /sw/include - ENV CPATH - PATH_SUFFIXES - libelf) - -find_library ( - LIBOMPTARGET_DEP_LIBELF_LIBRARIES - NAMES - elf - PATHS - /usr/lib - /usr/local/lib - /opt/local/lib - /sw/lib - ENV LIBRARY_PATH - ENV LD_LIBRARY_PATH) - -set(LIBOMPTARGET_DEP_LIBELF_INCLUDE_DIRS ${LIBOMPTARGET_DEP_LIBELF_INCLUDE_DIR}) -find_package_handle_standard_args( - LIBOMPTARGET_DEP_LIBELF - DEFAULT_MSG - LIBOMPTARGET_DEP_LIBELF_LIBRARIES - LIBOMPTARGET_DEP_LIBELF_INCLUDE_DIRS) - -mark_as_advanced( - LIBOMPTARGET_DEP_LIBELF_INCLUDE_DIRS - LIBOMPTARGET_DEP_LIBELF_LIBRARIES) - ################################################################################ # Looking for libffi... ################################################################################ diff --git a/openmp/libomptarget/plugins/CMakeLists.txt b/openmp/libomptarget/plugins/CMakeLists.txt --- a/openmp/libomptarget/plugins/CMakeLists.txt +++ b/openmp/libomptarget/plugins/CMakeLists.txt @@ -19,67 +19,60 @@ # - tmachine_libname: machine name to be appended to the plugin library name. macro(build_generic_elf64 tmachine tmachine_name tmachine_libname tmachine_triple elf_machine_id) if(CMAKE_SYSTEM_PROCESSOR MATCHES "${tmachine}$") - if(LIBOMPTARGET_DEP_LIBELF_FOUND) - if(LIBOMPTARGET_DEP_LIBFFI_FOUND) - - libomptarget_say("Building ${tmachine_name} offloading plugin.") - - # Define macro to be used as prefix of the runtime messages for this target. - add_definitions("-DTARGET_NAME=${tmachine_name}") - - # Define macro with the ELF ID for this target. - add_definitions("-DTARGET_ELF_ID=${elf_machine_id}") - - add_llvm_library("omptarget.rtl.${tmachine_libname}" - SHARED - - ${CMAKE_CURRENT_SOURCE_DIR}/../generic-elf-64bit/src/rtl.cpp - - ADDITIONAL_HEADER_DIRS - ${LIBOMPTARGET_INCLUDE_DIR} - ${LIBOMPTARGET_DEP_LIBFFI_INCLUDE_DIR} - ${LIBOMPTARGET_DEP_LIBELF_INCLUDE_DIR} - - LINK_LIBS - PRIVATE - elf_common - ${LIBOMPTARGET_DEP_LIBFFI_LIBRARIES} - ${LIBOMPTARGET_DEP_LIBELF_LIBRARIES} - dl - ${OPENMP_PTHREAD_LIB} - "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/../exports" - - NO_INSTALL_RPATH - ) - - # Install plugin under the lib destination folder. - install(TARGETS "omptarget.rtl.${tmachine_libname}" - LIBRARY DESTINATION "${OPENMP_INSTALL_LIBDIR}") - set_target_properties("omptarget.rtl.${tmachine_libname}" PROPERTIES - INSTALL_RPATH "$ORIGIN" BUILD_RPATH "$ORIGIN:${CMAKE_CURRENT_BINARY_DIR}/..") - - target_include_directories( "omptarget.rtl.${tmachine_libname}" PRIVATE - ${LIBOMPTARGET_INCLUDE_DIR} - ${LIBOMPTARGET_DEP_LIBFFI_INCLUDE_DIR} - ${LIBOMPTARGET_DEP_LIBELF_INCLUDE_DIR}) - - list(APPEND LIBOMPTARGET_TESTED_PLUGINS - "omptarget.rtl.${tmachine_libname}") - - # Report to the parent scope that we are building a plugin. - set(LIBOMPTARGET_SYSTEM_TARGETS - "${LIBOMPTARGET_SYSTEM_TARGETS} ${tmachine_triple} ${tmachine_triple}-oldDriver" PARENT_SCOPE) - set(LIBOMPTARGET_SYSTEM_TARGETS - "${LIBOMPTARGET_SYSTEM_TARGETS} ${tmachine_triple} ${tmachine_triple}-LTO" PARENT_SCOPE) - set(LIBOMPTARGET_TESTED_PLUGINS - "${LIBOMPTARGET_TESTED_PLUGINS}" PARENT_SCOPE) - - else(LIBOMPTARGET_DEP_LIBFFI_FOUND) - libomptarget_say("Not building ${tmachine_name} offloading plugin: libffi dependency not found.") - endif(LIBOMPTARGET_DEP_LIBFFI_FOUND) - else(LIBOMPTARGET_DEP_LIBELF_FOUND) - libomptarget_say("Not building ${tmachine_name} offloading plugin: libelf dependency not found.") - endif(LIBOMPTARGET_DEP_LIBELF_FOUND) + if(LIBOMPTARGET_DEP_LIBFFI_FOUND) + + libomptarget_say("Building ${tmachine_name} offloading plugin.") + + # Define macro to be used as prefix of the runtime messages for this target. + add_definitions("-DTARGET_NAME=${tmachine_name}") + + # Define macro with the ELF ID for this target. + add_definitions("-DTARGET_ELF_ID=${elf_machine_id}") + + add_llvm_library("omptarget.rtl.${tmachine_libname}" + SHARED + + ${CMAKE_CURRENT_SOURCE_DIR}/../generic-elf-64bit/src/rtl.cpp + + ADDITIONAL_HEADER_DIRS + ${LIBOMPTARGET_INCLUDE_DIR} + ${LIBOMPTARGET_DEP_LIBFFI_INCLUDE_DIR} + + LINK_LIBS + PRIVATE + elf_common + ${LIBOMPTARGET_DEP_LIBFFI_LIBRARIES} + dl + ${OPENMP_PTHREAD_LIB} + "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/../exports" + + NO_INSTALL_RPATH + ) + + # Install plugin under the lib destination folder. + install(TARGETS "omptarget.rtl.${tmachine_libname}" + LIBRARY DESTINATION "${OPENMP_INSTALL_LIBDIR}") + set_target_properties("omptarget.rtl.${tmachine_libname}" PROPERTIES + INSTALL_RPATH "$ORIGIN" BUILD_RPATH "$ORIGIN:${CMAKE_CURRENT_BINARY_DIR}/..") + + target_include_directories( "omptarget.rtl.${tmachine_libname}" PRIVATE + ${LIBOMPTARGET_INCLUDE_DIR} + ${LIBOMPTARGET_DEP_LIBFFI_INCLUDE_DIR}) + + list(APPEND LIBOMPTARGET_TESTED_PLUGINS + "omptarget.rtl.${tmachine_libname}") + + # Report to the parent scope that we are building a plugin. + set(LIBOMPTARGET_SYSTEM_TARGETS + "${LIBOMPTARGET_SYSTEM_TARGETS} ${tmachine_triple} ${tmachine_triple}-oldDriver" PARENT_SCOPE) + set(LIBOMPTARGET_SYSTEM_TARGETS + "${LIBOMPTARGET_SYSTEM_TARGETS} ${tmachine_triple} ${tmachine_triple}-LTO" PARENT_SCOPE) + set(LIBOMPTARGET_TESTED_PLUGINS + "${LIBOMPTARGET_TESTED_PLUGINS}" PARENT_SCOPE) + + else(LIBOMPTARGET_DEP_LIBFFI_FOUND) + libomptarget_say("Not building ${tmachine_name} offloading plugin: libffi dependency not found.") + endif(LIBOMPTARGET_DEP_LIBFFI_FOUND) else() libomptarget_say("Not building ${tmachine_name} offloading plugin: machine not found in the system.") endif() diff --git a/openmp/libomptarget/plugins/amdgpu/CMakeLists.txt b/openmp/libomptarget/plugins/amdgpu/CMakeLists.txt --- a/openmp/libomptarget/plugins/amdgpu/CMakeLists.txt +++ b/openmp/libomptarget/plugins/amdgpu/CMakeLists.txt @@ -22,11 +22,6 @@ # as of rocm-3.7, hsa is installed with cmake packages and kmt is found via hsa find_package(hsa-runtime64 QUIET 1.2.0 HINTS ${CMAKE_INSTALL_PREFIX} PATHS /opt/rocm) -if(NOT LIBOMPTARGET_DEP_LIBELF_FOUND) - libomptarget_say("Not building AMDGPU plugin: LIBELF not found") - return() -endif() - if(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "(x86_64)|(ppc64le)|(aarch64)$" AND CMAKE_SYSTEM_NAME MATCHES "Linux") libomptarget_say("Not building AMDGPU plugin: only support AMDGPU in Linux x86_64, ppc64le, or aarch64 hosts") return() @@ -85,7 +80,6 @@ elf_common ${LIBOMPTARGET_DEP_LIBRARIES} ${CMAKE_DL_LIBS} - ${LIBOMPTARGET_DEP_LIBELF_LIBRARIES} ${OPENMP_PTHREAD_LIB} "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/../exports" ${LDFLAGS_UNDEFINED} diff --git a/openmp/libomptarget/plugins/amdgpu/impl/system.cpp b/openmp/libomptarget/plugins/amdgpu/impl/system.cpp --- a/openmp/libomptarget/plugins/amdgpu/impl/system.cpp +++ b/openmp/libomptarget/plugins/amdgpu/impl/system.cpp @@ -5,7 +5,11 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// -#include + +#include "llvm/ADT/StringRef.h" +#include "llvm/BinaryFormat/ELF.h" +#include "llvm/Object/ELF.h" +#include "llvm/Object/ELFObjectFile.h" #include #include @@ -16,6 +20,10 @@ #include "msgpack.h" +using namespace llvm; +using namespace llvm::object; +using namespace llvm::ELF; + namespace hsa { // Wrap HSA iterate API in a shim that allows passing general callables template @@ -163,66 +171,62 @@ } } -static std::pair -find_metadata(void *binary, size_t binSize) { - std::pair failure = {nullptr, nullptr}; - - Elf *e = elf_memory(static_cast(binary), binSize); - if (elf_kind(e) != ELF_K_ELF) { - return failure; +static std::pair +findMetadata(const ELFObjectFile &ELFObj) { + constexpr std::pair Failure = { + nullptr, nullptr}; + const auto &Elf = ELFObj.getELFFile(); + auto PhdrsOrErr = Elf.program_headers(); + if (!PhdrsOrErr) { + consumeError(PhdrsOrErr.takeError()); + return Failure; } - size_t numpHdrs; - if (elf_getphdrnum(e, &numpHdrs) != 0) { - return failure; - } + for (auto Phdr : *PhdrsOrErr) { + if (Phdr.p_type != PT_NOTE) + continue; - Elf64_Phdr *pHdrs = elf64_getphdr(e); - for (size_t i = 0; i < numpHdrs; ++i) { - Elf64_Phdr pHdr = pHdrs[i]; - - // Look for the runtime metadata note - if (pHdr.p_type == PT_NOTE && pHdr.p_align >= sizeof(int)) { - // Iterate over the notes in this segment - address ptr = (address)binary + pHdr.p_offset; - address segmentEnd = ptr + pHdr.p_filesz; - - while (ptr < segmentEnd) { - Elf_Note *note = reinterpret_cast(ptr); - address name = (address)¬e[1]; - - if (note->n_type == 7 || note->n_type == 8) { - return failure; - } else if (note->n_type == 10 /* NT_AMD_AMDGPU_HSA_METADATA */ && - note->n_namesz == sizeof "AMD" && - !memcmp(name, "AMD", note->n_namesz)) { - // code object v2 uses yaml metadata, no longer supported - return failure; - } else if (note->n_type == 32 /* NT_AMDGPU_METADATA */ && - note->n_namesz == sizeof "AMDGPU" && - !memcmp(name, "AMDGPU", note->n_namesz)) { - - // n_descsz = 485 - // value is padded to 4 byte alignment, may want to move end up to - // match - size_t offset = sizeof(uint32_t) * 3 /* fields */ - + sizeof("AMDGPU") /* name */ - + 1 /* padding to 4 byte alignment */; - - // Including the trailing padding means both pointers are 4 bytes - // aligned, which may be useful later. - unsigned char *metadata_start = (unsigned char *)ptr + offset; - unsigned char *metadata_end = - metadata_start + core::alignUp(note->n_descsz, 4); - return {metadata_start, metadata_end}; - } - ptr += sizeof(*note) + core::alignUp(note->n_namesz, sizeof(int)) + - core::alignUp(note->n_descsz, sizeof(int)); - } + Error Err = Error::success(); + for (auto Note : Elf.notes(Phdr, Err)) { + if (Note.getType() == 7 || Note.getType() == 8) + return Failure; + + // Code object v2 uses yaml metadata and is no longer supported. + if (Note.getType() == NT_AMD_HSA_METADATA && Note.getName() == "AMD") + return Failure; + // Code object v3 should have AMDGPU metadata. + if (Note.getType() == NT_AMDGPU_METADATA && Note.getName() != "AMDGPU") + return Failure; + + ArrayRef Desc = Note.getDesc(); + return {Desc.data(), Desc.data() + Desc.size()}; + } + + if (Err) { + consumeError(std::move(Err)); + return Failure; } } - return failure; + return Failure; +} + +static std::pair +find_metadata(void *binary, size_t binSize) { + constexpr std::pair Failure = { + nullptr, nullptr}; + + StringRef Buffer = StringRef(static_cast(binary), binSize); + auto ElfOrErr = ObjectFile::createELFObjectFile(MemoryBufferRef(Buffer, ""), + /*InitContent=*/false); + if (!ElfOrErr) { + consumeError(ElfOrErr.takeError()); + return Failure; + } + + if (const auto *ELFObj = dyn_cast(ElfOrErr->get())) + return findMetadata(*ELFObj); + return Failure; } namespace { @@ -338,7 +342,7 @@ // also, the kernel name is not the same as the symbol name -- so a // symbol->name map is needed - std::pair metadata = + std::pair metadata = find_metadata(binary, binSize); if (!metadata.first) { return HSA_STATUS_ERROR_INVALID_CODE_OBJECT; diff --git a/openmp/libomptarget/plugins/amdgpu/src/rtl.cpp b/openmp/libomptarget/plugins/amdgpu/src/rtl.cpp --- a/openmp/libomptarget/plugins/amdgpu/src/rtl.cpp +++ b/openmp/libomptarget/plugins/amdgpu/src/rtl.cpp @@ -10,13 +10,19 @@ // //===----------------------------------------------------------------------===// +#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 #include #include #include #include #include -#include #include #include #include @@ -35,12 +41,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, @@ -1559,8 +1562,8 @@ } 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"); } @@ -1568,28 +1571,20 @@ } 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)); - return 0; - } - - Elf64_Ehdr *Eh64 = elf64_getehdr(E); - - if (!Eh64) { - DP("Unable to get machine ID from ELF file!\n"); - elf_end(E); + StringRef Buffer = StringRef(ImgBegin, ImgSize); + auto ElfOrErr = ObjectFile::createELFObjectFile(MemoryBufferRef(Buffer, ""), + /*InitContent=*/false); + if (!ElfOrErr) { + consumeError(ElfOrErr.takeError()); 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(ElfOrErr->get())) + return ELFObj->getPlatformFlags(); + return 0; } template bool enforceUpperBound(T *Value, T Upper) { @@ -1600,128 +1595,69 @@ 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(Base + SectionSymtab->sh_offset); - - const uint32_t *Hashtab = - reinterpret_cast(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) { - return 1; - } +int getSymbolInfoWithoutLoading(const ELFObjectFile &ELFObj, + StringRef SymName, SymbolInfo *Res) { + // Search for the symbol name in the ELF's hash table. If found, set the + // result information and return. + for (ELFSectionRef Sec : ELFObj.sections()) { + if (Sec.getType() != SHT_HASH) + continue; - const Elf64_Sym *Sym = elfLookup(Elf, Base, SectionHash, Symname); - if (!Sym) { - return 1; - } + auto &Elf = ELFObj.getELFFile(); + auto HashTabOrErr = Elf.getSection(Sec.getIndex()); + if (!HashTabOrErr) { + REPORT("Failed ELF lookup: %s\n", + toString(HashTabOrErr.takeError()).c_str()); + return 1; + } - if (Sym->st_size > UINT32_MAX) { - return 1; - } + auto SymOrErr = Elf.getSymbolFromHashTable(**HashTabOrErr, SymName); + if (!SymOrErr) { + REPORT("Failed ELF lookup: %s\n", toString(SymOrErr.takeError()).c_str()); + return 1; + } - if (Sym->st_shndx == SHN_UNDEF) { - return 1; - } + if (!*SymOrErr) + continue; - Elf_Scn *Section = elf_getscn(Elf, Sym->st_shndx); - if (!Section) { - return 1; - } + auto SymSecOrErr = Elf.getSection((*SymOrErr)->st_shndx); + if (!SymSecOrErr) { + REPORT("Failed ELF lookup: %s\n", toString(SymOrErr.takeError()).c_str()); + return 1; + } - Elf64_Shdr *Header = elf64_getshdr(Section); - if (!Header) { - return 1; + Res->Addr = (*SymOrErr)->st_value + Elf.base(); + Res->Size = static_cast((*SymOrErr)->st_size); + Res->ShType = static_cast((*SymSecOrErr)->sh_type); + return 0; } - Res->Addr = Sym->st_value + Base; - Res->Size = static_cast(Sym->st_size); - Res->ShType = Header->sh_type; - return 0; + return 1; } -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(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); @@ -2492,7 +2428,7 @@ 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, @@ -2531,7 +2467,7 @@ 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); @@ -2570,7 +2506,7 @@ 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); diff --git a/openmp/libomptarget/plugins/cuda/CMakeLists.txt b/openmp/libomptarget/plugins/cuda/CMakeLists.txt --- a/openmp/libomptarget/plugins/cuda/CMakeLists.txt +++ b/openmp/libomptarget/plugins/cuda/CMakeLists.txt @@ -19,9 +19,6 @@ if (NOT(CMAKE_SYSTEM_PROCESSOR MATCHES "(x86_64)|(ppc64le)|(aarch64)$" AND CMAKE_SYSTEM_NAME MATCHES "Linux")) libomptarget_say("Not building CUDA offloading plugin: only support CUDA in Linux x86_64, ppc64le, or aarch64 hosts.") return() -elseif (NOT LIBOMPTARGET_DEP_LIBELF_FOUND) - libomptarget_say("Not building CUDA offloading plugin: libelf dependency not found.") - return() endif() libomptarget_say("Building CUDA offloading plugin.") @@ -46,14 +43,12 @@ ADDITIONAL_HEADER_DIRS ${LIBOMPTARGET_INCLUDE_DIR} - ${LIBOMPTARGET_DEP_LIBELF_INCLUDE_DIRS} LINK_LIBS PRIVATE elf_common MemoryManager ${LIBOMPTARGET_DEP_CUDA_DRIVER_LIBRARIES} - ${LIBOMPTARGET_DEP_LIBELF_LIBRARIES} ${OPENMP_PTHREAD_LIB} "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/../exports" "-Wl,-z,defs" @@ -71,14 +66,12 @@ ADDITIONAL_HEADER_DIRS ${LIBOMPTARGET_INCLUDE_DIR} - ${LIBOMPTARGET_DEP_LIBELF_INCLUDE_DIRS} LINK_LIBS PRIVATE elf_common MemoryManager ${CMAKE_DL_LIBS} - ${LIBOMPTARGET_DEP_LIBELF_LIBRARIES} ${OPENMP_PTHREAD_LIB} "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/../exports" "-Wl,-z,defs" @@ -95,7 +88,6 @@ target_include_directories(omptarget.rtl.cuda PRIVATE ${LIBOMPTARGET_INCLUDE_DIR} - ${LIBOMPTARGET_DEP_LIBELF_INCLUDE_DIRS} ) # Report to the parent scope that we are building a plugin for CUDA. diff --git a/openmp/libomptarget/plugins/generic-elf-64bit/src/rtl.cpp b/openmp/libomptarget/plugins/generic-elf-64bit/src/rtl.cpp --- a/openmp/libomptarget/plugins/generic-elf-64bit/src/rtl.cpp +++ b/openmp/libomptarget/plugins/generic-elf-64bit/src/rtl.cpp @@ -10,6 +10,8 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Object/ELFObjectFile.h" + #include #include #include @@ -25,6 +27,9 @@ #include "Debug.h" #include "omptargetplugin.h" +using namespace llvm; +using namespace llvm::object; + #ifndef TARGET_NAME #define TARGET_NAME Generic ELF - 64bit #endif @@ -37,7 +42,7 @@ #include "elf_common.h" #define NUMBER_OF_DEVICES 4 -#define OFFLOADSECTIONNAME "omp_offloading_entries" +#define OFFLOAD_SECTION_NAME "omp_offloading_entries" /// Array of Dynamic libraries loaded for this target. struct DynLibTy { @@ -138,54 +143,31 @@ size_t NumEntries = (size_t)(Image->EntriesEnd - Image->EntriesBegin); DP("Expecting to have %zd entries defined.\n", NumEntries); - // Is the library version incompatible with the header file? - if (elf_version(EV_CURRENT) == EV_NONE) { - DP("Incompatible ELF library!\n"); - return NULL; + StringRef Buffer = StringRef((char *)Image->ImageStart, ImageSize); + auto ELFOrErr = ObjectFile::createObjectFile(MemoryBufferRef(Buffer, "")); + if (!ELFOrErr) { + REPORT("Unable to open ELF: %s\n", toString(ELFOrErr.takeError()).c_str()); + return nullptr; } - - // Obtain elf handler - Elf *E = elf_memory((char *)Image->ImageStart, ImageSize); - if (!E) { - DP("Unable to get ELF handle: %s!\n", elf_errmsg(-1)); - return NULL; + auto *ELF = dyn_cast((*ELFOrErr).get()); + if (!ELF) { + REPORT("Unable to open ELF: not an ELF file"); + return nullptr; } - if (elf_kind(E) != ELF_K_ELF) { - DP("Invalid Elf kind!\n"); - elf_end(E); - return NULL; - } - - // Find the entries section offset - Elf_Scn *Section = 0; - Elf64_Off EntriesOffset = 0; - - size_t Shstrndx; - - if (elf_getshdrstrndx(E, &Shstrndx)) { - DP("Unable to get ELF strings index!\n"); - elf_end(E); - return NULL; - } - - while ((Section = elf_nextscn(E, Section))) { - GElf_Shdr Hdr; - gelf_getshdr(Section, &Hdr); - - if (!strcmp(elf_strptr(E, Shstrndx, Hdr.sh_name), OFFLOADSECTIONNAME)) { - EntriesOffset = Hdr.sh_addr; - break; + uint64_t ElfEntriesAddr = 0; + for (ELFSectionRef Sec : ELF->sections()) { + auto NameOrErr = Sec.getName(); + if (!NameOrErr) { + REPORT("Unable to read: %s\n", toString(NameOrErr.takeError()).c_str()); + return nullptr; } - } - if (!EntriesOffset) { - DP("Entries Section Offset Not Found\n"); - elf_end(E); - return NULL; - } + if (!NameOrErr->equals(OFFLOAD_SECTION_NAME)) + continue; - DP("Offset of entries section is (" DPxMOD ").\n", DPxPTR(EntriesOffset)); + ElfEntriesAddr = Sec.getAddress(); + } // load dynamic library and get the entry points. We use the dl library // to do the loading of the library, but we could do it directly to avoid the @@ -196,17 +178,13 @@ char TmpName[] = "/tmp/tmpfile_XXXXXX"; int TmpFd = mkstemp(TmpName); - if (TmpFd == -1) { - elf_end(E); + if (TmpFd == -1) return NULL; - } FILE *Ftmp = fdopen(TmpFd, "wb"); - if (!Ftmp) { - elf_end(E); + if (!Ftmp) return NULL; - } fwrite(Image->ImageStart, ImageSize, 1, Ftmp); fclose(Ftmp); @@ -215,7 +193,6 @@ if (!Lib.Handle) { DP("Target library loading error: %s\n", dlerror()); - elf_end(E); return NULL; } @@ -225,7 +202,7 @@ // The place where the entries info is loaded is the library base address // plus the offset determined from the ELF file. - Elf64_Addr EntriesAddr = LibInfo->l_addr + EntriesOffset; + uint64_t EntriesAddr = LibInfo->l_addr + ElfEntriesAddr; DP("Pointer to first entry to be loaded is (" DPxMOD ").\n", DPxPTR(EntriesAddr)); @@ -238,7 +215,6 @@ if (!EntriesBegin) { DP("Can't obtain entries begin\n"); - elf_end(E); return NULL; } @@ -246,8 +222,6 @@ DPxPTR(EntriesBegin), DPxPTR(EntriesEnd)); DeviceInfo.createOffloadTable(DeviceId, EntriesBegin, EntriesEnd); - elf_end(E); - return DeviceInfo.getOffloadEntriesTable(DeviceId); } diff --git a/openmp/libomptarget/plugins/ve/CMakeLists.txt b/openmp/libomptarget/plugins/ve/CMakeLists.txt --- a/openmp/libomptarget/plugins/ve/CMakeLists.txt +++ b/openmp/libomptarget/plugins/ve/CMakeLists.txt @@ -29,14 +29,12 @@ ADDITIONAL_HEADER_DIRS ${LIBOMPTARGET_INCLUDE_DIR} - ${LIBOMPTARGET_DEP_LIBELF_INCLUDE_DIR} ${LIBOMPTARGET_DEP_VEO_INCLUDE_DIR} LINK_LIBS PRIVATE elf_common ${LIBOMPTARGET_DEP_LIBFFI_LIBRARIES} - ${LIBOMPTARGET_DEP_LIBELF_LIBRARIES} ${additional_libs} "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/../exports -Wl,-z,defs" @@ -50,14 +48,12 @@ target_include_directories("omptarget.rtl.${tmachine_libname}" PRIVATE ${LIBOMPTARGET_INCLUDE_DIR} - ${LIBOMPTARGET_DEP_LIBELF_INCLUDE_DIR} ${LIBOMPTARGET_DEP_VEO_INCLUDE_DIR}) target_link_libraries( "omptarget.rtl.${tmachine_libname}" elf_common ${LIBOMPTARGET_DEP_LIBFFI_LIBRARIES} - ${LIBOMPTARGET_DEP_LIBELF_LIBRARIES} ${additional_libs} "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/../exports -Wl,-z,defs")