2 * Copyright (c) 2007 John Birrell (jb@freebsd.org)
3 * Copyright (c) 2009-2011 Kai Wang
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #include "_libdwarf.h"
30 ELFTC_VCSID("$Id: libdwarf_attr.c 3748 2019-06-28 01:11:13Z emaste $");
33 _dwarf_attr_alloc(Dwarf_Die die, Dwarf_Attribute *atp, Dwarf_Error *error)
40 if ((at = calloc(1, sizeof(struct _Dwarf_Attribute))) == NULL) {
41 DWARF_SET_ERROR(die->die_dbg, error, DW_DLE_MEMORY);
42 return (DW_DLE_MEMORY);
51 _dwarf_attr_add(Dwarf_Die die, Dwarf_Attribute atref, Dwarf_Attribute *atp,
57 if ((ret = _dwarf_attr_alloc(die, &at, error)) != DW_DLE_NONE)
60 memcpy(at, atref, sizeof(struct _Dwarf_Attribute));
62 STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
64 /* Save a pointer to the attribute name if this is one. */
65 if (at->at_attrib == DW_AT_name) {
66 switch (at->at_form) {
68 die->die_name = at->u[1].s;
71 die->die_name = at->u[0].s;
85 _dwarf_attr_find(Dwarf_Die die, Dwarf_Half attr)
89 STAILQ_FOREACH(at, &die->die_attr, at_next) {
90 if (at->at_attrib == attr)
98 _dwarf_attr_init(Dwarf_Debug dbg, Dwarf_Section *ds, uint64_t *offsetp,
99 int dwarf_size, Dwarf_CU cu, Dwarf_Die die, Dwarf_AttrDef ad,
100 uint64_t form, int indirect, Dwarf_Error *error)
102 struct _Dwarf_Attribute atref;
106 memset(&atref, 0, sizeof(atref));
108 atref.at_offset = *offsetp;
109 atref.at_attrib = ad->ad_attrib;
110 atref.at_form = indirect ? form : ad->ad_form;
111 atref.at_indirect = indirect;
116 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp,
117 cu->cu_pointer_size);
120 case DW_FORM_exprloc:
121 atref.u[0].u64 = _dwarf_read_uleb128(ds->ds_data, offsetp);
122 atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
126 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 1);
127 atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
131 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 2);
132 atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
136 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 4);
137 atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
143 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 1);
147 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 2);
151 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 4);
155 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 8);
157 case DW_FORM_indirect:
158 form = _dwarf_read_uleb128(ds->ds_data, offsetp);
159 return (_dwarf_attr_init(dbg, ds, offsetp, dwarf_size, cu, die,
160 ad, form, 1, error));
161 case DW_FORM_ref_addr:
162 if (cu->cu_version == 2)
163 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp,
164 cu->cu_pointer_size);
166 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp,
169 case DW_FORM_ref_udata:
171 atref.u[0].u64 = _dwarf_read_uleb128(ds->ds_data, offsetp);
174 atref.u[0].s64 = _dwarf_read_sleb128(ds->ds_data, offsetp);
176 case DW_FORM_sec_offset:
177 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, dwarf_size);
180 atref.u[0].s = _dwarf_read_string(ds->ds_data, ds->ds_size,
184 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, dwarf_size);
185 atref.u[1].s = _dwarf_strtab_get_table(dbg) + atref.u[0].u64;
187 case DW_FORM_ref_sig8:
189 atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
192 case DW_FORM_flag_present:
193 /* This form has no value encoded in the DIE. */
197 DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
198 ret = DW_DLE_ATTR_FORM_BAD;
202 if (ret == DW_DLE_NONE) {
203 if (form == DW_FORM_block || form == DW_FORM_block1 ||
204 form == DW_FORM_block2 || form == DW_FORM_block4) {
205 atref.at_block.bl_len = atref.u[0].u64;
206 atref.at_block.bl_data = atref.u[1].u8p;
208 ret = _dwarf_attr_add(die, &atref, NULL, error);
215 _dwarf_attr_write(Dwarf_P_Debug dbg, Dwarf_P_Section ds, Dwarf_Rel_Section drs,
216 Dwarf_CU cu, Dwarf_Attribute at, int pass2, Dwarf_Error *error)
218 struct _Dwarf_P_Expr_Entry *ee;
219 uint64_t value, offset, bs;
222 assert(dbg != NULL && ds != NULL && cu != NULL && at != NULL);
224 /* Fill in reference to other DIE in the second pass. */
226 if (at->at_form != DW_FORM_ref4 && at->at_form != DW_FORM_ref8)
227 return (DW_DLE_NONE);
228 if (at->at_refdie == NULL || at->at_offset == 0)
229 return (DW_DLE_NONE);
230 offset = at->at_offset;
231 dbg->write(ds->ds_data, &offset, at->at_refdie->die_offset,
232 at->at_form == DW_FORM_ref4 ? 4 : 8);
233 return (DW_DLE_NONE);
236 switch (at->at_form) {
239 ret = _dwarf_reloc_entry_add(dbg, drs, ds,
240 dwarf_drt_data_reloc, cu->cu_pointer_size,
241 ds->ds_size, at->at_relsym, at->u[0].u64, NULL,
244 ret = WRITE_VALUE(at->u[0].u64, cu->cu_pointer_size);
250 /* Write block size. */
251 if (at->at_form == DW_FORM_block) {
252 ret = _dwarf_write_uleb128_alloc(&ds->ds_data,
253 &ds->ds_cap, &ds->ds_size, at->u[0].u64, error);
254 if (ret != DW_DLE_NONE)
257 if (at->at_form == DW_FORM_block1)
259 else if (at->at_form == DW_FORM_block2)
263 ret = WRITE_VALUE(at->u[0].u64, bs);
264 if (ret != DW_DLE_NONE)
268 /* Keep block data offset for later use. */
269 offset = ds->ds_size;
271 /* Write block data. */
272 ret = WRITE_BLOCK(at->u[1].u8p, at->u[0].u64);
273 if (ret != DW_DLE_NONE)
275 if (at->at_expr == NULL)
278 /* Generate relocation entry for DW_OP_addr expressions. */
279 STAILQ_FOREACH(ee, &at->at_expr->pe_eelist, ee_next) {
280 if (ee->ee_loc.lr_atom != DW_OP_addr || ee->ee_sym == 0)
282 ret = _dwarf_reloc_entry_add(dbg, drs, ds,
283 dwarf_drt_data_reloc, dbg->dbg_pointer_size,
284 offset + ee->ee_loc.lr_offset + 1, ee->ee_sym,
285 ee->ee_loc.lr_number, NULL, error);
286 if (ret != DW_DLE_NONE)
293 ret = WRITE_VALUE(at->u[0].u64, 1);
297 ret = WRITE_VALUE(at->u[0].u64, 2);
300 if (at->at_relsym || at->at_relsec != NULL)
301 ret = _dwarf_reloc_entry_add(dbg, drs, ds,
302 dwarf_drt_data_reloc, 4, ds->ds_size, at->at_relsym,
303 at->u[0].u64, at->at_relsec, error);
305 ret = WRITE_VALUE(at->u[0].u64, 4);
308 if (at->at_relsym || at->at_relsec != NULL)
309 ret = _dwarf_reloc_entry_add(dbg, drs, ds,
310 dwarf_drt_data_reloc, 8, ds->ds_size, at->at_relsym,
311 at->u[0].u64, at->at_relsec, error);
313 ret = WRITE_VALUE(at->u[0].u64, 8);
318 * The value of ref4 and ref8 could be a reference to another
319 * DIE within the CU. And if we don't know the ref DIE's
320 * offset at the moement, then we remember at_offset and fill
321 * it in the second pass.
324 value = at->at_refdie->die_offset;
327 at->at_offset = ds->ds_size;
330 value = at->u[0].u64;
331 ret = WRITE_VALUE(value, at->at_form == DW_FORM_ref4 ? 4 : 8);
333 case DW_FORM_indirect:
335 DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
336 ret = DW_DLE_ATTR_FORM_BAD;
338 case DW_FORM_ref_addr:
341 ret = _dwarf_reloc_entry_add(dbg, drs, ds,
342 dwarf_drt_data_reloc, cu->cu_pointer_size,
343 ds->ds_size, at->at_relsym, at->u[0].u64, NULL,
346 ret = WRITE_VALUE(at->u[0].u64, cu->cu_pointer_size);
348 case DW_FORM_ref_udata:
350 ret = WRITE_ULEB128(at->u[0].u64);
353 ret = WRITE_SLEB128(at->u[0].s64);
356 assert(at->u[0].s != NULL);
357 ret = WRITE_STRING(at->u[0].s);
360 ret = _dwarf_reloc_entry_add(dbg, drs, ds, dwarf_drt_data_reloc,
361 4, ds->ds_size, 0, at->u[0].u64, ".debug_str", error);
364 DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
365 ret = DW_DLE_ATTR_FORM_BAD;
373 _dwarf_add_AT_dataref(Dwarf_P_Debug dbg, Dwarf_P_Die die, Dwarf_Half attr,
374 Dwarf_Unsigned pc_value, Dwarf_Unsigned sym_index, const char *secname,
375 Dwarf_P_Attribute *atp, Dwarf_Error *error)
380 assert(dbg != NULL && die != NULL);
382 if ((ret = _dwarf_attr_alloc(die, &at, error)) != DW_DLE_NONE)
386 at->at_attrib = attr;
387 if (dbg->dbg_pointer_size == 4)
388 at->at_form = DW_FORM_data4;
390 at->at_form = DW_FORM_data8;
391 at->at_relsym = sym_index;
392 at->at_relsec = secname;
393 at->u[0].u64 = pc_value;
395 STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
400 return (DW_DLE_NONE);
404 _dwarf_add_string_attr(Dwarf_P_Die die, Dwarf_P_Attribute *atp, Dwarf_Half attr,
405 char *string, Dwarf_Error *error)
411 dbg = die != NULL ? die->die_dbg : NULL;
415 if (die == NULL || string == NULL) {
416 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
417 return (DW_DLE_ARGUMENT);
420 if ((ret = _dwarf_attr_alloc(die, &at, error)) != DW_DLE_NONE)
424 at->at_attrib = attr;
425 at->at_form = DW_FORM_strp;
426 if ((ret = _dwarf_strtab_add(dbg, string, &at->u[0].u64,
427 error)) != DW_DLE_NONE) {
431 at->u[1].s = _dwarf_strtab_get_table(dbg) + at->u[0].u64;
435 STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
437 return (DW_DLE_NONE);
441 _dwarf_attr_gen(Dwarf_P_Debug dbg, Dwarf_P_Section ds, Dwarf_Rel_Section drs,
442 Dwarf_CU cu, Dwarf_Die die, int pass2, Dwarf_Error *error)
447 assert(dbg != NULL && ds != NULL && cu != NULL && die != NULL);
449 STAILQ_FOREACH(at, &die->die_attr, at_next) {
450 ret = _dwarf_attr_write(dbg, ds, drs, cu, at, pass2, error);
451 if (ret != DW_DLE_NONE)
455 return (DW_DLE_NONE);