Chameleon

Chameleon Svn Source Tree

Root/branches/chucko/i386/util/dyldsymboltool.c

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
23typedef struct symbols_dylib
24{
25struct mach_headerheader;
26struct dylib_commanddylib_info;
27charmodule_name[sizeof(DYLIB_NAME)];
28struct symtab_commandsymtab;
29} symbols_dylib_t;
30
31
32typedef struct symbolList_t
33{
34char*name;
35uint32_taddr;
36intpos;
37struct symbolList_t*next;
38} symbolList_t;
39
40
41int num_symbols(symbolList_t* list);
42int string_size(symbolList_t* list);
43void add_symbol(symbolList_t** list, char* name, uint32_t addr);
44
45
46int main(int argc, char *argv[])
47{
48if(argc < 3)
49{
50fprintf(stderr, "usage: dyldsymboltool obj1 [obj2 ...] outfile\n");
51
52exit(-1);
53}
54
55
56
57symbols_dylib_t dylib;
58symbolList_t*symbols = NULL;
59
60uint32_t start_addr = 0;
61
62
63
64
65 int i;
66for(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{
96start_addr = address;
97}
98if(strcmp(name, START_SYMBOL) == 0)
99{
100if(!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
113if(start_addr == 0)
114{
115fprintf(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 */
125dylib.header.ncmds = 2;
126dylib.header.sizeofcmds = sizeof(dylib) - sizeof(struct mach_header);// + dylib.symtab.nsyms * sizeof(struct nlist) + dylib.symtab.strsize;
127
128dylib.header.magic = MH_MAGIC;
129dylib.header.cputype = CPU_TYPE_X86;
130dylib.header.cpusubtype = /*CPUSUBTYPE_I386*/ 3;
131dylib.header.filetype = MH_DYLIB;
132dylib.header.flags = MH_NOUNDEFS | MH_DYLDLINK | MH_NO_REEXPORTED_DYLIBS;
133
134/* Load Commands - dylib id */
135dylib.dylib_info.cmd = LC_ID_DYLIB;
136dylib.dylib_info.cmdsize = sizeof(struct dylib_command) + sizeof(dylib.module_name);// todo: verify
137dylib.dylib_info.dylib.name.offset = sizeof(struct dylib_command);
138dylib.dylib_info.dylib.timestamp = 0;// TODO: populate with time
139dylib.dylib_info.dylib.current_version = 0;// TODO
140dylib.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
147sprintf(dylib.module_name, "%s", DYLIB_NAME);
148
149/* Load Commands - Symtable */
150dylib.symtab.cmd = LC_SYMTAB;
151dylib.symtab.symoff = sizeof(dylib);
152dylib.symtab.nsyms = num_symbols(symbols);
153dylib.symtab.stroff = sizeof(dylib) + dylib.symtab.nsyms * sizeof(struct nlist);
154dylib.symtab.strsize = string_size(symbols);
155dylib.symtab.cmdsize = sizeof(struct symtab_command);
156
157
158
159FILE* outfile = fopen(argv[argc-1], "w");
160fwrite(&dylib,sizeof(dylib)/* Sizeof header + module name */
161, 1, outfile);
162
163char* symtab = malloc(dylib.symtab.stroff + dylib.symtab.strsize - sizeof(dylib) + 1); // Add extra 1 for last symbol
164bzero(symtab, dylib.symtab.nsyms * sizeof(struct nlist) + dylib.symtab.strsize + 1);
165char* orig = symtab;
166
167//symtab += offset;
168
169
170while(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;
178symtab+= sizeof(struct nlist);
179
180strcpy(orig + dylib.symtab.stroff - sizeof(dylib) + symbols->pos, symbols->name);
181
182symbols = symbols->next;
183}
184
185fwrite(orig,
186dylib.symtab.stroff+// Sizeof symbol nlists
187dylib.symtab.strsize - sizeof(dylib) + 1// sizeof symbol strings
188, 1, outfile);
189
190
191fclose(outfile);
192
193exit(0);
194}
195
196int num_symbols(symbolList_t* list)
197{
198int retVal = 0;
199while(list)
200{
201retVal++;
202list = list->next;
203}
204return retVal;
205}
206
207int string_size(symbolList_t* list)
208{
209int retVal = 0;
210while(list)
211{
212retVal += strlen(list->name)+1;
213list = list->next;
214}
215return retVal;
216
217}
218
219void add_symbol(symbolList_t** list, char* name, uint32_t addr)
220{
221symbolList_t* entry = malloc(sizeof(symbolList_t));
222entry->next = (*list);
223
224if(*list) entry->pos = (*list)->pos + strlen((*list)->name) + 1;
225else entry->pos = 1;
226*list = entry;
227
228entry->addr = addr;
229entry->name = malloc(strlen(name)+1);
230strcpy(entry->name, name);
231}
232

Archive Download this file

Revision: HEAD