}
yasm_symrec *
-yasm_expr_extract_symrec(yasm_expr **ep, int relocate,
+yasm_expr_extract_symrec(yasm_expr **ep,
+ yasm_symrec_relocate_action relocate_action,
yasm_calc_bc_dist_func calc_bc_dist)
{
yasm_symrec *sym = NULL;
/* 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);
+ relocate_action, calc_bc_dist);
/* Replace sym with 0 value, return sym */
if ((*ep)->terms[0].type == YASM_EXPR_SYM) {
sym = (*ep)->terms[0].data.sym;
/*@dependent@*/ /*@null@*/ yasm_bytecode *precbc;
/*@null@*/ yasm_intnum *intn;
- if (relocate && yasm_symrec_get_label(sym, &precbc)) {
+ if (yasm_symrec_get_label(sym, &precbc)
+ && (relocate_action == YASM_SYMREC_REPLACE_VALUE ||
+ (relocate_action == YASM_SYMREC_REPLACE_VALUE_IF_LOCAL
+ && yasm_symrec_get_visibility(sym) == YASM_SYM_LOCAL))) {
intn = calc_bc_dist(yasm_section_bcs_first(
yasm_bc_get_section(precbc)), precbc);
if (!intn)
#define yasm_expr_simplify(e, cbd) \
yasm_expr__level_tree(e, 1, 1, cbd, NULL, NULL, NULL)
+/** Relocation actions for yasm_expr_extract_symrec(). */
+typedef enum yasm_symrec_relocate_action {
+ YASM_SYMREC_REPLACE_ZERO = 0, /**< Replace the symbol with 0 */
+ YASM_SYMREC_REPLACE_VALUE, /**< Replace with symbol's value (offset)
+ * if symbol is a label.
+ */
+ YASM_SYMREC_REPLACE_VALUE_IF_LOCAL /**< Replace with symbol's value only
+ * if symbol is label and declared
+ * local.
+ */
+} yasm_symrec_relocate_action;
+
/** Extract a single symbol out of an expression. Replaces it with 0, or
* optionally the symbol's value (if it's a label).
- * \param ep expression (pointer to)
- * \param relocate replace symbol with value (if label) if nonzero
- * \param calc_bc_dist bytecode distance-calculation function
+ * \param ep expression (pointer to)
+ * \param relocate_action replacement action to take on symbol in expr
+ * \param calc_bc_dist bytecode distance-calculation function
* \return NULL if unable to extract a symbol (too complex of expr, none
* present, etc); otherwise returns the extracted symbol.
*/
/*@dependent@*/ /*@null@*/ yasm_symrec *yasm_expr_extract_symrec
- (yasm_expr **ep, int relocate, yasm_calc_bc_dist_func calc_bc_dist);
+ (yasm_expr **ep, yasm_symrec_relocate_action relocate_action,
+ yasm_calc_bc_dist_func calc_bc_dist);
/** Remove the SEG unary operator if present, leaving the lower level
* expression.
00
00
01
-03
+0f
00
00
18
00
00
01
-03
+0f
00
00
30
00
00
00
-11
00
00
00
-3c
+00
+00
00
00
00
00
00
01
-09
+0b
00
00
3c
00
00
01
-04
+0e
00
00
01
}
/* Handle integer expressions, with relocation if necessary */
- sym = yasm_expr_extract_symrec(ep, !objfmt_coff->win64,
- yasm_common_calc_bc_dist);
+ if (objfmt_coff->win64)
+ sym = yasm_expr_extract_symrec(ep, YASM_SYMREC_REPLACE_ZERO,
+ yasm_common_calc_bc_dist);
+ else
+ sym = yasm_expr_extract_symrec(ep, YASM_SYMREC_REPLACE_VALUE,
+ yasm_common_calc_bc_dist);
+
if (sym) {
unsigned long addr;
coff_reloc *reloc;
/* Check for a WRT relocation */
wrt_expr = yasm_expr_extract_wrt(ep);
if (wrt_expr) {
- wrt = yasm_expr_extract_symrec(&wrt_expr, 0,
+ wrt = yasm_expr_extract_symrec(&wrt_expr, YASM_SYMREC_REPLACE_ZERO,
yasm_common_calc_bc_dist);
yasm_expr_destroy(wrt_expr);
if (!wrt) {
}
/* Handle integer expressions, with relocation if necessary */
- sym = yasm_expr_extract_symrec(ep,
- !(wrt == info->objfmt_elf->dotdotsym ||
- (wrt && elf_is_wrt_sym_relative(wrt))),
- yasm_common_calc_bc_dist);
+ if (wrt == info->objfmt_elf->dotdotsym
+ || (wrt && elf_is_wrt_sym_relative(wrt)))
+ sym = yasm_expr_extract_symrec(ep, YASM_SYMREC_REPLACE_ZERO,
+ yasm_common_calc_bc_dist);
+ else
+ sym = yasm_expr_extract_symrec(ep, YASM_SYMREC_REPLACE_VALUE_IF_LOCAL,
+ yasm_common_calc_bc_dist);
+
if (sym) {
yasm_sym_vis vis;
wrt = NULL;
else if (wrt && elf_is_wrt_sym_relative(wrt))
;
- else if (!(vis & (YASM_SYM_COMMON|YASM_SYM_EXTERN)))
- {
+ else if (vis == YASM_SYM_LOCAL) {
yasm_bytecode *label_precbc;
/* Local symbols need relocation to their section's start */
if (yasm_symrec_get_label(sym, &label_precbc)) {
EXTRA_DIST += modules/objfmts/elf/tests/elfvisibility.hex
EXTRA_DIST += modules/objfmts/elf/tests/amd64/Makefile.inc
+EXTRA_DIST += modules/objfmts/elf/tests/gas64/Makefile.inc
include modules/objfmts/elf/tests/amd64/Makefile.inc
+include modules/objfmts/elf/tests/gas64/Makefile.inc
00
00
01
-02
+0e
00
00
18
00
00
01
-02
+0e
00
00
30
00
00
00
-11
00
00
00
-3c
+00
+00
00
00
00
00
00
01
-08
+0a
00
00
3c
00
00
01
-03
+0d
00
00
00
--- /dev/null
+# $Id: Makefile.inc 1168 2004-10-31 01:07:52Z peter $
+
+TESTS += modules/objfmts/elf/tests/gas64/elf_gas64_test.sh
+
+EXTRA_DIST += modules/objfmts/elf/tests/gas64/elf_gas64_test.sh
+EXTRA_DIST += modules/objfmts/elf/tests/amd64/elf_gas64_reloc.asm
+EXTRA_DIST += modules/objfmts/elf/tests/amd64/elf_gas64_reloc.hex
+EXTRA_DIST += modules/objfmts/elf/tests/amd64/elf_gas64_reloc.errwarn
--- /dev/null
+.comm _ZEROVAR, 32, 16
+.comm _VAR, 16, 16
+.data
+.org 0
+_ZEROVAR:
+.org 0xa0
+.globl _VAR
+.type _VAR, @object
+.size _VAR, 16
+_VAR:
+.4byte 0
+.4byte 0
+.4byte 0
+.4byte 0
+.org 0xc0
+_VAR2:
+.org 0xe0
+.globl _VAR3
+_VAR3:
+
+.text
+movq $0, %rax
+movq _VAR, %rax
+movq %rax, _VAR(%rip)
+movq _VAR+8(%rip), %rcx
+movlpd _VAR(%rip), %xmm1
+
+movq _VAR2, %rax
+movq %rax, _VAR2(%rip)
+movq _VAR2+8(%rip), %rcx
+movlpd _VAR2(%rip), %xmm1
+
+movq _VAR3, %rax
+movq %rax, _VAR3(%rip)
+movq _VAR3+8(%rip), %rcx
+movlpd _VAR3(%rip), %xmm1
+
--- /dev/null
+#! /bin/sh
+# $Id: elf_amd64_test.sh 1137 2004-09-04 01:24:57Z peter $
+${srcdir}/out_test.sh elf_gas64_test modules/objfmts/elf/tests/gas64 "GAS elf-amd64 objfmt" "-f elf64 -p gas" ".o"
+exit $?
wrt_expr = yasm_expr_extract_wrt(ep);
/* Handle integer expressions, with relocation if necessary */
- sym = yasm_expr_extract_symrec(ep, 0, yasm_common_calc_bc_dist);
+ sym = yasm_expr_extract_symrec(ep, YASM_SYMREC_REPLACE_ZERO,
+ yasm_common_calc_bc_dist);
if (sym) {
xdf_reloc *reloc;
if (seg)
reloc->type = XDF_RELOC_SEG;
else if (wrt_expr) {
- reloc->base = yasm_expr_extract_symrec(&wrt_expr, 0,
+ reloc->base = yasm_expr_extract_symrec(&wrt_expr,
+ YASM_SYMREC_REPLACE_ZERO,
yasm_common_calc_bc_dist);
if (!reloc->base) {
yasm__error(bc->line, N_("WRT expression too complex"));