X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Frs6000-nat.c;h=f99846052e92b37a155a77443088683bc457499c;hb=ad43e107eb233dcef8e76da6328aa4e4d74afd84;hp=1af8610b13b20f94f594c238f140492333646e68;hpb=2f565103afd525574ebefa781d87d39e86dfe693;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/rs6000-nat.c b/gdb/rs6000-nat.c index 1af8610b13..f99846052e 100644 --- a/gdb/rs6000-nat.c +++ b/gdb/rs6000-nat.c @@ -1,6 +1,6 @@ /* IBM RS/6000 native-dependent code for GDB, the GNU debugger. - Copyright (C) 1986-2013 Free Software Foundation, Inc. + Copyright (C) 1986-2016 Free Software Foundation, Inc. This file is part of GDB. @@ -23,9 +23,7 @@ #include "gdbcore.h" #include "symfile.h" #include "objfiles.h" -#include "libbfd.h" /* For bfd_default_set_arch_mach (FIXME) */ #include "bfd.h" -#include "exceptions.h" #include "gdb-stabs.h" #include "regcache.h" #include "arch-utils.h" @@ -33,6 +31,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" @@ -40,24 +39,21 @@ #include #include -#include #include #include #include #include #include -#include #include #include -#include "gdb_stat.h" +#include #include "gdb_bfd.h" #include #define __LDINFO_PTRACE32__ /* for __ld_info32 */ #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 @@ -66,7 +62,7 @@ /* In 32-bit compilation mode (which is the only mode from which ptrace() works on 4.3), __ld_info32 is #defined as equivalent to ld_info. */ -#ifdef __ld_info32 +#if defined (__ld_info32) || defined (__ld_info64) # define ARCH3264 #endif @@ -78,52 +74,7 @@ # 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 - (struct target_ops *ops, enum target_object object, - const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf, - ULONGEST offset, LONGEST len); +static target_xfer_partial_ftype rs6000_xfer_shared_libraries; /* Given REGNO, a gdb register number, return the corresponding number suitable for use as a ptrace() parameter. Return -1 if @@ -172,7 +123,11 @@ regmap (struct gdbarch *gdbarch, int regno, int *isfloat) static int rs6000_ptrace32 (int req, int id, int *addr, int data, int *buf) { +#ifdef HAVE_PTRACE64 + int ret = ptrace64 (req, id, (uintptr_t) addr, data, buf); +#else int ret = ptrace (req, id, (int *)addr, data, buf); +#endif #if 0 printf ("rs6000_ptrace32 (%d, %d, 0x%x, %08x, 0x%x) = 0x%x\n", req, id, (unsigned int)addr, data, (unsigned int)buf, ret); @@ -186,7 +141,11 @@ static int rs6000_ptrace64 (int req, int id, long long addr, int data, void *buf) { #ifdef ARCH3264 - int ret = ptracex (req, id, addr, data, buf); +# ifdef HAVE_PTRACE64 + int ret = ptrace64 (req, id, addr, data, (PTRACE_TYPE_ARG5) buf); +# else + int ret = ptracex (req, id, addr, data, (PTRACE_TYPE_ARG5) buf); +# endif #else int ret = 0; #endif @@ -213,7 +172,7 @@ fetch_register (struct regcache *regcache, int regno) /* Floating-point registers. */ if (isfloat) - rs6000_ptrace32 (PT_READ_FPR, PIDGET (inferior_ptid), addr, nr, 0); + rs6000_ptrace32 (PT_READ_FPR, ptid_get_pid (inferior_ptid), addr, nr, 0); /* Bogus register number. */ else if (nr < 0) @@ -229,14 +188,15 @@ fetch_register (struct regcache *regcache, int regno) else { if (!ARCH64 ()) - *addr = rs6000_ptrace32 (PT_READ_GPR, PIDGET (inferior_ptid), + *addr = rs6000_ptrace32 (PT_READ_GPR, ptid_get_pid (inferior_ptid), (int *) nr, 0, 0); else { /* PT_READ_GPR requires the buffer parameter to point to long long, even if the register is really only 32 bits. */ long long buf; - rs6000_ptrace64 (PT_READ_GPR, PIDGET (inferior_ptid), nr, 0, &buf); + rs6000_ptrace64 (PT_READ_GPR, ptid_get_pid (inferior_ptid), + nr, 0, &buf); if (register_size (gdbarch, regno) == 8) memcpy (addr, &buf, 8); else @@ -275,7 +235,7 @@ store_register (struct regcache *regcache, int regno) /* Floating-point registers. */ if (isfloat) - rs6000_ptrace32 (PT_WRITE_FPR, PIDGET (inferior_ptid), addr, nr, 0); + rs6000_ptrace32 (PT_WRITE_FPR, ptid_get_pid (inferior_ptid), addr, nr, 0); /* Bogus register number. */ else if (nr < 0) @@ -289,19 +249,11 @@ store_register (struct regcache *regcache, int regno) /* Fixed-point registers. */ else { - if (regno == gdbarch_sp_regnum (gdbarch)) - /* Execute one dummy instruction (which is a breakpoint) in inferior - process to give kernel a chance to do internal housekeeping. - Otherwise the following ptrace(2) calls will mess up user stack - since kernel will get confused about the bottom of the stack - (%sp). */ - exec_one_dummy_insn (regcache); - /* The PT_WRITE_GPR operation is rather odd. For 32-bit inferiors, the register's value is passed by value, but for 64-bit inferiors, the address of a buffer containing the value is passed. */ if (!ARCH64 ()) - rs6000_ptrace32 (PT_WRITE_GPR, PIDGET (inferior_ptid), + rs6000_ptrace32 (PT_WRITE_GPR, ptid_get_pid (inferior_ptid), (int *) nr, *addr, 0); else { @@ -312,7 +264,8 @@ store_register (struct regcache *regcache, int regno) memcpy (&buf, addr, 8); else buf = *addr; - rs6000_ptrace64 (PT_WRITE_GPR, PIDGET (inferior_ptid), nr, 0, &buf); + rs6000_ptrace64 (PT_WRITE_GPR, ptid_get_pid (inferior_ptid), + nr, 0, &buf); } } @@ -408,16 +361,13 @@ rs6000_store_inferior_registers (struct target_ops *ops, } } +/* Implement the to_xfer_partial target_ops method. */ -/* Attempt a transfer all LEN bytes starting at OFFSET between the - inferior's OBJECT:ANNEX space and GDB's READBUF/WRITEBUF buffer. - Return the number of bytes actually transferred. */ - -static LONGEST +static enum target_xfer_status rs6000_xfer_partial (struct target_ops *ops, enum target_object object, const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf, - ULONGEST offset, LONGEST len) + ULONGEST offset, ULONGEST len, ULONGEST *xfered_len) { pid_t pid = ptid_get_pid (inferior_ptid); int arch64 = ARCH64 (); @@ -427,7 +377,7 @@ rs6000_xfer_partial (struct target_ops *ops, enum target_object object, case TARGET_OBJECT_LIBRARIES_AIX: return rs6000_xfer_shared_libraries (ops, object, annex, readbuf, writebuf, - offset, len); + offset, len, xfered_len); case TARGET_OBJECT_MEMORY: { union @@ -485,7 +435,7 @@ rs6000_xfer_partial (struct target_ops *ops, enum target_object object, (int *) (uintptr_t) rounded_offset, buffer.word, NULL); if (errno) - return 0; + return TARGET_XFER_EOF; } if (readbuf) @@ -499,18 +449,19 @@ rs6000_xfer_partial (struct target_ops *ops, enum target_object object, (int *)(uintptr_t)rounded_offset, 0, NULL); if (errno) - return 0; + return TARGET_XFER_EOF; /* Copy appropriate bytes out of the buffer. */ memcpy (readbuf, buffer.byte + (offset - rounded_offset), partial_len); } - return partial_len; + *xfered_len = (ULONGEST) partial_len; + return TARGET_XFER_OK; } default: - return -1; + return TARGET_XFER_E_IO; } } @@ -570,52 +521,6 @@ rs6000_wait (struct target_ops *ops, return pid_to_ptid (pid); } - -/* Execute one dummy breakpoint instruction. This way we give the kernel - a chance to do some housekeeping and update inferior's internal data, - including u_area. */ - -static void -exec_one_dummy_insn (struct regcache *regcache) -{ -#define DUMMY_INSN_ADDR AIX_TEXT_SEGMENT_BASE+0x200 - - struct gdbarch *gdbarch = get_regcache_arch (regcache); - int ret, status, pid; - CORE_ADDR prev_pc; - void *bp; - - /* We plant one dummy breakpoint into DUMMY_INSN_ADDR address. We - assume that this address will never be executed again by the real - code. */ - - bp = deprecated_insert_raw_breakpoint (gdbarch, NULL, DUMMY_INSN_ADDR); - - /* You might think this could be done with a single ptrace call, and - you'd be correct for just about every platform I've ever worked - on. However, rs6000-ibm-aix4.1.3 seems to have screwed this up -- - the inferior never hits the breakpoint (it's also worth noting - powerpc-ibm-aix4.1.3 works correctly). */ - prev_pc = regcache_read_pc (regcache); - regcache_write_pc (regcache, DUMMY_INSN_ADDR); - if (ARCH64 ()) - ret = rs6000_ptrace64 (PT_CONTINUE, PIDGET (inferior_ptid), 1, 0, NULL); - else - ret = rs6000_ptrace32 (PT_CONTINUE, PIDGET (inferior_ptid), - (int *) 1, 0, NULL); - - if (ret != 0) - perror (_("pt_continue")); - - do - { - pid = waitpid (PIDGET (inferior_ptid), &status, 0); - } - while (pid != PIDGET (inferior_ptid)); - - regcache_write_pc (regcache, prev_pc); - deprecated_remove_raw_breakpoint (gdbarch, bp); -} /* Set the current architecture from the host running GDB. Called when @@ -682,12 +587,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); + void *ldi = xmalloc (ldi_size); int rc = -1; while (1) @@ -709,172 +614,45 @@ rs6000_ptrace_ldinfo (ptid_t ptid) ldi = xrealloc (ldi, ldi_size); } - 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, ""); + return (gdb_byte *) ldi; } /* Implement the to_xfer_partial target_ops method for TARGET_OBJECT_LIBRARIES_AIX objects. */ -static LONGEST +static enum target_xfer_status rs6000_xfer_shared_libraries (struct target_ops *ops, enum target_object object, const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf, - ULONGEST offset, LONGEST len) + ULONGEST offset, ULONGEST len, ULONGEST *xfered_len) { - const int arch64 = ARCH64 (); - LdInfo *ldi_data; - LdInfo *ldi; - struct obstack obstack; - const char *buf; - LONGEST len_avail; - - 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. */ - - 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)); + gdb_byte *ldi_buf; + ULONGEST result; + struct cleanup *cleanup; - rs6000_xfer_shared_library (ldi, &obstack); + /* This function assumes that it is being run with a live process. + Core files are handled via gdbarch. */ + gdb_assert (target_has_execution); - if (!LDI_NEXT (ldi, arch64)) - break; - ldi = (LdInfo *) ((char *) ldi + LDI_NEXT (ldi, arch64)); - } + if (writebuf) + return TARGET_XFER_E_IO; - xfree (ldi_data); + 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); - obstack_grow_str0 (&obstack, "\n"); + do_cleanups (cleanup); - buf = obstack_finish (&obstack); - len_avail = strlen (buf); - if (offset >= len_avail) - len= 0; + if (result == 0) + return TARGET_XFER_EOF; else { - if (len > len_avail - offset) - len = len_avail - offset; - memcpy (readbuf, buf + offset, len); + *xfered_len = result; + return TARGET_XFER_OK; } - - obstack_free (&obstack, NULL); - return len; } void _initialize_rs6000_nat (void);