[RFA] Find and read symbol files after attach (linux)

Michael Snyder
2002-01-08T02:20:17Z

[oops, hit send too soon...]
This change allows GDB to find and read the symbol files (including
all shared libraries) on Linux when you attach to an anonymous PID.
It should work for all Linuxen, but for now I've only added it to the
linux.mh and nm-linux.h files in config/i386. Please feel free to
add it to your targets.

(gdb) attach 29962
Attaching to process 29962
Reading symbols from /builds/native/gdb/testsuite/foo...
done.
Reading symbols from /lib/i686/libc.so.6...done.
Loaded symbols for /lib/i686/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
0x400dc8e1 in __libc_nanosleep () from /lib/i686/libc.so.6
(gdb) backtrace
#0 0x400dc8e1 in __libc_nanosleep () from /lib/i686/libc.so.6
#1 0x400dc761 in __sleep (seconds=1) at ../sysdeps/unix/sysv/linux/sleep.c:85
#2 0x08048482 in main () at foo.c:5
#3 0x4003e177 in __libc_start_main (main=0x8048460 , argc=1,
ubp_av=0xbffff51c, init=0x80482e0 <_init>, fini=0x80484d0 <_fini>,
rtld_fini=0x4000e184 <_dl_fini>, stack_end=0xbffff50c)
at ../sysdeps/generic/libc-start.c:129
(gdb)

2002-01-07 Michael Snyder <msnyder@redhat.com>

* linux-proc.c: New file. Implement proc_iterate_over_mappings
and child_pid_to_exec_file, so that attaching to a pid will
automatically read the process's symbol file and shlibs.
* config/i386/linux.mh: Add linux-proc.o to NATDEPFILES.
* config/i386/nm-linux.h: Define CHILD_PID_TO_EXEC_FILE
and HANDLE_SVR4_EXEC_EMULATORS (FIXME not a good name).

Index: linux-proc.c
===================================================================
RCS file: linux-proc.c
diff -N linux-proc.c
*** /dev/null Tue May 5 13:32:27 1998
--- linux-proc.c Mon Jan 7 16:34:05 2002
***************
*** 0 ****
--- 1,90 ----
+ /* Generate a core file for the inferior process -- Linux version.
+ Copyright 2001 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+ #include "defs.h"
+ #include "inferior.h"
+ #include <sys/param.h> /* for MAXPATHLEN */
+ #include <sys/procfs.h>
+ #include <fcntl.h> /* for O_RDONLY */
+
+ /* Linux version of "proc_iterate_over_mappings". */
+
+ int
+ read_mapping (FILE *mapfile,
+ long long *addr,
+ long long *endaddr,
+ char *permissions,
+ long long *offset,
+ char *device,
+ long long *inode,
+ char *filename)
+ {
+ int ret = fscanf (mapfile, "%llx-%llx %s %llx %s %llx",
+ addr, endaddr, permissions, offset, device, inode);
+
+ if (ret > 0 && ret != EOF && *inode != 0)
+ {
+ ret += fscanf (mapfile, "%s\n", filename);
+ }
+ else
+ {
+ filename[0] = '\0'; /* no filename */
+ fscanf (mapfile, "\n");
+ }
+ return (ret != 0 && ret != EOF);
+ }
+
+ int
+ proc_iterate_over_mappings (int (*func) (int, CORE_ADDR))
+ {
+ long long pid = PIDGET (inferior_ptid);
+ char procfilename[MAXPATHLEN];
+ FILE *mapsfile;
+ long long addr, endaddr, size, offset, inode;
+ char permissions[8], device[8], filename [MAXPATHLEN];
+ int funcret = 0;
+
+ /* Compose the filename for the /proc memory map, and open it. */
+ sprintf (procfilename, "/proc/%lld/maps", pid);
+ if ((mapsfile = fopen (procfilename, "r")) == NULL)
+ error ("Could not open %s\n", procfilename);
+
+ while (read_mapping (mapsfile, &addr, &endaddr, &permissions[0],
+ &offset, &device[0], &inode, &filename[0]))
+ {
+ if (filename[0])
+ {
+ int fd = open (filename, O_RDONLY);
+ if ((funcret = func (fd, (CORE_ADDR) addr)) != 0)
+ break;
+ }
+ }
+ fclose (mapsfile);
+ return funcret;
+ }
+
+ char *
+ child_pid_to_exec_file (int pid)
+ {
+ static char fname[MAXPATHLEN];
+
+ sprintf (fname, "/proc/%d/exe", pid);
+ return fname;
+ }
Index: config/i386/nm-linux.h
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/nm-linux.h,v
retrieving revision 1.15
diff -c -3 -p -r1.15 nm-linux.h
*** nm-linux.h 2001/10/14 20:42:07 1.15
--- nm-linux.h 2002/01/08 00:34:05
*************** extern int cannot_store_register (int re
*** 80,83 ****
--- 80,89 ----
/* Override child_resume in `infptrace.c'. */
#define CHILD_RESUME

+ /* Override child_pid_to_exec_file in 'inftarg.c'. */
+ #define CHILD_PID_TO_EXEC_FILE
+
+ /* Enable handling of shared libraries for a.out executables. */
+ #define HANDLE_SVR4_EXEC_EMULATORS
+
#endif /* nm-linux.h */
Index: config/i386/linux.mh
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/linux.mh,v
retrieving revision 1.8
diff -c -3 -p -r1.8 linux.mh
*** linux.mh 2001/07/31 19:22:57 1.8
--- linux.mh 2002/01/08 00:34:05
*************** XDEPFILES=
*** 6,12 ****
NAT_FILE= nm-linux.h
NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o \
core-aout.o i386-nat.o i386-linux-nat.o i387-nat.o \
! proc-service.o thread-db.o lin-lwp.o

# The dynamically loaded libthread_db needs access to symbols in the
# gdb executable.
--- 6,12 ----
NAT_FILE= nm-linux.h
NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o \
core-aout.o i386-nat.o i386-linux-nat.o i387-nat.o \
! proc-service.o thread-db.o lin-lwp.o linux-proc.o

# The dynamically loaded libthread_db needs access to symbols in the
# gdb executable.