Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
discover: Add helper functions to read ELF notes
The libelf has low level functions to access the ELF structures. This commit adds two external higher level functions: elf_open_image(): - Get the ELF structure from a binary; elf_getnote_desc() - Get the ELF note 'descriptor' using both namespace and ELF type. The definitions used in the 'elf.h' was taken from linux source code: - arch/powerpc/include/asm/elfnote.h - arch/powerpc/kernel/note.S Signed-off-by: Maxiwell S. Garcia <maxiwell@linux.ibm.com>
- Loading branch information
Showing
3 changed files
with
118 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <fcntl.h> | ||
|
||
#include <log/log.h> | ||
#include "elf.h" | ||
|
||
Elf *elf_open_image(const char *image) | ||
{ | ||
int fd; | ||
Elf *elf = NULL; | ||
int err; | ||
|
||
if (!image) { | ||
pb_log_fn("kernel image path is null\n"); | ||
return NULL; | ||
} | ||
|
||
if ((elf_version(EV_CURRENT) == EV_NONE) || | ||
((fd = open(image, O_RDONLY, 0)) == -1) || | ||
(!(elf = elf_begin(fd, ELF_C_READ, NULL)))) { | ||
err = elf_errno(); | ||
if (err) | ||
pb_log_fn("failed to read %s elf: %s\n", | ||
image, elf_errmsg(err)); | ||
} | ||
|
||
return elf; | ||
} | ||
|
||
static bool elf_getnote_offset(Elf_Data * const edata, | ||
const char *namespace, | ||
const uint32_t type, GElf_Nhdr *nhdr, | ||
size_t *n_off, size_t *d_off) | ||
{ | ||
size_t off = 0; | ||
size_t next; | ||
|
||
/* Iterate through notes */ | ||
while ((next = gelf_getnote(edata, off, nhdr, n_off, d_off)) > 0) { | ||
char *note_ns = (char *) edata->d_buf + (*n_off); | ||
if ((strcmp(note_ns, namespace) == 0) && (nhdr->n_type == type)) | ||
return true; | ||
|
||
off = next; | ||
} | ||
return false; | ||
} | ||
|
||
void *elf_getnote_desc(Elf *elf, | ||
const char *namespace, | ||
uint32_t type) | ||
{ | ||
Elf_Scn *scn = NULL; | ||
Elf_Data *edata = NULL; | ||
GElf_Shdr shdr; | ||
GElf_Nhdr nhdr; | ||
|
||
size_t n_off; | ||
size_t d_off; | ||
void *desc = NULL; | ||
|
||
if (!elf || !namespace) | ||
return NULL; | ||
|
||
/* Iterate through sections */ | ||
while ((scn = elf_nextscn(elf, scn))) { | ||
gelf_getshdr(scn, &shdr); | ||
|
||
/* ELF might have more than one SHT_NOTE section but | ||
only one has the 'namespace' note */ | ||
if (shdr.sh_type == SHT_NOTE) { | ||
edata = elf_getdata(scn, NULL); | ||
if (elf_getnote_offset(edata, namespace, type, | ||
&nhdr, &n_off, &d_off)) { | ||
desc = calloc(nhdr.n_descsz, sizeof(char)); | ||
memcpy(desc, edata->d_buf + d_off, | ||
nhdr.n_descsz); | ||
break; | ||
} | ||
} | ||
} | ||
|
||
return desc; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
#ifndef _PB_ELF_H | ||
#define _PB_ELF_H | ||
|
||
#include <elfutils/libdw.h> | ||
#include <libelf.h> | ||
|
||
/* | ||
* The PowerPC namespace in an ELF Note of the kernel binary is used to store | ||
* capabilities and information which can be used by a bootloader or userland | ||
* | ||
* docs: Documentation/powerpc/elfnote.rst | ||
*/ | ||
#define POWERPC_ELFNOTE_NAMESPACE "PowerPC" | ||
|
||
/* | ||
* The capabilities supported/required by the kernel | ||
* This type uses a bitmap as "desc" field. | ||
*/ | ||
#define PPC_ELFNOTE_CAPABILITIES 0x1 | ||
|
||
/* bitmap fields: */ | ||
#define PPCCAP_ULTRAVISOR_BIT 0x1 | ||
|
||
Elf *elf_open_image(const char *image); | ||
void *elf_getnote_desc(Elf *elf, | ||
const char *namespace, | ||
uint32_t type); | ||
|
||
#endif /* _PB_ELF_H */ |