diff options
Diffstat (limited to 'gdb/valops.c')
-rw-r--r-- | gdb/valops.c | 250 |
1 files changed, 193 insertions, 57 deletions
diff --git a/gdb/valops.c b/gdb/valops.c index f88069f..06091c4 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -17,14 +17,13 @@ notice and this notice must be preserved on all copies. In other words, go ahead and share GDB, but don't try to stop anyone else from sharing it farther. Help stamp out software hoarding! */ - +#include "stdio.h" #include "defs.h" -#include "initialize.h" #include "param.h" #include "symtab.h" #include "value.h" - -START_FILE +#include "frame.h" +#include "inferior.h" /* 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, @@ -60,7 +59,9 @@ value_cast (type, arg2) return arg2; } else if (VALUE_LVAL (arg2) == lval_memory) - return value_at (type, VALUE_ADDRESS (arg2) + VALUE_OFFSET (arg2)); + { + return value_at (type, VALUE_ADDRESS (arg2) + VALUE_OFFSET (arg2)); + } else error ("Invalid cast."); } @@ -73,8 +74,17 @@ value_at (type, addr) CORE_ADDR addr; { register value val = allocate_value (type); + int temp; + + temp = read_memory (addr, VALUE_CONTENTS (val), TYPE_LENGTH (type)); + if (temp) + { + if (have_inferior_p ()) + print_sys_errmsg ("ptrace", temp); + /* Actually, address between addr and addr + len was out of bounds. */ + error ("Cannot read memory: address 0x%x out of bounds.", addr); + } - read_memory (addr, VALUE_CONTENTS (val), TYPE_LENGTH (type)); VALUE_LVAL (val) = lval_memory; VALUE_ADDRESS (val) = addr; @@ -94,6 +104,8 @@ value_assign (toval, fromval) char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE]; int use_buffer = 0; + extern CORE_ADDR find_saved_register (); + COERCE_ARRAY (fromval); if (VALUE_LVAL (toval) != lval_internalvar) @@ -103,7 +115,7 @@ value_assign (toval, fromval) 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))) { @@ -136,7 +148,7 @@ value_assign (toval, fromval) int val; read_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval), &val, sizeof val); - modify_field (&val, value_as_long (fromval), + modify_field (&val, (int) value_as_long (fromval), VALUE_BITPOS (toval), VALUE_BITSIZE (toval)); write_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval), &val, sizeof val); @@ -156,7 +168,7 @@ value_assign (toval, fromval) read_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval), &val, sizeof val); - modify_field (&val, value_as_long (fromval), + modify_field (&val, (int) value_as_long (fromval), VALUE_BITPOS (toval), VALUE_BITSIZE (toval)); write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval), &val, sizeof val); @@ -169,6 +181,76 @@ value_assign (toval, fromval) 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; + CORE_ADDR addr; + + /* 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++) + { + addr = find_saved_register (frame, regno); + if (addr == 0) + read_register_bytes (REGISTER_BYTE (regno), + buffer + amount_copied, + reg_size); + else + read_memory (addr, buffer + amount_copied, reg_size); + } + + /* 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) + bcopy (raw_buffer, buffer + byte_offset, use_buffer); + else + bcopy (VALUE_CONTENTS (fromval), buffer + byte_offset, + 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++) + { + addr = find_saved_register (frame, regno); + if (addr == 0) + write_register_bytes (REGISTER_BYTE (regno), + buffer + amount_copied, + reg_size); + else + write_memory (addr, buffer + amount_copied, reg_size); + } + } + break; + + default: error ("Left side of = operation is not an lvalue."); } @@ -238,7 +320,7 @@ value_coerce_array (arg1) /* Get the type of the result. */ type = lookup_pointer_type (type); val = value_from_long (builtin_type_long, - VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1)); + (LONGEST) (VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1))); VALUE_TYPE (val) = type; return val; } @@ -265,7 +347,7 @@ value_addr (arg1) /* Get the type of the result. */ type = lookup_pointer_type (VALUE_TYPE (arg1)); val = value_from_long (builtin_type_long, - VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1)); + (LONGEST) (VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1))); VALUE_TYPE (val) = type; return val; } @@ -277,7 +359,7 @@ value_ind (arg1) value arg1; { /* Must do this before COERCE_ARRAY, otherwise an infinite loop - will result. */ + will result */ if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_REF) return value_at (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)), (CORE_ADDR) value_as_long (arg1)); @@ -289,7 +371,7 @@ value_ind (arg1) /* Allow * on an integer so we can cast it to whatever we want. */ if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_INT) - return value_at (builtin_type_long, + return value_at (builtin_type_long, (CORE_ADDR) value_as_long (arg1)); else if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR) return value_at (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)), @@ -415,15 +497,22 @@ call_function (function, nargs, args) 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; + + save_inferior_status (&inf_status, 1); + old_chain = make_cleanup (restore_inferior_status, &inf_status); PUSH_DUMMY_FRAME; old_sp = sp = read_register (SP_REGNUM); -#if 1 INNER_THAN 2 /* Stack grows down */ +#if 1 INNER_THAN 2 /* Stack grows down */ sp -= sizeof dummy; start_sp = sp; -#else /* Stack grows up */ +#else /* Stack grows up */ start_sp = sp; sp += sizeof dummy; #endif @@ -471,44 +560,98 @@ call_function (function, nargs, args) else error ("Invalid data type for function to be called."); + /* Are we returning a value using a structure return or a normal + value return? */ + + struct_return = using_struct_return (function, funaddr, value_type); + /* Create a call sequence customized for this function and the number of arguments for it. */ bcopy (dummy, dummy1, sizeof dummy); -#ifdef sun4 FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, value_type); -#else - FIX_CALL_DUMMY (dummy1, funaddr, nargs); -#endif } write_memory (start_sp, dummy1, sizeof dummy); +#ifdef convex + /* 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; + start_sp = text_end - sizeof dummy; + write_memory (start_sp, dummy1, sizeof dummy); + } +#else /* !convex */ #ifdef STACK_ALIGN - /* If stack grows down, we must leave a hole at the top. */ + /* 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 (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 +#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 + } + for (i = nargs - 1; i >= 0; i--) sp = value_arg_push (sp, args[i]); #ifdef CALL_DUMMY_STACK_ADJUST #if 1 INNER_THAN 2 - sp -= CALL_DUMMY_STACK_ADJUST; + sp -= CALL_DUMMY_STACK_ADJUST; #else - sp += CALL_DUMMY_STACK_ADJUST; -#endif + sp += CALL_DUMMY_STACK_ADJUST; #endif +#endif /* CALL_DUMMY_STACK_ADJUST */ +#endif /* !convex */ + + /* 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 this + convention in a slightly twisted way also. */ + if (struct_return) + STORE_STRUCT_RETURN (struct_addr, sp); + + /* Write the stack pointer. This is here because the statement above + might fool with it */ write_register (SP_REGNUM, sp); /* Figure out the value returned by the function. */ @@ -520,7 +663,9 @@ call_function (function, nargs, args) after storing the contents of all regs into retbuf. */ run_stack_dummy (start_sp + CALL_DUMMY_START_OFFSET, retbuf); - return value_being_returned (value_type, retbuf); + do_cleanups (old_chain); + + return value_being_returned (value_type, retbuf, struct_return); } } @@ -566,7 +711,7 @@ value_string (ptr, len) /* Find the address of malloc in the inferior. */ - sym = lookup_symbol ("malloc", 0, VAR_NAMESPACE); + sym = lookup_symbol ("malloc", 0, VAR_NAMESPACE, 0); if (sym != 0) { if (SYMBOL_CLASS (sym) != LOC_BLOCK) @@ -581,16 +726,16 @@ value_string (ptr, len) break; if (i < misc_function_count) val = value_from_long (builtin_type_long, - misc_function_vector[i].address); + (LONGEST) misc_function_vector[i].address); else error ("String constants require the program to have a function \"malloc\"."); } - blocklen = value_from_long (builtin_type_int, len + 1); + blocklen = value_from_long (builtin_type_int, (LONGEST) (len + 1)); val = call_function (val, 1, &blocklen); if (value_zerop (val)) error ("No memory available for string constant."); - write_memory (value_as_long (val), copy, len + 1); + write_memory ((CORE_ADDR) value_as_long (val), copy, len + 1); VALUE_TYPE (val) = lookup_pointer_type (builtin_type_char); return val; } @@ -634,14 +779,13 @@ value_struct_elt (arg1, args, name, err) error ("not implemented: member type in value_struct_elt"); if (TYPE_CODE (t) != TYPE_CODE_STRUCT - && - TYPE_CODE (t) != TYPE_CODE_UNION) + && TYPE_CODE (t) != TYPE_CODE_UNION) error ("Attempt to extract a component of a value that is not a %s.", err); baseclass = t; if (!args) - { + { /* if there are no arguments ...do this... */ /* Try as a variable first, because if we succeed, there @@ -656,7 +800,7 @@ value_struct_elt (arg1, args, name, err) break; } } - + if (i >= 0) return TYPE_FIELD_STATIC (t, i) ? value_static_field (t, name, i) : value_field (arg1, i); @@ -669,7 +813,7 @@ value_struct_elt (arg1, args, name, err) } /* C++: If it was not found as a data field, then try to - return it as a pointer to a method. */ + return it as a pointer to a method. */ t = baseclass; VALUE_TYPE (arg1) = t; /* side effect! */ @@ -702,7 +846,8 @@ value_struct_elt (arg1, args, name, err) if (!args[1]) { /* destructors are a special case. */ - return (value)value_fn_field (arg1, 0, TYPE_FN_FIELDLIST_LENGTH (t, 0)); + return (value)value_fn_field (arg1, 0, + TYPE_FN_FIELDLIST_LENGTH (t, 0)); } else { @@ -740,7 +885,7 @@ value_struct_elt (arg1, args, name, err) if (TYPE_N_BASECLASSES (t) == 0) break; - + t = TYPE_BASECLASS (t, 1); VALUE_TYPE (arg1) = t; /* side effect! */ } @@ -764,7 +909,7 @@ value_struct_elt (arg1, args, name, err) break; } } - + if (i >= 0) return TYPE_FIELD_STATIC (t, i) ? value_static_field (t, name, i) : value_field (arg1, i); @@ -808,7 +953,7 @@ destructor_name_p (name, type) /* C++: Given ARG1, a value of type (pointer to a)* structure/union, return 1 if the component named NAME from the ultimate target structure/union is defined, otherwise, return 0. */ - + int check_field (arg1, name) register value arg1; @@ -851,7 +996,6 @@ check_field (arg1, name) return 1; } } - if (TYPE_N_BASECLASSES (t) == 0) break; @@ -860,7 +1004,7 @@ check_field (arg1, name) } /* C++: If it was not found as a data field, then try to - return it as a pointer to a method. */ + return it as a pointer to a method. */ t = baseclass; VALUE_TYPE (arg1) = t; /* side effect! */ @@ -889,7 +1033,7 @@ check_field (arg1, name) type. If INTYPE is non-null, then it will be the type of the member we are looking for. This will help us resolve pointers to member functions. */ - + value value_struct_elt_for_address (domain, intype, name) struct type *domain, *intype; @@ -917,8 +1061,10 @@ value_struct_elt_for_address (domain, intype, name) if (TYPE_FIELD_PACKED (t, i)) error ("pointers to bitfield members not allowed"); - v = value_from_long (builtin_type_int, TYPE_FIELD_BITPOS (t, i) >> 3); - VALUE_TYPE (v) = lookup_pointer_type (lookup_member_type (TYPE_FIELD_TYPE (t, i), baseclass)); + v = value_from_long (builtin_type_int, + (LONGEST) (TYPE_FIELD_BITPOS (t, i) >> 3)); + VALUE_TYPE (v) = lookup_pointer_type ( + lookup_member_type (TYPE_FIELD_TYPE (t, i), baseclass)); return v; } } @@ -930,7 +1076,7 @@ value_struct_elt_for_address (domain, intype, name) } /* C++: If it was not found as a data field, then try to - return it as a pointer to a method. */ + return it as a pointer to a method. */ t = baseclass; /* Destructors are a special case. */ @@ -968,12 +1114,12 @@ value_struct_elt_for_address (domain, intype, name) if (TYPE_FN_FIELD_VIRTUAL_P (f, j)) { v = value_from_long (builtin_type_long, - TYPE_FN_FIELD_VOFFSET (f, j)); + (LONGEST) TYPE_FN_FIELD_VOFFSET (f, j)); } else { struct symbol *s = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, j), - 0, VAR_NAMESPACE); + 0, VAR_NAMESPACE, 0); v = locate_var_value (s, 0); } VALUE_TYPE (v) = lookup_pointer_type (lookup_member_type (TYPE_FN_FIELD_TYPE (f, j), baseclass)); @@ -1000,7 +1146,7 @@ int typecmp(t1, t2) value t2[]; { int i; - + if (t1[0]->code == TYPE_CODE_VOID) return 0; if (!t1[1]) return 0; for (i = 1; t1[i] && t1[i]->code != TYPE_CODE_VOID; i++) @@ -1016,10 +1162,6 @@ int typecmp(t1, t2) return t2[i] ? i+1 : 0; } -#ifndef FRAME -#include "frame.h" -#endif - /* C++: return the value of the class instance variable, if one exists. Flag COMPLAIN signals an error if the request is made in an inappropriate context. */ @@ -1061,9 +1203,3 @@ value_of_this (complain) return read_var_value (sym, selected_frame); } - -static -initialize () -{ } - -END_FILE |