📄 elf.c
字号:
/* * 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 + -