1 /* $NetBSD: dwarf_loclist.c,v 1.2 2014/03/09 16:58:04 christos Exp $ */
4 * Copyright (c) 2009 Kai Wang
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include "_libdwarf.h"
31 __RCSID("$NetBSD: dwarf_loclist.c,v 1.2 2014/03/09 16:58:04 christos Exp $");
32 ELFTC_VCSID("Id: dwarf_loclist.c 2074 2011-10-27 03:34:33Z jkoshy ");
35 dwarf_loclist_n(Dwarf_Attribute at
, Dwarf_Locdesc
***llbuf
,
36 Dwarf_Signed
*listlen
, Dwarf_Error
*error
)
42 dbg
= at
!= NULL
? at
->at_die
->die_dbg
: NULL
;
44 if (at
== NULL
|| llbuf
== NULL
|| listlen
== NULL
) {
45 DWARF_SET_ERROR(dbg
, error
, DW_DLE_ARGUMENT
);
46 return (DW_DLV_ERROR
);
49 switch (at
->at_attrib
) {
51 case DW_AT_string_length
:
52 case DW_AT_return_addr
:
53 case DW_AT_data_member_location
:
54 case DW_AT_frame_base
:
56 case DW_AT_static_link
:
57 case DW_AT_use_location
:
58 case DW_AT_vtable_elem_location
:
59 switch (at
->at_form
) {
63 * DW_FORM_data[48] can not be used as section offset
64 * since DWARF4. For DWARF[23], the application needs
65 * to determine if DW_FORM_data[48] is representing
66 * a constant or a section offset.
68 if (at
->at_die
->die_cu
->cu_version
>= 4) {
69 DWARF_SET_ERROR(dbg
, error
, DW_DLE_NO_ENTRY
);
70 return (DW_DLV_NO_ENTRY
);
73 case DW_FORM_sec_offset
:
74 ret
= _dwarf_loclist_find(dbg
, at
->at_die
->die_cu
,
75 at
->u
[0].u64
, &ll
, error
);
76 if (ret
== DW_DLE_NO_ENTRY
) {
77 DWARF_SET_ERROR(dbg
, error
, ret
);
78 return (DW_DLV_NO_ENTRY
);
80 if (ret
!= DW_DLE_NONE
)
81 return (DW_DLV_ERROR
);
82 *llbuf
= ll
->ll_ldlist
;
83 *listlen
= ll
->ll_ldlen
;
89 if (at
->at_ld
== NULL
) {
90 ret
= _dwarf_loc_add(at
->at_die
, at
, error
);
91 if (ret
!= DW_DLE_NONE
)
92 return (DW_DLV_ERROR
);
99 DWARF_SET_ERROR(dbg
, error
, DW_DLE_ATTR_FORM_BAD
);
100 return (DW_DLV_NO_ENTRY
);
103 /* Wrong attr supplied. */
104 DWARF_SET_ERROR(dbg
, error
, DW_DLE_ARGUMENT
);
105 return (DW_DLV_ERROR
);
110 dwarf_loclist(Dwarf_Attribute at
, Dwarf_Locdesc
**llbuf
,
111 Dwarf_Signed
*listlen
, Dwarf_Error
*error
)
117 dbg
= at
!= NULL
? at
->at_die
->die_dbg
: NULL
;
119 if (at
== NULL
|| llbuf
== NULL
|| listlen
== NULL
) {
120 DWARF_SET_ERROR(dbg
, error
, DW_DLE_ARGUMENT
);
121 return (DW_DLV_ERROR
);
124 switch (at
->at_attrib
) {
126 case DW_AT_string_length
:
127 case DW_AT_return_addr
:
128 case DW_AT_data_member_location
:
129 case DW_AT_frame_base
:
131 case DW_AT_static_link
:
132 case DW_AT_use_location
:
133 case DW_AT_vtable_elem_location
:
134 switch (at
->at_form
) {
138 * DW_FORM_data[48] can not be used as section offset
139 * since DWARF4. For DWARF[23], the application needs
140 * to determine if DW_FORM_data[48] is representing
141 * a constant or a section offset.
143 if (at
->at_die
->die_cu
->cu_version
>= 4) {
144 printf("called cu_version >= 4\n");
145 DWARF_SET_ERROR(dbg
, error
, DW_DLE_NO_ENTRY
);
146 return (DW_DLV_NO_ENTRY
);
149 case DW_FORM_sec_offset
:
150 ret
= _dwarf_loclist_find(at
->at_die
->die_dbg
,
151 at
->at_die
->die_cu
, at
->u
[0].u64
, &ll
, error
);
152 if (ret
== DW_DLE_NO_ENTRY
) {
153 DWARF_SET_ERROR(dbg
, error
, DW_DLV_NO_ENTRY
);
154 return (DW_DLV_NO_ENTRY
);
156 if (ret
!= DW_DLE_NONE
)
157 return (DW_DLV_ERROR
);
158 *llbuf
= ll
->ll_ldlist
[0];
165 if (at
->at_ld
== NULL
) {
166 ret
= _dwarf_loc_add(at
->at_die
, at
, error
);
167 if (ret
!= DW_DLE_NONE
)
168 return (DW_DLV_ERROR
);
174 DWARF_SET_ERROR(dbg
, error
, DW_DLE_ATTR_FORM_BAD
);
175 return (DW_DLV_ERROR
);
178 /* Wrong attr supplied. */
179 DWARF_SET_ERROR(dbg
, error
, DW_DLE_ARGUMENT
);
180 return (DW_DLV_ERROR
);
185 dwarf_get_loclist_entry(Dwarf_Debug dbg
, Dwarf_Unsigned offset
,
186 Dwarf_Addr
*hipc
, Dwarf_Addr
*lopc
, Dwarf_Ptr
*data
,
187 Dwarf_Unsigned
*entry_len
, Dwarf_Unsigned
*next_entry
,
190 Dwarf_Loclist ll
, next_ll
;
195 if (dbg
== NULL
|| hipc
== NULL
|| lopc
== NULL
|| data
== NULL
||
196 entry_len
== NULL
|| next_entry
== NULL
) {
197 DWARF_SET_ERROR(dbg
, error
, DW_DLE_ARGUMENT
);
198 return (DW_DLV_ERROR
);
201 ret
= _dwarf_loclist_find(dbg
, STAILQ_FIRST(&dbg
->dbg_cu
), offset
, &ll
,
203 if (ret
== DW_DLE_NO_ENTRY
) {
204 DWARF_SET_ERROR(dbg
, error
, DW_DLV_NO_ENTRY
);
205 return (DW_DLV_NO_ENTRY
);
206 } else if (ret
!= DW_DLE_NONE
)
207 return (DW_DLV_ERROR
);
210 for (i
= 0; i
< ll
->ll_ldlen
; i
++) {
211 ld
= ll
->ll_ldlist
[i
];
216 if (ld
->ld_lopc
< *lopc
)
218 if (ld
->ld_hipc
> *hipc
)
223 ds
= _dwarf_find_section(dbg
, ".debug_loc");
225 *data
= (uint8_t *) ds
->ds_data
+ ll
->ll_offset
;
226 *entry_len
= ll
->ll_length
;
228 next_ll
= TAILQ_NEXT(ll
, ll_next
);
230 *next_entry
= next_ll
->ll_offset
;
232 *next_entry
= ds
->ds_size
;
238 dwarf_loclist_from_expr(Dwarf_Debug dbg
, Dwarf_Ptr bytes_in
,
239 Dwarf_Unsigned bytes_len
, Dwarf_Locdesc
**llbuf
, Dwarf_Signed
*listlen
,
245 if (dbg
== NULL
|| bytes_in
== NULL
|| bytes_len
== 0 ||
246 llbuf
== NULL
|| listlen
== NULL
) {
247 DWARF_SET_ERROR(dbg
, error
, DW_DLE_ARGUMENT
);
248 return (DW_DLV_ERROR
);
251 ret
= _dwarf_loc_fill_locexpr(dbg
, &ld
, bytes_in
, bytes_len
,
252 dbg
->dbg_pointer_size
, error
);
253 if (ret
!= DW_DLE_NONE
)
254 return (DW_DLV_ERROR
);
263 dwarf_loclist_from_expr_a(Dwarf_Debug dbg
, Dwarf_Ptr bytes_in
,
264 Dwarf_Unsigned bytes_len
, Dwarf_Half addr_size
, Dwarf_Locdesc
**llbuf
,
265 Dwarf_Signed
*listlen
, Dwarf_Error
*error
)
270 if (dbg
== NULL
|| bytes_in
== NULL
|| bytes_len
== 0 ||
271 llbuf
== NULL
|| listlen
== NULL
) {
272 DWARF_SET_ERROR(dbg
, error
, DW_DLE_ARGUMENT
);
273 return (DW_DLV_ERROR
);
276 if (addr_size
!= 4 && addr_size
!= 8) {
277 DWARF_SET_ERROR(dbg
, error
, DW_DLE_ARGUMENT
);
278 return (DW_DLV_ERROR
);
281 ret
= _dwarf_loc_fill_locexpr(dbg
, &ld
, bytes_in
, bytes_len
, addr_size
,
283 if (ret
!= DW_DLE_NONE
)
284 return (DW_DLV_ERROR
);