From 8be455d765a7cfb8f2cb045ec80e2b2af1597d15 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Fri, 6 May 2011 15:06:49 +0000 Subject: [PATCH] gdb/ PR 12573 * dwarf2read.c (struct dwarf2_cu): New field has_loclist. (producer_is_gcc_ge_4_0): New function. (process_full_comp_unit): Set also symtab->locations_valid. Move the symtab->language code. (var_decode_location): Set cu->has_loclist. * symtab.c (skip_prologue_sal): New variables saved_pc, force_skip and skip. Intialize force_skip from locations_valid. Move the prologue skipping code into two passes. * symtab.h (struct symtab): Make the primary field a bitfield. New field locations_valid. gdb/testsuite/ PR 12573 * gdb.dwarf2/dw2-skip-prologue.S: New file. * gdb.dwarf2/dw2-skip-prologue.c: New file. * gdb.dwarf2/dw2-skip-prologue.exp: New file. --- gdb/ChangeLog | 14 + gdb/dwarf2read.c | 73 +++- gdb/symtab.c | 94 +++-- gdb/symtab.h | 8 +- gdb/testsuite/ChangeLog | 7 + gdb/testsuite/gdb.dwarf2/dw2-skip-prologue.S | 391 ++++++++++++++++++ gdb/testsuite/gdb.dwarf2/dw2-skip-prologue.c | 58 +++ .../gdb.dwarf2/dw2-skip-prologue.exp | 74 ++++ 8 files changed, 677 insertions(+), 42 deletions(-) create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-skip-prologue.S create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-skip-prologue.c create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-skip-prologue.exp diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 02689af8a34..1306b880307 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,17 @@ +2011-05-06 Jan Kratochvil + + PR 12573 + * dwarf2read.c (struct dwarf2_cu): New field has_loclist. + (producer_is_gcc_ge_4_0): New function. + (process_full_comp_unit): Set also symtab->locations_valid. Move the + symtab->language code. + (var_decode_location): Set cu->has_loclist. + * symtab.c (skip_prologue_sal): New variables saved_pc, force_skip and + skip. Intialize force_skip from locations_valid. Move the prologue + skipping code into two passes. + * symtab.h (struct symtab): Make the primary field a bitfield. New + field locations_valid. + 2011-05-06 Jan Kratochvil * c-exp.y (qualified_name): Call destructor_name_p with $1.type. diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index eb5d9245bdb..81b20c7edfc 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -404,6 +404,13 @@ struct dwarf2_cu DIEs for namespaces, we don't need to try to infer them from mangled names. */ unsigned int has_namespace_info : 1; + + /* This CU references .debug_loc. See the symtab->locations_valid field. + This test is imperfect as there may exist optimized debug code not using + any location list and still facing inlining issues if handled as + unoptimized code. For a future better test see GCC PR other/32998. */ + + unsigned int has_loclist : 1; }; /* Persistent data held for a compilation unit, even when not @@ -4610,6 +4617,44 @@ compute_delayed_physnames (struct dwarf2_cu *cu) } } +/* Check for GCC >= 4.0. */ + +static int +producer_is_gcc_ge_4_0 (struct dwarf2_cu *cu) +{ + const char *cs; + int major, minor; + + if (cu->producer == NULL) + { + /* For unknown compilers expect their behavior is not compliant. For GCC + this case can also happen for -gdwarf-4 type units supported since + gcc-4.5. */ + + return 0; + } + + /* Skip any identifier after "GNU " - such as "C++" or "Java". */ + + if (strncmp (cu->producer, "GNU ", strlen ("GNU ")) != 0) + { + /* For non-GCC compilers expect their behavior is not compliant. */ + + return 0; + } + cs = &cu->producer[strlen ("GNU ")]; + while (*cs && !isdigit (*cs)) + cs++; + if (sscanf (cs, "%d.%d", &major, &minor) != 2) + { + /* Not recognized as GCC. */ + + return 0; + } + + return major >= 4; +} + /* Generate full symbol information for PST and CU, whose DIEs have already been loaded into memory. */ @@ -4649,13 +4694,26 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu) symtab = end_symtab (highpc + baseaddr, objfile, SECT_OFF_TEXT (objfile)); - /* Set symtab language to language from DW_AT_language. - If the compilation is from a C file generated by language preprocessors, - do not set the language if it was already deduced by start_subfile. */ - if (symtab != NULL - && !(cu->language == language_c && symtab->language != language_c)) + if (symtab != NULL) { - symtab->language = cu->language; + /* Set symtab language to language from DW_AT_language. If the + compilation is from a C file generated by language preprocessors, do + not set the language if it was already deduced by start_subfile. */ + if (!(cu->language == language_c && symtab->language != language_c)) + symtab->language = cu->language; + + /* GCC-4.0 has started to support -fvar-tracking. GCC-3.x still can + produce DW_AT_location with location lists but it can be possibly + invalid without -fvar-tracking. + + For -gdwarf-4 type units LOCATIONS_VALID indication is fortunately not + needed, it would be wrong due to missing DW_AT_producer there. + + Still one can confuse GDB by using non-standard GCC compilation + options - this waits on GCC PR other/32998 (-frecord-gcc-switches). + */ + if (cu->has_loclist && producer_is_gcc_ge_4_0 (cu)) + symtab->locations_valid = 1; } if (dwarf2_per_objfile->using_index) @@ -10968,6 +11026,9 @@ var_decode_location (struct attribute *attr, struct symbol *sym, dwarf2_symbol_mark_computed (attr, sym, cu); SYMBOL_CLASS (sym) = LOC_COMPUTED; + + if (SYMBOL_COMPUTED_OPS (sym) == &dwarf2_loclist_funcs) + cu->has_loclist = 1; } /* Given a pointer to a DWARF information entry, figure out if we need diff --git a/gdb/symtab.c b/gdb/symtab.c index 7f8877fcb24..84e01a660cd 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -2441,12 +2441,13 @@ skip_prologue_sal (struct symtab_and_line *sal) struct symbol *sym; struct symtab_and_line start_sal; struct cleanup *old_chain; - CORE_ADDR pc; + CORE_ADDR pc, saved_pc; struct obj_section *section; const char *name; struct objfile *objfile; struct gdbarch *gdbarch; struct block *b, *function_block; + int force_skip, skip; /* Do not change the SAL is PC was specified explicitly. */ if (sal->explicit_pc) @@ -2484,46 +2485,69 @@ skip_prologue_sal (struct symtab_and_line *sal) gdbarch = get_objfile_arch (objfile); - /* If the function is in an unmapped overlay, use its unmapped LMA address, - so that gdbarch_skip_prologue has something unique to work on. */ - if (section_is_overlay (section) && !section_is_mapped (section)) - pc = overlay_unmapped_address (pc, section); + /* Process the prologue in two passes. In the first pass try to skip the + prologue (SKIP is true) and verify there is a real need for it (indicated + by FORCE_SKIP). If no such reason was found run a second pass where the + prologue is not skipped (SKIP is false). */ - /* Skip "first line" of function (which is actually its prologue). */ - pc += gdbarch_deprecated_function_start_offset (gdbarch); - pc = gdbarch_skip_prologue (gdbarch, pc); + skip = 1; + force_skip = 1; - /* For overlays, map pc back into its mapped VMA range. */ - pc = overlay_mapped_address (pc, section); + /* Be conservative - allow direct PC (without skipping prologue) only if we + have proven the CU (Compilation Unit) supports it. sal->SYMTAB does not + have to be set by the caller so we use SYM instead. */ + if (sym && SYMBOL_SYMTAB (sym)->locations_valid) + force_skip = 0; - /* Calculate line number. */ - start_sal = find_pc_sect_line (pc, section, 0); - - /* Check if gdbarch_skip_prologue left us in mid-line, and the next - line is still part of the same function. */ - if (start_sal.pc != pc - && (sym? (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) <= start_sal.end - && start_sal.end < BLOCK_END (SYMBOL_BLOCK_VALUE (sym))) - : (lookup_minimal_symbol_by_pc_section (start_sal.end, section) - == lookup_minimal_symbol_by_pc_section (pc, section)))) + saved_pc = pc; + do { - /* First pc of next line */ - pc = start_sal.end; - /* Recalculate the line number (might not be N+1). */ - start_sal = find_pc_sect_line (pc, section, 0); - } + pc = saved_pc; - /* On targets with executable formats that don't have a concept of - constructors (ELF with .init has, PE doesn't), gcc emits a call - to `__main' in `main' between the prologue and before user - code. */ - if (gdbarch_skip_main_prologue_p (gdbarch) - && name && strcmp (name, "main") == 0) - { - pc = gdbarch_skip_main_prologue (gdbarch, pc); - /* Recalculate the line number (might not be N+1). */ + /* If the function is in an unmapped overlay, use its unmapped LMA address, + so that gdbarch_skip_prologue has something unique to work on. */ + if (section_is_overlay (section) && !section_is_mapped (section)) + pc = overlay_unmapped_address (pc, section); + + /* Skip "first line" of function (which is actually its prologue). */ + pc += gdbarch_deprecated_function_start_offset (gdbarch); + if (skip) + pc = gdbarch_skip_prologue (gdbarch, pc); + + /* For overlays, map pc back into its mapped VMA range. */ + pc = overlay_mapped_address (pc, section); + + /* Calculate line number. */ start_sal = find_pc_sect_line (pc, section, 0); + + /* Check if gdbarch_skip_prologue left us in mid-line, and the next + line is still part of the same function. */ + if (skip && start_sal.pc != pc + && (sym? (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) <= start_sal.end + && start_sal.end < BLOCK_END (SYMBOL_BLOCK_VALUE (sym))) + : (lookup_minimal_symbol_by_pc_section (start_sal.end, section) + == lookup_minimal_symbol_by_pc_section (pc, section)))) + { + /* First pc of next line */ + pc = start_sal.end; + /* Recalculate the line number (might not be N+1). */ + start_sal = find_pc_sect_line (pc, section, 0); + } + + /* On targets with executable formats that don't have a concept of + constructors (ELF with .init has, PE doesn't), gcc emits a call + to `__main' in `main' between the prologue and before user + code. */ + if (gdbarch_skip_main_prologue_p (gdbarch) + && name && strcmp (name, "main") == 0) + { + pc = gdbarch_skip_main_prologue (gdbarch, pc); + /* Recalculate the line number (might not be N+1). */ + start_sal = find_pc_sect_line (pc, section, 0); + force_skip = 1; + } } + while (!force_skip && skip--); /* If we still don't have a valid source line, try to find the first PC in the lineinfo table that belongs to the same function. This @@ -2533,7 +2557,7 @@ skip_prologue_sal (struct symtab_and_line *sal) the case with the DJGPP target using "gcc -gcoff" when the compiler inserted code after the prologue to make sure the stack is aligned. */ - if (sym && start_sal.symtab == NULL) + if (!force_skip && sym && start_sal.symtab == NULL) { pc = skip_prologue_using_lineinfo (pc, SYMBOL_SYMTAB (sym)); /* Recalculate the line number. */ diff --git a/gdb/symtab.h b/gdb/symtab.h index 29e7d703b9e..12f52a21dc4 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -770,7 +770,13 @@ struct symtab should be designated the primary, so that the blockvector is relocated exactly once by objfile_relocate. */ - int primary; + unsigned int primary : 1; + + /* Symtab has been compiled with both optimizations and debug info so that + GDB may stop skipping prologues as variables locations are valid already + at function entry points. */ + + unsigned int locations_valid : 1; /* The macro table for this symtab. Like the blockvector, this may be shared between different symtabs --- and normally is for diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index e33565244b4..35db610271a 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2011-05-06 Jan Kratochvil + + PR 12573 + * gdb.dwarf2/dw2-skip-prologue.S: New file. + * gdb.dwarf2/dw2-skip-prologue.c: New file. + * gdb.dwarf2/dw2-skip-prologue.exp: New file. + 2011-05-06 Jan Kratochvil * gdb.cp/psymtab-parameter.cc: New file. diff --git a/gdb/testsuite/gdb.dwarf2/dw2-skip-prologue.S b/gdb/testsuite/gdb.dwarf2/dw2-skip-prologue.S new file mode 100644 index 00000000000..78d866d3b66 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/dw2-skip-prologue.S @@ -0,0 +1,391 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2011 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + .section .debug_info +.Lcu1_begin: + /* CU header */ + .4byte .Lcu1_end - .Lcu1_start /* Length of Compilation Unit */ +.Lcu1_start: + .2byte 2 /* DWARF Version */ + .4byte .Labbrev1_begin /* Offset into abbrev section */ + .byte 4 /* Pointer size */ + + /* CU die */ + .uleb128 1 /* Abbrev: DW_TAG_compile_unit */ + .4byte .Lline1_begin /* DW_AT_stmt_list */ + .4byte func_start /* DW_AT_low_pc */ + .4byte func_end /* DW_AT_high_pc */ + .ascii "main.c\0" /* DW_AT_name */ + .ascii "GNU C 4.0.0\0" /* DW_AT_producer must be >= 4.0 */ + .byte 2 /* DW_AT_language (DW_LANG_C) */ + + .uleb128 2 /* Abbrev: DW_TAG_subprogram */ + .byte 1 /* DW_AT_external */ + .ascii "func\0" /* DW_AT_name */ + .4byte .Ltype_int-.Lcu1_begin /* DW_AT_type */ + .4byte func_start /* DW_AT_low_pc */ + .4byte func_end /* DW_AT_high_pc */ + +/* GDB `has_loclist' detection of -O2 -g code needs to see a DW_AT_location + location list. There may exist -O2 -g CUs still not needing/using any such + location list - exactly like this CU. Make one up. */ + + .uleb128 0x7 /* (DIE (0x42) DW_TAG_formal_parameter) */ + .ascii "param\0" /* DW_AT_name */ + .long .Ltype_int - .Lcu1_begin /* DW_AT_type */ + .long loclist /* DW_AT_location */ + + .uleb128 4 /* Abbrev: DW_TAG_inlined_subroutine */ + .ascii "inlined\0" /* DW_AT_name */ + .4byte func0 /* DW_AT_low_pc */ + .4byte func1 /* DW_AT_high_pc */ + .byte 3 /* DW_AT_inline (DW_INL_declared_inlined) */ + .byte 1 /* DW_AT_call_file */ + .byte 8 /* DW_AT_call_line */ + + .uleb128 4 /* Abbrev: DW_TAG_inlined_subroutine */ + .ascii "inlined2\0" /* DW_AT_name */ + .4byte func2 /* DW_AT_low_pc */ + .4byte func3 /* DW_AT_high_pc */ + .byte 3 /* DW_AT_inline (DW_INL_declared_inlined) */ + .byte 1 /* DW_AT_call_file */ + .byte 11 /* DW_AT_call_line */ + +#ifdef INLINED + .uleb128 4 /* Abbrev: DW_TAG_inlined_subroutine */ + .ascii "otherinline\0" /* DW_AT_name */ + .4byte func3 /* DW_AT_low_pc */ + .4byte func_end /* DW_AT_high_pc */ + .byte 3 /* DW_AT_inline (DW_INL_declared_inlined) */ + .byte 1 /* DW_AT_call_file */ + .byte 9 /* DW_AT_call_line */ +#endif + +#ifdef LEXICAL + .uleb128 5 /* Abbrev: DW_TAG_lexical_block */ + .4byte func3 /* DW_AT_low_pc */ + .4byte func_end /* DW_AT_high_pc */ + + /* GDB would otherwise ignore the DW_TAG_lexical_block. */ + .uleb128 6 /* Abbrev: DW_TAG_variable */ + .ascii "lexicalvar\0" /* DW_AT_name */ + .4byte .Ltype_int-.Lcu1_begin /* DW_AT_type */ + + .byte 0 /* End of children of DW_TAG_lexical_block */ +#endif + + .byte 0 /* End of children of DW_TAG_subprogram */ + +/* Simulate `fund' is also named `func' so that the function name matches and + fund's SAL is not discarded in expand_line_sal_maybe. */ + + .uleb128 2 /* Abbrev: DW_TAG_subprogram */ + .byte 1 /* DW_AT_external */ + .ascii "func\0" /* DW_AT_name */ + .4byte .Ltype_int-.Lcu1_begin /* DW_AT_type */ + .4byte fund_start /* DW_AT_low_pc */ + .4byte fund_end /* DW_AT_high_pc */ + + .byte 0 /* End of children of DW_TAG_subprogram */ + +.Ltype_int: + .uleb128 3 /* Abbrev: DW_TAG_base_type */ + .ascii "int\0" /* DW_AT_name */ + .byte 4 /* DW_AT_byte_size */ + .byte 5 /* DW_AT_encoding */ + + .byte 0 /* End of children of CU */ + +.Lcu1_end: + + .section .debug_loc +loclist: + /* Reset the location list base address first. */ + .long -1, 0 + + .long func_start, func_end + .2byte 2f-1f +1: .byte 0x50 /* DW_OP_reg0 */ +2: + /* Location list end. */ + .long 0, 0 + +/* Abbrev table */ + .section .debug_abbrev +.Labbrev1_begin: + .uleb128 1 /* Abbrev code */ + .uleb128 0x11 /* DW_TAG_compile_unit */ + .byte 1 /* has_children */ + .uleb128 0x10 /* DW_AT_stmt_list */ + .uleb128 0x6 /* DW_FORM_data4 */ + .uleb128 0x11 /* DW_AT_low_pc */ + .uleb128 0x1 /* DW_FORM_addr */ + .uleb128 0x12 /* DW_AT_high_pc */ + .uleb128 0x1 /* DW_FORM_addr */ + .uleb128 0x3 /* DW_AT_name */ + .uleb128 0x8 /* DW_FORM_string */ + .uleb128 0x25 /* DW_AT_producer */ + .uleb128 0x8 /* DW_FORM_string */ + .uleb128 0x13 /* DW_AT_language */ + .uleb128 0xb /* DW_FORM_data1 */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + + .uleb128 2 /* Abbrev code */ + .uleb128 0x2e /* DW_TAG_subprogram */ + .byte 1 /* has_children */ + .uleb128 0x3f /* DW_AT_external */ + .uleb128 0xc /* DW_FORM_flag */ + .uleb128 0x3 /* DW_AT_name */ + .uleb128 0x8 /* DW_FORM_string */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .uleb128 0x11 /* DW_AT_low_pc */ + .uleb128 0x1 /* DW_FORM_addr */ + .uleb128 0x12 /* DW_AT_high_pc */ + .uleb128 0x1 /* DW_FORM_addr */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + + .uleb128 3 /* Abbrev code */ + .uleb128 0x24 /* DW_TAG_base_type */ + .byte 0 /* has_children */ + .uleb128 0x3 /* DW_AT_name */ + .uleb128 0x8 /* DW_FORM_string */ + .uleb128 0xb /* DW_AT_byte_size */ + .uleb128 0xb /* DW_FORM_data1 */ + .uleb128 0x3e /* DW_AT_encoding */ + .uleb128 0xb /* DW_FORM_data1 */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + + .uleb128 4 /* Abbrev code */ + .uleb128 0x1d /* DW_TAG_inlined_subroutine */ + .byte 0 /* has_children */ + .uleb128 0x3 /* DW_AT_name */ + .uleb128 0x8 /* DW_FORM_string */ + .uleb128 0x11 /* DW_AT_low_pc */ + .uleb128 0x1 /* DW_FORM_addr */ + .uleb128 0x12 /* DW_AT_high_pc */ + .uleb128 0x1 /* DW_FORM_addr */ + .uleb128 0x20 /* DW_AT_inline */ + .uleb128 0xb /* DW_FORM_data1 */ + .uleb128 0x58 /* DW_AT_call_file */ + .uleb128 0xb /* DW_FORM_data1 */ + .uleb128 0x59 /* DW_AT_call_line */ + .uleb128 0xb /* DW_FORM_data1 */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + + .uleb128 5 /* Abbrev code */ + .uleb128 0x0b /* DW_TAG_lexical_block */ + .byte 1 /* has_children */ + .uleb128 0x11 /* DW_AT_low_pc */ + .uleb128 0x1 /* DW_FORM_addr */ + .uleb128 0x12 /* DW_AT_high_pc */ + .uleb128 0x1 /* DW_FORM_addr */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + + .uleb128 6 /* Abbrev code */ + .uleb128 0x34 /* DW_TAG_variable */ + .byte 0 /* has_children */ + .uleb128 0x3 /* DW_AT_name */ + .uleb128 0x8 /* DW_FORM_string */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + + .uleb128 0x7 /* (abbrev code) */ + .uleb128 0x5 /* (TAG: DW_TAG_formal_parameter) */ + .byte 0x0 /* DW_children_no */ + .uleb128 0x3 /* DW_AT_name */ + .uleb128 0x8 /* DW_FORM_string */ + .uleb128 0x49 /* (DW_AT_type) */ + .uleb128 0x13 /* (DW_FORM_ref4) */ + .uleb128 0x02 /* (DW_AT_location) */ + .uleb128 0x06 /* (DW_FORM_data4) */ + .byte 0x0 + .byte 0x0 + + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + +/* Line table */ + .section .debug_line +.Lline1_begin: + .4byte .Lline1_end - .Lline1_start /* Initial length */ +.Lline1_start: + .2byte 2 /* Version */ + .4byte .Lline1_lines - .Lline1_hdr /* header_length */ +.Lline1_hdr: + .byte 1 /* Minimum insn length */ + .byte 1 /* default_is_stmt */ + .byte 1 /* line_base */ + .byte 1 /* line_range */ + .byte 0x10 /* opcode_base */ + + /* Standard lengths */ + .byte 0 + .byte 1 + .byte 1 + .byte 1 + .byte 1 + .byte 0 + .byte 0 + .byte 0 + .byte 1 + .byte 0 + .byte 0 + .byte 1 + .byte 0 + .byte 0 + .byte 0 + + /* Include directories */ + .byte 0 + + /* File names */ + .ascii "main.c\0" + .uleb128 0 + .uleb128 0 + .uleb128 0 + + .ascii "other.c\0" + .uleb128 0 + .uleb128 0 + .uleb128 0 + + .byte 0 + +.Lline1_lines: + .byte 0 /* DW_LNE_set_address */ + .uleb128 5 + .byte 2 + .4byte func_start + .byte 3 /* DW_LNS_advance_line */ + .sleb128 4 /* ... to 5 */ + .byte 1 /* DW_LNS_copy */ + + .byte 0 /* DW_LNE_set_address */ + .uleb128 5 + .byte 2 + .4byte func0 + .byte 4 /* DW_LNS_set_file */ + .uleb128 2 + .byte 3 /* DW_LNS_advance_line */ + .sleb128 -4 /* ... to 1 */ + .byte 1 /* DW_LNS_copy */ + + .byte 0 /* DW_LNE_set_address */ + .uleb128 5 + .byte 2 + .4byte func1 + .byte 4 /* DW_LNS_set_file */ + .uleb128 1 + .byte 3 /* DW_LNS_advance_line */ + .sleb128 8 /* ... to 9 */ + .byte 1 /* DW_LNS_copy */ + + .byte 0 /* DW_LNE_set_address */ + .uleb128 5 + .byte 2 + .4byte func2 + .byte 4 /* DW_LNS_set_file */ + .uleb128 2 + .byte 3 /* DW_LNS_advance_line */ + .sleb128 -8 /* ... to 1 */ + .byte 1 /* DW_LNS_copy */ + + .byte 0 /* DW_LNE_set_address */ + .uleb128 5 + .byte 2 + .4byte func3 + .byte 4 /* DW_LNS_set_file */ + .uleb128 1 + .byte 3 /* DW_LNS_advance_line */ + .sleb128 8 /* ... to 9 */ + .byte 1 /* DW_LNS_copy */ + + .byte 0 /* DW_LNE_set_address */ + .uleb128 5 + .byte 2 + .4byte func_end + +/* Equivalent copy but renamed s/func/fund/. */ + + .byte 0 /* DW_LNE_set_address */ + .uleb128 5 + .byte 2 + .4byte fund_start + .byte 3 /* DW_LNS_advance_line */ + .sleb128 -4 /* ... to 5 */ + .byte 1 /* DW_LNS_copy */ + + .byte 0 /* DW_LNE_set_address */ + .uleb128 5 + .byte 2 + .4byte fund0 + .byte 4 /* DW_LNS_set_file */ + .uleb128 2 + .byte 3 /* DW_LNS_advance_line */ + .sleb128 -4 /* ... to 1 */ + .byte 1 /* DW_LNS_copy */ + + .byte 0 /* DW_LNE_set_address */ + .uleb128 5 + .byte 2 + .4byte fund1 + .byte 4 /* DW_LNS_set_file */ + .uleb128 1 + .byte 3 /* DW_LNS_advance_line */ + .sleb128 8 /* ... to 9 */ + .byte 1 /* DW_LNS_copy */ + + .byte 0 /* DW_LNE_set_address */ + .uleb128 5 + .byte 2 + .4byte fund2 + .byte 4 /* DW_LNS_set_file */ + .uleb128 2 + .byte 3 /* DW_LNS_advance_line */ + .sleb128 -8 /* ... to 1 */ + .byte 1 /* DW_LNS_copy */ + + .byte 0 /* DW_LNE_set_address */ + .uleb128 5 + .byte 2 + .4byte fund3 + .byte 4 /* DW_LNS_set_file */ + .uleb128 1 + .byte 3 /* DW_LNS_advance_line */ + .sleb128 8 /* ... to 9 */ + .byte 1 /* DW_LNS_copy */ + + .byte 0 /* DW_LNE_set_address */ + .uleb128 5 + .byte 2 + .4byte fund_end + +/* Line numbering end. */ + + .byte 0 /* DW_LNE_end_of_sequence */ + .uleb128 1 + .byte 1 + +.Lline1_end: diff --git a/gdb/testsuite/gdb.dwarf2/dw2-skip-prologue.c b/gdb/testsuite/gdb.dwarf2/dw2-skip-prologue.c new file mode 100644 index 00000000000..fe814f2d8c2 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/dw2-skip-prologue.c @@ -0,0 +1,58 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2011 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +static volatile int v; + +asm ("func_start: .globl func_start\n"); +static int +func (void) +{ + v++; +asm ("func0: .globl func0\n"); + v++; +asm ("func1: .globl func1\n"); + v++; +asm ("func2: .globl func2\n"); + v++; +asm ("func3: .globl func3\n"); + return v; +} +asm ("func_end: .globl func_end\n"); + +/* Equivalent copy but renamed s/func/fund/. */ + +asm ("fund_start: .globl fund_start\n"); +static int +fund (void) +{ + v++; +asm ("fund0: .globl fund0\n"); + v++; +asm ("fund1: .globl fund1\n"); + v++; +asm ("fund2: .globl fund2\n"); + v++; +asm ("fund3: .globl fund3\n"); + return v; +} +asm ("fund_end: .globl fund_end\n"); + +int +main (void) +{ + return func () + fund (); +} diff --git a/gdb/testsuite/gdb.dwarf2/dw2-skip-prologue.exp b/gdb/testsuite/gdb.dwarf2/dw2-skip-prologue.exp new file mode 100644 index 00000000000..a1b0fb9fb51 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/dw2-skip-prologue.exp @@ -0,0 +1,74 @@ +# Copyright 2011 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +load_lib dwarf.exp + +# Test multiple location breakpoints vs. prologue analysis on -O2 -g code. +# when the first statement of a function is an inlined function GDB could +# crash. Map of this testcase: +# +# File name Line number Starting address +# main.c 5 func_start +# other.c 1 func0 +# `inlined' called at main.c line 8 +# main.c 9 func1 +# func1 = Breakpoint location 1 +# other.c 1 func2 +# `inlined2' called at main.c line 11 +# main.c 9 func3 +# func3 = Breakpoint location 2 +# `otherinline' called at main.c line 9 +# end of main func_end + +# This test can only be run on targets which support DWARF-2 and use gas. +if {![dwarf2_support]} { + return 0 +} + +set testfile "dw2-skip-prologue" +set executable ${testfile} +set binfile ${objdir}/${subdir}/${executable} + +if {[build_executable ${testfile}.exp ${executable} "${testfile}.c ${testfile}.S" {additional_flags=-DINLINED}] == -1} { + return -1 +} + +# We need those symbols global to access them from the .S file. +set test "strip stub symbols" +set objcopy_program [transform objcopy] +set result [catch "exec $objcopy_program \ + -N func0 -N func1 -N func2 -N func3 -N func_start -N func_end \ + -N fund0 -N fund1 -N fund2 -N fund3 -N fund -N fund_start \ + ${binfile}" output] +verbose "result is $result" +verbose "output is $output" +if {$result != 0} { + fail $test + return +} +pass $test + +clean_restart $executable + +if ![runto_main] { + return -1 +} + +gdb_breakpoint "func" +gdb_continue_to_breakpoint "func" + +# Sanity check GDB has really found 2 locations +gdb_test {info break $bpnum} "\r\n2\\.1\[ \t\]\[^\n\]*\r\n2\\.2\[ \t\]\[^\n\]*" "2 locations found" + +gdb_test "p v" " = 0" "no statement got executed" -- 2.30.2