1 /* $NetBSD: libdwarf_attr.c,v 1.2 2014/03/09 16:58:04 christos Exp $ */
4 * Copyright (c) 2007 John Birrell (jb@freebsd.org)
5 * Copyright (c) 2009-2011 Kai Wang
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include "_libdwarf.h"
32 __RCSID("$NetBSD: libdwarf_attr.c,v 1.2 2014/03/09 16:58:04 christos Exp $");
33 ELFTC_VCSID("Id: libdwarf_attr.c 2966 2013-09-21 14:40:14Z kaiwang27 ");
36 _dwarf_attr_alloc(Dwarf_Die die
, Dwarf_Attribute
*atp
, Dwarf_Error
*error
)
43 if ((at
= calloc(1, sizeof(struct _Dwarf_Attribute
))) == NULL
) {
44 DWARF_SET_ERROR(die
->die_dbg
, error
, DW_DLE_MEMORY
);
45 return (DW_DLE_MEMORY
);
54 _dwarf_attr_add(Dwarf_Die die
, Dwarf_Attribute atref
, Dwarf_Attribute
*atp
,
60 if ((ret
= _dwarf_attr_alloc(die
, &at
, error
)) != DW_DLE_NONE
)
63 memcpy(at
, atref
, sizeof(struct _Dwarf_Attribute
));
65 STAILQ_INSERT_TAIL(&die
->die_attr
, at
, at_next
);
67 /* Save a pointer to the attribute name if this is one. */
68 if (at
->at_attrib
== DW_AT_name
) {
69 switch (at
->at_form
) {
71 die
->die_name
= at
->u
[1].s
;
74 die
->die_name
= at
->u
[0].s
;
88 _dwarf_attr_find(Dwarf_Die die
, Dwarf_Half attr
)
92 STAILQ_FOREACH(at
, &die
->die_attr
, at_next
) {
93 if (at
->at_attrib
== attr
)
101 _dwarf_attr_init(Dwarf_Debug dbg
, Dwarf_Section
*ds
, uint64_t *offsetp
,
102 int dwarf_size
, Dwarf_CU cu
, Dwarf_Die die
, Dwarf_AttrDef ad
,
103 uint64_t form
, int indirect
, Dwarf_Error
*error
)
105 struct _Dwarf_Attribute atref
;
110 memset(&atref
, 0, sizeof(atref
));
112 atref
.at_attrib
= ad
->ad_attrib
;
113 atref
.at_form
= indirect
? form
: ad
->ad_form
;
114 atref
.at_indirect
= indirect
;
119 atref
.u
[0].u64
= dbg
->read(ds
->ds_data
, offsetp
,
120 cu
->cu_pointer_size
);
123 case DW_FORM_exprloc
:
124 atref
.u
[0].u64
= _dwarf_read_uleb128(ds
->ds_data
, offsetp
);
125 atref
.u
[1].u8p
= _dwarf_read_block(ds
->ds_data
, offsetp
,
129 atref
.u
[0].u64
= dbg
->read(ds
->ds_data
, offsetp
, 1);
130 atref
.u
[1].u8p
= _dwarf_read_block(ds
->ds_data
, offsetp
,
134 atref
.u
[0].u64
= dbg
->read(ds
->ds_data
, offsetp
, 2);
135 atref
.u
[1].u8p
= _dwarf_read_block(ds
->ds_data
, offsetp
,
139 atref
.u
[0].u64
= dbg
->read(ds
->ds_data
, offsetp
, 4);
140 atref
.u
[1].u8p
= _dwarf_read_block(ds
->ds_data
, offsetp
,
146 atref
.u
[0].u64
= dbg
->read(ds
->ds_data
, offsetp
, 1);
150 atref
.u
[0].u64
= dbg
->read(ds
->ds_data
, offsetp
, 2);
154 atref
.u
[0].u64
= dbg
->read(ds
->ds_data
, offsetp
, 4);
158 atref
.u
[0].u64
= dbg
->read(ds
->ds_data
, offsetp
, 8);
160 case DW_FORM_indirect
:
161 form
= _dwarf_read_uleb128(ds
->ds_data
, offsetp
);
162 return (_dwarf_attr_init(dbg
, ds
, offsetp
, dwarf_size
, cu
, die
,
163 ad
, form
, 1, error
));
164 case DW_FORM_ref_addr
:
165 if (cu
->cu_version
== 2)
166 atref
.u
[0].u64
= dbg
->read(ds
->ds_data
, offsetp
,
167 cu
->cu_pointer_size
);
168 else if (cu
->cu_version
== 3)
169 atref
.u
[0].u64
= dbg
->read(ds
->ds_data
, offsetp
,
172 case DW_FORM_ref_udata
:
174 atref
.u
[0].u64
= _dwarf_read_uleb128(ds
->ds_data
, offsetp
);
177 atref
.u
[0].s64
= _dwarf_read_sleb128(ds
->ds_data
, offsetp
);
179 case DW_FORM_sec_offset
:
180 atref
.u
[0].u64
= dbg
->read(ds
->ds_data
, offsetp
, dwarf_size
);
183 atref
.u
[0].s
= _dwarf_read_string(ds
->ds_data
, ds
->ds_size
,
187 atref
.u
[0].u64
= dbg
->read(ds
->ds_data
, offsetp
, dwarf_size
);
188 str
= _dwarf_find_section(dbg
, ".debug_str");
190 atref
.u
[1].s
= (char *) str
->ds_data
+ atref
.u
[0].u64
;
192 case DW_FORM_ref_sig8
:
194 atref
.u
[1].u8p
= _dwarf_read_block(ds
->ds_data
, offsetp
,
197 case DW_FORM_flag_present
:
198 /* This form has no value encoded in the DIE. */
202 DWARF_SET_ERROR(dbg
, error
, DW_DLE_ATTR_FORM_BAD
);
203 ret
= DW_DLE_ATTR_FORM_BAD
;
207 if (ret
== DW_DLE_NONE
) {
208 if (form
== DW_FORM_block
|| form
== DW_FORM_block1
||
209 form
== DW_FORM_block2
|| form
== DW_FORM_block4
) {
210 atref
.at_block
.bl_len
= atref
.u
[0].u64
;
211 atref
.at_block
.bl_data
= atref
.u
[1].u8p
;
213 ret
= _dwarf_attr_add(die
, &atref
, NULL
, error
);
220 _dwarf_attr_write(Dwarf_P_Debug dbg
, Dwarf_P_Section ds
, Dwarf_Rel_Section drs
,
221 Dwarf_CU cu
, Dwarf_Attribute at
, int pass2
, Dwarf_Error
*error
)
223 struct _Dwarf_P_Expr_Entry
*ee
;
224 uint64_t value
, offset
, bs
;
227 assert(dbg
!= NULL
&& ds
!= NULL
&& cu
!= NULL
&& at
!= NULL
);
229 /* Fill in reference to other DIE in the second pass. */
231 if (at
->at_form
!= DW_FORM_ref4
&& at
->at_form
!= DW_FORM_ref8
)
232 return (DW_DLE_NONE
);
233 if (at
->at_refdie
== NULL
|| at
->at_offset
== 0)
234 return (DW_DLE_NONE
);
235 offset
= at
->at_offset
;
236 dbg
->write(ds
->ds_data
, &offset
, at
->at_refdie
->die_offset
,
237 at
->at_form
== DW_FORM_ref4
? 4 : 8);
238 return (DW_DLE_NONE
);
241 switch (at
->at_form
) {
244 ret
= _dwarf_reloc_entry_add(dbg
, drs
, ds
,
245 dwarf_drt_data_reloc
, cu
->cu_pointer_size
,
246 ds
->ds_size
, at
->at_relsym
, at
->u
[0].u64
, NULL
,
249 ret
= WRITE_VALUE(at
->u
[0].u64
, cu
->cu_pointer_size
);
255 /* Write block size. */
256 if (at
->at_form
== DW_FORM_block
) {
257 ret
= _dwarf_write_uleb128_alloc(&ds
->ds_data
,
258 &ds
->ds_cap
, &ds
->ds_size
, at
->u
[0].u64
, error
);
259 if (ret
!= DW_DLE_NONE
)
262 if (at
->at_form
== DW_FORM_block1
)
264 else if (at
->at_form
== DW_FORM_block2
)
268 ret
= WRITE_VALUE(at
->u
[0].u64
, bs
);
269 if (ret
!= DW_DLE_NONE
)
273 /* Keep block data offset for later use. */
274 offset
= ds
->ds_size
;
276 /* Write block data. */
277 ret
= WRITE_BLOCK(at
->u
[1].u8p
, at
->u
[0].u64
);
278 if (ret
!= DW_DLE_NONE
)
280 if (at
->at_expr
== NULL
)
283 /* Generate relocation entry for DW_OP_addr expressions. */
284 STAILQ_FOREACH(ee
, &at
->at_expr
->pe_eelist
, ee_next
) {
285 if (ee
->ee_loc
.lr_atom
!= DW_OP_addr
|| ee
->ee_sym
== 0)
287 ret
= _dwarf_reloc_entry_add(dbg
, drs
, ds
,
288 dwarf_drt_data_reloc
, dbg
->dbg_pointer_size
,
289 offset
+ ee
->ee_loc
.lr_offset
+ 1, ee
->ee_sym
,
290 ee
->ee_loc
.lr_number
, NULL
, error
);
291 if (ret
!= DW_DLE_NONE
)
298 ret
= WRITE_VALUE(at
->u
[0].u64
, 1);
302 ret
= WRITE_VALUE(at
->u
[0].u64
, 2);
305 if (at
->at_relsym
|| at
->at_relsec
!= NULL
)
306 ret
= _dwarf_reloc_entry_add(dbg
, drs
, ds
,
307 dwarf_drt_data_reloc
, 4, ds
->ds_size
, at
->at_relsym
,
308 at
->u
[0].u64
, at
->at_relsec
, error
);
310 ret
= WRITE_VALUE(at
->u
[0].u64
, 4);
313 if (at
->at_relsym
|| at
->at_relsec
!= NULL
)
314 ret
= _dwarf_reloc_entry_add(dbg
, drs
, ds
,
315 dwarf_drt_data_reloc
, 8, ds
->ds_size
, at
->at_relsym
,
316 at
->u
[0].u64
, at
->at_relsec
, error
);
318 ret
= WRITE_VALUE(at
->u
[0].u64
, 8);
323 * The value of ref4 and ref8 could be a reference to another
324 * DIE within the CU. And if we don't know the ref DIE's
325 * offset at the moement, then we remember at_offset and fill
326 * it in the second pass.
329 value
= at
->at_refdie
->die_offset
;
332 at
->at_offset
= ds
->ds_size
;
335 value
= at
->u
[0].u64
;
336 ret
= WRITE_VALUE(value
, at
->at_form
== DW_FORM_ref4
? 4 : 8);
338 case DW_FORM_indirect
:
340 DWARF_SET_ERROR(dbg
, error
, DW_DLE_ATTR_FORM_BAD
);
341 ret
= DW_DLE_ATTR_FORM_BAD
;
343 case DW_FORM_ref_addr
:
346 ret
= _dwarf_reloc_entry_add(dbg
, drs
, ds
,
347 dwarf_drt_data_reloc
, cu
->cu_pointer_size
,
348 ds
->ds_size
, at
->at_relsym
, at
->u
[0].u64
, NULL
,
351 ret
= WRITE_VALUE(at
->u
[0].u64
, cu
->cu_pointer_size
);
353 case DW_FORM_ref_udata
:
355 ret
= WRITE_ULEB128(at
->u
[0].u64
);
358 ret
= WRITE_SLEB128(at
->u
[0].s64
);
361 assert(at
->u
[0].s
!= NULL
);
362 ret
= WRITE_STRING(at
->u
[0].s
);
365 ret
= _dwarf_reloc_entry_add(dbg
, drs
, ds
, dwarf_drt_data_reloc
,
366 4, ds
->ds_size
, 0, at
->u
[0].u64
, ".debug_str", error
);
369 DWARF_SET_ERROR(dbg
, error
, DW_DLE_ATTR_FORM_BAD
);
370 ret
= DW_DLE_ATTR_FORM_BAD
;
378 _dwarf_add_AT_dataref(Dwarf_P_Debug dbg
, Dwarf_P_Die die
, Dwarf_Half attr
,
379 Dwarf_Unsigned pc_value
, Dwarf_Unsigned sym_index
, const char *secname
,
380 Dwarf_P_Attribute
*atp
, Dwarf_Error
*error
)
385 assert(dbg
!= NULL
&& die
!= NULL
);
387 if ((ret
= _dwarf_attr_alloc(die
, &at
, error
)) != DW_DLE_NONE
)
391 at
->at_attrib
= attr
;
392 if (dbg
->dbg_pointer_size
== 4)
393 at
->at_form
= DW_FORM_data4
;
395 at
->at_form
= DW_FORM_data8
;
396 at
->at_relsym
= sym_index
;
397 at
->at_relsec
= secname
;
398 at
->u
[0].u64
= pc_value
;
400 STAILQ_INSERT_TAIL(&die
->die_attr
, at
, at_next
);
405 return (DW_DLE_NONE
);
409 _dwarf_add_string_attr(Dwarf_P_Die die
, Dwarf_P_Attribute
*atp
, Dwarf_Half attr
,
410 char *string
, Dwarf_Error
*error
)
416 dbg
= die
!= NULL
? die
->die_dbg
: NULL
;
420 if (die
== NULL
|| string
== NULL
) {
421 DWARF_SET_ERROR(dbg
, error
, DW_DLE_ARGUMENT
);
422 return (DW_DLE_ARGUMENT
);
425 if ((ret
= _dwarf_attr_alloc(die
, &at
, error
)) != DW_DLE_NONE
)
429 at
->at_attrib
= attr
;
430 at
->at_form
= DW_FORM_strp
;
431 if ((ret
= _dwarf_strtab_add(dbg
, string
, &at
->u
[0].u64
,
432 error
)) != DW_DLE_NONE
) {
436 at
->u
[1].s
= _dwarf_strtab_get_table(dbg
) + at
->u
[0].u64
;
440 STAILQ_INSERT_TAIL(&die
->die_attr
, at
, at_next
);
442 return (DW_DLE_NONE
);
446 _dwarf_attr_gen(Dwarf_P_Debug dbg
, Dwarf_P_Section ds
, Dwarf_Rel_Section drs
,
447 Dwarf_CU cu
, Dwarf_Die die
, int pass2
, Dwarf_Error
*error
)
452 assert(dbg
!= NULL
&& ds
!= NULL
&& cu
!= NULL
&& die
!= NULL
);
454 STAILQ_FOREACH(at
, &die
->die_attr
, at_next
) {
455 ret
= _dwarf_attr_write(dbg
, ds
, drs
, cu
, at
, pass2
, error
);
456 if (ret
!= DW_DLE_NONE
)
460 return (DW_DLE_NONE
);