1/*
2
3  Copyright (C) 2008-2010 David Anderson. All Rights Reserved.
4
5  This program is free software; you can redistribute it and/or modify it
6  under the terms of version 2.1 of the GNU Lesser General Public License
7  as published by the Free Software Foundation.
8
9  This program is distributed in the hope that it would be useful, but
10  WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13  Further, this software is distributed without any warranty that it is
14  free of the rightful claim of any third person regarding infringement
15  or the like.  Any license provided herein, whether implied or
16  otherwise, applies only to this software file.  Patent licenses, if
17  any, provided herein do not apply to combinations of this program with
18  other software, or any other product whatsoever.
19
20  You should have received a copy of the GNU Lesser General Public
21  License along with this program; if not, write the Free Software
22  Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
23  USA.
24
25  Contact information:  Silicon Graphics, Inc., 1500 Crittenden Lane,
26  Mountain View, CA 94043, or:
27
28  http://www.sgi.com
29
30  For further information regarding this notice, see:
31
32  http://oss.sgi.com/projects/GenInfo/NoticeExplan
33
34*/
35/* The address of the Free Software Foundation is
36   Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
37   Boston, MA 02110-1301, USA.
38   SGI has moved from the Crittenden Lane address.
39*/
40
41
42
43#include "config.h"
44#include <stdlib.h>
45#include "dwarf_incl.h"
46
47struct ranges_entry {
48   struct ranges_entry *next;
49   Dwarf_Ranges cur;
50};
51
52
53#define MAX_ADDR ((address_size == 8)?0xffffffffffffffffULL:0xffffffff)
54int dwarf_get_ranges_a(Dwarf_Debug dbg,
55    Dwarf_Off rangesoffset,
56    Dwarf_Die die,
57    Dwarf_Ranges ** rangesbuf,
58    Dwarf_Signed * listlen,
59    Dwarf_Unsigned * bytecount,
60    Dwarf_Error * error)
61{
62    Dwarf_Small *rangeptr = 0;
63    Dwarf_Small *beginrangeptr = 0;
64    Dwarf_Small *section_end = 0;
65    unsigned entry_count = 0;
66    struct ranges_entry *base = 0;
67    struct ranges_entry *last = 0;
68    struct ranges_entry *curre = 0;
69    Dwarf_Ranges * ranges_data_out = 0;
70    unsigned copyindex = 0;
71    Dwarf_Half address_size = 0;
72    int res = DW_DLV_ERROR;
73
74    res = _dwarf_load_section(dbg, &dbg->de_debug_ranges,error);
75    if (res != DW_DLV_OK) {
76        return res;
77    }
78    if(rangesoffset >= dbg->de_debug_ranges.dss_size) {
79        _dwarf_error(dbg, error, DW_DLE_DEBUG_RANGES_OFFSET_BAD);
80        return (DW_DLV_ERROR);
81
82    }
83    address_size = _dwarf_get_address_size(dbg, die);
84    section_end = dbg->de_debug_ranges.dss_data +
85        dbg->de_debug_ranges.dss_size;
86    rangeptr = dbg->de_debug_ranges.dss_data + rangesoffset;
87    beginrangeptr = rangeptr;
88
89    for(;;) {
90        struct ranges_entry * re = calloc(sizeof(struct ranges_entry),1);
91        if(!re) {
92            _dwarf_error(dbg, error, DW_DLE_DEBUG_RANGES_OUT_OF_MEM);
93            return (DW_DLV_ERROR);
94        }
95        if(rangeptr  >= section_end) {
96            return (DW_DLV_NO_ENTRY);
97        }
98        if((rangeptr + (2*address_size)) > section_end) {
99            _dwarf_error(dbg, error, DW_DLE_DEBUG_RANGES_OFFSET_BAD);
100            return (DW_DLV_ERROR);
101        }
102        entry_count++;
103        READ_UNALIGNED(dbg,re->cur.dwr_addr1,
104                       Dwarf_Addr, rangeptr,
105                       address_size);
106        rangeptr +=  address_size;
107        READ_UNALIGNED(dbg,re->cur.dwr_addr2 ,
108                       Dwarf_Addr, rangeptr,
109                       address_size);
110        rangeptr +=  address_size;
111        if(!base) {
112           base = re;
113           last = re;
114        } else {
115           last->next = re;
116           last = re;
117        }
118        if(re->cur.dwr_addr1 == 0 && re->cur.dwr_addr2 == 0) {
119            re->cur.dwr_type =  DW_RANGES_END;
120            break;
121        } else if ( re->cur.dwr_addr1 == MAX_ADDR) {
122            re->cur.dwr_type =  DW_RANGES_ADDRESS_SELECTION;
123        } else {
124            re->cur.dwr_type =  DW_RANGES_ENTRY;
125        }
126    }
127
128    ranges_data_out =   (Dwarf_Ranges *)
129    _dwarf_get_alloc(dbg,DW_DLA_RANGES,entry_count);
130    if(!ranges_data_out) {
131            _dwarf_error(dbg, error, DW_DLE_DEBUG_RANGES_OUT_OF_MEM);
132            return (DW_DLV_ERROR);
133    }
134    curre = base;
135    *rangesbuf = ranges_data_out;
136    *listlen = entry_count;
137    for( copyindex = 0; curre && (copyindex < entry_count);
138        ++copyindex,++ranges_data_out) {
139
140        struct ranges_entry *r = curre;
141        *ranges_data_out = curre->cur;
142        curre = curre->next;
143        free(r);
144    }
145    /* Callers will often not care about the bytes used. */
146    if(bytecount) {
147        *bytecount = rangeptr - beginrangeptr;
148    }
149    return DW_DLV_OK;
150}
151int dwarf_get_ranges(Dwarf_Debug dbg,
152    Dwarf_Off rangesoffset,
153    Dwarf_Ranges ** rangesbuf,
154    Dwarf_Signed * listlen,
155    Dwarf_Unsigned * bytecount,
156    Dwarf_Error * error)
157{
158    Dwarf_Die die = 0;
159    int res = dwarf_get_ranges_a(dbg,rangesoffset,die,
160        rangesbuf,listlen,bytecount,error);
161    return res;
162}
163
164void
165dwarf_ranges_dealloc(Dwarf_Debug dbg, Dwarf_Ranges * rangesbuf,
166    Dwarf_Signed rangecount)
167{
168    dwarf_dealloc(dbg,rangesbuf, DW_DLA_RANGES);
169
170}
171
172