From 55ae12052cd110cc27fa8ef15a114b4e75fa4c24 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Thu, 6 May 2010 15:25:43 -0700 Subject: [PATCH] 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 --- assemble.c | 16 ++------ listing.c | 113 +++++++++++++++----------------------------------------- nasm.h | 1 + output/outbin.c | 58 ++++++++++++++--------------- output/outdbg.c | 4 ++ output/outlib.c | 2 + 6 files changed, 68 insertions(+), 126 deletions(-) diff --git a/assemble.c b/assemble.c index ca6f18f1..00ee78fb 100644 --- a/assemble.c +++ b/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; + offset += wsize; + } } else if (e->type == EOT_DB_STRING || e->type == EOT_DB_STRING_FREE) { int align; diff --git a/listing.c b/listing.c index 5a09440c..38d7908e 100644 --- a/listing.c +++ b/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), "", size); list_out(offset, q); break; diff --git a/nasm.h b/nasm.h index 4bdaec8e..236f2f40 100644 --- a/nasm.h +++ b/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 */ diff --git a/output/outbin.c b/output/outbin.c index dca7721c..70a50998 100644 --- a/output/outbin.c +++ b/output/outbin.c @@ -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, diff --git a/output/outdbg.c b/output/outdbg.c index 13d53bd8..675af83e 100644 --- a/output/outdbg.c +++ b/output/outdbg.c @@ -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); diff --git a/output/outlib.c b/output/outlib.c index 56ac6cd5..10f1bfa0 100644 --- a/output/outlib.c +++ b/output/outlib.c @@ -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: -- 2.11.4.GIT