]> granicus.if.org Git - yasm/commitdiff
Fix #44 by adding support for WRT special symbols (e.g. [sym WRT ..plt] and
authorPeter Johnson <peter@tortall.net>
Sun, 31 Oct 2004 01:07:52 +0000 (01:07 -0000)
committerPeter Johnson <peter@tortall.net>
Sun, 31 Oct 2004 01:07:52 +0000 (01:07 -0000)
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

32 files changed:
libyasm/arch.h
libyasm/coretype.h
libyasm/expr.c
libyasm/symrec.c
modules/arch/lc3b/lc3barch.c
modules/arch/lc3b/lc3barch.h
modules/arch/lc3b/lc3bbc.c
modules/arch/x86/x86arch.c
modules/arch/x86/x86arch.h
modules/arch/x86/x86bc.c
modules/arch/x86/x86expr.c
modules/dbgfmts/stabs/stabs-dbgfmt.c
modules/listfmts/nasm/nasm-listfmt.c
modules/objfmts/bin/bin-objfmt.c
modules/objfmts/coff/coff-objfmt.c
modules/objfmts/elf/elf-machine.h
modules/objfmts/elf/elf-objfmt.c
modules/objfmts/elf/elf-x86-amd64.c
modules/objfmts/elf/elf-x86-x86.c
modules/objfmts/elf/elf.c
modules/objfmts/elf/elf.h
modules/objfmts/elf/tests/Makefile.inc
modules/objfmts/elf/tests/amd64/Makefile.inc
modules/objfmts/elf/tests/amd64/elf-rip.hex
modules/objfmts/elf/tests/amd64/elfso64.asm [new file with mode: 0644]
modules/objfmts/elf/tests/amd64/elfso64.errwarn [new file with mode: 0644]
modules/objfmts/elf/tests/amd64/elfso64.hex [new file with mode: 0644]
modules/objfmts/elf/tests/elfso.asm [new file with mode: 0644]
modules/objfmts/elf/tests/elfso.errwarn [new file with mode: 0644]
modules/objfmts/elf/tests/elfso.hex [new file with mode: 0644]
modules/objfmts/xdf/xdf-objfmt.c
modules/parsers/nasm/nasm-bison.y

index e522db9d45f9c7fa608d28f0e5541ee0bb4ad6fc..79a2313903ae89480d00dafabb056038d263b987 100644 (file)
@@ -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) \
index a1a39e1f25cfc6c968a24c544a62f85d3ad0d992..83fd0b70376a54f539219ccbea7f2c81589fd7f7 100644 (file)
@@ -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
index 12120b4cf3187faa8014be69ac7652f0b8fcbd85..cd53c6b69bac8a30aaed19d4067d45f51a493594 100644 (file)
@@ -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;
index 10741a234eaab589fb87a997e1481adaf9d64d95..ca5f6057c871d9ea0dd78c5e3cdad42dff048d46 100644 (file)
@@ -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;
     }
index de0c8771ef8f88622fef35ddd76921aede67aa1a..4a6b10b53c008bef345e7cf1154b0bab25170701 100644 (file)
@@ -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,
index 9390fe105bce5aadcff9e084261904d20509aa02..4b8c860e392a390fce34295761291cbf13f38f1f 100644 (file)
@@ -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
index be754200cf1ca4cdc3701cd9386c70ce06be8d14..87fdf27945666b693a95bb15bf2b0ee79e38ba14 100644 (file)
@@ -240,28 +240,29 @@ lc3b_bc_insn_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
     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;
 }
index d22f6e1f924f4158694056145dfaceb15aaff8fd..ca66258439f70163cb6287cdb4d72307355e66a7 100644 (file)
@@ -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,
index f6668b7049c084abe36a3bf941cbe7ad674f0346..c7fb9df48748d3cdca6883a1860dc3d65608c8ab 100644 (file)
@@ -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
index 02439fc7e12eaa83a7f4071fa3082e4663d41388..a959d2616a50239b9902742760dfc68446478d4b 100644 (file)
@@ -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))
@@ -1168,28 +1186,28 @@ x86_bc_jmp_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *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;
 }
index 4bea638bcd502c8c0304e9678064a31003aafef2..4d1f1a85b9b3126106757f5788b2215325c0a599 100644 (file)
@@ -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], &regnum, 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], &regnum, 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,
                                             &reg3264_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,
-                                            &reg16mult,
+       switch (x86_expr_checkea_getregusage(ep, &wrt, (int *)NULL, pcrel,
+                                            bits, &reg16mult,
                                             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;
 }
 
index cd2bc025ce5f08ef6dc029e5084f58aacd387b3c..9cdead875da042b66bf866f62703df481560005a 100644 (file)
@@ -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;
     }
index a8046d783b1c2a5c7438bfff744c123e29371397..9dcd8063b6cf2dcc3d939c1453bd2e24ad0d5208 100644 (file)
@@ -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;
 }
index 3995bcc2c665f5c5bf221d440db4da29d5f81f2a..f2ee7e61e8face90644d316eab658cc2c8ad0638 100644 (file)
@@ -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)) {
index 5616e4f3ed63caec9668a8b5b527120db0bcbe87..ff91968159f9fc17008883a8643d42df99aefd18 100644 (file)
@@ -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)) {
index edc3f10f03b9b11a4d956e78dae146395acc77bc..2a375971fec9e0ef6e9c5f35073237f113f67563 100644 (file)
@@ -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 */
index 78861b61517f59a00efacb518365f8ca20ea716c..9172b64d1928d827f4753d7ea63ba49cabc5d522 100644 (file)
@@ -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)) {
index 56121ba6bec7d11fe6d1d3dcec6e2e87a635f268..29542f92798c7717dac8e0266f4e165a55b492ee 100644 (file)
@@ -26,7 +26,7 @@
  */
 
 #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);
 }
 
@@ -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])
 };
index 689622e1d32ef38ae84d90d8e6b3117df740d89a..e20150ea76f3f373cb0bff0225a9a48572e7b965 100644 (file)
@@ -26,7 +26,7 @@
  */
 
 #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);
 }
 
@@ -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])
 };
index 7d63be490e0eae38f25670fbb672079ed2a5a8ee..513ed16110928b144d99b4eda71c2e51adfd2922 100644 (file)
@@ -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)
index edf62f7cdb23630318a2aa41c9541028829c0e2c..10208c5c02e05f1e038b4862d9b47b3420be865a 100644 (file)
@@ -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);
index 100cca0d8a437e9b549cf88fb860db46c0587512..dee1cb8a6c2d4a536fc9883a506ded1da4755353 100644 (file)
@@ -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
index 5fdfe3c22839d3abd949508a43dd56720cf3ad0a..28dec5680179bd74d25d9ecbf3dfd054ce142ce6 100644 (file)
@@ -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
index 9e68a15d08ae187a4a64e762e8a2db31143eda51..4294742114b24b3e1fbe796a2c602babadb6e495 100644 (file)
 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 
@@ -126,22 +118,30 @@ ff
 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 
@@ -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 
diff --git a/modules/objfmts/elf/tests/amd64/elfso64.asm b/modules/objfmts/elf/tests/amd64/elfso64.asm
new file mode 100644 (file)
index 0000000..39dbf2e
--- /dev/null
@@ -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]
diff --git a/modules/objfmts/elf/tests/amd64/elfso64.errwarn b/modules/objfmts/elf/tests/amd64/elfso64.errwarn
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/modules/objfmts/elf/tests/amd64/elfso64.hex b/modules/objfmts/elf/tests/amd64/elfso64.hex
new file mode 100644 (file)
index 0000000..f6bc60f
--- /dev/null
@@ -0,0 +1,1680 @@
+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 
diff --git a/modules/objfmts/elf/tests/elfso.asm b/modules/objfmts/elf/tests/elfso.asm
new file mode 100644 (file)
index 0000000..5adb633
--- /dev/null
@@ -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]
diff --git a/modules/objfmts/elf/tests/elfso.errwarn b/modules/objfmts/elf/tests/elfso.errwarn
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/modules/objfmts/elf/tests/elfso.hex b/modules/objfmts/elf/tests/elfso.hex
new file mode 100644 (file)
index 0000000..b23ed99
--- /dev/null
@@ -0,0 +1,1144 @@
+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 
index 1384c461ce2552708558be1e7fedd13c2b41b93c..b4434035d5900b334f81f48cadfa4dbde286852a 100644 (file)
@@ -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)) {
index 80c5bd80a9548d355578ab83d86873ceeb5c8b9b..aa23cda2251eb9383945f043f7dae72db0bb8540 100644 (file)
@@ -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 */