From b7807392f042c1bb9f3acdc73c285aa138fd8cb1 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 9 Sep 2010 10:18:12 +0000 Subject: [PATCH] * dwarf.h (debug_info): Add offset_info and dwarf_version fields. * dwarf.c (decode_location_expression): Add offset_size and dwarf_version arguments. Prefix DIE offset with 0x for DW_OP_call{2,4,_ref}. Fix up DW_OP_call_ref operand size, complain if in frame info section. Handle DW_OP_GNU_implicit_pointer. (read_and_display_attr_value, display_debug_loc, display_debug_frames): Adjust decode_location_expression callers. (process_debug_info): Save offset_size and dwarf_version values into debug_information array. * dwarf2.h (DW_OP_GNU_implicit_pointer): New. --- binutils/ChangeLog | 13 +++++++++ binutils/dwarf.c | 70 ++++++++++++++++++++++++++++++++++++++++------ binutils/dwarf.h | 4 ++- include/ChangeLog | 4 +++ include/dwarf2.h | 1 + 5 files changed, 82 insertions(+), 10 deletions(-) diff --git a/binutils/ChangeLog b/binutils/ChangeLog index d42141eadb..dcbf00b04b 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,16 @@ +2010-09-09 Jakub Jelinek + + * dwarf.h (debug_info): Add offset_info and dwarf_version fields. + * dwarf.c (decode_location_expression): Add offset_size and + dwarf_version arguments. Prefix DIE offset with 0x for + DW_OP_call{2,4,_ref}. Fix up DW_OP_call_ref operand size, + complain if in frame info section. Handle + DW_OP_GNU_implicit_pointer. + (read_and_display_attr_value, display_debug_loc, + display_debug_frames): Adjust decode_location_expression callers. + (process_debug_info): Save offset_size and dwarf_version values + into debug_information array. + 2010-09-07 Nick Clifton * readelf.c (process_section_headers): Mention meaning of 'l' diff --git a/binutils/dwarf.c b/binutils/dwarf.c index 599c0d2ba8..17a608c9fa 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -712,6 +712,8 @@ display_block (unsigned char *data, unsigned long length) static int decode_location_expression (unsigned char * data, unsigned int pointer_size, + unsigned int offset_size, + int dwarf_version, unsigned long length, unsigned long cu_offset, struct dwarf_section * section) @@ -1018,20 +1020,36 @@ decode_location_expression (unsigned char * data, case DW_OP_call2: /* XXX: Strictly speaking for 64-bit DWARF3 files this ought to be an 8-byte wide computation. */ - printf ("DW_OP_call2: <%lx>", (long) byte_get (data, 2) + cu_offset); + printf ("DW_OP_call2: <0x%lx>", (long) byte_get (data, 2) + cu_offset); data += 2; break; case DW_OP_call4: /* XXX: Strictly speaking for 64-bit DWARF3 files this ought to be an 8-byte wide computation. */ - printf ("DW_OP_call4: <%lx>", (long) byte_get (data, 4) + cu_offset); + printf ("DW_OP_call4: <0x%lx>", (long) byte_get (data, 4) + cu_offset); data += 4; break; case DW_OP_call_ref: /* XXX: Strictly speaking for 64-bit DWARF3 files this ought to be an 8-byte wide computation. */ - printf ("DW_OP_call_ref: <%lx>", (long) byte_get (data, 4) + cu_offset); - data += 4; + if (dwarf_version == -1) + { + printf (_("(DW_OP_call_ref in frame info)")); + /* No way to tell where the next op is, so just bail. */ + return need_frame_base; + } + if (dwarf_version == 2) + { + printf ("DW_OP_call_ref: <0x%lx>", + (long) byte_get (data, pointer_size)); + data += pointer_size; + } + else + { + printf ("DW_OP_call_ref: <0x%lx>", + (long) byte_get (data, offset_size)); + data += offset_size; + } break; case DW_OP_form_tls_address: printf ("DW_OP_form_tls_address"); @@ -1083,6 +1101,30 @@ decode_location_expression (unsigned char * data, print_dwarf_vma (addr, pointer_size); } break; + case DW_OP_GNU_implicit_pointer: + /* XXX: Strictly speaking for 64-bit DWARF3 files + this ought to be an 8-byte wide computation. */ + if (dwarf_version == -1) + { + printf (_("(DW_OP_GNU_implicit_pointer in frame info)")); + /* No way to tell where the next op is, so just bail. */ + return need_frame_base; + } + if (dwarf_version == 2) + { + printf ("DW_OP_GNU_implicit_pointer: <0x%lx> %ld", + (long) byte_get (data, pointer_size), + read_leb128 (data + pointer_size, &bytes_read, 1)); + data += pointer_size + bytes_read; + } + else + { + printf ("DW_OP_GNU_implicit_pointer: <0x%lx> %ld", + (long) byte_get (data, offset_size), + read_leb128 (data + offset_size, &bytes_read, 1)); + data += offset_size; + } + break; /* HP extensions. */ case DW_OP_HP_is_value: @@ -1632,6 +1674,8 @@ read_and_display_attr_value (unsigned long attribute, printf ("("); need_frame_base = decode_location_expression (block_start, pointer_size, + offset_size, + dwarf_version, uvalue, cu_offset, section); printf (")"); @@ -2023,6 +2067,8 @@ process_debug_info (struct dwarf_section *section, debug_information [unit].cu_offset = cu_offset; debug_information [unit].pointer_size = compunit.cu_pointer_size; + debug_information [unit].offset_size = offset_size; + debug_information [unit].dwarf_version = compunit.cu_version; debug_information [unit].base_address = 0; debug_information [unit].loc_offsets = NULL; debug_information [unit].have_frame_base = NULL; @@ -3405,6 +3451,8 @@ display_debug_loc (struct dwarf_section *section, void *file) unsigned short length; unsigned long offset; unsigned int pointer_size; + unsigned int offset_size; + int dwarf_version; unsigned long cu_offset; unsigned long base_address; int need_frame_base; @@ -3412,6 +3460,8 @@ display_debug_loc (struct dwarf_section *section, void *file) pointer_size = debug_information [i].pointer_size; cu_offset = debug_information [i].cu_offset; + offset_size = debug_information [i].offset_size; + dwarf_version = debug_information [i].dwarf_version; for (j = 0; j < debug_information [i].num_loc_offsets; j++) { @@ -3503,6 +3553,8 @@ display_debug_loc (struct dwarf_section *section, void *file) putchar ('('); need_frame_base = decode_location_expression (start, pointer_size, + offset_size, + dwarf_version, length, cu_offset, section); putchar (')'); @@ -4774,8 +4826,8 @@ display_debug_frames (struct dwarf_section *section, if (! do_debug_frames_interp) { printf (" DW_CFA_def_cfa_expression ("); - decode_location_expression (start, eh_addr_size, ul, 0, - section); + decode_location_expression (start, eh_addr_size, 0, -1, + ul, 0, section); printf (")\n"); } fc->cfa_exp = 1; @@ -4791,7 +4843,7 @@ display_debug_frames (struct dwarf_section *section, { printf (" DW_CFA_expression: %s%s (", reg_prefix, regname (reg, 0)); - decode_location_expression (start, eh_addr_size, + decode_location_expression (start, eh_addr_size, 0, -1, ul, 0, section); printf (")\n"); } @@ -4809,8 +4861,8 @@ display_debug_frames (struct dwarf_section *section, { printf (" DW_CFA_val_expression: %s%s (", reg_prefix, regname (reg, 0)); - decode_location_expression (start, eh_addr_size, ul, 0, - section); + decode_location_expression (start, eh_addr_size, 0, -1, + ul, 0, section); printf (")\n"); } if (*reg_prefix == '\0') diff --git a/binutils/dwarf.h b/binutils/dwarf.h index a9b501f3e7..df90ae0c33 100644 --- a/binutils/dwarf.h +++ b/binutils/dwarf.h @@ -1,5 +1,5 @@ /* dwarf.h - DWARF support header file - Copyright 2005, 2007, 2008, 2009 + Copyright 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Binutils. @@ -84,6 +84,8 @@ extern struct dwarf_section_display debug_displays []; typedef struct { unsigned int pointer_size; + unsigned int offset_size; + int dwarf_version; unsigned long cu_offset; unsigned long base_address; /* This is an array of offsets to the location list table. */ diff --git a/include/ChangeLog b/include/ChangeLog index 91b2edbed0..7f3682c264 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,7 @@ +2010-09-09 Jakub Jelinek + + * dwarf2.h (DW_OP_GNU_implicit_pointer): New. + 2010-07-06 Ken Werner * floatformat.h (floatformat_ieee_half_big): Add declaration. diff --git a/include/dwarf2.h b/include/dwarf2.h index 03c25812d0..fea23ad61e 100644 --- a/include/dwarf2.h +++ b/include/dwarf2.h @@ -622,6 +622,7 @@ enum dwarf_location_atom /* The following is for marking variables that are uninitialized. */ DW_OP_GNU_uninit = 0xf0, DW_OP_GNU_encoded_addr = 0xf1, + DW_OP_GNU_implicit_pointer = 0xf2, /* HP extensions. */ DW_OP_HP_unknown = 0xe0, /* Ouch, the same as GNU_push_tls_address. */ DW_OP_HP_is_value = 0xe1, -- 2.34.1