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