• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Return list address ranges.
2    Copyright (C) 2000, 2001, 2002, 2004 Red Hat, Inc.
3    Written by Ulrich Drepper <drepper@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
dwarf_getaranges(dbg,aranges,naranges)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