diff options
Diffstat (limited to 'qemu/roms/openhackware/src/libexec/macho.c')
-rw-r--r-- | qemu/roms/openhackware/src/libexec/macho.c | 517 |
1 files changed, 0 insertions, 517 deletions
diff --git a/qemu/roms/openhackware/src/libexec/macho.c b/qemu/roms/openhackware/src/libexec/macho.c deleted file mode 100644 index f07c92144..000000000 --- a/qemu/roms/openhackware/src/libexec/macho.c +++ /dev/null @@ -1,517 +0,0 @@ -/* - * <macho.c> - * - * Open Hack'Ware BIOS MACH-O executable file loader - * - * Copyright (c) 2004-2005 Jocelyn Mayer - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License V2 - * as published by the Free Software Foundation - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <stdlib.h> -#include <stdio.h> -#include "bios.h" -#include "exec.h" - -/* MACH-O executable loader */ -/* FAT definitions */ -/* CPU type definitions */ -typedef enum cpu_type_t { - CPU_TYPE_ANY = -1, - CPU_TYPE_VAX = 1, - CPU_TYPE_MC680x0 = 6, - CPU_TYPE_I386 = 7, - CPU_TYPE_MIPS = 8, - CPU_TYPE_MC98000 = 10, - CPU_TYPE_HPPA = 11, - CPU_TYPE_ARM = 12, - CPU_TYPE_MC88000 = 13, - CPU_TYPE_SPARC = 14, - CPU_TYPE_I860 = 15, - CPU_TYPE_ALPHA = 16, - CPU_TYPE_POWERPC = 18, -} cpu_type_t; - -/* Any CPU */ -typedef enum cpu_subtype_any_t { - CPU_SUBTYPE_MULTIPLE = -1, - CPU_SUBTYPE_LITTLE_ENDIAN = 0, - CPU_SUBTYPE_BIG_ENDIAN = 1, -} cpu_subtype_any_t; - -/* PowerPC */ -typedef enum cpu_subtype_ppc_t { - CPU_SUBTYPE_PPC_ALL = 0, - CPU_SUBTYPE_PPC_601 = 1, - CPU_SUBTYPE_PPC_602 = 2, - CPU_SUBTYPE_PPC_603 = 3, - CPU_SUBTYPE_PPC_603e = 4, - CPU_SUBTYPE_PPC_603ev = 5, - CPU_SUBTYPE_PPC_604 = 6, - CPU_SUBTYPE_PPC_604e = 7, - CPU_SUBTYPE_PPC_620 = 8, - CPU_SUBTYPE_PPC_750 = 9, - CPU_SUBTYPE_PPC_7400 = 10, - CPU_SUBTYPE_PPC_7450 = 11, -} cpu_subtype_ppc_t; - -/* Fat header definition */ -#define FAT_MAGIC 0xCAFEBABE - -typedef struct fat_head_t { - uint32_t magic; - uint32_t nfat_arch; -} fat_head_t; - -typedef struct fat_arch_t { - cpu_type_t cpu_type; - cpu_subtype_ppc_t cpu_subtype; - uint32_t offset; - uint32_t size; - uint32_t align; -} fat_arch_t; - -/* Mach-O binary definitions */ -#define MACH_O_MAGIC 0xFEEDFACE - -typedef enum filetype_t { - MH_OBJECT = 0x1, - MH_EXECUTE = 0x2, - MH_FVMLIB = 0x3, - MH_CORE = 0x4, - MH_PRELOAD = 0x5, - MH_DYLIB = 0x6, - MH_DYLINKER = 0x7, - MH_BUNDLE = 0x8, -} filetype_t; - -enum { - MH_NOUNDEFS = 0x01, - MH_INCRLINK = 0x02, - MH_DYLDLINK = 0x04, - MH_BINDATLOAD = 0x08, - MH_PREBOUND = 0x10, -}; - -typedef struct mach_head_t { - uint32_t magic; - cpu_type_t cpu_type; - cpu_subtype_ppc_t subtype; - filetype_t file_type; - uint32_t nb_cmds; - uint32_t cmds_size; - uint32_t flags; -} mach_head_t; - -typedef enum load_cmd_t { - LC_SEGMENT = 0x01, - LC_SYMTAB = 0x02, - LC_SYMSEG = 0x03, - LC_THREAD = 0x04, - LC_UNIXTHREAD = 0x05, - LC_LOADFVMLIB = 0x06, - LC_IDFVMLIB = 0x07, - LC_IDENT = 0x08, - LC_FVMFILE = 0x09, - LC_PREPAGE = 0x0A, - LC_DYSYMTAB = 0x0B, - LC_LOAD_DYLIB = 0x0C, - LC_ID_DYLIB = 0x0D, - LC_LOAD_DYLINKER = 0x0E, - LC_ID_DYLINKER = 0x0F, - LC_PREBOUND_DYLIB = 0x10, - LC_0x17 = 0x17, -} load_cmd_t; - -typedef struct mach_load_cmd_t { - load_cmd_t cmd; - uint32_t cmd_size; -} mach_load_cmd_t; - -typedef struct mach_string_t { - uint32_t offset; -} mach_string_t; - -enum { - SG_HIGHVM = 0x1, - SG_FVMLIB = 0x2, - SG_NORELOC = 0x4, -}; - -typedef struct mach_segment_t { - unsigned char segname[16]; - uint32_t vmaddr; - uint32_t vmsize; - uint32_t file_offset; - uint32_t file_size; - uint32_t max_prot; - uint32_t init_prot; - uint32_t nsects; - uint32_t flags; -} mach_segment_t; - -enum { - SECTION_TYPE = 0xFF, - S_REGULAR = 0x0, - S_ZEROFILL = 0x1, - S_CSTRING_LITERALS = 0x2, - S_4BYTE_LITERALS = 0x3, - S_8BYTE_LITERALS = 0x4, - S_LITERAL_POINTERS = 0x5, - S_NON_LAZY_SYMBOL_POINTERS = 0x6, - S_LAZY_SYMBOL_POINTERS = 0x7, - S_SYMBOL_STUBS = 0x8, - S_MOD_INIT_FUNC_POINTERS = 0x9, -}; - -enum { - S_ATTR_PURE_INSTRUCTIONS = 0x80000000, - S_ATTR_SOME_INSTRUCTIONS = 0x00000400, - S_ATTR_EXT_RELOC = 0x00000200, - S_ATTR_LOC_RELOC = 0x00000100, -}; - -typedef struct mach_section_t { - unsigned char sectname[16]; - unsigned char segname[16]; - uint32_t vmaddr; - uint32_t size; - uint32_t offset; - uint32_t align; - uint32_t reloc_offset; - uint32_t nreloc; - uint32_t flags; - uint32_t res1; - uint32_t res2; -} mach_section_t; - -typedef struct mach_symtab_t { - uint32_t offset; - uint32_t nsyms; - uint32_t str_offset; - uint32_t str_size; -} mach_symtab_t; - -typedef struct mach_symseg_t { - uint32_t offset; - uint32_t size; -} mach_symseg_t; - -typedef struct mach_unixth_t { - uint32_t flavor; - uint32_t count; - /* This is supposed to be a stack. - * Let's assume it's less than 1kB (arbitrary !) - */ - uint32_t data[256]; -} mach_unixth_t; - -typedef struct mach_fvmlib_t { - uint32_t str_offset; - uint32_t minor_version; - uint32_t header_addr; -} mach_fvmlib_t; - -typedef struct mach_fvmfile_t { - uint32_t str_offset; - uint32_t vmaddr; -} mach_fvmfile_t; - -typedef struct mach_dysymtab_t { - uint32_t ilocal_syms; - uint32_t nlocal_syms; - uint32_t iext_syms; - uint32_t next_syms; - uint32_t iundef_syms; - uint32_t nundef_syms; - uint32_t toc_offset; - uint32_t ntoc; - uint32_t modtab_offset; - uint32_t nmodtab; - uint32_t extsym_offset; - uint32_t nextsym; - uint32_t indirect_offset; - uint32_t nindirect; - uint32_t ext_reloc_offset; - uint32_t next_reloc; - uint32_t local_reloc_offset; - uint32_t nlocal_reloc; -} mach_dysymtab_t; - -typedef struct mach_dylib_t { - uint32_t str_offset; - uint32_t timestamp; - uint32_t cur_version; - uint32_t compat_version; -} mach_dylib_t; - -typedef struct mach_prebound_t { - uint32_t str_offset; - uint32_t nb_modules; - unsigned char linked_modules[256]; -} mach_prebound_t; - -int exec_load_macho (inode_t *file, void **dest, void **entry, void **end, - uint32_t loffset) -{ - mach_head_t mhdr; - mach_load_cmd_t lcmd; - fat_head_t fhdr; - fat_arch_t fahdr; - void *address, *first, *last; - uint32_t k, j, best, offset; - int entry_set; - - /* Probe FAT */ - file_seek(file, loffset); - if (fs_read(file, &fhdr, sizeof(fat_head_t)) < 0) { - ERROR("Cannot load fat header...\n"); - return -1; - } - fhdr.magic = get_be32(&fhdr.magic); - if (fhdr.magic != FAT_MAGIC) - goto macho_probe; - fhdr.nfat_arch = get_be32(&fhdr.nfat_arch); - DPRINTF("FAT file: %d archs\n", fhdr.nfat_arch); - /* Find the best architecture */ - best = -1; - offset = 0; - for (k = 0; k < fhdr.nfat_arch; k++) { - if (fs_read(file, &fahdr, sizeof(fat_arch_t)) < 0) { - ERROR("Cannot load fat arch header\n"); - return -1; - } - fahdr.cpu_type = get_be32(&fahdr.cpu_type); - if (fahdr.cpu_type != CPU_TYPE_POWERPC) - continue; - fahdr.cpu_subtype = get_be32(&fahdr.cpu_subtype); - fahdr.offset = get_be32(&fahdr.offset); - fahdr.size = get_be32(&fahdr.size); - fahdr.align = get_be32(&fahdr.align); - switch (fahdr.cpu_subtype) { - case CPU_SUBTYPE_PPC_750: - best = k; - offset = fahdr.offset; - goto fat_cpu_ok; - case CPU_SUBTYPE_PPC_ALL: - if (best == (uint32_t)-1) { - offset = fahdr.offset; - best = k; - } - break; - case CPU_SUBTYPE_PPC_603: - case CPU_SUBTYPE_PPC_603e: - case CPU_SUBTYPE_PPC_603ev: - case CPU_SUBTYPE_PPC_604: - case CPU_SUBTYPE_PPC_604e: - best = k; - offset = fahdr.offset; - break; - default: - break; - } - } - if (best == (uint32_t)-1) { - ERROR("No matching PPC FAT arch\n"); - return -1; - } - DPRINTF("Use FAT arch %d at %08x %08x\n", best, offset, loffset); - fat_cpu_ok: - loffset += offset; - - /* Probe macho */ - macho_probe: - file_seek(file, loffset); - if (fs_read(file, &mhdr, sizeof(mach_head_t)) < 0) { - ERROR("Cannot load MACH-O header...\n"); - return -1; - } - mhdr.magic = get_be32(&mhdr.magic); - if (mhdr.magic != MACH_O_MAGIC) { - ERROR("Not a MACH-O file\n"); - return -2; - } - mhdr.cpu_type = get_be32(&mhdr.cpu_type); - mhdr.subtype = get_be32(&mhdr.subtype); - mhdr.file_type = get_be32(&mhdr.file_type); - mhdr.nb_cmds = get_be32(&mhdr.nb_cmds); - mhdr.cmds_size = get_be32(&mhdr.cmds_size); - mhdr.flags = get_be32(&mhdr.flags); - DPRINTF("MACHO-O file cpu %d %d file type %08x %d cmds size %08x flags " - "%08x\n", mhdr.cpu_type, mhdr.subtype, mhdr.file_type, - mhdr.nb_cmds, mhdr.cmds_size, mhdr.flags); - offset = sizeof(mach_head_t); - first = (void *)-1; - last = NULL; - entry_set = 0; - for (k = 0; k < mhdr.nb_cmds; k++) { - file_seek(file, loffset + offset); - if (fs_read(file, &lcmd, sizeof(mach_load_cmd_t)) < 0) { - ERROR("Unable to load MACH-O cmd %d\n", k); - return -1; - } - lcmd.cmd = get_be32(&lcmd.cmd); - lcmd.cmd_size = get_be32(&lcmd.cmd_size); - DPRINTF("Cmd %d : %08x size %08x (%08x %08x)\n", k, lcmd.cmd, - lcmd.cmd_size, offset, offset + loffset); - switch (lcmd.cmd) { - case LC_SEGMENT: - /* To be loaded for execution */ - { - mach_segment_t segment; - mach_section_t section; - uint32_t pos; - - pos = offset + sizeof(mach_load_cmd_t); - if (fs_read(file, &segment, sizeof(mach_segment_t)) < 0) { - ERROR("Cannot load MACH-O segment\n"); - return -1; - } - pos += sizeof(mach_segment_t); - segment.vmaddr = get_be32(&segment.vmaddr); - segment.vmsize = get_be32(&segment.vmsize); - segment.file_offset = get_be32(&segment.file_offset); - segment.file_size = get_be32(&segment.file_size); - segment.max_prot = get_be32(&segment.max_prot); - segment.init_prot = get_be32(&segment.init_prot); - segment.nsects = get_be32(&segment.nsects); - segment.flags = get_be32(&segment.flags); - DPRINTF("MACH-O segment addr %08x size %08x off %08x fsize " - "%08x ns %d fl %08x\n", segment.vmaddr, segment.vmsize, - segment.file_offset, segment.file_size, - segment.nsects, segment.flags); - for (j = 0; j < segment.nsects; j++) { - file_seek(file, loffset + pos); - if (fs_read(file, §ion, sizeof(mach_section_t)) < 0) { - ERROR("Cannot load MACH-O section\n"); - return -1; - } - pos += sizeof(mach_section_t); - section.vmaddr = get_be32(§ion.vmaddr); - section.size = get_be32(§ion.size); - section.offset = get_be32(§ion.offset); - section.align = get_be32(§ion.align); - section.reloc_offset = get_be32(§ion.reloc_offset); - section.nreloc = get_be32(§ion.nreloc); - section.flags = get_be32(§ion.flags); - section.res1 = get_be32(§ion.res1); - section.res2 = get_be32(§ion.res2); - DPRINTF("MACH-O section vmaddr %08x size %08x off %08x " - "flags %08x\n", section.vmaddr, section.size, - section.offset, section.flags); - switch (section.flags & SECTION_TYPE) { - case S_REGULAR: - case S_CSTRING_LITERALS: - case S_4BYTE_LITERALS: - case S_8BYTE_LITERALS: - case S_LITERAL_POINTERS: - case S_NON_LAZY_SYMBOL_POINTERS: - case S_LAZY_SYMBOL_POINTERS: - case S_SYMBOL_STUBS: - case S_MOD_INIT_FUNC_POINTERS: - DPRINTF("Load section of type %d from %08x to %08x" - " %08x\n", section.flags, section.offset, - section.vmaddr, section.size); - file_seek(file, section.offset + loffset); - address = (void *)section.vmaddr; - if (address < first && address != NULL) - first = address; - if (address + section.size > last) - last = address + section.size; - if (fs_read(file, address, section.size) < 0) { - ERROR("Cannot load MACH-O section %d %d...\n", - k, j); - return -1; - } - break; - case S_ZEROFILL: - DPRINTF("Fill zero section to %08x %08x\n", - section.vmaddr, section.size); - address = (void *)section.vmaddr; - if (address < first && address != NULL) - first = address; - if (address + section.size > last) - last = address + section.size; - memset(address, 0, section.size); - break; - default: - ERROR("Unknown MACH-O section type: %d\n", - section.flags); - return -1; - } - } - } - break; - case LC_SYMTAB: - /* Don't care */ - break; - case LC_SYMSEG: - /* Don't care */ - break; - case LC_UNIXTHREAD: - /* To be loaded for execution */ - { - mach_unixth_t unixth; - - if (fs_read(file, &unixth, sizeof(mach_unixth_t)) < 0) { - ERROR("Cannot load MACH-O UNIX thread\n"); - return -1; - } - DPRINTF("Set entry point to %08x\n", unixth.data[0]); - *entry = (void *)unixth.data[0]; - entry_set = 1; - } - break; - case LC_THREAD: - break; - case LC_LOADFVMLIB: - break; - case LC_IDFVMLIB: - break; - case LC_IDENT: - break; - case LC_FVMFILE: - break; - case LC_PREPAGE: - printf("Prepage command\n"); - break; - case LC_DYSYMTAB: - break; - case LC_LOAD_DYLIB: - break; - case LC_ID_DYLIB: - break; - case LC_LOAD_DYLINKER: - /* To be loaded for execution */ - break; - case LC_ID_DYLINKER: - break; - case LC_PREBOUND_DYLIB: - break; - case LC_0x17: - /* ? */ - break; - default: - printf("unknown MACH-O command (%d %d)\n", k, lcmd.cmd); - return -1; - } - offset += lcmd.cmd_size; - } - *dest = first; - *end = last; - // if (entry_set == 0) - *entry = *dest; - - return 0; -} |