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>
withBytesAsElf(char * BytesBegin,char * BytesEnd,F Callback)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
elf_check_machine(__tgt_device_image * Image,uint16_t TargetId)70 int32_t elf_check_machine(__tgt_device_image *Image, uint16_t TargetId) {
71   auto CheckMachine = [TargetId](const ELFObjectFileBase *Object) {
72     return TargetId == Object->getEMachine();
73   };
74   return withBytesAsElf(reinterpret_cast<char *>(Image->ImageStart),
75                         reinterpret_cast<char *>(Image->ImageEnd),
76                         CheckMachine);
77 }
78 
elf_is_dynamic(__tgt_device_image * Image)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