mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-09-22 10:43:39 -04:00
Add support for one-byte relocations
Add OUT_REL1ADR (one-byte relative address) and support for OUT_ADDRESs with size == 1. Add support for it in outbin and outdbg. *It still needs to be added to other backends*, both the OUT_REL*ADR and OUT_ADDRESS codepaths need to be handled. Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
This commit is contained in:
14
assemble.c
14
assemble.c
@@ -365,23 +365,15 @@ int64_t assemble(int32_t segment, int64_t offset, int bits, uint32_t cp,
|
||||
while (t--) { /* repeat TIMES times */
|
||||
list_for_each(e, instruction->eops) {
|
||||
if (e->type == EOT_DB_NUMBER) {
|
||||
if (wsize == 1) {
|
||||
if (e->segment != NO_SEG)
|
||||
errfunc(ERR_NONFATAL,
|
||||
"one-byte relocation attempted");
|
||||
else {
|
||||
uint8_t out_byte = e->offset;
|
||||
out(offset, segment, &out_byte,
|
||||
OUT_RAWDATA, 1, NO_SEG, NO_SEG);
|
||||
}
|
||||
} else if (wsize > 8) {
|
||||
if (wsize > 8) {
|
||||
errfunc(ERR_NONFATAL,
|
||||
"integer supplied to a DT, DO or DY"
|
||||
" instruction");
|
||||
} else
|
||||
} else {
|
||||
out(offset, segment, &e->offset,
|
||||
OUT_ADDRESS, wsize, e->segment, e->wrt);
|
||||
offset += wsize;
|
||||
}
|
||||
} else if (e->type == EOT_DB_STRING ||
|
||||
e->type == EOT_DB_STRING_FREE) {
|
||||
int align;
|
||||
|
113
listing.c
113
listing.c
@@ -173,9 +173,30 @@ static void list_out(int32_t offset, char *str)
|
||||
strcat(listdata, str);
|
||||
}
|
||||
|
||||
static void list_address(int32_t offset, const char *brackets,
|
||||
int64_t addr, int size)
|
||||
{
|
||||
char q[20];
|
||||
char *r = q;
|
||||
|
||||
nasm_assert(size <= 8);
|
||||
|
||||
*r++ = brackets[0];
|
||||
while (size--) {
|
||||
HEX(r, addr);
|
||||
addr >>= 8;
|
||||
r += 2;
|
||||
}
|
||||
*r++ = brackets[1];
|
||||
*r = '\0';
|
||||
list_out(offset, q);
|
||||
}
|
||||
|
||||
static void list_output(int32_t offset, const void *data,
|
||||
enum out_type type, uint64_t size)
|
||||
{
|
||||
char q[20];
|
||||
|
||||
if (!listp || suppress || user_nolist) /* fbk - 9/2/00 */
|
||||
return;
|
||||
|
||||
@@ -183,7 +204,7 @@ static void list_output(int32_t offset, const void *data,
|
||||
case OUT_RAWDATA:
|
||||
{
|
||||
uint8_t const *p = data;
|
||||
char q[3];
|
||||
|
||||
if (size == 0 && !listdata[0])
|
||||
listoffset = offset;
|
||||
while (size--) {
|
||||
@@ -195,98 +216,22 @@ static void list_output(int32_t offset, const void *data,
|
||||
break;
|
||||
}
|
||||
case OUT_ADDRESS:
|
||||
{
|
||||
uint64_t d = *(int64_t *)data;
|
||||
char q[20];
|
||||
uint8_t p[8], *r = p;
|
||||
if (size == 4) {
|
||||
q[0] = '[';
|
||||
q[9] = ']';
|
||||
q[10] = '\0';
|
||||
WRITELONG(r, d);
|
||||
HEX(q + 1, p[0]);
|
||||
HEX(q + 3, p[1]);
|
||||
HEX(q + 5, p[2]);
|
||||
HEX(q + 7, p[3]);
|
||||
list_out(offset, q);
|
||||
} else if (size == 8) {
|
||||
q[0] = '[';
|
||||
q[17] = ']';
|
||||
q[18] = '\0';
|
||||
WRITEDLONG(r, d);
|
||||
HEX(q + 1, p[0]);
|
||||
HEX(q + 3, p[1]);
|
||||
HEX(q + 5, p[2]);
|
||||
HEX(q + 7, p[3]);
|
||||
HEX(q + 9, p[4]);
|
||||
HEX(q + 11, p[5]);
|
||||
HEX(q + 13, p[6]);
|
||||
HEX(q + 15, p[7]);
|
||||
list_out(offset, q);
|
||||
} else {
|
||||
q[0] = '[';
|
||||
q[5] = ']';
|
||||
q[6] = '\0';
|
||||
WRITESHORT(r, d);
|
||||
HEX(q + 1, p[0]);
|
||||
HEX(q + 3, p[1]);
|
||||
list_out(offset, q);
|
||||
}
|
||||
list_address(offset, "[]", *(int64_t *)data, size);
|
||||
break;
|
||||
case OUT_REL1ADR:
|
||||
list_address(offset, "()", *(int64_t *)data, 1);
|
||||
break;
|
||||
}
|
||||
case OUT_REL2ADR:
|
||||
{
|
||||
uint32_t d = *(int32_t *)data;
|
||||
char q[11];
|
||||
uint8_t p[4], *r = p;
|
||||
q[0] = '(';
|
||||
q[5] = ')';
|
||||
q[6] = '\0';
|
||||
WRITESHORT(r, d);
|
||||
HEX(q + 1, p[0]);
|
||||
HEX(q + 3, p[1]);
|
||||
list_out(offset, q);
|
||||
list_address(offset, "()", *(int64_t *)data, 2);
|
||||
break;
|
||||
}
|
||||
case OUT_REL4ADR:
|
||||
{
|
||||
uint32_t d = *(int32_t *)data;
|
||||
char q[11];
|
||||
uint8_t p[4], *r = p;
|
||||
q[0] = '(';
|
||||
q[9] = ')';
|
||||
q[10] = '\0';
|
||||
WRITELONG(r, d);
|
||||
HEX(q + 1, p[0]);
|
||||
HEX(q + 3, p[1]);
|
||||
HEX(q + 5, p[2]);
|
||||
HEX(q + 7, p[3]);
|
||||
list_out(offset, q);
|
||||
list_address(offset, "()", *(int64_t *)data, 4);
|
||||
break;
|
||||
}
|
||||
case OUT_REL8ADR:
|
||||
{
|
||||
uint64_t d = *(int64_t *)data;
|
||||
char q[19];
|
||||
uint8_t p[8], *r = p;
|
||||
q[0] = '(';
|
||||
q[17] = ')';
|
||||
q[18] = '\0';
|
||||
WRITEDLONG(r, d);
|
||||
HEX(q + 1, p[0]);
|
||||
HEX(q + 3, p[1]);
|
||||
HEX(q + 5, p[2]);
|
||||
HEX(q + 7, p[3]);
|
||||
HEX(q + 9, p[4]);
|
||||
HEX(q + 11, p[5]);
|
||||
HEX(q + 13, p[6]);
|
||||
HEX(q + 15, p[7]);
|
||||
list_out(offset, q);
|
||||
list_address(offset, "()", *(int64_t *)data, 8);
|
||||
break;
|
||||
}
|
||||
case OUT_RESERVE:
|
||||
{
|
||||
char q[20];
|
||||
snprintf(q, sizeof(q), "<res %08"PRIX64">", size);
|
||||
list_out(offset, q);
|
||||
break;
|
||||
|
1
nasm.h
1
nasm.h
@@ -101,6 +101,7 @@ enum out_type {
|
||||
OUT_RAWDATA, /* Plain bytes */
|
||||
OUT_ADDRESS, /* An address (symbol value) */
|
||||
OUT_RESERVE, /* Reserved bytes (RESB et al) */
|
||||
OUT_REL1ADR, /* 1-byte relative address */
|
||||
OUT_REL2ADR, /* 2-byte relative address */
|
||||
OUT_REL4ADR, /* 4-byte relative address */
|
||||
OUT_REL8ADR, /* 8-byte relative address */
|
||||
|
@@ -540,24 +540,13 @@ static void bin_cleanup(int debuginfo)
|
||||
list_for_each(r, relocs) {
|
||||
uint8_t *p, *q, mydata[8];
|
||||
int64_t l;
|
||||
int b;
|
||||
|
||||
saa_fread(r->target->contents, r->posn, mydata, r->bytes);
|
||||
p = q = mydata;
|
||||
l = *p++;
|
||||
|
||||
if (r->bytes > 1) {
|
||||
l += ((int64_t)*p++) << 8;
|
||||
if (r->bytes >= 4) {
|
||||
l += ((int64_t)*p++) << 16;
|
||||
l += ((int64_t)*p++) << 24;
|
||||
}
|
||||
if (r->bytes == 8) {
|
||||
l += ((int64_t)*p++) << 32;
|
||||
l += ((int64_t)*p++) << 40;
|
||||
l += ((int64_t)*p++) << 48;
|
||||
l += ((int64_t)*p++) << 56;
|
||||
}
|
||||
}
|
||||
l = 0;
|
||||
for (b = 0; b < r->bytes; b++)
|
||||
l = (l << 8) + *p++;
|
||||
|
||||
s = find_section_by_index(r->secref);
|
||||
if (s) {
|
||||
@@ -574,12 +563,7 @@ static void bin_cleanup(int debuginfo)
|
||||
l -= s->vstart;
|
||||
}
|
||||
|
||||
if (r->bytes >= 4)
|
||||
WRITEDLONG(q, l);
|
||||
else if (r->bytes == 2)
|
||||
WRITESHORT(q, l);
|
||||
else
|
||||
*q++ = (uint8_t)(l & 0xFF);
|
||||
WRITEADDR(q, l, r->bytes);
|
||||
saa_fwrite(r->target->contents, r->posn, mydata, r->bytes);
|
||||
}
|
||||
|
||||
@@ -776,7 +760,8 @@ static void bin_out(int32_t segto, const void *data,
|
||||
nasm_error(ERR_WARNING, "attempt to initialize memory in a"
|
||||
" nobits section: ignored");
|
||||
|
||||
if (type == OUT_ADDRESS) {
|
||||
switch (type) {
|
||||
case OUT_ADDRESS:
|
||||
if (segment != NO_SEG && !find_section_by_index(segment)) {
|
||||
if (segment % 2)
|
||||
nasm_error(ERR_NONFATAL, "binary output format does not support"
|
||||
@@ -793,20 +778,26 @@ static void bin_out(int32_t segto, const void *data,
|
||||
WRITEADDR(p, *(int64_t *)data, size);
|
||||
saa_wbytes(s->contents, mydata, size);
|
||||
}
|
||||
s->length += size;
|
||||
} else if (type == OUT_RAWDATA) {
|
||||
break;
|
||||
|
||||
case OUT_RAWDATA:
|
||||
if (s->flags & TYPE_PROGBITS)
|
||||
saa_wbytes(s->contents, data, size);
|
||||
s->length += size;
|
||||
} else if (type == OUT_RESERVE) {
|
||||
break;
|
||||
|
||||
case OUT_RESERVE:
|
||||
if (s->flags & TYPE_PROGBITS) {
|
||||
nasm_error(ERR_WARNING, "uninitialized space declared in"
|
||||
" %s section: zeroing", s->name);
|
||||
saa_wbytes(s->contents, NULL, size);
|
||||
}
|
||||
s->length += size;
|
||||
} else if (type == OUT_REL2ADR || type == OUT_REL4ADR ||
|
||||
type == OUT_REL8ADR) {
|
||||
break;
|
||||
|
||||
case OUT_REL1ADR:
|
||||
case OUT_REL2ADR:
|
||||
case OUT_REL4ADR:
|
||||
case OUT_REL8ADR:
|
||||
{
|
||||
int64_t addr = *(int64_t *)data - size;
|
||||
size = realsize(type, size);
|
||||
if (segment != NO_SEG && !find_section_by_index(segment)) {
|
||||
@@ -824,8 +815,15 @@ static void bin_out(int32_t segto, const void *data,
|
||||
WRITEADDR(p, addr - s->length, size);
|
||||
saa_wbytes(s->contents, mydata, size);
|
||||
}
|
||||
s->length += size;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
nasm_error(ERR_NONFATAL, "unsupported relocation type %d\n", type);
|
||||
break;
|
||||
}
|
||||
|
||||
s->length += size;
|
||||
}
|
||||
|
||||
static void bin_deflabel(char *name, int32_t segment, int64_t offset,
|
||||
|
@@ -147,6 +147,10 @@ static void dbg_out(int32_t segto, const void *data,
|
||||
fprintf(ofile, "addr %08"PRIx32" (seg %08"PRIx32", wrt %08"PRIx32")\n", ldata,
|
||||
segment, wrt);
|
||||
break;
|
||||
case OUT_REL1ADR:
|
||||
fprintf(ofile, "rel1adr %02"PRIx8" (seg %08"PRIx32")\n",
|
||||
(uint8_t)*(int64_t *)data, segment);
|
||||
break;
|
||||
case OUT_REL2ADR:
|
||||
fprintf(ofile, "rel2adr %04"PRIx16" (seg %08"PRIx32")\n",
|
||||
(uint16_t)*(int64_t *)data, segment);
|
||||
|
@@ -44,6 +44,8 @@
|
||||
uint64_t realsize(enum out_type type, uint64_t size)
|
||||
{
|
||||
switch (type) {
|
||||
case OUT_REL1ADR:
|
||||
return 1;
|
||||
case OUT_REL2ADR:
|
||||
return 2;
|
||||
case OUT_REL4ADR:
|
||||
|
Reference in New Issue
Block a user