summaryrefslogtreecommitdiff
path: root/output/outlib.h
diff options
context:
space:
mode:
Diffstat (limited to 'output/outlib.h')
-rw-r--r--output/outlib.h252
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 */