From 4f7daa4d39d6db24b21a49fb940ffe414f7c79db Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Wed, 20 Feb 2002 07:35:43 +0000 Subject: [PATCH] Fix issue with how symrec's are handled when an expression is copied: old code just assigned the pointer: but the symrec is deleted (if it's not in the symbol table) when the expr is deleted. Thus, we need to create a copy of the symrec instead of just reusing the same value if it's going to be deleted later. This trickles down to objfmt to copy the objfmt-local data. svn path=/trunk/yasm/; revision=467 --- libyasm/expr.c | 2 +- libyasm/objfmt.h | 4 +++- libyasm/symrec.c | 40 ++++++++++++++++++++++++++++++++ libyasm/symrec.h | 5 ++++ modules/objfmts/dbg/dbg-objfmt.c | 34 +++++++++++++++++++++++++++ src/expr.c | 2 +- src/objfmt.h | 4 +++- src/objfmts/dbg/dbg-objfmt.c | 34 +++++++++++++++++++++++++++ src/symrec.c | 40 ++++++++++++++++++++++++++++++++ src/symrec.h | 5 ++++ 10 files changed, 166 insertions(+), 4 deletions(-) diff --git a/libyasm/expr.c b/libyasm/expr.c index ea206ad1..31c32f3b 100644 --- a/libyasm/expr.c +++ b/libyasm/expr.c @@ -641,7 +641,7 @@ expr_copy_except(const expr *e, int except) dest->type = src->type; switch (src->type) { case EXPR_SYM: - dest->data.sym = src->data.sym; + dest->data.sym = symrec_copy(src->data.sym); break; case EXPR_EXPR: dest->data.expn = expr_copy_except(src->data.expn, -1); diff --git a/libyasm/objfmt.h b/libyasm/objfmt.h index a3938ab0..d0e7750b 100644 --- a/libyasm/objfmt.h +++ b/libyasm/objfmt.h @@ -76,9 +76,11 @@ struct objfmt { /*@only@*/ expr *size, /*@null@*/ valparamhead *objext_valparams); - /* It's only valid to pass these two functions *one* SymVisibility (eg, vis + /* It's only valid to pass these functions *one* SymVisibility (eg, vis * is an enum not a bitmask). */ + /*@only@*/ void * + (*declare_data_copy)(SymVisibility vis, /*@only@*/ void *data); void (*declare_data_delete)(SymVisibility vis, /*@only@*/ void *data); void (*declare_data_print)(FILE *f, SymVisibility vis, /*@null@*/ void *data); diff --git a/libyasm/symrec.c b/libyasm/symrec.c index 8fe3534e..ae85a7aa 100644 --- a/libyasm/symrec.c +++ b/libyasm/symrec.c @@ -304,6 +304,46 @@ symrec_delete_all(void) } } +symrec * +symrec_copy(symrec *sym) +{ + if (sym->status & SYM_NOTINTABLE) { + /* create an allocated duplicate of the symbol */ + symrec *rec = xmalloc(sizeof(symrec)); + rec->name = xstrdup(sym->name); + rec->type = sym->type; + rec->status = sym->status; + rec->visibility = sym->visibility; + rec->line = sym->line; + if (sym->type == SYM_EQU) + rec->value.expn = expr_copy(sym->value.expn); + else { + rec->value.label.sect = sym->value.label.sect; + rec->value.label.bc = sym->value.label.bc; + } + assert(cur_objfmt != NULL); + if (sym->of_data_vis_g && (sym->visibility & SYM_GLOBAL)) + rec->of_data_vis_g = + cur_objfmt->declare_data_copy(SYM_GLOBAL, sym->of_data_vis_g); + else + rec->of_data_vis_g = NULL; + if (sym->of_data_vis_ce) { + if (sym->visibility & SYM_COMMON) + rec->of_data_vis_ce = + cur_objfmt->declare_data_copy(SYM_COMMON, + sym->of_data_vis_ce); + else if (sym->visibility & SYM_EXTERN) + rec->of_data_vis_ce = + cur_objfmt->declare_data_copy(SYM_EXTERN, + sym->of_data_vis_ce); + } else + rec->of_data_vis_ce = NULL; + rec->opt_flags = sym->opt_flags; + return rec; + } else + return sym; +} + void symrec_delete(symrec *sym) { diff --git a/libyasm/symrec.h b/libyasm/symrec.h index 432dae92..59440673 100644 --- a/libyasm/symrec.h +++ b/libyasm/symrec.h @@ -57,6 +57,11 @@ void symrec_parser_finalize(void); void symrec_delete_all(void); +/* Copies symrec if it isn't in the symbol table. If it *is* in the symbol + * table, simply returns sym. + */ +symrec *symrec_copy(symrec *sym); + /* Deletes symrec if it isn't in the symbol table. If it *is* in the symbol * table, does nothing. */ diff --git a/modules/objfmts/dbg/dbg-objfmt.c b/modules/objfmts/dbg/dbg-objfmt.c index 7a606ca1..aa58ca36 100644 --- a/modules/objfmts/dbg/dbg-objfmt.c +++ b/modules/objfmts/dbg/dbg-objfmt.c @@ -23,6 +23,7 @@ /*@unused@*/ RCSID("$IdPath$"); #include "globals.h" +#include "errwarn.h" #include "expr.h" #include "symrec.h" @@ -125,6 +126,38 @@ dbg_objfmt_common_data_new(const char *name, /*@only@*/ expr *size, return size; } +static void * +dbg_objfmt_declare_data_copy(SymVisibility vis, /*@only@*/ void *data) +{ + void *retval; + + fprintf(dbg_f, "%*sdeclare_data_copy(", indent_level, ""); + switch (vis) { + case SYM_LOCAL: + fprintf(dbg_f, "Local, "); + break; + case SYM_GLOBAL: + fprintf(dbg_f, "Global, "); + break; + case SYM_COMMON: + fprintf(dbg_f, "Common, "); + break; + case SYM_EXTERN: + fprintf(dbg_f, "Extern, "); + break; + } + if (vis == SYM_COMMON) { + expr_print(dbg_f, data); + retval = expr_copy(data); + } else { + fprintf(dbg_f, "%p", data); + InternalError(_("Trying to copy unrecognized objfmt data")); + } + fprintf(dbg_f, "), returning copy\n"); + + return retval; +} + static void dbg_objfmt_declare_data_delete(SymVisibility vis, /*@only@*/ void *data) { @@ -193,6 +226,7 @@ objfmt dbg_objfmt = { dbg_objfmt_extern_data_new, dbg_objfmt_global_data_new, dbg_objfmt_common_data_new, + dbg_objfmt_declare_data_copy, dbg_objfmt_declare_data_delete, dbg_objfmt_declare_data_print, dbg_objfmt_directive diff --git a/src/expr.c b/src/expr.c index ea206ad1..31c32f3b 100644 --- a/src/expr.c +++ b/src/expr.c @@ -641,7 +641,7 @@ expr_copy_except(const expr *e, int except) dest->type = src->type; switch (src->type) { case EXPR_SYM: - dest->data.sym = src->data.sym; + dest->data.sym = symrec_copy(src->data.sym); break; case EXPR_EXPR: dest->data.expn = expr_copy_except(src->data.expn, -1); diff --git a/src/objfmt.h b/src/objfmt.h index a3938ab0..d0e7750b 100644 --- a/src/objfmt.h +++ b/src/objfmt.h @@ -76,9 +76,11 @@ struct objfmt { /*@only@*/ expr *size, /*@null@*/ valparamhead *objext_valparams); - /* It's only valid to pass these two functions *one* SymVisibility (eg, vis + /* It's only valid to pass these functions *one* SymVisibility (eg, vis * is an enum not a bitmask). */ + /*@only@*/ void * + (*declare_data_copy)(SymVisibility vis, /*@only@*/ void *data); void (*declare_data_delete)(SymVisibility vis, /*@only@*/ void *data); void (*declare_data_print)(FILE *f, SymVisibility vis, /*@null@*/ void *data); diff --git a/src/objfmts/dbg/dbg-objfmt.c b/src/objfmts/dbg/dbg-objfmt.c index 7a606ca1..aa58ca36 100644 --- a/src/objfmts/dbg/dbg-objfmt.c +++ b/src/objfmts/dbg/dbg-objfmt.c @@ -23,6 +23,7 @@ /*@unused@*/ RCSID("$IdPath$"); #include "globals.h" +#include "errwarn.h" #include "expr.h" #include "symrec.h" @@ -125,6 +126,38 @@ dbg_objfmt_common_data_new(const char *name, /*@only@*/ expr *size, return size; } +static void * +dbg_objfmt_declare_data_copy(SymVisibility vis, /*@only@*/ void *data) +{ + void *retval; + + fprintf(dbg_f, "%*sdeclare_data_copy(", indent_level, ""); + switch (vis) { + case SYM_LOCAL: + fprintf(dbg_f, "Local, "); + break; + case SYM_GLOBAL: + fprintf(dbg_f, "Global, "); + break; + case SYM_COMMON: + fprintf(dbg_f, "Common, "); + break; + case SYM_EXTERN: + fprintf(dbg_f, "Extern, "); + break; + } + if (vis == SYM_COMMON) { + expr_print(dbg_f, data); + retval = expr_copy(data); + } else { + fprintf(dbg_f, "%p", data); + InternalError(_("Trying to copy unrecognized objfmt data")); + } + fprintf(dbg_f, "), returning copy\n"); + + return retval; +} + static void dbg_objfmt_declare_data_delete(SymVisibility vis, /*@only@*/ void *data) { @@ -193,6 +226,7 @@ objfmt dbg_objfmt = { dbg_objfmt_extern_data_new, dbg_objfmt_global_data_new, dbg_objfmt_common_data_new, + dbg_objfmt_declare_data_copy, dbg_objfmt_declare_data_delete, dbg_objfmt_declare_data_print, dbg_objfmt_directive diff --git a/src/symrec.c b/src/symrec.c index 8fe3534e..ae85a7aa 100644 --- a/src/symrec.c +++ b/src/symrec.c @@ -304,6 +304,46 @@ symrec_delete_all(void) } } +symrec * +symrec_copy(symrec *sym) +{ + if (sym->status & SYM_NOTINTABLE) { + /* create an allocated duplicate of the symbol */ + symrec *rec = xmalloc(sizeof(symrec)); + rec->name = xstrdup(sym->name); + rec->type = sym->type; + rec->status = sym->status; + rec->visibility = sym->visibility; + rec->line = sym->line; + if (sym->type == SYM_EQU) + rec->value.expn = expr_copy(sym->value.expn); + else { + rec->value.label.sect = sym->value.label.sect; + rec->value.label.bc = sym->value.label.bc; + } + assert(cur_objfmt != NULL); + if (sym->of_data_vis_g && (sym->visibility & SYM_GLOBAL)) + rec->of_data_vis_g = + cur_objfmt->declare_data_copy(SYM_GLOBAL, sym->of_data_vis_g); + else + rec->of_data_vis_g = NULL; + if (sym->of_data_vis_ce) { + if (sym->visibility & SYM_COMMON) + rec->of_data_vis_ce = + cur_objfmt->declare_data_copy(SYM_COMMON, + sym->of_data_vis_ce); + else if (sym->visibility & SYM_EXTERN) + rec->of_data_vis_ce = + cur_objfmt->declare_data_copy(SYM_EXTERN, + sym->of_data_vis_ce); + } else + rec->of_data_vis_ce = NULL; + rec->opt_flags = sym->opt_flags; + return rec; + } else + return sym; +} + void symrec_delete(symrec *sym) { diff --git a/src/symrec.h b/src/symrec.h index 432dae92..59440673 100644 --- a/src/symrec.h +++ b/src/symrec.h @@ -57,6 +57,11 @@ void symrec_parser_finalize(void); void symrec_delete_all(void); +/* Copies symrec if it isn't in the symbol table. If it *is* in the symbol + * table, simply returns sym. + */ +symrec *symrec_copy(symrec *sym); + /* Deletes symrec if it isn't in the symbol table. If it *is* in the symbol * table, does nothing. */ -- 2.40.0