Subject: Re: Stabs and discarded functions (was Re: Old bug with 'gdb/dbxread.c' and screwed up MIPS symbolic debugging...)

From: Keith Owens <[email-masked]>
Date: Thu, 01 Nov 2001 23:43:10 +1100

On Wed, 31 Oct 2001 17:47:49 -0500, 
Daniel Jacobowitz <[email-masked]> wrote:
>Now, there's two things wrong here.  One of them is the bad value.  I
>think that I've already seen this problem, and that it has something to
>do with the way stabs are and used to be emitted.  packet_exit is
>presumably in the .text.exit section, which is presumably the problem. 
>Before linking, the stab looked like:
>
>2971   FUN    0      1870   0000000000000000 159366 packet_exit:f(0,20)
>
>and had a relocation:
>0000000000008b58 R_MIPS_32         .text.exit
>unless I miss my guess.
>
>So it looks like binutils did not relocate the stabs for .text.exit properly.
>
>Why?  It's pretty simple; there was nothing to relocate it to.  From the
>kernel's linker script:
>
>  /* Sections to be discarded */
>  /DISCARD/ :
>  {
>        *(.text.exit)
>        *(.data.exit)
>        *(.exitcall.exit)
>  }
>
>So instead of the subtle error we get in objfiles containing multiple
>sections, which we'll still need to deal with for the kernel for
>.text.init, we have a completely bogus result.
>
>We need to discard the stabs records for discarded symbols.

The problem is worse than stabs.  If a function is marked __exit _and_
some code in another section refers to that function then :-

* ld resolves the reference as offset xxx from the start of section
  .text.exit which is expected to get a decent start address.
* Section .text.exit is discarded, giving it a zero start address.
* The function call ends up as a branch to _address_ xxx.

This is a silent bug on many architectures, it only bites when the
__exit function is called, usually on a rarely tested error path.  On
architectures that use PC relative branches (such as IA64), the linker
may not be able to fit a PC relative branch from the high kernel
address to the low (and incorrect) xxx address into an instruction so
it gets an error during link.  Section .data.exit is even worse, most
references to data are via full word pointers and the bug is silent
again.

ld should probably discard sections and all symbols in those sections
before resolving external references.

---

From: "Steven J. Hill" <[email-masked]>
Date: Thu, 01 Nov 2001 11:14:35 -0600

Daniel Jacobowitz wrote:

[snip]

> We need to discard the stabs records for discarded symbols.  Of course,
> we're just reading the psymtab in when we get here.  We don't have
> symbols yet.  We could do this by a second pass after reading, instead
> of the hack with textlow, but that's gross.
> 
> This makes it impossible to debug at least MIPS kernels with stabs and
> gdb, so I very much want to fix it.  I'm not sure how this works on
> x86, but I'd guess it had to do with differences in relocation types.
> Anyone have an example handy?
> 
> Meanwhile, Steven, as a quick hack - try removing the /DISCARD/ bit
> from your linker script and relinking.  What happens?  Does everything
> else seem to work?
> 
Success! Yes, leaving those sections in allows for the debugger to work
properly. Here is output from a fresh gdb checked out of cvs this morning:

   GNU gdb 2001-11-01-cvs
   Copyright 2001 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=i686-pc-linux-gnu
--target=mips-linux-elf"...
   (gdb) target remote /dev/ttyS1
   Remote debugging using /dev/ttyS1
   0x80012c88 in breakinst () at gdb-stub.c:907
   907             __asm__ __volatile__("
   (gdb) bt
   #0  0x80012c88 in breakinst () at gdb-stub.c:907
   #1  0x8020aabc in brcm_irq_setup () at irq.c:421
   #2  0x8020aaf0 in init_IRQ () at irq.c:434
   #3  0x801fc83c in start_kernel () at init/main.c:524
   #4  0x801fd6f8 in init_arch (argc=160, argv=0xb3000000, envp=0x2, 
       prom_vec=0xbf) at setup.c:425
   (gdb) c
   Continuing.

   Program received signal SIGTRAP, Trace/breakpoint trap.
   0x80012c88 in breakinst () at gdb-stub.c:907
   907             __asm__ __volatile__("
   (gdb) bt
   #0  0x80012c88 in breakinst () at gdb-stub.c:907
   #1  0x8001a554 in sys_create_module (name_user=0x10001dc8 "brcmdrv", 
       size=713264) at module.c:305
   (gdb) c
   Continuing.

So, it would seem according to you and Keith, we have a linker bug that
is specific to MIPS and other architectures that do not use PC relative
branches that needs to be resolved?

I also tried a fresh checkout of the insight debugger from cvs this
morning and it works great too. Thanks for the interim solution.  I
would like to be copied on remaining discussions including the design
of the fix/patch. Thank you everyone.

-Steve

-- 
 Steven J. Hill - Embedded SW Engineer

---

From: Daniel Jacobowitz <[email-masked]>
Date: Thu, 1 Nov 2001 11:53:43 -0500

>    0x80012c88 in breakinst () at gdb-stub.c:907

... I wonder why you get a second SIGTRAP.  Never happens to me.  Quirk
of your hardware?

> branches that needs to be resolved?

No, I think that what Keith was saying described a worse side effect of
the removed sections.  I've no idea why this doesn't manifest on other
platforms.

So can we work around this in GDB, or can we get the .stabs removed? 
Does ld edit the .stabs?  I'll enquire over on that list.

-- 
Daniel Jacobowitz                           Carnegie Mellon University
MontaVista Software                         Debian GNU/Linux Developer

---

From: "Steven J. Hill" <[email-masked]>
Date: Thu, 01 Nov 2001 11:59:05 -0600

> ... I wonder why you get a second SIGTRAP.  Never happens to me.  Quirk
My bad. I have breakpoint instructions set inside 'kernel/module.c' so that
I can single step through module insertions. I should have added a 'bt'
output in gdb so you could see that. Everything is working great.

-Steve