ref: f5f5501c8ea833e2e40f4de72b733c4b50fe86dd
dir: /src/cmd/ld/main.c/
#include <errno.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <scc/syslibs.h> #include "ld.h" char *output = "a.out", *entry = "start"; char *filename, *membname; unsigned long textsiz, datasiz, bsssiz; unsigned long textbase, database, bssbase; int sflag; /* discard all the symbols */ int xflag; /* discard local symbols */ int Xflag; /* discard locals starting with 'L' */ int rflag; /* preserve relocation bits */ int dflag; /* define common even with rflag */ int gflag; /* preserve debug symbols */ char *Dflag; /* size of data */ static int status; char * errstr(void) { return strerror(errno); } void error(char *fmt, ...) { va_list va; va_start(va, fmt); fprintf(stderr, "ld: %s: ", filename); if (membname) fprintf(stderr, "%s: ", membname); vfprintf(stderr, fmt, va); putc('\n', stderr); va_end(va); status = EXIT_FAILURE; } static void cleanup(void) { if (status != EXIT_FAILURE) remove(output); } /* * pass1: Get the list of object files that are going to be linked. * pass2: Calculate the size of every segment. * pass3: Rebase all symbols in sections */ static void ld(int argc, char*argv[]) { pass1(argc, argv); pass2(argc, argv); pass3(argc, argv); debugsym(); } static void usage(void) { fputs("usage: ld [options] file ...\n", stderr); exit(EXIT_FAILURE); } static void Lpath(char *path) { char **bp, **end; end = &syslibs[MAX_LIB_PATHS]; for (bp = syslibs; bp < end && *bp; ++bp) ; if (bp == end) { fputs("ld: too many -L options\n", stderr); exit(1); } *bp = path; } int main(int argc, char *argv[]) { char *cp, **p; for (--argc; *++argv; --argc) { if (argv[0][0] != '-' || argv[0][1] == 'l') break; if (argv[0][1] == '-') { --argc, ++argv; break; } for (cp = &argv[0][1]; *cp; ++cp) { switch (*cp) { case 's': sflag = 1; break; case 'x': xflag = 1; break; case 'X': Xflag = 1; break; case 'r': rflag = 1; break; case 'd': dflag = 1; break; case 'i': case 'n': /* TODO */ break; case 'L': if (argc == 0) goto usage; ++argv, --argc; Lpath(*argv); break; case 'u': if (argc == 0) goto usage; ++argv, --argc; install(*argv); break; case 'o': if (argc == 0) goto usage; ++argv, --argc; output = *argv; break; case 'e': if (argc == 0) goto usage; ++argv, --argc; entry = *argv; break; case 'D': if (argc == 0) goto usage; ++argv, --argc; Dflag = *argv; break; default: usage: usage(); } } } if (argc == 0) usage(); atexit(cleanup); ld(argc, argv); return status; }