1 //===-- elf_common.c - Common ELF functionality -------------------*- C -*-===//
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 // Must be included in the plugin source file AFTER omptarget.h has been
11 // included and macro DP(...) has been defined.
12 // .
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #if !(defined(_OMPTARGET_H_) && defined(DP))
17 #error Include elf_common.c in the plugin source AFTER omptarget.h has been\
18  included and macro DP(...) has been defined.
19 #endif
20 
21 #include <elf.h>
22 #include <libelf.h>
23 
24 // Check whether an image is valid for execution on target_id
elf_check_machine(__tgt_device_image * image,uint16_t target_id)25 static inline int32_t elf_check_machine(__tgt_device_image *image,
26     uint16_t target_id) {
27 
28   // Is the library version incompatible with the header file?
29   if (elf_version(EV_CURRENT) == EV_NONE) {
30     DP("Incompatible ELF library!\n");
31     return 0;
32   }
33 
34   char *img_begin = (char *)image->ImageStart;
35   char *img_end = (char *)image->ImageEnd;
36   size_t img_size = img_end - img_begin;
37 
38   // Obtain elf handler
39   Elf *e = elf_memory(img_begin, img_size);
40   if (!e) {
41     DP("Unable to get ELF handle: %s!\n", elf_errmsg(-1));
42     return 0;
43   }
44 
45   // Check if ELF is the right kind.
46   if (elf_kind(e) != ELF_K_ELF) {
47     DP("Unexpected ELF type!\n");
48     elf_end(e);
49     return 0;
50   }
51   Elf64_Ehdr *eh64 = elf64_getehdr(e);
52   Elf32_Ehdr *eh32 = elf32_getehdr(e);
53 
54   if (!eh64 && !eh32) {
55     DP("Unable to get machine ID from ELF file!\n");
56     elf_end(e);
57     return 0;
58   }
59 
60   uint16_t MachineID;
61   if (eh64 && !eh32)
62     MachineID = eh64->e_machine;
63   else if (eh32 && !eh64)
64     MachineID = eh32->e_machine;
65   else {
66     DP("Ambiguous ELF header!\n");
67     elf_end(e);
68     return 0;
69   }
70 
71   elf_end(e);
72   return MachineID == target_id;
73 }
74 
elf_is_dynamic(__tgt_device_image * image)75 static inline int32_t elf_is_dynamic(__tgt_device_image *image) {
76 
77   char *img_begin = (char *)image->ImageStart;
78   char *img_end = (char *)image->ImageEnd;
79   size_t img_size = img_end - img_begin;
80 
81   // Obtain elf handler
82   Elf *e = elf_memory(img_begin, img_size);
83   if (!e) {
84     DP("Unable to get ELF handle: %s!\n", elf_errmsg(-1));
85     return 0;
86   }
87 
88   Elf64_Ehdr *eh64 = elf64_getehdr(e);
89   Elf32_Ehdr *eh32 = elf32_getehdr(e);
90 
91   if (!eh64 && !eh32) {
92     DP("Unable to get machine ID from ELF file!\n");
93     elf_end(e);
94     return 0;
95   }
96 
97   uint16_t Type;
98   if (eh64 && !eh32)
99     Type = eh64->e_type;
100   else if (eh32 && !eh64)
101     Type = eh32->e_type;
102   else {
103     DP("Ambiguous ELF header!\n");
104     elf_end(e);
105     return 0;
106   }
107 
108   elf_end(e);
109   DP("ELF Type: %d\n", Type);
110   return Type == ET_DYN;
111 }
112