...

Source file src/cmd/internal/obj/data.go

     1	// Derived from Inferno utils/6l/obj.c and utils/6l/span.c
     2	// https://bitbucket.org/inferno-os/inferno-os/src/default/utils/6l/obj.c
     3	// https://bitbucket.org/inferno-os/inferno-os/src/default/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		"cmd/internal/objabi"
    36		"log"
    37		"math"
    38	)
    39	
    40	// Grow increases the length of s.P to lsiz.
    41	func (s *LSym) Grow(lsiz int64) {
    42		siz := int(lsiz)
    43		if int64(siz) != lsiz {
    44			log.Fatalf("LSym.Grow size %d too long", lsiz)
    45		}
    46		if len(s.P) >= siz {
    47			return
    48		}
    49		s.P = append(s.P, make([]byte, siz-len(s.P))...)
    50	}
    51	
    52	// GrowCap increases the capacity of s.P to c.
    53	func (s *LSym) GrowCap(c int64) {
    54		if int64(cap(s.P)) >= c {
    55			return
    56		}
    57		if s.P == nil {
    58			s.P = make([]byte, 0, c)
    59			return
    60		}
    61		b := make([]byte, len(s.P), c)
    62		copy(b, s.P)
    63		s.P = b
    64	}
    65	
    66	// prepwrite prepares to write data of size siz into s at offset off.
    67	func (s *LSym) prepwrite(ctxt *Link, off int64, siz int) {
    68		if off < 0 || siz < 0 || off >= 1<<30 {
    69			ctxt.Diag("prepwrite: bad off=%d siz=%d s=%v", off, siz, s)
    70		}
    71		switch s.Type {
    72		case objabi.Sxxx, objabi.SBSS:
    73			s.Type = objabi.SDATA
    74		case objabi.SNOPTRBSS:
    75			s.Type = objabi.SNOPTRDATA
    76		case objabi.STLSBSS:
    77			ctxt.Diag("cannot supply data for %v var %v", s.Type, s.Name)
    78		}
    79		l := off + int64(siz)
    80		s.Grow(l)
    81		if l > s.Size {
    82			s.Size = l
    83		}
    84	}
    85	
    86	// WriteFloat32 writes f into s at offset off.
    87	func (s *LSym) WriteFloat32(ctxt *Link, off int64, f float32) {
    88		s.prepwrite(ctxt, off, 4)
    89		ctxt.Arch.ByteOrder.PutUint32(s.P[off:], math.Float32bits(f))
    90	}
    91	
    92	// WriteFloat64 writes f into s at offset off.
    93	func (s *LSym) WriteFloat64(ctxt *Link, off int64, f float64) {
    94		s.prepwrite(ctxt, off, 8)
    95		ctxt.Arch.ByteOrder.PutUint64(s.P[off:], math.Float64bits(f))
    96	}
    97	
    98	// WriteInt writes an integer i of size siz into s at offset off.
    99	func (s *LSym) WriteInt(ctxt *Link, off int64, siz int, i int64) {
   100		s.prepwrite(ctxt, off, siz)
   101		switch siz {
   102		default:
   103			ctxt.Diag("WriteInt: bad integer size: %d", siz)
   104		case 1:
   105			s.P[off] = byte(i)
   106		case 2:
   107			ctxt.Arch.ByteOrder.PutUint16(s.P[off:], uint16(i))
   108		case 4:
   109			ctxt.Arch.ByteOrder.PutUint32(s.P[off:], uint32(i))
   110		case 8:
   111			ctxt.Arch.ByteOrder.PutUint64(s.P[off:], uint64(i))
   112		}
   113	}
   114	
   115	func (s *LSym) writeAddr(ctxt *Link, off int64, siz int, rsym *LSym, roff int64, rtype objabi.RelocType) {
   116		// Allow 4-byte addresses for DWARF.
   117		if siz != ctxt.Arch.PtrSize && siz != 4 {
   118			ctxt.Diag("WriteAddr: bad address size %d in %s", siz, s.Name)
   119		}
   120		s.prepwrite(ctxt, off, siz)
   121		r := Addrel(s)
   122		r.Off = int32(off)
   123		if int64(r.Off) != off {
   124			ctxt.Diag("WriteAddr: off overflow %d in %s", off, s.Name)
   125		}
   126		r.Siz = uint8(siz)
   127		r.Sym = rsym
   128		r.Type = rtype
   129		r.Add = roff
   130	}
   131	
   132	// WriteAddr writes an address of size siz into s at offset off.
   133	// rsym and roff specify the relocation for the address.
   134	func (s *LSym) WriteAddr(ctxt *Link, off int64, siz int, rsym *LSym, roff int64) {
   135		s.writeAddr(ctxt, off, siz, rsym, roff, objabi.R_ADDR)
   136	}
   137	
   138	// WriteCURelativeAddr writes a pointer-sized address into s at offset off.
   139	// rsym and roff specify the relocation for the address which will be
   140	// resolved by the linker to an offset from the DW_AT_low_pc attribute of
   141	// the DWARF Compile Unit of rsym.
   142	func (s *LSym) WriteCURelativeAddr(ctxt *Link, off int64, rsym *LSym, roff int64) {
   143		s.writeAddr(ctxt, off, ctxt.Arch.PtrSize, rsym, roff, objabi.R_ADDRCUOFF)
   144	}
   145	
   146	// WriteOff writes a 4 byte offset to rsym+roff into s at offset off.
   147	// After linking the 4 bytes stored at s+off will be
   148	// rsym+roff-(start of section that s is in).
   149	func (s *LSym) WriteOff(ctxt *Link, off int64, rsym *LSym, roff int64) {
   150		s.prepwrite(ctxt, off, 4)
   151		r := Addrel(s)
   152		r.Off = int32(off)
   153		if int64(r.Off) != off {
   154			ctxt.Diag("WriteOff: off overflow %d in %s", off, s.Name)
   155		}
   156		r.Siz = 4
   157		r.Sym = rsym
   158		r.Type = objabi.R_ADDROFF
   159		r.Add = roff
   160	}
   161	
   162	// WriteWeakOff writes a weak 4 byte offset to rsym+roff into s at offset off.
   163	// After linking the 4 bytes stored at s+off will be
   164	// rsym+roff-(start of section that s is in).
   165	func (s *LSym) WriteWeakOff(ctxt *Link, off int64, rsym *LSym, roff int64) {
   166		s.prepwrite(ctxt, off, 4)
   167		r := Addrel(s)
   168		r.Off = int32(off)
   169		if int64(r.Off) != off {
   170			ctxt.Diag("WriteOff: off overflow %d in %s", off, s.Name)
   171		}
   172		r.Siz = 4
   173		r.Sym = rsym
   174		r.Type = objabi.R_WEAKADDROFF
   175		r.Add = roff
   176	}
   177	
   178	// WriteString writes a string of size siz into s at offset off.
   179	func (s *LSym) WriteString(ctxt *Link, off int64, siz int, str string) {
   180		if siz < len(str) {
   181			ctxt.Diag("WriteString: bad string size: %d < %d", siz, len(str))
   182		}
   183		s.prepwrite(ctxt, off, siz)
   184		copy(s.P[off:off+int64(siz)], str)
   185	}
   186	
   187	// WriteBytes writes a slice of bytes into s at offset off.
   188	func (s *LSym) WriteBytes(ctxt *Link, off int64, b []byte) int64 {
   189		s.prepwrite(ctxt, off, len(b))
   190		copy(s.P[off:], b)
   191		return off + int64(len(b))
   192	}
   193	
   194	func Addrel(s *LSym) *Reloc {
   195		if s.R == nil {
   196			s.R = make([]Reloc, 0, 4)
   197		}
   198		s.R = append(s.R, Reloc{})
   199		return &s.R[len(s.R)-1]
   200	}
   201	

View as plain text