(*section_switch)(yasm_object *object, yasm_valparamhead *valparams,
/*@null@*/ yasm_valparamhead *objext_valparams,
unsigned long line);
+
+ /** Module-level implementation of yasm_objfmt_get_special_sym().
+ * Call yasm_objfmt_get_special_sym() instead of calling this function.
+ */
+ /*@observer@*/ /*@null@*/ yasm_symrec *
+ (*get_special_sym)(yasm_object *object, const char *name,
+ const char *parser);
};
/** Create object format.
(yasm_object *object, yasm_valparamhead *valparams,
/*@null@*/ yasm_valparamhead *objext_valparams, unsigned long line);
+/** Get a special symbol. Special symbols are generally used to generate
+ * special relocation types via the WRT mechanism.
+ * \param object object
+ * \param name symbol name (not including any parser-specific prefix)
+ * \param parser parser keyword
+ * \return NULL if unrecognized, otherwise special symbol.
+ */
+/*@observer@*/ /*@null@*/ yasm_symrec *yasm_objfmt_get_special_sym
+ (yasm_object *object, const char *name, const char *parser);
+
#ifndef YASM_DOXYGEN
/* Inline macro implementations for objfmt functions */
#define yasm_objfmt_add_default_section(object) \
((yasm_objfmt_base *)((object)->objfmt))->module->add_default_section \
(object)
+#define yasm_objfmt_get_special_sym(object, name, parser) \
+ ((yasm_objfmt_base *)((object)->objfmt))->module->get_special_sym \
+ (object, name, parser)
#endif
return retval;
}
+static /*@observer@*/ /*@null@*/ yasm_symrec *
+bin_objfmt_get_special_sym(yasm_object *object, const char *name,
+ const char *parser)
+{
+ return NULL;
+}
+
static void
bin_objfmt_dir_org(yasm_object *object,
/*@null@*/ yasm_valparamhead *valparams,
bin_objfmt_output,
bin_objfmt_destroy,
bin_objfmt_add_default_section,
- bin_objfmt_section_switch
+ bin_objfmt_section_switch,
+ bin_objfmt_get_special_sym
};
return retval;
}
+static /*@observer@*/ /*@null@*/ yasm_symrec *
+coff_objfmt_get_special_sym(yasm_object *object, const char *name,
+ const char *parser)
+{
+ return NULL;
+}
+
static void
coff_section_data_destroy(void *data)
{
coff_objfmt_output,
coff_objfmt_destroy,
coff_objfmt_add_default_section,
- coff_objfmt_section_switch
+ coff_objfmt_section_switch,
+ coff_objfmt_get_special_sym
};
/* Define valid debug formats to use with this object format */
coff_objfmt_output,
coff_objfmt_destroy,
coff_objfmt_add_default_section,
- coff_objfmt_section_switch
+ coff_objfmt_section_switch,
+ coff_objfmt_get_special_sym
};
static const yasm_directive win64_objfmt_directives[] = {
coff_objfmt_output,
coff_objfmt_destroy,
coff_objfmt_add_default_section,
- coff_objfmt_section_switch
+ coff_objfmt_section_switch,
+ coff_objfmt_get_special_sym
};
yasm_objfmt_module yasm_x64_LTX_objfmt = {
"Win64",
coff_objfmt_output,
coff_objfmt_destroy,
coff_objfmt_add_default_section,
- coff_objfmt_section_switch
+ coff_objfmt_section_switch,
+ coff_objfmt_get_special_sym
};
return retval;
}
+static /*@observer@*/ /*@null@*/ yasm_symrec *
+dbg_objfmt_get_special_sym(yasm_object *object, const char *name,
+ const char *parser)
+{
+ yasm_objfmt_dbg *objfmt_dbg = (yasm_objfmt_dbg *)object->objfmt;
+ fprintf(objfmt_dbg->dbgfile, "get_special_sym(object, \"%s\", \"%s\")\n",
+ name, parser);
+ return NULL;
+}
+
/* Define valid debug formats to use with this object format */
static const char *dbg_objfmt_dbgfmt_keywords[] = {
"null",
dbg_objfmt_output,
dbg_objfmt_destroy,
dbg_objfmt_add_default_section,
- dbg_objfmt_section_switch
+ dbg_objfmt_section_switch,
+ dbg_objfmt_get_special_sym
};
return retval;
}
+static /*@observer@*/ /*@null@*/ yasm_symrec *
+elf_objfmt_get_special_sym(yasm_object *object, const char *name,
+ const char *parser)
+{
+ return elf_get_special_sym(name, parser);
+}
+
static void
dir_type(yasm_object *object, yasm_valparamhead *valparams,
yasm_valparamhead *objext_valparams, unsigned long line)
elf_objfmt_output,
elf_objfmt_destroy,
elf_objfmt_add_default_section,
- elf_objfmt_section_switch
+ elf_objfmt_section_switch,
+ elf_objfmt_get_special_sym
};
yasm_objfmt_module yasm_elf32_LTX_objfmt = {
elf_objfmt_output,
elf_objfmt_destroy,
elf_objfmt_add_default_section,
- elf_objfmt_section_switch
+ elf_objfmt_section_switch,
+ elf_objfmt_get_special_sym
};
yasm_objfmt_module yasm_elf64_LTX_objfmt = {
elf_objfmt_output,
elf_objfmt_destroy,
elf_objfmt_add_default_section,
- elf_objfmt_section_switch
+ elf_objfmt_section_switch,
+ elf_objfmt_get_special_sym
};
/* FIXME: misuse of NULL bytecode */
elf_ssyms[i] = yasm_symtab_define_label(symtab,
elf_march->ssyms[i].name,
- NULL, 1, 0);
+ NULL, 0, 0);
}
}
return elf_march;
}
+yasm_symrec *
+elf_get_special_sym(const char *name, const char *parser)
+{
+ int i;
+ for (i=0; (unsigned int)i<elf_march->num_ssyms; i++) {
+ if (yasm__strcasecmp(name, elf_march->ssyms[i].name) == 0)
+ return elf_ssyms[i];
+ }
+ return NULL;
+}
+
/* reloc functions */
int elf_ssym_has_flag(yasm_symrec *wrt, int flag);
yasm_symtab *symtab,
int bits_pref);
+yasm_symrec *elf_get_special_sym(const char *name, const char *parser);
+
/* reloc functions */
int elf_is_wrt_sym_relative(yasm_symrec *wrt);
int elf_is_wrt_pos_adjusted(yasm_symrec *wrt);
return retval;
}
+static /*@observer@*/ /*@null@*/ yasm_symrec *
+macho_objfmt_get_special_sym(yasm_object *object, const char *name,
+ const char *parser)
+{
+ return NULL;
+}
+
static void
macho_section_data_destroy(void *data)
{
macho_objfmt_output,
macho_objfmt_destroy,
macho_objfmt_add_default_section,
- macho_objfmt_section_switch
+ macho_objfmt_section_switch,
+ macho_objfmt_get_special_sym
};
yasm_objfmt_module yasm_macho32_LTX_objfmt = {
macho_objfmt_output,
macho_objfmt_destroy,
macho_objfmt_add_default_section,
- macho_objfmt_section_switch
+ macho_objfmt_section_switch,
+ macho_objfmt_get_special_sym
};
yasm_objfmt_module yasm_macho64_LTX_objfmt = {
macho_objfmt_output,
macho_objfmt_destroy,
macho_objfmt_add_default_section,
- macho_objfmt_section_switch
+ macho_objfmt_section_switch,
+ macho_objfmt_get_special_sym
};
return retval;
}
+static /*@observer@*/ /*@null@*/ yasm_symrec *
+rdf_objfmt_get_special_sym(yasm_object *object, const char *name,
+ const char *parser)
+{
+ return NULL;
+}
+
static void
rdf_section_data_destroy(void *data)
{
rdf_objfmt_output,
rdf_objfmt_destroy,
rdf_objfmt_add_default_section,
- rdf_objfmt_section_switch
+ rdf_objfmt_section_switch,
+ rdf_objfmt_get_special_sym
};
return retval;
}
+static /*@observer@*/ /*@null@*/ yasm_symrec *
+xdf_objfmt_get_special_sym(yasm_object *object, const char *name,
+ const char *parser)
+{
+ return NULL;
+}
+
static void
xdf_section_data_destroy(void *data)
{
xdf_objfmt_output,
xdf_objfmt_destroy,
xdf_objfmt_add_default_section,
- xdf_objfmt_section_switch
+ xdf_objfmt_section_switch,
+ xdf_objfmt_get_special_sym
};
{
char *name = ID_val;
get_next_token(); /* ID */
+
+ /* "." references the current assembly position */
+ if (name[1] == '\0' && name[0] == '.')
+ sym = yasm_symtab_define_curpos(p_symtab, ".",
+ parser_gas->prev_bc, cur_line);
+ else
+ sym = yasm_symtab_use(p_symtab, name, cur_line);
+ yasm_xfree(name);
+
if (curtok == '@') {
+ yasm_symrec *wrt;
/* TODO: this is needed for shared objects, e.g. sym@PLT */
get_next_token(); /* '@' */
if (!expect(ID)) {
yasm_xfree(name);
return NULL;
}
+ wrt = yasm_objfmt_get_special_sym(p_object, ID_val, "gas");
yasm_xfree(ID_val);
get_next_token(); /* ID */
- sym = yasm_symtab_use(p_symtab, name, cur_line);
- yasm_xfree(name);
- return p_expr_new_ident(yasm_expr_sym(sym));
+ if (!wrt) {
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("unrecognized identifier after `@'"));
+ return p_expr_new_ident(yasm_expr_sym(sym));
+ }
+ return p_expr_new(yasm_expr_sym(sym), YASM_EXPR_WRT,
+ yasm_expr_sym(wrt));
}
- /* "." references the current assembly position */
- if (name[1] == '\0' && name[0] == '.')
- sym = yasm_symtab_define_curpos(p_symtab, ".",
- parser_gas->prev_bc, cur_line);
- else
- sym = yasm_symtab_use(p_symtab, name, cur_line);
- yasm_xfree(name);
return p_expr_new_ident(yasm_expr_sym(sym));
}
default:
yasm_intnum_create_charconst_nasm(STRING_val.contents)));
yasm_xfree(STRING_val.contents);
break;
- case ID:
case SPECIAL_ID:
+ sym = yasm_objfmt_get_special_sym(p_object, ID_val+2, "nasm");
+ if (sym) {
+ e = p_expr_new_ident(yasm_expr_sym(sym));
+ yasm_xfree(ID_val);
+ break;
+ }
+ /*@fallthrough@*/
+ case ID:
case LOCAL_ID:
sym = yasm_symtab_use(p_symtab, ID_val, cur_line);
e = p_expr_new_ident(yasm_expr_sym(sym));
[-+|^*&/%~$():=,\[] { RETURN(s->tok[0]); }
"]" { RETURN(s->tok[0]); }
- /* special non-local ..@label and labels like ..start */
- ".." [a-zA-Z0-9_$#@~.?]+ {
+ /* special non-local ..@label */
+ "..@" [a-zA-Z0-9_$#@~.?]+ {
+ lvalp->str_val = yasm__xstrndup(TOK, TOKLEN);
+ RETURN(ID);
+ }
+
+ /* special non-local labels like ..start */
+ ".." [a-zA-Z0-9_$#~.?]+ {
lvalp->str_val = yasm__xstrndup(TOK, TOKLEN);
RETURN(SPECIAL_ID);
}