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