1b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Return list address ranges.
23e0f7d1d1b817040cef82f41879f471ab59b663eRoland McGrath   Copyright (C) 2000-2010 Red Hat, Inc.
3de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is part of elfutils.
4b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
5b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
6de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is free software; you can redistribute it and/or modify
7de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   it under the terms of either
8b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
9de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard     * the GNU Lesser General Public License as published by the Free
10de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       Software Foundation; either version 3 of the License, or (at
11de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       your option) any later version
12de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
13de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   or
14de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
15de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard     * the GNU General Public License as published by the Free
16de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       Software Foundation; either version 2 of the License, or (at
17de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       your option) any later version
18de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
19de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   or both in parallel, as here.
20de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
21de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   elfutils is distributed in the hope that it will be useful, but
22361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   WITHOUT ANY WARRANTY; without even the implied warranty of
23361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   General Public License for more details.
25361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper
26de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   You should have received copies of the GNU General Public License and
27de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   the GNU Lesser General Public License along with this program.  If
28de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   not, see <http://www.gnu.org/licenses/>.  */
29b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
30b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#ifdef HAVE_CONFIG_H
31b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper# include <config.h>
32b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#endif
33b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
34b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <stdlib.h>
35b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <assert.h>
36b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include "libdwP.h"
3735f08c4d52d0ffd9f8aa50f47b84de5603842b1fUlrich Drepper#include <dwarf.h>
38b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
39b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstruct arangelist
40b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
41b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Dwarf_Arange arange;
42b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  struct arangelist *next;
43b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper};
44b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
45b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Compare by Dwarf_Arange.addr, given pointers into an array of pointeers.  */
46b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic int
47b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppercompare_aranges (const void *a, const void *b)
48b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
495f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath  struct arangelist *const *p1 = a, *const *p2 = b;
505f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath  struct arangelist *l1 = *p1, *l2 = *p2;
514a330f62794abaa3db95a0b447f4c433e4275ce6Mark Wielaard  if (l1->arange.addr != l2->arange.addr)
524a330f62794abaa3db95a0b447f4c433e4275ce6Mark Wielaard    return (l1->arange.addr < l2->arange.addr) ? -1 : 1;
534a330f62794abaa3db95a0b447f4c433e4275ce6Mark Wielaard  return 0;
54b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
55b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
56b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperint
571ccdfb683ad6c7e59793136c3a657ddf131cafd1Mark Wielaarddwarf_getaranges (Dwarf *dbg, Dwarf_Aranges **aranges, size_t *naranges)
58b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
59b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (dbg == NULL)
60b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return -1;
61b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
62b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (dbg->aranges != NULL)
63b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
64b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      *aranges = dbg->aranges;
65b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (naranges != NULL)
66b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	*naranges = dbg->aranges->naranges;
67b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return 0;
68b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
69b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
70e7a73177dfbbc650fb43e5caa3ce29143f02fabdUlrich Drepper  if (dbg->sectiondata[IDX_debug_aranges] == NULL)
71e7a73177dfbbc650fb43e5caa3ce29143f02fabdUlrich Drepper    {
72e7a73177dfbbc650fb43e5caa3ce29143f02fabdUlrich Drepper      /* No such section.  */
73e7a73177dfbbc650fb43e5caa3ce29143f02fabdUlrich Drepper      *aranges = NULL;
74e7a73177dfbbc650fb43e5caa3ce29143f02fabdUlrich Drepper      if (naranges != NULL)
75e7a73177dfbbc650fb43e5caa3ce29143f02fabdUlrich Drepper	*naranges = 0;
76e7a73177dfbbc650fb43e5caa3ce29143f02fabdUlrich Drepper      return 0;
77e7a73177dfbbc650fb43e5caa3ce29143f02fabdUlrich Drepper    }
78e7a73177dfbbc650fb43e5caa3ce29143f02fabdUlrich Drepper
79b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (dbg->sectiondata[IDX_debug_aranges]->d_buf == NULL)
80b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return -1;
81b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
82b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  struct arangelist *arangelist = NULL;
83b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  unsigned int narangelist = 0;
84b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
8505c4e04640d173a4d1ce6e2f25a24060c21a67abRoland McGrath  const unsigned char *readp = dbg->sectiondata[IDX_debug_aranges]->d_buf;
8605c4e04640d173a4d1ce6e2f25a24060c21a67abRoland McGrath  const unsigned char *readendp
8705c4e04640d173a4d1ce6e2f25a24060c21a67abRoland McGrath    = readp + dbg->sectiondata[IDX_debug_aranges]->d_size;
88b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
89b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  while (readp < readendp)
90b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
9105c4e04640d173a4d1ce6e2f25a24060c21a67abRoland McGrath      const unsigned char *hdrstart = readp;
92b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
93b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Each entry starts with a header:
94b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
95b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 1. A 4-byte or 12-byte length containing the length of the
96b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 set of entries for this compilation unit, not including the
97b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 length field itself. [...]
98b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
99b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 2. A 2-byte version identifier containing the value 2 for
100b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 DWARF Version 2.1.
101b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
102b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 3. A 4-byte or 8-byte offset into the .debug_info section. [...]
103b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
104b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 4. A 1-byte unsigned integer containing the size in bytes of
105b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 an address (or the offset portion of an address for segmented
106b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 addressing) on the target system.
107b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
108b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 5. A 1-byte unsigned integer containing the size in bytes of
109b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 a segment descriptor on the target system.  */
110ae02916ba11547418c749ab0bebeb59c6094b96cMark Wielaard      if (unlikely (readp + 4 > readendp))
111ae02916ba11547418c749ab0bebeb59c6094b96cMark Wielaard	goto invalid;
112ae02916ba11547418c749ab0bebeb59c6094b96cMark Wielaard
113b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Dwarf_Word length = read_4ubyte_unaligned_inc (dbg, readp);
114b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      unsigned int length_bytes = 4;
11535f08c4d52d0ffd9f8aa50f47b84de5603842b1fUlrich Drepper      if (length == DWARF3_LENGTH_64_BIT)
116b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
117ae02916ba11547418c749ab0bebeb59c6094b96cMark Wielaard	  if (unlikely (readp + 8 > readendp))
118ae02916ba11547418c749ab0bebeb59c6094b96cMark Wielaard	    goto invalid;
119ae02916ba11547418c749ab0bebeb59c6094b96cMark Wielaard
120b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  length = read_8ubyte_unaligned_inc (dbg, readp);
121b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  length_bytes = 8;
122b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
12335f08c4d52d0ffd9f8aa50f47b84de5603842b1fUlrich Drepper      else if (unlikely (length >= DWARF3_LENGTH_MIN_ESCAPE_CODE
12435f08c4d52d0ffd9f8aa50f47b84de5603842b1fUlrich Drepper			 && length <= DWARF3_LENGTH_MAX_ESCAPE_CODE))
12535f08c4d52d0ffd9f8aa50f47b84de5603842b1fUlrich Drepper	goto invalid;
126b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
127ae02916ba11547418c749ab0bebeb59c6094b96cMark Wielaard      if (unlikely (readp + 2 > readendp))
128ae02916ba11547418c749ab0bebeb59c6094b96cMark Wielaard	goto invalid;
129ae02916ba11547418c749ab0bebeb59c6094b96cMark Wielaard
130b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      unsigned int version = read_2ubyte_unaligned_inc (dbg, readp);
131b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (version != 2)
132b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
133b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	invalid:
134b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
1355f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath	fail:
1365f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath	  while (arangelist != NULL)
1375f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath	    {
1385f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath	      struct arangelist *next = arangelist->next;
1395f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath	      free (arangelist);
1405f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath	      arangelist = next;
1415f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath	    }
142b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  return -1;
143b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
144b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
145ae02916ba11547418c749ab0bebeb59c6094b96cMark Wielaard      Dwarf_Word offset = 0;
14699d2372b25d1231d786b70278478c7a112f2b27cUlrich Drepper      if (__libdw_read_offset_inc (dbg,
14705c4e04640d173a4d1ce6e2f25a24060c21a67abRoland McGrath				   IDX_debug_aranges, &readp,
14899d2372b25d1231d786b70278478c7a112f2b27cUlrich Drepper				   length_bytes, &offset, IDX_debug_info, 4))
1495f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath	goto fail;
150a5a89687681ca81e82681b56612495c0d087829eRoland McGrath
151b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      unsigned int address_size = *readp++;
152ae02916ba11547418c749ab0bebeb59c6094b96cMark Wielaard      if (unlikely (address_size != 4 && address_size != 8))
153b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	goto invalid;
154b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
15503d76f4aec5e750b81198c7a24571e119e754b40Mark Wielaard      /* We don't actually support segment selectors.  */
15603d76f4aec5e750b81198c7a24571e119e754b40Mark Wielaard      unsigned int segment_size = *readp++;
15703d76f4aec5e750b81198c7a24571e119e754b40Mark Wielaard      if (segment_size != 0)
15803d76f4aec5e750b81198c7a24571e119e754b40Mark Wielaard	goto invalid;
159b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
160b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Round the address to the next multiple of 2*address_size.  */
161b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      readp += ((2 * address_size - ((readp - hdrstart) % (2 * address_size)))
162b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		% (2 * address_size));
163b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
164b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      while (1)
165b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
166b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  Dwarf_Word range_address;
167b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  Dwarf_Word range_length;
168b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
16905c4e04640d173a4d1ce6e2f25a24060c21a67abRoland McGrath	  if (__libdw_read_address_inc (dbg, IDX_debug_aranges, &readp,
17099d2372b25d1231d786b70278478c7a112f2b27cUlrich Drepper					address_size, &range_address))
1715f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath	    goto fail;
17299d2372b25d1231d786b70278478c7a112f2b27cUlrich Drepper
173ae02916ba11547418c749ab0bebeb59c6094b96cMark Wielaard	  if (readp + address_size > readendp)
174ae02916ba11547418c749ab0bebeb59c6094b96cMark Wielaard	    goto invalid;
175ae02916ba11547418c749ab0bebeb59c6094b96cMark Wielaard
176b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (address_size == 4)
17799d2372b25d1231d786b70278478c7a112f2b27cUlrich Drepper	    range_length = read_4ubyte_unaligned_inc (dbg, readp);
178b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else
17999d2372b25d1231d786b70278478c7a112f2b27cUlrich Drepper	    range_length = read_8ubyte_unaligned_inc (dbg, readp);
180b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
181b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Two zero values mark the end.  */
182b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (range_address == 0 && range_length == 0)
183b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    break;
184b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1855f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath	  /* We don't use alloca for these temporary structures because
1865f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath	     the total number of them can be quite large.  */
1875f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath	  struct arangelist *new_arange = malloc (sizeof *new_arange);
1885f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath	  if (unlikely (new_arange == NULL))
1895f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath	    {
1905f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath	      __libdw_seterrno (DWARF_E_NOMEM);
1915f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath	      goto fail;
1925f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath	    }
193b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
194b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  new_arange->arange.addr = range_address;
195b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  new_arange->arange.length = range_length;
196b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
197b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* We store the actual CU DIE offset, not the CU header offset.  */
198b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  const char *cu_header = (dbg->sectiondata[IDX_debug_info]->d_buf
199b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   + offset);
200b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  unsigned int offset_size;
20135f08c4d52d0ffd9f8aa50f47b84de5603842b1fUlrich Drepper	  if (read_4ubyte_unaligned_noncvt (cu_header) == DWARF3_LENGTH_64_BIT)
202b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    offset_size = 8;
203b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else
204b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    offset_size = 4;
205c57b65cf3b1a7a19b25fdac91e83c514fd93e565Ulrich Drepper	  new_arange->arange.offset = DIE_OFFSET_FROM_CU_OFFSET (offset,
2063e0f7d1d1b817040cef82f41879f471ab59b663eRoland McGrath								 offset_size,
2073e0f7d1d1b817040cef82f41879f471ab59b663eRoland McGrath								 false);
208b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
209b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  new_arange->next = arangelist;
210b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  arangelist = new_arange;
211b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  ++narangelist;
2125f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath
2135f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath	  /* Sanity-check the data.  */
2145f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath	  if (unlikely (new_arange->arange.offset
2155f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath			>= dbg->sectiondata[IDX_debug_info]->d_size))
2165f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath	    goto invalid;
217b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
218b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
219b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
220b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (narangelist == 0)
221b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2225f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath      assert (arangelist == NULL);
223b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (naranges != NULL)
224b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	*naranges = 0;
225b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      *aranges = NULL;
226b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return 0;
227b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
228b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
229b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Allocate the array for the result.  */
230b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  void *buf = libdw_alloc (dbg, Dwarf_Aranges,
231b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   sizeof (Dwarf_Aranges)
232b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   + narangelist * sizeof (Dwarf_Arange), 1);
233b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
234b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* First use the buffer for the pointers, and sort the entries.
235b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     We'll write the pointers in the end of the buffer, and then
236b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     copy into the buffer from the beginning so the overlap works.  */
237b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  assert (sizeof (Dwarf_Arange) >= sizeof (Dwarf_Arange *));
2385f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath  struct arangelist **sortaranges
2395f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath    = (buf + sizeof (Dwarf_Aranges)
2405f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath       + ((sizeof (Dwarf_Arange) - sizeof sortaranges[0]) * narangelist));
241b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
242b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* The list is in LIFO order and usually they come in clumps with
243b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     ascending addresses.  So fill from the back to probably start with
244b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     runs already in order before we sort.  */
245b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  unsigned int i = narangelist;
246b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  while (i-- > 0)
247b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
2485f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath      sortaranges[i] = arangelist;
249b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      arangelist = arangelist->next;
250b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
251b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  assert (arangelist == NULL);
252b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
253b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Sort by ascending address.  */
254b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  qsort (sortaranges, narangelist, sizeof sortaranges[0], &compare_aranges);
255b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
256b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Now that they are sorted, put them in the final array.
257b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     The buffers overlap, so we've clobbered the early elements
258b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     of SORTARANGES by the time we're reading the later ones.  */
259b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  *aranges = buf;
260b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  (*aranges)->dbg = dbg;
261b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  (*aranges)->naranges = narangelist;
262b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  dbg->aranges = *aranges;
263b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (naranges != NULL)
264b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    *naranges = narangelist;
265b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  for (i = 0; i < narangelist; ++i)
2665f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath    {
2675f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath      struct arangelist *elt = sortaranges[i];
2685f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath      (*aranges)->info[i] = elt->arange;
2695f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath      free (elt);
2705f95e2b093cdeb4610cbb049dd5e7dac5dd7c3efRoland McGrath    }
271b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
272b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return 0;
273b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
274b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperINTDEF(dwarf_getaranges)
275