github.com/4ad/go@v0.0.0-20161219182952-69a12818b605/src/cmd/link/internal/ld/pobj.go (about)

     1  // Inferno utils/6l/obj.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/6l/obj.c
     3  //
     4  //	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
     5  //	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
     6  //	Portions Copyright © 1997-1999 Vita Nuova Limited
     7  //	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
     8  //	Portions Copyright © 2004,2006 Bruce Ellis
     9  //	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
    10  //	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
    11  //	Portions Copyright © 2009 The Go Authors. All rights reserved.
    12  //
    13  // Permission is hereby granted, free of charge, to any person obtaining a copy
    14  // of this software and associated documentation files (the "Software"), to deal
    15  // in the Software without restriction, including without limitation the rights
    16  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    17  // copies of the Software, and to permit persons to whom the Software is
    18  // furnished to do so, subject to the following conditions:
    19  //
    20  // The above copyright notice and this permission notice shall be included in
    21  // all copies or substantial portions of the Software.
    22  //
    23  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    24  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    25  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    26  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    27  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    28  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    29  // THE SOFTWARE.
    30  
    31  package ld
    32  
    33  import (
    34  	"bufio"
    35  	"cmd/internal/obj"
    36  	"cmd/internal/sys"
    37  	"flag"
    38  	"fmt"
    39  	"os"
    40  	"strings"
    41  )
    42  
    43  var (
    44  	pkglistfornote []byte
    45  	buildid        string
    46  )
    47  
    48  func Ldmain() {
    49  	Bso = bufio.NewWriter(os.Stdout)
    50  
    51  	Ctxt = linknew(SysArch)
    52  	Ctxt.Diag = Diag
    53  	Ctxt.Bso = Bso
    54  
    55  	Debug = [128]int{}
    56  	nerrors = 0
    57  	outfile = ""
    58  	HEADTYPE = -1
    59  	INITTEXT = -1
    60  	INITDAT = -1
    61  	INITRND = -1
    62  	INITENTRY = ""
    63  	Linkmode = LinkAuto
    64  
    65  	// For testing behavior of go command when tools crash silently.
    66  	// Undocumented, not in standard flag parser to avoid
    67  	// exposing in usage message.
    68  	for _, arg := range os.Args {
    69  		if arg == "-crash_for_testing" {
    70  			os.Exit(2)
    71  		}
    72  	}
    73  
    74  	if SysArch.Family == sys.AMD64 && obj.Getgoos() == "plan9" {
    75  		obj.Flagcount("8", "use 64-bit addresses in symbol table", &Debug['8'])
    76  	}
    77  	obj.Flagfn1("B", "add an ELF NT_GNU_BUILD_ID `note` when using ELF", addbuildinfo)
    78  	obj.Flagcount("C", "check Go calls to C code", &Debug['C'])
    79  	obj.Flagint64("D", "set data segment `address`", &INITDAT)
    80  	obj.Flagstr("E", "set `entry` symbol name", &INITENTRY)
    81  	obj.Flagfn1("I", "use `linker` as ELF dynamic linker", setinterp)
    82  	obj.Flagfn1("L", "add specified `directory` to library path", Lflag)
    83  	obj.Flagfn1("H", "set header `type`", setheadtype)
    84  	obj.Flagint32("R", "set address rounding `quantum`", &INITRND)
    85  	obj.Flagint64("T", "set text segment `address`", &INITTEXT)
    86  	obj.Flagfn0("V", "print version and exit", doversion)
    87  	obj.Flagfn1("X", "add string value `definition` of the form importpath.name=value", addstrdata1)
    88  	obj.Flagcount("a", "disassemble output", &Debug['a'])
    89  	obj.Flagstr("buildid", "record `id` as Go toolchain build id", &buildid)
    90  	flag.Var(&Buildmode, "buildmode", "set build `mode`")
    91  	obj.Flagcount("c", "dump call graph", &Debug['c'])
    92  	obj.Flagcount("d", "disable dynamic executable", &Debug['d'])
    93  	flag.BoolVar(&flag_dumpdep, "dumpdep", false, "dump symbol dependency graph")
    94  	obj.Flagstr("extar", "archive program for buildmode=c-archive", &extar)
    95  	obj.Flagstr("extld", "use `linker` when linking in external mode", &extld)
    96  	obj.Flagstr("extldflags", "pass `flags` to external linker", &extldflags)
    97  	obj.Flagcount("f", "ignore version mismatch", &Debug['f'])
    98  	obj.Flagcount("g", "disable go package data checks", &Debug['g'])
    99  	obj.Flagcount("h", "halt on error", &Debug['h'])
   100  	obj.Flagstr("installsuffix", "set package directory `suffix`", &flag_installsuffix)
   101  	obj.Flagstr("k", "set field tracking `symbol`", &tracksym)
   102  	obj.Flagstr("libgcc", "compiler support lib for internal linking; use \"none\" to disable", &libgccfile)
   103  	obj.Flagfn1("linkmode", "set link `mode` (internal, external, auto)", setlinkmode)
   104  	flag.BoolVar(&Linkshared, "linkshared", false, "link against installed Go shared libraries")
   105  	obj.Flagcount("msan", "enable MSan interface", &flag_msan)
   106  	obj.Flagcount("n", "dump symbol table", &Debug['n'])
   107  	obj.Flagstr("o", "write output to `file`", &outfile)
   108  	flag.Var(&rpath, "r", "set the ELF dynamic linker search `path` to dir1:dir2:...")
   109  	obj.Flagcount("race", "enable race detector", &flag_race)
   110  	obj.Flagcount("s", "disable symbol table", &Debug['s'])
   111  	var flagShared int
   112  	if SysArch.InFamily(sys.ARM, sys.AMD64) {
   113  		obj.Flagcount("shared", "generate shared object (implies -linkmode external)", &flagShared)
   114  	}
   115  	obj.Flagstr("tmpdir", "use `directory` for temporary files", &tmpdir)
   116  	obj.Flagcount("u", "reject unsafe packages", &Debug['u'])
   117  	obj.Flagcount("v", "print link trace", &Debug['v'])
   118  	obj.Flagcount("w", "disable DWARF generation", &Debug['w'])
   119  
   120  	obj.Flagstr("cpuprofile", "write cpu profile to `file`", &cpuprofile)
   121  	obj.Flagstr("memprofile", "write memory profile to `file`", &memprofile)
   122  	obj.Flagint64("memprofilerate", "set runtime.MemProfileRate to `rate`", &memprofilerate)
   123  
   124  	obj.Flagparse(usage)
   125  
   126  	startProfile()
   127  	Ctxt.Bso = Bso
   128  	Ctxt.Debugvlog = int32(Debug['v'])
   129  	if flagShared != 0 {
   130  		if Buildmode == BuildmodeUnset {
   131  			Buildmode = BuildmodeCShared
   132  		} else if Buildmode != BuildmodeCShared {
   133  			Exitf("-shared and -buildmode=%s are incompatible", Buildmode.String())
   134  		}
   135  	}
   136  	if Buildmode == BuildmodeUnset {
   137  		Buildmode = BuildmodeExe
   138  	}
   139  
   140  	if Buildmode != BuildmodeShared && flag.NArg() != 1 {
   141  		usage()
   142  	}
   143  
   144  	if outfile == "" {
   145  		outfile = "a.out"
   146  		if HEADTYPE == obj.Hwindows {
   147  			outfile += ".exe"
   148  		}
   149  	}
   150  
   151  	libinit() // creates outfile
   152  
   153  	if HEADTYPE == -1 {
   154  		HEADTYPE = int32(headtype(goos))
   155  	}
   156  	Ctxt.Headtype = int(HEADTYPE)
   157  	if headstring == "" {
   158  		headstring = Headstr(int(HEADTYPE))
   159  	}
   160  
   161  	Thearch.Archinit()
   162  
   163  	if Linkshared && !Iself {
   164  		Exitf("-linkshared can only be used on elf systems")
   165  	}
   166  
   167  	if Debug['v'] != 0 {
   168  		fmt.Fprintf(Bso, "HEADER = -H%d -T0x%x -D0x%x -R0x%x\n", HEADTYPE, uint64(INITTEXT), uint64(INITDAT), uint32(INITRND))
   169  	}
   170  	Bso.Flush()
   171  
   172  	if Buildmode == BuildmodeShared {
   173  		for i := 0; i < flag.NArg(); i++ {
   174  			arg := flag.Arg(i)
   175  			parts := strings.SplitN(arg, "=", 2)
   176  			var pkgpath, file string
   177  			if len(parts) == 1 {
   178  				pkgpath, file = "main", arg
   179  			} else {
   180  				pkgpath, file = parts[0], parts[1]
   181  			}
   182  			pkglistfornote = append(pkglistfornote, pkgpath...)
   183  			pkglistfornote = append(pkglistfornote, '\n')
   184  			addlibpath(Ctxt, "command line", "command line", file, pkgpath, "")
   185  		}
   186  	} else {
   187  		addlibpath(Ctxt, "command line", "command line", flag.Arg(0), "main", "")
   188  	}
   189  	loadlib()
   190  
   191  	checkstrdata()
   192  	deadcode(Ctxt)
   193  	fieldtrack(Ctxt)
   194  	callgraph()
   195  
   196  	doelf()
   197  	if HEADTYPE == obj.Hdarwin {
   198  		domacho()
   199  	}
   200  	dostkcheck()
   201  	if HEADTYPE == obj.Hwindows {
   202  		dope()
   203  	}
   204  	addexport()
   205  	Thearch.Gentext() // trampolines, call stubs, etc.
   206  	textbuildid()
   207  	textaddress()
   208  	pclntab()
   209  	findfunctab()
   210  	symtab()
   211  	dodata()
   212  	address()
   213  	reloc()
   214  	Thearch.Asmb()
   215  	undef()
   216  	hostlink()
   217  	archive()
   218  	if Debug['v'] != 0 {
   219  		fmt.Fprintf(Bso, "%5.2f cpu time\n", obj.Cputime())
   220  		fmt.Fprintf(Bso, "%d symbols\n", len(Ctxt.Allsym))
   221  		fmt.Fprintf(Bso, "%d liveness data\n", liveness)
   222  	}
   223  
   224  	Bso.Flush()
   225  
   226  	errorexit()
   227  }