1 /* ld.c - linker for Introl format (6809 C) object files 6809/8086/80386 */
2
3 /* Copyright (C) 1994 Bruce Evans */
4
5 #include "syshead.h"
6 #include "const.h"
7 #include "byteord.h"
8 #include "type.h"
9 #include "globvar.h"
10
11 #define MAX_LIBS (NR_STDLIBS + 5)
12 #ifdef MC6809
13 #define NR_STDLIBS 1
14 #else
15 #define NR_STDLIBS 0
16 #endif
17
18 PUBLIC bin_off_t text_base_value = 0; /* XXX */
19 PUBLIC bin_off_t data_base_value = 0; /* XXX */
20 PUBLIC bin_off_t heap_top_value = 0; /* XXX */
21 PUBLIC int headerless = 0;
22 #ifndef VERY_SMALL_MEMORY
23 PUBLIC int v7 = 0;
24 #endif
25 #ifndef MSDOS
26 PUBLIC int cpm86 = 0;
27 #endif
28 PUBLIC char hexdigit[] = "0123456789abcdef";
29
30 PRIVATE bool_t flag[128];
31 PRIVATE char *libs[MAX_LIBS] = {
32 #ifdef MC6809
33 "/usr/local/lib/m09/",
34 #endif
35 0
36 };
37 PRIVATE int lastlib = NR_STDLIBS;
38
39 FORWARD char *buildname P((char *pre, char *mid, char *suf));
40 FORWARD char *expandlib P((char *fn));
41
buildname(pre,mid,suf)42 PRIVATE char *buildname(pre, mid, suf)
43 char *pre;
44 char *mid;
45 char *suf;
46 {
47 char *name;
48
49 name = ourmalloc(strlen(pre) + strlen(mid) + strlen(suf) + 1);
50 strcpy(name, pre);
51 strcat(name, mid);
52 strcat(name, suf);
53 return name;
54 }
55
expandlib(fn)56 PRIVATE char *expandlib(fn)
57 char *fn;
58 {
59 char *path, *s;
60 int i;
61
62 for (i = lastlib - 1; i >= 0; --i)
63 {
64 path = ourmalloc(strlen(libs[i]) + strlen(fn) + 2);
65 strcpy(path, libs[i]);
66 s = path + strlen(path);
67 if (s!=path && s[-1] != '/') strcat(path, "/");
68 strcat(path, fn);
69 if (access(path, R_OK) == 0)
70 return path;
71 ourfree(path);
72 }
73 return NUL_PTR;
74 }
75
main(argc,argv)76 PUBLIC int main(argc, argv)
77 int argc;
78 char **argv;
79 {
80 register char *arg;
81 int argn;
82 static char crtprefix[] = "crt";
83 static char crtsuffix[] = ".o";
84 char *infilename;
85 static char libprefix[] = "lib";
86 static char libsuffix[] = ".a";
87 char *outfilename;
88 char *tfn;
89 int icount=0;
90
91 ioinit(argv[0]);
92 objinit();
93 syminit();
94 typeconv_init(INT_BIG_ENDIAN, LONG_BIG_ENDIAN);
95 #ifndef MC6809
96 flag['3'] = sizeof(char *) >= 4;
97 #endif
98 outfilename = NUL_PTR;
99 for (argn = 1; argn < argc; ++argn)
100 {
101 arg = argv[argn];
102 if (*arg != '-')
103 {
104 readsyms(arg, flag['t']);
105 icount++;
106 }
107 else
108 switch (arg[1])
109 {
110 case 'v':
111 version_msg();
112 case 'r': /* relocatable output */
113 case 't': /* trace modules linked */
114 if (icount > 0) usage();
115 #ifdef REL_OUTPUT
116 case 'B': /* Broken -r for dosemu. */
117 #endif
118 case '0': /* use 16-bit libraries */
119 case '3': /* use 32-bit libraries */
120 case 'M': /* print symbols linked */
121 case 'i': /* separate I & D output */
122 case 'm': /* print modules linked */
123 case 's': /* strip symbols */
124 case 'z': /* unmapped zero page */
125 case 'N': /* Native format a.out */
126 case 'd': /* Make a headerless outfile */
127 #ifndef MSDOS
128 case 'c': /* Write header in CP/M-86 format */
129 #endif
130 case 'y': /* Use a newer symbol table */
131 #ifndef VERY_SMALL_MEMORY
132 case '7': /* Produce a UNIX v7 a.out header */
133 #endif
134 if (arg[2] == 0)
135 flag[(int) arg[1]] = TRUE;
136 else if (arg[2] == '-' && arg[3] == 0)
137 flag[(int) arg[1]] = FALSE;
138 else
139 usage();
140 if (arg[1] == '0') /* flag 0 is negative logic flag 3 */
141 flag['3'] = !flag['0'];
142 break;
143 case 'C': /* startfile name */
144 tfn = buildname(crtprefix, arg + 2, crtsuffix);
145 if ((infilename = expandlib(tfn)) == NUL_PTR)
146 infilename = tfn;
147 /*fatalerror(tfn); * XXX - need to describe failure */
148 readsyms(infilename, flag['t']);
149 icount++;
150 break;
151 case 'L': /* library path */
152 if (lastlib < MAX_LIBS)
153 libs[lastlib++] = arg + 2;
154 else
155 fatalerror("too many library paths");
156 break;
157 case 'O': /* library file name */
158 if ((infilename = expandlib(arg + 2)) == NUL_PTR)
159 infilename = arg+2;
160 /* fatalerror(arg); * XXX */
161 readsyms(infilename, flag['t']);
162 break;
163 case 'T': /* text base address */
164 if (arg[2] == 0 && ++argn >= argc)
165 usage();
166 errno = 0;
167 if (arg[2] == 0 )
168 text_base_value = strtoul(argv[argn], (char **)0, 16);
169 else
170 text_base_value = strtoul(arg+2, (char **)0, 16);
171 if (errno != 0)
172 use_error("invalid text address");
173 break;
174 case 'D': /* data base address */
175 if (arg[2] == 0 && ++argn >= argc)
176 usage();
177 errno = 0;
178 if (arg[2] == 0 )
179 data_base_value = strtoul(argv[argn], (char **)0, 16);
180 else
181 data_base_value = strtoul(arg+2, (char **)0, 16);
182 if (errno != 0)
183 use_error("invalid data address");
184 break;
185 case 'H': /* heap top address */
186 if (arg[2] == 0 && ++argn >= argc)
187 usage();
188 errno = 0;
189 if (arg[2] == 0 )
190 heap_top_value = strtoul(argv[argn], (char **)0, 16);
191 else
192 heap_top_value = strtoul(arg+2, (char **)0, 16);
193 if (errno != 0)
194 use_error("invalid heap top");
195 break;
196 case 'l': /* library name */
197 tfn = buildname(libprefix, arg + 2, libsuffix);
198 if ((infilename = expandlib(tfn)) == NUL_PTR)
199 infilename = tfn;
200 /* fatalerror(tfn); * XXX */
201 readsyms(infilename, flag['t']);
202 icount+=2;
203 break;
204 case 'o': /* output file name */
205 if (arg[2] != 0 || ++argn >= argc || outfilename != NUL_PTR)
206 usage();
207 outfilename = argv[argn];
208 break;
209 default:
210 usage();
211 }
212 }
213 if(icount==0) usage();
214
215 #ifdef BUGCOMPAT
216 if( icount==1 && ( flag['r'] && !flag['N'] ) ) {
217 flag['r'] = 0;
218 flag['B'] = 1;
219 }
220 #endif
221
222 #ifdef REL_OUTPUT
223 #ifndef MSDOS
224 if( flag['r'] && !flag['N'] )
225 {
226 /* Do a relocatable link -- actually fake it with 'ar.c' */
227 ld86r(argc, argv);
228 }
229 #endif
230 #endif
231
232 #ifdef MSDOS
233 /* MSDOS Native is special, we make a COM file */
234 if( flag['N'] )
235 {
236 flag['N'] = 0;
237 flag['d'] = 1;
238 text_base_value = 0x100;
239 }
240 #endif
241
242 /* Headerless executables can't use symbols. */
243 headerless = flag['d'];
244 if( headerless ) flag['s'] = 1;
245
246 #ifndef VERY_SMALL_MEMORY
247 /* UNIX seventh edition executables */
248 v7 = flag['7'];
249 #endif
250
251 #ifndef MSDOS
252 /* CP/M-86 executables can't use symbols. */
253 cpm86 = flag['c'];
254 if ( cpm86 ) flag['s'] = 1;
255 #endif
256
257 linksyms(flag['r'] | flag['B']);
258 if (outfilename == NUL_PTR)
259 outfilename = "a.out";
260 #ifndef MSDOS
261 if( flag['N'] )
262 writebin(outfilename, flag['i'], flag['3'], flag['s'],
263 flag['z'] & flag['3']);
264 else
265 #endif
266 if( flag['B'] )
267 write_dosemu(outfilename, flag['i'], flag['3'], flag['s'],
268 flag['z'] & flag['3']);
269 else
270 write_elks(outfilename, flag['i'], flag['3'], flag['s'],
271 flag['z'], flag['y']);
272 if (flag['m'])
273 dumpmods();
274 if (flag['M'])
275 dumpsyms();
276 flusherr();
277 return errcount ? 1 : 0;
278 }
279