]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/elftoolchain/libdwarf/dwarf_loclist.c
Merge OpenSSL 1.0.1h.
[FreeBSD/FreeBSD.git] / contrib / elftoolchain / libdwarf / dwarf_loclist.c
1 /*-
2  * Copyright (c) 2009 Kai Wang
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include "_libdwarf.h"
28
29 ELFTC_VCSID("$Id: dwarf_loclist.c 2074 2011-10-27 03:34:33Z jkoshy $");
30
31 int
32 dwarf_loclist_n(Dwarf_Attribute at, Dwarf_Locdesc ***llbuf,
33     Dwarf_Signed *listlen, Dwarf_Error *error)
34 {
35         Dwarf_Loclist ll;
36         Dwarf_Debug dbg;
37         int ret;
38
39         dbg = at != NULL ? at->at_die->die_dbg : NULL;
40
41         if (at == NULL || llbuf == NULL || listlen == NULL) {
42                 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
43                 return (DW_DLV_ERROR);
44         }
45
46         switch (at->at_attrib) {
47         case DW_AT_location:
48         case DW_AT_string_length:
49         case DW_AT_return_addr:
50         case DW_AT_data_member_location:
51         case DW_AT_frame_base:
52         case DW_AT_segment:
53         case DW_AT_static_link:
54         case DW_AT_use_location:
55         case DW_AT_vtable_elem_location:
56                 switch (at->at_form) {
57                 case DW_FORM_data4:
58                 case DW_FORM_data8:
59                         /*
60                          * DW_FORM_data[48] can not be used as section offset
61                          * since DWARF4. For DWARF[23], the application needs
62                          * to determine if DW_FORM_data[48] is representing
63                          * a constant or a section offset.
64                          */
65                         if (at->at_die->die_cu->cu_version >= 4) {
66                                 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
67                                 return (DW_DLV_NO_ENTRY);
68                         }
69                         /* FALLTHROUGH */
70                 case DW_FORM_sec_offset:
71                         ret = _dwarf_loclist_find(dbg, at->at_die->die_cu,
72                             at->u[0].u64, &ll, error);
73                         if (ret == DW_DLE_NO_ENTRY) {
74                                 DWARF_SET_ERROR(dbg, error, ret);
75                                 return (DW_DLV_NO_ENTRY);
76                         }
77                         if (ret != DW_DLE_NONE)
78                                 return (DW_DLV_ERROR);
79                         *llbuf = ll->ll_ldlist;
80                         *listlen = ll->ll_ldlen;
81                         return (DW_DLV_OK);
82                 case DW_FORM_block:
83                 case DW_FORM_block1:
84                 case DW_FORM_block2:
85                 case DW_FORM_block4:
86                         if (at->at_ld == NULL) {
87                                 ret = _dwarf_loc_add(at->at_die, at, error);
88                                 if (ret != DW_DLE_NONE)
89                                         return (DW_DLV_ERROR);
90                         }
91                         *llbuf = &at->at_ld;
92                         *listlen = 1;
93                         return (DW_DLV_OK);
94                 default:
95                         /* Malformed Attr? */
96                         DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
97                         return (DW_DLV_NO_ENTRY);
98                 }
99         default:
100                 /* Wrong attr supplied. */
101                 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
102                 return (DW_DLV_ERROR);
103         }
104 }
105
106 int
107 dwarf_loclist(Dwarf_Attribute at, Dwarf_Locdesc **llbuf,
108     Dwarf_Signed *listlen, Dwarf_Error *error)
109 {
110         Dwarf_Loclist ll;
111         Dwarf_Debug dbg;
112         int ret;
113
114         dbg = at != NULL ? at->at_die->die_dbg : NULL;
115
116         if (at == NULL || llbuf == NULL || listlen == NULL) {
117                 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
118                 return (DW_DLV_ERROR);
119         }
120
121         switch (at->at_attrib) {
122         case DW_AT_location:
123         case DW_AT_string_length:
124         case DW_AT_return_addr:
125         case DW_AT_data_member_location:
126         case DW_AT_frame_base:
127         case DW_AT_segment:
128         case DW_AT_static_link:
129         case DW_AT_use_location:
130         case DW_AT_vtable_elem_location:
131                 switch (at->at_form) {
132                 case DW_FORM_data4:
133                 case DW_FORM_data8:
134                         /*
135                          * DW_FORM_data[48] can not be used as section offset
136                          * since DWARF4. For DWARF[23], the application needs
137                          * to determine if DW_FORM_data[48] is representing
138                          * a constant or a section offset.
139                          */
140                         if (at->at_die->die_cu->cu_version >= 4) {
141                                 printf("called cu_version >= 4\n");
142                                 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
143                                 return (DW_DLV_NO_ENTRY);
144                         }
145                         /* FALLTHROUGH */
146                 case DW_FORM_sec_offset:
147                         ret = _dwarf_loclist_find(at->at_die->die_dbg,
148                             at->at_die->die_cu, at->u[0].u64, &ll, error);
149                         if (ret == DW_DLE_NO_ENTRY) {
150                                 DWARF_SET_ERROR(dbg, error, DW_DLV_NO_ENTRY);
151                                 return (DW_DLV_NO_ENTRY);
152                         }
153                         if (ret != DW_DLE_NONE)
154                                 return (DW_DLV_ERROR);
155                         *llbuf = ll->ll_ldlist[0];
156                         *listlen = 1;
157                         return (DW_DLV_OK);
158                 case DW_FORM_block:
159                 case DW_FORM_block1:
160                 case DW_FORM_block2:
161                 case DW_FORM_block4:
162                         if (at->at_ld == NULL) {
163                                 ret = _dwarf_loc_add(at->at_die, at, error);
164                                 if (ret != DW_DLE_NONE)
165                                         return (DW_DLV_ERROR);
166                         }
167                         *llbuf = at->at_ld;
168                         *listlen = 1;
169                         return (DW_DLV_OK);
170                 default:
171                         DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
172                         return (DW_DLV_ERROR);
173                 }
174         default:
175                 /* Wrong attr supplied. */
176                 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
177                 return (DW_DLV_ERROR);
178         }
179 }
180
181 int
182 dwarf_get_loclist_entry(Dwarf_Debug dbg, Dwarf_Unsigned offset,
183     Dwarf_Addr *hipc, Dwarf_Addr *lopc, Dwarf_Ptr *data,
184     Dwarf_Unsigned *entry_len, Dwarf_Unsigned *next_entry,
185     Dwarf_Error *error)
186 {
187         Dwarf_Loclist ll, next_ll;
188         Dwarf_Locdesc *ld;
189         Dwarf_Section *ds;
190         int i, ret;
191
192         if (dbg == NULL || hipc == NULL || lopc == NULL || data == NULL ||
193             entry_len == NULL || next_entry == NULL) {
194                 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
195                 return (DW_DLV_ERROR);
196         }
197
198         ret = _dwarf_loclist_find(dbg, STAILQ_FIRST(&dbg->dbg_cu), offset, &ll,
199             error);
200         if (ret == DW_DLE_NO_ENTRY) {
201                 DWARF_SET_ERROR(dbg, error, DW_DLV_NO_ENTRY);
202                 return (DW_DLV_NO_ENTRY);
203         } else if (ret != DW_DLE_NONE)
204                 return (DW_DLV_ERROR);
205
206         *hipc = *lopc = 0;
207         for (i = 0; i < ll->ll_ldlen; i++) {
208                 ld = ll->ll_ldlist[i];
209                 if (i == 0) {
210                         *hipc = ld->ld_hipc;
211                         *lopc = ld->ld_lopc;
212                 } else {
213                         if (ld->ld_lopc < *lopc)
214                                 *lopc = ld->ld_lopc;
215                         if (ld->ld_hipc > *hipc)
216                                 *hipc = ld->ld_hipc;
217                 }
218         }
219
220         ds = _dwarf_find_section(dbg, ".debug_loc");
221         assert(ds != NULL);
222         *data = (uint8_t *) ds->ds_data + ll->ll_offset;
223         *entry_len = ll->ll_length;
224
225         next_ll = TAILQ_NEXT(ll, ll_next);
226         if (next_ll != NULL)
227                 *next_entry = next_ll->ll_offset;
228         else
229                 *next_entry = ds->ds_size;
230
231         return (DW_DLV_OK);
232 }
233
234 int
235 dwarf_loclist_from_expr(Dwarf_Debug dbg, Dwarf_Ptr bytes_in,
236     Dwarf_Unsigned bytes_len, Dwarf_Locdesc **llbuf, Dwarf_Signed *listlen,
237     Dwarf_Error *error)
238 {
239         Dwarf_Locdesc *ld;
240         int ret;
241
242         if (dbg == NULL || bytes_in == NULL || bytes_len == 0 ||
243             llbuf == NULL || listlen == NULL) {
244                 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
245                 return (DW_DLV_ERROR);
246         }
247
248         ret = _dwarf_loc_fill_locexpr(dbg, &ld, bytes_in, bytes_len,
249             dbg->dbg_pointer_size, error);
250         if (ret != DW_DLE_NONE)
251                 return (DW_DLV_ERROR);
252
253         *llbuf = ld;
254         *listlen = 1;
255
256         return (DW_DLV_OK);
257 }
258
259 int
260 dwarf_loclist_from_expr_a(Dwarf_Debug dbg, Dwarf_Ptr bytes_in,
261     Dwarf_Unsigned bytes_len, Dwarf_Half addr_size, Dwarf_Locdesc **llbuf,
262     Dwarf_Signed *listlen, Dwarf_Error *error)
263 {
264         Dwarf_Locdesc *ld;
265         int ret;
266
267         if (dbg == NULL || bytes_in == NULL || bytes_len == 0 ||
268             llbuf == NULL || listlen == NULL) {
269                 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
270                 return (DW_DLV_ERROR);
271         }
272
273         if (addr_size != 4 && addr_size != 8) {
274                 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
275                 return (DW_DLV_ERROR);
276         }
277
278         ret = _dwarf_loc_fill_locexpr(dbg, &ld, bytes_in, bytes_len, addr_size,
279             error);
280         if (ret != DW_DLE_NONE)
281                 return (DW_DLV_ERROR);
282
283         *llbuf = ld;
284         *listlen = 1;
285
286         return (DW_DLV_OK);
287 }