Home | History | Annotate | Download | only in libdw
      1 /* Return list address ranges.
      2    Copyright (C) 2000, 2001, 2002, 2004 Red Hat, Inc.
      3    Written by Ulrich Drepper <drepper (at) redhat.com>, 2000.
      4 
      5    This program is Open Source software; you can redistribute it and/or
      6    modify it under the terms of the Open Software License version 1.0 as
      7    published by the Open Source Initiative.
      8 
      9    You should have received a copy of the Open Software License along
     10    with this program; if not, you may obtain a copy of the Open Software
     11    License version 1.0 from http://www.opensource.org/licenses/osl.php or
     12    by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
     13    3001 King Ranch Road, Ukiah, CA 95482.   */
     14 
     15 #ifdef HAVE_CONFIG_H
     16 # include <config.h>
     17 #endif
     18 
     19 #include <stdlib.h>
     20 
     21 #include <libdwP.h>
     22 
     23 
     24 struct arangelist
     25 {
     26   Dwarf_Arange arange;
     27   struct arangelist *next;
     28 };
     29 
     30 
     31 int
     32 dwarf_getaranges (dbg, aranges, naranges)
     33      Dwarf *dbg;
     34      Dwarf_Aranges **aranges;
     35      size_t *naranges;
     36 {
     37   if (dbg == NULL)
     38     return -1;
     39 
     40   if (dbg->aranges != NULL)
     41     {
     42       *aranges = dbg->aranges;
     43       if (naranges != NULL)
     44 	*naranges = dbg->aranges->naranges;
     45       return 0;
     46     }
     47 
     48   if (dbg->sectiondata[IDX_debug_aranges]->d_buf == NULL)
     49     return -1;
     50 
     51   struct arangelist *arangelist = NULL;
     52   unsigned int narangelist = 0;
     53 
     54   const char *readp
     55     = (const char *) dbg->sectiondata[IDX_debug_aranges]->d_buf;
     56   const char *readendp = readp + dbg->sectiondata[IDX_debug_aranges]->d_size;
     57 
     58   while (readp < readendp)
     59     {
     60       const char *hdrstart = readp;
     61 
     62       /* Each entry starts with a header:
     63 
     64 	 1. A 4-byte or 12-byte length containing the length of the
     65 	 set of entries for this compilation unit, not including the
     66 	 length field itself. [...]
     67 
     68 	 2. A 2-byte version identifier containing the value 2 for
     69 	 DWARF Version 2.1.
     70 
     71 	 3. A 4-byte or 8-byte offset into the .debug_info section. [...]
     72 
     73 	 4. A 1-byte unsigned integer containing the size in bytes of
     74 	 an address (or the offset portion of an address for segmented
     75 	 addressing) on the target system.
     76 
     77 	 5. A 1-byte unsigned integer containing the size in bytes of
     78 	 a segment descriptor on the target system.  */
     79       Dwarf_Word length = read_4ubyte_unaligned_inc (dbg, readp);
     80       unsigned int length_bytes = 4;
     81       if (length == 0xffffffff)
     82 	{
     83 	  length = read_8ubyte_unaligned_inc (dbg, readp);
     84 	  length_bytes = 8;
     85 	}
     86 
     87       unsigned int version = read_2ubyte_unaligned_inc (dbg, readp);
     88       if (version != 2)
     89 	{
     90 	invalid:
     91 	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
     92 	  return -1;
     93 	}
     94 
     95       Dwarf_Word offset;
     96       if (length_bytes == 4)
     97 	offset = read_4ubyte_unaligned_inc (dbg, readp);
     98       else
     99 	offset = read_8ubyte_unaligned_inc (dbg, readp);
    100 
    101       unsigned int address_size = *readp++;
    102       if (address_size != 4 && address_size != 8)
    103 	goto invalid;
    104 
    105       /* Ignore the segment size value.  */
    106       // XXX Really?
    107       (void) *readp++;
    108 
    109       /* Round the address to the next multiple of 2*address_size.  */
    110       readp += ((2 * address_size - ((readp - hdrstart) % (2 * address_size)))
    111 		% (2 * address_size));
    112 
    113       //arange_info->offset = offset;
    114 
    115       while (1)
    116 	{
    117 	  Dwarf_Word range_address;
    118 	  Dwarf_Word range_length;
    119 
    120 	  if (address_size == 4)
    121 	    {
    122 	      range_address = read_4ubyte_unaligned_inc (dbg, readp);
    123 	      range_length = read_4ubyte_unaligned_inc (dbg, readp);
    124 	    }
    125 	  else
    126 	    {
    127 	      range_address = read_8ubyte_unaligned_inc (dbg, readp);
    128 	      range_length = read_8ubyte_unaligned_inc (dbg, readp);
    129 	    }
    130 
    131 	  /* Two zero values mark the end.  */
    132 	  if (range_address == 0 && range_length == 0)
    133 	    break;
    134 
    135 	  struct arangelist *new_arange =
    136 	    (struct arangelist *) alloca (sizeof (struct arangelist));
    137 
    138 	  new_arange->arange.addr = range_address;
    139 	  new_arange->arange.length = range_length;
    140 
    141 	  /* We store the actual CU DIE offset, not the CU header offset.  */
    142 	  const char *cu_header = (dbg->sectiondata[IDX_debug_info]->d_buf
    143 				   + offset);
    144 	  unsigned int offset_size;
    145 	  if (read_4ubyte_unaligned_noncvt (cu_header) == 0xffffffff)
    146 	    offset_size = 8;
    147 	  else
    148 	    offset_size = 4;
    149 	  new_arange->arange.offset = offset + 3 * offset_size - 4 + 3;
    150 
    151 	  new_arange->next = arangelist;
    152 	  arangelist = new_arange;
    153 	  ++narangelist;
    154 	}
    155     }
    156 
    157   if (narangelist == 0)
    158     {
    159       if (naranges != NULL)
    160 	*naranges = 0;
    161       *aranges = NULL;
    162       return 0;
    163     }
    164 
    165   /* Allocate the array for the result.  */
    166   if (naranges != NULL)
    167     *naranges = narangelist;
    168   *aranges = libdw_alloc (dbg, Dwarf_Aranges,
    169 			  sizeof (Dwarf_Aranges)
    170 			  + narangelist * sizeof (Dwarf_Arange), 1);
    171 
    172   (*aranges)->dbg = dbg;
    173   (*aranges)->naranges = narangelist;
    174 
    175   while (narangelist-- > 0)
    176     {
    177       (*aranges)->info[narangelist] = arangelist->arange;
    178       arangelist = arangelist->next;
    179     }
    180 
    181   dbg->aranges = *aranges;
    182 
    183   return 0;
    184 }
    185