...

Source file src/pkg/cmd/link/internal/mips64/asm.go

     1	// Inferno utils/5l/asm.c
     2	// https://bitbucket.org/inferno-os/inferno-os/src/default/utils/5l/asm.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 mips64
    32	
    33	import (
    34		"cmd/internal/objabi"
    35		"cmd/internal/sys"
    36		"cmd/link/internal/ld"
    37		"cmd/link/internal/sym"
    38		"debug/elf"
    39		"fmt"
    40		"log"
    41	)
    42	
    43	func gentext(ctxt *ld.Link) {}
    44	
    45	func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
    46		log.Fatalf("adddynrel not implemented")
    47		return false
    48	}
    49	
    50	func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
    51		// mips64 ELF relocation (endian neutral)
    52		//		offset	uint64
    53		//		sym		uint32
    54		//		ssym	uint8
    55		//		type3	uint8
    56		//		type2	uint8
    57		//		type	uint8
    58		//		addend	int64
    59	
    60		ctxt.Out.Write64(uint64(sectoff))
    61	
    62		elfsym := r.Xsym.ElfsymForReloc()
    63		ctxt.Out.Write32(uint32(elfsym))
    64		ctxt.Out.Write8(0)
    65		ctxt.Out.Write8(0)
    66		ctxt.Out.Write8(0)
    67		switch r.Type {
    68		default:
    69			return false
    70		case objabi.R_ADDR:
    71			switch r.Siz {
    72			case 4:
    73				ctxt.Out.Write8(uint8(elf.R_MIPS_32))
    74			case 8:
    75				ctxt.Out.Write8(uint8(elf.R_MIPS_64))
    76			default:
    77				return false
    78			}
    79		case objabi.R_ADDRMIPS:
    80			ctxt.Out.Write8(uint8(elf.R_MIPS_LO16))
    81		case objabi.R_ADDRMIPSU:
    82			ctxt.Out.Write8(uint8(elf.R_MIPS_HI16))
    83		case objabi.R_ADDRMIPSTLS:
    84			ctxt.Out.Write8(uint8(elf.R_MIPS_TLS_TPREL_LO16))
    85		case objabi.R_CALLMIPS,
    86			objabi.R_JMPMIPS:
    87			ctxt.Out.Write8(uint8(elf.R_MIPS_26))
    88		}
    89		ctxt.Out.Write64(uint64(r.Xadd))
    90	
    91		return true
    92	}
    93	
    94	func elfsetupplt(ctxt *ld.Link) {
    95		return
    96	}
    97	
    98	func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
    99		return false
   100	}
   101	
   102	func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
   103		if ctxt.LinkMode == ld.LinkExternal {
   104			switch r.Type {
   105			default:
   106				return val, false
   107			case objabi.R_ADDRMIPS,
   108				objabi.R_ADDRMIPSU:
   109				r.Done = false
   110	
   111				// set up addend for eventual relocation via outer symbol.
   112				rs := r.Sym
   113				r.Xadd = r.Add
   114				for rs.Outer != nil {
   115					r.Xadd += ld.Symaddr(rs) - ld.Symaddr(rs.Outer)
   116					rs = rs.Outer
   117				}
   118	
   119				if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Sect == nil {
   120					ld.Errorf(s, "missing section for %s", rs.Name)
   121				}
   122				r.Xsym = rs
   123	
   124				return val, true
   125			case objabi.R_ADDRMIPSTLS,
   126				objabi.R_CALLMIPS,
   127				objabi.R_JMPMIPS:
   128				r.Done = false
   129				r.Xsym = r.Sym
   130				r.Xadd = r.Add
   131				return val, true
   132			}
   133		}
   134	
   135		switch r.Type {
   136		case objabi.R_CONST:
   137			return r.Add, true
   138		case objabi.R_GOTOFF:
   139			return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)), true
   140		case objabi.R_ADDRMIPS,
   141			objabi.R_ADDRMIPSU:
   142			t := ld.Symaddr(r.Sym) + r.Add
   143			o1 := ctxt.Arch.ByteOrder.Uint32(s.P[r.Off:])
   144			if r.Type == objabi.R_ADDRMIPS {
   145				return int64(o1&0xffff0000 | uint32(t)&0xffff), true
   146			}
   147			return int64(o1&0xffff0000 | uint32((t+1<<15)>>16)&0xffff), true
   148		case objabi.R_ADDRMIPSTLS:
   149			// thread pointer is at 0x7000 offset from the start of TLS data area
   150			t := ld.Symaddr(r.Sym) + r.Add - 0x7000
   151			if t < -32768 || t >= 32678 {
   152				ld.Errorf(s, "TLS offset out of range %d", t)
   153			}
   154			o1 := ctxt.Arch.ByteOrder.Uint32(s.P[r.Off:])
   155			return int64(o1&0xffff0000 | uint32(t)&0xffff), true
   156		case objabi.R_CALLMIPS,
   157			objabi.R_JMPMIPS:
   158			// Low 26 bits = (S + A) >> 2
   159			t := ld.Symaddr(r.Sym) + r.Add
   160			o1 := ctxt.Arch.ByteOrder.Uint32(s.P[r.Off:])
   161			return int64(o1&0xfc000000 | uint32(t>>2)&^0xfc000000), true
   162		}
   163	
   164		return val, false
   165	}
   166	
   167	func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
   168		return -1
   169	}
   170	
   171	func asmb(ctxt *ld.Link) {
   172		if ctxt.Debugvlog != 0 {
   173			ctxt.Logf("%5.2f asmb\n", ld.Cputime())
   174		}
   175	
   176		if ctxt.IsELF {
   177			ld.Asmbelfsetup()
   178		}
   179	
   180		sect := ld.Segtext.Sections[0]
   181		ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
   182		ld.Codeblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
   183		for _, sect = range ld.Segtext.Sections[1:] {
   184			ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
   185			ld.Datblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
   186		}
   187	
   188		if ld.Segrodata.Filelen > 0 {
   189			if ctxt.Debugvlog != 0 {
   190				ctxt.Logf("%5.2f rodatblk\n", ld.Cputime())
   191			}
   192			ctxt.Out.SeekSet(int64(ld.Segrodata.Fileoff))
   193			ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
   194		}
   195		if ld.Segrelrodata.Filelen > 0 {
   196			if ctxt.Debugvlog != 0 {
   197				ctxt.Logf("%5.2f rodatblk\n", ld.Cputime())
   198			}
   199			ctxt.Out.SeekSet(int64(ld.Segrelrodata.Fileoff))
   200			ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen))
   201		}
   202	
   203		if ctxt.Debugvlog != 0 {
   204			ctxt.Logf("%5.2f datblk\n", ld.Cputime())
   205		}
   206	
   207		ctxt.Out.SeekSet(int64(ld.Segdata.Fileoff))
   208		ld.Datblk(ctxt, int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
   209	
   210		ctxt.Out.SeekSet(int64(ld.Segdwarf.Fileoff))
   211		ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
   212	}
   213	
   214	func asmb2(ctxt *ld.Link) {
   215		/* output symbol table */
   216		ld.Symsize = 0
   217	
   218		ld.Lcsize = 0
   219		symo := uint32(0)
   220		if !*ld.FlagS {
   221			// TODO: rationalize
   222			if ctxt.Debugvlog != 0 {
   223				ctxt.Logf("%5.2f sym\n", ld.Cputime())
   224			}
   225			switch ctxt.HeadType {
   226			default:
   227				if ctxt.IsELF {
   228					symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
   229					symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
   230				}
   231	
   232			case objabi.Hplan9:
   233				symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
   234			}
   235	
   236			ctxt.Out.SeekSet(int64(symo))
   237			switch ctxt.HeadType {
   238			default:
   239				if ctxt.IsELF {
   240					if ctxt.Debugvlog != 0 {
   241						ctxt.Logf("%5.2f elfsym\n", ld.Cputime())
   242					}
   243					ld.Asmelfsym(ctxt)
   244					ctxt.Out.Flush()
   245					ctxt.Out.Write(ld.Elfstrdat)
   246	
   247					if ctxt.LinkMode == ld.LinkExternal {
   248						ld.Elfemitreloc(ctxt)
   249					}
   250				}
   251	
   252			case objabi.Hplan9:
   253				ld.Asmplan9sym(ctxt)
   254				ctxt.Out.Flush()
   255	
   256				sym := ctxt.Syms.Lookup("pclntab", 0)
   257				if sym != nil {
   258					ld.Lcsize = int32(len(sym.P))
   259					ctxt.Out.Write(sym.P)
   260					ctxt.Out.Flush()
   261				}
   262			}
   263		}
   264	
   265		if ctxt.Debugvlog != 0 {
   266			ctxt.Logf("%5.2f header\n", ld.Cputime())
   267		}
   268		ctxt.Out.SeekSet(0)
   269		switch ctxt.HeadType {
   270		default:
   271		case objabi.Hplan9: /* plan 9 */
   272			magic := uint32(4*18*18 + 7)
   273			if ctxt.Arch == sys.ArchMIPS64LE {
   274				magic = uint32(4*26*26 + 7)
   275			}
   276			ctxt.Out.Write32(magic)                      /* magic */
   277			ctxt.Out.Write32(uint32(ld.Segtext.Filelen)) /* sizes */
   278			ctxt.Out.Write32(uint32(ld.Segdata.Filelen))
   279			ctxt.Out.Write32(uint32(ld.Segdata.Length - ld.Segdata.Filelen))
   280			ctxt.Out.Write32(uint32(ld.Symsize))          /* nsyms */
   281			ctxt.Out.Write32(uint32(ld.Entryvalue(ctxt))) /* va of entry */
   282			ctxt.Out.Write32(0)
   283			ctxt.Out.Write32(uint32(ld.Lcsize))
   284	
   285		case objabi.Hlinux,
   286			objabi.Hfreebsd,
   287			objabi.Hnetbsd,
   288			objabi.Hopenbsd,
   289			objabi.Hnacl:
   290			ld.Asmbelf(ctxt, int64(symo))
   291		}
   292	
   293		ctxt.Out.Flush()
   294		if *ld.FlagC {
   295			fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
   296			fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
   297			fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
   298			fmt.Printf("symsize=%d\n", ld.Symsize)
   299			fmt.Printf("lcsize=%d\n", ld.Lcsize)
   300			fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))
   301		}
   302	}
   303	

View as plain text