Home | History | Annotate | Download | only in obj
      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