aboutsummaryrefslogtreecommitdiff
path: root/src/libmach/dwarfpubnames.c
blob: 68ff911605745af41b119a5e45d5422ab422b430 (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
#include <u.h>
#include <libc.h>
#include <bio.h>
#include "elf.h"
#include "dwarf.h"

static int
_dwarfnametounit(Dwarf *d, char *name, DwarfBlock *bl, DwarfSym *s)
{
	int vers;
	ulong len, unit, off;
	uchar *next;
	char *str;
	DwarfBuf b;

	b.d = d;
	b.p = bl->data;
	b.ep = b.p + bl->len;

	while(b.p < b.ep){
		len = dwarfget4(&b);
		if(len > b.ep-b.p){
			werrstr("bad length in dwarf name header");
			return -1;
		}
		next = b.p + len;
		vers = dwarfget2(&b);
		if(vers != 1 && vers != 2){
			werrstr("bad version %d in dwarf name header", vers);
			return -1;
		}
		unit = dwarfget4(&b);
		dwarfget4(&b);	/* unit length */
		while(b.p < next){
			off = dwarfget4(&b);
			if(off == 0)
				break;
			str = dwarfgetstring(&b);
			if(strcmp(str, name) == 0){
				if(dwarfenumunit(d, unit, s) < 0)
					return -1;
				if(unit + off >= s->b.ep - d->info.data){
					werrstr("bad offset in name entry");
					return -1;
				}
				s->b.p = d->info.data + unit + off;
				if(dwarfnextsym(d, s) < 0)
					return -1;
				if(s->attrs.name==nil || strcmp(s->attrs.name, name)!=0){
					werrstr("unexpected name %#q in lookup for %#q", s->attrs.name, name);
					return -1;
				}
				return 0;
			}
		}
		b.p = next;
	}
	werrstr("unknown name '%s'", name);
	return -1;
}

int
dwarflookupname(Dwarf *d, char *name, DwarfSym *sym)
{
	return _dwarfnametounit(d, name, &d->pubnames, sym);
}

/*

int
dwarflookuptype(Dwarf *d, char *name, DwarfSym *sym)
{
	return _dwarfnametounit(d, name, &d->pubtypes, sym);
}

 */