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

📄 elf.c

📁 支持AMD64的汇编编译器源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * ELF object format helpers * *  Copyright (C) 2003  Michael Urman * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. 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 AUTHOR AND OTHER 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 AUTHOR OR OTHER 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. */#include <util.h>/*@unused@*/ RCSID("$Id: elf.c 1168 2004-10-31 01:07:52Z peter $");#define YASM_LIB_INTERNAL#define YASM_EXPR_INTERNAL#include <libyasm.h>#define YASM_OBJFMT_ELF_INTERNAL#include "elf.h"#include "elf-machine.h"static void elf_section_data_destroy(void *data);static void elf_secthead_print(void *data, FILE *f, int indent_level);const yasm_assoc_data_callback elf_section_data = {    elf_section_data_destroy,    elf_secthead_print};static void elf_symrec_data_destroy(/*@only@*/ void *d);static void elf_symtab_entry_print(void *data, FILE *f, int indent_level);const yasm_assoc_data_callback elf_symrec_data = {    elf_symrec_data_destroy,    elf_symtab_entry_print};extern elf_machine_handler    elf_machine_handler_x86_x86,    elf_machine_handler_x86_amd64;static const elf_machine_handler *elf_machine_handlers[] ={    &elf_machine_handler_x86_x86,    &elf_machine_handler_x86_amd64,    NULL};static const elf_machine_handler elf_null_machine = {0};static elf_machine_handler const *elf_march = &elf_null_machine;static yasm_symrec **elf_ssyms;intelf_set_arch(yasm_arch *arch, yasm_symtab *symtab){    const char *machine = yasm_arch_get_machine(arch);    int i;    for (i=0, elf_march = elf_machine_handlers[0];         elf_march != NULL;         elf_march = elf_machine_handlers[++i])    {        if (yasm__strcasecmp(yasm_arch_keyword(arch), elf_march->arch)==0)            if (yasm__strcasecmp(machine, elf_march->machine)==0)                break;    }    if (elf_march && elf_march->num_ssyms > 0)    {	/* Allocate "special" syms */	elf_ssyms =	    yasm_xmalloc(elf_march->num_ssyms * sizeof(yasm_symrec *));	for (i=0; (unsigned int)i<elf_march->num_ssyms; i++)	{	    /* FIXME: misuse of NULL bytecode */	    elf_ssyms[i] = yasm_symtab_define_label(symtab,						    elf_march->ssyms[i].name,						    NULL, 1, 0);	}    }    return elf_march != NULL;}/* reloc functions */intelf_is_wrt_sym_relative(yasm_symrec *wrt){    int i;    for (i=0; (unsigned int)i<elf_march->num_ssyms; i++) {	if (elf_ssyms[i] == wrt)	    return elf_march->ssyms[i].sym_rel;    }    return 0;}/* takes ownership of addr */elf_reloc_entry *elf_reloc_entry_create(yasm_symrec *sym,		       yasm_symrec *wrt,		       yasm_intnum *addr,		       int rel,		       size_t valsize){    elf_reloc_entry *entry;    if (!elf_march->accepts_reloc)	yasm_internal_error(N_("Unsupported machine for ELF output"));    if (!elf_march->accepts_reloc(valsize, wrt, elf_ssyms))    {        if (addr)            yasm_intnum_destroy(addr);        return NULL;    }    if (sym == NULL)	yasm_internal_error("sym is null");    entry = yasm_xmalloc(sizeof(elf_reloc_entry));    entry->reloc.sym = sym;    entry->reloc.addr = addr;    entry->rtype_rel = rel;    entry->valsize = valsize;    entry->addend = NULL;    entry->wrt = wrt;    return entry;}voidelf_reloc_entry_destroy(void *entry){    if (((elf_reloc_entry*)entry)->addend)        yasm_intnum_destroy(((elf_reloc_entry*)entry)->addend);    yasm_xfree(entry);}/* strtab functions */elf_strtab_entry *elf_strtab_entry_create(const char *str){    elf_strtab_entry *entry = yasm_xmalloc(sizeof(elf_strtab_entry));    entry->str = yasm__xstrdup(str);    entry->index = 0;    return entry;}elf_strtab_head *elf_strtab_create(){    elf_strtab_head *strtab = yasm_xmalloc(sizeof(elf_strtab_head));    elf_strtab_entry *entry = yasm_xmalloc(sizeof(elf_strtab_entry));    STAILQ_INIT(strtab);    entry->index = 0;    entry->str = yasm__xstrdup("");    STAILQ_INSERT_TAIL(strtab, entry, qlink);    return strtab;}elf_strtab_entry *elf_strtab_append_str(elf_strtab_head *strtab, const char *str){    elf_strtab_entry *last, *entry;    if (strtab == NULL)	yasm_internal_error("strtab is null");    if (STAILQ_EMPTY(strtab))	yasm_internal_error("strtab is missing initial dummy entry");    last = STAILQ_LAST(strtab, elf_strtab_entry, qlink);    entry = elf_strtab_entry_create(str);    entry->index = last->index + strlen(last->str) + 1;    STAILQ_INSERT_TAIL(strtab, entry, qlink);    return entry;}voidelf_strtab_destroy(elf_strtab_head *strtab){    elf_strtab_entry *s1, *s2;    if (strtab == NULL)	yasm_internal_error("strtab is null");    if (STAILQ_EMPTY(strtab))	yasm_internal_error("strtab is missing initial dummy entry");    s1 = STAILQ_FIRST(strtab);    while (s1 != NULL) {	s2 = STAILQ_NEXT(s1, qlink);	yasm_xfree(s1->str);	yasm_xfree(s1);	s1 = s2;    }    yasm_xfree(strtab);}unsigned longelf_strtab_output_to_file(FILE *f, elf_strtab_head *strtab){    unsigned long size = 0;    elf_strtab_entry *entry;    if (strtab == NULL)	yasm_internal_error("strtab is null");    /* consider optimizing tables here */    STAILQ_FOREACH(entry, strtab, qlink) {	size_t len = 1 + strlen(entry->str);	fwrite(entry->str, len, 1, f);	size += len;    }    return size;}/* symtab functions */elf_symtab_entry *elf_symtab_entry_create(elf_strtab_entry *name,			yasm_symrec *sym){    elf_symtab_entry *entry = yasm_xmalloc(sizeof(elf_symtab_entry));    entry->sym = sym;    entry->sect = NULL;    entry->name = name;    entry->value = 0;    entry->xsize = NULL;    entry->size = 0;    entry->index = 0;    entry->bind = 0;    entry->type = STT_NOTYPE;    return entry;}static voidelf_symtab_entry_destroy(elf_symtab_entry *entry){    if (entry == NULL)	yasm_internal_error("symtab entry is null");    if (entry->xsize)	yasm_expr_destroy(entry->xsize);    yasm_xfree(entry);}static voidelf_symrec_data_destroy(void *data){    /* do nothing, as this stuff is in the symtab anyway...  this speaks of bad     * design/use or this stuff, i fear */    /* watch for double-free here ... */    /*elf_symtab_entry_destroy((elf_symtab_entry *)data);*/}static voidelf_symtab_entry_print(void *data, FILE *f, int indent_level){    elf_symtab_entry *entry = data;    if (entry == NULL)	yasm_internal_error("symtab entry is null");    fprintf(f, "%*sbind=", indent_level, "");    switch (entry->bind) {	case STB_LOCAL:		fprintf(f, "local\n");	break;	case STB_GLOBAL:	fprintf(f, "global\n"); break;	case STB_WEAK:		fprintf(f, "weak\n");	break;	default:		fprintf(f, "undef\n");	break;    }    fprintf(f, "%*stype=", indent_level, "");    switch (entry->type) {	case STT_NOTYPE:	fprintf(f, "notype\n");	break;	case STT_OBJECT:	fprintf(f, "object\n"); break;	case STT_FUNC:		fprintf(f, "func\n");	break;	case STT_SECTION:	fprintf(f, "section\n");break;	case STT_FILE:		fprintf(f, "file\n");	break;	default:		fprintf(f, "undef\n");	break;    }    fprintf(f, "%*ssize=", indent_level, "");    if (entry->xsize)	yasm_expr_print(entry->xsize, f);    else	fprintf(f, "%ld", entry->size);    fprintf(f, "\n");}elf_symtab_head *elf_symtab_create(){    elf_symtab_head *symtab = yasm_xmalloc(sizeof(elf_symtab_head));    elf_symtab_entry *entry = yasm_xmalloc(sizeof(elf_symtab_entry));    STAILQ_INIT(symtab);    entry->sym = NULL;    entry->sect = NULL;    entry->name = NULL;    entry->value = 0;    entry->xsize = NULL;    entry->size = 0;    entry->index = SHN_UNDEF;    entry->bind = 0;    entry->type = 0;    entry->symindex = 0;    STAILQ_INSERT_TAIL(symtab, entry, qlink);    return symtab;}elf_symtab_entry *elf_symtab_append_entry(elf_symtab_head *symtab, elf_symtab_entry *entry){    if (symtab == NULL)	yasm_internal_error("symtab is null");    if (entry == NULL)	yasm_internal_error("symtab entry is null");    if (STAILQ_EMPTY(symtab))	yasm_internal_error(N_("symtab is missing initial dummy entry"));    STAILQ_INSERT_TAIL(symtab, entry, qlink);    return entry;}elf_symtab_entry *elf_symtab_insert_local_sym(elf_symtab_head *symtab,			    elf_strtab_head *strtab,			    yasm_symrec *sym){    elf_strtab_entry *name = strtab	? elf_strtab_append_str(strtab, yasm_symrec_get_name(sym))	: NULL;    elf_symtab_entry *entry = elf_symtab_entry_create(name, sym);    elf_symtab_entry *after = STAILQ_FIRST(symtab);    elf_symtab_entry *before = NULL;    while (after && (after->bind == STB_LOCAL)) {	before = after;	if (before->type == STT_FILE) break;	after = STAILQ_NEXT(after, qlink);    }    STAILQ_INSERT_AFTER(symtab, before, entry, qlink);    return entry;}voidelf_symtab_destroy(elf_symtab_head *symtab){    elf_symtab_entry *s1, *s2;    if (symtab == NULL)	yasm_internal_error("symtab is null");    if (STAILQ_EMPTY(symtab))	yasm_internal_error(N_("symtab is missing initial dummy entry"));    s1 = STAILQ_FIRST(symtab);    while (s1 != NULL) {	s2 = STAILQ_NEXT(s1, qlink);	elf_symtab_entry_destroy(s1);	s1 = s2;    }    yasm_xfree(symtab);}unsigned longelf_symtab_assign_indices(elf_symtab_head *symtab){    elf_symtab_entry *entry, *prev=NULL;    unsigned long last_local=0;    if (symtab == NULL)	yasm_internal_error("symtab is null");    if (STAILQ_EMPTY(symtab))	yasm_internal_error(N_("symtab is missing initial dummy entry"));    STAILQ_FOREACH(entry, symtab, qlink) {	if (prev)	    entry->symindex = prev->symindex + 1;	if (entry->bind == STB_LOCAL)	    last_local = entry->symindex;	prev = entry;    }    return last_local + 1;}unsigned longelf_symtab_write_to_file(FILE *f, elf_symtab_head *symtab){    unsigned char buf[SYMTAB_MAXSIZE], *bufp;    elf_symtab_entry *entry, *prev;    unsigned long size = 0;    if (!symtab)	yasm_internal_error(N_("symtab is null"));    prev = NULL;    STAILQ_FOREACH(entry, symtab, qlink) {	yasm_intnum *size_intn=NULL, *value_intn=NULL;	bufp = buf;	/* get size (if specified); expr overrides stored integer */	if (entry->xsize) {	    size_intn = yasm_intnum_copy(		yasm_expr_get_intnum(&entry->xsize, yasm_common_calc_bc_dist));	    if (!size_intn)

⌨️ 快捷键说明

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