macho/reloc: Fixed offset adjustment in add_reloc()

If the target symbol is in the same file, add_reloc() emits an
internal reloc for the target section, and the offset written
is the offset in the target section.  If the target symbol is
external, its offset is zero (or an explicit addend), and
add_reloc() emits an external reloc for the symbol.

Based-on-code-from: zenith432 <zenith432@users.sourceforge.net>
Signed-off-by: Chang S. Bae <changseok.bae@gmail.com>
This commit is contained in:
Chang S. Bae 2018-10-08 18:49:54 -07:00 committed by Cyrill Gorcunov
parent 960efc3ff2
commit f63d211bcf

View File

@ -495,7 +495,7 @@ static int64_t add_reloc(struct section *sect, int32_t section,
r = nasm_malloc(sizeof(struct reloc));
r->addr = sect->size & ~R_SCATTERED;
r->ext = 1;
adjust = bytes;
adjust = 0;
/* match byte count 1, 2, 4, 8 to length codes 0, 1, 2, 3 respectively */
r->length = ilog2_32(bytes);
@ -521,7 +521,6 @@ static int64_t add_reloc(struct section *sect, int32_t section,
/* local */
r->ext = 0;
r->snum = fi;
adjust = -sect->size;
}
break;
@ -538,15 +537,12 @@ static int64_t add_reloc(struct section *sect, int32_t section,
r->snum = raa_read(extsyms, section);
if (reltype == RL_BRANCH)
r->type = X86_64_RELOC_BRANCH;
else if (r->type == GENERIC_RELOC_VANILLA)
adjust = -sect->size;
} else {
/* local */
r->ext = 0;
r->snum = fi;
if (reltype == RL_BRANCH)
r->type = X86_64_RELOC_BRANCH;
adjust = -sect->size;
}
break;
@ -587,6 +583,7 @@ static int64_t add_reloc(struct section *sect, int32_t section,
goto bail;
}
adjust -= sym->symv[0].key;
r->snum = sym->initial_snum;
}
break;
@ -600,12 +597,15 @@ static int64_t add_reloc(struct section *sect, int32_t section,
struct symbol *sym = macho_find_sym(s ? s : &absolute_sect,
offset, false, false);
if (sym) {
adjust = bytes - sym->symv[0].key;
adjust -= sym->symv[0].key;
r->snum = sym->initial_snum;
r->ext = 1;
}
}
if (r->pcrel)
adjust += ((r->ext && fmt.ptrsize == 8) ? bytes : -(int64_t)sect->size);
/* 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
** difference either way */