From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 5175 invoked by alias); 9 May 2009 14:26:31 -0000 Received: (qmail 5137 invoked by uid 22791); 9 May 2009 14:26:28 -0000 X-SWARE-Spam-Status: No, hits=-0.3 required=5.0 tests=AWL,BAYES_00,J_CHICKENPOX_32,J_CHICKENPOX_36,KAM_STOCKGEN,SPF_SOFTFAIL X-Spam-Check-By: sourceware.org Received: from mtaout4.012.net.il (HELO mtaout3.012.net.il) (84.95.2.10) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sat, 09 May 2009 14:26:21 +0000 Received: from conversion-daemon.i_mtaout3.012.net.il by i_mtaout3.012.net.il (HyperSendmail v2004.12) id <0KJD00H00R1B0C00@i_mtaout3.012.net.il> for gdb-patches@sourceware.org; Sat, 09 May 2009 17:26:17 +0300 (IDT) Received: from HOME-C4E4A596F7 ([84.228.73.80]) by i_mtaout3.012.net.il (HyperSendmail v2004.12) with ESMTPA id <0KJD00DMPS3S7XP0@i_mtaout3.012.net.il> for gdb-patches@sourceware.org; Sat, 09 May 2009 17:26:17 +0300 (IDT) Date: Sat, 09 May 2009 14:26:00 -0000 From: Eli Zaretskii Subject: [RFA] Fix "break foo" when `foo's prologue ends before line table To: gdb-patches@sourceware.org Reply-to: Eli Zaretskii Message-id: <83skjebbef.fsf@gnu.org> X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2009-05/txt/msg00186.txt.bz2 With the following test program (tchset.c) #include #include int main (void) { const char *cset = locale_charset (); if (cset) printf ("locale_charset: `%s'\n", cset); else printf ("locale_charset: NULL\n"); return 0; } and the DJGPP build of a recent snapshot, trying to set a breakpoint in `main' makes GDB think `main' has no source line info, if I compile the program with COFF debug info ("gcc -gcoff -o tchset44c.exe tchset.c"). Observe: D:\usr\djgpp\gnu\gdb-68.410\gdb>.\gdb.exe --nx ./tchset44c.exe GNU gdb (GDB) 6.8.50.20090410 Copyright (C) 2009 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "--host=i586-pc-msdosdjgpp --target=djgpp". For bug reporting instructions, please see: ... (gdb) break main Breakpoint 1 at 0x1732 (gdb) With GDB 6.1, it does work: GNU gdb 6.1 Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "--host=i386-pc-msdosdjgpp --target=djgpp"... (gdb) break main Breakpoint 1 at 0x1748: file tchset.c, line 6. The reason is this change: 2006-11-28 Daniel Jacobowitz * symtab.c (find_pc_sect_line): Do not return a line before the start of a symtab. (No, I'm not suggesting to revert that change. I want to show my analysis of this problem and suggest a solution.) Using "maint print symbols", I see this: Symtab for file tchset.c Read from object file d:/usr/djgpp/gnu/gdb-68.410/gdb/./tchset44c.exe (0x43be20) Language: c Line table: line 6 at 0x1748 line 8 at 0x1750 line 9 at 0x1756 line 11 at 0x176b line 13 at 0x177b line 14 at 0x1780 Blockvector: block #000, object at 0x4403fc, 1 syms/buckets in 0x1700..0x1782 int main(); block object 0x440394, 0x172c..0x1782 section .text block #001, object at 0x4403c4 under 0x4403fc, 2 syms/buckets in 0x1700..0x1782 [...] block #002, object at 0x440394 under 0x4403c4, 0 syms/buckets in 0x172c..0x1782, function main Note that the lineinfo table for the program starts at line 6 at PC 0x1748, whereas the function `main' begins at PC 0x172c. When I type "break main", we eventually call find_function_start_sal, which skips the prologue, and then calls find_pc_sect_line to find the sal for the PC after the prologue. But skipping the prologue in this cases gets us to PC 0x1732, which is still outside the lineinfo table. So find_pc_sect_line fails to find a suitable source line, returns a sal without a symtab, and GDB then thinks `main' is a function with no source line information. Here's the disassembly of `main', in case someone thinks that skip_prologue function didn't do a good job (I think it did a reasonable job, but I'm far from being an expert on prologue analysis): Dump of assembler code for function main: 0x0000172c : push %ebp 0x0000172d : mov %esp,%ebp 0x0000172f : sub $0x8,%esp 0x00001732 : and $0xfffffff0,%esp 0x00001735 : mov $0x0,%eax 0x0000173a : add $0xf,%eax 0x0000173d : add $0xf,%eax 0x00001740 : shr $0x4,%eax 0x00001743 : shl $0x4,%eax 0x00001746 : sub %eax,%esp 0x00001748 : call 0x17e0 0x0000174d : mov %eax,0xfffffffc(%ebp) 0x00001750 : cmpl $0x0,0xfffffffc(%ebp) 0x00001754 : je 0x176b 0x00001756 : sub $0x8,%esp 0x00001759 : pushl 0xfffffffc(%ebp) 0x0000175c : push $0x1700 0x00001761 : call 0x3950 0x00001766 : add $0x10,%esp 0x00001769 : jmp 0x177b 0x0000176b : sub $0xc,%esp 0x0000176e : push $0x1716 0x00001773 : call 0x3950 0x00001778 : add $0x10,%esp 0x0000177b : mov $0x0,%eax 0x00001780 : leave 0x00001781 : ret If I compile the same program with -gdwarf-2, the problem does not happen because the lineinfo table now includes one more entry, for line 5 of the file. But I cannot deprecate usage of COFF debug info in DJGPP, because that is the only way to build the DJGPP port of Emacs (the code in Emacs's unexec.c was never updated to handle DWARF-2, and probably never will). My suggestion for solving this is in the patch below. The idea is that we make one more attempt to find the first line of the function's body, using the lineinfo table. We loop over all symtabs for the function's file, looking for an entry in a lineinfo table whose PC is in the range [FUNC_START..FUNC_END] and whose line number is the smallest. FUNC_START and FUNC_END are obtained via a call to find_pc_partial_function. Is this idea reasonable? Is the patch okay to commit? 2009-05-09 Eli Zaretskii * symtab.c (skip_prologue_using_lineinfo): New function. (find_function_start_sal): Use it to get to the first line of function's body that has an entry in the lineinfo table. --- symtab.c~0 2009-04-01 02:21:07.000000000 +0300 +++ symtab.c 2009-05-09 16:40:36.442027000 +0300 @@ -2599,6 +2599,68 @@ return pc; } +/* Given a function start address FUNC_ADDR and SYMTAB, find the first + address for that function that has an entry in any line info table + that comes from any symtab for the same file as SYMTAB. If such an + entry cannot be found, return FUNC_ADDR unaltered. */ +CORE_ADDR +skip_prologue_using_lineinfo (CORE_ADDR func_addr, struct symtab *symtab) +{ + CORE_ADDR func_start, func_end; + struct objfile *objfile; + struct partial_symtab *p; + struct symtab *s; + int best_lineno = 0; + CORE_ADDR best_pc = func_addr; + + /* Get the range for the function's PC values, or give up if we + cannot, for some reason. */ + if (!find_pc_partial_function (func_addr, NULL, &func_start, &func_end)) + return func_addr; + + ALL_PSYMTABS (objfile, p) + { + if (FILENAME_CMP (symtab->filename, p->filename) != 0) + continue; + PSYMTAB_TO_SYMTAB (p); + } + + /* Loop over all symtabs for the function's file, looking for an + entry in a lineinfo table whose PC is in the range + [FUNC_START..FUNC_END] and whose line number is the smallest. */ + ALL_SYMTABS (objfile, s) + { + struct linetable *l; + int ind, i, len; + + if (FILENAME_CMP (symtab->filename, s->filename) != 0) + continue; + l = LINETABLE (s); + if (l == NULL) + continue; + + len = l->nitems; + for (i = 0; i < len; i++) + { + struct linetable_entry *item = &(l->item[i]); + + /* Don't use line numbers of zero, they mark special entries + in the table. See the commentary on symtab.h before the + definition of struct linetable. */ + if (item->line > 0 + && func_start <= item->pc && item->pc <= func_end) + { + if (!best_lineno || item->line < best_lineno) + { + best_lineno = item->line; + best_pc = item->pc; + } + } + } + } + return best_pc; +} + /* Given a function symbol SYM, find the symtab and line for the start of the function. If the argument FUNFIRSTLINE is nonzero, we want the first line @@ -2649,6 +2711,15 @@ sal = find_pc_sect_line (pc, SYMBOL_OBJ_SECTION (sym), 0); } + /* If we still don't have a valid source line, try to find the first + line in the lineinfo table that belongs to the same function. */ + if (funfirstline && sal.symtab == NULL) + { + pc = skip_prologue_using_lineinfo (pc, SYMBOL_SYMTAB (sym)); + /* Recalculate the line number. */ + sal = find_pc_sect_line (pc, SYMBOL_OBJ_SECTION (sym), 0); + } + sal.pc = pc; return sal;