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