Add --binary-architecture switch to objcopy to allow the output architecture
[deliverable/binutils-gdb.git] / gdb / arm-tdep.c
index 7112c4caf71d00a877013222a6ec8241e4b72674..a4d16329402a3e4da6f78bab309cdbc8aa36f6d6 100644 (file)
@@ -1,6 +1,6 @@
 /* Common target dependent code for GDB on ARM systems.
-   Copyright 1988, 1989, 1991, 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000
-   Free Software Foundation, Inc.
+   Copyright 1988, 1989, 1991, 1992, 1993, 1995, 1996, 1998, 1999, 2000,
+   2001 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "coff/internal.h"     /* Internal format of COFF symbols in BFD */
 #include "dis-asm.h"           /* For register flavors. */
 #include <ctype.h>             /* for isupper () */
+#include "regcache.h"
+
+/* Each OS has a different mechanism for accessing the various
+   registers stored in the sigcontext structure.
+
+   SIGCONTEXT_REGISTER_ADDRESS should be defined to the name (or
+   function pointer) which may be used to determine the addresses
+   of the various saved registers in the sigcontext structure.
+
+   For the ARM target, there are three parameters to this function. 
+   The first is the pc value of the frame under consideration, the
+   second the stack pointer of this frame, and the last is the
+   register number to fetch.  
+
+   If the tm.h file does not define this macro, then it's assumed that
+   no mechanism is needed and we define SIGCONTEXT_REGISTER_ADDRESS to
+   be 0. 
+   
+   When it comes time to multi-arching this code, see the identically
+   named machinery in ia64-tdep.c for an example of how it could be
+   done.  It should not be necessary to modify the code below where
+   this macro is used.  */
+
+#ifdef SIGCONTEXT_REGISTER_ADDRESS
+#ifndef SIGCONTEXT_REGISTER_ADDRESS_P
+#define SIGCONTEXT_REGISTER_ADDRESS_P() 1
+#endif
+#else
+#define SIGCONTEXT_REGISTER_ADDRESS(SP,PC,REG) 0
+#define SIGCONTEXT_REGISTER_ADDRESS_P() 0
+#endif
 
 extern void _initialize_arm_tdep (void);
 
@@ -52,10 +83,10 @@ static char * arm_register_name_strings[] =
 char **arm_register_names = arm_register_name_strings;
 
 /* Valid register name flavors.  */
-static char **valid_flavors;
+static const char **valid_flavors;
 
 /* Disassembly flavor to use. Default to "std" register names. */
-static char *disassembly_flavor;
+static const char *disassembly_flavor;
 static int current_option;     /* Index to that option in the opcodes table. */
 
 /* This is used to keep the bfd arch_info in sync with the disassembly
@@ -226,7 +257,7 @@ static int caller_is_thumb;
    function.  */
 
 int
-arm_pc_is_thumb (bfd_vma memaddr)
+arm_pc_is_thumb (CORE_ADDR memaddr)
 {
   struct minimal_symbol *sym;
 
@@ -250,7 +281,7 @@ arm_pc_is_thumb (bfd_vma memaddr)
    dummy being called from a Thumb function.  */
 
 int
-arm_pc_is_thumb_dummy (bfd_vma memaddr)
+arm_pc_is_thumb_dummy (CORE_ADDR memaddr)
 {
   CORE_ADDR sp = read_sp ();
 
@@ -605,7 +636,7 @@ check_prologue_cache (struct frame_info *fi)
       fi->framereg = prologue_cache.framereg;
       fi->framesize = prologue_cache.framesize;
       fi->frameoffset = prologue_cache.frameoffset;
-      for (i = 0; i <= NUM_REGS; i++)
+      for (i = 0; i < NUM_REGS; i++)
        fi->fsr.regs[i] = prologue_cache.fsr.regs[i];
       return 1;
     }
@@ -626,7 +657,7 @@ save_prologue_cache (struct frame_info *fi)
   prologue_cache.framesize = fi->framesize;
   prologue_cache.frameoffset = fi->frameoffset;
 
-  for (i = 0; i <= NUM_REGS; i++)
+  for (i = 0; i < NUM_REGS; i++)
     prologue_cache.fsr.regs[i] = fi->fsr.regs[i];
 }
 
@@ -725,14 +756,42 @@ arm_scan_prologue (struct frame_info *fi)
      the symbol table, peek in the stack frame to find the PC.  */
   if (find_pc_partial_function (fi->pc, NULL, &prologue_start, &prologue_end))
     {
-      /* Assume the prologue is everything between the first instruction
-         in the function and the first source line.  */
-      struct symtab_and_line sal = find_pc_line (prologue_start, 0);
-
-      if (sal.line == 0)       /* no line info, use current PC */
-       prologue_end = fi->pc;
-      else if (sal.end < prologue_end) /* next line begins after fn end */
-       prologue_end = sal.end; /* (probably means no prologue)  */
+      /* One way to find the end of the prologue (which works well
+         for unoptimized code) is to do the following:
+
+           struct symtab_and_line sal = find_pc_line (prologue_start, 0);
+
+           if (sal.line == 0)
+             prologue_end = fi->pc;
+           else if (sal.end < prologue_end)
+             prologue_end = sal.end;
+
+        This mechanism is very accurate so long as the optimizer
+        doesn't move any instructions from the function body into the
+        prologue.  If this happens, sal.end will be the last
+        instruction in the first hunk of prologue code just before
+        the first instruction that the scheduler has moved from
+        the body to the prologue.
+
+        In order to make sure that we scan all of the prologue
+        instructions, we use a slightly less accurate mechanism which
+        may scan more than necessary.  To help compensate for this
+        lack of accuracy, the prologue scanning loop below contains
+        several clauses which'll cause the loop to terminate early if
+        an implausible prologue instruction is encountered.  
+        
+        The expression
+        
+             prologue_start + 64
+           
+        is a suitable endpoint since it accounts for the largest
+        possible prologue plus up to five instructions inserted by
+        the scheduler. */
+         
+      if (prologue_end > prologue_start + 64)
+       {
+         prologue_end = prologue_start + 64;   /* See above. */
+       }
     }
   else
     {
@@ -740,10 +799,7 @@ arm_scan_prologue (struct frame_info *fi)
          PC is the address of the stmfd + 8.  */
       prologue_start = ADDR_BITS_REMOVE (read_memory_integer (fi->frame, 4))
        - 8;
-      prologue_end = prologue_start + 64;      /* This is all the insn's
-                                                  that could be in the prologue,
-                                                  plus room for 5 insn's inserted
-                                                  by the scheduler.  */
+      prologue_end = prologue_start + 64;      /* See above. */
     }
 
   /* Now search the prologue looking for instructions that set up the
@@ -833,6 +889,10 @@ arm_scan_prologue (struct frame_info *fi)
                  fi->fsr.regs[fp_start_reg++] = sp_offset;
                }
            }
+         else if ((insn & 0xf0000000) != 0xe0000000)
+           break;      /* Condition not true, exit early */
+         else if ((insn & 0xfe200000) == 0xe8200000) /* ldm? */
+           break;      /* Don't scan past a block load */
          else
            /* The optimizer might shove anything into the prologue,
               so we just skip what we don't recognize. */
@@ -973,6 +1033,40 @@ arm_init_extra_frame_info (int fromleaf, struct frame_info *fi)
     }
   else
 #endif
+
+  /* Determine whether or not we're in a sigtramp frame. 
+     Unfortunately, it isn't sufficient to test
+     fi->signal_handler_caller because this value is sometimes set
+     after invoking INIT_EXTRA_FRAME_INFO.  So we test *both*
+     fi->signal_handler_caller and IN_SIGTRAMP to determine if we need
+     to use the sigcontext addresses for the saved registers.
+
+     Note: If an ARM IN_SIGTRAMP method ever needs to compare against
+     the name of the function, the code below will have to be changed
+     to first fetch the name of the function and then pass this name
+     to IN_SIGTRAMP. */
+
+  if (SIGCONTEXT_REGISTER_ADDRESS_P () 
+      && (fi->signal_handler_caller || IN_SIGTRAMP (fi->pc, 0)))
+    {
+      CORE_ADDR sp;
+
+      if (!fi->next)
+       sp = read_sp();
+      else
+       sp = fi->next->frame - fi->next->frameoffset + fi->next->framesize;
+
+      for (reg = 0; reg < NUM_REGS; reg++)
+       fi->fsr.regs[reg] = SIGCONTEXT_REGISTER_ADDRESS (sp, fi->pc, reg);
+
+      /* FIXME: What about thumb mode? */
+      fi->framereg = SP_REGNUM;
+      fi->frame = read_memory_integer (fi->fsr.regs[fi->framereg], 4);
+      fi->framesize = 0;
+      fi->frameoffset = 0;
+
+    }
+  else
     {
       arm_scan_prologue (fi);
 
@@ -2037,7 +2131,9 @@ _initialize_arm_tdep (void)
   struct ui_file *stb;
   long length;
   struct cmd_list_element *new_cmd;
-  const char *setname, *setdesc, **regnames;
+  const char *setname;
+  const char *setdesc;
+  const char **regnames;
   int numregs, i, j;
   static char *helptext;
 
@@ -2059,13 +2155,13 @@ The valid values are:\n");
   for (i = 0; i < num_flavor_options; i++)
     {
       numregs = get_arm_regnames (i, &setname, &setdesc, &regnames);
-      valid_flavors[i] = (char *) setname;
+      valid_flavors[i] = setname;
       fprintf_unfiltered (stb, "%s - %s\n", setname,
                          setdesc);
       /* Copy the default names (if found) and synchronize disassembler. */
       if (!strcmp (setname, "std"))
        {
-          disassembly_flavor = (char *) setname;
+          disassembly_flavor = setname;
           current_option = i;
          for (j = 0; j < numregs; j++)
             arm_register_names[j] = (char *) regnames[j];
@@ -2083,7 +2179,7 @@ The valid values are:\n");
   /* Add the disassembly-flavor command */
   new_cmd = add_set_enum_cmd ("disassembly-flavor", no_class,
                              valid_flavors,
-                             (char *) &disassembly_flavor,
+                             &disassembly_flavor,
                              helptext,
                              &setlist);
   new_cmd->function.sfunc = set_disassembly_flavor_sfunc;
This page took 0.027247 seconds and 4 git commands to generate.