public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* Obtaining current address for .stabs
@ 2002-03-03 18:52 John Levon
  2002-03-04 12:11 ` Daniel Jacobowitz
  0 siblings, 1 reply; 7+ messages in thread
From: John Levon @ 2002-03-03 18:52 UTC (permalink / raw)
  To: binutils


I need to manually code some .stabs data via inline asm with gcc.

root linux 174 uname -a
Linux nastic 2.4.17rmap9smp #6 SMP Sat Mar 2 17:52:39 GMT 2002 i686
unknown
root linux 175 as --version
GNU assembler 2.10.90


My original code looked like this :

#define __stabs_text_lock_asm(l)               \
       ".section .text.lock,\"ax\"\n"          \
       ".stabs \"" __FILE__ "\",100,0,0,.\n"   \
       ".stabs " "\"text_lock_" #l             \
       " at " __FILE__                         \
       " line " __STRINGIFY(__LINE__)          \
       ":F(0,20)\",36,0,0,. \n"                \
       ".previous\n"

Now this is inserted before linux kernel code that generates actual
code in the .text.lock section.

This works to a degree, but the value for the second .stabs are wrong :

(objdump -g vmlinux and comments)

semaphore.c:
<undefined> text_lock_&semaphore_lock at semaphore.c line 64 ()
{ /* 0xc01f7c00 */ actually c01f7bb0 80 (+20, 8 + 12)
} /* 0xc01f7c0c */
semaphore.c:
<undefined> text_lock_&semaphore_lock at semaphore.c line 82 ()
{ /* 0xc01f7c18 */ actually c01f7bc0 88 (+8)
} /* 0xc01f7c24 */
semaphore.c:
<undefined> text_lock_&semaphore_lock at semaphore.c line 98 ()
{ /* 0xc01f7c30 */ actually c01f7bd0 96 (+8)
} /* 0xc01f7c3c */

given the differences, it seems that the .stabs data (which ends up in
.stab and .stabstr) is advancing the location counter, even though it
ends up automagically in a different section. For example it looks like
12 is added on for every file (100) entry, and 8 for every normal
function (36) entry.

Obviously this means the generated offset values are incorrect. Has
somebody a suggestion for this problem ? I have tried :

        ".section .text.lock,\"ax\"\n"          \
        ".set __text_lock_address, .\n"         \
        ".section .stabs.temp,\"a\"\n"          \
        ".stabs \"" __FILE__ "\""               \
        ",100,0,0,0\n"                          \
        ".stabs " "\"text_lock_" #l             \
        " at " __FILE__                         \
        " line " __STRINGIFY(__LINE__)          \
        ":F(0,0)\",36,0,0,__text_lock_address \n"       \
        ".previous\n"                           \
        ".previous\n"

But this asserts gas, and it's not clear it will work anyway.

Any ideas much appreciated.

regards
john


-- 
I am a complete moron for forgetting about endianness. May I be
forever marked as such.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Obtaining current address for .stabs
  2002-03-03 18:52 Obtaining current address for .stabs John Levon
@ 2002-03-04 12:11 ` Daniel Jacobowitz
  2002-03-04 12:54   ` John Levon
  0 siblings, 1 reply; 7+ messages in thread
From: Daniel Jacobowitz @ 2002-03-04 12:11 UTC (permalink / raw)
  To: John Levon; +Cc: binutils

On Mon, Mar 04, 2002 at 02:52:02AM +0000, John Levon wrote:
> 
> I need to manually code some .stabs data via inline asm with gcc.

Why?  Why, God, why?

Stabs does not have any support for multiple sections.  Anything
working is a bit of luck.  Use DWARF-2 and address ranges (which you
are not going to be able to do in inline assembly.).

> root linux 174 uname -a
> Linux nastic 2.4.17rmap9smp #6 SMP Sat Mar 2 17:52:39 GMT 2002 i686
> unknown
> root linux 175 as --version
> GNU assembler 2.10.90
> 
> 
> My original code looked like this :
> 
> #define __stabs_text_lock_asm(l)               \
>        ".section .text.lock,\"ax\"\n"          \
>        ".stabs \"" __FILE__ "\",100,0,0,.\n"   \
>        ".stabs " "\"text_lock_" #l             \
>        " at " __FILE__                         \
>        " line " __STRINGIFY(__LINE__)          \
>        ":F(0,20)\",36,0,0,. \n"                \
>        ".previous\n"
> 
> Now this is inserted before linux kernel code that generates actual
> code in the .text.lock section.

You're being very complicated here.  Why mess with sections?  .stabs do
not generate code; put them interspersed with .text.  Have them
reference a symbol declared in .text.lock in the following code.  What
happens then?

You may need an empty (ending) N_FUN stab if you don't want the linker
to mangle you later.

> given the differences, it seems that the .stabs data (which ends up in
> .stab and .stabstr) is advancing the location counter, even though it
> ends up automagically in a different section. For example it looks like
> 12 is added on for every file (100) entry, and 8 for every normal
> function (36) entry.

Conclusion here is almost certainly wrong.

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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Obtaining current address for .stabs
  2002-03-04 12:11 ` Daniel Jacobowitz
@ 2002-03-04 12:54   ` John Levon
  2002-03-04 13:16     ` Daniel Jacobowitz
  0 siblings, 1 reply; 7+ messages in thread
From: John Levon @ 2002-03-04 12:54 UTC (permalink / raw)
  To: binutils

On Mon, Mar 04, 2002 at 03:11:24PM -0500, Daniel Jacobowitz wrote:

> > I need to manually code some .stabs data via inline asm with gcc.
> 
> Why?  Why, God, why?

To generate values I can look up later.

> Stabs does not have any support for multiple sections.  Anything
> working is a bit of luck.  Use DWARF-2 and address ranges (which you
> are not going to be able to do in inline assembly.).

ok, so that's no good ...

> > #define __stabs_text_lock_asm(l)               \
> >        ".section .text.lock,\"ax\"\n"          \
> >        ".stabs \"" __FILE__ "\",100,0,0,.\n"   \
> >        ".stabs " "\"text_lock_" #l             \
> >        " at " __FILE__                         \
> >        " line " __STRINGIFY(__LINE__)          \
> >        ":F(0,20)\",36,0,0,. \n"                \
> >        ".previous\n"
> > 
> > Now this is inserted before linux kernel code that generates actual
> > code in the .text.lock section.
> 
> You're being very complicated here.  Why mess with sections?  .stabs do
> not generate code; put them interspersed with .text.  Have them
> reference a symbol declared in .text.lock in the following code.  What
> happens then?

That would work perfectly (and in fact 2.4.18 does something similar).
The problem with that is that it's impossible to generate valid symbol
names that are unique, which is why I turned to stabs.

The 2.4.18 approach via .ifndef that you suggest here means that some
.text.lock code does not have a symbol range for it, which means
profiling tools will wrongly attribute samples in that range to the
/previous/ symbol in .text.lock. This is obviously not ideal, since the
wrong attributions depend on the order things are linked into the final
vmlinux.

Basically I want to have useful data for example "(&lock) at
some_file.c line 89" for each little piece of code that gets added to
.text.lock (although since kernel 2.4.18 it ends up in subsection 1 of
.text anyway).

This is essentially a debugging tool, it doesn't have to be cleanly done
(although I would prefer it :)

> You may need an empty (ending) N_FUN stab if you don't want the linker
> to mangle you later.

This actually ends up working i.e. the kernel links and runs just fine.

> > given the differences, it seems that the .stabs data (which ends up in
> > .stab and .stabstr) is advancing the location counter, even though it
> > ends up automagically in a different section. For example it looks like
> > 12 is added on for every file (100) entry, and 8 for every normal
> > function (36) entry.
> 
> Conclusion here is almost certainly wrong.

OK, thanks. I thought that didn't make much sense. So where is the value
for "." in the .stabs entry coming from ? There is a strict correlation
between a change in which file vs. another entry in the same file (I
assumed we see the +20 offset only once per file since the 100 .stabs
entries are identical and get merged, yes ?)

I accept what I am doing is pretty much a perversion of the feature.
However I would be grateful if you can suggest a way to get this
working, or point me towards another alternative.

thanks,
john

-- 
I am a complete moron for forgetting about endianness. May I be
forever marked as such.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Obtaining current address for .stabs
  2002-03-04 12:54   ` John Levon
@ 2002-03-04 13:16     ` Daniel Jacobowitz
  2002-03-04 13:55       ` John Levon
  0 siblings, 1 reply; 7+ messages in thread
From: Daniel Jacobowitz @ 2002-03-04 13:16 UTC (permalink / raw)
  To: John Levon; +Cc: binutils

On Mon, Mar 04, 2002 at 08:54:32PM +0000, John Levon wrote:
> On Mon, Mar 04, 2002 at 03:11:24PM -0500, Daniel Jacobowitz wrote:
> 
> > > I need to manually code some .stabs data via inline asm with gcc.
> > 
> > Why?  Why, God, why?
> 
> To generate values I can look up later.

What are you doing that particularly needs stabs here?  Are you trying
to get backtraces on deadlock or some such?  Otherwise a table in some
other format might be much simpler.

I know lots of people (and lots of compilers, including gcc 3.1 on all
Linux targets!) that do not use stabs.  This will not work for them.

> > Stabs does not have any support for multiple sections.  Anything
> > working is a bit of luck.  Use DWARF-2 and address ranges (which you
> > are not going to be able to do in inline assembly.).
> 
> ok, so that's no good ...
> 
> > > #define __stabs_text_lock_asm(l)               \
> > >        ".section .text.lock,\"ax\"\n"          \
> > >        ".stabs \"" __FILE__ "\",100,0,0,.\n"   \
> > >        ".stabs " "\"text_lock_" #l             \
> > >        " at " __FILE__                         \
> > >        " line " __STRINGIFY(__LINE__)          \
> > >        ":F(0,20)\",36,0,0,. \n"                \
> > >        ".previous\n"
> > > 
> > > Now this is inserted before linux kernel code that generates actual
> > > code in the .text.lock section.
> > 
> > You're being very complicated here.  Why mess with sections?  .stabs do
> > not generate code; put them interspersed with .text.  Have them
> > reference a symbol declared in .text.lock in the following code.  What
> > happens then?
> 
> That would work perfectly (and in fact 2.4.18 does something similar).
> The problem with that is that it's impossible to generate valid symbol
> names that are unique, which is why I turned to stabs.

Is it really?  If the symbol is local to the file and depends on
__FUNCTION__ and __LINE__... well, no, inlining would mess that up. 
Hmm.

> The 2.4.18 approach via .ifndef that you suggest here means that some

I have no idea what you're talking about, so obviously I didn't suggest
such a thing.

> .text.lock code does not have a symbol range for it, which means
> profiling tools will wrongly attribute samples in that range to the
> /previous/ symbol in .text.lock. This is obviously not ideal, since the
> wrong attributions depend on the order things are linked into the final
> vmlinux.
> 
> Basically I want to have useful data for example "(&lock) at
> some_file.c line 89" for each little piece of code that gets added to
> .text.lock (although since kernel 2.4.18 it ends up in subsection 1 of
> .text anyway).
> 
> This is essentially a debugging tool, it doesn't have to be cleanly done
> (although I would prefer it :)

Using .set ought to give you the information you need; you might want
to investigate the failure.  I think what you suggested was roughly
like this:
	.section ".text.lock"
	.set a = .
	.previous

	.stabs "foo lock:F=(0,20)", 36, 0, 6, a

	blah

	.section ".text.lock"
	.set b = .
	.previous

	.stabs "", 36, 0, 0, b - a
> 
> > You may need an empty (ending) N_FUN stab if you don't want the linker
> > to mangle you later.
> 
> This actually ends up working i.e. the kernel links and runs just fine.

You're using an older linker.  I don't know how old, but your assert is
a hundred or so lines off from where it is in CVS.  Not having the
N_FUN stab would only bite you with a fairly current binutils.

> > > given the differences, it seems that the .stabs data (which ends up in
> > > .stab and .stabstr) is advancing the location counter, even though it
> > > ends up automagically in a different section. For example it looks like
> > > 12 is added on for every file (100) entry, and 8 for every normal
> > > function (36) entry.
> > 
> > Conclusion here is almost certainly wrong.
> 
> OK, thanks. I thought that didn't make much sense. So where is the value
> for "." in the .stabs entry coming from ? There is a strict correlation
> between a change in which file vs. another entry in the same file (I
> assumed we see the +20 offset only once per file since the 100 .stabs
> entries are identical and get merged, yes ?)
> 
> I accept what I am doing is pretty much a perversion of the feature.
> However I would be grateful if you can suggest a way to get this
> working, or point me towards another alternative.

I can't really say where it's coming from to get the value you see
(though I did not look too closely at your example, sorry).  '.' is the
current point in the current section, generally...

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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Obtaining current address for .stabs
  2002-03-04 13:16     ` Daniel Jacobowitz
@ 2002-03-04 13:55       ` John Levon
  2002-03-04 21:09         ` Daniel Jacobowitz
  0 siblings, 1 reply; 7+ messages in thread
From: John Levon @ 2002-03-04 13:55 UTC (permalink / raw)
  To: binutils

On Mon, Mar 04, 2002 at 04:16:20PM -0500, Daniel Jacobowitz wrote:

> What are you doing that particularly needs stabs here?  Are you trying
> to get backtraces on deadlock or some such?  Otherwise a table in some
> other format might be much simpler.

It is so that profile samples can be accurately attributed back to the
original (for example) spin_lock(&lock) call that caused the contention
i.e. a particular source line.

this is currently possible by hand by dumping the profile output of
.text.lock and using objdump --disassemble -j .text.lock, and figuring
it out backwards.

But this is a chore, and is what I'm trying to avoid. I can't
/radically/ re-work what the kernel does because I'll need to maintain
the patch, and I want it to be usable on actual production systems.

> I know lots of people (and lots of compilers, including gcc 3.1 on all
> Linux targets!) that do not use stabs.  This will not work for them.

I'm pretty new to stabs, as you can tell - why does the gcc version
affect what I output as inline asm ? Does it somehow strip any stabs
directives ? Or is it that the toolchain as a whole will not create
.stab and .stabstr ?

(I suppose I will have to look up what gcc3.1 uses for debug info ;)

> > That would work perfectly (and in fact 2.4.18 does something similar).
> > The problem with that is that it's impossible to generate valid symbol
> > names that are unique, which is why I turned to stabs.
> 
> Is it really?  If the symbol is local to the file and depends on
> __FUNCTION__ and __LINE__... well, no, inlining would mess that up. 

Yes, __FILE__,__LINE__ has a similar problem. Something like
__ORIGINAL__FUNCTION__ for gcc would be perfect, but I'm not going to
ask for that ;)

> > The 2.4.18 approach via .ifndef that you suggest here means that some
> 
> I have no idea what you're talking about, so obviously I didn't suggest
> such a thing.

2.4.18 generates something like :

	.ifndef __text_lock_semaphore
	__text_lock_semaphore:
		cmpb ...

for each point. So really I meant to say it's similar to what you
suggest - sorry.

> Using .set ought to give you the information you need; you might want
> to investigate the failure.  I think what you suggested was roughly
> like this:
> 	.section ".text.lock"
>	...

Yes, I will try it in the form you suggest - thanks.

> You're using an older linker.  I don't know how old, but your assert is
> a hundred or so lines off from where it is in CVS.  Not having the
> N_FUN stab would only bite you with a fairly current binutils.

I see.

You've been most helpful

thanks
john

-- 
I am a complete moron for forgetting about endianness. May I be
forever marked as such.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Obtaining current address for .stabs
  2002-03-04 13:55       ` John Levon
@ 2002-03-04 21:09         ` Daniel Jacobowitz
  2002-03-05  9:05           ` John Levon
  0 siblings, 1 reply; 7+ messages in thread
From: Daniel Jacobowitz @ 2002-03-04 21:09 UTC (permalink / raw)
  To: John Levon; +Cc: binutils

On Mon, Mar 04, 2002 at 09:55:42PM +0000, John Levon wrote:
> On Mon, Mar 04, 2002 at 04:16:20PM -0500, Daniel Jacobowitz wrote:
> 
> > What are you doing that particularly needs stabs here?  Are you trying
> > to get backtraces on deadlock or some such?  Otherwise a table in some
> > other format might be much simpler.
> 
> It is so that profile samples can be accurately attributed back to the
> original (for example) spin_lock(&lock) call that caused the contention
> i.e. a particular source line.
> 
> this is currently possible by hand by dumping the profile output of
> .text.lock and using objdump --disassemble -j .text.lock, and figuring
> it out backwards.
> 
> But this is a chore, and is what I'm trying to avoid. I can't
> /radically/ re-work what the kernel does because I'll need to maintain
> the patch, and I want it to be usable on actual production systems.

No need to do it this way at all.  I can give you a simpler solution, I
think.  And this even fixes your problems with stabs: Use local labels.

        .stabs  "a:F(0,20)",36,0,0,3f
        .section ".text.locks"
3:
        nop
        .previous

That works correctly, as best I can see.

An easier thing to do may be:
        .text
        nop
        nop
        nop
        .section ".text.lock"
3:
        nop
        .previous

        .section "lock.address.table"
        .long 3b
	.long __LINE__
	.pointer-to-__FILE__-string

(I think the BUG() mechanism now provides a unique pointer to a
__FILE__ somewhere...)

Both of these do in fact work :)  I believe all Linux platforms have
forward/backward local labels.

> > I know lots of people (and lots of compilers, including gcc 3.1 on all
> > Linux targets!) that do not use stabs.  This will not work for them.
> 
> I'm pretty new to stabs, as you can tell - why does the gcc version
> affect what I output as inline asm ? Does it somehow strip any stabs
> directives ? Or is it that the toolchain as a whole will not create
> .stab and .stabstr ?
> 
> (I suppose I will have to look up what gcc3.1 uses for debug info ;)

DWARF-2.  Stabs is a crufty, underdocumented, hard-to-parse format. 
DWARF-2 is well defined, and lets us actually express the sorts of
things it is useful to express.

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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Obtaining current address for .stabs
  2002-03-04 21:09         ` Daniel Jacobowitz
@ 2002-03-05  9:05           ` John Levon
  0 siblings, 0 replies; 7+ messages in thread
From: John Levon @ 2002-03-05  9:05 UTC (permalink / raw)
  To: binutils

On Tue, Mar 05, 2002 at 12:08:55AM -0500, Daniel Jacobowitz wrote:

> No need to do it this way at all.  I can give you a simpler solution, I
> think.  And this even fixes your problems with stabs: Use local labels.

This is exactly what I ended up doing, don't know why I thought of it
before :)

And it looks like it's working fine :

...
4884 hits (7.65109502772817%): &zone->lock in page_alloc.c:183
5741 hits (8.99363975310963%): &zone->lock in page_alloc.c:104
6196 hits (9.70642604254786%): &kernel_flag in readdir.c:26
12645 hits (19.8091925932888%): &dcache_lock in dcache.c:712

> DWARF-2.  Stabs is a crufty, underdocumented, hard-to-parse format. 

I have the spec, I shall go read :)

Thanks very much for your help Daniel.

regards
john
-- 
I am a complete moron for forgetting about endianness. May I be
forever marked as such.

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2002-03-05 17:05 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-03-03 18:52 Obtaining current address for .stabs John Levon
2002-03-04 12:11 ` Daniel Jacobowitz
2002-03-04 12:54   ` John Levon
2002-03-04 13:16     ` Daniel Jacobowitz
2002-03-04 13:55       ` John Levon
2002-03-04 21:09         ` Daniel Jacobowitz
2002-03-05  9:05           ` John Levon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).