david@CSVAX.CALTECH.EDU (David Hull) (03/16/89)
In the process of porting gdb 3.1 to the Intergraph CLIPPER, I found the following bug in the function print_frame_args() in printcmd.c: The CLIPPER C compiler (written by Green Hills) tries to pass the first two arguments to a function in registers. If the declared type of the argument is narrower than the type it was passed as, the argument is narrowed by copying it to a local variable, which is below the frame pointer on the stack. Thus its symbol value is negative. print_frame_args() will not print arguments with negative symbol values. Also, the function parameters are not necessarily ordered by symbol value, as print_frame_args() assumes. It turns out that, on the CLIPPER at least, the symbols for the arguments are always in the correct order in the symbol table (I think this is true for all COFF-format files). My solution was to have a special version of print_frame_args() for the CLIPPER. Since I think that it will work for all COFF machines, the new code is enabled with COFF_FORMAT. If I'm wrong, please let me know. In a related problem, print_frame_nameless_args() didn't always print a leading comma when it should. I added a new argument to tell it whether it needs to. -David --------------------------------------- David Hull TRW Inc. Redondo Beach, CA ...!{uunet,cit-vax,trwrb}!wiley!david david%wiley.uucp@csvax.caltech.edu *** orig/printcmd.c Thu Feb 16 15:23:26 1989 --- printcmd.c Tue Mar 14 14:18:17 1989 *************** *** 1159,1164 **** --- 1159,1224 ---- static void print_frame_nameless_args (); + #ifdef COFF_FORMAT + + void + print_frame_args (func, fi, num, stream) + struct symbol *func; + struct frame_info *fi; + int num; + FILE *stream; + { + struct block *b; + int nsyms = 0; + int first = 1; + register int i; + register int last_offset = FRAME_ARGS_SKIP; + register struct symbol *sym; + register value val; + register CORE_ADDR addr = FRAME_ARGS_ADDRESS (fi); + + if (func) + { + b = SYMBOL_BLOCK_VALUE (func); + nsyms = BLOCK_NSYMS (b); + } + + for (i = 0; i < nsyms; i++) + { + QUIT; + sym = BLOCK_SYM (b, i); + if ((SYMBOL_CLASS (sym) != LOC_ARG) && + (SYMBOL_CLASS (sym) != LOC_REGPARM)) + continue; + + /* Print the next arg. */ + if (SYMBOL_CLASS (sym) == LOC_REGPARM) + val = value_from_register (SYMBOL_TYPE (sym), + SYMBOL_VALUE (sym), + FRAME_INFO_ID (fi)); + else + val = value_at (SYMBOL_TYPE (sym), addr + SYMBOL_VALUE (sym)); + + if (! first) + fprintf (stream, ", "); + fprintf (stream, "%s=", SYMBOL_NAME (sym)); + value_print (val, stream, 0); + first = 0; + if ((SYMBOL_CLASS (sym) == LOC_ARG) && (SYMBOL_VALUE (sym) >= 0)) + last_offset = SYMBOL_VALUE (sym) + TYPE_LENGTH (SYMBOL_TYPE (sym)); + + /* Round up address of next arg to multiple of size of int. */ + last_offset + = ((last_offset + sizeof (int) - 1) / sizeof (int)) * sizeof (int); + } + if (num >= 0 && num * sizeof (int) + FRAME_ARGS_SKIP > last_offset) + print_frame_nameless_args (addr, last_offset, + num * sizeof (int) + FRAME_ARGS_SKIP, + first, stream); + } + + #else /* not COFF_FORMAT */ + void print_frame_args (func, fi, num, stream) struct symbol *func; *************** *** 1216,1222 **** && last_offset != (SYMBOL_VALUE (sym) / sizeof (int)) * sizeof (int)) { print_frame_nameless_args (addr, last_offset, SYMBOL_VALUE (sym), ! stream); first = 0; } /* Print the next arg. */ --- 1276,1282 ---- && last_offset != (SYMBOL_VALUE (sym) / sizeof (int)) * sizeof (int)) { print_frame_nameless_args (addr, last_offset, SYMBOL_VALUE (sym), ! first, stream); first = 0; } /* Print the next arg. */ *************** *** 1235,1244 **** if (SYMBOL_CLASS (sym) == LOC_ARG) last_offset = SYMBOL_VALUE (sym) + TYPE_LENGTH (SYMBOL_TYPE (sym)); else ! { ! last_regparm = SYMBOL_VALUE (sym) + 1; ! last_offset += TYPE_LENGTH (SYMBOL_TYPE (sym)); ! } /* Round up address of next arg to multiple of size of int. */ last_offset --- 1295,1301 ---- if (SYMBOL_CLASS (sym) == LOC_ARG) last_offset = SYMBOL_VALUE (sym) + TYPE_LENGTH (SYMBOL_TYPE (sym)); else ! last_regparm = SYMBOL_VALUE (sym) + 1; /* Round up address of next arg to multiple of size of int. */ last_offset *************** *** 1247,1267 **** } if (num >= 0 && num * sizeof (int) + FRAME_ARGS_SKIP > last_offset) print_frame_nameless_args (addr, last_offset, ! num * sizeof (int) + FRAME_ARGS_SKIP, stream); } static void ! print_frame_nameless_args (argsaddr, start, end, stream) CORE_ADDR argsaddr; int start; int end; FILE *stream; { while (start < end) { QUIT; ! if (start != FRAME_ARGS_SKIP) fprintf (stream, ", "); fprintf (stream, "%d", read_memory_integer (argsaddr + start, sizeof (int))); start += sizeof (int); --- 1304,1329 ---- } if (num >= 0 && num * sizeof (int) + FRAME_ARGS_SKIP > last_offset) print_frame_nameless_args (addr, last_offset, ! num * sizeof (int) + FRAME_ARGS_SKIP, ! first, stream); } + #endif /* not COFF_FORMAT */ + static void ! print_frame_nameless_args (argsaddr, start, end, first, stream) CORE_ADDR argsaddr; int start; int end; + int first; FILE *stream; { while (start < end) { QUIT; ! if (!first) fprintf (stream, ", "); + first = 0; fprintf (stream, "%d", read_memory_integer (argsaddr + start, sizeof (int))); start += sizeof (int);