[m-dev.] for review: new debugger command set (part 1 of 4)
Fergus Henderson
fjh at cs.mu.OZ.AU
Thu Oct 15 17:58:38 AEST 1998
On 14-Oct-1998, Zoltan Somogyi <zs at cs.mu.OZ.AU> wrote:
>
> > And that at long last completes this round of reviewing for me.
> > I'd like to see a relative diff next time.
>
> Most of the diff is dull, so I won't include it here; it is in the file
> DIRDIFF in ~zs/mer/ws5 on hydra.
...
from DIRDIFF:
> +BUG FIX: ! MR_STATIC_CODE_ADDRESSES and MR_USE_STACK_LAYOUTS
> +
> +runtime/mercury_conf_param.h:
> + Move the definition of MR_STATIC_CODE_ADDRESSES before the definition
> + of MR_USE_STACK_LAYOUTS, since MR_USE_STACK_LAYOUTS depends on whether
> + MR_STATIC_CODE_ADDRESSES is defined. This fixes a bug introduced
> + on september 15.
That fix is already committed, I think, so you should include
that in the log message for these other changes.
> +BUG FIX: REMOVE BROWSER/*.M
> +
> +configure.in:
> + When removing .c files generated by the C compiler, remove those
> + in the browser directory as well as the compiler, library and
> + profiler directories.
s/*.M/*.c/
> diff -u //home/mercury1/zs/2oct98/library/io.m library/io.m
> --- //home/mercury1/zs/2oct98/library/io.m Fri Oct 2 12:30:07 1998
> +++ library/io.m Wed Oct 14 18:05:24 1998
> @@ -1029,12 +1029,20 @@
> :- pred io__set_op_table(ops__table, io__state, io__state).
> :- mode io__set_op_table(di, di, uo) is det.
>
> +% For use by the debugger:
> +
> +:- pred io__get_io_input_stream_type(type_info, io__state, io__state).
> +:- mode io__get_io_input_stream_type(out, di, uo) is det.
> +
> +:- pred io__get_io_output_stream_type(type_info, io__state, io__state).
> +:- mode io__get_io_output_stream_type(out, di, uo) is det.
These predicates don't strictly need to be declared in the interface;
the `pragma export' declarations are enough. They will after all
be declared in the automatically generated C header file.
> +++ library/std_util.m Wed Oct 14 16:01:45 1998
...
> + % This predicate returns the type_info for the type std_util:type_info.
> + % It is intended for use from C code, since Mercury code can access
> + % this type_info easily enough even without this predicate.
> +:- pred get_type_info_for_type_info(type_info).
> +:- mode get_type_info_for_type_info(out) is det.
Likewise.
> + /* XXX We must pass NULL here because the registers */
> + /* have not been saved. This is probably a bug; */
> + /* Tyson should look into it. */
Comments should be formatted as
/*
** ...
*/
> +++ runtime/mercury_trace_base.c Wed Oct 14 20:42:08 1998
> - hfp = fopen(".mercury_histogram", "w");
> + hfp = fopen(MR_TRACE_HISTOGRAM_FILENAME, "w");
> if (hfp != NULL) {
...
> }
> }
There should be an `else' case here which prints an error message
if fopen() failed.
> +++ trace/mercury_trace_help.c Wed Oct 14 18:12:18 1998
...
> ** Before we call the C functions automatically generated by the Mercury
> ** compiler for the predicates we want to call, we call the function
> ** MR_copy_saved_regs_to_regs. This puts the contents in the saved_regs array
> ** (which includes all the control registers of the Mercury virtual machine,
> ** and which was saved on entry to the tracing system) into both the machine
> ** registers and into the MR_fake_reg array.
> **
> ** We do not save the registers anywhere after these functions return.
> ** We are not interested in the contents of the general registers and MR_succip
> ** at the return points, as we will restore the registers from saved_reg
> ** before the tracing system gives control back to the program. The call
> ** must leave the contents of MR_sp, MR_maxfr and MR_curfr unchanged.
> ** It may push new cells onto the heap or the trail, but we discard those
> ** cells (by not saving the new values of the heap and trail pointers),
> ** *after* copying any cells we want to keep to non-heap storage.
I thought about this a bit more.
I don't think this approach will work, because MR_global_hp, the heap
pointer for the "global" (permanent) heap, is one of the control
registers of the Mercury virtual machine.
> const char *
> -MR_trace_add_cat(const char *category, int slot, const char *text)
> +MR_trace_add_cat(const char *category, int slot, const char *text,
> + Word *saved_regs, int max_mr_num)
> {
> Word path;
>
> * MR_trace_help_ensure_init(saved_regs, max_mr_num);
> * MR_copy_saved_regs_to_regs(max_mr_num, saved_regs);
> path = list_empty();
> * save_transient_registers();
> * return MR_trace_help_add_node(path, category, slot, text,
> * saved_regs, max_mr_num);
> }
As well as the problem with MR_copy_saved_regs_to_regs() and MR_global_hp,
the call to list_empty() is still problematic, and
the call to save_transient_registers() will still save
bogus values. You need to add a call to restore_transient_registers()
before the call to list_empty().
> const char *
> MR_trace_add_item(const char *category, const char *item, int slot,
> - const char *text)
> + const char *text, Word *saved_regs, int max_mr_num)
> {
> Word path;
>
> - MR_trace_help_ensure_init();
> + MR_trace_help_ensure_init(saved_regs, max_mr_num);
> + MR_copy_saved_regs_to_regs(max_mr_num, saved_regs);
> path = list_empty();
> path = list_cons(category, path);
> - return MR_trace_help_add_node(path, item, slot, text);
> + save_transient_registers();
> + return MR_trace_help_add_node(path, item, slot, text,
> + saved_regs, max_mr_num);
> }
Likewise.
> +MR_trace_help_add_node(Word path, const char *name, int slot, const char *text,
> + Word *saved_regs, int max_mr_num)
> {
> Word result;
> char *msg;
>
> + MR_copy_saved_regs_to_regs(max_mr_num, saved_regs);
> ML_HELP_add_help_node(MR_trace_help_system, path, slot,
> (String) (Word) name, (String) (Word) text,
> &result, &MR_trace_help_system);
> +
> + MR_copy_saved_regs_to_regs(max_mr_num, saved_regs);
> + MR_trace_help_system = MR_make_permanent(MR_trace_help_system,
> + MR_trace_help_system_type);
> +
> + MR_copy_saved_regs_to_regs(max_mr_num, saved_regs);
You should delete the second call to MR_copy_saved_regs_to_regs(),
since that call will reset the heap pointer and thus effectively
deallocate the value pointed to be MR_trace_help_system before
it has been made permanent.
Same applies to the third call to MR_copy_saved_regs_to_regs(),
since that will deallocate the value pointed to by `result',
which is used later.
> void
> -MR_trace_help_cat_item(const char *category, const char *item)
> +MR_trace_help_cat_item(const char *category, const char *item,
> + Word *saved_regs, int max_mr_num)
> {
> Word path;
> Word result;
> char *msg;
>
> - MR_trace_help_ensure_init();
> + MR_trace_help_ensure_init(saved_regs, max_mr_num);
> path = list_empty();
> path = list_cons(item, path);
> path = list_cons(category, path);
> + save_transient_registers();
> ML_HELP_path(MR_trace_help_system, path, MR_trace_help_stdout, &result);
> + MR_copy_saved_regs_to_regs(max_mr_num, saved_regs);
> if (ML_HELP_result_is_error(result, &msg)) {
> printf("internal error in the trace help system: %s\n", msg);
> }
> }
Again you need a call to restore_transient_registers() before the
call to list_empty().
The call to MR_copy_saved_regs_to_regs() effectively deallocates
the memory pointed to by `result' before it is used.
I don't understand why the call to MR_copy_saved_regs_to_regs()
is where it is.
> static void
> +MR_trace_help_ensure_init(Word *saved_regs, int max_mr_num)
> {
> + static bool done = FALSE;
> + Word typeinfo_type;
> + Word output_stream_type;
> +
> + if (! done) {
> + MR_copy_saved_regs_to_regs(max_mr_num, saved_regs);
> + ML_get_type_info_for_type_info(&typeinfo_type);
> + ML_HELP_help_system_type(&MR_trace_help_system_type);
> + MR_trace_help_system = MR_make_permanent(
> + MR_trace_help_system_type,
> + typeinfo_type);
>
> + MR_copy_saved_regs_to_regs(max_mr_num, saved_regs);
> ML_HELP_init(&MR_trace_help_system);
> +
> + MR_copy_saved_regs_to_regs(max_mr_num, saved_regs);
> + MR_trace_help_system = MR_make_permanent(MR_trace_help_system,
> + MR_trace_help_system_type);
> +
> + MR_copy_saved_regs_to_regs(max_mr_num, saved_regs);
> + ML_io_output_stream_type(&output_stream_type);
> ML_io_stdout_stream(&MR_trace_help_stdout);
> + MR_trace_help_stdout = MR_make_permanent(MR_trace_help_stdout,
> + output_stream_type);
Again there are problems here with the calls to MR_copy_saved_regs_to_regs();
they may deallocate memory before it is used.
> +++ trace/mercury_trace_internal.c Wed Oct 14 20:08:35 1998
...
> static void
> MR_trace_internal_ensure_init(void)
> {
...
> - printf(MR_trace_banner);
> + if (getenv("MERCURY_SUPPRESS_MDB_VERSION") != NULL) {
> + printf(MR_trace_banner, "VERSION");
> + } else {
> + printf(MR_trace_banner, MR_VERSION);
> + }
> +
I don't understand what that code is trying to do.
What's the point of the undocumented MERCURY_SUPRESS_MDB_VERSION
environment variable?
> MR_trace_internal_init_from_env("MERCURY_DEBUGGER_INIT") ||
> MR_trace_internal_init_from_file(MDBRC_FILENAME) ||
> MR_trace_internal_init_from_env_dir("HOME", MDBRC_FILENAME) ||
> - MR_trace_internal_init_from_env("DEFAULT_MERCURY_DEBUGGER_INIT");
> + MR_trace_internal_init_from_env(
> + "DEFAULT_MERCURY_DEBUGGER_INIT");
Hmm, shouldn't you print an error message if all four steps fail?
> + /* XXX This code is too Unix specific. */
> buf = checked_malloc(strlen(env) + strlen(filename) + 2);
> (void) strcpy(buf, env);
> (void) strcat(buf, "/");
I would really much prefer you to
> +#ifdef MR_TRACE_HISTOGRAM
> } else if (streq(words[0], "histogram_all")) {
> if (word_count == 2) {
> FILE *fp;
>
> fp = fopen(words[1], "w");
> if (fp == NULL) {
> - perror(words[1]);
> + fprintf(stderr, "mdb: cannot open file `%s' "
> + "for output: %s.",
> + words[1], strerror(errno));
Missing `\n'.
> } else {
> MR_trace_print_histogram(fp, "All-inclusive",
> MR_trace_histogram_all,
> MR_trace_histogram_hwm);
> - fclose(fp);
> + if (fclose(fp) != 0) {
> + fprintf(stderr, "mdb: error closing "
> + "file `%s': %s.",
> + words[1], strerror(errno));
> + }
Ditto.
> + fp = fopen(words[1], "w");
> if (fp == NULL) {
> - perror(words[1]);
> + fprintf(stderr, "mdb: cannot open file `%s' "
> + "for output: %s.",
> + words[1], strerror(errno));
Ditto.
> } else {
> MR_trace_print_histogram(fp, "Experimental",
> MR_trace_histogram_exp,
> MR_trace_histogram_hwm);
> - fclose(fp);
> + if (fclose(fp) != 0) {
> + fprintf(stderr, "mdb: error closing "
> + "file `%s': %s.",
> + words[1], strerror(errno));
> + }
Ditto.
> } else if (streq(words[0], "source")) {
> if (word_count == 2) {
> - MR_trace_source(words[1]);
> + /* If it fails, the error message */
> + /* will have already been printed. */
> + (void) MR_trace_source(words[1]);
Non-standard comment formatting.
> +++ doc/user_guide.texi Wed Oct 14 19:55:40 1998
> @@ -2782,13 +2782,17 @@
> * Debugger commands::
> @end menu
>
> + at c XXX
> +This chapter of the user guide is still under construction.
s/user guide/user's guide/
> @@ -2957,6 +2964,8 @@
> mdb @var{prog} @var{arg1} ...
> @end example
>
> +XXX more to come
That should be "@c XXX ...".
--------------------
The stuff involving MR_copy_saved_regs_to_regs() will need another
review, but apart from that, it looks OK.
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3 | -- the last words of T. S. Garp.
More information about the developers
mailing list