1 /*-
2 * Copyright (c) 2007 John Birrell (jb@freebsd.org)
3 * Copyright (c) 2009-2011 Kai Wang
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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.
14 *
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
25 * SUCH DAMAGE.
26 */
27
28 #include "_libdwarf.h"
29
30 ELFTC_VCSID("$Id: libdwarf_attr.c 3064 2014-06-06 19:35:55Z kaiwang27 $");
31
32 int
_dwarf_attr_alloc(Dwarf_Die die,Dwarf_Attribute * atp,Dwarf_Error * error)33 _dwarf_attr_alloc(Dwarf_Die die, Dwarf_Attribute *atp, Dwarf_Error *error)
34 {
35 Dwarf_Attribute at;
36
37 assert(die != NULL);
38 assert(atp != NULL);
39
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);
43 }
44
45 *atp = at;
46
47 return (DW_DLE_NONE);
48 }
49
50 static int
_dwarf_attr_add(Dwarf_Die die,Dwarf_Attribute atref,Dwarf_Attribute * atp,Dwarf_Error * error)51 _dwarf_attr_add(Dwarf_Die die, Dwarf_Attribute atref, Dwarf_Attribute *atp,
52 Dwarf_Error *error)
53 {
54 Dwarf_Attribute at;
55 int ret;
56
57 if ((ret = _dwarf_attr_alloc(die, &at, error)) != DW_DLE_NONE)
58 return (ret);
59
60 memcpy(at, atref, sizeof(struct _Dwarf_Attribute));
61
62 STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
63
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) {
67 case DW_FORM_strp:
68 die->die_name = at->u[1].s;
69 break;
70 case DW_FORM_string:
71 die->die_name = at->u[0].s;
72 break;
73 default:
74 break;
75 }
76 }
77
78 if (atp != NULL)
79 *atp = at;
80
81 return (DW_DLE_NONE);
82 }
83
84 Dwarf_Attribute
_dwarf_attr_find(Dwarf_Die die,Dwarf_Half attr)85 _dwarf_attr_find(Dwarf_Die die, Dwarf_Half attr)
86 {
87 Dwarf_Attribute at;
88
89 STAILQ_FOREACH(at, &die->die_attr, at_next) {
90 if (at->at_attrib == attr)
91 break;
92 }
93
94 return (at);
95 }
96
97 int
_dwarf_attr_init(Dwarf_Debug dbg,Dwarf_Section * ds,uint64_t * offsetp,int dwarf_size,Dwarf_CU cu,Dwarf_Die die,Dwarf_AttrDef ad,uint64_t form,int indirect,Dwarf_Error * error)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)
101 {
102 struct _Dwarf_Attribute atref;
103 Dwarf_Section *str;
104 int ret;
105
106 ret = DW_DLE_NONE;
107 memset(&atref, 0, sizeof(atref));
108 atref.at_die = die;
109 atref.at_offset = *offsetp;
110 atref.at_attrib = ad->ad_attrib;
111 atref.at_form = indirect ? form : ad->ad_form;
112 atref.at_indirect = indirect;
113 atref.at_ld = NULL;
114
115 switch (form) {
116 case DW_FORM_addr:
117 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp,
118 cu->cu_pointer_size);
119 break;
120 case DW_FORM_block:
121 case DW_FORM_exprloc:
122 atref.u[0].u64 = _dwarf_read_uleb128(ds->ds_data, offsetp);
123 atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
124 atref.u[0].u64);
125 break;
126 case DW_FORM_block1:
127 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 1);
128 atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
129 atref.u[0].u64);
130 break;
131 case DW_FORM_block2:
132 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 2);
133 atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
134 atref.u[0].u64);
135 break;
136 case DW_FORM_block4:
137 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 4);
138 atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
139 atref.u[0].u64);
140 break;
141 case DW_FORM_data1:
142 case DW_FORM_flag:
143 case DW_FORM_ref1:
144 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 1);
145 break;
146 case DW_FORM_data2:
147 case DW_FORM_ref2:
148 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 2);
149 break;
150 case DW_FORM_data4:
151 case DW_FORM_ref4:
152 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 4);
153 break;
154 case DW_FORM_data8:
155 case DW_FORM_ref8:
156 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 8);
157 break;
158 case DW_FORM_indirect:
159 form = _dwarf_read_uleb128(ds->ds_data, offsetp);
160 return (_dwarf_attr_init(dbg, ds, offsetp, dwarf_size, cu, die,
161 ad, form, 1, error));
162 case DW_FORM_ref_addr:
163 if (cu->cu_version == 2)
164 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp,
165 cu->cu_pointer_size);
166 else
167 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp,
168 dwarf_size);
169 break;
170 case DW_FORM_ref_udata:
171 case DW_FORM_udata:
172 atref.u[0].u64 = _dwarf_read_uleb128(ds->ds_data, offsetp);
173 break;
174 case DW_FORM_sdata:
175 atref.u[0].s64 = _dwarf_read_sleb128(ds->ds_data, offsetp);
176 break;
177 case DW_FORM_sec_offset:
178 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, dwarf_size);
179 break;
180 case DW_FORM_string:
181 atref.u[0].s = _dwarf_read_string(ds->ds_data, ds->ds_size,
182 offsetp);
183 break;
184 case DW_FORM_strp:
185 atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, dwarf_size);
186 str = _dwarf_find_section(dbg, ".debug_str");
187 assert(str != NULL);
188 atref.u[1].s = (char *) str->ds_data + atref.u[0].u64;
189 break;
190 case DW_FORM_ref_sig8:
191 atref.u[0].u64 = 8;
192 atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
193 atref.u[0].u64);
194 break;
195 case DW_FORM_flag_present:
196 /* This form has no value encoded in the DIE. */
197 atref.u[0].u64 = 1;
198 break;
199 default:
200 DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
201 ret = DW_DLE_ATTR_FORM_BAD;
202 break;
203 }
204
205 if (ret == DW_DLE_NONE) {
206 if (form == DW_FORM_block || form == DW_FORM_block1 ||
207 form == DW_FORM_block2 || form == DW_FORM_block4) {
208 atref.at_block.bl_len = atref.u[0].u64;
209 atref.at_block.bl_data = atref.u[1].u8p;
210 }
211 ret = _dwarf_attr_add(die, &atref, NULL, error);
212 }
213
214 return (ret);
215 }
216
217 static int
_dwarf_attr_write(Dwarf_P_Debug dbg,Dwarf_P_Section ds,Dwarf_Rel_Section drs,Dwarf_CU cu,Dwarf_Attribute at,int pass2,Dwarf_Error * error)218 _dwarf_attr_write(Dwarf_P_Debug dbg, Dwarf_P_Section ds, Dwarf_Rel_Section drs,
219 Dwarf_CU cu, Dwarf_Attribute at, int pass2, Dwarf_Error *error)
220 {
221 struct _Dwarf_P_Expr_Entry *ee;
222 uint64_t value, offset, bs;
223 int ret;
224
225 assert(dbg != NULL && ds != NULL && cu != NULL && at != NULL);
226
227 /* Fill in reference to other DIE in the second pass. */
228 if (pass2) {
229 if (at->at_form != DW_FORM_ref4 && at->at_form != DW_FORM_ref8)
230 return (DW_DLE_NONE);
231 if (at->at_refdie == NULL || at->at_offset == 0)
232 return (DW_DLE_NONE);
233 offset = at->at_offset;
234 dbg->write(ds->ds_data, &offset, at->at_refdie->die_offset,
235 at->at_form == DW_FORM_ref4 ? 4 : 8);
236 return (DW_DLE_NONE);
237 }
238
239 switch (at->at_form) {
240 case DW_FORM_addr:
241 if (at->at_relsym)
242 ret = _dwarf_reloc_entry_add(dbg, drs, ds,
243 dwarf_drt_data_reloc, cu->cu_pointer_size,
244 ds->ds_size, at->at_relsym, at->u[0].u64, NULL,
245 error);
246 else
247 ret = WRITE_VALUE(at->u[0].u64, cu->cu_pointer_size);
248 break;
249 case DW_FORM_block:
250 case DW_FORM_block1:
251 case DW_FORM_block2:
252 case DW_FORM_block4:
253 /* Write block size. */
254 if (at->at_form == DW_FORM_block) {
255 ret = _dwarf_write_uleb128_alloc(&ds->ds_data,
256 &ds->ds_cap, &ds->ds_size, at->u[0].u64, error);
257 if (ret != DW_DLE_NONE)
258 break;
259 } else {
260 if (at->at_form == DW_FORM_block1)
261 bs = 1;
262 else if (at->at_form == DW_FORM_block2)
263 bs = 2;
264 else
265 bs = 4;
266 ret = WRITE_VALUE(at->u[0].u64, bs);
267 if (ret != DW_DLE_NONE)
268 break;
269 }
270
271 /* Keep block data offset for later use. */
272 offset = ds->ds_size;
273
274 /* Write block data. */
275 ret = WRITE_BLOCK(at->u[1].u8p, at->u[0].u64);
276 if (ret != DW_DLE_NONE)
277 break;
278 if (at->at_expr == NULL)
279 break;
280
281 /* Generate relocation entry for DW_OP_addr expressions. */
282 STAILQ_FOREACH(ee, &at->at_expr->pe_eelist, ee_next) {
283 if (ee->ee_loc.lr_atom != DW_OP_addr || ee->ee_sym == 0)
284 continue;
285 ret = _dwarf_reloc_entry_add(dbg, drs, ds,
286 dwarf_drt_data_reloc, dbg->dbg_pointer_size,
287 offset + ee->ee_loc.lr_offset + 1, ee->ee_sym,
288 ee->ee_loc.lr_number, NULL, error);
289 if (ret != DW_DLE_NONE)
290 break;
291 }
292 break;
293 case DW_FORM_data1:
294 case DW_FORM_flag:
295 case DW_FORM_ref1:
296 ret = WRITE_VALUE(at->u[0].u64, 1);
297 break;
298 case DW_FORM_data2:
299 case DW_FORM_ref2:
300 ret = WRITE_VALUE(at->u[0].u64, 2);
301 break;
302 case DW_FORM_data4:
303 if (at->at_relsym || at->at_relsec != NULL)
304 ret = _dwarf_reloc_entry_add(dbg, drs, ds,
305 dwarf_drt_data_reloc, 4, ds->ds_size, at->at_relsym,
306 at->u[0].u64, at->at_relsec, error);
307 else
308 ret = WRITE_VALUE(at->u[0].u64, 4);
309 break;
310 case DW_FORM_data8:
311 if (at->at_relsym || at->at_relsec != NULL)
312 ret = _dwarf_reloc_entry_add(dbg, drs, ds,
313 dwarf_drt_data_reloc, 8, ds->ds_size, at->at_relsym,
314 at->u[0].u64, at->at_relsec, error);
315 else
316 ret = WRITE_VALUE(at->u[0].u64, 8);
317 break;
318 case DW_FORM_ref4:
319 case DW_FORM_ref8:
320 /*
321 * The value of ref4 and ref8 could be a reference to another
322 * DIE within the CU. And if we don't know the ref DIE's
323 * offset at the moement, then we remember at_offset and fill
324 * it in the second pass.
325 */
326 if (at->at_refdie) {
327 value = at->at_refdie->die_offset;
328 if (value == 0) {
329 cu->cu_pass2 = 1;
330 at->at_offset = ds->ds_size;
331 }
332 } else
333 value = at->u[0].u64;
334 ret = WRITE_VALUE(value, at->at_form == DW_FORM_ref4 ? 4 : 8);
335 break;
336 case DW_FORM_indirect:
337 /* TODO. */
338 DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
339 ret = DW_DLE_ATTR_FORM_BAD;
340 break;
341 case DW_FORM_ref_addr:
342 /* DWARF2 format. */
343 if (at->at_relsym)
344 ret = _dwarf_reloc_entry_add(dbg, drs, ds,
345 dwarf_drt_data_reloc, cu->cu_pointer_size,
346 ds->ds_size, at->at_relsym, at->u[0].u64, NULL,
347 error);
348 else
349 ret = WRITE_VALUE(at->u[0].u64, cu->cu_pointer_size);
350 break;
351 case DW_FORM_ref_udata:
352 case DW_FORM_udata:
353 ret = WRITE_ULEB128(at->u[0].u64);
354 break;
355 case DW_FORM_sdata:
356 ret = WRITE_SLEB128(at->u[0].s64);
357 break;
358 case DW_FORM_string:
359 assert(at->u[0].s != NULL);
360 ret = WRITE_STRING(at->u[0].s);
361 break;
362 case DW_FORM_strp:
363 ret = _dwarf_reloc_entry_add(dbg, drs, ds, dwarf_drt_data_reloc,
364 4, ds->ds_size, 0, at->u[0].u64, ".debug_str", error);
365 break;
366 default:
367 DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
368 ret = DW_DLE_ATTR_FORM_BAD;
369 break;
370 }
371
372 return (ret);
373 }
374
375 int
_dwarf_add_AT_dataref(Dwarf_P_Debug dbg,Dwarf_P_Die die,Dwarf_Half attr,Dwarf_Unsigned pc_value,Dwarf_Unsigned sym_index,const char * secname,Dwarf_P_Attribute * atp,Dwarf_Error * error)376 _dwarf_add_AT_dataref(Dwarf_P_Debug dbg, Dwarf_P_Die die, Dwarf_Half attr,
377 Dwarf_Unsigned pc_value, Dwarf_Unsigned sym_index, const char *secname,
378 Dwarf_P_Attribute *atp, Dwarf_Error *error)
379 {
380 Dwarf_Attribute at;
381 int ret;
382
383 assert(dbg != NULL && die != NULL);
384
385 if ((ret = _dwarf_attr_alloc(die, &at, error)) != DW_DLE_NONE)
386 return (ret);
387
388 at->at_die = die;
389 at->at_attrib = attr;
390 if (dbg->dbg_pointer_size == 4)
391 at->at_form = DW_FORM_data4;
392 else
393 at->at_form = DW_FORM_data8;
394 at->at_relsym = sym_index;
395 at->at_relsec = secname;
396 at->u[0].u64 = pc_value;
397
398 STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
399
400 if (atp)
401 *atp = at;
402
403 return (DW_DLE_NONE);
404 }
405
406 int
_dwarf_add_string_attr(Dwarf_P_Die die,Dwarf_P_Attribute * atp,Dwarf_Half attr,char * string,Dwarf_Error * error)407 _dwarf_add_string_attr(Dwarf_P_Die die, Dwarf_P_Attribute *atp, Dwarf_Half attr,
408 char *string, Dwarf_Error *error)
409 {
410 Dwarf_Attribute at;
411 Dwarf_Debug dbg;
412 int ret;
413
414 dbg = die != NULL ? die->die_dbg : NULL;
415
416 assert(atp != NULL);
417
418 if (die == NULL || string == NULL) {
419 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
420 return (DW_DLE_ARGUMENT);
421 }
422
423 if ((ret = _dwarf_attr_alloc(die, &at, error)) != DW_DLE_NONE)
424 return (ret);
425
426 at->at_die = die;
427 at->at_attrib = attr;
428 at->at_form = DW_FORM_strp;
429 if ((ret = _dwarf_strtab_add(dbg, string, &at->u[0].u64,
430 error)) != DW_DLE_NONE) {
431 free(at);
432 return (ret);
433 }
434 at->u[1].s = _dwarf_strtab_get_table(dbg) + at->u[0].u64;
435
436 *atp = at;
437
438 STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
439
440 return (DW_DLE_NONE);
441 }
442
443 int
_dwarf_attr_gen(Dwarf_P_Debug dbg,Dwarf_P_Section ds,Dwarf_Rel_Section drs,Dwarf_CU cu,Dwarf_Die die,int pass2,Dwarf_Error * error)444 _dwarf_attr_gen(Dwarf_P_Debug dbg, Dwarf_P_Section ds, Dwarf_Rel_Section drs,
445 Dwarf_CU cu, Dwarf_Die die, int pass2, Dwarf_Error *error)
446 {
447 Dwarf_Attribute at;
448 int ret;
449
450 assert(dbg != NULL && ds != NULL && cu != NULL && die != NULL);
451
452 STAILQ_FOREACH(at, &die->die_attr, at_next) {
453 ret = _dwarf_attr_write(dbg, ds, drs, cu, at, pass2, error);
454 if (ret != DW_DLE_NONE)
455 return (ret);
456 }
457
458 return (DW_DLE_NONE);
459 }
460