Subject: i386/ELF stabs
To: None <tech-toolchain@netbsd.org>
From: Frank van der Linden <frank@wins.uva.nl>
List: tech-toolchain
Date: 07/07/1999 10:08:44
After the recent switch of the i386 port to ELF, people noticed that
gdb gets linenumbers wrong sometimes. I looked into this, and found
that it gets them wrong when it has to match a symbol -> linenumber,
or, to be more precise, PC -> linenumber.

It turns out that it's not actually gdb's fault (I think). Look at (part of)
the output of objdump --stabs for 2 similar programs. The first one
is NetBSD/sparc ELF, the other one NetBSD/i386 ELF.

sparc:
113    FUN    0      27     000108fc 2346   main:F(0,1)
114    SLINE  0      27     00000000 968
115    SLINE  0      28     00000004 968
116    SLINE  0      29     0000000c 968
117    SLINE  0      30     00000014 968
118    FUN    0      0      0000001c 968

i386:
96     SLINE  0      27     080486e4 1508   
97     SLINE  0      28     080486e7 1508   
98     SLINE  0      29     080486ec 1508   
99     SLINE  0      30     080486f1 1508   
100    FUN    0      27     080486e4 1532   main:F1
101    FUN    0      0      0000000f 1508   

There seem to be 2 problems here:

	* For the i386, the linenumber information lies outside
	  the function information, which can't be correct.
	* The values of the SLINE symbols (which are the matching
	  PCs at which this line is located) are supposed to be
	  relative to the start of the function. This is correct
	  in the sparc binary, but ld(1) has made them absolute
	  already on the i386 port, which is wrong.

Looking at the gdb code, it uses the N_FUN stab to get the
start of the function, and then adds the offset in the N_SLINE
stab to get the PC. So for the i386, this goes wrong in 2 ways:
you have not yet encountered N_FUN when you hit the N_SLINE
stabs, so the offset is wrong, plus the value of N_SLINE is not
relative as it's supposed to be. This actually makes things
go right accidentally for the first function, because the offset
is 0 at that point, and if you add the absolute value in the
N_SLINE stab, you end up at the right address.

Now, the reason I'm posting about this here, is that I'm not really
a bfd/binutils expert (and don't really want to be ;-)), and I'm
hoping that other people can track down what's wrong here. I don't
seem to see any large differences with regard to stabs between
sparc and i386 in the ld(1) sources, so I don't understand where
the problems come from.

Anyone?

- Frank