data.go 6.4 KB

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