📄 dyngen.c
字号:
/* * Generic Dynamic compiler generator * * Copyright (c) 2003 Fabrice Bellard * * The COFF object format support was extracted from Kazu's QEMU port * to Win32. * * Mach-O Support by Matt Reda and Pierre d'Herbemont * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <stdlib.h>#include <stdio.h>#include <string.h>#include <stdarg.h>#include <inttypes.h>#include <unistd.h>#include <fcntl.h>#include "config-host.h"/* NOTE: we test CONFIG_WIN32 instead of _WIN32 to enabled cross compilation */#if defined(CONFIG_WIN32)#define CONFIG_FORMAT_COFF#elif defined(CONFIG_DARWIN)#define CONFIG_FORMAT_MACH#else#define CONFIG_FORMAT_ELF#endif#ifdef CONFIG_FORMAT_ELF/* elf format definitions. We use these macros to test the CPU to allow cross compilation (this tool must be ran on the build platform) */#if defined(HOST_I386)#define ELF_CLASS ELFCLASS32#define ELF_ARCH EM_386#define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )#undef ELF_USES_RELOCA#elif defined(HOST_X86_64)#define ELF_CLASS ELFCLASS64#define ELF_ARCH EM_X86_64#define elf_check_arch(x) ((x) == EM_X86_64)#define ELF_USES_RELOCA#elif defined(HOST_PPC)#define ELF_CLASS ELFCLASS32#define ELF_ARCH EM_PPC#define elf_check_arch(x) ((x) == EM_PPC)#define ELF_USES_RELOCA#elif defined(HOST_S390)#define ELF_CLASS ELFCLASS32#define ELF_ARCH EM_S390#define elf_check_arch(x) ((x) == EM_S390)#define ELF_USES_RELOCA#elif defined(HOST_ALPHA)#define ELF_CLASS ELFCLASS64#define ELF_ARCH EM_ALPHA#define elf_check_arch(x) ((x) == EM_ALPHA)#define ELF_USES_RELOCA#elif defined(HOST_IA64)#define ELF_CLASS ELFCLASS64#define ELF_ARCH EM_IA_64#define elf_check_arch(x) ((x) == EM_IA_64)#define ELF_USES_RELOCA#elif defined(HOST_SPARC)#define ELF_CLASS ELFCLASS32#define ELF_ARCH EM_SPARC#define elf_check_arch(x) ((x) == EM_SPARC || (x) == EM_SPARC32PLUS)#define ELF_USES_RELOCA#elif defined(HOST_SPARC64)#define ELF_CLASS ELFCLASS64#define ELF_ARCH EM_SPARCV9#define elf_check_arch(x) ((x) == EM_SPARCV9)#define ELF_USES_RELOCA#elif defined(HOST_ARM)#define ELF_CLASS ELFCLASS32#define ELF_ARCH EM_ARM#define elf_check_arch(x) ((x) == EM_ARM)#define ELF_USES_RELOC#elif defined(HOST_M68K)#define ELF_CLASS ELFCLASS32#define ELF_ARCH EM_68K#define elf_check_arch(x) ((x) == EM_68K)#define ELF_USES_RELOCA#else#error unsupported CPU - please update the code#endif#include "elf.h"#if ELF_CLASS == ELFCLASS32typedef int32_t host_long;typedef uint32_t host_ulong;#define swabls(x) swab32s(x)#elsetypedef int64_t host_long;typedef uint64_t host_ulong;#define swabls(x) swab64s(x)#endif#ifdef ELF_USES_RELOCA#define SHT_RELOC SHT_RELA#else#define SHT_RELOC SHT_REL#endif#define EXE_RELOC ELF_RELOC#define EXE_SYM ElfW(Sym)#endif /* CONFIG_FORMAT_ELF */#ifdef CONFIG_FORMAT_COFF#include "a.out.h"typedef int32_t host_long;typedef uint32_t host_ulong;#define FILENAMELEN 256typedef struct coff_sym { struct external_syment *st_syment; char st_name[FILENAMELEN]; uint32_t st_value; int st_size; uint8_t st_type; uint8_t st_shndx;} coff_Sym;typedef struct coff_rel { struct external_reloc *r_reloc; int r_offset; uint8_t r_type;} coff_Rel;#define EXE_RELOC struct coff_rel#define EXE_SYM struct coff_sym#endif /* CONFIG_FORMAT_COFF */#ifdef CONFIG_FORMAT_MACH#include <mach-o/loader.h>#include <mach-o/nlist.h>#include <mach-o/reloc.h>#include <mach-o/ppc/reloc.h># define check_mach_header(x) (x.magic == MH_MAGIC)typedef int32_t host_long;typedef uint32_t host_ulong;struct nlist_extended{ union { char *n_name; long n_strx; } n_un; unsigned char n_type; unsigned char n_sect; short st_desc; unsigned long st_value; unsigned long st_size;};#define EXE_RELOC struct relocation_info#define EXE_SYM struct nlist_extended#endif /* CONFIG_FORMAT_MACH */#include "bswap.h"enum { OUT_GEN_OP, OUT_CODE, OUT_INDEX_OP,};/* all dynamically generated functions begin with this code */#define OP_PREFIX "op_"int do_swap;void __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) error(const char *fmt, ...){ va_list ap; va_start(ap, fmt); fprintf(stderr, "dyngen: "); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); va_end(ap); exit(1);}void *load_data(int fd, long offset, unsigned int size){ char *data; data = malloc(size); if (!data) return NULL; lseek(fd, offset, SEEK_SET); if (read(fd, data, size) != size) { free(data); return NULL; } return data;}int strstart(const char *str, const char *val, const char **ptr){ const char *p, *q; p = str; q = val; while (*q != '\0') { if (*p != *q) return 0; p++; q++; } if (ptr) *ptr = p; return 1;}void pstrcpy(char *buf, int buf_size, const char *str){ int c; char *q = buf; if (buf_size <= 0) return; for(;;) { c = *str++; if (c == 0 || q >= buf + buf_size - 1) break; *q++ = c; } *q = '\0';}void swab16s(uint16_t *p){ *p = bswap16(*p);}void swab32s(uint32_t *p){ *p = bswap32(*p);}void swab64s(uint64_t *p){ *p = bswap64(*p);}uint16_t get16(uint16_t *p){ uint16_t val; val = *p; if (do_swap) val = bswap16(val); return val;}uint32_t get32(uint32_t *p){ uint32_t val; val = *p; if (do_swap) val = bswap32(val); return val;}void put16(uint16_t *p, uint16_t val){ if (do_swap) val = bswap16(val); *p = val;}void put32(uint32_t *p, uint32_t val){ if (do_swap) val = bswap32(val); *p = val;}/* executable information */EXE_SYM *symtab;int nb_syms;int text_shndx;uint8_t *text;EXE_RELOC *relocs;int nb_relocs;#ifdef CONFIG_FORMAT_ELF/* ELF file info */struct elf_shdr *shdr;uint8_t **sdata;struct elfhdr ehdr;char *strtab;int elf_must_swap(struct elfhdr *h){ union { uint32_t i; uint8_t b[4]; } swaptest; swaptest.i = 1; return (h->e_ident[EI_DATA] == ELFDATA2MSB) != (swaptest.b[0] == 0);} void elf_swap_ehdr(struct elfhdr *h){ swab16s(&h->e_type); /* Object file type */ swab16s(&h-> e_machine); /* Architecture */ swab32s(&h-> e_version); /* Object file version */ swabls(&h-> e_entry); /* Entry point virtual address */ swabls(&h-> e_phoff); /* Program header table file offset */ swabls(&h-> e_shoff); /* Section header table file offset */ swab32s(&h-> e_flags); /* Processor-specific flags */ swab16s(&h-> e_ehsize); /* ELF header size in bytes */ swab16s(&h-> e_phentsize); /* Program header table entry size */ swab16s(&h-> e_phnum); /* Program header table entry count */ swab16s(&h-> e_shentsize); /* Section header table entry size */ swab16s(&h-> e_shnum); /* Section header table entry count */ swab16s(&h-> e_shstrndx); /* Section header string table index */}void elf_swap_shdr(struct elf_shdr *h){ swab32s(&h-> sh_name); /* Section name (string tbl index) */ swab32s(&h-> sh_type); /* Section type */ swabls(&h-> sh_flags); /* Section flags */ swabls(&h-> sh_addr); /* Section virtual addr at execution */ swabls(&h-> sh_offset); /* Section file offset */ swabls(&h-> sh_size); /* Section size in bytes */ swab32s(&h-> sh_link); /* Link to another section */ swab32s(&h-> sh_info); /* Additional section information */ swabls(&h-> sh_addralign); /* Section alignment */ swabls(&h-> sh_entsize); /* Entry size if section holds table */}void elf_swap_phdr(struct elf_phdr *h){ swab32s(&h->p_type); /* Segment type */ swabls(&h->p_offset); /* Segment file offset */ swabls(&h->p_vaddr); /* Segment virtual address */ swabls(&h->p_paddr); /* Segment physical address */ swabls(&h->p_filesz); /* Segment size in file */ swabls(&h->p_memsz); /* Segment size in memory */ swab32s(&h->p_flags); /* Segment flags */ swabls(&h->p_align); /* Segment alignment */}void elf_swap_rel(ELF_RELOC *rel){ swabls(&rel->r_offset); swabls(&rel->r_info);#ifdef ELF_USES_RELOCA swabls(&rel->r_addend);#endif}struct elf_shdr *find_elf_section(struct elf_shdr *shdr, int shnum, const char *shstr, const char *name){ int i; const char *shname; struct elf_shdr *sec; for(i = 0; i < shnum; i++) { sec = &shdr[i]; if (!sec->sh_name) continue; shname = shstr + sec->sh_name; if (!strcmp(shname, name)) return sec; } return NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -