📄 valops.c
字号:
return val;}valuevalue_of_variable (var) struct symbol *var;{ value val; val = read_var_value (var, (FRAME) 0); if (val == 0) error ("Address of symbol \"%s\" is unknown.", SYMBOL_NAME (var)); return val;}/* Given a value which is an array, return a value which is a pointer to its first (actually, zeroth) element. FIXME, this should be subtracting the array's lower bound. */valuevalue_coerce_array (arg1) value arg1;{ register struct type *type; if (VALUE_LVAL (arg1) != lval_memory) error ("Attempt to take address of value not located in memory."); /* Get type of elements. */ if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_ARRAY) type = TYPE_TARGET_TYPE (VALUE_TYPE (arg1)); else /* A phony array made by value_repeat. Its type is the type of the elements, not an array type. */ type = VALUE_TYPE (arg1); return value_from_longest (lookup_pointer_type (type), (LONGEST) (VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1)));}/* Given a value which is a function, return a value which is a pointer to it. */valuevalue_coerce_function (arg1) value arg1;{ if (VALUE_LVAL (arg1) != lval_memory) error ("Attempt to take address of value not located in memory."); return value_from_longest (lookup_pointer_type (VALUE_TYPE (arg1)), (LONGEST) (VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1)));} /* Return a pointer value for the object for which ARG1 is the contents. */valuevalue_addr (arg1) value arg1;{ struct type *type = VALUE_TYPE (arg1); if (TYPE_CODE (type) == TYPE_CODE_REF) { /* Copy the value, but change the type from (T&) to (T*). We keep the same location information, which is efficient, and allows &(&X) to get the location containing the reference. */ value arg2 = value_copy (arg1); VALUE_TYPE (arg2) = lookup_pointer_type (TYPE_TARGET_TYPE (type)); return arg2; } if (VALUE_REPEATED (arg1) || TYPE_CODE (type) == TYPE_CODE_ARRAY) return value_coerce_array (arg1); if (TYPE_CODE (type) == TYPE_CODE_FUNC) return value_coerce_function (arg1); if (VALUE_LVAL (arg1) != lval_memory) error ("Attempt to take address of value not located in memory."); return value_from_longest (lookup_pointer_type (type), (LONGEST) (VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1)));}/* Given a value of a pointer type, apply the C unary * operator to it. */valuevalue_ind (arg1) value arg1;{ COERCE_ARRAY (arg1); if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_MEMBER) error ("not implemented: member types in value_ind"); /* Allow * on an integer so we can cast it to whatever we want. This returns an int, which seems like the most C-like thing to do. "long long" variables are rare enough that BUILTIN_TYPE_LONGEST would seem to be a mistake. */ if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_INT) return value_at (builtin_type_int, (CORE_ADDR) value_as_long (arg1)); else if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR) return value_at_lazy (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)), value_as_pointer (arg1)); error ("Attempt to take contents of a non-pointer value."); return 0; /* For lint -- never reached */}/* Pushing small parts of stack frames. *//* Push one word (the size of object that a register holds). */CORE_ADDRpush_word (sp, buffer) CORE_ADDR sp; REGISTER_TYPE buffer;{ register int len = sizeof (REGISTER_TYPE); SWAP_TARGET_AND_HOST (&buffer, len);#if 1 INNER_THAN 2 sp -= len; write_memory (sp, (char *)&buffer, len);#else /* stack grows upward */ write_memory (sp, (char *)&buffer, len); sp += len;#endif /* stack grows upward */ return sp;}/* Push LEN bytes with data at BUFFER. */CORE_ADDRpush_bytes (sp, buffer, len) CORE_ADDR sp; char *buffer; int len;{#if 1 INNER_THAN 2 sp -= len; write_memory (sp, buffer, len);#else /* stack grows upward */ write_memory (sp, buffer, len); sp += len;#endif /* stack grows upward */ return sp;}/* Push onto the stack the specified value VALUE. */static CORE_ADDRvalue_push (sp, arg) register CORE_ADDR sp; value arg;{ register int len = TYPE_LENGTH (VALUE_TYPE (arg));#if 1 INNER_THAN 2 sp -= len; write_memory (sp, VALUE_CONTENTS (arg), len);#else /* stack grows upward */ write_memory (sp, VALUE_CONTENTS (arg), len); sp += len;#endif /* stack grows upward */ return sp;}/* Perform the standard coercions that are specified for arguments to be passed to C functions. */valuevalue_arg_coerce (arg) value arg;{ register struct type *type; COERCE_ENUM (arg); type = VALUE_TYPE (arg); if (TYPE_CODE (type) == TYPE_CODE_INT && TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_int)) return value_cast (builtin_type_int, arg); if (TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_double)) return value_cast (builtin_type_double, arg); return arg;}/* Push the value ARG, first coercing it as an argument to a C function. */CORE_ADDRvalue_arg_push (sp, arg) register CORE_ADDR sp; value arg;{ return value_push (sp, value_arg_coerce (arg));}/* Determine a function's address and its return type from its value. Calls error() if the function is not valid for calling. */static CORE_ADDRfind_function_addr (function, retval_type) value function; struct type **retval_type;{ register struct type *ftype = VALUE_TYPE (function); register enum type_code code = TYPE_CODE (ftype); struct type *value_type; CORE_ADDR funaddr; /* If it's a member function, just look at the function part of it. */ /* Determine address to call. */ if (code == TYPE_CODE_FUNC || code == TYPE_CODE_METHOD) { funaddr = VALUE_ADDRESS (function); value_type = TYPE_TARGET_TYPE (ftype); } else if (code == TYPE_CODE_PTR) { funaddr = value_as_pointer (function); if (TYPE_CODE (TYPE_TARGET_TYPE (ftype)) == TYPE_CODE_FUNC || TYPE_CODE (TYPE_TARGET_TYPE (ftype)) == TYPE_CODE_METHOD) value_type = TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (ftype)); else value_type = builtin_type_int; } else if (code == TYPE_CODE_INT) { /* Handle the case of functions lacking debugging info. Their values are characters since their addresses are char */ if (TYPE_LENGTH (ftype) == 1) funaddr = value_as_pointer (value_addr (function)); else /* Handle integer used as address of a function. */ funaddr = (CORE_ADDR) value_as_long (function); value_type = builtin_type_int; } else error ("Invalid data type for function to be called."); *retval_type = value_type; return funaddr;}intis_gcc_function(funaddr) CORE_ADDR funaddr;{ struct block *b = block_for_pc (funaddr); /* If compiled without -g, assume GCC. */ return (b == NULL || BLOCK_GCC_COMPILED (b));}#ifdef NEW_CALL_FUNCTIONintvalue_arg_bytes(nargs, args) int nargs; value *args;{ int len = 0; while (--nargs >= 0) len += TYPE_LENGTH(VALUE_TYPE(value_arg_coerce(args[nargs]))); return len;}/* Perform a function call in the inferior. ARGS is a vector of values of arguments (NARGS of them). FUNCTION is a value, the function to be called. Returns a value representing what the function returned. May fail to return, if a breakpoint or signal is hit during the execution of the function. */valuecall_function_by_hand(function, nargs, args) value function; int nargs; value *args;{ register CORE_ADDR sp, pc; struct type *value_type; struct inferior_status inf_status; struct cleanup *old_chain; register CORE_ADDR funaddr; int struct_return_bytes; int gcc_p; char retbuf[REGISTER_BYTES]; save_inferior_status(&inf_status, 1); old_chain = make_cleanup(restore_inferior_status, &inf_status); sp = read_register(SP_REGNUM); funaddr = find_function_addr(function, &value_type); gcc_p = is_gcc_function(funaddr); /* * Are we returning a value using a structure return or a * normal value return? */ if (using_struct_return(function, funaddr, value_type, gcc_p)) struct_return_bytes = TYPE_LENGTH(value_type); else struct_return_bytes = 0; /* * Create a call sequence customized for this function and * the number of arguments for it. */ pc = setup_dummy(sp, funaddr, nargs, args, struct_return_bytes, gcc_p); /* * Execute the stack dummy stub. The register state will be * returned in retbuf. It is restored below. */ run_stack_dummy(pc, retbuf); /* * This will restore the register context that existed before * we called the dummy function. */ do_cleanups(old_chain); /* * The proceed/wait_for_inferior interface is totally * brain dead. It sets the current frame using the stopped * pc and there is no easier way to fix this other * than starting over after we restore the registers. */ flush_cached_frames(); set_current_frame(create_new_frame(read_register(FP_REGNUM), read_pc ())); return value_being_returned(value_type, retbuf, struct_return_bytes);}#elif defined (CALL_DUMMY)/* All this stuff with a dummy frame may seem unnecessarily complicated (why not just save registers in GDB?). The purpose of pushing a dummy frame which looks just like a real frame is so that if you call a function and then hit a breakpoint (get a signal, etc), "backtrace" will look right. Whether the backtrace needs to actually show the stack at the time the inferior function was called is debatable, but it certainly needs to not display garbage. So if you are contemplating making dummy frames be different from normal frames, consider that. *//* Perform a function call in the inferior. ARGS is a vector of values of arguments (NARGS of them). FUNCTION is a value, the function to be called. Returns a value representing what the function returned. May fail to return, if a breakpoint or signal is hit during the execution of the function. */valuecall_function_by_hand (function, nargs, args) value function; int nargs; value *args;{ register CORE_ADDR sp; register int i; CORE_ADDR start_sp; /* CALL_DUMMY is an array of words (REGISTER_TYPE), but each word is in host byte order. It is switched to target byte order before calling FIX_CALL_DUMMY. */ static REGISTER_TYPE dummy[] = CALL_DUMMY; REGISTER_TYPE dummy1[sizeof dummy / sizeof (REGISTER_TYPE)]; CORE_ADDR old_sp; struct type *value_type; unsigned char struct_return; CORE_ADDR struct_addr; struct inferior_status inf_status; struct cleanup *old_chain; CORE_ADDR funaddr; int using_gcc; if (!target_has_execution) noprocess(); save_inferior_status (&inf_status, 1); old_chain = make_cleanup (restore_inferior_status, &inf_status); /* PUSH_DUMMY_FRAME is responsible for saving the inferior registers (and POP_FRAME for restoring them). (At least on most machines) they are saved on the stack in the inferior. */ PUSH_DUMMY_FRAME; old_sp = sp = read_register (SP_REGNUM);#if 1 INNER_THAN 2 /* Stack grows down */ sp -= sizeof dummy; start_sp = sp;#else /* Stack grows up */ start_sp = sp; sp += sizeof dummy;#endif funaddr = find_function_addr (function, &value_type); using_gcc = is_gcc_function(funaddr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -