Index: third_party/yasm/patched-yasm/modules/objfmts/coff/coff-objfmt.c |
=================================================================== |
--- third_party/yasm/patched-yasm/modules/objfmts/coff/coff-objfmt.c (revision 71129) |
+++ third_party/yasm/patched-yasm/modules/objfmts/coff/coff-objfmt.c (working copy) |
@@ -26,7 +26,7 @@ |
*/ |
#include <util.h> |
#include <time.h> |
-/*@unused@*/ RCSID("$Id: coff-objfmt.c 2166 2009-01-02 08:33:21Z peter $"); |
+/*@unused@*/ RCSID("$Id: coff-objfmt.c 2347 2010-08-01 17:31:12Z peter $"); |
#include <libyasm.h> |
@@ -162,7 +162,9 @@ |
} coff_symtab_auxtype; |
typedef struct coff_symrec_data { |
+ int forcevis; /* force visibility in symbol table */ |
unsigned long index; /* assigned COFF symbol table index */ |
+ unsigned int type; /* type */ |
coff_symrec_sclass sclass; /* storage class */ |
int numaux; /* number of auxiliary entries */ |
@@ -254,7 +256,9 @@ |
sym_data = yasm_xmalloc(sizeof(coff_symrec_data) + |
(numaux-1)*sizeof(coff_symtab_auxent)); |
+ sym_data->forcevis = 0; |
sym_data->index = 0; |
+ sym_data->type = 0; |
sym_data->sclass = sclass; |
sym_data->numaux = numaux; |
sym_data->auxtype = auxtype; |
@@ -343,6 +347,17 @@ |
} |
objfmt_coff->win32 = 1; |
+ /* Define a @feat.00 symbol for win32 safeseh handling */ |
+ if (!objfmt_coff->win64) { |
+ yasm_symrec *feat00; |
+ coff_symrec_data *sym_data; |
+ feat00 = yasm_symtab_define_equ(object->symtab, "@feat.00", |
+ yasm_expr_create_ident(yasm_expr_int( |
+ yasm_intnum_create_uint(1)), 0), 0); |
+ sym_data = coff_objfmt_sym_set_data(feat00, COFF_SCL_STAT, 0, |
+ COFF_SYMTAB_AUX_NONE); |
+ sym_data->forcevis = 1; |
+ } |
} |
return (yasm_objfmt *)objfmt_coff; |
} |
@@ -369,10 +384,11 @@ |
return (yasm_objfmt *)objfmt_coff; |
} |
-static coff_section_data * |
-coff_objfmt_init_new_section(yasm_object *object, yasm_section *sect, |
- const char *sectname, unsigned long line) |
+static void |
+coff_objfmt_init_new_section(yasm_section *sect, unsigned long line) |
{ |
+ yasm_object *object = yasm_section_get_object(sect); |
+ const char *sectname = yasm_section_get_name(sect); |
yasm_objfmt_coff *objfmt_coff = (yasm_objfmt_coff *)object->objfmt; |
coff_section_data *data; |
yasm_symrec *sym; |
@@ -388,6 +404,15 @@ |
data->flags2 = 0; |
data->strtab_name = 0; |
data->isdebug = 0; |
+ |
+ if (yasm__strncasecmp(sectname, ".debug", 6)==0) { |
+ data->flags = COFF_STYP_DATA; |
+ if (objfmt_coff->win32) |
+ data->flags |= COFF_STYP_DISCARD|COFF_STYP_READ; |
+ data->isdebug = 1; |
+ } else |
+ data->flags = COFF_STYP_TEXT; |
+ |
yasm_section_add_data(sect, &coff_section_data_cb, data); |
sym = yasm_symtab_define_label(object->symtab, sectname, |
@@ -395,34 +420,9 @@ |
yasm_symrec_declare(sym, YASM_SYM_GLOBAL, line); |
coff_objfmt_sym_set_data(sym, COFF_SCL_STAT, 1, COFF_SYMTAB_AUX_SECT); |
data->sym = sym; |
- return data; |
} |
static int |
-coff_objfmt_init_remaining_section(yasm_section *sect, /*@null@*/ void *d) |
-{ |
- /*@null@*/ coff_objfmt_output_info *info = (coff_objfmt_output_info *)d; |
- /*@dependent@*/ /*@null@*/ coff_section_data *csd; |
- |
- assert(info != NULL); |
- csd = yasm_section_get_data(sect, &coff_section_data_cb); |
- if (!csd) { |
- /* Initialize new one */ |
- const char *sectname = yasm_section_get_name(sect); |
- csd = coff_objfmt_init_new_section(info->object, sect, sectname, 0); |
- if (yasm__strncasecmp(sectname, ".debug", 6)==0) { |
- csd->flags = COFF_STYP_DATA; |
- if (info->objfmt_coff->win32) |
- csd->flags |= COFF_STYP_DISCARD|COFF_STYP_READ; |
- csd->isdebug = 1; |
- } else |
- csd->flags = COFF_STYP_TEXT; |
- } |
- |
- return 0; |
-} |
- |
-static int |
coff_objfmt_set_section_addr(yasm_section *sect, /*@null@*/ void *d) |
{ |
/*@null@*/ coff_objfmt_output_info *info = (coff_objfmt_output_info *)d; |
@@ -793,7 +793,8 @@ |
coff_objfmt_output_bytecode); |
/* Sanity check final section size */ |
- if (csd->size != yasm_bc_next_offset(yasm_section_bcs_last(sect))) |
+ if (yasm_errwarns_num_errors(info->errwarns, 0) == 0 && |
+ csd->size != yasm_bc_next_offset(yasm_section_bcs_last(sect))) |
yasm_internal_error( |
N_("coff: section computed size did not match actual size")); |
} |
@@ -947,16 +948,21 @@ |
assert(info != NULL); |
sym_data = yasm_symrec_get_data(sym, &coff_symrec_data_cb); |
- if ((vis & (YASM_SYM_EXTERN|YASM_SYM_GLOBAL|YASM_SYM_COMMON)) && !sym_data) |
- sym_data = coff_objfmt_sym_set_data(sym, COFF_SCL_EXT, 0, |
- COFF_SYMTAB_AUX_NONE); |
- if (info->all_syms || vis != YASM_SYM_LOCAL || yasm_symrec_is_abs(sym)) { |
+ if (info->all_syms || vis != YASM_SYM_LOCAL || yasm_symrec_is_abs(sym) || |
+ (sym_data && sym_data->forcevis)) { |
/* Save index in symrec data */ |
- if (!sym_data) { |
- sym_data = coff_objfmt_sym_set_data(sym, COFF_SCL_STAT, 0, |
+ if (!sym_data) |
+ sym_data = coff_objfmt_sym_set_data(sym, COFF_SCL_NULL, 0, |
COFF_SYMTAB_AUX_NONE); |
+ /* Set storage class based on visibility if not already set */ |
+ if (sym_data->sclass == COFF_SCL_NULL) { |
+ if (vis & (YASM_SYM_EXTERN|YASM_SYM_GLOBAL|YASM_SYM_COMMON)) |
+ sym_data->sclass = COFF_SCL_EXT; |
+ else |
+ sym_data->sclass = COFF_SCL_STAT; |
} |
+ |
sym_data->index = info->indx; |
info->indx += sym_data->numaux + 1; |
@@ -970,18 +976,20 @@ |
/*@null@*/ coff_objfmt_output_info *info = (coff_objfmt_output_info *)d; |
yasm_sym_vis vis = yasm_symrec_get_visibility(sym); |
int is_abs = yasm_symrec_is_abs(sym); |
+ /*@dependent@*/ /*@null@*/ coff_symrec_data *csymd; |
+ csymd = yasm_symrec_get_data(sym, &coff_symrec_data_cb); |
assert(info != NULL); |
/* Don't output local syms unless outputting all syms */ |
- if (info->all_syms || vis != YASM_SYM_LOCAL || is_abs) { |
+ if (info->all_syms || vis != YASM_SYM_LOCAL || is_abs || |
+ (csymd && csymd->forcevis)) { |
/*@only*/ char *name; |
const yasm_expr *equ_val; |
const yasm_intnum *intn; |
unsigned char *localbuf; |
size_t len; |
int aux; |
- /*@dependent@*/ /*@null@*/ coff_symrec_data *csymd; |
unsigned long value = 0; |
unsigned int scnum = 0xfffe; /* -2 = debugging symbol */ |
/*@dependent@*/ /*@null@*/ yasm_section *sect; |
@@ -997,7 +1005,6 @@ |
len = strlen(name); |
/* Get symrec's of_data (needed for storage class) */ |
- csymd = yasm_symrec_get_data(sym, &coff_symrec_data_cb); |
if (!csymd) |
yasm_internal_error(N_("coff: expected sym data to be present")); |
@@ -1069,7 +1076,7 @@ |
} |
YASM_WRITE_32_L(localbuf, value); /* value */ |
YASM_WRITE_16_L(localbuf, scnum); /* section number */ |
- YASM_WRITE_16_L(localbuf, 0); /* type is always zero (for now) */ |
+ YASM_WRITE_16_L(localbuf, csymd->type); /* type */ |
YASM_WRITE_8(localbuf, csymd->sclass); /* storage class */ |
YASM_WRITE_8(localbuf, csymd->numaux); /* number of aux entries */ |
fwrite(info->buf, 18, 1, info->f); |
@@ -1109,17 +1116,18 @@ |
{ |
/*@null@*/ coff_objfmt_output_info *info = (coff_objfmt_output_info *)d; |
yasm_sym_vis vis = yasm_symrec_get_visibility(sym); |
+ /*@dependent@*/ /*@null@*/ coff_symrec_data *csymd; |
+ csymd = yasm_symrec_get_data(sym, &coff_symrec_data_cb); |
assert(info != NULL); |
/* Don't output local syms unless outputting all syms */ |
- if (info->all_syms || vis != YASM_SYM_LOCAL) { |
+ if (info->all_syms || vis != YASM_SYM_LOCAL || |
+ (csymd && csymd->forcevis)) { |
/*@only@*/ char *name = yasm_symrec_get_global_name(sym, info->object); |
- /*@dependent@*/ /*@null@*/ coff_symrec_data *csymd; |
size_t len = strlen(name); |
int aux; |
- csymd = yasm_symrec_get_data(sym, &coff_symrec_data_cb); |
if (!csymd) |
yasm_internal_error(N_("coff: expected sym data to be present")); |
@@ -1181,12 +1189,6 @@ |
info.f = f; |
info.buf = yasm_xmalloc(REGULAR_OUTBUF_SIZE); |
- /* Initialize section data (and count in parse_scnum) any sections that |
- * we've not initialized so far. |
- */ |
- yasm_object_sections_traverse(object, &info, |
- coff_objfmt_init_remaining_section); |
- |
/* Allocate space for headers by seeking forward */ |
if (fseek(f, (long)(20+40*(objfmt_coff->parse_scnum-1)), SEEK_SET) < 0) { |
yasm__fatal(N_("could not seek on output file")); |
@@ -1287,7 +1289,7 @@ |
retval = yasm_object_get_general(object, ".text", 16, 1, 0, &isnew, 0); |
if (isnew) { |
- csd = coff_objfmt_init_new_section(object, retval, ".text", 0); |
+ csd = yasm_section_get_data(retval, &coff_section_data_cb); |
csd->flags = COFF_STYP_TEXT; |
if (objfmt_coff->win32) |
csd->flags |= COFF_STYP_EXECUTE | COFF_STYP_READ; |
@@ -1570,14 +1572,10 @@ |
retval = yasm_object_get_general(object, realname, align, iscode, |
resonly, &isnew, line); |
+ yasm_xfree(realname); |
- if (isnew) |
- csd = coff_objfmt_init_new_section(object, retval, realname, line); |
- else |
- csd = yasm_section_get_data(retval, &coff_section_data_cb); |
+ 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 = data.flags; |
@@ -1675,8 +1673,7 @@ |
/* Initialize directive section if needed */ |
if (isnew) { |
coff_section_data *csd; |
- csd = coff_objfmt_init_new_section(object, sect, |
- yasm_section_get_name(sect), line); |
+ csd = yasm_section_get_data(sect, &coff_section_data_cb); |
csd->flags = COFF_STYP_INFO | COFF_STYP_DISCARD | COFF_STYP_READ; |
} |
@@ -1701,13 +1698,20 @@ |
yasm_section *sect; |
/* Reference symbol (to generate error if not declared). |
- * Also, symbol must be externally visible, so force global. |
+ * Also, symbol must be externally visible, so force it. |
*/ |
vp = yasm_vps_first(valparams); |
symname = yasm_vp_id(vp); |
if (symname) { |
+ coff_symrec_data *sym_data; |
sym = yasm_symtab_use(object->symtab, symname, line); |
- yasm_symrec_declare(sym, YASM_SYM_GLOBAL, 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); |
+ } |
+ sym_data->forcevis = 1; |
+ sym_data->type = 0x20; /* function */ |
} else { |
yasm_error_set(YASM_ERROR_SYNTAX, |
N_("argument to SAFESEH must be symbol name")); |
@@ -1723,7 +1727,7 @@ |
/* Initialize sxdata section if needed */ |
if (isnew) { |
coff_section_data *csd; |
- csd = coff_objfmt_init_new_section(object, sect, ".sxdata", line); |
+ csd = yasm_section_get_data(sect, &coff_section_data_cb); |
csd->flags = COFF_STYP_INFO; |
} |
@@ -2133,7 +2137,7 @@ |
/* Initialize xdata section if needed */ |
if (isnew) { |
- csd = coff_objfmt_init_new_section(object, sect, ".xdata", line); |
+ csd = yasm_section_get_data(sect, &coff_section_data_cb); |
csd->flags = COFF_STYP_DATA | COFF_STYP_READ; |
yasm_section_set_align(sect, 8, line); |
} |
@@ -2158,7 +2162,7 @@ |
/* Initialize pdata section if needed */ |
if (isnew) { |
- csd = coff_objfmt_init_new_section(object, sect, ".pdata", line); |
+ csd = yasm_section_get_data(sect, &coff_section_data_cb); |
csd->flags = COFF_STYP_DATA | COFF_STYP_READ; |
csd->flags2 = COFF_FLAG_NOBASE; |
yasm_section_set_align(sect, 4, line); |
@@ -2208,6 +2212,7 @@ |
coff_objfmt_output, |
coff_objfmt_destroy, |
coff_objfmt_add_default_section, |
+ coff_objfmt_init_new_section, |
coff_objfmt_section_switch, |
coff_objfmt_get_special_sym |
}; |
@@ -2260,6 +2265,7 @@ |
coff_objfmt_output, |
coff_objfmt_destroy, |
coff_objfmt_add_default_section, |
+ coff_objfmt_init_new_section, |
coff_objfmt_section_switch, |
coff_objfmt_get_special_sym |
}; |
@@ -2314,6 +2320,7 @@ |
coff_objfmt_output, |
coff_objfmt_destroy, |
coff_objfmt_add_default_section, |
+ coff_objfmt_init_new_section, |
coff_objfmt_section_switch, |
coff_objfmt_get_special_sym |
}; |
@@ -2331,6 +2338,7 @@ |
coff_objfmt_output, |
coff_objfmt_destroy, |
coff_objfmt_add_default_section, |
+ coff_objfmt_init_new_section, |
coff_objfmt_section_switch, |
coff_objfmt_get_special_sym |
}; |