This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
Re: unwind support for Linux 2.6 vsyscall DSO
- From: Roland McGrath <roland at redhat dot com>
- To: Elena Zannoni <ezannoni at redhat dot com>
- Cc: gdb-patches at sources dot redhat dot com
- Date: Mon, 6 Oct 2003 20:33:44 -0700
- Subject: Re: unwind support for Linux 2.6 vsyscall DSO
Here is an alternate version of my patch, omitting the Solaris parts. This
uses an iterator interface as you requested. I didn't add a utility
function but duplicated the code that might be in one. This also works
(writes a good NT_AUXV note), but the core file writing additions are now
rather clunky, and that code has to be duplicated for Solaris (or factored
out). I prefer the first version.
Thanks,
Roland
Index: target.c
===================================================================
RCS file: /cvs/src/src/gdb/target.c,v
retrieving revision 1.55
diff -b -p -u -r1.55 target.c
--- target.c 2 Oct 2003 20:28:30 -0000 1.55
+++ target.c 7 Oct 2003 03:29:27 -0000
@@ -624,6 +624,7 @@ update_current_target (void)
INHERIT (to_async, t);
INHERIT (to_async_mask_value, t);
INHERIT (to_find_memory_regions, t);
+ INHERIT (to_read_aux_vector, t);
INHERIT (to_make_corefile_notes, t);
INHERIT (to_get_thread_local_address, t);
INHERIT (to_magic, t);
@@ -1500,6 +1501,13 @@ static int dummy_find_memory_regions (in
return 0;
}
+/* Error-catcher for target_read_aux_vector */
+static int dummy_read_aux_vector (int (*ignore1) (), void *ignore2)
+{
+ error ("No target.");
+ return 0;
+}
+
/* Error-catcher for target_make_corefile_notes */
static char * dummy_make_corefile_notes (bfd *ignore1, int *ignore2)
{
@@ -1521,6 +1529,7 @@ init_dummy_target (void)
dummy_target.to_pid_to_str = normal_pid_to_str;
dummy_target.to_stratum = dummy_stratum;
dummy_target.to_find_memory_regions = dummy_find_memory_regions;
+ dummy_target.to_read_aux_vector = dummy_read_aux_vector;
dummy_target.to_make_corefile_notes = dummy_make_corefile_notes;
dummy_target.to_magic = OPS_MAGIC;
}
Index: target.h
===================================================================
RCS file: /cvs/src/src/gdb/target.h,v
retrieving revision 1.41
diff -b -p -u -r1.41 target.h
--- target.h 17 Jun 2003 20:28:13 -0000 1.41
+++ target.h 7 Oct 2003 03:29:27 -0000
@@ -322,6 +322,7 @@ struct target_ops
int, int, int,
void *),
void *);
+ int (*to_read_aux_vector) (int (*) (const void *, void *), void *);
char * (*to_make_corefile_notes) (bfd *, int *);
/* Return the thread-local address at OFFSET in the
@@ -939,6 +940,14 @@ extern void (*target_new_objfile_hook) (
(current_target.to_find_memory_regions) (FUNC, DATA)
/*
+ * Function to read target startup auxilliary vector (ELF-specific).
+ * Returns a malloc'd buffer of ELF auxv data, and sets *LENP to its size.
+ */
+
+#define target_read_aux_vector(FUNC, DATA) \
+ (current_target.to_read_aux_vector) (FUNC, DATA)
+
+/*
* Compose corefile .note section.
*/
Index: inftarg.c
===================================================================
RCS file: /cvs/src/src/gdb/inftarg.c,v
retrieving revision 1.18
diff -b -p -u -r1.18 inftarg.c
--- inftarg.c 21 Sep 2003 01:26:45 -0000 1.18
+++ inftarg.c 7 Oct 2003 03:29:27 -0000
@@ -628,6 +628,14 @@ inftarg_set_find_memory_regions (int (*f
child_ops.to_find_memory_regions = func;
}
+/* Take over the 'read_aux_vector' vector from inftarg.c. */
+void
+inftarg_set_read_aux_vector (int (*func) (int (*) (const void *, void *),
+ void *))
+{
+ child_ops.to_read_aux_vector = func;
+}
+
/* Take over the 'make_corefile_notes' vector from inftarg.c. */
extern void
inftarg_set_make_corefile_notes (char * (*func) (bfd *, int *))
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 7 Oct 2003 03:29:27 -0000
@@ -161,6 +161,72 @@ linux_find_memory_regions (int (*func) (
return 0;
}
+static int
+procfs_read_aux_vector (int (*func) (const Elf_Internal_Auxv *, void *),
+ void *data)
+{
+ char pathname[MAXPATHLEN];
+ union
+ {
+ Elf32_External_Auxv av32[20];
+ Elf64_External_Auxv av64[10];
+ } buf;
+ int fd, n, ret;
+
+ sprintf (pathname, "/proc/%d/auxv", PIDGET (inferior_ptid));
+ fd = open (pathname, O_RDONLY);
+ if (fd < 0)
+ return 0; /* XXX Call error here? */
+
+ ret = 0;
+ while (1)
+ {
+ n = read (fd, &buf, sizeof buf);
+ if (n <= 0) /* Hit EOF or read error. */
+ return 0;
+
+ switch (bfd_arch_bits_per_address (exec_bfd))
+ {
+ default:
+ break;
+
+ case 32:
+ {
+ const Elf32_External_Auxv *av;
+ for (av = buf.av32; (char *) av < (char *) &buf + n; ++av)
+ {
+ Elf_Internal_Auxv elt;
+ elt.a_type = bfd_get_32 (exec_bfd, av->a_type);
+ elt.a_val = bfd_get_32 (exec_bfd, av->a_val);
+ ret = (*func) (&elt, data);
+ if (ret != 0)
+ break;
+ }
+ continue;
+ }
+ case 64:
+ {
+ const Elf64_External_Auxv *av;
+ for (av = buf.av64; (char *) av < (char *) &buf + n; ++av)
+ {
+ Elf_Internal_Auxv elt;
+ elt.a_type = bfd_get_64 (exec_bfd, av->a_type);
+ elt.a_val = bfd_get_64 (exec_bfd, av->a_val);
+ ret = (*func) (&elt, data);
+ if (ret != 0)
+ break;
+ }
+ continue;
+ }
+ }
+
+ break;
+ }
+
+ close (fd);
+ return ret;
+}
+
/* Function: linux_do_thread_registers
*
* Records the thread's register state for the corefile note section.
@@ -255,6 +321,46 @@ linux_do_registers (bfd *obfd, ptid_t pt
return note_data;
}
+static int
+linux_auxv_count (const void *av, void *data)
+{
+ ++*(int *) data;
+ return 0;
+}
+
+static int
+linux_auxv_reconstruct (const void *internal, void *data)
+{
+ const Elf_Internal_Auxv *av = internal;
+ bfd_byte **ptr = data;
+
+ switch (bfd_arch_bits_per_address (exec_bfd))
+ {
+ default:
+ break;
+
+ case 32:
+ {
+ bfd_put_32 (exec_bfd, av->a_type, *ptr);
+ *ptr += 4;
+ bfd_put_32 (exec_bfd, av->a_val, *ptr);
+ *ptr += 4;
+ break;
+ }
+
+ case 64:
+ {
+ bfd_put_64 (exec_bfd, av->a_type, *ptr);
+ *ptr += 8;
+ bfd_put_64 (exec_bfd, av->a_val, *ptr);
+ *ptr += 8;
+ break;
+ }
+ }
+
+ return 0;
+}
+
/* Function: linux_make_note_section
*
* Fills the "to_make_corefile_note" target vector.
@@ -271,6 +377,7 @@ linux_make_note_section (bfd *obfd, int
char psargs[80] = { '\0' };
char *note_data = NULL;
ptid_t current_ptid = inferior_ptid;
+ int auxv_len;
if (get_exec_file (0))
{
@@ -305,6 +412,19 @@ linux_make_note_section (bfd *obfd, int
note_data = thread_args.note_data;
}
+ auxv_len = 0;
+ target_read_aux_vector (linux_auxv_count, &auxv_len);
+ if (auxv_len != 0)
+ {
+ bfd_byte *auxv, *auxvptr;
+ auxv = alloca (auxv_len * 2
+ * (bfd_arch_bits_per_address (exec_bfd) / 8));
+ auxvptr = auxv;
+ target_read_aux_vector (linux_auxv_reconstruct, &auxvptr);
+ note_data = elfcore_write_note (obfd, note_data, note_size,
+ "CORE", NT_AUXV, auxv, auxvptr - auxv);
+ }
+
make_cleanup (xfree, note_data);
return note_data;
}
@@ -593,9 +713,11 @@ _initialize_linux_proc (void)
{
extern void inftarg_set_find_memory_regions ();
extern void inftarg_set_make_corefile_notes ();
+ extern void inftarg_set_read_aux_vector ();
inftarg_set_find_memory_regions (linux_find_memory_regions);
inftarg_set_make_corefile_notes (linux_make_note_section);
+ inftarg_set_read_aux_vector (procfs_read_aux_vector);
add_info ("proc", linux_info_proc_cmd,
"Show /proc process information about any running process.\n\
Index: corelow.c
===================================================================
RCS file: /cvs/src/src/gdb/corelow.c,v
retrieving revision 1.30
diff -b -p -u -r1.30 corelow.c
--- corelow.c 21 Sep 2003 01:26:44 -0000 1.30
+++ corelow.c 7 Oct 2003 03:29:27 -0000
@@ -474,6 +550,69 @@ core_files_info (struct target_ops *t)
print_section_info (t, core_bfd);
}
+static int
+core_read_aux_vector (int (*func) (const void *, void *), void *data)
+{
+ sec_ptr section;
+ bfd_size_type size;
+ char *contents;
+ int ret;
+
+ section = bfd_get_section_by_name (core_bfd, ".auxv");
+ if (section == NULL)
+ return 0;
+
+ size = bfd_section_size (core_bfd, section);
+ contents = (char *) 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.");
+ return 0;
+ }
+
+ switch (bfd_arch_bits_per_address (core_bfd))
+ {
+ default:
+ return 0;
+
+ case 32:
+ {
+ Elf32_External_Auxv *av;
+ for (av = (Elf32_External_Auxv *) contents;
+ (char *) av < contents + size;
+ ++av)
+ {
+ Elf_Internal_Auxv elt;
+ elt.a_type = bfd_get_32 (core_bfd, av->a_type);
+ elt.a_val = bfd_get_32 (core_bfd, av->a_val);
+ ret = (*func) (&elt, data);
+ if (ret != 0)
+ return ret;
+ }
+ break;
+ }
+ case 64:
+ {
+ Elf64_External_Auxv *av;
+ for (av = (Elf64_External_Auxv *) contents;
+ (char *) av < contents + size;
+ ++av)
+ {
+ Elf_Internal_Auxv elt;
+ elt.a_type = bfd_get_64 (core_bfd, av->a_type);
+ elt.a_val = bfd_get_64 (core_bfd, av->a_val);
+ ret = (*func) (&elt, data);
+ if (ret != 0)
+ return ret;
+ }
+ break;
+ }
+ }
+
+ return 0;
+}
+
/* If mourn is being called in all the right places, this could be say
`gdb internal error' (since generic_mourn calls breakpoint_init_inferior). */
@@ -520,6 +659,7 @@ init_core_ops (void)
core_ops.to_has_memory = 1;
core_ops.to_has_stack = 1;
core_ops.to_has_registers = 1;
+ core_ops.to_read_aux_vector = core_read_aux_vector;
core_ops.to_magic = OPS_MAGIC;
}