Source file src/cmd/link/internal/mips64/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 © 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/loader"
    38  	"cmd/link/internal/sym"
    39  	"debug/elf"
    40  )
    41  
    42  func gentext(ctxt *ld.Link, ldr *loader.Loader) {}
    43  
    44  func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, ri int, sectoff int64) bool {
    45  
    46  	// mips64 ELF relocation (endian neutral)
    47  	//		offset	uint64
    48  	//		sym		uint32
    49  	//		ssym	uint8
    50  	//		type3	uint8
    51  	//		type2	uint8
    52  	//		type	uint8
    53  	//		addend	int64
    54  
    55  	addend := r.Xadd
    56  
    57  	out.Write64(uint64(sectoff))
    58  
    59  	elfsym := ld.ElfSymForReloc(ctxt, r.Xsym)
    60  	out.Write32(uint32(elfsym))
    61  	out.Write8(0)
    62  	out.Write8(0)
    63  	out.Write8(0)
    64  	switch r.Type {
    65  	default:
    66  		return false
    67  	case objabi.R_ADDR, objabi.R_DWARFSECREF:
    68  		switch r.Size {
    69  		case 4:
    70  			out.Write8(uint8(elf.R_MIPS_32))
    71  		case 8:
    72  			out.Write8(uint8(elf.R_MIPS_64))
    73  		default:
    74  			return false
    75  		}
    76  	case objabi.R_ADDRMIPS:
    77  		out.Write8(uint8(elf.R_MIPS_LO16))
    78  	case objabi.R_ADDRMIPSU:
    79  		out.Write8(uint8(elf.R_MIPS_HI16))
    80  	case objabi.R_ADDRMIPSTLS:
    81  		out.Write8(uint8(elf.R_MIPS_TLS_TPREL_LO16))
    82  		if ctxt.Target.IsOpenbsd() {
    83  			// OpenBSD mips64 does not currently offset TLS by 0x7000,
    84  			// as such we need to add this back to get the correct offset
    85  			// via the external linker.
    86  			addend += 0x7000
    87  		}
    88  	case objabi.R_CALLMIPS,
    89  		objabi.R_JMPMIPS:
    90  		out.Write8(uint8(elf.R_MIPS_26))
    91  	}
    92  	out.Write64(uint64(addend))
    93  
    94  	return true
    95  }
    96  
    97  func elfsetupplt(ctxt *ld.Link, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) {
    98  	return
    99  }
   100  
   101  func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool {
   102  	return false
   103  }
   104  
   105  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) {
   106  	if target.IsExternal() {
   107  		switch r.Type() {
   108  		default:
   109  			return val, 0, false
   110  
   111  		case objabi.R_ADDRMIPS,
   112  			objabi.R_ADDRMIPSU,
   113  			objabi.R_ADDRMIPSTLS,
   114  			objabi.R_CALLMIPS,
   115  			objabi.R_JMPMIPS:
   116  			return val, 1, true
   117  		}
   118  	}
   119  
   120  	const isOk = true
   121  	const noExtReloc = 0
   122  	rs := r.Sym()
   123  	switch r.Type() {
   124  	case objabi.R_ADDRMIPS,
   125  		objabi.R_ADDRMIPSU:
   126  		t := ldr.SymValue(rs) + r.Add()
   127  		if r.Type() == objabi.R_ADDRMIPS {
   128  			return int64(val&0xffff0000 | t&0xffff), noExtReloc, isOk
   129  		}
   130  		return int64(val&0xffff0000 | ((t+1<<15)>>16)&0xffff), noExtReloc, isOk
   131  	case objabi.R_ADDRMIPSTLS:
   132  		// thread pointer is at 0x7000 offset from the start of TLS data area
   133  		t := ldr.SymValue(rs) + r.Add() - 0x7000
   134  		if target.IsOpenbsd() {
   135  			// OpenBSD mips64 does not currently offset TLS by 0x7000,
   136  			// as such we need to add this back to get the correct offset.
   137  			t += 0x7000
   138  		}
   139  		if t < -32768 || t >= 32678 {
   140  			ldr.Errorf(s, "TLS offset out of range %d", t)
   141  		}
   142  		return int64(val&0xffff0000 | t&0xffff), noExtReloc, isOk
   143  	case objabi.R_CALLMIPS,
   144  		objabi.R_JMPMIPS:
   145  		// Low 26 bits = (S + A) >> 2
   146  		t := ldr.SymValue(rs) + r.Add()
   147  		return int64(val&0xfc000000 | (t>>2)&^0xfc000000), noExtReloc, isOk
   148  	}
   149  
   150  	return val, 0, false
   151  }
   152  
   153  func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc, sym.RelocVariant, loader.Sym, int64, []byte) int64 {
   154  	return -1
   155  }
   156  
   157  func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sym) (loader.ExtReloc, bool) {
   158  	switch r.Type() {
   159  	case objabi.R_ADDRMIPS,
   160  		objabi.R_ADDRMIPSU:
   161  		return ld.ExtrelocViaOuterSym(ldr, r, s), true
   162  
   163  	case objabi.R_ADDRMIPSTLS,
   164  		objabi.R_CALLMIPS,
   165  		objabi.R_JMPMIPS:
   166  		return ld.ExtrelocSimple(ldr, r), true
   167  	}
   168  	return loader.ExtReloc{}, false
   169  }
   170  

View as plain text