1 //===-- elf_common.cpp - Common ELF functionality -------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Common ELF functionality for target plugins. 10 // 11 //===----------------------------------------------------------------------===// 12 #include "elf_common.h" 13 #include "Debug.h" 14 15 #include "llvm/BinaryFormat/Magic.h" 16 #include "llvm/Object/Binary.h" 17 #include "llvm/Object/ELFObjectFile.h" 18 #include "llvm/Object/ELFTypes.h" 19 #include "llvm/Object/ObjectFile.h" 20 #include "llvm/Support/MemoryBuffer.h" 21 22 #ifndef TARGET_NAME 23 #define TARGET_NAME ELF Common 24 #endif 25 #define DEBUG_PREFIX "TARGET " GETNAME(TARGET_NAME) 26 27 using namespace llvm; 28 using namespace llvm::ELF; 29 using namespace llvm::object; 30 31 /// If the given range of bytes [\p BytesBegin, \p BytesEnd) represents 32 /// a valid ELF, then invoke \p Callback on the ELFObjectFileBase 33 /// created from this range, otherwise, return 0. 34 /// If \p Callback is invoked, then return whatever value \p Callback returns. 35 template <typename F> 36 static int32_t withBytesAsElf(char *BytesBegin, char *BytesEnd, F Callback) { 37 size_t Size = BytesEnd - BytesBegin; 38 StringRef StrBuf(BytesBegin, Size); 39 40 auto Magic = identify_magic(StrBuf); 41 if (Magic != file_magic::elf && Magic != file_magic::elf_relocatable && 42 Magic != file_magic::elf_executable && 43 Magic != file_magic::elf_shared_object && Magic != file_magic::elf_core) { 44 DP("Not an ELF image!\n"); 45 return 0; 46 } 47 48 std::unique_ptr<MemoryBuffer> MemBuf = 49 MemoryBuffer::getMemBuffer(StrBuf, "", false); 50 Expected<std::unique_ptr<ObjectFile>> BinOrErr = 51 ObjectFile::createELFObjectFile(MemBuf->getMemBufferRef(), 52 /*InitContent=*/false); 53 if (!BinOrErr) { 54 DP("Unable to get ELF handle: %s!\n", 55 toString(BinOrErr.takeError()).c_str()); 56 return 0; 57 } 58 59 auto *Object = dyn_cast<const ELFObjectFileBase>(BinOrErr->get()); 60 61 if (!Object) { 62 DP("Unknown ELF format!\n"); 63 return 0; 64 } 65 66 return Callback(Object); 67 } 68 69 // Check whether an image is valid for execution on target_id 70 int32_t elf_check_machine(__tgt_device_image *image, uint16_t target_id) { 71 auto CheckMachine = [target_id](const ELFObjectFileBase *Object) { 72 return target_id == Object->getEMachine(); 73 }; 74 return withBytesAsElf(reinterpret_cast<char *>(image->ImageStart), 75 reinterpret_cast<char *>(image->ImageEnd), 76 CheckMachine); 77 } 78 79 int32_t elf_is_dynamic(__tgt_device_image *image) { 80 auto CheckDynType = [](const ELFObjectFileBase *Object) { 81 uint16_t Type = Object->getEType(); 82 DP("ELF Type: %d\n", Type); 83 return Type == ET_DYN; 84 }; 85 return withBytesAsElf(reinterpret_cast<char *>(image->ImageStart), 86 reinterpret_cast<char *>(image->ImageEnd), 87 CheckDynType); 88 } 89