Shilei Tian a81c68ae6b [OpenMP] Take elf_common.c as a interface library
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
2021-01-11 17:34:26 -05:00

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;
}