diff options
Diffstat (limited to 'output/outlib.h')
-rw-r--r-- | output/outlib.h | 252 |
1 files changed, 250 insertions, 2 deletions
diff --git a/output/outlib.h b/output/outlib.h index 30f2c0b2..a0b31245 100644 --- a/output/outlib.h +++ b/output/outlib.h @@ -1,6 +1,6 @@ /* ----------------------------------------------------------------------- * * - * Copyright 1996-2018 The NASM Authors - All Rights Reserved + * Copyright 1996-2020 The NASM Authors - All Rights Reserved * See the file AUTHORS included with the NASM distribution for * the specific copyright holders. * @@ -34,8 +34,12 @@ #ifndef NASM_OUTLIB_H #define NASM_OUTLIB_H +#include "compiler.h" #include "nasm.h" #include "error.h" +#include "hashtbl.h" +#include "saa.h" +#include "rbtree.h" uint64_t realsize(enum out_type type, uint64_t size); @@ -61,5 +65,249 @@ extern const struct dfmt * const null_debug_arr[2]; /* Wrapper for unported backends */ void nasm_do_legacy_output(const struct out_data *data); -#endif /* NASM_OUTLIB_H */ +/* + * Common routines for tasks that really should migrate into the core. + * This provides a common interface for maintaining sections and symbols, + * and provide quick lookups as well as declared-order sequential walks. + * + * These structures are intended to be embedded at the *top* of a + * backend-specific structure containing additional information. + * + * The tokens O_Section, O_Symbol and O_Reloc are intended to be + * defined as macros by the backend before including this file! + */ + +struct ol_sect; +struct ol_sym; + +#ifndef O_Section +typedef struct ol_sect O_Section; +#endif +#ifndef O_Symbol +typedef struct ol_sym O_Symbol; +#endif +#ifndef O_Reloc +typedef void * O_Reloc; +#endif + +/* Common section structure */ + +/* + * Common flags for sections and symbols; low values reserved for + * backend. Note that both ol_sect and ol_sym begin with a flags + * field, so if a section pointer points to an external symbol instead + * they can be trivially resolved. + */ +#define OF_SYMBOL 0x80000000 +#define OF_GLOBAL 0x40000000 +#define OF_IMPSEC 0x20000000 +#define OF_COMMON 0x10000000 + +struct ol_sym; + +struct ol_symlist { + struct ol_symlist *next; + struct rbtree tree; +}; +struct ol_symhead { + struct ol_symlist *head, **tail; + struct rbtree *tree; + uint64_t n; +}; + +struct ol_sect { + uint32_t flags; /* Section/symbol flags */ + struct ol_sect *next; /* Next section in declared order */ + const char *name; /* Name of section */ + struct ol_symhead syml; /* All symbols in this section */ + struct ol_symhead symg; /* Global symbols in this section */ + struct SAA *data; /* Contents of section */ + struct SAA *reloc; /* Section relocations */ + uint32_t index; /* Primary section index */ + uint32_t subindex; /* Current subsection index */ +}; + +/* Segment reference */ +enum ol_seg_type { + OS_NOSEG = 0, /* Plain number (no segment) */ + OS_SEGREF = 1, /* It is a segment reference */ + OS_ABS = 1, /* Absolute segment reference */ + OS_SECT = 2, /* It is a real section */ + OS_OFFS = OS_SECT, /* Offset reference in section */ + OS_SEG = OS_SECT|OS_SEGREF /* Section reference */ +}; + +union ol_segval { + struct ol_sect *sect; /* Section structure */ + struct ol_sym *sym; /* External symbol structure */ +}; + +struct ol_seg { + union ol_segval s; + enum ol_seg_type t; + + /* + * For a section: subsection index + * For a metasymbol: virtual segment index + * For an absolute symbol: absolute value + */ + uint32_t index; +}; + +/* seg:offs representing the full location value and type */ +struct ol_loc { + int64_t offs; + struct ol_seg seg; +}; + +/* Common symbol structure */ +struct ol_sym { + uint32_t flags; /* Section/symbol flags */ + uint32_t size; /* Size value (for backend) */ + struct ol_sym *next; /* Next symbol in declared order */ + const char *name; /* Symbol name */ + struct ol_symlist syml; /* Section-local symbol list */ + struct ol_symlist symg; /* Section-local global symbol list */ + struct ol_loc p; /* Symbol position ("where") */ + struct ol_loc v; /* Symbol value ("what") */ +}; + +/* + * Operations + */ +void ol_init(void); +void ol_cleanup(void); +/* Convert offs:seg to a location structure */ +extern void +ol_mkloc(struct ol_loc *loc, int64_t offs, int32_t seg); + +/* Get the section or external symbol from a struct ol_seg */ +static inline O_Section *seg_sect(struct ol_seg *seg) +{ + return (O_Section *)seg->s.sect; +} +static inline O_Symbol *seg_xsym(struct ol_seg *seg) +{ + return (O_Symbol *)seg->s.sym; +} + +/* + * Return a pointer to the symbol structure if and only if a section is + * really a symbol of some kind (extern, common...) + */ +static inline struct ol_sym *_seg_extsym(struct ol_sect *sect) +{ + return (sect->flags & OF_SYMBOL) ? (struct ol_sym *)sect : NULL; +} +static inline O_Symbol *seg_extsym(O_Section *sect) +{ + return (O_Symbol *)_seg_extsym((struct ol_sect *)sect); +} + +/* + * Find a section or create a new section structure if it does not exist + * and allocate it an index value via seg_alloc(). + */ +extern struct ol_sect * +_ol_get_sect(const char *name, size_t ssize, size_t rsize); +static inline O_Section *ol_get_sect(const char *name) +{ + return (O_Section *)_ol_get_sect(name, sizeof(O_Section), sizeof(O_Reloc)); +} + +/* Find a section by name without creating one */ +extern struct ol_sect *_ol_sect_by_name(const char *); +static inline O_Section *ol_sect_by_name(const char *name) +{ + return (O_Section *)_ol_sect_by_name(name); +} + +/* Find a section or external symbol by index; NULL if not valid */ +extern struct ol_sect *_ol_sect_by_index(int32_t index); +static inline O_Section *ol_sect_by_index(int32_t index) +{ + return (O_Section *)_ol_sect_by_index(index); +} + +/* Global list of sections (not including external symbols) */ +extern struct ol_sect *_ol_sect_list; +static inline O_Section *ol_sect_list(void) +{ + return (O_Section *)_ol_sect_list; +} + +/* Count of sections (not including external symbols) */ +extern uint64_t _ol_nsects; +static inline uint64_t ol_nsects(void) +{ + return _ol_nsects; +} + +/* + * Start a new subsection for the given section. At the moment, once a + * subsection has been created, it is not possible to revert to an + * earlier subsection. ol_sect_by_index() will return the main section + * structure. Returns the new section index. This is used to prevent + * the front end from optimizing across subsection boundaries. + */ +extern int32_t _ol_new_subsection(struct ol_sect *sect); +static inline int32_t ol_new_subsection(O_Section *sect) +{ + return ol_new_subsection((struct ol_sect *)sect); +} + +/* + * Create a new symbol. If this symbol is OS_OFFS, add it to the relevant + * section, too. If the symbol already exists, return NULL; this is + * different from ol_get_section() as a single section may be invoked + * many times. On the contrary, the front end will prevent a single symbol + * from being defined more than once. + * + * If flags has OF_GLOBAL set, add it to the global symbol hash for the + * containing section. If flags has OF_IMPSEC set, allocate a segment + * index for it via seg_alloc() and add it to the section by index list. + */ +extern struct ol_sym *_ol_new_sym(const char *name, const struct ol_loc *v, + uint32_t flags, size_t size); +static inline O_Symbol *ol_new_sym(const char *name, const struct ol_loc *v, + uint32_t flags) +{ + return (O_Symbol *)_ol_new_sym(name, v, flags, sizeof(O_Symbol)); +} + +/* Find a symbol by name in the global namespace */ +extern struct ol_sym *_ol_sym_by_name(const char *name); +static inline O_Symbol *ol_sym_by_name(const char *name) +{ + return (O_Symbol *)_ol_sym_by_name(name); +} + +/* + * Find a symbol by address in a specific section. If no symbol is defined + * at that exact address, return the immediately previously defined one. + * If global is set, then only return global symbols. + */ +extern struct ol_sym *_ol_sym_by_address(struct ol_sect *sect, int64_t addr, + bool global); +static inline O_Symbol *ol_sym_by_address(O_Section *sect, int64_t addr, + bool global) +{ + return (O_Symbol *)_ol_sym_by_address((struct ol_sect *)sect, addr, global); +} + +/* Global list of symbols */ +extern struct ol_sym *_ol_sym_list; +static inline O_Symbol *ol_sym_list(void) +{ + return (O_Symbol *)_ol_sym_list; +} + +/* Global count of symbols */ +extern uint64_t _ol_nsyms; +static inline uint64_t ol_nsyms(void) +{ + return _ol_nsyms; +} + +#endif /* NASM_OUTLIB_H */ |