xref: /illumos-gate/usr/src/lib/libdwarf/common/dwarf_ranges.c (revision bc1f688b4872ace323eaddbb1a6365d054e7bf56)
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 
47 struct ranges_entry {
48    struct ranges_entry *next;
49    Dwarf_Ranges cur;
50 };
51 
52 
53 #define MAX_ADDR ((address_size == 8)?0xffffffffffffffffULL:0xffffffff)
54 int 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 }
151 int 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 
164 void
165 dwarf_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