register char *mem, *objname;
char *mem, *objname, *filename;
add_vmap PARAMS ((struct ld_info *));static intobjfile_symbol_add PARAMS ((char *));static voidvmap_symtab PARAMS ((struct vmap *));static voidfetch_core_registers PARAMS ((char *, unsigned int, int, CORE_ADDR));static voidexec_one_dummy_insn PARAMS ((void));extern voidadd_text_to_loadinfo PARAMS ((CORE_ADDR textaddr, CORE_ADDR dataaddr));extern voidfixup_breakpoints PARAMS ((CORE_ADDR low, CORE_ADDR high, CORE_ADDR delta));/* Conversion from gdb-to-system special purpose register numbers.. */static int special_regs[] = {  IAR,				/* PC_REGNUM	*/  MSR,				/* PS_REGNUM	*/  CR,				/* CR_REGNUM	*/  LR,				/* LR_REGNUM	*/  CTR,				/* CTR_REGNUM	*/  XER,				/* XER_REGNUM   */  MQ				/* MQ_REGNUM	*/};voidfetch_inferior_registers (regno)  int regno;{  int ii;  extern char registers[];  if (regno < 0) {			/* for all registers */    /* read 32 general purpose registers. */    for (ii=0; ii < 32; ++ii)      *(int*)&registers[REGISTER_BYTE (ii)] = 	ptrace (PT_READ_GPR, inferior_pid, (PTRACE_ARG3_TYPE) ii, 0, 0);    /* read general purpose floating point registers. */    for (ii=0; ii < 32; ++ii)      ptrace (PT_READ_FPR, inferior_pid, 	      (PTRACE_ARG3_TYPE) &registers [REGISTER_BYTE (FP0_REGNUM+ii)],	      FPR0+ii, 0);    /* read special registers. */    for (ii=0; ii <= LAST_SP_REGNUM-FIRST_SP_REGNUM; ++ii)      *(int*)&registers[REGISTER_BYTE (FIRST_SP_REGNUM+ii)] = 	ptrace (PT_READ_GPR, inferior_pid, (PTRACE_ARG3_TYPE) special_regs[ii],		0, 0);    registers_fetched ();    return;  }  /* else an individual register is addressed. */  else if (regno < FP0_REGNUM) {		/* a GPR */    *(int*)&registers[REGISTER_BYTE (regno)] =	ptrace (PT_READ_GPR, inferior_pid, (PTRACE_ARG3_TYPE) regno, 0, 0);  }  else if (regno <= FPLAST_REGNUM) {		/* a FPR */    ptrace (PT_READ_FPR, inferior_pid,	    (PTRACE_ARG3_TYPE) &registers [REGISTER_BYTE (regno)],	    (regno-FP0_REGNUM+FPR0), 0);  }  else if (regno <= LAST_SP_REGNUM) {		/* a special register */    *(int*)&registers[REGISTER_BYTE (regno)] =	ptrace (PT_READ_GPR, inferior_pid,		(PTRACE_ARG3_TYPE) special_regs[regno-FIRST_SP_REGNUM], 0, 0);  }  else    fprintf_unfiltered (gdb_stderr, "gdb error: register no %d not implemented.\n", regno);  register_valid [regno] = 1;}/* Store our register values back into the inferior.   If REGNO is -1, do this for all registers.   Otherwise, REGNO specifies which register (so we can save time).  */voidstore_inferior_registers (regno)     int regno;{  extern char registers[];  errno = 0;  if (regno == -1)    {			/* for all registers..	*/      int ii;       /* execute one dummy instruction (which is a breakpoint) in inferior          process. So give kernel a chance to do internal house keeping.	  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 ();      /* write general purpose registers first! */      for ( ii=GPR0; ii<=GPR31; ++ii)	{	  ptrace (PT_WRITE_GPR, inferior_pid, (PTRACE_ARG3_TYPE) ii,		  *(int*)&registers[REGISTER_BYTE (ii)], 0);	  if (errno)	    { 	      perror ("ptrace write_gpr");	      errno = 0;	    }	}      /* write floating point registers now. */      for ( ii=0; ii < 32; ++ii)	{	  ptrace (PT_WRITE_FPR, inferior_pid, 		  (PTRACE_ARG3_TYPE) &registers[REGISTER_BYTE (FP0_REGNUM+ii)],		  FPR0+ii, 0);	  if (errno)	    {	      perror ("ptrace write_fpr");	      errno = 0;	    }	}      /* write special registers. */      for (ii=0; ii <= LAST_SP_REGNUM-FIRST_SP_REGNUM; ++ii)	{	  ptrace (PT_WRITE_GPR, inferior_pid,		  (PTRACE_ARG3_TYPE) special_regs[ii],		  *(int*)&registers[REGISTER_BYTE (FIRST_SP_REGNUM+ii)], 0);	  if (errno)	    {	      perror ("ptrace write_gpr");	      errno = 0;	    }	}    }  /* else, a specific register number is given... */  else if (regno < FP0_REGNUM)			/* a GPR */    {      ptrace (PT_WRITE_GPR, inferior_pid, (PTRACE_ARG3_TYPE) regno,	      *(int*)&registers[REGISTER_BYTE (regno)], 0);    }  else if (regno <= FPLAST_REGNUM)		/* a FPR */    {      ptrace (PT_WRITE_FPR, inferior_pid, 	      (PTRACE_ARG3_TYPE) &registers[REGISTER_BYTE (regno)],	      regno - FP0_REGNUM + FPR0, 0);    }  else if (regno <= LAST_SP_REGNUM)		/* a special register */    {      ptrace (PT_WRITE_GPR, inferior_pid,	      (PTRACE_ARG3_TYPE) special_regs [regno-FIRST_SP_REGNUM],	      *(int*)&registers[REGISTER_BYTE (regno)], 0);    }  else    fprintf_unfiltered (gdb_stderr, "Gdb error: register no %d not implemented.\n", regno);  if (errno)    {      perror ("ptrace write");      errno = 0;    }}/* 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 voidexec_one_dummy_insn (){#define	DUMMY_INSN_ADDR	(TEXT_SEGMENT_BASE)+0x200  char shadow_contents[BREAKPOINT_MAX];	/* Stash old bkpt addr contents */  unsigned int status, pid;  CORE_ADDR prev_pc;  /* We plant one dummy breakpoint into DUMMY_INSN_ADDR address. We assume that     this address will never be executed again by the real code. */  target_insert_breakpoint (DUMMY_INSN_ADDR, shadow_contents);  errno = 0;  /* 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 = read_pc ();  write_pc (DUMMY_INSN_ADDR);  ptrace (PT_CONTINUE, inferior_pid, (PTRACE_ARG3_TYPE)1, 0, 0);  if (errno)    perror ("pt_continue");  do {    pid = wait (&status);  } while (pid != inferior_pid);      write_pc (prev_pc);  target_remove_breakpoint (DUMMY_INSN_ADDR, shadow_contents);}static voidfetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)     char *core_reg_sect;     unsigned core_reg_size;     int which;     CORE_ADDR reg_addr;	/* Unused in this version */{  /* fetch GPRs and special registers from the first register section     in core bfd. */  if (which == 0)    {      /* copy GPRs first. */      memcpy (registers, core_reg_sect, 32 * 4);      /* gdb's internal register template and bfd's register section layout	 should share a common include file. FIXMEmgo */      /* then comes special registes. They are supposed to be in the same	 order in gdb template and bfd `.reg' section. */      core_reg_sect += (32 * 4);      memcpy (&registers [REGISTER_BYTE (FIRST_SP_REGNUM)], core_reg_sect, 	      (LAST_SP_REGNUM - FIRST_SP_REGNUM + 1) * 4);    }  /* fetch floating point registers from register section 2 in core bfd. */  else if (which == 2)    memcpy (&registers [REGISTER_BYTE (FP0_REGNUM)], core_reg_sect, 32 * 8);  else    fprintf_unfiltered (gdb_stderr, "Gdb error: unknown parameter to fetch_core_registers().\n");}/* handle symbol translation on vmapping */static voidvmap_symtab (vp)     register struct vmap *vp;{  register struct objfile *objfile;  CORE_ADDR text_delta;  CORE_ADDR data_delta;  CORE_ADDR bss_delta;  struct section_offsets *new_offsets;  int i;    objfile = vp->objfile;  if (objfile == NULL)    {      /* OK, it's not an objfile we opened ourselves.	 Currently, that can only happen with the exec file, so	 relocate the symbols for the symfile.  */      if (symfile_objfile == NULL)	return;      objfile = symfile_objfile;    }  new_offsets = alloca    (sizeof (struct section_offsets)     + sizeof (new_offsets->offsets) * objfile->num_sections);  for (i = 0; i < objfile->num_sections; ++i)    ANOFFSET (new_offsets, i) = ANOFFSET (objfile->section_offsets, i);    text_delta =    vp->tstart - ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT);  ANOFFSET (new_offsets, SECT_OFF_TEXT) = vp->tstart;  data_delta =    vp->dstart - ANOFFSET (objfile->section_offsets, SECT_OFF_DATA);  ANOFFSET (new_offsets, SECT_OFF_DATA) = vp->dstart;    bss_delta =    vp->dstart - ANOFFSET (objfile->section_offsets, SECT_OFF_BSS);  ANOFFSET (new_offsets, SECT_OFF_BSS) = vp->dstart;  objfile_relocate (objfile, new_offsets);}/* Add symbols for an objfile.  */static intobjfile_symbol_add (arg)     char *arg;{  struct objfile *obj = (struct objfile *) arg;  syms_from_objfile (obj, 0, 0, 0);  new_symfile_objfile (obj, 0, 0);  return 1;}/* Add a new vmap entry based on ldinfo() information.   If ldi->ldinfo_fd is not valid (e.g. this struct ld_info is from a   core file), the caller should set it to -1, and we will open the file.   Return the vmap new entry.  */static struct vmap *add_vmap (ldi)     register struct ld_info *ldi; {  bfd *abfd, *last;  register char *mem, *objname;  struct objfile *obj;  struct vmap *vp;  /* This ldi structure was allocated using alloca() in      xcoff_relocate_symtab(). Now we need to have persistent object      and member names, so we should save them. */  mem = ldi->ldinfo_filename + strlen (ldi->ldinfo_filename) + 1;  mem = savestring (mem, strlen (mem));  objname = savestring (ldi->ldinfo_filename, strlen (ldi->ldinfo_filename));  if (ldi->ldinfo_fd < 0)    /* Note that this opens it once for every member; a possible       enhancement would be to only open it once for every object.  */    abfd = bfd_openr (objname, gnutarget);  else    abfd = bfd_fdopenr (objname, gnutarget, ldi->ldinfo_fd);  if (!abfd)    error ("Could not open `%s' as an executable file: %s",	   objname, bfd_errmsg (bfd_get_error ()));  /* make sure we have an object file */  if (bfd_check_format (abfd, bfd_object))    vp = map_vmap (abfd, 0);  else if (bfd_check_format (abfd, bfd_archive))    {      last = 0;      /* FIXME??? am I tossing BFDs?  bfd? */      while ((last = bfd_openr_next_archived_file (abfd, last)))	if (STREQ (mem, last->filename))	  break;      if (!last)	{	  bfd_close (abfd);	  /* FIXME -- should be error */	  warning ("\"%s\": member \"%s\" missing.", abfd->filename, mem);	  return 0;	}      if (!bfd_check_format(last, bfd_object))	{	  bfd_close (last);	/* XXX???	*/	  goto obj_err;	}      vp = map_vmap (last, abfd);    }  else    {    obj_err:      bfd_close (abfd);      error ("\"%s\": not in executable format: %s.",	     objname, bfd_errmsg (bfd_get_error ()));      /*NOTREACHED*/    }  obj = allocate_objfile (vp->bfd, 0);  vp->objfile = obj;#ifndef SOLIB_SYMBOLS_MANUAL  if (catch_errors (objfile_symbol_add, (char *)obj,		    "Error while reading shared library symbols:\n",		    RETURN_MASK_ALL))    {      /* Note this is only done if symbol reading was successful.  */      vmap_symtab (vp);      vp->loaded = 1;    }#endif  return vp;}