Network: Move common utilities to the common area
[AROS.git] / tools / collect-aros / collect-aros.c
blob1c96693c46f33a7d5062f4964f866395595e76da
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <errno.h>
5 #include <fcntl.h>
6 #include <unistd.h>
7 #include <sys/stat.h>
9 #include "env.h"
10 #include "misc.h"
11 #include "docommand.h"
12 #include "backend.h"
13 #include "ldscript.h"
14 #include "gensets.h"
16 #define EXTRA_ARG_CNT 2
18 #define EI_OSABI 7
19 #define EI_ABIVERSION 8
21 #define ELFOSABI_AROS 15
24 static char *ldscriptname, *tempoutput, *ld_name, *strip_name;
25 static FILE *ldscriptfile;
27 static void exitfunc(void)
29 if (ldscriptfile != NULL)
30 fclose(ldscriptfile);
32 if (ldscriptname != NULL)
33 remove(ldscriptname);
35 if (tempoutput != NULL)
36 remove(tempoutput);
39 static int set_os_and_abi(const char *file)
41 int f;
42 const unsigned char osabi = ELFOSABI_AROS;
43 const unsigned char abiversion = 1;
45 /* Modify OS and ABI fields */
47 f = open(file, O_RDWR);
48 if (f >= 0) {
49 lseek(f, EI_OSABI, SEEK_SET);
50 if (write(f, &osabi, 1) == 1) {
51 lseek(f, EI_ABIVERSION, SEEK_SET);
52 if (write(f, &abiversion, 1) == 1) {
53 close(f);
54 return 1;
59 perror(file);
60 if (f >= 0)
61 close(f);
62 return 0;
65 int main(int argc, char *argv[])
67 int cnt, i;
68 char *output, **ldargs;
69 /* incremental = 1 -> don't do final linking.
70 incremental = 2 -> don't do final linking AND STILL produce symbol sets. */
71 int incremental = 0, ignore_undefined_symbols = 0;
72 int strip_all = 0;
73 char *do_verbose = NULL;
75 setnode *setlist = NULL, *liblist = NULL;
77 program_name = argv[0];
78 ld_name = LD_NAME;
79 strip_name = STRIP_NAME;
81 /* Do some stuff with the arguments */
82 output = "a.out";
83 for (cnt = 1; argv[cnt]; cnt++)
85 /* We've encountered an option */
86 if (argv[cnt][0]=='-')
88 /* Get the output file name */
89 if (argv[cnt][1]=='o')
90 output = argv[cnt][2]?&argv[cnt][2]:argv[++cnt];
91 else
92 /* Incremental linking is requested */
93 if ((argv[cnt][1]=='r' || argv[cnt][1]=='i') && argv[cnt][2]=='\0')
94 incremental = 1;
95 else
96 /* Incremental, but produce the symbol sets */
97 if (strncmp(&argv[cnt][1], "Ur", 3) == 0)
99 incremental = 2;
101 argv[cnt][1] = 'r'; /* Just some non-harming option... */
102 argv[cnt][2] = '\0';
104 else
105 /* Ignoring of missing symbols is requested */
106 if (strncmp(&argv[cnt][1], "ius", 4) == 0)
108 ignore_undefined_symbols = 1;
109 argv[cnt][1] = 'r'; /* Just some non-harming option... */
110 argv[cnt][2] = '\0';
112 else
113 /* Complete stripping is requested, but we do it our own way */
114 if (argv[cnt][1]=='s' && argv[cnt][2]=='\0')
116 strip_all = 1;
117 argv[cnt][1] = 'r'; /* Just some non-harming option... */
119 else
120 /* The user just requested help info, don't do anything else */
121 if (strncmp(&argv[cnt][1], "-help", 6) == 0)
123 /* I know, it's not incremental linking we're after, but the end result
124 is the same */
125 incremental = 1;
126 break;
128 else
129 /* verbose output */
130 if (strncmp(&argv[cnt][1], "-verbose", 9) == 0)
132 do_verbose = argv[cnt];
133 break;
138 ldargs = xmalloc(sizeof(char *) * (argc + EXTRA_ARG_CNT
139 + ((incremental == 1) ? 0 : 2) + 1));
141 ldargs[0] = ld_name;
142 ldargs[1] = OBJECT_FORMAT;
143 ldargs[2] = "-r";
145 for (i = 1; i < argc; i++)
146 ldargs[i + EXTRA_ARG_CNT] = argv[i];
147 cnt = argc + EXTRA_ARG_CNT;
149 if (incremental != 1)
151 atexit(exitfunc);
154 !(tempoutput = make_temp_file(NULL)) ||
155 !(ldscriptname = make_temp_file(NULL)) ||
156 !(ldscriptfile = fopen(ldscriptname, "w"))
159 fatal(ldscriptname ? ldscriptname : "make_temp_file()", strerror(errno));
162 ldargs[cnt++] = "-o";
163 ldargs[cnt++] = tempoutput;
166 ldargs[cnt] = NULL;
168 docommandvp(ld_name, ldargs);
170 if (incremental == 1)
171 return set_os_and_abi(output) ? EXIT_SUCCESS : EXIT_FAILURE;
173 collect_libs(tempoutput, &liblist);
174 collect_sets(tempoutput, &setlist);
176 if (setlist) {
177 struct setnode *n;
178 for (n = setlist; n; n = n->next) {
179 if (strncmp(n->secname,".aros.set.",10) == 0) {
180 fprintf(ldscriptfile, "EXTERN(__%s__symbol_set_handler_missing)\n", &n->secname[10]);
185 fwrite(LDSCRIPT_PART1, sizeof(LDSCRIPT_PART1) - 1, 1, ldscriptfile);
186 emit_sets(setlist, ldscriptfile);
187 emit_libs(liblist, ldscriptfile);
188 fwrite(LDSCRIPT_PART2, sizeof(LDSCRIPT_PART2) - 1, 1, ldscriptfile);
189 /* Append .eh_frame terminator only on final stage */
190 if (incremental == 0)
191 fputs("LONG(0)\n", ldscriptfile);
192 fwrite(LDSCRIPT_PART3, sizeof(LDSCRIPT_PART3) - 1, 1, ldscriptfile);
193 fwrite(LDSCRIPT_PART4, sizeof(LDSCRIPT_PART4) - 1, 1, ldscriptfile);
195 fclose(ldscriptfile);
196 ldscriptfile = NULL;
198 docommandlp(ld_name, ld_name, OBJECT_FORMAT, "-r", "-o", output,
199 tempoutput, "-T", ldscriptname, do_verbose, NULL);
201 if (incremental != 0)
202 return set_os_and_abi(output) ? EXIT_SUCCESS : EXIT_FAILURE;
204 if (!ignore_undefined_symbols && check_and_print_undefined_symbols(output))
206 remove(output);
207 return EXIT_FAILURE;
210 chmod(output, 0766);
212 if (strip_all)
214 docommandlp(strip_name, strip_name, "--strip-unneeded", output, NULL);
217 if (!set_os_and_abi(output))
219 remove(output);
220 return EXIT_FAILURE;
223 return 0;