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)
dwarf_get_ranges_a(Dwarf_Debug dbg,Dwarf_Off rangesoffset,Dwarf_Die die,Dwarf_Ranges ** rangesbuf,Dwarf_Signed * listlen,Dwarf_Unsigned * bytecount,Dwarf_Error * error)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 }
dwarf_get_ranges(Dwarf_Debug dbg,Dwarf_Off rangesoffset,Dwarf_Ranges ** rangesbuf,Dwarf_Signed * listlen,Dwarf_Unsigned * bytecount,Dwarf_Error * error)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
dwarf_ranges_dealloc(Dwarf_Debug dbg,Dwarf_Ranges * rangesbuf,Dwarf_Signed rangecount)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