Chameleon

Chameleon Svn Source Tree

Root/branches/xZenu/src/util/dyldsymboltool.c

Source at commit 1285 created 12 years 8 months ago.
By meklort, Utils folder compiled with native toolchain.
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) start_addr = address;
95 add_symbol(&symbols, name, address);
96 }
97 }
98
99 pclose(fpipe);
100
101 free(command);
102 }
103
104
105
106if(start_addr == 0)
107{
108fprintf(stderr, "Unable to locate Symbol.dylib start function\n");
109
110 //exit(1);
111}
112 else
113 {
114 add_symbol(&symbols, START_SYMBOL, start_addr);
115}
116
117/* Header command info */
118dylib.header.ncmds = 2;
119dylib.header.sizeofcmds = sizeof(dylib) - sizeof(struct mach_header);// + dylib.symtab.nsyms * sizeof(struct nlist) + dylib.symtab.strsize;
120
121dylib.header.magic = MH_MAGIC;
122dylib.header.cputype = CPU_TYPE_X86;
123dylib.header.cpusubtype = /*CPUSUBTYPE_I386*/ 3;
124dylib.header.filetype = MH_DYLIB;
125dylib.header.flags = MH_NOUNDEFS | MH_DYLDLINK | MH_NO_REEXPORTED_DYLIBS;
126
127/* Load Commands - dylib id */
128dylib.dylib_info.cmd = LC_ID_DYLIB;
129dylib.dylib_info.cmdsize = sizeof(struct dylib_command) + sizeof(dylib.module_name);// todo: verify
130dylib.dylib_info.dylib.name.offset = sizeof(struct dylib_command);
131dylib.dylib_info.dylib.timestamp = 0;// TODO: populate with time
132dylib.dylib_info.dylib.current_version = 0;// TODO
133dylib.dylib_info.dylib.compatibility_version = 0;// TODO
134
135
136//int offset = dylib.dylib_info.cmdsize%4 ? 4 - (dylib.dylib_info.cmdsize % 4) : 0;
137//dylib.dylib_info.cmdsize += offset;
138//dylib.header.sizeofcmds += offset;
139
140sprintf(dylib.module_name, "%s", DYLIB_NAME);
141
142/* Load Commands - Symtable */
143dylib.symtab.cmd = LC_SYMTAB;
144dylib.symtab.symoff = sizeof(dylib);
145dylib.symtab.nsyms = num_symbols(symbols);
146dylib.symtab.stroff = sizeof(dylib) + dylib.symtab.nsyms * sizeof(struct nlist);
147dylib.symtab.strsize = string_size(symbols);
148dylib.symtab.cmdsize = sizeof(struct symtab_command);
149
150
151
152FILE* outfile = fopen(argv[argc-1], "w");
153fwrite(&dylib,sizeof(dylib)/* Sizeof header + module name */
154, 1, outfile);
155
156char* symtab = malloc(dylib.symtab.stroff + dylib.symtab.strsize - sizeof(dylib) + 1); // Add extra 1 for last symbol
157memset(symtab, 0, dylib.symtab.nsyms * sizeof(struct nlist) + dylib.symtab.strsize + 1);
158char* orig = symtab;
159
160//symtab += offset;
161
162
163while(symbols)
164{
165
166((struct nlist*)symtab)->n_un.n_strx = symbols->pos;
167((struct nlist*)symtab)->n_type = 0xF;// TODO: read from boot.sys
168((struct nlist*)symtab)->n_sect = 0;
169((struct nlist*)symtab)->n_desc = REFERENCE_FLAG_DEFINED;
170((struct nlist*)symtab)->n_value = (uint32_t)symbols->addr;
171symtab+= sizeof(struct nlist);
172
173strcpy(orig + dylib.symtab.stroff - sizeof(dylib) + symbols->pos, symbols->name);
174
175symbols = symbols->next;
176}
177
178fwrite(orig,
179dylib.symtab.stroff+// Sizeof symbol nlists
180dylib.symtab.strsize - sizeof(dylib) + 1// sizeof symbol strings
181, 1, outfile);
182
183
184fclose(outfile);
185
186exit(0);
187}
188
189int num_symbols(symbolList_t* list)
190{
191int retVal = 0;
192while(list)
193{
194retVal++;
195list = list->next;
196}
197return retVal;
198}
199
200int string_size(symbolList_t* list)
201{
202int retVal = 0;
203while(list)
204{
205retVal += strlen(list->name)+1;
206list = list->next;
207}
208return retVal;
209
210}
211
212void add_symbol(symbolList_t** list, char* name, uint32_t addr)
213{
214symbolList_t* entry = malloc(sizeof(symbolList_t));
215entry->next = (*list);
216
217if(*list) entry->pos = (*list)->pos + strlen((*list)->name) + 1;
218else entry->pos = 1;
219*list = entry;
220
221entry->addr = addr;
222entry->name = malloc(strlen(name)+1);
223strcpy(entry->name, name);
224}
225

Archive Download this file

Revision: 1285