From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22593 invoked by alias); 29 Jan 2004 02:59:09 -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 22543 invoked from network); 29 Jan 2004 02:59:03 -0000 Received: from unknown (HELO gateway.sf.frob.com) (64.81.54.130) by sources.redhat.com with SMTP; 29 Jan 2004 02:59:03 -0000 Received: from magilla.sf.frob.com (magilla.sf.frob.com [198.49.250.228]) by gateway.sf.frob.com (Postfix) with ESMTP id B3BDA357B; Wed, 28 Jan 2004 18:59:02 -0800 (PST) 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 i0T2x2Oi001154; Wed, 28 Jan 2004 18:59:02 -0800 Received: (from roland@localhost) by magilla.sf.frob.com (8.12.9/8.12.9/Submit) id i0T2x1c6001143; Wed, 28 Jan 2004 18:59:01 -0800 Date: Thu, 29 Jan 2004 02:59:00 -0000 Message-Id: <200401290259.i0T2x1c6001143@magilla.sf.frob.com> From: Roland McGrath To: gdb-patches@sources.redhat.com Subject: [PATCH] auxv support X-Windows: simplicity made complex. X-SW-Source: 2004-01/txt/msg00732.txt.bz2 Ok, I think this is looking pretty polished now. I've tested it on Linux and Solaris. On both systems I tested the live process case, the core file case, and gcore. I did not test a multithreaded Solaris program, so that trivial part of the code path has not actually been exercised. This adds the underlying support we talked about before, implemented basically the same as my earlier patch. It also adds the `info auxv' command as Andrew proposed, but with slightly nicer output. The function for reading /proc/PID/auxv, and some of the other code previously duplicated between the procfs and linux implementations, is now shared code in auxv.c. There is also a utility function there that is what's needed for finding a single known tag's value, as some hook will do to check for AT_SYSINFO_EHDR. I would like to add remote protocol and gdbserver support as well, but someone knowledgeable about gdbserver should ping me. Solaris example output: (gdb) i aux 2008 AT_SUN_PLATFORM Platform name string 0xffbfffe1 "SUNW,Ultra-60" 2014 AT_SUN_EXECNAME Canonicalized file name given to execve 0xffbfffef "/usr/bin/cat" 3 AT_PHDR Program headers for program 0x10034 4 AT_PHENT Size of program header entry 32 5 AT_PHNUM Number of program headers 6 9 AT_ENTRY Entry point of program 0x10b3c 2016 AT_SUN_LDDATA Dynamic linker's data segment address 0x7fbf6000 7 AT_BASE Base address of interpreter 0x7fbc0000 8 AT_FLAGS Flags 0x300 6 AT_PAGESZ System page size 8192 2000 AT_SUN_UID Effective user ID 3520 2001 AT_SUN_RUID Real user ID 3520 2002 AT_SUN_GID Effective group ID 3520 2003 AT_SUN_RGID Real group ID 3520 2009 AT_SUN_HWCAP Machine-dependent CPU capability hints 0x7 0 AT_NULL End of vector 0x0 0 AT_NULL End of vector 0x0 0 AT_NULL End of vector 0x0 0 AT_NULL End of vector 0x0 (gdb) Linux example output: (gdb) i aux 32 AT_SYSINFO Special system info/entry points 0xffffe400 33 AT_SYSINFO_EHDR System-supplied DSO's ELF header 0xffffe000 16 AT_HWCAP Machine-dependent CPU capability hints 0x383fbff 6 AT_PAGESZ System page size 4096 17 AT_CLKTCK Frequency of times() 100 3 AT_PHDR Program headers for program 0x8048034 4 AT_PHENT Size of program header entry 32 5 AT_PHNUM Number of program headers 6 7 AT_BASE Base address of interpreter 0x40000000 8 AT_FLAGS Flags 0x0 9 AT_ENTRY Entry point of program 0x8048ae0 11 AT_UID Real user ID 5281 12 AT_EUID Effective user ID 5281 13 AT_GID Real group ID 5281 14 AT_EGID Effective group ID 5281 23 AT_SECURE Boolean, was exec setuid-like? 0 15 AT_PLATFORM String identifying platform 0xbffffb20 "i686" 0 AT_NULL End of vector 0x0 (gdb) Not shown in either is the output for an unknown value, which there aren't any since I've added all known values. But it would look like this: 99 ??? 0x12345678 Approved? Thanks, Roland 2004-01-28 Roland McGrath * sol-thread.c (sol_thread_xfer_partial): New function. (init_sol_thread_ops): Use that for to_xfer_partial hook. (init_sol_core_ops): Likewise. * procfs.c (procfs_xfer_partial): New function. (init_procfs_ops): Use that for procfs_ops.to_xfer_partial. * Makefile.in (procfs.o): Add $(auxv_h) dep. * config/nm-linux.h (NATIVE_XFER_AUXV): New macro, uses auxv.c's procfs_xfer_auxv function. * procfs.c (procfs_make_note_section): If we can read TARGET_OBJECT_AUXV data, add an NT_AUXV note containing it. * linux-proc.c (linux_make_note_section): Likewise. * auxv.h: New file. * auxv.c: New file. * Makefile.in (auxv_h): New variable. (COMMON_OBS): Add auxv.o here. (auxv.o): New target. * corelow.c (core_xfer_partial): New function. (init_core_ops): Use it for core_ops.to_xfer_partial. * target.h (enum target_object): Add TARGET_OBJECT_AUXV. * inftarg.c (child_xfer_partial): Support it using NATIVE_XFER_AUXV macro if that is defined. Index: auxv.c =================================================================== RCS file: auxv.c diff -N auxv.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ auxv.c 29 Jan 2004 02:48:03 -0000 @@ -0,0 +1,301 @@ +/* Auxiliary vector support for GDB, the GNU debugger. + + Copyright 2004 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 "target.h" +#include "gdbtypes.h" +#include "command.h" +#include "inferior.h" +#include "valprint.h" +#include "gdb_assert.h" + +#include "auxv.h" +#include "elf/common.h" + +#include +#include + + +/* This function is called like a to_xfer_partial hook, + but must be called with TARGET_OBJECT_AUXV. + It handles access via /proc/PID/auxv, which is the common method. + This function is appropriate for doing: + #define NATIVE_XFER_AUXV procfs_xfer_auxv + for a native target that uses inftarg.c's child_xfer_partial hook. */ + +LONGEST +procfs_xfer_auxv (struct target_ops *ops, + int /* enum target_object */ object, + const char *annex, + void *readbuf, + const void *writebuf, + ULONGEST offset, + LONGEST len) +{ + char *pathname; + int fd; + LONGEST n; + + gdb_assert (object == TARGET_OBJECT_AUXV); + gdb_assert (readbuf || writebuf); + + pathname = xstrprintf ("/proc/%d/auxv", PIDGET (inferior_ptid)); + fd = open (pathname, writebuf != NULL ? O_WRONLY : O_RDONLY); + xfree (pathname); + if (fd < 0) + return -1; + + if (offset != (ULONGEST) 0 + && lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset) + n = -1; + else if (readbuf != NULL) + n = read (fd, readbuf, len); + else + n = write (fd, writebuf, len); + + (void) close (fd); + + return n; +} + +/* Read all the auxv data into a contiguous xmalloc'd buffer, + stored in *DATA. Return the size in bytes of this data. + If zero, there is no data and *DATA is null. + if < 0, there was an error and *DATA is null. */ +LONGEST +target_auxv_read (struct target_ops *ops, char **data) +{ + size_t auxv_alloc = 512, auxv_pos = 0; + char *auxv = xmalloc (auxv_alloc); + int n; + + while (1) + { + n = target_read_partial (ops, TARGET_OBJECT_AUXV, + NULL, &auxv[auxv_pos], 0, + auxv_alloc - auxv_pos); + if (n <= 0) + break; + auxv_pos += n; + if (auxv_pos < auxv_alloc) /* Read all there was. */ + break; + gdb_assert (auxv_pos == auxv_alloc); + auxv_alloc *= 2; + auxv = xrealloc (auxv, auxv_alloc); + } + + if (auxv_pos == 0) + { + xfree (auxv); + *data = NULL; + return n; + } + + *data = auxv; + return auxv_pos; +} + +/* Read one auxv entry from *READPTR, not reading locations >= ENDPTR. + Return 0 if *READPTR is already at the end of the buffer. + Return -1 if there is insufficient buffer for a whole entry. + Return 1 if an entry was read into *TYPEP and *VALP. */ +int +target_auxv_parse (struct target_ops *ops, char **readptr, char *endptr, + CORE_ADDR *typep, CORE_ADDR *valp) +{ + const int sizeof_auxv_field = TYPE_LENGTH (builtin_type_void_data_ptr); + char *ptr = *readptr; + + if (endptr == ptr) + return 0; + + if (endptr - ptr < sizeof_auxv_field * 2) + return -1; + + *typep = extract_unsigned_integer (ptr, sizeof_auxv_field); + ptr += sizeof_auxv_field; + *valp = extract_unsigned_integer (ptr, sizeof_auxv_field); + ptr += sizeof_auxv_field; + + *readptr = ptr; + return 1; +} + +/* Extract the auxiliary vector entry with a_type matching MATCH. + Return zero if no such entry was found, or -1 if there was + an error getting the information. On success, return 1 after + storing the entry's value field in *VALP. */ +int +target_auxv_search (struct target_ops *ops, CORE_ADDR match, CORE_ADDR *valp) +{ + CORE_ADDR type, val; + char *data; + int n = target_auxv_read (ops, &data); + char *ptr = data; + int ents = 0; + + if (n <= 0) + return n; + + while (1) + switch (target_auxv_parse (ops, &ptr, data + n, &type, &val)) + { + case 1: /* Here's an entry, check it. */ + if (type == match) + { + xfree (data); + *valp = val; + return 1; + } + break; + case 0: /* End of the vector. */ + xfree (data); + return 0; + default: /* Bogosity. */ + xfree (data); + return -1; + } + + /*NOTREACHED*/ +} + + +/* Print the contents of the target's AUXV on the specified file. */ +int +fprint_target_auxv (struct ui_file *file, struct target_ops *ops) +{ + CORE_ADDR type, val; + char *data; + int len = target_auxv_read (ops, &data); + char *ptr = data; + int ents = 0; + + if (len <= 0) + return len; + + while (target_auxv_parse (ops, &ptr, data + len, &type, &val) > 0) + { + extern int addressprint; + const char *name = "???"; + const char *description = ""; + enum { dec, hex, str } flavor = hex; + + switch (type) + { +#define TAG(tag, text, kind) \ + case tag: name = #tag; description = text; flavor = kind; break + TAG (AT_NULL, "End of vector", hex); + TAG (AT_IGNORE, "Entry should be ignored", hex); + TAG (AT_EXECFD, "File descriptor of program", dec); + TAG (AT_PHDR, "Program headers for program", hex); + TAG (AT_PHENT, "Size of program header entry", dec); + TAG (AT_PHNUM, "Number of program headers", dec); + TAG (AT_PAGESZ, "System page size", dec); + TAG (AT_BASE, "Base address of interpreter", hex); + TAG (AT_FLAGS, "Flags", hex); + TAG (AT_ENTRY, "Entry point of program", hex); + TAG (AT_NOTELF, "Program is not ELF", dec); + TAG (AT_UID, "Real user ID", dec); + TAG (AT_EUID, "Effective user ID", dec); + TAG (AT_GID, "Real group ID", dec); + TAG (AT_EGID, "Effective group ID", dec); + TAG (AT_CLKTCK, "Frequency of times()", dec); + TAG (AT_PLATFORM, "String identifying platform", str); + TAG (AT_HWCAP, "Machine-dependent CPU capability hints", hex); + TAG (AT_FPUCW, "Used FPU control word", dec); + TAG (AT_DCACHEBSIZE, "Data cache block size", dec); + TAG (AT_ICACHEBSIZE, "Instruction cache block size", dec); + TAG (AT_UCACHEBSIZE, "Unified cache block size", dec); + TAG (AT_IGNOREPPC, "Entry should be ignored", dec); + TAG (AT_SYSINFO, "Special system info/entry points", hex); + TAG (AT_SYSINFO_EHDR, "System-supplied DSO's ELF header", hex); + TAG (AT_SECURE, "Boolean, was exec setuid-like?", dec); + TAG (AT_SUN_UID, "Effective user ID", dec); + TAG (AT_SUN_RUID, "Real user ID", dec); + TAG (AT_SUN_GID, "Effective group ID", dec); + TAG (AT_SUN_RGID, "Real group ID", dec); + TAG (AT_SUN_LDELF, "Dynamic linker's ELF header", hex); + TAG (AT_SUN_LDSHDR, "Dynamic linker's section headers", hex); + TAG (AT_SUN_LDNAME, "String giving name of dynamic linker", str); + TAG (AT_SUN_LPAGESZ, "Large pagesize", dec); + TAG (AT_SUN_PLATFORM, "Platform name string", str); + TAG (AT_SUN_HWCAP, "Machine-dependent CPU capability hints", hex); + TAG (AT_SUN_IFLUSH, "Should flush icache?", dec); + TAG (AT_SUN_CPU, "CPU name string", str); + TAG (AT_SUN_EMUL_ENTRY, "COFF entry point address", hex); + TAG (AT_SUN_EMUL_EXECFD, "COFF executable file descriptor", dec); + TAG (AT_SUN_EXECNAME, + "Canonicalized file name given to execve", str); + TAG (AT_SUN_MMU, "String for name of MMU module", str); + TAG (AT_SUN_LDDATA, "Dynamic linker's data segment address", hex); + } + + fprintf_filtered (file, "%-4s %-20s %-30s ", + paddr_d (type), name, description); + switch (flavor) + { + case dec: + fprintf_filtered (file, "%s\n", paddr_d (val)); + break; + case hex: + fprintf_filtered (file, "0x%s\n", paddr_nz (val)); + break; + case str: + if (addressprint) + fprintf_filtered (file, "0x%s", paddr_nz (val)); + val_print_string (val, -1, 1, file); + fprintf_filtered (file, "\n"); + break; + } + ++ents; + } + + xfree (data); + + return ents; +} + +static void +info_auxv_command (char *cmd, int from_tty) +{ + + if (! target_has_stack) + error ("The program has no auxiliary information now."); + else + { + int ents = fprint_target_auxv (gdb_stdout, ¤t_target); + if (ents < 0) + error ("No auxilary vector found, or failed reading it."); + else if (ents == 0) + error ("Auxilary vector is empty."); + } +} + + +extern initialize_file_ftype _initialize_auxv; /* -Wmissing-prototypes; */ + +void +_initialize_auxv (void) +{ + add_info ("auxv", info_auxv_command, + "Display the inferior's auxiliary vector.\n\ +This is information provided by the operating system at program startup."); +} Index: auxv.h =================================================================== RCS file: auxv.h diff -N auxv.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ auxv.h 29 Jan 2004 02:48:03 -0000 @@ -0,0 +1,75 @@ +/* Auxiliary vector support for GDB, the GNU debugger. + + Copyright 2004 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. */ + +#ifndef AUXV_H +#define AUXV_H + +/* See "include/elf/common.h" for the definition of valid AT_* values. */ + + +/* Avoid miscellaneous includes in this file, so that it can be + included by nm-*.h for the procfs_xfer_auxv decl if that is + used in NATIVE_XFER_AUXV. */ +struct target_ops; /* Forward declaration. */ + + +/* Read all the auxv data into a contiguous xmalloc'd buffer, + stored in *DATA. Return the size in bytes of this data. + If zero, there is no data and *DATA is null. + if < 0, there was an error and *DATA is null. */ +extern LONGEST target_auxv_read (struct target_ops *ops, char **data); + +/* Read one auxv entry from *READPTR, not reading locations >= ENDPTR. + Return 0 if *READPTR is already at the end of the buffer. + Return -1 if there is insufficient buffer for a whole entry. + Return 1 if an entry was read into *TYPEP and *VALP. */ +extern int target_auxv_parse (struct target_ops *ops, + char **readptr, char *endptr, + CORE_ADDR *typep, CORE_ADDR *valp); + +/* Extract the auxiliary vector entry with a_type matching MATCH. + Return zero if no such entry was found, or -1 if there was + an error getting the information. On success, return 1 after + storing the entry's value field in *VALP. */ +extern int target_auxv_search (struct target_ops *ops, + CORE_ADDR match, CORE_ADDR *valp); + +/* Print the contents of the target's AUXV on the specified file. */ +extern int fprint_target_auxv (struct ui_file *file, struct target_ops *ops); + + +/* This function is called like a to_xfer_partial hook, + but must be called with TARGET_OBJECT_AUXV. + It handles access via /proc/PID/auxv, which is the common method. + This function is appropriate for doing: + #define NATIVE_XFER_AUXV procfs_xfer_auxv + for a native target that uses inftarg.c's child_xfer_partial hook. */ + +extern LONGEST procfs_xfer_auxv (struct target_ops *ops, + int /* enum target_object */ object, + const char *annex, + void *readbuf, + const void *writebuf, + ULONGEST offset, + LONGEST len); + + +#endif Index: sol-thread.c =================================================================== RCS file: /cvs/src/src/gdb/sol-thread.c,v retrieving revision 1.38 diff -b -p -u -r1.38 sol-thread.c --- sol-thread.c 21 Sep 2003 01:26:45 -0000 1.38 +++ sol-thread.c 29 Jan 2004 02:44:52 -0000 @@ -750,6 +750,37 @@ sol_thread_xfer_memory (CORE_ADDR memadd return retval; } +/* Perform partial transfers on OBJECT. See target_read_partial + and target_write_partial for details of each variant. One, and + only one, of readbuf or writebuf must be non-NULL. */ + +static LONGEST +sol_thread_xfer_partial (struct target_ops *ops, enum target_object object, + const char *annex, void *readbuf, + const void *writebuf, ULONGEST offset, LONGEST len) +{ + int retval; + struct cleanup *old_chain; + + old_chain = save_inferior_ptid (); + + if (is_thread (inferior_ptid) || /* A thread */ + !target_thread_alive (inferior_ptid)) /* An lwp, but not alive */ + inferior_ptid = procfs_first_available (); /* Find any live lwp. */ + /* Note: don't need to call switch_to_thread; we're just reading memory. */ + + if (target_has_execution) + retval = procfs_ops.to_xfer_partial (ops, object, annex, + readbuf, writebuf, offset, len); + else + retval = orig_core_ops.to_xfer_partial (ops, object, annex, + readbuf, writebuf, offset, len); + + do_cleanups (old_chain); + + return retval; +} + /* Print status information about what we're accessing. */ static void @@ -1549,6 +1580,7 @@ init_sol_thread_ops (void) sol_thread_ops.to_store_registers = sol_thread_store_registers; sol_thread_ops.to_prepare_to_store = sol_thread_prepare_to_store; sol_thread_ops.to_xfer_memory = sol_thread_xfer_memory; + sol_thread_ops.to_xfer_partial = sol_thread_xfer_partial; sol_thread_ops.to_files_info = sol_thread_files_info; sol_thread_ops.to_insert_breakpoint = memory_insert_breakpoint; sol_thread_ops.to_remove_breakpoint = memory_remove_breakpoint; @@ -1592,6 +1624,7 @@ init_sol_core_ops (void) sol_core_ops.to_detach = sol_core_detach; sol_core_ops.to_fetch_registers = sol_thread_fetch_registers; sol_core_ops.to_xfer_memory = sol_thread_xfer_memory; + sol_core_ops.to_xfer_partial = sol_thread_xfer_partial; sol_core_ops.to_files_info = sol_core_files_info; sol_core_ops.to_insert_breakpoint = ignore; sol_core_ops.to_remove_breakpoint = ignore; Index: procfs.c =================================================================== RCS file: /cvs/src/src/gdb/procfs.c,v retrieving revision 1.50 diff -b -p -u -r1.50 procfs.c --- procfs.c 17 Jan 2004 18:24:15 -0000 1.50 +++ procfs.c 29 Jan 2004 02:44:53 -0000 @@ -45,8 +45,10 @@ Inc., 59 Temple Place - Suite 330, Bosto #include "gdb_wait.h" #include #include +#include #include "gdb_assert.h" #include "inflow.h" +#include "auxv.h" /* * PROCFS.C @@ -127,6 +129,11 @@ static ptid_t procfs_wait (ptid_t, struc static int procfs_xfer_memory (CORE_ADDR, char *, int, int, struct mem_attrib *attrib, struct target_ops *); +static LONGEST procfs_xfer_partial (struct target_ops *ops, + enum target_object object, + const char *annex, + void *readbuf, const void *writebuf, + ULONGEST offset, LONGEST len); static int procfs_thread_alive (ptid_t); @@ -164,6 +171,7 @@ init_procfs_ops (void) procfs_ops.to_prepare_to_store = procfs_prepare_to_store; procfs_ops.to_fetch_registers = procfs_fetch_registers; procfs_ops.to_store_registers = procfs_store_registers; + procfs_ops.to_xfer_partial = procfs_xfer_partial; procfs_ops.to_xfer_memory = procfs_xfer_memory; procfs_ops.to_insert_breakpoint = memory_insert_breakpoint; procfs_ops.to_remove_breakpoint = memory_remove_breakpoint; @@ -4267,6 +4275,40 @@ wait_again: return retval; } +/* Perform a partial transfer to/from the specified object. For + memory transfers, fall back to the old memory xfer functions. */ + +static LONGEST +procfs_xfer_partial (struct target_ops *ops, enum target_object object, + const char *annex, void *readbuf, + const void *writebuf, ULONGEST offset, LONGEST len) +{ + switch (object) + { + case TARGET_OBJECT_MEMORY: + if (readbuf) + return (*ops->to_xfer_memory) (offset, readbuf, len, 0/*write*/, + NULL, ops); + if (writebuf) + return (*ops->to_xfer_memory) (offset, readbuf, len, 1/*write*/, + NULL, ops); + return -1; + +#ifdef NEW_PROC_API + case TARGET_OBJECT_AUXV: + return procfs_xfer_auxv (ops, object, annex, readbuf, writebuf, + offset, len); +#endif + + default: + if (ops->beneath != NULL) + return ops->beneath->to_xfer_partial (ops->beneath, object, annex, + readbuf, writebuf, offset, len); + return -1; + } +} + + /* Transfer LEN bytes between GDB address MYADDR and target address MEMADDR. If DOWRITE is non-zero, transfer them to the target, otherwise transfer them from the target. TARGET is unused. @@ -5849,6 +5891,8 @@ procfs_make_note_section (bfd *obfd, int char *note_data = NULL; char *inf_args; struct procfs_corefile_thread_data thread_args; + char *auxv; + int auxv_len; if (get_exec_file (0)) { @@ -5895,6 +5939,14 @@ procfs_make_note_section (bfd *obfd, int else { note_data = thread_args.note_data; + } + + auxv_len = target_auxv_read (¤t_target, &auxv); + if (auxv_len > 0) + { + note_data = elfcore_write_note (obfd, note_data, note_size, + "CORE", NT_AUXV, auxv, auxv_len); + xfree (auxv); } make_cleanup (xfree, note_data); Index: linux-proc.c =================================================================== RCS file: /cvs/src/src/gdb/linux-proc.c,v retrieving revision 1.20 diff -b -p -u -r1.20 linux-proc.c --- linux-proc.c 1 Oct 2003 20:36:56 -0000 1.20 +++ linux-proc.c 29 Jan 2004 02:44:53 -0000 @@ -271,6 +271,8 @@ linux_make_note_section (bfd *obfd, int char psargs[80] = { '\0' }; char *note_data = NULL; ptid_t current_ptid = inferior_ptid; + char *auxv; + int auxv_len; if (get_exec_file (0)) { @@ -305,6 +307,14 @@ linux_make_note_section (bfd *obfd, int note_data = thread_args.note_data; } + auxv_len = target_auxv_read (¤t_target, &auxv); + if (auxv_len > 0) + { + note_data = elfcore_write_note (obfd, note_data, note_size, + "CORE", NT_AUXV, auxv, auxv_len); + xfree (auxv); + } + make_cleanup (xfree, note_data); return note_data; } Index: Makefile.in =================================================================== RCS file: /cvs/src/src/gdb/Makefile.in,v retrieving revision 1.482 diff -b -p -u -r1.482 Makefile.in --- Makefile.in 25 Jan 2004 11:46:44 -0000 1.482 +++ Makefile.in 29 Jan 2004 02:44:53 -0000 @@ -652,6 +652,7 @@ amd64_nat_h = amd64-nat.h annotate_h = annotate.h $(symtab_h) $(gdbtypes_h) arch_utils_h = arch-utils.h arm_tdep_h = arm-tdep.h +auxv_h = auxv.h ax_gdb_h = ax-gdb.h ax_h = ax.h $(doublest_h) bcache_h = bcache.h @@ -891,6 +892,7 @@ TAGFILES_NO_SRCDIR = $(SFILES) $(HFILES_ TAGFILES_WITH_SRCDIR = $(HFILES_WITH_SRCDIR) COMMON_OBS = version.o \ + auxv.o \ bfd-target.o \ blockframe.o breakpoint.o findvar.o regcache.o \ charset.o disasm.o dummy-frame.o \ @@ -1621,6 +1624,8 @@ arm-tdep.o: arm-tdep.c $(defs_h) $(frame $(frame_unwind_h) $(frame_base_h) $(trad_frame_h) $(arm_tdep_h) \ $(gdb_sim_arm_h) $(elf_bfd_h) $(coff_internal_h) $(elf_arm_h) \ $(gdb_assert_h) $(bfd_in2_h) $(libcoff_h) +auxv.o: $(defs_h) $(target_h) $(gdbtypes_h) $(command_h) $(gdb_assert_h) \ + $(auxv_h) $(elf_common_h) $(valprint_h) $(inferior_h) avr-tdep.o: avr-tdep.c $(defs_h) $(frame_h) $(frame_unwind_h) \ $(frame_base_h) $(trad_frame_h) $(gdbcmd_h) $(gdbcore_h) \ $(inferior_h) $(symfile_h) $(arch_utils_h) $(regcache_h) \ @@ -2180,7 +2187,7 @@ proc-flags.o: proc-flags.c $(defs_h) procfs.o: procfs.c $(defs_h) $(inferior_h) $(target_h) $(gdbcore_h) \ $(elf_bfd_h) $(gdbcmd_h) $(gdbthread_h) $(gdb_wait_h) \ $(gdb_assert_h) $(inflow_h) $(gdb_dirent_h) $(X_OK) $(gdb_stat_h) \ - $(proc_utils_h) $(gregset_h) + $(proc_utils_h) $(gregset_h) $(auxv_h) proc-service.o: proc-service.c $(defs_h) $(gdb_proc_service_h) $(inferior_h) \ $(symtab_h) $(target_h) $(gregset_h) proc-why.o: proc-why.c $(defs_h) $(proc_utils_h) cvs server: I know nothing about auxv.c cvs server: I know nothing about auxv.h Index: corelow.c =================================================================== RCS file: /cvs/src/src/gdb/corelow.c,v retrieving revision 1.33 diff -b -p -u -r1.33 corelow.c --- corelow.c 6 Nov 2003 02:52:27 -0000 1.33 +++ corelow.c 29 Jan 2004 02:44:53 -0000 @@ -515,6 +515,63 @@ core_files_info (struct target_ops *t) print_section_info (t, core_bfd); } +static LONGEST +core_xfer_partial (struct target_ops *ops, enum target_object object, + const char *annex, void *readbuf, + const void *writebuf, ULONGEST offset, LONGEST len) +{ + switch (object) + { + case TARGET_OBJECT_MEMORY: + if (readbuf) + return (*ops->to_xfer_memory) (offset, readbuf, len, 0/*write*/, + NULL, ops); + if (writebuf) + return (*ops->to_xfer_memory) (offset, readbuf, len, 1/*write*/, + NULL, ops); + return -1; + + case TARGET_OBJECT_AUXV: + if (readbuf) + { + /* When the aux vector is stored in core file, BFD + represents this with a fake section called ".auxv". */ + + sec_ptr section; + bfd_size_type size; + char *contents; + + section = bfd_get_section_by_name (core_bfd, ".auxv"); + if (section == NULL) + return -1; + + size = bfd_section_size (core_bfd, section); + if (offset >= size) + return 0; + size -= offset; + if (size > len) + size = len; + if (size > 0 && + ! bfd_get_section_contents (core_bfd, section, readbuf, + (file_ptr) offset, size)) + { + warning ("Couldn't read NT_AUXV note in core file."); + return -1; + } + + return size; + } + return -1; + + default: + if (ops->beneath != NULL) + return ops->beneath->to_xfer_partial (ops->beneath, object, annex, + readbuf, writebuf, offset, len); + return -1; + } +} + + /* If mourn is being called in all the right places, this could be say `gdb internal error' (since generic_mourn calls breakpoint_init_inferior). */ @@ -551,6 +608,7 @@ init_core_ops (void) core_ops.to_attach = find_default_attach; core_ops.to_detach = core_detach; core_ops.to_fetch_registers = get_core_registers; + core_ops.to_xfer_partial = core_xfer_partial; core_ops.to_xfer_memory = xfer_memory; core_ops.to_files_info = core_files_info; core_ops.to_insert_breakpoint = ignore; Index: target.h =================================================================== RCS file: /cvs/src/src/gdb/target.h,v retrieving revision 1.55 diff -b -p -u -r1.55 target.h --- target.h 17 Jan 2004 21:56:12 -0000 1.55 +++ target.h 29 Jan 2004 02:44:53 -0000 @@ -226,8 +226,10 @@ enum target_object TARGET_OBJECT_MEMORY, /* Kernel Unwind Table. See "ia64-tdep.c". */ TARGET_OBJECT_UNWIND_TABLE, - /* Possible future objects: TARGET_OBJECT_FILE, TARGET_OBJECT_PROC, - TARGET_OBJECT_AUXV, ... */ + /* Transfer auxilliary vector. */ + TARGET_OBJECT_AUXV, + + /* Possible future objects: TARGET_OBJECT_FILE, TARGET_OBJECT_PROC, ... */ }; extern LONGEST target_read_partial (struct target_ops *ops, Index: inftarg.c =================================================================== RCS file: /cvs/src/src/gdb/inftarg.c,v retrieving revision 1.21 diff -b -p -u -r1.21 inftarg.c --- inftarg.c 14 Nov 2003 20:49:23 -0000 1.21 +++ inftarg.c 29 Jan 2004 02:44:53 -0000 @@ -578,11 +578,12 @@ child_xfer_partial (struct target_ops *o return NATIVE_XFER_UNWIND_TABLE (ops, object, annex, readbuf, writebuf, offset, len); -#if 0 case TARGET_OBJECT_AUXV: - return native_xfer_auxv (PIDGET (inferior_ptid), readbuf, writebuf, - offset, len); +#ifndef NATIVE_XFER_AUXV +#define NATIVE_XFER_AUXV(OPS,OBJECT,ANNEX,WRITEBUF,READBUF,OFFSET,LEN) (-1) #endif + return NATIVE_XFER_AUXV (ops, object, annex, readbuf, writebuf, + offset, len); default: return -1; Index: config/nm-linux.h =================================================================== RCS file: /cvs/src/src/gdb/config/nm-linux.h,v retrieving revision 1.19 diff -b -p -u -r1.19 nm-linux.h --- config/nm-linux.h 17 Aug 2003 18:22:25 -0000 1.19 +++ config/nm-linux.h 29 Jan 2004 02:44:53 -0000 @@ -77,3 +77,6 @@ extern void lin_thread_get_thread_signal #define CHILD_POST_ATTACH #define CHILD_FOLLOW_FORK #define KILL_INFERIOR + +#define NATIVE_XFER_AUXV procfs_xfer_auxv +#include "auxv.h" /* Declares it. */