mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-10-10 00:25:06 -04:00
WIP: bin format improvements
- Remove linear lookups - Enable output of relocations in the map file - Other performance fixes Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
This commit is contained in:
@@ -19,3 +19,8 @@ int32_t seg_alloc(void)
|
|||||||
next_seg += 2;
|
next_seg += 2;
|
||||||
return this_seg;
|
return this_seg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t seg_maxindex(void)
|
||||||
|
{
|
||||||
|
return next_seg;
|
||||||
|
}
|
||||||
|
@@ -334,6 +334,11 @@ static inline const char *nasm_digit_chars(bool ucase)
|
|||||||
*/
|
*/
|
||||||
int32_t seg_alloc(void);
|
int32_t seg_alloc(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the lowest unused segment index, suitable for array sizing.
|
||||||
|
*/
|
||||||
|
int32_t seg_maxindex(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add/replace or remove an extension to the end of a filename
|
* Add/replace or remove an extension to the end of a filename
|
||||||
*/
|
*/
|
||||||
|
144
output/outbin.c
144
output/outbin.c
@@ -51,6 +51,7 @@
|
|||||||
#include "nasmlib.h"
|
#include "nasmlib.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "saa.h"
|
#include "saa.h"
|
||||||
|
#include "raa.h"
|
||||||
#include "stdscan.h"
|
#include "stdscan.h"
|
||||||
#include "labels.h"
|
#include "labels.h"
|
||||||
#include "eval.h"
|
#include "eval.h"
|
||||||
@@ -108,7 +109,7 @@ static struct Section {
|
|||||||
* any other good way for us to handle that label.
|
* any other good way for us to handle that label.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
} *sections, *last_section;
|
} *sections, **last_section, *default_section;
|
||||||
|
|
||||||
static struct Reloc {
|
static struct Reloc {
|
||||||
struct Reloc *next;
|
struct Reloc *next;
|
||||||
@@ -117,6 +118,7 @@ static struct Reloc {
|
|||||||
int32_t secref;
|
int32_t secref;
|
||||||
int32_t secrel;
|
int32_t secrel;
|
||||||
struct Section *target;
|
struct Section *target;
|
||||||
|
int64_t addend;
|
||||||
} *relocs, **reloctail;
|
} *relocs, **reloctail;
|
||||||
|
|
||||||
static uint64_t origin;
|
static uint64_t origin;
|
||||||
@@ -127,10 +129,14 @@ static int origin_defined;
|
|||||||
#define MAP_SUMMARY 2
|
#define MAP_SUMMARY 2
|
||||||
#define MAP_SECTIONS 4
|
#define MAP_SECTIONS 4
|
||||||
#define MAP_SYMBOLS 8
|
#define MAP_SYMBOLS 8
|
||||||
static int map_control = 0;
|
#define MAP_RELOCS 16
|
||||||
|
static unsigned int map_control = 0;
|
||||||
|
|
||||||
extern macros_t bin_stdmac[];
|
extern macros_t bin_stdmac[];
|
||||||
|
|
||||||
|
static struct RAA *section_by_index;
|
||||||
|
static struct hash_table section_by_name;
|
||||||
|
|
||||||
static void add_reloc(struct Section *s, int32_t bytes, int32_t secref,
|
static void add_reloc(struct Section *s, int32_t bytes, int32_t secref,
|
||||||
int32_t secrel)
|
int32_t secrel)
|
||||||
{
|
{
|
||||||
@@ -146,44 +152,42 @@ static void add_reloc(struct Section *s, int32_t bytes, int32_t secref,
|
|||||||
r->target = s;
|
r->target = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct Section *find_section_by_name(const char *name)
|
static struct Section *find_section_by_index(uint32_t index)
|
||||||
{
|
{
|
||||||
struct Section *s;
|
return (struct Section *)raa_read_ptr(section_by_index, index >> 1);
|
||||||
|
|
||||||
list_for_each(s, sections)
|
|
||||||
if (!strcmp(s->name, name))
|
|
||||||
break;
|
|
||||||
return s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct Section *find_section_by_index(int32_t index)
|
static bool find_or_create_section(char *name, struct Section **secp)
|
||||||
{
|
{
|
||||||
|
struct hash_insert hi;
|
||||||
|
size_t nsize = strlen(name) + 1;
|
||||||
|
void **sp;
|
||||||
struct Section *s;
|
struct Section *s;
|
||||||
|
|
||||||
list_for_each(s, sections)
|
sp = hash_findb(§ion_by_name, name, nsize, &hi);
|
||||||
if ((index == s->vstart_index) || (index == s->start_index))
|
if (sp) {
|
||||||
break;
|
*secp = (struct Section *)*sp;
|
||||||
return s;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct Section *create_section(char *name)
|
nasm_new(s);
|
||||||
{
|
s->prev = *last_section;
|
||||||
struct Section *s = nasm_zalloc(sizeof(*s));
|
*last_section = *secp = s;
|
||||||
|
last_section = &s->next;
|
||||||
|
|
||||||
s->prev = last_section;
|
|
||||||
s->name = nasm_strdup(name);
|
s->name = nasm_strdup(name);
|
||||||
s->labels_end = &(s->labels);
|
s->labels_end = &(s->labels);
|
||||||
s->contents = saa_init(1L);
|
s->contents = saa_init(1L);
|
||||||
|
|
||||||
/* Register our sections with NASM. */
|
/* Register our sections with NASM and the hash tables */
|
||||||
s->vstart_index = seg_alloc();
|
s->vstart_index = seg_alloc();
|
||||||
s->start_index = seg_alloc();
|
section_by_index = raa_write_ptr(section_by_index, s->vstart_index >> 1, s);
|
||||||
|
s->start_index = seg_alloc();
|
||||||
|
section_by_index = raa_write_ptr(section_by_index, s->start_index >> 1, s);
|
||||||
|
|
||||||
/* FIXME: Append to a tail, we need some helper */
|
hash_add(&hi, s->name, s);
|
||||||
last_section->next = s;
|
|
||||||
last_section = s;
|
|
||||||
|
|
||||||
return last_section;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bin_cleanup(void)
|
static void bin_cleanup(void)
|
||||||
@@ -195,7 +199,9 @@ static void bin_cleanup(void)
|
|||||||
struct Section *last_progbits;
|
struct Section *last_progbits;
|
||||||
struct bin_label *l;
|
struct bin_label *l;
|
||||||
struct Reloc *r;
|
struct Reloc *r;
|
||||||
|
uint64_t *segorg;
|
||||||
uint64_t pend;
|
uint64_t pend;
|
||||||
|
uint32_t maxsegix;
|
||||||
int h;
|
int h;
|
||||||
|
|
||||||
if (debug_level(2)) {
|
if (debug_level(2)) {
|
||||||
@@ -493,8 +499,13 @@ static void bin_cleanup(void)
|
|||||||
/* Step 5: Apply relocations. */
|
/* Step 5: Apply relocations. */
|
||||||
|
|
||||||
/* Prepare the sections for relocating. */
|
/* Prepare the sections for relocating. */
|
||||||
list_for_each(s, sections)
|
maxsegix = seg_maxindex();
|
||||||
|
nasm_newn(segorg, maxsegix >> 1);
|
||||||
|
list_for_each(s, sections) {
|
||||||
saa_rewind(s->contents);
|
saa_rewind(s->contents);
|
||||||
|
segorg[s->start_index >> 1] = s->start;
|
||||||
|
segorg[s->vstart_index >> 1] = s->vstart;
|
||||||
|
}
|
||||||
/* Apply relocations. */
|
/* Apply relocations. */
|
||||||
list_for_each(r, relocs) {
|
list_for_each(r, relocs) {
|
||||||
uint8_t *p, mydata[8];
|
uint8_t *p, mydata[8];
|
||||||
@@ -511,20 +522,12 @@ static void bin_cleanup(void)
|
|||||||
for (b = r->bytes - 1; b >= 0; b--)
|
for (b = r->bytes - 1; b >= 0; b--)
|
||||||
l = (l << 8) + mydata[b];
|
l = (l << 8) + mydata[b];
|
||||||
|
|
||||||
s = find_section_by_index(r->secref);
|
r->addend = l;
|
||||||
if (s) {
|
|
||||||
if (r->secref == s->start_index)
|
if ((uint32_t)r->secref < maxsegix)
|
||||||
l += s->start;
|
l += segorg[r->secref >> 1];
|
||||||
else
|
if ((uint32_t)r->secrel < maxsegix)
|
||||||
l += s->vstart;
|
l -= segorg[r->secrel >> 1];
|
||||||
}
|
|
||||||
s = find_section_by_index(r->secrel);
|
|
||||||
if (s) {
|
|
||||||
if (r->secrel == s->start_index)
|
|
||||||
l -= s->start;
|
|
||||||
else
|
|
||||||
l -= s->vstart;
|
|
||||||
}
|
|
||||||
|
|
||||||
WRITEADDR(p, l, r->bytes);
|
WRITEADDR(p, l, r->bytes);
|
||||||
saa_fwrite(r->target->contents, r->posn, mydata, r->bytes);
|
saa_fwrite(r->target->contents, r->posn, mydata, r->bytes);
|
||||||
@@ -649,15 +652,44 @@ static void bin_cleanup(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
/* Display relocations */
|
||||||
|
if (map_control & MAP_RELOCS) {
|
||||||
|
fprintf(rf, "-- Relocations ");
|
||||||
|
for (h = 68; h; h--)
|
||||||
|
fputc('-', rf);
|
||||||
|
fprintf(rf, "\n\n%-8s%-32s%-32s\n", "Type", "Location", "Target");
|
||||||
|
|
||||||
/* Close the report file. */
|
list_for_each(r, relocs) {
|
||||||
if (map_control && (rf != stdout) && (rf != stderr))
|
const struct Section *ts;
|
||||||
fclose(rf);
|
|
||||||
|
if (r->secrel == r->secref)
|
||||||
|
continue; /* Dummy relocation */
|
||||||
|
fprintf(rf, "%3s%-2d %14s:%016"PRIX64" ",
|
||||||
|
((uint32_t)r->secrel < maxsegix) ? "REL" : "ABS",
|
||||||
|
r->bytes << 3,
|
||||||
|
r->target->name, (uint64_t)r->posn);
|
||||||
|
|
||||||
|
ts = find_section_by_index(r->secref);
|
||||||
|
if (ts) {
|
||||||
|
fprintf(rf, "(%c) %14s",
|
||||||
|
r->secref == ts->start_index ? 'S' : 'V',
|
||||||
|
ts->name);
|
||||||
|
} else {
|
||||||
|
fprintf(rf, "%18s", "ABS");
|
||||||
|
}
|
||||||
|
fprintf(rf, ":%016"PRIX64"\n", r->addend);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close the report file. */
|
||||||
|
if (rf != stdout && rf != stderr)
|
||||||
|
fclose(rf);
|
||||||
|
}
|
||||||
|
|
||||||
/* Step 8: Release all allocated memory. */
|
/* Step 8: Release all allocated memory. */
|
||||||
|
|
||||||
/* Free sections, label pointer structs, etc.. */
|
/* Free sections, label pointer structs, etc.. */
|
||||||
|
nasm_free(segorg);
|
||||||
while (sections) {
|
while (sections) {
|
||||||
s = sections;
|
s = sections;
|
||||||
sections = s->next;
|
sections = s->next;
|
||||||
@@ -674,6 +706,8 @@ static void bin_cleanup(void)
|
|||||||
}
|
}
|
||||||
nasm_free(s);
|
nasm_free(s);
|
||||||
}
|
}
|
||||||
|
hash_free(§ion_by_name);
|
||||||
|
raa_free(section_by_index);
|
||||||
|
|
||||||
/* Free no-section labels. */
|
/* Free no-section labels. */
|
||||||
while (no_seg_labels) {
|
while (no_seg_labels) {
|
||||||
@@ -1192,7 +1226,7 @@ static int32_t bin_secname(char *name, int *bits)
|
|||||||
|
|
||||||
/* Establish the default (.text) section. */
|
/* Establish the default (.text) section. */
|
||||||
*bits = 16;
|
*bits = 16;
|
||||||
sec = find_section_by_name(".text");
|
sec = default_section;
|
||||||
sec->flags |= TYPE_DEFINED | TYPE_PROGBITS;
|
sec->flags |= TYPE_DEFINED | TYPE_PROGBITS;
|
||||||
return sec->vstart_index;
|
return sec->vstart_index;
|
||||||
}
|
}
|
||||||
@@ -1204,9 +1238,7 @@ static int32_t bin_secname(char *name, int *bits)
|
|||||||
p++;
|
p++;
|
||||||
if (*p)
|
if (*p)
|
||||||
*p++ = '\0';
|
*p++ = '\0';
|
||||||
sec = find_section_by_name(name);
|
if (find_or_create_section(name, &sec)) {
|
||||||
if (!sec) {
|
|
||||||
sec = create_section(name);
|
|
||||||
if (!strcmp(name, ".data"))
|
if (!strcmp(name, ".data"))
|
||||||
sec->flags |= TYPE_DEFINED | TYPE_PROGBITS;
|
sec->flags |= TYPE_DEFINED | TYPE_PROGBITS;
|
||||||
else if (!strcmp(name, ".bss")) {
|
else if (!strcmp(name, ".bss")) {
|
||||||
@@ -1279,7 +1311,8 @@ bin_directive(enum directive directive, char *args)
|
|||||||
*(args++) = '\0';
|
*(args++) = '\0';
|
||||||
if (!nasm_stricmp(p, "all"))
|
if (!nasm_stricmp(p, "all"))
|
||||||
map_control |=
|
map_control |=
|
||||||
MAP_ORIGIN | MAP_SUMMARY | MAP_SECTIONS | MAP_SYMBOLS;
|
MAP_ORIGIN | MAP_SUMMARY | MAP_SECTIONS | \
|
||||||
|
MAP_SYMBOLS | MAP_RELOCS;
|
||||||
else if (!nasm_stricmp(p, "brief"))
|
else if (!nasm_stricmp(p, "brief"))
|
||||||
map_control |= MAP_ORIGIN | MAP_SUMMARY;
|
map_control |= MAP_ORIGIN | MAP_SUMMARY;
|
||||||
else if (!nasm_stricmp(p, "sections"))
|
else if (!nasm_stricmp(p, "sections"))
|
||||||
@@ -1288,6 +1321,8 @@ bin_directive(enum directive directive, char *args)
|
|||||||
map_control |= MAP_ORIGIN | MAP_SUMMARY | MAP_SECTIONS;
|
map_control |= MAP_ORIGIN | MAP_SUMMARY | MAP_SECTIONS;
|
||||||
else if (!nasm_stricmp(p, "symbols"))
|
else if (!nasm_stricmp(p, "symbols"))
|
||||||
map_control |= MAP_SYMBOLS;
|
map_control |= MAP_SYMBOLS;
|
||||||
|
else if (!nasm_stricmp(p, "relocs"))
|
||||||
|
map_control |= MAP_RELOCS;
|
||||||
else if (!rf) {
|
else if (!rf) {
|
||||||
if (!nasm_stricmp(p, "stdout"))
|
if (!nasm_stricmp(p, "stdout"))
|
||||||
rf = stdout;
|
rf = stdout;
|
||||||
@@ -1350,13 +1385,10 @@ static void binfmt_init(void)
|
|||||||
nsl_tail = &no_seg_labels;
|
nsl_tail = &no_seg_labels;
|
||||||
|
|
||||||
/* Create default section (.text). */
|
/* Create default section (.text). */
|
||||||
sections = last_section = nasm_zalloc(sizeof(struct Section));
|
last_section = §ions;
|
||||||
last_section->name = nasm_strdup(".text");
|
find_or_create_section(".text", §ions);
|
||||||
last_section->contents = saa_init(1L);
|
default_section = sections;
|
||||||
last_section->flags = TYPE_DEFINED | TYPE_PROGBITS;
|
sections->flags = TYPE_DEFINED | TYPE_PROGBITS;
|
||||||
last_section->labels_end = &(last_section->labels);
|
|
||||||
last_section->start_index = seg_alloc();
|
|
||||||
last_section->vstart_index = seg_alloc();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate binary file output */
|
/* Generate binary file output */
|
||||||
|
@@ -20,6 +20,8 @@
|
|||||||
|
|
||||||
; let's see which of these sections can be placed in the specified order.
|
; let's see which of these sections can be placed in the specified order.
|
||||||
|
|
||||||
|
[map multisection.map all]
|
||||||
|
|
||||||
section .appspecific
|
section .appspecific
|
||||||
section .data
|
section .data
|
||||||
section .stringdata
|
section .stringdata
|
||||||
@@ -32,7 +34,7 @@ section .stringdata
|
|||||||
mystr1: db "Hello, this is string 1", 13, 10, '$'
|
mystr1: db "Hello, this is string 1", 13, 10, '$'
|
||||||
|
|
||||||
section .extra_code
|
section .extra_code
|
||||||
org 0x200
|
;org 0x200
|
||||||
bits 16
|
bits 16
|
||||||
more:
|
more:
|
||||||
mov si, asciz1
|
mov si, asciz1
|
||||||
|
Reference in New Issue
Block a user