Home | History | Annotate | Download | only in mips64
      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 (a] 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 (a] 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) bool {
    103 	if ctxt.LinkMode == ld.LinkExternal {
    104 		switch r.Type {
    105 		default:
    106 			return 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 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 true
    132 		}
    133 	}
    134 
    135 	switch r.Type {
    136 	case objabi.R_CONST:
    137 		*val = r.Add
    138 		return true
    139 	case objabi.R_GOTOFF:
    140 		*val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0))
    141 		return true
    142 	case objabi.R_ADDRMIPS,
    143 		objabi.R_ADDRMIPSU:
    144 		t := ld.Symaddr(r.Sym) + r.Add
    145 		o1 := ctxt.Arch.ByteOrder.Uint32(s.P[r.Off:])
    146 		if r.Type == objabi.R_ADDRMIPS {
    147 			*val = int64(o1&0xffff0000 | uint32(t)&0xffff)
    148 		} else {
    149 			*val = int64(o1&0xffff0000 | uint32((t+1<<15)>>16)&0xffff)
    150 		}
    151 		return true
    152 	case objabi.R_ADDRMIPSTLS:
    153 		// thread pointer is at 0x7000 offset from the start of TLS data area
    154 		t := ld.Symaddr(r.Sym) + r.Add - 0x7000
    155 		if t < -32768 || t >= 32678 {
    156 			ld.Errorf(s, "TLS offset out of range %d", t)
    157 		}
    158 		o1 := ctxt.Arch.ByteOrder.Uint32(s.P[r.Off:])
    159 		*val = int64(o1&0xffff0000 | uint32(t)&0xffff)
    160 		return true
    161 	case objabi.R_CALLMIPS,
    162 		objabi.R_JMPMIPS:
    163 		// Low 26 bits = (S + A) >> 2
    164 		t := ld.Symaddr(r.Sym) + r.Add
    165 		o1 := ctxt.Arch.ByteOrder.Uint32(s.P[r.Off:])
    166 		*val = int64(o1&0xfc000000 | uint32(t>>2)&^0xfc000000)
    167 		return true
    168 	}
    169 
    170 	return false
    171 }
    172 
    173 func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
    174 	return -1
    175 }
    176 
    177 func asmb(ctxt *ld.Link) {
    178 	if ctxt.Debugvlog != 0 {
    179 		ctxt.Logf("%5.2f asmb\n", ld.Cputime())
    180 	}
    181 
    182 	if ctxt.IsELF {
    183 		ld.Asmbelfsetup()
    184 	}
    185 
    186 	sect := ld.Segtext.Sections[0]
    187 	ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
    188 	ld.Codeblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
    189 	for _, sect = range ld.Segtext.Sections[1:] {
    190 		ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
    191 		ld.Datblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
    192 	}
    193 
    194 	if ld.Segrodata.Filelen > 0 {
    195 		if ctxt.Debugvlog != 0 {
    196 			ctxt.Logf("%5.2f rodatblk\n", ld.Cputime())
    197 		}
    198 		ctxt.Out.SeekSet(int64(ld.Segrodata.Fileoff))
    199 		ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
    200 	}
    201 	if ld.Segrelrodata.Filelen > 0 {
    202 		if ctxt.Debugvlog != 0 {
    203 			ctxt.Logf("%5.2f rodatblk\n", ld.Cputime())
    204 		}
    205 		ctxt.Out.SeekSet(int64(ld.Segrelrodata.Fileoff))
    206 		ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen))
    207 	}
    208 
    209 	if ctxt.Debugvlog != 0 {
    210 		ctxt.Logf("%5.2f datblk\n", ld.Cputime())
    211 	}
    212 
    213 	ctxt.Out.SeekSet(int64(ld.Segdata.Fileoff))
    214 	ld.Datblk(ctxt, int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
    215 
    216 	ctxt.Out.SeekSet(int64(ld.Segdwarf.Fileoff))
    217 	ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
    218 
    219 	/* output symbol table */
    220 	ld.Symsize = 0
    221 
    222 	ld.Lcsize = 0
    223 	symo := uint32(0)
    224 	if !*ld.FlagS {
    225 		// TODO: rationalize
    226 		if ctxt.Debugvlog != 0 {
    227 			ctxt.Logf("%5.2f sym\n", ld.Cputime())
    228 		}
    229 		switch ctxt.HeadType {
    230 		default:
    231 			if ctxt.IsELF {
    232 				symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
    233 				symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
    234 			}
    235 
    236 		case objabi.Hplan9:
    237 			symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
    238 		}
    239 
    240 		ctxt.Out.SeekSet(int64(symo))
    241 		switch ctxt.HeadType {
    242 		default:
    243 			if ctxt.IsELF {
    244 				if ctxt.Debugvlog != 0 {
    245 					ctxt.Logf("%5.2f elfsym\n", ld.Cputime())
    246 				}
    247 				ld.Asmelfsym(ctxt)
    248 				ctxt.Out.Flush()
    249 				ctxt.Out.Write(ld.Elfstrdat)
    250 
    251 				if ctxt.LinkMode == ld.LinkExternal {
    252 					ld.Elfemitreloc(ctxt)
    253 				}
    254 			}
    255 
    256 		case objabi.Hplan9:
    257 			ld.Asmplan9sym(ctxt)
    258 			ctxt.Out.Flush()
    259 
    260 			sym := ctxt.Syms.Lookup("pclntab", 0)
    261 			if sym != nil {
    262 				ld.Lcsize = int32(len(sym.P))
    263 				ctxt.Out.Write(sym.P)
    264 				ctxt.Out.Flush()
    265 			}
    266 		}
    267 	}
    268 
    269 	if ctxt.Debugvlog != 0 {
    270 		ctxt.Logf("%5.2f header\n", ld.Cputime())
    271 	}
    272 	ctxt.Out.SeekSet(0)
    273 	switch ctxt.HeadType {
    274 	default:
    275 	case objabi.Hplan9: /* plan 9 */
    276 		magic := uint32(4*18*18 + 7)
    277 		if ctxt.Arch == sys.ArchMIPS64LE {
    278 			magic = uint32(4*26*26 + 7)
    279 		}
    280 		ctxt.Out.Write32(magic)                      /* magic */
    281 		ctxt.Out.Write32(uint32(ld.Segtext.Filelen)) /* sizes */
    282 		ctxt.Out.Write32(uint32(ld.Segdata.Filelen))
    283 		ctxt.Out.Write32(uint32(ld.Segdata.Length - ld.Segdata.Filelen))
    284 		ctxt.Out.Write32(uint32(ld.Symsize))          /* nsyms */
    285 		ctxt.Out.Write32(uint32(ld.Entryvalue(ctxt))) /* va of entry */
    286 		ctxt.Out.Write32(0)
    287 		ctxt.Out.Write32(uint32(ld.Lcsize))
    288 
    289 	case objabi.Hlinux,
    290 		objabi.Hfreebsd,
    291 		objabi.Hnetbsd,
    292 		objabi.Hopenbsd,
    293 		objabi.Hnacl:
    294 		ld.Asmbelf(ctxt, int64(symo))
    295 	}
    296 
    297 	ctxt.Out.Flush()
    298 	if *ld.FlagC {
    299 		fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
    300 		fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
    301 		fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
    302 		fmt.Printf("symsize=%d\n", ld.Symsize)
    303 		fmt.Printf("lcsize=%d\n", ld.Lcsize)
    304 		fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))
    305 	}
    306 }
    307