0
0
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:
H. Peter Anvin
2010-05-06 15:25:43 -07:00
parent 97ec06a16a
commit 55ae12052c
6 changed files with 68 additions and 126 deletions

View File

@@ -365,23 +365,15 @@ int64_t assemble(int32_t segment, int64_t offset, int bits, uint32_t cp,
while (t--) { /* repeat TIMES times */ while (t--) { /* repeat TIMES times */
list_for_each(e, instruction->eops) { list_for_each(e, instruction->eops) {
if (e->type == EOT_DB_NUMBER) { if (e->type == EOT_DB_NUMBER) {
if (wsize == 1) { if (wsize > 8) {
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) {
errfunc(ERR_NONFATAL, errfunc(ERR_NONFATAL,
"integer supplied to a DT, DO or DY" "integer supplied to a DT, DO or DY"
" instruction"); " instruction");
} else } else {
out(offset, segment, &e->offset, out(offset, segment, &e->offset,
OUT_ADDRESS, wsize, e->segment, e->wrt); OUT_ADDRESS, wsize, e->segment, e->wrt);
offset += wsize; offset += wsize;
}
} else if (e->type == EOT_DB_STRING || } else if (e->type == EOT_DB_STRING ||
e->type == EOT_DB_STRING_FREE) { e->type == EOT_DB_STRING_FREE) {
int align; int align;

113
listing.c
View File

@@ -173,9 +173,30 @@ static void list_out(int32_t offset, char *str)
strcat(listdata, 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, static void list_output(int32_t offset, const void *data,
enum out_type type, uint64_t size) enum out_type type, uint64_t size)
{ {
char q[20];
if (!listp || suppress || user_nolist) /* fbk - 9/2/00 */ if (!listp || suppress || user_nolist) /* fbk - 9/2/00 */
return; return;
@@ -183,7 +204,7 @@ static void list_output(int32_t offset, const void *data,
case OUT_RAWDATA: case OUT_RAWDATA:
{ {
uint8_t const *p = data; uint8_t const *p = data;
char q[3];
if (size == 0 && !listdata[0]) if (size == 0 && !listdata[0])
listoffset = offset; listoffset = offset;
while (size--) { while (size--) {
@@ -195,98 +216,22 @@ static void list_output(int32_t offset, const void *data,
break; break;
} }
case OUT_ADDRESS: case OUT_ADDRESS:
{ list_address(offset, "[]", *(int64_t *)data, size);
uint64_t d = *(int64_t *)data; break;
char q[20]; case OUT_REL1ADR:
uint8_t p[8], *r = p; list_address(offset, "()", *(int64_t *)data, 1);
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);
}
break; break;
}
case OUT_REL2ADR: case OUT_REL2ADR:
{ list_address(offset, "()", *(int64_t *)data, 2);
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);
break; break;
}
case OUT_REL4ADR: case OUT_REL4ADR:
{ list_address(offset, "()", *(int64_t *)data, 4);
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);
break; break;
}
case OUT_REL8ADR: case OUT_REL8ADR:
{ list_address(offset, "()", *(int64_t *)data, 8);
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);
break; break;
}
case OUT_RESERVE: case OUT_RESERVE:
{ {
char q[20];
snprintf(q, sizeof(q), "<res %08"PRIX64">", size); snprintf(q, sizeof(q), "<res %08"PRIX64">", size);
list_out(offset, q); list_out(offset, q);
break; break;

1
nasm.h
View File

@@ -101,6 +101,7 @@ enum out_type {
OUT_RAWDATA, /* Plain bytes */ OUT_RAWDATA, /* Plain bytes */
OUT_ADDRESS, /* An address (symbol value) */ OUT_ADDRESS, /* An address (symbol value) */
OUT_RESERVE, /* Reserved bytes (RESB et al) */ OUT_RESERVE, /* Reserved bytes (RESB et al) */
OUT_REL1ADR, /* 1-byte relative address */
OUT_REL2ADR, /* 2-byte relative address */ OUT_REL2ADR, /* 2-byte relative address */
OUT_REL4ADR, /* 4-byte relative address */ OUT_REL4ADR, /* 4-byte relative address */
OUT_REL8ADR, /* 8-byte relative address */ OUT_REL8ADR, /* 8-byte relative address */

View File

@@ -540,24 +540,13 @@ static void bin_cleanup(int debuginfo)
list_for_each(r, relocs) { list_for_each(r, relocs) {
uint8_t *p, *q, mydata[8]; uint8_t *p, *q, mydata[8];
int64_t l; int64_t l;
int b;
saa_fread(r->target->contents, r->posn, mydata, r->bytes); saa_fread(r->target->contents, r->posn, mydata, r->bytes);
p = q = mydata; p = q = mydata;
l = *p++; l = 0;
for (b = 0; b < r->bytes; b++)
if (r->bytes > 1) { l = (l << 8) + *p++;
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;
}
}
s = find_section_by_index(r->secref); s = find_section_by_index(r->secref);
if (s) { if (s) {
@@ -574,12 +563,7 @@ static void bin_cleanup(int debuginfo)
l -= s->vstart; l -= s->vstart;
} }
if (r->bytes >= 4) WRITEADDR(q, l, r->bytes);
WRITEDLONG(q, l);
else if (r->bytes == 2)
WRITESHORT(q, l);
else
*q++ = (uint8_t)(l & 0xFF);
saa_fwrite(r->target->contents, r->posn, mydata, 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" nasm_error(ERR_WARNING, "attempt to initialize memory in a"
" nobits section: ignored"); " nobits section: ignored");
if (type == OUT_ADDRESS) { switch (type) {
case OUT_ADDRESS:
if (segment != NO_SEG && !find_section_by_index(segment)) { if (segment != NO_SEG && !find_section_by_index(segment)) {
if (segment % 2) if (segment % 2)
nasm_error(ERR_NONFATAL, "binary output format does not support" 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); WRITEADDR(p, *(int64_t *)data, size);
saa_wbytes(s->contents, mydata, size); saa_wbytes(s->contents, mydata, size);
} }
s->length += size; break;
} else if (type == OUT_RAWDATA) {
case OUT_RAWDATA:
if (s->flags & TYPE_PROGBITS) if (s->flags & TYPE_PROGBITS)
saa_wbytes(s->contents, data, size); saa_wbytes(s->contents, data, size);
s->length += size; break;
} else if (type == OUT_RESERVE) {
case OUT_RESERVE:
if (s->flags & TYPE_PROGBITS) { if (s->flags & TYPE_PROGBITS) {
nasm_error(ERR_WARNING, "uninitialized space declared in" nasm_error(ERR_WARNING, "uninitialized space declared in"
" %s section: zeroing", s->name); " %s section: zeroing", s->name);
saa_wbytes(s->contents, NULL, size); saa_wbytes(s->contents, NULL, size);
} }
s->length += size; break;
} else if (type == OUT_REL2ADR || type == OUT_REL4ADR ||
type == OUT_REL8ADR) { case OUT_REL1ADR:
case OUT_REL2ADR:
case OUT_REL4ADR:
case OUT_REL8ADR:
{
int64_t addr = *(int64_t *)data - size; int64_t addr = *(int64_t *)data - size;
size = realsize(type, size); size = realsize(type, size);
if (segment != NO_SEG && !find_section_by_index(segment)) { 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); WRITEADDR(p, addr - s->length, size);
saa_wbytes(s->contents, mydata, 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, static void bin_deflabel(char *name, int32_t segment, int64_t offset,

View File

@@ -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, fprintf(ofile, "addr %08"PRIx32" (seg %08"PRIx32", wrt %08"PRIx32")\n", ldata,
segment, wrt); segment, wrt);
break; break;
case OUT_REL1ADR:
fprintf(ofile, "rel1adr %02"PRIx8" (seg %08"PRIx32")\n",
(uint8_t)*(int64_t *)data, segment);
break;
case OUT_REL2ADR: case OUT_REL2ADR:
fprintf(ofile, "rel2adr %04"PRIx16" (seg %08"PRIx32")\n", fprintf(ofile, "rel2adr %04"PRIx16" (seg %08"PRIx32")\n",
(uint16_t)*(int64_t *)data, segment); (uint16_t)*(int64_t *)data, segment);

View File

@@ -44,6 +44,8 @@
uint64_t realsize(enum out_type type, uint64_t size) uint64_t realsize(enum out_type type, uint64_t size)
{ {
switch (type) { switch (type) {
case OUT_REL1ADR:
return 1;
case OUT_REL2ADR: case OUT_REL2ADR:
return 2; return 2;
case OUT_REL4ADR: case OUT_REL4ADR: