aboutsummaryrefslogtreecommitdiff
path: root/src/libmach/dwarfopen.c
blob: 27e965a36d178c4bab9b438618054ba35492039a (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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include <u.h>
#include <libc.h>
#include <bio.h>
#include "elf.h"
#include "dwarf.h"

static int
readblock(int fd, DwarfBlock *b, ulong off, ulong len)
{
	b->data = malloc(len);
	if(b->data == nil)
		return -1;
	if(seek(fd, off, 0) < 0 || readn(fd, b->data, len) != len){
		free(b->data);
		b->data = nil;
		return -1;
	}
	b->len = len;
	return 0;
}

static int
findsection(Elf *elf, char *name, ulong *off, ulong *len)
{
	ElfSect *s;

	if((s = elfsection(elf, name)) == nil)
		return -1;
	*off = s->offset;
	*len = s->size;
	return s - elf->sect;
}

static int
loadsection(Elf *elf, char *name, DwarfBlock *b)
{
	ulong off, len;

	if(findsection(elf, name, &off, &len) < 0)
		return -1;
	return readblock(elf->fd, b, off, len);
}

Dwarf*
dwarfopen(Elf *elf)
{
	Dwarf *d;

	if(elf == nil){
		werrstr("nil elf passed to dwarfopen");
		return nil;
	}

	d = mallocz(sizeof(Dwarf), 1);
	if(d == nil)
		return nil;

	d->elf = elf;
	if(loadsection(elf, ".debug_abbrev", &d->abbrev) < 0
	|| loadsection(elf, ".debug_aranges", &d->aranges) < 0
	|| loadsection(elf, ".debug_line", &d->line) < 0
	|| loadsection(elf, ".debug_pubnames", &d->pubnames) < 0
	|| loadsection(elf, ".debug_info", &d->info) < 0)
		goto err;
	loadsection(elf, ".debug_frame", &d->frame);
	loadsection(elf, ".debug_ranges", &d->ranges);
	loadsection(elf, ".debug_str", &d->str);

	/* make this a table once there are more */
	switch(d->elf->hdr.machine){
	case ElfMach386:
		d->reg = dwarf386regs;
		d->nreg = dwarf386nregs;
		break;
	default:
		werrstr("unsupported machine");
		goto err;
	}

	return d;

err:
	free(d->abbrev.data);
	free(d->aranges.data);
	free(d->frame.data);
	free(d->line.data);
	free(d->pubnames.data);
	free(d->ranges.data);
	free(d->str.data);
	free(d->info.data);
	free(d);
	return nil;
}

void
dwarfclose(Dwarf *d)
{
	free(d->abbrev.data);
	free(d->aranges.data);
	free(d->frame.data);
	free(d->line.data);
	free(d->pubnames.data);
	free(d->ranges.data);
	free(d->str.data);
	free(d->info.data);
	free(d);
}