summaryrefslogtreecommitdiff
path: root/output
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2010-05-06 15:25:43 -0700
committerH. Peter Anvin <hpa@linux.intel.com>2010-05-06 15:33:24 -0700
commit55ae12052cd110cc27fa8ef15a114b4e75fa4c24 (patch)
treebdb7acd17f7c4b75f2ff48e527a9d454260b35ba /output
parent97ec06a16a0871330d8f4544de9cd95fc88d31df (diff)
downloadnasm-55ae12052cd110cc27fa8ef15a114b4e75fa4c24.tar.gz
nasm-55ae12052cd110cc27fa8ef15a114b4e75fa4c24.tar.bz2
nasm-55ae12052cd110cc27fa8ef15a114b4e75fa4c24.zip
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>
Diffstat (limited to 'output')
-rw-r--r--output/outbin.c58
-rw-r--r--output/outdbg.c4
-rw-r--r--output/outlib.c2
3 files changed, 34 insertions, 30 deletions
diff --git a/output/outbin.c b/output/outbin.c
index dca7721..70a5099 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 13d53bd..675af83 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 56ac6cd..10f1bfa 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: