mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-01-30 16:41:05 +08:00
assemble.c: handle oversized relative relocations
Handle the case of oversized (larger than permitted by the output format) relative relocations. Relative relocations are always signed, and quite likely to actually have the sign bits set, so zero-extending them is not an option. Fortunately oversized relative relocations are rare, as no CPU instruction support 64-bit relative addresses. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
This commit is contained in:
parent
33814133bd
commit
b64125022d
29
assemble.c
29
assemble.c
@ -305,6 +305,27 @@ static void warn_overflow_opd(const struct operand *o, int size)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Size of an address relocation, or zero if not an address
|
||||
*/
|
||||
static int addrsize(enum out_type type, uint64_t size)
|
||||
{
|
||||
switch (type) {
|
||||
case OUT_ADDRESS:
|
||||
return abs((int)size);
|
||||
case OUT_REL1ADR:
|
||||
return 1;
|
||||
case OUT_REL2ADR:
|
||||
return 2;
|
||||
case OUT_REL4ADR:
|
||||
return 4;
|
||||
case OUT_REL8ADR:
|
||||
return 8;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine wrappers the real output format's output routine,
|
||||
* in order to pass a copy of the data off to the listing file
|
||||
@ -318,7 +339,7 @@ static void out(int64_t offset, int32_t segto, const void *data,
|
||||
static int32_t lineno = 0; /* static!!! */
|
||||
static char *lnfname = NULL;
|
||||
uint8_t p[8];
|
||||
const int asize = abs((int)size); /* True address size */
|
||||
int asize = addrsize(type, size); /* Address size in bytes */
|
||||
const int amax = outfmt->maxbits >> 3; /* Maximum address size in bytes */
|
||||
|
||||
if (type == OUT_ADDRESS && segment == NO_SEG && wrt == NO_SEG) {
|
||||
@ -336,6 +357,8 @@ static void out(int64_t offset, int32_t segto, const void *data,
|
||||
WRITEADDR(q, *(int64_t *)data, asize);
|
||||
data = p;
|
||||
type = OUT_RAWDATA;
|
||||
|
||||
asize = 0; /* No longer an address */
|
||||
}
|
||||
|
||||
list->output(offset, data, type, size);
|
||||
@ -352,8 +375,8 @@ static void out(int64_t offset, int32_t segto, const void *data,
|
||||
if (src_get(&lineno, &lnfname))
|
||||
outfmt->current_dfmt->linenum(lnfname, lineno, segto);
|
||||
|
||||
if (type == OUT_ADDRESS && asize > amax) {
|
||||
if (asize < 0) {
|
||||
if (asize && asize > amax) {
|
||||
if (type != OUT_ADDRESS || (int)size < 0) {
|
||||
errfunc(ERR_NONFATAL,
|
||||
"%d-bit signed relocation unsupported by output format %s\n",
|
||||
asize << 3, outfmt->shortname);
|
||||
|
Loading…
Reference in New Issue
Block a user