ReactOS 0.4.16-dev-87-g3dfbe52
dwarfpc.c
Go to the documentation of this file.
1/*
2 * Dwarf pc to source line conversion.
3 *
4 * Maybe should do the reverse here, but what should the interface look like?
5 * One possibility is to use the Plan 9 line2addr interface:
6 *
7 * long line2addr(ulong line, ulong basepc)
8 *
9 * which returns the smallest pc > basepc with line number line (ignoring file name).
10 *
11 * The encoding may be small, but it sure isn't simple!
12 */
13
14#include <precomp.h>
15
16#define NDEBUG
17#include <debug.h>
18#define trace 0
19
20enum
21{
22 Isstmt = 1<<0,
26 EpilogueBegin = 1<<4
27};
28
29typedef struct State State;
30struct State
31{
32 ulong addr;
33 ulong file;
34 ulong line;
37 ulong isa;
38};
39
40int
41dwarfpctoline(Dwarf *d, DwarfSym *proc, ulong pc, char **file, char **function, ulong *line)
42{
43 char *cdir;
44 uchar *prog, *opcount, *end, *dirs;
45 ulong off, unit, len, vers, x, start, lastline;
46 int i, first, firstline, op, a, l, quantum, isstmt, linebase, linerange, opcodebase, nf;
47 char *files, *s;
48 DwarfBuf b;
49 DwarfSym sym;
50 State emit, cur, reset;
51 char **f, **newf;
52
53 f = nil;
54 memset(proc, 0, sizeof(*proc));
55
56 int runit = dwarfaddrtounit(d, pc, &unit);
57 if (runit < 0)
58 return -1;
59 int rtag = dwarflookuptag(d, unit, TagCompileUnit, &sym);
60 if (rtag < 0)
61 return -1;
62
63 if(!sym.attrs.have.stmtlist){
64 werrstr("no line mapping information for 0x%x", pc);
65 return -1;
66 }
67 off = sym.attrs.stmtlist;
68 if(off >= d->line.len){
69 werrstr("bad stmtlist");
70 goto bad;
71 }
72
73 if(trace) werrstr("unit 0x%x stmtlist 0x%x", unit, sym.attrs.stmtlist);
74
75 memset(&b, 0, sizeof b);
76 b.d = d;
77 b.p = d->line.data + off;
78 b.ep = b.p + d->line.len;
79 b.addrsize = sym.b.addrsize; /* should i get this from somewhere else? */
80
81 len = dwarfget4(&b);
82 if(b.p==nil || b.p+len > b.ep || b.p+len < b.p){
83 werrstr("bad len");
84 goto bad;
85 }
86
87 b.ep = b.p+len;
88 vers = dwarfget2(&b);
89 if(vers != 2){
90 werrstr("bad dwarf version 0x%x", vers);
91 return -1;
92 }
93
94 len = dwarfget4(&b);
95 if(b.p==nil || b.p+len > b.ep || b.p+len < b.p){
96 werrstr("another bad len");
97 goto bad;
98 }
99 prog = b.p+len;
100
101 quantum = dwarfget1(&b);
102 isstmt = dwarfget1(&b);
103 linebase = (schar)dwarfget1(&b);
104 linerange = (schar)dwarfget1(&b);
105 opcodebase = dwarfget1(&b);
106
107 opcount = b.p-1;
108 dwarfgetnref(&b, opcodebase-1);
109 if(b.p == nil){
110 werrstr("bad opcode chart");
111 goto bad;
112 }
113
114 /* just skip the files and dirs for now; we'll come back */
115 dirs = b.p;
116 while (b.p && *b.p)
118 dwarfget1(&b);
119
120 files = (char*)b.p;
121 while(b.p!=nil && *b.p!=0){
123 dwarfget128(&b);
124 dwarfget128(&b);
125 dwarfget128(&b);
126 }
127 dwarfget1(&b);
128
129 /* move on to the program */
130 if(b.p == nil || b.p > prog){
131 werrstr("bad header");
132 goto bad;
133 }
134 b.p = prog;
135
136 reset.addr = 0;
137 reset.file = 1;
138 reset.line = 1;
139 reset.column = 0;
140 reset.flags = isstmt ? Isstmt : 0;
141 reset.isa = 0;
142
143 cur = reset;
144 emit = reset;
145 nf = 0;
146 start = 0;
147 if(trace) werrstr("program @ %lu ... %.*H opbase = %d", b.p - d->line.data, b.ep-b.p, b.p, opcodebase);
148 first = 1;
149 while(b.p != nil){
150 firstline = 0;
151 op = dwarfget1(&b);
152 if(trace) werrstr("\tline %lu, addr 0x%x, op %d %.10H", cur.line, cur.addr, op, b.p);
153 if(op >= opcodebase){
154 a = (op - opcodebase) / linerange;
155 l = (op - opcodebase) % linerange + linebase;
156 cur.line += l;
157 cur.addr += a * quantum;
158 if(trace) werrstr(" +%d,%d", a, l);
159 emit:
160 if(first){
161 if(cur.addr > pc){
162 werrstr("found wrong line mapping 0x%x for pc 0x%x", cur.addr, pc);
163 /* This is an overzealous check. gcc can produce discontiguous ranges
164 and reorder statements, so it's possible for a future line to start
165 ahead of pc and still find a matching one. */
166 /*goto out;*/
167 firstline = 1;
168 }
169 first = 0;
170 start = cur.addr;
171 }
172 if(cur.addr > pc && !firstline)
173 break;
174 if(b.p == nil){
175 werrstr("buffer underflow in line mapping");
176 goto out;
177 }
178 emit = cur;
179 if(emit.flags & EndSequence){
180 werrstr("found wrong line mapping 0x%x-0x%x for pc 0x%x", start, cur.addr, pc);
181 goto out;
182 }
184 }else{
185 switch(op){
186 case 0: /* extended op code */
187 if(trace) werrstr(" ext");
188 len = dwarfget128(&b);
189 end = b.p+len;
190 if(b.p == nil || end > b.ep || end < b.p || len < 1)
191 goto bad;
192 switch(dwarfget1(&b)){
193 case 1: /* end sequence */
194 if(trace) werrstr(" end");
195 cur.flags |= EndSequence;
196 goto emit;
197 case 2: /* set address */
198 cur.addr = dwarfgetaddr(&b);
199 if(trace) werrstr(" set pc 0x%x", cur.addr);
200 break;
201 case 3: /* define file */
202 newf = malloc(nf+1*sizeof(f[0]));
203 if (newf)
204 RtlMoveMemory(newf, f, nf*sizeof(f[0]));
205 if(newf == nil)
206 goto out;
207 free(f);
208 f = newf;
209 f[nf++] = s = dwarfgetstring(&b);
210 DPRINT1("str %s", s);
211 dwarfget128(&b);
212 dwarfget128(&b);
213 dwarfget128(&b);
214 if(trace) werrstr(" def file %s", s);
215 break;
216 }
217 if(b.p == nil || b.p > end)
218 goto bad;
219 b.p = end;
220 break;
221 case 1: /* emit */
222 if(trace) werrstr(" emit");
223 goto emit;
224 case 2: /* advance pc */
225 a = dwarfget128(&b);
226 if(trace) werrstr(" advance pc + %lu", a*quantum);
227 cur.addr += a * quantum;
228 break;
229 case 3: /* advance line */
230 l = dwarfget128s(&b);
231 if(trace) werrstr(" advance line + %ld", l);
232 cur.line += l;
233 break;
234 case 4: /* set file */
235 if(trace) werrstr(" set file");
236 cur.file = dwarfget128s(&b);
237 break;
238 case 5: /* set column */
239 if(trace) werrstr(" set column");
240 cur.column = dwarfget128(&b);
241 break;
242 case 6: /* negate stmt */
243 if(trace) werrstr(" negate stmt");
244 cur.flags ^= Isstmt;
245 break;
246 case 7: /* set basic block */
247 if(trace) werrstr(" set basic block");
248 cur.flags |= BasicDwarfBlock;
249 break;
250 case 8: /* const add pc */
251 a = (255 - opcodebase) / linerange * quantum;
252 if(trace) werrstr(" const add pc + %d", a);
253 cur.addr += a;
254 break;
255 case 9: /* fixed advance pc */
256 a = dwarfget2(&b);
257 if(trace) werrstr(" fixed advance pc + %d", a);
258 cur.addr += a;
259 break;
260 case 10: /* set prologue end */
261 if(trace) werrstr(" set prologue end");
262 cur.flags |= PrologueEnd;
263 break;
264 case 11: /* set epilogue begin */
265 if(trace) werrstr(" set epilogue begin");
266 cur.flags |= EpilogueBegin;
267 break;
268 case 12: /* set isa */
269 if(trace) werrstr(" set isa");
270 cur.isa = dwarfget128(&b);
271 break;
272 default: /* something new - skip it */
273 if(trace) werrstr(" unknown %d", opcount[op]);
274 for(i=0; i<opcount[op]; i++)
275 dwarfget128(&b);
276 break;
277 }
278 }
279 }
280 if(b.p == nil)
281 goto bad;
282
283 /* finally! the data we seek is in "emit" */
284
285 if(emit.file == 0){
286 werrstr("invalid file index in mapping data");
287 goto out;
288 }
289 if(line)
290 *line = emit.line;
291
292 /* skip over first emit.file-2 guys */
293 b.p = (uchar*)files;
294 for(i=emit.file-1; i > 0 && b.p!=nil && *b.p!=0; i--){
296 dwarfget128(&b);
297 dwarfget128(&b);
298 dwarfget128(&b);
299 }
300 if(b.p == nil){
301 werrstr("problem parsing file data second time (cannot happen)");
302 goto bad;
303 }
304 if(*b.p == 0){
305 if(i >= nf){
306 werrstr("bad file index in mapping data");
307 goto bad;
308 }
309 b.p = (uchar*)f[i];
310 }
311 s = dwarfgetstring(&b);
312 *file = s;
313 i = dwarfget128(&b); /* directory */
314 x = dwarfget128(&b);
315 x = dwarfget128(&b);
316
317 /* fetch dir name */
318 cdir = sym.attrs.have.compdir ? sym.attrs.compdir : 0;
319
320 char *dwarfdir;
321 dwarfdir = nil;
322 b.p = dirs;
323 for (x = 1; b.p && *b.p; x++) {
324 dwarfdir = dwarfgetstring(&b);
325 if (x == i) break;
326 }
327
328 if (!cdir && dwarfdir)
329 cdir = dwarfdir;
330
331 char *filefull = malloc(strlen(cdir) + strlen(*file) + 2);
332 strcpy(filefull, cdir);
333 strcat(filefull, "/");
334 strcat(filefull, *file);
335 *file = filefull;
336
337 *function = nil;
338 lastline = 0;
339
340 runit = dwarfaddrtounit(d, pc, &unit);
341 if (runit == 0) {
342 DwarfSym compunit = { };
343 int renum = dwarfenumunit(d, unit, &compunit);
344 if (renum < 0)
345 return -1;
346 renum = dwarfnextsymat(d, &compunit, proc);
347 while (renum == 0) {
348 if (proc->attrs.tag == TagSubprogram &&
349 proc->attrs.have.name)
350 {
351 if (proc->attrs.lowpc <= pc && proc->attrs.highpc > pc) {
352 *function = malloc(strlen(proc->attrs.name)+1);
353 strcpy(*function, proc->attrs.name);
354 goto done;
355 }
356 }
357 renum = dwarfnextsym(d, proc);
358 }
359 }
360
361 // Next search by declaration
362 runit = dwarfaddrtounit(d, pc, &unit);
363 if (runit == 0) {
364 DwarfSym compunit = { };
365 int renum = dwarfenumunit(d, unit, &compunit);
366 if (renum < 0)
367 return -1;
368 renum = dwarfnextsymat(d, &compunit, proc);
369 while (renum == 0) {
370 if (proc->attrs.tag == TagSubprogram &&
371 proc->attrs.have.name &&
372 proc->attrs.declfile == emit.file)
373 {
374 if (proc->attrs.declline <= *line &&
375 proc->attrs.declline > lastline) {
376 free(*function);
377 *function = malloc(strlen(proc->attrs.name)+1);
378 strcpy(*function, proc->attrs.name);
379 goto done;
380 }
381 lastline = proc->attrs.declline;
382 }
383 renum = dwarfnextsym(d, proc);
384 }
385 }
386
387 /* free at last, free at last */
388done:
389 free(f);
390 return 0;
391bad:
392 werrstr("corrupted line mapping for 0x%x", pc);
393out:
394 free(f);
395 return -1;
396}
397
399{
400 int i;
401 free(LineInfo->FileName);
402 LineInfo->FileName = NULL;
403 free(LineInfo->FunctionName);
404 LineInfo->FunctionName = NULL;
405 for (i = 0; i < sizeof(LineInfo->Parameters)/sizeof(LineInfo->Parameters[0]); i++)
406 free(LineInfo->Parameters[i].ValueName);
407}
unsigned char uchar
Definition: Unfrag.h:59
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define DPRINT1
Definition: precomp.h:8
r l[0]
Definition: byte_order.h:168
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
UINT op
Definition: effect.c:236
unsigned long ulong
Definition: linux.h:275
FxCollectionEntry * cur
GLuint start
Definition: gl.h:1545
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLdouble s
Definition: gl.h:2039
GLuint GLuint end
Definition: gl.h:1545
GLboolean reset
Definition: glext.h:5666
GLfloat f
Definition: glext.h:7540
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
const GLint * first
Definition: glext.h:5794
GLenum GLsizei len
Definition: glext.h:6722
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
char * prog
Definition: isohybrid.c:47
#define d
Definition: ke_i.h:81
#define f
Definition: ke_i.h:83
#define a
Definition: ke_i.h:78
#define b
Definition: ke_i.h:79
static HANDLE proc()
Definition: pdb.c:34
png_const_structrp png_const_inforp int * unit
Definition: png.h:2159
static FILE * out
Definition: regtests2xml.c:44
#define trace
Definition: dwarfpc.c:25
int dwarfpctoline(Dwarf *d, ulong pc, char **cdir, char **dir, char **file, char **function, ulong *line, ulong *mtime, ulong *length)
Definition: dwarfpc.c:48
@ BasicDwarfBlock
Definition: dwarfpc.c:30
@ EpilogueBegin
Definition: dwarfpc.c:33
@ Isstmt
Definition: dwarfpc.c:29
@ PrologueEnd
Definition: dwarfpc.c:32
@ EndSequence
Definition: dwarfpc.c:31
VOID RosSymFreeInfo(PROSSYM_LINEINFO LineInfo)
Definition: dwarfpc.c:398
signed char schar
Definition: compat.h:5
#define werrstr(str,...)
Definition: compat.h:34
#define nil
Definition: compat.h:23
#define memset(x, y, z)
Definition: compat.h:39
ulong dwarfget128(DwarfBuf *)
Definition: dwarfget.c:152
ulong dwarfget2(DwarfBuf *)
Definition: dwarfget.c:81
int dwarfenumunit(Dwarf *, ulong, DwarfSym *)
Definition: dwarfinfo.c:201
int dwarflookuptag(Dwarf *, ulong, ulong, DwarfSym *)
Definition: dwarfinfo.c:151
char * dwarfgetstring(DwarfBuf *)
Definition: dwarfget.c:54
ulong dwarfget1(DwarfBuf *)
Definition: dwarfget.c:17
long dwarfget128s(DwarfBuf *)
Definition: dwarfget.c:197
int dwarfnextsym(Dwarf *, DwarfSym *)
Definition: dwarfinfo.c:250
ulong dwarfgetaddr(DwarfBuf *)
Definition: dwarfget.c:123
@ TagCompileUnit
Definition: dwarf.h:24
@ TagSubprogram
Definition: dwarf.h:52
uchar * dwarfgetnref(DwarfBuf *, ulong)
Definition: dwarfget.c:40
int dwarfaddrtounit(Dwarf *, ulong, ulong *)
Definition: dwarfaranges.c:16
int dwarfnextsymat(Dwarf *, DwarfSym *, int)
Definition: dwarfinfo.c:292
ulong dwarfget4(DwarfBuf *)
Definition: dwarfget.c:95
uchar stmtlist
Definition: dwarf.h:282
struct DwarfAttrs::@4959 have
uchar compdir
Definition: dwarf.h:239
uint addrsize
Definition: dwarf.h:212
DwarfAttrs attrs
Definition: dwarf.h:375
DwarfBuf b
Definition: dwarf.h:378
Definition: dwarf.h:437
ulong line
Definition: dwarfpc.c:41
ulong file
Definition: dwarfpc.c:40
ulong column
Definition: dwarfpc.c:42
ulong addr
Definition: dwarfpc.c:39
ulong flags
Definition: dwarfpc.c:43
ulong isa
Definition: dwarfpc.c:44
char * FunctionName
Definition: rossym.h:87
char * FileName
Definition: rossym.h:86
ROSSYM_PARAMETER Parameters[16]
Definition: rossym.h:90
char * ValueName
Definition: rossym.h:67
Definition: fci.c:127
Definition: parser.c:49
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264