mirror of
https://github.com/yasm/yasm
synced 2026-08-26 22:26:05 -04:00
Fix #44 by adding support for WRT special symbols (e.g. [sym WRT ..plt] and
similar) to ELF. They are used identically to NASM's ELF shared object support. Due to limited WRT support throughout libyasm, this caused a lot of rippling changes. A major cleanup needs to be performed later to clear some of this hackiness up. * elf-machine.h (func_accepts_size_t): Rename to func_accepts_reloc(). (func_map_reloc_info_to_type): Add parameter ssyms for array of special syms. (elf_machine_ssym): New; for defining machine-specific special syms. (elf_machine_handler): Change accepts_reloc_size to accepts_reloc. Add new ssyms and num_ssyms members. * elf-x86-x86.c (ssym_index): New; this allows nice indexing of ssym arrays. (elf_x86_x86_accepts_reloc): Rename of elf_x86_x86_accepts_reloc_size. Add support for various WRT ssyms. (elf_x86_x86_map_reloc_info_to_type): Add support for various WRT ssyms. (elf_x86_x86_ssyms): New array of supported special symbols. (elf_machine_handler_x86_x86): Update for above changes/additions. * elf-x86-amd64.c (ssym_index, elf_x86_amd64_accepts_reloc) (elf_x86_amd64_map_reloc_info_to_type, elf_x86_amd64_ssyms) (elf_machine_handler_x86_amd64): Likewise. * elf.h (elf_reloc_entry): Add wrt member. (elf_set_arch): Add symtab parameter. (elf_is_wrt_sym_relative): New. (elf_reloc_entry_create): Add wrt parameter. * elf.c (elf_set_arch): Allocate special syms from machine level. (elf_is_wrt_sym_relative): New; search special syms, and report whether a WRT ssym should be symbol-relative or section-relative. (elf_reloc_entry_create): Pass WRT and ssyms info down to machine level. * elf-objfmt.c (yasm_objfmt_elf): Add dotdotsym (..sym) symrec member. (elf_objfmt_create): Pass symtab to elf_set_arch(). Allocate ..sym symbol. (elf_objfmt_output_reloc): Update for elf_reloc_entry_create() change. (elf_objfmt_output_expr): Handle WRT ssym. Make relocation symbol-relative rather than section-relative if either WRT ..sym or WRT ssym that machine level desires to be symbol-relative. * symrec.c (yasm_symrec_get_label): Check for NULL sym->value.precbc; this is now possible due to the user-accessible special symbols that ELF et al create, which all have NULL precbc's. * expr.c (yasm_expr_extract_symrec): Recurse into IDENT's to make more exprs acceptable. * coretype.h (yasm_output_reloc_func): Remove rel parameter as it shouldn't be needed and complexifies writing of the reloc functions. * stabs-dbgfmt.c (stabs_bc_stab_tobytes): Update output_reloc() call. * elf-objfmt.c (elf_objfmt_output_reloc): Update to match. * arch.h (yasm_arch_module): Add intnum_fixup_rel() function, change intnum_tobytes() to not take rel parameter. The rel functionality is being separated because sometimes it's desirable not to put the data into the written intnum (e.g. ELF RELA relocations). (YASM_ARCH_VERSION): Bump due to above change. (yasm_arch_intnum_fixup_rel): New wrapper. (yasm_arch_intnum_tobytes): Update wrapper (removing rel). * lc3bbc.c (yasm_lc3b__intnum_fixup_rel): New, with code from: (yasm_lc3b__intnum_tobytes): Remove rel code. * lc3barch.h (yasm_lc3b__intnum_fixup_rel): New. (yasm_lc3b__intnum_tobytes): Update. * lc3barch.c (yasm_lc3b_LTX_arch): Reference yasm_lc3b__intnum_fixup_rel(). * x86bc.c (yasm_x86__intnum_fixup_rel): New, with code from: (yasm_x86__intnum_tobytes): Remove rel code. * x86arch.h (yasm_x86__intnum_fixup_rel): New. (yasm_x86__intnum_tobytes): Update. * x86arch.c (yasm_x86_LTX_arch): Reference yasm_x86__intnum_fixup_rel(). * xdf-objfmt.c (xdf_objfmt_output_expr): Update to use intnum_fixup_rel() / new intnum_tobytes(). * bin-objfmt.c (bin_objfmt_output_expr): Likewise. * coff-objfmt.c (coff_objfmt_output_expr): Likewise. * elf-objfmt.c (elf_objfmt_output_expr: Likewise. * nasm-listfmt.c (nasm_listfmt_output_expr): Likewise. * nasm-bison.y: Change precedence of WRT and : operators: instead of being the strongest binders they are now the weakest. This is needed to correctly parse and be able to split WRT expressions. WRT handling is still somewhat of a hack throughout yasm; we'll fix this later. * x86expr.c (x86_expr_checkea_distcheck_reg): Don't check for WRT here. (x86_expr_checkea_getregusage): Add new wrt parameter. Use it to handle "WRT rip" separately from other operators. Recurse if there's a WRT below the WRT rip; this is to handle cases like ELF-AMD64's elfso64.asm. (yasm_x86__expr_checkea): Split off top-level WRT's and feed through separately to x86_expr_checkea_getregusage(). * x86bc.c (x86_bc_insn_tobytes): Ensure the SUB operation for PC-relative displacements goes BELOW any WRT expression. (x86_bc_jmp_tobytes): Likewise. * elfso.asm, elfso.hex, elfso.errwarn: New 32-bit ELF shared object tests. * modules/objfmts/elf/tests/Makefile.inc: Include in distribution. * elfso64.asm, elfso64.hex, elfso64.errwarn: New 64-bit ELF shared object tests. This is not a good example, as the assembled code doesn't work, but it at least tests the special symbols. * modules/objfmts/elf/tests/amd64/Makefile.inc: Include in distribution. svn path=/trunk/yasm/; revision=1168
This commit is contained in:
parent
f5b1d4532d
commit
23e53d41ce
32 changed files with 3428 additions and 168 deletions
|
|
@ -104,7 +104,7 @@ typedef struct yasm_arch_machine {
|
|||
* 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
|
||||
|
|
@ -208,12 +208,19 @@ typedef struct yasm_arch_module {
|
|||
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().
|
||||
|
|
@ -446,6 +453,19 @@ int yasm_arch_floatnum_tobytes(yasm_arch *arch, const yasm_floatnum *flt,
|
|||
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
|
||||
|
|
@ -458,7 +478,6 @@ int yasm_arch_floatnum_tobytes(yasm_arch *arch, const yasm_floatnum *flt,
|
|||
* \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
|
||||
|
|
@ -467,7 +486,7 @@ int yasm_arch_floatnum_tobytes(yasm_arch *arch, const yasm_floatnum *flt,
|
|||
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.
|
||||
|
|
@ -541,10 +560,13 @@ yasm_effaddr *yasm_arch_ea_create(yasm_arch *arch, /*@keep@*/ yasm_expr *e);
|
|||
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) \
|
||||
|
|
|
|||
|
|
@ -201,7 +201,6 @@ typedef int (*yasm_output_expr_func)
|
|||
* \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,
|
||||
|
|
@ -212,7 +211,7 @@ typedef int (*yasm_output_expr_func)
|
|||
*/
|
||||
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
|
||||
|
|
|
|||
|
|
@ -993,6 +993,10 @@ yasm_expr_extract_symrec(yasm_expr **ep, int relocate,
|
|||
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -356,7 +356,7 @@ int
|
|||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -130,6 +130,7 @@ yasm_arch_module yasm_lc3b_LTX_arch = {
|
|||
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,
|
||||
|
|
|
|||
|
|
@ -65,8 +65,12 @@ yasm_arch_check_id_retval yasm_lc3b__parse_check_id
|
|||
/*@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
|
||||
|
|
|
|||
|
|
@ -241,27 +241,28 @@ lc3b_bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
|
|||
}
|
||||
|
||||
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)
|
||||
yasm_lc3b__intnum_fixup_rel(yasm_arch *arch, yasm_intnum *intn,
|
||||
size_t valsize, const yasm_bytecode *bc,
|
||||
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);
|
||||
}
|
||||
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 warn,
|
||||
unsigned long line)
|
||||
{
|
||||
/* Write value out. */
|
||||
yasm_intnum_get_sized(intn, buf, destsize, valsize, shift, 0, warn,
|
||||
line);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -263,6 +263,7 @@ yasm_arch_module yasm_x86_LTX_arch = {
|
|||
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,
|
||||
|
|
|
|||
|
|
@ -218,10 +218,13 @@ int yasm_x86__floatnum_tobytes
|
|||
(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
|
||||
|
|
|
|||
|
|
@ -1026,10 +1026,17 @@ x86_bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
|
|||
|
||||
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,
|
||||
|
|
@ -1074,6 +1081,7 @@ x86_bc_jmp_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
|
|||
unsigned int i;
|
||||
unsigned char *bufp_orig = *bufp;
|
||||
/*@null@*/ yasm_expr *targetseg;
|
||||
/*@null@*/ yasm_expr *wrt;
|
||||
yasm_expr *dup;
|
||||
|
||||
/* Prefixes */
|
||||
|
|
@ -1101,9 +1109,14 @@ x86_bc_jmp_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
|
|||
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;
|
||||
|
|
@ -1122,9 +1135,14 @@ x86_bc_jmp_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
|
|||
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))
|
||||
|
|
@ -1169,27 +1187,27 @@ x86_bc_jmp_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
|
|||
}
|
||||
|
||||
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)
|
||||
yasm_x86__intnum_fixup_rel(yasm_arch *arch, yasm_intnum *intn, size_t valsize,
|
||||
const yasm_bytecode *bc, 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);
|
||||
}
|
||||
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 warn,
|
||||
unsigned long line)
|
||||
{
|
||||
/* Write value out. */
|
||||
yasm_intnum_get_sized(intn, buf, destsize, valsize, shift, 0, warn,
|
||||
line);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -157,11 +157,6 @@ x86_expr_checkea_distcheck_reg(yasm_expr **ep, unsigned int bits)
|
|||
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;
|
||||
}
|
||||
|
|
@ -252,9 +247,9 @@ x86_expr_checkea_distcheck_reg(yasm_expr **ep, unsigned int bits)
|
|||
* 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;
|
||||
|
|
@ -267,6 +262,9 @@ x86_expr_checkea_getregusage(yasm_expr **ep, /*@null@*/ int *indexreg,
|
|||
/*@-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;
|
||||
|
|
@ -283,27 +281,31 @@ x86_expr_checkea_getregusage(yasm_expr **ep, /*@null@*/ int *indexreg,
|
|||
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
|
||||
|
|
@ -563,7 +565,12 @@ yasm_x86__expr_checkea(yasm_expr **ep, unsigned char *addrsize,
|
|||
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:
|
||||
|
|
@ -651,7 +658,7 @@ yasm_x86__expr_checkea(yasm_expr **ep, unsigned char *addrsize,
|
|||
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)) {
|
||||
|
|
@ -660,6 +667,9 @@ yasm_x86__expr_checkea(yasm_expr **ep, unsigned char *addrsize,
|
|||
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;
|
||||
|
|
@ -782,6 +792,9 @@ yasm_x86__expr_checkea(yasm_expr **ep, unsigned char *addrsize,
|
|||
/* 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 */
|
||||
|
|
@ -860,9 +873,12 @@ yasm_x86__expr_checkea(yasm_expr **ep, unsigned char *addrsize,
|
|||
}
|
||||
|
||||
/* 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] */,
|
||||
|
|
@ -893,8 +909,8 @@ yasm_x86__expr_checkea(yasm_expr **ep, unsigned char *addrsize,
|
|||
*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:
|
||||
|
|
@ -902,6 +918,9 @@ yasm_x86__expr_checkea(yasm_expr **ep, unsigned char *addrsize,
|
|||
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;
|
||||
|
|
@ -935,9 +954,12 @@ yasm_x86__expr_checkea(yasm_expr **ep, unsigned char *addrsize,
|
|||
*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) {
|
||||
|
|
@ -963,6 +985,8 @@ yasm_x86__expr_checkea(yasm_expr **ep, unsigned char *addrsize,
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (wrt)
|
||||
*ep = yasm_expr_create_tree(*ep, YASM_EXPR_WRT, wrt, (*ep)->line);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -443,7 +443,7 @@ stabs_bc_stab_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ nasm_listfmt_output_expr(yasm_expr **ep, unsigned char *buf, size_t destsize,
|
|||
/*@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);
|
||||
|
|
@ -115,15 +115,14 @@ nasm_listfmt_output_expr(yasm_expr **ep, unsigned char *buf, size_t destsize,
|
|||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ bin_objfmt_output_expr(yasm_expr **ep, unsigned char *buf, size_t destsize,
|
|||
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);
|
||||
|
|
@ -180,10 +180,18 @@ bin_objfmt_output_expr(yasm_expr **ep, unsigned char *buf, size_t destsize,
|
|||
|
||||
/* 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)) {
|
||||
|
|
|
|||
|
|
@ -361,7 +361,7 @@ coff_objfmt_output_expr(yasm_expr **ep, unsigned char *buf, size_t destsize,
|
|||
{
|
||||
/*@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;
|
||||
|
|
@ -464,10 +464,16 @@ coff_objfmt_output_expr(yasm_expr **ep, unsigned char *buf, size_t destsize,
|
|||
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)) {
|
||||
|
|
|
|||
|
|
@ -44,7 +44,8 @@
|
|||
|
||||
#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,
|
||||
|
|
@ -57,7 +58,8 @@ typedef void(*func_write_secthead_rel)(unsigned char *bufp,
|
|||
|
||||
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,
|
||||
|
|
@ -67,6 +69,11 @@ typedef void (*func_write_proghead)(unsigned char **bufpp,
|
|||
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;
|
||||
|
|
@ -76,7 +83,7 @@ typedef struct {
|
|||
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;
|
||||
|
|
@ -84,6 +91,9 @@ typedef struct {
|
|||
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 */
|
||||
|
|
|
|||
|
|
@ -62,6 +62,8 @@ typedef struct yasm_objfmt_elf {
|
|||
yasm_object *object;
|
||||
yasm_symtab *symtab;
|
||||
/*@dependent@*/ yasm_arch *arch;
|
||||
|
||||
yasm_symrec *dotdotsym; /* ..sym symbol */
|
||||
} yasm_objfmt_elf;
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -154,7 +156,7 @@ elf_objfmt_create(const char *in_filename, yasm_object *object, yasm_arch *a)
|
|||
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;
|
||||
}
|
||||
|
|
@ -166,14 +168,18 @@ elf_objfmt_create(const char *in_filename, yasm_object *object, yasm_arch *a)
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
@ -204,15 +210,15 @@ elf_objfmt_output_align(FILE *f, unsigned int align)
|
|||
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;
|
||||
|
|
@ -224,7 +230,7 @@ elf_objfmt_output_reloc(yasm_symrec *sym, yasm_bytecode *bc,
|
|||
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;
|
||||
|
|
@ -241,6 +247,8 @@ elf_objfmt_output_expr(yasm_expr **ep, unsigned char *buf, size_t destsize,
|
|||
/*@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");
|
||||
|
|
@ -257,13 +265,32 @@ elf_objfmt_output_expr(yasm_expr **ep, unsigned char *buf, size_t destsize,
|
|||
(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 */
|
||||
|
|
@ -290,10 +317,10 @@ elf_objfmt_output_expr(yasm_expr **ep, unsigned char *buf, size_t destsize,
|
|||
*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 */
|
||||
|
|
@ -302,12 +329,20 @@ elf_objfmt_output_expr(yasm_expr **ep, unsigned char *buf, size_t destsize,
|
|||
}
|
||||
|
||||
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)) {
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
*/
|
||||
|
||||
#include <util.h>
|
||||
/*@unused@*/ RCSID("$Id:$");
|
||||
/*@unused@*/ RCSID("$Id$");
|
||||
|
||||
#define YASM_LIB_INTERNAL
|
||||
#define YASM_EXPR_INTERNAL
|
||||
|
|
@ -35,9 +35,23 @@
|
|||
#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);
|
||||
}
|
||||
|
||||
|
|
@ -126,9 +140,19 @@ elf_x86_amd64_handle_reloc_addend(yasm_intnum *intn, elf_reloc_entry *reloc)
|
|||
}
|
||||
|
||||
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;
|
||||
|
|
@ -190,16 +214,24 @@ elf_x86_amd64_write_proghead(unsigned char **bufpp,
|
|||
*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])
|
||||
};
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
*/
|
||||
|
||||
#include <util.h>
|
||||
/*@unused@*/ RCSID("$Id:$");
|
||||
/*@unused@*/ RCSID("$Id$");
|
||||
|
||||
#define YASM_LIB_INTERNAL
|
||||
#define YASM_EXPR_INTERNAL
|
||||
|
|
@ -35,9 +35,25 @@
|
|||
#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);
|
||||
}
|
||||
|
||||
|
|
@ -117,9 +133,21 @@ elf_x86_x86_handle_reloc_addend(yasm_intnum *intn, elf_reloc_entry *reloc)
|
|||
}
|
||||
|
||||
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;
|
||||
|
|
@ -175,16 +203,25 @@ elf_x86_x86_write_proghead(unsigned char **bufpp,
|
|||
*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])
|
||||
};
|
||||
|
|
|
|||
|
|
@ -63,9 +63,10 @@ static const elf_machine_handler *elf_machine_handlers[] =
|
|||
};
|
||||
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;
|
||||
|
|
@ -78,23 +79,50 @@ elf_set_arch(yasm_arch *arch)
|
|||
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);
|
||||
|
|
@ -110,6 +138,7 @@ elf_reloc_entry_create(yasm_symrec *sym,
|
|||
entry->rtype_rel = rel;
|
||||
entry->valsize = valsize;
|
||||
entry->addend = NULL;
|
||||
entry->wrt = wrt;
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
|
@ -670,7 +699,7 @@ elf_secthead_write_relocs_to_file(FILE *f, yasm_section *sect,
|
|||
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)
|
||||
|
|
|
|||
|
|
@ -354,6 +354,7 @@ struct elf_reloc_entry {
|
|||
int rtype_rel;
|
||||
size_t valsize;
|
||||
yasm_intnum *addend;
|
||||
/*@null@*/ yasm_symrec *wrt;
|
||||
};
|
||||
|
||||
STAILQ_HEAD(elf_strtab_head, elf_strtab_entry);
|
||||
|
|
@ -384,10 +385,12 @@ extern const yasm_assoc_data_callback elf_section_data;
|
|||
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);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ EXTRA_DIST += modules/objfmts/elf/tests/elf_test.sh
|
|||
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
|
||||
|
|
|
|||
|
|
@ -6,3 +6,6 @@ EXTRA_DIST += modules/objfmts/elf/tests/amd64/elf_amd64_test.sh
|
|||
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
|
||||
|
|
|
|||
|
|
@ -82,15 +82,15 @@
|
|||
00
|
||||
8b
|
||||
05
|
||||
fa
|
||||
ff
|
||||
ff
|
||||
ff
|
||||
00
|
||||
00
|
||||
00
|
||||
00
|
||||
e8
|
||||
fb
|
||||
ff
|
||||
ff
|
||||
ff
|
||||
00
|
||||
00
|
||||
00
|
||||
00
|
||||
00
|
||||
00
|
||||
00
|
||||
|
|
@ -134,14 +134,14 @@ ff
|
|||
00
|
||||
00
|
||||
00
|
||||
02
|
||||
00
|
||||
00
|
||||
00
|
||||
00
|
||||
00
|
||||
00
|
||||
00
|
||||
fc
|
||||
ff
|
||||
ff
|
||||
ff
|
||||
ff
|
||||
ff
|
||||
ff
|
||||
ff
|
||||
19
|
||||
00
|
||||
00
|
||||
|
|
@ -158,14 +158,14 @@ ff
|
|||
00
|
||||
00
|
||||
00
|
||||
01
|
||||
00
|
||||
00
|
||||
00
|
||||
00
|
||||
00
|
||||
00
|
||||
00
|
||||
fc
|
||||
ff
|
||||
ff
|
||||
ff
|
||||
ff
|
||||
ff
|
||||
ff
|
||||
ff
|
||||
00
|
||||
2e
|
||||
74
|
||||
|
|
|
|||
90
modules/objfmts/elf/tests/amd64/elfso64.asm
Normal file
90
modules/objfmts/elf/tests/amd64/elfso64.asm
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
; 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]
|
||||
0
modules/objfmts/elf/tests/amd64/elfso64.errwarn
Normal file
0
modules/objfmts/elf/tests/amd64/elfso64.errwarn
Normal file
1680
modules/objfmts/elf/tests/amd64/elfso64.hex
Normal file
1680
modules/objfmts/elf/tests/amd64/elfso64.hex
Normal file
File diff suppressed because it is too large
Load diff
97
modules/objfmts/elf/tests/elfso.asm
Normal file
97
modules/objfmts/elf/tests/elfso.asm
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
; 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]
|
||||
0
modules/objfmts/elf/tests/elfso.errwarn
Normal file
0
modules/objfmts/elf/tests/elfso.errwarn
Normal file
1144
modules/objfmts/elf/tests/elfso.hex
Normal file
1144
modules/objfmts/elf/tests/elfso.hex
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -206,7 +206,7 @@ xdf_objfmt_output_expr(yasm_expr **ep, unsigned char *buf, size_t destsize,
|
|||
{
|
||||
/*@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;
|
||||
|
|
@ -284,10 +284,16 @@ xdf_objfmt_output_expr(yasm_expr **ep, unsigned char *buf, size_t destsize,
|
|||
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)) {
|
||||
|
|
|
|||
|
|
@ -110,6 +110,8 @@ static void define_label(yasm_parser_nasm *parser_nasm, /*@only@*/ char *name,
|
|||
%type <insn_operands> operands
|
||||
%type <insn_operand> operand
|
||||
|
||||
%left ':'
|
||||
%left WRT
|
||||
%left '|'
|
||||
%left '^'
|
||||
%left '&'
|
||||
|
|
@ -117,8 +119,7 @@ static void define_label(yasm_parser_nasm *parser_nasm, /*@only@*/ char *name,
|
|||
%left '-' '+'
|
||||
%left '*' '/' SIGNDIV '%' SIGNMOD
|
||||
%nonassoc UNARYOP
|
||||
%nonassoc SEG WRT
|
||||
%left ':'
|
||||
%nonassoc SEG
|
||||
|
||||
%%
|
||||
input: /* empty */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue