int
internal_function
-__libdw_intern_expression (Dwarf *dbg,
- bool other_byte_order, unsigned int address_size,
+__libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
+ unsigned int address_size, unsigned int ref_size,
void **cache, const Dwarf_Block *block,
bool cfap, bool valuep,
Dwarf_Op **llbuf, size_t *listlen, int sec_index)
return -1;
break;
+ case DW_OP_call_ref:
+ /* DW_FORM_ref_addr, depends on offset size of CU. */
+ if (__libdw_read_offset_inc (dbg, sec_index, &data, ref_size,
+ &newloc->number, IDX_debug_info, 0))
+ return -1;
+ break;
+
case DW_OP_deref:
case DW_OP_dup:
case DW_OP_drop:
case DW_OP_reg0 ... DW_OP_reg31:
case DW_OP_nop:
case DW_OP_push_object_address:
- case DW_OP_call_ref:
case DW_OP_call_frame_cfa:
case DW_OP_form_tls_address:
case DW_OP_GNU_push_tls_address:
Dwarf_Op **llbuf, size_t *listlen, int sec_index)
{
return __libdw_intern_expression (cu->dbg, cu->dbg->other_byte_order,
- cu->address_size, &cu->locs, block,
+ cu->address_size, (cu->version == 2
+ ? cu->address_size
+ : cu->offset_size),
+ &cu->locs, block,
false, false,
llbuf, listlen, sec_index);
}
static void
print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
- unsigned int addrsize, Dwarf_Word len, const unsigned char *data)
+ unsigned int addrsize, unsigned int offset_size,
+ Dwarf_Word len, const unsigned char *data)
{
static const char *const known[] =
{
switch (op)
{
- case DW_OP_call_ref:
case DW_OP_addr:;
/* Address operand. */
Dwarf_Word addr;
data += addrsize;
len -= addrsize;
- if (op == DW_OP_addr)
+ char *a = format_dwarf_addr (dwflmod, 0, addr);
+ printf ("%*s[%4" PRIuMAX "] %s %s\n",
+ indent, "", (uintmax_t) offset, known[op], a);
+ free (a);
+
+ offset += 1 + addrsize;
+ break;
+
+ case DW_OP_call_ref:
+ /* Offset operand. */
+ NEED (offset_size);
+ if (offset_size == 4)
+ addr = read_4ubyte_unaligned (dbg, data);
+ else
{
- char *a = format_dwarf_addr (dwflmod, 0, addr);
- printf ("%*s[%4" PRIuMAX "] %s %s\n",
- indent, "", (uintmax_t) offset, known[op], a);
- free (a);
+ assert (offset_size == 8);
+ addr = read_8ubyte_unaligned (dbg, data);
}
- else
- printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX "\n",
- indent, "", (uintmax_t) offset,
- known[op], (uintmax_t) addr);
- offset += 1 + addrsize;
+ data += offset_size;
+ len -= offset_size;
+
+ printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX "\n",
+ indent, "", (uintmax_t) offset,
+ known[op], (uintmax_t) addr);
+ offset += 1 + offset_size;
break;
case DW_OP_deref_size:
// XXX overflow check
get_uleb128 (op1, readp); /* Length of DW_FORM_block. */
printf (" def_cfa_expression %" PRIu64 "\n", op1);
- print_ops (dwflmod, dbg, 10, 10, ptr_size, op1, readp);
+ print_ops (dwflmod, dbg, 10, 10, ptr_size, 0, op1, readp);
readp += op1;
break;
case DW_CFA_expression:
get_uleb128 (op2, readp); /* Length of DW_FORM_block. */
printf (" expression r%" PRIu64 " (%s) \n",
op1, regname (op1));
- print_ops (dwflmod, dbg, 10, 10, ptr_size, op2, readp);
+ print_ops (dwflmod, dbg, 10, 10, ptr_size, 0, op2, readp);
readp += op2;
break;
case DW_CFA_offset_extended_sf:
get_uleb128 (op2, readp); /* Length of DW_FORM_block. */
printf (" val_expression r%" PRIu64 " (%s)\n",
op1, regname (op1));
- print_ops (dwflmod, dbg, 10, 10, ptr_size, op2, readp);
+ print_ops (dwflmod, dbg, 10, 10, ptr_size, 0, op2, readp);
readp += op2;
break;
case DW_CFA_MIPS_advance_loc8:
Dwarf *dbg;
int level;
unsigned int addrsize;
+ unsigned int offset_size;
Dwarf_Off cu_offset;
};
case DW_AT_upper_bound:
print_ops (cbargs->dwflmod, cbargs->dbg,
12 + level * 2, 12 + level * 2,
- cbargs->addrsize, block.length, block.data);
+ cbargs->addrsize, cbargs->offset_size,
+ block.length, block.data);
break;
default:
(uint64_t) offset, /*version*/2, abbroffset, addrsize, offsize);
- struct attrcb_args args;
- args.dwflmod = dwflmod;
- args.dbg = dbg;
- args.addrsize = addrsize;
- args.cu_offset = offset;
+ struct attrcb_args args =
+ {
+ .dwflmod = dwflmod,
+ .dbg = dbg,
+ .addrsize = addrsize,
+ .offset_size = offsize,
+ .cu_offset = offset
+ };
offset += cuhl;
size_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
+ /* XXX This is wrong! We can only know the right size given the CU that
+ points to this location list. */
+ size_t offset_size = 4;
+
bool first = true;
unsigned char *readp = data->d_buf;
while (readp < (unsigned char *) data->d_buf + data->d_size)
free (e);
print_ops (dwflmod, dbg, 1, 18 + (address_size * 4),
- address_size, len, readp);
+ address_size, offset_size, len, readp);
first = false;
readp += len;