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