libdwarf_loc.c revision 260684
1260684Skaiw/*-
2260684Skaiw * Copyright (c) 2007 John Birrell (jb@freebsd.org)
3260684Skaiw * All rights reserved.
4260684Skaiw *
5260684Skaiw * Redistribution and use in source and binary forms, with or without
6260684Skaiw * modification, are permitted provided that the following conditions
7260684Skaiw * are met:
8260684Skaiw * 1. Redistributions of source code must retain the above copyright
9260684Skaiw *    notice, this list of conditions and the following disclaimer.
10260684Skaiw * 2. Redistributions in binary form must reproduce the above copyright
11260684Skaiw *    notice, this list of conditions and the following disclaimer in the
12260684Skaiw *    documentation and/or other materials provided with the distribution.
13260684Skaiw *
14260684Skaiw * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15260684Skaiw * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16260684Skaiw * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17260684Skaiw * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18260684Skaiw * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19260684Skaiw * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20260684Skaiw * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21260684Skaiw * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22260684Skaiw * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23260684Skaiw * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24260684Skaiw * SUCH DAMAGE.
25260684Skaiw */
26260684Skaiw
27260684Skaiw#include "_libdwarf.h"
28260684Skaiw
29260684SkaiwELFTC_VCSID("$Id: libdwarf_loc.c 2070 2011-10-27 03:05:32Z jkoshy $");
30260684Skaiw
31260684Skaiw/*
32260684Skaiw * Given an array of bytes of length 'len' representing a
33260684Skaiw * DWARF expression, compute the number of operations based
34260684Skaiw * on there being one byte describing the operation and
35260684Skaiw * zero or more bytes of operands as defined in the standard
36260684Skaiw * for each operation type. Also, if lbuf is non-null, store
37260684Skaiw * the opcode and oprand in it.
38260684Skaiw */
39260684Skaiwstatic int
40260684Skaiw_dwarf_loc_fill_loc(Dwarf_Debug dbg, Dwarf_Locdesc *lbuf, uint8_t pointer_size,
41260684Skaiw    uint8_t *p, int len)
42260684Skaiw{
43260684Skaiw	int count;
44260684Skaiw	uint64_t operand1;
45260684Skaiw	uint64_t operand2;
46260684Skaiw	uint8_t *ps, *pe;
47260684Skaiw
48260684Skaiw	count = 0;
49260684Skaiw	ps = p;
50260684Skaiw	pe = p + len;
51260684Skaiw
52260684Skaiw	/*
53260684Skaiw	 * Process each byte. If an error occurs, then the
54260684Skaiw	 * count will be set to -1.
55260684Skaiw	 */
56260684Skaiw	while (p < pe) {
57260684Skaiw
58260684Skaiw		operand1 = 0;
59260684Skaiw		operand2 = 0;
60260684Skaiw
61260684Skaiw		if (lbuf != NULL) {
62260684Skaiw			lbuf->ld_s[count].lr_atom = *p;
63260684Skaiw			lbuf->ld_s[count].lr_offset = p - ps;
64260684Skaiw		}
65260684Skaiw
66260684Skaiw		switch (*p++) {
67260684Skaiw		/* Operations with no operands. */
68260684Skaiw		case DW_OP_deref:
69260684Skaiw		case DW_OP_reg0:
70260684Skaiw		case DW_OP_reg1:
71260684Skaiw		case DW_OP_reg2:
72260684Skaiw		case DW_OP_reg3:
73260684Skaiw		case DW_OP_reg4:
74260684Skaiw		case DW_OP_reg5:
75260684Skaiw		case DW_OP_reg6:
76260684Skaiw		case DW_OP_reg7:
77260684Skaiw		case DW_OP_reg8:
78260684Skaiw		case DW_OP_reg9:
79260684Skaiw		case DW_OP_reg10:
80260684Skaiw		case DW_OP_reg11:
81260684Skaiw		case DW_OP_reg12:
82260684Skaiw		case DW_OP_reg13:
83260684Skaiw		case DW_OP_reg14:
84260684Skaiw		case DW_OP_reg15:
85260684Skaiw		case DW_OP_reg16:
86260684Skaiw		case DW_OP_reg17:
87260684Skaiw		case DW_OP_reg18:
88260684Skaiw		case DW_OP_reg19:
89260684Skaiw		case DW_OP_reg20:
90260684Skaiw		case DW_OP_reg21:
91260684Skaiw		case DW_OP_reg22:
92260684Skaiw		case DW_OP_reg23:
93260684Skaiw		case DW_OP_reg24:
94260684Skaiw		case DW_OP_reg25:
95260684Skaiw		case DW_OP_reg26:
96260684Skaiw		case DW_OP_reg27:
97260684Skaiw		case DW_OP_reg28:
98260684Skaiw		case DW_OP_reg29:
99260684Skaiw		case DW_OP_reg30:
100260684Skaiw		case DW_OP_reg31:
101260684Skaiw
102260684Skaiw		case DW_OP_lit0:
103260684Skaiw		case DW_OP_lit1:
104260684Skaiw		case DW_OP_lit2:
105260684Skaiw		case DW_OP_lit3:
106260684Skaiw		case DW_OP_lit4:
107260684Skaiw		case DW_OP_lit5:
108260684Skaiw		case DW_OP_lit6:
109260684Skaiw		case DW_OP_lit7:
110260684Skaiw		case DW_OP_lit8:
111260684Skaiw		case DW_OP_lit9:
112260684Skaiw		case DW_OP_lit10:
113260684Skaiw		case DW_OP_lit11:
114260684Skaiw		case DW_OP_lit12:
115260684Skaiw		case DW_OP_lit13:
116260684Skaiw		case DW_OP_lit14:
117260684Skaiw		case DW_OP_lit15:
118260684Skaiw		case DW_OP_lit16:
119260684Skaiw		case DW_OP_lit17:
120260684Skaiw		case DW_OP_lit18:
121260684Skaiw		case DW_OP_lit19:
122260684Skaiw		case DW_OP_lit20:
123260684Skaiw		case DW_OP_lit21:
124260684Skaiw		case DW_OP_lit22:
125260684Skaiw		case DW_OP_lit23:
126260684Skaiw		case DW_OP_lit24:
127260684Skaiw		case DW_OP_lit25:
128260684Skaiw		case DW_OP_lit26:
129260684Skaiw		case DW_OP_lit27:
130260684Skaiw		case DW_OP_lit28:
131260684Skaiw		case DW_OP_lit29:
132260684Skaiw		case DW_OP_lit30:
133260684Skaiw		case DW_OP_lit31:
134260684Skaiw
135260684Skaiw		case DW_OP_dup:
136260684Skaiw		case DW_OP_drop:
137260684Skaiw
138260684Skaiw		case DW_OP_over:
139260684Skaiw
140260684Skaiw		case DW_OP_swap:
141260684Skaiw		case DW_OP_rot:
142260684Skaiw		case DW_OP_xderef:
143260684Skaiw
144260684Skaiw		case DW_OP_abs:
145260684Skaiw		case DW_OP_and:
146260684Skaiw		case DW_OP_div:
147260684Skaiw		case DW_OP_minus:
148260684Skaiw		case DW_OP_mod:
149260684Skaiw		case DW_OP_mul:
150260684Skaiw		case DW_OP_neg:
151260684Skaiw		case DW_OP_not:
152260684Skaiw		case DW_OP_or:
153260684Skaiw		case DW_OP_plus:
154260684Skaiw
155260684Skaiw		case DW_OP_shl:
156260684Skaiw		case DW_OP_shr:
157260684Skaiw		case DW_OP_shra:
158260684Skaiw		case DW_OP_xor:
159260684Skaiw
160260684Skaiw		case DW_OP_eq:
161260684Skaiw		case DW_OP_ge:
162260684Skaiw		case DW_OP_gt:
163260684Skaiw		case DW_OP_le:
164260684Skaiw		case DW_OP_lt:
165260684Skaiw		case DW_OP_ne:
166260684Skaiw
167260684Skaiw		case DW_OP_nop:
168260684Skaiw		case DW_OP_form_tls_address:
169260684Skaiw		case DW_OP_call_frame_cfa:
170260684Skaiw		case DW_OP_stack_value:
171260684Skaiw		case DW_OP_GNU_push_tls_address:
172260684Skaiw			break;
173260684Skaiw
174260684Skaiw		/* Operations with 1-byte operands. */
175260684Skaiw		case DW_OP_const1u:
176260684Skaiw		case DW_OP_const1s:
177260684Skaiw		case DW_OP_pick:
178260684Skaiw		case DW_OP_deref_size:
179260684Skaiw		case DW_OP_xderef_size:
180260684Skaiw			operand1 = *p++;
181260684Skaiw			break;
182260684Skaiw
183260684Skaiw		/* Operations with 2-byte operands. */
184260684Skaiw		case DW_OP_call2:
185260684Skaiw		case DW_OP_const2u:
186260684Skaiw		case DW_OP_const2s:
187260684Skaiw		case DW_OP_bra:
188260684Skaiw		case DW_OP_skip:
189260684Skaiw			operand1 = dbg->decode(&p, 2);
190260684Skaiw			break;
191260684Skaiw
192260684Skaiw		/* Operations with 4-byte operands. */
193260684Skaiw		case DW_OP_call4:
194260684Skaiw		case DW_OP_const4u:
195260684Skaiw		case DW_OP_const4s:
196260684Skaiw			operand1 = dbg->decode(&p, 4);
197260684Skaiw			break;
198260684Skaiw
199260684Skaiw		/* Operations with 8-byte operands. */
200260684Skaiw		case DW_OP_const8u:
201260684Skaiw		case DW_OP_const8s:
202260684Skaiw			operand1 = dbg->decode(&p, 8);
203260684Skaiw			break;
204260684Skaiw
205260684Skaiw		/* Operations with an unsigned LEB128 operand. */
206260684Skaiw		case DW_OP_constu:
207260684Skaiw		case DW_OP_plus_uconst:
208260684Skaiw		case DW_OP_regx:
209260684Skaiw		case DW_OP_piece:
210260684Skaiw			operand1 = _dwarf_decode_uleb128(&p);
211260684Skaiw			break;
212260684Skaiw
213260684Skaiw		/* Operations with a signed LEB128 operand. */
214260684Skaiw		case DW_OP_consts:
215260684Skaiw		case DW_OP_breg0:
216260684Skaiw		case DW_OP_breg1:
217260684Skaiw		case DW_OP_breg2:
218260684Skaiw		case DW_OP_breg3:
219260684Skaiw		case DW_OP_breg4:
220260684Skaiw		case DW_OP_breg5:
221260684Skaiw		case DW_OP_breg6:
222260684Skaiw		case DW_OP_breg7:
223260684Skaiw		case DW_OP_breg8:
224260684Skaiw		case DW_OP_breg9:
225260684Skaiw		case DW_OP_breg10:
226260684Skaiw		case DW_OP_breg11:
227260684Skaiw		case DW_OP_breg12:
228260684Skaiw		case DW_OP_breg13:
229260684Skaiw		case DW_OP_breg14:
230260684Skaiw		case DW_OP_breg15:
231260684Skaiw		case DW_OP_breg16:
232260684Skaiw		case DW_OP_breg17:
233260684Skaiw		case DW_OP_breg18:
234260684Skaiw		case DW_OP_breg19:
235260684Skaiw		case DW_OP_breg20:
236260684Skaiw		case DW_OP_breg21:
237260684Skaiw		case DW_OP_breg22:
238260684Skaiw		case DW_OP_breg23:
239260684Skaiw		case DW_OP_breg24:
240260684Skaiw		case DW_OP_breg25:
241260684Skaiw		case DW_OP_breg26:
242260684Skaiw		case DW_OP_breg27:
243260684Skaiw		case DW_OP_breg28:
244260684Skaiw		case DW_OP_breg29:
245260684Skaiw		case DW_OP_breg30:
246260684Skaiw		case DW_OP_breg31:
247260684Skaiw		case DW_OP_fbreg:
248260684Skaiw			operand1 = _dwarf_decode_sleb128(&p);
249260684Skaiw			break;
250260684Skaiw
251260684Skaiw		/*
252260684Skaiw		 * Oeration with two unsigned LEB128 operands.
253260684Skaiw		 */
254260684Skaiw		case DW_OP_bit_piece:
255260684Skaiw			operand1 = _dwarf_decode_uleb128(&p);
256260684Skaiw			operand2 = _dwarf_decode_uleb128(&p);
257260684Skaiw			break;
258260684Skaiw
259260684Skaiw		/*
260260684Skaiw		 * Operations with an unsigned LEB128 operand
261260684Skaiw		 * followed by a signed LEB128 operand.
262260684Skaiw		 */
263260684Skaiw		case DW_OP_bregx:
264260684Skaiw			operand1 = _dwarf_decode_uleb128(&p);
265260684Skaiw			operand2 = _dwarf_decode_sleb128(&p);
266260684Skaiw			break;
267260684Skaiw
268260684Skaiw		/*
269260684Skaiw		 * Operation with an unsigned LEB128 operand
270260684Skaiw		 * followed by a block. Store a pointer to the
271260684Skaiw		 * block in the operand2.
272260684Skaiw		 */
273260684Skaiw		case DW_OP_implicit_value:
274260684Skaiw			operand1 = _dwarf_decode_uleb128(&p);
275260684Skaiw			operand2 = (Dwarf_Unsigned) (uintptr_t) p;
276260684Skaiw			p += operand1;
277260684Skaiw			break;
278260684Skaiw
279260684Skaiw		/* Target address size operand. */
280260684Skaiw		case DW_OP_addr:
281260684Skaiw			operand1 = dbg->decode(&p, pointer_size);
282260684Skaiw			break;
283260684Skaiw
284260684Skaiw		/*
285260684Skaiw		 * XXX Opcode DW_OP_call_ref has an operand with size
286260684Skaiw		 * "dwarf_size". Here we use dbg->dbg_offset_size
287260684Skaiw		 * as "dwarf_size" to be compatible with SGI libdwarf.
288260684Skaiw		 * However note that dbg->dbg_offset_size is just
289260684Skaiw		 * a "guess" value so the parsing result of
290260684Skaiw		 * DW_OP_call_ref might not be correct at all. XXX
291260684Skaiw		 */
292260684Skaiw		case DW_OP_call_ref:
293260684Skaiw			operand1 = dbg->decode(&p, dbg->dbg_offset_size);
294260684Skaiw			break;
295260684Skaiw
296260684Skaiw		/* All other operations cause an error. */
297260684Skaiw		default:
298260684Skaiw			count = -1;
299260684Skaiw			break;
300260684Skaiw		}
301260684Skaiw
302260684Skaiw		if (lbuf != NULL) {
303260684Skaiw			lbuf->ld_s[count].lr_number = operand1;
304260684Skaiw			lbuf->ld_s[count].lr_number2 = operand2;
305260684Skaiw		}
306260684Skaiw
307260684Skaiw		count++;
308260684Skaiw	}
309260684Skaiw
310260684Skaiw	return (count);
311260684Skaiw}
312260684Skaiw
313260684Skaiwint
314260684Skaiw_dwarf_loc_expr_add_atom(Dwarf_Debug dbg, uint8_t *out, uint8_t *end,
315260684Skaiw    Dwarf_Small atom, Dwarf_Unsigned operand1, Dwarf_Unsigned operand2,
316260684Skaiw    int *length, Dwarf_Error *error)
317260684Skaiw{
318260684Skaiw	uint8_t buf[64];
319260684Skaiw	uint8_t *p, *pe;
320260684Skaiw	uint64_t offset;
321260684Skaiw	int len;
322260684Skaiw
323260684Skaiw	if (out != NULL && end != NULL) {
324260684Skaiw		p = out;
325260684Skaiw		pe = end;
326260684Skaiw	} else {
327260684Skaiw		p = out = buf;
328260684Skaiw		pe = &buf[sizeof(buf)];
329260684Skaiw	}
330260684Skaiw
331260684Skaiw	switch (atom) {
332260684Skaiw	/* Operations with no operands. */
333260684Skaiw	case DW_OP_deref:
334260684Skaiw	case DW_OP_reg0:
335260684Skaiw	case DW_OP_reg1:
336260684Skaiw	case DW_OP_reg2:
337260684Skaiw	case DW_OP_reg3:
338260684Skaiw	case DW_OP_reg4:
339260684Skaiw	case DW_OP_reg5:
340260684Skaiw	case DW_OP_reg6:
341260684Skaiw	case DW_OP_reg7:
342260684Skaiw	case DW_OP_reg8:
343260684Skaiw	case DW_OP_reg9:
344260684Skaiw	case DW_OP_reg10:
345260684Skaiw	case DW_OP_reg11:
346260684Skaiw	case DW_OP_reg12:
347260684Skaiw	case DW_OP_reg13:
348260684Skaiw	case DW_OP_reg14:
349260684Skaiw	case DW_OP_reg15:
350260684Skaiw	case DW_OP_reg16:
351260684Skaiw	case DW_OP_reg17:
352260684Skaiw	case DW_OP_reg18:
353260684Skaiw	case DW_OP_reg19:
354260684Skaiw	case DW_OP_reg20:
355260684Skaiw	case DW_OP_reg21:
356260684Skaiw	case DW_OP_reg22:
357260684Skaiw	case DW_OP_reg23:
358260684Skaiw	case DW_OP_reg24:
359260684Skaiw	case DW_OP_reg25:
360260684Skaiw	case DW_OP_reg26:
361260684Skaiw	case DW_OP_reg27:
362260684Skaiw	case DW_OP_reg28:
363260684Skaiw	case DW_OP_reg29:
364260684Skaiw	case DW_OP_reg30:
365260684Skaiw	case DW_OP_reg31:
366260684Skaiw
367260684Skaiw	case DW_OP_lit0:
368260684Skaiw	case DW_OP_lit1:
369260684Skaiw	case DW_OP_lit2:
370260684Skaiw	case DW_OP_lit3:
371260684Skaiw	case DW_OP_lit4:
372260684Skaiw	case DW_OP_lit5:
373260684Skaiw	case DW_OP_lit6:
374260684Skaiw	case DW_OP_lit7:
375260684Skaiw	case DW_OP_lit8:
376260684Skaiw	case DW_OP_lit9:
377260684Skaiw	case DW_OP_lit10:
378260684Skaiw	case DW_OP_lit11:
379260684Skaiw	case DW_OP_lit12:
380260684Skaiw	case DW_OP_lit13:
381260684Skaiw	case DW_OP_lit14:
382260684Skaiw	case DW_OP_lit15:
383260684Skaiw	case DW_OP_lit16:
384260684Skaiw	case DW_OP_lit17:
385260684Skaiw	case DW_OP_lit18:
386260684Skaiw	case DW_OP_lit19:
387260684Skaiw	case DW_OP_lit20:
388260684Skaiw	case DW_OP_lit21:
389260684Skaiw	case DW_OP_lit22:
390260684Skaiw	case DW_OP_lit23:
391260684Skaiw	case DW_OP_lit24:
392260684Skaiw	case DW_OP_lit25:
393260684Skaiw	case DW_OP_lit26:
394260684Skaiw	case DW_OP_lit27:
395260684Skaiw	case DW_OP_lit28:
396260684Skaiw	case DW_OP_lit29:
397260684Skaiw	case DW_OP_lit30:
398260684Skaiw	case DW_OP_lit31:
399260684Skaiw
400260684Skaiw	case DW_OP_dup:
401260684Skaiw	case DW_OP_drop:
402260684Skaiw
403260684Skaiw	case DW_OP_over:
404260684Skaiw
405260684Skaiw	case DW_OP_swap:
406260684Skaiw	case DW_OP_rot:
407260684Skaiw	case DW_OP_xderef:
408260684Skaiw
409260684Skaiw	case DW_OP_abs:
410260684Skaiw	case DW_OP_and:
411260684Skaiw	case DW_OP_div:
412260684Skaiw	case DW_OP_minus:
413260684Skaiw	case DW_OP_mod:
414260684Skaiw	case DW_OP_mul:
415260684Skaiw	case DW_OP_neg:
416260684Skaiw	case DW_OP_not:
417260684Skaiw	case DW_OP_or:
418260684Skaiw	case DW_OP_plus:
419260684Skaiw
420260684Skaiw	case DW_OP_shl:
421260684Skaiw	case DW_OP_shr:
422260684Skaiw	case DW_OP_shra:
423260684Skaiw	case DW_OP_xor:
424260684Skaiw
425260684Skaiw	case DW_OP_eq:
426260684Skaiw	case DW_OP_ge:
427260684Skaiw	case DW_OP_gt:
428260684Skaiw	case DW_OP_le:
429260684Skaiw	case DW_OP_lt:
430260684Skaiw	case DW_OP_ne:
431260684Skaiw
432260684Skaiw	case DW_OP_nop:
433260684Skaiw	case DW_OP_GNU_push_tls_address:
434260684Skaiw		*p++ = atom;
435260684Skaiw		break;
436260684Skaiw
437260684Skaiw	/* Operations with 1-byte operands. */
438260684Skaiw	case DW_OP_const1u:
439260684Skaiw	case DW_OP_const1s:
440260684Skaiw	case DW_OP_pick:
441260684Skaiw	case DW_OP_deref_size:
442260684Skaiw	case DW_OP_xderef_size:
443260684Skaiw		*p++ = atom;
444260684Skaiw		*p++ = (uint8_t) operand1;
445260684Skaiw		break;
446260684Skaiw
447260684Skaiw	/* Operations with 2-byte operands. */
448260684Skaiw	case DW_OP_const2u:
449260684Skaiw	case DW_OP_const2s:
450260684Skaiw	case DW_OP_bra:
451260684Skaiw	case DW_OP_skip:
452260684Skaiw		*p++ = atom;
453260684Skaiw		offset = 0;
454260684Skaiw		dbg->write(p, &offset, operand1, 2);
455260684Skaiw		p += 2;
456260684Skaiw		break;
457260684Skaiw
458260684Skaiw	/* Operations with 4-byte operands. */
459260684Skaiw	case DW_OP_const4u:
460260684Skaiw	case DW_OP_const4s:
461260684Skaiw		*p++ = atom;
462260684Skaiw		offset = 0;
463260684Skaiw		dbg->write(p, &offset, operand1, 4);
464260684Skaiw		p += 4;
465260684Skaiw		break;
466260684Skaiw
467260684Skaiw	/* Operations with 8-byte operands. */
468260684Skaiw	case DW_OP_const8u:
469260684Skaiw	case DW_OP_const8s:
470260684Skaiw		*p++ = atom;
471260684Skaiw		offset = 0;
472260684Skaiw		dbg->write(p, &offset, operand1, 8);
473260684Skaiw		p += 8;
474260684Skaiw		break;
475260684Skaiw
476260684Skaiw	/* Operations with an unsigned LEB128 operand. */
477260684Skaiw	case DW_OP_constu:
478260684Skaiw	case DW_OP_plus_uconst:
479260684Skaiw	case DW_OP_regx:
480260684Skaiw	case DW_OP_piece:
481260684Skaiw		*p++ = atom;
482260684Skaiw		len = _dwarf_write_uleb128(p, pe, operand1);
483260684Skaiw		assert(len > 0);
484260684Skaiw		p += len;
485260684Skaiw		break;
486260684Skaiw
487260684Skaiw	/* Operations with a signed LEB128 operand. */
488260684Skaiw	case DW_OP_consts:
489260684Skaiw	case DW_OP_breg0:
490260684Skaiw	case DW_OP_breg1:
491260684Skaiw	case DW_OP_breg2:
492260684Skaiw	case DW_OP_breg3:
493260684Skaiw	case DW_OP_breg4:
494260684Skaiw	case DW_OP_breg5:
495260684Skaiw	case DW_OP_breg6:
496260684Skaiw	case DW_OP_breg7:
497260684Skaiw	case DW_OP_breg8:
498260684Skaiw	case DW_OP_breg9:
499260684Skaiw	case DW_OP_breg10:
500260684Skaiw	case DW_OP_breg11:
501260684Skaiw	case DW_OP_breg12:
502260684Skaiw	case DW_OP_breg13:
503260684Skaiw	case DW_OP_breg14:
504260684Skaiw	case DW_OP_breg15:
505260684Skaiw	case DW_OP_breg16:
506260684Skaiw	case DW_OP_breg17:
507260684Skaiw	case DW_OP_breg18:
508260684Skaiw	case DW_OP_breg19:
509260684Skaiw	case DW_OP_breg20:
510260684Skaiw	case DW_OP_breg21:
511260684Skaiw	case DW_OP_breg22:
512260684Skaiw	case DW_OP_breg23:
513260684Skaiw	case DW_OP_breg24:
514260684Skaiw	case DW_OP_breg25:
515260684Skaiw	case DW_OP_breg26:
516260684Skaiw	case DW_OP_breg27:
517260684Skaiw	case DW_OP_breg28:
518260684Skaiw	case DW_OP_breg29:
519260684Skaiw	case DW_OP_breg30:
520260684Skaiw	case DW_OP_breg31:
521260684Skaiw	case DW_OP_fbreg:
522260684Skaiw		*p++ = atom;
523260684Skaiw		len = _dwarf_write_sleb128(p, pe, operand1);
524260684Skaiw		assert(len > 0);
525260684Skaiw		p += len;
526260684Skaiw		break;
527260684Skaiw
528260684Skaiw	/*
529260684Skaiw	 * Operations with an unsigned LEB128 operand
530260684Skaiw	 * followed by a signed LEB128 operand.
531260684Skaiw	 */
532260684Skaiw	case DW_OP_bregx:
533260684Skaiw		*p++ = atom;
534260684Skaiw		len = _dwarf_write_uleb128(p, pe, operand1);
535260684Skaiw		assert(len > 0);
536260684Skaiw		p += len;
537260684Skaiw		len = _dwarf_write_sleb128(p, pe, operand2);
538260684Skaiw		assert(len > 0);
539260684Skaiw		p += len;
540260684Skaiw		break;
541260684Skaiw
542260684Skaiw	/* Target address size operand. */
543260684Skaiw	case DW_OP_addr:
544260684Skaiw		*p++ = atom;
545260684Skaiw		offset = 0;
546260684Skaiw		dbg->write(p, &offset, operand1, dbg->dbg_pointer_size);
547260684Skaiw		p += dbg->dbg_pointer_size;
548260684Skaiw		break;
549260684Skaiw
550260684Skaiw	/* All other operations cause an error. */
551260684Skaiw	default:
552260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_LOC_EXPR_BAD);
553260684Skaiw		return (DW_DLE_LOC_EXPR_BAD);
554260684Skaiw	}
555260684Skaiw
556260684Skaiw	if (length)
557260684Skaiw		*length = p - out;
558260684Skaiw
559260684Skaiw	return (DW_DLE_NONE);
560260684Skaiw}
561260684Skaiw
562260684Skaiwint
563260684Skaiw_dwarf_loc_fill_locdesc(Dwarf_Debug dbg, Dwarf_Locdesc *llbuf, uint8_t *in,
564260684Skaiw    uint64_t in_len, uint8_t pointer_size, Dwarf_Error *error)
565260684Skaiw{
566260684Skaiw	int num;
567260684Skaiw
568260684Skaiw	assert(llbuf != NULL);
569260684Skaiw	assert(in != NULL);
570260684Skaiw	assert(in_len > 0);
571260684Skaiw
572260684Skaiw	/* Compute the number of locations. */
573260684Skaiw	if ((num = _dwarf_loc_fill_loc(dbg, NULL, pointer_size, in, in_len)) <
574260684Skaiw	    0) {
575260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_LOC_EXPR_BAD);
576260684Skaiw		return (DW_DLE_LOC_EXPR_BAD);
577260684Skaiw	}
578260684Skaiw
579260684Skaiw	llbuf->ld_cents = num;
580260684Skaiw	if (num <= 0)
581260684Skaiw		return (DW_DLE_NONE);
582260684Skaiw
583260684Skaiw	if ((llbuf->ld_s = calloc(num, sizeof(Dwarf_Loc))) == NULL) {
584260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
585260684Skaiw		return (DW_DLE_MEMORY);
586260684Skaiw	}
587260684Skaiw
588260684Skaiw	(void) _dwarf_loc_fill_loc(dbg, llbuf, pointer_size, in, in_len);
589260684Skaiw
590260684Skaiw	return (DW_DLE_NONE);
591260684Skaiw}
592260684Skaiw
593260684Skaiwint
594260684Skaiw_dwarf_loc_fill_locexpr(Dwarf_Debug dbg, Dwarf_Locdesc **ret_llbuf, uint8_t *in,
595260684Skaiw    uint64_t in_len, uint8_t pointer_size, Dwarf_Error *error)
596260684Skaiw{
597260684Skaiw	Dwarf_Locdesc *llbuf;
598260684Skaiw	int ret;
599260684Skaiw
600260684Skaiw	if ((llbuf = malloc(sizeof(Dwarf_Locdesc))) == NULL) {
601260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
602260684Skaiw		return (DW_DLE_MEMORY);
603260684Skaiw	}
604260684Skaiw	llbuf->ld_lopc = 0;
605260684Skaiw	llbuf->ld_hipc = ~0ULL;
606260684Skaiw	llbuf->ld_s = NULL;
607260684Skaiw
608260684Skaiw	ret = _dwarf_loc_fill_locdesc(dbg, llbuf, in, in_len, pointer_size,
609260684Skaiw	    error);
610260684Skaiw	if (ret != DW_DLE_NONE) {
611260684Skaiw		free(llbuf);
612260684Skaiw		return (ret);
613260684Skaiw	}
614260684Skaiw
615260684Skaiw	*ret_llbuf = llbuf;
616260684Skaiw
617260684Skaiw	return (ret);
618260684Skaiw}
619260684Skaiw
620260684Skaiwint
621260684Skaiw_dwarf_loc_add(Dwarf_Die die, Dwarf_Attribute at, Dwarf_Error *error)
622260684Skaiw{
623260684Skaiw	Dwarf_Debug dbg;
624260684Skaiw	Dwarf_CU cu;
625260684Skaiw	int ret;
626260684Skaiw
627260684Skaiw	assert(at->at_ld == NULL);
628260684Skaiw	assert(at->u[1].u8p != NULL);
629260684Skaiw	assert(at->u[0].u64 > 0);
630260684Skaiw
631260684Skaiw	cu = die->die_cu;
632260684Skaiw	assert(cu != NULL);
633260684Skaiw
634260684Skaiw	dbg = cu->cu_dbg;
635260684Skaiw	assert(dbg != NULL);
636260684Skaiw
637260684Skaiw	ret = _dwarf_loc_fill_locexpr(dbg, &at->at_ld, at->u[1].u8p,
638260684Skaiw	    at->u[0].u64, cu->cu_pointer_size, error);
639260684Skaiw
640260684Skaiw	return (ret);
641260684Skaiw}
642