summaryrefslogtreecommitdiffstats
path: root/discover/elf.c
blob: 8c2711e48ae3b33a093eca56ac9bb749c70a77cc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
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;
}

OpenPOWER on IntegriCloud