From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 29293 invoked by alias); 3 Oct 2003 08:27:59 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 29286 invoked from network); 3 Oct 2003 08:27:56 -0000 Received: from unknown (HELO gateway.sf.frob.com) (64.81.54.130) by sources.redhat.com with SMTP; 3 Oct 2003 08:27:56 -0000 Received: from magilla.sf.frob.com (magilla.sf.frob.com [198.49.250.228]) by gateway.sf.frob.com (Postfix) with ESMTP id 57EAC357B; Fri, 3 Oct 2003 01:27:55 -0700 (PDT) Received: from magilla.sf.frob.com (localhost.localdomain [127.0.0.1]) by magilla.sf.frob.com (8.12.9/8.12.9) with ESMTP id h938RtN2019023; Fri, 3 Oct 2003 01:27:55 -0700 Received: (from roland@localhost) by magilla.sf.frob.com (8.12.9/8.12.9/Submit) id h938RsrS019019; Fri, 3 Oct 2003 01:27:54 -0700 Date: Fri, 03 Oct 2003 08:27:00 -0000 Message-Id: <200310030827.h938RsrS019019@magilla.sf.frob.com> From: Roland McGrath To: gdb-patches@sources.redhat.com Subject: unwind support for Linux 2.6 vsyscall DSO X-Zippy-Says: Yes, Private DOBERMAN!! X-SW-Source: 2003-10/txt/msg00048.txt.bz2 In the past (during this spring and summer) there were some discussions about the need to find unwind info in the vsyscall DSO image implicitly loaded in processes on Linux 2.5/2.6 on some platforms. I honestly don't recall which mailing lists this was on. If people are not clear on the issues, I can try to dig up the various summaries of the details I have posted before. This was tabled for a while when I had other priorities since it didn't turn out to be an issue with any kernel version used by Red Hat production systems. Now Linux 2.6 is getting firmed up, and it's time to revisit this. On Linux 2.6 kernels, backtraces from programs stopped in system calls do not work using current glibc on x86 and AMD64 machines. The same issue exists on IA64 in Linux 2.6, and glibc will before long make use of the feature so that system call backtraces need the same solutions for IA64. My changes to export the auxv information in core dumps and /proc are now making their way into Linux 2.6, and this gives us the tools we need to solve the problem in gdb. The following patches are some kludges I have tried out. They are not fit for inclusion, but demonstrate what needs to be done. I hope they can stimulate some advice on where such code should actually go. This patch relies on the symbol_file_add_from_memory function introduced by the patch I just posted a little earlier. Please review that patch first as context for what I'm doing here. With that patch plus this one, on a Linux 2.6 kernel with the very latest patches you surely don't have quite yet, a backtrace starting in the vsyscall entry point is unwound correctly from a core file and when using attach. Basically what needs to happen is a few places that should implicitly call symbol_file_add_from_memory on the address the kernel supplied with the AT_SYSINFO_EHDR tag on process startup. On examining a core file, the NT_AUXV note contains this info, and BFD makes it available as a ".auxv" fake section. On running or attaching to a live process, the /proc/PID/auxv fake file provided by the target kernel contains the info. The auxv_parse function below does the work of interpreting the auxv block (from a core file's NT_AUXV/.auxv or from /proc/PID/auxv). That little bit of code is about right as it is. The issues are when to call it. Questions for the core file case: 1 Where should this call go in the order of operations? I plopped the check in the middle of core_open because it seemed like it ought to come between the bfd opening and the register diddling that includes some calls about the grokking of the stack frame. I don't know how loading a symfile interacts with that diddling. Would it work to have the symbol_file_add_from_memory done after core_open? 2 Where should this support go in the target/generic code split? This code, and the need for it, is Linux-specific but not machine-specific. Linux 2.6 currently requires it on x86, IA64, and AMD64 (in both native and IA32 emulation versions). The user-level support for the preloaded DSO image is machine-independent in the glibc implementation; no other Linux platform will overload the AT_SYSINFO_EHDR tag value for another purpose. I would like to have this implemented in gdb in a place that doesn't require duplication for the three existing platforms requiring the support, and will cover any other Linux target where kernels start using the same feature. I don't see any obvious place like a common linux-tdep.c; where is the right place? Should it be a different to_core_open hook that wraps the generic one? Or maybe extend struct core_fns? (But core_fns is redefined only in machine-specific files, and it appears inconsistently so--sometimes in *-nat.c and sometimes in *-tdep.c; what's the story?) 3 When and how should I unload the symbols on detaching from the core file? The solib symbols are cleared in core_close from what I can see. Is that the right spot to drop the symfile added from reading NT_AUXV? How do I clear it all out properly? Do I just call free_objfile? Is remove_target_sections required as clear_solib does? Similar questions for the live process case: 4 Where to make the call? The patch below does it in linux-nat.c's child_post_attach. That makes it work for attach, but it is probably the wrong place. I really have no idea where the right place to insert this is for the "run" case. It needs to happen after the break-on-exec, the same time you would first insert breakpoints in the program. Where is the right place to make that happen? Is there one place that's right for both run and attach? 5 Same as #2, in context. linux-nat.c seems like it ought to be the right source file for the /proc parsing, or perhaps linux-proc.c; the auxv_parse function (renamed) should be shared between the core and live handling cases, it belongs in a linux-tdep sort of file logically. 6 Same as #3, in context. I can't figure out where things get cleared out when a process dies or you detach. Do they? I see objfile_purge_solibs is called from run_command. I think that will get the symfile I create. Is that sufficient? Do solibs get cleared on detach/attach? Thanks, Roland Index: corelow.c =================================================================== RCS file: /cvs/src/src/gdb/corelow.c,v retrieving revision 1.30 diff -p -b -u -r1.30 corelow.c --- corelow.c 21 Sep 2003 01:26:44 -0000 1.30 +++ corelow.c 3 Oct 2003 05:39:55 -0000 @@ -252,6 +252,63 @@ add_to_thread_list (bfd *abfd, asection inferior_ptid = pid_to_ptid (thread_id); /* Yes, make it current */ } +#include +#include + +int +auxv_parse (bfd *abfd, char *contents, bfd_size_type size, int from_tty) +{ + bfd_vma sysinfo_ehdr = 0; + + switch (bfd_arch_bits_per_address (abfd)) + { + default: + return 0; + + case 32: + { + Elf32_External_Auxv *av; + for (av = (Elf32_External_Auxv *) contents; + (char *) av < contents + size; + ++av) + { + const bfd_vma type = bfd_get_32 (abfd, av->a_type); + if (type == AT_NULL) + break; + if (type == AT_SYSINFO_EHDR) + { + sysinfo_ehdr = bfd_get_32 (abfd, av->a_val); + break; + } + } + break; + } + case 64: + { + Elf64_External_Auxv *av; + for (av = (Elf64_External_Auxv *) contents; + (char *) av < contents + size; + ++av) + { + const bfd_vma type = bfd_get_64 (abfd, av->a_type); + if (type == AT_NULL) + break; + if (type == AT_SYSINFO_EHDR) + { + sysinfo_ehdr = bfd_get_64 (abfd, av->a_val); + break; + } + } + break; + } + } + + if (sysinfo_ehdr != 0) + (void) symbol_file_add_from_memory (abfd, sysinfo_ehdr, from_tty); + + return 1; +} + /* This routine opens and sets up the core file bfd. */ static void @@ -264,6 +321,7 @@ core_open (char *filename, int from_tty) bfd *temp_bfd; int ontop; int scratch_chan; + asection *section; target_preopen (from_tty); if (!filename) @@ -344,6 +402,22 @@ core_open (char *filename, int from_tty) printf_filtered ("Program terminated with signal %d, %s.\n", siggy, target_signal_to_string (target_signal_from_host (siggy))); + section = bfd_get_section_by_name (core_bfd, ".auxv"); + if (section != NULL) + { + bfd_size_type size; + char *contents; + size = bfd_section_size (core_bfd, section); + contents = alloca (size); + if (! bfd_get_section_contents (core_bfd, section, contents, + (file_ptr) 0, size)) + warning ("Couldn't read NT_AUXV note in core file."); + else + { + auxv_parse (core_bfd, contents, size, from_tty); + } + } + /* Build up thread list from BFD sections. */ init_thread_list (); Index: linux-nat.c =================================================================== RCS file: /cvs/src/src/gdb/linux-nat.c,v retrieving revision 1.5 diff -p -b -u -r1.5 linux-nat.c --- linux-nat.c 17 Aug 2003 20:17:02 -0000 1.5 +++ linux-nat.c 3 Oct 2003 05:39:56 -0000 @@ -24,6 +24,7 @@ #include "gdb_wait.h" #include +#include #include "linux-nat.h" @@ -234,10 +235,30 @@ linux_enable_event_reporting (ptid_t pti ptrace (PTRACE_SETOPTIONS, pid, 0, options); } +static void +linux_add_sysinfo_symbols (int pid) +{ + extern bfd *exec_bfd; /* exec.c */ + char filename[64]; + int fd; + char contents[1024]; + int size; + + sprintf (filename, "/proc/%d/auxv", pid); + fd = open (filename, O_RDONLY); + if (fd < 0) + return; + size = read (fd, contents, sizeof contents); + close (fd); + + auxv_parse (exec_bfd, contents, size, 0); +} + void child_post_attach (int pid) { linux_enable_event_reporting (pid_to_ptid (pid)); + linux_add_sysinfo_symbols (pid); } void