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:
16
assemble.c
16
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 */
|
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
113
listing.c
@@ -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
1
nasm.h
@@ -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 */
|
||||||
|
@@ -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,
|
||||||
|
@@ -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);
|
||||||
|
@@ -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:
|
||||||
|
Reference in New Issue
Block a user