| /*␊ |
| * Copyright (c) 2010 Evan Lojewski. All rights reserved.␊ |
| *␉␊ |
| *␉dyldsymboltool␊ |
| *␊ |
| *␉␉Generates a dylib file for the dyld implimentation in chameleon␊ |
| *␉to load and link. This is used to import the boot symbols into the␊ |
| *␉module system. ␊ |
| */␊ |
| ␊ |
| #include <stdio.h>␊ |
| #include <stdlib.h>␊ |
| #include <mach/mach.h>␊ |
| #include <sys/file.h>␊ |
| #include <mach-o/loader.h>␊ |
| #include <mach-o/nlist.h>␊ |
| ␊ |
| ␊ |
| #define DYLIB_NAME "Symbols"␊ |
| #define VOID_SYMBOL "_load_all_modules"␊ |
| #define START_SYMBOL "start"␊ |
| ␊ |
| typedef struct symbols_dylib␊ |
| {␊ |
| ␉struct mach_header␉␉header;␊ |
| ␉struct dylib_command␉dylib_info;␊ |
| ␉char␉␉␉␉␉module_name[sizeof(DYLIB_NAME)];␉␊ |
| ␉struct symtab_command␉symtab;␊ |
| } symbols_dylib_t;␊ |
| ␊ |
| ␊ |
| typedef struct symbolList_t␊ |
| {␊ |
| ␉char*␉␉␉␉␉name;␊ |
| ␉uint32_t␉␉␉␉addr;␊ |
| ␉int␉␉␉␉␉␉pos;␊ |
| ␉struct symbolList_t*␉next;␊ |
| } symbolList_t;␊ |
| ␊ |
| ␊ |
| int num_symbols(symbolList_t* list);␊ |
| int string_size(symbolList_t* list);␊ |
| void add_symbol(symbolList_t** list, char* name, uint32_t addr);␊ |
| ␊ |
| ␊ |
| int main(int argc, char *argv[])␊ |
| {␊ |
| ␉if(argc != 3) ␊ |
| ␉{␊ |
| ␉␉fprintf(stderr, "usage: dyldsymboltool bootFile loadAddr outfile\n");␊ |
| ␊ |
| ␉␉exit(-1);␊ |
| ␉}␊ |
| ␊ |
| ␉␊ |
| ␉char line[256];␊ |
| ␉char* command = malloc(strlen(argv[1]) + sizeof("nm -g "));␊ |
| ␉FILE *fpipe;␊ |
| ␊ |
| ␉symbols_dylib_t dylib;␊ |
| ␉symbolList_t*␉symbols = NULL;␊ |
| ␊ |
| ␉uint32_t start_addr = 0;␊ |
| ␉␊ |
| ␉␊ |
| ␉␊ |
| ␉␊ |
| ␊ |
| ␉␊ |
| ␉// Parse boot.sys (arg1) to get symtab␊ |
| ␉sprintf(command, "nm -g %s", argv[1]);␉// TODO: read boot.sym directly, no need for nm␊ |
| ␊ |
| ␉if ( !(fpipe = (FILE*)popen(command,"r")) )␊ |
| ␉{ // If fpipe is NULL␊ |
| ␉␉perror("Problems with pipe");␊ |
| ␉␉exit(1);␊ |
| ␉}␊ |
| ␉␊ |
| ␉while ( fgets( line, sizeof line, fpipe))␊ |
| ␉{␊ |
| ␉␉uint32_t address = 0;␊ |
| ␉␉char* addr = strtok(line, " ");␊ |
| ␉␉strtok(NULL, " ");␊ |
| ␉␉char* name = strtok(NULL, " ");␊ |
| ␉␉name[strlen(name)-1] = 0;␉// remove newline␊ |
| ␉␉sscanf(addr, "%x", &address);␊ |
| ␉␉if(strcmp(name, VOID_SYMBOL) == 0) start_addr = address;␊ |
| ␉␉add_symbol(&symbols, name, address);␊ |
| ␉}␊ |
| ␉␊ |
| ␉␊ |
| ␉pclose(fpipe);␊ |
| ␉␊ |
| ␉if(start_addr == 0)␊ |
| ␉{␊ |
| ␉␉fprintf(stderr, "Unable to locate Symbol.dylib start function\n");␊ |
| ␉␉exit(1);␊ |
| ␉}␊ |
| ␉␊ |
| ␉add_symbol(&symbols, START_SYMBOL, start_addr);␊ |
| ␉␊ |
| ␉␊ |
| ␉/* Header command info */␊ |
| ␉dylib.header.ncmds = 2;␊ |
| ␉dylib.header.sizeofcmds = sizeof(dylib) - sizeof(struct mach_header);// + dylib.symtab.nsyms * sizeof(struct nlist) + dylib.symtab.strsize;␊ |
| ␉␊ |
| ␉dylib.header.magic = MH_MAGIC;␊ |
| ␉dylib.header.cputype = CPU_TYPE_X86;␊ |
| ␉dylib.header.cpusubtype = /*CPUSUBTYPE_I386*/ 3;␊ |
| ␉dylib.header.filetype = MH_DYLIB;␊ |
| ␉dylib.header.flags = MH_NOUNDEFS | MH_DYLDLINK | MH_NO_REEXPORTED_DYLIBS;␊ |
| ␉␉␊ |
| ␉/* Load Commands - dylib id */␊ |
| ␉dylib.dylib_info.cmd = LC_ID_DYLIB;␊ |
| ␉dylib.dylib_info.cmdsize = sizeof(struct dylib_command) + sizeof(dylib.module_name);␉// todo: verify␊ |
| ␉dylib.dylib_info.dylib.name.offset = sizeof(struct dylib_command);␊ |
| ␉dylib.dylib_info.dylib.timestamp = 0;␉// TODO: populate with time␊ |
| ␉dylib.dylib_info.dylib.current_version = 0;␉␉␉// TODO␊ |
| ␉dylib.dylib_info.dylib.compatibility_version = 0;␉// TODO␊ |
| ␉␊ |
| ␉␊ |
| ␉//int offset = dylib.dylib_info.cmdsize%4 ? 4 - (dylib.dylib_info.cmdsize % 4) : 0;␊ |
| ␉//dylib.dylib_info.cmdsize += offset;␊ |
| ␉//dylib.header.sizeofcmds += offset;␊ |
| ␉␊ |
| ␉sprintf(dylib.module_name, "%s", DYLIB_NAME);␊ |
| ␉␊ |
| ␉/* Load Commands - Symtable */␊ |
| ␉dylib.symtab.cmd = LC_SYMTAB;␊ |
| ␉dylib.symtab.symoff = sizeof(dylib);␉␊ |
| ␉dylib.symtab.nsyms = num_symbols(symbols);␊ |
| ␉dylib.symtab.stroff = sizeof(dylib) + dylib.symtab.nsyms * sizeof(struct nlist);␊ |
| ␉dylib.symtab.strsize = string_size(symbols);␊ |
| ␉dylib.symtab.cmdsize = sizeof(struct symtab_command);␊ |
| ␉␊ |
| ␉␊ |
| ␊ |
| ␉FILE* outfile = fopen(argv[2], "w");␊ |
| ␉fwrite(&dylib,␉sizeof(dylib)␉/* Sizeof header + module name */␊ |
| ␉␉␉␉␉, 1, outfile);␊ |
| ␉␊ |
| ␉char* symtab = malloc(dylib.symtab.stroff + dylib.symtab.strsize - sizeof(dylib) + 1); // Add extra 1 for last symbol␊ |
| ␉bzero(symtab, dylib.symtab.nsyms * sizeof(struct nlist) + dylib.symtab.strsize + 1);␊ |
| ␉char* orig = symtab;␊ |
| ␉␊ |
| ␉//symtab += offset;␊ |
| ␉␊ |
| ␉␊ |
| ␉while(symbols)␊ |
| ␉{␊ |
| ␉␉␊ |
| ␉␉((struct nlist*)symtab)->n_un.n_strx = symbols->pos;␊ |
| ␉␉((struct nlist*)symtab)->n_type = 0xF;␉// TODO: read from boot.sys␊ |
| ␉␉((struct nlist*)symtab)->n_sect = 0;␊ |
| ␉␉((struct nlist*)symtab)->n_desc = REFERENCE_FLAG_DEFINED;␊ |
| ␉␉((struct nlist*)symtab)->n_value = (uint32_t)symbols->addr;␊ |
| ␉␉symtab+= sizeof(struct nlist);␊ |
| ␉␉␊ |
| ␉␉strcpy(orig + dylib.symtab.stroff - sizeof(dylib) + symbols->pos, symbols->name);␊ |
| ␊ |
| ␉␉symbols = symbols->next;␊ |
| ␉}␊ |
| ␊ |
| ␉fwrite(orig,␉ ␊ |
| ␉␉␉␉␉dylib.symtab.stroff␉+␉␉␉␉␉// Sizeof symbol nlists ␊ |
| ␉␉␉␉␉dylib.symtab.strsize - sizeof(dylib) + 1␉// sizeof symbol strings␊ |
| ␉␉␉␉␉, 1, outfile);␊ |
| ␊ |
| ␉␊ |
| ␉fclose(outfile);␊ |
| ␉␊ |
| ␉exit(0);␊ |
| }␊ |
| ␊ |
| int num_symbols(symbolList_t* list)␊ |
| {␊ |
| ␉int retVal = 0;␊ |
| ␉while(list)␊ |
| ␉{␊ |
| ␉␉retVal++;␊ |
| ␉␉list = list->next;␊ |
| ␉}␊ |
| ␉return retVal;␊ |
| }␊ |
| ␊ |
| int string_size(symbolList_t* list)␊ |
| {␊ |
| ␉int retVal = 0;␊ |
| ␉while(list)␊ |
| ␉{␊ |
| ␉␉retVal += strlen(list->name)+1;␊ |
| ␉␉list = list->next;␊ |
| ␉}␊ |
| ␉return retVal;␊ |
| ␉␊ |
| }␊ |
| ␊ |
| void add_symbol(symbolList_t** list, char* name, uint32_t addr)␊ |
| {␊ |
| ␉symbolList_t* entry = malloc(sizeof(symbolList_t));␊ |
| ␉entry->next = (*list);␊ |
| ␉␊ |
| ␉if(*list) entry->pos = (*list)->pos + strlen((*list)->name) + 1;␊ |
| ␉else entry->pos = 1;␊ |
| ␉*list = entry;␊ |
| ␉␊ |
| ␉entry->addr = addr;␊ |
| ␉entry->name = malloc(strlen(name)+1);␊ |
| ␉strcpy(entry->name, name);␊ |
| }␊ |