/[gcl]/gcl/unixport/rsym_macosx.c
ViewVC logotype

Diff of /gcl/unixport/rsym_macosx.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1 by rlbk, Mon Sep 1 05:49:07 2003 UTC revision 1.2 by camm, Thu Sep 4 15:13:35 2003 UTC
# Line 0  Line 1 
1    /*
2        File rsym_macosx.c
3        
4        Build an executable rsym for Mac OS X (31 July 2003).
5        
6        Grab only the external symbols from a Mach-O object file, and put them
7        in a simple format. This information will be used for relocation.
8        
9        To compile in standalone mode:
10            gcc -DDEBUG -DSTANDALONE -I../h -o rsym_macosx rsym_macosx.c
11        
12        Aurelien Chanudet (aurelienDOTchanudetATm4xDOTorg)
13    */
14    
15    #include <mach-o/loader.h>
16    #include <mach-o/nlist.h>
17    
18    #include <mach/mach.h>
19    
20    #ifdef STANDALONE
21    #include <stdio.h>
22    #define SPECIAL_RSYM
23    #endif
24    
25    #include <fcntl.h>
26    #include <stdlib.h>
27    #include <unistd.h>
28    #include <sys/types.h>
29    #include <sys/stat.h>
30    
31    #define IN_RSYM 1
32    
33    /* #include "config.h" */
34    #include "ext_sym.h"
35    
36    void rsym_error (char *format, ...)
37    {
38        va_list ap;
39        
40        va_start (ap, format);
41        fprintf (stderr, "rsym: ");
42        vfprintf (stderr, format, ap);
43     /* fprintf (stderr, " (%s)", strerror(errno)); */
44        fprintf (stderr, "\n");
45        va_end (ap);
46        exit (1);
47    }
48    
49    int rsym_select_symbol(struct nlist *symbol)
50    {
51        if (symbol->n_type & N_STAB) {
52            return (FALSE);
53        }
54        if (symbol->n_sect == NO_SECT) {
55            return (FALSE);
56        }
57        return (symbol->n_type & N_EXT);
58    }
59    
60    void rsym_doit2 (struct nlist *symbols, unsigned long nsyms, char *outfile)
61    {
62        unsigned long i;
63        struct lsymbol_table tab;
64        FILE *symout;
65        
66        if (!(symout = fopen (outfile, "wb"))) {
67            rsym_error ("cannot open file for writing: %s", outfile);
68        }
69    
70        tab.n_symbols=0;
71        tab.tot_leng=0;
72        
73        fseek (symout, sizeof(tab), 0);
74        
75        for (i=0 ; i < nsyms ; i++)
76        {
77            int addr = (int) symbols[i].n_value;
78            char *name = symbols[i].n_un.n_name;
79            
80            if (name)
81            {
82                tab.n_symbols++;
83                fwrite (&addr, sizeof (int), 1, symout);
84                while (tab.tot_leng++, *name)
85                    putc (*name++, symout);
86                putc (0, symout);
87            }
88            else {
89                fprintf (stderr, "warning: malformed symbol\n");
90            }
91        }
92        
93      #ifdef DEBUG
94        fprintf (stderr, "%d/%d symbol(s) reviewed\n", tab.n_symbols, nsyms);
95      #endif
96        
97        fseek (symout, 0, 0);
98        fwrite (&tab, sizeof(tab), 1, symout);
99        
100        fclose (symout);
101    }
102    
103    void rsym_doit1 (char *infile, char *outfile)
104    {
105        struct stat stat_buf;
106        struct mach_header *mh;
107        struct load_command *lc;
108        struct symtab_command *st;
109        struct dysymtab_command *dyst;
110        unsigned long nsyms, i, size;
111        unsigned long strsize;
112        struct nlist *symtab, *selected_symbols;
113        kern_return_t r;
114        char *strtab;
115        vm_size_t s;
116        char *addr;
117        int fd;
118        
119        if ((fd = open (infile, O_RDONLY, 0)) < 0) {
120            rsym_error ("cannot open input file: %s", infile);
121        }
122        
123        if (fstat (fd, &stat_buf) == -1) {
124            rsym_error ("cannot fstat file: %s", infile);
125        }
126        
127        size = stat_buf.st_size;
128        
129        if ((r = map_fd (fd, (vm_offset_t) 0, (vm_offset_t *) &addr,
130                (boolean_t) TRUE, (vm_size_t) size)) != KERN_SUCCESS) {
131            rsym_error ("cannot map file in memory: %s", infile);
132        }
133        
134        mh = (struct mach_header *) addr;
135        lc = (struct load_command *) ((char *) addr + sizeof(struct mach_header));
136        
137        for (i=0 ; i < mh->ncmds ; i++) {
138            if (lc->cmd == LC_SYMTAB) {
139                st = (struct symtab_command *) lc;
140            }
141            else if (lc->cmd == LC_DYSYMTAB) {
142                dyst = (struct dysymtab_command *) lc;
143            }
144            lc = (struct load_command *) ((char *) lc + lc->cmdsize);
145        }
146        
147        symtab = (struct nlist *) ((char *) addr + st->symoff);
148        
149        s = sizeof(struct nlist) * st->nsyms;
150        if (vm_allocate (mach_task_self (), (vm_address_t *) &selected_symbols, s, 1) != KERN_SUCCESS) {
151            rsym_error ("could not vm_allocate");
152        }
153        
154        nsyms = 0;
155        
156        for (i = 0 ; i < st->nsyms ; i++) {
157            if (rsym_select_symbol (symtab + i))
158                selected_symbols[nsyms++] = symtab[i];
159        }
160        
161        strtab = addr + st->stroff;
162        strsize = st->strsize;
163        
164        for (i = 0 ; i < nsyms ; i++) {
165            if (selected_symbols[i].n_un.n_strx == 0)
166                selected_symbols[i].n_un.n_name = "";
167            else if (selected_symbols[i].n_un.n_strx < 0 ||
168                    selected_symbols[i].n_un.n_strx > strsize)
169                selected_symbols[i].n_un.n_name = "bad string index";
170            else
171                selected_symbols[i].n_un.n_name = selected_symbols[i].n_un.n_strx + strtab;
172            
173          #if DEBUG
174            fprintf (stderr, "debug: %8x %s\n", (unsigned int) selected_symbols[i].n_value,
175                selected_symbols[i].n_un.n_name);
176          #endif
177        }
178        
179        rsym_doit2 (selected_symbols, nsyms, outfile);
180        
181        if (vm_deallocate (mach_task_self (), (vm_address_t) selected_symbols, s) != KERN_SUCCESS) {
182            fprintf (stderr, "warning: failed to free memory\n");
183        }
184        
185        if (vm_deallocate (mach_task_self (), (vm_address_t) addr, (vm_size_t) size) != KERN_SUCCESS) {
186            fprintf (stderr, "warning: failed to deallocate mapped file\n");
187        }
188            
189        close (fd);
190    }
191    
192    int main (int argc, char **argv, char **envp)
193    {
194        if (argc != 3) {
195            fprintf (stderr, "usage: rsym <infile> <outfile>\n");
196            exit (1);
197        }
198        
199        rsym_doit1 (argv[1], argv[2]);
200        
201        return 0;
202    }

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.2

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26