⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 valops.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Perform non-arithmetic operations on values, for GDB.   Copyright 1986, 1987, 1989, 1991, 1992 Free Software Foundation, Inc.This file is part of GDB.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */#include "defs.h"#include "symtab.h"#include "gdbtypes.h"#include "value.h"#include "frame.h"#include "inferior.h"#include "gdbcore.h"#include "target.h"#include <errno.h>/* Local functions.  */static CORE_ADDRfind_function_addr PARAMS ((value, struct type **));static CORE_ADDRvalue_push PARAMS ((CORE_ADDR, value));CORE_ADDRvalue_arg_push PARAMS ((CORE_ADDR, value));static valuesearch_struct_field PARAMS ((char *, value, int, struct type *, int));static valuesearch_struct_method PARAMS ((char *, value *, value *, int, int *,			      struct type *));static intcheck_field_in PARAMS ((struct type *, const char *));/* Cast value ARG2 to type TYPE and return as a value.   More general than a C cast: accepts any two types of the same length,   and if ARG2 is an lvalue it can be cast into anything at all.  *//* In C++, casts may change pointer representations.  */valuevalue_cast (type, arg2)     struct type *type;     register value arg2;{  register enum type_code code1;  register enum type_code code2;  register int scalar;  /* Coerce arrays but not enums.  Enums will work as-is     and coercing them would cause an infinite recursion.  */  if (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_ENUM)    COERCE_ARRAY (arg2);  code1 = TYPE_CODE (type);  code2 = TYPE_CODE (VALUE_TYPE (arg2));  scalar = (code2 == TYPE_CODE_INT || code2 == TYPE_CODE_FLT	    || code2 == TYPE_CODE_ENUM);  if (code1 == TYPE_CODE_FLT && scalar)    return value_from_double (type, value_as_double (arg2));  else if ((code1 == TYPE_CODE_INT || code1 == TYPE_CODE_ENUM)	   && (scalar || code2 == TYPE_CODE_PTR))    return value_from_longest (type, value_as_long (arg2));  else if (TYPE_LENGTH (type) == TYPE_LENGTH (VALUE_TYPE (arg2)))    {      if (code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_PTR)	{	  /* Look in the type of the source to see if it contains the	     type of the target as a superclass.  If so, we'll need to	     offset the pointer rather than just change its type.  */	  struct type *t1 = TYPE_TARGET_TYPE (type);	  struct type *t2 = TYPE_TARGET_TYPE (VALUE_TYPE (arg2));	  if (   TYPE_CODE (t1) == TYPE_CODE_STRUCT	      && TYPE_CODE (t2) == TYPE_CODE_STRUCT	      && TYPE_NAME (t1) != 0) /* if name unknown, can't have supercl */	    {	      value v = search_struct_field (type_name_no_tag (t1),					     value_ind (arg2), 0, t2, 1);	      if (v)		{		  v = value_addr (v);		  VALUE_TYPE (v) = type;		  return v;		}	    }	  /* No superclass found, just fall through to change ptr type.  */	}      VALUE_TYPE (arg2) = type;      return arg2;    }  else if (VALUE_LVAL (arg2) == lval_memory)    {      return value_at_lazy (type, VALUE_ADDRESS (arg2) + VALUE_OFFSET (arg2));    }  else if (code1 == TYPE_CODE_VOID)    {      return value_zero (builtin_type_void, not_lval);    }  else    {      error ("Invalid cast.");      return 0;    }}/* Create a value of type TYPE that is zero, and return it.  */valuevalue_zero (type, lv)     struct type *type;     enum lval_type lv;{  register value val = allocate_value (type);  memset (VALUE_CONTENTS (val), 0, TYPE_LENGTH (type));  VALUE_LVAL (val) = lv;  return val;}/* Return a value with type TYPE located at ADDR.     Call value_at only if the data needs to be fetched immediately;   if we can be 'lazy' and defer the fetch, perhaps indefinately, call   value_at_lazy instead.  value_at_lazy simply records the address of   the data and sets the lazy-evaluation-required flag.  The lazy flag    is tested in the VALUE_CONTENTS macro, which is used if and when    the contents are actually required.  */valuevalue_at (type, addr)     struct type *type;     CORE_ADDR addr;{  register value val = allocate_value (type);  read_memory (addr, VALUE_CONTENTS_RAW (val), TYPE_LENGTH (type));  VALUE_LVAL (val) = lval_memory;  VALUE_ADDRESS (val) = addr;  return val;}/* Return a lazy value with type TYPE located at ADDR (cf. value_at).  */valuevalue_at_lazy (type, addr)     struct type *type;     CORE_ADDR addr;{  register value val = allocate_value (type);  VALUE_LVAL (val) = lval_memory;  VALUE_ADDRESS (val) = addr;  VALUE_LAZY (val) = 1;  return val;}/* Called only from the VALUE_CONTENTS macro, if the current data for   a variable needs to be loaded into VALUE_CONTENTS(VAL).  Fetches the   data from the user's process, and clears the lazy flag to indicate   that the data in the buffer is valid.   If the value is zero-length, we avoid calling read_memory, which would   abort.  We mark the value as fetched anyway -- all 0 bytes of it.   This function returns a value because it is used in the VALUE_CONTENTS   macro as part of an expression, where a void would not work.  The   value is ignored.  */intvalue_fetch_lazy (val)     register value val;{  CORE_ADDR addr = VALUE_ADDRESS (val) + VALUE_OFFSET (val);  if (TYPE_LENGTH (VALUE_TYPE (val)))    read_memory (addr, VALUE_CONTENTS_RAW (val), 	         TYPE_LENGTH (VALUE_TYPE (val)));  VALUE_LAZY (val) = 0;  return 0;}/* Store the contents of FROMVAL into the location of TOVAL.   Return a new value with the location of TOVAL and contents of FROMVAL.  */valuevalue_assign (toval, fromval)     register value toval, fromval;{  register struct type *type = VALUE_TYPE (toval);  register value val;  char raw_buffer[MAX_REGISTER_RAW_SIZE];  char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];  int use_buffer = 0;  COERCE_ARRAY (fromval);  COERCE_REF (toval);  if (VALUE_LVAL (toval) != lval_internalvar)    fromval = value_cast (type, fromval);  /* If TOVAL is a special machine register requiring conversion     of program values to a special raw format,     convert FROMVAL's contents now, with result in `raw_buffer',     and set USE_BUFFER to the number of bytes to write.  */  if (VALUE_REGNO (toval) >= 0      && REGISTER_CONVERTIBLE (VALUE_REGNO (toval)))    {      int regno = VALUE_REGNO (toval);      if (VALUE_TYPE (fromval) != REGISTER_VIRTUAL_TYPE (regno))	fromval = value_cast (REGISTER_VIRTUAL_TYPE (regno), fromval);      memcpy (virtual_buffer, VALUE_CONTENTS (fromval),	     REGISTER_VIRTUAL_SIZE (regno));      REGISTER_CONVERT_TO_RAW (regno, virtual_buffer, raw_buffer);      use_buffer = REGISTER_RAW_SIZE (regno);    }  switch (VALUE_LVAL (toval))    {    case lval_internalvar:      set_internalvar (VALUE_INTERNALVAR (toval), fromval);      break;    case lval_internalvar_component:      set_internalvar_component (VALUE_INTERNALVAR (toval),				 VALUE_OFFSET (toval),				 VALUE_BITPOS (toval),				 VALUE_BITSIZE (toval),				 fromval);      break;    case lval_memory:      if (VALUE_BITSIZE (toval))	{	  int v;		/* FIXME, this won't work for large bitfields */	  read_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),		       (char *) &v, sizeof v);	  modify_field ((char *) &v, (int) value_as_long (fromval),			VALUE_BITPOS (toval), VALUE_BITSIZE (toval));	  write_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),			(char *)&v, sizeof v);	}      else if (use_buffer)	write_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),		      raw_buffer, use_buffer);      else	write_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),		      VALUE_CONTENTS (fromval), TYPE_LENGTH (type));      break;    case lval_register:      if (VALUE_BITSIZE (toval))	{	  int v;	  read_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),			       (char *) &v, sizeof v);	  modify_field ((char *) &v, (int) value_as_long (fromval),			VALUE_BITPOS (toval), VALUE_BITSIZE (toval));	  write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),				(char *) &v, sizeof v);	}      else if (use_buffer)	write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),			      raw_buffer, use_buffer);      else	write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),			      VALUE_CONTENTS (fromval), TYPE_LENGTH (type));      break;    case lval_reg_frame_relative:      {	/* value is stored in a series of registers in the frame	   specified by the structure.  Copy that value out, modify	   it, and copy it back in.  */	int amount_to_copy = (VALUE_BITSIZE (toval) ? 1 : TYPE_LENGTH (type));	int reg_size = REGISTER_RAW_SIZE (VALUE_FRAME_REGNUM (toval));	int byte_offset = VALUE_OFFSET (toval) % reg_size;	int reg_offset = VALUE_OFFSET (toval) / reg_size;	int amount_copied;	char *buffer = (char *) alloca (amount_to_copy);	int regno;	FRAME frame;	/* Figure out which frame this is in currently.  */	for (frame = get_current_frame ();	     frame && FRAME_FP (frame) != VALUE_FRAME (toval);	     frame = get_prev_frame (frame))	  ;	if (!frame)	  error ("Value being assigned to is no longer active.");	amount_to_copy += (reg_size - amount_to_copy % reg_size);	/* Copy it out.  */	for ((regno = VALUE_FRAME_REGNUM (toval) + reg_offset,	      amount_copied = 0);	     amount_copied < amount_to_copy;	     amount_copied += reg_size, regno++)	  {	    get_saved_register (buffer + amount_copied,				(int *)NULL, (CORE_ADDR *)NULL,				frame, regno, (enum lval_type *)NULL);	  }	/* Modify what needs to be modified.  */	if (VALUE_BITSIZE (toval))	  modify_field (buffer + byte_offset,			(int) value_as_long (fromval),			VALUE_BITPOS (toval), VALUE_BITSIZE (toval));	else if (use_buffer)	  memcpy (buffer + byte_offset, raw_buffer, use_buffer);	else	  memcpy (buffer + byte_offset, VALUE_CONTENTS (fromval),		  TYPE_LENGTH (type));	/* Copy it back.  */	for ((regno = VALUE_FRAME_REGNUM (toval) + reg_offset,	      amount_copied = 0);	     amount_copied < amount_to_copy;	     amount_copied += reg_size, regno++)	  {	    enum lval_type lval;	    CORE_ADDR addr;	    int optim;	    /* Just find out where to put it.  */	    get_saved_register ((char *)NULL,			        &optim, &addr, frame, regno, &lval);	    	    if (optim)	      error ("Attempt to assign to a value that was optimized out.");	    if (lval == lval_memory)	      write_memory (addr, buffer + amount_copied, reg_size);	    else if (lval == lval_register)	      write_register_bytes (addr, buffer + amount_copied, reg_size);	    else	      error ("Attempt to assign to an unmodifiable value.");	  }      }      break;	    default:      error ("Left side of = operation is not an lvalue.");    }  /* Return a value just like TOVAL except with the contents of FROMVAL     (except in the case of the type if TOVAL is an internalvar).  */  if (VALUE_LVAL (toval) == lval_internalvar      || VALUE_LVAL (toval) == lval_internalvar_component)    {      type = VALUE_TYPE (fromval);    }  val = allocate_value (type);  memcpy (val, toval, VALUE_CONTENTS_RAW (val) - (char *) val);  memcpy (VALUE_CONTENTS_RAW (val), VALUE_CONTENTS (fromval),	  TYPE_LENGTH (type));  VALUE_TYPE (val) = type;    return val;}/* Extend a value VAL to COUNT repetitions of its type.  */valuevalue_repeat (arg1, count)     value arg1;     int count;{  register value val;  if (VALUE_LVAL (arg1) != lval_memory)    error ("Only values in memory can be extended with '@'.");  if (count < 1)    error ("Invalid number %d of repetitions.", count);  val = allocate_repeat_value (VALUE_TYPE (arg1), count);  read_memory (VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1),	       VALUE_CONTENTS_RAW (val),	       TYPE_LENGTH (VALUE_TYPE (val)) * count);  VALUE_LVAL (val) = lval_memory;  VALUE_ADDRESS (val) = VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -