Source file src/cmd/link/internal/mips/asm.go

     1  // Inferno utils/5l/asm.c
     2  // https://bitbucket.org/inferno-os/inferno-os/src/master/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 © 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/loader"
    38  	"cmd/link/internal/sym"
    39  	"debug/elf"
    40  )
    41  
    42  func gentext(ctxt *ld.Link, ldr *loader.Loader) {
    43  	return
    44  }
    45  
    46  func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, ri int, sectoff int64) bool {
    47  	out.Write32(uint32(sectoff))
    48  
    49  	elfsym := ld.ElfSymForReloc(ctxt, r.Xsym)
    50  	switch r.Type {
    51  	default:
    52  		return false
    53  	case objabi.R_ADDR, objabi.R_DWARFSECREF:
    54  		if r.Size != 4 {
    55  			return false
    56  		}
    57  		out.Write32(uint32(elf.R_MIPS_32) | uint32(elfsym)<<8)
    58  	case objabi.R_ADDRMIPS:
    59  		out.Write32(uint32(elf.R_MIPS_LO16) | uint32(elfsym)<<8)
    60  	case objabi.R_ADDRMIPSU:
    61  		out.Write32(uint32(elf.R_MIPS_HI16) | uint32(elfsym)<<8)
    62  	case objabi.R_ADDRMIPSTLS:
    63  		out.Write32(uint32(elf.R_MIPS_TLS_TPREL_LO16) | uint32(elfsym)<<8)
    64  	case objabi.R_CALLMIPS, objabi.R_JMPMIPS:
    65  		out.Write32(uint32(elf.R_MIPS_26) | uint32(elfsym)<<8)
    66  	}
    67  
    68  	return true
    69  }
    70  
    71  func elfsetupplt(ctxt *ld.Link, ldr *loader.Loader, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) {
    72  	return
    73  }
    74  
    75  func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool {
    76  	return false
    77  }
    78  
    79  func applyrel(arch *sys.Arch, ldr *loader.Loader, rt objabi.RelocType, off int32, s loader.Sym, val int64, t int64) int64 {
    80  	o := uint32(val)
    81  	switch rt {
    82  	case objabi.R_ADDRMIPS, objabi.R_ADDRMIPSTLS:
    83  		return int64(o&0xffff0000 | uint32(t)&0xffff)
    84  	case objabi.R_ADDRMIPSU:
    85  		return int64(o&0xffff0000 | uint32((t+(1<<15))>>16)&0xffff)
    86  	case objabi.R_CALLMIPS, objabi.R_JMPMIPS:
    87  		return int64(o&0xfc000000 | uint32(t>>2)&^0xfc000000)
    88  	default:
    89  		return val
    90  	}
    91  }
    92  
    93  func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) (o int64, nExtReloc int, ok bool) {
    94  	rs := r.Sym()
    95  	if target.IsExternal() {
    96  		switch r.Type() {
    97  		default:
    98  			return val, 0, false
    99  
   100  		case objabi.R_ADDRMIPS, objabi.R_ADDRMIPSU:
   101  			// set up addend for eventual relocation via outer symbol.
   102  			_, off := ld.FoldSubSymbolOffset(ldr, rs)
   103  			xadd := r.Add() + off
   104  			return applyrel(target.Arch, ldr, r.Type(), r.Off(), s, val, xadd), 1, true
   105  
   106  		case objabi.R_ADDRMIPSTLS, objabi.R_CALLMIPS, objabi.R_JMPMIPS:
   107  			return applyrel(target.Arch, ldr, r.Type(), r.Off(), s, val, r.Add()), 1, true
   108  		}
   109  	}
   110  
   111  	const isOk = true
   112  	const noExtReloc = 0
   113  	switch rt := r.Type(); rt {
   114  	case objabi.R_ADDRMIPS, objabi.R_ADDRMIPSU:
   115  		t := ldr.SymValue(rs) + r.Add()
   116  		return applyrel(target.Arch, ldr, rt, r.Off(), s, val, t), noExtReloc, isOk
   117  	case objabi.R_CALLMIPS, objabi.R_JMPMIPS:
   118  		t := ldr.SymValue(rs) + r.Add()
   119  
   120  		if t&3 != 0 {
   121  			ldr.Errorf(s, "direct call is not aligned: %s %x", ldr.SymName(rs), t)
   122  		}
   123  
   124  		// check if target address is in the same 256 MB region as the next instruction
   125  		if (ldr.SymValue(s)+int64(r.Off())+4)&0xf0000000 != (t & 0xf0000000) {
   126  			ldr.Errorf(s, "direct call too far: %s %x", ldr.SymName(rs), t)
   127  		}
   128  
   129  		return applyrel(target.Arch, ldr, rt, r.Off(), s, val, t), noExtReloc, isOk
   130  	case objabi.R_ADDRMIPSTLS:
   131  		// thread pointer is at 0x7000 offset from the start of TLS data area
   132  		t := ldr.SymValue(rs) + r.Add() - 0x7000
   133  		if t < -32768 || t >= 32678 {
   134  			ldr.Errorf(s, "TLS offset out of range %d", t)
   135  		}
   136  		return applyrel(target.Arch, ldr, rt, r.Off(), s, val, t), noExtReloc, isOk
   137  	}
   138  
   139  	return val, 0, false
   140  }
   141  
   142  func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc, sym.RelocVariant, loader.Sym, int64, []byte) int64 {
   143  	return -1
   144  }
   145  
   146  func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sym) (loader.ExtReloc, bool) {
   147  	switch r.Type() {
   148  	case objabi.R_ADDRMIPS, objabi.R_ADDRMIPSU:
   149  		return ld.ExtrelocViaOuterSym(ldr, r, s), true
   150  
   151  	case objabi.R_ADDRMIPSTLS, objabi.R_CALLMIPS, objabi.R_JMPMIPS:
   152  		return ld.ExtrelocSimple(ldr, r), true
   153  	}
   154  	return loader.ExtReloc{}, false
   155  }
   156  

View as plain text