File: bpf_dump.c

package info (click to toggle)
dtrace 2.0.5-1
  • links: PTS
  • area: main
  • in suites: sid
  • size: 24,408 kB
  • sloc: ansic: 61,247; sh: 17,997; asm: 1,717; lex: 947; awk: 754; yacc: 695; perl: 37; sed: 17; makefile: 15
file content (140 lines) | stat: -rw-r--r-- 3,269 bytes parent folder | download
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include <errno.h>
#include <fcntl.h>
#include <gelf.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <port.h>

static int readBPFFile(const char *fn)
{
	int		fd;
	int		rc = -1;
	int		idx = 0;
	int		text_shidx = 0;
	size_t		text_size = 0, offset = 0;
	Elf		*elf = NULL;
	Elf_Data	*data;
	Elf_Scn		*scn;
	GElf_Ehdr	ehdr;
	GElf_Shdr	shdr;

	if ((fd = open64(fn, O_RDONLY)) == -1) {
		fprintf(stderr, "Failed to open %s: %s\n",
			fn, strerror(errno));
		return -1;
	}
	if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
		fprintf(stderr, "Failed to open ELF in %s\n", fn);
		goto err_elf;
	}
	if (elf_kind(elf) != ELF_K_ELF) {
		fprintf(stderr, "Unsupported ELF file type for %s: %d\n",
			fn, elf_kind(elf));
		goto out;
	}
	if (gelf_getehdr(elf, &ehdr) == NULL) {
		fprintf(stderr, "Failed to read EHDR from %s", fn);
		goto err_elf;
	}
	if (ehdr.e_machine != EM_BPF) {
		fprintf(stderr, "Unsupported ELF machine type %d for %s\n",
			ehdr.e_machine, fn);
		goto out;
	}

	scn = NULL;
	while ((scn = elf_nextscn(elf, scn)) != NULL) {
		char *name;

		idx++;
		if (gelf_getshdr(scn, &shdr) == NULL) {
			fprintf(stderr, "Failed to get SHDR from %s", fn);
			goto err_elf;
		}

		name = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name);
		if (name == NULL) {
			fprintf(stderr, "Failed to get section name from %s\n",
				fn);
			goto out;
		}
printf("Found section [%s], idx %d\n", name, idx);
		if (shdr.sh_type == SHT_SYMTAB) {
			size_t	i;

			if ((data = elf_getdata(scn, NULL)) == NULL) {
				fprintf(stderr, "Failed to get .symtab data "
						"from %s", fn);
				goto err_elf;
			}

			for (i = 0; i < data->d_size / sizeof(GElf_Sym); i++) {
				GElf_Sym	sym;
				char		*sname;

				if (!gelf_getsym(data, i, &sym))
					continue;
				if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL)
					continue;
				if (sym.st_shndx != text_shidx)
					continue;
				sname = elf_strptr(elf, shdr.sh_link,
						   sym.st_name);
				if (sname == NULL) {
					fprintf(stderr, "Failed to get symbol "
							"name from %s\n", fn);
					goto out;
				}
if (sym.st_value > offset) printf("    Updated previous symbol size = %lu (%lu dw)\n", sym.st_value - offset, (sym.st_value - offset) / 8);
offset = sym.st_value;
printf("  Found symbol [%s], size = %lu, val = %lu, bind %d, type %d, section %d\n", sname, sym.st_size != 0 ? sym.st_size : text_size - sym.st_value, sym.st_value, GELF_ST_BIND(sym.st_info), GELF_ST_TYPE(sym.st_info), sym.st_shndx);
			}
                } else if (shdr.sh_type == SHT_PROGBITS) {
			if ((data = elf_getdata(scn, NULL)) == NULL) {
				fprintf(stderr, "Failed to get data from %s",
					fn);
				goto err_elf;
			}
			if (!(shdr.sh_flags & SHF_EXECINSTR))
				continue;

			if (strcmp(name, ".text") == 0) {
				text_shidx = idx;
				text_size = shdr.sh_size;
			}
		}
	}

	rc = 0;
	goto out;

err_elf:
	fprintf(stderr, ": %s\n", elf_errmsg(elf_errno()));

out:
	if (elf)
		elf_end(elf);

	close(fd);

	return rc;
}

int main(int argc, char *argv[])
{
	int	i;

	if (elf_version(EV_CURRENT) == EV_NONE) {
		fprintf(stderr, "Invalid current ELF version.\n");
		exit(1);
	}
	if (argc < 2) {
		fprintf(stderr, "No object files specified.\n");
		exit(1);
	}

	for (i = 1; i < argc; i++)
		readBPFFile(argv[i]);
}