#include "defs.h"
#include "inferior.h"
#include "target.h"
#include "gdbcore.h"
#include "xcoffsolib.h"
#include "symfile.h"
#include "objfiles.h"
#include "libbfd.h"
#include "bfd.h"
#include "gdb-stabs.h"
#include "regcache.h"
#include "arch-utils.h"
#include "language.h"
#include "ppc-tdep.h"
#include <sys/ptrace.h>
#include <sys/reg.h>
#include <sys/param.h>
#include <sys/dir.h>
#include <sys/user.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <errno.h>
#include <a.out.h>
#include <sys/file.h>
#include "gdb_stat.h"
#include <sys/core.h>
#define __LDINFO_PTRACE32__
#define __LDINFO_PTRACE64__
#include <sys/ldr.h>
#include <sys/systemcfg.h>
#ifdef __ld_info32
# define ARCH3264
#endif
#ifndef ARCH3264
# define ARCH64() 0
#else
# define ARCH64() (REGISTER_RAW_SIZE (0) == 8)
#endif
typedef union {
#ifdef ARCH3264
struct __context64 r64;
#else
struct mstsave r64;
#endif
struct mstsave r32;
} CoreRegs;
typedef union {
#ifndef ARCH3264
struct ld_info l32;
struct ld_info l64;
#else
struct __ld_info32 l32;
struct __ld_info64 l64;
#endif
} LdInfo;
#ifndef ARCH3264
# define ARCH64_DECL(var)
#else
# define ARCH64_DECL(var) int var = ARCH64 ()
#endif
#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
#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)
extern struct vmap *map_vmap (bfd * bf, bfd * arch);
extern struct target_ops exec_ops;
static void vmap_exec (void);
static void vmap_ldinfo (LdInfo *);
static struct vmap *add_vmap (LdInfo *);
static int objfile_symbol_add (void *);
static void vmap_symtab (struct vmap *);
static void fetch_core_registers (char *, unsigned int, int, CORE_ADDR);
static void exec_one_dummy_insn (void);
extern void fixup_breakpoints (CORE_ADDR low, CORE_ADDR high, CORE_ADDR delta);
static int
regmap (int regno, int *isfloat)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
*isfloat = 0;
if (tdep->ppc_gp0_regnum <= regno && regno <= tdep->ppc_gplast_regnum)
return regno;
else if (FP0_REGNUM <= regno && regno <= FPLAST_REGNUM)
{
*isfloat = 1;
return regno - FP0_REGNUM + FPR0;
}
else if (regno == PC_REGNUM)
return IAR;
else if (regno == tdep->ppc_ps_regnum)
return MSR;
else if (regno == tdep->ppc_cr_regnum)
return CR;
else if (regno == tdep->ppc_lr_regnum)
return LR;
else if (regno == tdep->ppc_ctr_regnum)
return CTR;
else if (regno == tdep->ppc_xer_regnum)
return XER;
else if (regno == tdep->ppc_fpscr_regnum)
return FPSCR;
else if (tdep->ppc_mq_regnum >= 0 && regno == tdep->ppc_mq_regnum)
return MQ;
else
return -1;
}
static int
rs6000_ptrace32 (int req, int id, int *addr, int data, int *buf)
{
int ret = ptrace (req, id, (int *)addr, data, buf);
#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);
#endif
return ret;
}
static int
rs6000_ptrace64 (int req, int id, long long addr, int data, int *buf)
{
#ifdef ARCH3264
int ret = ptracex (req, id, addr, data, buf);
#else
int ret = 0;
#endif
#if 0
printf ("rs6000_ptrace64 (%d, %d, 0x%llx, %08x, 0x%x) = 0x%x\n",
req, id, addr, data, (unsigned int)buf, ret);
#endif
return ret;
}
static void
fetch_register (int regno)
{
int *addr = alloca (MAX_REGISTER_RAW_SIZE);
int nr, isfloat;
errno = 0;
nr = regmap (regno, &isfloat);
if (isfloat)
rs6000_ptrace32 (PT_READ_FPR, PIDGET (inferior_ptid), addr, nr, 0);
else if (nr < 0)
{
if (regno >= NUM_REGS)
fprintf_unfiltered (gdb_stderr,
"gdb error: register no %d not implemented.\n",
regno);
return;
}
else
{
if (!ARCH64 ())
*addr = rs6000_ptrace32 (PT_READ_GPR, PIDGET (inferior_ptid), (int *)nr, 0, 0);
else
{
long long buf;
rs6000_ptrace64 (PT_READ_GPR, PIDGET (inferior_ptid), nr, 0, (int *)&buf);
if (REGISTER_RAW_SIZE (regno) == 8)
memcpy (addr, &buf, 8);
else
*addr = buf;
}
}
if (!errno)
supply_register (regno, (char *) addr);
else
{
#if 0
perror ("ptrace read");
#endif
errno = 0;
}
}
static void
store_register (int regno)
{
int *addr = alloca (MAX_REGISTER_RAW_SIZE);
int nr, isfloat;
regcache_collect (regno, addr);
errno = 0;
nr = regmap (regno, &isfloat);
if (isfloat)
rs6000_ptrace32 (PT_WRITE_FPR, PIDGET (inferior_ptid), addr, nr, 0);
else if (nr < 0)
{
if (regno >= NUM_REGS)
fprintf_unfiltered (gdb_stderr,
"gdb error: register no %d not implemented.\n",
regno);
}
else
{
if (regno == SP_REGNUM)
exec_one_dummy_insn ();
if (!ARCH64 ())
rs6000_ptrace32 (PT_WRITE_GPR, PIDGET (inferior_ptid), (int *)nr, *addr, 0);
else
{
long long buf;
if (REGISTER_RAW_SIZE (regno) == 8)
memcpy (&buf, addr, 8);
else
buf = *addr;
rs6000_ptrace64 (PT_WRITE_GPR, PIDGET (inferior_ptid), nr, 0, (int *)&buf);
}
}
if (errno)
{
perror ("ptrace write");
errno = 0;
}
}
void
fetch_inferior_registers (int regno)
{
if (regno != -1)
fetch_register (regno);
else
{
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
for (regno = tdep->ppc_gp0_regnum;
regno <= tdep->ppc_gplast_regnum;
regno++)
{
fetch_register (regno);
}
for (regno = FP0_REGNUM; regno <= FPLAST_REGNUM; regno++)
fetch_register (regno);
fetch_register (PC_REGNUM);
fetch_register (tdep->ppc_ps_regnum);
fetch_register (tdep->ppc_cr_regnum);
fetch_register (tdep->ppc_lr_regnum);
fetch_register (tdep->ppc_ctr_regnum);
fetch_register (tdep->ppc_xer_regnum);
fetch_register (tdep->ppc_fpscr_regnum);
if (tdep->ppc_mq_regnum >= 0)
fetch_register (tdep->ppc_mq_regnum);
}
}
void
store_inferior_registers (int regno)
{
if (regno != -1)
store_register (regno);
else
{
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
for (regno = tdep->ppc_gp0_regnum;
regno <= tdep->ppc_gplast_regnum;
regno++)
{
store_register (regno);
}
for (regno = FP0_REGNUM; regno <= FPLAST_REGNUM; regno++)
store_register (regno);
store_register (PC_REGNUM);
store_register (tdep->ppc_ps_regnum);
store_register (tdep->ppc_cr_regnum);
store_register (tdep->ppc_lr_regnum);
store_register (tdep->ppc_ctr_regnum);
store_register (tdep->ppc_xer_regnum);
store_register (tdep->ppc_fpscr_regnum);
if (tdep->ppc_mq_regnum >= 0)
store_register (tdep->ppc_mq_regnum);
}
}
static int
read_word (CORE_ADDR from, int *to, int arch64)
{
errno = 0;
if (arch64)
*to = rs6000_ptrace64 (PT_READ_I, PIDGET (inferior_ptid), from, 0, NULL);
else
*to = rs6000_ptrace32 (PT_READ_I, PIDGET (inferior_ptid), (int *)(long) from,
0, NULL);
return !errno;
}
int
child_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
int write, struct mem_attrib *attrib,
struct target_ops *target)
{
int mask = sizeof (int) - 1;
CORE_ADDR addr = memaddr & ~(CORE_ADDR)mask;
int count = ((memaddr + len - addr + mask) & ~(CORE_ADDR)mask)
/ sizeof (int);
int *buf = (int *) alloca (count * sizeof (int));
int arch64 = ARCH64 ();
int i;
if (!write)
{
for (i = 0; i < count; i++, addr += sizeof (int))
{
if (!read_word (addr, buf + i, arch64))
return 0;
QUIT;
}
addr -= count * sizeof (int);
memcpy (myaddr, (char *)buf + (memaddr - addr), len);
}
else
{
if (addr < memaddr)
if (!read_word (addr, buf, arch64))
return 0;
if (addr + count * sizeof (int) > memaddr + len)
if (!read_word (addr, buf + count - 1, arch64))
return 0;
memcpy ((char *)buf + (memaddr - addr), myaddr, len);
for (i = 0, errno = 0; i < count; i++, addr += sizeof (int))
{
if (arch64)
rs6000_ptrace64 (PT_WRITE_D, PIDGET (inferior_ptid), addr, buf[i], NULL);
else
rs6000_ptrace32 (PT_WRITE_D, PIDGET (inferior_ptid), (int *)(long) addr,
buf[i], NULL);
if (errno)
return 0;
QUIT;
}
}
return len;
}
static void
exec_one_dummy_insn (void)
{
#define DUMMY_INSN_ADDR (TEXT_SEGMENT_BASE)+0x200
char shadow_contents[BREAKPOINT_MAX];
int ret, status, pid;
CORE_ADDR prev_pc;
target_insert_breakpoint (DUMMY_INSN_ADDR, shadow_contents);
prev_pc = read_pc ();
write_pc (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 = wait (&status);
}
while (pid != PIDGET (inferior_ptid));
write_pc (prev_pc);
target_remove_breakpoint (DUMMY_INSN_ADDR, shadow_contents);
}
static void
fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
int which, CORE_ADDR reg_addr)
{
CoreRegs *regs;
int regi;
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
if (which != 0)
{
fprintf_unfiltered
(gdb_stderr,
"Gdb error: unknown parameter to fetch_core_registers().\n");
return;
}
regs = (CoreRegs *) core_reg_sect;
if (ARCH64 ())
{
for (regi = 0; regi < 32; regi++)
supply_register (regi, (char *) ®s->r64.gpr[regi]);
for (regi = 0; regi < 32; regi++)
supply_register (FP0_REGNUM + regi, (char *) ®s->r64.fpr[regi]);
supply_register (PC_REGNUM, (char *) ®s->r64.iar);
supply_register (tdep->ppc_ps_regnum, (char *) ®s->r64.msr);
supply_register (tdep->ppc_cr_regnum, (char *) ®s->r64.cr);
supply_register (tdep->ppc_lr_regnum, (char *) ®s->r64.lr);
supply_register (tdep->ppc_ctr_regnum, (char *) ®s->r64.ctr);
supply_register (tdep->ppc_xer_regnum, (char *) ®s->r64.xer);
supply_register (tdep->ppc_fpscr_regnum, (char *) ®s->r64.fpscr);
}
else
{
for (regi = 0; regi < 32; regi++)
supply_register (regi, (char *) ®s->r32.gpr[regi]);
for (regi = 0; regi < 32; regi++)
supply_register (FP0_REGNUM + regi, (char *) ®s->r32.fpr[regi]);
supply_register (PC_REGNUM, (char *) ®s->r32.iar);
supply_register (tdep->ppc_ps_regnum, (char *) ®s->r32.msr);
supply_register (tdep->ppc_cr_regnum, (char *) ®s->r32.cr);
supply_register (tdep->ppc_lr_regnum, (char *) ®s->r32.lr);
supply_register (tdep->ppc_ctr_regnum, (char *) ®s->r32.ctr);
supply_register (tdep->ppc_xer_regnum, (char *) ®s->r32.xer);
supply_register (tdep->ppc_fpscr_regnum, (char *) ®s->r32.fpscr);
if (tdep->ppc_mq_regnum >= 0)
supply_register (tdep->ppc_mq_regnum, (char *) ®s->r32.mq);
}
}
static void
vmap_secs (struct vmap *vp, LdInfo *ldi, int arch64)
{
if (arch64)
{
vp->tstart = (CORE_ADDR) ldi->l64.ldinfo_textorg;
vp->tend = vp->tstart + ldi->l64.ldinfo_textsize;
vp->dstart = (CORE_ADDR) ldi->l64.ldinfo_dataorg;
vp->dend = vp->dstart + ldi->l64.ldinfo_datasize;
}
else
{
vp->tstart = (unsigned long) ldi->l32.ldinfo_textorg;
vp->tend = vp->tstart + ldi->l32.ldinfo_textsize;
vp->dstart = (unsigned long) ldi->l32.ldinfo_dataorg;
vp->dend = vp->dstart + ldi->l32.ldinfo_datasize;
}
vp->tstart += vp->toffs;
}
static void
vmap_symtab (struct vmap *vp)
{
register struct objfile *objfile;
struct section_offsets *new_offsets;
int i;
objfile = vp->objfile;
if (objfile == NULL)
{
if (symfile_objfile == NULL)
return;
objfile = symfile_objfile;
}
else if (!vp->loaded)
return;
new_offsets = (struct section_offsets *) alloca (SIZEOF_SECTION_OFFSETS);
for (i = 0; i < objfile->num_sections; ++i)
new_offsets->offsets[i] = ANOFFSET (objfile->section_offsets, i);
new_offsets->offsets[SECT_OFF_TEXT (objfile)] = vp->tstart - vp->tvma;
new_offsets->offsets[SECT_OFF_DATA (objfile)] = vp->dstart - vp->dvma;
new_offsets->offsets[SECT_OFF_BSS (objfile)] = vp->dstart - vp->dvma;
objfile_relocate (objfile, new_offsets);
}
static int
objfile_symbol_add (void *arg)
{
struct objfile *obj = (struct objfile *) arg;
syms_from_objfile (obj, NULL, 0, 0, 0, 0);
new_symfile_objfile (obj, 0, 0);
return 1;
}
int
vmap_add_symbols (struct vmap *vp)
{
if (catch_errors (objfile_symbol_add, vp->objfile,
"Error while reading shared library symbols:\n",
RETURN_MASK_ALL))
{
vp->loaded = 1;
vmap_symtab (vp);
return 1;
}
return 0;
}
static struct vmap *
add_vmap (LdInfo *ldi)
{
bfd *abfd, *last;
register char *mem, *objname, *filename;
struct objfile *obj;
struct vmap *vp;
int fd;
ARCH64_DECL (arch64);
filename = LDI_FILENAME (ldi, arch64);
mem = filename + strlen (filename) + 1;
mem = savestring (mem, strlen (mem));
objname = savestring (filename, strlen (filename));
fd = LDI_FD (ldi, arch64);
if (fd < 0)
abfd = bfd_openr (objname, gnutarget);
else
abfd = bfd_fdopenr (objname, gnutarget, fd);
if (!abfd)
{
warning ("Could not open `%s' as an executable file: %s",
objname, bfd_errmsg (bfd_get_error ()));
return NULL;
}
if (bfd_check_format (abfd, bfd_object))
vp = map_vmap (abfd, 0);
else if (bfd_check_format (abfd, bfd_archive))
{
last = 0;
while ((last = bfd_openr_next_archived_file (abfd, last)))
if (STREQ (mem, last->filename))
break;
if (!last)
{
warning ("\"%s\": member \"%s\" missing.", objname, mem);
bfd_close (abfd);
return NULL;
}
if (!bfd_check_format (last, bfd_object))
{
warning ("\"%s\": member \"%s\" not in executable format: %s.",
objname, mem, bfd_errmsg (bfd_get_error ()));
bfd_close (last);
bfd_close (abfd);
return NULL;
}
vp = map_vmap (last, abfd);
}
else
{
warning ("\"%s\": not in executable format: %s.",
objname, bfd_errmsg (bfd_get_error ()));
bfd_close (abfd);
return NULL;
}
obj = allocate_objfile (vp->bfd, 0);
vp->objfile = obj;
if (vp == vmap || auto_solib_add)
vmap_add_symbols (vp);
return vp;
}
static void
vmap_ldinfo (LdInfo *ldi)
{
struct stat ii, vi;
register struct vmap *vp;
int got_one, retried;
int got_exec_file = 0;
uint next;
int arch64 = ARCH64 ();
do
{
char *name = LDI_FILENAME (ldi, arch64);
char *memb = name + strlen (name) + 1;
int fd = LDI_FD (ldi, arch64);
retried = 0;
if (fstat (fd, &ii) < 0)
{
warning ("%s (fd=%d) has disappeared, keeping its symbols",
name, fd);
continue;
}
retry:
for (got_one = 0, vp = vmap; vp; vp = vp->nxt)
{
struct objfile *objfile;
if ((name[0] == '/' && !STREQ (name, vp->name))
|| (memb[0] && !STREQ (memb, vp->member)))
continue;
objfile = vp->objfile == NULL ? symfile_objfile : vp->objfile;
if (objfile == NULL
|| objfile->obfd == NULL
|| bfd_stat (objfile->obfd, &vi) < 0)
{
warning ("Unable to stat %s, keeping its symbols", name);
continue;
}
if (ii.st_dev != vi.st_dev || ii.st_ino != vi.st_ino)
continue;
if (!retried)
close (fd);
++got_one;
vmap_secs (vp, ldi, arch64);
if (vp->objfile == NULL)
got_exec_file = 1;
vmap_symtab (vp);
if (target_new_objfile_hook && vp->objfile)
target_new_objfile_hook (vp->objfile);
}
if (!got_one && !retried)
{
add_vmap (ldi);
++retried;
goto retry;
}
}
while ((next = LDI_NEXT (ldi, arch64))
&& (ldi = (void *) (next + (char *) ldi)));
if (symfile_objfile != NULL && !got_exec_file)
{
warning ("Symbol file %s\nis not mapped; discarding it.\n\
If in fact that file has symbols which the mapped files listed by\n\
\"info files\" lack, you can load symbols with the \"symbol-file\" or\n\
\"add-symbol-file\" commands (note that you must take care of relocating\n\
symbols to the proper address).",
symfile_objfile->name);
free_objfile (symfile_objfile);
symfile_objfile = NULL;
}
breakpoint_re_set (NULL);
}
static void
vmap_exec (void)
{
static bfd *execbfd;
int i;
if (execbfd == exec_bfd)
return;
execbfd = exec_bfd;
if (!vmap || !exec_ops.to_sections)
error ("vmap_exec: vmap or exec_ops.to_sections == 0\n");
for (i = 0; &exec_ops.to_sections[i] < exec_ops.to_sections_end; i++)
{
if (STREQ (".text", exec_ops.to_sections[i].the_bfd_section->name))
{
exec_ops.to_sections[i].addr += vmap->tstart - vmap->tvma;
exec_ops.to_sections[i].endaddr += vmap->tstart - vmap->tvma;
}
else if (STREQ (".data", exec_ops.to_sections[i].the_bfd_section->name))
{
exec_ops.to_sections[i].addr += vmap->dstart - vmap->dvma;
exec_ops.to_sections[i].endaddr += vmap->dstart - vmap->dvma;
}
else if (STREQ (".bss", exec_ops.to_sections[i].the_bfd_section->name))
{
exec_ops.to_sections[i].addr += vmap->dstart - vmap->dvma;
exec_ops.to_sections[i].endaddr += vmap->dstart - vmap->dvma;
}
}
}
static void
set_host_arch (int pid)
{
enum bfd_architecture arch;
unsigned long mach;
bfd abfd;
struct gdbarch_info info;
if (__power_rs ())
{
arch = bfd_arch_rs6000;
mach = bfd_mach_rs6k;
}
else
{
arch = bfd_arch_powerpc;
mach = bfd_mach_ppc;
}
if (exec_bfd)
{
const struct bfd_arch_info *exec_bfd_arch_info;
exec_bfd_arch_info = bfd_get_arch_info (exec_bfd);
if (arch == exec_bfd_arch_info->arch)
return;
}
bfd_default_set_arch_mach (&abfd, arch, mach);
gdbarch_info_init (&info);
info.bfd_arch_info = bfd_get_arch_info (&abfd);
if (!gdbarch_update_p (info))
{
internal_error (__FILE__, __LINE__,
"set_host_arch: failed to select architecture");
}
}
void
xcoff_relocate_symtab (unsigned int pid)
{
int load_segs = 64;
int rc;
LdInfo *ldi = NULL;
int arch64 = ARCH64 ();
int ldisize = arch64 ? sizeof (ldi->l64) : sizeof (ldi->l32);
int size;
do
{
size = load_segs * ldisize;
ldi = (void *) xrealloc (ldi, size);
#if 0
usleep (36000);
#endif
if (arch64)
rc = rs6000_ptrace64 (PT_LDINFO, pid, (unsigned long) ldi, size, NULL);
else
rc = rs6000_ptrace32 (PT_LDINFO, pid, (int *) ldi, size, NULL);
if (rc == -1)
{
if (errno == ENOMEM)
load_segs *= 2;
else
perror_with_name ("ptrace ldinfo");
}
else
{
vmap_ldinfo (ldi);
vmap_exec ();
}
} while (rc == -1);
if (ldi)
xfree (ldi);
}
void
xcoff_relocate_core (struct target_ops *target)
{
sec_ptr ldinfo_sec;
int offset = 0;
LdInfo *ldi;
struct vmap *vp;
int arch64 = ARCH64 ();
int nonfilesz = (int)LDI_FILENAME ((LdInfo *)0, arch64);
int buffer_size = nonfilesz;
char *buffer = xmalloc (buffer_size);
struct cleanup *old = make_cleanup (free_current_contents, &buffer);
ldinfo_sec = bfd_get_section_by_name (core_bfd, ".ldinfo");
if (ldinfo_sec == NULL)
{
bfd_err:
fprintf_filtered (gdb_stderr, "Couldn't get ldinfo from core file: %s\n",
bfd_errmsg (bfd_get_error ()));
do_cleanups (old);
return;
}
do
{
int i;
int names_found = 0;
if (bfd_get_section_contents (core_bfd, ldinfo_sec, buffer,
offset, nonfilesz) == 0)
goto bfd_err;
i = nonfilesz;
do
{
if (i == buffer_size)
{
buffer_size *= 2;
buffer = xrealloc (buffer, buffer_size);
}
if (bfd_get_section_contents (core_bfd, ldinfo_sec, &buffer[i],
offset + i, 1) == 0)
goto bfd_err;
if (buffer[i++] == '\0')
++names_found;
}
while (names_found < 2);
ldi = (LdInfo *) buffer;
if (arch64)
ldi->l64.ldinfo_fd = -1;
else
ldi->l32.ldinfo_fd = -1;
if (offset == 0 && vmap != NULL)
vp = vmap;
else
vp = add_vmap (ldi);
offset += LDI_NEXT (ldi, arch64);
if (vp == NULL)
continue;
vmap_secs (vp, ldi, arch64);
if (vp != vmap)
{
struct section_table *stp;
target_resize_to_sections (target, 2);
stp = target->to_sections_end - 2;
stp->bfd = vp->bfd;
stp->the_bfd_section = bfd_get_section_by_name (stp->bfd, ".text");
stp->addr = vp->tstart;
stp->endaddr = vp->tend;
stp++;
stp->bfd = vp->bfd;
stp->the_bfd_section = bfd_get_section_by_name (stp->bfd, ".data");
stp->addr = vp->dstart;
stp->endaddr = vp->dend;
}
vmap_symtab (vp);
if (target_new_objfile_hook && vp != vmap && vp->objfile)
target_new_objfile_hook (vp->objfile);
}
while (LDI_NEXT (ldi, arch64) != 0);
vmap_exec ();
breakpoint_re_set (NULL);
do_cleanups (old);
}
int
kernel_u_size (void)
{
return (sizeof (struct user));
}
static CORE_ADDR
find_toc_address (CORE_ADDR pc)
{
struct vmap *vp;
extern CORE_ADDR get_toc_offset (struct objfile *);
for (vp = vmap; vp; vp = vp->nxt)
{
if (pc >= vp->tstart && pc < vp->tend)
{
return vp->dstart + get_toc_offset (vp->objfile == NULL
? symfile_objfile
: vp->objfile);
}
}
error ("Unable to find TOC entry for pc %s\n", local_hex_string (pc));
}
static struct core_fns rs6000_core_fns =
{
bfd_target_xcoff_flavour,
default_check_format,
default_core_sniffer,
fetch_core_registers,
NULL
};
void
_initialize_core_rs6000 (void)
{
rs6000_find_toc_address_hook = find_toc_address;
rs6000_set_host_arch_hook = set_host_arch;
add_core_fns (&rs6000_core_fns);
}