From: Peter Johnson Date: Wed, 27 Feb 2002 05:43:16 +0000 (-0000) Subject: Revamp object format functional interface a bit. Now, only the output() X-Git-Tag: v0.1.0~63 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0177d689a1abbdb5c7132dfe4884d132c0229d3d;p=yasm Revamp object format functional interface a bit. Now, only the output() function gets a FILE *, and it's the only function that can write to a file. The object file is thus not opened until AFTER parsing and most error checking is complete. Necessitated adding a special case for the dbg object format because it needs to output to the "object" (debug) file from essentially every function. Added a global (debug_file) to support this. svn path=/trunk/yasm/; revision=476 --- diff --git a/frontends/yasm/yasm.c b/frontends/yasm/yasm.c index df46632c..87f1fea5 100644 --- a/frontends/yasm/yasm.c +++ b/frontends/yasm/yasm.c @@ -51,6 +51,9 @@ static int files_open = 0; /*@null@*/ static FILE *in = NULL, *obj = NULL; static int special_options = 0; +static int open_obj(void); +static void cleanup(sectionhead *sections); + /* Forward declarations: cmd line parser handlers */ static int opt_special_handler(char *cmd, /*@null@*/ char *param, int extra); static int opt_format_handler(char *cmd, /*@null@*/ char *param, int extra); @@ -154,12 +157,10 @@ main(int argc, char *argv[]) /* Set x86 as the architecture */ cur_arch = &x86_arch; - /* Set dbg as the object format */ - cur_objfmt = find_objfmt("dbg"); - if (!cur_objfmt) { - ErrorNow(_("unrecognized output format `%s'"), "dbg"); - return EXIT_FAILURE; - } + /* If not already specified, default to dbg as the object format. */ + if (!cur_objfmt) + cur_objfmt = find_objfmt("dbg"); + assert(cur_objfmt != NULL); /* open the object file if not specified */ if (!obj) { @@ -170,17 +171,19 @@ main(int argc, char *argv[]) /* replace (or add) extension */ obj_filename = replace_extension(in_filename, cur_objfmt->extension, "yasm.out"); + } - /* open the built filename */ - obj = fopen(obj_filename, "wb"); - if (!obj) { - ErrorNow(_("could not open file `%s'"), obj_filename); + /* Pre-open the object file as debug_file if we're using a debug-type + * format. (This is so the format can output ALL function call info). + */ + if (strcmp(cur_objfmt->keyword, "dbg") == 0) { + if (!open_obj()) return EXIT_FAILURE; - } + debug_file = obj; } /* Initialize the object format */ - cur_objfmt->initialize(obj); + cur_objfmt->initialize(in_filename, obj_filename); /* Set NASM as the parser */ cur_parser = find_parser("nasm"); @@ -200,53 +203,69 @@ main(int argc, char *argv[]) xfree(in_filename); if (OutputAllErrorWarning() > 0) { - sections_delete(sections); - symrec_delete_all(); - line_shutdown(); - floatnum_shutdown(); - intnum_shutdown(); - BitVector_Shutdown(); + cleanup(sections); return EXIT_FAILURE; } - /* XXX Only for temporary debugging! */ - fprintf(obj, "\nSections after parsing:\n"); - indent_level++; - sections_print(obj, sections); - indent_level--; - - fprintf(obj, "\nSymbol Table:\n"); - indent_level++; - symrec_print_all(obj); - indent_level--; - symrec_parser_finalize(); basic_optimizer.optimize(sections); if (OutputAllErrorWarning() > 0) { - sections_delete(sections); - symrec_delete_all(); - line_shutdown(); - floatnum_shutdown(); - intnum_shutdown(); - BitVector_Shutdown(); + cleanup(sections); return EXIT_FAILURE; } - fprintf(obj, "\nSections after optimization:\n"); - indent_level++; - sections_print(obj, sections); - indent_level--; + /* open the object file for output (if not already opened above) */ + if (!debug_file) { + if (!open_obj()) + return EXIT_FAILURE; + } + + /* Write the object file */ + cur_objfmt->output(obj, sections); /* Finalize the object output */ - cur_objfmt->finalize(); + cur_objfmt->cleanup(); if (obj != stdout) fclose(obj); + /* If we had an error at this point, we also need to delete the output + * object file (to make sure it's not left newer than the source). + */ + if (OutputAllErrorWarning() > 0) { + cleanup(sections); + if (obj != stdout) + remove(obj_filename); + return EXIT_FAILURE; + } + if (obj_filename) xfree(obj_filename); + cleanup(sections); + return EXIT_SUCCESS; +} +/*@=globstate =unrecog@*/ + +/* Open the object file. Returns 0 on failure. */ +static int +open_obj(void) +{ + if (obj != stdout) { + obj = fopen(obj_filename, "wb"); + if (!obj) { + ErrorNow(_("could not open file `%s'"), obj_filename); + return 0; + } + } + return 1; +} + +/* Cleans up all allocated structures. */ +static void +cleanup(sectionhead *sections) +{ sections_delete(sections); symrec_delete_all(); line_shutdown(); @@ -255,9 +274,7 @@ main(int argc, char *argv[]) intnum_shutdown(); BitVector_Shutdown(); - return EXIT_SUCCESS; } -/*@=globstate =unrecog@*/ /* * Command line options handlers @@ -296,7 +313,11 @@ static int opt_format_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra) { assert(param != NULL); - printf("selected format: %s\n", param); + cur_objfmt = find_objfmt(param); + if (!cur_objfmt) { + ErrorNow(_("unrecognized object format `%s'"), param); + return 1; + } return 0; } @@ -305,22 +326,22 @@ opt_objfile_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra) { assert(param != NULL); - if (strcasecmp(param, "stdout") == 0) + if (strcmp(param, "-") == 0) obj = stdout; - else if (strcasecmp(param, "stderr") == 0) - obj = stderr; else { if (obj) { WarningNow("can open only one output file, last specified used"); - if (obj != stdout && obj != stderr && fclose(obj)) + if (obj != stdout && fclose(obj)) ErrorNow("could not close old output file"); } } - obj = fopen(param, "wb"); - if (!obj) { - ErrorNow(_("could not open file `%s'"), param); - return 1; + if (obj != stdout) { + obj = fopen(param, "wb"); + if (!obj) { + ErrorNow(_("could not open file `%s'"), param); + return 1; + } } if (obj_filename) diff --git a/libyasm/linemgr.c b/libyasm/linemgr.c index f91a26f3..0e90638f 100644 --- a/libyasm/linemgr.c +++ b/libyasm/linemgr.c @@ -27,6 +27,14 @@ #include "globals.h" +/* Output file for debugging-type formats. This is so that functions that are + * called before the object file is usually opened can still write data out to + * it (whereas for "normal" formats the object file is not opened until later + * in the assembly process). Opening the file early is special-cased in + * main(). + */ +/*@null@*/ FILE *debug_file = NULL; + /* Current (selected) parser */ /*@null@*/ parser *cur_parser = NULL; diff --git a/libyasm/linemgr.h b/libyasm/linemgr.h index 54ffec47..72b69375 100644 --- a/libyasm/linemgr.h +++ b/libyasm/linemgr.h @@ -22,6 +22,14 @@ #ifndef YASM_GLOBALS_H #define YASM_GLOBALS_H +/* Output file for debugging-type formats. This is so that functions that are + * called before the object file is usually opened can still write data out to + * it (whereas for "normal" formats the object file is not opened until later + * in the assembly process). Opening the file early is special-cased in + * main(). + */ +extern /*@null@*/ FILE *debug_file; + /* Current (selected) parser */ extern /*@null@*/ parser *cur_parser; diff --git a/libyasm/objfmt.h b/libyasm/objfmt.h index d0e7750b..ae409a00 100644 --- a/libyasm/objfmt.h +++ b/libyasm/objfmt.h @@ -50,12 +50,19 @@ struct objfmt { /* debugfmt *default_df;*/ /* Initializes object output. Must be called before any other object - * format functions. + * format functions. Should NOT open the object file; the filenames are + * provided solely for informational purposes. */ - void (*initialize) (/*@dependent@*/ FILE *f); + void (*initialize) (const char *in_filename, const char *obj_filename); - /* Finishes object output, and cleans up anything created by initialize. */ - void (*finalize) (void); + /* Write out (post-optimized) sections to the object file. + * This function may call symrec functions as necessary (including + * symrec_traverse) to retrieve symbolic information. + */ + void (*output) (FILE *f, sectionhead *sections); + + /* Cleans up anything allocated by initialize. */ + void (*cleanup) (void); /* Switch object file sections. The first val of the valparams should * be the section name. Returns NULL if something's wrong, otherwise diff --git a/modules/objfmts/dbg/dbg-objfmt.c b/modules/objfmts/dbg/dbg-objfmt.c index aa58ca36..9866b67d 100644 --- a/modules/objfmts/dbg/dbg-objfmt.c +++ b/modules/objfmts/dbg/dbg-objfmt.c @@ -31,19 +31,36 @@ #include "objfmt.h" -/*@dependent@*/ FILE *dbg_f; +/* Note that the functions here write to debug_file. This is NOT legal for + * other object formats to do--only the output() function can write to a file, + * and only the file it's passed in its f parameter! + */ + +static void +dbg_objfmt_initialize(const char *in_filename, const char *obj_filename) +{ + fprintf(debug_file, "%*sinitialize(\"%s\", \"%s\")\n", indent_level, "", + in_filename, obj_filename); +} static void -dbg_objfmt_initialize(/*@dependent@*/ FILE *f) +dbg_objfmt_output(FILE *f, sectionhead *sections) { - dbg_f = f; - fprintf(dbg_f, "%*sinitialize(f)\n", indent_level, ""); + fprintf(f, "%*soutput(f, sections->\n", indent_level, ""); + indent_level++; + sections_print(f, sections); + indent_level--; + fprintf(f, "%*s)\n", indent_level, ""); + indent_level++; + fprintf(f, "%*sSymbol Table:\n", indent_level, ""); + symrec_print_all(f); + indent_level--; } static void -dbg_objfmt_finalize(void) +dbg_objfmt_cleanup(void) { - fprintf(dbg_f, "%*sfinalize()\n", indent_level, ""); + fprintf(debug_file, "%*scleanup()\n", indent_level, ""); } static /*@dependent@*/ /*@null@*/ section * @@ -55,22 +72,22 @@ dbg_objfmt_sections_switch(sectionhead *headp, valparamhead *valparams, section *retval; int isnew; - fprintf(dbg_f, "%*ssections_switch(headp, ", indent_level, ""); - vps_print(dbg_f, valparams); - fprintf(dbg_f, ", "); - vps_print(dbg_f, objext_valparams); - fprintf(dbg_f, "), returning "); + fprintf(debug_file, "%*ssections_switch(headp, ", indent_level, ""); + vps_print(debug_file, valparams); + fprintf(debug_file, ", "); + vps_print(debug_file, objext_valparams); + fprintf(debug_file, "), returning "); if ((vp = vps_first(valparams)) && !vp->param && vp->val != NULL) { retval = sections_switch_general(headp, vp->val, NULL, 0, &isnew); if (isnew) { - fprintf(dbg_f, "(new) "); + fprintf(debug_file, "(new) "); symrec_define_label(vp->val, retval, (bytecode *)NULL, 1); } - fprintf(dbg_f, "\"%s\" section\n", vp->val); + fprintf(debug_file, "\"%s\" section\n", vp->val); return retval; } else { - fprintf(dbg_f, "NULL\n"); + fprintf(debug_file, "NULL\n"); return NULL; } } @@ -78,7 +95,7 @@ dbg_objfmt_sections_switch(sectionhead *headp, valparamhead *valparams, static void dbg_objfmt_section_data_delete(/*@only@*/ void *data) { - fprintf(dbg_f, "%*ssection_data_delete(%p)\n", indent_level, "", data); + fprintf(debug_file, "%*ssection_data_delete(%p)\n", indent_level, "", data); xfree(data); } @@ -95,9 +112,9 @@ static /*@null@*/ void * dbg_objfmt_extern_data_new(const char *name, /*@unused@*/ /*@null@*/ valparamhead *objext_valparams) { - fprintf(dbg_f, "%*sextern_data_new(\"%s\", ", indent_level, "", name); - vps_print(dbg_f, objext_valparams); - fprintf(dbg_f, "), returning NULL\n"); + fprintf(debug_file, "%*sextern_data_new(\"%s\", ", indent_level, "", name); + vps_print(debug_file, objext_valparams); + fprintf(debug_file, "), returning NULL\n"); return NULL; } @@ -105,9 +122,9 @@ static /*@null@*/ void * dbg_objfmt_global_data_new(const char *name, /*@unused@*/ /*@null@*/ valparamhead *objext_valparams) { - fprintf(dbg_f, "%*sglobal_data_new(\"%s\", ", indent_level, "", name); - vps_print(dbg_f, objext_valparams); - fprintf(dbg_f, "), returning NULL\n"); + fprintf(debug_file, "%*sglobal_data_new(\"%s\", ", indent_level, "", name); + vps_print(debug_file, objext_valparams); + fprintf(debug_file, "), returning NULL\n"); return NULL; } @@ -116,13 +133,13 @@ dbg_objfmt_common_data_new(const char *name, /*@only@*/ expr *size, /*@unused@*/ /*@null@*/ valparamhead *objext_valparams) { - fprintf(dbg_f, "%*scommon_data_new(\"%s\", ", indent_level, "", name); - expr_print(dbg_f, size); - fprintf(dbg_f, ", "); - vps_print(dbg_f, objext_valparams); - fprintf(dbg_f, "), returning "); - expr_print(dbg_f, size); - fprintf(dbg_f, "\n"); + fprintf(debug_file, "%*scommon_data_new(\"%s\", ", indent_level, "", name); + expr_print(debug_file, size); + fprintf(debug_file, ", "); + vps_print(debug_file, objext_valparams); + fprintf(debug_file, "), returning "); + expr_print(debug_file, size); + fprintf(debug_file, "\n"); return size; } @@ -131,29 +148,29 @@ dbg_objfmt_declare_data_copy(SymVisibility vis, /*@only@*/ void *data) { void *retval; - fprintf(dbg_f, "%*sdeclare_data_copy(", indent_level, ""); + fprintf(debug_file, "%*sdeclare_data_copy(", indent_level, ""); switch (vis) { case SYM_LOCAL: - fprintf(dbg_f, "Local, "); + fprintf(debug_file, "Local, "); break; case SYM_GLOBAL: - fprintf(dbg_f, "Global, "); + fprintf(debug_file, "Global, "); break; case SYM_COMMON: - fprintf(dbg_f, "Common, "); + fprintf(debug_file, "Common, "); break; case SYM_EXTERN: - fprintf(dbg_f, "Extern, "); + fprintf(debug_file, "Extern, "); break; } if (vis == SYM_COMMON) { - expr_print(dbg_f, data); + expr_print(debug_file, data); retval = expr_copy(data); } else { - fprintf(dbg_f, "%p", data); + fprintf(debug_file, "%p", data); InternalError(_("Trying to copy unrecognized objfmt data")); } - fprintf(dbg_f, "), returning copy\n"); + fprintf(debug_file, "), returning copy\n"); return retval; } @@ -161,29 +178,29 @@ dbg_objfmt_declare_data_copy(SymVisibility vis, /*@only@*/ void *data) static void dbg_objfmt_declare_data_delete(SymVisibility vis, /*@only@*/ void *data) { - fprintf(dbg_f, "%*sdeclare_data_delete(", indent_level, ""); + fprintf(debug_file, "%*sdeclare_data_delete(", indent_level, ""); switch (vis) { case SYM_LOCAL: - fprintf(dbg_f, "Local, "); + fprintf(debug_file, "Local, "); break; case SYM_GLOBAL: - fprintf(dbg_f, "Global, "); + fprintf(debug_file, "Global, "); break; case SYM_COMMON: - fprintf(dbg_f, "Common, "); + fprintf(debug_file, "Common, "); break; case SYM_EXTERN: - fprintf(dbg_f, "Extern, "); + fprintf(debug_file, "Extern, "); break; } if (vis == SYM_COMMON) { - expr_print(dbg_f, data); + expr_print(debug_file, data); expr_delete(data); } else { - fprintf(dbg_f, "%p", data); + fprintf(debug_file, "%p", data); xfree(data); } - fprintf(dbg_f, ")\n"); + fprintf(debug_file, ")\n"); } static void @@ -203,11 +220,11 @@ static int dbg_objfmt_directive(const char *name, valparamhead *valparams, /*@null@*/ valparamhead *objext_valparams) { - fprintf(dbg_f, "%*sdirective(\"%s\", ", indent_level, "", name); - vps_print(dbg_f, valparams); - fprintf(dbg_f, ", "); - vps_print(dbg_f, objext_valparams); - fprintf(dbg_f, "), returning 0 (recognized)\n"); + fprintf(debug_file, "%*sdirective(\"%s\", ", indent_level, "", name); + vps_print(debug_file, valparams); + fprintf(debug_file, ", "); + vps_print(debug_file, objext_valparams); + fprintf(debug_file, "), returning 0 (recognized)\n"); return 0; /* dbg format "recognizes" all directives */ } @@ -219,7 +236,8 @@ objfmt dbg_objfmt = { ".text", 32, dbg_objfmt_initialize, - dbg_objfmt_finalize, + dbg_objfmt_output, + dbg_objfmt_cleanup, dbg_objfmt_sections_switch, dbg_objfmt_section_data_delete, dbg_objfmt_section_data_print, diff --git a/src/globals.c b/src/globals.c index f91a26f3..0e90638f 100644 --- a/src/globals.c +++ b/src/globals.c @@ -27,6 +27,14 @@ #include "globals.h" +/* Output file for debugging-type formats. This is so that functions that are + * called before the object file is usually opened can still write data out to + * it (whereas for "normal" formats the object file is not opened until later + * in the assembly process). Opening the file early is special-cased in + * main(). + */ +/*@null@*/ FILE *debug_file = NULL; + /* Current (selected) parser */ /*@null@*/ parser *cur_parser = NULL; diff --git a/src/globals.h b/src/globals.h index 54ffec47..72b69375 100644 --- a/src/globals.h +++ b/src/globals.h @@ -22,6 +22,14 @@ #ifndef YASM_GLOBALS_H #define YASM_GLOBALS_H +/* Output file for debugging-type formats. This is so that functions that are + * called before the object file is usually opened can still write data out to + * it (whereas for "normal" formats the object file is not opened until later + * in the assembly process). Opening the file early is special-cased in + * main(). + */ +extern /*@null@*/ FILE *debug_file; + /* Current (selected) parser */ extern /*@null@*/ parser *cur_parser; diff --git a/src/linemgr.c b/src/linemgr.c index f91a26f3..0e90638f 100644 --- a/src/linemgr.c +++ b/src/linemgr.c @@ -27,6 +27,14 @@ #include "globals.h" +/* Output file for debugging-type formats. This is so that functions that are + * called before the object file is usually opened can still write data out to + * it (whereas for "normal" formats the object file is not opened until later + * in the assembly process). Opening the file early is special-cased in + * main(). + */ +/*@null@*/ FILE *debug_file = NULL; + /* Current (selected) parser */ /*@null@*/ parser *cur_parser = NULL; diff --git a/src/linemgr.h b/src/linemgr.h index 54ffec47..72b69375 100644 --- a/src/linemgr.h +++ b/src/linemgr.h @@ -22,6 +22,14 @@ #ifndef YASM_GLOBALS_H #define YASM_GLOBALS_H +/* Output file for debugging-type formats. This is so that functions that are + * called before the object file is usually opened can still write data out to + * it (whereas for "normal" formats the object file is not opened until later + * in the assembly process). Opening the file early is special-cased in + * main(). + */ +extern /*@null@*/ FILE *debug_file; + /* Current (selected) parser */ extern /*@null@*/ parser *cur_parser; diff --git a/src/main.c b/src/main.c index df46632c..87f1fea5 100644 --- a/src/main.c +++ b/src/main.c @@ -51,6 +51,9 @@ static int files_open = 0; /*@null@*/ static FILE *in = NULL, *obj = NULL; static int special_options = 0; +static int open_obj(void); +static void cleanup(sectionhead *sections); + /* Forward declarations: cmd line parser handlers */ static int opt_special_handler(char *cmd, /*@null@*/ char *param, int extra); static int opt_format_handler(char *cmd, /*@null@*/ char *param, int extra); @@ -154,12 +157,10 @@ main(int argc, char *argv[]) /* Set x86 as the architecture */ cur_arch = &x86_arch; - /* Set dbg as the object format */ - cur_objfmt = find_objfmt("dbg"); - if (!cur_objfmt) { - ErrorNow(_("unrecognized output format `%s'"), "dbg"); - return EXIT_FAILURE; - } + /* If not already specified, default to dbg as the object format. */ + if (!cur_objfmt) + cur_objfmt = find_objfmt("dbg"); + assert(cur_objfmt != NULL); /* open the object file if not specified */ if (!obj) { @@ -170,17 +171,19 @@ main(int argc, char *argv[]) /* replace (or add) extension */ obj_filename = replace_extension(in_filename, cur_objfmt->extension, "yasm.out"); + } - /* open the built filename */ - obj = fopen(obj_filename, "wb"); - if (!obj) { - ErrorNow(_("could not open file `%s'"), obj_filename); + /* Pre-open the object file as debug_file if we're using a debug-type + * format. (This is so the format can output ALL function call info). + */ + if (strcmp(cur_objfmt->keyword, "dbg") == 0) { + if (!open_obj()) return EXIT_FAILURE; - } + debug_file = obj; } /* Initialize the object format */ - cur_objfmt->initialize(obj); + cur_objfmt->initialize(in_filename, obj_filename); /* Set NASM as the parser */ cur_parser = find_parser("nasm"); @@ -200,53 +203,69 @@ main(int argc, char *argv[]) xfree(in_filename); if (OutputAllErrorWarning() > 0) { - sections_delete(sections); - symrec_delete_all(); - line_shutdown(); - floatnum_shutdown(); - intnum_shutdown(); - BitVector_Shutdown(); + cleanup(sections); return EXIT_FAILURE; } - /* XXX Only for temporary debugging! */ - fprintf(obj, "\nSections after parsing:\n"); - indent_level++; - sections_print(obj, sections); - indent_level--; - - fprintf(obj, "\nSymbol Table:\n"); - indent_level++; - symrec_print_all(obj); - indent_level--; - symrec_parser_finalize(); basic_optimizer.optimize(sections); if (OutputAllErrorWarning() > 0) { - sections_delete(sections); - symrec_delete_all(); - line_shutdown(); - floatnum_shutdown(); - intnum_shutdown(); - BitVector_Shutdown(); + cleanup(sections); return EXIT_FAILURE; } - fprintf(obj, "\nSections after optimization:\n"); - indent_level++; - sections_print(obj, sections); - indent_level--; + /* open the object file for output (if not already opened above) */ + if (!debug_file) { + if (!open_obj()) + return EXIT_FAILURE; + } + + /* Write the object file */ + cur_objfmt->output(obj, sections); /* Finalize the object output */ - cur_objfmt->finalize(); + cur_objfmt->cleanup(); if (obj != stdout) fclose(obj); + /* If we had an error at this point, we also need to delete the output + * object file (to make sure it's not left newer than the source). + */ + if (OutputAllErrorWarning() > 0) { + cleanup(sections); + if (obj != stdout) + remove(obj_filename); + return EXIT_FAILURE; + } + if (obj_filename) xfree(obj_filename); + cleanup(sections); + return EXIT_SUCCESS; +} +/*@=globstate =unrecog@*/ + +/* Open the object file. Returns 0 on failure. */ +static int +open_obj(void) +{ + if (obj != stdout) { + obj = fopen(obj_filename, "wb"); + if (!obj) { + ErrorNow(_("could not open file `%s'"), obj_filename); + return 0; + } + } + return 1; +} + +/* Cleans up all allocated structures. */ +static void +cleanup(sectionhead *sections) +{ sections_delete(sections); symrec_delete_all(); line_shutdown(); @@ -255,9 +274,7 @@ main(int argc, char *argv[]) intnum_shutdown(); BitVector_Shutdown(); - return EXIT_SUCCESS; } -/*@=globstate =unrecog@*/ /* * Command line options handlers @@ -296,7 +313,11 @@ static int opt_format_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra) { assert(param != NULL); - printf("selected format: %s\n", param); + cur_objfmt = find_objfmt(param); + if (!cur_objfmt) { + ErrorNow(_("unrecognized object format `%s'"), param); + return 1; + } return 0; } @@ -305,22 +326,22 @@ opt_objfile_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra) { assert(param != NULL); - if (strcasecmp(param, "stdout") == 0) + if (strcmp(param, "-") == 0) obj = stdout; - else if (strcasecmp(param, "stderr") == 0) - obj = stderr; else { if (obj) { WarningNow("can open only one output file, last specified used"); - if (obj != stdout && obj != stderr && fclose(obj)) + if (obj != stdout && fclose(obj)) ErrorNow("could not close old output file"); } } - obj = fopen(param, "wb"); - if (!obj) { - ErrorNow(_("could not open file `%s'"), param); - return 1; + if (obj != stdout) { + obj = fopen(param, "wb"); + if (!obj) { + ErrorNow(_("could not open file `%s'"), param); + return 1; + } } if (obj_filename) diff --git a/src/objfmt.h b/src/objfmt.h index d0e7750b..ae409a00 100644 --- a/src/objfmt.h +++ b/src/objfmt.h @@ -50,12 +50,19 @@ struct objfmt { /* debugfmt *default_df;*/ /* Initializes object output. Must be called before any other object - * format functions. + * format functions. Should NOT open the object file; the filenames are + * provided solely for informational purposes. */ - void (*initialize) (/*@dependent@*/ FILE *f); + void (*initialize) (const char *in_filename, const char *obj_filename); - /* Finishes object output, and cleans up anything created by initialize. */ - void (*finalize) (void); + /* Write out (post-optimized) sections to the object file. + * This function may call symrec functions as necessary (including + * symrec_traverse) to retrieve symbolic information. + */ + void (*output) (FILE *f, sectionhead *sections); + + /* Cleans up anything allocated by initialize. */ + void (*cleanup) (void); /* Switch object file sections. The first val of the valparams should * be the section name. Returns NULL if something's wrong, otherwise diff --git a/src/objfmts/dbg/dbg-objfmt.c b/src/objfmts/dbg/dbg-objfmt.c index aa58ca36..9866b67d 100644 --- a/src/objfmts/dbg/dbg-objfmt.c +++ b/src/objfmts/dbg/dbg-objfmt.c @@ -31,19 +31,36 @@ #include "objfmt.h" -/*@dependent@*/ FILE *dbg_f; +/* Note that the functions here write to debug_file. This is NOT legal for + * other object formats to do--only the output() function can write to a file, + * and only the file it's passed in its f parameter! + */ + +static void +dbg_objfmt_initialize(const char *in_filename, const char *obj_filename) +{ + fprintf(debug_file, "%*sinitialize(\"%s\", \"%s\")\n", indent_level, "", + in_filename, obj_filename); +} static void -dbg_objfmt_initialize(/*@dependent@*/ FILE *f) +dbg_objfmt_output(FILE *f, sectionhead *sections) { - dbg_f = f; - fprintf(dbg_f, "%*sinitialize(f)\n", indent_level, ""); + fprintf(f, "%*soutput(f, sections->\n", indent_level, ""); + indent_level++; + sections_print(f, sections); + indent_level--; + fprintf(f, "%*s)\n", indent_level, ""); + indent_level++; + fprintf(f, "%*sSymbol Table:\n", indent_level, ""); + symrec_print_all(f); + indent_level--; } static void -dbg_objfmt_finalize(void) +dbg_objfmt_cleanup(void) { - fprintf(dbg_f, "%*sfinalize()\n", indent_level, ""); + fprintf(debug_file, "%*scleanup()\n", indent_level, ""); } static /*@dependent@*/ /*@null@*/ section * @@ -55,22 +72,22 @@ dbg_objfmt_sections_switch(sectionhead *headp, valparamhead *valparams, section *retval; int isnew; - fprintf(dbg_f, "%*ssections_switch(headp, ", indent_level, ""); - vps_print(dbg_f, valparams); - fprintf(dbg_f, ", "); - vps_print(dbg_f, objext_valparams); - fprintf(dbg_f, "), returning "); + fprintf(debug_file, "%*ssections_switch(headp, ", indent_level, ""); + vps_print(debug_file, valparams); + fprintf(debug_file, ", "); + vps_print(debug_file, objext_valparams); + fprintf(debug_file, "), returning "); if ((vp = vps_first(valparams)) && !vp->param && vp->val != NULL) { retval = sections_switch_general(headp, vp->val, NULL, 0, &isnew); if (isnew) { - fprintf(dbg_f, "(new) "); + fprintf(debug_file, "(new) "); symrec_define_label(vp->val, retval, (bytecode *)NULL, 1); } - fprintf(dbg_f, "\"%s\" section\n", vp->val); + fprintf(debug_file, "\"%s\" section\n", vp->val); return retval; } else { - fprintf(dbg_f, "NULL\n"); + fprintf(debug_file, "NULL\n"); return NULL; } } @@ -78,7 +95,7 @@ dbg_objfmt_sections_switch(sectionhead *headp, valparamhead *valparams, static void dbg_objfmt_section_data_delete(/*@only@*/ void *data) { - fprintf(dbg_f, "%*ssection_data_delete(%p)\n", indent_level, "", data); + fprintf(debug_file, "%*ssection_data_delete(%p)\n", indent_level, "", data); xfree(data); } @@ -95,9 +112,9 @@ static /*@null@*/ void * dbg_objfmt_extern_data_new(const char *name, /*@unused@*/ /*@null@*/ valparamhead *objext_valparams) { - fprintf(dbg_f, "%*sextern_data_new(\"%s\", ", indent_level, "", name); - vps_print(dbg_f, objext_valparams); - fprintf(dbg_f, "), returning NULL\n"); + fprintf(debug_file, "%*sextern_data_new(\"%s\", ", indent_level, "", name); + vps_print(debug_file, objext_valparams); + fprintf(debug_file, "), returning NULL\n"); return NULL; } @@ -105,9 +122,9 @@ static /*@null@*/ void * dbg_objfmt_global_data_new(const char *name, /*@unused@*/ /*@null@*/ valparamhead *objext_valparams) { - fprintf(dbg_f, "%*sglobal_data_new(\"%s\", ", indent_level, "", name); - vps_print(dbg_f, objext_valparams); - fprintf(dbg_f, "), returning NULL\n"); + fprintf(debug_file, "%*sglobal_data_new(\"%s\", ", indent_level, "", name); + vps_print(debug_file, objext_valparams); + fprintf(debug_file, "), returning NULL\n"); return NULL; } @@ -116,13 +133,13 @@ dbg_objfmt_common_data_new(const char *name, /*@only@*/ expr *size, /*@unused@*/ /*@null@*/ valparamhead *objext_valparams) { - fprintf(dbg_f, "%*scommon_data_new(\"%s\", ", indent_level, "", name); - expr_print(dbg_f, size); - fprintf(dbg_f, ", "); - vps_print(dbg_f, objext_valparams); - fprintf(dbg_f, "), returning "); - expr_print(dbg_f, size); - fprintf(dbg_f, "\n"); + fprintf(debug_file, "%*scommon_data_new(\"%s\", ", indent_level, "", name); + expr_print(debug_file, size); + fprintf(debug_file, ", "); + vps_print(debug_file, objext_valparams); + fprintf(debug_file, "), returning "); + expr_print(debug_file, size); + fprintf(debug_file, "\n"); return size; } @@ -131,29 +148,29 @@ dbg_objfmt_declare_data_copy(SymVisibility vis, /*@only@*/ void *data) { void *retval; - fprintf(dbg_f, "%*sdeclare_data_copy(", indent_level, ""); + fprintf(debug_file, "%*sdeclare_data_copy(", indent_level, ""); switch (vis) { case SYM_LOCAL: - fprintf(dbg_f, "Local, "); + fprintf(debug_file, "Local, "); break; case SYM_GLOBAL: - fprintf(dbg_f, "Global, "); + fprintf(debug_file, "Global, "); break; case SYM_COMMON: - fprintf(dbg_f, "Common, "); + fprintf(debug_file, "Common, "); break; case SYM_EXTERN: - fprintf(dbg_f, "Extern, "); + fprintf(debug_file, "Extern, "); break; } if (vis == SYM_COMMON) { - expr_print(dbg_f, data); + expr_print(debug_file, data); retval = expr_copy(data); } else { - fprintf(dbg_f, "%p", data); + fprintf(debug_file, "%p", data); InternalError(_("Trying to copy unrecognized objfmt data")); } - fprintf(dbg_f, "), returning copy\n"); + fprintf(debug_file, "), returning copy\n"); return retval; } @@ -161,29 +178,29 @@ dbg_objfmt_declare_data_copy(SymVisibility vis, /*@only@*/ void *data) static void dbg_objfmt_declare_data_delete(SymVisibility vis, /*@only@*/ void *data) { - fprintf(dbg_f, "%*sdeclare_data_delete(", indent_level, ""); + fprintf(debug_file, "%*sdeclare_data_delete(", indent_level, ""); switch (vis) { case SYM_LOCAL: - fprintf(dbg_f, "Local, "); + fprintf(debug_file, "Local, "); break; case SYM_GLOBAL: - fprintf(dbg_f, "Global, "); + fprintf(debug_file, "Global, "); break; case SYM_COMMON: - fprintf(dbg_f, "Common, "); + fprintf(debug_file, "Common, "); break; case SYM_EXTERN: - fprintf(dbg_f, "Extern, "); + fprintf(debug_file, "Extern, "); break; } if (vis == SYM_COMMON) { - expr_print(dbg_f, data); + expr_print(debug_file, data); expr_delete(data); } else { - fprintf(dbg_f, "%p", data); + fprintf(debug_file, "%p", data); xfree(data); } - fprintf(dbg_f, ")\n"); + fprintf(debug_file, ")\n"); } static void @@ -203,11 +220,11 @@ static int dbg_objfmt_directive(const char *name, valparamhead *valparams, /*@null@*/ valparamhead *objext_valparams) { - fprintf(dbg_f, "%*sdirective(\"%s\", ", indent_level, "", name); - vps_print(dbg_f, valparams); - fprintf(dbg_f, ", "); - vps_print(dbg_f, objext_valparams); - fprintf(dbg_f, "), returning 0 (recognized)\n"); + fprintf(debug_file, "%*sdirective(\"%s\", ", indent_level, "", name); + vps_print(debug_file, valparams); + fprintf(debug_file, ", "); + vps_print(debug_file, objext_valparams); + fprintf(debug_file, "), returning 0 (recognized)\n"); return 0; /* dbg format "recognizes" all directives */ } @@ -219,7 +236,8 @@ objfmt dbg_objfmt = { ".text", 32, dbg_objfmt_initialize, - dbg_objfmt_finalize, + dbg_objfmt_output, + dbg_objfmt_cleanup, dbg_objfmt_sections_switch, dbg_objfmt_section_data_delete, dbg_objfmt_section_data_print,