github.com/huandu/go@v0.0.0-20151114150818-04e615e41150/src/cmd/internal/obj/data.go (about)

     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@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@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  }