static int _dwarf_lineno_add_file(Dwarf_LineInfo li, uint8_t **p, const char *compdir, Dwarf_Error *error, Dwarf_Debug dbg) { char *fname; //const char *dirname; uint8_t *src; int slen; src = *p; /* if ((lf = malloc(sizeof(struct _Dwarf_LineFile))) == NULL) { DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); return (DW_DLE_MEMORY); } */ //lf->lf_fullpath = NULL; fname = (char *) src; src += strlen(fname) + 1; _dwarf_decode_uleb128(&src); /* Make full pathname if need. if (*lf->lf_fname != '/') { dirname = compdir; if (lf->lf_dirndx > 0) dirname = li->li_incdirs[lf->lf_dirndx - 1]; if (dirname != NULL) { slen = strlen(dirname) + strlen(lf->lf_fname) + 2; if ((lf->lf_fullpath = malloc(slen)) == NULL) { free(lf); DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); return (DW_DLE_MEMORY); } snprintf(lf->lf_fullpath, slen, "%s/%s", dirname, lf->lf_fname); } } */ _dwarf_decode_uleb128(&src); _dwarf_decode_uleb128(&src); //STAILQ_INSERT_TAIL(&li->li_lflist, lf, lf_next); //li->li_lflen++; *p = src; return (DW_DLE_NONE); }
/* * Given an array of bytes of length 'len' representing a * DWARF expression, compute the number of operations based * on there being one byte describing the operation and * zero or more bytes of operands as defined in the standard * for each operation type. Also, if lbuf is non-null, store * the opcode and oprand in it. */ static int _dwarf_loc_fill_loc(Dwarf_Debug dbg, Dwarf_Locdesc *lbuf, uint8_t pointer_size, uint8_t *p, int len) { int count; uint64_t operand1; uint64_t operand2; uint8_t *ps, *pe; count = 0; ps = p; pe = p + len; /* * Process each byte. If an error occurs, then the * count will be set to -1. */ while (p < pe) { operand1 = 0; operand2 = 0; if (lbuf != NULL) { lbuf->ld_s[count].lr_atom = *p; lbuf->ld_s[count].lr_offset = p - ps; } switch (*p++) { /* Operations with no operands. */ case DW_OP_deref: case DW_OP_reg0: case DW_OP_reg1: case DW_OP_reg2: case DW_OP_reg3: case DW_OP_reg4: case DW_OP_reg5: case DW_OP_reg6: case DW_OP_reg7: case DW_OP_reg8: case DW_OP_reg9: case DW_OP_reg10: case DW_OP_reg11: case DW_OP_reg12: case DW_OP_reg13: case DW_OP_reg14: case DW_OP_reg15: case DW_OP_reg16: case DW_OP_reg17: case DW_OP_reg18: case DW_OP_reg19: case DW_OP_reg20: case DW_OP_reg21: case DW_OP_reg22: case DW_OP_reg23: case DW_OP_reg24: case DW_OP_reg25: case DW_OP_reg26: case DW_OP_reg27: case DW_OP_reg28: case DW_OP_reg29: case DW_OP_reg30: case DW_OP_reg31: case DW_OP_lit0: case DW_OP_lit1: case DW_OP_lit2: case DW_OP_lit3: case DW_OP_lit4: case DW_OP_lit5: case DW_OP_lit6: case DW_OP_lit7: case DW_OP_lit8: case DW_OP_lit9: case DW_OP_lit10: case DW_OP_lit11: case DW_OP_lit12: case DW_OP_lit13: case DW_OP_lit14: case DW_OP_lit15: case DW_OP_lit16: case DW_OP_lit17: case DW_OP_lit18: case DW_OP_lit19: case DW_OP_lit20: case DW_OP_lit21: case DW_OP_lit22: case DW_OP_lit23: case DW_OP_lit24: case DW_OP_lit25: case DW_OP_lit26: case DW_OP_lit27: case DW_OP_lit28: case DW_OP_lit29: case DW_OP_lit30: case DW_OP_lit31: case DW_OP_dup: case DW_OP_drop: case DW_OP_over: case DW_OP_swap: case DW_OP_rot: case DW_OP_xderef: case DW_OP_abs: case DW_OP_and: case DW_OP_div: case DW_OP_minus: case DW_OP_mod: case DW_OP_mul: case DW_OP_neg: case DW_OP_not: case DW_OP_or: case DW_OP_plus: case DW_OP_shl: case DW_OP_shr: case DW_OP_shra: case DW_OP_xor: case DW_OP_eq: case DW_OP_ge: case DW_OP_gt: case DW_OP_le: case DW_OP_lt: case DW_OP_ne: case DW_OP_nop: case DW_OP_form_tls_address: case DW_OP_call_frame_cfa: case DW_OP_stack_value: case DW_OP_GNU_push_tls_address: break; /* Operations with 1-byte operands. */ case DW_OP_const1u: case DW_OP_const1s: case DW_OP_pick: case DW_OP_deref_size: case DW_OP_xderef_size: operand1 = *p++; break; /* Operations with 2-byte operands. */ case DW_OP_call2: case DW_OP_const2u: case DW_OP_const2s: case DW_OP_bra: case DW_OP_skip: operand1 = dbg->decode(&p, 2); break; /* Operations with 4-byte operands. */ case DW_OP_call4: case DW_OP_const4u: case DW_OP_const4s: operand1 = dbg->decode(&p, 4); break; /* Operations with 8-byte operands. */ case DW_OP_const8u: case DW_OP_const8s: operand1 = dbg->decode(&p, 8); break; /* Operations with an unsigned LEB128 operand. */ case DW_OP_constu: case DW_OP_plus_uconst: case DW_OP_regx: case DW_OP_piece: operand1 = _dwarf_decode_uleb128(&p); break; /* Operations with a signed LEB128 operand. */ case DW_OP_consts: case DW_OP_breg0: case DW_OP_breg1: case DW_OP_breg2: case DW_OP_breg3: case DW_OP_breg4: case DW_OP_breg5: case DW_OP_breg6: case DW_OP_breg7: case DW_OP_breg8: case DW_OP_breg9: case DW_OP_breg10: case DW_OP_breg11: case DW_OP_breg12: case DW_OP_breg13: case DW_OP_breg14: case DW_OP_breg15: case DW_OP_breg16: case DW_OP_breg17: case DW_OP_breg18: case DW_OP_breg19: case DW_OP_breg20: case DW_OP_breg21: case DW_OP_breg22: case DW_OP_breg23: case DW_OP_breg24: case DW_OP_breg25: case DW_OP_breg26: case DW_OP_breg27: case DW_OP_breg28: case DW_OP_breg29: case DW_OP_breg30: case DW_OP_breg31: case DW_OP_fbreg: operand1 = _dwarf_decode_sleb128(&p); break; /* * Oeration with two unsigned LEB128 operands. */ case DW_OP_bit_piece: operand1 = _dwarf_decode_uleb128(&p); operand2 = _dwarf_decode_uleb128(&p); break; /* * Operations with an unsigned LEB128 operand * followed by a signed LEB128 operand. */ case DW_OP_bregx: operand1 = _dwarf_decode_uleb128(&p); operand2 = _dwarf_decode_sleb128(&p); break; /* * Operation with an unsigned LEB128 operand * followed by a block. Store a pointer to the * block in the operand2. */ case DW_OP_implicit_value: operand1 = _dwarf_decode_uleb128(&p); operand2 = (Dwarf_Unsigned) (uintptr_t) p; p += operand1; break; /* Target address size operand. */ case DW_OP_addr: operand1 = dbg->decode(&p, pointer_size); break; /* * XXX Opcode DW_OP_call_ref has an operand with size * "dwarf_size". Here we use dbg->dbg_offset_size * as "dwarf_size" to be compatible with SGI libdwarf. * However note that dbg->dbg_offset_size is just * a "guess" value so the parsing result of * DW_OP_call_ref might not be correct at all. XXX */ case DW_OP_call_ref: operand1 = dbg->decode(&p, dbg->dbg_offset_size); break; /* All other operations cause an error. */ default: count = -1; break; } if (lbuf != NULL) { lbuf->ld_s[count].lr_number = operand1; lbuf->ld_s[count].lr_number2 = operand2; } count++; } return (count); }
static int _dwarf_lineno_run_program(Dwarf_CU *cu, Dwarf_LineInfo li, uint8_t *p, uint8_t *pe, Dwarf_Addr pc, Dwarf_Error *error) { Dwarf_Line ln, tln; uint64_t address, file, line, column, isa, opsize; int is_stmt, basic_block, end_sequence; int prologue_end, epilogue_begin; int ret; ln = &li->li_line; #define RESET_REGISTERS \ do { \ address = 0; \ file = 1; \ line = 1; \ column = 0; \ is_stmt = li->li_defstmt; \ basic_block = 0; \ end_sequence = 0; \ prologue_end = 0; \ epilogue_begin = 0; \ } while(0) #define APPEND_ROW \ do { \ if (pc < address) { \ return DW_DLE_NONE; \ } \ ln->ln_addr = address; \ ln->ln_symndx = 0; \ ln->ln_fileno = file; \ ln->ln_lineno = line; \ ln->ln_column = column; \ ln->ln_bblock = basic_block; \ ln->ln_stmt = is_stmt; \ ln->ln_endseq = end_sequence; \ li->li_lnlen++; \ } while(0) #define LINE(x) (li->li_lbase + (((x) - li->li_opbase) % li->li_lrange)) #define ADDRESS(x) ((((x) - li->li_opbase) / li->li_lrange) * li->li_minlen) /* * ln->ln_li = li; \ * Set registers to their default values. */ RESET_REGISTERS; /* * Start line number program. */ while (p < pe) { if (*p == 0) { /* * Extended Opcodes. */ p++; opsize = _dwarf_decode_uleb128(&p); switch (*p) { case DW_LNE_end_sequence: p++; end_sequence = 1; RESET_REGISTERS; break; case DW_LNE_set_address: p++; address = dbg->decode(&p, cu->addr_size); break; case DW_LNE_define_file: p++; ret = _dwarf_lineno_add_file(li, &p, NULL, error, dbg); if (ret != DW_DLE_NONE) goto prog_fail; break; default: /* Unrecognized extened opcodes. */ p += opsize; } } else if (*p > 0 && *p < li->li_opbase) { /* * Standard Opcodes. */ switch (*p++) { case DW_LNS_copy: APPEND_ROW; basic_block = 0; prologue_end = 0; epilogue_begin = 0; break; case DW_LNS_advance_pc: address += _dwarf_decode_uleb128(&p) * li->li_minlen; break; case DW_LNS_advance_line: line += _dwarf_decode_sleb128(&p); break; case DW_LNS_set_file: file = _dwarf_decode_uleb128(&p); break; case DW_LNS_set_column: column = _dwarf_decode_uleb128(&p); break; case DW_LNS_negate_stmt: is_stmt = !is_stmt; break; case DW_LNS_set_basic_block: basic_block = 1; break; case DW_LNS_const_add_pc: address += ADDRESS(255); break; case DW_LNS_fixed_advance_pc: address += dbg->decode(&p, 2); break; case DW_LNS_set_prologue_end: prologue_end = 1; break; case DW_LNS_set_epilogue_begin: epilogue_begin = 1; break; case DW_LNS_set_isa: isa = _dwarf_decode_uleb128(&p); break; default: /* Unrecognized extened opcodes. What to do? */ break; } } else { /* * Special Opcodes. */ line += LINE(*p); address += ADDRESS(*p); APPEND_ROW; basic_block = 0; prologue_end = 0; epilogue_begin = 0; p++; } } return (DW_DLE_NONE); prog_fail: return (ret); #undef RESET_REGISTERS #undef APPEND_ROW #undef LINE #undef ADDRESS }
/* * Given an array of bytes of length 'len' representing a * DWARF expression, compute the number of operations based * on there being one byte describing the operation and * zero or more bytes of operands as defined in the standard * for each operation type. Also, if lbuf is non-null, store * the opcode and oprand in it. */ 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) { int count; uint64_t operand1; uint64_t operand2; uint8_t *ps, *pe, s; count = 0; ps = p; pe = p + len; /* * Process each byte. If an error occurs, then the * count will be set to -1. */ while (p < pe) { operand1 = 0; operand2 = 0; if (lbuf != NULL) { lbuf->ld_s[count].lr_atom = *p; lbuf->ld_s[count].lr_offset = p - ps; } switch (*p++) { /* Operations with no operands. */ case DW_OP_deref: case DW_OP_reg0: case DW_OP_reg1: case DW_OP_reg2: case DW_OP_reg3: case DW_OP_reg4: case DW_OP_reg5: case DW_OP_reg6: case DW_OP_reg7: case DW_OP_reg8: case DW_OP_reg9: case DW_OP_reg10: case DW_OP_reg11: case DW_OP_reg12: case DW_OP_reg13: case DW_OP_reg14: case DW_OP_reg15: case DW_OP_reg16: case DW_OP_reg17: case DW_OP_reg18: case DW_OP_reg19: case DW_OP_reg20: case DW_OP_reg21: case DW_OP_reg22: case DW_OP_reg23: case DW_OP_reg24: case DW_OP_reg25: case DW_OP_reg26: case DW_OP_reg27: case DW_OP_reg28: case DW_OP_reg29: case DW_OP_reg30: case DW_OP_reg31: case DW_OP_lit0: case DW_OP_lit1: case DW_OP_lit2: case DW_OP_lit3: case DW_OP_lit4: case DW_OP_lit5: case DW_OP_lit6: case DW_OP_lit7: case DW_OP_lit8: case DW_OP_lit9: case DW_OP_lit10: case DW_OP_lit11: case DW_OP_lit12: case DW_OP_lit13: case DW_OP_lit14: case DW_OP_lit15: case DW_OP_lit16: case DW_OP_lit17: case DW_OP_lit18: case DW_OP_lit19: case DW_OP_lit20: case DW_OP_lit21: case DW_OP_lit22: case DW_OP_lit23: case DW_OP_lit24: case DW_OP_lit25: case DW_OP_lit26: case DW_OP_lit27: case DW_OP_lit28: case DW_OP_lit29: case DW_OP_lit30: case DW_OP_lit31: case DW_OP_dup: case DW_OP_drop: case DW_OP_over: case DW_OP_swap: case DW_OP_rot: case DW_OP_xderef: case DW_OP_abs: case DW_OP_and: case DW_OP_div: case DW_OP_minus: case DW_OP_mod: case DW_OP_mul: case DW_OP_neg: case DW_OP_not: case DW_OP_or: case DW_OP_plus: case DW_OP_shl: case DW_OP_shr: case DW_OP_shra: case DW_OP_xor: case DW_OP_eq: case DW_OP_ge: case DW_OP_gt: case DW_OP_le: case DW_OP_lt: case DW_OP_ne: case DW_OP_nop: case DW_OP_push_object_address: case DW_OP_form_tls_address: case DW_OP_call_frame_cfa: case DW_OP_stack_value: case DW_OP_GNU_push_tls_address: case DW_OP_GNU_uninit: break; /* Operations with 1-byte operands. */ case DW_OP_const1u: case DW_OP_pick: case DW_OP_deref_size: case DW_OP_xderef_size: operand1 = *p++; break; case DW_OP_const1s: operand1 = (int8_t) *p++; break; /* Operations with 2-byte operands. */ case DW_OP_call2: case DW_OP_const2u: case DW_OP_bra: case DW_OP_skip: operand1 = dbg->decode(&p, 2); break; case DW_OP_const2s: operand1 = (int16_t) dbg->decode(&p, 2); break; /* Operations with 4-byte operands. */ case DW_OP_call4: case DW_OP_const4u: case DW_OP_GNU_parameter_ref: operand1 = dbg->decode(&p, 4); break; case DW_OP_const4s: operand1 = (int32_t) dbg->decode(&p, 4); break; /* Operations with 8-byte operands. */ case DW_OP_const8u: case DW_OP_const8s: operand1 = dbg->decode(&p, 8); break; /* Operations with an unsigned LEB128 operand. */ case DW_OP_constu: case DW_OP_plus_uconst: case DW_OP_regx: case DW_OP_piece: case DW_OP_GNU_deref_type: case DW_OP_GNU_convert: case DW_OP_GNU_reinterpret: operand1 = _dwarf_decode_uleb128(&p); break; /* Operations with a signed LEB128 operand. */ case DW_OP_consts: case DW_OP_breg0: case DW_OP_breg1: case DW_OP_breg2: case DW_OP_breg3: case DW_OP_breg4: case DW_OP_breg5: case DW_OP_breg6: case DW_OP_breg7: case DW_OP_breg8: case DW_OP_breg9: case DW_OP_breg10: case DW_OP_breg11: case DW_OP_breg12: case DW_OP_breg13: case DW_OP_breg14: case DW_OP_breg15: case DW_OP_breg16: case DW_OP_breg17: case DW_OP_breg18: case DW_OP_breg19: case DW_OP_breg20: case DW_OP_breg21: case DW_OP_breg22: case DW_OP_breg23: case DW_OP_breg24: case DW_OP_breg25: case DW_OP_breg26: case DW_OP_breg27: case DW_OP_breg28: case DW_OP_breg29: case DW_OP_breg30: case DW_OP_breg31: case DW_OP_fbreg: operand1 = _dwarf_decode_sleb128(&p); break; /* * Oeration with two unsigned LEB128 operands. */ case DW_OP_bit_piece: case DW_OP_GNU_regval_type: operand1 = _dwarf_decode_uleb128(&p); operand2 = _dwarf_decode_uleb128(&p); break; /* * Operations with an unsigned LEB128 operand * followed by a signed LEB128 operand. */ case DW_OP_bregx: operand1 = _dwarf_decode_uleb128(&p); operand2 = _dwarf_decode_sleb128(&p); break; /* * Operation with an unsigned LEB128 operand * representing the size of a block, followed * by the block content. * * Store the size of the block in the operand1 * and a pointer to the block in the operand2. */ case DW_OP_implicit_value: case DW_OP_GNU_entry_value: operand1 = _dwarf_decode_uleb128(&p); operand2 = (Dwarf_Unsigned) (uintptr_t) p; p += operand1; break; /* Target address size operand. */ case DW_OP_addr: case DW_OP_GNU_addr_index: case DW_OP_GNU_const_index: operand1 = dbg->decode(&p, pointer_size); break; /* Offset size operand. */ case DW_OP_call_ref: operand1 = dbg->decode(&p, offset_size); break; /* * The first byte is address byte length, followed by * the address value. If the length is 0, the address * size is the same as target pointer size. */ case DW_OP_GNU_encoded_addr: s = *p++; if (s == 0) s = pointer_size; operand1 = dbg->decode(&p, s); break; /* * Operand1: DIE offset (size depending on DWARF version) * DWARF2: pointer size * DWARF{3,4}: offset size * * Operand2: SLEB128 */ case DW_OP_GNU_implicit_pointer: if (version == 2) operand1 = dbg->decode(&p, pointer_size); else operand1 = dbg->decode(&p, offset_size); operand2 = _dwarf_decode_sleb128(&p); break; /* * Operand1: DIE offset (ULEB128) * Operand2: pointer to a block. The block's first byte * is its size. */ case DW_OP_GNU_const_type: operand1 = _dwarf_decode_uleb128(&p); operand2 = (Dwarf_Unsigned) (uintptr_t) p; s = *p++; p += s; break; /* All other operations cause an error. */ default: count = -1; goto done; } if (lbuf != NULL) { lbuf->ld_s[count].lr_number = operand1; lbuf->ld_s[count].lr_number2 = operand2; } count++; } done: return (count); }