]> asedeno.scripts.mit.edu Git - peal.git/blob - postlink/postlinker.cc
Greg Parker's Palm Elf Arm Loader (PEAL)
[peal.git] / postlink / postlinker.cc
1 /**********
2  * Copyright (c) 2004-2005 Greg Parker.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY GREG PARKER ``AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  **********/
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <stdint.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <sys/uio.h>
31 #include <unistd.h>
32 #include <fcntl.h>
33 #include <stdarg.h>
34 #include <string.h>
35
36 #include "elf.h"
37
38 #include <map>
39 #include <string>
40 #include <vector>
41 #include <algorithm>
42
43 using namespace std;
44
45 #include "got.h"
46 #include "swap.h"
47 #include "image.h"
48 #include "symbol.h"
49 #include "section.h"
50 #include "postlinker.h"
51 #include "symboltable.h"
52 #include "stringtable.h"
53
54 #ifndef O_BINARY
55 #define O_BINARY 0
56 #endif
57
58 #define Version "2005-4-14"
59 #define Copyright  \
60 "Copyright (c) 2004-2005 Greg Parker\n" \
61 "Copyright (c) 2001 David E. O'Brien\n" \
62 "Copyright (c) 1996-1998 John D. Polstra\n" \
63 "All rights reserved.\n" \
64 "\n" \
65 "Redistribution and use in source and binary forms, with or without\n" \
66 "modification, are permitted provided that the following conditions\n" \
67 "are met:\n" \
68 "1. Redistributions of source code must retain the above copyright\n" \
69 "   notice, this list of conditions and the following disclaimer.\n" \
70 "2. Redistributions in binary form must reproduce the above copyright\n" \
71 "   notice, this list of conditions and the following disclaimer in the\n" \
72 "   documentation and/or other materials provided with the distribution.\n" \
73 "\n" \
74 "THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\n" \
75 "ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n" \
76 "IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n"\
77 "ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n" \
78 "FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n"\
79 "DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n" \
80 "OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n" \
81 "HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n"\
82 "LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n" \
83 "OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n" \
84 "SUCH DAMAGE.\n"
85
86 int Verbose = 0;
87
88
89 static void version(void)
90 {
91     fprintf(stderr, "peal-postlink version %s\n\n", Version);
92     fprintf(stderr, "%s\n", Copyright);
93 }
94
95
96 static void usage(const char *name)
97 {
98     fprintf(stderr, 
99             "Usage: %s [-vV] [-K filename] [-t resType] [-s resID] [-o output] filename\n"
100             "   -V: print version info\n"
101             "   -v: verbose\n"
102             "   -K <filename>: only keep global symbols listed in file 'filename'\n"
103             "   -t <resType>: set resource type for -s (default is 'armc')\n"
104             "   -o <output>: write result to file 'output'\n"
105             "   -s <resID>: write result in .ro format with one resource per ELF section\n"
106             "            (default is .bin format with everything in one resource)\n"
107             , name);
108     exit(1);
109 }
110
111 int main(int argc, char **argv)
112 {
113     int fd;
114     int err;
115     struct stat sb;
116     int ch;
117     const char *infilename;
118     const char *outfilename = NULL;
119     const char *keepfilename = NULL;
120     const char *selfname;
121     vector<string> *keepSymbols = NULL;
122     int printversion = 0;
123     int splitindex = -1;
124     const char *resType = "armc";
125
126     // Parse options 
127     Verbose = 0;
128     selfname = strrchr(argv[0], '/');
129     if (!selfname) selfname = argv[0];
130
131     while ((ch = getopt(argc, argv, "vVK:o:s:t:")) != -1) {
132         switch (ch) {
133         case 'V': 
134             printversion = 1;
135             break;
136
137         case 'v':
138             Verbose = 1;
139             break;
140
141         case 'K':
142             if (keepfilename) {
143                 fprintf(stderr, "%s: -K may be used only once\n", selfname);
144                 usage(selfname);
145             } else {
146                 keepfilename = optarg;
147             }
148             break;
149
150         case 'o':
151             if (outfilename) {
152                 fprintf(stderr, "%s: -o may be used only once\n", selfname);
153                 usage(selfname);
154             } else {
155                 outfilename = optarg;
156             }
157             break;
158
159         case 's':
160             if (splitindex != -1) {
161                 fprintf(stderr, "%s: -s may be used only once\n", selfname);
162                 usage(selfname);
163             } else {
164                 splitindex = atoi(optarg);
165             }
166             break;
167
168         case 't':
169             resType = optarg;
170             if (strlen(resType) != 4) {
171                 fprintf(stderr, "%s: -t resource type must be exactly four characters long\n", selfname);
172                 usage(selfname);
173             }
174             break;
175
176         case '?':
177         default:
178             usage(selfname);
179             break;
180         }
181     }
182     
183     argc -= optind;
184     argv += optind;
185
186     if (printversion) {
187         version();
188     }
189
190     if (argc == 0) {
191         fprintf(stderr, "%s: no file specified\n", selfname);
192         usage(selfname);
193     }
194
195     infilename = argv[argc-1];
196     if (!outfilename) outfilename = infilename;
197
198
199     // Read keepfile, if any
200     if (keepfilename) {
201         FILE *keepfile = fopen(keepfilename, "r");
202         if (!keepfile) { perror(keepfilename); return 1; }
203         keepSymbols = new vector<string>(0);
204         char buf[1024];
205         char *keep;
206         size_t len;
207         while ((keep = fgets(buf, sizeof(buf), keepfile))) {
208             char *end = strstr(keep, "\n");
209             if (end) len = end - keep;  // skip newline, if any
210             else len = strlen(keep);
211             keepSymbols->push_back(string(keep, len));
212         }
213     }
214
215
216     // Read file into memory
217
218     fd = open(infilename, O_RDONLY | O_BINARY, 0);
219     if (fd < 0) { perror(infilename); return 1; }
220
221     err = fstat(fd, &sb);
222     if (err) { perror(infilename); return 1; }
223
224     uint8_t *buf = (uint8_t *)malloc(sb.st_size);
225     if (sb.st_size != read(fd, buf, sb.st_size)) { 
226         perror(infilename); return 1;
227     }
228     close(fd);
229
230
231     // Read the ELF image, undo relocations, and record new relocations.
232
233     Image image(buf);
234
235
236     // Scrub the symbol table. 
237     // - keep all global symbols
238     // - keep a symbol for data and text sections
239     // - fixme apply export list here
240     
241     image.symtab().strip(keepSymbols);
242     image.trimSections();  // removes all string tables
243     image.addSectionGlobals();
244     image.buildSymbolStringTable();
245     image.buildRelocations();
246     image.buildSectionStringTable();
247
248     image.write(resType, splitindex, outfilename);
249
250     // fixme paranoia checks:
251     // all ro+alloc+contents sections contiguous (in file and vm)
252     // no ro+alloc-contents sections
253     // all rw+alloc sections coniguous (in file and vm)
254
255     return 0;
256 }