📄 outelf64.c
字号:
/* outelf64.c output routines for the Netwide Assembler to produce
* ELF64 (x86_64 of course) object file format
*
* The Netwide Assembler is copyright (C) 1996 Simon Tatham and
* Julian Hall. All rights reserved. The software is
* redistributable under the license given in the file "LICENSE"
* distributed in the NASM archive.
*/
#include "compiler.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <inttypes.h>
#include "nasm.h"
#include "nasmlib.h"
#include "saa.h"
#include "raa.h"
#include "stdscan.h"
#include "outform.h"
/* Definitions in lieu of elf.h */
#define SHT_NULL 0 /* Inactive section header */
#define SHT_PROGBITS 1 /* Program defined content */
#define SHT_RELA 4 /* Relocation entries with addends */
#define SHT_NOBITS 8 /* Section requires no space in file */
#define SHF_WRITE (1 << 0) /* Writable */
#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */
#define SHF_EXECINSTR (1 << 2) /* Executable */
#define SHN_ABS 0xfff1 /* Associated symbol is absolute */
#define SHN_COMMON 0xfff2 /* Associated symbol is common */
#define R_X86_64_NONE 0 /* No reloc */
#define R_X86_64_64 1 /* Direct 64 bit */
#define R_X86_64_PC32 2 /* PC relative 32 bit signed */
#define R_X86_64_GOT32 3 /* 32 bit GOT entry */
#define R_X86_64_PLT32 4 /* 32 bit PLT address */
#define R_X86_64_COPY 5 /* Copy symbol at runtime */
#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */
#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */
#define R_X86_64_RELATIVE 8 /* Adjust by program base */
#define R_X86_64_GOTPCREL 9 /* 32 bit signed PC relative
offset to GOT */
#define R_X86_64_32 10 /* Direct 32 bit zero extended */
#define R_X86_64_32S 11 /* Direct 32 bit sign extended */
#define R_X86_64_16 12 /* Direct 16 bit zero extended */
#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */
#define R_X86_64_8 14 /* Direct 8 bit sign extended */
#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */
#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */
#define R_X86_64_DTPOFF64 17 /* Offset in module's TLS block */
#define R_X86_64_TPOFF64 18 /* Offset in initial TLS block */
#define R_X86_64_TLSGD 19 /* 32 bit signed PC relative offset
to two GOT entries for GD symbol */
#define R_X86_64_TLSLD 20 /* 32 bit signed PC relative offset
to two GOT entries for LD symbol */
#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */
#define R_X86_64_GOTTPOFF 22 /* 32 bit signed PC relative offset
to GOT entry for IE symbol */
#define R_X86_64_TPOFF32 23 /* Offset in initial TLS block */
#define R_X86_64_PC64 24 /* word64 S + A - P */
#define R_X86_64_GOTOFF64 25 /* word64 S + A - GOT */
#define R_X86_64_GOTPC32 26 /* word32 GOT + A - P */
#define R_X86_64_GOT64 27 /* word64 G + A */
#define R_X86_64_GOTPCREL64 28 /* word64 G + GOT - P + A */
#define R_X86_64_GOTPC64 29 /* word64 GOT - P + A */
#define R_X86_64_GOTPLT64 30 /* word64 G + A */
#define R_X86_64_PLTOFF64 31 /* word64 L - GOT + A */
#define R_X86_64_SIZE32 32 /* word32 Z + A */
#define R_X86_64_SIZE64 33 /* word64 Z + A */
#define R_X86_64_GOTPC32_TLSDESC 34 /* word32 */
#define R_X86_64_TLSDESC_CALL 35 /* none */
#define R_X86_64_TLSDESC 36 /* word64×2 */
#define ET_REL 1 /* Relocatable file */
#define EM_X86_64 62 /* AMD x86-64 architecture */
#define STT_NOTYPE 0 /* Symbol type is unspecified */
#define STT_OBJECT 1 /* Symbol is a data object */
#define STT_FUNC 2 /* Symbol is a code object */
#define STT_SECTION 3 /* Symbol associated with a section */
#define STT_FILE 4 /* Symbol's name is file name */
#define STT_COMMON 5 /* Symbol is a common data object */
#define STT_TLS 6 /* Symbol is thread-local data object*/
#define STT_NUM 7 /* Number of defined types. */
/* Definitions in lieu of dwarf.h */
#define DW_TAG_compile_unit 0x11
#define DW_TAG_subprogram 0x2e
#define DW_AT_name 0x03
#define DW_AT_stmt_list 0x10
#define DW_AT_low_pc 0x11
#define DW_AT_high_pc 0x12
#define DW_AT_language 0x13
#define DW_AT_producer 0x25
#define DW_AT_frame_base 0x40
#define DW_FORM_addr 0x01
#define DW_FORM_data2 0x05
#define DW_FORM_data4 0x06
#define DW_FORM_string 0x08
#define DW_LNS_extended_op 0
#define DW_LNS_advance_pc 2
#define DW_LNS_advance_line 3
#define DW_LNS_set_file 4
#define DW_LNE_end_sequence 1
#define DW_LNE_set_address 2
#define DW_LNE_define_file 3
#define DW_LANG_Mips_Assembler 0x8001
#define SOC(ln,aa) ln - line_base + (line_range * aa) + opcode_base
typedef uint32_t Elf64_Word;
typedef uint64_t Elf64_Xword;
typedef uint64_t Elf64_Addr;
typedef uint64_t Elf64_Off;
typedef struct
{
Elf64_Word sh_name; /* Section name (string tbl index) */
Elf64_Word sh_type; /* Section type */
Elf64_Xword sh_flags; /* Section flags */
Elf64_Addr sh_addr; /* Section virtual addr at execution */
Elf64_Off sh_offset; /* Section file offset */
Elf64_Xword sh_size; /* Section size in bytes */
Elf64_Word sh_link; /* Link to another section */
Elf64_Word sh_info; /* Additional section information */
Elf64_Xword sh_addralign; /* Section alignment */
Elf64_Xword sh_entsize; /* Entry size if section holds table */
} Elf64_Shdr;
#ifdef OF_ELF64
struct Reloc {
struct Reloc *next;
int64_t address; /* relative to _start_ of section */
int64_t symbol; /* symbol index */
int64_t offset; /* symbol addend */
int type; /* type of relocation */
};
struct Symbol {
int32_t strpos; /* string table position of name */
int32_t section; /* section ID of the symbol */
int type; /* symbol type */
int other; /* symbol visibility */
int64_t value; /* address, or COMMON variable align */
int32_t size; /* size of symbol */
int32_t globnum; /* symbol table offset if global */
struct Symbol *next; /* list of globals in each section */
struct Symbol *nextfwd; /* list of unresolved-size symbols */
char *name; /* used temporarily if in above list */
};
struct Section {
struct SAA *data;
uint64_t len, size;
uint32_t nrelocs;
int32_t index; /* index into sects array */
uint32_t type; /* SHT_PROGBITS or SHT_NOBITS */
uint64_t align; /* alignment: power of two */
uint64_t flags; /* section flags */
char *name;
struct SAA *rel;
uint64_t rellen;
struct Reloc *head, **tail;
struct Symbol *gsyms; /* global symbols in section */
};
#define SECT_DELTA 32
static struct Section **sects;
static int nsects, sectlen;
#define SHSTR_DELTA 256
static char *shstrtab;
static int shstrtablen, shstrtabsize;
static struct SAA *syms;
static uint32_t nlocals, nglobs;
static int32_t def_seg;
static struct RAA *bsym;
static struct SAA *strs;
static uint32_t strslen;
static FILE *elffp;
static efunc error;
static evalfunc evaluate;
static struct Symbol *fwds;
static char elf_module[FILENAME_MAX];
static uint8_t elf_osabi = 0; /* Default OSABI = 0 (System V or Linux) */
static uint8_t elf_abiver = 0; /* Current ABI version */
extern struct ofmt of_elf64;
#define SHN_UNDEF 0
#define SYM_GLOBAL 0x10
#define STV_DEFAULT 0
#define STV_INTERNAL 1
#define STV_HIDDEN 2
#define STV_PROTECTED 3
#define GLOBAL_TEMP_BASE 1048576 /* bigger than any reasonable sym id */
#define SEG_ALIGN 16 /* alignment of sections in file */
#define SEG_ALIGN_1 (SEG_ALIGN-1)
#define TY_DEBUGSYMLIN 0x40 /* internal call to debug_out */
static const char align_str[SEG_ALIGN] = ""; /* ANSI will pad this with 0s */
static struct ELF_SECTDATA {
void *data;
int64_t len;
bool is_saa;
} *elf_sects;
static int elf_nsect, nsections;
static int64_t elf_foffs;
static void elf_write(void);
static void elf_sect_write(struct Section *, const void *, size_t);
static void elf_sect_writeaddr(struct Section *, int64_t, size_t);
static void elf_section_header(int, int, uint64_t, void *, bool, uint64_t, int, int,
int, int);
static void elf_write_sections(void);
static struct SAA *elf_build_symtab(int32_t *, int32_t *);
static struct SAA *elf_build_reltab(uint64_t *, struct Reloc *);
static void add_sectname(char *, char *);
/* type values for stabs debugging sections */
#define N_SO 0x64 /* ID for main source file */
#define N_SOL 0x84 /* ID for sub-source file */
#define N_BINCL 0x82 /* not currently used */
#define N_EINCL 0xA2 /* not currently used */
#define N_SLINE 0x44
struct stabentry {
uint32_t n_strx;
uint8_t n_type;
uint8_t n_other;
uint16_t n_desc;
uint32_t n_value;
};
struct erel {
int offset, info;
};
struct symlininfo {
int offset;
int section; /* index into sects[] */
int segto; /* internal section number */
char *name; /* shallow-copied pointer of section name */
};
struct linelist {
struct symlininfo info;
int line;
char *filename;
struct linelist *next;
struct linelist *last;
};
struct sectlist {
struct SAA *psaa;
int section;
int line;
int offset;
int file;
struct sectlist *next;
struct sectlist *last;
};
/* common debug variables */
static int currentline = 1;
static int debug_immcall = 0;
/* stabs debug variables */
static struct linelist *stabslines = 0;
static int numlinestabs = 0;
static char *stabs_filename = 0;
static int symtabsection;
static uint8_t *stabbuf = 0, *stabstrbuf = 0, *stabrelbuf = 0;
static int stablen, stabstrlen, stabrellen;
/* dwarf debug variables */
static struct linelist *dwarf_flist = 0, *dwarf_clist = 0, *dwarf_elist = 0;
static struct sectlist *dwarf_fsect = 0, *dwarf_csect = 0, *dwarf_esect = 0;
static int dwarf_numfiles = 0, dwarf_nsections;
static uint8_t *arangesbuf = 0, *arangesrelbuf = 0, *pubnamesbuf = 0, *infobuf = 0, *inforelbuf = 0,
*abbrevbuf = 0, *linebuf = 0, *linerelbuf = 0, *framebuf = 0, *locbuf = 0;
static int8_t line_base = -5, line_range = 14, opcode_base = 13;
static int arangeslen, arangesrellen, pubnameslen, infolen, inforellen,
abbrevlen, linelen, linerellen, framelen, loclen;
static int64_t dwarf_infosym, dwarf_abbrevsym, dwarf_linesym;
static struct dfmt df_dwarf;
static struct dfmt df_stabs;
static struct Symbol *lastsym;
/* common debugging routines */
void debug64_typevalue(int32_t);
void debug64_init(struct ofmt *, void *, FILE *, efunc);
void debug64_deflabel(char *, int32_t, int64_t, int, char *);
void debug64_directive(const char *, const char *);
/* stabs debugging routines */
void stabs64_linenum(const char *filename, int32_t linenumber, int32_t);
void stabs64_output(int, void *);
void stabs64_generate(void);
void stabs64_cleanup(void);
/* dwarf debugging routines */
void dwarf64_linenum(const char *filename, int32_t linenumber, int32_t);
void dwarf64_output(int, void *);
void dwarf64_generate(void);
void dwarf64_cleanup(void);
void dwarf64_findfile(const char *);
void dwarf64_findsect(const int);
/*
* Special section numbers which are used to define ELF special
* symbols, which can be used with WRT to provide PIC relocation
* types.
*/
static int32_t elf_gotpc_sect, elf_gotoff_sect;
static int32_t elf_got_sect, elf_plt_sect;
static int32_t elf_sym_sect;
static void elf_init(FILE * fp, efunc errfunc, ldfunc ldef, evalfunc eval)
{
maxbits = 64;
elffp = fp;
error = errfunc;
evaluate = eval;
(void)ldef; /* placate optimisers */
sects = NULL;
nsects = sectlen = 0;
syms = saa_init((int32_t)sizeof(struct Symbol));
nlocals = nglobs = 0;
bsym = raa_init();
strs = saa_init(1L);
saa_wbytes(strs, "\0", 1L);
saa_wbytes(strs, elf_module, (int32_t)(strlen(elf_module) + 1));
strslen = 2 + strlen(elf_module);
shstrtab = NULL;
shstrtablen = shstrtabsize = 0;;
add_sectname("", "");
fwds = NULL;
elf_gotpc_sect = seg_alloc();
ldef("..gotpc", elf_gotpc_sect + 1, 0L, NULL, false, false, &of_elf64,
error);
elf_gotoff_sect = seg_alloc();
ldef("..gotoff", elf_gotoff_sect + 1, 0L, NULL, false, false, &of_elf64,
error);
elf_got_sect = seg_alloc();
ldef("..got", elf_got_sect + 1, 0L, NULL, false, false, &of_elf64,
error);
elf_plt_sect = seg_alloc();
ldef("..plt", elf_plt_sect + 1, 0L, NULL, false, false, &of_elf64,
error);
elf_sym_sect = seg_alloc();
ldef("..sym", elf_sym_sect + 1, 0L, NULL, false, false, &of_elf64,
error);
def_seg = seg_alloc();
}
static void elf_cleanup(int debuginfo)
{
struct Reloc *r;
int i;
(void)debuginfo;
elf_write();
fclose(elffp);
for (i = 0; i < nsects; i++) {
if (sects[i]->type != SHT_NOBITS)
saa_free(sects[i]->data);
if (sects[i]->head)
saa_free(sects[i]->rel);
while (sects[i]->head) {
r = sects[i]->head;
sects[i]->head = sects[i]->head->next;
nasm_free(r);
}
}
nasm_free(sects);
saa_free(syms);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -