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 @@ -75,7 +75,9 @@ PRIVATE elf_common hsa-runtime64::hsa-runtime64 - pthread dl elf + dl + ${LIBOMPTARGET_DEP_LIBELF_LIBRARIES} + ${OPENMP_PTHREAD_LIB} "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/../exports" "-Wl,-z,defs" ) diff --git a/openmp/libomptarget/plugins/common/elf_common/CMakeLists.txt b/openmp/libomptarget/plugins/common/elf_common/CMakeLists.txt --- a/openmp/libomptarget/plugins/common/elf_common/CMakeLists.txt +++ b/openmp/libomptarget/plugins/common/elf_common/CMakeLists.txt @@ -10,6 +10,15 @@ # ##===----------------------------------------------------------------------===## -add_library(elf_common INTERFACE) +add_library(elf_common OBJECT elf_common.cpp) +llvm_update_compile_flags(elf_common) +set(LINK_LLVM_LIBS LLVMBinaryFormat LLVMObject LLVMSupport) +target_link_libraries(elf_common INTERFACE ${LINK_LLVM_LIBS} ${LIBOMPTARGET_DEP_LIBELF_LIBRARIES}) +add_dependencies(elf_common ${LINK_LLVM_LIBS}) + +# The code uses Debug.h, which requires threads support. +target_link_libraries(elf_common INTERFACE ${OPENMP_PTHREAD_LIB}) + +# Expose elf_common.h directory to the users of this library. target_include_directories(elf_common INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/openmp/libomptarget/plugins/common/elf_common/elf_common.h b/openmp/libomptarget/plugins/common/elf_common/elf_common.h --- a/openmp/libomptarget/plugins/common/elf_common/elf_common.h +++ b/openmp/libomptarget/plugins/common/elf_common/elf_common.h @@ -1,4 +1,4 @@ -//===-- elf_common.h - Common ELF functionality -------------------*- C -*-===// +//===-- elf_common.h - Common ELF functionality -----------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -7,105 +7,21 @@ //===----------------------------------------------------------------------===// // // Common ELF functionality for target plugins. -// Must be included in the plugin source file AFTER omptarget.h has been -// included and macro DP(...) has been defined. -// . // //===----------------------------------------------------------------------===// -#if !(defined(_OMPTARGET_DEBUG_H)) -#error Include elf_common.h in the plugin source AFTER Debug.h has\ - been included. -#endif +#ifndef LLVM_OPENMP_LIBOMPTARGET_PLUGINS_COMMON_ELF_COMMON_ELF_COMMON_H +#define LLVM_OPENMP_LIBOMPTARGET_PLUGINS_COMMON_ELF_COMMON_ELF_COMMON_H -#include -#include +#include "omptargetplugin.h" +#include -// Check whether an image is valid for execution on target_id -static inline int32_t elf_check_machine(__tgt_device_image *image, - uint16_t target_id) { +/// Return non-zero, if the given \p image is an ELF object, which +/// e_machine matches \p target_id; return zero otherwise. +EXTERN int32_t elf_check_machine(__tgt_device_image *image, uint16_t target_id); - // Is the library version incompatible with the header file? - if (elf_version(EV_CURRENT) == EV_NONE) { - DP("Incompatible ELF library!\n"); - return 0; - } +/// Return non-zero, if the given \p image is an ET_DYN ELF object; +/// return zero otherwise. +EXTERN int32_t elf_is_dynamic(__tgt_device_image *image); - char *img_begin = (char *)image->ImageStart; - char *img_end = (char *)image->ImageEnd; - size_t img_size = img_end - img_begin; - - // Obtain elf handler - Elf *e = elf_memory(img_begin, img_size); - if (!e) { - DP("Unable to get ELF handle: %s!\n", elf_errmsg(-1)); - return 0; - } - - // Check if ELF is the right kind. - if (elf_kind(e) != ELF_K_ELF) { - DP("Unexpected ELF type!\n"); - elf_end(e); - return 0; - } - Elf64_Ehdr *eh64 = elf64_getehdr(e); - Elf32_Ehdr *eh32 = elf32_getehdr(e); - - if (!eh64 && !eh32) { - DP("Unable to get machine ID from ELF file!\n"); - elf_end(e); - return 0; - } - - uint16_t MachineID; - if (eh64 && !eh32) - MachineID = eh64->e_machine; - else if (eh32 && !eh64) - MachineID = eh32->e_machine; - else { - DP("Ambiguous ELF header!\n"); - elf_end(e); - return 0; - } - - elf_end(e); - return MachineID == target_id; -} - -static inline int32_t elf_is_dynamic(__tgt_device_image *image) { - - char *img_begin = (char *)image->ImageStart; - char *img_end = (char *)image->ImageEnd; - size_t img_size = img_end - img_begin; - - // Obtain elf handler - Elf *e = elf_memory(img_begin, img_size); - if (!e) { - DP("Unable to get ELF handle: %s!\n", elf_errmsg(-1)); - return 0; - } - - Elf64_Ehdr *eh64 = elf64_getehdr(e); - Elf32_Ehdr *eh32 = elf32_getehdr(e); - - if (!eh64 && !eh32) { - DP("Unable to get machine ID from ELF file!\n"); - elf_end(e); - return 0; - } - - uint16_t Type; - if (eh64 && !eh32) - Type = eh64->e_type; - else if (eh32 && !eh64) - Type = eh32->e_type; - else { - DP("Ambiguous ELF header!\n"); - elf_end(e); - return 0; - } - - elf_end(e); - DP("ELF Type: %d\n", Type); - return Type == ET_DYN; -} +#endif // LLVM_OPENMP_LIBOMPTARGET_PLUGINS_COMMON_ELF_COMMON_ELF_COMMON_H diff --git a/openmp/libomptarget/plugins/common/elf_common/elf_common.cpp b/openmp/libomptarget/plugins/common/elf_common/elf_common.cpp new file mode 100644 --- /dev/null +++ b/openmp/libomptarget/plugins/common/elf_common/elf_common.cpp @@ -0,0 +1,88 @@ +//===-- elf_common.cpp - Common ELF functionality -------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Common ELF functionality for target plugins. +// +//===----------------------------------------------------------------------===// +#include "elf_common.h" +#include "Debug.h" + +#include "llvm/BinaryFormat/Magic.h" +#include "llvm/Object/Binary.h" +#include "llvm/Object/ELFObjectFile.h" +#include "llvm/Object/ELFTypes.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/MemoryBuffer.h" + +#ifndef TARGET_NAME +#define TARGET_NAME ELF Common +#endif +#define DEBUG_PREFIX "TARGET " GETNAME(TARGET_NAME) + +using namespace llvm; +using namespace llvm::ELF; +using namespace llvm::object; + +/// If the given range of bytes [\p BytesBegin, \p BytesEnd) represents +/// a valid ELF, then invoke \p Callback on the ELFObjectFileBase +/// created from this range, otherwise, return 0. +/// If \p Callback is invoked, then return whatever value \p Callback returns. +template +static int32_t withBytesAsElf(char *BytesBegin, char *BytesEnd, F Callback) { + size_t Size = BytesEnd - BytesBegin; + StringRef StrBuf(BytesBegin, Size); + + auto Magic = identify_magic(StrBuf); + if (Magic != file_magic::elf && Magic != file_magic::elf_relocatable && + Magic != file_magic::elf_executable && + Magic != file_magic::elf_shared_object && Magic != file_magic::elf_core) { + DP("Not an ELF image!\n"); + return 0; + } + + std::unique_ptr MemBuf = + MemoryBuffer::getMemBuffer(StrBuf, "", false); + Expected> BinOrErr = + ObjectFile::createELFObjectFile(MemBuf->getMemBufferRef(), + /*InitContent=*/false); + if (!BinOrErr) { + DP("Unable to get ELF handle: %s!\n", + toString(BinOrErr.takeError()).c_str()); + return 0; + } + + auto *Object = dyn_cast(BinOrErr->get()); + + if (!Object) { + DP("Unknown ELF format!\n"); + return 0; + } + + return Callback(Object); +} + +// Check whether an image is valid for execution on target_id +int32_t elf_check_machine(__tgt_device_image *image, uint16_t target_id) { + auto CheckMachine = [target_id](const ELFObjectFileBase *Object) { + return target_id == Object->getEMachine(); + }; + return withBytesAsElf(reinterpret_cast(image->ImageStart), + reinterpret_cast(image->ImageEnd), + CheckMachine); +} + +int32_t elf_is_dynamic(__tgt_device_image *image) { + auto CheckDynType = [](const ELFObjectFileBase *Object) { + uint16_t Type = Object->getEType(); + DP("ELF Type: %d\n", Type); + return Type == ET_DYN; + }; + return withBytesAsElf(reinterpret_cast(image->ImageStart), + reinterpret_cast(image->ImageEnd), + CheckDynType); +} diff --git a/openmp/libomptarget/plugins/remote/server/CMakeLists.txt b/openmp/libomptarget/plugins/remote/server/CMakeLists.txt --- a/openmp/libomptarget/plugins/remote/server/CMakeLists.txt +++ b/openmp/libomptarget/plugins/remote/server/CMakeLists.txt @@ -10,7 +10,6 @@ # ##===----------------------------------------------------------------------===## -include_directories(${LIBOMPTARGET_DEP_LIBELF_INCLUDE_DIRS}) include_directories(${LIBOMPTARGET_SRC_DIR}) include_directories(${LIBOMPTARGET_INCLUDE_DIR}) include_directories(${GRPC_INCLUDE_DIR}) @@ -28,4 +27,4 @@ grpc++ protobuf ${OPENMP_PTHREAD_LIB} - "-ldl" "-lomp" "-fopenmp" "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/../../exports" ${LIBOMPTARGET_DEP_LIBELF_LIBRARIES}) + "-ldl" "-lomp" "-fopenmp" "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/../../exports")