mirror of
https://github.com/netwide-assembler/nasm.git
synced 2024-11-21 03:14:19 +08:00
1b50fec496
recursion: see recursion. A wrapper function needs to call the function being wrapped, not itself. Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
314 lines
10 KiB
C
314 lines
10 KiB
C
/* ----------------------------------------------------------------------- *
|
|
*
|
|
* Copyright 1996-2020 The NASM Authors - All Rights Reserved
|
|
* See the file AUTHORS included with the NASM distribution for
|
|
* the specific copyright holders.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following
|
|
* conditions are met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above
|
|
* copyright notice, this list of conditions and the following
|
|
* disclaimer in the documentation and/or other materials provided
|
|
* with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
|
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
* ----------------------------------------------------------------------- */
|
|
|
|
#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);
|
|
|
|
/* Do-nothing versions of some output routines */
|
|
enum directive_result
|
|
null_directive(enum directive directive, char *value);
|
|
void null_sectalign(int32_t seg, unsigned int value);
|
|
void null_reset(void);
|
|
int32_t null_segbase(int32_t seg);
|
|
|
|
/* Do-nothing versions of all the debug routines */
|
|
void null_debug_init(void);
|
|
void null_debug_linenum(const char *filename, int32_t linenumber,
|
|
int32_t segto);
|
|
void null_debug_deflabel(char *name, int32_t segment, int64_t offset,
|
|
int is_global, char *special);
|
|
void null_debug_directive(const char *directive, const char *params);
|
|
void null_debug_typevalue(int32_t type);
|
|
void null_debug_output(int type, void *param);
|
|
void null_debug_cleanup(void);
|
|
extern const struct dfmt * const null_debug_arr[2];
|
|
|
|
/* Wrapper for unported backends */
|
|
void nasm_do_legacy_output(const struct out_data *data);
|
|
|
|
/*
|
|
* 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 */
|