static CORE_ADDR
skip_hurd_resolver (CORE_ADDR pc)
{
  /* The HURD dynamic linker is part of the GNU C library, so many
     GNU/Linux distributions use it.  (All ELF versions, as far as I
     know.)  An unresolved PLT entry points to "_dl_runtime_resolve",
     which calls "fixup" to patch the PLT, and then passes control to
     the function.

     We look for the symbol `_dl_runtime_resolve', and find `fixup' in
     the same objfile.  If we are at the entry point of `fixup', then
     we set a breakpoint at the return address (at the top of the
     stack), and continue.
  
     It's kind of gross to do all these checks every time we're
     called, since they don't change once the executable has gotten
     started.  But this is only a temporary hack --- upcoming versions
     of GNU/Linux will provide a portable, efficient interface for
     debugging programs that use shared libraries.  */

  struct objfile *objfile;
  struct minimal_symbol *resolver 
    = find_minsym_and_objfile ("_dl_runtime_resolve", &objfile);

  if (resolver)
    {
      struct minimal_symbol *fixup
	= lookup_minimal_symbol ("fixup", NULL, objfile);

      if (fixup && SYMBOL_VALUE_ADDRESS (fixup) == pc)
	return (SAVED_PC_AFTER_CALL (get_current_frame ()));
    }

  return 0;
}      
Beispiel #2
0
void
init_frame_pc_default (int fromleaf, struct frame_info *prev)
{
  if (fromleaf)
    prev->pc = SAVED_PC_AFTER_CALL (prev->next);
  else if (prev->next != NULL)
    prev->pc = FRAME_SAVED_PC (prev->next);
  else
    prev->pc = read_pc ();
}
Beispiel #3
0
int
frame_num_args (struct frame_info *fi)
{
    CORE_ADDR enter_addr;
    CORE_ADDR argp;
    int inst;
    int args;
    int i;

    if (read_memory_integer (fi->frame, 4) == 0 && fi->pc < 0x10000)
    {
        /* main is always called with three args */
        return (3);
    }
    enter_addr = ns32k_get_enter_addr (fi->pc);
    if (enter_addr = 0)
        return (-1);
    argp = enter_addr == 1 ? SAVED_PC_AFTER_CALL (fi) : FRAME_SAVED_PC (fi);
    for (i = 0; i < 16; i++)
    {
        /*
         * After a bsr gcc may emit the following instructions
         * to remove the arguments from the stack:
         *   cmpqd 0,tos        - to remove 4 bytes from the stack
         *   cmpd tos,tos       - to remove 8 bytes from the stack
         *   adjsp[bwd] -n      - to remove n bytes from the stack
         * Gcc sometimes delays emitting these instructions and
         * may even throw a branch between our feet.
         */
        inst = read_memory_integer (argp, 4);
        args = read_memory_integer (argp + 2, 4);
        if ((inst & 0xff) == 0xea)
        {   /* br */
            args = ((inst >> 8) & 0xffffff) | (args << 24);
            if (args & 0x80)
            {
                if (args & 0x40)
                {
                    args = ntohl (args);
                }
                else
                {
                    args = ntohs (args & 0xffff);
                    if (args & 0x2000)
                        args |= 0xc000;
                }
            }
            else
            {
                args = args & 0xff;
                if (args & 0x40)
                    args |= 0x80;
            }
            argp += args;
            continue;
        }
        if ((inst & 0xffff) == 0xb81f)	/* cmpqd 0,tos */
            return (1);
        else if ((inst & 0xffff) == 0xbdc7)	/* cmpd tos,tos */
            return (2);
        else if ((inst & 0xfffc) == 0xa57c)
        {   /* adjsp[bwd] */
            switch (inst & 3)
            {
            case 0:
                args = ((args & 0xff) + 0x80);
                break;
            case 1:
                args = ((ntohs (args) & 0xffff) + 0x8000);
                break;
            case 3:
                args = -ntohl (args);
                break;
            default:
                return (-1);
            }
            if (args / 4 > 10 || (args & 3) != 0)
                continue;
            return (args / 4);
        }
        argp += 1;
    }