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