summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2010-05-06 16:14:00 -0700
committerH. Peter Anvin <hpa@linux.intel.com>2010-05-06 16:14:00 -0700
commit32575e46acd5d569ee3119b6cab1770e92245b89 (patch)
tree3242b2ede25c4bded66be54ec9c86f0334c2b6d1
parentfea84d7fec9e5cc181ff148a6e49ac60cfdd8193 (diff)
downloadnasm-32575e46acd5d569ee3119b6cab1770e92245b89.tar.gz
nasm-32575e46acd5d569ee3119b6cab1770e92245b89.tar.bz2
nasm-32575e46acd5d569ee3119b6cab1770e92245b89.zip
ELF support for 8-bit relocations
Support 8-bit relocations (OUT_ADDRESS and OUT_REL1ADR) in ELF. Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r--output/outelf32.c84
-rw-r--r--output/outelf64.c43
2 files changed, 92 insertions, 35 deletions
diff --git a/output/outelf32.c b/output/outelf32.c
index 4d238a7..8a14af4 100644
--- a/output/outelf32.c
+++ b/output/outelf32.c
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
- * Copyright 1996-2009 The NASM Authors - All Rights Reserved
+ * Copyright 1996-2010 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@@ -715,7 +715,8 @@ static void elf_out(int32_t segto, const void *data,
{
struct Section *s;
int32_t addr;
- uint8_t mydata[4], *p;
+ uint8_t mydata[8], *p;
+ int reltype, bytes;
int i;
static struct symlininfo sinfo;
@@ -761,18 +762,24 @@ static void elf_out(int32_t segto, const void *data,
return;
}
- if (type == OUT_RESERVE) {
+ switch (type) {
+ case OUT_RESERVE:
if (s->type == SHT_PROGBITS) {
nasm_error(ERR_WARNING, "uninitialized space declared in"
" non-BSS section `%s': zeroing", s->name);
elf_sect_write(s, NULL, size);
} else
s->len += size;
- } else if (type == OUT_RAWDATA) {
+ break;
+
+ case OUT_RAWDATA:
if (segment != NO_SEG)
nasm_error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
elf_sect_write(s, data, size);
- } else if (type == OUT_ADDRESS) {
+ break;
+
+ case OUT_ADDRESS:
+ {
bool gnu16 = false;
addr = *(int64_t *)data;
if (segment != NO_SEG) {
@@ -781,11 +788,20 @@ static void elf_out(int32_t segto, const void *data,
" segment base references");
} else {
if (wrt == NO_SEG) {
- if (size == 2) {
- gnu16 = true;
+ switch (size) {
+ case 1:
+ gnu16 = true;
+ elf_add_reloc(s, segment, R_386_8);
+ break;
+ case 2:
+ gnu16 = true;
elf_add_reloc(s, segment, R_386_16);
- } else {
+ break;
+ case 4:
elf_add_reloc(s, segment, R_386_32);
+ break;
+ default: /* Error issued further down */
+ break;
}
} else if (wrt == elf_gotpc_sect + 1) {
/*
@@ -825,36 +841,45 @@ static void elf_out(int32_t segto, const void *data,
p = mydata;
if (gnu16) {
nasm_error(ERR_WARNING | ERR_WARN_GNUELF,
- "16-bit relocations in ELF is a GNU extension");
- WRITESHORT(p, addr);
- } else {
- if (size != 4 && segment != NO_SEG) {
- nasm_error(ERR_NONFATAL,
- "Unsupported non-32-bit ELF relocation");
- }
- WRITELONG(p, addr);
+ "8- or 16-bit relocations in ELF32 is a GNU extension");
+ } else if (size != 4 && segment != NO_SEG) {
+ nasm_error(ERR_NONFATAL, "Unsupported non-32-bit ELF relocation");
}
+ WRITEADDR(p, addr, size);
elf_sect_write(s, mydata, size);
- } else if (type == OUT_REL2ADR) {
- if (segment == segto)
- nasm_error(ERR_PANIC, "intra-segment OUT_REL2ADR");
+ break;
+ }
+
+ case OUT_REL1ADR:
+ bytes = 1;
+ reltype = R_386_PC8;
+ goto rel12adr;
+ case OUT_REL2ADR:
+ bytes = 2;
+ reltype = R_386_PC16;
+ goto rel12adr;
+
+ rel12adr:
+ nasm_assert(segment != segto);
if (segment != NO_SEG && segment % 2) {
nasm_error(ERR_NONFATAL, "ELF format does not support"
" segment base references");
} else {
if (wrt == NO_SEG) {
nasm_error(ERR_WARNING | ERR_WARN_GNUELF,
- "16-bit relocations in ELF is a GNU extension");
- elf_add_reloc(s, segment, R_386_PC16);
+ "8- or 16-bit relocations in ELF is a GNU extension");
+ elf_add_reloc(s, segment, reltype);
} else {
nasm_error(ERR_NONFATAL,
"Unsupported non-32-bit ELF relocation");
}
}
- p = mydata;
+ p = mydata;
WRITESHORT(p, *(int64_t *)data - size);
- elf_sect_write(s, mydata, 2L);
- } else if (type == OUT_REL4ADR) {
+ elf_sect_write(s, mydata, bytes);
+ break;
+
+ case OUT_REL4ADR:
if (segment == segto)
nasm_error(ERR_PANIC, "intra-segment OUT_REL4ADR");
if (segment != NO_SEG && segment % 2) {
@@ -876,9 +901,18 @@ static void elf_out(int32_t segto, const void *data,
wrt = NO_SEG; /* we can at least _try_ to continue */
}
}
- p = mydata;
+ p = mydata;
WRITELONG(p, *(int64_t *)data - size);
elf_sect_write(s, mydata, 4L);
+ break;
+
+ case OUT_REL8ADR:
+ nasm_error(ERR_NONFATAL,
+ "32-bit ELF format does not support 64-bit relocations");
+ p = mydata;
+ WRITEDLONG(p, 0);
+ elf_sect_write(s, mydata, 8L);
+ break;
}
}
diff --git a/output/outelf64.c b/output/outelf64.c
index 47581b4..76a6464 100644
--- a/output/outelf64.c
+++ b/output/outelf64.c
@@ -724,6 +724,7 @@ static void elf_out(int32_t segto, const void *data,
{
struct Section *s;
int64_t addr, zero;
+ int reltype, bytes;
int i;
static struct symlininfo sinfo;
@@ -783,18 +784,23 @@ static void elf_out(int32_t segto, const void *data,
return;
}
- if (type == OUT_RESERVE) {
+ switch (type) {
+ case OUT_RESERVE:
if (s->type == SHT_PROGBITS) {
nasm_error(ERR_WARNING, "uninitialized space declared in"
" non-BSS section `%s': zeroing", s->name);
elf_sect_write(s, NULL, size);
} else
s->len += size;
- } else if (type == OUT_RAWDATA) {
+ break;
+
+ case OUT_RAWDATA:
if (segment != NO_SEG)
nasm_error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
elf_sect_write(s, data, size);
- } else if (type == OUT_ADDRESS) {
+ break;
+
+ case OUT_ADDRESS:
addr = *(int64_t *)data;
if (segment == NO_SEG) {
/* Do nothing */
@@ -889,10 +895,22 @@ static void elf_out(int32_t segto, const void *data,
}
}
elf_sect_writeaddr(s, addr, size);
- } else if (type == OUT_REL2ADR) {
+ break;
+
+ case OUT_REL1ADR:
+ reltype = R_X86_64_PC8;
+ bytes = 1;
+ goto rel12adr;
+
+ case OUT_REL2ADR:
+ reltype = R_X86_64_PC16;
+ bytes = 2;
+ goto rel12adr;
+
+ rel12adr:
addr = *(int64_t *)data - size;
if (segment == segto)
- nasm_error(ERR_PANIC, "intra-segment OUT_REL2ADR");
+ nasm_error(ERR_PANIC, "intra-segment OUT_REL1ADR");
if (segment == NO_SEG) {
/* Do nothing */
} else if (segment % 2) {
@@ -900,15 +918,17 @@ static void elf_out(int32_t segto, const void *data,
" segment base references");
} else {
if (wrt == NO_SEG) {
- elf_add_reloc(s, segment, addr, R_X86_64_PC16);
+ elf_add_reloc(s, segment, addr, reltype);
addr = 0;
} else {
nasm_error(ERR_NONFATAL,
- "Unsupported non-32-bit ELF relocation [2]");
+ "Unsupported non-32-bit ELF relocation");
}
}
- elf_sect_writeaddr(s, addr, 2);
- } else if (type == OUT_REL4ADR) {
+ elf_sect_writeaddr(s, addr, bytes);
+ break;
+
+ case OUT_REL4ADR:
addr = *(int64_t *)data - size;
if (segment == segto)
nasm_error(ERR_PANIC, "intra-segment OUT_REL4ADR");
@@ -944,7 +964,9 @@ static void elf_out(int32_t segto, const void *data,
}
}
elf_sect_writeaddr(s, addr, 4);
- } else if (type == OUT_REL8ADR) {
+ break;
+
+ case OUT_REL8ADR:
addr = *(int64_t *)data - size;
if (segment == segto)
nasm_error(ERR_PANIC, "intra-segment OUT_REL8ADR");
@@ -975,6 +997,7 @@ static void elf_out(int32_t segto, const void *data,
}
}
elf_sect_writeaddr(s, addr, 8);
+ break;
}
}