]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
More merging.
authorAndrew Cagney <cagney@redhat.com>
Fri, 21 Jun 2002 16:46:56 +0000 (16:46 +0000)
committerAndrew Cagney <cagney@redhat.com>
Fri, 21 Jun 2002 16:46:56 +0000 (16:46 +0000)
19 files changed:
gdb/ada-exp.y
gdb/c-exp.y
gdb/config/m68k/tm-m68k.h
gdb/dwarf2cfi.c
gdb/event-top.c
gdb/f-exp.y
gdb/jv-exp.y
gdb/m2-exp.y
gdb/m68k-tdep.c
gdb/osabi.c
gdb/osabi.h
gdb/p-exp.y
gdb/parse.c
gdb/parser-defs.h
gdb/regcache.c
gdb/regcache.h
gdb/x86-64-linux-nat.c
gdb/x86-64-tdep.c
gdb/x86-64-tdep.h

index 7d46dd2cf8b749fa7a890ccf995815df41baa723..67185a3e497dd99791ce1763669a0bb68c96c87d 100644 (file)
@@ -92,9 +92,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #define yytoks ada_toks                /* With YYDEBUG defined */
 
 #ifndef YYDEBUG
-#define        YYDEBUG 0               /* Default to no yydebug support */
+#define        YYDEBUG 1               /* Default to yydebug support */
 #endif
 
+#define YYFPRINTF parser_fprintf
+
 struct name_info {
   struct symbol* sym;
   struct minimal_symbol* msym;
index f555518ea0013c7ba40bf6e8135d1d89d185af52..ea5083646e0ef785a41e17281206659ad0d80f57 100644 (file)
@@ -100,9 +100,11 @@ extern int hp_som_som_object_present;
 #define yycheck         c_yycheck
 
 #ifndef YYDEBUG
-#define        YYDEBUG 0               /* Default to no yydebug support */
+#define        YYDEBUG 1               /* Default to yydebug support */
 #endif
 
+#define YYFPRINTF parser_fprintf
+
 int yyparse (void);
 
 static int yylex (void);
index 8f0f6a843a96ad62bc1af3d5d63584410c7121cc..c114be0b184d48a596374d6ebd3d27ab615b9e27 100644 (file)
@@ -48,11 +48,8 @@ extern CORE_ADDR m68k_skip_prologue (CORE_ADDR ip);
    some instructions.  */
 
 struct frame_info;
-struct frame_saved_regs;
 
 extern CORE_ADDR m68k_saved_pc_after_call (struct frame_info *);
-extern void m68k_find_saved_regs (struct frame_info *,
-                                 struct frame_saved_regs *);
 
 #define SAVED_PC_AFTER_CALL(frame) \
   m68k_saved_pc_after_call(frame)
@@ -287,16 +284,6 @@ extern void m68k_find_saved_regs (struct frame_info *,
 /* Return number of bytes at start of arglist that are not really args.  */
 
 #define FRAME_ARGS_SKIP 8
-
-/* Put here the code to store, into a struct frame_saved_regs,
-   the addresses of the saved registers of frame described by FRAME_INFO.
-   This includes special registers such as pc and fp saved in special
-   ways in the stack frame.  sp is even more special:
-   the address we return for it IS the sp for the next frame.  */
-
-#if !defined (FRAME_FIND_SAVED_REGS)
-#define FRAME_FIND_SAVED_REGS(fi,fsr) m68k_find_saved_regs ((fi), &(fsr))
-#endif /* no FIND_FRAME_SAVED_REGS.  */
 \f
 
 /* Things needed for making the inferior call functions.  */
@@ -330,7 +317,7 @@ extern void m68k_find_saved_regs (struct frame_info *,
 /* FIXME: Wrong to hardwire this as BPT_VECTOR when sometimes it
    should be REMOTE_BPT_VECTOR.  Best way to fix it would be to define
    CALL_DUMMY_BREAKPOINT_OFFSET.  */
-
+#if !GDB_MULTI_ARCH_PARTIAL
 #define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, (0x4e404e71 | (BPT_VECTOR << 16))}
 #define CALL_DUMMY_LENGTH 28   /* Size of CALL_DUMMY */
 #define CALL_DUMMY_START_OFFSET 12     /* Offset to jsr instruction */
@@ -355,7 +342,7 @@ extern void m68k_pop_frame (void);
 /* Discard from the stack the innermost frame, restoring all registers.  */
 
 #define POP_FRAME              { m68k_pop_frame (); }
-
+#endif
 /* Offset from SP to first arg on stack at first instruction of a function */
 
 #define SP_ARG0 (1 * 4)
index ea501551c8e6412ef0402de9d626ea6aca924a7b..442ae70e54039fbc652190b9102ab3c7954fc053 100644 (file)
@@ -34,7 +34,7 @@
    Frame Descriptors.  */
 struct cie_unit
 {
-  /* Offset of this unit in dwarf_frame_buffer.  */
+  /* Offset of this unit in .debug_frame or .eh_frame.  */
   ULONGEST offset;
 
   /* A null-terminated string that identifies the augmentation to this CIE or
@@ -176,6 +176,15 @@ struct frame_state
   struct objfile *objfile;
 };
 
+enum ptr_encoding
+{
+  PE_absptr = DW_EH_PE_absptr,
+  PE_pcrel = DW_EH_PE_pcrel,
+  PE_textrel = DW_EH_PE_textrel,
+  PE_datarel = DW_EH_PE_datarel,
+  PE_funcrel = DW_EH_PE_funcrel
+};
+
 #define UNWIND_CONTEXT(fi) ((struct context *) (fi->context))
 \f
 
@@ -188,8 +197,6 @@ extern file_ptr dwarf_frame_offset;
 extern unsigned int dwarf_frame_size;
 extern file_ptr dwarf_eh_frame_offset;
 extern unsigned int dwarf_eh_frame_size;
-
-static char *dwarf_frame_buffer;
 \f
 
 extern char *dwarf2_read_section (struct objfile *objfile, file_ptr offset,
@@ -219,6 +226,7 @@ static LONGEST read_sleb128 (bfd * abfd, char **p);
 static CORE_ADDR read_pointer (bfd * abfd, char **p);
 static CORE_ADDR read_encoded_pointer (bfd * abfd, char **p,
                                       unsigned char encoding);
+static enum ptr_encoding pointer_encoding (unsigned char encoding);
 
 static LONGEST read_initial_length (bfd * abfd, char *buf, int *bytes_read);
 static ULONGEST read_length (bfd * abfd, char *buf, int *bytes_read,
@@ -494,6 +502,9 @@ read_pointer (bfd * abfd, char **p)
     }
 }
 
+/* This functions only reads appropriate amount of data from *p 
+ * and returns the resulting value. Calling function must handle
+ * different encoding possibilities itself!  */
 static CORE_ADDR
 read_encoded_pointer (bfd * abfd, char **p, unsigned char encoding)
 {
@@ -537,22 +548,33 @@ read_encoded_pointer (bfd * abfd, char **p, unsigned char encoding)
                      "read_encoded_pointer: unknown pointer encoding");
     }
 
-  if (ret != 0)
-    switch (encoding & 0xf0)
-      {
-      case DW_EH_PE_absptr:
-       break;
-      case DW_EH_PE_pcrel:
-       ret += (CORE_ADDR) * p;
-       break;
-      case DW_EH_PE_textrel:
-      case DW_EH_PE_datarel:
-      case DW_EH_PE_funcrel:
-      default:
-       internal_error (__FILE__, __LINE__,
-                       "read_encoded_pointer: unknown pointer encoding");
-      }
+  return ret;
+}
 
+/* Variable 'encoding' carries 3 different flags:
+ * - encoding & 0x0f : size of the address (handled in read_encoded_pointer())
+ * - encoding & 0x70 : type (absolute, relative, ...)
+ * - encoding & 0x80 : indirect flag (DW_EH_PE_indirect == 0x80).  */
+enum ptr_encoding
+pointer_encoding (unsigned char encoding)
+{
+  int ret;
+
+  if (encoding & DW_EH_PE_indirect)
+    warning ("CFI: Unsupported pointer encoding: DW_EH_PE_indirect");
+
+  switch (encoding & 0x70)
+    {
+    case DW_EH_PE_absptr:
+    case DW_EH_PE_pcrel:
+    case DW_EH_PE_textrel:
+    case DW_EH_PE_datarel:
+    case DW_EH_PE_funcrel:
+      ret = encoding & 0x70;
+      break;
+    default:
+      internal_error (__FILE__, __LINE__, "CFI: unknown pointer encoding");
+    }
   return ret;
 }
 
@@ -627,6 +649,10 @@ execute_cfa_program (struct objfile *objfile, char *insn_ptr, char *insn_end,
          case DW_CFA_set_loc:
            fs->pc = read_encoded_pointer (objfile->obfd, &insn_ptr,
                                           fs->addr_encoding);
+
+           if (pointer_encoding (fs->addr_encoding) != PE_absptr)
+             warning ("CFI: DW_CFA_set_loc uses relative addressing");
+
            break;
 
          case DW_CFA_advance_loc1:
@@ -1380,39 +1406,46 @@ compare_fde_unit (const void *a, const void *b)
 }
 
 /*  Build the cie_chunks and fde_chunks tables from informations
-    in .debug_frame section.  */
-void
-dwarf2_build_frame_info (struct objfile *objfile)
+    found in .debug_frame and .eh_frame sections.  */
+/* We can handle both of these sections almost in the same way, however there
+   are some exceptions:
+   - CIE ID is -1 in debug_frame, but 0 in eh_frame
+   - eh_frame may contain some more information that are used only by gcc 
+     (eg. personality pointer, LSDA pointer, ...). Most of them we can ignore.
+   - In debug_frame FDE's item cie_id contains offset of it's parent CIE.
+     In eh_frame FDE's item cie_id is a relative pointer to the parent CIE.
+     Anyway we don't need to bother with this, because we are smart enough 
+     to keep the pointer to the parent CIE of oncomming FDEs in 'last_cie'.
+   - Although debug_frame items can contain Augmentation as well as 
+     eh_frame ones, I have never seen them non-empty. Thus only in eh_frame 
+     we can encounter for example non-absolute pointers (Aug. 'R').  
+                                                              -- mludvig  */
+static void
+parse_frame_info (struct objfile *objfile, file_ptr frame_offset,
+                 unsigned int frame_size, int eh_frame)
 {
   bfd *abfd = objfile->obfd;
+  asection *curr_section_ptr;
   char *start = NULL;
   char *end = NULL;
-  int from_eh = 0;
+  char *frame_buffer = NULL;
+  char *curr_section_name, *aug_data;
+  struct cie_unit *last_cie = NULL;
+  int last_dup_fde = 0;
+  int aug_len, i;
+  CORE_ADDR curr_section_vma = 0;
 
   unwind_tmp_obstack_init ();
 
-  dwarf_frame_buffer = 0;
-
-  if (dwarf_frame_offset)
-    {
-      dwarf_frame_buffer = dwarf2_read_section (objfile,
-                                               dwarf_frame_offset,
-                                               dwarf_frame_size);
+  frame_buffer = dwarf2_read_section (objfile, frame_offset, frame_size);
 
-      start = dwarf_frame_buffer;
-      end = dwarf_frame_buffer + dwarf_frame_size;
-    }
-  else if (dwarf_eh_frame_offset)
-    {
-      dwarf_frame_buffer = dwarf2_read_section (objfile,
-                                               dwarf_eh_frame_offset,
-                                               dwarf_eh_frame_size);
+  start = frame_buffer;
+  end = frame_buffer + frame_size;
 
-      start = dwarf_frame_buffer;
-      end = dwarf_frame_buffer + dwarf_eh_frame_size;
-
-      from_eh = 1;
-    }
+  curr_section_name = eh_frame ? ".eh_frame" : ".debug_frame";
+  curr_section_ptr = bfd_get_section_by_name (abfd, curr_section_name);
+  if (curr_section_ptr)
+    curr_section_vma = curr_section_ptr->vma;
 
   if (start)
     {
@@ -1420,9 +1453,8 @@ dwarf2_build_frame_info (struct objfile *objfile)
        {
          unsigned long length;
          ULONGEST cie_id;
-         ULONGEST unit_offset = start - dwarf_frame_buffer;
-         int bytes_read;
-         int dwarf64;
+         ULONGEST unit_offset = start - frame_buffer;
+         int bytes_read, dwarf64;
          char *block_end;
 
          length = read_initial_length (abfd, start, &bytes_read);
@@ -1430,10 +1462,16 @@ dwarf2_build_frame_info (struct objfile *objfile)
          dwarf64 = (bytes_read == 12);
          block_end = start + length;
 
+         if (length == 0)
+           {
+             start = block_end;
+             continue;
+           }
+
          cie_id = read_length (abfd, start, &bytes_read, dwarf64);
          start += bytes_read;
 
-         if ((from_eh && cie_id == 0) || is_cie (cie_id, dwarf64))
+         if ((eh_frame && cie_id == 0) || is_cie (cie_id, dwarf64))
            {
              struct cie_unit *cie = cie_unit_alloc ();
              char *aug;
@@ -1449,87 +1487,186 @@ dwarf2_build_frame_info (struct objfile *objfile)
              start++;          /* version */
 
              cie->augmentation = aug = start;
-             while (*start)
-               start++;
-             start++;          /* skip past NUL */
+             while (*start++); /* Skips last NULL as well */
 
              cie->code_align = read_uleb128 (abfd, &start);
              cie->data_align = read_sleb128 (abfd, &start);
              cie->ra = read_1u (abfd, &start);
 
+             /* Augmentation:
+                z      Indicates that a uleb128 is present to size the
+                augmentation section.
+                L      Indicates the encoding (and thus presence) of
+                an LSDA pointer in the FDE augmentation.
+                R      Indicates a non-default pointer encoding for
+                FDE code pointers.
+                P      Indicates the presence of an encoding + language
+                personality routine in the CIE augmentation.
+
+                [This info comes from GCC's dwarf2out.c]
+              */
              if (*aug == 'z')
                {
-                 int xtra = read_uleb128 (abfd, &start);
-                 start += xtra;
+                 aug_len = read_uleb128 (abfd, &start);
+                 aug_data = start;
+                 start += aug_len;
                  ++aug;
                }
 
+             cie->data = start;
+             cie->data_length = block_end - cie->data;
+
              while (*aug != '\0')
                {
                  if (aug[0] == 'e' && aug[1] == 'h')
                    {
-                     start += sizeof (void *);
-                     aug += 2;
+                     aug_data += sizeof (void *);
+                     aug++;
                    }
                  else if (aug[0] == 'R')
+                   cie->addr_encoding = *aug_data++;
+                 else if (aug[0] == 'P')
                    {
-                     cie->addr_encoding = *start++;
-                     aug += 1;
+                     CORE_ADDR pers_addr;
+                     int pers_addr_enc;
+
+                     pers_addr_enc = *aug_data++;
+                     /* We don't need pers_addr value and so we 
+                        don't care about it's encoding.  */
+                     pers_addr = read_encoded_pointer (abfd, &aug_data,
+                                                       pers_addr_enc);
                    }
-                 else if (aug[0] == 'P')
+                 else if (aug[0] == 'L' && eh_frame)
                    {
-                     CORE_ADDR ptr;
-                     ptr = read_encoded_pointer (abfd, &start,
-                                                 cie->addr_encoding);
-                     aug += 1;
+                     int lsda_addr_enc;
+
+                     /* Perhaps we should save this to CIE for later use?
+                        Do we need it for something in GDB?  */
+                     lsda_addr_enc = *aug_data++;
                    }
                  else
-                   warning ("%s(): unknown augmentation", __func__);
+                   warning ("CFI warning: unknown augmentation \"%c\""
+                            " in \"%s\" of\n"
+                            "\t%s", aug[0], curr_section_name,
+                            objfile->name);
+                 aug++;
                }
 
-             cie->data = start;
-             cie->data_length = block_end - start;
+             last_cie = cie;
            }
          else
            {
              struct fde_unit *fde;
              struct cie_unit *cie;
+             int dup = 0;
+             CORE_ADDR init_loc;
+
+             /* We assume that debug_frame is in order 
+                CIE,FDE,CIE,FDE,FDE,...  and thus the CIE for this FDE
+                should be stored in last_cie pointer. If not, we'll 
+                try to find it by the older way.  */
+             if (last_cie)
+               cie = last_cie;
+             else
+               {
+                 warning ("CFI: last_cie == NULL. "
+                          "Perhaps a malformed %s section in '%s'...?\n",
+                          curr_section_name, objfile->name);
 
-             fde_chunks_need_space ();
-             fde = fde_unit_alloc ();
-
-             fde_chunks.array[fde_chunks.elems++] = fde;
+                 cie = cie_chunks;
+                 while (cie)
+                   {
+                     if (cie->objfile == objfile)
+                       {
+                         if (eh_frame &&
+                             (cie->offset ==
+                              (unit_offset + bytes_read - cie_id)))
+                           break;
+                         if (!eh_frame && (cie->offset == cie_id))
+                           break;
+                       }
+
+                     cie = cie->next;
+                   }
+                 if (!cie)
+                   error ("CFI: can't find CIE pointer");
+               }
 
-             fde->initial_location = read_pointer (abfd, &start)
-               + ANOFFSET (objfile->section_offsets,
-                           SECT_OFF_TEXT (objfile));
-             fde->address_range = read_pointer (abfd, &start);
+             init_loc = read_encoded_pointer (abfd, &start,
+                                              cie->addr_encoding);
 
-             cie = cie_chunks;
-             while (cie)
+             switch (pointer_encoding (cie->addr_encoding))
                {
-                 if (cie->objfile == objfile)
-                   {
-                     if (from_eh
-                         && (cie->offset ==
-                             (unit_offset + bytes_read - cie_id)))
-                       break;
-                     if (!from_eh && (cie->offset == cie_id))
+               case PE_absptr:
+                 break;
+               case PE_pcrel:
+                 /* start-frame_buffer gives offset from 
+                    the beginning of actual section.  */
+                 init_loc += curr_section_vma + start - frame_buffer;
+                 break;
+               default:
+                 warning ("CFI: Unsupported pointer encoding\n");
+               }
+
+             /* For relocatable objects we must add an offset telling
+                where the section is actually mapped in the memory.  */
+             init_loc += ANOFFSET (objfile->section_offsets,
+                                   SECT_OFF_TEXT (objfile));
+
+             /* If we have both .debug_frame and .eh_frame present in 
+                a file, we must eliminate duplicate FDEs. For now we'll 
+                run through all entries in fde_chunks and check it one 
+                by one. Perhaps in the future we can implement a faster 
+                searching algorithm.  */
+             /* eh_frame==2 indicates, that this file has an already 
+                parsed .debug_frame too. When eh_frame==1 it means, that no
+                .debug_frame is present and thus we don't need to check for
+                duplicities. eh_frame==0 means, that we parse .debug_frame
+                and don't need to care about duplicate FDEs, because
+                .debug_frame is parsed first.  */
+             if (eh_frame == 2)
+               for (i = 0; eh_frame == 2 && i < fde_chunks.elems; i++)
+                 {
+                   /* We assume that FDEs in .debug_frame and .eh_frame 
+                      have the same order (if they are present, of course).
+                      If we find a duplicate entry for one FDE and save
+                      it's index to last_dup_fde it's very likely, that 
+                      we'll find an entry for the following FDE right after 
+                      the previous one. Thus in many cases we'll run this 
+                      loop only once.  */
+                   last_dup_fde = (last_dup_fde + i) % fde_chunks.elems;
+                   if (fde_chunks.array[last_dup_fde]->initial_location
+                       == init_loc)
+                     {
+                       dup = 1;
                        break;
-                   }
+                     }
+                 }
 
-                 cie = cie->next;
-               }
+             /* Allocate a new entry only if this FDE isn't a duplicate of
+                something we have already seen.   */
+             if (!dup)
+               {
+                 fde_chunks_need_space ();
+                 fde = fde_unit_alloc ();
+
+                 fde_chunks.array[fde_chunks.elems++] = fde;
+
+                 fde->initial_location = init_loc;
+                 fde->address_range = read_encoded_pointer (abfd, &start,
+                                                            cie->
+                                                            addr_encoding);
 
-             if (!cie)
-               error ("%s(): can't find CIE pointer", __func__);
-             fde->cie_ptr = cie;
+                 fde->cie_ptr = cie;
 
-             if (cie->augmentation[0] == 'z')
-               read_uleb128 (abfd, &start);
+                 /* Here we intentionally ignore augmentation data
+                    from FDE, because we don't need them.  */
+                 if (cie->augmentation[0] == 'z')
+                   start += read_uleb128 (abfd, &start);
 
-             fde->data = start;
-             fde->data_length = block_end - start;
+                 fde->data = start;
+                 fde->data_length = block_end - start;
+               }
            }
          start = block_end;
        }
@@ -1537,7 +1674,30 @@ dwarf2_build_frame_info (struct objfile *objfile)
             sizeof (struct fde_unit *), compare_fde_unit);
     }
 }
-\f
+
+/* We must parse both .debug_frame section and .eh_frame because 
+ * not all frames must be present in both of these sections. */
+void
+dwarf2_build_frame_info (struct objfile *objfile)
+{
+  int after_debug_frame = 0;
+
+  /* If we have .debug_frame then the parser is called with 
+     eh_frame==0 for .debug_frame and eh_frame==2 for .eh_frame, 
+     otherwise it's only called once for .eh_frame with argument 
+     eh_frame==1.  */
+
+  if (dwarf_frame_offset)
+    {
+      parse_frame_info (objfile, dwarf_frame_offset,
+                       dwarf_frame_size, 0 /* = debug_frame */ );
+      after_debug_frame = 1;
+    }
+
+  if (dwarf_eh_frame_offset)
+    parse_frame_info (objfile, dwarf_eh_frame_offset, dwarf_eh_frame_size,
+                     1 /* = eh_frame */  + after_debug_frame);
+}
 
 /* Return the frame address.  */
 CORE_ADDR
@@ -1701,7 +1861,7 @@ cfi_get_ra (struct frame_info *fi)
 void
 cfi_get_saved_register (char *raw_buffer,
                        int *optimized,
-                       CORE_ADDR * addrp,
+                       CORE_ADDR *addrp,
                        struct frame_info *frame,
                        int regnum, enum lval_type *lval)
 {
index b472694a347720be95078bbb8cc1afe6b85dd341..823a3e1f68d6e9de871382ca41ed233292419c2d 100644 (file)
@@ -514,8 +514,10 @@ command_handler (char *command)
        (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
       arg1->next = arg2;
       arg2->next = NULL;
-      arg1->data.integer = time_at_cmd_start;
-      arg2->data.integer = space_at_cmd_start;
+      arg1->data.longint = time_at_cmd_start;
+#ifdef HAVE_SBRK
+      arg2->data.longint = space_at_cmd_start;
+#endif
       add_continuation (command_line_handler_continuation, arg1);
     }
 
index e11687726ef5edf7be767e18da710e7794c357b4..a26f019fe96222d3bdd5cc512257162190e1b150 100644 (file)
@@ -102,9 +102,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #define yycheck         f_yycheck
 
 #ifndef YYDEBUG
-#define        YYDEBUG 1               /* Default to no yydebug support */
+#define        YYDEBUG 1               /* Default to yydebug support */
 #endif
 
+#define YYFPRINTF parser_fprintf
+
 int yyparse (void);
 
 static int yylex (void);
index 495bf3e05379b53a16c14944039e6832dbef66c0..f95de247b1a43f58ca5e22ffbed96b46414e5b4e 100644 (file)
@@ -96,9 +96,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #define yycheck         java_yycheck
 
 #ifndef YYDEBUG
-#define        YYDEBUG 0               /* Default to no yydebug support */
+#define        YYDEBUG 1               /* Default to yydebug support */
 #endif
 
+#define YYFPRINTF parser_fprintf
+
 int yyparse (void);
 
 static int yylex (void);
index 772c6b7b2860763bd265863746446853b40cd345..707c9e210913243f171b928bc7a9dc1af481429d 100644 (file)
@@ -98,9 +98,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #define yycheck         m2_yycheck
 
 #ifndef YYDEBUG
-#define        YYDEBUG 0               /* Default to no yydebug support */
+#define        YYDEBUG 1               /* Default to yydebug support */
 #endif
 
+#define YYFPRINTF parser_fprintf
+
 int yyparse (void);
 
 static int yylex (void);
index 05a3e50fdecc089843231bbcfb6a8bfafb22fbc7..39d2a2277f5a96d6443349555998dc815504670d 100644 (file)
@@ -41,6 +41,8 @@
 #define P_FMOVM                0xf237
 #define P_TRAP         0x4e40
 
+void m68k_frame_init_saved_regs (struct frame_info *frame_info);
+
 /* The only reason this is here is the tm-altos.h reference below.  It
    was moved back here from tm-m68k.h.  FIXME? */
 
@@ -166,6 +168,20 @@ news_frame_num_args (struct frame_info *fi)
   return val;
 }
 
+/* Insert the specified number of args and function address
+   into a call sequence of the above form stored at DUMMYNAME.
+   We use the BFD routines to store a big-endian value of known size.  */
+
+void
+m68k_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs,
+                    struct value **args, struct type *type, int gcc_p)
+{
+  bfd_putb32 (fun, (unsigned char *) dummy + CALL_DUMMY_START_OFFSET + 2);
+  bfd_putb32 (nargs * 4,
+             (unsigned char *) dummy + CALL_DUMMY_START_OFFSET + 8);
+}
+
+
 /* Push an empty stack frame, to record the current PC, etc.  */
 
 void
@@ -204,30 +220,30 @@ m68k_pop_frame (void)
   register struct frame_info *frame = get_current_frame ();
   register CORE_ADDR fp;
   register int regnum;
-  struct frame_saved_regs fsr;
   char raw_buffer[12];
 
   fp = FRAME_FP (frame);
-  get_frame_saved_regs (frame, &fsr);
+  m68k_frame_init_saved_regs (frame);
   for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--)
     {
-      if (fsr.regs[regnum])
+      if (frame->saved_regs[regnum])
        {
-         read_memory (fsr.regs[regnum], raw_buffer, 12);
+         read_memory (frame->saved_regs[regnum], raw_buffer, 12);
          write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12);
        }
     }
   for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--)
     {
-      if (fsr.regs[regnum])
+      if (frame->saved_regs[regnum])
        {
-         write_register (regnum, read_memory_integer (fsr.regs[regnum], 4));
+         write_register (regnum,
+                         read_memory_integer (frame->saved_regs[regnum], 4));
        }
     }
-  if (fsr.regs[PS_REGNUM])
+  if (frame->saved_regs[PS_REGNUM])
     {
       write_register (PS_REGNUM,
-                     read_memory_integer (fsr.regs[PS_REGNUM], 4));
+                     read_memory_integer (frame->saved_regs[PS_REGNUM], 4));
     }
   write_register (FP_REGNUM, read_memory_integer (fp, 4));
   write_register (PC_REGNUM, read_memory_integer (fp + 4, 4));
@@ -304,9 +320,14 @@ m68k_skip_prologue (CORE_ADDR ip)
   return (ip);
 }
 
+/* Store the addresses of the saved registers of the frame described by 
+   FRAME_INFO in its saved_regs field.
+   This includes special registers such as pc and fp saved in special
+   ways in the stack frame.  sp is even more special:
+   the address we return for it IS the sp for the next frame.  */
+
 void
-m68k_find_saved_regs (struct frame_info *frame_info,
-                     struct frame_saved_regs *saved_regs)
+m68k_frame_init_saved_regs (struct frame_info *frame_info)
 {
   register int regnum;
   register int regmask;
@@ -315,10 +336,17 @@ m68k_find_saved_regs (struct frame_info *frame_info,
 
   /* First possible address for a pc in a call dummy for this frame.  */
   CORE_ADDR possible_call_dummy_start =
-    (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 4 - 8 * 12;
+    (frame_info)->frame - 28 - FP_REGNUM * 4 - 4 - 8 * 12;
 
   int nextinsn;
-  memset (saved_regs, 0, sizeof (*saved_regs));
+
+  if (frame_info->saved_regs)
+    return;
+
+  frame_saved_regs_zalloc (frame_info);
+
+  memset (frame_info->saved_regs, 0, SIZEOF_FRAME_SAVED_REGS);
+
   if ((frame_info)->pc >= possible_call_dummy_start
       && (frame_info)->pc <= (frame_info)->frame)
     {
@@ -378,7 +406,7 @@ m68k_find_saved_regs (struct frame_info *frame_info,
          /* Regmask's low bit is for register fp7, the first pushed */
          for (regnum = FP0_REGNUM + 8; --regnum >= FP0_REGNUM; regmask >>= 1)
            if (regmask & 1)
-             saved_regs->regs[regnum] = (next_addr -= 12);
+             frame_info->saved_regs[regnum] = (next_addr -= 12);
          pc += 4;
        }
       /* fmovemx to (fp + displacement) */
@@ -391,7 +419,7 @@ m68k_find_saved_regs (struct frame_info *frame_info,
          for (regnum = FP0_REGNUM + 8; --regnum >= FP0_REGNUM; regmask >>= 1)
            if (regmask & 1)
              {
-               saved_regs->regs[regnum] = addr;
+               frame_info->saved_regs[regnum] = addr;
                addr += 12;
              }
          pc += 6;
@@ -403,7 +431,7 @@ m68k_find_saved_regs (struct frame_info *frame_info,
          for (regnum = 0; regnum < 16; regnum++, regmask >>= 1)
            if (regmask & 1)
              {
-               saved_regs->regs[regnum] = next_addr;
+               frame_info->saved_regs[regnum] = next_addr;
                next_addr += 4;
              }
          pc += 4;
@@ -418,7 +446,7 @@ m68k_find_saved_regs (struct frame_info *frame_info,
          for (regnum = 0; regnum < 16; regnum++, regmask >>= 1)
            if (regmask & 1)
              {
-               saved_regs->regs[regnum] = addr;
+               frame_info->saved_regs[regnum] = addr;
                addr += 4;
              }
          pc += 6;
@@ -429,14 +457,14 @@ m68k_find_saved_regs (struct frame_info *frame_info,
          /* Regmask's low bit is for register 15, the first pushed */
          for (regnum = 16; --regnum >= 0; regmask >>= 1)
            if (regmask & 1)
-             saved_regs->regs[regnum] = (next_addr -= 4);
+             frame_info->saved_regs[regnum] = (next_addr -= 4);
          pc += 4;
        }
       /* movl r,-(sp) */
       else if (0x2f00 == (0xfff0 & nextinsn))
        {
          regnum = 0xf & nextinsn;
-         saved_regs->regs[regnum] = (next_addr -= 4);
+         frame_info->saved_regs[regnum] = (next_addr -= 4);
          pc += 2;
        }
       /* fmovemx to index of sp */
@@ -446,7 +474,7 @@ m68k_find_saved_regs (struct frame_info *frame_info,
          for (regnum = FP0_REGNUM + 8; --regnum >= FP0_REGNUM; regmask >>= 1)
            if (regmask & 1)
              {
-               saved_regs->regs[regnum] = next_addr;
+               frame_info->saved_regs[regnum] = next_addr;
                next_addr += 12;
              }
          pc += 10;
@@ -454,20 +482,21 @@ m68k_find_saved_regs (struct frame_info *frame_info,
       /* clrw -(sp); movw ccr,-(sp) */
       else if (0x4267 == nextinsn && 0x42e7 == regmask)
        {
-         saved_regs->regs[PS_REGNUM] = (next_addr -= 4);
+         frame_info->saved_regs[PS_REGNUM] = (next_addr -= 4);
          pc += 4;
        }
       else
        break;
     }
 lose:;
-  saved_regs->regs[SP_REGNUM] = (frame_info)->frame + 8;
-  saved_regs->regs[FP_REGNUM] = (frame_info)->frame;
-  saved_regs->regs[PC_REGNUM] = (frame_info)->frame + 4;
+  frame_info->saved_regs[SP_REGNUM] = (frame_info)->frame + 8;
+  frame_info->saved_regs[FP_REGNUM] = (frame_info)->frame;
+  frame_info->saved_regs[PC_REGNUM] = (frame_info)->frame + 4;
 #ifdef SIG_SP_FP_OFFSET
   /* Adjust saved SP_REGNUM for fake _sigtramp frames.  */
   if (frame_info->signal_handler_caller && frame_info->next)
-    saved_regs->regs[SP_REGNUM] = frame_info->next->frame + SIG_SP_FP_OFFSET;
+    frame_info->saved_regs[SP_REGNUM] =
+      frame_info->next->frame + SIG_SP_FP_OFFSET;
 #endif
 }
 
@@ -684,6 +713,10 @@ m68k_saved_pc_after_call (struct frame_info *frame)
 static struct gdbarch *
 m68k_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 {
+  static LONGEST call_dummy_words[7] = { 0xf227e0ff, 0x48e7fffc, 0x426742e7,
+    0x4eb93232, 0x3232dffc, 0x69696969,
+    (0x4e404e71 | (BPT_VECTOR << 16))
+  };
   struct gdbarch_tdep *tdep = NULL;
   struct gdbarch *gdbarch;
 
@@ -698,6 +731,25 @@ m68k_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   gdbarch = gdbarch_alloc (&info, 0);
 
+  set_gdbarch_frame_init_saved_regs (gdbarch, m68k_frame_init_saved_regs);
+
+  set_gdbarch_use_generic_dummy_frames (gdbarch, 0);
+  set_gdbarch_call_dummy_location (gdbarch, ON_STACK);
+  set_gdbarch_call_dummy_breakpoint_offset_p (gdbarch, 1);
+  set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 24);
+  set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_on_stack);
+  set_gdbarch_call_dummy_p (gdbarch, 1);
+  set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 0);
+  set_gdbarch_call_dummy_length (gdbarch, 28);
+  set_gdbarch_call_dummy_start_offset (gdbarch, 12);
+
+  set_gdbarch_call_dummy_words (gdbarch, call_dummy_words);
+  set_gdbarch_sizeof_call_dummy_words (gdbarch, sizeof (call_dummy_words));
+  set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 0);
+  set_gdbarch_fix_call_dummy (gdbarch, m68k_fix_call_dummy);
+  set_gdbarch_push_dummy_frame (gdbarch, m68k_push_dummy_frame);
+  set_gdbarch_pop_frame (gdbarch, m68k_pop_frame);
+
   return gdbarch;
 }
 
index 0abc4a25b3545c239864ec8f911c9c02b28b0ed9..1e122b8fb9f317a31cc1248a31673c86da2615bb 100644 (file)
@@ -42,6 +42,7 @@ static const char * const gdb_osabi_names[] =
   "Windows CE",
   "DJGPP",
   "NetWare",
+  "LynxOS",
 
   "ARM EABI v1",
   "ARM EABI v2",
index f3882e78541c30d987d23973f1f206e59a21e496..1654f9d6fa1cb556ab48123f5082a4908d08e902 100644 (file)
@@ -39,6 +39,7 @@ enum gdb_osabi
   GDB_OSABI_WINCE,
   GDB_OSABI_GO32,
   GDB_OSABI_NETWARE,
+  GDB_OSABI_LYNXOS,
 
   GDB_OSABI_ARM_EABI_V1,
   GDB_OSABI_ARM_EABI_V2,
index 7333f6d04a0dbff8036b84a8ca150a42c723fa96..fbdd3f69e186990c9815899feebc2619cc898a43 100644 (file)
@@ -104,9 +104,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #define yycheck         pascal_yycheck
 
 #ifndef YYDEBUG
-#define        YYDEBUG 0               /* Default to no yydebug support */
+#define        YYDEBUG 1               /* Default to yydebug support */
 #endif
 
+#define YYFPRINTF parser_fprintf
+
 int yyparse (void);
 
 static int yylex (void);
index bc81f221b52aacdf686b89d56faaa69e811d62b6..c5de0af33346a8a9e6af646c54f28021dbcb8841 100644 (file)
@@ -1366,6 +1366,23 @@ build_parse (void)
               NULL);
 }
 
+/* This function avoids direct calls to fprintf 
+   in the parser generated debug code.  */
+void
+parser_fprintf (FILE *x, const char *y, ...)
+{ 
+  va_list args;
+  va_start (args, y);
+  if (x == stderr)
+    vfprintf_unfiltered (gdb_stderr, y, args); 
+  else
+    {
+      fprintf_unfiltered (gdb_stderr, " Unknown FILE used.\n");
+      vfprintf_unfiltered (gdb_stderr, y, args);
+    }
+  va_end (args);
+}
+
 void
 _initialize_parse (void)
 {
index 7db1c77e1232057e181619a1680fdce18d1989bc..062c34d54a3b9bde2b37c746de715051b431ae7b 100644 (file)
@@ -216,4 +216,9 @@ struct op_print
 
 extern int target_map_name_to_register (char *, int);
 
+/* Function used to avoid direct calls to fprintf
+   in the code generated by the bison parser.  */
+
+extern void parser_fprintf (FILE *, const char *, ...) ATTR_FORMAT (printf, 2 ,3);
+
 #endif /* PARSER_DEFS_H */
index 11ed8c4f70d71fcfd51e54626592c2273ba9d32d..7f3e43938ecaf6e3e4f31104dea109a2bf00bd3a 100644 (file)
@@ -1,6 +1,7 @@
 /* Cache and manage the values of registers for GDB, the GNU debugger.
-   Copyright 1986, 1987, 1989, 1991, 1994, 1995, 1996, 1998, 2000, 2001
-   Free Software Foundation, Inc.
+
+   Copyright 1986, 1987, 1989, 1991, 1994, 1995, 1996, 1998, 2000,
+   2001, 2002 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
  * Here is the actual register cache.
  */
 
+/* Per-architecture object describing the layout of a register cache.
+   Computed once when the architecture is created */
+
+struct gdbarch_data *regcache_descr_handle;
+
+struct regcache_descr
+{
+  /* The architecture this descriptor belongs to.  */
+  struct gdbarch *gdbarch;
+
+  /* Is this a ``legacy'' register cache?  Such caches reserve space
+     for raw and pseudo registers and allow access to both.  */
+  int legacy_p;
+
+  /* The raw register cache.  This should contain just [0
+     .. NUM_RAW_REGISTERS).  However, for older targets, it contains
+     space for the full [0 .. NUM_RAW_REGISTERS +
+     NUM_PSEUDO_REGISTERS).  */
+  int nr_raw_registers;
+  long sizeof_raw_registers;
+  long sizeof_raw_register_valid_p;
+
+  /* Offset, in bytes, of reach register in the raw register cache.
+     Pseudo registers have an offset even though they don't
+     (shouldn't) have a correspoinding space in the register cache.
+     It is to keep existing code, that relies on
+     write/write_register_bytes working.  */
+  long *register_offset;
+
+  /* The cooked / frame / virtual register space.  The registers in
+     the range [0..NR_RAW_REGISTERS) should be mapped directly onto
+     the corresponding raw register.  The next [NR_RAW_REGISTERS
+     .. NR_REGISTERS) should have been mapped, via
+     gdbarch_register_read/write onto either raw registers or memory.  */
+  int nr_registers;
+  long *sizeof_register;
+  long max_register_size;
+
+};
+
+static void *
+init_legacy_regcache_descr (struct gdbarch *gdbarch)
+{
+  int i;
+  struct regcache_descr *descr;
+  /* FIXME: cagney/2002-05-11: gdbarch_data() should take that
+     ``gdbarch'' as a parameter.  */
+  gdb_assert (gdbarch != NULL);
+
+  descr = XMALLOC (struct regcache_descr);
+  descr->gdbarch = gdbarch;
+  descr->legacy_p = 1;
+
+  /* FIXME: cagney/2002-05-11: Shouldn't be including pseudo-registers
+     in the register buffer.  Unfortunatly some architectures do.  */
+  descr->nr_registers = NUM_REGS + NUM_PSEUDO_REGS;
+  descr->nr_raw_registers = descr->nr_registers;
+  descr->sizeof_raw_register_valid_p = descr->nr_registers;
+
+  /* FIXME: cagney/2002-05-11: Instead of using REGISTER_BYTE() this
+     code should compute the offets et.al. at runtime.  This currently
+     isn't possible because some targets overlap register locations -
+     see the mess in read_register_bytes() and write_register_bytes()
+     registers.  */
+  descr->sizeof_register = XCALLOC (descr->nr_registers, long);
+  descr->register_offset = XCALLOC (descr->nr_registers, long);
+  descr->max_register_size = 0;
+  for (i = 0; i < descr->nr_registers; i++)
+    {
+      descr->register_offset[i] = REGISTER_BYTE (i);
+      descr->sizeof_register[i] = REGISTER_RAW_SIZE (i);
+      if (descr->max_register_size < REGISTER_RAW_SIZE (i))
+       descr->max_register_size = REGISTER_RAW_SIZE (i);
+    }
+
+  /* Come up with the real size of the registers buffer.  */
+  descr->sizeof_raw_registers = REGISTER_BYTES; /* OK use.  */
+  for (i = 0; i < descr->nr_registers; i++)
+    {
+      long regend;
+      /* Keep extending the buffer so that there is always enough
+         space for all registers.  The comparison is necessary since
+         legacy code is free to put registers in random places in the
+         buffer separated by holes.  Once REGISTER_BYTE() is killed
+         this can be greatly simplified.  */
+      /* FIXME: cagney/2001-12-04: This code shouldn't need to use
+         REGISTER_BYTE().  Unfortunatly, legacy code likes to lay the
+         buffer out so that certain registers just happen to overlap.
+         Ulgh!  New targets use gdbarch's register read/write and
+         entirely avoid this uglyness.  */
+      regend = descr->register_offset[i] + descr->sizeof_register[i];
+      if (descr->sizeof_raw_registers < regend)
+       descr->sizeof_raw_registers = regend;
+    }
+  return descr;
+}
+
+static void *
+init_regcache_descr (struct gdbarch *gdbarch)
+{
+  int i;
+  struct regcache_descr *descr;
+  gdb_assert (gdbarch != NULL);
+
+  /* If an old style architecture, construct the register cache
+     description using all the register macros.  */
+  if (!gdbarch_register_read_p (gdbarch)
+      && !gdbarch_register_write_p (gdbarch))
+    return init_legacy_regcache_descr (gdbarch);
+
+  descr = XMALLOC (struct regcache_descr);
+  descr->gdbarch = gdbarch;
+  descr->legacy_p = 0;
+
+  /* Total size of the register space.  The raw registers should
+     directly map onto the raw register cache while the pseudo's are
+     either mapped onto raw-registers or memory.  */
+  descr->nr_registers = NUM_REGS + NUM_PSEUDO_REGS;
+
+  /* Construct a strictly RAW register cache.  Don't allow pseudo's
+     into the register cache.  */
+  descr->nr_raw_registers = NUM_REGS;
+  descr->sizeof_raw_register_valid_p = NUM_REGS;
+
+  /* Lay out the register cache.  The pseud-registers are included in
+     the layout even though their value isn't stored in the register
+     cache.  Some code, via read_register_bytes() access a register
+     using an offset/length rather than a register number.
+
+     NOTE: cagney/2002-05-22: Only REGISTER_VIRTUAL_TYPE() needs to be
+     used when constructing the register cache.  It is assumed that
+     register raw size, virtual size and type length of the type are
+     all the same.  */
+
+  {
+    long offset = 0;
+    descr->sizeof_register = XCALLOC (descr->nr_registers, long);
+    descr->register_offset = XCALLOC (descr->nr_registers, long);
+    descr->max_register_size = 0;
+    for (i = 0; i < descr->nr_registers; i++)
+      {
+       descr->sizeof_register[i] = TYPE_LENGTH (REGISTER_VIRTUAL_TYPE (i));
+       descr->register_offset[i] = offset;
+       offset += descr->sizeof_register[i];
+       if (descr->max_register_size < descr->sizeof_register[i])
+         descr->max_register_size = descr->sizeof_register[i];
+      }
+    /* Set the real size of the register cache buffer.  */
+    /* FIXME: cagney/2002-05-22: Should only need to allocate space
+       for the raw registers.  Unfortunatly some code still accesses
+       the register array directly using the global registers[].
+       Until that code has been purged, play safe and over allocating
+       the register buffer.  Ulgh!  */
+    descr->sizeof_raw_registers = offset;
+    /* = descr->register_offset[descr->nr_raw_registers]; */
+  }
+
+#if 0
+  /* Sanity check.  Confirm that the assumptions about gdbarch are
+     true.  The REGCACHE_DESCR_HANDLE is set before doing the checks
+     so that targets using the generic methods supplied by regcache
+     don't go into infinite recursion trying to, again, create the
+     regcache.  */
+  set_gdbarch_data (gdbarch, regcache_descr_handle, descr);
+  for (i = 0; i < descr->nr_registers; i++)
+    {
+      gdb_assert (descr->sizeof_register[i] == REGISTER_RAW_SIZE (i));
+      gdb_assert (descr->sizeof_register[i] == REGISTER_VIRTUAL_SIZE (i));
+      gdb_assert (descr->register_offset[i] == REGISTER_BYTE (i));
+    }
+  /* gdb_assert (descr->sizeof_raw_registers == REGISTER_BYTES (i));  */
+#endif
+
+  return descr;
+}
+
+static struct regcache_descr *
+regcache_descr (struct gdbarch *gdbarch)
+{
+  return gdbarch_data (gdbarch, regcache_descr_handle);
+}
+
+static void
+xfree_regcache_descr (struct gdbarch *gdbarch, void *ptr)
+{
+  struct regcache_descr *descr = ptr;
+  if (descr == NULL)
+    return;
+  xfree (descr->register_offset);
+  xfree (descr->sizeof_register);
+  descr->register_offset = NULL;
+  descr->sizeof_register = NULL;
+  xfree (descr);
+}
+
+/* The register cache for storing raw register values.  */
+
+struct regcache
+{
+  struct regcache_descr *descr;
+  char *raw_registers;
+  char *raw_register_valid_p;
+  /* If a value isn't in the cache should the corresponding target be
+     queried for a value.  */
+  int passthrough_p;
+};
+
+struct regcache *
+regcache_xmalloc (struct gdbarch *gdbarch)
+{
+  struct regcache_descr *descr;
+  struct regcache *regcache;
+  gdb_assert (gdbarch != NULL);
+  descr = regcache_descr (gdbarch);
+  regcache = XMALLOC (struct regcache);
+  regcache->descr = descr;
+  regcache->raw_registers
+    = XCALLOC (descr->sizeof_raw_registers, char);
+  regcache->raw_register_valid_p
+    = XCALLOC (descr->sizeof_raw_register_valid_p, char);
+  regcache->passthrough_p = 0;
+  return regcache;
+}
+
+void
+regcache_xfree (struct regcache *regcache)
+{
+  if (regcache == NULL)
+    return;
+  xfree (regcache->raw_registers);
+  xfree (regcache->raw_register_valid_p);
+  xfree (regcache);
+}
+
+void
+regcache_cpy (struct regcache *dst, struct regcache *src)
+{
+  int i;
+  char *buf;
+  gdb_assert (src != NULL && dst != NULL);
+  gdb_assert (src->descr->gdbarch == dst->descr->gdbarch);
+  gdb_assert (src != dst);
+  /* FIXME: cagney/2002-05-17: To say this bit is bad is being polite.
+     It keeps the existing code working where things rely on going
+     through to the register cache.  */
+  if (src == current_regcache && src->descr->legacy_p)
+    {
+      /* ULGH!!!!  Old way.  Use REGISTER bytes and let code below
+        untangle fetch.  */
+      read_register_bytes (0, dst->raw_registers, REGISTER_BYTES);
+      return;
+    }
+  /* FIXME: cagney/2002-05-17: To say this bit is bad is being polite.
+     It keeps the existing code working where things rely on going
+     through to the register cache.  */
+  if (dst == current_regcache && dst->descr->legacy_p)
+    {
+      /* ULGH!!!!  Old way.  Use REGISTER bytes and let code below
+        untangle fetch.  */
+      write_register_bytes (0, src->raw_registers, REGISTER_BYTES);
+      return;
+    }
+  buf = alloca (src->descr->max_register_size);
+  for (i = 0; i < src->descr->nr_raw_registers; i++)
+    {
+      /* Should we worry about the valid bit here?  */
+      regcache_read (src, i, buf);
+      regcache_write (dst, i, buf);
+    }
+}
+
+void
+regcache_cpy_no_passthrough (struct regcache *dst, struct regcache *src)
+{
+  int i;
+  gdb_assert (src != NULL && dst != NULL);
+  gdb_assert (src->descr->gdbarch == dst->descr->gdbarch);
+  /* NOTE: cagney/2002-05-17: Don't let the caller do a no-passthrough
+     move of data into the current_regcache().  Doing this would be
+     silly - it would mean that valid_p would be completly invalid.  */
+  gdb_assert (dst != current_regcache);
+  memcpy (dst->raw_registers, src->raw_registers,
+         dst->descr->sizeof_raw_registers);
+  memcpy (dst->raw_register_valid_p, src->raw_register_valid_p,
+         dst->descr->sizeof_raw_register_valid_p);
+}
+
+struct regcache *
+regcache_dup (struct regcache *src)
+{
+  struct regcache *newbuf;
+  gdb_assert (current_regcache != NULL);
+  newbuf = regcache_xmalloc (src->descr->gdbarch);
+  regcache_cpy (newbuf, src);
+  return newbuf;
+}
+
+struct regcache *
+regcache_dup_no_passthrough (struct regcache *src)
+{
+  struct regcache *newbuf;
+  gdb_assert (current_regcache != NULL);
+  newbuf = regcache_xmalloc (src->descr->gdbarch);
+  regcache_cpy_no_passthrough (newbuf, src);
+  return newbuf;
+}
+
+int
+regcache_valid_p (struct regcache *regcache, int regnum)
+{
+  gdb_assert (regcache != NULL);
+  gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers);
+  return regcache->raw_register_valid_p[regnum];
+}
+
+CORE_ADDR
+regcache_read_as_address (struct regcache *regcache, int regnum)
+{
+  char *buf;
+  gdb_assert (regcache != NULL);
+  gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers);
+  buf = alloca (regcache->descr->sizeof_register[regnum]);
+  regcache_read (regcache, regnum, buf);
+  return extract_address (buf, regcache->descr->sizeof_register[regnum]);
+}
+
+char *
+deprecated_grub_regcache_for_registers (struct regcache *regcache)
+{
+  return regcache->raw_registers;
+}
+
+char *
+deprecated_grub_regcache_for_register_valid (struct regcache *regcache)
+{
+  return regcache->raw_register_valid_p;
+}
+
+/* Global structure containing the current regcache.  */
+/* FIXME: cagney/2002-05-11: The two global arrays registers[] and
+   register_valid[] currently point into this structure.  */
+struct regcache *current_regcache;
+
 /* NOTE: this is a write-through cache.  There is no "dirty" bit for
    recording if the register values have been changed (eg. by the
    user).  Therefore all registers must be written back to the
@@ -97,10 +441,9 @@ register_changed (int regnum)
    else return a pointer to the start of the cache buffer.  */
 
 static char *
-register_buffer (int regnum)
+register_buffer (struct regcache *regcache, int regnum)
 {
-  gdb_assert (regnum >= 0 && regnum < (NUM_REGS + NUM_PSEUDO_REGS));
-  return &registers[REGISTER_BYTE (regnum)];
+  return regcache->raw_registers + regcache->descr->register_offset[regnum];
 }
 
 /* Return whether register REGNUM is a real register.  */
@@ -311,22 +654,52 @@ legacy_read_register_gen (int regnum, char *myaddr)
   if (!register_cached (regnum))
     fetch_register (regnum);
 
-  memcpy (myaddr, register_buffer (regnum),
+  memcpy (myaddr, register_buffer (current_regcache, regnum),
          REGISTER_RAW_SIZE (regnum));
 }
 
 void
-regcache_read (int rawnum, char *buf)
+regcache_read (struct regcache *regcache, int regnum, char *buf)
 {
-  gdb_assert (rawnum >= 0 && rawnum < (NUM_REGS + NUM_PSEUDO_REGS));
-  /* For moment, just use underlying legacy code. Ulgh!!! */
-  legacy_read_register_gen (rawnum, buf);
+  gdb_assert (regcache != NULL && buf != NULL);
+  gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers);
+  if (regcache->descr->legacy_p
+      && regcache->passthrough_p)
+    {
+      gdb_assert (regcache == current_regcache);
+      /* For moment, just use underlying legacy code.  Ulgh!!! This
+        silently and very indirectly updates the regcache's regcache
+        via the global register_valid[].  */
+      legacy_read_register_gen (regnum, buf);
+      return;
+    }
+  /* Make certain that the register cache is up-to-date with respect
+     to the current thread.  This switching shouldn't be necessary
+     only there is still only one target side register cache.  Sigh!
+     On the bright side, at least there is a regcache object.  */
+  if (regcache->passthrough_p)
+    {
+      gdb_assert (regcache == current_regcache);
+      if (! ptid_equal (registers_ptid, inferior_ptid))
+       {
+         registers_changed ();
+         registers_ptid = inferior_ptid;
+       }
+      if (!register_cached (regnum))
+       fetch_register (regnum);
+    }
+  /* Copy the value directly into the register cache.  */
+  memcpy (buf, (regcache->raw_registers
+               + regcache->descr->register_offset[regnum]),
+         regcache->descr->sizeof_register[regnum]);
 }
 
 void
 read_register_gen (int regnum, char *buf)
 {
-  if (! gdbarch_register_read_p (current_gdbarch))
+  gdb_assert (current_regcache != NULL);
+  gdb_assert (current_regcache->descr->gdbarch == current_gdbarch);
+  if (current_regcache->descr->legacy_p)
     {
       legacy_read_register_gen (regnum, buf);
       return;
@@ -362,30 +735,80 @@ legacy_write_register_gen (int regnum, char *myaddr)
       /* If we have a valid copy of the register, and new value == old
         value, then don't bother doing the actual store. */
       if (register_cached (regnum)
-         && memcmp (register_buffer (regnum), myaddr, size) == 0)
+         && (memcmp (register_buffer (current_regcache, regnum), myaddr, size)
+             == 0))
        return;
       else
        target_prepare_to_store ();
     }
 
-  memcpy (register_buffer (regnum), myaddr, size);
+  memcpy (register_buffer (current_regcache, regnum), myaddr, size);
 
   set_register_cached (regnum, 1);
   store_register (regnum);
 }
 
 void
-regcache_write (int rawnum, char *buf)
+regcache_write (struct regcache *regcache, int regnum, char *buf)
 {
-  gdb_assert (rawnum >= 0 && rawnum < (NUM_REGS + NUM_PSEUDO_REGS));
-  /* For moment, just use underlying legacy code. Ulgh!!! */
-  legacy_write_register_gen (rawnum, buf);
+  gdb_assert (regcache != NULL && buf != NULL);
+  gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers);
+
+  if (regcache->passthrough_p
+      && regcache->descr->legacy_p)
+    {
+      /* For moment, just use underlying legacy code.  Ulgh!!! This
+        silently and very indirectly updates the regcache's buffers
+        via the globals register_valid[] and registers[].  */
+      gdb_assert (regcache == current_regcache);
+      legacy_write_register_gen (regnum, buf);
+      return;
+    }
+
+  /* On the sparc, writing %g0 is a no-op, so we don't even want to
+     change the registers array if something writes to this register.  */
+  if (CANNOT_STORE_REGISTER (regnum))
+    return;
+
+  /* Handle the simple case first -> not write through so just store
+     value in cache.  */
+  if (!regcache->passthrough_p)
+    {
+      memcpy ((regcache->raw_registers
+              + regcache->descr->register_offset[regnum]), buf,
+             regcache->descr->sizeof_register[regnum]);
+      regcache->raw_register_valid_p[regnum] = 1;
+      return;
+    }
+
+  /* Make certain that the correct cache is selected.  */
+  gdb_assert (regcache == current_regcache);
+  if (! ptid_equal (registers_ptid, inferior_ptid))
+    {
+      registers_changed ();
+      registers_ptid = inferior_ptid;
+    }
+
+  /* If we have a valid copy of the register, and new value == old
+     value, then don't bother doing the actual store. */
+  if (regcache_valid_p (regcache, regnum)
+      && (memcmp (register_buffer (regcache, regnum), buf,
+                 regcache->descr->sizeof_register[regnum]) == 0))
+    return;
+
+  target_prepare_to_store ();
+  memcpy (register_buffer (regcache, regnum), buf,
+         regcache->descr->sizeof_register[regnum]);
+  regcache->raw_register_valid_p[regnum] = 1;
+  store_register (regnum);
 }
 
 void
 write_register_gen (int regnum, char *buf)
 {
-  if (! gdbarch_register_write_p (current_gdbarch))
+  gdb_assert (current_regcache != NULL);
+  gdb_assert (current_regcache->descr->gdbarch == current_gdbarch);
+  if (current_regcache->descr->legacy_p)
     {
       legacy_write_register_gen (regnum, buf);
       return;
@@ -564,10 +987,10 @@ supply_register (int regnum, char *val)
 
   set_register_cached (regnum, 1);
   if (val)
-    memcpy (register_buffer (regnum), val, 
+    memcpy (register_buffer (current_regcache, regnum), val, 
            REGISTER_RAW_SIZE (regnum));
   else
-    memset (register_buffer (regnum), '\000', 
+    memset (register_buffer (current_regcache, regnum), '\000', 
            REGISTER_RAW_SIZE (regnum));
 
   /* On some architectures, e.g. HPPA, there are a few stray bits in
@@ -587,7 +1010,8 @@ supply_register (int regnum, char *val)
 void
 regcache_collect (int regnum, void *buf)
 {
-  memcpy (buf, register_buffer (regnum), REGISTER_RAW_SIZE (regnum));
+  memcpy (buf, register_buffer (current_regcache, regnum),
+         REGISTER_RAW_SIZE (regnum));
 }
 
 
@@ -754,38 +1178,54 @@ reg_flush_command (char *command, int from_tty)
 
 static void
 build_regcache (void)
+{
+  current_regcache = regcache_xmalloc (current_gdbarch);
+  current_regcache->passthrough_p = 1;
+  registers = deprecated_grub_regcache_for_registers (current_regcache);
+  register_valid = deprecated_grub_regcache_for_register_valid (current_regcache);
+}
+
+void
+regcache_save (struct regcache *regcache)
 {
   int i;
-  int sizeof_register_valid;
-  /* Come up with the real size of the registers buffer.  */
-  int sizeof_registers = REGISTER_BYTES; /* OK use.  */
-  for (i = 0; i < NUM_REGS + NUM_PSEUDO_REGS; i++)
-    {
-      long regend;
-      /* Keep extending the buffer so that there is always enough
-         space for all registers.  The comparison is necessary since
-         legacy code is free to put registers in random places in the
-         buffer separated by holes.  Once REGISTER_BYTE() is killed
-         this can be greatly simplified.  */
-      /* FIXME: cagney/2001-12-04: This code shouldn't need to use
-         REGISTER_BYTE().  Unfortunatly, legacy code likes to lay the
-         buffer out so that certain registers just happen to overlap.
-         Ulgh!  New targets use gdbarch's register read/write and
-         entirely avoid this uglyness.  */
-      regend = REGISTER_BYTE (i) + REGISTER_RAW_SIZE (i);
-      if (sizeof_registers < regend)
-       sizeof_registers = regend;
-    }
-  registers = xmalloc (sizeof_registers);
-  sizeof_register_valid = ((NUM_REGS + NUM_PSEUDO_REGS)
-                          * sizeof (*register_valid));
-  register_valid = xmalloc (sizeof_register_valid);
-  memset (register_valid, 0, sizeof_register_valid);
+  gdb_assert (current_regcache != NULL && regcache != NULL);
+  gdb_assert (current_regcache->descr->gdbarch == regcache->descr->gdbarch);
+  regcache_cpy (regcache, current_regcache);
+}
+
+void
+regcache_save_no_passthrough (struct regcache *regcache)
+{
+  gdb_assert (current_regcache != NULL && regcache != NULL);
+  gdb_assert (current_regcache->descr->gdbarch == regcache->descr->gdbarch);
+  regcache_cpy_no_passthrough (regcache, current_regcache);
+}
+
+void
+regcache_restore (struct regcache *regcache)
+{
+  int i;
+  gdb_assert (current_regcache != NULL && regcache != NULL);
+  gdb_assert (current_regcache->descr->gdbarch == regcache->descr->gdbarch);
+  regcache_cpy (current_regcache, regcache);
+}
+
+void
+regcache_restore_no_passthrough (struct regcache *regcache)
+{
+  char *regcache_registers;
+  gdb_assert (current_regcache != NULL && regcache != NULL);
+  gdb_assert (current_regcache->descr->gdbarch == regcache->descr->gdbarch);
+  regcache_cpy_no_passthrough (current_regcache, regcache);
 }
 
 void
 _initialize_regcache (void)
 {
+  regcache_descr_handle = register_gdbarch_data (init_regcache_descr,
+                                                xfree_regcache_descr);
+  REGISTER_GDBARCH_SWAP (current_regcache);
   register_gdbarch_swap (&registers, sizeof (registers), NULL);
   register_gdbarch_swap (&register_valid, sizeof (register_valid), NULL);
   register_gdbarch_swap (NULL, 0, build_regcache);
index 4e854d3166768a03d9897cae83b36fe25a448f8f..4b564a8c88eede52bdf17d17369462c9b852112e 100644 (file)
@@ -1,6 +1,7 @@
 /* Cache and manage the values of registers for GDB, the GNU debugger.
-   Copyright 1986, 1987, 1989, 1991, 1994, 1995, 1996, 1998, 2000, 2001
-   Free Software Foundation, Inc.
+
+   Copyright 1986, 1987, 1989, 1991, 1994, 1995, 1996, 1998, 2000,
+   2001, 2002 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #ifndef REGCACHE_H
 #define REGCACHE_H
 
+struct regcache;
+struct gdbarch;
+
+extern struct regcache *current_regcache;
+
+void regcache_xfree (struct regcache *regcache);
+struct regcache *regcache_xmalloc (struct gdbarch *gdbarch);
+
 /* Transfer a raw register [0..NUM_REGS) between core-gdb and the
    regcache. */
 
-void regcache_read (int rawnum, char *buf);
-void regcache_write (int rawnum, char *buf);
+void regcache_read (struct regcache *regcache, int rawnum, char *buf);
+void regcache_write (struct regcache *regcache, int rawnum, char *buf);
+int regcache_valid_p (struct regcache *regcache, int regnum);
+CORE_ADDR regcache_read_as_address (struct regcache *regcache, int rawnum);
 
 /* Transfer a raw register [0..NUM_REGS) between the regcache and the
    target.  These functions are called by the target in response to a
@@ -47,6 +58,25 @@ extern char *registers;
 
 extern signed char *register_valid;
 
+/* Save/restore the register cache using the regbuf.  The operation is
+   write through - it is strictly for code that needs to restore the
+   target's registers to a previous state.
+
+   ``no passthrough'' versions do not go through to the target.  They
+   only save values already in the cache.  */
+
+extern void regcache_save (struct regcache *regcache);
+extern void regcache_restore (struct regcache *regcache);
+extern struct regcache *regcache_dup (struct regcache *regcache);
+extern void regcache_save_no_passthrough (struct regcache *regcache);
+extern void regcache_restore_no_passthrough (struct regcache *regcache);
+extern struct regcache *regcache_dup_no_passthrough (struct regcache *regcache);
+extern void regcache_cpy (struct regcache *dest, struct regcache *src);
+extern void regcache_cpy_no_passthrough (struct regcache *dest, struct regcache *src);
+
+extern char *deprecated_grub_regcache_for_registers (struct regcache *);
+extern char *deprecated_grub_regcache_for_register_valid (struct regcache *);
+
 extern int register_cached (int regnum);
 
 extern void set_register_cached (int regnum, int state);
index 4c4f64382c402e97d051573744538105a412e243..7749b415114819525aaf178dd8105d80eb66be00 100644 (file)
@@ -197,12 +197,12 @@ store_regs (int tid, int regno)
 static void *
 x86_64_fxsave_offset (elf_fpregset_t * fxsave, int regnum)
 {
-  char *reg_name;
+  const char *reg_name;
   int reg_index;
 
   gdb_assert (x86_64_num_gregs - 1 < regnum && regnum < x86_64_num_regs);
 
-  reg_name = x86_64_register_nr2name (regnum);
+  reg_name = x86_64_register_name (regnum);
 
   if (reg_name[0] == 's' && reg_name[1] == 't')
     {
@@ -231,8 +231,8 @@ supply_fpregset (elf_fpregset_t * fxsave)
 {
   int i, reg_st0, reg_mxcsr;
 
-  reg_st0 = x86_64_register_name2nr ("st0");
-  reg_mxcsr = x86_64_register_name2nr ("mxcsr");
+  reg_st0 = x86_64_register_number ("st0");
+  reg_mxcsr = x86_64_register_number ("mxcsr");
 
   gdb_assert (reg_st0 > 0 && reg_mxcsr > reg_st0);
 
index 111861aaafe6dba20caa57d5e27c80e5f53d2d68..5b6d2cd8161a0b5c8b5878dd453610aedf73446b 100644 (file)
@@ -798,8 +798,8 @@ x86_64_store_return_value (struct type *type, char *valbuf)
 }
 \f
 
-char *
-x86_64_register_nr2name (int reg_nr)
+const char *
+x86_64_register_name (int reg_nr)
 {
   if (reg_nr < 0 || reg_nr >= X86_64_NUM_REGS)
     return NULL;
@@ -807,7 +807,7 @@ x86_64_register_nr2name (int reg_nr)
 }
 
 int
-x86_64_register_name2nr (const char *name)
+x86_64_register_number (const char *name)
 {
   int reg_nr;
 
@@ -989,7 +989,7 @@ x86_64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_long_double_format (gdbarch, &floatformat_i387_ext);
 
   set_gdbarch_num_regs (gdbarch, X86_64_NUM_REGS);
-  set_gdbarch_register_name (gdbarch, x86_64_register_nr2name);
+  set_gdbarch_register_name (gdbarch, x86_64_register_name);
   set_gdbarch_register_size (gdbarch, 8);
   set_gdbarch_register_raw_size (gdbarch, x86_64_register_raw_size);
   set_gdbarch_max_register_raw_size (gdbarch, 16);
index dda94bc5eb87f458748dcd5bacddf2b060952dac..711486077fb2ac650f98ced31f818ad568e900be 100644 (file)
@@ -28,8 +28,9 @@
 extern int x86_64_num_regs;
 extern int x86_64_num_gregs;
 
-int x86_64_register_name2nr (const char *name);
-char *x86_64_register_nr2name (int reg_nr);
+int x86_64_register_number (const char *name);
+const char *x86_64_register_name (int reg_nr);
+       
 
 gdbarch_frame_saved_pc_ftype x86_64_linux_frame_saved_pc;
 gdbarch_saved_pc_after_call_ftype x86_64_linux_saved_pc_after_call;