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

📄 valops.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
  /* Are we returning a value using a structure return or a normal     value return? */  struct_return = using_struct_return (function, funaddr, value_type,				       using_gcc);  /* Create a call sequence customized for this function     and the number of arguments for it.  */  memcpy (dummy1, dummy, sizeof dummy);  for (i = 0; i < sizeof dummy / sizeof (REGISTER_TYPE); i++)    SWAP_TARGET_AND_HOST (&dummy1[i], sizeof (REGISTER_TYPE));  FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, args,		  value_type, using_gcc);#if CALL_DUMMY_LOCATION == ON_STACK  write_memory (start_sp, (char *)dummy1, sizeof dummy);#else /* Not on stack.  */#if CALL_DUMMY_LOCATION == BEFORE_TEXT_END  /* Convex Unix prohibits executing in the stack segment. */  /* Hope there is empty room at the top of the text segment. */  {    extern CORE_ADDR text_end;    static checked = 0;    if (!checked)      for (start_sp = text_end - sizeof dummy; start_sp < text_end; ++start_sp)	if (read_memory_integer (start_sp, 1) != 0)	  error ("text segment full -- no place to put call");    checked = 1;    sp = old_sp;    start_sp = text_end - sizeof dummy;    write_memory (start_sp, (char *)dummy1, sizeof dummy);  }#else /* After text_end.  */  {    extern CORE_ADDR text_end;    int errcode;    sp = old_sp;    start_sp = text_end;    errcode = target_write_memory (start_sp, (char *)dummy1, sizeof dummy);    if (errcode != 0)      error ("Cannot write text segment -- call_function failed");  }#endif /* After text_end.  */#endif /* Not on stack.  */#ifdef lint  sp = old_sp;		/* It really is used, for some ifdef's... */#endif#ifdef STACK_ALIGN  /* If stack grows down, we must leave a hole at the top. */  {    int len = 0;    /* Reserve space for the return structure to be written on the       stack, if necessary */    if (struct_return)      len += TYPE_LENGTH (value_type);        for (i = nargs - 1; i >= 0; i--)      len += TYPE_LENGTH (VALUE_TYPE (value_arg_coerce (args[i])));#ifdef CALL_DUMMY_STACK_ADJUST    len += CALL_DUMMY_STACK_ADJUST;#endif#if 1 INNER_THAN 2    sp -= STACK_ALIGN (len) - len;#else    sp += STACK_ALIGN (len) - len;#endif  }#endif /* STACK_ALIGN */    /* Reserve space for the return structure to be written on the       stack, if necessary */    if (struct_return)      {#if 1 INNER_THAN 2	sp -= TYPE_LENGTH (value_type);	struct_addr = sp;#else	struct_addr = sp;	sp += TYPE_LENGTH (value_type);#endif      }#if defined (REG_STRUCT_HAS_ADDR)  {    /* This is a machine like the sparc, where we need to pass a pointer       to the structure, not the structure itself.  */    if (REG_STRUCT_HAS_ADDR (using_gcc))      for (i = nargs - 1; i >= 0; i--)	if (TYPE_CODE (VALUE_TYPE (args[i])) == TYPE_CODE_STRUCT)	  {	    CORE_ADDR addr;#if !(1 INNER_THAN 2)	    /* The stack grows up, so the address of the thing we push	       is the stack pointer before we push it.  */	    addr = sp;#endif	    /* Push the structure.  */	    sp = value_push (sp, args[i]);#if 1 INNER_THAN 2	    /* The stack grows down, so the address of the thing we push	       is the stack pointer after we push it.  */	    addr = sp;#endif	    /* The value we're going to pass is the address of the thing	       we just pushed.  */	    args[i] = value_from_longest (lookup_pointer_type (value_type),				       (LONGEST) addr);	  }  }#endif /* REG_STRUCT_HAS_ADDR.  */#ifdef PUSH_ARGUMENTS  PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr);#else /* !PUSH_ARGUMENTS */  for (i = nargs - 1; i >= 0; i--)    sp = value_arg_push (sp, args[i]);#endif /* !PUSH_ARGUMENTS */#ifdef CALL_DUMMY_STACK_ADJUST#if 1 INNER_THAN 2  sp -= CALL_DUMMY_STACK_ADJUST;#else  sp += CALL_DUMMY_STACK_ADJUST;#endif#endif /* CALL_DUMMY_STACK_ADJUST */  /* Store the address at which the structure is supposed to be     written.  Note that this (and the code which reserved the space     above) assumes that gcc was used to compile this function.  Since     it doesn't cost us anything but space and if the function is pcc     it will ignore this value, we will make that assumption.     Also note that on some machines (like the sparc) pcc uses a      convention like gcc's.  */  if (struct_return)    STORE_STRUCT_RETURN (struct_addr, sp);  /* Write the stack pointer.  This is here because the statements above     might fool with it.  On SPARC, this write also stores the register     window into the right place in the new stack frame, which otherwise     wouldn't happen.  (See write_inferior_registers in sparc-xdep.c.)  */  write_register (SP_REGNUM, sp);  /* Figure out the value returned by the function.  */  {    char retbuf[REGISTER_BYTES];    /* Execute the stack dummy routine, calling FUNCTION.       When it is done, discard the empty frame       after storing the contents of all regs into retbuf.  */    run_stack_dummy (start_sp + CALL_DUMMY_START_OFFSET, retbuf);    do_cleanups (old_chain);    return value_being_returned (value_type, retbuf, struct_return);  }}#else /* no CALL_DUMMY.  */valuecall_function_by_hand (function, nargs, args)     value function;     int nargs;     value *args;{  error ("Cannot invoke functions on this machine.");}#endif /* no CALL_DUMMY.  *//* Create a value for a string constant:   Call the function malloc in the inferior to get space for it,   then copy the data into that space   and then return the address with type char *.   PTR points to the string constant data; LEN is number of characters.  */valuevalue_string (ptr, len)     char *ptr;     int len;{  register value val;  register struct symbol *sym;  value blocklen;  register char *copy = (char *) alloca (len + 1);  char *i = ptr;  register char *o = copy, *ibeg = ptr;  register int c;  /* Copy the string into COPY, processing escapes.     We could not conveniently process them in the parser     because the string there wants to be a substring of the input.  */  while (i - ibeg < len)    {      c = *i++;      if (c == '\\')	{	  c = parse_escape (&i);	  if (c == -1)	    continue;	}      *o++ = c;    }  *o = 0;  /* Get the length of the string after escapes are processed.  */  len = o - copy;  /* Find the address of malloc in the inferior.  */  sym = lookup_symbol ("malloc", 0, VAR_NAMESPACE, 0, NULL);  if (sym != 0)    {      if (SYMBOL_CLASS (sym) != LOC_BLOCK)	error ("\"malloc\" exists in this program but is not a function.");      val = value_of_variable (sym);    }  else    {      struct minimal_symbol *msymbol;      msymbol = lookup_minimal_symbol ("malloc", (struct objfile *) NULL);      if (msymbol != NULL)	val =	  value_from_longest (lookup_pointer_type (lookup_function_type (				lookup_pointer_type (builtin_type_char))),			      (LONGEST) msymbol -> address);      else	error ("String constants require the program to have a function \"malloc\".");    }  blocklen = value_from_longest (builtin_type_int, (LONGEST) (len + 1));  val = call_function_by_hand (val, 1, &blocklen);  if (value_zerop (val))    error ("No memory available for string constant.");  write_memory (value_as_pointer (val), copy, len + 1);  VALUE_TYPE (val) = lookup_pointer_type (builtin_type_char);  return val;}/* Helper function used by value_struct_elt to recurse through baseclasses.   Look for a field NAME in ARG1. Adjust the address of ARG1 by OFFSET bytes,   and search in it assuming it has (class) type TYPE.   If found, return value, else return NULL.   If LOOKING_FOR_BASECLASS, then instead of looking for struct fields,   look for a baseclass named NAME.  */static valuesearch_struct_field (name, arg1, offset, type, looking_for_baseclass)     char *name;     register value arg1;     int offset;     register struct type *type;     int looking_for_baseclass;{  int i;  check_stub_type (type);  if (! looking_for_baseclass)    for (i = TYPE_NFIELDS (type) - 1; i >= TYPE_N_BASECLASSES (type); i--)      {	char *t_field_name = TYPE_FIELD_NAME (type, i);	if (t_field_name && !strcmp (t_field_name, name))	  {	    value v;	    if (TYPE_FIELD_STATIC (type, i))	      {		char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, i);		struct symbol *sym =		  lookup_symbol (phys_name, 0, VAR_NAMESPACE, 0, NULL);		if (! sym) error (	  "Internal error: could not find physical static variable named %s",				  phys_name);		v = value_at (TYPE_FIELD_TYPE (type, i),			      (CORE_ADDR)SYMBOL_BLOCK_VALUE (sym));	      }	    else	      v = value_primitive_field (arg1, offset, i, type);	    if (v == 0)	      error("there is no field named %s", name);	    return v;	  }      }  for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--)    {      value v;      /* If we are looking for baseclasses, this is what we get when we	 hit them.  */      int found_baseclass = (looking_for_baseclass			     && !strcmp (name, TYPE_BASECLASS_NAME (type, i)));      if (BASETYPE_VIA_VIRTUAL (type, i))	{	  value v2;	  /* Fix to use baseclass_offset instead. FIXME */	  baseclass_addr (type, i, VALUE_CONTENTS (arg1) + offset,			  &v2, (int *)NULL);	  if (v2 == 0)	    error ("virtual baseclass botch");	  if (found_baseclass)	    return v2;	  v = search_struct_field (name, v2, 0, TYPE_BASECLASS (type, i),				   looking_for_baseclass);	}      else if (found_baseclass)	v = value_primitive_field (arg1, offset, i, type);      else	v = search_struct_field (name, arg1,				 offset + TYPE_BASECLASS_BITPOS (type, i) / 8,				 TYPE_BASECLASS (type, i),				 looking_for_baseclass);      if (v) return v;    }  return NULL;}/* Helper function used by value_struct_elt to recurse through baseclasses.   Look for a field NAME in ARG1. Adjust the address of ARG1 by OFFSET bytes,   and search in it assuming it has (class) type TYPE.   If found, return value, else return NULL. */static valuesearch_struct_method (name, arg1p, args, offset, static_memfuncp, type)     char *name;     register value *arg1p, *args;     int offset, *static_memfuncp;     register struct type *type;{  int i;  check_stub_type (type);  for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; i--)    {      char *t_field_name = TYPE_FN_FIELDLIST_NAME (type, i);      if (t_field_name && !strcmp (t_field_name, name))	{	  int j = TYPE_FN_FIELDLIST_LENGTH (type, i) - 1;	  struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);	  if (j > 0 && args == 0)	    error ("cannot resolve overloaded method `%s'", name);	  while (j >= 0)	    {	      if (TYPE_FN_FIELD_STUB (f, j))		check_stub_method (type, i, j);	      if (!typecmp (TYPE_FN_FIELD_STATIC_P (f, j),			    TYPE_FN_FIELD_ARGS (f, j), args))		{		  if (TYPE_FN_FIELD_VIRTUAL_P (f, j))		    return (value)value_virtual_fn_field (arg1p, f, j, type, offset);		  if (TYPE_FN_FIELD_STATIC_P (f, j) && static_memfuncp)		    *static_memfuncp = 1;		  return (value)value_fn_field (arg1p, f, j, type, offset);		}	      j--;	    }	}    }  for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--)    {      value v;      int base_offset;      if (BASETYPE_VIA_VIRTUAL (type, i))	{	  base_offset =	      baseclass_offset (type, i, *arg1p, offset);	  if (base_offset == -1)	    error ("virtual baseclass botch");	}      else	{	  base_offset = TYPE_BASECLASS_BITPOS (type, i) / 8;        }      v = search_struct_method (name, arg1p, args, base_offset + offset,				static_memfuncp, TYPE_BASECLASS (type, i));      if (v)	{/* FIXME-bothner:  Why is this commented out?  Why is it here?  *//*	  *arg1p = arg1_tmp;*/	  return v;        }    }  return NULL;}/* Given *ARGP, a value of type (pointer to a)* structure/union,   extract the component named NAME from the ultimate target structure/union   and return it as a value with its appropriate type.   ERR is used in the error message if *ARGP's type is wrong.   C++: ARGS is a list of argument types to aid in the selection of   an appropriate method. Also, handle derived types.   STATIC_MEMFUNCP, if non-NULL, points to a caller-supplied location   where the truthvalue of whether the function that was resolved was   a static member function or not is stored.   ERR is an error message to be printed in case the field is not found.  */

⌨️ 快捷键说明

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