diff options
-rw-r--r-- | trunk/ChangeLog | 35 | ||||
-rw-r--r-- | trunk/src/dwarf2.c | 74 | ||||
-rw-r--r-- | trunk/src/dwarf2.h | 25 |
3 files changed, 112 insertions, 22 deletions
diff --git a/trunk/ChangeLog b/trunk/ChangeLog index d743677..1cd080f 100644 --- a/trunk/ChangeLog +++ b/trunk/ChangeLog @@ -1,3 +1,38 @@ +2009-06-15 Jakub Jelinek <jakub@redhat.com> + + * dwarf2.h (DW_TAG_condition, DW_TAG_shared_type): Define. + (DW_OP_form_tls_address, DW_OP_call_frame_cfa, DW_OP_bit_piece, + DW_OP_implicit_value, DW_OP_stack_value, DW_OP_GNU_uninit, + DW_OP_GNU_encoded_addr): Define. + (DW_ATE_packed_decimal, DW_ATE_numeric_string, DW_ATE_edited, + DW_ATE_signed_fixed, DW_ATE_unsigned_fixed, DW_ATE_decimal_float): + Define. + (DW_CFA_val_offset, DW_CFA_val_offset_sf, DW_CFA_val_expression): + Define. + (DW_LANG_PLI, DW_LANG_ObjC, DW_LANG_ObjC_plus_plus, DW_LANG_UPC, + DW_LANG_D): Define. + * dwarf2.c (debug_sections): Add .debug_pubtypes. + (DEBUG_PUBTYPES): Define. + (DEBUG_MACINFO, DEBUG_LOC, DEBUG_STR, DEBUG_FRAME, DEBUG_RANGES): + Adjust. + (struct cu_data): Add cu_version field. + (read_abbrev): Adjust error messages not to be DWARF-2 specific. + (adjust_location_list): Likewise. Fix up DW_OP_call_ref handling, + handle DW_OP_form_tls_address, DW_OP_call_frame_cfa, + DW_OP_GNU_uninit, DW_OP_bit_piece, DW_OP_stack_value and + DW_OP_implicit_value. + (adjust_attributes): For cu->cu_version == 2 skip ptr_size bytes + instead of just 4. Adjust error messages not to be DWARF-2 + specific. + (adjust_dwarf2_line): Handle version 3 of .debug_line. + (adjust_dwarf2_frame): Just that CIE version is 1 or 3, for + version 1 skip just one byte instead of uleb128 for return address + column. Handle DW_CFA_val_offset, DW_CFA_val_offset_sf and + DW_CFA_val_expression. + (adjust_dwarf2): Handle version 3 of .debug_info, initialize + cu.cu_version. Adjust error messages not to be DWARF-2 specific. + Note that .debug_pubtypes doesn't need adjustments. + 2009-03-11 Jakub Jelinek <jakub@redhat.com> * src/prelink.h (PLArch): Add rtype_class_valid field. diff --git a/trunk/src/dwarf2.c b/trunk/src/dwarf2.c index 4c27836..8869dc3 100644 --- a/trunk/src/dwarf2.c +++ b/trunk/src/dwarf2.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001, 2002, 2003, 2005, 2006 Red Hat, Inc. +/* Copyright (C) 2001, 2002, 2003, 2005, 2006, 2009 Red Hat, Inc. Written by Jakub Jelinek <jakub@redhat.com>, 2001. This program is free software; you can redistribute it and/or modify @@ -155,16 +155,18 @@ static struct #define DEBUG_LINE 2 #define DEBUG_ARANGES 3 #define DEBUG_PUBNAMES 4 -#define DEBUG_MACINFO 5 -#define DEBUG_LOC 6 -#define DEBUG_STR 7 -#define DEBUG_FRAME 8 -#define DEBUG_RANGES 9 +#define DEBUG_PUBTYPES 5 +#define DEBUG_MACINFO 6 +#define DEBUG_LOC 7 +#define DEBUG_STR 8 +#define DEBUG_FRAME 9 +#define DEBUG_RANGES 10 { ".debug_info", NULL, 0, 0 }, { ".debug_abbrev", NULL, 0, 0 }, { ".debug_line", NULL, 0, 0 }, { ".debug_aranges", NULL, 0, 0 }, { ".debug_pubnames", NULL, 0, 0 }, + { ".debug_pubtypes", NULL, 0, 0 }, { ".debug_macinfo", NULL, 0, 0 }, { ".debug_loc", NULL, 0, 0 }, { ".debug_str", NULL, 0, 0 }, @@ -191,6 +193,7 @@ struct cu_data { GElf_Addr cu_entry_pc; GElf_Addr cu_low_pc; + unsigned char cu_version; }; static hashval_t @@ -250,7 +253,7 @@ no_memory: } if (*slot != NULL) { - error (0, 0, "%s: Duplicate DWARF-2 abbreviation %d", dso->filename, + error (0, 0, "%s: Duplicate DWARF abbreviation %d", dso->filename, t->entry); free (t); htab_delete (h); @@ -270,7 +273,7 @@ no_memory: form = read_uleb128 (ptr); if (form == 2 || form > DW_FORM_indirect) { - error (0, 0, "%s: Unknown DWARF-2 DW_FORM_%d", dso->filename, form); + error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, form); htab_delete (h); return NULL; } @@ -280,7 +283,7 @@ no_memory: } if (read_uleb128 (ptr) != 0) { - error (0, 0, "%s: DWARF-2 abbreviation does not end with 2 zeros", + error (0, 0, "%s: DWARF abbreviation does not end with 2 zeros", dso->filename); htab_delete (h); return NULL; @@ -340,8 +343,11 @@ adjust_location_list (DSO *dso, unsigned char *ptr, size_t len, 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_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; case DW_OP_const1u: case DW_OP_pick: @@ -360,6 +366,7 @@ adjust_location_list (DSO *dso, unsigned char *ptr, size_t len, case DW_OP_const4u: case DW_OP_const4s: case DW_OP_call4: + case DW_OP_call_ref: ptr += 4; break; case DW_OP_const8u: @@ -376,11 +383,17 @@ adjust_location_list (DSO *dso, unsigned char *ptr, size_t len, read_uleb128 (ptr); break; case DW_OP_bregx: + case DW_OP_bit_piece: read_uleb128 (ptr); read_uleb128 (ptr); break; + case DW_OP_implicit_value: + { + uint32_t len = read_uleb128 (ptr); + ptr += len; + } default: - error (0, 0, "%s: Unknown DWARF-2 DW_OP_%d", dso->filename, op); + error (0, 0, "%s: Unknown DWARF DW_OP_%d", dso->filename, op); return 1; } } @@ -596,6 +609,11 @@ adjust_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, read_uleb128 (ptr); break; case DW_FORM_ref_addr: + if (cu->cu_version == 2) + ptr += ptr_size; + else + ptr += 4; + break; case DW_FORM_strp: ptr += 4; break; @@ -622,7 +640,7 @@ adjust_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, assert (len < UINT_MAX); break; default: - error (0, 0, "%s: Unknown DWARF-2 DW_FORM_%d", dso->filename, + error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, form); return NULL; } @@ -645,7 +663,7 @@ adjust_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, || (t->attr[i].attr >= DW_AT_sf_names && t->attr[i].attr <= DW_AT_body_end)) break; - error (0, 0, "%s: Unknown DWARF-2 DW_AT_%d with block DW_FORM", + error (0, 0, "%s: Unknown DWARF DW_AT_%d with block DW_FORM", dso->filename, t->attr[i].attr); return NULL; } @@ -688,7 +706,7 @@ adjust_dwarf2_line (DSO *dso, GElf_Addr start, GElf_Addr adjust) } value = read_16 (ptr); - if (value != 2) + if (value != 2 && value != 3) { error (0, 0, "%s: DWARF version %d unhandled", dso->filename, value); @@ -836,7 +854,13 @@ adjust_dwarf2_frame (DSO *dso, GElf_Addr start, GElf_Addr adjust) if (value == 0xffffffff) { /* CIE. */ - ptr++; /* Skip version. */ + uint32_t version = *ptr++; + if (version != 1 && version != 3) + { + error (0, 0, "%s: unhandled .debug_frame version %d", + dso->filename, version); + return 1; + } if (*ptr != '\0') { error (0, 0, "%s: .debug_frame unhandled augmentation \"%s\"", @@ -846,7 +870,10 @@ adjust_dwarf2_frame (DSO *dso, GElf_Addr start, GElf_Addr adjust) ptr++; /* Skip augmentation. */ read_uleb128 (ptr); /* Skip code_alignment factor. */ read_uleb128 (ptr); /* Skip data_alignment factor. */ - read_uleb128 (ptr); /* Skip return_address_register. */ + if (version >= 3) + read_uleb128 (ptr); /* Skip return_address_register. */ + else + ptr++; } else { @@ -881,6 +908,8 @@ adjust_dwarf2_frame (DSO *dso, GElf_Addr start, GElf_Addr adjust) case DW_CFA_offset_extended_sf: case DW_CFA_def_cfa_sf: case DW_CFA_GNU_negative_offset_extended: + case DW_CFA_val_offset: + case DW_CFA_val_offset_sf: read_uleb128 (ptr); /* FALLTHROUGH */ case DW_CFA_restore_extended: @@ -907,6 +936,7 @@ adjust_dwarf2_frame (DSO *dso, GElf_Addr start, GElf_Addr adjust) ptr += 4; break; case DW_CFA_expression: + case DW_CFA_val_expression: read_uleb128 (ptr); /* FALLTHROUGH */ case DW_CFA_def_cfa_expression: @@ -1041,12 +1071,13 @@ adjust_dwarf2 (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust) } value = read_16 (ptr); - if (value != 2) + if (value != 2 && value != 3) { error (0, 0, "%s: DWARF version %d unhandled", dso->filename, value); return 1; } + cu.cu_version = value; value = read_32 (ptr); if (value >= debug_sections[DEBUG_ABBREV].size) @@ -1054,7 +1085,7 @@ adjust_dwarf2 (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust) if (debug_sections[DEBUG_ABBREV].data == NULL) error (0, 0, "%s: .debug_abbrev not present", dso->filename); else - error (0, 0, "%s: DWARF-2 CU abbrev offset too large", + error (0, 0, "%s: DWARF CU abbrev offset too large", dso->filename); return 1; } @@ -1074,14 +1105,14 @@ adjust_dwarf2 (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust) } else { - error (0, 0, "%s: Invalid DWARF-2 pointer size %d", + error (0, 0, "%s: Invalid DWARF pointer size %d", dso->filename, ptr_size); return 1; } } else if (read_1 (ptr) != ptr_size) { - error (0, 0, "%s: DWARF-2 pointer size differs between CUs", + error (0, 0, "%s: DWARF pointer size differs between CUs", dso->filename); return 1; } @@ -1102,7 +1133,7 @@ adjust_dwarf2 (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust) t = htab_find_with_hash (abbrev, &tag, tag.entry); if (t == NULL) { - error (0, 0, "%s: Could not find DWARF-2 abbreviation %d", + error (0, 0, "%s: Could not find DWARF abbreviation %d", dso->filename, tag.entry); htab_delete (abbrev); return 1; @@ -1138,6 +1169,7 @@ adjust_dwarf2 (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust) /* .debug_abbrev requires no adjustement. */ /* .debug_pubnames requires no adjustement. */ + /* .debug_pubtypes requires no adjustement. */ /* .debug_macinfo requires no adjustement. */ /* .debug_str requires no adjustement. */ /* .debug_ranges adjusted for each DW_AT_ranges pointing into it. */ diff --git a/trunk/src/dwarf2.h b/trunk/src/dwarf2.h index 1f938f5..143a00b 100644 --- a/trunk/src/dwarf2.h +++ b/trunk/src/dwarf2.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001, 2002 Red Hat, Inc. +/* Copyright (C) 2001, 2002, 2009 Red Hat, Inc. Written by Jakub Jelinek <jakub@redhat.com>, 2001. This program is free software; you can redistribute it and/or modify @@ -71,6 +71,8 @@ #define DW_TAG_unspecified_type 0x3b #define DW_TAG_partial_unit 0x3c #define DW_TAG_imported_unit 0x3d +#define DW_TAG_condition 0x3f +#define DW_TAG_shared_type 0x40 #define DW_TAG_MIPS_loop 0x4081 #define DW_TAG_format_label 0x4101 #define DW_TAG_function_template 0x4102 @@ -348,7 +350,14 @@ #define DW_OP_call2 0x98 #define DW_OP_call4 0x99 #define DW_OP_call_ref 0x9a +#define DW_OP_form_tls_address 0x9b +#define DW_OP_call_frame_cfa 0x9c +#define DW_OP_bit_piece 0x9d +#define DW_OP_implicit_value 0x9e +#define DW_OP_stack_value 0x9f #define DW_OP_GNU_push_tls_address 0xe0 +#define DW_OP_GNU_uninit 0xf0 +#define DW_OP_GNU_encoded_addr 0xf1 #define DW_OP_lo_user 0xe0 #define DW_OP_hi_user 0xff @@ -362,6 +371,12 @@ #define DW_ATE_unsigned 0x7 #define DW_ATE_unsigned_char 0x8 #define DW_ATE_imaginary_float 0x9 +#define DW_ATE_packed_decimal 0xa +#define DW_ATE_numeric_string 0xb +#define DW_ATE_edited 0xc +#define DW_ATE_signed_fixed 0xd +#define DW_ATE_unsigned_fixed 0xe +#define DW_ATE_decimal_float 0xf #define DW_ATE_lo_user 0x80 #define DW_ATE_hi_user 0xff @@ -437,6 +452,9 @@ #define DW_CFA_offset_extended_sf 0x11 #define DW_CFA_def_cfa_sf 0x12 #define DW_CFA_def_cfa_offset_sf 0x13 +#define DW_CFA_val_offset 0x14 +#define DW_CFA_val_offset_sf 0x15 +#define DW_CFA_val_expression 0x16 #define DW_CFA_MIPS_advance_loc8 0x1d #define DW_CFA_GNU_window_save 0x2d #define DW_CFA_GNU_args_size 0x2e @@ -468,6 +486,11 @@ #define DW_LANG_C99 0x000c #define DW_LANG_Ada95 0x000d #define DW_LANG_Fortran95 0x000e +#define DW_LANG_PLI 0x000f +#define DW_LANG_ObjC 0x0010 +#define DW_LANG_ObjC_plus_plus 0x0011 +#define DW_LANG_UPC 0x0012 +#define DW_LANG_D 0x0013 #define DW_LANG_Mips_Assembler 0x8001 #define DW_LANG_lo_user 0x8000 #define DW_LANG_hi_user 0xffff |