* module loader's function definitions. The version number must never be
* decreased.
*/
-#define YASM_ARCH_VERSION 2
+#define YASM_ARCH_VERSION 3
/** YASM architecture module interface.
* \note All "data" in parser-related functions (yasm_arch_parse_*) needs to
size_t valsize, size_t shift, int warn,
unsigned long line);
+ /** Module-level implementation of yasm_arch_intnum_fixup_rel().
+ * Call yasm_arch_intnum_fixup_rel() instead of calling this function.
+ */
+ int (*intnum_fixup_rel) (yasm_arch *arch, yasm_intnum *intn,
+ size_t valsize, const yasm_bytecode *bc,
+ unsigned long line);
+
/** Module-level implementation of yasm_arch_intnum_tobytes().
* Call yasm_arch_intnum_tobytes() instead of calling this function.
*/
int (*intnum_tobytes) (yasm_arch *arch, const yasm_intnum *intn,
unsigned char *buf, size_t destsize, size_t valsize,
- int shift, const yasm_bytecode *bc, int rel,
+ int shift, const yasm_bytecode *bc,
int warn, unsigned long line);
/** Module-level implementation of yasm_arch_get_reg_size().
size_t valsize, size_t shift, int warn,
unsigned long line);
+/** Adjust #yasm_intnum for relative displacement from bc. Displacement
+ * is modified in-place.
+ * \param arch architecture
+ * \param intn integer value
+ * \param valsize size (in bits)
+ * \param bc bytecode being output ("parent" of value)
+ * \param line virtual line; may be 0 if warn is 0
+ * \return Nonzero on error.
+ */
+int yasm_arch_intnum_fixup_rel(yasm_arch *arch, yasm_intnum *intn,
+ size_t valsize, const yasm_bytecode *bc,
+ unsigned long line);
+
/** Output #yasm_intnum to buffer. Puts the value into the least
* significant bits of the destination, or may be shifted into more
* significant bits by the shift parameter. The destination bits are
* \param shift left shift (in bits); may be negative to specify right
* shift (standard warnings include truncation to boundary)
* \param bc bytecode being output ("parent" of value)
- * \param rel value is a relative displacement from bc
* \param warn enables standard warnings (value doesn't fit into
* valsize bits)
* \param line virtual line; may be 0 if warn is 0
int yasm_arch_intnum_tobytes(yasm_arch *arch, const yasm_intnum *intn,
unsigned char *buf, size_t destsize,
size_t valsize, int shift,
- const yasm_bytecode *bc, int rel, int warn,
+ const yasm_bytecode *bc, int warn,
unsigned long line);
/** Get the equivalent byte size of a register.
warn, line) \
((yasm_arch_base *)arch)->module->floatnum_tobytes \
(arch, flt, buf, destsize, valsize, shift, warn, line)
+#define yasm_arch_intnum_fixup_rel(arch, intn, valsize, bc, line) \
+ ((yasm_arch_base *)arch)->module->intnum_fixup_rel \
+ (arch, intn, valsize, bc, line)
#define yasm_arch_intnum_tobytes(arch, intn, buf, destsize, valsize, shift, \
- bc, rel, warn, line) \
+ bc, warn, line) \
((yasm_arch_base *)arch)->module->intnum_tobytes \
- (arch, intn, buf, destsize, valsize, shift, bc, rel, warn, line)
+ (arch, intn, buf, destsize, valsize, shift, bc, warn, line)
#define yasm_arch_get_reg_size(arch, reg) \
((yasm_arch_base *)arch)->module->get_reg_size(arch, reg)
#define yasm_arch_reg_print(arch, reg, f) \
* \param buf buffer for byte representation
* \param destsize destination size (in bytes)
* \param valsize size (in bits)
- * \param rel if nonzero, expr should be treated as PC/IP-relative
* \param warn enables standard warnings: zero for none;
* nonzero for overflow/underflow floating point warnings;
* negative for signed integer warnings,
*/
typedef int (*yasm_output_reloc_func)
(yasm_symrec *sym, yasm_bytecode *bc, unsigned char *buf, size_t destsize,
- size_t valsize, int rel, int warn, void *d);
+ size_t valsize, int warn, void *d);
/** Sort an array using merge sort algorithm.
* \internal
switch ((*ep)->op) {
case YASM_EXPR_IDENT:
+ /* Be kind, recurse */
+ if ((*ep)->terms[0].type == YASM_EXPR_EXPR)
+ return yasm_expr_extract_symrec(&((*ep)->terms[0].data.expn),
+ relocate, calc_bc_dist);
/* Replace sym with 0 value, return sym */
if ((*ep)->terms[0].type == YASM_EXPR_SYM) {
sym = (*ep)->terms[0].data.sym;
yasm_symrec_get_label(const yasm_symrec *sym,
yasm_symrec_get_label_bytecodep *precbc)
{
- if (sym->type != SYM_LABEL) {
+ if (sym->type != SYM_LABEL || !sym->value.precbc) {
*precbc = (yasm_symrec_get_label_bytecodep)0xDEADBEEF;
return 0;
}
NULL, /*yasm_lc3b__parse_seg_prefix*/
NULL, /*yasm_lc3b__parse_seg_override*/
lc3b_floatnum_tobytes,
+ yasm_lc3b__intnum_fixup_rel,
yasm_lc3b__intnum_tobytes,
lc3b_get_reg_size,
lc3b_reg_print,
/*@null@*/ yasm_insn_operands *operands, yasm_bytecode *prev_bc,
unsigned long line);
+int yasm_lc3b__intnum_fixup_rel
+ (yasm_arch *arch, yasm_intnum *intn, size_t valsize,
+ const yasm_bytecode *bc, unsigned long line);
+
int yasm_lc3b__intnum_tobytes
(yasm_arch *arch, const yasm_intnum *intn, unsigned char *buf,
size_t destsize, size_t valsize, int shift, const yasm_bytecode *bc,
- int rel, int warn, unsigned long line);
+ int warn, unsigned long line);
#endif
return 0;
}
+int
+yasm_lc3b__intnum_fixup_rel(yasm_arch *arch, yasm_intnum *intn,
+ size_t valsize, const yasm_bytecode *bc,
+ unsigned long line)
+{
+ yasm_intnum *delta;
+ if (valsize != 9)
+ yasm_internal_error(
+ N_("tried to do PC-relative offset from invalid sized value"));
+ delta = yasm_intnum_create_uint(bc->len);
+ yasm_intnum_calc(intn, YASM_EXPR_SUB, delta, line);
+ yasm_intnum_destroy(delta);
+ return 0;
+}
+
int
yasm_lc3b__intnum_tobytes(yasm_arch *arch, const yasm_intnum *intn,
unsigned char *buf, size_t destsize, size_t valsize,
- int shift, const yasm_bytecode *bc, int rel,
- int warn, unsigned long line)
+ int shift, const yasm_bytecode *bc, int warn,
+ unsigned long line)
{
- if (rel) {
- yasm_intnum *relnum, *delta;
- if (valsize != 9)
- yasm_internal_error(
- N_("tried to do PC-relative offset from invalid sized value"));
- relnum = yasm_intnum_copy(intn);
- delta = yasm_intnum_create_uint(bc->len);
- yasm_intnum_calc(relnum, YASM_EXPR_SUB, delta, line);
- yasm_intnum_destroy(delta);
- yasm_intnum_get_sized(relnum, buf, destsize, valsize, shift, 0, warn,
- line);
- yasm_intnum_destroy(relnum);
- } else {
- /* Write value out. */
- yasm_intnum_get_sized(intn, buf, destsize, valsize, shift, 0, warn,
- line);
- }
+ /* Write value out. */
+ yasm_intnum_get_sized(intn, buf, destsize, valsize, shift, 0, warn,
+ line);
return 0;
}
x86_parse_seg_prefix,
x86_parse_seg_override,
yasm_x86__floatnum_tobytes,
+ yasm_x86__intnum_fixup_rel,
yasm_x86__intnum_tobytes,
yasm_x86__get_reg_size,
x86_reg_print,
(yasm_arch *arch, const yasm_floatnum *flt, unsigned char *buf,
size_t destsize, size_t valsize, size_t shift, int warn,
unsigned long line);
+int yasm_x86__intnum_fixup_rel
+ (yasm_arch *arch, yasm_intnum *intn, size_t valsize,
+ const yasm_bytecode *bc, unsigned long line);
int yasm_x86__intnum_tobytes
(yasm_arch *arch, const yasm_intnum *intn, unsigned char *buf,
size_t destsize, size_t valsize, int shift, const yasm_bytecode *bc,
- int rel, int warn, unsigned long line);
+ int warn, unsigned long line);
unsigned int yasm_x86__get_reg_size(yasm_arch *arch, unsigned long reg);
#endif
if (ea->disp) {
if (eat.pcrel) {
+ /*@null@*/ yasm_expr *wrt = yasm_expr_extract_wrt(&ea->disp);
ea->disp =
yasm_expr_create(YASM_EXPR_SUB,
yasm_expr_expr(ea->disp),
yasm_expr_sym(eat.origin), bc->line);
+ if (wrt) {
+ ea->disp =
+ yasm_expr_create(YASM_EXPR_WRT,
+ yasm_expr_expr(ea->disp),
+ yasm_expr_expr(wrt), bc->line);
+ }
if (output_expr(&ea->disp, *bufp, ea->len,
(size_t)(ea->len*8), 0,
(unsigned long)(*bufp-bufp_orig), bc, 1, 1,
unsigned int i;
unsigned char *bufp_orig = *bufp;
/*@null@*/ yasm_expr *targetseg;
+ /*@null@*/ yasm_expr *wrt;
yasm_expr *dup;
/* Prefixes */
YASM_WRITE_8(*bufp, jmp->shortop.opcode[i]);
/* Relative displacement */
+ wrt = yasm_expr_extract_wrt(&jmp->target);
jmp->target =
yasm_expr_create(YASM_EXPR_SUB, yasm_expr_expr(jmp->target),
yasm_expr_sym(jmp->origin), bc->line);
+ if (wrt)
+ jmp->target = yasm_expr_create_tree(jmp->target,
+ YASM_EXPR_WRT, wrt,
+ bc->line);
if (output_expr(&jmp->target, *bufp, 1, 8, 0,
(unsigned long)(*bufp-bufp_orig), bc, 1, 1, d))
return 1;
YASM_WRITE_8(*bufp, jmp->nearop.opcode[i]);
/* Relative displacement */
+ wrt = yasm_expr_extract_wrt(&jmp->target);
jmp->target =
yasm_expr_create(YASM_EXPR_SUB, yasm_expr_expr(jmp->target),
yasm_expr_sym(jmp->origin), bc->line);
+ if (wrt)
+ jmp->target = yasm_expr_create_tree(jmp->target,
+ YASM_EXPR_WRT, wrt,
+ bc->line);
i = (opersize == 16) ? 2 : 4;
if (output_expr(&jmp->target, *bufp, i, i*8, 0,
(unsigned long)(*bufp-bufp_orig), bc, 1, 1, d))
return 0;
}
+int
+yasm_x86__intnum_fixup_rel(yasm_arch *arch, yasm_intnum *intn, size_t valsize,
+ const yasm_bytecode *bc, unsigned long line)
+{
+ yasm_intnum *delta;
+ if (valsize != 8 && valsize != 16 && valsize != 32)
+ yasm_internal_error(
+ N_("tried to do PC-relative offset from invalid sized value"));
+ delta = yasm_intnum_create_uint(bc->len);
+ yasm_intnum_calc(intn, YASM_EXPR_SUB, delta, line);
+ yasm_intnum_destroy(delta);
+ return 0;
+}
+
int
yasm_x86__intnum_tobytes(yasm_arch *arch, const yasm_intnum *intn,
unsigned char *buf, size_t destsize, size_t valsize,
- int shift, const yasm_bytecode *bc, int rel, int warn,
+ int shift, const yasm_bytecode *bc, int warn,
unsigned long line)
{
- if (rel) {
- yasm_intnum *relnum, *delta;
- if (valsize != 8 && valsize != 16 && valsize != 32)
- yasm_internal_error(
- N_("tried to do PC-relative offset from invalid sized value"));
- relnum = yasm_intnum_copy(intn);
- delta = yasm_intnum_create_uint(bc->len);
- yasm_intnum_calc(relnum, YASM_EXPR_SUB, delta, line);
- yasm_intnum_destroy(delta);
- yasm_intnum_get_sized(relnum, buf, destsize, valsize, shift, 0, warn,
- line);
- yasm_intnum_destroy(relnum);
- } else {
- /* Write value out. */
- yasm_intnum_get_sized(intn, buf, destsize, valsize, shift, 0, warn,
- line);
- }
+ /* Write value out. */
+ yasm_intnum_get_sized(intn, buf, destsize, valsize, shift, 0, warn,
+ line);
return 0;
}
case YASM_EXPR_ADD:
case YASM_EXPR_IDENT:
break;
- case YASM_EXPR_WRT:
- /* Allow expr WRT rip in 64-bit mode. */
- if (bits != 64 || i != 1)
- return 0;
- break;
default:
return 0;
}
* and 0 if all values successfully determined and saved in data.
*/
static int
-x86_expr_checkea_getregusage(yasm_expr **ep, /*@null@*/ int *indexreg,
- unsigned char *pcrel, unsigned int bits, void *data,
- int *(*get_reg)(yasm_expr__item *ei, int *regnum, void *d),
+x86_expr_checkea_getregusage(yasm_expr **ep, /*@null@*/ yasm_expr **wrt,
+ /*@null@*/ int *indexreg, unsigned char *pcrel, unsigned int bits,
+ void *data, int *(*get_reg)(yasm_expr__item *ei, int *regnum, void *d),
yasm_calc_bc_dist_func calc_bc_dist)
{
int i;
/*@-unqualifiedtrans@*/
*ep = yasm_expr__level_tree(*ep, 1, indexreg == 0, calc_bc_dist, NULL,
NULL, NULL);
+ if (*wrt)
+ *wrt = yasm_expr__level_tree(*wrt, 1, indexreg == 0, calc_bc_dist,
+ NULL, NULL, NULL);
/*@=unqualifiedtrans@*/
assert(*ep != NULL);
e = *ep;
break;
}
- switch (e->op) {
- case YASM_EXPR_WRT:
- /* Handle xx WRT rip. */
- if (e->terms[1].type == YASM_EXPR_REG) {
- if (bits != 64) /* only valid in 64-bit mode */
- return 1;
- reg = get_reg(&e->terms[1], ®num, data);
- if (!reg || regnum != 16) /* only accept rip */
- return 1;
- (*reg)++;
+ if (*wrt && (*wrt)->op == YASM_EXPR_IDENT &&
+ (*wrt)->terms[0].type == YASM_EXPR_REG) {
+ /* Handle xx WRT rip. */
+ if (bits != 64) /* only valid in 64-bit mode */
+ return 1;
+ reg = get_reg(&(*wrt)->terms[0], ®num, data);
+ if (!reg || regnum != 16) /* only accept rip */
+ return 1;
+ (*reg)++;
- /* Simplify WRT to ident. Set pcrel to 1 to indicate to x86
- * bytecode code to do PC-relative displacement transform.
- */
- *pcrel = 1;
- e->op = YASM_EXPR_IDENT;
- e->numterms = 1;
- /* Delete the intnum created by get_reg(). */
- yasm_intnum_destroy(e->terms[1].data.intn);
- }
- break;
+ /* Delete WRT. Set pcrel to 1 to indicate to x86
+ * bytecode code to do PC-relative displacement transform.
+ */
+ *pcrel = 1;
+ yasm_expr_destroy(*wrt);
+
+ /* Drill down to next WRT and recurse if there was one. */
+ *wrt = yasm_expr_extract_wrt(ep);
+ if (*wrt)
+ return x86_expr_checkea_getregusage(ep, wrt, indexreg, pcrel,
+ bits, data, get_reg,
+ calc_bc_dist);
+ }
+
+ switch (e->op) {
case YASM_EXPR_ADD:
/* Prescan for non-int multipliers against a reg.
* This is because if any of the terms is a more complex
unsigned char *rex,
yasm_calc_bc_dist_func calc_bc_dist)
{
- yasm_expr *e = *ep;
+ yasm_expr *e, *wrt;
+ int retval;
+
+ /* First split off any top-level WRT. We'll add it back in at the end */
+ wrt = yasm_expr_extract_wrt(ep);
+ e = *ep;
if (*addrsize == 0) {
/* we need to figure out the address size from what we know about:
reg3264_data.regs = reg3264mult;
reg3264_data.bits = bits;
reg3264_data.addrsize = *addrsize;
- switch (x86_expr_checkea_getregusage(ep, &indexreg, pcrel, bits,
+ switch (x86_expr_checkea_getregusage(ep, &wrt, &indexreg, pcrel, bits,
®3264_data,
x86_expr_checkea_get_reg3264,
calc_bc_dist)) {
yasm__error(e->line, N_("invalid effective address"));
return 1;
case 2:
+ if (wrt)
+ *ep = yasm_expr_create_tree(*ep, YASM_EXPR_WRT, wrt,
+ (*ep)->line);
return 2;
default:
e = *ep;
/* RIP always requires a 32-bit displacement */
*v_modrm = 1;
*displen = 4;
+ if (wrt)
+ *ep = yasm_expr_create_tree(*ep, YASM_EXPR_WRT, wrt,
+ (*ep)->line);
return 0;
} else if (indexreg == REG3264_NONE) {
/* basereg only */
}
/* Calculate displacement length (if possible) */
- return x86_checkea_calc_displen(ep, 4, basereg == REG3264_NONE,
+ retval = x86_checkea_calc_displen(ep, 4, basereg == REG3264_NONE,
basereg == REG3264_EBP || basereg == REG64_R13, displen, modrm,
v_modrm);
+ if (wrt)
+ *ep = yasm_expr_create_tree(*ep, YASM_EXPR_WRT, wrt, (*ep)->line);
+ return retval;
} else if (*addrsize == 16 && *n_modrm && !*v_modrm) {
static const unsigned char modrm16[16] = {
0006 /* disp16 */, 0007 /* [BX] */, 0004 /* [SI] */,
*v_sib = 0;
*n_sib = 0;
- switch (x86_expr_checkea_getregusage(ep, (int *)NULL, pcrel, bits,
- ®16mult,
+ switch (x86_expr_checkea_getregusage(ep, &wrt, (int *)NULL, pcrel,
+ bits, ®16mult,
x86_expr_checkea_get_reg16,
calc_bc_dist)) {
case 1:
yasm__error(e->line, N_("invalid effective address"));
return 1;
case 2:
+ if (wrt)
+ *ep = yasm_expr_create_tree(*ep, YASM_EXPR_WRT, wrt,
+ (*ep)->line);
return 2;
default:
e = *ep;
*modrm |= modrm16[havereg];
/* Calculate displacement length (if possible) */
- return x86_checkea_calc_displen(ep, 2, havereg == HAVE_NONE,
- havereg == HAVE_BP, displen, modrm,
- v_modrm);
+ retval = x86_checkea_calc_displen(ep, 2, havereg == HAVE_NONE,
+ havereg == HAVE_BP, displen, modrm,
+ v_modrm);
+ if (wrt)
+ *ep = yasm_expr_create_tree(*ep, YASM_EXPR_WRT, wrt, (*ep)->line);
+ return retval;
} else if (!*n_modrm && !*n_sib) {
/* Special case for MOV MemOffs opcode: displacement but no modrm. */
switch (*addrsize) {
break;
}
}
+ if (wrt)
+ *ep = yasm_expr_create_tree(*ep, YASM_EXPR_WRT, wrt, (*ep)->line);
return 0;
}
if (stab->symvalue != NULL) {
bc->offset += 8;
- output_reloc(stab->symvalue, bc, buf, 4, 32, 0, 0, d);
+ output_reloc(stab->symvalue, bc, buf, 4, 32, 0, d);
bc->offset -= 8;
buf += 4;
}
/*@null@*/ void *d)
{
/*@null@*/ nasm_listfmt_output_info *info = (nasm_listfmt_output_info *)d;
- /*@dependent@*/ /*@null@*/ const yasm_intnum *intn;
+ /*@dependent@*/ /*@null@*/ yasm_intnum *intn;
/*@dependent@*/ /*@null@*/ const yasm_floatnum *flt;
assert(info != NULL);
if (shift < 0)
yasm_internal_error(N_("attempting to negative shift a float"));
return yasm_arch_floatnum_tobytes(info->arch, flt, buf, destsize,
- valsize, (unsigned int)shift, warn,
+ valsize, (unsigned int)shift, 0,
bc->line);
}
intn = yasm_expr_get_intnum(ep, NULL);
if (intn)
return yasm_arch_intnum_tobytes(info->arch, intn, buf, destsize,
- valsize, shift, bc, rel, warn,
- bc->line);
+ valsize, shift, bc, 0, bc->line);
return 0;
}
int rel, int warn, /*@null@*/ void *d)
{
/*@null@*/ bin_objfmt_output_info *info = (bin_objfmt_output_info *)d;
- /*@dependent@*/ /*@null@*/ const yasm_intnum *intn;
+ /*@dependent@*/ /*@null@*/ yasm_intnum *intn;
/*@dependent@*/ /*@null@*/ const yasm_floatnum *flt;
assert(info != NULL);
/* Handle integer expressions */
intn = yasm_expr_get_intnum(ep, NULL);
- if (intn)
+ if (intn) {
+ if (rel) {
+ int retval = yasm_arch_intnum_fixup_rel(info->objfmt_bin->arch,
+ intn, valsize, bc,
+ bc->line);
+ if (retval)
+ return retval;
+ }
return yasm_arch_intnum_tobytes(info->objfmt_bin->arch, intn, buf,
- destsize, valsize, shift, bc, rel,
- warn, bc->line);
+ destsize, valsize, shift, bc, warn,
+ bc->line);
+ }
/* Check for complex float expressions */
if (yasm_expr__contains(*ep, YASM_EXPR_FLOAT)) {
{
/*@null@*/ coff_objfmt_output_info *info = (coff_objfmt_output_info *)d;
yasm_objfmt_coff *objfmt_coff;
- /*@dependent@*/ /*@null@*/ const yasm_intnum *intn;
+ /*@dependent@*/ /*@null@*/ yasm_intnum *intn;
/*@dependent@*/ /*@null@*/ const yasm_floatnum *flt;
/*@dependent@*/ /*@null@*/ yasm_symrec *sym;
/*@dependent@*/ yasm_section *label_sect;
yasm_section_add_reloc(info->sect, (yasm_reloc *)reloc, yasm_xfree);
}
intn = yasm_expr_get_intnum(ep, NULL);
- if (intn)
+ if (intn) {
+ if (rel) {
+ int retval = yasm_arch_intnum_fixup_rel(objfmt_coff->arch, intn,
+ valsize, bc, bc->line);
+ if (retval)
+ return retval;
+ }
return yasm_arch_intnum_tobytes(objfmt_coff->arch, intn, buf, destsize,
- valsize, shift, bc, rel, warn,
- bc->line);
+ valsize, shift, bc, warn, bc->line);
+ }
/* Check for complex float expressions */
if (yasm_expr__contains(*ep, YASM_EXPR_FLOAT)) {
#define YASM_WRITE_64Z_L(p, i) YASM_WRITE_64C_L(p, 0, i)
-typedef int(*func_accepts_size_t)(size_t);
+typedef int(*func_accepts_reloc)(size_t val, yasm_symrec *wrt,
+ yasm_symrec **ssyms);
typedef void(*func_write_symtab_entry)(unsigned char *bufp,
elf_symtab_entry *entry,
yasm_intnum *value_intn,
typedef void(*func_handle_reloc_addend)(yasm_intnum *intn,
elf_reloc_entry *reloc);
-typedef unsigned int(*func_map_reloc_info_to_type)(elf_reloc_entry *reloc);
+typedef unsigned int(*func_map_reloc_info_to_type)(elf_reloc_entry *reloc,
+ yasm_symrec **ssyms);
typedef void(*func_write_reloc)(unsigned char *bufp,
elf_reloc_entry *reloc,
unsigned int r_type,
unsigned long secthead_count,
elf_section_index shstrtab_index);
+typedef struct {
+ const char *name; /* should be something like ..name */
+ const int sym_rel; /* symbol or section-relative? */
+} elf_machine_ssym;
+
typedef struct {
const char *arch;
const char *machine;
const unsigned long reloc_entry_size;
const unsigned long secthead_size;
const unsigned long proghead_size;
- func_accepts_size_t accepts_reloc_size;
+ func_accepts_reloc accepts_reloc;
func_write_symtab_entry write_symtab_entry;
func_write_secthead write_secthead;
func_write_secthead_rel write_secthead_rel;
func_map_reloc_info_to_type map_reloc_info_to_type;
func_write_reloc write_reloc;
func_write_proghead write_proghead;
+
+ const elf_machine_ssym *ssyms; /* array of "special" syms */
+ const size_t num_ssyms; /* size of array */
} elf_machine_handler;
#endif /* ELF_MACHINE_H_INCLUDED */
yasm_object *object;
yasm_symtab *symtab;
/*@dependent@*/ yasm_arch *arch;
+
+ yasm_symrec *dotdotsym; /* ..sym symbol */
} yasm_objfmt_elf;
typedef struct {
objfmt_elf->object = object;
objfmt_elf->symtab = yasm_object_get_symtab(object);
objfmt_elf->arch = a;
- if (!elf_set_arch(a)) {
+ if (!elf_set_arch(a, objfmt_elf->symtab)) {
yasm_xfree(objfmt_elf);
return NULL;
}
objfmt_elf->elf_symtab = elf_symtab_create();
/* FIXME: misuse of NULL bytecode here; it works, but only barely. */
- filesym = yasm_symtab_define_label(yasm_object_get_symtab(object), ".file",
- NULL, 0, 0);
+ filesym = yasm_symtab_define_label(objfmt_elf->symtab, ".file", NULL, 0,
+ 0);
entry = elf_symtab_entry_create(
elf_strtab_append_str(objfmt_elf->strtab, in_filename), filesym);
yasm_symrec_add_data(filesym, &elf_symrec_data, entry);
elf_symtab_set_nonzero(entry, NULL, SHN_ABS, STB_LOCAL, STT_FILE, NULL, 0);
elf_symtab_append_entry(objfmt_elf->elf_symtab, entry);
+ /* FIXME: misuse of NULL bytecode */
+ objfmt_elf->dotdotsym = yasm_symtab_define_label(objfmt_elf->symtab,
+ "..sym", NULL, 1, 0);
+
return (yasm_objfmt *)objfmt_elf;
}
static int
elf_objfmt_output_reloc(yasm_symrec *sym, yasm_bytecode *bc,
unsigned char *buf, size_t destsize, size_t valsize,
- int rel, int warn, void *d)
+ int warn, void *d)
{
elf_reloc_entry *reloc;
elf_objfmt_output_info *info = d;
yasm_intnum *zero;
int retval;
- reloc = elf_reloc_entry_create(sym,
- yasm_intnum_create_uint(bc->offset), rel, valsize);
+ reloc = elf_reloc_entry_create(sym, NULL,
+ yasm_intnum_create_uint(bc->offset), 0, valsize);
if (reloc == NULL) {
yasm__error(bc->line, N_("elf: invalid relocation size"));
return 1;
zero = yasm_intnum_create_uint(0);
elf_handle_reloc_addend(zero, reloc);
retval = yasm_arch_intnum_tobytes(info->objfmt_elf->arch, zero, buf,
- destsize, valsize, 0, bc, rel, warn,
+ destsize, valsize, 0, bc, warn,
bc->line);
yasm_intnum_destroy(zero);
return retval;
/*@dependent@*/ /*@null@*/ const yasm_floatnum *flt;
/*@dependent@*/ /*@null@*/ yasm_symrec *sym;
/*@null@*/ elf_reloc_entry *reloc = NULL;
+ /*@null@*/ yasm_expr *wrt_expr;
+ /*@dependent@*/ /*@null@*/ yasm_symrec *wrt = NULL;
if (info == NULL)
yasm_internal_error("null info struct");
(unsigned int)shift, warn, bc->line);
}
+ /* Check for a WRT relocation */
+ wrt_expr = yasm_expr_extract_wrt(ep);
+ if (wrt_expr) {
+ wrt = yasm_expr_extract_symrec(&wrt_expr, 0,
+ yasm_common_calc_bc_dist);
+ yasm_expr_destroy(wrt_expr);
+ if (!wrt) {
+ yasm__error(bc->line, N_("WRT expression too complex"));
+ return 1;
+ }
+ }
+
/* Handle integer expressions, with relocation if necessary */
- sym = yasm_expr_extract_symrec(ep, 1, yasm_common_calc_bc_dist);
+ sym = yasm_expr_extract_symrec(ep,
+ !(wrt == info->objfmt_elf->dotdotsym ||
+ (wrt && elf_is_wrt_sym_relative(wrt))),
+ yasm_common_calc_bc_dist);
if (sym) {
yasm_sym_vis vis;
vis = yasm_symrec_get_visibility(sym);
- if (!(vis & (YASM_SYM_COMMON|YASM_SYM_EXTERN)))
+ if (wrt == info->objfmt_elf->dotdotsym)
+ wrt = NULL;
+ else if (wrt && elf_is_wrt_sym_relative(wrt))
+ ;
+ else if (!(vis & (YASM_SYM_COMMON|YASM_SYM_EXTERN)))
{
yasm_bytecode *label_precbc;
/* Local symbols need relocation to their section's start */
*ep = yasm_expr_simplify(*ep, yasm_common_calc_bc_dist);
}
- reloc = elf_reloc_entry_create(sym,
+ reloc = elf_reloc_entry_create(sym, wrt,
yasm_intnum_create_uint(bc->offset + offset), rel, valsize);
if (reloc == NULL) {
- yasm__error(bc->line, N_("elf: invalid relocation size"));
+ yasm__error(bc->line, N_("elf: invalid relocation (WRT or size)"));
return 1;
}
/* allocate .rel[a] sections on a need-basis */
}
intn = yasm_expr_get_intnum(ep, NULL);
- if (intn && reloc)
- elf_handle_reloc_addend(intn, reloc);
- if (intn)
+ if (intn) {
+ if (rel) {
+ int retval = yasm_arch_intnum_fixup_rel(info->objfmt_elf->arch,
+ intn, valsize, bc,
+ bc->line);
+ if (retval)
+ return retval;
+ }
+ if (reloc)
+ elf_handle_reloc_addend(intn, reloc);
return yasm_arch_intnum_tobytes(info->objfmt_elf->arch, intn, buf,
- destsize, valsize, shift, bc, rel,
- warn, bc->line);
+ destsize, valsize, shift, bc, warn,
+ bc->line);
+ }
/* Check for complex float expressions */
if (yasm_expr__contains(*ep, YASM_EXPR_FLOAT)) {
*/
#include <util.h>
-/*@unused@*/ RCSID("$Id:$");
+/*@unused@*/ RCSID("$Id$");
#define YASM_LIB_INTERNAL
#define YASM_EXPR_INTERNAL
#include "elf.h"
#include "elf-machine.h"
+enum ssym_index {
+ SSYM_GOTPCREL = 0,
+ SSYM_GOT,
+ SSYM_PLT
+};
+
static int
-elf_x86_amd64_accepts_reloc_size(size_t val)
+elf_x86_amd64_accepts_reloc(size_t val, yasm_symrec *wrt, yasm_symrec **ssyms)
{
+ if (wrt) {
+ if ((wrt == ssyms[SSYM_GOTPCREL] && val == 32)
+ || (wrt == ssyms[SSYM_GOT] && val == 32)
+ || (wrt == ssyms[SSYM_PLT] && val == 32))
+ return 1;
+ else
+ return 0;
+ }
return (val&(val-1)) ? 0 : ((val & (8|16|32|64)) != 0);
}
}
static unsigned int
-elf_x86_amd64_map_reloc_info_to_type(elf_reloc_entry *reloc)
+elf_x86_amd64_map_reloc_info_to_type(elf_reloc_entry *reloc,
+ yasm_symrec **ssyms)
{
- if (reloc->rtype_rel) {
+ if (reloc->wrt) {
+ if (reloc->wrt == ssyms[SSYM_GOTPCREL] && reloc->valsize == 32)
+ return (unsigned char) R_X86_64_GOTPCREL;
+ else if (reloc->wrt == ssyms[SSYM_GOT] && reloc->valsize == 32)
+ return (unsigned char) R_X86_64_GOT32;
+ else if (reloc->wrt == ssyms[SSYM_PLT] && reloc->valsize == 32)
+ return (unsigned char) R_X86_64_PLT32;
+ else
+ yasm_internal_error(N_("Unsupported WRT"));
+ } else if (reloc->rtype_rel) {
switch (reloc->valsize) {
case 8: return (unsigned char) R_X86_64_PC8;
case 16: return (unsigned char) R_X86_64_PC16;
*bufpp = bufp;
}
+static elf_machine_ssym elf_x86_amd64_ssyms[] = {
+ {"..gotpcrel", 1},
+ {"..got", 1},
+ {"..plt", 0}
+};
+
const elf_machine_handler
elf_machine_handler_x86_amd64 = {
"x86", "amd64", ".rela",
SYMTAB64_SIZE, SYMTAB64_ALIGN, RELOC64A_SIZE, SHDR64_SIZE, EHDR64_SIZE,
- elf_x86_amd64_accepts_reloc_size,
+ elf_x86_amd64_accepts_reloc,
elf_x86_amd64_write_symtab_entry,
elf_x86_amd64_write_secthead,
elf_x86_amd64_write_secthead_rel,
elf_x86_amd64_handle_reloc_addend,
elf_x86_amd64_map_reloc_info_to_type,
elf_x86_amd64_write_reloc,
- elf_x86_amd64_write_proghead
+ elf_x86_amd64_write_proghead,
+ elf_x86_amd64_ssyms,
+ sizeof(elf_x86_amd64_ssyms)/sizeof(elf_x86_amd64_ssyms[0])
};
*/
#include <util.h>
-/*@unused@*/ RCSID("$Id:$");
+/*@unused@*/ RCSID("$Id$");
#define YASM_LIB_INTERNAL
#define YASM_EXPR_INTERNAL
#include "elf.h"
#include "elf-machine.h"
+enum ssym_index {
+ SSYM_GOTPC = 0,
+ SSYM_GOTOFF,
+ SSYM_GOT,
+ SSYM_PLT
+};
+
static int
-elf_x86_x86_accepts_reloc_size(size_t val)
+elf_x86_x86_accepts_reloc(size_t val, yasm_symrec *wrt, yasm_symrec **ssyms)
{
+ if (wrt) {
+ if ((wrt == ssyms[SSYM_GOTPC] && val == 32)
+ || (wrt == ssyms[SSYM_GOTOFF] && val == 32)
+ || (wrt == ssyms[SSYM_GOT] && val == 32)
+ || (wrt == ssyms[SSYM_PLT] && val == 32))
+ return 1;
+ else
+ return 0;
+ }
return (val&(val-1)) ? 0 : ((val & (8|16|32)) != 0);
}
}
static unsigned int
-elf_x86_x86_map_reloc_info_to_type(elf_reloc_entry *reloc)
+elf_x86_x86_map_reloc_info_to_type(elf_reloc_entry *reloc,
+ yasm_symrec **ssyms)
{
- if (reloc->rtype_rel) {
+ if (reloc->wrt) {
+ if (reloc->wrt == ssyms[SSYM_GOTPC] && reloc->valsize == 32)
+ return (unsigned char) R_386_GOTPC;
+ else if (reloc->wrt == ssyms[SSYM_GOTOFF] && reloc->valsize == 32)
+ return (unsigned char) R_386_GOTOFF;
+ else if (reloc->wrt == ssyms[SSYM_GOT] && reloc->valsize == 32)
+ return (unsigned char) R_386_GOT32;
+ else if (reloc->wrt == ssyms[SSYM_PLT] && reloc->valsize == 32)
+ return (unsigned char) R_386_PLT32;
+ else
+ yasm_internal_error(N_("Unsupported WRT"));
+ } else if (reloc->rtype_rel) {
switch (reloc->valsize) {
case 8: return (unsigned char) R_386_PC8;
case 16: return (unsigned char) R_386_PC16;
*bufpp = bufp;
}
+static elf_machine_ssym elf_x86_x86_ssyms[] = {
+ {"..gotpc", 0},
+ {"..gotoff", 0},
+ {"..got", 1},
+ {"..plt", 0}
+};
+
const elf_machine_handler
elf_machine_handler_x86_x86 = {
"x86", "x86", ".rel",
SYMTAB32_SIZE, SYMTAB32_ALIGN, RELOC32_SIZE, SHDR32_SIZE, EHDR32_SIZE,
- elf_x86_x86_accepts_reloc_size,
+ elf_x86_x86_accepts_reloc,
elf_x86_x86_write_symtab_entry,
elf_x86_x86_write_secthead,
elf_x86_x86_write_secthead_rel,
elf_x86_x86_handle_reloc_addend,
elf_x86_x86_map_reloc_info_to_type,
elf_x86_x86_write_reloc,
- elf_x86_x86_write_proghead
+ elf_x86_x86_write_proghead,
+ elf_x86_x86_ssyms,
+ sizeof(elf_x86_x86_ssyms)/sizeof(elf_x86_x86_ssyms[0])
};
};
static const elf_machine_handler elf_null_machine = {0};
static elf_machine_handler const *elf_march = &elf_null_machine;
+static yasm_symrec **elf_ssyms;
int
-elf_set_arch(yasm_arch *arch)
+elf_set_arch(yasm_arch *arch, yasm_symtab *symtab)
{
const char *machine = yasm_arch_get_machine(arch);
int i;
if (yasm__strcasecmp(machine, elf_march->machine)==0)
break;
}
+
+ if (elf_march && elf_march->num_ssyms > 0)
+ {
+ /* Allocate "special" syms */
+ elf_ssyms =
+ yasm_xmalloc(elf_march->num_ssyms * sizeof(yasm_symrec *));
+ for (i=0; (unsigned int)i<elf_march->num_ssyms; i++)
+ {
+ /* FIXME: misuse of NULL bytecode */
+ elf_ssyms[i] = yasm_symtab_define_label(symtab,
+ elf_march->ssyms[i].name,
+ NULL, 1, 0);
+ }
+ }
+
return elf_march != NULL;
}
/* reloc functions */
+int
+elf_is_wrt_sym_relative(yasm_symrec *wrt)
+{
+ int i;
+ for (i=0; (unsigned int)i<elf_march->num_ssyms; i++) {
+ if (elf_ssyms[i] == wrt)
+ return elf_march->ssyms[i].sym_rel;
+ }
+ return 0;
+}
+
/* takes ownership of addr */
elf_reloc_entry *
elf_reloc_entry_create(yasm_symrec *sym,
+ yasm_symrec *wrt,
yasm_intnum *addr,
int rel,
size_t valsize)
{
elf_reloc_entry *entry;
- if (!elf_march->accepts_reloc_size)
+ if (!elf_march->accepts_reloc)
yasm_internal_error(N_("Unsupported machine for ELF output"));
- if (!elf_march->accepts_reloc_size(valsize))
+ if (!elf_march->accepts_reloc(valsize, wrt, elf_ssyms))
{
if (addr)
yasm_intnum_destroy(addr);
entry->rtype_rel = rel;
entry->valsize = valsize;
entry->addend = NULL;
+ entry->wrt = wrt;
return entry;
}
vis = yasm_symrec_get_visibility(reloc->reloc.sym);
if (!elf_march->map_reloc_info_to_type)
yasm_internal_error(N_("Unsupported arch/machine for elf output"));
- r_type = elf_march->map_reloc_info_to_type(reloc);
+ r_type = elf_march->map_reloc_info_to_type(reloc, elf_ssyms);
bufp = buf;
if (!elf_march->write_reloc || !elf_march->reloc_entry_size)
int rtype_rel;
size_t valsize;
yasm_intnum *addend;
+ /*@null@*/ yasm_symrec *wrt;
};
STAILQ_HEAD(elf_strtab_head, elf_strtab_entry);
extern const yasm_assoc_data_callback elf_symrec_data;
-int elf_set_arch(struct yasm_arch *arch);
+int elf_set_arch(struct yasm_arch *arch, yasm_symtab *symtab);
/* reloc functions */
+int elf_is_wrt_sym_relative(yasm_symrec *wrt);
elf_reloc_entry *elf_reloc_entry_create(yasm_symrec *sym,
+ /*@null@*/ yasm_symrec *wrt,
yasm_intnum *addr,
int rel,
size_t valsize);
EXTRA_DIST += modules/objfmts/elf/tests/elfsectalign.asm
EXTRA_DIST += modules/objfmts/elf/tests/elfsectalign.hex
EXTRA_DIST += modules/objfmts/elf/tests/elfsectalign.errwarn
+EXTRA_DIST += modules/objfmts/elf/tests/elfso.asm
+EXTRA_DIST += modules/objfmts/elf/tests/elfso.hex
+EXTRA_DIST += modules/objfmts/elf/tests/elfso.errwarn
EXTRA_DIST += modules/objfmts/elf/tests/elftest.c
EXTRA_DIST += modules/objfmts/elf/tests/elftest.asm
EXTRA_DIST += modules/objfmts/elf/tests/elftest.hex
EXTRA_DIST += modules/objfmts/elf/tests/amd64/elf-rip.asm
EXTRA_DIST += modules/objfmts/elf/tests/amd64/elf-rip.hex
EXTRA_DIST += modules/objfmts/elf/tests/amd64/elf-rip.errwarn
+EXTRA_DIST += modules/objfmts/elf/tests/amd64/elfso64.asm
+EXTRA_DIST += modules/objfmts/elf/tests/amd64/elfso64.hex
+EXTRA_DIST += modules/objfmts/elf/tests/amd64/elfso64.errwarn
00
8b
05
-fa
-ff
-ff
-ff
-e8
-fb
-ff
-ff
-ff
00
00
00
-0e
00
+e8
00
00
00
00
00
00
-0a
+00
+0e
00
00
00
-03
00
00
00
00
+0a
00
00
00
+03
00
00
00
00
-14
00
00
00
00
00
00
-02
+14
00
00
00
-03
00
00
00
-02
00
+02
00
00
00
+03
00
00
00
+fc
+ff
+ff
+ff
+ff
+ff
+ff
+ff
19
00
00
00
00
00
-01
-00
-00
-00
-00
-00
-00
-00
+fc
+ff
+ff
+ff
+ff
+ff
+ff
+ff
00
2e
74
--- /dev/null
+; This code is UNTESTED, and almost certainly DOES NOT WORK!
+; Do NOT use this as an example of how to write AMD64 shared libraries!
+; This code is simply to test the AMD64 ELF WRT relocations.
+
+; This file should test the following:
+; [1] Define and export a global text-section symbol
+; [2] Define and export a global data-section symbol
+; [3] Define and export a global BSS-section symbol
+; [4] Define a non-global text-section symbol
+; [5] Define a non-global data-section symbol
+; [6] Define a non-global BSS-section symbol
+; [7] Define a COMMON symbol
+; [8] Define a NASM local label
+; [9] Reference a NASM local label
+; [10] Import an external symbol
+; [11] Make a PC-relative call to an external symbol
+; [12] Reference a text-section symbol in the text section
+; [13] Reference a data-section symbol in the text section
+; [14] Reference a BSS-section symbol in the text section
+; [15] Reference a text-section symbol in the data section
+; [16] Reference a data-section symbol in the data section
+; [17] Reference a BSS-section symbol in the data section
+
+ BITS 64
+ GLOBAL lrotate:function ; [1]
+ GLOBAL greet:function ; [1]
+ GLOBAL asmstr:data asmstr.end-asmstr ; [2]
+ GLOBAL textptr:data 4 ; [2]
+ GLOBAL selfptr:data 4 ; [2]
+ GLOBAL integer:data 4 ; [3]
+ EXTERN printf ; [10]
+ COMMON commvar 4:4 ; [7]
+ EXTERN _GLOBAL_OFFSET_TABLE_
+
+ SECTION .text
+
+; prototype: long lrotate(long x, int num);
+lrotate: ; [1]
+ push rbp
+ mov rbp,rsp
+ mov rax,[rbp+8]
+ mov rcx,[rbp+12]
+.label rol rax,1 ; [4] [8]
+ loop .label ; [9] [12]
+ mov rsp,rbp
+ pop rbp
+ ret
+
+; prototype: void greet(void);
+greet push rbx ; we'll use RBX for GOT, so save it
+ mov rbx,[integer wrt ..gotpcrel wrt rip]
+ mov rax,[rbx] ; [14]
+ inc rax
+ mov rbx,[_GLOBAL_OFFSET_TABLE_ wrt ..gotpcrel wrt rip]
+ mov [rbx+localint wrt ..got],eax ; [14]
+ mov rax,[rbx+commvar wrt ..got]
+ push qword [rax]
+ mov rax,[rbx+localptr wrt ..got] ; [13]
+ push qword [rax]
+ mov rax,[rbx+integer wrt ..got] ; [1] [14]
+ push qword [rax]
+ lea rax,[rbx+printfstr wrt ..got]
+ push rax ; [13]
+ call printf wrt ..plt ; [11]
+ add rsp,16
+ pop rbx
+ ret
+
+ SECTION .data
+
+; a string
+asmstr db 'hello, world', 0 ; [2]
+.end
+
+; a string for Printf
+printfstr db "integer==%d, localint==%d, commvar=%d"
+ db 10, 0
+
+; some pointers
+localptr dd localint ; [5] [17]
+textptr dd greet wrt ..sym ; [15]
+selfptr dd selfptr wrt ..sym ; [16]
+
+ SECTION .bss
+
+; an integer
+integer resd 1 ; [3]
+
+; a local integer
+localint resd 1 ; [6]
--- /dev/null
+7f
+45
+4c
+46
+02
+01
+01
+00
+00
+00
+00
+00
+00
+00
+00
+00
+01
+00
+3e
+00
+01
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+50
+04
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+40
+00
+00
+00
+00
+00
+40
+00
+09
+00
+01
+00
+55
+48
+89
+e5
+48
+8b
+45
+08
+48
+8b
+4d
+0c
+48
+d1
+c0
+e2
+fb
+48
+89
+ec
+5d
+c3
+53
+48
+8b
+1d
+00
+00
+00
+00
+48
+8b
+03
+48
+ff
+c0
+48
+8b
+1d
+00
+00
+00
+00
+89
+83
+00
+00
+00
+00
+48
+8b
+83
+00
+00
+00
+00
+ff
+30
+48
+8b
+83
+00
+00
+00
+00
+ff
+30
+48
+8b
+83
+00
+00
+00
+00
+ff
+30
+48
+8d
+83
+00
+00
+00
+00
+50
+e8
+00
+00
+00
+00
+48
+81
+c4
+10
+00
+00
+00
+5b
+c3
+00
+00
+1a
+00
+00
+00
+00
+00
+00
+00
+09
+00
+00
+00
+0f
+00
+00
+00
+fc
+ff
+ff
+ff
+ff
+ff
+ff
+ff
+27
+00
+00
+00
+00
+00
+00
+00
+09
+00
+00
+00
+12
+00
+00
+00
+fc
+ff
+ff
+ff
+ff
+ff
+ff
+ff
+2d
+00
+00
+00
+00
+00
+00
+00
+03
+00
+00
+00
+05
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+34
+00
+00
+00
+00
+00
+00
+00
+03
+00
+00
+00
+11
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+3d
+00
+00
+00
+00
+00
+00
+00
+03
+00
+00
+00
+06
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+46
+00
+00
+00
+00
+00
+00
+00
+03
+00
+00
+00
+0f
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+4f
+00
+00
+00
+00
+00
+00
+00
+03
+00
+00
+00
+07
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+55
+00
+00
+00
+00
+00
+00
+00
+04
+00
+00
+00
+10
+00
+00
+00
+fc
+ff
+ff
+ff
+ff
+ff
+ff
+ff
+68
+65
+6c
+6c
+6f
+2c
+20
+77
+6f
+72
+6c
+64
+00
+69
+6e
+74
+65
+67
+65
+72
+3d
+3d
+25
+64
+2c
+20
+6c
+6f
+63
+61
+6c
+69
+6e
+74
+3d
+3d
+25
+64
+2c
+20
+63
+6f
+6d
+6d
+76
+61
+72
+3d
+25
+64
+0a
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+34
+00
+00
+00
+00
+00
+00
+00
+0a
+00
+00
+00
+09
+00
+00
+00
+04
+00
+00
+00
+00
+00
+00
+00
+38
+00
+00
+00
+00
+00
+00
+00
+0a
+00
+00
+00
+0b
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+3c
+00
+00
+00
+00
+00
+00
+00
+0a
+00
+00
+00
+0e
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+2e
+74
+65
+78
+74
+00
+2e
+64
+61
+74
+61
+00
+2e
+62
+73
+73
+00
+2e
+72
+65
+6c
+61
+2e
+74
+65
+78
+74
+00
+2e
+72
+65
+6c
+61
+2e
+64
+61
+74
+61
+00
+2e
+73
+74
+72
+74
+61
+62
+00
+2e
+73
+79
+6d
+74
+61
+62
+00
+2e
+73
+68
+73
+74
+72
+74
+61
+62
+00
+00
+00
+00
+2d
+00
+6c
+72
+6f
+74
+61
+74
+65
+00
+67
+72
+65
+65
+74
+00
+61
+73
+6d
+73
+74
+72
+00
+74
+65
+78
+74
+70
+74
+72
+00
+73
+65
+6c
+66
+70
+74
+72
+00
+69
+6e
+74
+65
+67
+65
+72
+00
+70
+72
+69
+6e
+74
+66
+00
+63
+6f
+6d
+6d
+76
+61
+72
+00
+5f
+47
+4c
+4f
+42
+41
+4c
+5f
+4f
+46
+46
+53
+45
+54
+5f
+54
+41
+42
+4c
+45
+5f
+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
+04
+00
+f1
+ff
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+03
+00
+04
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+06
+00
+0d
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+04
+00
+0c
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+08
+00
+04
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+06
+00
+34
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+06
+00
+0d
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+03
+00
+06
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+03
+00
+08
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+03
+00
+00
+00
+12
+00
+04
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+0b
+00
+00
+00
+12
+00
+04
+00
+16
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+11
+00
+00
+00
+11
+00
+06
+00
+00
+00
+00
+00
+00
+00
+00
+00
+0d
+00
+00
+00
+00
+00
+00
+00
+18
+00
+00
+00
+11
+00
+06
+00
+38
+00
+00
+00
+00
+00
+00
+00
+04
+00
+00
+00
+00
+00
+00
+00
+20
+00
+00
+00
+11
+00
+06
+00
+3c
+00
+00
+00
+00
+00
+00
+00
+04
+00
+00
+00
+00
+00
+00
+00
+28
+00
+00
+00
+11
+00
+08
+00
+00
+00
+00
+00
+00
+00
+00
+00
+04
+00
+00
+00
+00
+00
+00
+00
+30
+00
+00
+00
+10
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+37
+00
+00
+00
+10
+00
+f2
+ff
+04
+00
+00
+00
+00
+00
+00
+00
+04
+00
+00
+00
+00
+00
+00
+00
+3f
+00
+00
+00
+10
+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
+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
+38
+00
+00
+00
+03
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ec
+01
+00
+00
+00
+00
+00
+00
+42
+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
+28
+00
+00
+00
+03
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+30
+02
+00
+00
+00
+00
+00
+00
+55
+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
+30
+00
+00
+00
+02
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+88
+02
+00
+00
+00
+00
+00
+00
+c8
+01
+00
+00
+00
+00
+00
+00
+02
+00
+00
+00
+0a
+00
+00
+00
+08
+00
+00
+00
+00
+00
+00
+00
+18
+00
+00
+00
+00
+00
+00
+00
+01
+00
+00
+00
+01
+00
+00
+00
+06
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+40
+00
+00
+00
+00
+00
+00
+00
+62
+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
+12
+00
+00
+00
+04
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+a4
+00
+00
+00
+00
+00
+00
+00
+c0
+00
+00
+00
+00
+00
+00
+00
+03
+00
+00
+00
+04
+00
+00
+00
+08
+00
+00
+00
+00
+00
+00
+00
+18
+00
+00
+00
+00
+00
+00
+00
+07
+00
+00
+00
+01
+00
+00
+00
+03
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+64
+01
+00
+00
+00
+00
+00
+00
+40
+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
+1d
+00
+00
+00
+04
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+a4
+01
+00
+00
+00
+00
+00
+00
+48
+00
+00
+00
+00
+00
+00
+00
+03
+00
+00
+00
+06
+00
+00
+00
+08
+00
+00
+00
+00
+00
+00
+00
+18
+00
+00
+00
+00
+00
+00
+00
+0d
+00
+00
+00
+08
+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
+00
+00
+08
+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
--- /dev/null
+; test source file for assembling to ELF shared library
+; build with:
+; nasm -f elf elfso.asm
+; ld -shared -o elfso.so elfso.o
+; test with:
+; gcc -o elfso elftest.c ./elfso.so
+; ./elfso
+; (assuming your gcc is ELF, and you're running bash)
+
+; This file should test the following:
+; [1] Define and export a global text-section symbol
+; [2] Define and export a global data-section symbol
+; [3] Define and export a global BSS-section symbol
+; [4] Define a non-global text-section symbol
+; [5] Define a non-global data-section symbol
+; [6] Define a non-global BSS-section symbol
+; [7] Define a COMMON symbol
+; [8] Define a NASM local label
+; [9] Reference a NASM local label
+; [10] Import an external symbol
+; [11] Make a PC-relative call to an external symbol
+; [12] Reference a text-section symbol in the text section
+; [13] Reference a data-section symbol in the text section
+; [14] Reference a BSS-section symbol in the text section
+; [15] Reference a text-section symbol in the data section
+; [16] Reference a data-section symbol in the data section
+; [17] Reference a BSS-section symbol in the data section
+
+ BITS 32
+ GLOBAL lrotate:function ; [1]
+ GLOBAL greet:function ; [1]
+ GLOBAL asmstr:data asmstr.end-asmstr ; [2]
+ GLOBAL textptr:data 4 ; [2]
+ GLOBAL selfptr:data 4 ; [2]
+ GLOBAL integer:data 4 ; [3]
+ EXTERN printf ; [10]
+ COMMON commvar 4:4 ; [7]
+ EXTERN _GLOBAL_OFFSET_TABLE_
+
+ SECTION .text
+
+; prototype: long lrotate(long x, int num);
+lrotate: ; [1]
+ push ebp
+ mov ebp,esp
+ mov eax,[ebp+8]
+ mov ecx,[ebp+12]
+.label rol eax,1 ; [4] [8]
+ loop .label ; [9] [12]
+ mov esp,ebp
+ pop ebp
+ ret
+
+; prototype: void greet(void);
+greet push ebx ; we'll use EBX for GOT, so save it
+ call .getgot
+.getgot: pop ebx
+ add ebx,_GLOBAL_OFFSET_TABLE_ + $$ - .getgot wrt ..gotpc
+ mov eax,[ebx+integer wrt ..got] ; [14]
+ mov eax,[eax]
+ inc eax
+ mov [ebx+localint wrt ..gotoff],eax ; [14]
+ mov eax,[ebx+commvar wrt ..got]
+ push dword [eax]
+ mov eax,[ebx+localptr wrt ..gotoff] ; [13]
+ push dword [eax]
+ mov eax,[ebx+integer wrt ..got] ; [1] [14]
+ push dword [eax]
+ lea eax,[ebx+printfstr wrt ..gotoff]
+ push eax ; [13]
+ call printf wrt ..plt ; [11]
+ add esp,16
+ pop ebx
+ ret
+
+ SECTION .data
+
+; a string
+asmstr db 'hello, world', 0 ; [2]
+.end
+
+; a string for Printf
+printfstr db "integer==%d, localint==%d, commvar=%d"
+ db 10, 0
+
+; some pointers
+localptr dd localint ; [5] [17]
+textptr dd greet wrt ..sym ; [15]
+selfptr dd selfptr wrt ..sym ; [16]
+
+ SECTION .bss
+
+; an integer
+integer resd 1 ; [3]
+
+; a local integer
+localint resd 1 ; [6]
--- /dev/null
+7f
+45
+4c
+46
+01
+01
+01
+00
+00
+00
+00
+00
+00
+00
+00
+00
+01
+00
+03
+00
+01
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+10
+03
+00
+00
+00
+00
+00
+00
+34
+00
+00
+00
+00
+00
+28
+00
+09
+00
+01
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+55
+89
+e5
+8b
+45
+08
+8b
+4d
+0c
+d1
+c0
+e2
+fc
+89
+ec
+5d
+c3
+53
+e8
+00
+00
+00
+00
+5b
+81
+c3
+e9
+ff
+ff
+ff
+8b
+83
+00
+00
+00
+00
+8b
+00
+40
+89
+83
+04
+00
+00
+00
+8b
+83
+00
+00
+00
+00
+ff
+30
+8b
+83
+34
+00
+00
+00
+ff
+30
+8b
+83
+00
+00
+00
+00
+ff
+30
+8d
+83
+0d
+00
+00
+00
+50
+e8
+fc
+ff
+ff
+ff
+81
+c4
+10
+00
+00
+00
+5b
+c3
+00
+00
+00
+1a
+00
+00
+00
+0a
+13
+00
+00
+20
+00
+00
+00
+03
+10
+00
+00
+29
+00
+00
+00
+09
+0a
+00
+00
+2f
+00
+00
+00
+03
+12
+00
+00
+37
+00
+00
+00
+09
+09
+00
+00
+3f
+00
+00
+00
+03
+10
+00
+00
+47
+00
+00
+00
+09
+09
+00
+00
+4d
+00
+00
+00
+04
+11
+00
+00
+68
+65
+6c
+6c
+6f
+2c
+20
+77
+6f
+72
+6c
+64
+00
+69
+6e
+74
+65
+67
+65
+72
+3d
+3d
+25
+64
+2c
+20
+6c
+6f
+63
+61
+6c
+69
+6e
+74
+3d
+3d
+25
+64
+2c
+20
+63
+6f
+6d
+6d
+76
+61
+72
+3d
+25
+64
+0a
+00
+04
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+34
+00
+00
+00
+01
+0a
+00
+00
+38
+00
+00
+00
+01
+0c
+00
+00
+3c
+00
+00
+00
+01
+0f
+00
+00
+00
+2e
+74
+65
+78
+74
+00
+2e
+64
+61
+74
+61
+00
+2e
+62
+73
+73
+00
+2e
+72
+65
+6c
+2e
+74
+65
+78
+74
+00
+2e
+72
+65
+6c
+2e
+64
+61
+74
+61
+00
+2e
+73
+74
+72
+74
+61
+62
+00
+2e
+73
+79
+6d
+74
+61
+62
+00
+2e
+73
+68
+73
+74
+72
+74
+61
+62
+00
+00
+2d
+00
+6c
+72
+6f
+74
+61
+74
+65
+00
+67
+72
+65
+65
+74
+00
+61
+73
+6d
+73
+74
+72
+00
+74
+65
+78
+74
+70
+74
+72
+00
+73
+65
+6c
+66
+70
+74
+72
+00
+69
+6e
+74
+65
+67
+65
+72
+00
+70
+72
+69
+6e
+74
+66
+00
+63
+6f
+6d
+6d
+76
+61
+72
+00
+5f
+47
+4c
+4f
+42
+41
+4c
+5f
+4f
+46
+46
+53
+45
+54
+5f
+54
+41
+42
+4c
+45
+5f
+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
+04
+00
+f1
+ff
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+03
+00
+04
+00
+00
+00
+00
+00
+0d
+00
+00
+00
+00
+00
+00
+00
+00
+00
+06
+00
+00
+00
+00
+00
+09
+00
+00
+00
+00
+00
+00
+00
+00
+00
+04
+00
+00
+00
+00
+00
+17
+00
+00
+00
+00
+00
+00
+00
+00
+00
+04
+00
+00
+00
+00
+00
+04
+00
+00
+00
+00
+00
+00
+00
+00
+00
+08
+00
+00
+00
+00
+00
+34
+00
+00
+00
+00
+00
+00
+00
+00
+00
+06
+00
+00
+00
+00
+00
+0d
+00
+00
+00
+00
+00
+00
+00
+00
+00
+06
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+03
+00
+06
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+03
+00
+08
+00
+03
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+12
+00
+04
+00
+0b
+00
+00
+00
+11
+00
+00
+00
+00
+00
+00
+00
+12
+00
+04
+00
+11
+00
+00
+00
+00
+00
+00
+00
+0d
+00
+00
+00
+11
+00
+06
+00
+18
+00
+00
+00
+38
+00
+00
+00
+04
+00
+00
+00
+11
+00
+06
+00
+20
+00
+00
+00
+3c
+00
+00
+00
+04
+00
+00
+00
+11
+00
+06
+00
+28
+00
+00
+00
+00
+00
+00
+00
+04
+00
+00
+00
+11
+00
+08
+00
+30
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+10
+00
+00
+00
+37
+00
+00
+00
+04
+00
+00
+00
+04
+00
+00
+00
+10
+00
+f2
+ff
+3f
+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
+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
+36
+00
+00
+00
+03
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+34
+01
+00
+00
+40
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+26
+00
+00
+00
+03
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+74
+01
+00
+00
+55
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+2e
+00
+00
+00
+02
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+cc
+01
+00
+00
+40
+01
+00
+00
+02
+00
+00
+00
+0b
+00
+00
+00
+04
+00
+00
+00
+10
+00
+00
+00
+01
+00
+00
+00
+01
+00
+00
+00
+06
+00
+00
+00
+00
+00
+00
+00
+40
+00
+00
+00
+59
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+10
+00
+00
+00
+00
+00
+00
+00
+12
+00
+00
+00
+09
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+9c
+00
+00
+00
+40
+00
+00
+00
+03
+00
+00
+00
+04
+00
+00
+00
+04
+00
+00
+00
+08
+00
+00
+00
+07
+00
+00
+00
+01
+00
+00
+00
+03
+00
+00
+00
+00
+00
+00
+00
+dc
+00
+00
+00
+40
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+04
+00
+00
+00
+00
+00
+00
+00
+1c
+00
+00
+00
+09
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+1c
+01
+00
+00
+18
+00
+00
+00
+03
+00
+00
+00
+06
+00
+00
+00
+04
+00
+00
+00
+08
+00
+00
+00
+0d
+00
+00
+00
+08
+00
+00
+00
+03
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+08
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+04
+00
+00
+00
+00
+00
+00
+00
{
/*@null@*/ xdf_objfmt_output_info *info = (xdf_objfmt_output_info *)d;
yasm_objfmt_xdf *objfmt_xdf;
- /*@dependent@*/ /*@null@*/ const yasm_intnum *intn;
+ /*@dependent@*/ /*@null@*/ yasm_intnum *intn;
/*@dependent@*/ /*@null@*/ const yasm_floatnum *flt;
/*@dependent@*/ /*@null@*/ yasm_symrec *sym;
yasm_expr *shr_expr;
yasm_section_add_reloc(info->sect, (yasm_reloc *)reloc, yasm_xfree);
}
intn = yasm_expr_get_intnum(ep, NULL);
- if (intn)
+ if (intn) {
+ if (rel) {
+ int retval = yasm_arch_intnum_fixup_rel(objfmt_xdf->arch, intn,
+ valsize, bc, bc->line);
+ if (retval)
+ return retval;
+ }
return yasm_arch_intnum_tobytes(objfmt_xdf->arch, intn, buf, destsize,
- valsize, shift, bc, rel, warn,
- bc->line);
+ valsize, shift, bc, warn, bc->line);
+ }
/* Check for complex float expressions */
if (yasm_expr__contains(*ep, YASM_EXPR_FLOAT)) {
%type <insn_operands> operands
%type <insn_operand> operand
+%left ':'
+%left WRT
%left '|'
%left '^'
%left '&'
%left '-' '+'
%left '*' '/' SIGNDIV '%' SIGNMOD
%nonassoc UNARYOP
-%nonassoc SEG WRT
-%left ':'
+%nonassoc SEG
%%
input: /* empty */