1 | /*␊ |
2 | * Copyright (c) 2010 Evan Lojewski. All rights reserved.␊ |
3 | *␉␊ |
4 | *␉dyldsymboltool␊ |
5 | *␊ |
6 | *␉␉Generates a dylib file for the dyld implimentation in chameleon␊ |
7 | *␉to load and link. This is used to import the boot symbols into the␊ |
8 | *␉module system. ␊ |
9 | */␊ |
10 | ␊ |
11 | #include <stdio.h>␊ |
12 | #include <stdlib.h>␊ |
13 | #include <mach/mach.h>␊ |
14 | #include <sys/file.h>␊ |
15 | #include <mach-o/loader.h>␊ |
16 | #include <mach-o/nlist.h>␊ |
17 | ␊ |
18 | ␊ |
19 | #define DYLIB_NAME "Symbols"␊ |
20 | #define VOID_SYMBOL "_load_all_modules"␊ |
21 | #define START_SYMBOL "start"␊ |
22 | ␊ |
23 | typedef struct symbols_dylib␊ |
24 | {␊ |
25 | ␉struct mach_header␉␉header;␊ |
26 | ␉struct dylib_command␉dylib_info;␊ |
27 | ␉char␉␉␉␉␉module_name[sizeof(DYLIB_NAME)];␉␊ |
28 | ␉struct symtab_command␉symtab;␊ |
29 | } symbols_dylib_t;␊ |
30 | ␊ |
31 | ␊ |
32 | typedef struct symbolList_t␊ |
33 | {␊ |
34 | ␉char*␉␉␉␉␉name;␊ |
35 | ␉uint32_t␉␉␉␉addr;␊ |
36 | ␉int␉␉␉␉␉␉pos;␊ |
37 | ␉struct symbolList_t*␉next;␊ |
38 | } symbolList_t;␊ |
39 | ␊ |
40 | ␊ |
41 | int num_symbols(symbolList_t* list);␊ |
42 | int string_size(symbolList_t* list);␊ |
43 | void add_symbol(symbolList_t** list, char* name, uint32_t addr);␊ |
44 | ␊ |
45 | ␊ |
46 | int main(int argc, char *argv[])␊ |
47 | {␊ |
48 | ␉if(argc < 3) ␊ |
49 | ␉{␊ |
50 | ␉␉fprintf(stderr, "usage: dyldsymboltool obj1 [obj2 ...] outfile\n");␊ |
51 | ␊ |
52 | ␉␉exit(-1);␊ |
53 | ␉}␊ |
54 | ␊ |
55 | ␉␊ |
56 | ␊ |
57 | ␉symbols_dylib_t dylib;␊ |
58 | ␉symbolList_t*␉symbols = NULL;␊ |
59 | ␊ |
60 | ␉uint32_t start_addr = 0;␊ |
61 | ␉␊ |
62 | ␉␊ |
63 | ␉␊ |
64 | ␉␊ |
65 | int i;␊ |
66 | ␉for(i = 1; i < argc-1; i++)␊ |
67 | {␊ |
68 | char line[256];␊ |
69 | char* command = malloc(strlen(argv[1]) + sizeof("nm -g "));␊ |
70 | FILE *fpipe;␊ |
71 | ␊ |
72 | // Parse boot.sys (arg1) to get symtab␊ |
73 | sprintf(command, "nm -g %s", argv[i]);␉// TODO: read boot.sym directly, no need for nm␊ |
74 | ␊ |
75 | if ( !(fpipe = (FILE*)popen(command,"r")) )␊ |
76 | { // If fpipe is NULL␊ |
77 | perror("Problems with pipe");␊ |
78 | exit(1);␊ |
79 | }␊ |
80 | ␊ |
81 | ␊ |
82 | while ( fgets( line, sizeof line, fpipe))␊ |
83 | {␊ |
84 | if((strlen(line) < strlen(argv[i]) ||␊ |
85 | strncmp(line, argv[i], strlen(argv[i])) != 0)␊ |
86 | && line[0] != ' ')␊ |
87 | {␊ |
88 | uint32_t address = 0;␊ |
89 | char* addr = strtok(line, " ");␊ |
90 | strtok(NULL, " ");␊ |
91 | char* name = strtok(NULL, " ");␊ |
92 | name[strlen(name)-1] = 0;␉// remove newline␊ |
93 | sscanf(addr, "%x", &address);␊ |
94 | if(strcmp(name, VOID_SYMBOL) == 0) ␊ |
95 | ␉␉␉␉{␊ |
96 | ␉␉␉␉␉start_addr = address;␊ |
97 | ␉␉␉␉}␊ |
98 | ␉␉␉␉if(strcmp(name, START_SYMBOL) == 0)␊ |
99 | ␉␉␉␉{␊ |
100 | ␉␉␉␉␉if(!start_addr) start_addr = address;␊ |
101 | ␉␉␉␉}␊ |
102 | else add_symbol(&symbols, name, address);␊ |
103 | }␊ |
104 | } ␊ |
105 | ␊ |
106 | pclose(fpipe);␊ |
107 | ␊ |
108 | free(command);␊ |
109 | }␊ |
110 | ␊ |
111 | ␊ |
112 | ␉␊ |
113 | ␉if(start_addr == 0)␊ |
114 | ␉{␊ |
115 | ␉␉fprintf(stderr, "Unable to locate Symbol.dylib start function\n");␊ |
116 | ␊ |
117 | //exit(1);␊ |
118 | ␉}␊ |
119 | else␊ |
120 | {␊ |
121 | add_symbol(&symbols, START_SYMBOL, start_addr);␊ |
122 | ␉}␊ |
123 | ␉␊ |
124 | ␉/* Header command info */␊ |
125 | ␉dylib.header.ncmds = 2;␊ |
126 | ␉dylib.header.sizeofcmds = sizeof(dylib) - sizeof(struct mach_header);// + dylib.symtab.nsyms * sizeof(struct nlist) + dylib.symtab.strsize;␊ |
127 | ␉␊ |
128 | ␉dylib.header.magic = MH_MAGIC;␊ |
129 | ␉dylib.header.cputype = CPU_TYPE_X86;␊ |
130 | ␉dylib.header.cpusubtype = /*CPUSUBTYPE_I386*/ 3;␊ |
131 | ␉dylib.header.filetype = MH_DYLIB;␊ |
132 | ␉dylib.header.flags = MH_NOUNDEFS | MH_DYLDLINK | MH_NO_REEXPORTED_DYLIBS;␊ |
133 | ␉␉␊ |
134 | ␉/* Load Commands - dylib id */␊ |
135 | ␉dylib.dylib_info.cmd = LC_ID_DYLIB;␊ |
136 | ␉dylib.dylib_info.cmdsize = sizeof(struct dylib_command) + sizeof(dylib.module_name);␉// todo: verify␊ |
137 | ␉dylib.dylib_info.dylib.name.offset = sizeof(struct dylib_command);␊ |
138 | ␉dylib.dylib_info.dylib.timestamp = 0;␉// TODO: populate with time␊ |
139 | ␉dylib.dylib_info.dylib.current_version = 0;␉␉␉// TODO␊ |
140 | ␉dylib.dylib_info.dylib.compatibility_version = 0;␉// TODO␊ |
141 | ␉␊ |
142 | ␉␊ |
143 | ␉//int offset = dylib.dylib_info.cmdsize%4 ? 4 - (dylib.dylib_info.cmdsize % 4) : 0;␊ |
144 | ␉//dylib.dylib_info.cmdsize += offset;␊ |
145 | ␉//dylib.header.sizeofcmds += offset;␊ |
146 | ␉␊ |
147 | ␉sprintf(dylib.module_name, "%s", DYLIB_NAME);␊ |
148 | ␉␊ |
149 | ␉/* Load Commands - Symtable */␊ |
150 | ␉dylib.symtab.cmd = LC_SYMTAB;␊ |
151 | ␉dylib.symtab.symoff = sizeof(dylib);␉␊ |
152 | ␉dylib.symtab.nsyms = num_symbols(symbols);␊ |
153 | ␉dylib.symtab.stroff = sizeof(dylib) + dylib.symtab.nsyms * sizeof(struct nlist);␊ |
154 | ␉dylib.symtab.strsize = string_size(symbols);␊ |
155 | ␉dylib.symtab.cmdsize = sizeof(struct symtab_command);␊ |
156 | ␉␊ |
157 | ␉␊ |
158 | ␊ |
159 | ␉FILE* outfile = fopen(argv[argc-1], "w");␊ |
160 | ␉fwrite(&dylib,␉sizeof(dylib)␉/* Sizeof header + module name */␊ |
161 | ␉␉␉␉␉, 1, outfile);␊ |
162 | ␉␊ |
163 | ␉char* symtab = malloc(dylib.symtab.stroff + dylib.symtab.strsize - sizeof(dylib) + 1); // Add extra 1 for last symbol␊ |
164 | ␉bzero(symtab, dylib.symtab.nsyms * sizeof(struct nlist) + dylib.symtab.strsize + 1);␊ |
165 | ␉char* orig = symtab;␊ |
166 | ␉␊ |
167 | ␉//symtab += offset;␊ |
168 | ␉␊ |
169 | ␉␊ |
170 | ␉while(symbols)␊ |
171 | ␉{␊ |
172 | ␉␉␊ |
173 | ␉␉((struct nlist*)symtab)->n_un.n_strx = symbols->pos;␊ |
174 | ␉␉((struct nlist*)symtab)->n_type = 0xF;␉// TODO: read from boot.sys␊ |
175 | ␉␉((struct nlist*)symtab)->n_sect = 0;␊ |
176 | ␉␉((struct nlist*)symtab)->n_desc = REFERENCE_FLAG_DEFINED;␊ |
177 | ␉␉((struct nlist*)symtab)->n_value = (uint32_t)symbols->addr;␊ |
178 | ␉␉symtab+= sizeof(struct nlist);␊ |
179 | ␉␉␊ |
180 | ␉␉strcpy(orig + dylib.symtab.stroff - sizeof(dylib) + symbols->pos, symbols->name);␊ |
181 | ␊ |
182 | ␉␉symbols = symbols->next;␊ |
183 | ␉}␊ |
184 | ␊ |
185 | ␉fwrite(orig,␉ ␊ |
186 | ␉␉␉␉␉dylib.symtab.stroff␉+␉␉␉␉␉// Sizeof symbol nlists ␊ |
187 | ␉␉␉␉␉dylib.symtab.strsize - sizeof(dylib) + 1␉// sizeof symbol strings␊ |
188 | ␉␉␉␉␉, 1, outfile);␊ |
189 | ␊ |
190 | ␉␊ |
191 | ␉fclose(outfile);␊ |
192 | ␉␊ |
193 | ␉exit(0);␊ |
194 | }␊ |
195 | ␊ |
196 | int num_symbols(symbolList_t* list)␊ |
197 | {␊ |
198 | ␉int retVal = 0;␊ |
199 | ␉while(list)␊ |
200 | ␉{␊ |
201 | ␉␉retVal++;␊ |
202 | ␉␉list = list->next;␊ |
203 | ␉}␊ |
204 | ␉return retVal;␊ |
205 | }␊ |
206 | ␊ |
207 | int string_size(symbolList_t* list)␊ |
208 | {␊ |
209 | ␉int retVal = 0;␊ |
210 | ␉while(list)␊ |
211 | ␉{␊ |
212 | ␉␉retVal += strlen(list->name)+1;␊ |
213 | ␉␉list = list->next;␊ |
214 | ␉}␊ |
215 | ␉return retVal;␊ |
216 | ␉␊ |
217 | }␊ |
218 | ␊ |
219 | void add_symbol(symbolList_t** list, char* name, uint32_t addr)␊ |
220 | {␊ |
221 | ␉symbolList_t* entry = malloc(sizeof(symbolList_t));␊ |
222 | ␉entry->next = (*list);␊ |
223 | ␉␊ |
224 | ␉if(*list) entry->pos = (*list)->pos + strlen((*list)->name) + 1;␊ |
225 | ␉else entry->pos = 1;␊ |
226 | ␉*list = entry;␊ |
227 | ␉␊ |
228 | ␉entry->addr = addr;␊ |
229 | ␉entry->name = malloc(strlen(name)+1);␊ |
230 | ␉strcpy(entry->name, name);␊ |
231 | }␊ |
232 | |