* RFC on how to implement something between solib-irix and procfs
@ 2004-07-04 19:25 Joel Brobecker
2004-07-04 19:28 ` Joel Brobecker
2004-07-05 2:11 ` Joel Brobecker
0 siblings, 2 replies; 3+ messages in thread
From: Joel Brobecker @ 2004-07-04 19:25 UTC (permalink / raw)
To: gdb-patches
Hello,
One of our customers noticed that breakpoints inserted in functions
called from a shared library -init code were inneffective (the "-init
code" is the some special code in the shared library that is executed
by the loader before it runs the program).
Here is what happens at the moment:
- GDB sets up a procfs trap on exec system calls, and then fork.
The child GDB then does an exec, which causes it to stop on that trap.
- The parent GDB then sets up a breakpoint at the program entry point,
and runs until it is reached. Only then does it load the symbols
for all used shared libraries, and insert the shared libs breakpoints.
Unfortunately, this is already too late, as by this time, the code has
already been executed by the loader. Here is the sequence of events as
documented in the DSO(5) man page:
> What Happens at Runtime?
> The runtime events are as follows:
>
> 1. exec(2) loads the main program and then loads one of the following
> interpreters as specified in the main program:
>
> * /usr/lib/libc.so.1 is loaded for programs compiled with the -32
> compiler option.
>
> * /usr/lib32/libc.so.1 is loaded for programs compiled with the
> -n32 compiler option.
>
> * /usr/lib64/libc.so.1 is loaded for programs compiled with the -64
> compiler option.
>
> 2. The interpreter loads rld(5), the runtime linking loader, which
> finishes the exec(2) operation. Starting with the main program's
> liblist, rld(5) loads each DSO on the list that is not marked to be
> delay-loaded. rld(5) reads that object's liblist and repeats the
> operation until all DSOs have been loaded, in a breadth-first
> manner. The breadth first loading process, which ignores objects
> marked to be delay-loaded, results in defining a sequence of
> objects.
>
> 3. rld(5) allocates storage for COMMON block symbols and fixes up
> symbolic references in each loaded object. This is necessary
> because the location at which the object will be loaded is not
> known until runtime. To look up a given symbol in the process of
> fixing up symbolic references, rld(5) examines each object's
> dynamic symbol table. If rld(5) finds a strong symbol that
> satisfies the reference (that is, it has the name of the given
> symbol and is an external definition) it stops with that symbol.
> If it does not find a strong definition with that name, then the
> first weak symbol found is accepted as the definition.
>
> 4. Each object's -init code is executed. This is code specified as an
> argument to the -init option on the ld(1) command. For information
> on -init code, see ld(1).
>
> 5. Control transfers to __start in the main program
Thanks to David Anderson of SGI, I have been told how to have a more
proper startup sequence. The idea relies on the fact that the runtime
loader (rld) calls a dummy internal-to-rld function __dbx_link() once
the DSOs have been mapped in memory, but before the -init code has been
executed.
The trick is therefore to break on that function instead of breaking
of at the program entry point. However, this is not that easy, as:
- rld hasn't been loaded yet at the time when the inferior stops on
the exec-exit event. So we can't insert the breakpoint just yet.
- Which rld has been used depends on a number of factors, so we have
to find which one in order to find the address of __dbx_link().
So, first of all, we need to find a way of waiting until rld has been
loaded. For that, we need to setup another system-call-exit trap on
syssgi() this time. And keep waiting until we find rld. Finding rld
is done by iterating over each TEXT memory regions, getting its
associated fd, and using that fd to scan the symbol table (ELF) until
we find "__dbx_link".
My question is: Where should I put the code: I need to do some procfs
operations from solib-irix. I was thinking of having all the code doing
the procfs stuff inside procfs, and call that code from solib-irix.c
until I get the __dbx_lin() address. But at the same, it seems to me
that solib-irix.c is a target-dependent file, while procfs.c is
host-dependent. So it is not impossible that a cross-debugger be built,
making my procfs operations unavoidable (assuming I can link, which is
not guarantied either).
How do you think I should solve this issue?
Thanks,
--
Joel
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: RFC on how to implement something between solib-irix and procfs
2004-07-04 19:25 RFC on how to implement something between solib-irix and procfs Joel Brobecker
@ 2004-07-04 19:28 ` Joel Brobecker
2004-07-05 2:11 ` Joel Brobecker
1 sibling, 0 replies; 3+ messages in thread
From: Joel Brobecker @ 2004-07-04 19:28 UTC (permalink / raw)
To: gdb-patches
Sigh, a couple of corrections:
> My question is: Where should I put the code: I need to do some procfs
> operations from solib-irix. I was thinking of having all the code doing
> the procfs stuff inside procfs, and call that code from solib-irix.c
procfs.c
> until I get the __dbx_lin() address. But at the same, it seems to me
> that solib-irix.c is a target-dependent file, while procfs.c is
> host-dependent. So it is not impossible that a cross-debugger be built,
> making my procfs operations unavoidable (assuming I can link, which is
unavailable
> not guarantied either).
--
Joel
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: RFC on how to implement something between solib-irix and procfs
2004-07-04 19:25 RFC on how to implement something between solib-irix and procfs Joel Brobecker
2004-07-04 19:28 ` Joel Brobecker
@ 2004-07-05 2:11 ` Joel Brobecker
1 sibling, 0 replies; 3+ messages in thread
From: Joel Brobecker @ 2004-07-05 2:11 UTC (permalink / raw)
To: gdb-patches
> My question is: Where should I put the code: I need to do some procfs
> operations from solib-irix. I was thinking of having all the code doing
> the procfs stuff inside procfs.c, and call that code from solib-irix.c
> until I get the __dbx_lin() address. But at the same, it seems to me
> that solib-irix.c is a target-dependent file, while procfs.c is
> host-dependent. So it is not impossible that a cross-debugger be built,
> making my procfs operations unavailable (assuming I can link, which is
> not guarantied either).
I think I found an approach that should work (untested):
1. Add some code in procfs_init_inferior some code that will add
syssgi() syscall exit notification (#ifdef SYS_syssgi).
The idea is that, when irix_solib_create_inferior_hook() does the
target_resume(), the SYS_syssgi exit notification have already been
setup automatically iff appropriate (ie iff procfs is the target).
So when this routines does the target_resume, either:
+ We don't use procfs, and we'll just hit our entry point breakpoint.
Oh well, we're just in the same situation as we have always been.
Nothing's changed, so we do as we have done in the past.
+ Or, we use procfs, in which case the inferior will stop on
the first syssgi() call exit event before our entry point.
We will now suppose that we use procfs. So after we have resumed
the inferior, it stopped on the first SYS_syssgi exit event.
2. I will add some code in procfs_wait() to detect such events, and
do the following:
+ Search the text regions for __dbx_link.
+ If found, then: - Insert a breakpoint there
- Remove SYS_syssgi() exit notifications.
+ resume the target and start over (goto wait_again).
The intent is to put the procfs_wait() routine into a wait until
we can find the routine we're looking for. As soon as this is done,
then insert the breakpoint, and continue. This is all transparent
to solib-irix.c.
3. Add some code again in procfs_wait() to detect when we reach
the breakpoint that we just inserted (by detecting breakpoint
events occurring at the address where the brekapoint was inserted).
Remove the breakpoint before returning from the function.
At this point, the control eventually returns to
irix_solib_create_inferior_hook(), which knows we just stopped on a
breakpoint. Up to now, it checks that we landed where it inserted
its own breakpoint (at the entry point), but this is no longer a
valid assertion, as we may have landed in __dbx_link() instead.
4. So I'll remove the check in solib-irix.c:disable_break().
After that, irix_solib_create_inferior_hook() is just free to load
the symbols of all shared libraries as usual, and continue as before.
The last bit that's left to do is to answer the following question:
What if the inferior does *not* use shared libraries. If you follow
the algorithm above, you'll find that GDB will never detect __dbx_link
and therefore will never remove the SYS_syssgi exit notification. Each
time the inferior makes a call to syssgi(), we'll end up stopping the
inferior, checking all the text memory regions, and then restarting the
inferior.
To avoid this, I will modify procfs_create_inferior() to remove
the SYS_syssgi exit notification after the call to fork_inferior.
Sounds OK?
--
Joel
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2004-07-05 2:11 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-07-04 19:25 RFC on how to implement something between solib-irix and procfs Joel Brobecker
2004-07-04 19:28 ` Joel Brobecker
2004-07-05 2:11 ` Joel Brobecker
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox