summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2016-02-12 15:06:23 -0800
committerH. Peter Anvin <hpa@linux.intel.com>2016-02-12 15:06:23 -0800
commit941356b2ca5499469ec31427b18019b5456b7606 (patch)
treee26e556963ce782afbbfae951572d9a10eeae7ac
parentca351fa1756a47d70b9fa7db6fe6ad8c9ab0d8c6 (diff)
downloadnasm-941356b2ca5499469ec31427b18019b5456b7606.tar.gz
outmac: generate section-relative relocations for local symbols
We generate section-relative relocations for local symbols for all the other output formats, and we should do the same for MachO; this was done in MachO-32 but not in MachO-64, presumably because the MachO spec implies that such relocations shouldn't exist in 64-bit code. They are indeed rare, but that is a programmer's decision, and the spec is clear that they are legal. Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r--output/outmac.c55
1 files changed, 13 insertions, 42 deletions
diff --git a/output/outmac.c b/output/outmac.c
index dc1111d4..a2209c6e 100644
--- a/output/outmac.c
+++ b/output/outmac.c
@@ -328,26 +328,6 @@ static uint8_t get_section_fileindex_by_index(const int32_t index)
return NO_SECT;
}
-static struct symbol *get_closest_section_symbol_by_offset(uint8_t fileindex, int64_t offset)
-{
- struct symbol *nearest = NULL;
- struct symbol *sym;
-
- for (sym = syms; sym; sym = sym->next) {
- if ((sym->sect != NO_SECT) && (sym->sect == fileindex)) {
- if ((int64_t)sym->value > offset)
- break;
- nearest = sym;
- }
- }
-
- if (!nearest)
- nasm_error(ERR_FATAL, "No section for index %x offset %llx found\n",
- fileindex, (long long)offset);
-
- return nearest;
-}
-
/*
* Special section numbers which are used to define Mach-O special
* symbols, which can be used with WRT to provide PIC relocation
@@ -390,16 +370,11 @@ enum reltype {
RL_GOTLOAD, /* X86_64_RELOC_GOT_LOAD */
};
-static int32_t add_reloc(struct section *sect, int32_t section,
- enum reltype reltype, int bytes, int64_t reloff)
+static void add_reloc(struct section *sect, int32_t section,
+ enum reltype reltype, int bytes)
{
struct reloc *r;
- struct symbol *sym;
int32_t fi;
- int32_t adjustment = 0;
-
- if (section == NO_SEG)
- return 0;
/* NeXT as puts relocs in reversed order (address-wise) into the
** files, so we do the same, doesn't seem to make much of a
@@ -427,20 +402,19 @@ static int32_t add_reloc(struct section *sect, int32_t section,
switch (reltype) {
case RL_ABS:
if (section == NO_SEG) {
- /* intra-section */
+ /* absolute (can this even happen?) */
+ r->ext = 0;
r->snum = R_ABS;
} else {
/* inter-section */
fi = get_section_fileindex_by_index(section);
-
if (fi == NO_SECT) {
/* external */
r->snum = raa_read(extsyms, section);
} else {
/* local */
- sym = get_closest_section_symbol_by_offset(fi, reloff);
- r->snum = sym->initial_snum;
- adjustment = sym->value;
+ r->ext = 0;
+ r->snum = fi;
}
}
break;
@@ -461,9 +435,8 @@ static int32_t add_reloc(struct section *sect, int32_t section,
r->snum = raa_read(extsyms, section);
} else {
/* local */
- sym = get_closest_section_symbol_by_offset(fi, reloff);
- r->snum = sym->initial_snum;
- adjustment = sym->value;
+ r->ext = 0;
+ r->snum = fi;
}
}
break;
@@ -487,8 +460,6 @@ static int32_t add_reloc(struct section *sect, int32_t section,
}
++sect->nreloc;
-
- return adjustment;
}
static void macho_output(int32_t secto, const void *data,
@@ -564,7 +535,7 @@ static void macho_output(int32_t secto, const void *data,
nasm_error(ERR_NONFATAL, "Mach-O 64-bit format does not support"
" 32-bit absolute addresses");
} else {
- addr -= add_reloc(s, section, RL_ABS, asize, addr);
+ add_reloc(s, section, RL_ABS, asize);
}
} else {
nasm_error(ERR_NONFATAL, "Mach-O format does not support"
@@ -595,7 +566,7 @@ static void macho_output(int32_t secto, const void *data,
" this use of WRT");
wrt = NO_SEG; /* we can at least _try_ to continue */
} else {
- addr -= add_reloc(s, section, RL_REL, 2, addr);
+ add_reloc(s, section, RL_REL, 2);
}
WRITESHORT(p, addr);
@@ -613,7 +584,7 @@ static void macho_output(int32_t secto, const void *data,
" section base references");
} else if (wrt == NO_SEG) {
/* Plain relative relocation */
- addr -= add_reloc(s, section, RL_REL, 4, addr);
+ add_reloc(s, section, RL_REL, 4);
} else if (wrt == macho_gotpcrel_sect) {
if (s->data->datalen > 1) {
/* Retrieve instruction opcode */
@@ -623,10 +594,10 @@ static void macho_output(int32_t secto, const void *data,
}
if (gotload == 0x8B) {
/* Check for MOVQ Opcode -> X86_64_RELOC_GOT_LOAD */
- addr -= add_reloc(s, section, RL_GOTLOAD, 4, addr);
+ add_reloc(s, section, RL_GOTLOAD, 4);
} else {
/* X86_64_RELOC_GOT */
- addr -= add_reloc(s, section, RL_GOT, 4, addr);
+ add_reloc(s, section, RL_GOT, 4);
}
} else {
nasm_error(ERR_NONFATAL, "Mach-O format does not support"