📄 valops.c
字号:
/* 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 + -