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