ReactOS 0.4.16-dev-336-gb667d82
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 <ntddk.h>
15#include <reactos/rossym.h>
16#include "rossympriv.h"
17#include <ntimage.h>
18
19#define NDEBUG
20#include <debug.h>
21
22#include "dwarf.h"
23#include "pe.h"
24
25#define trace 0
26
27enum
28{
29 Isstmt = 1<<0,
33 EpilogueBegin = 1<<4
34};
35
36typedef struct State State;
37struct State
38{
45};
46
47int
48dwarfpctoline(Dwarf *d, ulong pc, char **cdir, char **dir, char **file, char **function, ulong *line, ulong *mtime, ulong *length)
49{
50 uchar *prog, *opcount, *end, *dirs;
51 ulong off, unit, len, vers, x, start, lastline;
52 int i, first, firstline, op, a, l, quantum, isstmt, linebase, linerange, opcodebase, nf;
53 char *files, *s;
54 DwarfBuf b;
55 DwarfSym sym;
56 State emit, cur, reset;
57 uchar **f, **newf;
58
59 f = nil;
60
61 if(dwarfaddrtounit(d, pc, &unit) < 0
62 || dwarflookuptag(d, unit, TagCompileUnit, &sym) < 0)
63 return -1;
64
65 if(!sym.attrs.have.stmtlist){
66 werrstr("no line mapping information for 0x%x", pc);
67 return -1;
68 }
69 off = sym.attrs.stmtlist;
70 if(off >= d->line.len){
71 werrstr("bad stmtlist\n");
72 goto bad;
73 }
74
75 if(trace) werrstr("unit 0x%x stmtlist 0x%x", unit, sym.attrs.stmtlist);
76
77 memset(&b, 0, sizeof b);
78 b.d = d;
79 b.p = d->line.data + off;
80 b.ep = b.p + d->line.len;
81 b.addrsize = sym.b.addrsize; /* should i get this from somewhere else? */
82
83 len = dwarfget4(&b);
84 if(b.p==nil || b.p+len > b.ep || b.p+len < b.p){
85 werrstr("bad len\n");
86 goto bad;
87 }
88
89 b.ep = b.p+len;
90 vers = dwarfget2(&b);
91 if(vers != 2){
92 werrstr("bad dwarf version 0x%x", vers);
93 return -1;
94 }
95
96 len = dwarfget4(&b);
97 if(b.p==nil || b.p+len > b.ep || b.p+len < b.p){
98 werrstr("another bad len\n");
99 goto bad;
100 }
101 prog = b.p+len;
102
103 quantum = dwarfget1(&b);
104 isstmt = dwarfget1(&b);
105 linebase = (schar)dwarfget1(&b);
106 linerange = (schar)dwarfget1(&b);
107 opcodebase = dwarfget1(&b);
108
109 opcount = b.p-1;
110 dwarfgetnref(&b, opcodebase-1);
111 if(b.p == nil){
112 werrstr("bad opcode chart\n");
113 goto bad;
114 }
115
116 /* just skip the files and dirs for now; we'll come back */
117 dirs = b.p;
118 while (b.p && *b.p)
120 dwarfget1(&b);
121
122 files = (char*)b.p;
123 while(b.p!=nil && *b.p!=0){
125 dwarfget128(&b);
126 dwarfget128(&b);
127 dwarfget128(&b);
128 }
129 dwarfget1(&b);
130
131 /* move on to the program */
132 if(b.p == nil || b.p > prog){
133 werrstr("bad header\n");
134 goto bad;
135 }
136 b.p = prog;
137
138 reset.addr = 0;
139 reset.file = 1;
140 reset.line = 1;
141 reset.column = 0;
142 reset.flags = isstmt ? Isstmt : 0;
143 reset.isa = 0;
144
145 cur = reset;
146 emit = reset;
147 nf = 0;
148 start = 0;
149 if(trace) werrstr("program @ %lu ... %.*H opbase = %d\n", b.p - d->line.data, b.ep-b.p, b.p, opcodebase);
150 first = 1;
151 while(b.p != nil){
152 firstline = 0;
153 op = dwarfget1(&b);
154 if(trace) werrstr("\tline %lu, addr 0x%x, op %d %.10H", cur.line, cur.addr, op, b.p);
155 if(op >= opcodebase){
156 a = (op - opcodebase) / linerange;
157 l = (op - opcodebase) % linerange + linebase;
158 cur.line += l;
159 cur.addr += a * quantum;
160 if(trace) werrstr(" +%d,%d\n", a, l);
161 emit:
162 if(first){
163 if(cur.addr > pc){
164 werrstr("found wrong line mapping 0x%x for pc 0x%x", cur.addr, pc);
165 /* This is an overzealous check. gcc can produce discontiguous ranges
166 and reorder statements, so it's possible for a future line to start
167 ahead of pc and still find a matching one. */
168 /*goto out;*/
169 firstline = 1;
170 }
171 first = 0;
172 start = cur.addr;
173 }
174 if(cur.addr > pc && !firstline)
175 break;
176 if(b.p == nil){
177 werrstr("buffer underflow in line mapping");
178 goto out;
179 }
180 emit = cur;
181 if(emit.flags & EndSequence){
182 werrstr("found wrong line mapping 0x%x-0x%x for pc 0x%x", start, cur.addr, pc);
183 goto out;
184 }
186 }else{
187 switch(op){
188 case 0: /* extended op code */
189 if(trace) werrstr(" ext");
190 len = dwarfget128(&b);
191 end = b.p+len;
192 if(b.p == nil || end > b.ep || end < b.p || len < 1)
193 goto bad;
194 switch(dwarfget1(&b)){
195 case 1: /* end sequence */
196 if(trace) werrstr(" end\n");
197 cur.flags |= EndSequence;
198 goto emit;
199 case 2: /* set address */
200 cur.addr = dwarfgetaddr(&b);
201 if(trace) werrstr(" set pc 0x%x\n", cur.addr);
202 break;
203 case 3: /* define file */
204 newf = malloc(nf+1*sizeof(f[0]));
205 if (newf)
206 RtlMoveMemory(newf, f, nf*sizeof(f[0]));
207 if(newf == nil)
208 goto out;
209 f[nf++] = b.p;
210 s = dwarfgetstring(&b);
211 dwarfget128(&b);
212 dwarfget128(&b);
213 dwarfget128(&b);
214 if(trace) werrstr(" def file %s\n", 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\n");
223 goto emit;
224 case 2: /* advance pc */
225 a = dwarfget128(&b);
226 if(trace) werrstr(" advance pc + %lu\n", 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\n", l);
232 cur.line += l;
233 break;
234 case 4: /* set file */
235 if(trace) werrstr(" set file\n");
236 cur.file = dwarfget128s(&b);
237 break;
238 case 5: /* set column */
239 if(trace) werrstr(" set column\n");
240 cur.column = dwarfget128(&b);
241 break;
242 case 6: /* negate stmt */
243 if(trace) werrstr(" negate stmt\n");
244 cur.flags ^= Isstmt;
245 break;
246 case 7: /* set basic block */
247 if(trace) werrstr(" set basic block\n");
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\n", 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\n", a);
258 cur.addr += a;
259 break;
260 case 10: /* set prologue end */
261 if(trace) werrstr(" set prologue end\n");
262 cur.flags |= PrologueEnd;
263 break;
264 case 11: /* set epilogue begin */
265 if(trace) werrstr(" set epilogue begin\n");
266 cur.flags |= EpilogueBegin;
267 break;
268 case 12: /* set isa */
269 if(trace) werrstr(" set isa\n");
270 cur.isa = dwarfget128(&b);
271 break;
272 default: /* something new - skip it */
273 if(trace) werrstr(" unknown %d\n", 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 = f[i];
310 }
311 s = dwarfgetstring(&b);
312 if(file)
313 *file = s;
314 i = dwarfget128(&b); /* directory */
315 x = dwarfget128(&b);
316 if(mtime)
317 *mtime = x;
318 x = dwarfget128(&b);
319 if(length)
320 *length = x;
321
322 /* fetch dir name */
323 if(cdir)
324 *cdir = sym.attrs.compdir;
325
326 if(dir){
327 *dir = nil;
328 b.p = dirs;
329 for (x = 1; b.p && *b.p; x++)
330 if (x == i) {
331 *dir = dwarfgetstring(&b);
332 break;
333 }
334 }
335
336 *function = nil;
337 lastline = 0;
338#if 0
339 if (dwarfenumunit(d, unit, &proc) >= 0) {
340 dwarfnextsymat(d, &proc, 0);
341 while (dwarfnextsymat(d, &proc, 1) == 1) {
342 if (proc.attrs.tag == TagSubprogram &&
343 proc.attrs.have.name &&
344 proc.attrs.declfile == emit.file &&
345 proc.attrs.declline <= *line &&
346 proc.attrs.declline > lastline) {
347 lastline = proc.attrs.declline;
348 free(*function);
349 *function = malloc(strlen(proc.attrs.name)+1);
350 strcpy(*function, proc.attrs.name);
351 }
352 }
353 }
354#elif 1
355 ulong lastaddr = 0;
356 *function = NULL;
357 for (i = 0; i < d->pe->nsymbols; i++) {
358 if (d->pe->symtab[i].address > lastaddr &&
359 d->pe->symtab[i].address <= pc - d->pe->imagebase &&
360 d->pe->symtab[i].address < d->pe->imagesize) {
361 lastaddr = d->pe->symtab[i].address;
362 *function = d->pe->symtab[i].name;
363 }
364 }
365#else
366 // *sigh* we get unrelocated low_pc and high_pc because the dwarf symbols
367 // are not 'loaded' in the PE sense.
368 if (dwarflookupfn(d, unit, pc, &proc) >= 0) {
369 *function = malloc(strlen(proc.attrs.name)+1);
370 strcpy(*function, proc.attrs.name);
371 }
372#endif
373
374 /* free at last, free at last */
375 free(f);
376 return 0;
377
378bad:
379 werrstr("corrupted line mapping for 0x%x", pc);
380out:
381 free(f);
382 return -1;
383}
384
unsigned char uchar
Definition: Unfrag.h:59
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
unsigned int dir
Definition: maze.c:112
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
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
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
@ 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
#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
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
int dwarflookupfn(Dwarf *, ulong, ulong, DwarfSym *)
Definition: dwarfinfo.c:181
char * dwarfgetstring(DwarfBuf *)
Definition: dwarfget.c:54
ulong dwarfget1(DwarfBuf *)
Definition: dwarfget.c:17
long dwarfget128s(DwarfBuf *)
Definition: dwarfget.c:197
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
struct DwarfAttrs::@4963 have
uchar stmtlist
Definition: dwarf.h:282
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 * name
Definition: compiler.c:66
Definition: fci.c:127
Definition: parser.c:49
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264