From: Peter Johnson Date: Sat, 26 May 2007 17:56:36 +0000 (-0000) Subject: Clean up directive handling. This standardizes error/warning messages and X-Git-Tag: v0.6.1~4^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3e5fed2ad1725c0608fad598e182e8852638392d;p=yasm Clean up directive handling. This standardizes error/warning messages and makes value/parameters more well-defined and flexible enough to handle string parameters. Value/parameters would now be better called name/values, but avoid changing the name for now. svn path=/trunk/yasm/; revision=1851 --- diff --git a/libyasm/section.c b/libyasm/section.c index 15549c96..2b5d4342 100644 --- a/libyasm/section.c +++ b/libyasm/section.c @@ -103,7 +103,8 @@ dir_extern(yasm_object *object, yasm_valparamhead *valparams, { yasm_valparam *vp = yasm_vps_first(valparams); yasm_symrec *sym; - sym = yasm_symtab_declare(object->symtab, vp->val, YASM_SYM_EXTERN, line); + sym = yasm_symtab_declare(object->symtab, yasm_vp_id(vp), YASM_SYM_EXTERN, + line); if (objext_valparams) { yasm_valparamhead *vps = yasm_vps_create(); *vps = *objext_valparams; /* structure copy */ @@ -118,7 +119,8 @@ dir_global(yasm_object *object, yasm_valparamhead *valparams, { yasm_valparam *vp = yasm_vps_first(valparams); yasm_symrec *sym; - sym = yasm_symtab_declare(object->symtab, vp->val, YASM_SYM_GLOBAL, line); + sym = yasm_symtab_declare(object->symtab, yasm_vp_id(vp), YASM_SYM_GLOBAL, + line); if (objext_valparams) { yasm_valparamhead *vps = yasm_vps_create(); *vps = *objext_valparams; /* structure copy */ @@ -141,7 +143,8 @@ dir_common(yasm_object *object, yasm_valparamhead *valparams, N_("no size specified in %s declaration"), "COMMON"); return; } - sym = yasm_symtab_declare(object->symtab, vp->val, YASM_SYM_COMMON, line); + sym = yasm_symtab_declare(object->symtab, yasm_vp_id(vp), YASM_SYM_COMMON, + line); yasm_symrec_set_common_size(sym, size); if (objext_valparams) { yasm_valparamhead *vps = yasm_vps_create(); diff --git a/libyasm/valparam.c b/libyasm/valparam.c index 336ae9e7..84cf984d 100644 --- a/libyasm/valparam.c +++ b/libyasm/valparam.c @@ -33,9 +33,11 @@ #include "valparam.h" #include "errwarn.h" +#include "intnum.h" #include "expr.h" #include "symrec.h" +#include "section.h" void yasm_call_directive(const yasm_directive *directive, yasm_object *object, @@ -53,7 +55,8 @@ yasm_call_directive(const yasm_directive *directive, yasm_object *object, } if (valparams) { vp = yasm_vps_first(valparams); - if ((directive->flags & YASM_DIR_ID_REQUIRED) && !vp->val) { + if ((directive->flags & YASM_DIR_ID_REQUIRED) && + vp->type != YASM_PARAM_ID) { yasm_error_set(YASM_ERROR_SYNTAX, N_("directive `%s' requires an identifier parameter"), directive->name); @@ -64,28 +67,81 @@ yasm_call_directive(const yasm_directive *directive, yasm_object *object, } yasm_valparam * -yasm_vp_create(/*@keep@*/ char *v, /*@keep@*/ yasm_expr *p) +yasm_vp_create_id(/*@keep@*/ char *v, /*@keep@*/ char *p, int id_prefix) { yasm_valparam *r = yasm_xmalloc(sizeof(yasm_valparam)); r->val = v; - r->param = p; + r->type = YASM_PARAM_ID; + r->param.id = p; + r->id_prefix = (char)id_prefix; + return r; +} + +yasm_valparam * +yasm_vp_create_string(/*@keep@*/ char *v, /*@keep@*/ char *p) +{ + yasm_valparam *r = yasm_xmalloc(sizeof(yasm_valparam)); + r->val = v; + r->type = YASM_PARAM_STRING; + r->param.str = p; + r->id_prefix = '\0'; + return r; +} + +yasm_valparam * +yasm_vp_create_expr(/*@keep@*/ char *v, /*@keep@*/ yasm_expr *p) +{ + yasm_valparam *r = yasm_xmalloc(sizeof(yasm_valparam)); + r->val = v; + r->type = YASM_PARAM_EXPR; + r->param.e = p; + r->id_prefix = '\0'; return r; } /*@null@*/ /*@only@*/ yasm_expr * -yasm_vp_expr(yasm_valparam *vp, yasm_symtab *symtab, unsigned long line) +yasm_vp_expr(const yasm_valparam *vp, yasm_symtab *symtab, unsigned long line) { if (!vp) return NULL; - if (vp->val) { - return yasm_expr_create_ident(yasm_expr_sym( - yasm_symtab_use(symtab, vp->val, line)), line); - } else if (vp->param) { - yasm_expr *e = vp->param; - vp->param = NULL; /* to avoid double-free */ - return e; - } else + switch (vp->type) { + case YASM_PARAM_ID: + return yasm_expr_create_ident(yasm_expr_sym( + yasm_symtab_use(symtab, yasm_vp_id(vp), line)), line); + case YASM_PARAM_EXPR: + return yasm_expr_copy(vp->param.e); + default: + return NULL; + } +} + +/*@null@*/ /*@dependent@*/ const char * +yasm_vp_string(const yasm_valparam *vp) +{ + if (!vp) + return NULL; + switch (vp->type) { + case YASM_PARAM_ID: + return vp->param.id; + case YASM_PARAM_STRING: + return vp->param.str; + default: + return NULL; + } +} + +/*@null@*/ /*@dependent@*/ const char * +yasm_vp_id(const yasm_valparam *vp) +{ + if (!vp) return NULL; + if (vp->type == YASM_PARAM_ID) { + if (vp->param.id[0] == vp->id_prefix) + return &vp->param.id[1]; + else + return vp->param.id; + } + return NULL; } void @@ -98,8 +154,17 @@ yasm_vps_delete(yasm_valparamhead *headp) next = STAILQ_NEXT(cur, link); if (cur->val) yasm_xfree(cur->val); - if (cur->param) - yasm_expr_destroy(cur->param); + switch (cur->type) { + case YASM_PARAM_ID: + yasm_xfree(cur->param.id); + break; + case YASM_PARAM_STRING: + yasm_xfree(cur->param.str); + break; + case YASM_PARAM_EXPR: + yasm_expr_destroy(cur->param.e); + break; + } yasm_xfree(cur); cur = next; } @@ -121,10 +186,17 @@ yasm_vps_print(const yasm_valparamhead *headp, FILE *f) fprintf(f, "(\"%s\",", vp->val); else fprintf(f, "((nil),"); - if (vp->param) - yasm_expr_print(vp->param, f); - else - fprintf(f, "(nil)"); + switch (vp->type) { + case YASM_PARAM_ID: + fprintf(f, "%s", vp->param.id); + break; + case YASM_PARAM_STRING: + fprintf(f, "\"%s\"", vp->param.str); + break; + case YASM_PARAM_EXPR: + yasm_expr_print(vp->param.e, f); + break; + } fprintf(f, ")"); if (yasm_vps_next(vp)) fprintf(f, ","); @@ -170,3 +242,135 @@ yasm_vps_next(yasm_valparam *cur) { return STAILQ_NEXT(cur, link); } + +int +yasm_dir_helper(void *obj, yasm_valparam *vp_first, unsigned long line, + const yasm_dir_help *help, size_t nhelp, void *data, + int (*helper_valparam) (void *obj, yasm_valparam *vp, + unsigned long line, void *data)) +{ + yasm_valparam *vp = vp_first; + int anymatched = 0; + int matched; + + if (!vp) + return 0; + + do { + const char *s; + size_t i; + + matched = 0; + if (!vp->val && (s = yasm_vp_id(vp))) { + for (i=0; ival) { + for (i=0; ival, help[i].name) == 0) { + if (help[i].helper(obj, vp, line, + ((char *)data)+help[i].off, + help[i].arg) != 0) + return -1; + matched = 1; + anymatched = 1; + break; + } + } + } + + if (!matched) { + int final = helper_valparam(obj, vp, line, data); + if (final < 0) + return -1; + if (final > 0) + anymatched = 1; + } + } while((vp = yasm_vps_next(vp))); + + return anymatched; +} + +int +yasm_dir_helper_flag_or(void *obj, yasm_valparam *vp, unsigned long line, + void *d, uintptr_t flag) +{ + unsigned long *flags = (unsigned long *)d; + *flags |= flag; + return 0; +} + +int +yasm_dir_helper_flag_and(void *obj, yasm_valparam *vp, unsigned long line, + void *d, uintptr_t flag) +{ + unsigned long *flags = (unsigned long *)d; + *flags &= ~flag; + return 0; +} + +int +yasm_dir_helper_flag_set(void *obj, yasm_valparam *vp, unsigned long line, + void *d, uintptr_t flag) +{ + unsigned long *flags = (unsigned long *)d; + *flags = flag; + return 0; +} + +int +yasm_dir_helper_intn(void *obj, yasm_valparam *vp, unsigned long line, + void *data, uintptr_t arg) +{ + yasm_object *object = (yasm_object *)obj; + /*@only@*/ /*@null@*/ yasm_expr *e; + /*@dependent@*/ /*@null@*/ yasm_intnum *local; + yasm_intnum **intn = (yasm_intnum **)data; + + if (*intn) + yasm_intnum_destroy(*intn); + if (!(e = yasm_vp_expr(vp, object->symtab, line)) || + !(local = yasm_expr_get_intnum(&e, 0))) { + yasm_error_set(YASM_ERROR_NOT_CONSTANT, + N_("argument to `%s' is not an integer"), + vp->val); + if (e) + yasm_expr_destroy(e); + return -1; + } + *intn = yasm_intnum_copy(local); + yasm_expr_destroy(e); + return 0; +} + +int +yasm_dir_helper_valparam_warn(void *obj, yasm_valparam *vp, + unsigned long line, void *data) +{ + const char *s; + + if (vp->val) { + yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized qualifier `%s'"), + vp->val); + return 0; + } + + if ((s = yasm_vp_id(vp))) + yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized qualifier `%s'"), s); + else if (vp->type == YASM_PARAM_STRING) + yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized string qualifier")); + else + yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized numeric qualifier")); + + return 0; +} diff --git a/libyasm/valparam.h b/libyasm/valparam.h index ee5d23fa..9a2a1303 100644 --- a/libyasm/valparam.h +++ b/libyasm/valparam.h @@ -39,7 +39,26 @@ struct yasm_valparam { /*@reldef@*/ STAILQ_ENTRY(yasm_valparam) link; /**< Next pair in list */ /*@owned@*/ /*@null@*/ char *val; /**< Value */ - /*@owned@*/ /*@null@*/ yasm_expr *param; /**< Parameter */ + + enum yasm_param_type { + YASM_PARAM_ID, /**< Identifier */ + YASM_PARAM_STRING, /**< String */ + YASM_PARAM_EXPR /**< Expression */ + } type; /**< Parameter type */ + + union yasm_param { + /*@owned@*/ char *id; /**< Identifier */ + /*@owned@*/ char *str; /**< String */ + /*@owned@*/ yasm_expr *e; /**< Expression */ + } param; /**< Parameter */ + + /* Prefix character that indicates a raw identifier. When yasm_vp_string() + * is called on a #YASM_PARAM_ID, all characters are returned. When + * yasm_vp_id() is called on a #YASM_PARAM_ID, if the identifier begins + * with this character, this character is stripped from the returned + * value. + */ + char id_prefix; }; /** Linked list of value/parameter pairs. \internal */ @@ -87,23 +106,55 @@ void yasm_call_directive(const yasm_directive *directive, yasm_object *object, yasm_valparamhead *objext_valparams, unsigned long line); -/** Create a new valparam. +/** Create a new valparam with identifier parameter. + * \param v value + * \param p parameter + * \param id_prefix identifier prefix for raw identifiers + * \return Newly allocated valparam. + */ +yasm_valparam *yasm_vp_create_id(/*@keep@*/ char *v, /*@keep@*/ char *p, + int id_prefix); + +/** Create a new valparam with string parameter. + * \param v value + * \param p parameter + * \return Newly allocated valparam. + */ +yasm_valparam *yasm_vp_create_string(/*@keep@*/ char *v, /*@keep@*/ char *p); + +/** Create a new valparam with expression parameter. * \param v value * \param p parameter * \return Newly allocated valparam. */ -yasm_valparam *yasm_vp_create(/*@keep@*/ char *v, /*@keep@*/ yasm_expr *p); +yasm_valparam *yasm_vp_create_expr(/*@keep@*/ char *v, + /*@keep@*/ yasm_expr *p); -/** Get a valparam as an expr. If the valparam is a value, it's treated - * as a symbol (yasm_symtab_use() is called to convert it). The valparam - * is modified as necessary to avoid double-frees. +/** Get a valparam parameter as an expr. If the parameter is an identifier, + * it's treated as a symbol (yasm_symtab_use() is called to convert it). * \param vp valparam * \param symtab symbol table * \param line virtual line - * \return Expression, or NULL if vp is NULL or if val and param are both NULL. + * \return Expression, or NULL if vp is NULL or the parameter cannot be + * converted to an expression. */ /*@null@*/ /*@only@*/ yasm_expr *yasm_vp_expr - (yasm_valparam *vp, yasm_symtab *symtab, unsigned long line); + (const yasm_valparam *vp, yasm_symtab *symtab, unsigned long line); + +/** Get a valparam parameter as a string. If the parameter is an identifier, + * it's treated as a string. + * \param vp valparam + * \return String, or NULL if vp is NULL or the parameter cannot be realized + * as a string. + */ +/*@null@*/ /*@dependent@*/ const char *yasm_vp_string(const yasm_valparam *vp); + +/** Get a valparam parameter as an identifier. + * \param vp valparam + * \return Identifier (string), or NULL if vp is NULL or the parameter is not + * an identifier. + */ +/*@null@*/ /*@dependent@*/ const char *yasm_vp_id(const yasm_valparam *vp); /** Create a new linked list of valparams. * \return Newly allocated valparam list. @@ -173,4 +224,130 @@ void yasm_vps_append(yasm_valparamhead *headp, /*@keep@*/ yasm_valparam *vp); */ void yasm_vps_print(/*@null@*/ const yasm_valparamhead *headp, FILE *f); +/** Directive valparam parse helper structure. */ +typedef struct yasm_dir_help { + /** Value portion of val=param (if needsparam=1), or standalone identifier + * (if needsparam=0). + */ + const char *name; + + /** 1 if value requires parameter, 0 if it must not have a parameter. */ + int needsparam; + + /** Helper callback function if name and parameter existence match. + * \param obj obj passed into yasm_dir_helper() + * \param vp value/parameter + * \param line line passed into yasm_dir_helper() + * \param data data passed into yasm_dir_helper() plus + #yasm_dir_help.off offset + * \param arg #yasm_dir_help.arg argument + * \return -1 on error, 0 otherwise. + */ + int (*helper) (void *obj, yasm_valparam *vp, unsigned long line, + void *data, uintptr_t arg); + + /** Offset added to data pointer passed into yasm_dir_helper() before + * data pointer is given to #yasm_dir_help.helper(). This is so that + * a structure can be passed into yasm_dir_helper() and this can be an + * offsetof() to point the helper function to a specific structure + * member. + */ + size_t off; + + /** Argument to pass in as the arg parameter to #yasm_dir_help.helper(). + */ + uintptr_t arg; +} yasm_dir_help; + +/** Help parse a list of directive value/parameters. Takes an array of + * #yasm_dir_help structures and tries to match val=param (or just val) + * against the passed value/parameters. When no match is found in the + * array of help structures, calls helper_valparam. + * \param obj object to be passed to yasm_dir_help.helper() or + * helper_valparam() callback + * \param vp_first first value/parameter to examine + * \param line virtual line number; passed down to helper callback + * \param help array of #yasm_dir_help structures + * \param nhelp number of array elements + * \param data base data pointer; if a match is found, + * the respective #yasm_dir_help.off is added to this + * prior to it being passed to the helper callback + * \param helper_valparam catch-all callback; should return -1 on error, + * 0 if not matched, 1 if matched. + * \return -1 on error, 1 if any arguments matched (including via + * catch-all callback), 0 if no match. + */ +int yasm_dir_helper(void *obj, yasm_valparam *vp_first, unsigned long line, + const yasm_dir_help *help, size_t nhelp, void *data, + int (*helper_valparam) (void *object, + yasm_valparam *vp, + unsigned long line, + void *data)); + +/** Standard helper for yasm_dir_helper() that simply sets a flag when called. + * It does not look at the vp; rather, it uses the value of the arg parameter, + * and stores an unsigned long value to data. + * \param obj unused + * \param vp unused + * \param line unused + * \param data pointer to an unsigned long + * \param arg flag to set + * \return 0 + */ +int yasm_dir_helper_flag_set(void *obj, yasm_valparam *vp, unsigned long line, + void *data, uintptr_t arg); + +/** Standard helper for yasm_dir_helper() that simply ORs a flag when called. + * It does not look at the vp; rather, it uses the value of the arg parameter, + * and ORs it with the unsigned long value in data. + * \param obj unused + * \param vp unused + * \param line unused + * \param data pointer to an unsigned long + * \param arg flag to OR + * \return 0 + */ +int yasm_dir_helper_flag_or(void *obj, yasm_valparam *vp, unsigned long line, + void *data, uintptr_t arg); + +/** Standard helper for yasm_dir_helper() that simply ANDs a flag when called. + * It does not look at the vp; rather, it uses the value of the arg parameter, + * and ANDs its inverse (~) with the unsigned long value in data. + * \param obj unused + * \param vp unused + * \param line unused + * \param data pointer to an unsigned long + * \param arg flag to AND + * \return 0 + */ +int yasm_dir_helper_flag_and(void *obj, yasm_valparam *vp, unsigned long line, + void *data, uintptr_t arg); + +/** Standard helper for yasm_dir_helper() that parses an intnum parameter. + * The #yasm_dir_help structure that uses this function should have + * needsparam=1. The obj parameter to yasm_dir_helper() when this helper + * is used MUST point to a #yasm_object. In addition, the data parameter + * that is ultimately passed to this function (e.g. yasm_dir_helper() data + * parameter plus #yasm_dir_help.off) must point to a #yasm_intnum * + * initialized to NULL. + * \param obj object; must be #yasm_object + * \param vp valparam + * \param line virtual line number + * \param data pointer to #yasm_intnum * + * \param arg unused argument + * \return -1 on error, 0 otherwise. + */ +int yasm_dir_helper_intn(void *obj, yasm_valparam *vp, unsigned long line, + void *data, uintptr_t arg); + +/** Standard catch-all callback fro yasm_dir_helper(). Generates standard + * warning for all valparams. + * \param obj unused + * \param vp valparam + * \param line unused + * \param data unused + * \return 0 + */ +int yasm_dir_helper_valparam_warn(void *obj, yasm_valparam *vp, + unsigned long line, void *data); #endif diff --git a/modules/arch/x86/x86arch.c b/modules/arch/x86/x86arch.c index 371e5b47..42a95389 100644 --- a/modules/arch/x86/x86arch.c +++ b/modules/arch/x86/x86arch.c @@ -126,11 +126,12 @@ x86_dir_cpu(yasm_object *object, yasm_valparamhead *valparams, yasm_valparam *vp; yasm_vps_foreach(vp, valparams) { - if (vp->val) - yasm_x86__parse_cpu(arch_x86, vp->val, strlen(vp->val)); - else if (vp->param) { + /*@null@*/ /*@dependent@*/ const char *s = yasm_vp_string(vp); + if (s) + yasm_x86__parse_cpu(arch_x86, s, strlen(s)); + else if (vp->type == YASM_PARAM_EXPR) { const yasm_intnum *intcpu; - intcpu = yasm_expr_get_intnum(&vp->param, 0); + intcpu = yasm_expr_get_intnum(&vp->param.e, 0); if (!intcpu) yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid argument to [%s]"), "CPU"); @@ -139,7 +140,9 @@ x86_dir_cpu(yasm_object *object, yasm_valparamhead *valparams, sprintf(strcpu, "%lu", yasm_intnum_get_uint(intcpu)); yasm_x86__parse_cpu(arch_x86, strcpu, strlen(strcpu)); } - } + } else + yasm_error_set(YASM_ERROR_SYNTAX, N_("invalid argument to [%s]"), + "CPU"); } } @@ -149,17 +152,21 @@ x86_dir_bits(yasm_object *object, yasm_valparamhead *valparams, { yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)object->arch; yasm_valparam *vp; + /*@only@*/ /*@null@*/ yasm_expr *e = NULL; const yasm_intnum *intn; long lval; - if ((vp = yasm_vps_first(valparams)) && !vp->val && vp->param != NULL && - (intn = yasm_expr_get_intnum(&vp->param, 0)) != NULL && + if ((vp = yasm_vps_first(valparams)) && !vp->val && + (e = yasm_vp_expr(vp, object->symtab, line)) != NULL && + (intn = yasm_expr_get_intnum(&e, 0)) != NULL && (lval = yasm_intnum_get_int(intn)) && (lval == 16 || lval == 32 || lval == 64)) arch_x86->mode_bits = (unsigned char)lval; else yasm_error_set(YASM_ERROR_VALUE, N_("invalid argument to [%s]"), "BITS"); + if (e) + yasm_expr_destroy(e); } static void diff --git a/modules/dbgfmts/dwarf2/dwarf2-line.c b/modules/dbgfmts/dwarf2/dwarf2-line.c index c85763cf..6e77ceb4 100644 --- a/modules/dbgfmts/dwarf2/dwarf2-line.c +++ b/modules/dbgfmts/dwarf2/dwarf2-line.c @@ -831,18 +831,20 @@ yasm_dwarf2__dir_loc(yasm_object *object, yasm_valparamhead *valparams, yasm_valparamhead *objext_valparams, unsigned long line) { yasm_valparam *vp; + int in_is_stmt = 0, in_isa = 0; /*@dependent@*/ /*@null@*/ const yasm_intnum *intn; dwarf2_section_data *dsd; dwarf2_loc *loc = yasm_xmalloc(sizeof(dwarf2_loc)); /* File number (required) */ - if (!valparams || !(vp = yasm_vps_first(valparams)) || !vp->param) { + if (!valparams || !(vp = yasm_vps_first(valparams)) || + vp->val || vp->type != YASM_PARAM_EXPR) { yasm_error_set(YASM_ERROR_SYNTAX, N_("file number required")); yasm_xfree(loc); return; } - intn = yasm_expr_get_intnum(&vp->param, 0); + intn = yasm_expr_get_intnum(&vp->param.e, 0); if (!intn) { yasm_error_set(YASM_ERROR_NOT_CONSTANT, N_("file number is not a constant")); @@ -858,15 +860,15 @@ yasm_dwarf2__dir_loc(yasm_object *object, yasm_valparamhead *valparams, /* Line number (required) */ vp = yasm_vps_next(vp); - if (!vp || !vp->param) { + if (!vp || vp->val || vp->type != YASM_PARAM_EXPR) { yasm_error_set(YASM_ERROR_SYNTAX, N_("line number required")); yasm_xfree(loc); return; } - intn = yasm_expr_get_intnum(&vp->param, 0); + intn = yasm_expr_get_intnum(&vp->param.e, 0); if (!intn) { yasm_error_set(YASM_ERROR_NOT_CONSTANT, - N_("file number is not a constant")); + N_("line number is not a constant")); yasm_xfree(loc); return; } @@ -899,8 +901,8 @@ yasm_dwarf2__dir_loc(yasm_object *object, yasm_valparamhead *valparams, /* Optional column number */ vp = yasm_vps_next(vp); - if (vp && vp->param) { - intn = yasm_expr_get_intnum(&vp->param, 0); + if (vp && !vp->val && vp->type == YASM_PARAM_EXPR) { + intn = yasm_expr_get_intnum(&vp->param.e, 0); if (!intn) { yasm_error_set(YASM_ERROR_NOT_CONSTANT, N_("column number is not a constant")); @@ -911,26 +913,24 @@ yasm_dwarf2__dir_loc(yasm_object *object, yasm_valparamhead *valparams, vp = yasm_vps_next(vp); } - /* Other options */ - while (vp && vp->val) { - if (yasm__strcasecmp(vp->val, "basic_block") == 0) - loc->basic_block = 1; - else if (yasm__strcasecmp(vp->val, "prologue_end") == 0) - loc->prologue_end = 1; - else if (yasm__strcasecmp(vp->val, "epilogue_begin") == 0) - loc->epilogue_begin = 1; - else if (yasm__strcasecmp(vp->val, "is_stmt") == 0) { - if (!vp->param) { - yasm_error_set(YASM_ERROR_SYNTAX, - N_("is_stmt requires value")); - yasm_xfree(loc); - return; - } - intn = yasm_expr_get_intnum(&vp->param, 0); - if (!intn) { + /* Other options; note for GAS compatibility we need to support both: + * is_stmt=1 (NASM) and + * is_stmt 1 (GAS) + */ + while (vp) { + /*@null@*/ /*@dependent@*/ const char *s; + /*@null@*/ /*@only@*/ yasm_expr *e; + +restart: + if (in_is_stmt) { + in_is_stmt = 0; + if (!(e = yasm_vp_expr(vp, object->symtab, line)) || + !(intn = yasm_expr_get_intnum(&e, 0))) { yasm_error_set(YASM_ERROR_NOT_CONSTANT, N_("is_stmt value is not a constant")); yasm_xfree(loc); + if (e) + yasm_expr_destroy(e); return; } if (yasm_intnum_is_zero(intn)) @@ -941,32 +941,65 @@ yasm_dwarf2__dir_loc(yasm_object *object, yasm_valparamhead *valparams, yasm_error_set(YASM_ERROR_VALUE, N_("is_stmt value not 0 or 1")); yasm_xfree(loc); + yasm_expr_destroy(e); return; } - } else if (yasm__strcasecmp(vp->val, "isa") == 0) { - if (!vp->param) { - yasm_error_set(YASM_ERROR_SYNTAX, N_("isa requires value")); - yasm_xfree(loc); - return; - } - intn = yasm_expr_get_intnum(&vp->param, 0); - if (!intn) { + yasm_expr_destroy(e); + } else if (in_isa) { + in_isa = 0; + if (!(e = yasm_vp_expr(vp, object->symtab, line)) || + !(intn = yasm_expr_get_intnum(&e, 0))) { yasm_error_set(YASM_ERROR_NOT_CONSTANT, N_("isa value is not a constant")); yasm_xfree(loc); + if (e) + yasm_expr_destroy(e); return; } if (yasm_intnum_sign(intn) < 0) { yasm_error_set(YASM_ERROR_VALUE, N_("isa value less than zero")); yasm_xfree(loc); + yasm_expr_destroy(e); return; } loc->isa_change = 1; loc->isa = yasm_intnum_get_uint(intn); + yasm_expr_destroy(e); + } else if (!vp->val && (s = yasm_vp_id(vp))) { + if (yasm__strcasecmp(s, "is_stmt") == 0) + in_is_stmt = 1; + else if (yasm__strcasecmp(s, "isa") == 0) + in_isa = 1; + else if (yasm__strcasecmp(s, "basic_block") == 0) + loc->basic_block = 1; + else if (yasm__strcasecmp(s, "prologue_end") == 0) + loc->prologue_end = 1; + else if (yasm__strcasecmp(s, "epilogue_begin") == 0) + loc->epilogue_begin = 1; + else + yasm_warn_set(YASM_WARN_GENERAL, + N_("unrecognized loc option `%s'"), s); + } else if (!vp->val) { + yasm_warn_set(YASM_WARN_GENERAL, + N_("unrecognized numeric qualifier")); + } else if (yasm__strcasecmp(vp->val, "is_stmt") == 0) { + in_is_stmt = 1; + goto restart; /* don't go to the next valparam */ + } else if (yasm__strcasecmp(vp->val, "isa") == 0) { + in_isa = 1; + goto restart; /* don't go to the next valparam */ } else yasm_warn_set(YASM_WARN_GENERAL, N_("unrecognized loc option `%s'"), vp->val); + vp = yasm_vps_next(vp); + } + + if (in_is_stmt || in_isa) { + yasm_error_set(YASM_ERROR_SYNTAX, N_("%s requires value"), + in_is_stmt ? "is_stmt" : "isa"); + yasm_xfree(loc); + return; } /* Append new location */ @@ -992,15 +1025,15 @@ yasm_dwarf2__dir_file(yasm_object *object, yasm_valparamhead *valparams, } vp = yasm_vps_first(valparams); - if (vp->val) { + if (yasm_vp_string(vp)) { /* Just a bare filename */ - yasm_object_set_source_fn(object, vp->val); + yasm_object_set_source_fn(object, yasm_vp_string(vp)); return; } /* Otherwise.. first vp is the file number */ - file_intn = yasm_expr_get_intnum(&vp->param, 0); - if (!file_intn) { + if (vp->type != YASM_PARAM_EXPR || + !(file_intn = yasm_expr_get_intnum(&vp->param.e, 0))) { yasm_error_set(YASM_ERROR_NOT_CONSTANT, N_("file number is not a constant")); return; @@ -1008,11 +1041,11 @@ yasm_dwarf2__dir_file(yasm_object *object, yasm_valparamhead *valparams, filenum = yasm_intnum_get_uint(file_intn); vp = yasm_vps_next(vp); - if (!vp || !vp->val) { + if (!yasm_vp_string(vp)) { yasm_error_set(YASM_ERROR_SYNTAX, N_("file number given but no filename")); return; } - dwarf2_dbgfmt_add_file(dbgfmt_dwarf2, filenum, vp->val); + dwarf2_dbgfmt_add_file(dbgfmt_dwarf2, filenum, yasm_vp_string(vp)); } diff --git a/modules/dbgfmts/dwarf2/tests/pass32/Makefile.inc b/modules/dbgfmts/dwarf2/tests/pass32/Makefile.inc index 5637c3ea..4c3fabc9 100644 --- a/modules/dbgfmts/dwarf2/tests/pass32/Makefile.inc +++ b/modules/dbgfmts/dwarf2/tests/pass32/Makefile.inc @@ -3,6 +3,8 @@ TESTS += modules/dbgfmts/dwarf2/tests/pass32/dwarf2_pass32_test.sh EXTRA_DIST += modules/dbgfmts/dwarf2/tests/pass32/dwarf2_pass32_test.sh +EXTRA_DIST += modules/dbgfmts/dwarf2/tests/pass32/dwarf32-err.asm +EXTRA_DIST += modules/dbgfmts/dwarf2/tests/pass32/dwarf32-err.errwarn EXTRA_DIST += modules/dbgfmts/dwarf2/tests/pass32/dwarf32_testhd.asm EXTRA_DIST += modules/dbgfmts/dwarf2/tests/pass32/dwarf32_testhd.hex diff --git a/modules/dbgfmts/dwarf2/tests/pass32/dwarf32-err.asm b/modules/dbgfmts/dwarf2/tests/pass32/dwarf32-err.asm new file mode 100644 index 00000000..97f7ae56 --- /dev/null +++ b/modules/dbgfmts/dwarf2/tests/pass32/dwarf32-err.asm @@ -0,0 +1,34 @@ +.loc +.loc "foo" +.loc bar +.loc -5 +#.loc foo=1 +.loc 1 +.loc 1 "foo" +.loc 1 bar +.loc 1 2 +#.loc 1 bar=2 +.loc 1 bar 2 +.loc 1 2 "foo" +.loc 1 2 bar+1 +.loc 1 2 is_stmt +.loc 1 2 is_stmt 1 +#.loc 1 2 is_stmt="foo" +.loc 1 2 is_stmt "foo" +#.loc 1 2 is_stmt=bar +.loc 1 2 is_stmt bar +.loc 1 2 is_stmt (bar) +#.loc 1 2 is_stmt=2 +.loc 1 2 is_stmt 2 +.loc 1 2 isa +.loc 1 2 isa 1 +#.loc 1 2 isa="foo" +.loc 1 2 isa "foo" +#.loc 1 2 isa=bar +.loc 1 2 isa bar +#.loc 1 2 isa=-2 +.loc 1 2 isa (-2) +.loc 1 2 isa -2 +#.loc 1 2 foo=1 +.loc 1 2 foo 1 +#.loc 1 2 bar diff --git a/modules/dbgfmts/dwarf2/tests/pass32/dwarf32-err.errwarn b/modules/dbgfmts/dwarf2/tests/pass32/dwarf32-err.errwarn new file mode 100644 index 00000000..d22fdf91 --- /dev/null +++ b/modules/dbgfmts/dwarf2/tests/pass32/dwarf32-err.errwarn @@ -0,0 +1,22 @@ +-:1: directive `.loc' requires an argument +-:2: file number required +-:3: file number required +-:4: file number less than one +-:6: line number required +-:7: line number required +-:8: line number required +-:11: line number required +-:12: warning: unrecognized numeric qualifier +-:13: column number is not a constant +-:14: is_stmt requires value +-:17: is_stmt value is not a constant +-:19: is_stmt value is not a constant +-:20: is_stmt value is not a constant +-:22: is_stmt value not 0 or 1 +-:23: isa requires value +-:26: isa value is not a constant +-:28: isa value is not a constant +-:30: isa value less than zero +-:31: column number is not a constant +-:33: warning: unrecognized loc option `foo' +-:33: warning: unrecognized numeric qualifier diff --git a/modules/dbgfmts/dwarf2/tests/passwin64/dwarfwin64_testhd.hex b/modules/dbgfmts/dwarf2/tests/passwin64/dwarfwin64_testhd.hex index dd90b3aa..fdf74cc5 100644 --- a/modules/dbgfmts/dwarf2/tests/passwin64/dwarfwin64_testhd.hex +++ b/modules/dbgfmts/dwarf2/tests/passwin64/dwarfwin64_testhd.hex @@ -297,7 +297,7 @@ e2 20 00 40 -60 +c0 2f 38 30 @@ -537,7 +537,7 @@ f4 20 00 00 -60 +c0 48 89 6c diff --git a/modules/objfmts/bin/bin-objfmt.c b/modules/objfmts/bin/bin-objfmt.c index 1524ac6c..1a0c9ec2 100644 --- a/modules/objfmts/bin/bin-objfmt.c +++ b/modules/objfmts/bin/bin-objfmt.c @@ -412,87 +412,73 @@ bin_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams, yasm_section *retval; int isnew; unsigned long start; - char *sectname; + const char *sectname; int resonly = 0; + /*@only@*/ /*@null@*/ yasm_intnum *align_intn = NULL; unsigned long align = 4; int have_align = 0; - if ((vp = yasm_vps_first(valparams)) && !vp->param && vp->val != NULL) { - /* If it's the first section output (.text) start at 0, otherwise - * make sure the start is > 128. - */ - sectname = vp->val; - if (strcmp(sectname, ".text") == 0) - start = 0; - else if (strcmp(sectname, ".data") == 0) - start = 200; - else if (strcmp(sectname, ".bss") == 0) { - start = 200; - resonly = 1; - } else { - /* other section names not recognized. */ - yasm_error_set(YASM_ERROR_GENERAL, - N_("segment name `%s' not recognized"), sectname); - return NULL; - } + static const yasm_dir_help help[] = { + { "align", 1, yasm_dir_helper_intn, 0, 0 } + }; - /* Check for ALIGN qualifier */ - while ((vp = yasm_vps_next(vp))) { - if (!vp->val) { - yasm_warn_set(YASM_WARN_GENERAL, - N_("Unrecognized numeric qualifier")); - continue; - } + vp = yasm_vps_first(valparams); + sectname = yasm_vp_string(vp); + if (!sectname) + return NULL; + vp = yasm_vps_next(vp); - if (yasm__strcasecmp(vp->val, "align") == 0 && vp->param) { - /*@dependent@*/ /*@null@*/ const yasm_intnum *align_expr; - - if (strcmp(sectname, ".text") == 0) { - yasm_error_set(YASM_ERROR_GENERAL, - N_("cannot specify an alignment to the `%s' section"), - sectname); - return NULL; - } - - align_expr = yasm_expr_get_intnum(&vp->param, 0); - if (!align_expr) { - yasm_error_set(YASM_ERROR_VALUE, - N_("argument to `%s' is not an integer"), - vp->val); - return NULL; - } - align = yasm_intnum_get_uint(align_expr); - - /* Alignments must be a power of two. */ - if (!is_exp2(align)) { - yasm_error_set(YASM_ERROR_VALUE, - N_("argument to `%s' is not a power of two"), - vp->val); - return NULL; - } - - have_align = 1; - } + /* If it's the first section output (.text) start at 0, otherwise + * make sure the start is > 128. + */ + if (strcmp(sectname, ".text") == 0) + start = 0; + else if (strcmp(sectname, ".data") == 0) + start = 200; + else if (strcmp(sectname, ".bss") == 0) { + start = 200; + resonly = 1; + } else { + /* other section names not recognized. */ + yasm_error_set(YASM_ERROR_GENERAL, + N_("segment name `%s' not recognized"), sectname); + return NULL; + } + + have_align = yasm_dir_helper(object, vp, line, help, NELEMS(help), + &align_intn, yasm_dir_helper_valparam_warn); + if (have_align < 0) + return NULL; /* error occurred */ + + if (align_intn) { + align = yasm_intnum_get_uint(align_intn); + yasm_intnum_destroy(align_intn); + + /* Alignments must be a power of two. */ + if (!is_exp2(align)) { + yasm_error_set(YASM_ERROR_VALUE, + N_("argument to `%s' is not a power of two"), + "align"); + return NULL; } + } - retval = yasm_object_get_general(object, sectname, - yasm_expr_create_ident( - yasm_expr_int(yasm_intnum_create_uint(start)), line), align, - strcmp(sectname, ".text") == 0, resonly, &isnew, line); + retval = yasm_object_get_general(object, sectname, + yasm_expr_create_ident( + yasm_expr_int(yasm_intnum_create_uint(start)), line), align, + strcmp(sectname, ".text") == 0, resonly, &isnew, line); - if (isnew) - bin_objfmt_init_new_section(object, retval, sectname, line); + if (isnew) + bin_objfmt_init_new_section(object, retval, sectname, line); - if (isnew || yasm_section_is_default(retval)) { - yasm_section_set_default(retval, 0); - yasm_section_set_align(retval, align, line); - } else if (have_align) - yasm_warn_set(YASM_WARN_GENERAL, - N_("alignment value ignored on section redeclaration")); + if (isnew || yasm_section_is_default(retval)) { + yasm_section_set_default(retval, 0); + yasm_section_set_align(retval, align, line); + } else if (have_align) + yasm_warn_set(YASM_WARN_GENERAL, + N_("alignment value ignored on section redeclaration")); - return retval; - } else - return NULL; + return retval; } static void @@ -503,25 +489,11 @@ bin_objfmt_dir_org(yasm_object *object, { yasm_section *sect; yasm_valparam *vp; - - /*@null@*/ yasm_expr *start = NULL; - - if (!valparams) { - yasm_error_set(YASM_ERROR_SYNTAX, N_("[%s] requires an argument"), - "ORG"); - return; - } + /*@only@*/ /*@null@*/ yasm_expr *start; /* ORG takes just a simple integer as param */ vp = yasm_vps_first(valparams); - if (vp->val) - start = yasm_expr_create_ident(yasm_expr_sym(yasm_symtab_use( - object->symtab, vp->val, line)), line); - else if (vp->param) { - start = vp->param; - vp->param = NULL; /* Don't let valparams delete it */ - } - + start = yasm_vp_expr(vp, object->symtab, line); if (!start) { yasm_error_set(YASM_ERROR_SYNTAX, N_("argument to ORG must be expression")); diff --git a/modules/objfmts/coff/coff-objfmt.c b/modules/objfmts/coff/coff-objfmt.c index b7208fa7..1df7c4cf 100644 --- a/modules/objfmts/coff/coff-objfmt.c +++ b/modules/objfmts/coff/coff-objfmt.c @@ -1266,6 +1266,90 @@ coff_objfmt_add_default_section(yasm_object *object) return retval; } +struct coff_section_switch_data { + int isdefault; + int gasflags; + unsigned long flags; + unsigned long flags2; + /*@only@*/ /*@null@*/ yasm_intnum *align_intn; +}; + +/* GAS-style flags */ +static int +coff_helper_gasflags(void *obj, yasm_valparam *vp, unsigned long line, void *d, + /*@unused@*/ uintptr_t arg) +{ + struct coff_section_switch_data *data = + (struct coff_section_switch_data *)d; + int alloc = 0, load = 0, readonly = 0, code = 0, datasect = 0; + int shared = 0; + const char *s = yasm_vp_string(vp); + size_t i; + + if (!s) { + yasm_error_set(YASM_ERROR_VALUE, N_("non-string section attribute")); + return -1; + } + + /* For GAS, default to read/write data */ + if (data->isdefault) + data->flags = COFF_STYP_TEXT | COFF_STYP_READ | COFF_STYP_WRITE; + + for (i=0; iflags = COFF_STYP_TEXT | COFF_STYP_EXECUTE | COFF_STYP_READ; + else if (datasect) + data->flags = COFF_STYP_DATA | COFF_STYP_READ | COFF_STYP_WRITE; + else if (readonly) + data->flags = COFF_STYP_DATA | COFF_STYP_READ; + else if (load) + data->flags = COFF_STYP_TEXT; + else if (alloc) + data->flags = COFF_STYP_BSS; + + if (shared) + data->flags |= COFF_STYP_SHARED; + + data->gasflags = 1; + return 0; +} + static /*@observer@*/ /*@null@*/ yasm_section * coff_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams, /*@unused@*/ /*@null@*/ @@ -1273,79 +1357,99 @@ coff_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams, unsigned long line) { yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)object->objfmt; - yasm_valparam *vp = yasm_vps_first(valparams); + yasm_valparam *vp; yasm_section *retval; int isnew; int iscode = 0; - unsigned long flags; - unsigned long flags2 = 0; - int flags_override = 0; - char *sectname; + int flags_override; + const char *sectname; + char *realname; int resonly = 0; unsigned long align = 0; coff_section_data *csd; - static const struct { - const char *name; - unsigned long stdflags; /* if 0, win32 only qualifier */ - unsigned long win32flags; - unsigned long flags2; - /* Mode: 0 => clear specified bits - * 1 => set specified bits - * 2 => clear all bits, then set specified bits - */ - int mode; - } flagquals[] = { - { "code", COFF_STYP_TEXT, COFF_STYP_EXECUTE | COFF_STYP_READ, 0, 2 }, - { "text", COFF_STYP_TEXT, COFF_STYP_EXECUTE | COFF_STYP_READ, 0, 2 }, - { "data", COFF_STYP_DATA, COFF_STYP_READ | COFF_STYP_WRITE, 0, 2 }, - { "bss", COFF_STYP_BSS, COFF_STYP_READ | COFF_STYP_WRITE, 0, 2 }, - { "info", COFF_STYP_INFO, COFF_STYP_DISCARD | COFF_STYP_READ, 0, 2 }, - { "discard", 0, COFF_STYP_DISCARD, 0, 1 }, - { "nodiscard", 0, COFF_STYP_DISCARD, 0, 0 }, - { "cache", 0, COFF_STYP_NOCACHE, 0, 0 }, - { "nocache", 0, COFF_STYP_NOCACHE, 0, 1 }, - { "page", 0, COFF_STYP_NOPAGE, 0, 0 }, - { "nopage", 0, COFF_STYP_NOPAGE, 0, 1 }, - { "share", 0, COFF_STYP_SHARED, 0, 1 }, - { "noshare", 0, COFF_STYP_SHARED, 0, 0 }, - { "execute", 0, COFF_STYP_EXECUTE, 0, 1 }, - { "noexecute", 0, COFF_STYP_EXECUTE, 0, 0 }, - { "read", 0, COFF_STYP_READ, 0, 1 }, - { "noread", 0, COFF_STYP_READ, 0, 0 }, - { "write", 0, COFF_STYP_WRITE, 0, 1 }, - { "nowrite", 0, COFF_STYP_WRITE, 0, 0 }, - { "base", 0, 0, COFF_FLAG_NOBASE, 0 }, - { "nobase", 0, 0, COFF_FLAG_NOBASE, 1 }, + struct coff_section_switch_data data; + + static const yasm_dir_help help[] = { + { "code", 0, yasm_dir_helper_flag_set, + offsetof(struct coff_section_switch_data, flags), + COFF_STYP_TEXT | COFF_STYP_EXECUTE | COFF_STYP_READ }, + { "text", 0, yasm_dir_helper_flag_set, + offsetof(struct coff_section_switch_data, flags), + COFF_STYP_TEXT | COFF_STYP_EXECUTE | COFF_STYP_READ }, + { "data", 0, yasm_dir_helper_flag_set, + offsetof(struct coff_section_switch_data, flags), + COFF_STYP_DATA | COFF_STYP_READ | COFF_STYP_WRITE }, + { "rdata", 0, yasm_dir_helper_flag_set, + offsetof(struct coff_section_switch_data, flags), + COFF_STYP_DATA | COFF_STYP_READ }, + { "bss", 0, yasm_dir_helper_flag_set, + offsetof(struct coff_section_switch_data, flags), + COFF_STYP_BSS | COFF_STYP_READ | COFF_STYP_WRITE }, + { "info", 0, yasm_dir_helper_flag_set, + offsetof(struct coff_section_switch_data, flags), + COFF_STYP_INFO | COFF_STYP_DISCARD | COFF_STYP_READ }, + { "gasflags", 1, coff_helper_gasflags, 0, 0 }, + /* Win32 only below this point */ + { "discard", 0, yasm_dir_helper_flag_or, + offsetof(struct coff_section_switch_data, flags), COFF_STYP_DISCARD}, + { "nodiscard", 0, yasm_dir_helper_flag_and, + offsetof(struct coff_section_switch_data, flags), COFF_STYP_DISCARD}, + { "cache", 0, yasm_dir_helper_flag_and, + offsetof(struct coff_section_switch_data, flags), COFF_STYP_NOCACHE}, + { "nocache", 0, yasm_dir_helper_flag_or, + offsetof(struct coff_section_switch_data, flags), COFF_STYP_NOCACHE}, + { "page", 0, yasm_dir_helper_flag_and, + offsetof(struct coff_section_switch_data, flags), COFF_STYP_NOPAGE }, + { "nopage", 0, yasm_dir_helper_flag_or, + offsetof(struct coff_section_switch_data, flags), COFF_STYP_NOPAGE }, + { "share", 0, yasm_dir_helper_flag_or, + offsetof(struct coff_section_switch_data, flags), COFF_STYP_SHARED }, + { "noshare", 0, yasm_dir_helper_flag_and, + offsetof(struct coff_section_switch_data, flags), COFF_STYP_SHARED }, + { "execute", 0, yasm_dir_helper_flag_or, + offsetof(struct coff_section_switch_data, flags), COFF_STYP_EXECUTE}, + { "noexecute", 0, yasm_dir_helper_flag_and, + offsetof(struct coff_section_switch_data, flags), COFF_STYP_EXECUTE}, + { "read", 0, yasm_dir_helper_flag_or, + offsetof(struct coff_section_switch_data, flags), COFF_STYP_READ }, + { "noread", 0, yasm_dir_helper_flag_and, + offsetof(struct coff_section_switch_data, flags), COFF_STYP_READ }, + { "write", 0, yasm_dir_helper_flag_or, + offsetof(struct coff_section_switch_data, flags), COFF_STYP_WRITE }, + { "nowrite", 0, yasm_dir_helper_flag_and, + offsetof(struct coff_section_switch_data, flags), COFF_STYP_WRITE }, + { "base", 0, yasm_dir_helper_flag_and, + offsetof(struct coff_section_switch_data, flags2), COFF_FLAG_NOBASE}, + { "nobase", 0, yasm_dir_helper_flag_or, + offsetof(struct coff_section_switch_data, flags2), COFF_FLAG_NOBASE}, + { "align", 1, yasm_dir_helper_intn, + offsetof(struct coff_section_switch_data, align_intn), 0 } }; - if (!vp || vp->param || !vp->val) + vp = yasm_vps_first(valparams); + sectname = yasm_vp_string(vp); + if (!sectname) return NULL; + vp = yasm_vps_next(vp); - sectname = vp->val; - if (strlen(sectname) > 8 && !objfmt_coff->win32) { - /* win32 format supports >8 character section names in object - * files via "/nnnn" (where nnnn is decimal offset into string table), - * so only warn for regular COFF. - */ - yasm_warn_set(YASM_WARN_GENERAL, - N_("COFF section names limited to 8 characters: truncating")); - sectname[8] = '\0'; - } + data.isdefault = 0; + data.gasflags = 0; + data.flags = 0; + data.flags2 = 0; + data.align_intn = NULL; if (strcmp(sectname, ".data") == 0) { - flags = COFF_STYP_DATA; + data.flags = COFF_STYP_DATA | COFF_STYP_READ | COFF_STYP_WRITE; if (objfmt_coff->win32) { - flags |= COFF_STYP_READ | COFF_STYP_WRITE; if (objfmt_coff->machine == COFF_MACHINE_AMD64) align = 16; else align = 4; } } else if (strcmp(sectname, ".bss") == 0) { - flags = COFF_STYP_BSS; + data.flags = COFF_STYP_BSS | COFF_STYP_READ | COFF_STYP_WRITE; if (objfmt_coff->win32) { - flags |= COFF_STYP_READ | COFF_STYP_WRITE; if (objfmt_coff->machine == COFF_MACHINE_AMD64) align = 16; else @@ -1353,215 +1457,101 @@ coff_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams, } resonly = 1; } else if (strcmp(sectname, ".text") == 0) { - flags = COFF_STYP_TEXT; - if (objfmt_coff->win32) { - flags |= COFF_STYP_EXECUTE | COFF_STYP_READ; + data.flags = COFF_STYP_TEXT | COFF_STYP_EXECUTE | COFF_STYP_READ; + if (objfmt_coff->win32) align = 16; - } - iscode = 1; } else if (strcmp(sectname, ".rdata") == 0 || strncmp(sectname, ".rodata", 7) == 0 || strncmp(sectname, ".rdata$", 7) == 0) { - flags = COFF_STYP_DATA; - if (objfmt_coff->win32) { - flags |= COFF_STYP_READ; + data.flags = COFF_STYP_DATA | COFF_STYP_READ; + if (objfmt_coff->win32) align = 8; - } else + else yasm_warn_set(YASM_WARN_GENERAL, N_("Standard COFF does not support read-only data sections")); } else if (strcmp(sectname, ".drectve") == 0) { - flags = COFF_STYP_INFO; + data.flags = COFF_STYP_INFO; if (objfmt_coff->win32) - flags |= COFF_STYP_DISCARD | COFF_STYP_READ; + data.flags |= COFF_STYP_DISCARD | COFF_STYP_READ; } else if (objfmt_coff->win64 && strcmp(sectname, ".pdata") == 0) { - flags = COFF_STYP_DATA | COFF_STYP_READ; + data.flags = COFF_STYP_DATA | COFF_STYP_READ; align = 4; - flags2 = COFF_FLAG_NOBASE; + data.flags2 = COFF_FLAG_NOBASE; } else if (objfmt_coff->win64 && strcmp(sectname, ".xdata") == 0) { - flags = COFF_STYP_DATA | COFF_STYP_READ; + data.flags = COFF_STYP_DATA | COFF_STYP_READ; align = 8; } else if (strcmp(sectname, ".comment") == 0) { - flags = COFF_STYP_INFO; - if (objfmt_coff->win32) - flags |= COFF_STYP_DISCARD | COFF_STYP_READ; + data.flags = COFF_STYP_INFO | COFF_STYP_DISCARD | COFF_STYP_READ; } else if (yasm__strncasecmp(sectname, ".debug", 6)==0) { - flags = COFF_STYP_DATA; - if (objfmt_coff->win32) - flags |= COFF_STYP_DISCARD|COFF_STYP_READ; + data.flags = COFF_STYP_DATA | COFF_STYP_DISCARD | COFF_STYP_READ; align = 1; } else { - /* Default to code */ - flags = COFF_STYP_TEXT; - if (objfmt_coff->win32) - flags |= COFF_STYP_EXECUTE | COFF_STYP_READ; - iscode = 1; + /* Default to code, but set a flag so if we get gasflags we can + * change it (NASM and GAS have different defaults). + */ + data.isdefault = 1; + data.flags = COFF_STYP_TEXT | COFF_STYP_EXECUTE | COFF_STYP_READ; } - while ((vp = yasm_vps_next(vp))) { - size_t i; - int match, win32warn; - - win32warn = 0; - - if (!vp->val) { - yasm_warn_set(YASM_WARN_GENERAL, - N_("Unrecognized numeric qualifier")); - continue; - } + flags_override = yasm_dir_helper(object, vp, line, help, + objfmt_coff->win32 ? NELEMS(help) : 7, + &data, yasm_dir_helper_valparam_warn); + if (flags_override < 0) + return NULL; /* error occurred */ - match = 0; - for (i=0; ival, flagquals[i].name) == 0) { - if (!objfmt_coff->win32 && flagquals[i].stdflags == 0) - win32warn = 1; - else switch (flagquals[i].mode) { - case 0: - flags &= ~flagquals[i].stdflags; - flags2 &= ~flagquals[i].flags2; - if (objfmt_coff->win32) - flags &= ~flagquals[i].win32flags; - if (flagquals[i].win32flags & COFF_STYP_EXECUTE) - iscode = 0; - break; - case 1: - flags |= flagquals[i].stdflags; - flags2 |= flagquals[i].flags2; - if (objfmt_coff->win32) - flags |= flagquals[i].win32flags; - if (flagquals[i].win32flags & COFF_STYP_EXECUTE) - iscode = 1; - break; - case 2: - flags &= ~COFF_STYP_STD_MASK; - flags |= flagquals[i].stdflags; - flags2 = flagquals[i].flags2; - if (objfmt_coff->win32) { - flags &= ~COFF_STYP_WIN32_MASK; - flags |= flagquals[i].win32flags; - } - if (flagquals[i].win32flags & COFF_STYP_EXECUTE) - iscode = 1; - break; - } - flags_override = 1; - match = 1; - } - } + if (data.flags & COFF_STYP_EXECUTE) + iscode = 1; - if (match) - ; - else if (yasm__strncasecmp(vp->val, "gas_", 4) == 0) { - /* GAS-style flags */ - int alloc = 0, load = 0, readonly = 0, code = 0, data = 0; - int shared = 0; - iscode = 0; - for (i=4; ival); i++) { - switch (vp->val[i]) { - case 'a': - break; - case 'b': - alloc = 1; - load = 0; - break; - case 'n': - load = 0; - break; - case 's': - shared = 1; - /*@fallthrough@*/ - case 'd': - data = 1; - load = 1; - readonly = 0; - case 'x': - code = 1; - load = 1; - break; - case 'r': - data = 1; - load = 1; - readonly = 1; - break; - case 'w': - readonly = 0; - break; - default: - yasm_warn_set(YASM_WARN_GENERAL, - N_("unrecognized section attribute: `%c'"), - vp->val[i]); - } - } - if (code) { - flags = COFF_STYP_TEXT; - if (objfmt_coff->win32) - flags |= COFF_STYP_EXECUTE | COFF_STYP_READ; - iscode = 1; - } else if (data) { - flags = COFF_STYP_DATA; - if (objfmt_coff->win32) - flags |= COFF_STYP_READ | COFF_STYP_WRITE; - } else if (readonly) { - flags = COFF_STYP_DATA; - if (objfmt_coff->win32) - flags |= COFF_STYP_READ; - } else if (load) - flags = COFF_STYP_TEXT; - else if (alloc) - flags = COFF_STYP_BSS; - if (shared && objfmt_coff->win32) - flags |= COFF_STYP_SHARED; - } else if (yasm__strcasecmp(vp->val, "align") == 0 && vp->param) { - if (objfmt_coff->win32) { - /*@dependent@*/ /*@null@*/ const yasm_intnum *align_expr; - align_expr = yasm_expr_get_intnum(&vp->param, 0); - if (!align_expr) { - yasm_error_set(YASM_ERROR_VALUE, - N_("argument to `%s' is not an integer"), - vp->val); - return NULL; - } - align = yasm_intnum_get_uint(align_expr); + if (!objfmt_coff->win32) + data.flags &= ~COFF_STYP_WIN32_MASK; - /* Alignments must be a power of two. */ - if (!is_exp2(align)) { - yasm_error_set(YASM_ERROR_VALUE, - N_("argument to `%s' is not a power of two"), - vp->val); - return NULL; - } + if (data.align_intn) { + align = yasm_intnum_get_uint(data.align_intn); + yasm_intnum_destroy(data.align_intn); - /* Check to see if alignment is supported size */ - if (align > 8192) { - yasm_error_set(YASM_ERROR_VALUE, - N_("Win32 does not support alignments > 8192")); - return NULL; - } + /* Alignments must be a power of two. */ + if (!is_exp2(align)) { + yasm_error_set(YASM_ERROR_VALUE, + N_("argument to `%s' is not a power of two"), + "align"); + return NULL; + } - } else - win32warn = 1; - } else - yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized qualifier `%s'"), - vp->val); + /* Check to see if alignment is supported size */ + if (align > 8192) { + yasm_error_set(YASM_ERROR_VALUE, + N_("Win32 does not support alignments > 8192")); + return NULL; + } + } - if (win32warn) - yasm_warn_set(YASM_WARN_GENERAL, - N_("Standard COFF does not support qualifier `%s'"), vp->val); + realname = yasm__xstrdup(sectname); + if (strlen(sectname) > 8 && !objfmt_coff->win32) { + /* win32 format supports >8 character section names in object + * files via "/nnnn" (where nnnn is decimal offset into string table), + * so only warn for regular COFF. + */ + yasm_warn_set(YASM_WARN_GENERAL, + N_("COFF section names limited to 8 characters: truncating")); + realname[8] = '\0'; } - retval = yasm_object_get_general(object, sectname, 0, align, iscode, + retval = yasm_object_get_general(object, realname, 0, align, iscode, resonly, &isnew, line); if (isnew) - csd = coff_objfmt_init_new_section(object, retval, sectname, line); + csd = coff_objfmt_init_new_section(object, retval, realname, line); else csd = yasm_section_get_data(retval, &coff_section_data_cb); + yasm_xfree(realname); + if (isnew || yasm_section_is_default(retval)) { yasm_section_set_default(retval, 0); - csd->flags = flags; - csd->flags2 = flags2; + csd->flags = data.flags; + csd->flags2 = data.flags2; yasm_section_set_align(retval, align, line); - } else if (flags_override) + } else if (flags_override && !data.gasflags) yasm_warn_set(YASM_WARN_GENERAL, N_("section flags ignored on section redeclaration")); return retval; @@ -1624,14 +1614,16 @@ dir_export(yasm_object *object, yasm_valparamhead *valparams, yasm_valparamhead *objext_valparams, unsigned long line) { yasm_valparam *vp; + /*@null@*/ const char *symname; int isnew; yasm_section *sect; yasm_datavalhead dvs; /* Reference exported symbol (to generate error if not declared) */ vp = yasm_vps_first(valparams); - if (vp->val) - yasm_symtab_use(object->symtab, vp->val, line); + symname = yasm_vp_id(vp); + if (symname) + yasm_symtab_use(object->symtab, symname, line); else { yasm_error_set(YASM_ERROR_SYNTAX, N_("argument to EXPORT must be symbol name")); @@ -1654,8 +1646,8 @@ dir_export(yasm_object *object, yasm_valparamhead *valparams, yasm_dvs_initialize(&dvs); yasm_dvs_append(&dvs, yasm_dv_create_string(yasm__xstrdup("-export:"), strlen("-export:"))); - yasm_dvs_append(&dvs, yasm_dv_create_string(yasm__xstrdup(vp->val), - strlen(vp->val))); + yasm_dvs_append(&dvs, yasm_dv_create_string(yasm__xstrdup(symname), + strlen(symname))); yasm_dvs_append(&dvs, yasm_dv_create_string(yasm__xstrdup(" "), 1)); yasm_section_bcs_append(sect, yasm_bc_create_data(&dvs, 1, 0, NULL, line)); } @@ -1689,7 +1681,7 @@ dir_ident(yasm_object *object, yasm_valparamhead *valparams, sectname = ".comment"; } yasm_vps_initialize(§_vps); - vp2 = yasm_vp_create(yasm__xstrdup(sectname), NULL); + vp2 = yasm_vp_create_id(NULL, yasm__xstrdup(sectname), '\0'); yasm_vps_append(§_vps, vp2); comment = coff_objfmt_section_switch(object, §_vps, NULL, line); yasm_vps_delete(§_vps); @@ -1708,8 +1700,15 @@ dir_ident(yasm_object *object, yasm_valparamhead *valparams, yasm_dvs_initialize(&dvs); do { - yasm_dvs_append(&dvs, yasm_dv_create_string(vp->val, strlen(vp->val))); - vp->val = NULL; + const char *s = yasm_vp_string(vp); + if (!s) { + yasm_error_set(YASM_ERROR_VALUE, + N_(".comment requires string parameters")); + yasm_dvs_delete(&dvs); + return; + } + yasm_dvs_append(&dvs, + yasm_dv_create_string(yasm__xstrdup(s), strlen(s))); } while ((vp = yasm_vps_next(vp))); yasm_section_bcs_append(comment, @@ -1722,6 +1721,8 @@ dir_proc_frame(yasm_object *object, /*@null@*/ yasm_valparamhead *valparams, { yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)object->objfmt; yasm_valparam *vp = yasm_vps_first(valparams); + const char *name = yasm_vp_id(vp); + if (objfmt_coff->proc_frame) { yasm_error_set_xref(objfmt_coff->proc_frame, N_("previous procedure started here")); @@ -1729,23 +1730,17 @@ dir_proc_frame(yasm_object *object, /*@null@*/ yasm_valparamhead *valparams, N_("nested procedures not supported (didn't use [ENDPROC_FRAME]?)")); return; } - if (!vp || !vp->val) { - yasm_error_set(YASM_ERROR_SYNTAX, - N_("[%s] requires a procedure symbol name"), - "PROC_FRAME"); - return; - } objfmt_coff->proc_frame = line; objfmt_coff->done_prolog = 0; objfmt_coff->unwind = yasm_win64__uwinfo_create(); - objfmt_coff->unwind->proc = yasm_symtab_use(object->symtab, vp->val, line); + objfmt_coff->unwind->proc = yasm_symtab_use(object->symtab, name, line); /* Optional error handler */ vp = yasm_vps_next(vp); - if (!vp || !vp->val) + if (!vp || !(name = yasm_vp_id(vp))) return; objfmt_coff->unwind->ehandler = - yasm_symtab_use(object->symtab, vp->val, line); + yasm_symtab_use(object->symtab, name, line); } static int @@ -1796,7 +1791,8 @@ dir_pushreg(yasm_object *object, yasm_valparamhead *valparams, if (!procframe_checkstate(objfmt_coff, "PUSHREG")) return; - if (!vp || !vp->param || !(reg = yasm_expr_get_reg(&vp->param, 0))) { + if (vp->type != YASM_PARAM_EXPR || + !(reg = yasm_expr_get_reg(&vp->param.e, 0))) { yasm_error_set(YASM_ERROR_SYNTAX, N_("[%s] requires a register as the first parameter"), "PUSHREG"); @@ -1826,7 +1822,8 @@ dir_setframe(yasm_object *object, yasm_valparamhead *valparams, if (!procframe_checkstate(objfmt_coff, "SETFRAME")) return; - if (!vp || !vp->param || !(reg = yasm_expr_get_reg(&vp->param, 0))) { + if (vp->type != YASM_PARAM_EXPR || + !(reg = yasm_expr_get_reg(&vp->param.e, 0))) { yasm_error_set(YASM_ERROR_SYNTAX, N_("[%s] requires a register as the first parameter"), "SETFRAME"); @@ -1834,10 +1831,8 @@ dir_setframe(yasm_object *object, yasm_valparamhead *valparams, } vp = yasm_vps_next(vp); - if (vp && vp->param) { - off = vp->param; - vp->param = NULL; - } + if (vp) + off = yasm_vp_expr(vp, object->symtab, line); /* Set the frame fields in the unwind info */ objfmt_coff->unwind->framereg = (unsigned long)(*reg); @@ -1859,18 +1854,14 @@ dir_allocstack(yasm_object *object, yasm_valparamhead *valparams, { yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)object->objfmt; yasm_valparam *vp = yasm_vps_first(valparams); + /*@null@*/ /*@only@*/ yasm_expr *size; coff_unwind_code *code; if (!procframe_checkstate(objfmt_coff, "ALLOCSTACK")) return; - /* Transform ID to expression if needed */ - if (vp && vp->val && !vp->param) { - vp->param = yasm_expr_create_ident(yasm_expr_sym( - yasm_symtab_use(object->symtab, vp->val, line)), line); - } - - if (!vp || !vp->param) { + size = yasm_vp_expr(vp, object->symtab, line); + if (!size) { yasm_error_set(YASM_ERROR_SYNTAX, N_("[%s] requires a size"), "ALLOCSTACK"); return; @@ -1884,8 +1875,7 @@ dir_allocstack(yasm_object *object, yasm_valparamhead *valparams, code->loc = get_curpos(object, "ALLOCSTACK", line); code->opcode = UWOP_ALLOC_SMALL; code->info = 0; - yasm_value_initialize(&code->off, vp->param, 7); - vp->param = NULL; + yasm_value_initialize(&code->off, size, 7); SLIST_INSERT_HEAD(&objfmt_coff->unwind->codes, code, link); } @@ -1897,11 +1887,13 @@ dir_save_common(yasm_object *object, yasm_valparamhead *valparams, yasm_valparam *vp = yasm_vps_first(valparams); coff_unwind_code *code; const uintptr_t *reg; + /*@only@*/ /*@null@*/ yasm_expr *offset; if (!procframe_checkstate(objfmt_coff, name)) return; - if (!vp || !vp->param || !(reg = yasm_expr_get_reg(&vp->param, 0))) { + if (vp->type != YASM_PARAM_EXPR || + !(reg = yasm_expr_get_reg(&vp->param.e, 0))) { yasm_error_set(YASM_ERROR_SYNTAX, N_("[%s] requires a register as the first parameter"), name); @@ -1909,14 +1901,8 @@ dir_save_common(yasm_object *object, yasm_valparamhead *valparams, } vp = yasm_vps_next(vp); - - /* Transform ID to expression if needed */ - if (vp && vp->val && !vp->param) { - vp->param = yasm_expr_create_ident(yasm_expr_sym( - yasm_symtab_use(object->symtab, vp->val, line)), line); - } - - if (!vp || !vp->param) { + offset = yasm_vp_expr(vp, object->symtab, line); + if (!offset) { yasm_error_set(YASM_ERROR_SYNTAX, N_("[%s] requires an offset as the second parameter"), name); @@ -1931,8 +1917,7 @@ dir_save_common(yasm_object *object, yasm_valparamhead *valparams, code->loc = get_curpos(object, name, line); code->opcode = op; code->info = (unsigned int)(*reg & 0xF); - yasm_value_initialize(&code->off, vp->param, 16); - vp->param = NULL; + yasm_value_initialize(&code->off, offset, 16); SLIST_INSERT_HEAD(&objfmt_coff->unwind->codes, code, link); } @@ -1968,7 +1953,7 @@ dir_pushframe(yasm_object *object, /*@null@*/ yasm_valparamhead *valparams, code->proc = objfmt_coff->unwind->proc; code->loc = get_curpos(object, "PUSHFRAME", line); code->opcode = UWOP_PUSH_MACHFRAME; - code->info = vp && (vp->val || vp->param); + code->info = vp != NULL; yasm_value_initialize(&code->off, NULL, 0); SLIST_INSERT_HEAD(&objfmt_coff->unwind->codes, code, link); } @@ -2141,7 +2126,7 @@ static const yasm_directive win64_objfmt_directives[] = { { "ident", "nasm", dir_ident, YASM_DIR_ANY }, { ".export", "gas", dir_export, YASM_DIR_ID_REQUIRED }, { "export", "nasm", dir_export, YASM_DIR_ID_REQUIRED }, - { "proc_frame", "nasm", dir_proc_frame, YASM_DIR_ANY }, + { "proc_frame", "nasm", dir_proc_frame, YASM_DIR_ID_REQUIRED }, { "pushreg", "nasm", dir_pushreg, YASM_DIR_ARG_REQUIRED }, { "setframe", "nasm", dir_setframe, YASM_DIR_ARG_REQUIRED }, { "allocstack", "nasm", dir_allocstack, YASM_DIR_ARG_REQUIRED }, diff --git a/modules/objfmts/dbg/dbg-objfmt.c b/modules/objfmts/dbg/dbg-objfmt.c index b2e8d451..e1aad7ad 100644 --- a/modules/objfmts/dbg/dbg-objfmt.c +++ b/modules/objfmts/dbg/dbg-objfmt.c @@ -126,22 +126,22 @@ dbg_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams, yasm_vps_print(objext_valparams, objfmt_dbg->dbgfile); fprintf(objfmt_dbg->dbgfile, ", %lu), returning ", line); - if ((vp = yasm_vps_first(valparams)) && !vp->param && vp->val != NULL) { - retval = yasm_object_get_general(object, vp->val, - yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_uint(200)), - line), 0, 0, 0, &isnew, line); - if (isnew) { - fprintf(objfmt_dbg->dbgfile, "(new) "); - yasm_symtab_define_label(object->symtab, vp->val, - yasm_section_bcs_first(retval), 1, line); - } - yasm_section_set_default(retval, 0); - fprintf(objfmt_dbg->dbgfile, "\"%s\" section\n", vp->val); - return retval; - } else { + vp = yasm_vps_first(valparams); + if (!yasm_vp_string(vp)) { fprintf(objfmt_dbg->dbgfile, "NULL\n"); return NULL; } + retval = yasm_object_get_general(object, yasm_vp_string(vp), + yasm_expr_create_ident(yasm_expr_int(yasm_intnum_create_uint(200)), + line), 0, 0, 0, &isnew, line); + if (isnew) { + fprintf(objfmt_dbg->dbgfile, "(new) "); + yasm_symtab_define_label(object->symtab, vp->val, + yasm_section_bcs_first(retval), 1, line); + } + yasm_section_set_default(retval, 0); + fprintf(objfmt_dbg->dbgfile, "\"%s\" section\n", vp->val); + return retval; } /* Define valid debug formats to use with this object format */ diff --git a/modules/objfmts/elf/elf-objfmt.c b/modules/objfmts/elf/elf-objfmt.c index 84a27e3b..d53e2430 100644 --- a/modules/objfmts/elf/elf-objfmt.c +++ b/modules/objfmts/elf/elf-objfmt.c @@ -74,6 +74,7 @@ typedef struct { } elf_objfmt_output_info; typedef struct { + yasm_object *object; yasm_objfmt_elf *objfmt_elf; yasm_errwarns *errwarns; int local_names; @@ -119,9 +120,10 @@ build_extern(yasm_objfmt_elf *objfmt_elf, yasm_symrec *sym) if (objext_valparams) { yasm_valparam *vp = yasm_vps_first(objext_valparams); for (; vp; vp = yasm_vps_next(vp)) { - if (vp->val) + if (yasm_vp_string(vp)) yasm_error_set(YASM_ERROR_TYPE, - N_("unrecognized symbol type `%s'"), vp->val); + N_("unrecognized symbol type `%s'"), + yasm_vp_string(vp)); } } @@ -129,60 +131,84 @@ build_extern(yasm_objfmt_elf *objfmt_elf, yasm_symrec *sym) STV_DEFAULT, NULL, NULL); } +struct elf_build_global_data { + yasm_expr *size; + unsigned long type; /* elf_symbol_type */ + elf_symbol_vis vis; + unsigned int vis_overrides; +}; + +static int +elf_global_helper_valparam(void *obj, yasm_valparam *vp, unsigned long line, + void *d) + +{ + struct elf_build_global_data *data = (struct elf_build_global_data *)d; + const char *s; + + if (!vp->val && (s = yasm_vp_id(vp))) { + yasm_error_set(YASM_ERROR_TYPE, N_("unrecognized symbol type `%s'"), + s); + return -1; + } else if (!vp->val && vp->type == YASM_PARAM_EXPR && !data->size) { + data->size = yasm_expr_copy(vp->param.e); + return 0; + } else + return yasm_dir_helper_valparam_warn(obj, vp, line, d); +} + +static int +elf_global_helper_vis(void *obj, yasm_valparam *vp, unsigned long line, + void *d, uintptr_t vis) +{ + struct elf_build_global_data *data = (struct elf_build_global_data *)d; + data->vis = vis; + data->vis_overrides++; + return 0; +} + + static elf_symtab_entry * build_global(yasm_objfmt_elf *objfmt_elf, yasm_symrec *sym) { yasm_valparamhead *objext_valparams = yasm_symrec_get_objext_valparams(sym); - elf_symbol_type type = 0; - yasm_expr *size = NULL; - elf_symbol_vis vis = STV_DEFAULT; - unsigned int vis_overrides = 0; - if (objext_valparams) { - yasm_valparam *vp = yasm_vps_first(objext_valparams); - for (; vp; vp = yasm_vps_next(vp)) - { - if (vp->val) { - if (yasm__strcasecmp(vp->val, "function") == 0) - type = STT_FUNC; - else if (yasm__strcasecmp(vp->val, "data") == 0 || - yasm__strcasecmp(vp->val, "object") == 0) - type = STT_OBJECT; - else if (yasm__strcasecmp(vp->val, "internal") == 0) { - vis = STV_INTERNAL; - vis_overrides++; - } - else if (yasm__strcasecmp(vp->val, "hidden") == 0) { - vis = STV_HIDDEN; - vis_overrides++; - } - else if (yasm__strcasecmp(vp->val, "protected") == 0) { - vis = STV_PROTECTED; - vis_overrides++; - } - else - yasm_error_set(YASM_ERROR_TYPE, - N_("unrecognized symbol type `%s'"), - vp->val); - } - else if (vp->param && !size) { - size = vp->param; - vp->param = NULL; /* to avoid double-free of expr */ - } - } - if (vis_overrides > 1) { - yasm_warn_set(YASM_WARN_GENERAL, - N_("More than one symbol visibility provided; using last")); - } + struct elf_build_global_data data; + + static const yasm_dir_help help[] = { + { "function", 0, yasm_dir_helper_flag_set, + offsetof(struct elf_build_global_data, type), STT_FUNC }, + { "data", 0, yasm_dir_helper_flag_set, + offsetof(struct elf_build_global_data, type), STT_OBJECT }, + { "object", 0, yasm_dir_helper_flag_set, + offsetof(struct elf_build_global_data, type), STT_OBJECT }, + { "internal", 0, elf_global_helper_vis, 0, STV_INTERNAL }, + { "hidden", 0, elf_global_helper_vis, 0, STV_HIDDEN }, + { "protected", 0, elf_global_helper_vis, 0, STV_PROTECTED }, + }; + + data.size = NULL; + data.type = 0; + data.vis = STV_DEFAULT; + data.vis_overrides = 0; + + if (objext_valparams) + yasm_dir_helper(sym, yasm_vps_first(objext_valparams), + yasm_symrec_get_decl_line(sym), help, NELEMS(help), + &data, elf_global_helper_valparam); + + if (data.vis_overrides > 1) { + yasm_warn_set(YASM_WARN_GENERAL, + N_("More than one symbol visibility provided; using last")); } return elf_objfmt_symtab_append(objfmt_elf, sym, SHN_UNDEF, STB_GLOBAL, - type, vis, size, NULL); + data.type, data.vis, data.size, NULL); } static /*@null@*/ elf_symtab_entry * -build_common(yasm_objfmt_elf *objfmt_elf, yasm_symrec *sym) +build_common(yasm_objfmt_elf *objfmt_elf, yasm_symrec *sym, yasm_object *object) { yasm_expr **size = yasm_symrec_get_common_size(sym); yasm_valparamhead *objext_valparams = @@ -192,16 +218,21 @@ build_common(yasm_objfmt_elf *objfmt_elf, yasm_symrec *sym) if (objext_valparams) { yasm_valparam *vp = yasm_vps_first(objext_valparams); for (; vp; vp = yasm_vps_next(vp)) { - if (!vp->val && vp->param) { - /*@dependent@*/ /*@null@*/ const yasm_intnum *align_expr; + if (!vp->val) { + /*@only@*/ /*@null@*/ yasm_expr *align_expr; + /*@dependent@*/ /*@null@*/ const yasm_intnum *align_intn; - align_expr = yasm_expr_get_intnum(&vp->param, 0); - if (!align_expr) { + if (!(align_expr = yasm_vp_expr(vp, object->symtab, + yasm_symrec_get_def_line(sym))) + || !(align_intn = yasm_expr_get_intnum(&align_expr, 0))) { yasm_error_set(YASM_ERROR_VALUE, N_("alignment constraint is not an integer")); + if (align_expr) + yasm_expr_destroy(align_expr); return NULL; } - addralign = yasm_intnum_get_uint(align_expr); + addralign = yasm_intnum_get_uint(align_intn); + yasm_expr_destroy(align_expr); /* Alignments must be a power of two. */ if (!is_exp2(addralign)) { @@ -209,7 +240,7 @@ build_common(yasm_objfmt_elf *objfmt_elf, yasm_symrec *sym) N_("alignment constraint is not a power of two")); return NULL; } - } else if (vp->val) + } else yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized qualifier `%s'"), vp->val); } @@ -240,7 +271,7 @@ elf_objfmt_build_symtab(yasm_symrec *sym, /*@null@*/ void *d) } if (vis & YASM_SYM_COMMON) { - entry = build_common(info->objfmt_elf, sym); + entry = build_common(info->objfmt_elf, sym, info->object); yasm_errwarn_propagate(info->errwarns, yasm_symrec_get_decl_line(sym)); /* If the COMMON variable was actually defined, fall through. */ @@ -764,6 +795,7 @@ elf_objfmt_output(yasm_object *object, FILE *f, int all_syms, /* add all (local) syms to symtab because relocation needs a symtab index * if all_syms, register them by name. if not, use strtab entry 0 */ + buildsym_info.object = object; buildsym_info.objfmt_elf = objfmt_elf; buildsym_info.errwarns = errwarns; buildsym_info.local_names = all_syms; @@ -921,186 +953,193 @@ elf_objfmt_add_default_section(yasm_object *object) return retval; } +struct elf_section_switch_data { + /*@only@*/ /*@null@*/ yasm_intnum *align_intn; + unsigned long flags; + unsigned long type; + int gasflags; +}; + +/* GAS-style flags */ +static int +elf_helper_gasflags(void *obj, yasm_valparam *vp, unsigned long line, void *d, + /*@unused@*/ uintptr_t arg) +{ + struct elf_section_switch_data *data = (struct elf_section_switch_data *)d; + const char *s = yasm_vp_string(vp); + size_t i; + + if (!s) { + yasm_error_set(YASM_ERROR_VALUE, + N_("non-string section attribute")); + return -1; + } + + data->flags = 0; + for (i=0; iflags |= SHF_ALLOC; + break; + case 'w': + data->flags |= SHF_WRITE; + break; + case 'x': + data->flags |= SHF_EXECINSTR; + break; + case 'M': + data->flags |= SHF_MERGE; + break; + case 'S': + data->flags |= SHF_STRINGS; + break; + case 'G': + data->flags |= SHF_GROUP; + break; + case 'T': + data->flags |= SHF_TLS; + break; + default: + yasm_warn_set(YASM_WARN_GENERAL, + N_("unrecognized section attribute: `%c'"), + s[i]); + } + } + + data->gasflags = 1; + return 0; +} + static /*@observer@*/ /*@null@*/ yasm_section * elf_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams, /*@null@*/ yasm_valparamhead *objext_valparams, unsigned long line) { - yasm_valparam *vp = yasm_vps_first(valparams); + yasm_valparam *vp; yasm_section *retval; int isnew; - unsigned long type = SHT_PROGBITS; - unsigned long flags = SHF_ALLOC; unsigned long align = 4; int flags_override = 0; - char *sectname; + const char *sectname; int resonly = 0; - static const struct { - const char *name; - unsigned long flags; - } flagquals[] = { - { "alloc", SHF_ALLOC }, - { "exec", SHF_EXECINSTR }, - { "write", SHF_WRITE }, - /*{ "progbits", SHT_PROGBITS },*/ - /*{ "align", 0 } */ + + struct elf_section_switch_data data; + + static const yasm_dir_help help[] = { + { "alloc", 0, yasm_dir_helper_flag_or, + offsetof(struct elf_section_switch_data, flags), SHF_ALLOC }, + { "exec", 0, yasm_dir_helper_flag_or, + offsetof(struct elf_section_switch_data, flags), SHF_EXECINSTR }, + { "write", 0, yasm_dir_helper_flag_or, + offsetof(struct elf_section_switch_data, flags), SHF_WRITE }, + { "progbits", 0, yasm_dir_helper_flag_set, + offsetof(struct elf_section_switch_data, type), SHT_PROGBITS }, + { "noalloc", 0, yasm_dir_helper_flag_and, + offsetof(struct elf_section_switch_data, flags), SHF_ALLOC }, + { "noexec", 0, yasm_dir_helper_flag_and, + offsetof(struct elf_section_switch_data, flags), SHF_EXECINSTR }, + { "nowrite", 0, yasm_dir_helper_flag_and, + offsetof(struct elf_section_switch_data, flags), SHF_WRITE }, + { "noprogbits", 0, yasm_dir_helper_flag_set, + offsetof(struct elf_section_switch_data, type), SHT_NOBITS }, + { "nobits", 0, yasm_dir_helper_flag_set, + offsetof(struct elf_section_switch_data, type), SHT_NOBITS }, + { "gasflags", 1, elf_helper_gasflags, 0, 0 }, + { "align", 1, yasm_dir_helper_intn, + offsetof(struct elf_section_switch_data, align_intn), 0 } }; + /*@only@*/ /*@null@*/ yasm_expr *merge_expr = NULL; /*@dependent@*/ /*@null@*/ const yasm_intnum *merge_intn = NULL; elf_secthead *esd; - if (!vp || vp->param || !vp->val) - return NULL; + data.align_intn = NULL; + data.flags = SHF_ALLOC; + data.type = SHT_PROGBITS; + data.gasflags = 0; - sectname = vp->val; + vp = yasm_vps_first(valparams); + sectname = yasm_vp_string(vp); + if (!sectname) + return NULL; + vp = yasm_vps_next(vp); if (strcmp(sectname, ".bss") == 0) { - type = SHT_NOBITS; - flags = SHF_ALLOC + SHF_WRITE; + data.type = SHT_NOBITS; + data.flags = SHF_ALLOC + SHF_WRITE; resonly = 1; } else if (strcmp(sectname, ".data") == 0) { - type = SHT_PROGBITS; - flags = SHF_ALLOC + SHF_WRITE; + data.type = SHT_PROGBITS; + data.flags = SHF_ALLOC + SHF_WRITE; } else if (strcmp(sectname, ".rodata") == 0) { - type = SHT_PROGBITS; - flags = SHF_ALLOC; + data.type = SHT_PROGBITS; + data.flags = SHF_ALLOC; } else if (strcmp(sectname, ".text") == 0) { align = 16; - type = SHT_PROGBITS; - flags = SHF_ALLOC + SHF_EXECINSTR; + data.type = SHT_PROGBITS; + data.flags = SHF_ALLOC + SHF_EXECINSTR; } else if (strcmp(sectname, ".comment") == 0) { align = 0; - type = SHT_PROGBITS; - flags = 0; + data.type = SHT_PROGBITS; + data.flags = 0; } else { /* Default to code */ align = 1; } - while ((vp = yasm_vps_next(vp))) { - size_t i; - int match; - - if (!vp->val) { - yasm_warn_set(YASM_WARN_GENERAL, - N_("Unrecognized numeric qualifier")); - continue; - } - - match = 0; - for (i=0; ival, flagquals[i].name) == 0) { - flags_override = 1; - match = 1; - flags |= flagquals[i].flags; - } - else if (yasm__strcasecmp(vp->val+2, flagquals[i].name) == 0 - && yasm__strncasecmp(vp->val, "no", 2) == 0) { - flags &= ~flagquals[i].flags; - flags_override = 1; - match = 1; - } - } - - if (match) - ; - else if (yasm__strncasecmp(vp->val, "gas_", 4) == 0) { - /* GAS-style flags */ - flags = 0; - for (i=4; ival); i++) { - switch (vp->val[i]) { - case 'a': - flags |= SHF_ALLOC; - break; - case 'w': - flags |= SHF_WRITE; - break; - case 'x': - flags |= SHF_EXECINSTR; - break; - case 'M': - flags |= SHF_MERGE; - break; - case 'S': - flags |= SHF_STRINGS; - break; - case 'G': - flags |= SHF_GROUP; - break; - case 'T': - flags |= SHF_TLS; - break; - default: - yasm_warn_set(YASM_WARN_GENERAL, - N_("unrecognized section attribute: `%c'"), - vp->val[i]); - } - } - } else if (yasm__strcasecmp(vp->val, "progbits") == 0) { - type |= SHT_PROGBITS; - } - else if (yasm__strcasecmp(vp->val, "noprogbits") == 0 || - yasm__strcasecmp(vp->val, "nobits") == 0) { - type &= ~SHT_PROGBITS; - type |= SHT_NOBITS; + flags_override = yasm_dir_helper(object, vp, line, help, NELEMS(help), + &data, yasm_dir_helper_valparam_warn); + if (flags_override < 0) + return NULL; /* error occurred */ + + if (data.align_intn) { + align = yasm_intnum_get_uint(data.align_intn); + yasm_intnum_destroy(data.align_intn); + + /* Alignments must be a power of two. */ + if (!is_exp2(align)) { + yasm_error_set(YASM_ERROR_VALUE, + N_("argument to `%s' is not a power of two"), + "align"); + return NULL; } - else if (yasm__strcasecmp(vp->val, "align") == 0 && vp->param) { - /*@dependent@*/ /*@null@*/ const yasm_intnum *align_expr; - - align_expr = yasm_expr_get_intnum(&vp->param, 0); - if (!align_expr) { - yasm_error_set(YASM_ERROR_VALUE, - N_("argument to `%s' is not an integer"), - vp->val); - return NULL; - } - align = yasm_intnum_get_uint(align_expr); - - /* Alignments must be a power of two. */ - if (!is_exp2(align)) { - yasm_error_set(YASM_ERROR_VALUE, - N_("argument to `%s' is not a power of two"), - vp->val); - return NULL; - } - } else - yasm_warn_set(YASM_WARN_GENERAL, - N_("Unrecognized qualifier `%s'"), vp->val); } - /* Handle merge entity size */ - if (flags & SHF_MERGE) { - if (objext_valparams && (vp = yasm_vps_first(objext_valparams)) - && vp->param) { - - merge_intn = yasm_expr_get_intnum(&vp->param, 0); - if (!merge_intn) - yasm_warn_set(YASM_WARN_GENERAL, - N_("invalid merge entity size")); - } else { + + /* Handle merge entity size */ + if (data.flags & SHF_MERGE) { + if (objext_valparams && (vp = yasm_vps_first(objext_valparams)) + && !vp->val) { + if (!(merge_expr = yasm_vp_expr(vp, object->symtab, line)) || + !(merge_intn = yasm_expr_get_intnum(&merge_expr, 0))) yasm_warn_set(YASM_WARN_GENERAL, - N_("entity size for SHF_MERGE not specified")); - flags &= ~SHF_MERGE; - } + N_("invalid merge entity size")); + } else { + yasm_warn_set(YASM_WARN_GENERAL, + N_("entity size for SHF_MERGE not specified")); + data.flags &= ~SHF_MERGE; } + } retval = yasm_object_get_general(object, sectname, 0, align, - (flags & SHF_EXECINSTR) != 0, resonly, - &isnew, line); + (data.flags & SHF_EXECINSTR) != 0, + resonly, &isnew, line); if (isnew) - esd = elf_objfmt_init_new_section(object, retval, sectname, type, - flags, line); + esd = elf_objfmt_init_new_section(object, retval, sectname, data.type, + data.flags, line); else esd = yasm_section_get_data(retval, &elf_section_data); if (isnew || yasm_section_is_default(retval)) { yasm_section_set_default(retval, 0); - elf_secthead_set_typeflags(esd, type, flags); + elf_secthead_set_typeflags(esd, data.type, data.flags); if (merge_intn) elf_secthead_set_entsize(esd, yasm_intnum_get_uint(merge_intn)); yasm_section_set_align(retval, align, line); - } else if (flags_override) + } else if (flags_override && !data.gasflags) yasm_warn_set(YASM_WARN_GENERAL, N_("section flags ignored on section redeclaration")); + if (merge_expr) + yasm_expr_destroy(merge_expr); return retval; } @@ -1108,12 +1147,13 @@ static void dir_type(yasm_object *object, yasm_valparamhead *valparams, yasm_valparamhead *objext_valparams, unsigned long line) { - yasm_valparam *vp = yasm_vps_first(valparams); yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt; - char *symname = vp->val; + yasm_valparam *vp = yasm_vps_first(valparams); + const char *symname = yasm_vp_id(vp); /* Get symbol elf data */ yasm_symrec *sym = yasm_symtab_use(object->symtab, symname, line); elf_symtab_entry *entry = yasm_symrec_get_data(sym, &elf_symrec_data); + /*@null@*/ const char *type; /* Create entry if necessary */ if (!entry) { @@ -1122,16 +1162,16 @@ dir_type(yasm_object *object, yasm_valparamhead *valparams, yasm_symrec_add_data(sym, &elf_symrec_data, entry); } - /* Pull new type from val */ + /* Pull new type from param */ vp = yasm_vps_next(vp); - if (vp && vp->val) { - if (yasm__strcasecmp(vp->val, "function") == 0) + if (vp && !vp->val && (type = yasm_vp_id(vp))) { + if (yasm__strcasecmp(type, "function") == 0) elf_sym_set_type(entry, STT_FUNC); - else if (yasm__strcasecmp(vp->val, "object") == 0) + else if (yasm__strcasecmp(type, "object") == 0) elf_sym_set_type(entry, STT_OBJECT); else yasm_warn_set(YASM_WARN_GENERAL, - N_("unrecognized symbol type `%s'"), vp->val); + N_("unrecognized symbol type `%s'"), type); } else yasm_error_set(YASM_ERROR_SYNTAX, N_("no type specified")); } @@ -1140,12 +1180,13 @@ static void dir_size(yasm_object *object, yasm_valparamhead *valparams, yasm_valparamhead *objext_valparams, unsigned long line) { - yasm_valparam *vp = yasm_vps_first(valparams); yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt; - char *symname = vp->val; + yasm_valparam *vp = yasm_vps_first(valparams); + const char *symname = yasm_vp_id(vp); /* Get symbol elf data */ yasm_symrec *sym = yasm_symtab_use(object->symtab, symname, line); elf_symtab_entry *entry = yasm_symrec_get_data(sym, &elf_symrec_data); + /*@only@*/ /*@null@*/ yasm_expr *size; /* Create entry if necessary */ if (!entry) { @@ -1154,14 +1195,10 @@ dir_size(yasm_object *object, yasm_valparamhead *valparams, yasm_symrec_add_data(sym, &elf_symrec_data, entry); } - /* Pull new size from either param (expr) or val */ + /* Pull new size from param */ vp = yasm_vps_next(vp); - if (vp && vp->param) { - elf_sym_set_size(entry, vp->param); - vp->param = NULL; - } else if (vp && vp->val) - elf_sym_set_size(entry, yasm_expr_create_ident(yasm_expr_sym( - yasm_symtab_use(object->symtab, vp->val, line)), line)); + if (vp && !vp->val && (size = yasm_vp_expr(vp, object->symtab, line))) + elf_sym_set_size(entry, size); else yasm_error_set(YASM_ERROR_SYNTAX, N_("no size specified")); } @@ -1170,9 +1207,9 @@ static void dir_weak(yasm_object *object, yasm_valparamhead *valparams, yasm_valparamhead *objext_valparams, unsigned long line) { - yasm_valparam *vp = yasm_vps_first(valparams); yasm_objfmt_elf *objfmt_elf = (yasm_objfmt_elf *)object->objfmt; - char *symname = vp->val; + yasm_valparam *vp = yasm_vps_first(valparams); + const char *symname = yasm_vp_id(vp); yasm_symrec *sym = yasm_symtab_declare(object->symtab, symname, YASM_SYM_GLOBAL, line); elf_objfmt_symtab_append(objfmt_elf, sym, SHN_UNDEF, STB_WEAK, 0, @@ -1186,12 +1223,19 @@ dir_ident(yasm_object *object, yasm_valparamhead *valparams, yasm_valparamhead sect_vps; yasm_datavalhead dvs; yasm_section *comment; - yasm_valparam *vp = yasm_vps_first(valparams); + yasm_valparam *vp; yasm_valparam *vp2; + /* Accept, but do nothing with empty ident */ + if (!valparams) + return; + vp = yasm_vps_first(valparams); + if (!vp) + return; + /* Put ident data into .comment section */ yasm_vps_initialize(§_vps); - vp2 = yasm_vp_create(yasm__xstrdup(".comment"), NULL); + vp2 = yasm_vp_create_string(NULL, yasm__xstrdup(".comment")); yasm_vps_append(§_vps, vp2); comment = elf_objfmt_section_switch(object, §_vps, NULL, line); yasm_vps_delete(§_vps); @@ -1210,8 +1254,15 @@ dir_ident(yasm_object *object, yasm_valparamhead *valparams, yasm_dvs_initialize(&dvs); do { - yasm_dvs_append(&dvs, yasm_dv_create_string(vp->val, strlen(vp->val))); - vp->val = NULL; + const char *s = yasm_vp_string(vp); + if (!s) { + yasm_error_set(YASM_ERROR_VALUE, + N_(".comment requires string parameters")); + yasm_dvs_delete(&dvs); + return; + } + yasm_dvs_append(&dvs, + yasm_dv_create_string(yasm__xstrdup(s), strlen(s))); } while ((vp = yasm_vps_next(vp))); yasm_section_bcs_append(comment, @@ -1230,11 +1281,11 @@ static const yasm_directive elf_objfmt_directives[] = { { ".type", "gas", dir_type, YASM_DIR_ID_REQUIRED }, { ".size", "gas", dir_size, YASM_DIR_ID_REQUIRED }, { ".weak", "gas", dir_weak, YASM_DIR_ID_REQUIRED }, - { ".ident", "gas", dir_ident, YASM_DIR_ARG_REQUIRED }, + { ".ident", "gas", dir_ident, YASM_DIR_ANY }, { "type", "nasm", dir_type, YASM_DIR_ID_REQUIRED }, { "size", "nasm", dir_size, YASM_DIR_ID_REQUIRED }, { "weak", "nasm", dir_weak, YASM_DIR_ID_REQUIRED }, - { "ident", "nasm", dir_ident, YASM_DIR_ARG_REQUIRED }, + { "ident", "nasm", dir_ident, YASM_DIR_ANY }, { NULL, NULL, NULL, 0 } }; diff --git a/modules/objfmts/macho/macho-objfmt.c b/modules/objfmts/macho/macho-objfmt.c index 70f463ba..109c3f91 100644 --- a/modules/objfmts/macho/macho-objfmt.c +++ b/modules/objfmts/macho/macho-objfmt.c @@ -1288,14 +1288,14 @@ macho_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams, yasm_valparamhead *objext_valparams, unsigned long line) { - yasm_valparam *vp = yasm_vps_first(valparams); + yasm_valparam *vp; yasm_section *retval; int isnew; const char *f_segname, *f_sectname; unsigned long flags; unsigned long align; int flags_override = 0; - char *sectname; + const char *sectname; int resonly = 0; macho_section_data *msd; size_t i; @@ -1365,10 +1365,22 @@ macho_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams, S_ATTR_NO_DEAD_STRIP, 0} }; - if (!vp || vp->param || !vp->val) - return NULL; + struct macho_section_switch_data { + /*@only@*/ /*@null@*/ yasm_intnum *align_intn; + } data; + + static const yasm_dir_help help[] = { + { "align", 1, yasm_dir_helper_intn, + offsetof(struct macho_section_switch_data, align_intn), 0 } + }; - sectname = vp->val; + data.align_intn = NULL; + + vp = yasm_vps_first(valparams); + sectname = yasm_vp_string(vp); + if (!sectname) + return NULL; + vp = yasm_vps_next(vp); /* translate .text,.data,.bss to __text,__data,__bss... */ for (i=0; ival) { - yasm_warn_set(YASM_WARN_GENERAL, - N_("Unrecognized numeric qualifier")); - continue; + flags_override = yasm_dir_helper(object, vp, line, help, NELEMS(help), + &data, yasm_dir_helper_valparam_warn); + if (flags_override < 0) + return NULL; /* error occurred */ + + if (data.align_intn) { + align = yasm_intnum_get_uint(data.align_intn); + yasm_intnum_destroy(data.align_intn); + + /* Alignments must be a power of two. */ + if (!is_exp2(align)) { + yasm_error_set(YASM_ERROR_VALUE, + N_("argument to `%s' is not a power of two"), + vp->val); + return NULL; } - flags_override = 1; - if (yasm__strcasecmp(vp->val, "align") == 0 && vp->param) { - /*@dependent@ *//*@null@ */ const yasm_intnum *align_expr; - - align_expr = yasm_expr_get_intnum(&vp->param, 0); - if (!align_expr) { - yasm_error_set(YASM_ERROR_VALUE, - N_("argument to `%s' is not an integer"), - vp->val); - return NULL; - } - align = yasm_intnum_get_uint(align_expr); - - /* Alignments must be a power of two. */ - if (!is_exp2(align)) { - yasm_error_set(YASM_ERROR_VALUE, - N_("argument to `%s' is not a power of two"), - vp->val); - return NULL; - } - - /* Check to see if alignment is supported size */ - if (align > 16384) { - yasm_error_set(YASM_ERROR_VALUE, - N_("macho implementation does not support alignments > 16384")); - return NULL; - } - } else - yasm_warn_set(YASM_WARN_GENERAL, - N_("Unrecognized qualifier `%s'"), vp->val); + /* Check to see if alignment is supported size */ + if (align > 16384) { + yasm_error_set(YASM_ERROR_VALUE, + N_("macho implementation does not support alignments > 16384")); + return NULL; + } } retval = yasm_object_get_general(object, sectname, 0, align, 1, resonly, diff --git a/modules/objfmts/rdf/rdf-objfmt.c b/modules/objfmts/rdf/rdf-objfmt.c index aa583a5b..124f2560 100644 --- a/modules/objfmts/rdf/rdf-objfmt.c +++ b/modules/objfmts/rdf/rdf-objfmt.c @@ -463,68 +463,57 @@ rdf_objfmt_output_section_file(yasm_section *sect, /*@null@*/ void *d) return 0; } +#define FLAG_EXT 0x1000 +#define FLAG_GLOB 0x2000 +#define FLAG_SET 0x4000 +#define FLAG_CLR 0x8000 +#define FLAG_MASK 0x0fff + +static int +rdf_helper_flag(void *obj, yasm_valparam *vp, unsigned long line, void *d, + uintptr_t flag) +{ + yasm_symrec *sym = (yasm_symrec *)obj; + yasm_sym_vis vis = yasm_symrec_get_visibility(sym); + unsigned int *flags = (unsigned int *)d; + + if (((vis & YASM_SYM_GLOBAL) && (flag & FLAG_GLOB)) || + ((vis & YASM_SYM_EXTERN) && (flag & FLAG_EXT))) { + if (flag & FLAG_SET) + *flags |= flag & FLAG_MASK; + else if (flag & FLAG_CLR) + *flags &= ~(flag & FLAG_MASK); + } + return 0; +} + static unsigned int rdf_parse_flags(yasm_symrec *sym) { - yasm_sym_vis vis = yasm_symrec_get_visibility(sym); /*@dependent@*/ /*@null@*/ yasm_valparamhead *objext_valparams = yasm_symrec_get_objext_valparams(sym); - yasm_valparam *vp; unsigned int flags = 0; - static const struct { - enum { - FLAG_EXT = 1, - FLAG_GLOB = 2 - } type; - enum { - FLAG_SET = 1, - FLAG_CLR = 2 - } action; - const char *name; - unsigned int flags; - } flagtbl[] = { - { FLAG_EXT|FLAG_GLOB, FLAG_SET, "data", SYM_DATA }, - { FLAG_EXT|FLAG_GLOB, FLAG_SET, "object", SYM_DATA }, - { FLAG_EXT|FLAG_GLOB, FLAG_SET, "proc", SYM_FUNCTION }, - { FLAG_EXT|FLAG_GLOB, FLAG_SET, "function", SYM_FUNCTION }, - { FLAG_EXT, FLAG_SET, "import", SYM_IMPORT }, - { FLAG_GLOB, FLAG_SET, "export", SYM_GLOBAL }, - { FLAG_EXT, FLAG_SET, "far", SYM_FAR }, - { FLAG_EXT, FLAG_CLR, "near", SYM_FAR }, + static const yasm_dir_help help[] = { + { "data", 0, rdf_helper_flag, 0, + FLAG_EXT|FLAG_GLOB|FLAG_SET|SYM_DATA }, + { "object", 0, rdf_helper_flag, 0, + FLAG_EXT|FLAG_GLOB|FLAG_SET|SYM_DATA }, + { "proc", 0, rdf_helper_flag, 0, + FLAG_EXT|FLAG_GLOB|FLAG_SET|SYM_FUNCTION }, + { "function", 0, rdf_helper_flag, 0, + FLAG_EXT|FLAG_GLOB|FLAG_SET|SYM_FUNCTION }, + { "import", 0, rdf_helper_flag, 0, FLAG_EXT|FLAG_SET|SYM_IMPORT }, + { "export", 0, rdf_helper_flag, 0, FLAG_GLOB|FLAG_SET|SYM_GLOBAL }, + { "far", 0, rdf_helper_flag, 0, FLAG_EXT|FLAG_SET|SYM_FAR }, + { "near", 0, rdf_helper_flag, 0, FLAG_EXT|FLAG_CLR|SYM_FAR } }; if (!objext_valparams) return 0; - vp = yasm_vps_first(objext_valparams); - for (; vp; vp = yasm_vps_next(vp)) { - size_t i; - int match; - - if (!vp->val) { - yasm_warn_set(YASM_WARN_GENERAL, - N_("Unrecognized numeric qualifier")); - continue; - } - - match = 0; - for (i=0; ival, flagtbl[i].name) == 0) { - if (flagtbl[i].action == FLAG_SET) - flags |= flagtbl[i].flags; - else if (flagtbl[i].action == FLAG_CLR) - flags &= ~flagtbl[i].flags; - match = 1; - } - } - - if (!match) - yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized qualifier `%s'"), - vp->val); - } + yasm_dir_helper(sym, yasm_vps_first(objext_valparams), 0, help, + NELEMS(help), &flags, yasm_dir_helper_valparam_warn); return flags; } @@ -620,16 +609,25 @@ rdf_objfmt_output_sym(yasm_symrec *sym, /*@null@*/ void *d) if (objext_valparams) { yasm_valparam *vp = yasm_vps_first(objext_valparams); for (; vp; vp = yasm_vps_next(vp)) { - if (!vp->val && vp->param) { - /*@null@*/ const yasm_intnum *align_expr; - - align_expr = yasm_expr_get_intnum(&vp->param, 0); - if (!align_expr) { + if (!vp->val) { + /*@only@*/ /*@null@*/ yasm_expr *align_expr; + /*@dependent@*/ /*@null@*/ + const yasm_intnum *align_intn; + + if (!(align_expr = yasm_vp_expr(vp, + info->object->symtab, + yasm_symrec_get_decl_line(sym))) || + !(align_intn = yasm_expr_get_intnum(&align_expr, + 0))) { yasm_error_set(YASM_ERROR_VALUE, - N_("alignment constraint is not an integer")); + N_("argument to `%s' is not an integer"), + vp->val); + if (align_expr) + yasm_expr_destroy(align_expr); continue; } - addralign = yasm_intnum_get_uint(align_expr); + addralign = yasm_intnum_get_uint(align_intn); + yasm_expr_destroy(align_expr); /* Alignments must be a power of two. */ if (!is_exp2(addralign)) { @@ -637,7 +635,7 @@ rdf_objfmt_output_sym(yasm_symrec *sym, /*@null@*/ void *d) N_("alignment constraint is not a power of two")); continue; } - } else if (vp->val) + } else yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized qualifier `%s'"), vp->val); } @@ -854,6 +852,32 @@ rdf_objfmt_add_default_section(yasm_object *object) return retval; } +static int +rdf_helper_set_type(void *obj, yasm_valparam *vp, unsigned long line, + void *d, uintptr_t newtype) +{ + unsigned int *type = (unsigned int *)d; + *type = newtype; + return 0; +} + +struct rdf_section_switch_data { + /*@only@*/ /*@null@*/ yasm_intnum *reserved_intn; + unsigned int type; +}; + +static int +rdf_helper_set_reserved(void *obj, yasm_valparam *vp, unsigned long line, + void *d) +{ + struct rdf_section_switch_data *data = (struct rdf_section_switch_data *)d; + + if (!vp->val && vp->type == YASM_PARAM_EXPR) + return yasm_dir_helper_intn(obj, vp, line, &data->reserved_intn, 0); + else + return yasm_dir_helper_valparam_warn(obj, vp, line, d); +} + static /*@observer@*/ /*@null@*/ yasm_section * rdf_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams, /*@unused@*/ /*@null@*/ @@ -863,85 +887,70 @@ rdf_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams, yasm_valparam *vp = yasm_vps_first(valparams); yasm_section *retval; int isnew; - unsigned int type = 0xffff; unsigned int reserved = 0; int flags_override = 0; - char *sectname; + const char *sectname; rdf_section_data *rsd; - static const struct { - const char *name; - unsigned int type; - } typenames[] = { - { "bss", RDF_SECT_BSS }, - { "code", RDF_SECT_CODE }, - { "text", RDF_SECT_CODE }, - { "data", RDF_SECT_DATA }, - { "comment", RDF_SECT_COMMENT }, - { "lcomment", RDF_SECT_LCOMMENT }, - { "pcomment", RDF_SECT_PCOMMENT }, - { "symdebug", RDF_SECT_SYMDEBUG }, - { "linedebug", RDF_SECT_LINEDEBUG }, + struct rdf_section_switch_data data; + + static const yasm_dir_help help[] = { + { "bss", 0, rdf_helper_set_type, + offsetof(struct rdf_section_switch_data, type), RDF_SECT_BSS }, + { "code", 0, rdf_helper_set_type, + offsetof(struct rdf_section_switch_data, type), RDF_SECT_CODE }, + { "text", 0, rdf_helper_set_type, + offsetof(struct rdf_section_switch_data, type), RDF_SECT_CODE }, + { "data", 0, rdf_helper_set_type, + offsetof(struct rdf_section_switch_data, type), RDF_SECT_DATA }, + { "comment", 0, rdf_helper_set_type, + offsetof(struct rdf_section_switch_data, type), RDF_SECT_COMMENT }, + { "lcomment", 0, rdf_helper_set_type, + offsetof(struct rdf_section_switch_data, type), RDF_SECT_LCOMMENT }, + { "pcomment", 0, rdf_helper_set_type, + offsetof(struct rdf_section_switch_data, type), RDF_SECT_PCOMMENT }, + { "symdebug", 0, rdf_helper_set_type, + offsetof(struct rdf_section_switch_data, type), RDF_SECT_SYMDEBUG }, + { "linedebug", 0, rdf_helper_set_type, + offsetof(struct rdf_section_switch_data, type), RDF_SECT_LINEDEBUG }, + { "reserved", 1, yasm_dir_helper_intn, + offsetof(struct rdf_section_switch_data, reserved_intn), 0 } }; - if (!vp || vp->param || !vp->val) - return NULL; + data.reserved_intn = NULL; + data.type = 0xffff; - sectname = vp->val; + vp = yasm_vps_first(valparams); + sectname = yasm_vp_string(vp); + if (!sectname) + return NULL; + vp = yasm_vps_next(vp); if (strcmp(sectname, ".text") == 0) - type = RDF_SECT_CODE; + data.type = RDF_SECT_CODE; else if (strcmp(sectname, ".data") == 0) - type = RDF_SECT_DATA; + data.type = RDF_SECT_DATA; else if (strcmp(sectname, ".bss") == 0) - type = RDF_SECT_BSS; - - /* Look for section type */ - if ((vp = yasm_vps_next(vp))) { - size_t i; - int match; - if (vp->val) { - match = 0; - for (i=0; ival, typenames[i].name) == 0) { - type = typenames[i].type; - flags_override = 1; - match = 1; - } - } - if (!match) - yasm_warn_set(YASM_WARN_GENERAL, - N_("Unrecognized RDF segment type `%s'"), - vp->val); - } else - yasm_warn_set(YASM_WARN_GENERAL, - N_("Unrecognized numeric qualifier")); - } + data.type = RDF_SECT_BSS; + + flags_override = yasm_dir_helper(object, vp, line, help, NELEMS(help), + &data, rdf_helper_set_reserved); + if (flags_override < 0) + return NULL; /* error occurred */ - if (type == 0xffff) { + if (data.type == 0xffff) { yasm_error_set(YASM_ERROR_VALUE, N_("new segment declared without type code")); - type = RDF_SECT_DATA; + data.type = RDF_SECT_DATA; } - /* Look for reserved value */ - if (vp && (vp = yasm_vps_next(vp))) { - if (!vp->val && vp->param) { - /*@dependent@*/ /*@null@*/ const yasm_intnum *reserved_expr; - - reserved_expr = yasm_expr_get_intnum(&vp->param, 0); - if (!reserved_expr) - yasm_error_set(YASM_ERROR_VALUE, - N_("reserved value must be numeric")); - else - reserved = yasm_intnum_get_uint(reserved_expr); - } else if (vp->val) - yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized qualifier `%s'"), - vp->val); + if (data.reserved_intn) { + reserved = yasm_intnum_get_uint(data.reserved_intn); + yasm_intnum_destroy(data.reserved_intn); } retval = yasm_object_get_general(object, sectname, 0, 0, 1, - type == RDF_SECT_BSS, &isnew, line); + data.type == RDF_SECT_BSS, &isnew, line); if (isnew) rsd = rdf_objfmt_init_new_section(object, retval, sectname, line); @@ -950,7 +959,7 @@ rdf_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams, if (isnew || yasm_section_is_default(retval)) { yasm_section_set_default(retval, 0); - rsd->type = type; + rsd->type = data.type; rsd->reserved = reserved; } else if (flags_override) yasm_warn_set(YASM_WARN_GENERAL, @@ -1021,8 +1030,7 @@ dir_library(yasm_object *object, yasm_valparamhead *valparams, yasm_valparamhead *objext_valparams, unsigned long line) { yasm_valparam *vp = yasm_vps_first(valparams); - rdf_objfmt_add_libmodule(object, vp->val, 1); - vp->val = NULL; /* don't free it */ + rdf_objfmt_add_libmodule(object, yasm__xstrdup(yasm_vp_string(vp)), 1); } static void @@ -1030,8 +1038,7 @@ dir_module(yasm_object *object, yasm_valparamhead *valparams, yasm_valparamhead *objext_valparams, unsigned long line) { yasm_valparam *vp = yasm_vps_first(valparams); - rdf_objfmt_add_libmodule(object, vp->val, 0); - vp->val = NULL; /* don't free it */ + rdf_objfmt_add_libmodule(object, yasm__xstrdup(yasm_vp_string(vp)), 0); } /* Define valid debug formats to use with this object format */ @@ -1041,8 +1048,8 @@ static const char *rdf_objfmt_dbgfmt_keywords[] = { }; static const yasm_directive rdf_objfmt_directives[] = { - { "library", "nasm", dir_library, YASM_DIR_ID_REQUIRED }, - { "module", "nasm", dir_module, YASM_DIR_ID_REQUIRED }, + { "library", "nasm", dir_library, YASM_DIR_ARG_REQUIRED }, + { "module", "nasm", dir_module, YASM_DIR_ARG_REQUIRED }, { NULL, NULL, NULL, 0 } }; diff --git a/modules/objfmts/rdf/tests/rdfext.asm b/modules/objfmts/rdf/tests/rdfext.asm index 1239c4dd..8bf5ea0f 100644 --- a/modules/objfmts/rdf/tests/rdfext.asm +++ b/modules/objfmts/rdf/tests/rdfext.asm @@ -1,5 +1,5 @@ module thismodule -module "$thismodule" +module $thismodule global foo:export global bar:export proc global bar2:export function diff --git a/modules/objfmts/xdf/tests/Makefile.inc b/modules/objfmts/xdf/tests/Makefile.inc index 4b430e80..7bd402dc 100644 --- a/modules/objfmts/xdf/tests/Makefile.inc +++ b/modules/objfmts/xdf/tests/Makefile.inc @@ -12,5 +12,9 @@ EXTRA_DIST += modules/objfmts/xdf/tests/xdfother.asm EXTRA_DIST += modules/objfmts/xdf/tests/xdfother.hex EXTRA_DIST += modules/objfmts/xdf/tests/xdfprotect.asm EXTRA_DIST += modules/objfmts/xdf/tests/xdfprotect.hex +EXTRA_DIST += modules/objfmts/xdf/tests/xdfsect.asm +EXTRA_DIST += modules/objfmts/xdf/tests/xdfsect.hex +EXTRA_DIST += modules/objfmts/xdf/tests/xdfsect-err.asm +EXTRA_DIST += modules/objfmts/xdf/tests/xdfsect-err.errwarn EXTRA_DIST += modules/objfmts/xdf/tests/xdfvirtual.asm EXTRA_DIST += modules/objfmts/xdf/tests/xdfvirtual.hex diff --git a/modules/objfmts/xdf/tests/xdfsect-err.asm b/modules/objfmts/xdf/tests/xdfsect-err.asm new file mode 100644 index 00000000..cca409a4 --- /dev/null +++ b/modules/objfmts/xdf/tests/xdfsect-err.asm @@ -0,0 +1,18 @@ +[section] +section 1 use16=5 +section 2 use32=5 +section 3 use64=5 +section 4 bss=5 +section 5 flat=5 +section 6 foo +section 7 foo=5 +section 8 absolute=foo +section 9 absolute="foo" +section 10 absolute +section 11 virtual=foo +section 12 virtual="foo" +section 13 virtual +section 14 align=foo +section 15 align="foo" +section 16 align +section 17 "bar" diff --git a/modules/objfmts/xdf/tests/xdfsect-err.errwarn b/modules/objfmts/xdf/tests/xdfsect-err.errwarn new file mode 100644 index 00000000..4a9d5b3a --- /dev/null +++ b/modules/objfmts/xdf/tests/xdfsect-err.errwarn @@ -0,0 +1,20 @@ +-:1: directive `section' requires an argument +-:2: warning: Unrecognized qualifier `use16' +-:3: warning: Unrecognized qualifier `use32' +-:4: warning: Unrecognized qualifier `use64' +-:5: warning: Unrecognized qualifier `bss' +-:6: warning: Unrecognized qualifier `flat' +-:7: warning: Unrecognized qualifier `foo' +-:8: warning: Unrecognized qualifier `foo' +-:9: argument to `absolute' is not an integer +-:9: undefined symbol `foo' (first use) +-:9: (Each undefined symbol is reported only once.) +-:10: argument to `absolute' is not an integer +-:11: warning: Unrecognized qualifier `absolute' +-:12: argument to `virtual' is not an integer +-:13: argument to `virtual' is not an integer +-:14: warning: Unrecognized qualifier `virtual' +-:15: argument to `align' is not an integer +-:16: argument to `align' is not an integer +-:17: warning: Unrecognized qualifier `align' +-:18: warning: Unrecognized string qualifier diff --git a/modules/objfmts/xdf/tests/xdfsect.asm b/modules/objfmts/xdf/tests/xdfsect.asm new file mode 100644 index 00000000..8d20155e --- /dev/null +++ b/modules/objfmts/xdf/tests/xdfsect.asm @@ -0,0 +1,13 @@ +section 1 +section 2 use16 +section 3 use32 +section 4 use64 +section 5 bss +section 6 flat +section 7 use16 flat +section 8 use32 bss +section 9 use64 absolute=0x5555 flat +section 10 flat virtual=0x1111 absolute=0x2222 +section 11 use32 align=4 +section 12 use16 absolute=0x1111 virtual=0x2222 align=4 flat bss +section 13 use16 use32 use64 diff --git a/modules/objfmts/xdf/tests/xdfsect.hex b/modules/objfmts/xdf/tests/xdfsect.hex new file mode 100644 index 00000000..4f0c0c1c --- /dev/null +++ b/modules/objfmts/xdf/tests/xdfsect.hex @@ -0,0 +1,836 @@ +22 +43 +65 +87 +0e +00 +00 +00 +0e +00 +00 +00 +34 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +02 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +10 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +20 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +04 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +40 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +05 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +04 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +06 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +02 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +07 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +12 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +08 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +24 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +09 +00 +00 +00 +55 +55 +00 +00 +00 +00 +00 +00 +55 +55 +00 +00 +00 +00 +00 +00 +00 +00 +43 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +0a +00 +00 +00 +22 +22 +00 +00 +00 +00 +00 +00 +11 +11 +00 +00 +00 +00 +00 +00 +00 +00 +03 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +0b +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +04 +00 +20 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +0c +00 +00 +00 +11 +11 +00 +00 +00 +00 +00 +00 +22 +22 +00 +00 +00 +00 +00 +00 +04 +00 +17 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +0d +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +40 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +20 +03 +00 +00 +00 +00 +00 +00 +01 +00 +00 +00 +00 +00 +00 +00 +26 +03 +00 +00 +00 +00 +00 +00 +02 +00 +00 +00 +00 +00 +00 +00 +28 +03 +00 +00 +00 +00 +00 +00 +03 +00 +00 +00 +00 +00 +00 +00 +2a +03 +00 +00 +00 +00 +00 +00 +04 +00 +00 +00 +00 +00 +00 +00 +2c +03 +00 +00 +00 +00 +00 +00 +05 +00 +00 +00 +00 +00 +00 +00 +2e +03 +00 +00 +00 +00 +00 +00 +06 +00 +00 +00 +00 +00 +00 +00 +30 +03 +00 +00 +00 +00 +00 +00 +07 +00 +00 +00 +00 +00 +00 +00 +32 +03 +00 +00 +00 +00 +00 +00 +08 +00 +00 +00 +00 +00 +00 +00 +34 +03 +00 +00 +00 +00 +00 +00 +09 +00 +00 +00 +00 +00 +00 +00 +36 +03 +00 +00 +00 +00 +00 +00 +0a +00 +00 +00 +00 +00 +00 +00 +38 +03 +00 +00 +00 +00 +00 +00 +0b +00 +00 +00 +00 +00 +00 +00 +3b +03 +00 +00 +00 +00 +00 +00 +0c +00 +00 +00 +00 +00 +00 +00 +3e +03 +00 +00 +00 +00 +00 +00 +0d +00 +00 +00 +00 +00 +00 +00 +41 +03 +00 +00 +00 +00 +00 +00 +2e +74 +65 +78 +74 +00 +31 +00 +32 +00 +33 +00 +34 +00 +35 +00 +36 +00 +37 +00 +38 +00 +39 +00 +31 +30 +00 +31 +31 +00 +31 +32 +00 +31 +33 +00 diff --git a/modules/objfmts/xdf/xdf-objfmt.c b/modules/objfmts/xdf/xdf-objfmt.c index 5c23c4ed..84e0e314 100644 --- a/modules/objfmts/xdf/xdf-objfmt.c +++ b/modules/objfmts/xdf/xdf-objfmt.c @@ -645,99 +645,107 @@ xdf_objfmt_add_default_section(yasm_object *object) return retval; } +static int +xdf_helper_use(void *obj, yasm_valparam *vp, unsigned long line, void *d, + uintptr_t bits) +{ + yasm_object *object = (yasm_object *)obj; + unsigned long *flags = (unsigned long *)d; + *flags &= ~(XDF_SECT_USE_16|XDF_SECT_USE_32|XDF_SECT_USE_64); + switch (bits) { + case 16: *flags |= XDF_SECT_USE_16; break; + case 32: *flags |= XDF_SECT_USE_32; break; + case 64: *flags |= XDF_SECT_USE_64; break; + }; + yasm_arch_set_var(object->arch, "mode_bits", bits); + return 0; +} + static /*@observer@*/ /*@null@*/ yasm_section * xdf_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams, /*@unused@*/ /*@null@*/ yasm_valparamhead *objext_valparams, unsigned long line) { - yasm_valparam *vp = yasm_vps_first(valparams); + yasm_valparam *vp; yasm_section *retval; int isnew; - /*@dependent@*/ /*@null@*/ const yasm_intnum *absaddr = NULL; - /*@dependent@*/ /*@null@*/ const yasm_intnum *vaddr = NULL; - unsigned long align = 0; - unsigned long flags = 0; int flags_override = 0; - char *sectname; + const char *sectname; int resonly = 0; xdf_section_data *xsd; + unsigned long align = 0; - if (!vp || vp->param || !vp->val) + struct xdf_section_switch_data { + /*@only@*/ /*@null@*/ yasm_intnum *absaddr; + /*@only@*/ /*@null@*/ yasm_intnum *vaddr; + /*@only@*/ /*@null@*/ yasm_intnum *align_intn; + unsigned long flags; + } data; + + static const yasm_dir_help help[] = { + { "use16", 0, xdf_helper_use, + offsetof(struct xdf_section_switch_data, flags), 16 }, + { "use32", 0, xdf_helper_use, + offsetof(struct xdf_section_switch_data, flags), 32 }, + { "use64", 0, xdf_helper_use, + offsetof(struct xdf_section_switch_data, flags), 64 }, + { "bss", 0, yasm_dir_helper_flag_or, + offsetof(struct xdf_section_switch_data, flags), XDF_SECT_BSS }, + { "flat", 0, yasm_dir_helper_flag_or, + offsetof(struct xdf_section_switch_data, flags), XDF_SECT_FLAT }, + { "absolute", 1, yasm_dir_helper_intn, + offsetof(struct xdf_section_switch_data, absaddr), 0 }, + { "virtual", 1, yasm_dir_helper_intn, + offsetof(struct xdf_section_switch_data, vaddr), 0 }, + { "align", 1, yasm_dir_helper_intn, + offsetof(struct xdf_section_switch_data, align_intn), 0 } + }; + + data.absaddr = NULL; + data.vaddr = NULL; + data.align_intn = NULL; + data.flags = 0; + + vp = yasm_vps_first(valparams); + sectname = yasm_vp_string(vp); + if (!sectname) return NULL; - - sectname = vp->val; - - while ((vp = yasm_vps_next(vp))) { - if (!vp->val) { - yasm_warn_set(YASM_WARN_GENERAL, - N_("Unrecognized numeric qualifier")); - continue; + vp = yasm_vps_next(vp); + + flags_override = yasm_dir_helper(object, vp, line, help, NELEMS(help), + &data, yasm_dir_helper_valparam_warn); + if (flags_override < 0) + return NULL; /* error occurred */ + + if (data.absaddr) + data.flags |= XDF_SECT_ABSOLUTE; + if (data.align_intn) { + align = yasm_intnum_get_uint(data.align_intn); + yasm_intnum_destroy(data.align_intn); + + /* Alignments must be a power of two. */ + if (!is_exp2(align)) { + yasm_error_set(YASM_ERROR_VALUE, + N_("argument to `%s' is not a power of two"), + "align"); + if (data.vaddr) + yasm_intnum_destroy(data.vaddr); + if (data.absaddr) + yasm_intnum_destroy(data.absaddr); + return NULL; } - flags_override = 1; - if (yasm__strcasecmp(vp->val, "use16") == 0) { - flags &= ~(XDF_SECT_USE_32|XDF_SECT_USE_64); - flags |= XDF_SECT_USE_16; - yasm_arch_set_var(object->arch, "mode_bits", 16); - } else if (yasm__strcasecmp(vp->val, "use32") == 0) { - flags &= ~(XDF_SECT_USE_16|XDF_SECT_USE_64); - flags |= XDF_SECT_USE_32; - yasm_arch_set_var(object->arch, "mode_bits", 32); - } else if (yasm__strcasecmp(vp->val, "use64") == 0) { - flags &= ~(XDF_SECT_USE_16|XDF_SECT_USE_32); - flags |= XDF_SECT_USE_64; - yasm_arch_set_var(object->arch, "mode_bits", 64); - } else if (yasm__strcasecmp(vp->val, "bss") == 0) { - flags |= XDF_SECT_BSS; - } else if (yasm__strcasecmp(vp->val, "flat") == 0) { - flags |= XDF_SECT_FLAT; - } else if (yasm__strcasecmp(vp->val, "absolute") == 0 && vp->param) { - flags |= XDF_SECT_ABSOLUTE; - absaddr = yasm_expr_get_intnum(&vp->param, 0); - if (!absaddr) { - yasm_error_set(YASM_ERROR_NOT_CONSTANT, - N_("argument to `%s' is not an integer"), - vp->val); - return NULL; - } - } else if (yasm__strcasecmp(vp->val, "virtual") == 0 && vp->param) { - vaddr = yasm_expr_get_intnum(&vp->param, 0); - if (!vaddr) { - yasm_error_set(YASM_ERROR_NOT_CONSTANT, - N_("argument to `%s' is not an integer"), - vp->val); - return NULL; - } - } else if (yasm__strcasecmp(vp->val, "align") == 0 && vp->param) { - /*@dependent@*/ /*@null@*/ const yasm_intnum *align_expr; - - align_expr = yasm_expr_get_intnum(&vp->param, 0); - if (!align_expr) { - yasm_error_set(YASM_ERROR_VALUE, - N_("argument to `%s' is not an integer"), - vp->val); - return NULL; - } - align = yasm_intnum_get_uint(align_expr); - - /* Alignments must be a power of two. */ - if (!is_exp2(align)) { - yasm_error_set(YASM_ERROR_VALUE, - N_("argument to `%s' is not a power of two"), - vp->val); - return NULL; - } - - /* Check to see if alignment is supported size */ - if (align > 4096) { - yasm_error_set(YASM_ERROR_VALUE, - N_("XDF does not support alignments > 4096")); - return NULL; - } - } else - yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized qualifier `%s'"), - vp->val); + /* Check to see if alignment is supported size */ + if (align > 4096) { + yasm_error_set(YASM_ERROR_VALUE, + N_("XDF does not support alignments > 4096")); + if (data.vaddr) + yasm_intnum_destroy(data.vaddr); + if (data.absaddr) + yasm_intnum_destroy(data.absaddr); + return NULL; + } } retval = yasm_object_get_general(object, sectname, 0, align, 1, resonly, @@ -750,16 +758,16 @@ xdf_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams, if (isnew || yasm_section_is_default(retval)) { yasm_section_set_default(retval, 0); - xsd->flags = flags; - if (absaddr) { + xsd->flags = data.flags; + if (data.absaddr) { if (xsd->addr) yasm_intnum_destroy(xsd->addr); - xsd->addr = yasm_intnum_copy(absaddr); + xsd->addr = data.absaddr; } - if (vaddr) { + if (data.vaddr) { if (xsd->vaddr) yasm_intnum_destroy(xsd->vaddr); - xsd->vaddr = yasm_intnum_copy(vaddr); + xsd->vaddr = data.vaddr; } yasm_section_set_align(retval, align, line); } else if (flags_override) diff --git a/modules/parsers/gas/gas-parse.c b/modules/parsers/gas/gas-parse.c index 45b36c32..702b47dd 100644 --- a/modules/parsers/gas/gas-parse.c +++ b/modules/parsers/gas/gas-parse.c @@ -439,7 +439,7 @@ parse_line(yasm_parser_gas *parser_gas) } else if (align) { /* Give third parameter as objext valparam */ yasm_valparamhead *extvps = yasm_vps_create(); - vp = yasm_vp_create(NULL, align); + vp = yasm_vp_create_expr(NULL, align); yasm_vps_append(extvps, vp); sym = yasm_symtab_declare(p_symtab, id, YASM_SYM_COMMON, @@ -652,7 +652,7 @@ parse_line(yasm_parser_gas *parser_gas) /* Pass change along to debug format */ yasm_vps_initialize(&vps); - vp = yasm_vp_create(filename, NULL); + vp = yasm_vp_create_string(NULL, filename); yasm_vps_append(&vps, vp); yasm_object_directive(p_object, ".file", "gas", &vps, NULL, @@ -666,8 +666,8 @@ parse_line(yasm_parser_gas *parser_gas) yasm_vps_initialize(&vps); if (!expect(INTNUM)) return NULL; - vp = yasm_vp_create(NULL, - p_expr_new_ident(yasm_expr_int(INTNUM_val))); + vp = yasm_vp_create_expr(NULL, + p_expr_new_ident(yasm_expr_int(INTNUM_val))); yasm_vps_append(&vps, vp); get_next_token(); /* INTNUM */ @@ -675,7 +675,7 @@ parse_line(yasm_parser_gas *parser_gas) yasm_vps_delete(&vps); return NULL; } - vp = yasm_vp_create(STRING_val.contents, NULL); + vp = yasm_vp_create_string(NULL, STRING_val.contents); yasm_vps_append(&vps, vp); get_next_token(); /* STRING */ @@ -771,18 +771,22 @@ parse_dirvals(yasm_parser_gas *parser_gas, yasm_valparamhead *vps) switch (curtok) { case ID: get_peek_token(parser_gas); - if (parser_gas->peek_token == ',' || - is_eol_tok(parser_gas->peek_token)) { - /* Just an ID */ - vp = yasm_vp_create(ID_val, NULL); - get_next_token(); /* ID */ - } else { - e = parse_expr(parser_gas); - vp = yasm_vp_create(NULL, e); + switch (parser_gas->peek_token) { + case '+': case '-': + case '|': case '^': case '&': case '!': + case '*': case '/': case '%': case LEFT_OP: case RIGHT_OP: + e = parse_expr(parser_gas); + vp = yasm_vp_create_expr(NULL, e); + break; + default: + /* Just an ID */ + vp = yasm_vp_create_id(NULL, ID_val, '\0'); + get_next_token(); /* ID */ + break; } break; case STRING: - vp = yasm_vp_create(STRING_val.contents, NULL); + vp = yasm_vp_create_string(NULL, STRING_val.contents); get_next_token(); /* STRING */ break; case '@': @@ -793,7 +797,7 @@ parse_dirvals(yasm_parser_gas *parser_gas, yasm_valparamhead *vps) e = parse_expr(parser_gas); if (!e) return num; - vp = yasm_vp_create(NULL, e); + vp = yasm_vp_create_expr(NULL, e); break; } yasm_vps_append(vps, vp); @@ -1284,20 +1288,18 @@ gas_get_section(yasm_parser_gas *parser_gas, char *name, yasm_section *new_section; yasm_vps_initialize(&vps); - vp = yasm_vp_create(name, NULL); + vp = yasm_vp_create_id(NULL, name, '\0'); yasm_vps_append(&vps, vp); if (!builtin) { - if (flags) { - gasflags = yasm_xmalloc(5+strlen(flags)); - strcpy(gasflags, "gas_"); - strcat(gasflags, flags); - } else - gasflags = yasm__xstrdup("gas_"); - vp = yasm_vp_create(gasflags, NULL); + if (flags) + gasflags = yasm__xstrdup(flags); + else + gasflags = yasm__xstrdup(""); + vp = yasm_vp_create_string(yasm__xstrdup("gasflags"), gasflags); yasm_vps_append(&vps, vp); if (type) { - vp = yasm_vp_create(type, NULL); + vp = yasm_vp_create_id(NULL, type, '\0'); yasm_vps_append(&vps, vp); } } diff --git a/modules/parsers/nasm/nasm-parse.c b/modules/parsers/nasm/nasm-parse.c index 0202eae0..cbd84993 100644 --- a/modules/parsers/nasm/nasm-parse.c +++ b/modules/parsers/nasm/nasm-parse.c @@ -65,8 +65,6 @@ static void nasm_parser_directive (yasm_parser_nasm *parser_nasm, const char *name, /*@null@*/ yasm_valparamhead *valparams, /*@null@*/ yasm_valparamhead *objext_valparams); -static int fix_directive_symrec(/*@null@*/ yasm_expr__item *ei, - /*@null@*/ void *d); static void define_label(yasm_parser_nasm *parser_nasm, /*@only@*/ char *name, int local); @@ -394,63 +392,54 @@ parse_directive_valparams(yasm_parser_nasm *parser_nasm, for (;;) { yasm_valparam *vp; yasm_expr *e; + char *id = NULL; + + /* Look for value first */ + if (curtok == ID) { + get_peek_token(parser_nasm); + if (parser_nasm->peek_token == '=') { + id = ID_val; + get_next_token(); /* id */ + get_next_token(); /* '=' */ + } + } + /* Look for parameter */ switch (curtok) { case STRING: - vp = yasm_vp_create(STRING_val.contents, NULL); + vp = yasm_vp_create_string(id, STRING_val.contents); get_next_token(); break; case ID: - { - char *id = ID_val; - get_peek_token(parser_nasm); - if (parser_nasm->peek_token == '=') { - get_next_token(); /* id */ - get_next_token(); /* = */ - e = parse_expr(parser_nasm, DIR_EXPR); - if (!e) { - yasm_vps_delete(vps); - return 0; - } - yasm_expr__traverse_leaves_in(e, parser_nasm, - fix_directive_symrec); - vp = yasm_vp_create(id, e); - break; - } - if (parser_nasm->peek_token == ',' - || parser_nasm->peek_token == ']' - || parser_nasm->peek_token == ':') { - /* Try to catch just IDs here first */ - get_next_token(); /* id */ - vp = yasm_vp_create(id, NULL); - break; + /* We need a peek token, but avoid error if we have one + * already; we need to work whether or not we hit the + * "value=" if test above. + * + * We cheat and peek ahead to see if this is just an ID or + * the ID is part of an expression. We assume a + or - means + * that it's part of an expression (e.g. "x+y" is parsed as + * the expression "x+y" and not as "x", "+y"). + */ + if (parser_nasm->peek_token == NONE) + get_peek_token(parser_nasm); + switch (parser_nasm->peek_token) { + case '|': case '^': case '&': case LEFT_OP: case RIGHT_OP: + case '+': case '-': + case '*': case '/': case '%': case SIGNDIV: case SIGNMOD: + break; + default: + /* Just an id */ + vp = yasm_vp_create_id(id, ID_val, '$'); + get_next_token(); + goto next; } /*@fallthrough@*/ - } default: - { - /* If direxpr is just an ID, put it in val and delete the expr. - * Otherwise, we need to go through the expr and replace the - * current (local) symrecs with the use of global ones. - */ - const /*@null@*/ yasm_symrec *vp_symrec; e = parse_expr(parser_nasm, DIR_EXPR); - if (!e) { - yasm_vps_delete(vps); - return 0; - } - if ((vp_symrec = yasm_expr_get_symrec(&e, 0))) { - vp = yasm_vp_create( - yasm__xstrdup(yasm_symrec_get_name(vp_symrec)), NULL); - yasm_expr_destroy(e); - } else { - yasm_expr__traverse_leaves_in(e, parser_nasm, - fix_directive_symrec); - vp = yasm_vp_create(NULL, e); - } - } + vp = yasm_vp_create_expr(id, e); + break; } - +next: yasm_vps_append(vps, vp); if (curtok == ',') get_next_token(); @@ -985,9 +974,8 @@ parse_expr6(yasm_parser_nasm *parser_nasm, expr_type type) e = p_expr_new_ident(yasm_expr_reg(REG_val[0])); break; case ID: - e = p_expr_new_ident(yasm_expr_sym( - yasm_symtab_define_label(p_symtab, ID_val, - yasm_section_bcs_first(cursect), 0, cur_line))); + sym = yasm_symtab_use(p_symtab, ID_val, cur_line); + e = p_expr_new_ident(yasm_expr_sym(sym)); yasm_xfree(ID_val); break; default: @@ -1100,21 +1088,6 @@ define_label(yasm_parser_nasm *parser_nasm, char *name, int local) yasm_xfree(name); } -static int -fix_directive_symrec(yasm_expr__item *ei, void *d) -{ - yasm_parser_nasm *parser_nasm = (yasm_parser_nasm *)d; - if (!ei || ei->type != YASM_EXPR_SYM) - return 0; - - /* FIXME: Delete current symrec */ - ei->data.sym = - yasm_symtab_use(p_symtab, yasm_symrec_get_name(ei->data.sym), - cur_line); - - return 0; -} - static void dir_align(yasm_object *object, yasm_valparamhead *valparams, yasm_valparamhead *objext_valparams, unsigned long line) diff --git a/modules/parsers/nasm/nasm-token.re b/modules/parsers/nasm/nasm-token.re index 4931498c..56bd8dfc 100644 --- a/modules/parsers/nasm/nasm-token.re +++ b/modules/parsers/nasm/nasm-token.re @@ -605,9 +605,11 @@ directive2: RETURN(s->tok[0]); } - /* forced identifier */ + /* forced identifier; within directive, don't strip '$', this is + * handled later. + */ "$" [a-zA-Z0-9_$#@~.?]+ { - lvalp->str_val = yasm__xstrndup(TOK+1, TOKLEN-1); + lvalp->str_val = yasm__xstrndup(TOK, TOKLEN); RETURN(ID); }