Listtree.mcc: update version and date
[AROS.git] / tools / collect-aros / collect-aros.c
blob0b8bf2264296131a5ed242dc9f6a9dfc97429f5d
1 /*
2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <stdio.h>
7 #include <string.h>
8 #include <stdlib.h>
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <unistd.h>
12 #include <sys/stat.h>
14 #include "env.h"
15 #include "misc.h"
16 #include "docommand.h"
17 #include "backend.h"
18 #include "ldscript.h"
19 #include "gensets.h"
21 #define EXTRA_ARG_CNT 2
23 #define EI_OSABI 7
24 #define EI_ABIVERSION 8
26 #define ELFOSABI_AROS 15
29 static char *ldscriptname, *tempoutput, *ld_name, *strip_name;
30 static FILE *ldscriptfile;
32 static void exitfunc(void)
34 if (ldscriptfile != NULL)
35 fclose(ldscriptfile);
37 if (ldscriptname != NULL)
38 remove(ldscriptname);
40 if (tempoutput != NULL)
41 remove(tempoutput);
44 static int set_os_and_abi(const char *file)
46 int f;
47 const unsigned char osabi = ELFOSABI_AROS;
48 const unsigned char abiversion = 1;
50 /* Modify OS and ABI fields */
52 f = open(file, O_RDWR);
53 if (f >= 0) {
54 lseek(f, EI_OSABI, SEEK_SET);
55 if (write(f, &osabi, 1) == 1) {
56 lseek(f, EI_ABIVERSION, SEEK_SET);
57 if (write(f, &abiversion, 1) == 1) {
58 close(f);
59 return 1;
64 perror(file);
65 if (f >= 0)
66 close(f);
67 return 0;
70 int main(int argc, char *argv[])
72 int cnt, i;
73 char *output, **ldargs;
74 /* incremental = 1 -> don't do final linking.
75 incremental = 2 -> don't do final linking AND STILL produce symbol sets. */
76 int incremental = 0, ignore_undefined_symbols = 0;
77 int strip_all = 0;
78 char *do_verbose = NULL;
80 setnode *setlist = NULL, *liblist = NULL;
82 program_name = argv[0];
83 ld_name = LD_NAME;
84 strip_name = STRIP_NAME;
86 /* Do some stuff with the arguments */
87 output = "a.out";
88 for (cnt = 1; argv[cnt]; cnt++)
90 /* We've encountered an option */
91 if (argv[cnt][0]=='-')
93 /* Get the output file name */
94 if (argv[cnt][1]=='o')
95 output = argv[cnt][2]?&argv[cnt][2]:argv[++cnt];
96 else
97 /* Incremental linking is requested */
98 if ((argv[cnt][1]=='r' || argv[cnt][1]=='i') && argv[cnt][2]=='\0')
99 incremental = 1;
100 else
101 /* Incremental, but produce the symbol sets */
102 if (strncmp(&argv[cnt][1], "Ur", 3) == 0)
104 incremental = 2;
106 argv[cnt][1] = 'r'; /* Just some non-harming option... */
107 argv[cnt][2] = '\0';
109 else
110 /* Ignoring of missing symbols is requested */
111 if (strncmp(&argv[cnt][1], "ius", 4) == 0)
113 ignore_undefined_symbols = 1;
114 argv[cnt][1] = 'r'; /* Just some non-harming option... */
115 argv[cnt][2] = '\0';
117 else
118 /* Complete stripping is requested, but we do it our own way */
119 if (argv[cnt][1]=='s' && argv[cnt][2]=='\0')
121 strip_all = 1;
122 argv[cnt][1] = 'r'; /* Just some non-harming option... */
124 else
125 /* The user just requested help info, don't do anything else */
126 if (strncmp(&argv[cnt][1], "-help", 6) == 0)
128 /* I know, it's not incremental linking we're after, but the end result
129 is the same */
130 incremental = 1;
131 break;
133 else
134 /* verbose output */
135 if (strncmp(&argv[cnt][1], "-verbose", 9) == 0)
137 do_verbose = argv[cnt];
138 break;
143 ldargs = xmalloc(sizeof(char *) * (argc + EXTRA_ARG_CNT
144 + ((incremental == 1) ? 0 : 2) + 1));
146 ldargs[0] = ld_name;
147 ldargs[1] = OBJECT_FORMAT;
148 ldargs[2] = "-r";
150 for (i = 1; i < argc; i++)
151 ldargs[i + EXTRA_ARG_CNT] = argv[i];
152 cnt = argc + EXTRA_ARG_CNT;
154 if (incremental != 1)
156 atexit(exitfunc);
159 !(tempoutput = make_temp_file(NULL)) ||
160 !(ldscriptname = make_temp_file(NULL)) ||
161 !(ldscriptfile = fopen(ldscriptname, "w"))
164 fatal(ldscriptname ? ldscriptname : "make_temp_file()", strerror(errno));
167 ldargs[cnt++] = "-o";
168 ldargs[cnt++] = tempoutput;
171 ldargs[cnt] = NULL;
173 docommandvp(ld_name, ldargs);
175 if (incremental == 1)
176 return set_os_and_abi(output) ? EXIT_SUCCESS : EXIT_FAILURE;
178 collect_libs(tempoutput, &liblist);
179 collect_sets(tempoutput, &setlist);
181 if (setlist) {
182 struct setnode *n;
183 for (n = setlist; n; n = n->next) {
184 if (strncmp(n->secname,".aros.set.",10) == 0) {
185 fprintf(ldscriptfile, "EXTERN(__%s__symbol_set_handler_missing)\n", &n->secname[10]);
190 fwrite(LDSCRIPT_PART1, sizeof(LDSCRIPT_PART1) - 1, 1, ldscriptfile);
191 emit_sets(setlist, ldscriptfile);
192 emit_libs(liblist, ldscriptfile);
193 fwrite(LDSCRIPT_PART2, sizeof(LDSCRIPT_PART2) - 1, 1, ldscriptfile);
194 /* Append .eh_frame terminator only on final stage */
195 if (incremental == 0)
196 fputs("LONG(0)\n", ldscriptfile);
197 fwrite(LDSCRIPT_PART3, sizeof(LDSCRIPT_PART3) - 1, 1, ldscriptfile);
198 fwrite(LDSCRIPT_PART4, sizeof(LDSCRIPT_PART4) - 1, 1, ldscriptfile);
200 fclose(ldscriptfile);
201 ldscriptfile = NULL;
203 docommandlp(ld_name, ld_name, OBJECT_FORMAT, "-r", "-o", output,
204 tempoutput, "-T", ldscriptname, do_verbose, NULL);
206 if (incremental != 0)
207 return set_os_and_abi(output) ? EXIT_SUCCESS : EXIT_FAILURE;
209 if (!ignore_undefined_symbols && check_and_print_undefined_symbols(output))
211 remove(output);
212 return EXIT_FAILURE;
215 chmod(output, 0766);
217 if (strip_all)
219 docommandlp(strip_name, strip_name, "--strip-unneeded", output, NULL);
222 if (!set_os_and_abi(output))
224 remove(output);
225 return EXIT_FAILURE;
228 return 0;