objfile.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755
  1. // Copyright 2013 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // Writing Go object files.
  5. package obj
  6. import (
  7. "bytes"
  8. "github.com/twitchyliquid64/golang-asm/bio"
  9. "github.com/twitchyliquid64/golang-asm/goobj"
  10. "github.com/twitchyliquid64/golang-asm/objabi"
  11. "github.com/twitchyliquid64/golang-asm/sys"
  12. "crypto/sha1"
  13. "encoding/binary"
  14. "fmt"
  15. "io"
  16. "path/filepath"
  17. "sort"
  18. "strings"
  19. )
  20. // Entry point of writing new object file.
  21. func WriteObjFile(ctxt *Link, b *bio.Writer) {
  22. debugAsmEmit(ctxt)
  23. genFuncInfoSyms(ctxt)
  24. w := writer{
  25. Writer: goobj.NewWriter(b),
  26. ctxt: ctxt,
  27. pkgpath: objabi.PathToPrefix(ctxt.Pkgpath),
  28. }
  29. start := b.Offset()
  30. w.init()
  31. // Header
  32. // We just reserve the space. We'll fill in the offsets later.
  33. flags := uint32(0)
  34. if ctxt.Flag_shared {
  35. flags |= goobj.ObjFlagShared
  36. }
  37. if w.pkgpath == "" {
  38. flags |= goobj.ObjFlagNeedNameExpansion
  39. }
  40. if ctxt.IsAsm {
  41. flags |= goobj.ObjFlagFromAssembly
  42. }
  43. h := goobj.Header{
  44. Magic: goobj.Magic,
  45. Fingerprint: ctxt.Fingerprint,
  46. Flags: flags,
  47. }
  48. h.Write(w.Writer)
  49. // String table
  50. w.StringTable()
  51. // Autolib
  52. h.Offsets[goobj.BlkAutolib] = w.Offset()
  53. for i := range ctxt.Imports {
  54. ctxt.Imports[i].Write(w.Writer)
  55. }
  56. // Package references
  57. h.Offsets[goobj.BlkPkgIdx] = w.Offset()
  58. for _, pkg := range w.pkglist {
  59. w.StringRef(pkg)
  60. }
  61. // File table (for DWARF and pcln generation).
  62. h.Offsets[goobj.BlkFile] = w.Offset()
  63. for _, f := range ctxt.PosTable.FileTable() {
  64. w.StringRef(filepath.ToSlash(f))
  65. }
  66. // Symbol definitions
  67. h.Offsets[goobj.BlkSymdef] = w.Offset()
  68. for _, s := range ctxt.defs {
  69. w.Sym(s)
  70. }
  71. // Short hashed symbol definitions
  72. h.Offsets[goobj.BlkHashed64def] = w.Offset()
  73. for _, s := range ctxt.hashed64defs {
  74. w.Sym(s)
  75. }
  76. // Hashed symbol definitions
  77. h.Offsets[goobj.BlkHasheddef] = w.Offset()
  78. for _, s := range ctxt.hasheddefs {
  79. w.Sym(s)
  80. }
  81. // Non-pkg symbol definitions
  82. h.Offsets[goobj.BlkNonpkgdef] = w.Offset()
  83. for _, s := range ctxt.nonpkgdefs {
  84. w.Sym(s)
  85. }
  86. // Non-pkg symbol references
  87. h.Offsets[goobj.BlkNonpkgref] = w.Offset()
  88. for _, s := range ctxt.nonpkgrefs {
  89. w.Sym(s)
  90. }
  91. // Referenced package symbol flags
  92. h.Offsets[goobj.BlkRefFlags] = w.Offset()
  93. w.refFlags()
  94. // Hashes
  95. h.Offsets[goobj.BlkHash64] = w.Offset()
  96. for _, s := range ctxt.hashed64defs {
  97. w.Hash64(s)
  98. }
  99. h.Offsets[goobj.BlkHash] = w.Offset()
  100. for _, s := range ctxt.hasheddefs {
  101. w.Hash(s)
  102. }
  103. // TODO: hashedrefs unused/unsupported for now
  104. // Reloc indexes
  105. h.Offsets[goobj.BlkRelocIdx] = w.Offset()
  106. nreloc := uint32(0)
  107. lists := [][]*LSym{ctxt.defs, ctxt.hashed64defs, ctxt.hasheddefs, ctxt.nonpkgdefs}
  108. for _, list := range lists {
  109. for _, s := range list {
  110. w.Uint32(nreloc)
  111. nreloc += uint32(len(s.R))
  112. }
  113. }
  114. w.Uint32(nreloc)
  115. // Symbol Info indexes
  116. h.Offsets[goobj.BlkAuxIdx] = w.Offset()
  117. naux := uint32(0)
  118. for _, list := range lists {
  119. for _, s := range list {
  120. w.Uint32(naux)
  121. naux += uint32(nAuxSym(s))
  122. }
  123. }
  124. w.Uint32(naux)
  125. // Data indexes
  126. h.Offsets[goobj.BlkDataIdx] = w.Offset()
  127. dataOff := uint32(0)
  128. for _, list := range lists {
  129. for _, s := range list {
  130. w.Uint32(dataOff)
  131. dataOff += uint32(len(s.P))
  132. }
  133. }
  134. w.Uint32(dataOff)
  135. // Relocs
  136. h.Offsets[goobj.BlkReloc] = w.Offset()
  137. for _, list := range lists {
  138. for _, s := range list {
  139. for i := range s.R {
  140. w.Reloc(&s.R[i])
  141. }
  142. }
  143. }
  144. // Aux symbol info
  145. h.Offsets[goobj.BlkAux] = w.Offset()
  146. for _, list := range lists {
  147. for _, s := range list {
  148. w.Aux(s)
  149. }
  150. }
  151. // Data
  152. h.Offsets[goobj.BlkData] = w.Offset()
  153. for _, list := range lists {
  154. for _, s := range list {
  155. w.Bytes(s.P)
  156. }
  157. }
  158. // Pcdata
  159. h.Offsets[goobj.BlkPcdata] = w.Offset()
  160. for _, s := range ctxt.Text { // iteration order must match genFuncInfoSyms
  161. if s.Func != nil {
  162. pc := &s.Func.Pcln
  163. w.Bytes(pc.Pcsp.P)
  164. w.Bytes(pc.Pcfile.P)
  165. w.Bytes(pc.Pcline.P)
  166. w.Bytes(pc.Pcinline.P)
  167. for i := range pc.Pcdata {
  168. w.Bytes(pc.Pcdata[i].P)
  169. }
  170. }
  171. }
  172. // Blocks used only by tools (objdump, nm).
  173. // Referenced symbol names from other packages
  174. h.Offsets[goobj.BlkRefName] = w.Offset()
  175. w.refNames()
  176. h.Offsets[goobj.BlkEnd] = w.Offset()
  177. // Fix up block offsets in the header
  178. end := start + int64(w.Offset())
  179. b.MustSeek(start, 0)
  180. h.Write(w.Writer)
  181. b.MustSeek(end, 0)
  182. }
  183. type writer struct {
  184. *goobj.Writer
  185. ctxt *Link
  186. pkgpath string // the package import path (escaped), "" if unknown
  187. pkglist []string // list of packages referenced, indexed by ctxt.pkgIdx
  188. }
  189. // prepare package index list
  190. func (w *writer) init() {
  191. w.pkglist = make([]string, len(w.ctxt.pkgIdx)+1)
  192. w.pkglist[0] = "" // dummy invalid package for index 0
  193. for pkg, i := range w.ctxt.pkgIdx {
  194. w.pkglist[i] = pkg
  195. }
  196. }
  197. func (w *writer) StringTable() {
  198. w.AddString("")
  199. for _, p := range w.ctxt.Imports {
  200. w.AddString(p.Pkg)
  201. }
  202. for _, pkg := range w.pkglist {
  203. w.AddString(pkg)
  204. }
  205. w.ctxt.traverseSyms(traverseAll, func(s *LSym) {
  206. // TODO: this includes references of indexed symbols from other packages,
  207. // for which the linker doesn't need the name. Consider moving them to
  208. // a separate block (for tools only).
  209. if w.pkgpath != "" {
  210. s.Name = strings.Replace(s.Name, "\"\".", w.pkgpath+".", -1)
  211. }
  212. // Don't put names of builtins into the string table (to save
  213. // space).
  214. if s.PkgIdx == goobj.PkgIdxBuiltin {
  215. return
  216. }
  217. w.AddString(s.Name)
  218. })
  219. // All filenames are in the postable.
  220. for _, f := range w.ctxt.PosTable.FileTable() {
  221. w.AddString(filepath.ToSlash(f))
  222. }
  223. }
  224. func (w *writer) Sym(s *LSym) {
  225. abi := uint16(s.ABI())
  226. if s.Static() {
  227. abi = goobj.SymABIstatic
  228. }
  229. flag := uint8(0)
  230. if s.DuplicateOK() {
  231. flag |= goobj.SymFlagDupok
  232. }
  233. if s.Local() {
  234. flag |= goobj.SymFlagLocal
  235. }
  236. if s.MakeTypelink() {
  237. flag |= goobj.SymFlagTypelink
  238. }
  239. if s.Leaf() {
  240. flag |= goobj.SymFlagLeaf
  241. }
  242. if s.NoSplit() {
  243. flag |= goobj.SymFlagNoSplit
  244. }
  245. if s.ReflectMethod() {
  246. flag |= goobj.SymFlagReflectMethod
  247. }
  248. if s.TopFrame() {
  249. flag |= goobj.SymFlagTopFrame
  250. }
  251. if strings.HasPrefix(s.Name, "type.") && s.Name[5] != '.' && s.Type == objabi.SRODATA {
  252. flag |= goobj.SymFlagGoType
  253. }
  254. flag2 := uint8(0)
  255. if s.UsedInIface() {
  256. flag2 |= goobj.SymFlagUsedInIface
  257. }
  258. if strings.HasPrefix(s.Name, "go.itab.") && s.Type == objabi.SRODATA {
  259. flag2 |= goobj.SymFlagItab
  260. }
  261. name := s.Name
  262. if strings.HasPrefix(name, "gofile..") {
  263. name = filepath.ToSlash(name)
  264. }
  265. var align uint32
  266. if s.Func != nil {
  267. align = uint32(s.Func.Align)
  268. }
  269. if s.ContentAddressable() {
  270. // We generally assume data symbols are natually aligned,
  271. // except for strings. If we dedup a string symbol and a
  272. // non-string symbol with the same content, we should keep
  273. // the largest alignment.
  274. // TODO: maybe the compiler could set the alignment for all
  275. // data symbols more carefully.
  276. if s.Size != 0 && !strings.HasPrefix(s.Name, "go.string.") {
  277. switch {
  278. case w.ctxt.Arch.PtrSize == 8 && s.Size%8 == 0:
  279. align = 8
  280. case s.Size%4 == 0:
  281. align = 4
  282. case s.Size%2 == 0:
  283. align = 2
  284. }
  285. // don't bother setting align to 1.
  286. }
  287. }
  288. var o goobj.Sym
  289. o.SetName(name, w.Writer)
  290. o.SetABI(abi)
  291. o.SetType(uint8(s.Type))
  292. o.SetFlag(flag)
  293. o.SetFlag2(flag2)
  294. o.SetSiz(uint32(s.Size))
  295. o.SetAlign(align)
  296. o.Write(w.Writer)
  297. }
  298. func (w *writer) Hash64(s *LSym) {
  299. if !s.ContentAddressable() || len(s.R) != 0 {
  300. panic("Hash of non-content-addresable symbol")
  301. }
  302. b := contentHash64(s)
  303. w.Bytes(b[:])
  304. }
  305. func (w *writer) Hash(s *LSym) {
  306. if !s.ContentAddressable() {
  307. panic("Hash of non-content-addresable symbol")
  308. }
  309. b := w.contentHash(s)
  310. w.Bytes(b[:])
  311. }
  312. func contentHash64(s *LSym) goobj.Hash64Type {
  313. var b goobj.Hash64Type
  314. copy(b[:], s.P)
  315. return b
  316. }
  317. // Compute the content hash for a content-addressable symbol.
  318. // We build a content hash based on its content and relocations.
  319. // Depending on the category of the referenced symbol, we choose
  320. // different hash algorithms such that the hash is globally
  321. // consistent.
  322. // - For referenced content-addressable symbol, its content hash
  323. // is globally consistent.
  324. // - For package symbol and builtin symbol, its local index is
  325. // globally consistent.
  326. // - For non-package symbol, its fully-expanded name is globally
  327. // consistent. For now, we require we know the current package
  328. // path so we can always expand symbol names. (Otherwise,
  329. // symbols with relocations are not considered hashable.)
  330. //
  331. // For now, we assume there is no circular dependencies among
  332. // hashed symbols.
  333. func (w *writer) contentHash(s *LSym) goobj.HashType {
  334. h := sha1.New()
  335. // The compiler trims trailing zeros _sometimes_. We just do
  336. // it always.
  337. h.Write(bytes.TrimRight(s.P, "\x00"))
  338. var tmp [14]byte
  339. for i := range s.R {
  340. r := &s.R[i]
  341. binary.LittleEndian.PutUint32(tmp[:4], uint32(r.Off))
  342. tmp[4] = r.Siz
  343. tmp[5] = uint8(r.Type)
  344. binary.LittleEndian.PutUint64(tmp[6:14], uint64(r.Add))
  345. h.Write(tmp[:])
  346. rs := r.Sym
  347. switch rs.PkgIdx {
  348. case goobj.PkgIdxHashed64:
  349. h.Write([]byte{0})
  350. t := contentHash64(rs)
  351. h.Write(t[:])
  352. case goobj.PkgIdxHashed:
  353. h.Write([]byte{1})
  354. t := w.contentHash(rs)
  355. h.Write(t[:])
  356. case goobj.PkgIdxNone:
  357. h.Write([]byte{2})
  358. io.WriteString(h, rs.Name) // name is already expanded at this point
  359. case goobj.PkgIdxBuiltin:
  360. h.Write([]byte{3})
  361. binary.LittleEndian.PutUint32(tmp[:4], uint32(rs.SymIdx))
  362. h.Write(tmp[:4])
  363. case goobj.PkgIdxSelf:
  364. io.WriteString(h, w.pkgpath)
  365. binary.LittleEndian.PutUint32(tmp[:4], uint32(rs.SymIdx))
  366. h.Write(tmp[:4])
  367. default:
  368. io.WriteString(h, rs.Pkg)
  369. binary.LittleEndian.PutUint32(tmp[:4], uint32(rs.SymIdx))
  370. h.Write(tmp[:4])
  371. }
  372. }
  373. var b goobj.HashType
  374. copy(b[:], h.Sum(nil))
  375. return b
  376. }
  377. func makeSymRef(s *LSym) goobj.SymRef {
  378. if s == nil {
  379. return goobj.SymRef{}
  380. }
  381. if s.PkgIdx == 0 || !s.Indexed() {
  382. fmt.Printf("unindexed symbol reference: %v\n", s)
  383. panic("unindexed symbol reference")
  384. }
  385. return goobj.SymRef{PkgIdx: uint32(s.PkgIdx), SymIdx: uint32(s.SymIdx)}
  386. }
  387. func (w *writer) Reloc(r *Reloc) {
  388. var o goobj.Reloc
  389. o.SetOff(r.Off)
  390. o.SetSiz(r.Siz)
  391. o.SetType(uint8(r.Type))
  392. o.SetAdd(r.Add)
  393. o.SetSym(makeSymRef(r.Sym))
  394. o.Write(w.Writer)
  395. }
  396. func (w *writer) aux1(typ uint8, rs *LSym) {
  397. var o goobj.Aux
  398. o.SetType(typ)
  399. o.SetSym(makeSymRef(rs))
  400. o.Write(w.Writer)
  401. }
  402. func (w *writer) Aux(s *LSym) {
  403. if s.Gotype != nil {
  404. w.aux1(goobj.AuxGotype, s.Gotype)
  405. }
  406. if s.Func != nil {
  407. w.aux1(goobj.AuxFuncInfo, s.Func.FuncInfoSym)
  408. for _, d := range s.Func.Pcln.Funcdata {
  409. w.aux1(goobj.AuxFuncdata, d)
  410. }
  411. if s.Func.dwarfInfoSym != nil && s.Func.dwarfInfoSym.Size != 0 {
  412. w.aux1(goobj.AuxDwarfInfo, s.Func.dwarfInfoSym)
  413. }
  414. if s.Func.dwarfLocSym != nil && s.Func.dwarfLocSym.Size != 0 {
  415. w.aux1(goobj.AuxDwarfLoc, s.Func.dwarfLocSym)
  416. }
  417. if s.Func.dwarfRangesSym != nil && s.Func.dwarfRangesSym.Size != 0 {
  418. w.aux1(goobj.AuxDwarfRanges, s.Func.dwarfRangesSym)
  419. }
  420. if s.Func.dwarfDebugLinesSym != nil && s.Func.dwarfDebugLinesSym.Size != 0 {
  421. w.aux1(goobj.AuxDwarfLines, s.Func.dwarfDebugLinesSym)
  422. }
  423. }
  424. }
  425. // Emits flags of referenced indexed symbols.
  426. func (w *writer) refFlags() {
  427. seen := make(map[*LSym]bool)
  428. w.ctxt.traverseSyms(traverseRefs, func(rs *LSym) { // only traverse refs, not auxs, as tools don't need auxs
  429. switch rs.PkgIdx {
  430. case goobj.PkgIdxNone, goobj.PkgIdxHashed64, goobj.PkgIdxHashed, goobj.PkgIdxBuiltin, goobj.PkgIdxSelf: // not an external indexed reference
  431. return
  432. case goobj.PkgIdxInvalid:
  433. panic("unindexed symbol reference")
  434. }
  435. if seen[rs] {
  436. return
  437. }
  438. seen[rs] = true
  439. symref := makeSymRef(rs)
  440. flag2 := uint8(0)
  441. if rs.UsedInIface() {
  442. flag2 |= goobj.SymFlagUsedInIface
  443. }
  444. if flag2 == 0 {
  445. return // no need to write zero flags
  446. }
  447. var o goobj.RefFlags
  448. o.SetSym(symref)
  449. o.SetFlag2(flag2)
  450. o.Write(w.Writer)
  451. })
  452. }
  453. // Emits names of referenced indexed symbols, used by tools (objdump, nm)
  454. // only.
  455. func (w *writer) refNames() {
  456. seen := make(map[*LSym]bool)
  457. w.ctxt.traverseSyms(traverseRefs, func(rs *LSym) { // only traverse refs, not auxs, as tools don't need auxs
  458. switch rs.PkgIdx {
  459. case goobj.PkgIdxNone, goobj.PkgIdxHashed64, goobj.PkgIdxHashed, goobj.PkgIdxBuiltin, goobj.PkgIdxSelf: // not an external indexed reference
  460. return
  461. case goobj.PkgIdxInvalid:
  462. panic("unindexed symbol reference")
  463. }
  464. if seen[rs] {
  465. return
  466. }
  467. seen[rs] = true
  468. symref := makeSymRef(rs)
  469. var o goobj.RefName
  470. o.SetSym(symref)
  471. o.SetName(rs.Name, w.Writer)
  472. o.Write(w.Writer)
  473. })
  474. // TODO: output in sorted order?
  475. // Currently tools (cmd/internal/goobj package) doesn't use mmap,
  476. // and it just read it into a map in memory upfront. If it uses
  477. // mmap, if the output is sorted, it probably could avoid reading
  478. // into memory and just do lookups in the mmap'd object file.
  479. }
  480. // return the number of aux symbols s have.
  481. func nAuxSym(s *LSym) int {
  482. n := 0
  483. if s.Gotype != nil {
  484. n++
  485. }
  486. if s.Func != nil {
  487. // FuncInfo is an aux symbol, each Funcdata is an aux symbol
  488. n += 1 + len(s.Func.Pcln.Funcdata)
  489. if s.Func.dwarfInfoSym != nil && s.Func.dwarfInfoSym.Size != 0 {
  490. n++
  491. }
  492. if s.Func.dwarfLocSym != nil && s.Func.dwarfLocSym.Size != 0 {
  493. n++
  494. }
  495. if s.Func.dwarfRangesSym != nil && s.Func.dwarfRangesSym.Size != 0 {
  496. n++
  497. }
  498. if s.Func.dwarfDebugLinesSym != nil && s.Func.dwarfDebugLinesSym.Size != 0 {
  499. n++
  500. }
  501. }
  502. return n
  503. }
  504. // generate symbols for FuncInfo.
  505. func genFuncInfoSyms(ctxt *Link) {
  506. infosyms := make([]*LSym, 0, len(ctxt.Text))
  507. var pcdataoff uint32
  508. var b bytes.Buffer
  509. symidx := int32(len(ctxt.defs))
  510. for _, s := range ctxt.Text {
  511. if s.Func == nil {
  512. continue
  513. }
  514. o := goobj.FuncInfo{
  515. Args: uint32(s.Func.Args),
  516. Locals: uint32(s.Func.Locals),
  517. FuncID: objabi.FuncID(s.Func.FuncID),
  518. }
  519. pc := &s.Func.Pcln
  520. o.Pcsp = pcdataoff
  521. pcdataoff += uint32(len(pc.Pcsp.P))
  522. o.Pcfile = pcdataoff
  523. pcdataoff += uint32(len(pc.Pcfile.P))
  524. o.Pcline = pcdataoff
  525. pcdataoff += uint32(len(pc.Pcline.P))
  526. o.Pcinline = pcdataoff
  527. pcdataoff += uint32(len(pc.Pcinline.P))
  528. o.Pcdata = make([]uint32, len(pc.Pcdata))
  529. for i, pcd := range pc.Pcdata {
  530. o.Pcdata[i] = pcdataoff
  531. pcdataoff += uint32(len(pcd.P))
  532. }
  533. o.PcdataEnd = pcdataoff
  534. o.Funcdataoff = make([]uint32, len(pc.Funcdataoff))
  535. for i, x := range pc.Funcdataoff {
  536. o.Funcdataoff[i] = uint32(x)
  537. }
  538. i := 0
  539. o.File = make([]goobj.CUFileIndex, len(pc.UsedFiles))
  540. for f := range pc.UsedFiles {
  541. o.File[i] = f
  542. i++
  543. }
  544. sort.Slice(o.File, func(i, j int) bool { return o.File[i] < o.File[j] })
  545. o.InlTree = make([]goobj.InlTreeNode, len(pc.InlTree.nodes))
  546. for i, inl := range pc.InlTree.nodes {
  547. f, l := getFileIndexAndLine(ctxt, inl.Pos)
  548. o.InlTree[i] = goobj.InlTreeNode{
  549. Parent: int32(inl.Parent),
  550. File: goobj.CUFileIndex(f),
  551. Line: l,
  552. Func: makeSymRef(inl.Func),
  553. ParentPC: inl.ParentPC,
  554. }
  555. }
  556. o.Write(&b)
  557. isym := &LSym{
  558. Type: objabi.SDATA, // for now, I don't think it matters
  559. PkgIdx: goobj.PkgIdxSelf,
  560. SymIdx: symidx,
  561. P: append([]byte(nil), b.Bytes()...),
  562. }
  563. isym.Set(AttrIndexed, true)
  564. symidx++
  565. infosyms = append(infosyms, isym)
  566. s.Func.FuncInfoSym = isym
  567. b.Reset()
  568. dwsyms := []*LSym{s.Func.dwarfRangesSym, s.Func.dwarfLocSym, s.Func.dwarfDebugLinesSym, s.Func.dwarfInfoSym}
  569. for _, s := range dwsyms {
  570. if s == nil || s.Size == 0 {
  571. continue
  572. }
  573. s.PkgIdx = goobj.PkgIdxSelf
  574. s.SymIdx = symidx
  575. s.Set(AttrIndexed, true)
  576. symidx++
  577. infosyms = append(infosyms, s)
  578. }
  579. }
  580. ctxt.defs = append(ctxt.defs, infosyms...)
  581. }
  582. // debugDumpAux is a dumper for selected aux symbols.
  583. func writeAuxSymDebug(ctxt *Link, par *LSym, aux *LSym) {
  584. // Most aux symbols (ex: funcdata) are not interesting--
  585. // pick out just the DWARF ones for now.
  586. if aux.Type != objabi.SDWARFLOC &&
  587. aux.Type != objabi.SDWARFFCN &&
  588. aux.Type != objabi.SDWARFABSFCN &&
  589. aux.Type != objabi.SDWARFLINES &&
  590. aux.Type != objabi.SDWARFRANGE {
  591. return
  592. }
  593. ctxt.writeSymDebugNamed(aux, "aux for "+par.Name)
  594. }
  595. func debugAsmEmit(ctxt *Link) {
  596. if ctxt.Debugasm > 0 {
  597. ctxt.traverseSyms(traverseDefs, ctxt.writeSymDebug)
  598. if ctxt.Debugasm > 1 {
  599. fn := func(par *LSym, aux *LSym) {
  600. writeAuxSymDebug(ctxt, par, aux)
  601. }
  602. ctxt.traverseAuxSyms(traverseAux, fn)
  603. }
  604. }
  605. }
  606. func (ctxt *Link) writeSymDebug(s *LSym) {
  607. ctxt.writeSymDebugNamed(s, s.Name)
  608. }
  609. func (ctxt *Link) writeSymDebugNamed(s *LSym, name string) {
  610. ver := ""
  611. if ctxt.Debugasm > 1 {
  612. ver = fmt.Sprintf("<%d>", s.ABI())
  613. }
  614. fmt.Fprintf(ctxt.Bso, "%s%s ", name, ver)
  615. if s.Type != 0 {
  616. fmt.Fprintf(ctxt.Bso, "%v ", s.Type)
  617. }
  618. if s.Static() {
  619. fmt.Fprint(ctxt.Bso, "static ")
  620. }
  621. if s.DuplicateOK() {
  622. fmt.Fprintf(ctxt.Bso, "dupok ")
  623. }
  624. if s.CFunc() {
  625. fmt.Fprintf(ctxt.Bso, "cfunc ")
  626. }
  627. if s.NoSplit() {
  628. fmt.Fprintf(ctxt.Bso, "nosplit ")
  629. }
  630. if s.TopFrame() {
  631. fmt.Fprintf(ctxt.Bso, "topframe ")
  632. }
  633. fmt.Fprintf(ctxt.Bso, "size=%d", s.Size)
  634. if s.Type == objabi.STEXT {
  635. fmt.Fprintf(ctxt.Bso, " args=%#x locals=%#x funcid=%#x", uint64(s.Func.Args), uint64(s.Func.Locals), uint64(s.Func.FuncID))
  636. if s.Leaf() {
  637. fmt.Fprintf(ctxt.Bso, " leaf")
  638. }
  639. }
  640. fmt.Fprintf(ctxt.Bso, "\n")
  641. if s.Type == objabi.STEXT {
  642. for p := s.Func.Text; p != nil; p = p.Link {
  643. fmt.Fprintf(ctxt.Bso, "\t%#04x ", uint(int(p.Pc)))
  644. if ctxt.Debugasm > 1 {
  645. io.WriteString(ctxt.Bso, p.String())
  646. } else {
  647. p.InnermostString(ctxt.Bso)
  648. }
  649. fmt.Fprintln(ctxt.Bso)
  650. }
  651. }
  652. for i := 0; i < len(s.P); i += 16 {
  653. fmt.Fprintf(ctxt.Bso, "\t%#04x", uint(i))
  654. j := i
  655. for ; j < i+16 && j < len(s.P); j++ {
  656. fmt.Fprintf(ctxt.Bso, " %02x", s.P[j])
  657. }
  658. for ; j < i+16; j++ {
  659. fmt.Fprintf(ctxt.Bso, " ")
  660. }
  661. fmt.Fprintf(ctxt.Bso, " ")
  662. for j = i; j < i+16 && j < len(s.P); j++ {
  663. c := int(s.P[j])
  664. b := byte('.')
  665. if ' ' <= c && c <= 0x7e {
  666. b = byte(c)
  667. }
  668. ctxt.Bso.WriteByte(b)
  669. }
  670. fmt.Fprintf(ctxt.Bso, "\n")
  671. }
  672. sort.Sort(relocByOff(s.R)) // generate stable output
  673. for _, r := range s.R {
  674. name := ""
  675. ver := ""
  676. if r.Sym != nil {
  677. name = r.Sym.Name
  678. if ctxt.Debugasm > 1 {
  679. ver = fmt.Sprintf("<%d>", s.ABI())
  680. }
  681. } else if r.Type == objabi.R_TLS_LE {
  682. name = "TLS"
  683. }
  684. if ctxt.Arch.InFamily(sys.ARM, sys.PPC64) {
  685. fmt.Fprintf(ctxt.Bso, "\trel %d+%d t=%d %s%s+%x\n", int(r.Off), r.Siz, r.Type, name, ver, uint64(r.Add))
  686. } else {
  687. fmt.Fprintf(ctxt.Bso, "\trel %d+%d t=%d %s%s+%d\n", int(r.Off), r.Siz, r.Type, name, ver, r.Add)
  688. }
  689. }
  690. }
  691. // relocByOff sorts relocations by their offsets.
  692. type relocByOff []Reloc
  693. func (x relocByOff) Len() int { return len(x) }
  694. func (x relocByOff) Less(i, j int) bool { return x[i].Off < x[j].Off }
  695. func (x relocByOff) Swap(i, j int) { x[i], x[j] = x[j], x[i] }