1260684Skaiw/*-
2260684Skaiw * Copyright (c) 2007 John Birrell (jb@freebsd.org)
3276371Semaste * Copyright (c) 2014 Kai Wang
4260684Skaiw * All rights reserved.
5260684Skaiw *
6260684Skaiw * Redistribution and use in source and binary forms, with or without
7260684Skaiw * modification, are permitted provided that the following conditions
8260684Skaiw * are met:
9260684Skaiw * 1. Redistributions of source code must retain the above copyright
10260684Skaiw *    notice, this list of conditions and the following disclaimer.
11260684Skaiw * 2. Redistributions in binary form must reproduce the above copyright
12260684Skaiw *    notice, this list of conditions and the following disclaimer in the
13260684Skaiw *    documentation and/or other materials provided with the distribution.
14260684Skaiw *
15260684Skaiw * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16260684Skaiw * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17260684Skaiw * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18260684Skaiw * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19260684Skaiw * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20260684Skaiw * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21260684Skaiw * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22260684Skaiw * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23260684Skaiw * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24260684Skaiw * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25260684Skaiw * SUCH DAMAGE.
26260684Skaiw */
27260684Skaiw
28260684Skaiw#include "_libdwarf.h"
29260684Skaiw
30276371SemasteELFTC_VCSID("$Id: libdwarf_loc.c 3070 2014-06-23 03:08:33Z kaiwang27 $");
31260684Skaiw
32260684Skaiw/*
33260684Skaiw * Given an array of bytes of length 'len' representing a
34260684Skaiw * DWARF expression, compute the number of operations based
35260684Skaiw * on there being one byte describing the operation and
36260684Skaiw * zero or more bytes of operands as defined in the standard
37260684Skaiw * for each operation type. Also, if lbuf is non-null, store
38260684Skaiw * the opcode and oprand in it.
39260684Skaiw */
40260684Skaiwstatic int
41260684Skaiw_dwarf_loc_fill_loc(Dwarf_Debug dbg, Dwarf_Locdesc *lbuf, uint8_t pointer_size,
42276371Semaste    uint8_t offset_size, uint8_t version, uint8_t *p, int len)
43260684Skaiw{
44260684Skaiw	int count;
45260684Skaiw	uint64_t operand1;
46260684Skaiw	uint64_t operand2;
47276371Semaste	uint8_t *ps, *pe, s;
48260684Skaiw
49260684Skaiw	count = 0;
50260684Skaiw	ps = p;
51260684Skaiw	pe = p + len;
52260684Skaiw
53260684Skaiw	/*
54260684Skaiw	 * Process each byte. If an error occurs, then the
55260684Skaiw	 * count will be set to -1.
56260684Skaiw	 */
57260684Skaiw	while (p < pe) {
58260684Skaiw
59260684Skaiw		operand1 = 0;
60260684Skaiw		operand2 = 0;
61260684Skaiw
62260684Skaiw		if (lbuf != NULL) {
63260684Skaiw			lbuf->ld_s[count].lr_atom = *p;
64260684Skaiw			lbuf->ld_s[count].lr_offset = p - ps;
65260684Skaiw		}
66260684Skaiw
67260684Skaiw		switch (*p++) {
68260684Skaiw		/* Operations with no operands. */
69260684Skaiw		case DW_OP_deref:
70260684Skaiw		case DW_OP_reg0:
71260684Skaiw		case DW_OP_reg1:
72260684Skaiw		case DW_OP_reg2:
73260684Skaiw		case DW_OP_reg3:
74260684Skaiw		case DW_OP_reg4:
75260684Skaiw		case DW_OP_reg5:
76260684Skaiw		case DW_OP_reg6:
77260684Skaiw		case DW_OP_reg7:
78260684Skaiw		case DW_OP_reg8:
79260684Skaiw		case DW_OP_reg9:
80260684Skaiw		case DW_OP_reg10:
81260684Skaiw		case DW_OP_reg11:
82260684Skaiw		case DW_OP_reg12:
83260684Skaiw		case DW_OP_reg13:
84260684Skaiw		case DW_OP_reg14:
85260684Skaiw		case DW_OP_reg15:
86260684Skaiw		case DW_OP_reg16:
87260684Skaiw		case DW_OP_reg17:
88260684Skaiw		case DW_OP_reg18:
89260684Skaiw		case DW_OP_reg19:
90260684Skaiw		case DW_OP_reg20:
91260684Skaiw		case DW_OP_reg21:
92260684Skaiw		case DW_OP_reg22:
93260684Skaiw		case DW_OP_reg23:
94260684Skaiw		case DW_OP_reg24:
95260684Skaiw		case DW_OP_reg25:
96260684Skaiw		case DW_OP_reg26:
97260684Skaiw		case DW_OP_reg27:
98260684Skaiw		case DW_OP_reg28:
99260684Skaiw		case DW_OP_reg29:
100260684Skaiw		case DW_OP_reg30:
101260684Skaiw		case DW_OP_reg31:
102260684Skaiw
103260684Skaiw		case DW_OP_lit0:
104260684Skaiw		case DW_OP_lit1:
105260684Skaiw		case DW_OP_lit2:
106260684Skaiw		case DW_OP_lit3:
107260684Skaiw		case DW_OP_lit4:
108260684Skaiw		case DW_OP_lit5:
109260684Skaiw		case DW_OP_lit6:
110260684Skaiw		case DW_OP_lit7:
111260684Skaiw		case DW_OP_lit8:
112260684Skaiw		case DW_OP_lit9:
113260684Skaiw		case DW_OP_lit10:
114260684Skaiw		case DW_OP_lit11:
115260684Skaiw		case DW_OP_lit12:
116260684Skaiw		case DW_OP_lit13:
117260684Skaiw		case DW_OP_lit14:
118260684Skaiw		case DW_OP_lit15:
119260684Skaiw		case DW_OP_lit16:
120260684Skaiw		case DW_OP_lit17:
121260684Skaiw		case DW_OP_lit18:
122260684Skaiw		case DW_OP_lit19:
123260684Skaiw		case DW_OP_lit20:
124260684Skaiw		case DW_OP_lit21:
125260684Skaiw		case DW_OP_lit22:
126260684Skaiw		case DW_OP_lit23:
127260684Skaiw		case DW_OP_lit24:
128260684Skaiw		case DW_OP_lit25:
129260684Skaiw		case DW_OP_lit26:
130260684Skaiw		case DW_OP_lit27:
131260684Skaiw		case DW_OP_lit28:
132260684Skaiw		case DW_OP_lit29:
133260684Skaiw		case DW_OP_lit30:
134260684Skaiw		case DW_OP_lit31:
135260684Skaiw
136260684Skaiw		case DW_OP_dup:
137260684Skaiw		case DW_OP_drop:
138260684Skaiw
139260684Skaiw		case DW_OP_over:
140260684Skaiw
141260684Skaiw		case DW_OP_swap:
142260684Skaiw		case DW_OP_rot:
143260684Skaiw		case DW_OP_xderef:
144260684Skaiw
145260684Skaiw		case DW_OP_abs:
146260684Skaiw		case DW_OP_and:
147260684Skaiw		case DW_OP_div:
148260684Skaiw		case DW_OP_minus:
149260684Skaiw		case DW_OP_mod:
150260684Skaiw		case DW_OP_mul:
151260684Skaiw		case DW_OP_neg:
152260684Skaiw		case DW_OP_not:
153260684Skaiw		case DW_OP_or:
154260684Skaiw		case DW_OP_plus:
155260684Skaiw
156260684Skaiw		case DW_OP_shl:
157260684Skaiw		case DW_OP_shr:
158260684Skaiw		case DW_OP_shra:
159260684Skaiw		case DW_OP_xor:
160260684Skaiw
161260684Skaiw		case DW_OP_eq:
162260684Skaiw		case DW_OP_ge:
163260684Skaiw		case DW_OP_gt:
164260684Skaiw		case DW_OP_le:
165260684Skaiw		case DW_OP_lt:
166260684Skaiw		case DW_OP_ne:
167260684Skaiw
168260684Skaiw		case DW_OP_nop:
169276371Semaste		case DW_OP_push_object_address:
170260684Skaiw		case DW_OP_form_tls_address:
171260684Skaiw		case DW_OP_call_frame_cfa:
172260684Skaiw		case DW_OP_stack_value:
173260684Skaiw		case DW_OP_GNU_push_tls_address:
174276371Semaste		case DW_OP_GNU_uninit:
175260684Skaiw			break;
176260684Skaiw
177260684Skaiw		/* Operations with 1-byte operands. */
178260684Skaiw		case DW_OP_const1u:
179260684Skaiw		case DW_OP_pick:
180260684Skaiw		case DW_OP_deref_size:
181260684Skaiw		case DW_OP_xderef_size:
182260684Skaiw			operand1 = *p++;
183260684Skaiw			break;
184260684Skaiw
185276371Semaste		case DW_OP_const1s:
186276371Semaste			operand1 = (int8_t) *p++;
187276371Semaste			break;
188276371Semaste
189260684Skaiw		/* Operations with 2-byte operands. */
190260684Skaiw		case DW_OP_call2:
191260684Skaiw		case DW_OP_const2u:
192260684Skaiw		case DW_OP_bra:
193260684Skaiw		case DW_OP_skip:
194260684Skaiw			operand1 = dbg->decode(&p, 2);
195260684Skaiw			break;
196260684Skaiw
197276371Semaste		case DW_OP_const2s:
198276371Semaste			operand1 = (int16_t) dbg->decode(&p, 2);
199276371Semaste			break;
200276371Semaste
201260684Skaiw		/* Operations with 4-byte operands. */
202260684Skaiw		case DW_OP_call4:
203260684Skaiw		case DW_OP_const4u:
204276371Semaste		case DW_OP_GNU_parameter_ref:
205260684Skaiw			operand1 = dbg->decode(&p, 4);
206260684Skaiw			break;
207260684Skaiw
208276371Semaste		case DW_OP_const4s:
209276371Semaste			operand1 = (int32_t) dbg->decode(&p, 4);
210276371Semaste			break;
211276371Semaste
212260684Skaiw		/* Operations with 8-byte operands. */
213260684Skaiw		case DW_OP_const8u:
214260684Skaiw		case DW_OP_const8s:
215260684Skaiw			operand1 = dbg->decode(&p, 8);
216260684Skaiw			break;
217260684Skaiw
218260684Skaiw		/* Operations with an unsigned LEB128 operand. */
219260684Skaiw		case DW_OP_constu:
220260684Skaiw		case DW_OP_plus_uconst:
221260684Skaiw		case DW_OP_regx:
222260684Skaiw		case DW_OP_piece:
223276371Semaste		case DW_OP_GNU_deref_type:
224276371Semaste		case DW_OP_GNU_convert:
225276371Semaste		case DW_OP_GNU_reinterpret:
226260684Skaiw			operand1 = _dwarf_decode_uleb128(&p);
227260684Skaiw			break;
228260684Skaiw
229260684Skaiw		/* Operations with a signed LEB128 operand. */
230260684Skaiw		case DW_OP_consts:
231260684Skaiw		case DW_OP_breg0:
232260684Skaiw		case DW_OP_breg1:
233260684Skaiw		case DW_OP_breg2:
234260684Skaiw		case DW_OP_breg3:
235260684Skaiw		case DW_OP_breg4:
236260684Skaiw		case DW_OP_breg5:
237260684Skaiw		case DW_OP_breg6:
238260684Skaiw		case DW_OP_breg7:
239260684Skaiw		case DW_OP_breg8:
240260684Skaiw		case DW_OP_breg9:
241260684Skaiw		case DW_OP_breg10:
242260684Skaiw		case DW_OP_breg11:
243260684Skaiw		case DW_OP_breg12:
244260684Skaiw		case DW_OP_breg13:
245260684Skaiw		case DW_OP_breg14:
246260684Skaiw		case DW_OP_breg15:
247260684Skaiw		case DW_OP_breg16:
248260684Skaiw		case DW_OP_breg17:
249260684Skaiw		case DW_OP_breg18:
250260684Skaiw		case DW_OP_breg19:
251260684Skaiw		case DW_OP_breg20:
252260684Skaiw		case DW_OP_breg21:
253260684Skaiw		case DW_OP_breg22:
254260684Skaiw		case DW_OP_breg23:
255260684Skaiw		case DW_OP_breg24:
256260684Skaiw		case DW_OP_breg25:
257260684Skaiw		case DW_OP_breg26:
258260684Skaiw		case DW_OP_breg27:
259260684Skaiw		case DW_OP_breg28:
260260684Skaiw		case DW_OP_breg29:
261260684Skaiw		case DW_OP_breg30:
262260684Skaiw		case DW_OP_breg31:
263260684Skaiw		case DW_OP_fbreg:
264260684Skaiw			operand1 = _dwarf_decode_sleb128(&p);
265260684Skaiw			break;
266260684Skaiw
267260684Skaiw		/*
268260684Skaiw		 * Oeration with two unsigned LEB128 operands.
269260684Skaiw		 */
270260684Skaiw		case DW_OP_bit_piece:
271276371Semaste		case DW_OP_GNU_regval_type:
272260684Skaiw			operand1 = _dwarf_decode_uleb128(&p);
273260684Skaiw			operand2 = _dwarf_decode_uleb128(&p);
274260684Skaiw			break;
275260684Skaiw
276260684Skaiw		/*
277260684Skaiw		 * Operations with an unsigned LEB128 operand
278260684Skaiw		 * followed by a signed LEB128 operand.
279260684Skaiw		 */
280260684Skaiw		case DW_OP_bregx:
281260684Skaiw			operand1 = _dwarf_decode_uleb128(&p);
282260684Skaiw			operand2 = _dwarf_decode_sleb128(&p);
283260684Skaiw			break;
284260684Skaiw
285260684Skaiw		/*
286260684Skaiw		 * Operation with an unsigned LEB128 operand
287276371Semaste		 * representing the size of a block, followed
288276371Semaste		 * by the block content.
289276371Semaste		 *
290276371Semaste		 * Store the size of the block in the operand1
291276371Semaste		 * and a pointer to the block in the operand2.
292260684Skaiw		 */
293260684Skaiw		case DW_OP_implicit_value:
294276371Semaste		case DW_OP_GNU_entry_value:
295260684Skaiw			operand1 = _dwarf_decode_uleb128(&p);
296260684Skaiw			operand2 = (Dwarf_Unsigned) (uintptr_t) p;
297260684Skaiw			p += operand1;
298260684Skaiw			break;
299260684Skaiw
300260684Skaiw		/* Target address size operand. */
301260684Skaiw		case DW_OP_addr:
302276371Semaste		case DW_OP_GNU_addr_index:
303276371Semaste		case DW_OP_GNU_const_index:
304260684Skaiw			operand1 = dbg->decode(&p, pointer_size);
305260684Skaiw			break;
306260684Skaiw
307276371Semaste		/* Offset size operand. */
308276371Semaste		case DW_OP_call_ref:
309276371Semaste			operand1 = dbg->decode(&p, offset_size);
310276371Semaste			break;
311276371Semaste
312260684Skaiw		/*
313276371Semaste		 * The first byte is address byte length, followed by
314276371Semaste		 * the address value. If the length is 0, the address
315276371Semaste		 * size is the same as target pointer size.
316260684Skaiw		 */
317276371Semaste		case DW_OP_GNU_encoded_addr:
318276371Semaste			s = *p++;
319276371Semaste			if (s == 0)
320276371Semaste				s = pointer_size;
321276371Semaste			operand1 = dbg->decode(&p, s);
322260684Skaiw			break;
323260684Skaiw
324276371Semaste		/*
325276371Semaste		 * Operand1: DIE offset (size depending on DWARF version)
326276371Semaste		 * DWARF2: pointer size
327276371Semaste		 * DWARF{3,4}: offset size
328276371Semaste		 *
329276371Semaste		 * Operand2: SLEB128
330276371Semaste		 */
331276371Semaste		case DW_OP_GNU_implicit_pointer:
332276371Semaste			if (version == 2)
333276371Semaste				operand1 = dbg->decode(&p, pointer_size);
334276371Semaste			else
335276371Semaste				operand1 = dbg->decode(&p, offset_size);
336276371Semaste			operand2 = _dwarf_decode_sleb128(&p);
337276371Semaste			break;
338276371Semaste
339276371Semaste		/*
340276371Semaste		 * Operand1: DIE offset (ULEB128)
341276371Semaste		 * Operand2: pointer to a block. The block's first byte
342276371Semaste		 * is its size.
343276371Semaste		 */
344276371Semaste		case DW_OP_GNU_const_type:
345276371Semaste			operand1 = _dwarf_decode_uleb128(&p);
346276371Semaste			operand2 = (Dwarf_Unsigned) (uintptr_t) p;
347276371Semaste			s = *p++;
348276371Semaste			p += s;
349276371Semaste			break;
350276371Semaste
351260684Skaiw		/* All other operations cause an error. */
352260684Skaiw		default:
353260684Skaiw			count = -1;
354276371Semaste			goto done;
355260684Skaiw		}
356260684Skaiw
357260684Skaiw		if (lbuf != NULL) {
358260684Skaiw			lbuf->ld_s[count].lr_number = operand1;
359260684Skaiw			lbuf->ld_s[count].lr_number2 = operand2;
360260684Skaiw		}
361260684Skaiw
362260684Skaiw		count++;
363260684Skaiw	}
364260684Skaiw
365276371Semastedone:
366260684Skaiw	return (count);
367260684Skaiw}
368260684Skaiw
369260684Skaiwint
370260684Skaiw_dwarf_loc_expr_add_atom(Dwarf_Debug dbg, uint8_t *out, uint8_t *end,
371260684Skaiw    Dwarf_Small atom, Dwarf_Unsigned operand1, Dwarf_Unsigned operand2,
372260684Skaiw    int *length, Dwarf_Error *error)
373260684Skaiw{
374260684Skaiw	uint8_t buf[64];
375260684Skaiw	uint8_t *p, *pe;
376260684Skaiw	uint64_t offset;
377260684Skaiw	int len;
378260684Skaiw
379260684Skaiw	if (out != NULL && end != NULL) {
380260684Skaiw		p = out;
381260684Skaiw		pe = end;
382260684Skaiw	} else {
383260684Skaiw		p = out = buf;
384260684Skaiw		pe = &buf[sizeof(buf)];
385260684Skaiw	}
386260684Skaiw
387260684Skaiw	switch (atom) {
388260684Skaiw	/* Operations with no operands. */
389260684Skaiw	case DW_OP_deref:
390260684Skaiw	case DW_OP_reg0:
391260684Skaiw	case DW_OP_reg1:
392260684Skaiw	case DW_OP_reg2:
393260684Skaiw	case DW_OP_reg3:
394260684Skaiw	case DW_OP_reg4:
395260684Skaiw	case DW_OP_reg5:
396260684Skaiw	case DW_OP_reg6:
397260684Skaiw	case DW_OP_reg7:
398260684Skaiw	case DW_OP_reg8:
399260684Skaiw	case DW_OP_reg9:
400260684Skaiw	case DW_OP_reg10:
401260684Skaiw	case DW_OP_reg11:
402260684Skaiw	case DW_OP_reg12:
403260684Skaiw	case DW_OP_reg13:
404260684Skaiw	case DW_OP_reg14:
405260684Skaiw	case DW_OP_reg15:
406260684Skaiw	case DW_OP_reg16:
407260684Skaiw	case DW_OP_reg17:
408260684Skaiw	case DW_OP_reg18:
409260684Skaiw	case DW_OP_reg19:
410260684Skaiw	case DW_OP_reg20:
411260684Skaiw	case DW_OP_reg21:
412260684Skaiw	case DW_OP_reg22:
413260684Skaiw	case DW_OP_reg23:
414260684Skaiw	case DW_OP_reg24:
415260684Skaiw	case DW_OP_reg25:
416260684Skaiw	case DW_OP_reg26:
417260684Skaiw	case DW_OP_reg27:
418260684Skaiw	case DW_OP_reg28:
419260684Skaiw	case DW_OP_reg29:
420260684Skaiw	case DW_OP_reg30:
421260684Skaiw	case DW_OP_reg31:
422260684Skaiw
423260684Skaiw	case DW_OP_lit0:
424260684Skaiw	case DW_OP_lit1:
425260684Skaiw	case DW_OP_lit2:
426260684Skaiw	case DW_OP_lit3:
427260684Skaiw	case DW_OP_lit4:
428260684Skaiw	case DW_OP_lit5:
429260684Skaiw	case DW_OP_lit6:
430260684Skaiw	case DW_OP_lit7:
431260684Skaiw	case DW_OP_lit8:
432260684Skaiw	case DW_OP_lit9:
433260684Skaiw	case DW_OP_lit10:
434260684Skaiw	case DW_OP_lit11:
435260684Skaiw	case DW_OP_lit12:
436260684Skaiw	case DW_OP_lit13:
437260684Skaiw	case DW_OP_lit14:
438260684Skaiw	case DW_OP_lit15:
439260684Skaiw	case DW_OP_lit16:
440260684Skaiw	case DW_OP_lit17:
441260684Skaiw	case DW_OP_lit18:
442260684Skaiw	case DW_OP_lit19:
443260684Skaiw	case DW_OP_lit20:
444260684Skaiw	case DW_OP_lit21:
445260684Skaiw	case DW_OP_lit22:
446260684Skaiw	case DW_OP_lit23:
447260684Skaiw	case DW_OP_lit24:
448260684Skaiw	case DW_OP_lit25:
449260684Skaiw	case DW_OP_lit26:
450260684Skaiw	case DW_OP_lit27:
451260684Skaiw	case DW_OP_lit28:
452260684Skaiw	case DW_OP_lit29:
453260684Skaiw	case DW_OP_lit30:
454260684Skaiw	case DW_OP_lit31:
455260684Skaiw
456260684Skaiw	case DW_OP_dup:
457260684Skaiw	case DW_OP_drop:
458260684Skaiw
459260684Skaiw	case DW_OP_over:
460260684Skaiw
461260684Skaiw	case DW_OP_swap:
462260684Skaiw	case DW_OP_rot:
463260684Skaiw	case DW_OP_xderef:
464260684Skaiw
465260684Skaiw	case DW_OP_abs:
466260684Skaiw	case DW_OP_and:
467260684Skaiw	case DW_OP_div:
468260684Skaiw	case DW_OP_minus:
469260684Skaiw	case DW_OP_mod:
470260684Skaiw	case DW_OP_mul:
471260684Skaiw	case DW_OP_neg:
472260684Skaiw	case DW_OP_not:
473260684Skaiw	case DW_OP_or:
474260684Skaiw	case DW_OP_plus:
475260684Skaiw
476260684Skaiw	case DW_OP_shl:
477260684Skaiw	case DW_OP_shr:
478260684Skaiw	case DW_OP_shra:
479260684Skaiw	case DW_OP_xor:
480260684Skaiw
481260684Skaiw	case DW_OP_eq:
482260684Skaiw	case DW_OP_ge:
483260684Skaiw	case DW_OP_gt:
484260684Skaiw	case DW_OP_le:
485260684Skaiw	case DW_OP_lt:
486260684Skaiw	case DW_OP_ne:
487260684Skaiw
488260684Skaiw	case DW_OP_nop:
489260684Skaiw	case DW_OP_GNU_push_tls_address:
490260684Skaiw		*p++ = atom;
491260684Skaiw		break;
492260684Skaiw
493260684Skaiw	/* Operations with 1-byte operands. */
494260684Skaiw	case DW_OP_const1u:
495260684Skaiw	case DW_OP_const1s:
496260684Skaiw	case DW_OP_pick:
497260684Skaiw	case DW_OP_deref_size:
498260684Skaiw	case DW_OP_xderef_size:
499260684Skaiw		*p++ = atom;
500260684Skaiw		*p++ = (uint8_t) operand1;
501260684Skaiw		break;
502260684Skaiw
503260684Skaiw	/* Operations with 2-byte operands. */
504260684Skaiw	case DW_OP_const2u:
505260684Skaiw	case DW_OP_const2s:
506260684Skaiw	case DW_OP_bra:
507260684Skaiw	case DW_OP_skip:
508260684Skaiw		*p++ = atom;
509260684Skaiw		offset = 0;
510260684Skaiw		dbg->write(p, &offset, operand1, 2);
511260684Skaiw		p += 2;
512260684Skaiw		break;
513260684Skaiw
514260684Skaiw	/* Operations with 4-byte operands. */
515260684Skaiw	case DW_OP_const4u:
516260684Skaiw	case DW_OP_const4s:
517260684Skaiw		*p++ = atom;
518260684Skaiw		offset = 0;
519260684Skaiw		dbg->write(p, &offset, operand1, 4);
520260684Skaiw		p += 4;
521260684Skaiw		break;
522260684Skaiw
523260684Skaiw	/* Operations with 8-byte operands. */
524260684Skaiw	case DW_OP_const8u:
525260684Skaiw	case DW_OP_const8s:
526260684Skaiw		*p++ = atom;
527260684Skaiw		offset = 0;
528260684Skaiw		dbg->write(p, &offset, operand1, 8);
529260684Skaiw		p += 8;
530260684Skaiw		break;
531260684Skaiw
532260684Skaiw	/* Operations with an unsigned LEB128 operand. */
533260684Skaiw	case DW_OP_constu:
534260684Skaiw	case DW_OP_plus_uconst:
535260684Skaiw	case DW_OP_regx:
536260684Skaiw	case DW_OP_piece:
537260684Skaiw		*p++ = atom;
538260684Skaiw		len = _dwarf_write_uleb128(p, pe, operand1);
539260684Skaiw		assert(len > 0);
540260684Skaiw		p += len;
541260684Skaiw		break;
542260684Skaiw
543260684Skaiw	/* Operations with a signed LEB128 operand. */
544260684Skaiw	case DW_OP_consts:
545260684Skaiw	case DW_OP_breg0:
546260684Skaiw	case DW_OP_breg1:
547260684Skaiw	case DW_OP_breg2:
548260684Skaiw	case DW_OP_breg3:
549260684Skaiw	case DW_OP_breg4:
550260684Skaiw	case DW_OP_breg5:
551260684Skaiw	case DW_OP_breg6:
552260684Skaiw	case DW_OP_breg7:
553260684Skaiw	case DW_OP_breg8:
554260684Skaiw	case DW_OP_breg9:
555260684Skaiw	case DW_OP_breg10:
556260684Skaiw	case DW_OP_breg11:
557260684Skaiw	case DW_OP_breg12:
558260684Skaiw	case DW_OP_breg13:
559260684Skaiw	case DW_OP_breg14:
560260684Skaiw	case DW_OP_breg15:
561260684Skaiw	case DW_OP_breg16:
562260684Skaiw	case DW_OP_breg17:
563260684Skaiw	case DW_OP_breg18:
564260684Skaiw	case DW_OP_breg19:
565260684Skaiw	case DW_OP_breg20:
566260684Skaiw	case DW_OP_breg21:
567260684Skaiw	case DW_OP_breg22:
568260684Skaiw	case DW_OP_breg23:
569260684Skaiw	case DW_OP_breg24:
570260684Skaiw	case DW_OP_breg25:
571260684Skaiw	case DW_OP_breg26:
572260684Skaiw	case DW_OP_breg27:
573260684Skaiw	case DW_OP_breg28:
574260684Skaiw	case DW_OP_breg29:
575260684Skaiw	case DW_OP_breg30:
576260684Skaiw	case DW_OP_breg31:
577260684Skaiw	case DW_OP_fbreg:
578260684Skaiw		*p++ = atom;
579260684Skaiw		len = _dwarf_write_sleb128(p, pe, operand1);
580260684Skaiw		assert(len > 0);
581260684Skaiw		p += len;
582260684Skaiw		break;
583260684Skaiw
584260684Skaiw	/*
585260684Skaiw	 * Operations with an unsigned LEB128 operand
586260684Skaiw	 * followed by a signed LEB128 operand.
587260684Skaiw	 */
588260684Skaiw	case DW_OP_bregx:
589260684Skaiw		*p++ = atom;
590260684Skaiw		len = _dwarf_write_uleb128(p, pe, operand1);
591260684Skaiw		assert(len > 0);
592260684Skaiw		p += len;
593260684Skaiw		len = _dwarf_write_sleb128(p, pe, operand2);
594260684Skaiw		assert(len > 0);
595260684Skaiw		p += len;
596260684Skaiw		break;
597260684Skaiw
598260684Skaiw	/* Target address size operand. */
599260684Skaiw	case DW_OP_addr:
600260684Skaiw		*p++ = atom;
601260684Skaiw		offset = 0;
602260684Skaiw		dbg->write(p, &offset, operand1, dbg->dbg_pointer_size);
603260684Skaiw		p += dbg->dbg_pointer_size;
604260684Skaiw		break;
605260684Skaiw
606260684Skaiw	/* All other operations cause an error. */
607260684Skaiw	default:
608260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_LOC_EXPR_BAD);
609260684Skaiw		return (DW_DLE_LOC_EXPR_BAD);
610260684Skaiw	}
611260684Skaiw
612260684Skaiw	if (length)
613260684Skaiw		*length = p - out;
614260684Skaiw
615260684Skaiw	return (DW_DLE_NONE);
616260684Skaiw}
617260684Skaiw
618260684Skaiwint
619260684Skaiw_dwarf_loc_fill_locdesc(Dwarf_Debug dbg, Dwarf_Locdesc *llbuf, uint8_t *in,
620276371Semaste    uint64_t in_len, uint8_t pointer_size, uint8_t offset_size,
621276371Semaste    uint8_t version, Dwarf_Error *error)
622260684Skaiw{
623260684Skaiw	int num;
624260684Skaiw
625260684Skaiw	assert(llbuf != NULL);
626260684Skaiw	assert(in != NULL);
627260684Skaiw	assert(in_len > 0);
628260684Skaiw
629260684Skaiw	/* Compute the number of locations. */
630276371Semaste	if ((num = _dwarf_loc_fill_loc(dbg, NULL, pointer_size, offset_size,
631276371Semaste	    version, in, in_len)) < 0) {
632260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_LOC_EXPR_BAD);
633260684Skaiw		return (DW_DLE_LOC_EXPR_BAD);
634260684Skaiw	}
635260684Skaiw
636260684Skaiw	llbuf->ld_cents = num;
637260684Skaiw	if (num <= 0)
638260684Skaiw		return (DW_DLE_NONE);
639260684Skaiw
640260684Skaiw	if ((llbuf->ld_s = calloc(num, sizeof(Dwarf_Loc))) == NULL) {
641260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
642260684Skaiw		return (DW_DLE_MEMORY);
643260684Skaiw	}
644260684Skaiw
645276371Semaste	(void) _dwarf_loc_fill_loc(dbg, llbuf, pointer_size, offset_size,
646276371Semaste	    version, in, in_len);
647260684Skaiw
648260684Skaiw	return (DW_DLE_NONE);
649260684Skaiw}
650260684Skaiw
651260684Skaiwint
652260684Skaiw_dwarf_loc_fill_locexpr(Dwarf_Debug dbg, Dwarf_Locdesc **ret_llbuf, uint8_t *in,
653276371Semaste    uint64_t in_len, uint8_t pointer_size, uint8_t offset_size,
654276371Semaste    uint8_t version, Dwarf_Error *error)
655260684Skaiw{
656260684Skaiw	Dwarf_Locdesc *llbuf;
657260684Skaiw	int ret;
658260684Skaiw
659260684Skaiw	if ((llbuf = malloc(sizeof(Dwarf_Locdesc))) == NULL) {
660260684Skaiw		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
661260684Skaiw		return (DW_DLE_MEMORY);
662260684Skaiw	}
663260684Skaiw	llbuf->ld_lopc = 0;
664260684Skaiw	llbuf->ld_hipc = ~0ULL;
665260684Skaiw	llbuf->ld_s = NULL;
666260684Skaiw
667260684Skaiw	ret = _dwarf_loc_fill_locdesc(dbg, llbuf, in, in_len, pointer_size,
668276371Semaste	    offset_size, version, error);
669260684Skaiw	if (ret != DW_DLE_NONE) {
670260684Skaiw		free(llbuf);
671260684Skaiw		return (ret);
672260684Skaiw	}
673260684Skaiw
674260684Skaiw	*ret_llbuf = llbuf;
675260684Skaiw
676260684Skaiw	return (ret);
677260684Skaiw}
678260684Skaiw
679260684Skaiwint
680260684Skaiw_dwarf_loc_add(Dwarf_Die die, Dwarf_Attribute at, Dwarf_Error *error)
681260684Skaiw{
682260684Skaiw	Dwarf_Debug dbg;
683260684Skaiw	Dwarf_CU cu;
684260684Skaiw	int ret;
685260684Skaiw
686260684Skaiw	assert(at->at_ld == NULL);
687260684Skaiw	assert(at->u[1].u8p != NULL);
688260684Skaiw	assert(at->u[0].u64 > 0);
689260684Skaiw
690260684Skaiw	cu = die->die_cu;
691260684Skaiw	assert(cu != NULL);
692260684Skaiw
693260684Skaiw	dbg = cu->cu_dbg;
694260684Skaiw	assert(dbg != NULL);
695260684Skaiw
696260684Skaiw	ret = _dwarf_loc_fill_locexpr(dbg, &at->at_ld, at->u[1].u8p,
697276371Semaste	    at->u[0].u64, cu->cu_pointer_size, cu->cu_length_size == 4 ? 4 : 8,
698276371Semaste	    cu->cu_version, error);
699260684Skaiw
700260684Skaiw	return (ret);
701260684Skaiw}
702