From 479fdd26ee1390b558509aec8e5f8a6a4d7074df Mon Sep 17 00:00:00 2001 From: Jim Kingdon Date: Wed, 18 Aug 1993 19:33:39 +0000 Subject: [PATCH] * blockframe.c (block_innermost_frame): Uncomment. Return NULL if passed NULL. * frame.h: Declare it. * expression.h (union exp_element): Add field block. * parse.c (write_exp_elt_block): New function. * expression.h (OP_VAR_VALUE): Now takes additional struct block *. * *-exp.y: Write block for OP_VAR_VALUE. * eval.c, expprint.c, parse.c: Deal with block for OP_VAR_VALUE. * valops.c, value.h (value_of_variable), callers: Add second argument, for block. --- gdb/ChangeLog | 11 ++++++++ gdb/blockframe.c | 11 ++++---- gdb/c-exp.y | 7 +++++ gdb/ch-exp.y | 2 ++ gdb/eval.c | 55 +++++++++++++++++++++++++++---------- gdb/frame.h | 33 +++++++++------------- gdb/m2-exp.y | 7 +++++ gdb/parse.c | 13 +++++++-- gdb/valops.c | 71 ++++++++++++++++++++++++++++++++++++++---------- 9 files changed, 153 insertions(+), 57 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index ecea9bedcb..c85a36930c 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,16 @@ Wed Aug 18 12:03:00 1993 Jim Kingdon (kingdon@lioth.cygnus.com) + * blockframe.c (block_innermost_frame): Uncomment. + Return NULL if passed NULL. + * frame.h: Declare it. + * expression.h (union exp_element): Add field block. + * parse.c (write_exp_elt_block): New function. + * expression.h (OP_VAR_VALUE): Now takes additional struct block *. + * *-exp.y: Write block for OP_VAR_VALUE. + * eval.c, expprint.c, parse.c: Deal with block for OP_VAR_VALUE. + * valops.c, value.h (value_of_variable), callers: + Add second argument, for block. + * main.c (gdb_readline): If we read some characters followed by EOF, return them rather than returning NULL. diff --git a/gdb/blockframe.c b/gdb/blockframe.c index 0e5dc1ab6c..6430cba7b9 100644 --- a/gdb/blockframe.c +++ b/gdb/blockframe.c @@ -724,10 +724,8 @@ find_pc_partial_function (pc, name, address, endaddr) return 1; } -/* Return the innermost stack frame executing inside of the specified block, - or zero if there is no such frame. */ - -#if 0 /* Currently unused */ +/* Return the innermost stack frame executing inside of BLOCK, + or zero if there is no such frame. If BLOCK is NULL, just return NULL. */ FRAME block_innermost_frame (block) @@ -738,6 +736,9 @@ block_innermost_frame (block) register CORE_ADDR start = BLOCK_START (block); register CORE_ADDR end = BLOCK_END (block); + if (block == NULL) + return NULL; + frame = 0; while (1) { @@ -750,8 +751,6 @@ block_innermost_frame (block) } } -#endif /* 0 */ - #ifdef SIGCONTEXT_PC_OFFSET /* Get saved user PC for sigtramp from sigcontext for BSD style sigtramp. */ diff --git a/gdb/c-exp.y b/gdb/c-exp.y index b841498275..42e482b357 100644 --- a/gdb/c-exp.y +++ b/gdb/c-exp.y @@ -564,6 +564,8 @@ variable: block COLONCOLON name copy_name ($3)); write_exp_elt_opcode (OP_VAR_VALUE); + /* block_found is set by lookup_symbol. */ + write_exp_elt_block (block_found); write_exp_elt_sym (sym); write_exp_elt_opcode (OP_VAR_VALUE); } ; @@ -620,6 +622,7 @@ variable: qualified_name if (sym) { write_exp_elt_opcode (OP_VAR_VALUE); + write_exp_elt_block (NULL); write_exp_elt_sym (sym); write_exp_elt_opcode (OP_VAR_VALUE); break; @@ -689,6 +692,10 @@ variable: name_not_typename break; } write_exp_elt_opcode (OP_VAR_VALUE); + /* We want to use the selected frame, not + another more inner frame which happens to + be in the same block. */ + write_exp_elt_block (NULL); write_exp_elt_sym (sym); write_exp_elt_opcode (OP_VAR_VALUE); } diff --git a/gdb/ch-exp.y b/gdb/ch-exp.y index 166d01aeba..58b82ead56 100644 --- a/gdb/ch-exp.y +++ b/gdb/ch-exp.y @@ -346,6 +346,7 @@ location : access_name access_name : LOCATION_NAME { write_exp_elt_opcode (OP_VAR_VALUE); + write_exp_elt_block (NULL); write_exp_elt_sym ($1.sym); write_exp_elt_opcode (OP_VAR_VALUE); } @@ -477,6 +478,7 @@ value_name : synonym_name | GENERAL_PROCEDURE_NAME { write_exp_elt_opcode (OP_VAR_VALUE); + write_exp_elt_block (NULL); write_exp_elt_sym ($1.sym); write_exp_elt_opcode (OP_VAR_VALUE); } diff --git a/gdb/eval.c b/gdb/eval.c index 98774bfc41..4aba99f777 100644 --- a/gdb/eval.c +++ b/gdb/eval.c @@ -197,7 +197,7 @@ evaluate_subexp (expect_type, exp, pos, noside) exp->elts[pc + 2].doubleconst); case OP_VAR_VALUE: - (*pos) += 2; + (*pos) += 3; if (noside == EVAL_SKIP) goto nosideret; if (noside == EVAL_AVOID_SIDE_EFFECTS) @@ -226,7 +226,8 @@ evaluate_subexp (expect_type, exp, pos, noside) return value_zero (SYMBOL_TYPE (sym), lv); } else - return value_of_variable (exp->elts[pc + 1].symbol); + return value_of_variable (exp->elts[pc + 2].symbol, + exp->elts[pc + 1].block); case OP_LAST: (*pos) += 2; @@ -373,6 +374,20 @@ evaluate_subexp (expect_type, exp, pos, noside) if (op == STRUCTOP_STRUCT) { + /* If v is a variable in a register, and the user types + v.method (), this will produce an error, because v has + no address. + + A possible way around this would be to allocate a + copy of the variable on the stack, copy in the + contents, call the function, and copy out the + contents. I.e. convert this from call by reference + to call by copy-return (or whatever it's called). + However, this does not work because it is not the + same: the method being called could stash a copy of + the address, and then future uses through that address + (after the method returns) would be expected to + use the variable itself, not some copy of it. */ arg2 = evaluate_subexp_for_address (exp, pos, noside); } else @@ -1041,14 +1056,14 @@ evaluate_subexp_for_address (exp, pos, noside) evaluate_subexp (NULL_TYPE, exp, pos, noside)); case OP_VAR_VALUE: - var = exp->elts[pc + 1].symbol; + var = exp->elts[pc + 2].symbol; /* C++: The "address" of a reference should yield the address * of the object pointed to. Let value_addr() deal with it. */ if (TYPE_CODE (SYMBOL_TYPE (var)) == TYPE_CODE_REF) goto default_case; - (*pos) += 3; + (*pos) += 4; if (noside == EVAL_AVOID_SIDE_EFFECTS) { struct type *type = @@ -1065,7 +1080,10 @@ evaluate_subexp_for_address (exp, pos, noside) value_zero (type, not_lval); } else - return locate_var_value (var, (FRAME) 0); + return + locate_var_value + (var, + block_innermost_frame (exp->elts[pc + 1].block)); default: default_case: @@ -1085,14 +1103,15 @@ evaluate_subexp_for_address (exp, pos, noside) /* Evaluate like `evaluate_subexp' except coercing arrays to pointers. When used in contexts where arrays will be coerced anyway, this is equivalent to `evaluate_subexp' but much faster because it avoids - actually fetching array contents. + actually fetching array contents (perhaps obsolete now that we have + VALUE_LAZY). Note that we currently only do the coercion for C expressions, where arrays are zero based and the coercion is correct. For other languages, with nonzero based arrays, coercion loses. Use CAST_IS_CONVERSION to decide if coercion is appropriate. - */ + */ static value evaluate_subexp_with_coercion (exp, pos, noside) @@ -1111,17 +1130,21 @@ evaluate_subexp_with_coercion (exp, pos, noside) switch (op) { case OP_VAR_VALUE: - var = exp->elts[pc + 1].symbol; + var = exp->elts[pc + 2].symbol; if (TYPE_CODE (SYMBOL_TYPE (var)) == TYPE_CODE_ARRAY && CAST_IS_CONVERSION) { - (*pos) += 3; - val = locate_var_value (var, (FRAME) 0); + (*pos) += 4; + val = + locate_var_value + (var, block_innermost_frame (exp->elts[pc + 1].block)); return value_cast (lookup_pointer_type (TYPE_TARGET_TYPE (SYMBOL_TYPE (var))), val); } - default: - return evaluate_subexp (NULL_TYPE, exp, pos, noside); + /* FALLTHROUGH */ + + default: + return evaluate_subexp (NULL_TYPE, exp, pos, noside); } } @@ -1159,9 +1182,11 @@ evaluate_subexp_for_sizeof (exp, pos) (LONGEST) TYPE_LENGTH (exp->elts[pc + 1].type)); case OP_VAR_VALUE: - (*pos) += 3; - return value_from_longest (builtin_type_int, - (LONGEST) TYPE_LENGTH (SYMBOL_TYPE (exp->elts[pc + 1].symbol))); + (*pos) += 4; + return + value_from_longest + (builtin_type_int, + (LONGEST) TYPE_LENGTH (SYMBOL_TYPE (exp->elts[pc + 2].symbol))); default: val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS); diff --git a/gdb/frame.h b/gdb/frame.h index 89df84313d..042eb0b89a 100644 --- a/gdb/frame.h +++ b/gdb/frame.h @@ -223,34 +223,27 @@ get_frame_pc PARAMS ((FRAME)); extern CORE_ADDR get_pc_function_start PARAMS ((CORE_ADDR)); -extern struct block * -block_for_pc PARAMS ((CORE_ADDR)); +extern struct block * block_for_pc PARAMS ((CORE_ADDR)); -extern int -frameless_look_for_prologue PARAMS ((FRAME)); +extern int frameless_look_for_prologue PARAMS ((FRAME)); -extern void -print_frame_args PARAMS ((struct symbol *, struct frame_info *, int, FILE *)); +extern void print_frame_args PARAMS ((struct symbol *, struct frame_info *, + int, FILE *)); -extern FRAME -find_relative_frame PARAMS ((FRAME, int*)); +extern FRAME find_relative_frame PARAMS ((FRAME, int*)); -extern void -print_stack_frame PARAMS ((FRAME, int, int)); +extern void print_stack_frame PARAMS ((FRAME, int, int)); -extern void -select_frame PARAMS ((FRAME, int)); +extern void select_frame PARAMS ((FRAME, int)); -extern void -record_selected_frame PARAMS ((FRAME_ADDR *, int *)); +extern void record_selected_frame PARAMS ((FRAME_ADDR *, int *)); -extern void -print_frame_info PARAMS ((struct frame_info *, int, int, int)); +extern void print_frame_info PARAMS ((struct frame_info *, int, int, int)); -extern CORE_ADDR -find_saved_register PARAMS ((FRAME, int)); +extern CORE_ADDR find_saved_register PARAMS ((FRAME, int)); -extern CORE_ADDR -sigtramp_saved_pc PARAMS ((FRAME)); +extern FRAME block_innermost_frame PARAMS ((struct block *)); + +extern CORE_ADDR sigtramp_saved_pc PARAMS ((FRAME)); #endif /* !defined (FRAME_H) */ diff --git a/gdb/m2-exp.y b/gdb/m2-exp.y index 56ed6e675e..b00af97d50 100644 --- a/gdb/m2-exp.y +++ b/gdb/m2-exp.y @@ -559,6 +559,7 @@ fblock : block COLONCOLON BLOCKNAME /* Useful for assigning to PROCEDURE variables */ variable: fblock { write_exp_elt_opcode(OP_VAR_VALUE); + write_exp_elt_block (NULL); write_exp_elt_sym ($1); write_exp_elt_opcode (OP_VAR_VALUE); } ; @@ -580,6 +581,8 @@ variable: block COLONCOLON NAME copy_name ($3)); write_exp_elt_opcode (OP_VAR_VALUE); + /* block_found is set by lookup_symbol. */ + write_exp_elt_block (block_found); write_exp_elt_sym (sym); write_exp_elt_opcode (OP_VAR_VALUE); } ; @@ -623,6 +626,10 @@ variable: NAME break; } write_exp_elt_opcode (OP_VAR_VALUE); + /* We want to use the selected frame, not + another more inner frame which happens to + be in the same block. */ + write_exp_elt_block (NULL); write_exp_elt_sym (sym); write_exp_elt_opcode (OP_VAR_VALUE); } diff --git a/gdb/parse.c b/gdb/parse.c index 4cec13b38b..94e467e3d2 100644 --- a/gdb/parse.c +++ b/gdb/parse.c @@ -178,6 +178,15 @@ write_exp_elt_sym (expelt) write_exp_elt (tmp); } +void +write_exp_elt_block (b) + struct block *b; +{ + union exp_element tmp; + tmp.block = b; + write_exp_elt (tmp); +} + void write_exp_elt_longcst (expelt) LONGEST expelt; @@ -389,12 +398,12 @@ length_of_subexp (expr, endpos) case OP_LONG: case OP_DOUBLE: + case OP_VAR_VALUE: oplen = 4; break; case OP_TYPE: case OP_BOOL: - case OP_VAR_VALUE: case OP_LAST: case OP_REGISTER: case OP_INTERNALVAR: @@ -518,12 +527,12 @@ prefixify_subexp (inexpr, outexpr, inend, outbeg) case OP_LONG: case OP_DOUBLE: + case OP_VAR_VALUE: oplen = 4; break; case OP_TYPE: case OP_BOOL: - case OP_VAR_VALUE: case OP_LAST: case OP_REGISTER: case OP_INTERNALVAR: diff --git a/gdb/valops.c b/gdb/valops.c index 24eefcadee..1b409ff82a 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -81,7 +81,7 @@ allocate_space_in_inferior (len) { error ("\"malloc\" exists in this program but is not a function."); } - val = value_of_variable (sym); + val = value_of_variable (sym, NULL); } else { @@ -332,7 +332,7 @@ value_assign (toval, fromval) 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), + modify_field ((char *) &v, value_as_long (fromval), VALUE_BITPOS (toval), VALUE_BITSIZE (toval)); write_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval), (char *)&v, sizeof v); @@ -352,7 +352,7 @@ value_assign (toval, fromval) read_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval), (char *) &v, sizeof v); - modify_field ((char *) &v, (int) value_as_long (fromval), + modify_field ((char *) &v, value_as_long (fromval), VALUE_BITPOS (toval), VALUE_BITSIZE (toval)); write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval), (char *) &v, sizeof v); @@ -415,7 +415,7 @@ value_assign (toval, fromval) /* Modify what needs to be modified. */ if (VALUE_BITSIZE (toval)) modify_field (buffer + byte_offset, - (int) value_as_long (fromval), + value_as_long (fromval), VALUE_BITPOS (toval), VALUE_BITSIZE (toval)); else if (use_buffer) memcpy (buffer + byte_offset, raw_buffer, use_buffer); @@ -498,12 +498,30 @@ value_repeat (arg1, count) } value -value_of_variable (var) +value_of_variable (var, b) struct symbol *var; + struct block *b; { value val; + FRAME fr; - val = read_var_value (var, (FRAME) 0); + if (b == NULL) + /* Use selected frame. */ + fr = NULL; + else + { + fr = block_innermost_frame (b); + if (fr == NULL) + { + if (BLOCK_FUNCTION (b) != NULL + && SYMBOL_NAME (BLOCK_FUNCTION (b)) != NULL) + error ("No frame is currently executing in block %s.", + SYMBOL_NAME (BLOCK_FUNCTION (b))); + else + error ("No frame is currently executing in specified block"); + } + } + val = read_var_value (var, fr); if (val == 0) error ("Address of symbol \"%s\" is unknown.", SYMBOL_SOURCE_NAME (var)); return val; @@ -632,14 +650,14 @@ push_word (sp, word) REGISTER_TYPE word; { register int len = sizeof (REGISTER_TYPE); - REGISTER_TYPE buffer; + char buffer[MAX_REGISTER_RAW_SIZE]; - store_unsigned_integer (&buffer, len, word); + store_unsigned_integer (buffer, len, word); #if 1 INNER_THAN 2 sp -= len; - write_memory (sp, (char *)&buffer, len); + write_memory (sp, buffer, len); #else /* stack grows upward */ - write_memory (sp, (char *)&buffer, len); + write_memory (sp, buffer, len); sp += len; #endif /* stack grows upward */ @@ -694,7 +712,15 @@ value_arg_coerce (arg) { register struct type *type; - COERCE_ENUM (arg); + /* FIXME: We should coerce this according to the prototype (if we have + one). Right now we do a little bit of this in typecmp(), but that + doesn't always get called. For example, if passing a ref to a function + without a prototype, we probably should de-reference it. Currently + we don't. */ + + if (TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_ENUM) + arg = value_cast (builtin_type_unsigned_int, arg); + #if 1 /* FIXME: This is only a temporary patch. -fnf */ if (VALUE_REPEATED (arg) || TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_ARRAY) @@ -1153,8 +1179,11 @@ value_string (ptr, len) return (val); } -/* Compare two argument lists and return the position in which they differ, - or zero if equal. +/* See if we can pass arguments in T2 to a function which takes arguments + of types T1. Both t1 and t2 are NULL-terminated vectors. If some + arguments need coercion of some sort, then the coerced values are written + into T2. Return value is 0 if the arguments could be matched, or the + position at which they differ if not. STATICP is nonzero if the T1 argument list came from a static member function. @@ -1186,8 +1215,22 @@ typecmp (staticp, t1, t2) if (! t2[i]) return i+1; if (TYPE_CODE (t1[i]) == TYPE_CODE_REF - && TYPE_TARGET_TYPE (t1[i]) == VALUE_TYPE (t2[i])) + /* We should be doing hairy argument matching, as below. */ + && (TYPE_CODE (TYPE_TARGET_TYPE (t1[i])) + == TYPE_CODE (VALUE_TYPE (t2[i])))) + { + t2[i] = value_addr (t2[i]); + continue; + } + + if (TYPE_CODE (t1[i]) == TYPE_CODE_PTR + && TYPE_CODE (VALUE_TYPE (t2[i])) == TYPE_CODE_ARRAY) + /* Array to pointer is a `trivial conversion' according to the ARM. */ continue; + + /* We should be doing much hairier argument matching (see section 13.2 + of the ARM), but as a quick kludge, just check for the same type + code. */ if (TYPE_CODE (t1[i]) != TYPE_CODE (VALUE_TYPE (t2[i]))) return i+1; } -- 2.34.1