ref: 5b919477354727041f8a522f0f91273e623fa58d
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" 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 */ char *filename, *membname; Segment text = {.type = 'T'}; Segment rodata = {.type = 'R'}; Segment data = {.type = 'D'}; Segment bss = {.type = 'B'}; char *output = "a.out", *entry = "start"; 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 * pass4: Create the temporary files per section * pass5: Create the temporary files per segment */ static void ld(int argc, char*argv[]) { pass1(argc, argv); pass2(argc, argv); pass3(argc, argv); pass4(argc, argv); pass5(argc, argv); debugsym(); debugsec(); } 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[]) { int files = 0; char *cp, *arg, **ap; for (ap = argv+1; *ap; ++ap) { if (ap[0][0] != '-') { files = 1; continue; } for (cp = &ap[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 'u': case 'l': arg = (cp[1]) ? cp+1 : *++ap; if (!arg) goto usage; goto next_arg; case 'L': arg = (cp[1]) ? cp+1 : *++ap; if (!arg) goto usage; Lpath(arg); goto next_arg; case 'o': arg = (cp[1]) ? cp+1 : *++ap; if (!arg) goto usage; output = arg; goto next_arg; case 'e': arg = (cp[1]) ? cp+1 : *++ap; if (!arg) goto usage; entry = arg; goto next_arg; case 'D': arg = (cp[1]) ? cp+1 : *++ap; if (!arg) goto usage; Dflag = arg; goto next_arg; default: usage: usage(); } } next_arg: continue; } if (!files) usage(); atexit(cleanup); ld(argc, argv); return status; }