For now `elf_common.c` is taken as a common part included into different plugin implementations directly via `#include "../../common/elf_common.c"`, which is not a best practice. Since it is simple enough such that we don't need to create a real library for it, we just take it as a interface library so that other targets can link it directly. Another advantage of this method is, we don't need to add the folder into header search path which can potentially pollute the search path. VE and AMD platforms have not been tested because I don't have target machines. Reviewed By: JonChesterfield Differential Revision: https://reviews.llvm.org/D94443
112 lines
2.8 KiB
C
112 lines
2.8 KiB
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.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// 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
|
|
|
|
#include <elf.h>
|
|
#include <libelf.h>
|
|
|
|
// 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) {
|
|
|
|
// Is the library version incompatible with the header file?
|
|
if (elf_version(EV_CURRENT) == EV_NONE) {
|
|
DP("Incompatible ELF library!\n");
|
|
return 0;
|
|
}
|
|
|
|
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;
|
|
}
|