1228072Sbapt/*-
2228072Sbapt * Copyright (c) 2007 John Birrell (jb@freebsd.org)
3228072Sbapt * All rights reserved.
4228072Sbapt *
5228072Sbapt * Redistribution and use in source and binary forms, with or without
6228072Sbapt * modification, are permitted provided that the following conditions
7228072Sbapt * are met:
8228072Sbapt * 1. Redistributions of source code must retain the above copyright
9228072Sbapt *    notice, this list of conditions and the following disclaimer.
10228072Sbapt * 2. Redistributions in binary form must reproduce the above copyright
11228072Sbapt *    notice, this list of conditions and the following disclaimer in the
12228072Sbapt *    documentation and/or other materials provided with the distribution.
13228072Sbapt *
14228072Sbapt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15228072Sbapt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16228072Sbapt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17228072Sbapt * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18228072Sbapt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19228072Sbapt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20228072Sbapt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21228072Sbapt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22228072Sbapt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23228072Sbapt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24228072Sbapt * SUCH DAMAGE.
25228072Sbapt *
26228072Sbapt * $FreeBSD$
27228072Sbapt */
28228072Sbapt
29228072Sbapt#include <stdlib.h>
30228072Sbapt#include "_libdwarf.h"
31228072Sbapt
32228072Sbaptstatic int64_t
33228072Sbaptdwarf_decode_sleb128(uint8_t **dp)
34228072Sbapt{
35228072Sbapt	int64_t ret = 0;
36228072Sbapt	uint8_t b;
37228072Sbapt	int shift = 0;
38228072Sbapt
39250874Sjkim	uint8_t *src = *dp;
40228072Sbapt
41228072Sbapt	do {
42228072Sbapt		b = *src++;
43228072Sbapt
44228072Sbapt		ret |= ((b & 0x7f) << shift);
45228072Sbapt
46228072Sbapt		shift += 7;
47228072Sbapt	} while ((b & 0x80) != 0);
48228072Sbapt
49228072Sbapt	if (shift < 64 && (b & 0x40) != 0)
50228072Sbapt		ret |= (-1 << shift);
51228072Sbapt
52228072Sbapt	*dp = src;
53228072Sbapt
54228072Sbapt	return ret;
55228072Sbapt}
56228072Sbapt
57228072Sbaptstatic uint64_t
58228072Sbaptdwarf_decode_uleb128(uint8_t **dp)
59228072Sbapt{
60228072Sbapt	uint64_t ret = 0;
61228072Sbapt	uint8_t b;
62228072Sbapt	int shift = 0;
63228072Sbapt
64228072Sbapt	uint8_t *src = *dp;
65228072Sbapt
66228072Sbapt	do {
67228072Sbapt		b = *src++;
68228072Sbapt
69228072Sbapt		ret |= ((b & 0x7f) << shift);
70228072Sbapt
71228072Sbapt		shift += 7;
72228072Sbapt	} while ((b & 0x80) != 0);
73228072Sbapt
74228072Sbapt	*dp = src;
75228072Sbapt
76228072Sbapt	return ret;
77228072Sbapt}
78228072Sbapt
79228072Sbapt/*
80228072Sbapt * Given an array of bytes of length 'len' representing a
81228072Sbapt * DWARF expression, compute the number of operations based
82228072Sbapt * on there being one byte describing the operation and
83228072Sbapt * zero or more bytes of operands as defined in the standard
84228072Sbapt * for each operation type.
85228072Sbapt */
86228072Sbaptint
87228072Sbaptdwarf_op_num(uint8_t pointer_size, uint8_t *p, int len)
88228072Sbapt{
89228072Sbapt	int count = 0;
90228072Sbapt	int64_t sval;
91228072Sbapt	uint64_t uval;
92228072Sbapt	uint8_t *last = p + len;
93228072Sbapt
94228072Sbapt	/*
95228072Sbapt	 * Process each byte. If an error occurs, then the
96228072Sbapt	 * count will be set to -1.
97228072Sbapt	 */
98228072Sbapt	while (p < last && count >= 0) {
99228072Sbapt		count++;
100228072Sbapt
101228072Sbapt		switch (*p++) {
102228072Sbapt		/* Operations with no operands. */
103228072Sbapt		case DW_OP_deref:
104228072Sbapt		case DW_OP_reg0:
105228072Sbapt		case DW_OP_reg1:
106228072Sbapt		case DW_OP_reg2:
107228072Sbapt		case DW_OP_reg3:
108228072Sbapt		case DW_OP_reg4:
109228072Sbapt		case DW_OP_reg5:
110228072Sbapt		case DW_OP_reg6:
111228072Sbapt		case DW_OP_reg7:
112228072Sbapt		case DW_OP_reg8:
113228072Sbapt		case DW_OP_reg9:
114228072Sbapt		case DW_OP_reg10:
115228072Sbapt		case DW_OP_reg11:
116228072Sbapt		case DW_OP_reg12:
117228072Sbapt		case DW_OP_reg13:
118228072Sbapt		case DW_OP_reg14:
119228072Sbapt		case DW_OP_reg15:
120228072Sbapt		case DW_OP_reg16:
121228072Sbapt		case DW_OP_reg17:
122228072Sbapt		case DW_OP_reg18:
123228072Sbapt		case DW_OP_reg19:
124228072Sbapt		case DW_OP_reg20:
125228072Sbapt		case DW_OP_reg21:
126228072Sbapt		case DW_OP_reg22:
127228072Sbapt		case DW_OP_reg23:
128228072Sbapt		case DW_OP_reg24:
129228072Sbapt		case DW_OP_reg25:
130228072Sbapt		case DW_OP_reg26:
131228072Sbapt		case DW_OP_reg27:
132228072Sbapt		case DW_OP_reg28:
133228072Sbapt		case DW_OP_reg29:
134228072Sbapt		case DW_OP_reg30:
135228072Sbapt		case DW_OP_reg31:
136228072Sbapt
137228072Sbapt		case DW_OP_lit0:
138228072Sbapt		case DW_OP_lit1:
139228072Sbapt		case DW_OP_lit2:
140228072Sbapt		case DW_OP_lit3:
141228072Sbapt		case DW_OP_lit4:
142228072Sbapt		case DW_OP_lit5:
143228072Sbapt		case DW_OP_lit6:
144228072Sbapt		case DW_OP_lit7:
145228072Sbapt		case DW_OP_lit8:
146228072Sbapt		case DW_OP_lit9:
147228072Sbapt		case DW_OP_lit10:
148228072Sbapt		case DW_OP_lit11:
149228072Sbapt		case DW_OP_lit12:
150228072Sbapt		case DW_OP_lit13:
151228072Sbapt		case DW_OP_lit14:
152228072Sbapt		case DW_OP_lit15:
153228072Sbapt		case DW_OP_lit16:
154228072Sbapt		case DW_OP_lit17:
155228072Sbapt		case DW_OP_lit18:
156228072Sbapt		case DW_OP_lit19:
157228072Sbapt		case DW_OP_lit20:
158228072Sbapt		case DW_OP_lit21:
159228072Sbapt		case DW_OP_lit22:
160228072Sbapt		case DW_OP_lit23:
161228072Sbapt		case DW_OP_lit24:
162228072Sbapt		case DW_OP_lit25:
163228072Sbapt		case DW_OP_lit26:
164228072Sbapt		case DW_OP_lit27:
165228072Sbapt		case DW_OP_lit28:
166228072Sbapt		case DW_OP_lit29:
167228072Sbapt		case DW_OP_lit30:
168228072Sbapt		case DW_OP_lit31:
169228072Sbapt
170228072Sbapt		case DW_OP_dup:
171228072Sbapt		case DW_OP_drop:
172228072Sbapt
173228072Sbapt		case DW_OP_over:
174228072Sbapt
175228072Sbapt		case DW_OP_swap:
176228072Sbapt		case DW_OP_rot:
177228072Sbapt		case DW_OP_xderef:
178228072Sbapt
179228072Sbapt		case DW_OP_abs:
180228072Sbapt		case DW_OP_and:
181228072Sbapt		case DW_OP_div:
182228072Sbapt		case DW_OP_minus:
183228072Sbapt		case DW_OP_mod:
184228072Sbapt		case DW_OP_mul:
185228072Sbapt		case DW_OP_neg:
186228072Sbapt		case DW_OP_not:
187228072Sbapt		case DW_OP_or:
188228072Sbapt		case DW_OP_plus:
189228072Sbapt
190228072Sbapt		case DW_OP_shl:
191228072Sbapt		case DW_OP_shr:
192228072Sbapt		case DW_OP_shra:
193228072Sbapt		case DW_OP_xor:
194228072Sbapt
195228072Sbapt		case DW_OP_eq:
196228072Sbapt		case DW_OP_ge:
197228072Sbapt		case DW_OP_gt:
198228072Sbapt		case DW_OP_le:
199228072Sbapt		case DW_OP_lt:
200228072Sbapt		case DW_OP_ne:
201228072Sbapt
202228072Sbapt		case DW_OP_nop:
203228072Sbapt			break;
204228072Sbapt
205228072Sbapt		/* Operations with 1-byte operands. */
206228072Sbapt		case DW_OP_const1u:
207228072Sbapt		case DW_OP_const1s:
208228072Sbapt		case DW_OP_pick:
209228072Sbapt		case DW_OP_deref_size:
210228072Sbapt		case DW_OP_xderef_size:
211228072Sbapt			p++;
212228072Sbapt			break;
213228072Sbapt
214228072Sbapt		/* Operations with 2-byte operands. */
215228072Sbapt		case DW_OP_const2u:
216228072Sbapt		case DW_OP_const2s:
217228072Sbapt		case DW_OP_bra:
218228072Sbapt		case DW_OP_skip:
219228072Sbapt			p += 2;
220228072Sbapt			break;
221228072Sbapt
222228072Sbapt		/* Operations with 4-byte operands. */
223228072Sbapt		case DW_OP_const4u:
224228072Sbapt		case DW_OP_const4s:
225228072Sbapt			p += 4;
226228072Sbapt			break;
227250874Sjkim
228228072Sbapt		/* Operations with 8-byte operands. */
229228072Sbapt		case DW_OP_const8u:
230228072Sbapt		case DW_OP_const8s:
231228072Sbapt			p += 8;
232228072Sbapt			break;
233228072Sbapt
234228072Sbapt		/* Operations with an unsigned LEB128 operand. */
235228072Sbapt		case DW_OP_constu:
236228072Sbapt		case DW_OP_plus_uconst:
237228072Sbapt		case DW_OP_regx:
238228072Sbapt		case DW_OP_piece:
239228072Sbapt			uval = dwarf_decode_uleb128(&p);
240228072Sbapt			break;
241228072Sbapt
242228072Sbapt		/* Operations with a signed LEB128 operand. */
243228072Sbapt		case DW_OP_consts:
244228072Sbapt		case DW_OP_breg0:
245228072Sbapt		case DW_OP_breg1:
246228072Sbapt		case DW_OP_breg2:
247228072Sbapt		case DW_OP_breg3:
248228072Sbapt		case DW_OP_breg4:
249228072Sbapt		case DW_OP_breg5:
250228072Sbapt		case DW_OP_breg6:
251228072Sbapt		case DW_OP_breg7:
252228072Sbapt		case DW_OP_breg8:
253228072Sbapt		case DW_OP_breg9:
254228072Sbapt		case DW_OP_breg10:
255228072Sbapt		case DW_OP_breg11:
256228072Sbapt		case DW_OP_breg12:
257228072Sbapt		case DW_OP_breg13:
258228072Sbapt		case DW_OP_breg14:
259228072Sbapt		case DW_OP_breg15:
260228072Sbapt		case DW_OP_breg16:
261228072Sbapt		case DW_OP_breg17:
262228072Sbapt		case DW_OP_breg18:
263228072Sbapt		case DW_OP_breg19:
264228072Sbapt		case DW_OP_breg20:
265228072Sbapt		case DW_OP_breg21:
266228072Sbapt		case DW_OP_breg22:
267228072Sbapt		case DW_OP_breg23:
268228072Sbapt		case DW_OP_breg24:
269228072Sbapt		case DW_OP_breg25:
270228072Sbapt		case DW_OP_breg26:
271228072Sbapt		case DW_OP_breg27:
272228072Sbapt		case DW_OP_breg28:
273228072Sbapt		case DW_OP_breg29:
274228072Sbapt		case DW_OP_breg30:
275228072Sbapt		case DW_OP_breg31:
276228072Sbapt		case DW_OP_fbreg:
277228072Sbapt			sval = dwarf_decode_sleb128(&p);
278228072Sbapt			break;
279228072Sbapt
280228072Sbapt		/*
281228072Sbapt		 * Operations with an unsigned LEB128 operand
282228072Sbapt		 * followed by a signed LEB128 operand.
283228072Sbapt		 */
284228072Sbapt		case DW_OP_bregx:
285228072Sbapt			uval = dwarf_decode_uleb128(&p);
286228072Sbapt			sval = dwarf_decode_sleb128(&p);
287228072Sbapt			break;
288228072Sbapt
289228072Sbapt		/* Target address size operand. */
290228072Sbapt		case DW_OP_addr:
291228072Sbapt			p += pointer_size;
292228072Sbapt			break;
293228072Sbapt
294250874Sjkim		/* All other operations cause an error. */
295228072Sbapt		default:
296228072Sbapt			count = -1;
297228072Sbapt			break;
298228072Sbapt		}
299228072Sbapt	}
300228072Sbapt
301228072Sbapt	return count;
302228072Sbapt}
303228072Sbapt
304228072Sbaptstatic int
305228072Sbaptdwarf_loc_fill(Dwarf_Locdesc *lbuf, uint8_t pointer_size, uint8_t *p, int len)
306228072Sbapt{
307228072Sbapt	int count = 0;
308228072Sbapt	int ret = DWARF_E_NONE;
309228072Sbapt	uint64_t operand1;
310228072Sbapt	uint64_t operand2;
311228072Sbapt	uint8_t *last = p + len;
312228072Sbapt
313228072Sbapt	/*
314228072Sbapt	 * Process each byte. If an error occurs, then the
315228072Sbapt	 * count will be set to -1.
316228072Sbapt	 */
317228072Sbapt	while (p < last && ret == DWARF_E_NONE) {
318228072Sbapt		operand1 = 0;
319228072Sbapt		operand2 = 0;
320228072Sbapt
321228072Sbapt		lbuf->ld_s[count].lr_atom = *p;
322228072Sbapt
323228072Sbapt		switch (*p++) {
324228072Sbapt		/* Operations with no operands. */
325228072Sbapt		case DW_OP_deref:
326228072Sbapt		case DW_OP_reg0:
327228072Sbapt		case DW_OP_reg1:
328228072Sbapt		case DW_OP_reg2:
329228072Sbapt		case DW_OP_reg3:
330228072Sbapt		case DW_OP_reg4:
331228072Sbapt		case DW_OP_reg5:
332228072Sbapt		case DW_OP_reg6:
333250874Sjkim		case DW_OP_reg7:
334250874Sjkim		case DW_OP_reg8:
335250874Sjkim		case DW_OP_reg9:
336228072Sbapt		case DW_OP_reg10:
337228072Sbapt		case DW_OP_reg11:
338228072Sbapt		case DW_OP_reg12:
339228072Sbapt		case DW_OP_reg13:
340228072Sbapt		case DW_OP_reg14:
341228072Sbapt		case DW_OP_reg15:
342228072Sbapt		case DW_OP_reg16:
343228072Sbapt		case DW_OP_reg17:
344228072Sbapt		case DW_OP_reg18:
345228072Sbapt		case DW_OP_reg19:
346228072Sbapt		case DW_OP_reg20:
347228072Sbapt		case DW_OP_reg21:
348228072Sbapt		case DW_OP_reg22:
349228072Sbapt		case DW_OP_reg23:
350228072Sbapt		case DW_OP_reg24:
351228072Sbapt		case DW_OP_reg25:
352228072Sbapt		case DW_OP_reg26:
353228072Sbapt		case DW_OP_reg27:
354228072Sbapt		case DW_OP_reg28:
355228072Sbapt		case DW_OP_reg29:
356228072Sbapt		case DW_OP_reg30:
357228072Sbapt		case DW_OP_reg31:
358228072Sbapt
359228072Sbapt		case DW_OP_lit0:
360228072Sbapt		case DW_OP_lit1:
361228072Sbapt		case DW_OP_lit2:
362228072Sbapt		case DW_OP_lit3:
363228072Sbapt		case DW_OP_lit4:
364228072Sbapt		case DW_OP_lit5:
365228072Sbapt		case DW_OP_lit6:
366228072Sbapt		case DW_OP_lit7:
367228072Sbapt		case DW_OP_lit8:
368228072Sbapt		case DW_OP_lit9:
369228072Sbapt		case DW_OP_lit10:
370228072Sbapt		case DW_OP_lit11:
371228072Sbapt		case DW_OP_lit12:
372228072Sbapt		case DW_OP_lit13:
373228072Sbapt		case DW_OP_lit14:
374228072Sbapt		case DW_OP_lit15:
375228072Sbapt		case DW_OP_lit16:
376228072Sbapt		case DW_OP_lit17:
377228072Sbapt		case DW_OP_lit18:
378228072Sbapt		case DW_OP_lit19:
379228072Sbapt		case DW_OP_lit20:
380228072Sbapt		case DW_OP_lit21:
381228072Sbapt		case DW_OP_lit22:
382228072Sbapt		case DW_OP_lit23:
383228072Sbapt		case DW_OP_lit24:
384228072Sbapt		case DW_OP_lit25:
385228072Sbapt		case DW_OP_lit26:
386228072Sbapt		case DW_OP_lit27:
387228072Sbapt		case DW_OP_lit28:
388228072Sbapt		case DW_OP_lit29:
389228072Sbapt		case DW_OP_lit30:
390228072Sbapt		case DW_OP_lit31:
391228072Sbapt
392228072Sbapt		case DW_OP_dup:
393228072Sbapt		case DW_OP_drop:
394228072Sbapt
395228072Sbapt		case DW_OP_over:
396228072Sbapt
397228072Sbapt		case DW_OP_swap:
398228072Sbapt		case DW_OP_rot:
399228072Sbapt		case DW_OP_xderef:
400228072Sbapt
401228072Sbapt		case DW_OP_abs:
402228072Sbapt		case DW_OP_and:
403228072Sbapt		case DW_OP_div:
404228072Sbapt		case DW_OP_minus:
405228072Sbapt		case DW_OP_mod:
406228072Sbapt		case DW_OP_mul:
407228072Sbapt		case DW_OP_neg:
408228072Sbapt		case DW_OP_not:
409228072Sbapt		case DW_OP_or:
410228072Sbapt		case DW_OP_plus:
411228072Sbapt
412228072Sbapt		case DW_OP_shl:
413228072Sbapt		case DW_OP_shr:
414228072Sbapt		case DW_OP_shra:
415228072Sbapt		case DW_OP_xor:
416228072Sbapt
417228072Sbapt		case DW_OP_eq:
418228072Sbapt		case DW_OP_ge:
419228072Sbapt		case DW_OP_gt:
420228072Sbapt		case DW_OP_le:
421228072Sbapt		case DW_OP_lt:
422228072Sbapt		case DW_OP_ne:
423228072Sbapt
424250874Sjkim		case DW_OP_nop:
425228072Sbapt			break;
426228072Sbapt
427228072Sbapt		/* Operations with 1-byte operands. */
428228072Sbapt		case DW_OP_const1u:
429228072Sbapt		case DW_OP_const1s:
430228072Sbapt		case DW_OP_pick:
431228072Sbapt		case DW_OP_deref_size:
432228072Sbapt		case DW_OP_xderef_size:
433228072Sbapt			operand1 = *p++;
434228072Sbapt			break;
435228072Sbapt
436228072Sbapt		/* Operations with 2-byte operands. */
437228072Sbapt		case DW_OP_const2u:
438228072Sbapt		case DW_OP_const2s:
439228072Sbapt		case DW_OP_bra:
440228072Sbapt		case DW_OP_skip:
441228072Sbapt			p += 2;
442228072Sbapt			break;
443228072Sbapt
444228072Sbapt		/* Operations with 4-byte operands. */
445228072Sbapt		case DW_OP_const4u:
446228072Sbapt		case DW_OP_const4s:
447228072Sbapt			p += 4;
448228072Sbapt			break;
449228072Sbapt
450228072Sbapt		/* Operations with 8-byte operands. */
451228072Sbapt		case DW_OP_const8u:
452228072Sbapt		case DW_OP_const8s:
453228072Sbapt			p += 8;
454228072Sbapt			break;
455228072Sbapt
456228072Sbapt		/* Operations with an unsigned LEB128 operand. */
457228072Sbapt		case DW_OP_constu:
458228072Sbapt		case DW_OP_plus_uconst:
459228072Sbapt		case DW_OP_regx:
460228072Sbapt		case DW_OP_piece:
461228072Sbapt			operand1 = dwarf_decode_uleb128(&p);
462228072Sbapt			break;
463228072Sbapt
464228072Sbapt		/* Operations with a signed LEB128 operand. */
465228072Sbapt		case DW_OP_consts:
466228072Sbapt		case DW_OP_breg0:
467228072Sbapt		case DW_OP_breg1:
468228072Sbapt		case DW_OP_breg2:
469228072Sbapt		case DW_OP_breg3:
470228072Sbapt		case DW_OP_breg4:
471228072Sbapt		case DW_OP_breg5:
472228072Sbapt		case DW_OP_breg6:
473228072Sbapt		case DW_OP_breg7:
474228072Sbapt		case DW_OP_breg8:
475228072Sbapt		case DW_OP_breg9:
476228072Sbapt		case DW_OP_breg10:
477228072Sbapt		case DW_OP_breg11:
478228072Sbapt		case DW_OP_breg12:
479228072Sbapt		case DW_OP_breg13:
480228072Sbapt		case DW_OP_breg14:
481228072Sbapt		case DW_OP_breg15:
482228072Sbapt		case DW_OP_breg16:
483228072Sbapt		case DW_OP_breg17:
484228072Sbapt		case DW_OP_breg18:
485228072Sbapt		case DW_OP_breg19:
486228072Sbapt		case DW_OP_breg20:
487228072Sbapt		case DW_OP_breg21:
488228072Sbapt		case DW_OP_breg22:
489228072Sbapt		case DW_OP_breg23:
490228072Sbapt		case DW_OP_breg24:
491228072Sbapt		case DW_OP_breg25:
492228072Sbapt		case DW_OP_breg26:
493228072Sbapt		case DW_OP_breg27:
494228072Sbapt		case DW_OP_breg28:
495228072Sbapt		case DW_OP_breg29:
496228072Sbapt		case DW_OP_breg30:
497250874Sjkim		case DW_OP_breg31:
498228072Sbapt		case DW_OP_fbreg:
499228072Sbapt			operand1 = dwarf_decode_sleb128(&p);
500228072Sbapt			break;
501228072Sbapt
502228072Sbapt		/*
503228072Sbapt		 * Operations with an unsigned LEB128 operand
504250874Sjkim		 * followed by a signed LEB128 operand.
505228072Sbapt		 */
506228072Sbapt		case DW_OP_bregx:
507250874Sjkim			operand1 = dwarf_decode_uleb128(&p);
508228072Sbapt			operand2 = dwarf_decode_sleb128(&p);
509228072Sbapt			break;
510228072Sbapt
511228072Sbapt		/* Target address size operand. */
512228072Sbapt		case DW_OP_addr:
513228072Sbapt			p += pointer_size;
514228072Sbapt			break;
515228072Sbapt
516228072Sbapt		/* All other operations cause an error. */
517228072Sbapt		default:
518228072Sbapt			break;
519228072Sbapt		}
520228072Sbapt
521228072Sbapt		lbuf->ld_s[count].lr_number = operand1;
522228072Sbapt		lbuf->ld_s[count].lr_number2 = operand2;
523228072Sbapt
524228072Sbapt		count++;
525228072Sbapt	}
526228072Sbapt
527228072Sbapt	return ret;
528228072Sbapt}
529228072Sbapt
530228072Sbaptint
531228072Sbaptdwarf_locdesc(Dwarf_Die die, uint64_t attr, Dwarf_Locdesc **llbuf, Dwarf_Signed *lenp, Dwarf_Error *err)
532228072Sbapt{
533228072Sbapt	Dwarf_AttrValue av;
534228072Sbapt	Dwarf_Locdesc *lbuf;
535228072Sbapt	int num;
536228072Sbapt	int ret = DWARF_E_NONE;
537228072Sbapt
538228072Sbapt	if (err == NULL)
539228072Sbapt		return DWARF_E_ERROR;
540228072Sbapt
541228072Sbapt	if (die == NULL || llbuf == NULL || lenp == NULL) {
542228072Sbapt		DWARF_SET_ERROR(err, DWARF_E_ARGUMENT);
543228072Sbapt		return DWARF_E_ARGUMENT;
544228072Sbapt	}
545228072Sbapt
546228072Sbapt	if ((av = dwarf_attrval_find(die, attr)) == NULL) {
547228072Sbapt		DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY);
548228072Sbapt		ret = DWARF_E_NO_ENTRY;
549228072Sbapt	} else if ((lbuf = calloc(sizeof(Dwarf_Locdesc), 1)) == NULL) {
550228072Sbapt		DWARF_SET_ERROR(err, DWARF_E_MEMORY);
551228072Sbapt		ret = DWARF_E_MEMORY;
552228072Sbapt	} else {
553228072Sbapt		*lenp = 0;
554228072Sbapt		switch (av->av_form) {
555228072Sbapt		case DW_FORM_block:
556228072Sbapt		case DW_FORM_block1:
557228072Sbapt		case DW_FORM_block2:
558228072Sbapt		case DW_FORM_block4:
559228072Sbapt			/* Compute the number of locations: */
560228072Sbapt			if ((num = dwarf_op_num(die->die_cu->cu_pointer_size,
561228072Sbapt			    av->u[1].u8p, av->u[0].u64)) < 0) {
562228072Sbapt				DWARF_SET_ERROR(err, DWARF_E_INVALID_EXPR);
563228072Sbapt				ret = DWARF_E_INVALID_EXPR;
564228072Sbapt
565228072Sbapt			/* Allocate an array of location structures. */
566228072Sbapt			} else if ((lbuf->ld_s =
567228072Sbapt			    calloc(sizeof(Dwarf_Loc), num)) == NULL) {
568228072Sbapt				DWARF_SET_ERROR(err, DWARF_E_MEMORY);
569228072Sbapt				ret = DWARF_E_MEMORY;
570228072Sbapt
571228072Sbapt			/* Fill the array of location structures. */
572228072Sbapt			} else if ((ret = dwarf_loc_fill(lbuf,
573228072Sbapt			    die->die_cu->cu_pointer_size,
574228072Sbapt			    av->u[1].u8p, av->u[0].u64)) != DWARF_E_NONE) {
575228072Sbapt				free(lbuf->ld_s);
576228072Sbapt			} else
577228072Sbapt				/* Only one descriptor is returned. */
578228072Sbapt				*lenp = 1;
579228072Sbapt			break;
580228072Sbapt		default:
581228072Sbapt			printf("%s(%d): form %s not handled\n",__func__,
582228072Sbapt			    __LINE__,get_form_desc(av->av_form));
583228072Sbapt			DWARF_SET_ERROR(err, DWARF_E_NOT_IMPLEMENTED);
584228072Sbapt			ret = DWARF_E_ERROR;
585228072Sbapt		}
586228072Sbapt
587228072Sbapt		if (ret == DWARF_E_NONE) {
588228072Sbapt			*llbuf = lbuf;
589228072Sbapt		} else
590228072Sbapt			free(lbuf);
591228072Sbapt	}
592228072Sbapt
593228072Sbapt	return ret;
594228072Sbapt}
595228072Sbapt
596228072Sbaptint
597228072Sbaptdwarf_locdesc_free(Dwarf_Locdesc *lbuf, Dwarf_Error *err)
598228072Sbapt{
599228072Sbapt	if (err == NULL)
600228072Sbapt		return DWARF_E_ERROR;
601228072Sbapt
602228072Sbapt	if (lbuf == NULL) {
603228072Sbapt		DWARF_SET_ERROR(err, DWARF_E_ARGUMENT);
604228072Sbapt		return DWARF_E_ARGUMENT;
605228072Sbapt	}
606228072Sbapt
607228072Sbapt	if (lbuf->ld_s != NULL)
608228072Sbapt		free(lbuf->ld_s);
609228072Sbapt
610228072Sbapt	free(lbuf);
611228072Sbapt
612228072Sbapt	return DWARF_E_NONE;
613228072Sbapt}
614228072Sbapt