123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- /* ld.c - linker for Introl format (6809 C) object files 6809/8086/80386 */
- /* Copyright (C) 1994 Bruce Evans */
- #include "syshead.h"
- #include "const.h"
- #include "byteord.h"
- #include "type.h"
- #include "globvar.h"
- #define MAX_LIBS (NR_STDLIBS + 5)
- #ifdef MC6809
- #define NR_STDLIBS 1
- #else
- #define NR_STDLIBS 0
- #endif
- PUBLIC bin_off_t text_base_value = 0; /* XXX */
- PUBLIC bin_off_t data_base_value = 0; /* XXX */
- PUBLIC bin_off_t heap_top_value = 0; /* XXX */
- PUBLIC int headerless = 0;
- #ifndef VERY_SMALL_MEMORY
- PUBLIC int v7 = 0;
- #endif
- #ifndef MSDOS
- PUBLIC int cpm86 = 0;
- #endif
- PUBLIC char hexdigit[] = "0123456789abcdef";
- PRIVATE bool_t flag[128];
- PRIVATE char *libs[MAX_LIBS] = {
- #ifdef MC6809
- "/usr/local/lib/m09/",
- #endif
- 0
- };
- PRIVATE int lastlib = NR_STDLIBS;
- FORWARD char *buildname P((char *pre, char *mid, char *suf));
- FORWARD char *expandlib P((char *fn));
- PRIVATE char *buildname(pre, mid, suf)
- char *pre;
- char *mid;
- char *suf;
- {
- char *name;
- name = ourmalloc(strlen(pre) + strlen(mid) + strlen(suf) + 1);
- strcpy(name, pre);
- strcat(name, mid);
- strcat(name, suf);
- return name;
- }
- PRIVATE char *expandlib(fn)
- char *fn;
- {
- char *path, *s;
- int i;
- for (i = lastlib - 1; i >= 0; --i)
- {
- path = ourmalloc(strlen(libs[i]) + strlen(fn) + 2);
- strcpy(path, libs[i]);
- s = path + strlen(path);
- if (s!=path && s[-1] != '/') strcat(path, "/");
- strcat(path, fn);
- if (access(path, R_OK) == 0)
- return path;
- ourfree(path);
- }
- return NUL_PTR;
- }
- PUBLIC int main(argc, argv)
- int argc;
- char **argv;
- {
- register char *arg;
- int argn;
- static char crtprefix[] = "crt";
- static char crtsuffix[] = ".o";
- char *infilename;
- static char libprefix[] = "lib";
- static char libsuffix[] = ".a";
- char *outfilename;
- char *tfn;
- int icount=0;
- ioinit(argv[0]);
- objinit();
- syminit();
- typeconv_init(INT_BIG_ENDIAN, LONG_BIG_ENDIAN);
- #ifndef MC6809
- flag['3'] = sizeof(char *) >= 4;
- #endif
- outfilename = NUL_PTR;
- for (argn = 1; argn < argc; ++argn)
- {
- arg = argv[argn];
- if (*arg != '-')
- {
- readsyms(arg, flag['t']);
- icount++;
- }
- else
- switch (arg[1])
- {
- case 'v':
- version_msg();
- case 'r': /* relocatable output */
- case 't': /* trace modules linked */
- if (icount > 0) usage();
- #ifdef REL_OUTPUT
- case 'B': /* Broken -r for dosemu. */
- #endif
- case '0': /* use 16-bit libraries */
- case '3': /* use 32-bit libraries */
- case 'M': /* print symbols linked */
- case 'i': /* separate I & D output */
- case 'm': /* print modules linked */
- case 's': /* strip symbols */
- case 'z': /* unmapped zero page */
- case 'N': /* Native format a.out */
- case 'd': /* Make a headerless outfile */
- #ifndef MSDOS
- case 'c': /* Write header in CP/M-86 format */
- #endif
- case 'y': /* Use a newer symbol table */
- #ifndef VERY_SMALL_MEMORY
- case '7': /* Produce a UNIX v7 a.out header */
- #endif
- if (arg[2] == 0)
- flag[(int) arg[1]] = TRUE;
- else if (arg[2] == '-' && arg[3] == 0)
- flag[(int) arg[1]] = FALSE;
- else
- usage();
- if (arg[1] == '0') /* flag 0 is negative logic flag 3 */
- flag['3'] = !flag['0'];
- break;
- case 'C': /* startfile name */
- tfn = buildname(crtprefix, arg + 2, crtsuffix);
- if ((infilename = expandlib(tfn)) == NUL_PTR)
- infilename = tfn;
- /*fatalerror(tfn); * XXX - need to describe failure */
- readsyms(infilename, flag['t']);
- icount++;
- break;
- case 'L': /* library path */
- if (lastlib < MAX_LIBS)
- libs[lastlib++] = arg + 2;
- else
- fatalerror("too many library paths");
- break;
- case 'O': /* library file name */
- if ((infilename = expandlib(arg + 2)) == NUL_PTR)
- infilename = arg+2;
- /* fatalerror(arg); * XXX */
- readsyms(infilename, flag['t']);
- break;
- case 'T': /* text base address */
- if (arg[2] == 0 && ++argn >= argc)
- usage();
- errno = 0;
- if (arg[2] == 0 )
- text_base_value = strtoul(argv[argn], (char **)0, 16);
- else
- text_base_value = strtoul(arg+2, (char **)0, 16);
- if (errno != 0)
- use_error("invalid text address");
- break;
- case 'D': /* data base address */
- if (arg[2] == 0 && ++argn >= argc)
- usage();
- errno = 0;
- if (arg[2] == 0 )
- data_base_value = strtoul(argv[argn], (char **)0, 16);
- else
- data_base_value = strtoul(arg+2, (char **)0, 16);
- if (errno != 0)
- use_error("invalid data address");
- break;
- case 'H': /* heap top address */
- if (arg[2] == 0 && ++argn >= argc)
- usage();
- errno = 0;
- if (arg[2] == 0 )
- heap_top_value = strtoul(argv[argn], (char **)0, 16);
- else
- heap_top_value = strtoul(arg+2, (char **)0, 16);
- if (errno != 0)
- use_error("invalid heap top");
- break;
- case 'l': /* library name */
- tfn = buildname(libprefix, arg + 2, libsuffix);
- if ((infilename = expandlib(tfn)) == NUL_PTR)
- infilename = tfn;
- /* fatalerror(tfn); * XXX */
- readsyms(infilename, flag['t']);
- icount+=2;
- break;
- case 'o': /* output file name */
- if (arg[2] != 0 || ++argn >= argc || outfilename != NUL_PTR)
- usage();
- outfilename = argv[argn];
- break;
- default:
- usage();
- }
- }
- if(icount==0) usage();
- #ifdef BUGCOMPAT
- if( icount==1 && ( flag['r'] && !flag['N'] ) ) {
- flag['r'] = 0;
- flag['B'] = 1;
- }
- #endif
- #ifdef REL_OUTPUT
- #ifndef MSDOS
- if( flag['r'] && !flag['N'] )
- {
- /* Do a relocatable link -- actually fake it with 'ar.c' */
- ld86r(argc, argv);
- }
- #endif
- #endif
- #ifdef MSDOS
- /* MSDOS Native is special, we make a COM file */
- if( flag['N'] )
- {
- flag['N'] = 0;
- flag['d'] = 1;
- text_base_value = 0x100;
- }
- #endif
- /* Headerless executables can't use symbols. */
- headerless = flag['d'];
- if( headerless ) flag['s'] = 1;
- #ifndef VERY_SMALL_MEMORY
- /* UNIX seventh edition executables */
- v7 = flag['7'];
- #endif
- #ifndef MSDOS
- /* CP/M-86 executables can't use symbols. */
- cpm86 = flag['c'];
- if ( cpm86 ) flag['s'] = 1;
- #endif
- linksyms(flag['r'] | flag['B']);
- if (outfilename == NUL_PTR)
- outfilename = "a.out";
- #ifndef MSDOS
- if( flag['N'] )
- writebin(outfilename, flag['i'], flag['3'], flag['s'],
- flag['z'] & flag['3']);
- else
- #endif
- if( flag['B'] )
- write_dosemu(outfilename, flag['i'], flag['3'], flag['s'],
- flag['z'] & flag['3']);
- else
- write_elks(outfilename, flag['i'], flag['3'], flag['s'],
- flag['z'], flag['y']);
- if (flag['m'])
- dumpmods();
- if (flag['M'])
- dumpsyms();
- flusherr();
- return errcount ? 1 : 0;
- }
|