Home | History | Annotate | Download | only in mips
      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  2016 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 mips
     32 
     33 import (
     34 	"cmd/internal/obj"
     35 	"cmd/link/internal/ld"
     36 	"fmt"
     37 	"log"
     38 )
     39 
     40 func gentext(ctxt *ld.Link) {
     41 	return
     42 }
     43 
     44 func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
     45 	log.Fatalf("adddynrel not implemented")
     46 	return false
     47 }
     48 
     49 func elfreloc1(ctxt *ld.Link, r *ld.Reloc, sectoff int64) int {
     50 	ld.Thearch.Lput(uint32(sectoff))
     51 
     52 	elfsym := r.Xsym.ElfsymForReloc()
     53 	switch r.Type {
     54 	default:
     55 		return -1
     56 
     57 	case obj.R_ADDR:
     58 		if r.Siz != 4 {
     59 			return -1
     60 		}
     61 		ld.Thearch.Lput(ld.R_MIPS_32 | uint32(elfsym)<<8)
     62 
     63 	case obj.R_ADDRMIPS:
     64 		ld.Thearch.Lput(ld.R_MIPS_LO16 | uint32(elfsym)<<8)
     65 
     66 	case obj.R_ADDRMIPSU:
     67 		ld.Thearch.Lput(ld.R_MIPS_HI16 | uint32(elfsym)<<8)
     68 
     69 	case obj.R_ADDRMIPSTLS:
     70 		ld.Thearch.Lput(ld.R_MIPS_TLS_TPREL_LO16 | uint32(elfsym)<<8)
     71 
     72 	case obj.R_CALLMIPS, obj.R_JMPMIPS:
     73 		ld.Thearch.Lput(ld.R_MIPS_26 | uint32(elfsym)<<8)
     74 	}
     75 
     76 	return 0
     77 }
     78 
     79 func elfsetupplt(ctxt *ld.Link) {
     80 	return
     81 }
     82 
     83 func machoreloc1(s *ld.Symbol, r *ld.Reloc, sectoff int64) int {
     84 	return -1
     85 }
     86 
     87 func applyrel(r *ld.Reloc, s *ld.Symbol, val *int64, t int64) {
     88 	o := ld.SysArch.ByteOrder.Uint32(s.P[r.Off:])
     89 	switch r.Type {
     90 	case obj.R_ADDRMIPS, obj.R_ADDRMIPSTLS:
     91 		*val = int64(o&0xffff0000 | uint32(t)&0xffff)
     92 	case obj.R_ADDRMIPSU:
     93 		*val = int64(o&0xffff0000 | uint32((t+(1<<15))>>16)&0xffff)
     94 	case obj.R_CALLMIPS, obj.R_JMPMIPS:
     95 		*val = int64(o&0xfc000000 | uint32(t>>2)&^0xfc000000)
     96 	}
     97 }
     98 
     99 func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) int {
    100 	if ld.Linkmode == ld.LinkExternal {
    101 		switch r.Type {
    102 		default:
    103 			return -1
    104 
    105 		case obj.R_ADDRMIPS, obj.R_ADDRMIPSU:
    106 
    107 			r.Done = 0
    108 
    109 			// set up addend for eventual relocation via outer symbol.
    110 			rs := r.Sym
    111 			r.Xadd = r.Add
    112 			for rs.Outer != nil {
    113 				r.Xadd += ld.Symaddr(rs) - ld.Symaddr(rs.Outer)
    114 				rs = rs.Outer
    115 			}
    116 
    117 			if rs.Type != obj.SHOSTOBJ && rs.Type != obj.SDYNIMPORT && rs.Sect == nil {
    118 				ld.Errorf(s, "missing section for %s", rs.Name)
    119 			}
    120 			r.Xsym = rs
    121 			applyrel(r, s, val, r.Xadd)
    122 			return 0
    123 
    124 		case obj.R_ADDRMIPSTLS, obj.R_CALLMIPS, obj.R_JMPMIPS:
    125 			r.Done = 0
    126 			r.Xsym = r.Sym
    127 			r.Xadd = r.Add
    128 			applyrel(r, s, val, r.Add)
    129 			return 0
    130 		}
    131 	}
    132 
    133 	switch r.Type {
    134 	case obj.R_CONST:
    135 		*val = r.Add
    136 		return 0
    137 
    138 	case obj.R_GOTOFF:
    139 		*val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0))
    140 		return 0
    141 
    142 	case obj.R_ADDRMIPS, obj.R_ADDRMIPSU:
    143 		t := ld.Symaddr(r.Sym) + r.Add
    144 		applyrel(r, s, val, t)
    145 		return 0
    146 
    147 	case obj.R_CALLMIPS, obj.R_JMPMIPS:
    148 		t := ld.Symaddr(r.Sym) + r.Add
    149 
    150 		if t&3 != 0 {
    151 			ld.Errorf(s, "direct call is not aligned: %s %x", r.Sym.Name, t)
    152 		}
    153 
    154 		// check if target address is in the same 256 MB region as the next instruction
    155 		if (s.Value+int64(r.Off)+4)&0xf0000000 != (t & 0xf0000000) {
    156 			ld.Errorf(s, "direct call too far: %s %x", r.Sym.Name, t)
    157 		}
    158 
    159 		applyrel(r, s, val, t)
    160 		return 0
    161 
    162 	case obj.R_ADDRMIPSTLS:
    163 		// thread pointer is at 0x7000 offset from the start of TLS data area
    164 		t := ld.Symaddr(r.Sym) + r.Add - 0x7000
    165 		if t < -32768 || t >= 32678 {
    166 			ld.Errorf(s, "TLS offset out of range %d", t)
    167 		}
    168 		applyrel(r, s, val, t)
    169 		return 0
    170 	}
    171 
    172 	return -1
    173 }
    174 
    175 func archrelocvariant(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, t int64) int64 {
    176 	return -1
    177 }
    178 
    179 func asmb(ctxt *ld.Link) {
    180 	if ctxt.Debugvlog != 0 {
    181 		ctxt.Logf("%5.2f asmb\n", obj.Cputime())
    182 	}
    183 
    184 	if ld.Iself {
    185 		ld.Asmbelfsetup()
    186 	}
    187 
    188 	sect := ld.Segtext.Sect
    189 	ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
    190 	ld.Codeblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
    191 	for sect = sect.Next; sect != nil; sect = sect.Next {
    192 		ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
    193 		ld.Datblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
    194 	}
    195 
    196 	if ld.Segrodata.Filelen > 0 {
    197 		if ctxt.Debugvlog != 0 {
    198 			ctxt.Logf("%5.2f rodatblk\n", obj.Cputime())
    199 		}
    200 
    201 		ld.Cseek(int64(ld.Segrodata.Fileoff))
    202 		ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
    203 	}
    204 
    205 	if ctxt.Debugvlog != 0 {
    206 		ctxt.Logf("%5.2f datblk\n", obj.Cputime())
    207 	}
    208 
    209 	ld.Cseek(int64(ld.Segdata.Fileoff))
    210 	ld.Datblk(ctxt, int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
    211 
    212 	ld.Cseek(int64(ld.Segdwarf.Fileoff))
    213 	ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
    214 
    215 	/* output symbol table */
    216 	ld.Symsize = 0
    217 
    218 	ld.Lcsize = 0
    219 	symo := uint32(0)
    220 	if !*ld.FlagS {
    221 		if !ld.Iself {
    222 			ld.Errorf(nil, "unsupported executable format")
    223 		}
    224 		if ctxt.Debugvlog != 0 {
    225 			ctxt.Logf("%5.2f sym\n", obj.Cputime())
    226 		}
    227 		symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
    228 		symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
    229 
    230 		ld.Cseek(int64(symo))
    231 		if ctxt.Debugvlog != 0 {
    232 			ctxt.Logf("%5.2f elfsym\n", obj.Cputime())
    233 		}
    234 		ld.Asmelfsym(ctxt)
    235 		ld.Cflush()
    236 		ld.Cwrite(ld.Elfstrdat)
    237 
    238 		if ctxt.Debugvlog != 0 {
    239 			ctxt.Logf("%5.2f dwarf\n", obj.Cputime())
    240 		}
    241 
    242 		if ld.Linkmode == ld.LinkExternal {
    243 			ld.Elfemitreloc(ctxt)
    244 		}
    245 	}
    246 
    247 	if ctxt.Debugvlog != 0 {
    248 		ctxt.Logf("%5.2f header\n", obj.Cputime())
    249 	}
    250 
    251 	ld.Cseek(0)
    252 	switch ld.Headtype {
    253 	default:
    254 		ld.Errorf(nil, "unsupported operating system")
    255 	case obj.Hlinux:
    256 		ld.Asmbelf(ctxt, int64(symo))
    257 	}
    258 
    259 	ld.Cflush()
    260 	if *ld.FlagC {
    261 		fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
    262 		fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
    263 		fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
    264 		fmt.Printf("symsize=%d\n", ld.Symsize)
    265 		fmt.Printf("lcsize=%d\n", ld.Lcsize)
    266 		fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))
    267 	}
    268 }
    269