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,66 +19,59 @@ # - 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) + if(LIBOMPTARGET_DEP_LIBFFI_FOUND) - libomptarget_say("Building ${tmachine_name} offloading plugin.") + 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 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}") + # 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 + add_llvm_library("omptarget.rtl.${tmachine_libname}" + SHARED - ${CMAKE_CURRENT_SOURCE_DIR}/../generic-elf-64bit/src/rtl.cpp + ${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} + ADDITIONAL_HEADER_DIRS + ${LIBOMPTARGET_INCLUDE_DIR} + ${LIBOMPTARGET_DEP_LIBFFI_INCLUDE_DIR} LINK_LIBS PRIVATE elf_common ${LIBOMPTARGET_DEP_LIBFFI_LIBRARIES} - ${LIBOMPTARGET_DEP_LIBELF_LIBRARIES} ${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) + 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() @@ -84,7 +79,6 @@ PRIVATE elf_common ${LIBOMPTARGET_DEP_LIBRARIES} - ${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 @@ -162,66 +170,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 { @@ -337,7 +341,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 @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -45,6 +44,7 @@ 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, @@ -1563,8 +1563,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"); } @@ -1572,28 +1572,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) { 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,13 +66,11 @@ ADDITIONAL_HEADER_DIRS ${LIBOMPTARGET_INCLUDE_DIR} - ${LIBOMPTARGET_DEP_LIBELF_INCLUDE_DIRS} LINK_LIBS PRIVATE elf_common MemoryManager - ${LIBOMPTARGET_DEP_LIBELF_LIBRARIES} ${OPENMP_PTHREAD_LIB} "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/../exports" "-Wl,-z,defs" @@ -94,7 +87,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 @@ -42,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 { @@ -141,7 +141,6 @@ size_t ImageSize = (size_t)Image->ImageEnd - (size_t)Image->ImageStart; size_t NumEntries = (size_t)(Image->EntriesEnd - Image->EntriesBegin); - DP("Expecting to have %zd entries defined.\n", NumEntries); // 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 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")