Blame


1 a84cbb2a 2004-04-19 devnull /*
2 a84cbb2a 2004-04-19 devnull * Dwarf pc to source line conversion.
3 fa325e9b 2020-01-10 cross *
4 a84cbb2a 2004-04-19 devnull * Maybe should do the reverse here, but what should the interface look like?
5 a84cbb2a 2004-04-19 devnull * One possibility is to use the Plan 9 line2addr interface:
6 a84cbb2a 2004-04-19 devnull *
7 a84cbb2a 2004-04-19 devnull * long line2addr(ulong line, ulong basepc)
8 a84cbb2a 2004-04-19 devnull *
9 a84cbb2a 2004-04-19 devnull * which returns the smallest pc > basepc with line number line (ignoring file name).
10 a84cbb2a 2004-04-19 devnull *
11 a84cbb2a 2004-04-19 devnull * The encoding may be small, but it sure isn't simple!
12 a84cbb2a 2004-04-19 devnull */
13 a84cbb2a 2004-04-19 devnull
14 a84cbb2a 2004-04-19 devnull #include <u.h>
15 a84cbb2a 2004-04-19 devnull #include <libc.h>
16 a84cbb2a 2004-04-19 devnull #include <bio.h>
17 a84cbb2a 2004-04-19 devnull #include "elf.h"
18 a84cbb2a 2004-04-19 devnull #include "dwarf.h"
19 a84cbb2a 2004-04-19 devnull
20 a84cbb2a 2004-04-19 devnull #define trace 0
21 a84cbb2a 2004-04-19 devnull
22 a84cbb2a 2004-04-19 devnull enum
23 a84cbb2a 2004-04-19 devnull {
24 a84cbb2a 2004-04-19 devnull Isstmt = 1<<0,
25 a84cbb2a 2004-04-19 devnull BasicDwarfBlock = 1<<1,
26 a84cbb2a 2004-04-19 devnull EndSequence = 1<<2,
27 a84cbb2a 2004-04-19 devnull PrologueEnd = 1<<3,
28 cbeb0b26 2006-04-01 devnull EpilogueBegin = 1<<4
29 a84cbb2a 2004-04-19 devnull };
30 a84cbb2a 2004-04-19 devnull
31 a84cbb2a 2004-04-19 devnull typedef struct State State;
32 a84cbb2a 2004-04-19 devnull struct State
33 a84cbb2a 2004-04-19 devnull {
34 a84cbb2a 2004-04-19 devnull ulong addr;
35 a84cbb2a 2004-04-19 devnull ulong file;
36 a84cbb2a 2004-04-19 devnull ulong line;
37 a84cbb2a 2004-04-19 devnull ulong column;
38 a84cbb2a 2004-04-19 devnull ulong flags;
39 a84cbb2a 2004-04-19 devnull ulong isa;
40 a84cbb2a 2004-04-19 devnull };
41 a84cbb2a 2004-04-19 devnull
42 a84cbb2a 2004-04-19 devnull int
43 a84cbb2a 2004-04-19 devnull dwarfpctoline(Dwarf *d, ulong pc, char **cdir, char **dir, char **file, ulong *line, ulong *mtime, ulong *length)
44 a84cbb2a 2004-04-19 devnull {
45 a84cbb2a 2004-04-19 devnull uchar *prog, *opcount, *end;
46 a84cbb2a 2004-04-19 devnull ulong off, unit, len, vers, x, start;
47 a84cbb2a 2004-04-19 devnull int i, first, op, a, l, quantum, isstmt, linebase, linerange, opcodebase, nf;
48 a84cbb2a 2004-04-19 devnull char *files, *dirs, *s;
49 a84cbb2a 2004-04-19 devnull DwarfBuf b;
50 a84cbb2a 2004-04-19 devnull DwarfSym sym;
51 a84cbb2a 2004-04-19 devnull State emit, cur, reset;
52 a84cbb2a 2004-04-19 devnull uchar **f, **newf;
53 a84cbb2a 2004-04-19 devnull
54 a84cbb2a 2004-04-19 devnull f = nil;
55 a84cbb2a 2004-04-19 devnull
56 a84cbb2a 2004-04-19 devnull if(dwarfaddrtounit(d, pc, &unit) < 0
57 a84cbb2a 2004-04-19 devnull || dwarflookuptag(d, unit, TagCompileUnit, &sym) < 0)
58 a84cbb2a 2004-04-19 devnull return -1;
59 a84cbb2a 2004-04-19 devnull
60 a84cbb2a 2004-04-19 devnull if(!sym.attrs.have.stmtlist){
61 a84cbb2a 2004-04-19 devnull werrstr("no line mapping information for 0x%lux", pc);
62 a84cbb2a 2004-04-19 devnull return -1;
63 a84cbb2a 2004-04-19 devnull }
64 a84cbb2a 2004-04-19 devnull off = sym.attrs.stmtlist;
65 a84cbb2a 2004-04-19 devnull if(off >= d->line.len){
66 a84cbb2a 2004-04-19 devnull fprint(2, "bad stmtlist\n");
67 a84cbb2a 2004-04-19 devnull goto bad;
68 a84cbb2a 2004-04-19 devnull }
69 a84cbb2a 2004-04-19 devnull
70 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "unit 0x%lux stmtlist 0x%lux\n", unit, sym.attrs.stmtlist);
71 a84cbb2a 2004-04-19 devnull
72 a84cbb2a 2004-04-19 devnull memset(&b, 0, sizeof b);
73 a84cbb2a 2004-04-19 devnull b.d = d;
74 a84cbb2a 2004-04-19 devnull b.p = d->line.data + off;
75 a84cbb2a 2004-04-19 devnull b.ep = b.p + d->line.len;
76 a84cbb2a 2004-04-19 devnull b.addrsize = sym.b.addrsize; /* should i get this from somewhere else? */
77 a84cbb2a 2004-04-19 devnull
78 a84cbb2a 2004-04-19 devnull len = dwarfget4(&b);
79 a84cbb2a 2004-04-19 devnull if(b.p==nil || b.p+len > b.ep || b.p+len < b.p){
80 a84cbb2a 2004-04-19 devnull fprint(2, "bad len\n");
81 a84cbb2a 2004-04-19 devnull goto bad;
82 a84cbb2a 2004-04-19 devnull }
83 a84cbb2a 2004-04-19 devnull
84 a84cbb2a 2004-04-19 devnull b.ep = b.p+len;
85 a84cbb2a 2004-04-19 devnull vers = dwarfget2(&b);
86 a84cbb2a 2004-04-19 devnull if(vers != 2){
87 a84cbb2a 2004-04-19 devnull werrstr("bad dwarf version 0x%lux", vers);
88 a84cbb2a 2004-04-19 devnull return -1;
89 a84cbb2a 2004-04-19 devnull }
90 a84cbb2a 2004-04-19 devnull
91 a84cbb2a 2004-04-19 devnull len = dwarfget4(&b);
92 a84cbb2a 2004-04-19 devnull if(b.p==nil || b.p+len > b.ep || b.p+len < b.p){
93 a84cbb2a 2004-04-19 devnull fprint(2, "another bad len\n");
94 a84cbb2a 2004-04-19 devnull goto bad;
95 a84cbb2a 2004-04-19 devnull }
96 a84cbb2a 2004-04-19 devnull prog = b.p+len;
97 a84cbb2a 2004-04-19 devnull
98 a84cbb2a 2004-04-19 devnull quantum = dwarfget1(&b);
99 a84cbb2a 2004-04-19 devnull isstmt = dwarfget1(&b);
100 a84cbb2a 2004-04-19 devnull linebase = (schar)dwarfget1(&b);
101 a84cbb2a 2004-04-19 devnull linerange = (schar)dwarfget1(&b);
102 a84cbb2a 2004-04-19 devnull opcodebase = dwarfget1(&b);
103 a84cbb2a 2004-04-19 devnull
104 a84cbb2a 2004-04-19 devnull opcount = b.p-1;
105 a84cbb2a 2004-04-19 devnull dwarfgetnref(&b, opcodebase-1);
106 a84cbb2a 2004-04-19 devnull if(b.p == nil){
107 a84cbb2a 2004-04-19 devnull fprint(2, "bad opcode chart\n");
108 a84cbb2a 2004-04-19 devnull goto bad;
109 a84cbb2a 2004-04-19 devnull }
110 a84cbb2a 2004-04-19 devnull
111 a84cbb2a 2004-04-19 devnull /* just skip the files and dirs for now; we'll come back */
112 929ba9b9 2004-04-20 devnull dirs = (char*)b.p;
113 a84cbb2a 2004-04-19 devnull while(b.p!=nil && *b.p!=0)
114 a84cbb2a 2004-04-19 devnull dwarfgetstring(&b);
115 a84cbb2a 2004-04-19 devnull dwarfget1(&b);
116 a84cbb2a 2004-04-19 devnull
117 929ba9b9 2004-04-20 devnull files = (char*)b.p;
118 a84cbb2a 2004-04-19 devnull while(b.p!=nil && *b.p!=0){
119 a84cbb2a 2004-04-19 devnull dwarfgetstring(&b);
120 a84cbb2a 2004-04-19 devnull dwarfget128(&b);
121 a84cbb2a 2004-04-19 devnull dwarfget128(&b);
122 a84cbb2a 2004-04-19 devnull dwarfget128(&b);
123 a84cbb2a 2004-04-19 devnull }
124 a84cbb2a 2004-04-19 devnull dwarfget1(&b);
125 a84cbb2a 2004-04-19 devnull
126 a84cbb2a 2004-04-19 devnull /* move on to the program */
127 a84cbb2a 2004-04-19 devnull if(b.p == nil || b.p > prog){
128 a84cbb2a 2004-04-19 devnull fprint(2, "bad header\n");
129 a84cbb2a 2004-04-19 devnull goto bad;
130 a84cbb2a 2004-04-19 devnull }
131 a84cbb2a 2004-04-19 devnull b.p = prog;
132 a84cbb2a 2004-04-19 devnull
133 a84cbb2a 2004-04-19 devnull reset.addr = 0;
134 a84cbb2a 2004-04-19 devnull reset.file = 1;
135 a84cbb2a 2004-04-19 devnull reset.line = 1;
136 a84cbb2a 2004-04-19 devnull reset.column = 0;
137 a84cbb2a 2004-04-19 devnull reset.flags = isstmt ? Isstmt : 0;
138 a84cbb2a 2004-04-19 devnull reset.isa = 0;
139 a84cbb2a 2004-04-19 devnull
140 a84cbb2a 2004-04-19 devnull cur = reset;
141 a84cbb2a 2004-04-19 devnull emit = reset;
142 a84cbb2a 2004-04-19 devnull nf = 0;
143 a84cbb2a 2004-04-19 devnull start = 0;
144 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "program @ %lud ... %.*H opbase = %d\n", b.p - d->line.data, b.ep-b.p, b.p, opcodebase);
145 a84cbb2a 2004-04-19 devnull first = 1;
146 a84cbb2a 2004-04-19 devnull while(b.p != nil){
147 a84cbb2a 2004-04-19 devnull op = dwarfget1(&b);
148 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "\tline %lud, addr 0x%lux, op %d %.10H", cur.line, cur.addr, op, b.p);
149 a84cbb2a 2004-04-19 devnull if(op >= opcodebase){
150 a84cbb2a 2004-04-19 devnull a = (op - opcodebase) / linerange;
151 a84cbb2a 2004-04-19 devnull l = (op - opcodebase) % linerange + linebase;
152 a84cbb2a 2004-04-19 devnull cur.line += l;
153 a84cbb2a 2004-04-19 devnull cur.addr += a * quantum;
154 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, " +%d,%d\n", a, l);
155 a84cbb2a 2004-04-19 devnull emit:
156 a84cbb2a 2004-04-19 devnull if(first){
157 a84cbb2a 2004-04-19 devnull if(cur.addr > pc){
158 a84cbb2a 2004-04-19 devnull werrstr("found wrong line mapping 0x%lux for pc 0x%lux", cur.addr, pc);
159 a84cbb2a 2004-04-19 devnull goto out;
160 a84cbb2a 2004-04-19 devnull }
161 a84cbb2a 2004-04-19 devnull first = 0;
162 a84cbb2a 2004-04-19 devnull start = cur.addr;
163 a84cbb2a 2004-04-19 devnull }
164 a84cbb2a 2004-04-19 devnull if(cur.addr > pc)
165 a84cbb2a 2004-04-19 devnull break;
166 a84cbb2a 2004-04-19 devnull if(b.p == nil){
167 a84cbb2a 2004-04-19 devnull werrstr("buffer underflow in line mapping");
168 a84cbb2a 2004-04-19 devnull goto out;
169 a84cbb2a 2004-04-19 devnull }
170 a84cbb2a 2004-04-19 devnull emit = cur;
171 a84cbb2a 2004-04-19 devnull if(emit.flags & EndSequence){
172 a84cbb2a 2004-04-19 devnull werrstr("found wrong line mapping 0x%lux-0x%lux for pc 0x%lux", start, cur.addr, pc);
173 a84cbb2a 2004-04-19 devnull goto out;
174 a84cbb2a 2004-04-19 devnull }
175 a84cbb2a 2004-04-19 devnull cur.flags &= ~(BasicDwarfBlock|PrologueEnd|EpilogueBegin);
176 a84cbb2a 2004-04-19 devnull }else{
177 a84cbb2a 2004-04-19 devnull switch(op){
178 a84cbb2a 2004-04-19 devnull case 0: /* extended op code */
179 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, " ext");
180 a84cbb2a 2004-04-19 devnull len = dwarfget128(&b);
181 a84cbb2a 2004-04-19 devnull end = b.p+len;
182 a84cbb2a 2004-04-19 devnull if(b.p == nil || end > b.ep || end < b.p || len < 1)
183 a84cbb2a 2004-04-19 devnull goto bad;
184 a84cbb2a 2004-04-19 devnull switch(dwarfget1(&b)){
185 a84cbb2a 2004-04-19 devnull case 1: /* end sequence */
186 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, " end\n");
187 a84cbb2a 2004-04-19 devnull cur.flags |= EndSequence;
188 a84cbb2a 2004-04-19 devnull goto emit;
189 a84cbb2a 2004-04-19 devnull case 2: /* set address */
190 a84cbb2a 2004-04-19 devnull cur.addr = dwarfgetaddr(&b);
191 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, " set pc 0x%lux\n", cur.addr);
192 a84cbb2a 2004-04-19 devnull break;
193 a84cbb2a 2004-04-19 devnull case 3: /* define file */
194 a84cbb2a 2004-04-19 devnull newf = realloc(f, (nf+1)*sizeof(f[0]));
195 a84cbb2a 2004-04-19 devnull if(newf == nil)
196 a84cbb2a 2004-04-19 devnull goto out;
197 0dc3aa4b 2013-01-31 rsc f = newf;
198 a84cbb2a 2004-04-19 devnull f[nf++] = b.p;
199 a84cbb2a 2004-04-19 devnull s = dwarfgetstring(&b);
200 a84cbb2a 2004-04-19 devnull dwarfget128(&b);
201 a84cbb2a 2004-04-19 devnull dwarfget128(&b);
202 a84cbb2a 2004-04-19 devnull dwarfget128(&b);
203 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, " def file %s\n", s);
204 a84cbb2a 2004-04-19 devnull break;
205 a84cbb2a 2004-04-19 devnull }
206 a84cbb2a 2004-04-19 devnull if(b.p == nil || b.p > end)
207 a84cbb2a 2004-04-19 devnull goto bad;
208 a84cbb2a 2004-04-19 devnull b.p = end;
209 a84cbb2a 2004-04-19 devnull break;
210 a84cbb2a 2004-04-19 devnull case 1: /* emit */
211 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, " emit\n");
212 a84cbb2a 2004-04-19 devnull goto emit;
213 a84cbb2a 2004-04-19 devnull case 2: /* advance pc */
214 a84cbb2a 2004-04-19 devnull a = dwarfget128(&b);
215 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, " advance pc + %lud\n", a*quantum);
216 a84cbb2a 2004-04-19 devnull cur.addr += a * quantum;
217 a84cbb2a 2004-04-19 devnull break;
218 a84cbb2a 2004-04-19 devnull case 3: /* advance line */
219 a84cbb2a 2004-04-19 devnull l = dwarfget128s(&b);
220 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, " advance line + %ld\n", l);
221 a84cbb2a 2004-04-19 devnull cur.line += l;
222 a84cbb2a 2004-04-19 devnull break;
223 a84cbb2a 2004-04-19 devnull case 4: /* set file */
224 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, " set file\n");
225 a84cbb2a 2004-04-19 devnull cur.file = dwarfget128s(&b);
226 a84cbb2a 2004-04-19 devnull break;
227 a84cbb2a 2004-04-19 devnull case 5: /* set column */
228 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, " set column\n");
229 a84cbb2a 2004-04-19 devnull cur.column = dwarfget128(&b);
230 a84cbb2a 2004-04-19 devnull break;
231 a84cbb2a 2004-04-19 devnull case 6: /* negate stmt */
232 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, " negate stmt\n");
233 a84cbb2a 2004-04-19 devnull cur.flags ^= Isstmt;
234 a84cbb2a 2004-04-19 devnull break;
235 a84cbb2a 2004-04-19 devnull case 7: /* set basic block */
236 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, " set basic block\n");
237 a84cbb2a 2004-04-19 devnull cur.flags |= BasicDwarfBlock;
238 a84cbb2a 2004-04-19 devnull break;
239 a84cbb2a 2004-04-19 devnull case 8: /* const add pc */
240 a84cbb2a 2004-04-19 devnull a = (255 - opcodebase) / linerange * quantum;
241 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, " const add pc + %d\n", a);
242 a84cbb2a 2004-04-19 devnull cur.addr += a;
243 a84cbb2a 2004-04-19 devnull break;
244 a84cbb2a 2004-04-19 devnull case 9: /* fixed advance pc */
245 a84cbb2a 2004-04-19 devnull a = dwarfget2(&b);
246 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, " fixed advance pc + %d\n", a);
247 a84cbb2a 2004-04-19 devnull cur.addr += a;
248 a84cbb2a 2004-04-19 devnull break;
249 a84cbb2a 2004-04-19 devnull case 10: /* set prologue end */
250 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, " set prologue end\n");
251 a84cbb2a 2004-04-19 devnull cur.flags |= PrologueEnd;
252 a84cbb2a 2004-04-19 devnull break;
253 a84cbb2a 2004-04-19 devnull case 11: /* set epilogue begin */
254 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, " set epilogue begin\n");
255 a84cbb2a 2004-04-19 devnull cur.flags |= EpilogueBegin;
256 a84cbb2a 2004-04-19 devnull break;
257 a84cbb2a 2004-04-19 devnull case 12: /* set isa */
258 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, " set isa\n");
259 a84cbb2a 2004-04-19 devnull cur.isa = dwarfget128(&b);
260 a84cbb2a 2004-04-19 devnull break;
261 a84cbb2a 2004-04-19 devnull default: /* something new - skip it */
262 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, " unknown %d\n", opcount[op]);
263 a84cbb2a 2004-04-19 devnull for(i=0; i<opcount[op]; i++)
264 a84cbb2a 2004-04-19 devnull dwarfget128(&b);
265 a84cbb2a 2004-04-19 devnull break;
266 a84cbb2a 2004-04-19 devnull }
267 a84cbb2a 2004-04-19 devnull }
268 a84cbb2a 2004-04-19 devnull }
269 a84cbb2a 2004-04-19 devnull if(b.p == nil)
270 a84cbb2a 2004-04-19 devnull goto bad;
271 a84cbb2a 2004-04-19 devnull
272 a84cbb2a 2004-04-19 devnull /* finally! the data we seek is in "emit" */
273 a84cbb2a 2004-04-19 devnull
274 a84cbb2a 2004-04-19 devnull if(emit.file == 0){
275 a84cbb2a 2004-04-19 devnull werrstr("invalid file index in mapping data");
276 a84cbb2a 2004-04-19 devnull goto out;
277 a84cbb2a 2004-04-19 devnull }
278 a84cbb2a 2004-04-19 devnull if(line)
279 a84cbb2a 2004-04-19 devnull *line = emit.line;
280 a84cbb2a 2004-04-19 devnull
281 a84cbb2a 2004-04-19 devnull /* skip over first emit.file-2 guys */
282 929ba9b9 2004-04-20 devnull b.p = (uchar*)files;
283 a84cbb2a 2004-04-19 devnull for(i=emit.file-1; i > 0 && b.p!=nil && *b.p!=0; i--){
284 a84cbb2a 2004-04-19 devnull dwarfgetstring(&b);
285 a84cbb2a 2004-04-19 devnull dwarfget128(&b);
286 a84cbb2a 2004-04-19 devnull dwarfget128(&b);
287 a84cbb2a 2004-04-19 devnull dwarfget128(&b);
288 a84cbb2a 2004-04-19 devnull }
289 a84cbb2a 2004-04-19 devnull if(b.p == nil){
290 a84cbb2a 2004-04-19 devnull werrstr("problem parsing file data second time (cannot happen)");
291 a84cbb2a 2004-04-19 devnull goto bad;
292 a84cbb2a 2004-04-19 devnull }
293 a84cbb2a 2004-04-19 devnull if(*b.p == 0){
294 a84cbb2a 2004-04-19 devnull if(i >= nf){
295 a84cbb2a 2004-04-19 devnull werrstr("bad file index in mapping data");
296 a84cbb2a 2004-04-19 devnull goto bad;
297 a84cbb2a 2004-04-19 devnull }
298 a84cbb2a 2004-04-19 devnull b.p = f[i];
299 a84cbb2a 2004-04-19 devnull }
300 a84cbb2a 2004-04-19 devnull s = dwarfgetstring(&b);
301 a84cbb2a 2004-04-19 devnull if(file)
302 a84cbb2a 2004-04-19 devnull *file = s;
303 a84cbb2a 2004-04-19 devnull i = dwarfget128(&b); /* directory */
304 a84cbb2a 2004-04-19 devnull x = dwarfget128(&b);
305 a84cbb2a 2004-04-19 devnull if(mtime)
306 a84cbb2a 2004-04-19 devnull *mtime = x;
307 a84cbb2a 2004-04-19 devnull x = dwarfget128(&b);
308 a84cbb2a 2004-04-19 devnull if(length)
309 a84cbb2a 2004-04-19 devnull *length = x;
310 a84cbb2a 2004-04-19 devnull
311 a84cbb2a 2004-04-19 devnull /* fetch dir name */
312 a84cbb2a 2004-04-19 devnull if(cdir)
313 a84cbb2a 2004-04-19 devnull *cdir = sym.attrs.compdir;
314 a84cbb2a 2004-04-19 devnull
315 a84cbb2a 2004-04-19 devnull if(dir){
316 a84cbb2a 2004-04-19 devnull if(i == 0)
317 a84cbb2a 2004-04-19 devnull *dir = nil;
318 a84cbb2a 2004-04-19 devnull else{
319 929ba9b9 2004-04-20 devnull b.p = (uchar*)dirs;
320 a84cbb2a 2004-04-19 devnull for(i--; i>0 && b.p!=nil && *b.p!=0; i--)
321 a84cbb2a 2004-04-19 devnull dwarfgetstring(&b);
322 a84cbb2a 2004-04-19 devnull if(b.p==nil || *b.p==0){
323 a84cbb2a 2004-04-19 devnull werrstr("bad directory reference in line mapping");
324 a84cbb2a 2004-04-19 devnull goto out; /* can only happen with bad dir index */
325 a84cbb2a 2004-04-19 devnull }
326 a84cbb2a 2004-04-19 devnull *dir = dwarfgetstring(&b);
327 a84cbb2a 2004-04-19 devnull }
328 a84cbb2a 2004-04-19 devnull }
329 a84cbb2a 2004-04-19 devnull
330 a84cbb2a 2004-04-19 devnull /* free at last, free at last */
331 a84cbb2a 2004-04-19 devnull free(f);
332 a84cbb2a 2004-04-19 devnull return 0;
333 a84cbb2a 2004-04-19 devnull
334 a84cbb2a 2004-04-19 devnull bad:
335 a84cbb2a 2004-04-19 devnull werrstr("corrupted line mapping for 0x%lux", pc);
336 a84cbb2a 2004-04-19 devnull out:
337 a84cbb2a 2004-04-19 devnull free(f);
338 a84cbb2a 2004-04-19 devnull return -1;
339 a84cbb2a 2004-04-19 devnull }