github.com/rsc/tmp@v0.0.0-20240517235954-6deaab19748b/bootstrap/internal/ld/pobj.go (about)

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