1 // Derived from Inferno utils/6l/obj.c and utils/6l/span.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/6l/obj.c 3 // http://code.google.com/p/inferno-os/source/browse/utils/6l/span.c 4 // 5 // Copyright 1994-1999 Lucent Technologies Inc. All rights reserved. 6 // Portions Copyright 1995-1997 C H Forsyth (forsyth (a] terzarima.net) 7 // Portions Copyright 1997-1999 Vita Nuova Limited 8 // Portions Copyright 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 9 // Portions Copyright 2004,2006 Bruce Ellis 10 // Portions Copyright 2005-2007 C H Forsyth (forsyth (a] terzarima.net) 11 // Revisions Copyright 2000-2007 Lucent Technologies Inc. and others 12 // Portions Copyright 2009 The Go Authors. All rights reserved. 13 // 14 // Permission is hereby granted, free of charge, to any person obtaining a copy 15 // of this software and associated documentation files (the "Software"), to deal 16 // in the Software without restriction, including without limitation the rights 17 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 // copies of the Software, and to permit persons to whom the Software is 19 // furnished to do so, subject to the following conditions: 20 // 21 // The above copyright notice and this permission notice shall be included in 22 // all copies or substantial portions of the Software. 23 // 24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 30 // THE SOFTWARE. 31 32 package obj 33 34 import ( 35 "log" 36 "math" 37 ) 38 39 func mangle(file string) { 40 log.Fatalf("%s: mangled input file", file) 41 } 42 43 func Symgrow(ctxt *Link, s *LSym, lsiz int64) { 44 siz := int(lsiz) 45 if int64(siz) != lsiz { 46 log.Fatalf("Symgrow size %d too long", lsiz) 47 } 48 if len(s.P) >= siz { 49 return 50 } 51 for cap(s.P) < siz { 52 s.P = append(s.P[:cap(s.P)], 0) 53 } 54 s.P = s.P[:siz] 55 } 56 57 func savedata(ctxt *Link, s *LSym, p *Prog, pn string) { 58 off := int32(p.From.Offset) 59 siz := int32(p.From3.Offset) 60 if off < 0 || siz < 0 || off >= 1<<30 || siz >= 100 { 61 mangle(pn) 62 } 63 if ctxt.Enforce_data_order != 0 && off < int32(len(s.P)) { 64 ctxt.Diag("data out of order (already have %d)\n%v", len(s.P), p) 65 } 66 Symgrow(ctxt, s, int64(off+siz)) 67 68 switch int(p.To.Type) { 69 default: 70 ctxt.Diag("bad data: %v", p) 71 72 case TYPE_FCONST: 73 switch siz { 74 default: 75 ctxt.Diag("unexpected %d-byte floating point constant", siz) 76 77 case 4: 78 flt := math.Float32bits(float32(p.To.Val.(float64))) 79 ctxt.Arch.ByteOrder.PutUint32(s.P[off:], flt) 80 81 case 8: 82 flt := math.Float64bits(p.To.Val.(float64)) 83 ctxt.Arch.ByteOrder.PutUint64(s.P[off:], flt) 84 } 85 86 case TYPE_SCONST: 87 copy(s.P[off:off+siz], p.To.Val.(string)) 88 89 case TYPE_CONST, TYPE_ADDR: 90 if p.To.Sym != nil || int(p.To.Type) == TYPE_ADDR { 91 r := Addrel(s) 92 r.Off = off 93 r.Siz = uint8(siz) 94 r.Sym = p.To.Sym 95 r.Type = R_ADDR 96 r.Add = p.To.Offset 97 break 98 } 99 o := p.To.Offset 100 switch siz { 101 default: 102 ctxt.Diag("unexpected %d-byte integer constant", siz) 103 case 1: 104 s.P[off] = byte(o) 105 case 2: 106 ctxt.Arch.ByteOrder.PutUint16(s.P[off:], uint16(o)) 107 case 4: 108 ctxt.Arch.ByteOrder.PutUint32(s.P[off:], uint32(o)) 109 case 8: 110 ctxt.Arch.ByteOrder.PutUint64(s.P[off:], uint64(o)) 111 } 112 } 113 } 114 115 func Addrel(s *LSym) *Reloc { 116 s.R = append(s.R, Reloc{}) 117 return &s.R[len(s.R)-1] 118 } 119 120 func Setuintxx(ctxt *Link, s *LSym, off int64, v uint64, wid int64) int64 { 121 if s.Type == 0 { 122 s.Type = SDATA 123 } 124 if s.Size < off+wid { 125 s.Size = off + wid 126 Symgrow(ctxt, s, s.Size) 127 } 128 129 switch wid { 130 case 1: 131 s.P[off] = uint8(v) 132 case 2: 133 ctxt.Arch.ByteOrder.PutUint16(s.P[off:], uint16(v)) 134 case 4: 135 ctxt.Arch.ByteOrder.PutUint32(s.P[off:], uint32(v)) 136 case 8: 137 ctxt.Arch.ByteOrder.PutUint64(s.P[off:], uint64(v)) 138 } 139 140 return off + wid 141 } 142 143 func adduintxx(ctxt *Link, s *LSym, v uint64, wid int) int64 { 144 off := s.Size 145 Setuintxx(ctxt, s, off, v, int64(wid)) 146 return off 147 } 148 149 func adduint8(ctxt *Link, s *LSym, v uint8) int64 { 150 return adduintxx(ctxt, s, uint64(v), 1) 151 } 152 153 func adduint16(ctxt *Link, s *LSym, v uint16) int64 { 154 return adduintxx(ctxt, s, uint64(v), 2) 155 } 156 157 func Adduint32(ctxt *Link, s *LSym, v uint32) int64 { 158 return adduintxx(ctxt, s, uint64(v), 4) 159 } 160 161 func Adduint64(ctxt *Link, s *LSym, v uint64) int64 { 162 return adduintxx(ctxt, s, v, 8) 163 } 164 165 func setuint8(ctxt *Link, s *LSym, r int64, v uint8) int64 { 166 return Setuintxx(ctxt, s, r, uint64(v), 1) 167 } 168 169 func setuint16(ctxt *Link, s *LSym, r int64, v uint16) int64 { 170 return Setuintxx(ctxt, s, r, uint64(v), 2) 171 } 172 173 func setuint32(ctxt *Link, s *LSym, r int64, v uint32) int64 { 174 return Setuintxx(ctxt, s, r, uint64(v), 4) 175 } 176 177 func setuint64(ctxt *Link, s *LSym, r int64, v uint64) int64 { 178 return Setuintxx(ctxt, s, r, v, 8) 179 } 180 181 func addaddrplus(ctxt *Link, s *LSym, t *LSym, add int64) int64 { 182 if s.Type == 0 { 183 s.Type = SDATA 184 } 185 i := s.Size 186 s.Size += int64(ctxt.Arch.Ptrsize) 187 Symgrow(ctxt, s, s.Size) 188 r := Addrel(s) 189 r.Sym = t 190 r.Off = int32(i) 191 r.Siz = uint8(ctxt.Arch.Ptrsize) 192 r.Type = R_ADDR 193 r.Add = add 194 return i + int64(r.Siz) 195 } 196 197 func addpcrelplus(ctxt *Link, s *LSym, t *LSym, add int64) int64 { 198 if s.Type == 0 { 199 s.Type = SDATA 200 } 201 i := s.Size 202 s.Size += 4 203 Symgrow(ctxt, s, s.Size) 204 r := Addrel(s) 205 r.Sym = t 206 r.Off = int32(i) 207 r.Add = add 208 r.Type = R_PCREL 209 r.Siz = 4 210 return i + int64(r.Siz) 211 } 212 213 func addaddr(ctxt *Link, s *LSym, t *LSym) int64 { 214 return addaddrplus(ctxt, s, t, 0) 215 } 216 217 func setaddrplus(ctxt *Link, s *LSym, off int64, t *LSym, add int64) int64 { 218 if s.Type == 0 { 219 s.Type = SDATA 220 } 221 if off+int64(ctxt.Arch.Ptrsize) > s.Size { 222 s.Size = off + int64(ctxt.Arch.Ptrsize) 223 Symgrow(ctxt, s, s.Size) 224 } 225 226 r := Addrel(s) 227 r.Sym = t 228 r.Off = int32(off) 229 r.Siz = uint8(ctxt.Arch.Ptrsize) 230 r.Type = R_ADDR 231 r.Add = add 232 return off + int64(r.Siz) 233 } 234 235 func setaddr(ctxt *Link, s *LSym, off int64, t *LSym) int64 { 236 return setaddrplus(ctxt, s, off, t, 0) 237 } 238 239 func addsize(ctxt *Link, s *LSym, t *LSym) int64 { 240 if s.Type == 0 { 241 s.Type = SDATA 242 } 243 i := s.Size 244 s.Size += int64(ctxt.Arch.Ptrsize) 245 Symgrow(ctxt, s, s.Size) 246 r := Addrel(s) 247 r.Sym = t 248 r.Off = int32(i) 249 r.Siz = uint8(ctxt.Arch.Ptrsize) 250 r.Type = R_SIZE 251 return i + int64(r.Siz) 252 } 253 254 func addaddrplus4(ctxt *Link, s *LSym, t *LSym, add int64) int64 { 255 if s.Type == 0 { 256 s.Type = SDATA 257 } 258 i := s.Size 259 s.Size += 4 260 Symgrow(ctxt, s, s.Size) 261 r := Addrel(s) 262 r.Sym = t 263 r.Off = int32(i) 264 r.Siz = 4 265 r.Type = R_ADDR 266 r.Add = add 267 return i + int64(r.Siz) 268 } 269