⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 outelf.c

📁 开源的nasm编译器源码,研究编译器原理很有帮且
💻 C
📖 第 1 页 / 共 3 页
字号:
/* outelf.c	output routines for the Netwide Assembler to produce *		ELF32 (i386 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 licence given in the file "Licence" * distributed in the NASM archive. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include "nasm.h"#include "nasmlib.h"#include "outform.h"#ifdef OF_ELF/* * Relocation types. */enum reloc_type {  R_386_32        =  1,		/* ordinary absolute relocation */  R_386_PC32      =  2,		/* PC-relative relocation */  R_386_GOT32     =  3,		/* an offset into GOT */  R_386_PLT32     =  4,		/* a PC-relative offset into PLT */  R_386_COPY      =  5,		/* ??? */  R_386_GLOB_DAT  =  6,		/* ??? */  R_386_JUMP_SLOT =  7,		/* ??? */  R_386_RELATIVE  =  8,		/* ??? */  R_386_GOTOFF    =  9,		/* an offset from GOT base */  R_386_GOTPC     = 10,		/* a PC-relative offset _to_ GOT */  /* These are GNU extensions, but useful */  R_386_16        = 20,		/* A 16-bit absolute relocation */  R_386_PC16      = 21,		/* A 16-bit PC-relative relocation */  R_386_8         = 22,		/* An 8-bit absolute relocation */  R_386_PC8       = 23		/* An 8-bit PC-relative relocation */};struct Reloc {    struct Reloc *next;    long address;		       /* relative to _start_ of section */    long symbol;		       /* ELF symbol info thingy */    int type;			       /* type of relocation */};struct Symbol {    long strpos;		       /* string table position of name */    long section;		       /* section ID of the symbol */    int type;			       /* symbol type */    long value;			       /* address, or COMMON variable align */    long size;			       /* size of symbol */    long 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 */};#define SHT_PROGBITS 1#define SHT_NOBITS 8#define SHF_WRITE 1#define SHF_ALLOC 2#define SHF_EXECINSTR 4struct Section {    struct SAA *data;    unsigned long len, size, nrelocs;    long index;    int type;			       /* SHT_PROGBITS or SHT_NOBITS */    int align;			       /* alignment: power of two */    unsigned long flags;	       /* section flags */    char *name;    struct SAA *rel;    long rellen;    struct Reloc *head, **tail;    struct Symbol *gsyms;	       /* global symbols in section */};#define SECT_DELTA 32static struct Section **sects;static int nsects, sectlen;#define SHSTR_DELTA 256static char *shstrtab;static int shstrtablen, shstrtabsize;static struct SAA *syms;static unsigned long nlocals, nglobs;static long def_seg;static struct RAA *bsym;static struct SAA *strs;static unsigned long strslen;static FILE *elffp;static efunc error;static evalfunc evaluate;static struct Symbol *fwds;static char elf_module[FILENAME_MAX];extern struct ofmt of_elf;#define SHN_ABS 0xFFF1#define SHN_COMMON 0xFFF2#define SHN_UNDEF 0#define SYM_SECTION 0x04#define SYM_GLOBAL 0x10#define SYM_DATA 0x01#define SYM_FUNCTION 0x02#define GLOBAL_TEMP_BASE 16	       /* bigger than any constant sym id */#define SEG_ALIGN 16		       /* alignment of sections in file */#define SEG_ALIGN_1 (SEG_ALIGN-1)static const char align_str[SEG_ALIGN] = ""; /* ANSI will pad this with 0s */#define ELF_MAX_SECTIONS 16	       /* really 10, but let's play safe */static struct ELF_SECTDATA {    void *data;    long len;    int is_saa;} *elf_sects;static int elf_nsect;static long elf_foffs;static void elf_write(void);static void elf_sect_write(struct Section *, const unsigned char *, unsigned long);static void elf_section_header (int, int, int, void *, int, long,				int, int, int, int);static void elf_write_sections (void);static struct SAA *elf_build_symtab (long *, long *);static struct SAA *elf_build_reltab (long *, struct Reloc *);static void add_sectname (char *, char *);/* this stuff is needed for the stabs debugging format */#define N_SO 0x64     /* ID for main source file */#define N_SOL 0x84    /* ID for sub-source file */#define N_BINCL 0x82#define N_EINCL 0xA2#define N_SLINE 0x44#define TY_STABSSYMLIN 0x40 /* ouch */struct stabentry {  unsigned long n_strx;  unsigned char n_type;  unsigned char n_other;  unsigned short n_desc;  unsigned long n_value;};struct erel {  int offset,info;};struct symlininfo {  int offset;  int section; /* section index */  char *name; /* shallow-copied pointer of section name */};struct linelist {  struct symlininfo info;  int line;  char *filename;  struct linelist * next;  struct linelist * last;};static struct linelist *stabslines=0;static int stabs_immcall=0;static int currentline=0;static int numlinestabs=0;static char * stabs_filename=0;static int symtabsection;static unsigned char *stabbuf=0,*stabstrbuf=0,*stabrelbuf=0;static int stablen,stabstrlen,stabrellen;static struct dfmt df_stabs;void stabs_init(struct ofmt *,void *,FILE *,efunc );void stabs_linenum(const char *filename,long linenumber,long);void stabs_deflabel(char *,long ,long ,int ,char *);void stabs_directive(const char *,const char *);void stabs_typevalue(long );void stabs_output(int ,void *);void stabs_generate();void stabs_cleanup();/* end of stabs debugging stuff *//* * Special section numbers which are used to define ELF special * symbols, which can be used with WRT to provide PIC relocation * types. */static long elf_gotpc_sect, elf_gotoff_sect;static long elf_got_sect, elf_plt_sect;static long elf_sym_sect;static void elf_init(FILE *fp, efunc errfunc, ldfunc ldef, evalfunc eval){    elffp = fp;    error = errfunc;    evaluate = eval;    (void) ldef;		       /* placate optimisers */    sects = NULL;    nsects = sectlen = 0;    syms = saa_init((long)sizeof(struct Symbol));    nlocals = nglobs = 0;    bsym = raa_init();    strs = saa_init(1L);    saa_wbytes (strs, "\0", 1L);    saa_wbytes (strs, elf_module, (long)(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_elf, error);    elf_gotoff_sect = seg_alloc();    ldef("..gotoff", elf_gotoff_sect+1, 0L, NULL, FALSE, FALSE,&of_elf,error);    elf_got_sect = seg_alloc();    ldef("..got", elf_got_sect+1, 0L, NULL, FALSE, FALSE, &of_elf, error);    elf_plt_sect = seg_alloc();    ldef("..plt", elf_plt_sect+1, 0L, NULL, FALSE, FALSE, &of_elf, error);    elf_sym_sect = seg_alloc();    ldef("..sym", elf_sym_sect+1, 0L, NULL, FALSE, FALSE, &of_elf, 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);    raa_free (bsym);    saa_free (strs);    if (of_elf.current_dfmt) {      of_elf.current_dfmt->cleanup();    }}static void add_sectname (char *firsthalf, char *secondhalf){    int len = strlen(firsthalf)+strlen(secondhalf);    while (shstrtablen + len + 1 > shstrtabsize)	shstrtab = nasm_realloc (shstrtab, (shstrtabsize += SHSTR_DELTA));    strcpy (shstrtab+shstrtablen, firsthalf);    strcat (shstrtab+shstrtablen, secondhalf);    shstrtablen += len+1;}static int elf_make_section (char *name, int type, int flags, int align){    struct Section *s;    s = nasm_malloc (sizeof(*s));    if (type != SHT_NOBITS)	s->data = saa_init (1L);    s->head = NULL;    s->tail = &s->head;    s->len = s->size = 0;    s->nrelocs = 0;    if (!strcmp(name, ".text"))	s->index = def_seg;    else	s->index = seg_alloc();    add_sectname ("", name);    s->name = nasm_malloc (1+strlen(name));    strcpy (s->name, name);    s->type = type;    s->flags = flags;    s->align = align;    s->gsyms = NULL;    if (nsects >= sectlen)	sects = nasm_realloc (sects, (sectlen += SECT_DELTA)*sizeof(*sects));    sects[nsects++] = s;    return nsects-1;}static long elf_section_names (char *name, int pass, int *bits){    char *p;    int flags_and, flags_or, type, align, i;    /*     * Default is 32 bits.     */    if (!name) {	*bits = 32;	return def_seg;    }    p = name;    while (*p && !isspace(*p)) p++;    if (*p) *p++ = '\0';    flags_and = flags_or = type = align = 0;    while (*p && isspace(*p)) p++;    while (*p) {	char *q = p;	while (*p && !isspace(*p)) p++;	if (*p) *p++ = '\0';	while (*p && isspace(*p)) p++;		if (!nasm_strnicmp(q, "align=", 6)) {	    align = atoi(q+6);	    if (align == 0)		align = 1;	    if ( (align-1) & align ) {   /* means it's not a power of two */		error (ERR_NONFATAL, "section alignment %d is not"		       " a power of two", align);		align = 1;	    }	} else if (!nasm_stricmp(q, "alloc")) {	    flags_and |= SHF_ALLOC;	    flags_or |= SHF_ALLOC;	} else if (!nasm_stricmp(q, "noalloc")) {	    flags_and |= SHF_ALLOC;	    flags_or &= ~SHF_ALLOC;	} else if (!nasm_stricmp(q, "exec")) {	    flags_and |= SHF_EXECINSTR;	    flags_or |= SHF_EXECINSTR;	} else if (!nasm_stricmp(q, "noexec")) {	    flags_and |= SHF_EXECINSTR;	    flags_or &= ~SHF_EXECINSTR;	} else if (!nasm_stricmp(q, "write")) {	    flags_and |= SHF_WRITE;	    flags_or |= SHF_WRITE;	} else if (!nasm_stricmp(q, "nowrite")) {	    flags_and |= SHF_WRITE;	    flags_or &= ~SHF_WRITE;	} else if (!nasm_stricmp(q, "progbits")) {	    type = SHT_PROGBITS;	} else if (!nasm_stricmp(q, "nobits")) {	    type = SHT_NOBITS;	}    }    if (!strcmp(name, ".comment") ||	!strcmp(name, ".shstrtab") ||	!strcmp(name, ".symtab") ||	!strcmp(name, ".strtab")) {	error (ERR_NONFATAL, "attempt to redefine reserved section"	       "name `%s'", name);	return NO_SEG;    }    for (i=0; i<nsects; i++)	if (!strcmp(name, sects[i]->name))	    break;    if (i == nsects) {	if (!strcmp(name, ".text"))	    i = elf_make_section (name, SHT_PROGBITS,				  SHF_ALLOC | SHF_EXECINSTR, 16);	else if (!strcmp(name, ".rodata"))	    i = elf_make_section (name, SHT_PROGBITS,				  SHF_ALLOC, 4);	else if (!strcmp(name, ".data"))	    i = elf_make_section (name, SHT_PROGBITS,				  SHF_ALLOC | SHF_WRITE, 4);	else if (!strcmp(name, ".bss"))	    i = elf_make_section (name, SHT_NOBITS,				  SHF_ALLOC | SHF_WRITE, 4);	else	    i = elf_make_section (name, SHT_PROGBITS, SHF_ALLOC, 1);	if (type)	    sects[i]->type = type;	if (align)	    sects[i]->align = align;	sects[i]->flags &= ~flags_and;	sects[i]->flags |= flags_or;    } else if (pass == 1) {	if (type || align || flags_and)	    error (ERR_WARNING, "section attributes ignored on"		   " redeclaration of section `%s'", name);    }    return sects[i]->index;}static void elf_deflabel (char *name, long segment, long offset,			   int is_global, char *special){    int pos = strslen;    struct Symbol *sym;    int special_used = FALSE;#if defined(DEBUG) && DEBUG>2fprintf(stderr, " elf_deflabel: %s, seg=%ld, off=%ld, is_global=%d, %s\n",      name, segment, offset, is_global, special);#endif    if (name[0] == '.' && name[1] == '.' && name[2] != '@') {	/*	 * This is a NASM special symbol. We never allow it into	 * the ELF symbol table, even if it's a valid one. If it	 * _isn't_ a valid one, we should barf immediately.	 */	if (strcmp(name, "..gotpc") && strcmp(name, "..gotoff") &&	    strcmp(name, "..got") && strcmp(name, "..plt") &&	    strcmp(name, "..sym"))	    error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);	return;    }    if (is_global == 3) {	struct Symbol **s;	/*	 * Fix up a forward-reference symbol size from the first	 * pass.	 */	for (s = &fwds; *s; s = &(*s)->nextfwd)	    if (!strcmp((*s)->name, name)) {		struct tokenval tokval;		expr *e;		char *p = special;		while (*p && !isspace(*p)) p++;		while (*p && isspace(*p)) p++;		stdscan_reset();		stdscan_bufptr = p;		tokval.t_type = TOKEN_INVALID;		e = evaluate(stdscan, NULL, &tokval, NULL, 1, error, NULL);		if (e) {		    if (!is_simple(e))			error (ERR_NONFATAL, "cannot use relocatable"			       " expression as symbol size");		    else			(*s)->size = reloc_value(e);		}		/*		 * Remove it from the list of unresolved sizes.		 */		nasm_free ((*s)->name);		*s = (*s)->nextfwd;		return;	    }	return;			       /* it wasn't an important one */    }    saa_wbytes (strs, name, (long)(1+strlen(name)));    strslen += 1+strlen(name);    sym = saa_wstruct (syms);    sym->strpos = pos;    sym->type = is_global ? SYM_GLOBAL : 0;    sym->size = 0;    if (segment == NO_SEG)	sym->section = SHN_ABS;    else {	int i;	sym->section = SHN_UNDEF;	if (nsects == 0 && segment == def_seg) {	    int tempint;	    if (segment != elf_section_names (".text", 2, &tempint))		error (ERR_PANIC, "strange segment conditions in ELF driver");	    sym->section = nsects;	} else {	    for (i=0; i<nsects; i++)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -