xref: /freebsd/contrib/elftoolchain/libdwarf/libdwarf_loc.c (revision 98e0ffaefb0f241cda3a72395d3be04192ae0d47)
12de3b87aSKai Wang /*-
22de3b87aSKai Wang  * Copyright (c) 2007 John Birrell (jb@freebsd.org)
3*cf781b2eSEd Maste  * Copyright (c) 2014 Kai Wang
42de3b87aSKai Wang  * All rights reserved.
52de3b87aSKai Wang  *
62de3b87aSKai Wang  * Redistribution and use in source and binary forms, with or without
72de3b87aSKai Wang  * modification, are permitted provided that the following conditions
82de3b87aSKai Wang  * are met:
92de3b87aSKai Wang  * 1. Redistributions of source code must retain the above copyright
102de3b87aSKai Wang  *    notice, this list of conditions and the following disclaimer.
112de3b87aSKai Wang  * 2. Redistributions in binary form must reproduce the above copyright
122de3b87aSKai Wang  *    notice, this list of conditions and the following disclaimer in the
132de3b87aSKai Wang  *    documentation and/or other materials provided with the distribution.
142de3b87aSKai Wang  *
152de3b87aSKai Wang  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
162de3b87aSKai Wang  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
172de3b87aSKai Wang  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
182de3b87aSKai Wang  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
192de3b87aSKai Wang  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
202de3b87aSKai Wang  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
212de3b87aSKai Wang  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
222de3b87aSKai Wang  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
232de3b87aSKai Wang  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
242de3b87aSKai Wang  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
252de3b87aSKai Wang  * SUCH DAMAGE.
262de3b87aSKai Wang  */
272de3b87aSKai Wang 
282de3b87aSKai Wang #include "_libdwarf.h"
292de3b87aSKai Wang 
30*cf781b2eSEd Maste ELFTC_VCSID("$Id: libdwarf_loc.c 3070 2014-06-23 03:08:33Z kaiwang27 $");
312de3b87aSKai Wang 
322de3b87aSKai Wang /*
332de3b87aSKai Wang  * Given an array of bytes of length 'len' representing a
342de3b87aSKai Wang  * DWARF expression, compute the number of operations based
352de3b87aSKai Wang  * on there being one byte describing the operation and
362de3b87aSKai Wang  * zero or more bytes of operands as defined in the standard
372de3b87aSKai Wang  * for each operation type. Also, if lbuf is non-null, store
382de3b87aSKai Wang  * the opcode and oprand in it.
392de3b87aSKai Wang  */
402de3b87aSKai Wang static int
_dwarf_loc_fill_loc(Dwarf_Debug dbg,Dwarf_Locdesc * lbuf,uint8_t pointer_size,uint8_t offset_size,uint8_t version,uint8_t * p,int len)412de3b87aSKai Wang _dwarf_loc_fill_loc(Dwarf_Debug dbg, Dwarf_Locdesc *lbuf, uint8_t pointer_size,
42*cf781b2eSEd Maste     uint8_t offset_size, uint8_t version, uint8_t *p, int len)
432de3b87aSKai Wang {
442de3b87aSKai Wang 	int count;
452de3b87aSKai Wang 	uint64_t operand1;
462de3b87aSKai Wang 	uint64_t operand2;
47*cf781b2eSEd Maste 	uint8_t *ps, *pe, s;
482de3b87aSKai Wang 
492de3b87aSKai Wang 	count = 0;
502de3b87aSKai Wang 	ps = p;
512de3b87aSKai Wang 	pe = p + len;
522de3b87aSKai Wang 
532de3b87aSKai Wang 	/*
542de3b87aSKai Wang 	 * Process each byte. If an error occurs, then the
552de3b87aSKai Wang 	 * count will be set to -1.
562de3b87aSKai Wang 	 */
572de3b87aSKai Wang 	while (p < pe) {
582de3b87aSKai Wang 
592de3b87aSKai Wang 		operand1 = 0;
602de3b87aSKai Wang 		operand2 = 0;
612de3b87aSKai Wang 
622de3b87aSKai Wang 		if (lbuf != NULL) {
632de3b87aSKai Wang 			lbuf->ld_s[count].lr_atom = *p;
642de3b87aSKai Wang 			lbuf->ld_s[count].lr_offset = p - ps;
652de3b87aSKai Wang 		}
662de3b87aSKai Wang 
672de3b87aSKai Wang 		switch (*p++) {
682de3b87aSKai Wang 		/* Operations with no operands. */
692de3b87aSKai Wang 		case DW_OP_deref:
702de3b87aSKai Wang 		case DW_OP_reg0:
712de3b87aSKai Wang 		case DW_OP_reg1:
722de3b87aSKai Wang 		case DW_OP_reg2:
732de3b87aSKai Wang 		case DW_OP_reg3:
742de3b87aSKai Wang 		case DW_OP_reg4:
752de3b87aSKai Wang 		case DW_OP_reg5:
762de3b87aSKai Wang 		case DW_OP_reg6:
772de3b87aSKai Wang 		case DW_OP_reg7:
782de3b87aSKai Wang 		case DW_OP_reg8:
792de3b87aSKai Wang 		case DW_OP_reg9:
802de3b87aSKai Wang 		case DW_OP_reg10:
812de3b87aSKai Wang 		case DW_OP_reg11:
822de3b87aSKai Wang 		case DW_OP_reg12:
832de3b87aSKai Wang 		case DW_OP_reg13:
842de3b87aSKai Wang 		case DW_OP_reg14:
852de3b87aSKai Wang 		case DW_OP_reg15:
862de3b87aSKai Wang 		case DW_OP_reg16:
872de3b87aSKai Wang 		case DW_OP_reg17:
882de3b87aSKai Wang 		case DW_OP_reg18:
892de3b87aSKai Wang 		case DW_OP_reg19:
902de3b87aSKai Wang 		case DW_OP_reg20:
912de3b87aSKai Wang 		case DW_OP_reg21:
922de3b87aSKai Wang 		case DW_OP_reg22:
932de3b87aSKai Wang 		case DW_OP_reg23:
942de3b87aSKai Wang 		case DW_OP_reg24:
952de3b87aSKai Wang 		case DW_OP_reg25:
962de3b87aSKai Wang 		case DW_OP_reg26:
972de3b87aSKai Wang 		case DW_OP_reg27:
982de3b87aSKai Wang 		case DW_OP_reg28:
992de3b87aSKai Wang 		case DW_OP_reg29:
1002de3b87aSKai Wang 		case DW_OP_reg30:
1012de3b87aSKai Wang 		case DW_OP_reg31:
1022de3b87aSKai Wang 
1032de3b87aSKai Wang 		case DW_OP_lit0:
1042de3b87aSKai Wang 		case DW_OP_lit1:
1052de3b87aSKai Wang 		case DW_OP_lit2:
1062de3b87aSKai Wang 		case DW_OP_lit3:
1072de3b87aSKai Wang 		case DW_OP_lit4:
1082de3b87aSKai Wang 		case DW_OP_lit5:
1092de3b87aSKai Wang 		case DW_OP_lit6:
1102de3b87aSKai Wang 		case DW_OP_lit7:
1112de3b87aSKai Wang 		case DW_OP_lit8:
1122de3b87aSKai Wang 		case DW_OP_lit9:
1132de3b87aSKai Wang 		case DW_OP_lit10:
1142de3b87aSKai Wang 		case DW_OP_lit11:
1152de3b87aSKai Wang 		case DW_OP_lit12:
1162de3b87aSKai Wang 		case DW_OP_lit13:
1172de3b87aSKai Wang 		case DW_OP_lit14:
1182de3b87aSKai Wang 		case DW_OP_lit15:
1192de3b87aSKai Wang 		case DW_OP_lit16:
1202de3b87aSKai Wang 		case DW_OP_lit17:
1212de3b87aSKai Wang 		case DW_OP_lit18:
1222de3b87aSKai Wang 		case DW_OP_lit19:
1232de3b87aSKai Wang 		case DW_OP_lit20:
1242de3b87aSKai Wang 		case DW_OP_lit21:
1252de3b87aSKai Wang 		case DW_OP_lit22:
1262de3b87aSKai Wang 		case DW_OP_lit23:
1272de3b87aSKai Wang 		case DW_OP_lit24:
1282de3b87aSKai Wang 		case DW_OP_lit25:
1292de3b87aSKai Wang 		case DW_OP_lit26:
1302de3b87aSKai Wang 		case DW_OP_lit27:
1312de3b87aSKai Wang 		case DW_OP_lit28:
1322de3b87aSKai Wang 		case DW_OP_lit29:
1332de3b87aSKai Wang 		case DW_OP_lit30:
1342de3b87aSKai Wang 		case DW_OP_lit31:
1352de3b87aSKai Wang 
1362de3b87aSKai Wang 		case DW_OP_dup:
1372de3b87aSKai Wang 		case DW_OP_drop:
1382de3b87aSKai Wang 
1392de3b87aSKai Wang 		case DW_OP_over:
1402de3b87aSKai Wang 
1412de3b87aSKai Wang 		case DW_OP_swap:
1422de3b87aSKai Wang 		case DW_OP_rot:
1432de3b87aSKai Wang 		case DW_OP_xderef:
1442de3b87aSKai Wang 
1452de3b87aSKai Wang 		case DW_OP_abs:
1462de3b87aSKai Wang 		case DW_OP_and:
1472de3b87aSKai Wang 		case DW_OP_div:
1482de3b87aSKai Wang 		case DW_OP_minus:
1492de3b87aSKai Wang 		case DW_OP_mod:
1502de3b87aSKai Wang 		case DW_OP_mul:
1512de3b87aSKai Wang 		case DW_OP_neg:
1522de3b87aSKai Wang 		case DW_OP_not:
1532de3b87aSKai Wang 		case DW_OP_or:
1542de3b87aSKai Wang 		case DW_OP_plus:
1552de3b87aSKai Wang 
1562de3b87aSKai Wang 		case DW_OP_shl:
1572de3b87aSKai Wang 		case DW_OP_shr:
1582de3b87aSKai Wang 		case DW_OP_shra:
1592de3b87aSKai Wang 		case DW_OP_xor:
1602de3b87aSKai Wang 
1612de3b87aSKai Wang 		case DW_OP_eq:
1622de3b87aSKai Wang 		case DW_OP_ge:
1632de3b87aSKai Wang 		case DW_OP_gt:
1642de3b87aSKai Wang 		case DW_OP_le:
1652de3b87aSKai Wang 		case DW_OP_lt:
1662de3b87aSKai Wang 		case DW_OP_ne:
1672de3b87aSKai Wang 
1682de3b87aSKai Wang 		case DW_OP_nop:
169*cf781b2eSEd Maste 		case DW_OP_push_object_address:
1702de3b87aSKai Wang 		case DW_OP_form_tls_address:
1712de3b87aSKai Wang 		case DW_OP_call_frame_cfa:
1722de3b87aSKai Wang 		case DW_OP_stack_value:
1732de3b87aSKai Wang 		case DW_OP_GNU_push_tls_address:
174*cf781b2eSEd Maste 		case DW_OP_GNU_uninit:
1752de3b87aSKai Wang 			break;
1762de3b87aSKai Wang 
1772de3b87aSKai Wang 		/* Operations with 1-byte operands. */
1782de3b87aSKai Wang 		case DW_OP_const1u:
1792de3b87aSKai Wang 		case DW_OP_pick:
1802de3b87aSKai Wang 		case DW_OP_deref_size:
1812de3b87aSKai Wang 		case DW_OP_xderef_size:
1822de3b87aSKai Wang 			operand1 = *p++;
1832de3b87aSKai Wang 			break;
1842de3b87aSKai Wang 
185*cf781b2eSEd Maste 		case DW_OP_const1s:
186*cf781b2eSEd Maste 			operand1 = (int8_t) *p++;
187*cf781b2eSEd Maste 			break;
188*cf781b2eSEd Maste 
1892de3b87aSKai Wang 		/* Operations with 2-byte operands. */
1902de3b87aSKai Wang 		case DW_OP_call2:
1912de3b87aSKai Wang 		case DW_OP_const2u:
1922de3b87aSKai Wang 		case DW_OP_bra:
1932de3b87aSKai Wang 		case DW_OP_skip:
1942de3b87aSKai Wang 			operand1 = dbg->decode(&p, 2);
1952de3b87aSKai Wang 			break;
1962de3b87aSKai Wang 
197*cf781b2eSEd Maste 		case DW_OP_const2s:
198*cf781b2eSEd Maste 			operand1 = (int16_t) dbg->decode(&p, 2);
199*cf781b2eSEd Maste 			break;
200*cf781b2eSEd Maste 
2012de3b87aSKai Wang 		/* Operations with 4-byte operands. */
2022de3b87aSKai Wang 		case DW_OP_call4:
2032de3b87aSKai Wang 		case DW_OP_const4u:
204*cf781b2eSEd Maste 		case DW_OP_GNU_parameter_ref:
2052de3b87aSKai Wang 			operand1 = dbg->decode(&p, 4);
2062de3b87aSKai Wang 			break;
2072de3b87aSKai Wang 
208*cf781b2eSEd Maste 		case DW_OP_const4s:
209*cf781b2eSEd Maste 			operand1 = (int32_t) dbg->decode(&p, 4);
210*cf781b2eSEd Maste 			break;
211*cf781b2eSEd Maste 
2122de3b87aSKai Wang 		/* Operations with 8-byte operands. */
2132de3b87aSKai Wang 		case DW_OP_const8u:
2142de3b87aSKai Wang 		case DW_OP_const8s:
2152de3b87aSKai Wang 			operand1 = dbg->decode(&p, 8);
2162de3b87aSKai Wang 			break;
2172de3b87aSKai Wang 
2182de3b87aSKai Wang 		/* Operations with an unsigned LEB128 operand. */
2192de3b87aSKai Wang 		case DW_OP_constu:
2202de3b87aSKai Wang 		case DW_OP_plus_uconst:
2212de3b87aSKai Wang 		case DW_OP_regx:
2222de3b87aSKai Wang 		case DW_OP_piece:
223*cf781b2eSEd Maste 		case DW_OP_GNU_deref_type:
224*cf781b2eSEd Maste 		case DW_OP_GNU_convert:
225*cf781b2eSEd Maste 		case DW_OP_GNU_reinterpret:
2262de3b87aSKai Wang 			operand1 = _dwarf_decode_uleb128(&p);
2272de3b87aSKai Wang 			break;
2282de3b87aSKai Wang 
2292de3b87aSKai Wang 		/* Operations with a signed LEB128 operand. */
2302de3b87aSKai Wang 		case DW_OP_consts:
2312de3b87aSKai Wang 		case DW_OP_breg0:
2322de3b87aSKai Wang 		case DW_OP_breg1:
2332de3b87aSKai Wang 		case DW_OP_breg2:
2342de3b87aSKai Wang 		case DW_OP_breg3:
2352de3b87aSKai Wang 		case DW_OP_breg4:
2362de3b87aSKai Wang 		case DW_OP_breg5:
2372de3b87aSKai Wang 		case DW_OP_breg6:
2382de3b87aSKai Wang 		case DW_OP_breg7:
2392de3b87aSKai Wang 		case DW_OP_breg8:
2402de3b87aSKai Wang 		case DW_OP_breg9:
2412de3b87aSKai Wang 		case DW_OP_breg10:
2422de3b87aSKai Wang 		case DW_OP_breg11:
2432de3b87aSKai Wang 		case DW_OP_breg12:
2442de3b87aSKai Wang 		case DW_OP_breg13:
2452de3b87aSKai Wang 		case DW_OP_breg14:
2462de3b87aSKai Wang 		case DW_OP_breg15:
2472de3b87aSKai Wang 		case DW_OP_breg16:
2482de3b87aSKai Wang 		case DW_OP_breg17:
2492de3b87aSKai Wang 		case DW_OP_breg18:
2502de3b87aSKai Wang 		case DW_OP_breg19:
2512de3b87aSKai Wang 		case DW_OP_breg20:
2522de3b87aSKai Wang 		case DW_OP_breg21:
2532de3b87aSKai Wang 		case DW_OP_breg22:
2542de3b87aSKai Wang 		case DW_OP_breg23:
2552de3b87aSKai Wang 		case DW_OP_breg24:
2562de3b87aSKai Wang 		case DW_OP_breg25:
2572de3b87aSKai Wang 		case DW_OP_breg26:
2582de3b87aSKai Wang 		case DW_OP_breg27:
2592de3b87aSKai Wang 		case DW_OP_breg28:
2602de3b87aSKai Wang 		case DW_OP_breg29:
2612de3b87aSKai Wang 		case DW_OP_breg30:
2622de3b87aSKai Wang 		case DW_OP_breg31:
2632de3b87aSKai Wang 		case DW_OP_fbreg:
2642de3b87aSKai Wang 			operand1 = _dwarf_decode_sleb128(&p);
2652de3b87aSKai Wang 			break;
2662de3b87aSKai Wang 
2672de3b87aSKai Wang 		/*
2682de3b87aSKai Wang 		 * Oeration with two unsigned LEB128 operands.
2692de3b87aSKai Wang 		 */
2702de3b87aSKai Wang 		case DW_OP_bit_piece:
271*cf781b2eSEd Maste 		case DW_OP_GNU_regval_type:
2722de3b87aSKai Wang 			operand1 = _dwarf_decode_uleb128(&p);
2732de3b87aSKai Wang 			operand2 = _dwarf_decode_uleb128(&p);
2742de3b87aSKai Wang 			break;
2752de3b87aSKai Wang 
2762de3b87aSKai Wang 		/*
2772de3b87aSKai Wang 		 * Operations with an unsigned LEB128 operand
2782de3b87aSKai Wang 		 * followed by a signed LEB128 operand.
2792de3b87aSKai Wang 		 */
2802de3b87aSKai Wang 		case DW_OP_bregx:
2812de3b87aSKai Wang 			operand1 = _dwarf_decode_uleb128(&p);
2822de3b87aSKai Wang 			operand2 = _dwarf_decode_sleb128(&p);
2832de3b87aSKai Wang 			break;
2842de3b87aSKai Wang 
2852de3b87aSKai Wang 		/*
2862de3b87aSKai Wang 		 * Operation with an unsigned LEB128 operand
287*cf781b2eSEd Maste 		 * representing the size of a block, followed
288*cf781b2eSEd Maste 		 * by the block content.
289*cf781b2eSEd Maste 		 *
290*cf781b2eSEd Maste 		 * Store the size of the block in the operand1
291*cf781b2eSEd Maste 		 * and a pointer to the block in the operand2.
2922de3b87aSKai Wang 		 */
2932de3b87aSKai Wang 		case DW_OP_implicit_value:
294*cf781b2eSEd Maste 		case DW_OP_GNU_entry_value:
2952de3b87aSKai Wang 			operand1 = _dwarf_decode_uleb128(&p);
2962de3b87aSKai Wang 			operand2 = (Dwarf_Unsigned) (uintptr_t) p;
2972de3b87aSKai Wang 			p += operand1;
2982de3b87aSKai Wang 			break;
2992de3b87aSKai Wang 
3002de3b87aSKai Wang 		/* Target address size operand. */
3012de3b87aSKai Wang 		case DW_OP_addr:
302*cf781b2eSEd Maste 		case DW_OP_GNU_addr_index:
303*cf781b2eSEd Maste 		case DW_OP_GNU_const_index:
3042de3b87aSKai Wang 			operand1 = dbg->decode(&p, pointer_size);
3052de3b87aSKai Wang 			break;
3062de3b87aSKai Wang 
307*cf781b2eSEd Maste 		/* Offset size operand. */
3082de3b87aSKai Wang 		case DW_OP_call_ref:
309*cf781b2eSEd Maste 			operand1 = dbg->decode(&p, offset_size);
310*cf781b2eSEd Maste 			break;
311*cf781b2eSEd Maste 
312*cf781b2eSEd Maste 		/*
313*cf781b2eSEd Maste 		 * The first byte is address byte length, followed by
314*cf781b2eSEd Maste 		 * the address value. If the length is 0, the address
315*cf781b2eSEd Maste 		 * size is the same as target pointer size.
316*cf781b2eSEd Maste 		 */
317*cf781b2eSEd Maste 		case DW_OP_GNU_encoded_addr:
318*cf781b2eSEd Maste 			s = *p++;
319*cf781b2eSEd Maste 			if (s == 0)
320*cf781b2eSEd Maste 				s = pointer_size;
321*cf781b2eSEd Maste 			operand1 = dbg->decode(&p, s);
322*cf781b2eSEd Maste 			break;
323*cf781b2eSEd Maste 
324*cf781b2eSEd Maste 		/*
325*cf781b2eSEd Maste 		 * Operand1: DIE offset (size depending on DWARF version)
326*cf781b2eSEd Maste 		 * DWARF2: pointer size
327*cf781b2eSEd Maste 		 * DWARF{3,4}: offset size
328*cf781b2eSEd Maste 		 *
329*cf781b2eSEd Maste 		 * Operand2: SLEB128
330*cf781b2eSEd Maste 		 */
331*cf781b2eSEd Maste 		case DW_OP_GNU_implicit_pointer:
332*cf781b2eSEd Maste 			if (version == 2)
333*cf781b2eSEd Maste 				operand1 = dbg->decode(&p, pointer_size);
334*cf781b2eSEd Maste 			else
335*cf781b2eSEd Maste 				operand1 = dbg->decode(&p, offset_size);
336*cf781b2eSEd Maste 			operand2 = _dwarf_decode_sleb128(&p);
337*cf781b2eSEd Maste 			break;
338*cf781b2eSEd Maste 
339*cf781b2eSEd Maste 		/*
340*cf781b2eSEd Maste 		 * Operand1: DIE offset (ULEB128)
341*cf781b2eSEd Maste 		 * Operand2: pointer to a block. The block's first byte
342*cf781b2eSEd Maste 		 * is its size.
343*cf781b2eSEd Maste 		 */
344*cf781b2eSEd Maste 		case DW_OP_GNU_const_type:
345*cf781b2eSEd Maste 			operand1 = _dwarf_decode_uleb128(&p);
346*cf781b2eSEd Maste 			operand2 = (Dwarf_Unsigned) (uintptr_t) p;
347*cf781b2eSEd Maste 			s = *p++;
348*cf781b2eSEd Maste 			p += s;
3492de3b87aSKai Wang 			break;
3502de3b87aSKai Wang 
3512de3b87aSKai Wang 		/* All other operations cause an error. */
3522de3b87aSKai Wang 		default:
3532de3b87aSKai Wang 			count = -1;
354*cf781b2eSEd Maste 			goto done;
3552de3b87aSKai Wang 		}
3562de3b87aSKai Wang 
3572de3b87aSKai Wang 		if (lbuf != NULL) {
3582de3b87aSKai Wang 			lbuf->ld_s[count].lr_number = operand1;
3592de3b87aSKai Wang 			lbuf->ld_s[count].lr_number2 = operand2;
3602de3b87aSKai Wang 		}
3612de3b87aSKai Wang 
3622de3b87aSKai Wang 		count++;
3632de3b87aSKai Wang 	}
3642de3b87aSKai Wang 
365*cf781b2eSEd Maste done:
3662de3b87aSKai Wang 	return (count);
3672de3b87aSKai Wang }
3682de3b87aSKai Wang 
3692de3b87aSKai Wang int
_dwarf_loc_expr_add_atom(Dwarf_Debug dbg,uint8_t * out,uint8_t * end,Dwarf_Small atom,Dwarf_Unsigned operand1,Dwarf_Unsigned operand2,int * length,Dwarf_Error * error)3702de3b87aSKai Wang _dwarf_loc_expr_add_atom(Dwarf_Debug dbg, uint8_t *out, uint8_t *end,
3712de3b87aSKai Wang     Dwarf_Small atom, Dwarf_Unsigned operand1, Dwarf_Unsigned operand2,
3722de3b87aSKai Wang     int *length, Dwarf_Error *error)
3732de3b87aSKai Wang {
3742de3b87aSKai Wang 	uint8_t buf[64];
3752de3b87aSKai Wang 	uint8_t *p, *pe;
3762de3b87aSKai Wang 	uint64_t offset;
3772de3b87aSKai Wang 	int len;
3782de3b87aSKai Wang 
3792de3b87aSKai Wang 	if (out != NULL && end != NULL) {
3802de3b87aSKai Wang 		p = out;
3812de3b87aSKai Wang 		pe = end;
3822de3b87aSKai Wang 	} else {
3832de3b87aSKai Wang 		p = out = buf;
3842de3b87aSKai Wang 		pe = &buf[sizeof(buf)];
3852de3b87aSKai Wang 	}
3862de3b87aSKai Wang 
3872de3b87aSKai Wang 	switch (atom) {
3882de3b87aSKai Wang 	/* Operations with no operands. */
3892de3b87aSKai Wang 	case DW_OP_deref:
3902de3b87aSKai Wang 	case DW_OP_reg0:
3912de3b87aSKai Wang 	case DW_OP_reg1:
3922de3b87aSKai Wang 	case DW_OP_reg2:
3932de3b87aSKai Wang 	case DW_OP_reg3:
3942de3b87aSKai Wang 	case DW_OP_reg4:
3952de3b87aSKai Wang 	case DW_OP_reg5:
3962de3b87aSKai Wang 	case DW_OP_reg6:
3972de3b87aSKai Wang 	case DW_OP_reg7:
3982de3b87aSKai Wang 	case DW_OP_reg8:
3992de3b87aSKai Wang 	case DW_OP_reg9:
4002de3b87aSKai Wang 	case DW_OP_reg10:
4012de3b87aSKai Wang 	case DW_OP_reg11:
4022de3b87aSKai Wang 	case DW_OP_reg12:
4032de3b87aSKai Wang 	case DW_OP_reg13:
4042de3b87aSKai Wang 	case DW_OP_reg14:
4052de3b87aSKai Wang 	case DW_OP_reg15:
4062de3b87aSKai Wang 	case DW_OP_reg16:
4072de3b87aSKai Wang 	case DW_OP_reg17:
4082de3b87aSKai Wang 	case DW_OP_reg18:
4092de3b87aSKai Wang 	case DW_OP_reg19:
4102de3b87aSKai Wang 	case DW_OP_reg20:
4112de3b87aSKai Wang 	case DW_OP_reg21:
4122de3b87aSKai Wang 	case DW_OP_reg22:
4132de3b87aSKai Wang 	case DW_OP_reg23:
4142de3b87aSKai Wang 	case DW_OP_reg24:
4152de3b87aSKai Wang 	case DW_OP_reg25:
4162de3b87aSKai Wang 	case DW_OP_reg26:
4172de3b87aSKai Wang 	case DW_OP_reg27:
4182de3b87aSKai Wang 	case DW_OP_reg28:
4192de3b87aSKai Wang 	case DW_OP_reg29:
4202de3b87aSKai Wang 	case DW_OP_reg30:
4212de3b87aSKai Wang 	case DW_OP_reg31:
4222de3b87aSKai Wang 
4232de3b87aSKai Wang 	case DW_OP_lit0:
4242de3b87aSKai Wang 	case DW_OP_lit1:
4252de3b87aSKai Wang 	case DW_OP_lit2:
4262de3b87aSKai Wang 	case DW_OP_lit3:
4272de3b87aSKai Wang 	case DW_OP_lit4:
4282de3b87aSKai Wang 	case DW_OP_lit5:
4292de3b87aSKai Wang 	case DW_OP_lit6:
4302de3b87aSKai Wang 	case DW_OP_lit7:
4312de3b87aSKai Wang 	case DW_OP_lit8:
4322de3b87aSKai Wang 	case DW_OP_lit9:
4332de3b87aSKai Wang 	case DW_OP_lit10:
4342de3b87aSKai Wang 	case DW_OP_lit11:
4352de3b87aSKai Wang 	case DW_OP_lit12:
4362de3b87aSKai Wang 	case DW_OP_lit13:
4372de3b87aSKai Wang 	case DW_OP_lit14:
4382de3b87aSKai Wang 	case DW_OP_lit15:
4392de3b87aSKai Wang 	case DW_OP_lit16:
4402de3b87aSKai Wang 	case DW_OP_lit17:
4412de3b87aSKai Wang 	case DW_OP_lit18:
4422de3b87aSKai Wang 	case DW_OP_lit19:
4432de3b87aSKai Wang 	case DW_OP_lit20:
4442de3b87aSKai Wang 	case DW_OP_lit21:
4452de3b87aSKai Wang 	case DW_OP_lit22:
4462de3b87aSKai Wang 	case DW_OP_lit23:
4472de3b87aSKai Wang 	case DW_OP_lit24:
4482de3b87aSKai Wang 	case DW_OP_lit25:
4492de3b87aSKai Wang 	case DW_OP_lit26:
4502de3b87aSKai Wang 	case DW_OP_lit27:
4512de3b87aSKai Wang 	case DW_OP_lit28:
4522de3b87aSKai Wang 	case DW_OP_lit29:
4532de3b87aSKai Wang 	case DW_OP_lit30:
4542de3b87aSKai Wang 	case DW_OP_lit31:
4552de3b87aSKai Wang 
4562de3b87aSKai Wang 	case DW_OP_dup:
4572de3b87aSKai Wang 	case DW_OP_drop:
4582de3b87aSKai Wang 
4592de3b87aSKai Wang 	case DW_OP_over:
4602de3b87aSKai Wang 
4612de3b87aSKai Wang 	case DW_OP_swap:
4622de3b87aSKai Wang 	case DW_OP_rot:
4632de3b87aSKai Wang 	case DW_OP_xderef:
4642de3b87aSKai Wang 
4652de3b87aSKai Wang 	case DW_OP_abs:
4662de3b87aSKai Wang 	case DW_OP_and:
4672de3b87aSKai Wang 	case DW_OP_div:
4682de3b87aSKai Wang 	case DW_OP_minus:
4692de3b87aSKai Wang 	case DW_OP_mod:
4702de3b87aSKai Wang 	case DW_OP_mul:
4712de3b87aSKai Wang 	case DW_OP_neg:
4722de3b87aSKai Wang 	case DW_OP_not:
4732de3b87aSKai Wang 	case DW_OP_or:
4742de3b87aSKai Wang 	case DW_OP_plus:
4752de3b87aSKai Wang 
4762de3b87aSKai Wang 	case DW_OP_shl:
4772de3b87aSKai Wang 	case DW_OP_shr:
4782de3b87aSKai Wang 	case DW_OP_shra:
4792de3b87aSKai Wang 	case DW_OP_xor:
4802de3b87aSKai Wang 
4812de3b87aSKai Wang 	case DW_OP_eq:
4822de3b87aSKai Wang 	case DW_OP_ge:
4832de3b87aSKai Wang 	case DW_OP_gt:
4842de3b87aSKai Wang 	case DW_OP_le:
4852de3b87aSKai Wang 	case DW_OP_lt:
4862de3b87aSKai Wang 	case DW_OP_ne:
4872de3b87aSKai Wang 
4882de3b87aSKai Wang 	case DW_OP_nop:
4892de3b87aSKai Wang 	case DW_OP_GNU_push_tls_address:
4902de3b87aSKai Wang 		*p++ = atom;
4912de3b87aSKai Wang 		break;
4922de3b87aSKai Wang 
4932de3b87aSKai Wang 	/* Operations with 1-byte operands. */
4942de3b87aSKai Wang 	case DW_OP_const1u:
4952de3b87aSKai Wang 	case DW_OP_const1s:
4962de3b87aSKai Wang 	case DW_OP_pick:
4972de3b87aSKai Wang 	case DW_OP_deref_size:
4982de3b87aSKai Wang 	case DW_OP_xderef_size:
4992de3b87aSKai Wang 		*p++ = atom;
5002de3b87aSKai Wang 		*p++ = (uint8_t) operand1;
5012de3b87aSKai Wang 		break;
5022de3b87aSKai Wang 
5032de3b87aSKai Wang 	/* Operations with 2-byte operands. */
5042de3b87aSKai Wang 	case DW_OP_const2u:
5052de3b87aSKai Wang 	case DW_OP_const2s:
5062de3b87aSKai Wang 	case DW_OP_bra:
5072de3b87aSKai Wang 	case DW_OP_skip:
5082de3b87aSKai Wang 		*p++ = atom;
5092de3b87aSKai Wang 		offset = 0;
5102de3b87aSKai Wang 		dbg->write(p, &offset, operand1, 2);
5112de3b87aSKai Wang 		p += 2;
5122de3b87aSKai Wang 		break;
5132de3b87aSKai Wang 
5142de3b87aSKai Wang 	/* Operations with 4-byte operands. */
5152de3b87aSKai Wang 	case DW_OP_const4u:
5162de3b87aSKai Wang 	case DW_OP_const4s:
5172de3b87aSKai Wang 		*p++ = atom;
5182de3b87aSKai Wang 		offset = 0;
5192de3b87aSKai Wang 		dbg->write(p, &offset, operand1, 4);
5202de3b87aSKai Wang 		p += 4;
5212de3b87aSKai Wang 		break;
5222de3b87aSKai Wang 
5232de3b87aSKai Wang 	/* Operations with 8-byte operands. */
5242de3b87aSKai Wang 	case DW_OP_const8u:
5252de3b87aSKai Wang 	case DW_OP_const8s:
5262de3b87aSKai Wang 		*p++ = atom;
5272de3b87aSKai Wang 		offset = 0;
5282de3b87aSKai Wang 		dbg->write(p, &offset, operand1, 8);
5292de3b87aSKai Wang 		p += 8;
5302de3b87aSKai Wang 		break;
5312de3b87aSKai Wang 
5322de3b87aSKai Wang 	/* Operations with an unsigned LEB128 operand. */
5332de3b87aSKai Wang 	case DW_OP_constu:
5342de3b87aSKai Wang 	case DW_OP_plus_uconst:
5352de3b87aSKai Wang 	case DW_OP_regx:
5362de3b87aSKai Wang 	case DW_OP_piece:
5372de3b87aSKai Wang 		*p++ = atom;
5382de3b87aSKai Wang 		len = _dwarf_write_uleb128(p, pe, operand1);
5392de3b87aSKai Wang 		assert(len > 0);
5402de3b87aSKai Wang 		p += len;
5412de3b87aSKai Wang 		break;
5422de3b87aSKai Wang 
5432de3b87aSKai Wang 	/* Operations with a signed LEB128 operand. */
5442de3b87aSKai Wang 	case DW_OP_consts:
5452de3b87aSKai Wang 	case DW_OP_breg0:
5462de3b87aSKai Wang 	case DW_OP_breg1:
5472de3b87aSKai Wang 	case DW_OP_breg2:
5482de3b87aSKai Wang 	case DW_OP_breg3:
5492de3b87aSKai Wang 	case DW_OP_breg4:
5502de3b87aSKai Wang 	case DW_OP_breg5:
5512de3b87aSKai Wang 	case DW_OP_breg6:
5522de3b87aSKai Wang 	case DW_OP_breg7:
5532de3b87aSKai Wang 	case DW_OP_breg8:
5542de3b87aSKai Wang 	case DW_OP_breg9:
5552de3b87aSKai Wang 	case DW_OP_breg10:
5562de3b87aSKai Wang 	case DW_OP_breg11:
5572de3b87aSKai Wang 	case DW_OP_breg12:
5582de3b87aSKai Wang 	case DW_OP_breg13:
5592de3b87aSKai Wang 	case DW_OP_breg14:
5602de3b87aSKai Wang 	case DW_OP_breg15:
5612de3b87aSKai Wang 	case DW_OP_breg16:
5622de3b87aSKai Wang 	case DW_OP_breg17:
5632de3b87aSKai Wang 	case DW_OP_breg18:
5642de3b87aSKai Wang 	case DW_OP_breg19:
5652de3b87aSKai Wang 	case DW_OP_breg20:
5662de3b87aSKai Wang 	case DW_OP_breg21:
5672de3b87aSKai Wang 	case DW_OP_breg22:
5682de3b87aSKai Wang 	case DW_OP_breg23:
5692de3b87aSKai Wang 	case DW_OP_breg24:
5702de3b87aSKai Wang 	case DW_OP_breg25:
5712de3b87aSKai Wang 	case DW_OP_breg26:
5722de3b87aSKai Wang 	case DW_OP_breg27:
5732de3b87aSKai Wang 	case DW_OP_breg28:
5742de3b87aSKai Wang 	case DW_OP_breg29:
5752de3b87aSKai Wang 	case DW_OP_breg30:
5762de3b87aSKai Wang 	case DW_OP_breg31:
5772de3b87aSKai Wang 	case DW_OP_fbreg:
5782de3b87aSKai Wang 		*p++ = atom;
5792de3b87aSKai Wang 		len = _dwarf_write_sleb128(p, pe, operand1);
5802de3b87aSKai Wang 		assert(len > 0);
5812de3b87aSKai Wang 		p += len;
5822de3b87aSKai Wang 		break;
5832de3b87aSKai Wang 
5842de3b87aSKai Wang 	/*
5852de3b87aSKai Wang 	 * Operations with an unsigned LEB128 operand
5862de3b87aSKai Wang 	 * followed by a signed LEB128 operand.
5872de3b87aSKai Wang 	 */
5882de3b87aSKai Wang 	case DW_OP_bregx:
5892de3b87aSKai Wang 		*p++ = atom;
5902de3b87aSKai Wang 		len = _dwarf_write_uleb128(p, pe, operand1);
5912de3b87aSKai Wang 		assert(len > 0);
5922de3b87aSKai Wang 		p += len;
5932de3b87aSKai Wang 		len = _dwarf_write_sleb128(p, pe, operand2);
5942de3b87aSKai Wang 		assert(len > 0);
5952de3b87aSKai Wang 		p += len;
5962de3b87aSKai Wang 		break;
5972de3b87aSKai Wang 
5982de3b87aSKai Wang 	/* Target address size operand. */
5992de3b87aSKai Wang 	case DW_OP_addr:
6002de3b87aSKai Wang 		*p++ = atom;
6012de3b87aSKai Wang 		offset = 0;
6022de3b87aSKai Wang 		dbg->write(p, &offset, operand1, dbg->dbg_pointer_size);
6032de3b87aSKai Wang 		p += dbg->dbg_pointer_size;
6042de3b87aSKai Wang 		break;
6052de3b87aSKai Wang 
6062de3b87aSKai Wang 	/* All other operations cause an error. */
6072de3b87aSKai Wang 	default:
6082de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_LOC_EXPR_BAD);
6092de3b87aSKai Wang 		return (DW_DLE_LOC_EXPR_BAD);
6102de3b87aSKai Wang 	}
6112de3b87aSKai Wang 
6122de3b87aSKai Wang 	if (length)
6132de3b87aSKai Wang 		*length = p - out;
6142de3b87aSKai Wang 
6152de3b87aSKai Wang 	return (DW_DLE_NONE);
6162de3b87aSKai Wang }
6172de3b87aSKai Wang 
6182de3b87aSKai Wang int
_dwarf_loc_fill_locdesc(Dwarf_Debug dbg,Dwarf_Locdesc * llbuf,uint8_t * in,uint64_t in_len,uint8_t pointer_size,uint8_t offset_size,uint8_t version,Dwarf_Error * error)6192de3b87aSKai Wang _dwarf_loc_fill_locdesc(Dwarf_Debug dbg, Dwarf_Locdesc *llbuf, uint8_t *in,
620*cf781b2eSEd Maste     uint64_t in_len, uint8_t pointer_size, uint8_t offset_size,
621*cf781b2eSEd Maste     uint8_t version, Dwarf_Error *error)
6222de3b87aSKai Wang {
6232de3b87aSKai Wang 	int num;
6242de3b87aSKai Wang 
6252de3b87aSKai Wang 	assert(llbuf != NULL);
6262de3b87aSKai Wang 	assert(in != NULL);
6272de3b87aSKai Wang 	assert(in_len > 0);
6282de3b87aSKai Wang 
6292de3b87aSKai Wang 	/* Compute the number of locations. */
630*cf781b2eSEd Maste 	if ((num = _dwarf_loc_fill_loc(dbg, NULL, pointer_size, offset_size,
631*cf781b2eSEd Maste 	    version, in, in_len)) < 0) {
6322de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_LOC_EXPR_BAD);
6332de3b87aSKai Wang 		return (DW_DLE_LOC_EXPR_BAD);
6342de3b87aSKai Wang 	}
6352de3b87aSKai Wang 
6362de3b87aSKai Wang 	llbuf->ld_cents = num;
6372de3b87aSKai Wang 	if (num <= 0)
6382de3b87aSKai Wang 		return (DW_DLE_NONE);
6392de3b87aSKai Wang 
6402de3b87aSKai Wang 	if ((llbuf->ld_s = calloc(num, sizeof(Dwarf_Loc))) == NULL) {
6412de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
6422de3b87aSKai Wang 		return (DW_DLE_MEMORY);
6432de3b87aSKai Wang 	}
6442de3b87aSKai Wang 
645*cf781b2eSEd Maste 	(void) _dwarf_loc_fill_loc(dbg, llbuf, pointer_size, offset_size,
646*cf781b2eSEd Maste 	    version, in, in_len);
6472de3b87aSKai Wang 
6482de3b87aSKai Wang 	return (DW_DLE_NONE);
6492de3b87aSKai Wang }
6502de3b87aSKai Wang 
6512de3b87aSKai Wang int
_dwarf_loc_fill_locexpr(Dwarf_Debug dbg,Dwarf_Locdesc ** ret_llbuf,uint8_t * in,uint64_t in_len,uint8_t pointer_size,uint8_t offset_size,uint8_t version,Dwarf_Error * error)6522de3b87aSKai Wang _dwarf_loc_fill_locexpr(Dwarf_Debug dbg, Dwarf_Locdesc **ret_llbuf, uint8_t *in,
653*cf781b2eSEd Maste     uint64_t in_len, uint8_t pointer_size, uint8_t offset_size,
654*cf781b2eSEd Maste     uint8_t version, Dwarf_Error *error)
6552de3b87aSKai Wang {
6562de3b87aSKai Wang 	Dwarf_Locdesc *llbuf;
6572de3b87aSKai Wang 	int ret;
6582de3b87aSKai Wang 
6592de3b87aSKai Wang 	if ((llbuf = malloc(sizeof(Dwarf_Locdesc))) == NULL) {
6602de3b87aSKai Wang 		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
6612de3b87aSKai Wang 		return (DW_DLE_MEMORY);
6622de3b87aSKai Wang 	}
6632de3b87aSKai Wang 	llbuf->ld_lopc = 0;
6642de3b87aSKai Wang 	llbuf->ld_hipc = ~0ULL;
6652de3b87aSKai Wang 	llbuf->ld_s = NULL;
6662de3b87aSKai Wang 
6672de3b87aSKai Wang 	ret = _dwarf_loc_fill_locdesc(dbg, llbuf, in, in_len, pointer_size,
668*cf781b2eSEd Maste 	    offset_size, version, error);
6692de3b87aSKai Wang 	if (ret != DW_DLE_NONE) {
6702de3b87aSKai Wang 		free(llbuf);
6712de3b87aSKai Wang 		return (ret);
6722de3b87aSKai Wang 	}
6732de3b87aSKai Wang 
6742de3b87aSKai Wang 	*ret_llbuf = llbuf;
6752de3b87aSKai Wang 
6762de3b87aSKai Wang 	return (ret);
6772de3b87aSKai Wang }
6782de3b87aSKai Wang 
6792de3b87aSKai Wang int
_dwarf_loc_add(Dwarf_Die die,Dwarf_Attribute at,Dwarf_Error * error)6802de3b87aSKai Wang _dwarf_loc_add(Dwarf_Die die, Dwarf_Attribute at, Dwarf_Error *error)
6812de3b87aSKai Wang {
6822de3b87aSKai Wang 	Dwarf_Debug dbg;
6832de3b87aSKai Wang 	Dwarf_CU cu;
6842de3b87aSKai Wang 	int ret;
6852de3b87aSKai Wang 
6862de3b87aSKai Wang 	assert(at->at_ld == NULL);
6872de3b87aSKai Wang 	assert(at->u[1].u8p != NULL);
6882de3b87aSKai Wang 	assert(at->u[0].u64 > 0);
6892de3b87aSKai Wang 
6902de3b87aSKai Wang 	cu = die->die_cu;
6912de3b87aSKai Wang 	assert(cu != NULL);
6922de3b87aSKai Wang 
6932de3b87aSKai Wang 	dbg = cu->cu_dbg;
6942de3b87aSKai Wang 	assert(dbg != NULL);
6952de3b87aSKai Wang 
6962de3b87aSKai Wang 	ret = _dwarf_loc_fill_locexpr(dbg, &at->at_ld, at->u[1].u8p,
697*cf781b2eSEd Maste 	    at->u[0].u64, cu->cu_pointer_size, cu->cu_length_size == 4 ? 4 : 8,
698*cf781b2eSEd Maste 	    cu->cu_version, error);
6992de3b87aSKai Wang 
7002de3b87aSKai Wang 	return (ret);
7012de3b87aSKai Wang }
702