Blame


1 a84cbb2a 2004-04-19 devnull /*
2 a84cbb2a 2004-04-19 devnull * Dwarf abbreviation parsing code.
3 a84cbb2a 2004-04-19 devnull *
4 a84cbb2a 2004-04-19 devnull * The convention here is that calling dwarfgetabbrevs relinquishes
5 fa325e9b 2020-01-10 cross * access to any abbrevs returned previously. Will have to add
6 a84cbb2a 2004-04-19 devnull * explicit reference counting if this turns out not to be acceptable.
7 a84cbb2a 2004-04-19 devnull */
8 a84cbb2a 2004-04-19 devnull
9 a84cbb2a 2004-04-19 devnull #include <u.h>
10 a84cbb2a 2004-04-19 devnull #include <libc.h>
11 a84cbb2a 2004-04-19 devnull #include <bio.h>
12 a84cbb2a 2004-04-19 devnull #include "elf.h"
13 a84cbb2a 2004-04-19 devnull #include "dwarf.h"
14 a84cbb2a 2004-04-19 devnull
15 a84cbb2a 2004-04-19 devnull static int parseabbrevs(Dwarf*, ulong, DwarfAbbrev*, DwarfAttr*, int*, int*);
16 a84cbb2a 2004-04-19 devnull DwarfAbbrev *dwarfgetabbrev(Dwarf*, ulong, ulong);
17 a84cbb2a 2004-04-19 devnull
18 a84cbb2a 2004-04-19 devnull static int
19 a84cbb2a 2004-04-19 devnull loadabbrevs(Dwarf *d, ulong off, DwarfAbbrev **aa)
20 a84cbb2a 2004-04-19 devnull {
21 a84cbb2a 2004-04-19 devnull int nattr, nabbrev;
22 a84cbb2a 2004-04-19 devnull DwarfAbbrev *abbrev;
23 a84cbb2a 2004-04-19 devnull DwarfAttr *attr;
24 a84cbb2a 2004-04-19 devnull
25 a84cbb2a 2004-04-19 devnull if(d->acache.off == off && d->acache.na){
26 a84cbb2a 2004-04-19 devnull *aa = d->acache.a;
27 a84cbb2a 2004-04-19 devnull return d->acache.na;
28 a84cbb2a 2004-04-19 devnull }
29 a84cbb2a 2004-04-19 devnull
30 a84cbb2a 2004-04-19 devnull /* two passes - once to count, then allocate, then a second to copy */
31 a84cbb2a 2004-04-19 devnull if(parseabbrevs(d, off, nil, nil, &nabbrev, &nattr) < 0)
32 a84cbb2a 2004-04-19 devnull return -1;
33 a84cbb2a 2004-04-19 devnull
34 a84cbb2a 2004-04-19 devnull abbrev = malloc(nabbrev*sizeof(DwarfAbbrev) + nattr*sizeof(DwarfAttr));
35 a84cbb2a 2004-04-19 devnull attr = (DwarfAttr*)(abbrev+nabbrev);
36 a84cbb2a 2004-04-19 devnull
37 a84cbb2a 2004-04-19 devnull if(parseabbrevs(d, off, abbrev, attr, nil, nil) < 0){
38 a84cbb2a 2004-04-19 devnull free(abbrev);
39 a84cbb2a 2004-04-19 devnull return -1;
40 a84cbb2a 2004-04-19 devnull }
41 a84cbb2a 2004-04-19 devnull
42 a84cbb2a 2004-04-19 devnull free(d->acache.a);
43 a84cbb2a 2004-04-19 devnull d->acache.a = abbrev;
44 a84cbb2a 2004-04-19 devnull d->acache.na = nabbrev;
45 a84cbb2a 2004-04-19 devnull d->acache.off = off;
46 a84cbb2a 2004-04-19 devnull
47 a84cbb2a 2004-04-19 devnull *aa = abbrev;
48 a84cbb2a 2004-04-19 devnull return nabbrev;
49 a84cbb2a 2004-04-19 devnull }
50 a84cbb2a 2004-04-19 devnull
51 a84cbb2a 2004-04-19 devnull static int
52 a84cbb2a 2004-04-19 devnull parseabbrevs(Dwarf *d, ulong off, DwarfAbbrev *abbrev, DwarfAttr *attr, int *pnabbrev, int *pnattr)
53 a84cbb2a 2004-04-19 devnull {
54 a84cbb2a 2004-04-19 devnull int i, nabbrev, nattr, haskids;
55 a84cbb2a 2004-04-19 devnull ulong num, tag, name, form;
56 a84cbb2a 2004-04-19 devnull DwarfBuf b;
57 a84cbb2a 2004-04-19 devnull
58 a84cbb2a 2004-04-19 devnull if(off >= d->abbrev.len){
59 a84cbb2a 2004-04-19 devnull werrstr("bad abbrev section offset 0x%lux >= 0x%lux\n", off, d->abbrev.len);
60 a84cbb2a 2004-04-19 devnull return -1;
61 a84cbb2a 2004-04-19 devnull }
62 a84cbb2a 2004-04-19 devnull
63 a84cbb2a 2004-04-19 devnull memset(&b, 0, sizeof b);
64 a84cbb2a 2004-04-19 devnull b.p = d->abbrev.data + off;
65 a84cbb2a 2004-04-19 devnull b.ep = d->abbrev.data + d->abbrev.len;
66 a84cbb2a 2004-04-19 devnull
67 a84cbb2a 2004-04-19 devnull nabbrev = 0;
68 a84cbb2a 2004-04-19 devnull nattr = 0;
69 a84cbb2a 2004-04-19 devnull for(;;){
70 a84cbb2a 2004-04-19 devnull if(b.p == nil){
71 a84cbb2a 2004-04-19 devnull werrstr("malformed abbrev data");
72 a84cbb2a 2004-04-19 devnull return -1;
73 a84cbb2a 2004-04-19 devnull }
74 a84cbb2a 2004-04-19 devnull num = dwarfget128(&b);
75 a84cbb2a 2004-04-19 devnull if(num == 0)
76 a84cbb2a 2004-04-19 devnull break;
77 a84cbb2a 2004-04-19 devnull tag = dwarfget128(&b);
78 a84cbb2a 2004-04-19 devnull haskids = dwarfget1(&b);
79 a84cbb2a 2004-04-19 devnull for(i=0;; i++){
80 a84cbb2a 2004-04-19 devnull name = dwarfget128(&b);
81 a84cbb2a 2004-04-19 devnull form = dwarfget128(&b);
82 a84cbb2a 2004-04-19 devnull if(name == 0 && form == 0)
83 a84cbb2a 2004-04-19 devnull break;
84 a84cbb2a 2004-04-19 devnull if(attr){
85 a84cbb2a 2004-04-19 devnull attr[i].name = name;
86 a84cbb2a 2004-04-19 devnull attr[i].form = form;
87 a84cbb2a 2004-04-19 devnull }
88 a84cbb2a 2004-04-19 devnull }
89 a84cbb2a 2004-04-19 devnull if(abbrev){
90 a84cbb2a 2004-04-19 devnull abbrev->num = num;
91 a84cbb2a 2004-04-19 devnull abbrev->tag = tag;
92 a84cbb2a 2004-04-19 devnull abbrev->haskids = haskids;
93 a84cbb2a 2004-04-19 devnull abbrev->attr = attr;
94 a84cbb2a 2004-04-19 devnull abbrev->nattr = i;
95 a84cbb2a 2004-04-19 devnull abbrev++;
96 a84cbb2a 2004-04-19 devnull attr += i;
97 a84cbb2a 2004-04-19 devnull }
98 a84cbb2a 2004-04-19 devnull nabbrev++;
99 a84cbb2a 2004-04-19 devnull nattr += i;
100 a84cbb2a 2004-04-19 devnull }
101 a84cbb2a 2004-04-19 devnull if(pnabbrev)
102 a84cbb2a 2004-04-19 devnull *pnabbrev = nabbrev;
103 a84cbb2a 2004-04-19 devnull if(pnattr)
104 a84cbb2a 2004-04-19 devnull *pnattr = nattr;
105 a84cbb2a 2004-04-19 devnull return 0;
106 a84cbb2a 2004-04-19 devnull }
107 a84cbb2a 2004-04-19 devnull
108 a84cbb2a 2004-04-19 devnull static DwarfAbbrev*
109 a84cbb2a 2004-04-19 devnull findabbrev(DwarfAbbrev *a, int na, ulong num)
110 a84cbb2a 2004-04-19 devnull {
111 a84cbb2a 2004-04-19 devnull int i;
112 a84cbb2a 2004-04-19 devnull
113 a84cbb2a 2004-04-19 devnull for(i=0; i<na; i++)
114 a84cbb2a 2004-04-19 devnull if(a[i].num == num)
115 a84cbb2a 2004-04-19 devnull return &a[i];
116 eaf56db5 2004-04-21 devnull werrstr("abbrev not found");
117 a84cbb2a 2004-04-19 devnull return nil;
118 a84cbb2a 2004-04-19 devnull }
119 a84cbb2a 2004-04-19 devnull
120 a84cbb2a 2004-04-19 devnull DwarfAbbrev*
121 a84cbb2a 2004-04-19 devnull dwarfgetabbrev(Dwarf *d, ulong off, ulong num)
122 a84cbb2a 2004-04-19 devnull {
123 a84cbb2a 2004-04-19 devnull DwarfAbbrev *a;
124 a84cbb2a 2004-04-19 devnull int na;
125 a84cbb2a 2004-04-19 devnull
126 eaf56db5 2004-04-21 devnull if((na = loadabbrevs(d, off, &a)) < 0){
127 eaf56db5 2004-04-21 devnull werrstr("loadabbrevs: %r");
128 a84cbb2a 2004-04-19 devnull return nil;
129 eaf56db5 2004-04-21 devnull }
130 a84cbb2a 2004-04-19 devnull return findabbrev(a, na, num);
131 a84cbb2a 2004-04-19 devnull }