xref: /freebsd/contrib/elftoolchain/libdwarf/libdwarf_attr.c (revision 9ecd54f24fe9fa373e07c9fd7c052deb2188f545)
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 2966 2013-09-21 14:40:14Z kaiwang27 $");
31 
32 int
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
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
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
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_attrib = ad->ad_attrib;
110 	atref.at_form = indirect ? form : ad->ad_form;
111 	atref.at_indirect = indirect;
112 	atref.at_ld = NULL;
113 
114 	switch (form) {
115 	case DW_FORM_addr:
116 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp,
117 		    cu->cu_pointer_size);
118 		break;
119 	case DW_FORM_block:
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,
123 		    atref.u[0].u64);
124 		break;
125 	case DW_FORM_block1:
126 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 1);
127 		atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
128 		    atref.u[0].u64);
129 		break;
130 	case DW_FORM_block2:
131 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 2);
132 		atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
133 		    atref.u[0].u64);
134 		break;
135 	case DW_FORM_block4:
136 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 4);
137 		atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
138 		    atref.u[0].u64);
139 		break;
140 	case DW_FORM_data1:
141 	case DW_FORM_flag:
142 	case DW_FORM_ref1:
143 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 1);
144 		break;
145 	case DW_FORM_data2:
146 	case DW_FORM_ref2:
147 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 2);
148 		break;
149 	case DW_FORM_data4:
150 	case DW_FORM_ref4:
151 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 4);
152 		break;
153 	case DW_FORM_data8:
154 	case DW_FORM_ref8:
155 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, 8);
156 		break;
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);
165 		else if (cu->cu_version == 3)
166 			atref.u[0].u64 = dbg->read(ds->ds_data, offsetp,
167 			    dwarf_size);
168 		break;
169 	case DW_FORM_ref_udata:
170 	case DW_FORM_udata:
171 		atref.u[0].u64 = _dwarf_read_uleb128(ds->ds_data, offsetp);
172 		break;
173 	case DW_FORM_sdata:
174 		atref.u[0].s64 = _dwarf_read_sleb128(ds->ds_data, offsetp);
175 		break;
176 	case DW_FORM_sec_offset:
177 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, dwarf_size);
178 		break;
179 	case DW_FORM_string:
180 		atref.u[0].s = _dwarf_read_string(ds->ds_data, ds->ds_size,
181 		    offsetp);
182 		break;
183 	case DW_FORM_strp:
184 		atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, dwarf_size);
185 		str = _dwarf_find_section(dbg, ".debug_str");
186 		assert(str != NULL);
187 		atref.u[1].s = (char *) str->ds_data + atref.u[0].u64;
188 		break;
189 	case DW_FORM_ref_sig8:
190 		atref.u[0].u64 = 8;
191 		atref.u[1].u8p = _dwarf_read_block(ds->ds_data, offsetp,
192 		    atref.u[0].u64);
193 		break;
194 	case DW_FORM_flag_present:
195 		/* This form has no value encoded in the DIE. */
196 		atref.u[0].u64 = 1;
197 		break;
198 	default:
199 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
200 		ret = DW_DLE_ATTR_FORM_BAD;
201 		break;
202 	}
203 
204 	if (ret == DW_DLE_NONE) {
205 		if (form == DW_FORM_block || form == DW_FORM_block1 ||
206 		    form == DW_FORM_block2 || form == DW_FORM_block4) {
207 			atref.at_block.bl_len = atref.u[0].u64;
208 			atref.at_block.bl_data = atref.u[1].u8p;
209 		}
210 		ret = _dwarf_attr_add(die, &atref, NULL, error);
211 	}
212 
213 	return (ret);
214 }
215 
216 static int
217 _dwarf_attr_write(Dwarf_P_Debug dbg, Dwarf_P_Section ds, Dwarf_Rel_Section drs,
218     Dwarf_CU cu, Dwarf_Attribute at, int pass2, Dwarf_Error *error)
219 {
220 	struct _Dwarf_P_Expr_Entry *ee;
221 	uint64_t value, offset, bs;
222 	int ret;
223 
224 	assert(dbg != NULL && ds != NULL && cu != NULL && at != NULL);
225 
226 	/* Fill in reference to other DIE in the second pass. */
227 	if (pass2) {
228 		if (at->at_form != DW_FORM_ref4 && at->at_form != DW_FORM_ref8)
229 			return (DW_DLE_NONE);
230 		if (at->at_refdie == NULL || at->at_offset == 0)
231 			return (DW_DLE_NONE);
232 		offset = at->at_offset;
233 		dbg->write(ds->ds_data, &offset, at->at_refdie->die_offset,
234 		    at->at_form == DW_FORM_ref4 ? 4 : 8);
235 		return (DW_DLE_NONE);
236 	}
237 
238 	switch (at->at_form) {
239 	case DW_FORM_addr:
240 		if (at->at_relsym)
241 			ret = _dwarf_reloc_entry_add(dbg, drs, ds,
242 			    dwarf_drt_data_reloc, cu->cu_pointer_size,
243 			    ds->ds_size, at->at_relsym, at->u[0].u64, NULL,
244 			    error);
245 		else
246 			ret = WRITE_VALUE(at->u[0].u64, cu->cu_pointer_size);
247 		break;
248 	case DW_FORM_block:
249 	case DW_FORM_block1:
250 	case DW_FORM_block2:
251 	case DW_FORM_block4:
252 		/* Write block size. */
253 		if (at->at_form == DW_FORM_block) {
254 			ret = _dwarf_write_uleb128_alloc(&ds->ds_data,
255 			    &ds->ds_cap, &ds->ds_size, at->u[0].u64, error);
256 			if (ret != DW_DLE_NONE)
257 				break;
258 		} else {
259 			if (at->at_form == DW_FORM_block1)
260 				bs = 1;
261 			else if (at->at_form == DW_FORM_block2)
262 				bs = 2;
263 			else
264 				bs = 4;
265 			ret = WRITE_VALUE(at->u[0].u64, bs);
266 			if (ret != DW_DLE_NONE)
267 				break;
268 		}
269 
270 		/* Keep block data offset for later use. */
271 		offset = ds->ds_size;
272 
273 		/* Write block data. */
274 		ret = WRITE_BLOCK(at->u[1].u8p, at->u[0].u64);
275 		if (ret != DW_DLE_NONE)
276 			break;
277 		if (at->at_expr == NULL)
278 			break;
279 
280 		/* Generate relocation entry for DW_OP_addr expressions. */
281 		STAILQ_FOREACH(ee, &at->at_expr->pe_eelist, ee_next) {
282 			if (ee->ee_loc.lr_atom != DW_OP_addr || ee->ee_sym == 0)
283 				continue;
284 			ret = _dwarf_reloc_entry_add(dbg, drs, ds,
285 			    dwarf_drt_data_reloc, dbg->dbg_pointer_size,
286 			    offset + ee->ee_loc.lr_offset + 1, ee->ee_sym,
287 			    ee->ee_loc.lr_number, NULL, error);
288 			if (ret != DW_DLE_NONE)
289 				break;
290 		}
291 		break;
292 	case DW_FORM_data1:
293 	case DW_FORM_flag:
294 	case DW_FORM_ref1:
295 		ret = WRITE_VALUE(at->u[0].u64, 1);
296 		break;
297 	case DW_FORM_data2:
298 	case DW_FORM_ref2:
299 		ret = WRITE_VALUE(at->u[0].u64, 2);
300 		break;
301 	case DW_FORM_data4:
302 		if (at->at_relsym || at->at_relsec != NULL)
303 			ret = _dwarf_reloc_entry_add(dbg, drs, ds,
304 			    dwarf_drt_data_reloc, 4, ds->ds_size, at->at_relsym,
305 			    at->u[0].u64, at->at_relsec, error);
306 		else
307 			ret = WRITE_VALUE(at->u[0].u64, 4);
308 		break;
309 	case DW_FORM_data8:
310 		if (at->at_relsym || at->at_relsec != NULL)
311 			ret = _dwarf_reloc_entry_add(dbg, drs, ds,
312 			    dwarf_drt_data_reloc, 8, ds->ds_size, at->at_relsym,
313 			    at->u[0].u64, at->at_relsec, error);
314 		else
315 			ret = WRITE_VALUE(at->u[0].u64, 8);
316 		break;
317 	case DW_FORM_ref4:
318 	case DW_FORM_ref8:
319 		/*
320 		 * The value of ref4 and ref8 could be a reference to another
321 		 * DIE within the CU. And if we don't know the ref DIE's
322 		 * offset at the moement, then we remember at_offset and fill
323 		 * it in the second pass.
324 		 */
325 		if (at->at_refdie) {
326 			value = at->at_refdie->die_offset;
327 			if (value == 0) {
328 				cu->cu_pass2 = 1;
329 				at->at_offset = ds->ds_size;
330 			}
331 		} else
332 			value = at->u[0].u64;
333 		ret = WRITE_VALUE(value, at->at_form == DW_FORM_ref4 ? 4 : 8);
334 		break;
335 	case DW_FORM_indirect:
336 		/* TODO. */
337 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
338 		ret = DW_DLE_ATTR_FORM_BAD;
339 		break;
340 	case DW_FORM_ref_addr:
341 		/* DWARF2 format. */
342 		if (at->at_relsym)
343 			ret = _dwarf_reloc_entry_add(dbg, drs, ds,
344 			    dwarf_drt_data_reloc, cu->cu_pointer_size,
345 			    ds->ds_size, at->at_relsym, at->u[0].u64, NULL,
346 			    error);
347 		else
348 			ret = WRITE_VALUE(at->u[0].u64, cu->cu_pointer_size);
349 		break;
350 	case DW_FORM_ref_udata:
351 	case DW_FORM_udata:
352 		ret = WRITE_ULEB128(at->u[0].u64);
353 		break;
354 	case DW_FORM_sdata:
355 		ret = WRITE_SLEB128(at->u[0].s64);
356 		break;
357 	case DW_FORM_string:
358 		assert(at->u[0].s != NULL);
359 		ret = WRITE_STRING(at->u[0].s);
360 		break;
361 	case DW_FORM_strp:
362 		ret = _dwarf_reloc_entry_add(dbg, drs, ds, dwarf_drt_data_reloc,
363 		    4, ds->ds_size, 0, at->u[0].u64, ".debug_str", error);
364 		break;
365 	default:
366 		DWARF_SET_ERROR(dbg, error, DW_DLE_ATTR_FORM_BAD);
367 		ret = DW_DLE_ATTR_FORM_BAD;
368 		break;
369 	}
370 
371 	return (ret);
372 }
373 
374 int
375 _dwarf_add_AT_dataref(Dwarf_P_Debug dbg, Dwarf_P_Die die, Dwarf_Half attr,
376     Dwarf_Unsigned pc_value, Dwarf_Unsigned sym_index, const char *secname,
377     Dwarf_P_Attribute *atp, Dwarf_Error *error)
378 {
379 	Dwarf_Attribute at;
380 	int ret;
381 
382 	assert(dbg != NULL && die != NULL);
383 
384 	if ((ret = _dwarf_attr_alloc(die, &at, error)) != DW_DLE_NONE)
385 		return (ret);
386 
387 	at->at_die = die;
388 	at->at_attrib = attr;
389 	if (dbg->dbg_pointer_size == 4)
390 		at->at_form = DW_FORM_data4;
391 	else
392 		at->at_form = DW_FORM_data8;
393 	at->at_relsym = sym_index;
394 	at->at_relsec = secname;
395 	at->u[0].u64 = pc_value;
396 
397 	STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
398 
399 	if (atp)
400 		*atp = at;
401 
402 	return (DW_DLE_NONE);
403 }
404 
405 int
406 _dwarf_add_string_attr(Dwarf_P_Die die, Dwarf_P_Attribute *atp, Dwarf_Half attr,
407     char *string, Dwarf_Error *error)
408 {
409 	Dwarf_Attribute at;
410 	Dwarf_Debug dbg;
411 	int ret;
412 
413 	dbg = die != NULL ? die->die_dbg : NULL;
414 
415 	assert(atp != NULL);
416 
417 	if (die == NULL || string == NULL) {
418 		DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
419 		return (DW_DLE_ARGUMENT);
420 	}
421 
422 	if ((ret = _dwarf_attr_alloc(die, &at, error)) != DW_DLE_NONE)
423 		return (ret);
424 
425 	at->at_die = die;
426 	at->at_attrib = attr;
427 	at->at_form = DW_FORM_strp;
428 	if ((ret = _dwarf_strtab_add(dbg, string, &at->u[0].u64,
429 	    error)) != DW_DLE_NONE) {
430 		free(at);
431 		return (ret);
432 	}
433 	at->u[1].s = _dwarf_strtab_get_table(dbg) + at->u[0].u64;
434 
435 	*atp = at;
436 
437 	STAILQ_INSERT_TAIL(&die->die_attr, at, at_next);
438 
439 	return (DW_DLE_NONE);
440 }
441 
442 int
443 _dwarf_attr_gen(Dwarf_P_Debug dbg, Dwarf_P_Section ds, Dwarf_Rel_Section drs,
444     Dwarf_CU cu, Dwarf_Die die, int pass2, Dwarf_Error *error)
445 {
446 	Dwarf_Attribute at;
447 	int ret;
448 
449 	assert(dbg != NULL && ds != NULL && cu != NULL && die != NULL);
450 
451 	STAILQ_FOREACH(at, &die->die_attr, at_next) {
452 		ret = _dwarf_attr_write(dbg, ds, drs, cu, at, pass2, error);
453 		if (ret != DW_DLE_NONE)
454 			return (ret);
455 	}
456 
457 	return (DW_DLE_NONE);
458 }
459