New backend interface - assembler internals #1

This provides the first pass of assembler internals for a new, richer,
backend interface.  It also reduces the amount of data carried in
function parameters inside the assembler.

The new interface is in the form of a structure, which will contain
substantially more information that the previous interface.  This will
allow things like ELF GOT32X and Mach-O X86_64_RELOC_BRANCH
relocations to be reliably emitted.

This provides the initial set of structures.  Future additions should
include:

1. Pass down the base symbol, if any.
2. Segments should be a structure rather than a number, and the
   horrible hack of adding one for a segment reference should be
   removed (OUT_SEGMENT replaces it.)

Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
This commit is contained in:
H. Peter Anvin 2016-09-20 14:04:33 -07:00
parent 9938bb6333
commit a77692b34d
5 changed files with 593 additions and 594 deletions

File diff suppressed because it is too large Load diff

View file

@ -166,7 +166,7 @@ static void list_cleanup(void)
fclose(listfp);
}
static void list_out(int32_t offset, char *str)
static void list_out(int64_t offset, char *str)
{
if (strlen(listdata) + strlen(str) > LIST_HEXBIT) {
strcat(listdata, "-");
@ -177,7 +177,7 @@ static void list_out(int32_t offset, char *str)
strcat(listdata, str);
}
static void list_address(int32_t offset, const char *brackets,
static void list_address(int64_t offset, const char *brackets,
int64_t addr, int size)
{
char q[20];
@ -196,21 +196,22 @@ static void list_address(int32_t offset, const char *brackets,
list_out(offset, q);
}
static void list_output(int32_t offset, const void *data,
enum out_type type, uint64_t size)
static void list_output(const struct out_data *data)
{
char q[20];
uint64_t size = data->size;
uint64_t offset = data->offset;
if (!listp || suppress || user_nolist)
return;
switch (type) {
switch (data->type) {
case OUT_RAWDATA:
{
uint8_t const *p = data;
const uint8_t *p = data->data;
if (size == 0 && !listdata[0])
listoffset = offset;
listoffset = data->offset;
while (size--) {
HEX(q, *p);
q[2] = '\0';
@ -220,19 +221,11 @@ static void list_output(int32_t offset, const void *data,
break;
}
case OUT_ADDRESS:
list_address(offset, "[]", *(int64_t *)data, abs((int)size));
case OUT_SEGMENT:
list_address(offset, "[]", data->toffset, size);
break;
case OUT_REL1ADR:
list_address(offset, "()", *(int64_t *)data, 1);
break;
case OUT_REL2ADR:
list_address(offset, "()", *(int64_t *)data, 2);
break;
case OUT_REL4ADR:
list_address(offset, "()", *(int64_t *)data, 4);
break;
case OUT_REL8ADR:
list_address(offset, "()", *(int64_t *)data, 8);
case OUT_RELADDR:
list_address(offset, "()", data->toffset, size);
break;
case OUT_RESERVE:
{
@ -240,6 +233,8 @@ static void list_output(int32_t offset, const void *data,
list_out(offset, q);
break;
}
default:
panic();
}
}
@ -324,6 +319,10 @@ static void list_error(int severity, const char *pfx, const char *msg)
list_emit();
}
static void list_set_offset(uint64_t offset)
{
listoffset = offset;
}
static const struct lfmt nasm_list = {
list_init,
@ -332,7 +331,8 @@ static const struct lfmt nasm_list = {
list_line,
list_uplevel,
list_downlevel,
list_error
list_error,
list_set_offset
};
const struct lfmt *lfmt = &nasm_list;

View file

@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
* Copyright 1996-2009 The NASM Authors - All Rights Reserved
* Copyright 1996-2016 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@ -61,12 +61,9 @@ struct lfmt {
* output-format interface, only OUT_ADDRESS will _always_ be
* displayed as if it's relocatable, so ensure that any non-
* relocatable address has been converted to OUT_RAWDATA by
* then. Note that OUT_RAWDATA,0 is a valid data type, and is a
* dummy call used to give the listing generator an offset to
* work with when doing things like uplevel(LIST_TIMES) or
* uplevel(LIST_INCBIN).
* then.
*/
void (*output)(int32_t offset, const void *data, enum out_type type, uint64_t size);
void (*output)(const struct out_data *data);
/*
* Called to send a text line to the listing generator. The
@ -100,6 +97,14 @@ struct lfmt {
* Called on a warning or error, with the error message.
*/
void (*error)(int severity, const char *pfx, const char *msg);
/*
* Update the current offset. Used to give the listing generator
* an offset to work with when doing things like
* uplevel(LIST_TIMES) or uplevel(LIST_INCBIN); see
* list_set_offset();
*/
void (*set_offset)(uint64_t offset);
};
extern const struct lfmt *lfmt;

View file

@ -1687,6 +1687,7 @@ static void assemble_file(char *fname, StrList **depend_ptr)
int64_t l = insn_size(location.segment, offs, sb, cpu,
&output_ins);
l *= output_ins.times;
/* if (using_debug_info) && output_ins.opcode != -1) */
if (using_debug_info)

View file

@ -100,12 +100,43 @@ struct ofmt;
*/
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 */
OUT_ADDRESS, /* An address (symbol value) */
OUT_RELADDR, /* A relative address (relative to instruction end) */
OUT_SEGMENT, /* A segment number */
/* These are temporary until the backend change */
OUT_REL1ADR,
OUT_REL2ADR,
OUT_REL4ADR,
OUT_REL8ADR
};
enum out_sign {
OUT_WRAP, /* Undefined signedness (wraps) */
OUT_SIGNED, /* Value is signed */
OUT_UNSIGNED /* Value is unsigned */
};
/*
* The data we send down to the backend.
* XXX: We still want to push down the base address symbol if
* available, and replace the segment numbers with a structure.
*/
struct out_data {
int64_t offset; /* Offset within segment */
int32_t segment; /* Segment written to */
enum out_type type; /* See above */
enum out_sign sign; /* See above */
int inslen; /* Length of instruction */
int insoffs; /* Offset inside instruction */
int bits; /* Bits mode of compilation */
uint64_t size; /* Size of output */
const struct itemplate *itemp; /* Instruction template */
const void *data; /* Data for OUT_RAWDATA */
uint64_t toffset; /* Target address offset for relocation */
int32_t tsegment; /* Target segment for relocation */
int32_t twrt; /* Relocation with respect to */
};
/*