blob: 120cbf79c28e0de10b95115d20655f26917fb071 [file] [log] [blame]
njn4bbdc972003-10-16 10:10:55 +00001/*--------------------------------------------------------------------*/
jseward8b3131a2003-12-13 23:16:26 +00002/*--- Read DWARF2 debug info. vg_dwarf.c ---*/
njn4bbdc972003-10-16 10:10:55 +00003/*--------------------------------------------------------------------*/
4
5/*
njnb9c427c2004-12-01 14:14:42 +00006 This file is part of Valgrind, a dynamic binary instrumentation
7 framework.
njn4bbdc972003-10-16 10:10:55 +00008
njn53612422005-03-12 16:22:54 +00009 Copyright (C) 2000-2005 Julian Seward
njn4bbdc972003-10-16 10:10:55 +000010 jseward@acm.org
11
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License as
14 published by the Free Software Foundation; either version 2 of the
15 License, or (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful, but
18 WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25 02111-1307, USA.
26
27 The GNU General Public License is contained in the file COPYING.
28*/
jsgfcb1d1c02003-10-14 21:55:10 +000029
nethercotef1e5e152004-09-01 23:58:16 +000030#include "core.h"
jsgfcb1d1c02003-10-14 21:55:10 +000031#include "vg_symtab2.h"
32
33
jsgfcb1d1c02003-10-14 21:55:10 +000034/* Structure found in the .debug_line section. */
35typedef struct
36{
37 UChar li_length [4];
38 UChar li_version [2];
39 UChar li_prologue_length [4];
40 UChar li_min_insn_length [1];
41 UChar li_default_is_stmt [1];
42 UChar li_line_base [1];
43 UChar li_line_range [1];
44 UChar li_opcode_base [1];
45}
46DWARF2_External_LineInfo;
47
48typedef struct
49{
50 UInt li_length;
51 UShort li_version;
52 UInt li_prologue_length;
53 UChar li_min_insn_length;
54 UChar li_default_is_stmt;
55 Int li_line_base;
56 UChar li_line_range;
57 UChar li_opcode_base;
58}
59DWARF2_Internal_LineInfo;
60
61/* Line number opcodes. */
62enum dwarf_line_number_ops
63 {
64 DW_LNS_extended_op = 0,
65 DW_LNS_copy = 1,
66 DW_LNS_advance_pc = 2,
67 DW_LNS_advance_line = 3,
68 DW_LNS_set_file = 4,
69 DW_LNS_set_column = 5,
70 DW_LNS_negate_stmt = 6,
71 DW_LNS_set_basic_block = 7,
72 DW_LNS_const_add_pc = 8,
73 DW_LNS_fixed_advance_pc = 9,
74 /* DWARF 3. */
75 DW_LNS_set_prologue_end = 10,
76 DW_LNS_set_epilogue_begin = 11,
77 DW_LNS_set_isa = 12
78 };
79
80/* Line number extended opcodes. */
81enum dwarf_line_number_x_ops
82 {
83 DW_LNE_end_sequence = 1,
84 DW_LNE_set_address = 2,
85 DW_LNE_define_file = 3
86 };
87
88typedef struct State_Machine_Registers
89{
90 /* Information for the last statement boundary.
91 * Needed to calculate statement lengths. */
92 Addr last_address;
93 UInt last_file;
94 UInt last_line;
95
96 Addr address;
97 UInt file;
98 UInt line;
99 UInt column;
100 Int is_stmt;
101 Int basic_block;
102 Int end_sequence;
103 /* This variable hold the number of the last entry seen
104 in the File Table. */
105 UInt last_file_entry;
106} SMR;
107
108
109static
110UInt read_leb128 ( UChar* data, Int* length_return, Int sign )
111{
112 UInt result = 0;
113 UInt num_read = 0;
114 Int shift = 0;
115 UChar byte;
116
117 do
118 {
119 byte = * data ++;
120 num_read ++;
121
122 result |= (byte & 0x7f) << shift;
123
124 shift += 7;
125
126 }
127 while (byte & 0x80);
128
129 if (length_return != NULL)
130 * length_return = num_read;
131
132 if (sign && (shift < 32) && (byte & 0x40))
133 result |= -1 << shift;
134
135 return result;
136}
137
138
139static SMR state_machine_regs;
140
141static
142void reset_state_machine ( Int is_stmt )
143{
144 if (0) VG_(printf)("smr.a := %p (reset)\n", 0 );
145 state_machine_regs.last_address = 0;
146 state_machine_regs.last_file = 1;
147 state_machine_regs.last_line = 1;
148 state_machine_regs.address = 0;
149 state_machine_regs.file = 1;
150 state_machine_regs.line = 1;
151 state_machine_regs.column = 0;
152 state_machine_regs.is_stmt = is_stmt;
153 state_machine_regs.basic_block = 0;
154 state_machine_regs.end_sequence = 0;
155 state_machine_regs.last_file_entry = 0;
156}
157
158/* Handled an extend line op. Returns true if this is the end
159 of sequence. */
160static
161int process_extended_line_op( SegInfo *si, Char*** fnames,
162 UChar* data, Int is_stmt, Int pointer_size)
163{
164 UChar op_code;
165 Int bytes_read;
166 UInt len;
167 UChar * name;
168 Addr adr;
169
170 len = read_leb128 (data, & bytes_read, 0);
171 data += bytes_read;
172
173 if (len == 0)
174 {
175 VG_(message)(Vg_UserMsg,
176 "badly formed extended line op encountered!\n");
177 return bytes_read;
178 }
179
180 len += bytes_read;
181 op_code = * data ++;
182
183 if (0) VG_(printf)("dwarf2: ext OPC: %d\n", op_code);
184
185 switch (op_code)
186 {
187 case DW_LNE_end_sequence:
188 if (0) VG_(printf)("1001: si->o %p, smr.a %p\n",
189 si->offset, state_machine_regs.address );
190 state_machine_regs.end_sequence = 1; /* JRS: added for compliance
191 with spec; is pointless due to reset_state_machine below
192 */
193 if (state_machine_regs.is_stmt) {
194 if (state_machine_regs.last_address)
195 VG_(addLineInfo) (si, (*fnames)[state_machine_regs.last_file],
196 si->offset + state_machine_regs.last_address,
197 si->offset + state_machine_regs.address,
198 state_machine_regs.last_line, 0);
199 }
200 reset_state_machine (is_stmt);
201 break;
202
203 case DW_LNE_set_address:
204 /* XXX: Pointer size could be 8 */
njnbde30272004-11-29 15:45:31 +0000205 // (and there may be other 32-bit assumptions within this file?
206 // not sure... --njn)
jsgfcb1d1c02003-10-14 21:55:10 +0000207 vg_assert(pointer_size == 4);
208 adr = *((Addr *)data);
209 if (0) VG_(printf)("smr.a := %p\n", adr );
210 state_machine_regs.address = adr;
211 break;
212
213 case DW_LNE_define_file:
214 ++ state_machine_regs.last_file_entry;
215 name = data;
216 if (*fnames == NULL)
217 *fnames = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof (UInt) * 2);
218 else
219 *fnames = VG_(arena_realloc)(
njn828022a2005-03-13 14:56:31 +0000220 VG_AR_SYMTAB, *fnames,
221 sizeof(UInt) * (state_machine_regs.last_file_entry + 1));
jsgfcb1d1c02003-10-14 21:55:10 +0000222 (*fnames)[state_machine_regs.last_file_entry] = VG_(addStr) (si,name, -1);
223 data += VG_(strlen) ((char *) data) + 1;
224 read_leb128 (data, & bytes_read, 0);
225 data += bytes_read;
226 read_leb128 (data, & bytes_read, 0);
227 data += bytes_read;
228 read_leb128 (data, & bytes_read, 0);
229 break;
230
231 default:
232 break;
233 }
234
235 return len;
236}
237
238
239void VG_(read_debuginfo_dwarf2) ( SegInfo* si, UChar* dwarf2, Int dwarf2_sz )
240{
241 DWARF2_External_LineInfo * external;
242 DWARF2_Internal_LineInfo info;
243 UChar * standard_opcodes;
244 UChar * data = dwarf2;
245 UChar * end = dwarf2 + dwarf2_sz;
246 UChar * end_of_sequence;
247 Char ** fnames = NULL;
248
249 /* Fails due to gcc padding ...
250 vg_assert(sizeof(DWARF2_External_LineInfo)
251 == sizeof(DWARF2_Internal_LineInfo));
252 */
253
254 while (data < end)
255 {
256 external = (DWARF2_External_LineInfo *) data;
257
258 /* Check the length of the block. */
259 info.li_length = * ((UInt *)(external->li_length));
260
261 if (info.li_length == 0xffffffff)
262 {
263 VG_(symerr)("64-bit DWARF line info is not supported yet.");
264 break;
265 }
266
267 if (info.li_length + sizeof (external->li_length) > dwarf2_sz)
268 {
269 VG_(symerr)("DWARF line info appears to be corrupt "
270 "- the section is too small");
271 return;
272 }
273
274 /* Check its version number. */
275 info.li_version = * ((UShort *) (external->li_version));
276 if (info.li_version != 2)
277 {
278 VG_(symerr)("Only DWARF version 2 line info "
279 "is currently supported.");
280 return;
281 }
282
283 info.li_prologue_length = * ((UInt *) (external->li_prologue_length));
284 info.li_min_insn_length = * ((UChar *)(external->li_min_insn_length));
285
286 info.li_default_is_stmt = True;
287 /* WAS: = * ((UChar *)(external->li_default_is_stmt)); */
288 /* Josef Weidendorfer (20021021) writes:
289
290 It seems to me that the Intel Fortran compiler generates
291 bad DWARF2 line info code: It sets "is_stmt" of the state
292 machine in the the line info reader to be always
293 false. Thus, there is never a statement boundary generated
294 and therefore never a instruction range/line number
295 mapping generated for valgrind.
296
297 Please have a look at the DWARF2 specification, Ch. 6.2
298 (x86.ddj.com/ftp/manuals/tools/dwarf.pdf). Perhaps I
299 understand this wrong, but I don't think so.
300
301 I just had a look at the GDB DWARF2 reader... They
302 completely ignore "is_stmt" when recording line info ;-)
303 That's the reason "objdump -S" works on files from the the
304 intel fortran compiler.
305 */
306
307
308 /* JRS: changed (UInt*) to (UChar*) */
309 info.li_line_base = * ((UChar *)(external->li_line_base));
310
311 info.li_line_range = * ((UChar *)(external->li_line_range));
312 info.li_opcode_base = * ((UChar *)(external->li_opcode_base));
313
314 if (0) VG_(printf)("dwarf2: line base: %d, range %d, opc base: %d\n",
315 info.li_line_base, info.li_line_range, info.li_opcode_base);
316
317 /* Sign extend the line base field. */
318 info.li_line_base <<= 24;
319 info.li_line_base >>= 24;
320
321 end_of_sequence = data + info.li_length
322 + sizeof (external->li_length);
323
324 reset_state_machine (info.li_default_is_stmt);
325
326 /* Read the contents of the Opcodes table. */
327 standard_opcodes = data + sizeof (* external);
328
329 /* Read the contents of the Directory table. */
330 data = standard_opcodes + info.li_opcode_base - 1;
331
332 if (* data == 0)
333 {
334 }
335 else
336 {
337 /* We ignore the directory table, since gcc gives the entire
338 path as part of the filename */
339 while (* data != 0)
340 {
341 data += VG_(strlen) ((char *) data) + 1;
342 }
343 }
344
345 /* Skip the NUL at the end of the table. */
346 if (*data != 0) {
347 VG_(symerr)("can't find NUL at end of DWARF2 directory table");
348 return;
349 }
350 data ++;
351
352 /* Read the contents of the File Name table. */
353 if (* data == 0)
354 {
355 }
356 else
357 {
358 while (* data != 0)
359 {
360 UChar * name;
361 Int bytes_read;
362
363 ++ state_machine_regs.last_file_entry;
364 name = data;
365 /* Since we don't have realloc (0, ....) == malloc (...)
366 semantics, we need to malloc the first time. */
367
368 if (fnames == NULL)
369 fnames = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof (UInt) * 2);
370 else
nethercote2d5b8162004-08-11 09:40:52 +0000371 fnames = VG_(arena_realloc)(VG_AR_SYMTAB, fnames,
jsgfcb1d1c02003-10-14 21:55:10 +0000372 sizeof(UInt)
373 * (state_machine_regs.last_file_entry + 1));
374 data += VG_(strlen) ((Char *) data) + 1;
375 fnames[state_machine_regs.last_file_entry] = VG_(addStr) (si,name, -1);
376
377 read_leb128 (data, & bytes_read, 0);
378 data += bytes_read;
379 read_leb128 (data, & bytes_read, 0);
380 data += bytes_read;
381 read_leb128 (data, & bytes_read, 0);
382 data += bytes_read;
383 }
384 }
385
386 /* Skip the NUL at the end of the table. */
387 if (*data != 0) {
388 VG_(symerr)("can't find NUL at end of DWARF2 file name table");
389 return;
390 }
391 data ++;
392
393 /* Now display the statements. */
394
395 while (data < end_of_sequence)
396 {
397 UChar op_code;
398 Int adv;
399 Int bytes_read;
400
401 op_code = * data ++;
402
403 if (0) VG_(printf)("dwarf2: OPC: %d\n", op_code);
404
405 if (op_code >= info.li_opcode_base)
406 {
407 Int advAddr;
408 op_code -= info.li_opcode_base;
409 adv = (op_code / info.li_line_range)
410 * info.li_min_insn_length;
411 advAddr = adv;
412 state_machine_regs.address += adv;
413 if (0) VG_(printf)("smr.a += %p\n", adv );
414 adv = (op_code % info.li_line_range) + info.li_line_base;
415 if (0) VG_(printf)("1002: si->o %p, smr.a %p\n",
416 si->offset, state_machine_regs.address );
417 state_machine_regs.line += adv;
418
419 if (state_machine_regs.is_stmt) {
420 /* only add a statement if there was a previous boundary */
421 if (state_machine_regs.last_address)
422 VG_(addLineInfo) (si, fnames[state_machine_regs.last_file],
423 si->offset + state_machine_regs.last_address,
424 si->offset + state_machine_regs.address,
425 state_machine_regs.last_line, 0);
426 state_machine_regs.last_address = state_machine_regs.address;
427 state_machine_regs.last_file = state_machine_regs.file;
428 state_machine_regs.last_line = state_machine_regs.line;
429 }
430 }
431 else switch (op_code)
432 {
433 case DW_LNS_extended_op:
434 data += process_extended_line_op (
435 si, &fnames, data,
436 info.li_default_is_stmt, sizeof (Addr));
437 break;
438
439 case DW_LNS_copy:
440 if (0) VG_(printf)("1002: si->o %p, smr.a %p\n",
441 si->offset, state_machine_regs.address );
442 if (state_machine_regs.is_stmt) {
443 /* only add a statement if there was a previous boundary */
444 if (state_machine_regs.last_address)
445 VG_(addLineInfo) (si, fnames[state_machine_regs.last_file],
446 si->offset + state_machine_regs.last_address,
447 si->offset + state_machine_regs.address,
448 state_machine_regs.last_line, 0);
449 state_machine_regs.last_address = state_machine_regs.address;
450 state_machine_regs.last_file = state_machine_regs.file;
451 state_machine_regs.last_line = state_machine_regs.line;
452 }
453 state_machine_regs.basic_block = 0; /* JRS added */
454 break;
455
456 case DW_LNS_advance_pc:
457 adv = info.li_min_insn_length
458 * read_leb128 (data, & bytes_read, 0);
459 data += bytes_read;
460 state_machine_regs.address += adv;
461 if (0) VG_(printf)("smr.a += %p\n", adv );
462 break;
463
464 case DW_LNS_advance_line:
465 adv = read_leb128 (data, & bytes_read, 1);
466 data += bytes_read;
467 state_machine_regs.line += adv;
468 break;
469
470 case DW_LNS_set_file:
471 adv = read_leb128 (data, & bytes_read, 0);
472 data += bytes_read;
473 state_machine_regs.file = adv;
474 break;
475
476 case DW_LNS_set_column:
477 adv = read_leb128 (data, & bytes_read, 0);
478 data += bytes_read;
479 state_machine_regs.column = adv;
480 break;
481
482 case DW_LNS_negate_stmt:
483 adv = state_machine_regs.is_stmt;
484 adv = ! adv;
485 state_machine_regs.is_stmt = adv;
486 break;
487
488 case DW_LNS_set_basic_block:
489 state_machine_regs.basic_block = 1;
490 break;
491
492 case DW_LNS_const_add_pc:
493 adv = (((255 - info.li_opcode_base) / info.li_line_range)
494 * info.li_min_insn_length);
495 state_machine_regs.address += adv;
496 if (0) VG_(printf)("smr.a += %p\n", adv );
497 break;
498
499 case DW_LNS_fixed_advance_pc:
500 /* XXX: Need something to get 2 bytes */
501 adv = *((UShort *)data);
502 data += 2;
503 state_machine_regs.address += adv;
504 if (0) VG_(printf)("smr.a += %p\n", adv );
505 break;
506
507 case DW_LNS_set_prologue_end:
508 break;
509
510 case DW_LNS_set_epilogue_begin:
511 break;
512
513 case DW_LNS_set_isa:
514 adv = read_leb128 (data, & bytes_read, 0);
515 data += bytes_read;
516 break;
517
518 default:
519 {
520 int j;
521 for (j = standard_opcodes[op_code - 1]; j > 0 ; --j)
522 {
523 read_leb128 (data, &bytes_read, 0);
524 data += bytes_read;
525 }
526 }
527 break;
528 }
529 }
530 VG_(arena_free)(VG_AR_SYMTAB, fnames);
531 fnames = NULL;
532 }
533}
njn4bbdc972003-10-16 10:10:55 +0000534
jseward8b3131a2003-12-13 23:16:26 +0000535
536/*------------------------------------------------------------*/
537/*--- Read DWARF1 format line number info. ---*/
538/*------------------------------------------------------------*/
539
540/* DWARF1 appears to be redundant, but nevertheless the Lahey Fortran
541 compiler generates it.
542*/
543
544/* The following three enums (dwarf_tag, dwarf_form, dwarf_attribute)
545 are taken from the file include/elf/dwarf.h in the GNU gdb-6.0
546 sources, which are Copyright 1992, 1993, 1995, 1999 Free Software
547 Foundation, Inc and naturally licensed under the GNU General Public
548 License version 2 or later.
549*/
550
551/* Tag names and codes. */
552
553enum dwarf_tag {
554 TAG_padding = 0x0000,
555 TAG_array_type = 0x0001,
556 TAG_class_type = 0x0002,
557 TAG_entry_point = 0x0003,
558 TAG_enumeration_type = 0x0004,
559 TAG_formal_parameter = 0x0005,
560 TAG_global_subroutine = 0x0006,
561 TAG_global_variable = 0x0007,
562 /* 0x0008 -- reserved */
563 /* 0x0009 -- reserved */
564 TAG_label = 0x000a,
565 TAG_lexical_block = 0x000b,
566 TAG_local_variable = 0x000c,
567 TAG_member = 0x000d,
568 /* 0x000e -- reserved */
569 TAG_pointer_type = 0x000f,
570 TAG_reference_type = 0x0010,
571 TAG_compile_unit = 0x0011,
572 TAG_string_type = 0x0012,
573 TAG_structure_type = 0x0013,
574 TAG_subroutine = 0x0014,
575 TAG_subroutine_type = 0x0015,
576 TAG_typedef = 0x0016,
577 TAG_union_type = 0x0017,
578 TAG_unspecified_parameters = 0x0018,
579 TAG_variant = 0x0019,
580 TAG_common_block = 0x001a,
581 TAG_common_inclusion = 0x001b,
582 TAG_inheritance = 0x001c,
583 TAG_inlined_subroutine = 0x001d,
584 TAG_module = 0x001e,
585 TAG_ptr_to_member_type = 0x001f,
586 TAG_set_type = 0x0020,
587 TAG_subrange_type = 0x0021,
588 TAG_with_stmt = 0x0022,
589
590 /* GNU extensions */
591
592 TAG_format_label = 0x8000, /* for FORTRAN 77 and Fortran 90 */
593 TAG_namelist = 0x8001, /* For Fortran 90 */
594 TAG_function_template = 0x8002, /* for C++ */
595 TAG_class_template = 0x8003 /* for C++ */
596};
597
598/* Form names and codes. */
599
600enum dwarf_form {
601 FORM_ADDR = 0x1,
602 FORM_REF = 0x2,
603 FORM_BLOCK2 = 0x3,
604 FORM_BLOCK4 = 0x4,
605 FORM_DATA2 = 0x5,
606 FORM_DATA4 = 0x6,
607 FORM_DATA8 = 0x7,
608 FORM_STRING = 0x8
609};
610
611/* Attribute names and codes. */
612
613enum dwarf_attribute {
614 AT_sibling = (0x0010|FORM_REF),
615 AT_location = (0x0020|FORM_BLOCK2),
616 AT_name = (0x0030|FORM_STRING),
617 AT_fund_type = (0x0050|FORM_DATA2),
618 AT_mod_fund_type = (0x0060|FORM_BLOCK2),
619 AT_user_def_type = (0x0070|FORM_REF),
620 AT_mod_u_d_type = (0x0080|FORM_BLOCK2),
621 AT_ordering = (0x0090|FORM_DATA2),
622 AT_subscr_data = (0x00a0|FORM_BLOCK2),
623 AT_byte_size = (0x00b0|FORM_DATA4),
624 AT_bit_offset = (0x00c0|FORM_DATA2),
625 AT_bit_size = (0x00d0|FORM_DATA4),
626 /* (0x00e0|FORM_xxxx) -- reserved */
627 AT_element_list = (0x00f0|FORM_BLOCK4),
628 AT_stmt_list = (0x0100|FORM_DATA4),
629 AT_low_pc = (0x0110|FORM_ADDR),
630 AT_high_pc = (0x0120|FORM_ADDR),
631 AT_language = (0x0130|FORM_DATA4),
632 AT_member = (0x0140|FORM_REF),
633 AT_discr = (0x0150|FORM_REF),
634 AT_discr_value = (0x0160|FORM_BLOCK2),
635 /* (0x0170|FORM_xxxx) -- reserved */
636 /* (0x0180|FORM_xxxx) -- reserved */
637 AT_string_length = (0x0190|FORM_BLOCK2),
638 AT_common_reference = (0x01a0|FORM_REF),
639 AT_comp_dir = (0x01b0|FORM_STRING),
640 AT_const_value_string = (0x01c0|FORM_STRING),
641 AT_const_value_data2 = (0x01c0|FORM_DATA2),
642 AT_const_value_data4 = (0x01c0|FORM_DATA4),
643 AT_const_value_data8 = (0x01c0|FORM_DATA8),
644 AT_const_value_block2 = (0x01c0|FORM_BLOCK2),
645 AT_const_value_block4 = (0x01c0|FORM_BLOCK4),
646 AT_containing_type = (0x01d0|FORM_REF),
647 AT_default_value_addr = (0x01e0|FORM_ADDR),
648 AT_default_value_data2 = (0x01e0|FORM_DATA2),
649 AT_default_value_data4 = (0x01e0|FORM_DATA4),
650 AT_default_value_data8 = (0x01e0|FORM_DATA8),
651 AT_default_value_string = (0x01e0|FORM_STRING),
652 AT_friends = (0x01f0|FORM_BLOCK2),
653 AT_inline = (0x0200|FORM_STRING),
654 AT_is_optional = (0x0210|FORM_STRING),
655 AT_lower_bound_ref = (0x0220|FORM_REF),
656 AT_lower_bound_data2 = (0x0220|FORM_DATA2),
657 AT_lower_bound_data4 = (0x0220|FORM_DATA4),
658 AT_lower_bound_data8 = (0x0220|FORM_DATA8),
659 AT_private = (0x0240|FORM_STRING),
660 AT_producer = (0x0250|FORM_STRING),
661 AT_program = (0x0230|FORM_STRING),
662 AT_protected = (0x0260|FORM_STRING),
663 AT_prototyped = (0x0270|FORM_STRING),
664 AT_public = (0x0280|FORM_STRING),
665 AT_pure_virtual = (0x0290|FORM_STRING),
666 AT_return_addr = (0x02a0|FORM_BLOCK2),
667 AT_abstract_origin = (0x02b0|FORM_REF),
668 AT_start_scope = (0x02c0|FORM_DATA4),
669 AT_stride_size = (0x02e0|FORM_DATA4),
670 AT_upper_bound_ref = (0x02f0|FORM_REF),
671 AT_upper_bound_data2 = (0x02f0|FORM_DATA2),
672 AT_upper_bound_data4 = (0x02f0|FORM_DATA4),
673 AT_upper_bound_data8 = (0x02f0|FORM_DATA8),
674 AT_virtual = (0x0300|FORM_STRING),
675
676 /* GNU extensions. */
677
678 AT_sf_names = (0x8000|FORM_DATA4),
679 AT_src_info = (0x8010|FORM_DATA4),
680 AT_mac_info = (0x8020|FORM_DATA4),
681 AT_src_coords = (0x8030|FORM_DATA4),
682 AT_body_begin = (0x8040|FORM_ADDR),
683 AT_body_end = (0x8050|FORM_ADDR)
684};
685
686/* end of enums taken from gdb-6.0 sources */
687
688void VG_(read_debuginfo_dwarf1) (
689 SegInfo* si,
690 UChar* dwarf1d, Int dwarf1d_sz,
691 UChar* dwarf1l, Int dwarf1l_sz )
692{
693 UInt stmt_list;
694 Bool stmt_list_found;
695 Int die_offset, die_szb, at_offset;
696 UShort die_kind, at_kind;
697 UChar* at_base;
698 UChar* src_filename;
699
700 if (0)
701 VG_(printf)("read_debuginfo_dwarf1 ( %p, %d, %p, %d )\n",
702 dwarf1d, dwarf1d_sz, dwarf1l, dwarf1l_sz );
703
704 /* This loop scans the DIEs. */
705 die_offset = 0;
706 while (True) {
707 if (die_offset >= dwarf1d_sz) break;
708
709 die_szb = *(Int*)(dwarf1d + die_offset);
710 die_kind = *(UShort*)(dwarf1d + die_offset + 4);
711
712 /* We're only interested in compile_unit DIEs; ignore others. */
713 if (die_kind != TAG_compile_unit) {
714 die_offset += die_szb;
715 continue;
716 }
717
718 if (0)
719 VG_(printf)("compile-unit DIE: offset %d, tag 0x%x, size %d\n",
720 die_offset, (Int)die_kind, die_szb );
721
722 /* We've got a compile_unit DIE starting at (dwarf1d +
723 die_offset+6). Try and find the AT_name and AT_stmt_list
724 attributes. Then, finally, we can read the line number info
725 for this source file. */
726
727 /* The next 3 are set as we find the relevant attrs. */
728 src_filename = NULL;
729 stmt_list_found = False;
730 stmt_list = 0;
731
732 /* This loop scans the Attrs inside compile_unit DIEs. */
733 at_base = dwarf1d + die_offset + 6;
734 at_offset = 0;
735 while (True) {
736 if (at_offset >= die_szb-6) break;
737
738 at_kind = *(UShort*)(at_base + at_offset);
739 if (0) VG_(printf)("atoffset %d, attag 0x%x\n",
740 at_offset, (Int)at_kind );
741 at_offset += 2; /* step over the attribute itself */
742 /* We have to examine the attribute to figure out its
743 length. */
744 switch (at_kind) {
745 case AT_stmt_list:
746 case AT_language:
747 case AT_sibling:
748 if (at_kind == AT_stmt_list) {
749 stmt_list_found = True;
750 stmt_list = *(Int*)(at_base+at_offset);
751 }
752 at_offset += 4; break;
753 case AT_high_pc:
754 case AT_low_pc:
755 at_offset += sizeof(void*); break;
756 case AT_name:
757 case AT_producer:
758 case AT_comp_dir:
759 /* Zero terminated string, step over it. */
760 if (at_kind == AT_name)
761 src_filename = at_base + at_offset;
762 while (at_offset < die_szb-6 && at_base[at_offset] != 0)
763 at_offset++;
764 at_offset++;
765 break;
766 default:
767 VG_(printf)("Unhandled DWARF-1 attribute 0x%x\n",
768 (Int)at_kind );
769 VG_(core_panic)("Unhandled DWARF-1 attribute");
770 } /* switch (at_kind) */
771 } /* looping over attributes */
772
773 /* So, did we find the required stuff for a line number table in
774 this DIE? If yes, read it. */
775 if (stmt_list_found /* there is a line number table */
776 && src_filename != NULL /* we know the source filename */
777 ) {
778 /* Table starts:
779 Length:
780 4 bytes, includes the entire table
781 Base address:
782 unclear (4? 8?), assuming native pointer size here.
783 Then a sequence of triples
784 (source line number -- 32 bits
785 source line column -- 16 bits
786 address delta -- 32 bits)
787 */
788 Addr base;
789 Int len;
790 Char* curr_filenm;
791 UChar* ptr;
792 UInt prev_line, prev_delta;
793
794 curr_filenm = VG_(addStr) ( si, src_filename, -1 );
795 prev_line = prev_delta = 0;
796
797 ptr = dwarf1l + stmt_list;
798 len = *(Int*)ptr; ptr += sizeof(Int);
799 base = (Addr)(*(void**)ptr); ptr += sizeof(void*);
800 len -= (sizeof(Int) + sizeof(void*));
801 while (len > 0) {
802 UInt line;
803 UShort col;
804 UInt delta;
805 line = *(UInt*)ptr; ptr += sizeof(UInt);
806 col = *(UShort*)ptr; ptr += sizeof(UShort);
807 delta = *(UShort*)ptr; ptr += sizeof(UInt);
808 if (0) VG_(printf)("line %d, col %d, delta %d\n",
809 line, (Int)col, delta );
810 len -= (sizeof(UInt) + sizeof(UShort) + sizeof(UInt));
811
812 if (delta > 0 && prev_line > 0) {
813 if (0) VG_(printf) (" %d %d-%d\n",
814 prev_line, prev_delta, delta-1);
815 VG_(addLineInfo) ( si, curr_filenm,
816 base + prev_delta, base + delta,
817 prev_line, 0 );
818 }
819 prev_line = line;
820 prev_delta = delta;
821 }
822 }
823
824 /* Move on the the next DIE. */
825 die_offset += die_szb;
826
827 } /* Looping over DIEs */
828
829}
830
831
njn4bbdc972003-10-16 10:10:55 +0000832/*--------------------------------------------------------------------*/
jseward8b3131a2003-12-13 23:16:26 +0000833/*--- end vg_dwarf.c ---*/
njn4bbdc972003-10-16 10:10:55 +0000834/*--------------------------------------------------------------------*/