xref: /dflybsd-src/contrib/gdb-7/bfd/dwarf1.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
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