data.go raw
1 // Derived from Inferno utils/6l/obj.c and utils/6l/span.c
2 // https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/obj.c
3 // https://bitbucket.org/inferno-os/inferno-os/src/master/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 "github.com/twitchyliquid64/golang-asm/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