xref: /openbsd-src/gnu/usr.bin/binutils/bfd/dwarf1.c (revision d2201f2f89f0be1a0be6f7568000ed297414a06d)
1f7cc78ecSespie /* DWARF 1 find nearest line (_bfd_dwarf1_find_nearest_line).
2*d2201f2fSdrahn    Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3f7cc78ecSespie 
4f7cc78ecSespie Written by Gavin Romig-Koch of Cygnus Solutions (gavin@cygnus.com).
5f7cc78ecSespie 
6f7cc78ecSespie This file is part of BFD.
7f7cc78ecSespie 
8f7cc78ecSespie This program is free software; you can redistribute it and/or modify
9f7cc78ecSespie it under the terms of the GNU General Public License as published by
10f7cc78ecSespie the Free Software Foundation; either version 2 of the License, or (at
11f7cc78ecSespie your option) any later version.
12f7cc78ecSespie 
13f7cc78ecSespie This program is distributed in the hope that it will be useful, but
14f7cc78ecSespie WITHOUT ANY WARRANTY; without even the implied warranty of
15f7cc78ecSespie MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16f7cc78ecSespie General Public License for more details.
17f7cc78ecSespie 
18f7cc78ecSespie You should have received a copy of the GNU General Public License
19f7cc78ecSespie along with this program; if not, write to the Free Software
20f7cc78ecSespie Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
21f7cc78ecSespie 
22f7cc78ecSespie #include "bfd.h"
23f7cc78ecSespie #include "sysdep.h"
24f7cc78ecSespie #include "libiberty.h"
25f7cc78ecSespie #include "libbfd.h"
26f7cc78ecSespie #include "elf-bfd.h"
27f7cc78ecSespie #include "elf/dwarf.h"
28f7cc78ecSespie 
29f7cc78ecSespie /* dwarf1_debug is the starting point for all dwarf1 info.  */
30f7cc78ecSespie 
31f7cc78ecSespie struct dwarf1_debug {
32f7cc78ecSespie 
33f7cc78ecSespie   /* The bfd we are working with.  */
34f7cc78ecSespie   bfd* abfd;
35f7cc78ecSespie 
36f7cc78ecSespie   /* List of already parsed compilation units.  */
37f7cc78ecSespie   struct dwarf1_unit* lastUnit;
38f7cc78ecSespie 
39f7cc78ecSespie   /* The buffer for the .debug section.
40f7cc78ecSespie      Zero indicates that the .debug section failed to load.  */
41f7cc78ecSespie   char* debug_section;
42f7cc78ecSespie 
43f7cc78ecSespie   /* Pointer to the end of the .debug_info section memory buffer.  */
44f7cc78ecSespie   char* debug_section_end;
45f7cc78ecSespie 
46f7cc78ecSespie   /* The buffer for the .line section.  */
47f7cc78ecSespie   char* line_section;
48f7cc78ecSespie 
49f7cc78ecSespie   /* End of that buffer.  */
50f7cc78ecSespie   char* line_section_end;
51f7cc78ecSespie 
52f7cc78ecSespie   /* The current or next unread die within the .debug section.  */
53f7cc78ecSespie   char* currentDie;
54f7cc78ecSespie };
55f7cc78ecSespie 
56f7cc78ecSespie /* One dwarf1_unit for each parsed compilation unit die.  */
57f7cc78ecSespie 
58f7cc78ecSespie struct dwarf1_unit {
59f7cc78ecSespie   /* Linked starting from stash->lastUnit.  */
60f7cc78ecSespie   struct dwarf1_unit* prev;
61f7cc78ecSespie 
62f7cc78ecSespie   /* Name of the compilation unit.  */
63f7cc78ecSespie   char* name;
64f7cc78ecSespie 
65f7cc78ecSespie   /* The highest and lowest address used in the compilation unit.  */
66f7cc78ecSespie   unsigned long low_pc;
67f7cc78ecSespie   unsigned long high_pc;
68f7cc78ecSespie 
69f7cc78ecSespie   /* Does this unit have a statement list? */
70f7cc78ecSespie   int has_stmt_list;
71f7cc78ecSespie 
72f7cc78ecSespie   /* If any, the offset of the line number table in the .line section.  */
73f7cc78ecSespie   unsigned long stmt_list_offset;
74f7cc78ecSespie 
75f7cc78ecSespie   /* If non-zero, a pointer to the first child of this unit.  */
76f7cc78ecSespie   char* first_child;
77f7cc78ecSespie 
78f7cc78ecSespie   /* How many line entries? */
79f7cc78ecSespie   unsigned long line_count;
80f7cc78ecSespie 
81f7cc78ecSespie   /* The decoded line number table (line_count entries).  */
82f7cc78ecSespie   struct linenumber* linenumber_table;
83f7cc78ecSespie 
84f7cc78ecSespie   /* The list of functions in this unit.  */
85f7cc78ecSespie   struct dwarf1_func* func_list;
86f7cc78ecSespie };
87f7cc78ecSespie 
88f7cc78ecSespie /* One dwarf1_func for each parsed function die.  */
89f7cc78ecSespie 
90f7cc78ecSespie struct dwarf1_func {
91f7cc78ecSespie   /* Linked starting from aUnit->func_list.  */
92f7cc78ecSespie   struct dwarf1_func* prev;
93f7cc78ecSespie 
94f7cc78ecSespie   /* Name of function.  */
95f7cc78ecSespie   char* name;
96f7cc78ecSespie 
97f7cc78ecSespie   /* The highest and lowest address used in the compilation unit.  */
98f7cc78ecSespie   unsigned long low_pc;
99f7cc78ecSespie   unsigned long high_pc;
100f7cc78ecSespie };
101f7cc78ecSespie 
102f7cc78ecSespie /* Used to return info about a parsed die.  */
103f7cc78ecSespie struct die_info {
104f7cc78ecSespie   unsigned long length;
105f7cc78ecSespie   unsigned long sibling;
106f7cc78ecSespie   unsigned long low_pc;
107f7cc78ecSespie   unsigned long high_pc;
108f7cc78ecSespie   unsigned long stmt_list_offset;
109f7cc78ecSespie 
110f7cc78ecSespie   char* name;
111f7cc78ecSespie 
112f7cc78ecSespie   int has_stmt_list;
113f7cc78ecSespie 
114f7cc78ecSespie   unsigned short tag;
115f7cc78ecSespie };
116f7cc78ecSespie 
117f7cc78ecSespie /* Parsed line number information.  */
118f7cc78ecSespie struct linenumber {
119f7cc78ecSespie   /* First address in the line.  */
120f7cc78ecSespie   unsigned long addr;
121f7cc78ecSespie 
122f7cc78ecSespie   /* The line number.  */
123f7cc78ecSespie   unsigned long linenumber;
124f7cc78ecSespie };
125f7cc78ecSespie 
126f7cc78ecSespie /* Find the form of an attr, from the attr field.  */
127f7cc78ecSespie #define FORM_FROM_ATTR(attr)	((attr) & 0xF)	/* Implicitly specified */
128f7cc78ecSespie 
129*d2201f2fSdrahn static struct dwarf1_unit *alloc_dwarf1_unit
130*d2201f2fSdrahn   PARAMS ((struct dwarf1_debug *));
131*d2201f2fSdrahn static struct dwarf1_func *alloc_dwarf1_func
132*d2201f2fSdrahn   PARAMS ((struct dwarf1_debug *, struct dwarf1_unit *));
133*d2201f2fSdrahn static bfd_boolean parse_die
134*d2201f2fSdrahn   PARAMS ((bfd *, struct die_info *, char *, char *));
135*d2201f2fSdrahn static bfd_boolean parse_line_table
136*d2201f2fSdrahn   PARAMS ((struct dwarf1_debug *, struct dwarf1_unit *));
137*d2201f2fSdrahn static bfd_boolean parse_functions_in_unit
138*d2201f2fSdrahn   PARAMS ((struct dwarf1_debug *, struct dwarf1_unit *));
139*d2201f2fSdrahn static bfd_boolean dwarf1_unit_find_nearest_line
140*d2201f2fSdrahn   PARAMS ((struct dwarf1_debug *, struct dwarf1_unit *, unsigned long,
141*d2201f2fSdrahn 	   const char **, const char **, unsigned int *));
142*d2201f2fSdrahn 
143f7cc78ecSespie /* Return a newly allocated dwarf1_unit.  It should be cleared and
144f7cc78ecSespie    then attached into the 'stash' at 'stash->lastUnit'.  */
145f7cc78ecSespie 
146f7cc78ecSespie static struct dwarf1_unit*
alloc_dwarf1_unit(stash)147f7cc78ecSespie alloc_dwarf1_unit (stash)
148f7cc78ecSespie   struct dwarf1_debug* stash;
149f7cc78ecSespie {
150*d2201f2fSdrahn   bfd_size_type amt = sizeof (struct dwarf1_unit);
151*d2201f2fSdrahn 
152*d2201f2fSdrahn   struct dwarf1_unit* x = (struct dwarf1_unit*) bfd_zalloc (stash->abfd, amt);
153f7cc78ecSespie   x->prev = stash->lastUnit;
154f7cc78ecSespie   stash->lastUnit = x;
155f7cc78ecSespie 
156f7cc78ecSespie   return x;
157f7cc78ecSespie }
158f7cc78ecSespie 
159f7cc78ecSespie /* Return a newly allocated dwarf1_func.  It must be cleared and
160f7cc78ecSespie    attached into 'aUnit' at 'aUnit->func_list'.  */
161f7cc78ecSespie 
162f7cc78ecSespie static struct dwarf1_func*
alloc_dwarf1_func(stash,aUnit)163f7cc78ecSespie alloc_dwarf1_func (stash, aUnit)
164f7cc78ecSespie      struct dwarf1_debug* stash;
165f7cc78ecSespie      struct dwarf1_unit* aUnit;
166f7cc78ecSespie {
167*d2201f2fSdrahn   bfd_size_type amt = sizeof (struct dwarf1_func);
168*d2201f2fSdrahn 
169*d2201f2fSdrahn   struct dwarf1_func* x = (struct dwarf1_func*) bfd_zalloc (stash->abfd, amt);
170f7cc78ecSespie   x->prev = aUnit->func_list;
171f7cc78ecSespie   aUnit->func_list = x;
172f7cc78ecSespie 
173f7cc78ecSespie   return x;
174f7cc78ecSespie }
175f7cc78ecSespie 
176f7cc78ecSespie /* parse_die - parse a Dwarf1 die.
177f7cc78ecSespie    Parse the die starting at 'aDiePtr' into 'aDieInfo'.
178f7cc78ecSespie    'abfd' must be the bfd from which the section that 'aDiePtr'
179f7cc78ecSespie    points to was pulled from.
180f7cc78ecSespie 
181*d2201f2fSdrahn    Return FALSE if the die is invalidly formatted; TRUE otherwise.  */
182f7cc78ecSespie 
183*d2201f2fSdrahn static bfd_boolean
parse_die(abfd,aDieInfo,aDiePtr,aDiePtrEnd)184*d2201f2fSdrahn parse_die (abfd, aDieInfo, aDiePtr, aDiePtrEnd)
185f7cc78ecSespie      bfd* abfd;
186f7cc78ecSespie      struct die_info* aDieInfo;
187f7cc78ecSespie      char*            aDiePtr;
188*d2201f2fSdrahn      char*            aDiePtrEnd;
189f7cc78ecSespie {
190f7cc78ecSespie   char* this_die = aDiePtr;
191f7cc78ecSespie   char* xptr = this_die;
192f7cc78ecSespie 
193f7cc78ecSespie   memset (aDieInfo,0,sizeof (*aDieInfo));
194f7cc78ecSespie 
195f7cc78ecSespie   /* First comes the length.  */
1965f210c2aSfgsch   aDieInfo->length = bfd_get_32 (abfd, (bfd_byte *) xptr);
197f7cc78ecSespie   xptr += 4;
198*d2201f2fSdrahn   if (aDieInfo->length == 0
199*d2201f2fSdrahn       || (this_die + aDieInfo->length) >= aDiePtrEnd)
200*d2201f2fSdrahn     return FALSE;
201f7cc78ecSespie   if (aDieInfo->length < 6)
202f7cc78ecSespie     {
203f7cc78ecSespie       /* Just padding bytes.  */
204f7cc78ecSespie       aDieInfo->tag = TAG_padding;
205*d2201f2fSdrahn       return TRUE;
206f7cc78ecSespie     }
207f7cc78ecSespie 
208f7cc78ecSespie   /* Then the tag.  */
2095f210c2aSfgsch   aDieInfo->tag = bfd_get_16 (abfd, (bfd_byte *) xptr);
210f7cc78ecSespie   xptr += 2;
211f7cc78ecSespie 
212f7cc78ecSespie   /* Then the attributes.  */
213f7cc78ecSespie   while (xptr < (this_die + aDieInfo->length))
214f7cc78ecSespie     {
215f7cc78ecSespie       unsigned short attr;
216f7cc78ecSespie 
217f7cc78ecSespie       /* Parse the attribute based on its form.  This section
218f7cc78ecSespie          must handle all dwarf1 forms, but need only handle the
219f7cc78ecSespie 	 actual attributes that we care about.  */
220f7cc78ecSespie 
2215f210c2aSfgsch       attr = bfd_get_16 (abfd, (bfd_byte *) xptr);
222f7cc78ecSespie       xptr += 2;
223f7cc78ecSespie 
224f7cc78ecSespie       switch (FORM_FROM_ATTR (attr))
225f7cc78ecSespie 	{
226f7cc78ecSespie 	case FORM_DATA2:
227f7cc78ecSespie 	  xptr += 2;
228f7cc78ecSespie 	  break;
229f7cc78ecSespie 	case FORM_DATA4:
230f7cc78ecSespie 	case FORM_REF:
231f7cc78ecSespie 	  if (attr == AT_sibling)
2325f210c2aSfgsch 	    aDieInfo->sibling = bfd_get_32 (abfd, (bfd_byte *) xptr);
233f7cc78ecSespie 	  else if (attr == AT_stmt_list)
234f7cc78ecSespie 	    {
2355f210c2aSfgsch 	      aDieInfo->stmt_list_offset = bfd_get_32 (abfd, (bfd_byte *) xptr);
236f7cc78ecSespie 	      aDieInfo->has_stmt_list = 1;
237f7cc78ecSespie 	    }
238f7cc78ecSespie 	  xptr += 4;
239f7cc78ecSespie 	  break;
240f7cc78ecSespie 	case FORM_DATA8:
241f7cc78ecSespie 	  xptr += 8;
242f7cc78ecSespie 	  break;
243f7cc78ecSespie 	case FORM_ADDR:
244f7cc78ecSespie 	  if (attr == AT_low_pc)
2455f210c2aSfgsch 	    aDieInfo->low_pc = bfd_get_32 (abfd, (bfd_byte *) xptr);
246f7cc78ecSespie 	  else if (attr == AT_high_pc)
2475f210c2aSfgsch 	    aDieInfo->high_pc = bfd_get_32 (abfd, (bfd_byte *) xptr);
248f7cc78ecSespie 	  xptr += 4;
249f7cc78ecSespie 	  break;
250f7cc78ecSespie 	case FORM_BLOCK2:
2515f210c2aSfgsch 	  xptr += 2 + bfd_get_16 (abfd, (bfd_byte *) xptr);
252f7cc78ecSespie 	  break;
253f7cc78ecSespie 	case FORM_BLOCK4:
2545f210c2aSfgsch 	  xptr += 4 + bfd_get_32 (abfd, (bfd_byte *) xptr);
255f7cc78ecSespie 	  break;
256f7cc78ecSespie 	case FORM_STRING:
257f7cc78ecSespie 	  if (attr == AT_name)
258f7cc78ecSespie 	    aDieInfo->name = xptr;
259f7cc78ecSespie 	  xptr += strlen (xptr) + 1;
260f7cc78ecSespie 	  break;
261f7cc78ecSespie 	}
262f7cc78ecSespie     }
263f7cc78ecSespie 
264*d2201f2fSdrahn   return TRUE;
265f7cc78ecSespie }
266f7cc78ecSespie 
267f7cc78ecSespie /* Parse a dwarf1 line number table for 'aUnit->stmt_list_offset'
268*d2201f2fSdrahn    into 'aUnit->linenumber_table'.  Return FALSE if an error
269*d2201f2fSdrahn    occurs; TRUE otherwise.  */
270f7cc78ecSespie 
271*d2201f2fSdrahn static bfd_boolean
parse_line_table(stash,aUnit)272f7cc78ecSespie parse_line_table (stash, aUnit)
273f7cc78ecSespie   struct dwarf1_debug* stash;
274f7cc78ecSespie   struct dwarf1_unit* aUnit;
275f7cc78ecSespie {
276f7cc78ecSespie   char* xptr;
277f7cc78ecSespie 
278f7cc78ecSespie   /* Load the ".line" section from the bfd if we haven't already.  */
279f7cc78ecSespie   if (stash->line_section == 0)
280f7cc78ecSespie     {
281f7cc78ecSespie       asection *msec;
282*d2201f2fSdrahn       bfd_size_type size;
283f7cc78ecSespie 
284f7cc78ecSespie       msec = bfd_get_section_by_name (stash->abfd, ".line");
285f7cc78ecSespie       if (! msec)
286*d2201f2fSdrahn 	return FALSE;
287f7cc78ecSespie 
288f7cc78ecSespie       size = bfd_get_section_size_before_reloc (msec);
2895f210c2aSfgsch       stash->line_section = (char *) bfd_alloc (stash->abfd, size);
290f7cc78ecSespie 
291f7cc78ecSespie       if (! stash->line_section)
292*d2201f2fSdrahn 	return FALSE;
293f7cc78ecSespie 
294*d2201f2fSdrahn       if (! bfd_get_section_contents (stash->abfd, msec, stash->line_section,
295*d2201f2fSdrahn 				      (bfd_vma) 0, size))
296f7cc78ecSespie 	{
297f7cc78ecSespie 	  stash->line_section = 0;
298*d2201f2fSdrahn 	  return FALSE;
299f7cc78ecSespie 	}
300f7cc78ecSespie 
301f7cc78ecSespie       stash->line_section_end = stash->line_section + size;
302f7cc78ecSespie     }
303f7cc78ecSespie 
304f7cc78ecSespie   xptr = stash->line_section + aUnit->stmt_list_offset;
305f7cc78ecSespie   if (xptr < stash->line_section_end)
306f7cc78ecSespie     {
307f7cc78ecSespie       unsigned long eachLine;
308f7cc78ecSespie       char *tblend;
309f7cc78ecSespie       unsigned long base;
310*d2201f2fSdrahn       bfd_size_type amt;
311f7cc78ecSespie 
312f7cc78ecSespie       /* First comes the length.  */
3135f210c2aSfgsch       tblend = bfd_get_32 (stash->abfd, (bfd_byte *) xptr) + xptr;
314f7cc78ecSespie       xptr += 4;
315f7cc78ecSespie 
316f7cc78ecSespie       /* Then the base address for each address in the table.  */
3175f210c2aSfgsch       base = bfd_get_32 (stash->abfd, (bfd_byte *) xptr);
318f7cc78ecSespie       xptr += 4;
319f7cc78ecSespie 
320f7cc78ecSespie       /* How many line entrys?
321f7cc78ecSespie 	 10 = 4 (line number) + 2 (pos in line) + 4 (address in line) */
322f7cc78ecSespie       aUnit->line_count = (tblend - xptr) / 10;
323f7cc78ecSespie 
324f7cc78ecSespie       /* Allocate an array for the entries.  */
325*d2201f2fSdrahn       amt = sizeof (struct linenumber) * aUnit->line_count;
326*d2201f2fSdrahn       aUnit->linenumber_table = ((struct linenumber *)
327*d2201f2fSdrahn 				 bfd_alloc (stash->abfd, amt));
328f7cc78ecSespie 
329f7cc78ecSespie       for (eachLine = 0; eachLine < aUnit->line_count; eachLine++)
330f7cc78ecSespie 	{
331f7cc78ecSespie 	  /* A line number.  */
332f7cc78ecSespie 	  aUnit->linenumber_table[eachLine].linenumber
3335f210c2aSfgsch 	    = bfd_get_32 (stash->abfd, (bfd_byte *) xptr);
334f7cc78ecSespie 	  xptr += 4;
335f7cc78ecSespie 
336f7cc78ecSespie 	  /* Skip the position within the line.  */
337f7cc78ecSespie 	  xptr += 2;
338f7cc78ecSespie 
339f7cc78ecSespie 	  /* And finally the address.  */
340f7cc78ecSespie 	  aUnit->linenumber_table[eachLine].addr
3415f210c2aSfgsch 	    = base + bfd_get_32 (stash->abfd, (bfd_byte *) xptr);
342f7cc78ecSespie 	  xptr += 4;
343f7cc78ecSespie 	}
344f7cc78ecSespie     }
345f7cc78ecSespie 
346*d2201f2fSdrahn   return TRUE;
347f7cc78ecSespie }
348f7cc78ecSespie 
349f7cc78ecSespie /* Parse each function die in a compilation unit 'aUnit'.
350f7cc78ecSespie    The first child die of 'aUnit' should be in 'aUnit->first_child',
351f7cc78ecSespie    the result is placed in 'aUnit->func_list'.
352*d2201f2fSdrahn    Return FALSE if error; TRUE otherwise.  */
353f7cc78ecSespie 
354*d2201f2fSdrahn static bfd_boolean
parse_functions_in_unit(stash,aUnit)355f7cc78ecSespie parse_functions_in_unit (stash, aUnit)
356f7cc78ecSespie      struct dwarf1_debug* stash;
357f7cc78ecSespie      struct dwarf1_unit* aUnit;
358f7cc78ecSespie {
359f7cc78ecSespie   char* eachDie;
360f7cc78ecSespie 
361f7cc78ecSespie   if (aUnit->first_child)
362f7cc78ecSespie     for (eachDie = aUnit->first_child;
363f7cc78ecSespie 	 eachDie < stash->debug_section_end;
364f7cc78ecSespie 	 )
365f7cc78ecSespie       {
366f7cc78ecSespie 	struct die_info eachDieInfo;
367f7cc78ecSespie 
368*d2201f2fSdrahn 	if (! parse_die (stash->abfd, &eachDieInfo, eachDie,
369*d2201f2fSdrahn 			 stash->debug_section_end))
370*d2201f2fSdrahn 	  return FALSE;
371f7cc78ecSespie 
372f7cc78ecSespie 	if (eachDieInfo.tag == TAG_global_subroutine
373f7cc78ecSespie 	    || eachDieInfo.tag == TAG_subroutine
374f7cc78ecSespie 	    || eachDieInfo.tag == TAG_inlined_subroutine
375f7cc78ecSespie 	    || eachDieInfo.tag == TAG_entry_point)
376f7cc78ecSespie 	  {
377f7cc78ecSespie 	    struct dwarf1_func* aFunc = alloc_dwarf1_func (stash,aUnit);
378f7cc78ecSespie 
379f7cc78ecSespie 	    aFunc->name = eachDieInfo.name;
380f7cc78ecSespie 	    aFunc->low_pc = eachDieInfo.low_pc;
381f7cc78ecSespie 	    aFunc->high_pc = eachDieInfo.high_pc;
382f7cc78ecSespie 	  }
383f7cc78ecSespie 
384f7cc78ecSespie 	/* Move to next sibling, if none, end loop */
385f7cc78ecSespie 	if (eachDieInfo.sibling)
386f7cc78ecSespie 	  eachDie = stash->debug_section + eachDieInfo.sibling;
387f7cc78ecSespie 	else
388f7cc78ecSespie 	  break;
389f7cc78ecSespie       }
390f7cc78ecSespie 
391*d2201f2fSdrahn   return TRUE;
392f7cc78ecSespie }
393f7cc78ecSespie 
394f7cc78ecSespie /* Find the nearest line to 'addr' in 'aUnit'.
395f7cc78ecSespie    Return whether we found the line (or a function) without error.  */
396f7cc78ecSespie 
397*d2201f2fSdrahn static bfd_boolean
dwarf1_unit_find_nearest_line(stash,aUnit,addr,filename_ptr,functionname_ptr,linenumber_ptr)398f7cc78ecSespie dwarf1_unit_find_nearest_line (stash, aUnit, addr,
399f7cc78ecSespie 		       filename_ptr, functionname_ptr,
400f7cc78ecSespie 		       linenumber_ptr)
401f7cc78ecSespie   struct dwarf1_debug* stash;
402f7cc78ecSespie   struct dwarf1_unit* aUnit;
403f7cc78ecSespie   unsigned long addr;
404f7cc78ecSespie   const char **filename_ptr;
405f7cc78ecSespie   const char **functionname_ptr;
406f7cc78ecSespie   unsigned int *linenumber_ptr;
407f7cc78ecSespie {
408*d2201f2fSdrahn   int line_p = FALSE;
409*d2201f2fSdrahn   int func_p = FALSE;
410f7cc78ecSespie 
411f7cc78ecSespie   if (aUnit->low_pc <= addr && addr < aUnit->high_pc)
412f7cc78ecSespie     {
413f7cc78ecSespie       if (aUnit->has_stmt_list)
414f7cc78ecSespie 	{
415f7cc78ecSespie 	  unsigned long i;
416f7cc78ecSespie 	  struct dwarf1_func* eachFunc;
417f7cc78ecSespie 
418f7cc78ecSespie 	  if (! aUnit->linenumber_table)
419f7cc78ecSespie 	    {
420f7cc78ecSespie 	      if (! parse_line_table (stash, aUnit))
421*d2201f2fSdrahn 		return FALSE;
422f7cc78ecSespie 	    }
423f7cc78ecSespie 
424f7cc78ecSespie 	  if (! aUnit->func_list)
425f7cc78ecSespie 	    {
426f7cc78ecSespie 	      if (! parse_functions_in_unit (stash, aUnit))
427*d2201f2fSdrahn 		return FALSE;
428f7cc78ecSespie 	    }
429f7cc78ecSespie 
430f7cc78ecSespie 	  for (i = 0; i < aUnit->line_count; i++)
431f7cc78ecSespie 	    {
432f7cc78ecSespie 	      if (aUnit->linenumber_table[i].addr <= addr
433f7cc78ecSespie 		  && addr < aUnit->linenumber_table[i+1].addr)
434f7cc78ecSespie 		{
435f7cc78ecSespie 		  *filename_ptr = aUnit->name;
436f7cc78ecSespie 		  *linenumber_ptr = aUnit->linenumber_table[i].linenumber;
437*d2201f2fSdrahn 		  line_p = TRUE;
438f7cc78ecSespie 		  break;
439f7cc78ecSespie 		}
440f7cc78ecSespie 	    }
441f7cc78ecSespie 
442f7cc78ecSespie 	  for (eachFunc = aUnit->func_list;
443f7cc78ecSespie 	       eachFunc;
444f7cc78ecSespie 	       eachFunc = eachFunc->prev)
445f7cc78ecSespie 	    {
446f7cc78ecSespie 	      if (eachFunc->low_pc <= addr
447f7cc78ecSespie 		  && addr < eachFunc->high_pc)
448f7cc78ecSespie 		{
449f7cc78ecSespie 		  *functionname_ptr = eachFunc->name;
450*d2201f2fSdrahn 		  func_p = TRUE;
451f7cc78ecSespie 		  break;
452f7cc78ecSespie 		}
453f7cc78ecSespie 	    }
454f7cc78ecSespie 	}
455f7cc78ecSespie     }
456f7cc78ecSespie 
457f7cc78ecSespie   return line_p || func_p;
458f7cc78ecSespie }
459f7cc78ecSespie 
460f7cc78ecSespie /* The DWARF 1 version of find_nearest line.
461*d2201f2fSdrahn    Return TRUE if the line is found without error.  */
462f7cc78ecSespie 
463*d2201f2fSdrahn bfd_boolean
_bfd_dwarf1_find_nearest_line(abfd,section,symbols,offset,filename_ptr,functionname_ptr,linenumber_ptr)464f7cc78ecSespie _bfd_dwarf1_find_nearest_line (abfd, section, symbols, offset,
465f7cc78ecSespie                               filename_ptr, functionname_ptr, linenumber_ptr)
466f7cc78ecSespie      bfd *abfd;
467f7cc78ecSespie      asection *section;
468f7cc78ecSespie      asymbol **symbols ATTRIBUTE_UNUSED;
469f7cc78ecSespie      bfd_vma offset;
470f7cc78ecSespie      const char **filename_ptr;
471f7cc78ecSespie      const char **functionname_ptr;
472f7cc78ecSespie      unsigned int *linenumber_ptr;
473f7cc78ecSespie {
474f7cc78ecSespie   struct dwarf1_debug *stash = elf_tdata (abfd)->dwarf1_find_line_info;
475f7cc78ecSespie 
476f7cc78ecSespie   struct dwarf1_unit* eachUnit;
477f7cc78ecSespie 
478f7cc78ecSespie   /* What address are we looking for? */
4795f210c2aSfgsch   unsigned long addr = (unsigned long)(offset + section->vma);
480f7cc78ecSespie 
481f7cc78ecSespie   *filename_ptr = NULL;
482f7cc78ecSespie   *functionname_ptr = NULL;
483f7cc78ecSespie   *linenumber_ptr = 0;
484f7cc78ecSespie 
485f7cc78ecSespie   if (! stash)
486f7cc78ecSespie     {
487f7cc78ecSespie       asection *msec;
488*d2201f2fSdrahn       bfd_size_type size = sizeof (struct dwarf1_debug);
489f7cc78ecSespie 
490*d2201f2fSdrahn       stash = elf_tdata (abfd)->dwarf1_find_line_info
491*d2201f2fSdrahn 	= (struct dwarf1_debug *) bfd_zalloc (abfd, size);
492f7cc78ecSespie 
493f7cc78ecSespie       if (! stash)
494*d2201f2fSdrahn 	return FALSE;
495f7cc78ecSespie 
496f7cc78ecSespie       msec = bfd_get_section_by_name (abfd, ".debug");
497f7cc78ecSespie       if (! msec)
498f7cc78ecSespie 	{
499f7cc78ecSespie 	  /* No dwarf1 info.  Note that at this point the stash
500f7cc78ecSespie 	     has been allocated, but contains zeros, this lets
501f7cc78ecSespie 	     future calls to this function fail quicker.  */
502*d2201f2fSdrahn 	  return FALSE;
503f7cc78ecSespie 	}
504f7cc78ecSespie 
505f7cc78ecSespie       size = bfd_get_section_size_before_reloc (msec);
5065f210c2aSfgsch       stash->debug_section = (char *) bfd_alloc (abfd, size);
507f7cc78ecSespie 
508f7cc78ecSespie       if (! stash->debug_section)
509*d2201f2fSdrahn 	return FALSE;
510f7cc78ecSespie 
511*d2201f2fSdrahn       if (! bfd_get_section_contents (abfd, msec, stash->debug_section,
512*d2201f2fSdrahn 				      (bfd_vma) 0, size))
513f7cc78ecSespie 	{
514f7cc78ecSespie 	  stash->debug_section = 0;
515*d2201f2fSdrahn 	  return FALSE;
516f7cc78ecSespie 	}
517f7cc78ecSespie 
518f7cc78ecSespie       stash->debug_section_end = stash->debug_section + size;
519f7cc78ecSespie       stash->currentDie = stash->debug_section;
520f7cc78ecSespie       stash->abfd = abfd;
521f7cc78ecSespie     }
522f7cc78ecSespie 
523f7cc78ecSespie   /* A null debug_section indicates that there was no dwarf1 info
524f7cc78ecSespie      or that an error occured while setting up the stash.  */
525f7cc78ecSespie 
526f7cc78ecSespie   if (! stash->debug_section)
527*d2201f2fSdrahn     return FALSE;
528f7cc78ecSespie 
529f7cc78ecSespie   /* Look at the previously parsed units to see if any contain
530f7cc78ecSespie      the addr.  */
531f7cc78ecSespie   for (eachUnit = stash->lastUnit; eachUnit; eachUnit = eachUnit->prev)
532f7cc78ecSespie     {
533f7cc78ecSespie       if (eachUnit->low_pc <= addr && addr < eachUnit->high_pc)
534f7cc78ecSespie 	return dwarf1_unit_find_nearest_line (stash, eachUnit, addr,
535f7cc78ecSespie 					      filename_ptr,
536f7cc78ecSespie 					      functionname_ptr,
537f7cc78ecSespie 					      linenumber_ptr);
538f7cc78ecSespie     }
539f7cc78ecSespie 
540f7cc78ecSespie   while (stash->currentDie < stash->debug_section_end)
541f7cc78ecSespie     {
542f7cc78ecSespie       struct die_info aDieInfo;
543f7cc78ecSespie 
544*d2201f2fSdrahn       if (! parse_die (stash->abfd, &aDieInfo, stash->currentDie,
545*d2201f2fSdrahn 		       stash->debug_section_end))
546*d2201f2fSdrahn 	return FALSE;
547f7cc78ecSespie 
548f7cc78ecSespie       if (aDieInfo.tag == TAG_compile_unit)
549f7cc78ecSespie 	{
550f7cc78ecSespie 	  struct dwarf1_unit* aUnit
551f7cc78ecSespie 	    = alloc_dwarf1_unit (stash);
552f7cc78ecSespie 
553f7cc78ecSespie 	  aUnit->name = aDieInfo.name;
554f7cc78ecSespie 	  aUnit->low_pc = aDieInfo.low_pc;
555f7cc78ecSespie 	  aUnit->high_pc = aDieInfo.high_pc;
556f7cc78ecSespie 	  aUnit->has_stmt_list = aDieInfo.has_stmt_list;
557f7cc78ecSespie 	  aUnit->stmt_list_offset = aDieInfo.stmt_list_offset;
558f7cc78ecSespie 
559f7cc78ecSespie 	  /* A die has a child if it's followed by a die that is
560f7cc78ecSespie 	     not it's sibling.  */
561f7cc78ecSespie 	  if (aDieInfo.sibling
562f7cc78ecSespie 	      && stash->currentDie + aDieInfo.length
563f7cc78ecSespie                     < stash->debug_section_end
564f7cc78ecSespie 	      && stash->currentDie + aDieInfo.length
565f7cc78ecSespie 	            != stash->debug_section + aDieInfo.sibling)
566f7cc78ecSespie 	    aUnit->first_child = stash->currentDie + aDieInfo.length;
567f7cc78ecSespie 	  else
568f7cc78ecSespie 	    aUnit->first_child = 0;
569f7cc78ecSespie 
570f7cc78ecSespie 	  if (aUnit->low_pc <= addr && addr < aUnit->high_pc)
571f7cc78ecSespie 	    return dwarf1_unit_find_nearest_line (stash, aUnit, addr,
572f7cc78ecSespie 						  filename_ptr,
573f7cc78ecSespie 						  functionname_ptr,
574f7cc78ecSespie 						  linenumber_ptr);
575f7cc78ecSespie 	}
576f7cc78ecSespie 
577f7cc78ecSespie       if (aDieInfo.sibling != 0)
578f7cc78ecSespie 	stash->currentDie = stash->debug_section + aDieInfo.sibling;
579f7cc78ecSespie       else
580f7cc78ecSespie 	stash->currentDie += aDieInfo.length;
581f7cc78ecSespie     }
582f7cc78ecSespie 
583*d2201f2fSdrahn   return FALSE;
584f7cc78ecSespie }
585f7cc78ecSespie 
586f7cc78ecSespie /* EOF */
587