From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 28350 invoked by alias); 4 Apr 2002 22:25:01 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 28340 invoked from network); 4 Apr 2002 22:24:58 -0000 Received: from unknown (HELO nevyn.them.org) (128.2.145.6) by sources.redhat.com with SMTP; 4 Apr 2002 22:24:58 -0000 Received: from drow by nevyn.them.org with local (Exim 3.35 #1 (Debian)) id 16tFf7-0001K1-00; Thu, 04 Apr 2002 17:24:57 -0500 Date: Thu, 04 Apr 2002 14:25:00 -0000 From: Daniel Jacobowitz To: Jim Blandy Cc: gdb-patches@sources.redhat.com Subject: Re: [RFA/stabs] Fix for line table problems (was: Re: [RFC] Gdb line table implementation tweak) Message-ID: <20020404172457.A4233@nevyn.them.org> Mail-Followup-To: Jim Blandy , gdb-patches@sources.redhat.com References: <200203251758.g2PHwbe31730@duracef.shout.net> <3CA2A76E.8090209@cygnus.com> <20020329133508.A12204@nevyn.them.org> <20020329160533.A24451@nevyn.them.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.3.23i X-SW-Source: 2002-04/txt/msg00138.txt.bz2 On Thu, Apr 04, 2002 at 04:51:27PM -0500, Jim Blandy wrote: > > Daniel Jacobowitz writes: > > On Fri, Mar 29, 2002 at 03:59:13PM -0500, Jim Blandy wrote: > > > > > > Daniel Jacobowitz writes: > > > > I think so. Want me to wait for Michael C's report first? > > > > > > If doing so wouldn't delay 5.2 too much, yes. > > > > OK, I will. Could you look over: > > http://sources.redhat.com/ml/gdb-patches/2002-03/msg00415.html > > (the equivalent patch for DWARF-2), if you get a chance? > > So, it's not that the first line number marker is *missing*, it's that > it's *misplaced*. So repositioning the line is sufficient --- we > don't need to make up an extra entry. Is that right? Yes, that's right. It's much easier to add an extra entry - but that causes problems all over GDB. Trust me, I tried it :) > If so, it seems fine, some minor comments: > > Could you move the code that initializes the function range list and > the code that adds a new entry to the function range list into their > own functions? Sure. > Could check_cu_functions complain when it has to back up a line entry? Sure. I've committed this version, thanks! We'll see if we have time to move this one to the branch later. -- Daniel Jacobowitz Carnegie Mellon University MontaVista Software Debian GNU/Linux Developer 2002-04-04 Daniel Jacobowitz * dwarf2read.c (struct function_range): New. (cu_first_fn, cu_last_fn, cu_cached_fn): New. (check_cu_functions): New. (read_file_scope): Initialize global function lists. Call dwarf_decode_line after processing children. (read_func_scope): Add to global function list. (dwarf_decode_lines): Call check_cu_functions everywhere record_line is called. Call record_line with a linenumber of 0 to mark sequence ends. Index: dwarf2read.c =================================================================== RCS file: /cvs/src/src/gdb/dwarf2read.c,v retrieving revision 1.51 diff -u -p -r1.51 dwarf2read.c --- dwarf2read.c 2002/03/21 00:53:44 1.51 +++ dwarf2read.c 2002/04/04 22:23:19 @@ -256,6 +256,16 @@ struct attribute u; }; +struct function_range +{ + const char *name; + CORE_ADDR lowpc, highpc; + int seen_line; + struct function_range *next; +}; + +static struct function_range *cu_first_fn, *cu_last_fn, *cu_cached_fn; + /* Get at parts of an attribute structure */ #define DW_STRING(attr) ((attr)->u.str) @@ -560,6 +570,10 @@ static struct complaint dwarf2_unsupport { "unsupported const value attribute form: '%s'", 0, 0 }; +static struct complaint dwarf2_misplaced_line_number = +{ + "misplaced first line number at 0x%lx for '%s'", 0, 0 +}; /* local function prototypes */ @@ -794,6 +808,10 @@ static struct abbrev_info *dwarf_alloc_a static struct die_info *dwarf_alloc_die (void); +static void initialize_cu_func_list (void); + +static void add_to_cu_func_list (const char *, CORE_ADDR, CORE_ADDR); + /* Try to locate the sections we need for DWARF 2 debugging information and return true if we have enough to do something. */ @@ -1542,6 +1560,12 @@ process_die (struct die_info *die, struc } static void +initialize_cu_func_list (void) +{ + cu_first_fn = cu_last_fn = cu_cached_fn = NULL; +} + +static void read_file_scope (struct die_info *die, struct objfile *objfile, const struct comp_unit_head *cu_header) { @@ -1633,13 +1657,7 @@ read_file_scope (struct die_info *die, s start_symtab (name, comp_dir, lowpc); record_debugformat ("DWARF 2"); - /* Decode line number information if present. */ - attr = dwarf_attr (die, DW_AT_stmt_list); - if (attr) - { - line_offset = DW_UNSND (attr); - dwarf_decode_lines (line_offset, comp_dir, abfd, cu_header); - } + initialize_cu_func_list (); /* Process all dies in compilation unit. */ if (die->has_children) @@ -1651,9 +1669,38 @@ read_file_scope (struct die_info *die, s child_die = sibling_die (child_die); } } + + /* Decode line number information if present. */ + attr = dwarf_attr (die, DW_AT_stmt_list); + if (attr) + { + line_offset = DW_UNSND (attr); + dwarf_decode_lines (line_offset, comp_dir, abfd, cu_header); + } } static void +add_to_cu_func_list (const char *name, CORE_ADDR lowpc, CORE_ADDR highpc) +{ + struct function_range *thisfn; + + thisfn = (struct function_range *) + obstack_alloc (&dwarf2_tmp_obstack, sizeof (struct function_range)); + thisfn->name = name; + thisfn->lowpc = lowpc; + thisfn->highpc = highpc; + thisfn->seen_line = 0; + thisfn->next = NULL; + + if (cu_last_fn == NULL) + cu_first_fn = thisfn; + else + cu_last_fn->next = thisfn; + + cu_last_fn = thisfn; +} + +static void read_func_scope (struct die_info *die, struct objfile *objfile, const struct comp_unit_head *cu_header) { @@ -1674,6 +1721,9 @@ read_func_scope (struct die_info *die, s lowpc += baseaddr; highpc += baseaddr; + /* Record the function range for dwarf_decode_lines. */ + add_to_cu_func_list (name, lowpc, highpc); + if (objfile->ei.entry_point >= lowpc && objfile->ei.entry_point < highpc) { @@ -3908,6 +3958,51 @@ struct directories char **dirs; }; +/* This function exists to work around a bug in certain compilers + (particularly GCC 2.95), in which the first line number marker of a + function does not show up until after the prologue, right before + the second line number marker. This function shifts ADDRESS down + to the beginning of the function if necessary, and is called on + addresses passed to record_line. */ + +static CORE_ADDR +check_cu_functions (CORE_ADDR address) +{ + struct function_range *fn; + + /* Find the function_range containing address. */ + if (!cu_first_fn) + return address; + + if (!cu_cached_fn) + cu_cached_fn = cu_first_fn; + + fn = cu_cached_fn; + while (fn) + if (fn->lowpc <= address && fn->highpc > address) + goto found; + else + fn = fn->next; + + fn = cu_first_fn; + while (fn && fn != cu_cached_fn) + if (fn->lowpc <= address && fn->highpc > address) + goto found; + else + fn = fn->next; + + return address; + + found: + if (fn->seen_line) + return address; + if (address != fn->lowpc) + complain (&dwarf2_misplaced_line_number, + (unsigned long) address, fn->name); + fn->seen_line = 1; + return fn->lowpc; +} + static void dwarf_decode_lines (unsigned int offset, char *comp_dir, bfd *abfd, const struct comp_unit_head *cu_header) @@ -4048,6 +4143,7 @@ dwarf_decode_lines (unsigned int offset, * lh.minimum_instruction_length; line += lh.line_base + (adj_opcode % lh.line_range); /* append row to matrix using current values */ + address = check_cu_functions (address); record_line (current_subfile, line, address); basic_block = 1; } @@ -4061,12 +4157,7 @@ dwarf_decode_lines (unsigned int offset, { case DW_LNE_end_sequence: end_sequence = 1; - /* Don't call record_line here. The end_sequence - instruction provides the address of the first byte - *after* the last line in the sequence; it's not the - address of any real source line. However, the GDB - linetable structure only records the starts of lines, - not the ends. This is a weakness of GDB. */ + record_line (current_subfile, 0, address); break; case DW_LNE_set_address: address = read_address (abfd, line_ptr, cu_header, &bytes_read); @@ -4103,6 +4194,7 @@ dwarf_decode_lines (unsigned int offset, } break; case DW_LNS_copy: + address = check_cu_functions (address); record_line (current_subfile, line, address); basic_block = 0; break;