blob: b413539cf035b139e2ccdf0896cc17d3fd4c81dc [file] [log] [blame]
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001/* Return line number information of CU.
2 Copyright (C) 2004, 2005 Red Hat, Inc.
Ulrich Drepper361df7d2006-04-04 21:38:57 +00003 This file is part of Red Hat elfutils.
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004 Written by Ulrich Drepper <drepper@redhat.com>, 2004.
5
Ulrich Drepper361df7d2006-04-04 21:38:57 +00006 Red Hat elfutils is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by the
8 Free Software Foundation; version 2 of the License.
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00009
Ulrich Drepper361df7d2006-04-04 21:38:57 +000010 Red Hat elfutils is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with Red Hat elfutils; if not, write to the Free Software Foundation,
17 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
18
19 In addition, as a special exception, Red Hat, Inc. gives You the
20 additional right to link the code of Red Hat elfutils with code licensed
21 under any Open Source Initiative certified open source license
22 (http://www.opensource.org/licenses/index.php) which requires the
23 distribution of source code with any binary distribution and to
24 distribute linked combinations of the two. Non-GPL Code permitted under
25 this exception must only link to the code of Red Hat elfutils through
26 those well defined interfaces identified in the file named EXCEPTION
27 found in the source code files (the "Approved Interfaces"). The files
28 of Non-GPL Code may instantiate templates or use macros or inline
29 functions from the Approved Interfaces without causing the resulting
30 work to be covered by the GNU General Public License. Only Red Hat,
31 Inc. may make changes or additions to the list of Approved Interfaces.
32 Red Hat's grant of this exception is conditioned upon your not adding
33 any new exceptions. If you wish to add a new Approved Interface or
34 exception, please contact Red Hat. You must obey the GNU General Public
35 License in all respects for all of the Red Hat elfutils code and other
36 code used in conjunction with Red Hat elfutils except the Non-GPL Code
37 covered by this exception. If you modify this file, you may extend this
38 exception to your version of the file, but you are not obligated to do
39 so. If you do not wish to provide this exception without modification,
40 you must delete this exception statement from your version and license
41 this file solely under the GPL without exception.
42
43 Red Hat elfutils is an included package of the Open Invention Network.
44 An included package of the Open Invention Network is a package for which
45 Open Invention Network licensees cross-license their patents. No patent
46 license is granted, either expressly or impliedly, by designation as an
47 included package. Should you wish to participate in the Open Invention
48 Network licensing program, please visit www.openinventionnetwork.com
49 <http://www.openinventionnetwork.com>. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000050
51#ifdef HAVE_CONFIG_H
52# include <config.h>
53#endif
54
55#include <assert.h>
56#include <stdlib.h>
57#include <string.h>
58#include "dwarf.h"
59#include "libdwP.h"
60
61
62struct filelist
63{
64 Dwarf_Fileinfo info;
65 struct filelist *next;
66};
67
68struct linelist
69{
70 Dwarf_Line line;
71 struct linelist *next;
72};
73
74
75/* Compare by Dwarf_Line.addr, given pointers into an array of pointers. */
76static int
77compare_lines (const void *a, const void *b)
78{
79 Dwarf_Line *const *p1 = a;
80 Dwarf_Line *const *p2 = b;
81
Roland McGrath07d4f2f2005-10-28 06:56:24 +000082 if ((*p1)->addr == (*p2)->addr)
83 /* An end_sequence marker precedes a normal record at the same address. */
84 return (*p2)->end_sequence - (*p1)->end_sequence;
85
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000086 return (*p1)->addr - (*p2)->addr;
87}
88
89
90/* Adds a new line to the matrix. We cannot define a function because
91 we want to use alloca. */
92#define NEW_LINE(end_seq) \
93 do { \
94 /* Add the new line. */ \
95 new_line = (struct linelist *) alloca (sizeof (struct linelist)); \
96 \
97 /* Set the line information. */ \
98 new_line->line.addr = address; \
99 new_line->line.file = file; \
100 new_line->line.line = line; \
101 new_line->line.column = column; \
102 new_line->line.is_stmt = is_stmt; \
103 new_line->line.basic_block = basic_block; \
104 new_line->line.end_sequence = end_seq; \
105 new_line->line.prologue_end = prologue_end; \
106 new_line->line.epilogue_begin = epilogue_begin; \
107 \
108 new_line->next = linelist; \
109 linelist = new_line; \
110 ++nlinelist; \
111 } while (0)
112
113
114int
115dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines)
116{
117 if (unlikely (cudie == NULL
118 || INTUSE(dwarf_tag) (cudie) != DW_TAG_compile_unit))
119 return -1;
120
121 int res = -1;
122
123 /* Get the information if it is not already known. */
124 struct Dwarf_CU *const cu = cudie->cu;
125 if (cu->lines == NULL)
126 {
127 /* Failsafe mode: no data found. */
128 cu->lines = (void *) -1l;
129 cu->files = (void *) -1l;
130
131 /* The die must have a statement list associated. */
132 Dwarf_Attribute stmt_list_mem;
133 Dwarf_Attribute *stmt_list = INTUSE(dwarf_attr) (cudie, DW_AT_stmt_list,
134 &stmt_list_mem);
135
136 /* Get the offset into the .debug_line section. NB: this call
137 also checks whether the previous dwarf_attr call failed. */
138 Dwarf_Word offset;
139 if (INTUSE(dwarf_formudata) (stmt_list, &offset) != 0)
140 goto out;
141
142 Dwarf *dbg = cu->dbg;
143 if (dbg->sectiondata[IDX_debug_line] == NULL)
144 {
145 __libdw_seterrno (DWARF_E_NO_DEBUG_LINE);
146 goto out;
147 }
148 const uint8_t *linep = dbg->sectiondata[IDX_debug_line]->d_buf + offset;
149 const uint8_t *lineendp = (dbg->sectiondata[IDX_debug_line]->d_buf
150 + dbg->sectiondata[IDX_debug_line]->d_size);
151
152 /* Get the compilation directory. */
153 Dwarf_Attribute compdir_attr_mem;
154 Dwarf_Attribute *compdir_attr = INTUSE(dwarf_attr) (cudie,
155 DW_AT_comp_dir,
156 &compdir_attr_mem);
157 const char *comp_dir = INTUSE(dwarf_formstring) (compdir_attr);
158
159 if (unlikely (linep + 4 > lineendp))
160 {
161 invalid_data:
162 __libdw_seterrno (DWARF_E_INVALID_DEBUG_LINE);
163 goto out;
164 }
165 Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
166 unsigned int length = 4;
167 if (unlikely (unit_length == 0xffffffff))
168 {
169 if (unlikely (linep + 8 > lineendp))
170 goto invalid_data;
171 unit_length = read_8ubyte_unaligned_inc (dbg, linep);
172 length = 8;
173 }
174
175 /* Check whether we have enough room in the section. */
176 if (unit_length < 2 + length + 5 * 1
177 || unlikely (linep + unit_length > lineendp))
178 goto invalid_data;
179 lineendp = linep + unit_length;
180
181 /* The next element of the header is the version identifier. */
182 uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
183 if (unlikely (version != DWARF_VERSION))
184 {
185 __libdw_seterrno (DWARF_E_VERSION);
186 goto out;
187 }
188
189 /* Next comes the header length. */
190 Dwarf_Word header_length;
191 if (length == 4)
192 header_length = read_4ubyte_unaligned_inc (dbg, linep);
193 else
194 header_length = read_8ubyte_unaligned_inc (dbg, linep);
195 const unsigned char *header_start = linep;
196
197 /* Next the minimum instruction length. */
198 uint_fast8_t minimum_instr_len = *linep++;
199
200 /* Then the flag determining the default value of the is_stmt
201 register. */
202 uint_fast8_t default_is_stmt = *linep++;
203
204 /* Now the line base. */
205 int_fast8_t line_base = *((int_fast8_t *) linep);
206 ++linep;
207
208 /* And the line range. */
209 uint_fast8_t line_range = *linep++;
210
211 /* The opcode base. */
212 uint_fast8_t opcode_base = *linep++;
213
214 /* Remember array with the standard opcode length (-1 to account for
215 the opcode with value zero not being mentioned). */
216 const uint8_t *standard_opcode_lengths = linep - 1;
217 linep += opcode_base - 1;
218 if (unlikely (linep >= lineendp))
219 goto invalid_data;
220
221 /* First comes the list of directories. Add the compilation
222 directory first since the index zero is used for it. */
223 struct dirlist
224 {
225 const char *dir;
226 size_t len;
227 struct dirlist *next;
228 } comp_dir_elem =
229 {
230 .dir = comp_dir,
231 .len = comp_dir ? strlen (comp_dir) : 0,
232 .next = NULL
233 };
234 struct dirlist *dirlist = &comp_dir_elem;
235 unsigned int ndirlist = 1;
236
237 // XXX Directly construct array to conserve memory?
238 while (*linep != 0)
239 {
240 struct dirlist *new_dir =
241 (struct dirlist *) alloca (sizeof (*new_dir));
242
243 new_dir->dir = (char *) linep;
244 uint8_t *endp = memchr (linep, '\0', lineendp - linep);
245 if (endp == NULL)
246 goto invalid_data;
247 new_dir->len = endp - linep;
248 new_dir->next = dirlist;
249 dirlist = new_dir;
250 ++ndirlist;
251 linep = endp + 1;
252 }
253 /* Skip the final NUL byte. */
254 ++linep;
255
256 /* Rearrange the list in array form. */
257 struct dirlist **dirarray
258 = (struct dirlist **) alloca (ndirlist * sizeof (*dirarray));
259 while (ndirlist-- > 0)
260 {
261 dirarray[ndirlist] = dirlist;
262 dirlist = dirlist->next;
263 }
264
265 /* Now read the files. */
266 struct filelist null_file =
267 {
268 .info =
269 {
270 .name = "???",
271 .mtime = 0,
272 .length = 0
273 },
274 .next = NULL
275 };
276 struct filelist *filelist = &null_file;
277 unsigned int nfilelist = 1;
278
279 if (unlikely (linep >= lineendp))
280 goto invalid_data;
281 while (*linep != 0)
282 {
283 struct filelist *new_file =
284 (struct filelist *) alloca (sizeof (*new_file));
285
286 /* First comes the file name. */
287 char *fname = (char *) linep;
288 uint8_t *endp = memchr (fname, '\0', lineendp - linep);
289 if (endp == NULL)
290 goto invalid_data;
291 size_t fnamelen = endp - (uint8_t *) fname;
292 linep = endp + 1;
293
294 /* Then the index. */
295 Dwarf_Word diridx;
296 get_uleb128 (diridx, linep);
297 if (unlikely (diridx >= ndirlist))
298 {
299 __libdw_seterrno (DWARF_E_INVALID_DIR_IDX);
300 goto out;
301 }
302
303 if (*fname == '/')
304 /* It's an absolute path. */
305 new_file->info.name = fname;
306 else
307 {
308 new_file->info.name = libdw_alloc (dbg, char, 1,
309 dirarray[diridx]->len + 1
310 + fnamelen + 1);
311 char *cp = new_file->info.name;
312
313 if (dirarray[diridx]->dir != NULL)
314 {
315 /* This value could be NULL in case the DW_AT_comp_dir
316 was not present. We cannot do much in this case.
317 The easiest thing is to convert the path in an
318 absolute path. */
319 cp = stpcpy (cp, dirarray[diridx]->dir);
320 }
321 *cp++ = '/';
322 strcpy (cp, fname);
323 assert (strlen (new_file->info.name)
324 < dirarray[diridx]->len + 1 + fnamelen + 1);
325 }
326
327 /* Next comes the modification time. */
328 get_uleb128 (new_file->info.mtime, linep);
329
330 /* Finally the length of the file. */
331 get_uleb128 (new_file->info.length, linep);
332
333 new_file->next = filelist;
334 filelist = new_file;
335 ++nfilelist;
336 }
337 /* Skip the final NUL byte. */
338 ++linep;
339
340 /* Consistency check. */
341 if (unlikely (linep != header_start + header_length))
342 {
343 __libdw_seterrno (DWARF_E_INVALID_DWARF);
344 goto out;
345 }
346
347 /* We are about to process the statement program. Initialize the
348 state machine registers (see 6.2.2 in the v2.1 specification). */
349 Dwarf_Word address = 0;
350 size_t file = 1;
351 size_t line = 1;
352 size_t column = 0;
353 uint_fast8_t is_stmt = default_is_stmt;
354 int basic_block = 0;
355 int prologue_end = 0;
356 int epilogue_begin = 0;
357
358 /* Process the instructions. */
359 struct linelist *linelist = NULL;
360 unsigned int nlinelist = 0;
361 while (linep < lineendp)
362 {
363 struct linelist *new_line;
364 unsigned int opcode;
365 unsigned int u128;
366 int s128;
367
368 /* Read the opcode. */
369 opcode = *linep++;
370
371 /* Is this a special opcode? */
372 if (likely (opcode >= opcode_base))
373 {
374 /* Yes. Handling this is quite easy since the opcode value
375 is computed with
376
377 opcode = (desired line increment - line_base)
378 + (line_range * address advance) + opcode_base
379 */
380 int line_increment = (line_base
381 + (opcode - opcode_base) % line_range);
382 unsigned int address_increment = (minimum_instr_len
383 * ((opcode - opcode_base)
384 / line_range));
385
386 /* Perform the increments. */
387 line += line_increment;
388 address += address_increment;
389
390 /* Add a new line with the current state machine values. */
391 NEW_LINE (0);
392
393 /* Reset the flags. */
394 basic_block = 0;
395 prologue_end = 0;
396 epilogue_begin = 0;
397 }
398 else if (opcode == 0)
399 {
400 /* This an extended opcode. */
401 if (unlikely (linep + 2 > lineendp))
402 goto invalid_data;
403
404 /* The length. */
405 unsigned int len = *linep++;
406
407 if (unlikely (linep + len > lineendp))
408 goto invalid_data;
409
410 /* The sub-opcode. */
411 opcode = *linep++;
412
413 switch (opcode)
414 {
415 case DW_LNE_end_sequence:
416 /* Add a new line with the current state machine values.
417 The is the end of the sequence. */
418 NEW_LINE (1);
419
420 /* Reset the registers. */
421 address = 0;
422 file = 1;
423 line = 1;
424 column = 0;
425 is_stmt = default_is_stmt;
426 basic_block = 0;
427 prologue_end = 0;
428 epilogue_begin = 0;
429 break;
430
431 case DW_LNE_set_address:
432 /* The value is an address. The size is defined as
433 apporiate for the target machine. We use the
434 address size field from the CU header. */
435 if (cu->address_size == 4)
436 address = read_4ubyte_unaligned_inc (dbg, linep);
437 else
438 address = read_8ubyte_unaligned_inc (dbg, linep);
439 break;
440
441 case DW_LNE_define_file:
442 {
443 char *fname = (char *) linep;
444 uint8_t *endp = memchr (linep, '\0', lineendp - linep);
445 if (endp == NULL)
446 goto invalid_data;
447 size_t fnamelen = endp - linep;
448 linep = endp + 1;
449
450 unsigned int diridx;
451 get_uleb128 (diridx, linep);
452 Dwarf_Word mtime;
453 get_uleb128 (mtime, linep);
454 Dwarf_Word filelength;
455 get_uleb128 (filelength, linep);
456
457 struct filelist *new_file =
458 (struct filelist *) alloca (sizeof (*new_file));
459 if (fname[0] == '/')
460 new_file->info.name = fname;
461 else
462 {
463 new_file->info.name =
464 libdw_alloc (dbg, char, 1, (dirarray[diridx]->len + 1
465 + fnamelen + 1));
466 char *cp = new_file->info.name;
467
468 if (dirarray[diridx]->dir != NULL)
469 /* This value could be NULL in case the
470 DW_AT_comp_dir was not present. We
471 cannot do much in this case. The easiest
472 thing is to convert the path in an
473 absolute path. */
474 cp = stpcpy (cp, dirarray[diridx]->dir);
475 *cp++ = '/';
476 strcpy (cp, fname);
477 }
478
479 new_file->info.mtime = mtime;
480 new_file->info.length = filelength;
481 new_file->next = filelist;
482 filelist = new_file;
483 ++nfilelist;
484 }
485 break;
486
487 default:
488 /* Unknown, ignore it. */
489 linep += len - 1;
490 break;
491 }
492 }
Ulrich Drepper6d5c3bd2005-08-11 04:37:52 +0000493 else if (opcode <= DW_LNS_set_epilogue_begin)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000494 {
495 /* This is a known standard opcode. */
496 switch (opcode)
497 {
498 case DW_LNS_copy:
499 /* Takes no argument. */
500 if (unlikely (standard_opcode_lengths[opcode] != 0))
501 goto invalid_data;
502
503 /* Add a new line with the current state machine values. */
504 NEW_LINE (0);
505
506 /* Reset the flags. */
507 basic_block = 0;
508 /* XXX Whether the following two lines are necessary is
509 unclear. I guess the current v2.1 specification has
510 a bug in that it says clearing these two registers is
511 not necessary. */
512 prologue_end = 0;
513 epilogue_begin = 0;
514 break;
515
516 case DW_LNS_advance_pc:
517 /* Takes one uleb128 parameter which is added to the
518 address. */
519 if (unlikely (standard_opcode_lengths[opcode] != 1))
520 goto invalid_data;
521
522 get_uleb128 (u128, linep);
523 address += minimum_instr_len * u128;
524 break;
525
526 case DW_LNS_advance_line:
527 /* Takes one sleb128 parameter which is added to the
528 line. */
529 if (unlikely (standard_opcode_lengths[opcode] != 1))
530 goto invalid_data;
531
532 get_sleb128 (s128, linep);
533 line += s128;
534 break;
535
536 case DW_LNS_set_file:
537 /* Takes one uleb128 parameter which is stored in file. */
538 if (unlikely (standard_opcode_lengths[opcode] != 1))
539 goto invalid_data;
540
541 get_uleb128 (u128, linep);
542 file = u128;
543 break;
544
545 case DW_LNS_set_column:
546 /* Takes one uleb128 parameter which is stored in column. */
547 if (unlikely (standard_opcode_lengths[opcode] != 1))
548 goto invalid_data;
549
550 get_uleb128 (u128, linep);
551 column = u128;
552 break;
553
554 case DW_LNS_negate_stmt:
555 /* Takes no argument. */
556 if (unlikely (standard_opcode_lengths[opcode] != 0))
557 goto invalid_data;
558
559 is_stmt = 1 - is_stmt;
560 break;
561
562 case DW_LNS_set_basic_block:
563 /* Takes no argument. */
564 if (unlikely (standard_opcode_lengths[opcode] != 0))
565 goto invalid_data;
566
567 basic_block = 1;
568 break;
569
570 case DW_LNS_const_add_pc:
571 /* Takes no argument. */
572 if (unlikely (standard_opcode_lengths[opcode] != 0))
573 goto invalid_data;
574
575 address += (minimum_instr_len
576 * ((255 - opcode_base) / line_range));
577 break;
578
579 case DW_LNS_fixed_advance_pc:
580 /* Takes one 16 bit parameter which is added to the
581 address. */
582 if (unlikely (standard_opcode_lengths[opcode] != 1))
583 goto invalid_data;
584
585 address += read_2ubyte_unaligned_inc (dbg, linep);
586 break;
587
588 case DW_LNS_set_prologue_end:
589 /* Takes no argument. */
590 if (unlikely (standard_opcode_lengths[opcode] != 0))
591 goto invalid_data;
592
593 prologue_end = 1;
594 break;
595
Ulrich Drepper6d5c3bd2005-08-11 04:37:52 +0000596 case DW_LNS_set_epilogue_begin:
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000597 /* Takes no argument. */
598 if (unlikely (standard_opcode_lengths[opcode] != 0))
599 goto invalid_data;
600
601 epilogue_begin = 1;
602 break;
603 }
604 }
605 else
606 {
607 /* This is a new opcode the generator but not we know about.
608 Read the parameters associated with it but then discard
609 everything. Read all the parameters for this opcode. */
610 for (int n = standard_opcode_lengths[opcode]; n > 0; --n)
611 get_uleb128 (u128, linep);
612
613 /* Next round, ignore this opcode. */
614 continue;
615 }
616 }
617
618 /* Put all the files in an array. */
619 Dwarf_Files *files = libdw_alloc (dbg, Dwarf_Files,
620 sizeof (Dwarf_Files)
621 + nfilelist * sizeof (Dwarf_Fileinfo),
622 1);
623 files->nfiles = nfilelist;
624 while (nfilelist-- > 0)
625 {
626 files->info[nfilelist] = filelist->info;
627 filelist = filelist->next;
628 }
629 assert (filelist == NULL);
630
631 /* Remember the debugging descriptor. */
632 files->dbg = dbg;
633
634 /* Make the file data structure available through the CU. */
635 cu->files = files;
636
637 void *buf = libdw_alloc (dbg, Dwarf_Lines, (sizeof (Dwarf_Lines)
638 + (sizeof (Dwarf_Line)
639 * nlinelist)), 1);
640
641 /* First use the buffer for the pointers, and sort the entries.
642 We'll write the pointers in the end of the buffer, and then
643 copy into the buffer from the beginning so the overlap works. */
644 assert (sizeof (Dwarf_Line) >= sizeof (Dwarf_Line *));
645 Dwarf_Line **sortlines = (buf + sizeof (Dwarf_Lines)
646 + ((sizeof (Dwarf_Line)
647 - sizeof (Dwarf_Line *)) * nlinelist));
648
649 /* The list is in LIFO order and usually they come in clumps with
650 ascending addresses. So fill from the back to probably start with
651 runs already in order before we sort. */
652 unsigned int i = nlinelist;
653 while (i-- > 0)
654 {
655 sortlines[i] = &linelist->line;
656 linelist = linelist->next;
657 }
658 assert (linelist == NULL);
659
660 /* Sort by ascending address. */
661 qsort (sortlines, nlinelist, sizeof sortlines[0], &compare_lines);
662
663 /* Now that they are sorted, put them in the final array.
664 The buffers overlap, so we've clobbered the early elements
665 of SORTLINES by the time we're reading the later ones. */
666 cu->lines = buf;
667 cu->lines->nlines = nlinelist;
668 for (i = 0; i < nlinelist; ++i)
669 {
670 cu->lines->info[i] = *sortlines[i];
671 cu->lines->info[i].files = files;
672 }
673
674 /* Success. */
675 res = 0;
676 }
677 else if (cu->lines != (void *) -1l)
678 /* We already have the information. */
679 res = 0;
680
681 if (likely (res == 0))
682 {
683 *lines = cu->lines;
684 *nlines = cu->lines->nlines;
685 }
686 out:
687
688 // XXX Eventually: unlocking here.
689
690 return res;
691}
692INTDEF(dwarf_getsrclines)