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 */
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;
offset += wsize;
}
} else if (e->type == EOT_DB_STRING ||
e->type == EOT_DB_STRING_FREE) {
int align;

113
listing.c
View File

@@ -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
View File

@@ -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 */

View File

@@ -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,

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,
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);

View File

@@ -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: