Re: [PATCH] solib-svr4: Avoid unwanted shlib internal BPs When debugging Linux kernel or u-boot

Pedro Alves
2012-06-01T18:19:53Z

On 06/01/2012 06:45 PM, Jan Kratochvil wrote:

> On Fri, 01 Jun 2012 19:37:22 +0200, Pedro Alves wrote:
>> > Yeah, that's a really contrived example. You're relying on stopping at main,
>> > not when the DSO is really loaded (_dl_debug_state) to set the breakpoint.
>> > I can see _start not existing, with the entry point named something else,
>> > but if you strip your static binary to miss _dl_debug_state, you won't get
>> > main either. (and then static binaries that dlopen aren't something you'd
>> > want to do normally.)
> I do not have to strip the binary to not have _dl_debug_state, there are many
> libc implementations out there and I guess they are not all compatible with
> the "_dl_debug_state" naming.

The fix for those would be to either list the name in GDB, or fix the
loaded to use the same name as GDB already knows. I think the fallback must
be for something else.

> I guess this is also the reason why GDB knows
> so many names for it:
> "r_debug_state",
> "_r_debug_state",
> "_dl_debug_state",
> "rtld_db_dlactivity",
> "__dl_rtld_db_dlactivity",
> "_rtld_debug_state",

> And the goal of this non-ld.so breakpoint is that most of programs loads

> libraries only during its init, before main, therefore a breakpoint at "main"
> should catch them all.

Looking a bit more, I don't think that's the original motivation.
Instead, it looks more like the intent was to get to a point after the
interpreter has mapped in the program, and therefore it is safe to install
breakpoints in the main program. See solib-sunos.c (and remember
that solib.c originally supported both svr4 and sunos):

For SunOS executables, this first instruction is typically the
one at "_start", or a similar text label, regardless of whether
the executable is statically or dynamically linked. The runtime
startup code takes care of dynamically linking in any shared
libraries, once gdb allows the inferior to continue.

So even for static binaries, you still need to place a breakpoint at
_start and run to it, in order to see the main program mapped in.
And since programs might choose a different entry point name,
"main" is chosen as fallback.

Looking even further back, to gdb 4.6, we see:

#else /* SVR4_SHARED_LIBS */

#ifdef BKPT_AT_MAIN

struct minimal_symbol *msymbol;

msymbol = lookup_minimal_symbol ("main", symfile_objfile);
if ((msymbol != NULL) && (msymbol -> address != 0))
{
breakpoint_addr = msymbol -> address;
}
else
{
return (0);
}

if (target_insert_breakpoint (breakpoint_addr, shadow_contents) != 0)
{
return (0);
}

#else /* !BKPT_AT_MAIN */

struct symtab_and_line sal;

/* Read the debugger interface structure directly. */

read_memory (debug_base, (char *) &debug_copy, sizeof (debug_copy));

/* Set breakpoint at the debugger interface stub routine that will
be called just prior to each mapping change and again after the
mapping change is complete. Set up the (nonexistent) handler to
deal with hitting these breakpoints. (FIXME). */

warning ("'%s': line %d: missing SVR4 support code", __FILE__, __LINE__);

#endif /* BKPT_AT_MAIN */

So at that point (1992), SVR4 support was quite infant, and BKPT_AT_MAIN,
is mutually exclusive with the other method, and looks quite like an
easy fallback used because nothing else better had been written yet.

Over the years, all the macros disappeared, and got converted into
runtime fallbacks, and we ended up with what we have.

>
> OTOH as I said current GDB will place the breakpoint to _start first and it
> will miss those libraries anyway. So it is not a regression.

Right. So you're okay with the patch as is, right?

> Also nowadays some 3rd party runtime probably more adapts to GDB than vice
> verse.

Certainly.

--
Pedro Alves