diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 7c6e1f0bc1..13bdc3d3cf 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,35 @@ +2013-05-15 Joel Brobecker + + * gdbarch.sh (core_xfer_shared_libraries_aix): New method. + * gdbarch.h, gdbarch.c: Regenerate. + * corelow.c (core_xfer_partial): Add TARGET_OBJECT_LIBRARIES_AIX + handling. + + * rs6000-aix-tdep.h: New file. + * Makefile.in (HFILES_NO_SRCDIR): Add rs6000-aix-tdep.h. + * rs6000-aix-tdep.c: Include "rs6000-aix-tdep.h" and + "xml-utils.h". + (struct field_info, struct ld_info_desc): New types. + (ld_info32_desc, ld_info64_desc): New static constants. + (struct ld_info): New type. + (rs6000_aix_extract_ld_info): New function. + (rs6000_aix_shared_library_to_xml): Likewise. + (rs6000_aix_ld_info_to_xml): Likewise. + (rs6000_aix_core_xfer_shared_libraries_aix): Likewise. + (rs6000_aix_init_osabi): Add call to + set_gdbarch_core_xfer_shared_libraries_aix. + * rs6000-nat.c: Add "rs6000-aix-tdep.h" include. + Remove "xml-utils.h" include. + (LdInfo): Delete typedef. + (ARCH64_DECL, LDI_FIELD, LDI_NEXT, LDI_FD, LDI_FILENAME): + Delete macros. + (rs6000_ptrace_ldinfo): Change return type to gdb_byte *. + Adjust code accordingly. + (rs6000_core_ldinfo): Delete, folded into + rs6000_aix_core_xfer_shared_libraries_aix. + (rs6000_xfer_shared_library): Delete. + (rs6000_xfer_shared_libraries): Reimplement. + 2013-05-15 Markus Metzger * record.c (record_goto_cmdlist): New. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 91278945b9..69ec68ba07 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -820,7 +820,8 @@ amd64-linux-tdep.h linespec.h i387-tdep.h mn10300-tdep.h \ sparc64-tdep.h monitor.h ppcobsd-tdep.h srec.h solib-pa64.h \ coff-pe-read.h parser-defs.h gdb_ptrace.h mips-linux-tdep.h \ m68k-tdep.h spu-tdep.h jv-lang.h environ.h solib-irix.h amd64-tdep.h \ -doublest.h regset.h hppa-tdep.h ppc-linux-tdep.h ppc64-tdep.h rs6000-tdep.h \ +doublest.h regset.h hppa-tdep.h ppc-linux-tdep.h ppc64-tdep.h \ +rs6000-tdep.h rs6000-aix-tdep.h \ common/gdb_locale.h common/gdb_dirent.h arch-utils.h trad-frame.h gnu-nat.h \ language.h nbsd-tdep.h solib-svr4.h \ macroexp.h ui-file.h regcache.h tracepoint.h i386-tdep.h \ diff --git a/gdb/corelow.c b/gdb/corelow.c index de940fcd75..0bfa7431d7 100644 --- a/gdb/corelow.c +++ b/gdb/corelow.c @@ -756,6 +756,18 @@ core_xfer_partial (struct target_ops *ops, enum target_object object, } /* FALL THROUGH */ + case TARGET_OBJECT_LIBRARIES_AIX: + if (core_gdbarch + && gdbarch_core_xfer_shared_libraries_aix_p (core_gdbarch)) + { + if (writebuf) + return -1; + return + gdbarch_core_xfer_shared_libraries_aix (core_gdbarch, + readbuf, offset, len); + } + /* FALL THROUGH */ + case TARGET_OBJECT_SPU: if (readbuf && annex) { diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index 129268fe58..db35b40fae 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -241,6 +241,7 @@ struct gdbarch gdbarch_elfcore_write_linux_prpsinfo_ftype *elfcore_write_linux_prpsinfo; gdbarch_find_memory_regions_ftype *find_memory_regions; gdbarch_core_xfer_shared_libraries_ftype *core_xfer_shared_libraries; + gdbarch_core_xfer_shared_libraries_aix_ftype *core_xfer_shared_libraries_aix; gdbarch_core_pid_to_str_ftype *core_pid_to_str; const char * gcore_bfd_target; int vtable_function_descriptors; @@ -412,6 +413,7 @@ struct gdbarch startup_gdbarch = 0, /* elfcore_write_linux_prpsinfo */ 0, /* find_memory_regions */ 0, /* core_xfer_shared_libraries */ + 0, /* core_xfer_shared_libraries_aix */ 0, /* core_pid_to_str */ 0, /* gcore_bfd_target */ 0, /* vtable_function_descriptors */ @@ -714,6 +716,7 @@ verify_gdbarch (struct gdbarch *gdbarch) /* Skip verify of elfcore_write_linux_prpsinfo, has predicate. */ /* Skip verify of find_memory_regions, has predicate. */ /* Skip verify of core_xfer_shared_libraries, has predicate. */ + /* Skip verify of core_xfer_shared_libraries_aix, has predicate. */ /* Skip verify of core_pid_to_str, has predicate. */ /* Skip verify of gcore_bfd_target, has predicate. */ /* Skip verify of vtable_function_descriptors, invalid_p == 0 */ @@ -903,6 +906,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) fprintf_unfiltered (file, "gdbarch_dump: core_xfer_shared_libraries = <%s>\n", host_address_to_string (gdbarch->core_xfer_shared_libraries)); + fprintf_unfiltered (file, + "gdbarch_dump: gdbarch_core_xfer_shared_libraries_aix_p() = %d\n", + gdbarch_core_xfer_shared_libraries_aix_p (gdbarch)); + fprintf_unfiltered (file, + "gdbarch_dump: core_xfer_shared_libraries_aix = <%s>\n", + host_address_to_string (gdbarch->core_xfer_shared_libraries_aix)); fprintf_unfiltered (file, "gdbarch_dump: decr_pc_after_break = %s\n", core_addr_to_string_nz (gdbarch->decr_pc_after_break)); @@ -3448,6 +3457,30 @@ set_gdbarch_core_xfer_shared_libraries (struct gdbarch *gdbarch, gdbarch->core_xfer_shared_libraries = core_xfer_shared_libraries; } +int +gdbarch_core_xfer_shared_libraries_aix_p (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + return gdbarch->core_xfer_shared_libraries_aix != NULL; +} + +LONGEST +gdbarch_core_xfer_shared_libraries_aix (struct gdbarch *gdbarch, gdb_byte *readbuf, ULONGEST offset, LONGEST len) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->core_xfer_shared_libraries_aix != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_core_xfer_shared_libraries_aix called\n"); + return gdbarch->core_xfer_shared_libraries_aix (gdbarch, readbuf, offset, len); +} + +void +set_gdbarch_core_xfer_shared_libraries_aix (struct gdbarch *gdbarch, + gdbarch_core_xfer_shared_libraries_aix_ftype core_xfer_shared_libraries_aix) +{ + gdbarch->core_xfer_shared_libraries_aix = core_xfer_shared_libraries_aix; +} + int gdbarch_core_pid_to_str_p (struct gdbarch *gdbarch) { diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index 464c4b6848..e1959c3918 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -766,6 +766,15 @@ typedef LONGEST (gdbarch_core_xfer_shared_libraries_ftype) (struct gdbarch *gdba extern LONGEST gdbarch_core_xfer_shared_libraries (struct gdbarch *gdbarch, gdb_byte *readbuf, ULONGEST offset, LONGEST len); extern void set_gdbarch_core_xfer_shared_libraries (struct gdbarch *gdbarch, gdbarch_core_xfer_shared_libraries_ftype *core_xfer_shared_libraries); +/* Read offset OFFSET of TARGET_OBJECT_LIBRARIES_AIX formatted shared + libraries list from core file into buffer READBUF with length LEN. */ + +extern int gdbarch_core_xfer_shared_libraries_aix_p (struct gdbarch *gdbarch); + +typedef LONGEST (gdbarch_core_xfer_shared_libraries_aix_ftype) (struct gdbarch *gdbarch, gdb_byte *readbuf, ULONGEST offset, LONGEST len); +extern LONGEST gdbarch_core_xfer_shared_libraries_aix (struct gdbarch *gdbarch, gdb_byte *readbuf, ULONGEST offset, LONGEST len); +extern void set_gdbarch_core_xfer_shared_libraries_aix (struct gdbarch *gdbarch, gdbarch_core_xfer_shared_libraries_aix_ftype *core_xfer_shared_libraries_aix); + /* How the core target converts a PTID from a core file to a string. */ extern int gdbarch_core_pid_to_str_p (struct gdbarch *gdbarch); diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index 92d4f0fff2..c92a857b70 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -655,6 +655,10 @@ M:int:find_memory_regions:find_memory_region_ftype func, void *data:func, data # core file into buffer READBUF with length LEN. M:LONGEST:core_xfer_shared_libraries:gdb_byte *readbuf, ULONGEST offset, LONGEST len:readbuf, offset, len +# Read offset OFFSET of TARGET_OBJECT_LIBRARIES_AIX formatted shared +# libraries list from core file into buffer READBUF with length LEN. +M:LONGEST:core_xfer_shared_libraries_aix:gdb_byte *readbuf, ULONGEST offset, LONGEST len:readbuf, offset, len + # How the core target converts a PTID from a core file to a string. M:char *:core_pid_to_str:ptid_t ptid:ptid diff --git a/gdb/rs6000-aix-tdep.c b/gdb/rs6000-aix-tdep.c index 0d4fec5ce0..9956eb3cdc 100644 --- a/gdb/rs6000-aix-tdep.c +++ b/gdb/rs6000-aix-tdep.c @@ -34,10 +34,12 @@ #include "breakpoint.h" #include "rs6000-tdep.h" #include "ppc-tdep.h" +#include "rs6000-aix-tdep.h" #include "exceptions.h" #include "xcoffread.h" #include "solib.h" #include "solib-aix.h" +#include "xml-utils.h" /* If the kernel has to deliver a signal, it pushes a sigcontext structure on the stack and then calls the signal handler, passing @@ -747,6 +749,299 @@ rs6000_aix_osabi_sniffer (bfd *abfd) return GDB_OSABI_AIX; } +/* A structure encoding the offset and size of a field within + a struct. */ + +struct field_info +{ + int offset; + int size; +}; + +/* A structure describing the layout of all the fields of interest + in AIX's struct ld_info. Each field in this struct corresponds + to the field of the same name in struct ld_info. */ + +struct ld_info_desc +{ + struct field_info ldinfo_next; + struct field_info ldinfo_fd; + struct field_info ldinfo_textorg; + struct field_info ldinfo_textsize; + struct field_info ldinfo_dataorg; + struct field_info ldinfo_datasize; + struct field_info ldinfo_filename; +}; + +/* The following data has been generated by compiling and running + the following program on AIX 5.3. */ + +#if 0 + #include + #include + #define __LDINFO_PTRACE32__ + #define __LDINFO_PTRACE64__ + #include + + #define pinfo(type,member) \ + { \ + struct type ldi = {0}; \ + \ + printf (" {%d, %d},\t/* %s */\n", \ + offsetof (struct type, member), \ + sizeof (ldi.member), \ + #member); \ + } \ + while (0) + + int + main (void) + { + printf ("static const struct ld_info_desc ld_info32_desc =\n{\n"); + pinfo (__ld_info32, ldinfo_next); + pinfo (__ld_info32, ldinfo_fd); + pinfo (__ld_info32, ldinfo_textorg); + pinfo (__ld_info32, ldinfo_textsize); + pinfo (__ld_info32, ldinfo_dataorg); + pinfo (__ld_info32, ldinfo_datasize); + pinfo (__ld_info32, ldinfo_filename); + printf ("};\n"); + + printf ("\n"); + + printf ("static const struct ld_info_desc ld_info64_desc =\n{\n"); + pinfo (__ld_info64, ldinfo_next); + pinfo (__ld_info64, ldinfo_fd); + pinfo (__ld_info64, ldinfo_textorg); + pinfo (__ld_info64, ldinfo_textsize); + pinfo (__ld_info64, ldinfo_dataorg); + pinfo (__ld_info64, ldinfo_datasize); + pinfo (__ld_info64, ldinfo_filename); + printf ("};\n"); + + return 0; + } +#endif /* 0 */ + +/* Layout of the 32bit version of struct ld_info. */ + +static const struct ld_info_desc ld_info32_desc = +{ + {0, 4}, /* ldinfo_next */ + {4, 4}, /* ldinfo_fd */ + {8, 4}, /* ldinfo_textorg */ + {12, 4}, /* ldinfo_textsize */ + {16, 4}, /* ldinfo_dataorg */ + {20, 4}, /* ldinfo_datasize */ + {24, 2}, /* ldinfo_filename */ +}; + +/* Layout of the 64bit version of struct ld_info. */ + +static const struct ld_info_desc ld_info64_desc = +{ + {0, 4}, /* ldinfo_next */ + {8, 4}, /* ldinfo_fd */ + {16, 8}, /* ldinfo_textorg */ + {24, 8}, /* ldinfo_textsize */ + {32, 8}, /* ldinfo_dataorg */ + {40, 8}, /* ldinfo_datasize */ + {48, 2}, /* ldinfo_filename */ +}; + +/* A structured representation of one entry read from the ld_info + binary data provided by the AIX loader. */ + +struct ld_info +{ + ULONGEST next; + int fd; + CORE_ADDR textorg; + ULONGEST textsize; + CORE_ADDR dataorg; + ULONGEST datasize; + char *filename; + char *member_name; +}; + +/* Return a struct ld_info object corresponding to the entry at + LDI_BUF. + + Note that the filename and member_name strings still point + to the data in LDI_BUF. So LDI_BUF must not be deallocated + while the struct ld_info object returned is in use. */ + +static struct ld_info +rs6000_aix_extract_ld_info (struct gdbarch *gdbarch, + const gdb_byte *ldi_buf) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr; + const struct ld_info_desc desc + = tdep->wordsize == 8 ? ld_info64_desc : ld_info32_desc; + struct ld_info info; + + info.next = extract_unsigned_integer (ldi_buf + desc.ldinfo_next.offset, + desc.ldinfo_next.size, + byte_order); + info.fd = extract_signed_integer (ldi_buf + desc.ldinfo_fd.offset, + desc.ldinfo_fd.size, + byte_order); + info.textorg = extract_typed_address (ldi_buf + desc.ldinfo_textorg.offset, + ptr_type); + info.textsize + = extract_unsigned_integer (ldi_buf + desc.ldinfo_textsize.offset, + desc.ldinfo_textsize.size, + byte_order); + info.dataorg = extract_typed_address (ldi_buf + desc.ldinfo_dataorg.offset, + ptr_type); + info.datasize + = extract_unsigned_integer (ldi_buf + desc.ldinfo_datasize.offset, + desc.ldinfo_datasize.size, + byte_order); + info.filename = (char *) ldi_buf + desc.ldinfo_filename.offset; + info.member_name = info.filename + strlen (info.filename) + 1; + + return info; +} + +/* Append to OBJSTACK an XML string description of the shared library + corresponding to LDI, following the TARGET_OBJECT_LIBRARIES_AIX + format. */ + +static void +rs6000_aix_shared_library_to_xml (struct ld_info *ldi, + struct obstack *obstack) +{ + char *p; + + obstack_grow_str (obstack, "filename); + obstack_grow_str (obstack, p); + xfree (p); + obstack_grow_str (obstack, "\""); + + if (ldi->member_name[0] != '\0') + { + obstack_grow_str (obstack, " member=\""); + p = xml_escape_text (ldi->member_name); + obstack_grow_str (obstack, p); + xfree (p); + obstack_grow_str (obstack, "\""); + } + + obstack_grow_str (obstack, " text_addr=\""); + obstack_grow_str (obstack, core_addr_to_string (ldi->textorg)); + obstack_grow_str (obstack, "\""); + + obstack_grow_str (obstack, " text_size=\""); + obstack_grow_str (obstack, pulongest (ldi->textsize)); + obstack_grow_str (obstack, "\""); + + obstack_grow_str (obstack, " data_addr=\""); + obstack_grow_str (obstack, core_addr_to_string (ldi->dataorg)); + obstack_grow_str (obstack, "\""); + + obstack_grow_str (obstack, " data_size=\""); + obstack_grow_str (obstack, pulongest (ldi->datasize)); + obstack_grow_str (obstack, "\""); + + obstack_grow_str (obstack, ">"); +} + +/* Convert the ld_info binary data provided by the AIX loader into + an XML representation following the TARGET_OBJECT_LIBRARIES_AIX + format. + + LDI_BUF is a buffer containing the ld_info data. + READBUF, OFFSET and LEN follow the same semantics as target_ops' + to_xfer_partial target_ops method. + + If CLOSE_LDINFO_FD is nonzero, then this routine also closes + the ldinfo_fd file descriptor. This is useful when the ldinfo + data is obtained via ptrace, as ptrace opens a file descriptor + for each and every entry; but we cannot use this descriptor + as the consumer of the XML library list might live in a different + process. */ + +LONGEST +rs6000_aix_ld_info_to_xml (struct gdbarch *gdbarch, const gdb_byte *ldi_buf, + gdb_byte *readbuf, ULONGEST offset, LONGEST len, + int close_ldinfo_fd) +{ + struct obstack obstack; + const char *buf; + LONGEST len_avail; + + obstack_init (&obstack); + obstack_grow_str (&obstack, "\n"); + + while (1) + { + struct ld_info ldi = rs6000_aix_extract_ld_info (gdbarch, ldi_buf); + + rs6000_aix_shared_library_to_xml (&ldi, &obstack); + if (close_ldinfo_fd) + close (ldi.fd); + + if (!ldi.next) + break; + ldi_buf = ldi_buf + ldi.next; + } + + obstack_grow_str0 (&obstack, "\n"); + + buf = obstack_finish (&obstack); + len_avail = strlen (buf); + if (offset >= len_avail) + len= 0; + else + { + if (len > len_avail - offset) + len = len_avail - offset; + memcpy (readbuf, buf + offset, len); + } + + obstack_free (&obstack, NULL); + return len; +} + +/* Implement the core_xfer_shared_libraries_aix gdbarch method. */ + +static LONGEST +rs6000_aix_core_xfer_shared_libraries_aix (struct gdbarch *gdbarch, + gdb_byte *readbuf, + ULONGEST offset, + LONGEST len) +{ + struct bfd_section *ldinfo_sec; + int ldinfo_size; + gdb_byte *ldinfo_buf; + struct cleanup *cleanup; + LONGEST result; + + ldinfo_sec = bfd_get_section_by_name (core_bfd, ".ldinfo"); + if (ldinfo_sec == NULL) + error (_("cannot find .ldinfo section from core file: %s"), + bfd_errmsg (bfd_get_error ())); + ldinfo_size = bfd_get_section_size (ldinfo_sec); + + ldinfo_buf = xmalloc (ldinfo_size); + cleanup = make_cleanup (xfree, ldinfo_buf); + + if (! bfd_get_section_contents (core_bfd, ldinfo_sec, + ldinfo_buf, 0, ldinfo_size)) + error (_("unable to read .ldinfo section from core file: %s"), + bfd_errmsg (bfd_get_error ())); + + result = rs6000_aix_ld_info_to_xml (gdbarch, ldinfo_buf, readbuf, + offset, len, 0); + + do_cleanups (cleanup); + return result; +} + static void rs6000_aix_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch) { @@ -774,6 +1069,8 @@ rs6000_aix_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch) /* Core file support. */ set_gdbarch_regset_from_core_section (gdbarch, rs6000_aix_regset_from_core_section); + set_gdbarch_core_xfer_shared_libraries_aix + (gdbarch, rs6000_aix_core_xfer_shared_libraries_aix); if (tdep->wordsize == 8) tdep->lr_frame_offset = 16; diff --git a/gdb/rs6000-aix-tdep.h b/gdb/rs6000-aix-tdep.h new file mode 100644 index 0000000000..07c37f54d8 --- /dev/null +++ b/gdb/rs6000-aix-tdep.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2013 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 3 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, see . */ + +#ifndef RS6000_AIX_TDEP_H +#define RS6000_AIX_TDEP_H + +extern LONGEST rs6000_aix_ld_info_to_xml (struct gdbarch *gdbarch, + const gdb_byte *ldi_buf, + gdb_byte *readbuf, + ULONGEST offset, + LONGEST len, + int close_ldinfo_fd); + +#endif /* RS6000_AIX_TDEP_H */ diff --git a/gdb/rs6000-nat.c b/gdb/rs6000-nat.c index 1af8610b13..1b600f0fb5 100644 --- a/gdb/rs6000-nat.c +++ b/gdb/rs6000-nat.c @@ -33,6 +33,7 @@ #include "inf-ptrace.h" #include "ppc-tdep.h" #include "rs6000-tdep.h" +#include "rs6000-aix-tdep.h" #include "exec.h" #include "observer.h" #include "xcoffread.h" @@ -57,7 +58,6 @@ #define __LDINFO_PTRACE64__ /* for __ld_info64 */ #include #include -#include "xml-utils.h" /* On AIX4.3+, sys/ldr.h provides different versions of struct ld_info for debugging 32-bit and 64-bit processes. Define a typedef and macros for @@ -78,46 +78,6 @@ # define ARCH64() (register_size (target_gdbarch (), 0) == 8) #endif -/* Union of 32-bit and 64-bit versions of ld_info. */ - -typedef union { -#ifndef ARCH3264 - struct ld_info l32; - struct ld_info l64; -#else - struct __ld_info32 l32; - struct __ld_info64 l64; -#endif -} LdInfo; - -/* If compiling with 32-bit and 64-bit debugging capability (e.g. AIX 4.x), - declare and initialize a variable named VAR suitable for use as the arch64 - parameter to the various LDI_*() macros. */ - -#ifndef ARCH3264 -# define ARCH64_DECL(var) -#else -# define ARCH64_DECL(var) int var = ARCH64 () -#endif - -/* Return LDI's FIELD for a 64-bit process if ARCH64 and for a 32-bit process - otherwise. This technique only works for FIELDs with the same data type in - 32-bit and 64-bit versions of ld_info. */ - -#ifndef ARCH3264 -# define LDI_FIELD(ldi, arch64, field) (ldi)->l32.ldinfo_##field -#else -# define LDI_FIELD(ldi, arch64, field) \ - (arch64 ? (ldi)->l64.ldinfo_##field : (ldi)->l32.ldinfo_##field) -#endif - -/* Return various LDI fields for a 64-bit process if ARCH64 and for a 32-bit - process otherwise. */ - -#define LDI_NEXT(ldi, arch64) LDI_FIELD(ldi, arch64, next) -#define LDI_FD(ldi, arch64) LDI_FIELD(ldi, arch64, fd) -#define LDI_FILENAME(ldi, arch64) LDI_FIELD(ldi, arch64, filename) - static void exec_one_dummy_insn (struct regcache *); static LONGEST rs6000_xfer_shared_libraries @@ -682,12 +642,12 @@ rs6000_create_inferior (struct target_ops * ops, char *exec_file, The returned value must be deallocated after use. */ -static LdInfo * +static gdb_byte * rs6000_ptrace_ldinfo (ptid_t ptid) { const int pid = ptid_get_pid (ptid); int ldi_size = 1024; - LdInfo *ldi = xmalloc (ldi_size); + gdb_byte *ldi = xmalloc (ldi_size); int rc = -1; while (1) @@ -712,104 +672,6 @@ rs6000_ptrace_ldinfo (ptid_t ptid) return ldi; } -/* Assuming ABFD refers to a core file, return the LdInfo data - stored in that core file. Raises an error if the data could - not be read or extracted. - - The returned value much be deallocated after use. */ - -static LdInfo * -rs6000_core_ldinfo (bfd *abfd) -{ - struct bfd_section *ldinfo_sec; - int ldinfo_size; - gdb_byte *ldinfo_buf; - struct cleanup *cleanup; - - ldinfo_sec = bfd_get_section_by_name (abfd, ".ldinfo"); - if (ldinfo_sec == NULL) - error (_("cannot find .ldinfo section from core file: %s"), - bfd_errmsg (bfd_get_error ())); - ldinfo_size = bfd_get_section_size (ldinfo_sec); - - ldinfo_buf = xmalloc (ldinfo_size); - cleanup = make_cleanup (xfree, ldinfo_buf); - - if (! bfd_get_section_contents (abfd, ldinfo_sec, - ldinfo_buf, 0, ldinfo_size)) - error (_("unable to read .ldinfo section from core file: %s"), - bfd_errmsg (bfd_get_error ())); - - discard_cleanups (cleanup); - return (LdInfo *) ldinfo_buf; -} - -/* Append to OBJSTACK an XML string description of the shared library - corresponding to LDI, following the TARGET_OBJECT_LIBRARIES_AIX - format. */ - -static void -rs6000_xfer_shared_library (LdInfo *ldi, struct obstack *obstack) -{ - const int arch64 = ARCH64 (); - const char *archive_name = LDI_FILENAME (ldi, arch64); - const char *member_name = archive_name + strlen (archive_name) + 1; - CORE_ADDR text_addr, data_addr; - ULONGEST text_size, data_size; - char *p; - - if (arch64) - { - text_addr = ldi->l64.ldinfo_textorg; - text_size = ldi->l64.ldinfo_textsize; - data_addr = ldi->l64.ldinfo_dataorg; - data_size = ldi->l64.ldinfo_datasize; - } - else - { - /* The text and data addresses are defined as pointers. - To avoid sign-extending their value in the assignments - below, we cast their value to unsigned long first. */ - text_addr = (unsigned long) ldi->l32.ldinfo_textorg; - text_size = ldi->l32.ldinfo_textsize; - data_addr = (unsigned long) ldi->l32.ldinfo_dataorg; - data_size = ldi->l32.ldinfo_datasize; - } - - obstack_grow_str (obstack, ""); -} - /* Implement the to_xfer_partial target_ops method for TARGET_OBJECT_LIBRARIES_AIX objects. */ @@ -819,62 +681,26 @@ rs6000_xfer_shared_libraries const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf, ULONGEST offset, LONGEST len) { - const int arch64 = ARCH64 (); - LdInfo *ldi_data; - LdInfo *ldi; - struct obstack obstack; - const char *buf; - LONGEST len_avail; + gdb_byte *ldi_buf; + ULONGEST result; + struct cleanup *cleanup; + + /* This function assumes that it is being run with a live process. + Core files are handled via gdbarch. */ + gdb_assert (target_has_execution); if (writebuf) return -1; - /* Get the ldinfo raw data: If debugging a live process, we get it - using ptrace. Otherwise, the info is stored in the .ldinfo - section of the core file. */ + ldi_buf = rs6000_ptrace_ldinfo (inferior_ptid); + gdb_assert (ldi_buf != NULL); + cleanup = make_cleanup (xfree, ldi_buf); + result = rs6000_aix_ld_info_to_xml (target_gdbarch (), ldi_buf, + readbuf, offset, len, 1); + xfree (ldi_buf); - if (target_has_execution) - ldi_data = rs6000_ptrace_ldinfo (inferior_ptid); - else - ldi_data = rs6000_core_ldinfo (core_bfd); - - /* Convert the raw data into an XML representation. */ - - obstack_init (&obstack); - obstack_grow_str (&obstack, "\n"); - - ldi = ldi_data; - while (1) - { - /* Close the fd. We cannot use it, because we cannot assume - that the user of this descriptor will be in the same - process. */ - close (LDI_FD (ldi, arch64)); - - rs6000_xfer_shared_library (ldi, &obstack); - - if (!LDI_NEXT (ldi, arch64)) - break; - ldi = (LdInfo *) ((char *) ldi + LDI_NEXT (ldi, arch64)); - } - - xfree (ldi_data); - - obstack_grow_str0 (&obstack, "\n"); - - buf = obstack_finish (&obstack); - len_avail = strlen (buf); - if (offset >= len_avail) - len= 0; - else - { - if (len > len_avail - offset) - len = len_avail - offset; - memcpy (readbuf, buf + offset, len); - } - - obstack_free (&obstack, NULL); - return len; + do_cleanups (cleanup); + return result; } void _initialize_rs6000_nat (void);