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