diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2016-02-12 15:06:23 -0800 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2016-02-12 15:06:23 -0800 |
commit | 941356b2ca5499469ec31427b18019b5456b7606 (patch) | |
tree | e26e556963ce782afbbfae951572d9a10eeae7ac | |
parent | ca351fa1756a47d70b9fa7db6fe6ad8c9ab0d8c6 (diff) | |
download | nasm-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.c | 55 |
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" |