github.com/rsc/go@v0.0.0-20150416155037-e040fd465409/src/cmd/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  	"cmd/internal/obj"
    35  	"flag"
    36  	"fmt"
    37  	"os"
    38  	"strings"
    39  )
    40  
    41  // Reading object files.
    42  
    43  func Ldmain() {
    44  	Ctxt = linknew(Thelinkarch)
    45  	Ctxt.Thechar = int32(Thearch.Thechar)
    46  	Ctxt.Thestring = Thestring
    47  	Ctxt.Diag = Diag
    48  	Ctxt.Bso = &Bso
    49  
    50  	Bso = *Binitw(os.Stdout)
    51  	Debug = [128]int{}
    52  	nerrors = 0
    53  	outfile = ""
    54  	HEADTYPE = -1
    55  	INITTEXT = -1
    56  	INITDAT = -1
    57  	INITRND = -1
    58  	INITENTRY = ""
    59  	Linkmode = LinkAuto
    60  
    61  	// For testing behavior of go command when tools crash.
    62  	// Undocumented, not in standard flag parser to avoid
    63  	// exposing in usage message.
    64  	for _, arg := range os.Args {
    65  		if arg == "-crash_for_testing" {
    66  			*(*int)(nil) = 0
    67  		}
    68  	}
    69  
    70  	if Thearch.Thechar == '5' && Ctxt.Goarm == 5 {
    71  		Debug['F'] = 1
    72  	}
    73  
    74  	obj.Flagcount("1", "use alternate profiling code", &Debug['1'])
    75  	if Thearch.Thechar == '6' {
    76  		obj.Flagcount("8", "assume 64-bit addresses", &Debug['8'])
    77  	}
    78  	obj.Flagfn1("B", "info: define ELF NT_GNU_BUILD_ID note", addbuildinfo)
    79  	obj.Flagcount("C", "check Go calls to C code", &Debug['C'])
    80  	obj.Flagint64("D", "addr: data address", &INITDAT)
    81  	obj.Flagstr("E", "sym: entry symbol", &INITENTRY)
    82  	if Thearch.Thechar == '5' {
    83  		obj.Flagcount("G", "debug pseudo-ops", &Debug['G'])
    84  	}
    85  	obj.Flagfn1("I", "interp: set ELF interp", setinterp)
    86  	obj.Flagfn1("L", "dir: add dir to library path", Lflag)
    87  	obj.Flagfn1("H", "head: header type", setheadtype)
    88  	obj.Flagcount("K", "add stack underflow checks", &Debug['K'])
    89  	if Thearch.Thechar == '5' {
    90  		obj.Flagcount("M", "disable software div/mod", &Debug['M'])
    91  	}
    92  	obj.Flagcount("O", "print pc-line tables", &Debug['O'])
    93  	obj.Flagcount("Q", "debug byte-register code gen", &Debug['Q'])
    94  	if Thearch.Thechar == '5' {
    95  		obj.Flagcount("P", "debug code generation", &Debug['P'])
    96  	}
    97  	obj.Flagint32("R", "rnd: address rounding", &INITRND)
    98  	obj.Flagcount("nil", "check type signatures", &Debug['S'])
    99  	obj.Flagint64("T", "addr: text address", &INITTEXT)
   100  	obj.Flagfn0("V", "print version and exit", doversion)
   101  	obj.Flagcount("W", "disassemble input", &Debug['W'])
   102  	obj.Flagfn1("X", "name value: define string data", addstrdata1)
   103  	obj.Flagcount("Z", "clear stack frame on entry", &Debug['Z'])
   104  	obj.Flagcount("a", "disassemble output", &Debug['a'])
   105  	flag.Var(&Buildmode, "buildmode", "build mode to use")
   106  	obj.Flagcount("c", "dump call graph", &Debug['c'])
   107  	obj.Flagcount("d", "disable dynamic executable", &Debug['d'])
   108  	obj.Flagstr("extld", "ld: linker to run in external mode", &extld)
   109  	obj.Flagstr("extldflags", "ldflags: flags for external linker", &extldflags)
   110  	obj.Flagcount("f", "ignore version mismatch", &Debug['f'])
   111  	obj.Flagcount("g", "disable go package data checks", &Debug['g'])
   112  	obj.Flagstr("installsuffix", "suffix: pkg directory suffix", &flag_installsuffix)
   113  	obj.Flagstr("k", "sym: set field tracking symbol", &tracksym)
   114  	obj.Flagfn1("linkmode", "mode: set link mode (internal, external, auto)", setlinkmode)
   115  	flag.BoolVar(&Linkshared, "linkshared", false, "link against installed Go shared libraries")
   116  	obj.Flagcount("n", "dump symbol table", &Debug['n'])
   117  	obj.Flagstr("o", "outfile: set output file", &outfile)
   118  	flag.Var(&rpath, "r", "dir1:dir2:...: set ELF dynamic linker search path")
   119  	obj.Flagcount("race", "enable race detector", &flag_race)
   120  	obj.Flagcount("s", "disable symbol table", &Debug['s'])
   121  	var flagShared int
   122  	if Thearch.Thechar == '5' || Thearch.Thechar == '6' {
   123  		obj.Flagcount("shared", "generate shared object (implies -linkmode external)", &flagShared)
   124  	}
   125  	obj.Flagstr("tmpdir", "dir: leave temporary files in this directory", &tmpdir)
   126  	obj.Flagcount("u", "reject unsafe packages", &Debug['u'])
   127  	obj.Flagcount("v", "print link trace", &Debug['v'])
   128  	obj.Flagcount("w", "disable DWARF generation", &Debug['w'])
   129  
   130  	// Clumsy hack to preserve old behavior of -X taking two arguments.
   131  	for i := 0; i < len(os.Args); i++ {
   132  		arg := os.Args[i]
   133  		if (arg == "--X" || arg == "-X") && i+2 < len(os.Args) {
   134  			os.Args[i+2] = "-X=VALUE:" + os.Args[i+2]
   135  			i += 2
   136  		} else if (strings.HasPrefix(arg, "--X=") || strings.HasPrefix(arg, "-X=")) && i+1 < len(os.Args) {
   137  			os.Args[i+1] = "-X=VALUE:" + os.Args[i+1]
   138  			i++
   139  		}
   140  	}
   141  	obj.Flagstr("cpuprofile", "file: write cpu profile to file", &cpuprofile)
   142  	obj.Flagstr("memprofile", "file: write memory profile to file", &memprofile)
   143  	obj.Flagparse(usage)
   144  	startProfile()
   145  	Ctxt.Bso = &Bso
   146  	Ctxt.Debugvlog = int32(Debug['v'])
   147  	if flagShared != 0 {
   148  		if Buildmode == BuildmodeExe {
   149  			Buildmode = BuildmodeCShared
   150  		} else if Buildmode != BuildmodeCShared {
   151  			Diag("-shared and -buildmode=%s are incompatible\n", Buildmode.String())
   152  			Errorexit()
   153  		}
   154  	}
   155  
   156  	if Buildmode != BuildmodeShared && flag.NArg() != 1 {
   157  		usage()
   158  	}
   159  
   160  	if outfile == "" {
   161  		if HEADTYPE == Hwindows {
   162  			outfile = fmt.Sprintf("%c.out.exe", Thearch.Thechar)
   163  		} else {
   164  			outfile = fmt.Sprintf("%c.out", Thearch.Thechar)
   165  		}
   166  	}
   167  
   168  	libinit() // creates outfile
   169  
   170  	if HEADTYPE == -1 {
   171  		HEADTYPE = int32(headtype(goos))
   172  	}
   173  	Ctxt.Headtype = int(HEADTYPE)
   174  	if headstring == "" {
   175  		headstring = Headstr(int(HEADTYPE))
   176  	}
   177  
   178  	Thearch.Archinit()
   179  
   180  	if Linkshared && !Iself {
   181  		Diag("-linkshared can only be used on elf systems")
   182  		Errorexit()
   183  	}
   184  
   185  	if Debug['v'] != 0 {
   186  		fmt.Fprintf(&Bso, "HEADER = -H%d -T0x%x -D0x%x -R0x%x\n", HEADTYPE, uint64(INITTEXT), uint64(INITDAT), uint32(INITRND))
   187  	}
   188  	Bflush(&Bso)
   189  
   190  	if Buildmode == BuildmodeShared {
   191  		for i := 0; i < flag.NArg(); i++ {
   192  			arg := flag.Arg(i)
   193  			parts := strings.SplitN(arg, "=", 2)
   194  			var pkgpath, file string
   195  			if len(parts) == 1 {
   196  				pkgpath, file = "main", arg
   197  			} else {
   198  				pkgpath, file = parts[0], parts[1]
   199  			}
   200  			addlibpath(Ctxt, "command line", "command line", file, pkgpath, "")
   201  		}
   202  	} else {
   203  		addlibpath(Ctxt, "command line", "command line", flag.Arg(0), "main", "")
   204  	}
   205  	loadlib()
   206  
   207  	if Thearch.Thechar == '5' {
   208  		// mark some functions that are only referenced after linker code editing
   209  		if Debug['F'] != 0 {
   210  			mark(Linkrlookup(Ctxt, "_sfloat", 0))
   211  		}
   212  		mark(Linklookup(Ctxt, "runtime.read_tls_fallback", 0))
   213  	}
   214  
   215  	checkgo()
   216  	deadcode()
   217  	callgraph()
   218  
   219  	doelf()
   220  	if HEADTYPE == Hdarwin {
   221  		domacho()
   222  	}
   223  	dostkcheck()
   224  	if HEADTYPE == Hwindows {
   225  		dope()
   226  	}
   227  	addexport()
   228  	Thearch.Gentext() // trampolines, call stubs, etc.
   229  	textaddress()
   230  	pclntab()
   231  	findfunctab()
   232  	symtab()
   233  	dodata()
   234  	address()
   235  	doweak()
   236  	reloc()
   237  	Thearch.Asmb()
   238  	undef()
   239  	hostlink()
   240  	archive()
   241  	if Debug['v'] != 0 {
   242  		fmt.Fprintf(&Bso, "%5.2f cpu time\n", obj.Cputime())
   243  		fmt.Fprintf(&Bso, "%d symbols\n", Ctxt.Nsymbol)
   244  		fmt.Fprintf(&Bso, "%d liveness data\n", liveness)
   245  	}
   246  
   247  	Bflush(&Bso)
   248  
   249  	Errorexit()
   250  }