186d7f5d3SJohn Marino /* DWARF 1 find nearest line (_bfd_dwarf1_find_nearest_line).
286d7f5d3SJohn Marino Copyright 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2007, 2008, 2009, 2010
386d7f5d3SJohn Marino Free Software Foundation, Inc.
486d7f5d3SJohn Marino
586d7f5d3SJohn Marino Written by Gavin Romig-Koch of Cygnus Solutions (gavin@cygnus.com).
686d7f5d3SJohn Marino
786d7f5d3SJohn Marino This file is part of BFD.
886d7f5d3SJohn Marino
986d7f5d3SJohn Marino This program is free software; you can redistribute it and/or modify
1086d7f5d3SJohn Marino it under the terms of the GNU General Public License as published by
1186d7f5d3SJohn Marino the Free Software Foundation; either version 3 of the License, or (at
1286d7f5d3SJohn Marino your option) any later version.
1386d7f5d3SJohn Marino
1486d7f5d3SJohn Marino This program is distributed in the hope that it will be useful, but
1586d7f5d3SJohn Marino WITHOUT ANY WARRANTY; without even the implied warranty of
1686d7f5d3SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1786d7f5d3SJohn Marino General Public License for more details.
1886d7f5d3SJohn Marino
1986d7f5d3SJohn Marino You should have received a copy of the GNU General Public License
2086d7f5d3SJohn Marino along with this program; if not, write to the Free Software
2186d7f5d3SJohn Marino Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
2286d7f5d3SJohn Marino MA 02110-1301, USA. */
2386d7f5d3SJohn Marino
2486d7f5d3SJohn Marino #include "sysdep.h"
2586d7f5d3SJohn Marino #include "bfd.h"
2686d7f5d3SJohn Marino #include "libiberty.h"
2786d7f5d3SJohn Marino #include "libbfd.h"
2886d7f5d3SJohn Marino #include "elf-bfd.h"
2986d7f5d3SJohn Marino #include "elf/dwarf.h"
3086d7f5d3SJohn Marino
3186d7f5d3SJohn Marino /* dwarf1_debug is the starting point for all dwarf1 info. */
3286d7f5d3SJohn Marino
3386d7f5d3SJohn Marino struct dwarf1_debug
3486d7f5d3SJohn Marino {
3586d7f5d3SJohn Marino /* The bfd we are working with. */
3686d7f5d3SJohn Marino bfd* abfd;
3786d7f5d3SJohn Marino
3886d7f5d3SJohn Marino /* Pointer to the symbol table. */
3986d7f5d3SJohn Marino asymbol** syms;
4086d7f5d3SJohn Marino
4186d7f5d3SJohn Marino /* List of already parsed compilation units. */
4286d7f5d3SJohn Marino struct dwarf1_unit* lastUnit;
4386d7f5d3SJohn Marino
4486d7f5d3SJohn Marino /* The buffer for the .debug section.
4586d7f5d3SJohn Marino Zero indicates that the .debug section failed to load. */
4686d7f5d3SJohn Marino bfd_byte *debug_section;
4786d7f5d3SJohn Marino
4886d7f5d3SJohn Marino /* Pointer to the end of the .debug_info section memory buffer. */
4986d7f5d3SJohn Marino bfd_byte *debug_section_end;
5086d7f5d3SJohn Marino
5186d7f5d3SJohn Marino /* The buffer for the .line section. */
5286d7f5d3SJohn Marino bfd_byte *line_section;
5386d7f5d3SJohn Marino
5486d7f5d3SJohn Marino /* End of that buffer. */
5586d7f5d3SJohn Marino bfd_byte *line_section_end;
5686d7f5d3SJohn Marino
5786d7f5d3SJohn Marino /* The current or next unread die within the .debug section. */
5886d7f5d3SJohn Marino bfd_byte *currentDie;
5986d7f5d3SJohn Marino };
6086d7f5d3SJohn Marino
6186d7f5d3SJohn Marino /* One dwarf1_unit for each parsed compilation unit die. */
6286d7f5d3SJohn Marino
6386d7f5d3SJohn Marino struct dwarf1_unit
6486d7f5d3SJohn Marino {
6586d7f5d3SJohn Marino /* Linked starting from stash->lastUnit. */
6686d7f5d3SJohn Marino struct dwarf1_unit* prev;
6786d7f5d3SJohn Marino
6886d7f5d3SJohn Marino /* Name of the compilation unit. */
6986d7f5d3SJohn Marino char *name;
7086d7f5d3SJohn Marino
7186d7f5d3SJohn Marino /* The highest and lowest address used in the compilation unit. */
7286d7f5d3SJohn Marino unsigned long low_pc;
7386d7f5d3SJohn Marino unsigned long high_pc;
7486d7f5d3SJohn Marino
7586d7f5d3SJohn Marino /* Does this unit have a statement list? */
7686d7f5d3SJohn Marino int has_stmt_list;
7786d7f5d3SJohn Marino
7886d7f5d3SJohn Marino /* If any, the offset of the line number table in the .line section. */
7986d7f5d3SJohn Marino unsigned long stmt_list_offset;
8086d7f5d3SJohn Marino
8186d7f5d3SJohn Marino /* If non-zero, a pointer to the first child of this unit. */
8286d7f5d3SJohn Marino bfd_byte *first_child;
8386d7f5d3SJohn Marino
8486d7f5d3SJohn Marino /* How many line entries? */
8586d7f5d3SJohn Marino unsigned long line_count;
8686d7f5d3SJohn Marino
8786d7f5d3SJohn Marino /* The decoded line number table (line_count entries). */
8886d7f5d3SJohn Marino struct linenumber* linenumber_table;
8986d7f5d3SJohn Marino
9086d7f5d3SJohn Marino /* The list of functions in this unit. */
9186d7f5d3SJohn Marino struct dwarf1_func* func_list;
9286d7f5d3SJohn Marino };
9386d7f5d3SJohn Marino
9486d7f5d3SJohn Marino /* One dwarf1_func for each parsed function die. */
9586d7f5d3SJohn Marino
9686d7f5d3SJohn Marino struct dwarf1_func
9786d7f5d3SJohn Marino {
9886d7f5d3SJohn Marino /* Linked starting from aUnit->func_list. */
9986d7f5d3SJohn Marino struct dwarf1_func* prev;
10086d7f5d3SJohn Marino
10186d7f5d3SJohn Marino /* Name of function. */
10286d7f5d3SJohn Marino char* name;
10386d7f5d3SJohn Marino
10486d7f5d3SJohn Marino /* The highest and lowest address used in the compilation unit. */
10586d7f5d3SJohn Marino unsigned long low_pc;
10686d7f5d3SJohn Marino unsigned long high_pc;
10786d7f5d3SJohn Marino };
10886d7f5d3SJohn Marino
10986d7f5d3SJohn Marino /* Used to return info about a parsed die. */
11086d7f5d3SJohn Marino struct die_info
11186d7f5d3SJohn Marino {
11286d7f5d3SJohn Marino unsigned long length;
11386d7f5d3SJohn Marino unsigned long sibling;
11486d7f5d3SJohn Marino unsigned long low_pc;
11586d7f5d3SJohn Marino unsigned long high_pc;
11686d7f5d3SJohn Marino unsigned long stmt_list_offset;
11786d7f5d3SJohn Marino
11886d7f5d3SJohn Marino char* name;
11986d7f5d3SJohn Marino
12086d7f5d3SJohn Marino int has_stmt_list;
12186d7f5d3SJohn Marino
12286d7f5d3SJohn Marino unsigned short tag;
12386d7f5d3SJohn Marino };
12486d7f5d3SJohn Marino
12586d7f5d3SJohn Marino /* Parsed line number information. */
12686d7f5d3SJohn Marino struct linenumber
12786d7f5d3SJohn Marino {
12886d7f5d3SJohn Marino /* First address in the line. */
12986d7f5d3SJohn Marino unsigned long addr;
13086d7f5d3SJohn Marino
13186d7f5d3SJohn Marino /* The line number. */
13286d7f5d3SJohn Marino unsigned long linenumber;
13386d7f5d3SJohn Marino };
13486d7f5d3SJohn Marino
13586d7f5d3SJohn Marino /* Find the form of an attr, from the attr field. */
13686d7f5d3SJohn Marino #define FORM_FROM_ATTR(attr) ((attr) & 0xF) /* Implicitly specified. */
13786d7f5d3SJohn Marino
13886d7f5d3SJohn Marino /* Return a newly allocated dwarf1_unit. It should be cleared and
13986d7f5d3SJohn Marino then attached into the 'stash' at 'stash->lastUnit'. */
14086d7f5d3SJohn Marino
14186d7f5d3SJohn Marino static struct dwarf1_unit*
alloc_dwarf1_unit(struct dwarf1_debug * stash)14286d7f5d3SJohn Marino alloc_dwarf1_unit (struct dwarf1_debug* stash)
14386d7f5d3SJohn Marino {
14486d7f5d3SJohn Marino bfd_size_type amt = sizeof (struct dwarf1_unit);
14586d7f5d3SJohn Marino
14686d7f5d3SJohn Marino struct dwarf1_unit* x = (struct dwarf1_unit *) bfd_zalloc (stash->abfd, amt);
14786d7f5d3SJohn Marino if (x)
14886d7f5d3SJohn Marino {
14986d7f5d3SJohn Marino x->prev = stash->lastUnit;
15086d7f5d3SJohn Marino stash->lastUnit = x;
15186d7f5d3SJohn Marino }
15286d7f5d3SJohn Marino
15386d7f5d3SJohn Marino return x;
15486d7f5d3SJohn Marino }
15586d7f5d3SJohn Marino
15686d7f5d3SJohn Marino /* Return a newly allocated dwarf1_func. It must be cleared and
15786d7f5d3SJohn Marino attached into 'aUnit' at 'aUnit->func_list'. */
15886d7f5d3SJohn Marino
15986d7f5d3SJohn Marino static struct dwarf1_func *
alloc_dwarf1_func(struct dwarf1_debug * stash,struct dwarf1_unit * aUnit)16086d7f5d3SJohn Marino alloc_dwarf1_func (struct dwarf1_debug* stash, struct dwarf1_unit* aUnit)
16186d7f5d3SJohn Marino {
16286d7f5d3SJohn Marino bfd_size_type amt = sizeof (struct dwarf1_func);
16386d7f5d3SJohn Marino
16486d7f5d3SJohn Marino struct dwarf1_func* x = (struct dwarf1_func *) bfd_zalloc (stash->abfd, amt);
16586d7f5d3SJohn Marino if (x)
16686d7f5d3SJohn Marino {
16786d7f5d3SJohn Marino x->prev = aUnit->func_list;
16886d7f5d3SJohn Marino aUnit->func_list = x;
16986d7f5d3SJohn Marino }
17086d7f5d3SJohn Marino
17186d7f5d3SJohn Marino return x;
17286d7f5d3SJohn Marino }
17386d7f5d3SJohn Marino
17486d7f5d3SJohn Marino /* parse_die - parse a Dwarf1 die.
17586d7f5d3SJohn Marino Parse the die starting at 'aDiePtr' into 'aDieInfo'.
17686d7f5d3SJohn Marino 'abfd' must be the bfd from which the section that 'aDiePtr'
17786d7f5d3SJohn Marino points to was pulled from.
17886d7f5d3SJohn Marino
17986d7f5d3SJohn Marino Return FALSE if the die is invalidly formatted; TRUE otherwise. */
18086d7f5d3SJohn Marino
18186d7f5d3SJohn Marino static bfd_boolean
parse_die(bfd * abfd,struct die_info * aDieInfo,bfd_byte * aDiePtr,bfd_byte * aDiePtrEnd)18286d7f5d3SJohn Marino parse_die (bfd * abfd,
18386d7f5d3SJohn Marino struct die_info * aDieInfo,
18486d7f5d3SJohn Marino bfd_byte * aDiePtr,
18586d7f5d3SJohn Marino bfd_byte * aDiePtrEnd)
18686d7f5d3SJohn Marino {
18786d7f5d3SJohn Marino bfd_byte *this_die = aDiePtr;
18886d7f5d3SJohn Marino bfd_byte *xptr = this_die;
18986d7f5d3SJohn Marino
19086d7f5d3SJohn Marino memset (aDieInfo, 0, sizeof (* aDieInfo));
19186d7f5d3SJohn Marino
19286d7f5d3SJohn Marino /* First comes the length. */
19386d7f5d3SJohn Marino aDieInfo->length = bfd_get_32 (abfd, (bfd_byte *) xptr);
19486d7f5d3SJohn Marino xptr += 4;
19586d7f5d3SJohn Marino if (aDieInfo->length == 0
19686d7f5d3SJohn Marino || (this_die + aDieInfo->length) >= aDiePtrEnd)
19786d7f5d3SJohn Marino return FALSE;
19886d7f5d3SJohn Marino if (aDieInfo->length < 6)
19986d7f5d3SJohn Marino {
20086d7f5d3SJohn Marino /* Just padding bytes. */
20186d7f5d3SJohn Marino aDieInfo->tag = TAG_padding;
20286d7f5d3SJohn Marino return TRUE;
20386d7f5d3SJohn Marino }
20486d7f5d3SJohn Marino
20586d7f5d3SJohn Marino /* Then the tag. */
20686d7f5d3SJohn Marino aDieInfo->tag = bfd_get_16 (abfd, (bfd_byte *) xptr);
20786d7f5d3SJohn Marino xptr += 2;
20886d7f5d3SJohn Marino
20986d7f5d3SJohn Marino /* Then the attributes. */
21086d7f5d3SJohn Marino while (xptr < (this_die + aDieInfo->length))
21186d7f5d3SJohn Marino {
21286d7f5d3SJohn Marino unsigned short attr;
21386d7f5d3SJohn Marino
21486d7f5d3SJohn Marino /* Parse the attribute based on its form. This section
21586d7f5d3SJohn Marino must handle all dwarf1 forms, but need only handle the
21686d7f5d3SJohn Marino actual attributes that we care about. */
21786d7f5d3SJohn Marino attr = bfd_get_16 (abfd, (bfd_byte *) xptr);
21886d7f5d3SJohn Marino xptr += 2;
21986d7f5d3SJohn Marino
22086d7f5d3SJohn Marino switch (FORM_FROM_ATTR (attr))
22186d7f5d3SJohn Marino {
22286d7f5d3SJohn Marino case FORM_DATA2:
22386d7f5d3SJohn Marino xptr += 2;
22486d7f5d3SJohn Marino break;
22586d7f5d3SJohn Marino case FORM_DATA4:
22686d7f5d3SJohn Marino case FORM_REF:
22786d7f5d3SJohn Marino if (attr == AT_sibling)
22886d7f5d3SJohn Marino aDieInfo->sibling = bfd_get_32 (abfd, (bfd_byte *) xptr);
22986d7f5d3SJohn Marino else if (attr == AT_stmt_list)
23086d7f5d3SJohn Marino {
23186d7f5d3SJohn Marino aDieInfo->stmt_list_offset = bfd_get_32 (abfd, (bfd_byte *) xptr);
23286d7f5d3SJohn Marino aDieInfo->has_stmt_list = 1;
23386d7f5d3SJohn Marino }
23486d7f5d3SJohn Marino xptr += 4;
23586d7f5d3SJohn Marino break;
23686d7f5d3SJohn Marino case FORM_DATA8:
23786d7f5d3SJohn Marino xptr += 8;
23886d7f5d3SJohn Marino break;
23986d7f5d3SJohn Marino case FORM_ADDR:
24086d7f5d3SJohn Marino if (attr == AT_low_pc)
24186d7f5d3SJohn Marino aDieInfo->low_pc = bfd_get_32 (abfd, (bfd_byte *) xptr);
24286d7f5d3SJohn Marino else if (attr == AT_high_pc)
24386d7f5d3SJohn Marino aDieInfo->high_pc = bfd_get_32 (abfd, (bfd_byte *) xptr);
24486d7f5d3SJohn Marino xptr += 4;
24586d7f5d3SJohn Marino break;
24686d7f5d3SJohn Marino case FORM_BLOCK2:
24786d7f5d3SJohn Marino xptr += 2 + bfd_get_16 (abfd, (bfd_byte *) xptr);
24886d7f5d3SJohn Marino break;
24986d7f5d3SJohn Marino case FORM_BLOCK4:
25086d7f5d3SJohn Marino xptr += 4 + bfd_get_32 (abfd, (bfd_byte *) xptr);
25186d7f5d3SJohn Marino break;
25286d7f5d3SJohn Marino case FORM_STRING:
25386d7f5d3SJohn Marino if (attr == AT_name)
25486d7f5d3SJohn Marino aDieInfo->name = (char *) xptr;
25586d7f5d3SJohn Marino xptr += strlen ((char *) xptr) + 1;
25686d7f5d3SJohn Marino break;
25786d7f5d3SJohn Marino }
25886d7f5d3SJohn Marino }
25986d7f5d3SJohn Marino
26086d7f5d3SJohn Marino return TRUE;
26186d7f5d3SJohn Marino }
26286d7f5d3SJohn Marino
26386d7f5d3SJohn Marino /* Parse a dwarf1 line number table for 'aUnit->stmt_list_offset'
26486d7f5d3SJohn Marino into 'aUnit->linenumber_table'. Return FALSE if an error
26586d7f5d3SJohn Marino occurs; TRUE otherwise. */
26686d7f5d3SJohn Marino
26786d7f5d3SJohn Marino static bfd_boolean
parse_line_table(struct dwarf1_debug * stash,struct dwarf1_unit * aUnit)26886d7f5d3SJohn Marino parse_line_table (struct dwarf1_debug* stash, struct dwarf1_unit* aUnit)
26986d7f5d3SJohn Marino {
27086d7f5d3SJohn Marino bfd_byte *xptr;
27186d7f5d3SJohn Marino
27286d7f5d3SJohn Marino /* Load the ".line" section from the bfd if we haven't already. */
27386d7f5d3SJohn Marino if (stash->line_section == 0)
27486d7f5d3SJohn Marino {
27586d7f5d3SJohn Marino asection *msec;
27686d7f5d3SJohn Marino bfd_size_type size;
27786d7f5d3SJohn Marino
27886d7f5d3SJohn Marino msec = bfd_get_section_by_name (stash->abfd, ".line");
27986d7f5d3SJohn Marino if (! msec)
28086d7f5d3SJohn Marino return FALSE;
28186d7f5d3SJohn Marino
28286d7f5d3SJohn Marino size = msec->rawsize ? msec->rawsize : msec->size;
28386d7f5d3SJohn Marino stash->line_section
28486d7f5d3SJohn Marino = bfd_simple_get_relocated_section_contents
28586d7f5d3SJohn Marino (stash->abfd, msec, NULL, stash->syms);
28686d7f5d3SJohn Marino
28786d7f5d3SJohn Marino if (! stash->line_section)
28886d7f5d3SJohn Marino return FALSE;
28986d7f5d3SJohn Marino
29086d7f5d3SJohn Marino stash->line_section_end = stash->line_section + size;
29186d7f5d3SJohn Marino }
29286d7f5d3SJohn Marino
29386d7f5d3SJohn Marino xptr = stash->line_section + aUnit->stmt_list_offset;
29486d7f5d3SJohn Marino if (xptr < stash->line_section_end)
29586d7f5d3SJohn Marino {
29686d7f5d3SJohn Marino unsigned long eachLine;
29786d7f5d3SJohn Marino bfd_byte *tblend;
29886d7f5d3SJohn Marino unsigned long base;
29986d7f5d3SJohn Marino bfd_size_type amt;
30086d7f5d3SJohn Marino
30186d7f5d3SJohn Marino /* First comes the length. */
30286d7f5d3SJohn Marino tblend = bfd_get_32 (stash->abfd, (bfd_byte *) xptr) + xptr;
30386d7f5d3SJohn Marino xptr += 4;
30486d7f5d3SJohn Marino
30586d7f5d3SJohn Marino /* Then the base address for each address in the table. */
30686d7f5d3SJohn Marino base = bfd_get_32 (stash->abfd, (bfd_byte *) xptr);
30786d7f5d3SJohn Marino xptr += 4;
30886d7f5d3SJohn Marino
30986d7f5d3SJohn Marino /* How many line entrys?
31086d7f5d3SJohn Marino 10 = 4 (line number) + 2 (pos in line) + 4 (address in line). */
31186d7f5d3SJohn Marino aUnit->line_count = (tblend - xptr) / 10;
31286d7f5d3SJohn Marino
31386d7f5d3SJohn Marino /* Allocate an array for the entries. */
31486d7f5d3SJohn Marino amt = sizeof (struct linenumber) * aUnit->line_count;
31586d7f5d3SJohn Marino aUnit->linenumber_table = (struct linenumber *) bfd_alloc (stash->abfd,
31686d7f5d3SJohn Marino amt);
31786d7f5d3SJohn Marino if (!aUnit->linenumber_table)
31886d7f5d3SJohn Marino return FALSE;
31986d7f5d3SJohn Marino
32086d7f5d3SJohn Marino for (eachLine = 0; eachLine < aUnit->line_count; eachLine++)
32186d7f5d3SJohn Marino {
32286d7f5d3SJohn Marino /* A line number. */
32386d7f5d3SJohn Marino aUnit->linenumber_table[eachLine].linenumber
32486d7f5d3SJohn Marino = bfd_get_32 (stash->abfd, (bfd_byte *) xptr);
32586d7f5d3SJohn Marino xptr += 4;
32686d7f5d3SJohn Marino
32786d7f5d3SJohn Marino /* Skip the position within the line. */
32886d7f5d3SJohn Marino xptr += 2;
32986d7f5d3SJohn Marino
33086d7f5d3SJohn Marino /* And finally the address. */
33186d7f5d3SJohn Marino aUnit->linenumber_table[eachLine].addr
33286d7f5d3SJohn Marino = base + bfd_get_32 (stash->abfd, (bfd_byte *) xptr);
33386d7f5d3SJohn Marino xptr += 4;
33486d7f5d3SJohn Marino }
33586d7f5d3SJohn Marino }
33686d7f5d3SJohn Marino
33786d7f5d3SJohn Marino return TRUE;
33886d7f5d3SJohn Marino }
33986d7f5d3SJohn Marino
34086d7f5d3SJohn Marino /* Parse each function die in a compilation unit 'aUnit'.
34186d7f5d3SJohn Marino The first child die of 'aUnit' should be in 'aUnit->first_child',
34286d7f5d3SJohn Marino the result is placed in 'aUnit->func_list'.
34386d7f5d3SJohn Marino Return FALSE if error; TRUE otherwise. */
34486d7f5d3SJohn Marino
34586d7f5d3SJohn Marino static bfd_boolean
parse_functions_in_unit(struct dwarf1_debug * stash,struct dwarf1_unit * aUnit)34686d7f5d3SJohn Marino parse_functions_in_unit (struct dwarf1_debug* stash, struct dwarf1_unit* aUnit)
34786d7f5d3SJohn Marino {
34886d7f5d3SJohn Marino bfd_byte *eachDie;
34986d7f5d3SJohn Marino
35086d7f5d3SJohn Marino if (aUnit->first_child)
35186d7f5d3SJohn Marino for (eachDie = aUnit->first_child;
35286d7f5d3SJohn Marino eachDie < stash->debug_section_end;
35386d7f5d3SJohn Marino )
35486d7f5d3SJohn Marino {
35586d7f5d3SJohn Marino struct die_info eachDieInfo;
35686d7f5d3SJohn Marino
35786d7f5d3SJohn Marino if (! parse_die (stash->abfd, &eachDieInfo, eachDie,
35886d7f5d3SJohn Marino stash->debug_section_end))
35986d7f5d3SJohn Marino return FALSE;
36086d7f5d3SJohn Marino
36186d7f5d3SJohn Marino if (eachDieInfo.tag == TAG_global_subroutine
36286d7f5d3SJohn Marino || eachDieInfo.tag == TAG_subroutine
36386d7f5d3SJohn Marino || eachDieInfo.tag == TAG_inlined_subroutine
36486d7f5d3SJohn Marino || eachDieInfo.tag == TAG_entry_point)
36586d7f5d3SJohn Marino {
36686d7f5d3SJohn Marino struct dwarf1_func* aFunc = alloc_dwarf1_func (stash,aUnit);
36786d7f5d3SJohn Marino if (!aFunc)
36886d7f5d3SJohn Marino return FALSE;
36986d7f5d3SJohn Marino
37086d7f5d3SJohn Marino aFunc->name = eachDieInfo.name;
37186d7f5d3SJohn Marino aFunc->low_pc = eachDieInfo.low_pc;
37286d7f5d3SJohn Marino aFunc->high_pc = eachDieInfo.high_pc;
37386d7f5d3SJohn Marino }
37486d7f5d3SJohn Marino
37586d7f5d3SJohn Marino /* Move to next sibling, if none, end loop */
37686d7f5d3SJohn Marino if (eachDieInfo.sibling)
37786d7f5d3SJohn Marino eachDie = stash->debug_section + eachDieInfo.sibling;
37886d7f5d3SJohn Marino else
37986d7f5d3SJohn Marino break;
38086d7f5d3SJohn Marino }
38186d7f5d3SJohn Marino
38286d7f5d3SJohn Marino return TRUE;
38386d7f5d3SJohn Marino }
38486d7f5d3SJohn Marino
38586d7f5d3SJohn Marino /* Find the nearest line to 'addr' in 'aUnit'.
38686d7f5d3SJohn Marino Return whether we found the line (or a function) without error. */
38786d7f5d3SJohn Marino
38886d7f5d3SJohn Marino static bfd_boolean
dwarf1_unit_find_nearest_line(struct dwarf1_debug * stash,struct dwarf1_unit * aUnit,unsigned long addr,const char ** filename_ptr,const char ** functionname_ptr,unsigned int * linenumber_ptr)38986d7f5d3SJohn Marino dwarf1_unit_find_nearest_line (struct dwarf1_debug* stash,
39086d7f5d3SJohn Marino struct dwarf1_unit* aUnit,
39186d7f5d3SJohn Marino unsigned long addr,
39286d7f5d3SJohn Marino const char **filename_ptr,
39386d7f5d3SJohn Marino const char **functionname_ptr,
39486d7f5d3SJohn Marino unsigned int *linenumber_ptr)
39586d7f5d3SJohn Marino {
39686d7f5d3SJohn Marino int line_p = FALSE;
39786d7f5d3SJohn Marino int func_p = FALSE;
39886d7f5d3SJohn Marino
39986d7f5d3SJohn Marino if (aUnit->low_pc <= addr && addr < aUnit->high_pc)
40086d7f5d3SJohn Marino {
40186d7f5d3SJohn Marino if (aUnit->has_stmt_list)
40286d7f5d3SJohn Marino {
40386d7f5d3SJohn Marino unsigned long i;
40486d7f5d3SJohn Marino struct dwarf1_func* eachFunc;
40586d7f5d3SJohn Marino
40686d7f5d3SJohn Marino if (! aUnit->linenumber_table)
40786d7f5d3SJohn Marino {
40886d7f5d3SJohn Marino if (! parse_line_table (stash, aUnit))
40986d7f5d3SJohn Marino return FALSE;
41086d7f5d3SJohn Marino }
41186d7f5d3SJohn Marino
41286d7f5d3SJohn Marino if (! aUnit->func_list)
41386d7f5d3SJohn Marino {
41486d7f5d3SJohn Marino if (! parse_functions_in_unit (stash, aUnit))
41586d7f5d3SJohn Marino return FALSE;
41686d7f5d3SJohn Marino }
41786d7f5d3SJohn Marino
41886d7f5d3SJohn Marino for (i = 0; i < aUnit->line_count; i++)
41986d7f5d3SJohn Marino {
42086d7f5d3SJohn Marino if (aUnit->linenumber_table[i].addr <= addr
42186d7f5d3SJohn Marino && addr < aUnit->linenumber_table[i+1].addr)
42286d7f5d3SJohn Marino {
42386d7f5d3SJohn Marino *filename_ptr = aUnit->name;
42486d7f5d3SJohn Marino *linenumber_ptr = aUnit->linenumber_table[i].linenumber;
42586d7f5d3SJohn Marino line_p = TRUE;
42686d7f5d3SJohn Marino break;
42786d7f5d3SJohn Marino }
42886d7f5d3SJohn Marino }
42986d7f5d3SJohn Marino
43086d7f5d3SJohn Marino for (eachFunc = aUnit->func_list;
43186d7f5d3SJohn Marino eachFunc;
43286d7f5d3SJohn Marino eachFunc = eachFunc->prev)
43386d7f5d3SJohn Marino {
43486d7f5d3SJohn Marino if (eachFunc->low_pc <= addr
43586d7f5d3SJohn Marino && addr < eachFunc->high_pc)
43686d7f5d3SJohn Marino {
43786d7f5d3SJohn Marino *functionname_ptr = eachFunc->name;
43886d7f5d3SJohn Marino func_p = TRUE;
43986d7f5d3SJohn Marino break;
44086d7f5d3SJohn Marino }
44186d7f5d3SJohn Marino }
44286d7f5d3SJohn Marino }
44386d7f5d3SJohn Marino }
44486d7f5d3SJohn Marino
44586d7f5d3SJohn Marino return line_p || func_p;
44686d7f5d3SJohn Marino }
44786d7f5d3SJohn Marino
44886d7f5d3SJohn Marino /* The DWARF 1 version of find_nearest line.
44986d7f5d3SJohn Marino Return TRUE if the line is found without error. */
45086d7f5d3SJohn Marino
45186d7f5d3SJohn Marino bfd_boolean
_bfd_dwarf1_find_nearest_line(bfd * abfd,asection * section,asymbol ** symbols,bfd_vma offset,const char ** filename_ptr,const char ** functionname_ptr,unsigned int * linenumber_ptr)45286d7f5d3SJohn Marino _bfd_dwarf1_find_nearest_line (bfd *abfd,
45386d7f5d3SJohn Marino asection *section,
45486d7f5d3SJohn Marino asymbol **symbols,
45586d7f5d3SJohn Marino bfd_vma offset,
45686d7f5d3SJohn Marino const char **filename_ptr,
45786d7f5d3SJohn Marino const char **functionname_ptr,
45886d7f5d3SJohn Marino unsigned int *linenumber_ptr)
45986d7f5d3SJohn Marino {
46086d7f5d3SJohn Marino struct dwarf1_debug *stash = elf_tdata (abfd)->dwarf1_find_line_info;
46186d7f5d3SJohn Marino
46286d7f5d3SJohn Marino struct dwarf1_unit* eachUnit;
46386d7f5d3SJohn Marino
46486d7f5d3SJohn Marino /* What address are we looking for? */
46586d7f5d3SJohn Marino unsigned long addr = (unsigned long)(offset + section->vma);
46686d7f5d3SJohn Marino
46786d7f5d3SJohn Marino *filename_ptr = NULL;
46886d7f5d3SJohn Marino *functionname_ptr = NULL;
46986d7f5d3SJohn Marino *linenumber_ptr = 0;
47086d7f5d3SJohn Marino
47186d7f5d3SJohn Marino if (! stash)
47286d7f5d3SJohn Marino {
47386d7f5d3SJohn Marino asection *msec;
47486d7f5d3SJohn Marino bfd_size_type size = sizeof (struct dwarf1_debug);
47586d7f5d3SJohn Marino
47686d7f5d3SJohn Marino stash = elf_tdata (abfd)->dwarf1_find_line_info
47786d7f5d3SJohn Marino = (struct dwarf1_debug *) bfd_zalloc (abfd, size);
47886d7f5d3SJohn Marino
47986d7f5d3SJohn Marino if (! stash)
48086d7f5d3SJohn Marino return FALSE;
48186d7f5d3SJohn Marino
48286d7f5d3SJohn Marino msec = bfd_get_section_by_name (abfd, ".debug");
48386d7f5d3SJohn Marino if (! msec)
48486d7f5d3SJohn Marino /* No dwarf1 info. Note that at this point the stash
48586d7f5d3SJohn Marino has been allocated, but contains zeros, this lets
48686d7f5d3SJohn Marino future calls to this function fail quicker. */
48786d7f5d3SJohn Marino return FALSE;
48886d7f5d3SJohn Marino
48986d7f5d3SJohn Marino size = msec->rawsize ? msec->rawsize : msec->size;
49086d7f5d3SJohn Marino stash->debug_section
49186d7f5d3SJohn Marino = bfd_simple_get_relocated_section_contents (abfd, msec, NULL,
49286d7f5d3SJohn Marino symbols);
49386d7f5d3SJohn Marino
49486d7f5d3SJohn Marino if (! stash->debug_section)
49586d7f5d3SJohn Marino return FALSE;
49686d7f5d3SJohn Marino
49786d7f5d3SJohn Marino stash->debug_section_end = stash->debug_section + size;
49886d7f5d3SJohn Marino stash->currentDie = stash->debug_section;
49986d7f5d3SJohn Marino stash->abfd = abfd;
50086d7f5d3SJohn Marino stash->syms = symbols;
50186d7f5d3SJohn Marino }
50286d7f5d3SJohn Marino
50386d7f5d3SJohn Marino /* A null debug_section indicates that there was no dwarf1 info
50486d7f5d3SJohn Marino or that an error occured while setting up the stash. */
50586d7f5d3SJohn Marino
50686d7f5d3SJohn Marino if (! stash->debug_section)
50786d7f5d3SJohn Marino return FALSE;
50886d7f5d3SJohn Marino
50986d7f5d3SJohn Marino /* Look at the previously parsed units to see if any contain
51086d7f5d3SJohn Marino the addr. */
51186d7f5d3SJohn Marino for (eachUnit = stash->lastUnit; eachUnit; eachUnit = eachUnit->prev)
51286d7f5d3SJohn Marino if (eachUnit->low_pc <= addr && addr < eachUnit->high_pc)
51386d7f5d3SJohn Marino return dwarf1_unit_find_nearest_line (stash, eachUnit, addr,
51486d7f5d3SJohn Marino filename_ptr,
51586d7f5d3SJohn Marino functionname_ptr,
51686d7f5d3SJohn Marino linenumber_ptr);
51786d7f5d3SJohn Marino
51886d7f5d3SJohn Marino while (stash->currentDie < stash->debug_section_end)
51986d7f5d3SJohn Marino {
52086d7f5d3SJohn Marino struct die_info aDieInfo;
52186d7f5d3SJohn Marino
52286d7f5d3SJohn Marino if (! parse_die (stash->abfd, &aDieInfo, stash->currentDie,
52386d7f5d3SJohn Marino stash->debug_section_end))
52486d7f5d3SJohn Marino return FALSE;
52586d7f5d3SJohn Marino
52686d7f5d3SJohn Marino if (aDieInfo.tag == TAG_compile_unit)
52786d7f5d3SJohn Marino {
52886d7f5d3SJohn Marino struct dwarf1_unit* aUnit
52986d7f5d3SJohn Marino = alloc_dwarf1_unit (stash);
53086d7f5d3SJohn Marino if (!aUnit)
53186d7f5d3SJohn Marino return FALSE;
53286d7f5d3SJohn Marino
53386d7f5d3SJohn Marino aUnit->name = aDieInfo.name;
53486d7f5d3SJohn Marino aUnit->low_pc = aDieInfo.low_pc;
53586d7f5d3SJohn Marino aUnit->high_pc = aDieInfo.high_pc;
53686d7f5d3SJohn Marino aUnit->has_stmt_list = aDieInfo.has_stmt_list;
53786d7f5d3SJohn Marino aUnit->stmt_list_offset = aDieInfo.stmt_list_offset;
53886d7f5d3SJohn Marino
53986d7f5d3SJohn Marino /* A die has a child if it's followed by a die that is
54086d7f5d3SJohn Marino not it's sibling. */
54186d7f5d3SJohn Marino if (aDieInfo.sibling
54286d7f5d3SJohn Marino && stash->currentDie + aDieInfo.length
54386d7f5d3SJohn Marino < stash->debug_section_end
54486d7f5d3SJohn Marino && stash->currentDie + aDieInfo.length
54586d7f5d3SJohn Marino != stash->debug_section + aDieInfo.sibling)
54686d7f5d3SJohn Marino aUnit->first_child = stash->currentDie + aDieInfo.length;
54786d7f5d3SJohn Marino else
54886d7f5d3SJohn Marino aUnit->first_child = 0;
54986d7f5d3SJohn Marino
55086d7f5d3SJohn Marino if (aUnit->low_pc <= addr && addr < aUnit->high_pc)
55186d7f5d3SJohn Marino return dwarf1_unit_find_nearest_line (stash, aUnit, addr,
55286d7f5d3SJohn Marino filename_ptr,
55386d7f5d3SJohn Marino functionname_ptr,
55486d7f5d3SJohn Marino linenumber_ptr);
55586d7f5d3SJohn Marino }
55686d7f5d3SJohn Marino
55786d7f5d3SJohn Marino if (aDieInfo.sibling != 0)
55886d7f5d3SJohn Marino stash->currentDie = stash->debug_section + aDieInfo.sibling;
55986d7f5d3SJohn Marino else
56086d7f5d3SJohn Marino stash->currentDie += aDieInfo.length;
56186d7f5d3SJohn Marino }
56286d7f5d3SJohn Marino
56386d7f5d3SJohn Marino return FALSE;
56486d7f5d3SJohn Marino }
565