| Index: third_party/yasm/patched-yasm/modules/objfmts/coff/coff-objfmt.c
|
| ===================================================================
|
| --- third_party/yasm/patched-yasm/modules/objfmts/coff/coff-objfmt.c (revision 165590)
|
| +++ third_party/yasm/patched-yasm/modules/objfmts/coff/coff-objfmt.c (working copy)
|
| @@ -26,7 +26,6 @@
|
| */
|
| #include <util.h>
|
| #include <time.h>
|
| -/*@unused@*/ RCSID("$Id: coff-objfmt.c 2347 2010-08-01 17:31:12Z peter $");
|
|
|
| #include <libyasm.h>
|
|
|
| @@ -183,10 +182,15 @@
|
|
|
| coff_symrec_data *filesym_data; /* Data for .file symbol */
|
|
|
| + /* data for .def/.endef and related directives */
|
| + coff_symrec_data *def_sym; /* symbol specified by .def */
|
| +
|
| /* data for win64 proc_frame and related directives */
|
| unsigned long proc_frame; /* Line number of start of proc, or 0 */
|
| unsigned long done_prolog; /* Line number of end of prologue, or 0 */
|
| /*@null@*/ coff_unwind_info *unwind; /* Unwind info */
|
| +
|
| + yasm_symrec *ssym_imagebase; /* ..imagebase symbol for win64 */
|
| } yasm_objfmt_coff;
|
|
|
| typedef struct coff_objfmt_output_info {
|
| @@ -227,7 +231,7 @@
|
| static int win32_sxdata_bc_calc_len
|
| (yasm_bytecode *bc, yasm_bc_add_span_func add_span, void *add_span_data);
|
| static int win32_sxdata_bc_tobytes
|
| - (yasm_bytecode *bc, unsigned char **bufp, void *d,
|
| + (yasm_bytecode *bc, unsigned char **bufp, unsigned char *bufstart, void *d,
|
| yasm_output_value_func output_value,
|
| /*@null@*/ yasm_output_reloc_func output_reloc);
|
|
|
| @@ -294,6 +298,7 @@
|
| objfmt_coff->proc_frame = 0;
|
| objfmt_coff->done_prolog = 0;
|
| objfmt_coff->unwind = NULL;
|
| + objfmt_coff->ssym_imagebase = NULL;
|
|
|
| return objfmt_coff;
|
| }
|
| @@ -380,6 +385,8 @@
|
| objfmt_coff->objfmt.module = &yasm_win64_LTX_objfmt;
|
| objfmt_coff->win32 = 1;
|
| objfmt_coff->win64 = 1;
|
| + objfmt_coff->ssym_imagebase =
|
| + yasm_symtab_define_label(object->symtab, "..imagebase", NULL, 0, 0);
|
| }
|
| return (yasm_objfmt *)objfmt_coff;
|
| }
|
| @@ -487,14 +494,18 @@
|
| /*@dependent@*/ /*@null@*/ yasm_symrec *sym = value->rel;
|
| unsigned long addr;
|
| coff_reloc *reloc;
|
| + int nobase = info->csd->flags2 & COFF_FLAG_NOBASE;
|
|
|
| /* Sometimes we want the relocation to be generated against one
|
| * symbol but the value generated correspond to a different symbol.
|
| * This is done through (sym being referenced) WRT (sym used for
|
| * reloc). Note both syms need to be in the same section!
|
| */
|
| - if (value->wrt) {
|
| + if (value->wrt && value->wrt == objfmt_coff->ssym_imagebase)
|
| + nobase = 1;
|
| + else if (value->wrt) {
|
| /*@dependent@*/ /*@null@*/ yasm_bytecode *rel_precbc, *wrt_precbc;
|
| +
|
| if (!yasm_symrec_get_label(sym, &rel_precbc)
|
| || !yasm_symrec_get_label(value->wrt, &wrt_precbc)) {
|
| yasm_error_set(YASM_ERROR_TOO_COMPLEX,
|
| @@ -569,8 +580,8 @@
|
| intn_minus = bc->offset;
|
| }
|
|
|
| - if (value->seg_of || value->section_rel) {
|
| - /* Segment or section-relative generation; zero value. */
|
| + if (value->seg_of) {
|
| + /* Segment generation; zero value. */
|
| intn_val = 0;
|
| intn_minus = 0;
|
| }
|
| @@ -642,13 +653,13 @@
|
| yasm_internal_error(N_("coff objfmt: unrecognized machine"));
|
| } else {
|
| if (objfmt_coff->machine == COFF_MACHINE_I386) {
|
| - if (info->csd->flags2 & COFF_FLAG_NOBASE)
|
| + if (nobase)
|
| reloc->type = COFF_RELOC_I386_ADDR32NB;
|
| else
|
| reloc->type = COFF_RELOC_I386_ADDR32;
|
| } else if (objfmt_coff->machine == COFF_MACHINE_AMD64) {
|
| if (valsize == 32) {
|
| - if (info->csd->flags2 & COFF_FLAG_NOBASE)
|
| + if (nobase)
|
| reloc->type = COFF_RELOC_AMD64_ADDR32NB;
|
| else
|
| reloc->type = COFF_RELOC_AMD64_ADDR32;
|
| @@ -1512,6 +1523,7 @@
|
| } else if (objfmt_coff->win64 && strcmp(sectname, ".xdata") == 0) {
|
| data.flags = COFF_STYP_DATA | COFF_STYP_READ;
|
| align = 8;
|
| + data.flags2 = COFF_FLAG_NOBASE;
|
| } else if (objfmt_coff->win32 && strcmp(sectname, ".sxdata") == 0) {
|
| data.flags = COFF_STYP_INFO;
|
| } else if (strcmp(sectname, ".comment") == 0) {
|
| @@ -1594,6 +1606,17 @@
|
| return NULL;
|
| }
|
|
|
| +static /*@observer@*/ /*@null@*/ yasm_symrec *
|
| +win64_objfmt_get_special_sym(yasm_object *object, const char *name,
|
| + const char *parser)
|
| +{
|
| + if (yasm__strcasecmp(name, "imagebase") == 0) {
|
| + yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)object->objfmt;
|
| + return objfmt_coff->ssym_imagebase;
|
| + }
|
| + return NULL;
|
| +}
|
| +
|
| static void
|
| coff_section_data_destroy(void *data)
|
| {
|
| @@ -1758,7 +1781,8 @@
|
| }
|
|
|
| static int
|
| -win32_sxdata_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
|
| +win32_sxdata_bc_tobytes(yasm_bytecode *bc, unsigned char **bufp,
|
| + unsigned char *bufstart, void *d,
|
| yasm_output_value_func output_value,
|
| yasm_output_reloc_func output_reloc)
|
| {
|
| @@ -1840,6 +1864,131 @@
|
| }
|
|
|
| static void
|
| +dir_secrel32(yasm_object *object, yasm_valparamhead *valparams,
|
| + yasm_valparamhead *objext_valparams, unsigned long line)
|
| +{
|
| + yasm_datavalhead dvs;
|
| + yasm_valparam *vp;
|
| +
|
| + if (!object->cur_section) {
|
| + yasm_error_set(YASM_ERROR_SYNTAX,
|
| + N_(".secrel32 can only be used inside of a section"));
|
| + return;
|
| + }
|
| +
|
| + vp = yasm_vps_first(valparams);
|
| + yasm_dvs_initialize(&dvs);
|
| + do {
|
| + yasm_expr *e = yasm_vp_expr(vp, object->symtab, line);
|
| + yasm_dataval *dv;
|
| + if (!e) {
|
| + yasm_error_set(YASM_ERROR_VALUE,
|
| + N_(".secrel32 requires expressions"));
|
| + yasm_dvs_delete(&dvs);
|
| + return;
|
| + }
|
| + dv = yasm_dv_create_expr(e);
|
| + yasm_dv_get_value(dv)->section_rel = 1;
|
| + yasm_dvs_append(&dvs, dv);
|
| + } while ((vp = yasm_vps_next(vp)));
|
| +
|
| + yasm_section_bcs_append(object->cur_section,
|
| + yasm_bc_create_data(&dvs, 4, 0, object->arch, line));
|
| +}
|
| +
|
| +static void
|
| +dir_def(yasm_object *object, yasm_valparamhead *valparams,
|
| + yasm_valparamhead *objext_valparams, unsigned long line)
|
| +{
|
| + yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)object->objfmt;
|
| + yasm_valparam *vp;
|
| + const char *symname;
|
| + yasm_symrec *sym;
|
| + coff_symrec_data *sym_data;
|
| +
|
| + if (objfmt_coff->def_sym) {
|
| + yasm_warn_set(YASM_WARN_GENERAL,
|
| + N_(".def pseudo-op used inside of .def/.endef; ignored"));
|
| + return;
|
| + }
|
| +
|
| + vp = yasm_vps_first(valparams);
|
| + symname = yasm_vp_id(vp);
|
| + if (!symname) {
|
| + yasm_error_set(YASM_ERROR_SYNTAX,
|
| + N_("argument to SAFESEH must be symbol name"));
|
| + return;
|
| + }
|
| +
|
| + sym = yasm_symtab_use(object->symtab, symname, line);
|
| + sym_data = yasm_symrec_get_data(sym, &coff_symrec_data_cb);
|
| + if (!sym_data) {
|
| + sym_data = coff_objfmt_sym_set_data(sym, COFF_SCL_NULL, 0,
|
| + COFF_SYMTAB_AUX_NONE);
|
| + }
|
| + objfmt_coff->def_sym = sym_data;
|
| +}
|
| +
|
| +static void
|
| +dir_scl(yasm_object *object, yasm_valparamhead *valparams,
|
| + yasm_valparamhead *objext_valparams, unsigned long line)
|
| +{
|
| + yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)object->objfmt;
|
| + yasm_intnum *intn = NULL;
|
| +
|
| + if (!objfmt_coff->def_sym) {
|
| + yasm_warn_set(YASM_WARN_GENERAL,
|
| + N_("%s pseudo-op used outside of .def/.endef; ignored"),
|
| + ".scl");
|
| + return;
|
| + }
|
| +
|
| + if (yasm_dir_helper_intn(object, yasm_vps_first(valparams), line,
|
| + &intn, 0) < 0)
|
| + return;
|
| + if (!intn)
|
| + return;
|
| + objfmt_coff->def_sym->sclass = yasm_intnum_get_uint(intn);
|
| + yasm_intnum_destroy(intn);
|
| +}
|
| +
|
| +static void
|
| +dir_type(yasm_object *object, yasm_valparamhead *valparams,
|
| + yasm_valparamhead *objext_valparams, unsigned long line)
|
| +{
|
| + yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)object->objfmt;
|
| + yasm_intnum *intn = NULL;
|
| +
|
| + if (!objfmt_coff->def_sym) {
|
| + yasm_warn_set(YASM_WARN_GENERAL,
|
| + N_("%s pseudo-op used outside of .def/.endef; ignored"),
|
| + ".type");
|
| + return;
|
| + }
|
| +
|
| + if (yasm_dir_helper_intn(object, yasm_vps_first(valparams), line,
|
| + &intn, 0) < 0)
|
| + return;
|
| + if (!intn)
|
| + return;
|
| + objfmt_coff->def_sym->type = yasm_intnum_get_uint(intn);
|
| + yasm_intnum_destroy(intn);
|
| +}
|
| +
|
| +static void
|
| +dir_endef(yasm_object *object, yasm_valparamhead *valparams,
|
| + yasm_valparamhead *objext_valparams, unsigned long line)
|
| +{
|
| + yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)object->objfmt;
|
| + if (!objfmt_coff->def_sym) {
|
| + yasm_warn_set(YASM_WARN_GENERAL,
|
| + N_(".endef pseudo-op used before .def; ignored"));
|
| + return;
|
| + }
|
| + objfmt_coff->def_sym = NULL;
|
| +}
|
| +
|
| +static void
|
| dir_proc_frame(yasm_object *object, /*@null@*/ yasm_valparamhead *valparams,
|
| yasm_valparamhead *objext_valparams, unsigned long line)
|
| {
|
| @@ -2194,6 +2343,11 @@
|
| static const yasm_directive coff_objfmt_directives[] = {
|
| { ".ident", "gas", dir_ident, YASM_DIR_ANY },
|
| { "ident", "nasm", dir_ident, YASM_DIR_ANY },
|
| + { ".def", "gas", dir_def, YASM_DIR_ID_REQUIRED },
|
| + { ".endef", "gas", dir_endef, YASM_DIR_ANY },
|
| + { ".scl", "gas", dir_scl, YASM_DIR_ARG_REQUIRED },
|
| + { ".type", "gas", dir_type, YASM_DIR_ARG_REQUIRED },
|
| + { ".secrel32", "gas", dir_secrel32, YASM_DIR_ARG_REQUIRED },
|
| { NULL, NULL, NULL, 0 }
|
| };
|
|
|
| @@ -2228,6 +2382,11 @@
|
| static const yasm_directive win32_objfmt_directives[] = {
|
| { ".ident", "gas", dir_ident, YASM_DIR_ANY },
|
| { "ident", "nasm", dir_ident, YASM_DIR_ANY },
|
| + { ".def", "gas", dir_def, YASM_DIR_ID_REQUIRED },
|
| + { ".endef", "gas", dir_endef, YASM_DIR_ANY },
|
| + { ".scl", "gas", dir_scl, YASM_DIR_ARG_REQUIRED },
|
| + { ".type", "gas", dir_type, YASM_DIR_ARG_REQUIRED },
|
| + { ".secrel32", "gas", dir_secrel32, YASM_DIR_ARG_REQUIRED },
|
| { ".export", "gas", dir_export, YASM_DIR_ID_REQUIRED },
|
| { "export", "nasm", dir_export, YASM_DIR_ID_REQUIRED },
|
| { ".safeseh", "gas", dir_safeseh, YASM_DIR_ID_REQUIRED },
|
| @@ -2273,6 +2432,11 @@
|
| static const yasm_directive win64_objfmt_directives[] = {
|
| { ".ident", "gas", dir_ident, YASM_DIR_ANY },
|
| { "ident", "nasm", dir_ident, YASM_DIR_ANY },
|
| + { ".def", "gas", dir_def, YASM_DIR_ID_REQUIRED },
|
| + { ".endef", "gas", dir_endef, YASM_DIR_ANY },
|
| + { ".scl", "gas", dir_scl, YASM_DIR_ARG_REQUIRED },
|
| + { ".type", "gas", dir_type, YASM_DIR_ARG_REQUIRED },
|
| + { ".secrel32", "gas", dir_secrel32, YASM_DIR_ARG_REQUIRED },
|
| { ".export", "gas", dir_export, YASM_DIR_ID_REQUIRED },
|
| { "export", "nasm", dir_export, YASM_DIR_ID_REQUIRED },
|
| { ".proc_frame", "gas", dir_proc_frame, YASM_DIR_ID_REQUIRED },
|
| @@ -2322,7 +2486,7 @@
|
| coff_objfmt_add_default_section,
|
| coff_objfmt_init_new_section,
|
| coff_objfmt_section_switch,
|
| - coff_objfmt_get_special_sym
|
| + win64_objfmt_get_special_sym
|
| };
|
| yasm_objfmt_module yasm_x64_LTX_objfmt = {
|
| "Win64",
|
| @@ -2340,5 +2504,5 @@
|
| coff_objfmt_add_default_section,
|
| coff_objfmt_init_new_section,
|
| coff_objfmt_section_switch,
|
| - coff_objfmt_get_special_sym
|
| + win64_objfmt_get_special_sym
|
| };
|
|
|