You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

840 lines
20 KiB

  1. // Copyright 2018 Google Inc. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // Package elf implements access to ELF object files.
  15. package elf
  16. import (
  17. "bytes"
  18. "encoding/binary"
  19. "errors"
  20. "fmt"
  21. "io"
  22. "os"
  23. "cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug/dwarf"
  24. )
  25. // TODO: error reporting detail
  26. /*
  27. * Internal ELF representation
  28. */
  29. // A FileHeader represents an ELF file header.
  30. type FileHeader struct {
  31. Class Class
  32. Data Data
  33. Version Version
  34. OSABI OSABI
  35. ABIVersion uint8
  36. ByteOrder binary.ByteOrder
  37. Type Type
  38. Machine Machine
  39. Entry uint64
  40. }
  41. // A File represents an open ELF file.
  42. type File struct {
  43. FileHeader
  44. Sections []*Section
  45. Progs []*Prog
  46. closer io.Closer
  47. gnuNeed []verneed
  48. gnuVersym []byte
  49. }
  50. // A SectionHeader represents a single ELF section header.
  51. type SectionHeader struct {
  52. Name string
  53. Type SectionType
  54. Flags SectionFlag
  55. Addr uint64
  56. Offset uint64
  57. Size uint64
  58. Link uint32
  59. Info uint32
  60. Addralign uint64
  61. Entsize uint64
  62. }
  63. // A Section represents a single section in an ELF file.
  64. type Section struct {
  65. SectionHeader
  66. // Embed ReaderAt for ReadAt method.
  67. // Do not embed SectionReader directly
  68. // to avoid having Read and Seek.
  69. // If a client wants Read and Seek it must use
  70. // Open() to avoid fighting over the seek offset
  71. // with other clients.
  72. io.ReaderAt
  73. sr *io.SectionReader
  74. }
  75. // Data reads and returns the contents of the ELF section.
  76. func (s *Section) Data() ([]byte, error) {
  77. dat := make([]byte, s.sr.Size())
  78. n, err := s.sr.ReadAt(dat, 0)
  79. if n == len(dat) {
  80. err = nil
  81. }
  82. return dat[0:n], err
  83. }
  84. // stringTable reads and returns the string table given by the
  85. // specified link value.
  86. func (f *File) stringTable(link uint32) ([]byte, error) {
  87. if link <= 0 || link >= uint32(len(f.Sections)) {
  88. return nil, errors.New("section has invalid string table link")
  89. }
  90. return f.Sections[link].Data()
  91. }
  92. // Open returns a new ReadSeeker reading the ELF section.
  93. func (s *Section) Open() io.ReadSeeker { return io.NewSectionReader(s.sr, 0, 1<<63-1) }
  94. // A ProgHeader represents a single ELF program header.
  95. type ProgHeader struct {
  96. Type ProgType
  97. Flags ProgFlag
  98. Off uint64
  99. Vaddr uint64
  100. Paddr uint64
  101. Filesz uint64
  102. Memsz uint64
  103. Align uint64
  104. }
  105. // A Prog represents a single ELF program header in an ELF binary.
  106. type Prog struct {
  107. ProgHeader
  108. // Embed ReaderAt for ReadAt method.
  109. // Do not embed SectionReader directly
  110. // to avoid having Read and Seek.
  111. // If a client wants Read and Seek it must use
  112. // Open() to avoid fighting over the seek offset
  113. // with other clients.
  114. io.ReaderAt
  115. sr *io.SectionReader
  116. }
  117. // Open returns a new ReadSeeker reading the ELF program body.
  118. func (p *Prog) Open() io.ReadSeeker { return io.NewSectionReader(p.sr, 0, 1<<63-1) }
  119. // A Symbol represents an entry in an ELF symbol table section.
  120. type Symbol struct {
  121. Name string
  122. Info, Other byte
  123. Section SectionIndex
  124. Value, Size uint64
  125. }
  126. /*
  127. * ELF reader
  128. */
  129. type FormatError struct {
  130. off int64
  131. msg string
  132. val interface{}
  133. }
  134. func (e *FormatError) Error() string {
  135. msg := e.msg
  136. if e.val != nil {
  137. msg += fmt.Sprintf(" '%v' ", e.val)
  138. }
  139. msg += fmt.Sprintf("in record at byte %#x", e.off)
  140. return msg
  141. }
  142. // Open opens the named file using os.Open and prepares it for use as an ELF binary.
  143. func Open(name string) (*File, error) {
  144. f, err := os.Open(name)
  145. if err != nil {
  146. return nil, err
  147. }
  148. ff, err := NewFile(f)
  149. if err != nil {
  150. f.Close()
  151. return nil, err
  152. }
  153. ff.closer = f
  154. return ff, nil
  155. }
  156. // Close closes the File.
  157. // If the File was created using NewFile directly instead of Open,
  158. // Close has no effect.
  159. func (f *File) Close() error {
  160. var err error
  161. if f.closer != nil {
  162. err = f.closer.Close()
  163. f.closer = nil
  164. }
  165. return err
  166. }
  167. // SectionByType returns the first section in f with the
  168. // given type, or nil if there is no such section.
  169. func (f *File) SectionByType(typ SectionType) *Section {
  170. for _, s := range f.Sections {
  171. if s.Type == typ {
  172. return s
  173. }
  174. }
  175. return nil
  176. }
  177. // NewFile creates a new File for accessing an ELF binary in an underlying reader.
  178. // The ELF binary is expected to start at position 0 in the ReaderAt.
  179. func NewFile(r io.ReaderAt) (*File, error) {
  180. sr := io.NewSectionReader(r, 0, 1<<63-1)
  181. // Read and decode ELF identifier
  182. var ident [16]uint8
  183. if _, err := r.ReadAt(ident[0:], 0); err != nil {
  184. return nil, err
  185. }
  186. if ident[0] != '\x7f' || ident[1] != 'E' || ident[2] != 'L' || ident[3] != 'F' {
  187. return nil, &FormatError{0, "bad magic number", ident[0:4]}
  188. }
  189. f := new(File)
  190. f.Class = Class(ident[EI_CLASS])
  191. switch f.Class {
  192. case ELFCLASS32:
  193. case ELFCLASS64:
  194. // ok
  195. default:
  196. return nil, &FormatError{0, "unknown ELF class", f.Class}
  197. }
  198. f.Data = Data(ident[EI_DATA])
  199. switch f.Data {
  200. case ELFDATA2LSB:
  201. f.ByteOrder = binary.LittleEndian
  202. case ELFDATA2MSB:
  203. f.ByteOrder = binary.BigEndian
  204. default:
  205. return nil, &FormatError{0, "unknown ELF data encoding", f.Data}
  206. }
  207. f.Version = Version(ident[EI_VERSION])
  208. if f.Version != EV_CURRENT {
  209. return nil, &FormatError{0, "unknown ELF version", f.Version}
  210. }
  211. f.OSABI = OSABI(ident[EI_OSABI])
  212. f.ABIVersion = ident[EI_ABIVERSION]
  213. // Read ELF file header
  214. var phoff int64
  215. var phentsize, phnum int
  216. var shoff int64
  217. var shentsize, shnum, shstrndx int
  218. shstrndx = -1
  219. switch f.Class {
  220. case ELFCLASS32:
  221. hdr := new(Header32)
  222. sr.Seek(0, os.SEEK_SET)
  223. if err := binary.Read(sr, f.ByteOrder, hdr); err != nil {
  224. return nil, err
  225. }
  226. f.Type = Type(hdr.Type)
  227. f.Machine = Machine(hdr.Machine)
  228. f.Entry = uint64(hdr.Entry)
  229. if v := Version(hdr.Version); v != f.Version {
  230. return nil, &FormatError{0, "mismatched ELF version", v}
  231. }
  232. phoff = int64(hdr.Phoff)
  233. phentsize = int(hdr.Phentsize)
  234. phnum = int(hdr.Phnum)
  235. shoff = int64(hdr.Shoff)
  236. shentsize = int(hdr.Shentsize)
  237. shnum = int(hdr.Shnum)
  238. shstrndx = int(hdr.Shstrndx)
  239. case ELFCLASS64:
  240. hdr := new(Header64)
  241. sr.Seek(0, os.SEEK_SET)
  242. if err := binary.Read(sr, f.ByteOrder, hdr); err != nil {
  243. return nil, err
  244. }
  245. f.Type = Type(hdr.Type)
  246. f.Machine = Machine(hdr.Machine)
  247. f.Entry = uint64(hdr.Entry)
  248. if v := Version(hdr.Version); v != f.Version {
  249. return nil, &FormatError{0, "mismatched ELF version", v}
  250. }
  251. phoff = int64(hdr.Phoff)
  252. phentsize = int(hdr.Phentsize)
  253. phnum = int(hdr.Phnum)
  254. shoff = int64(hdr.Shoff)
  255. shentsize = int(hdr.Shentsize)
  256. shnum = int(hdr.Shnum)
  257. shstrndx = int(hdr.Shstrndx)
  258. }
  259. if shnum > 0 && shoff > 0 && (shstrndx < 0 || shstrndx >= shnum) {
  260. return nil, &FormatError{0, "invalid ELF shstrndx", shstrndx}
  261. }
  262. // Read program headers
  263. f.Progs = make([]*Prog, phnum)
  264. for i := 0; i < phnum; i++ {
  265. off := phoff + int64(i)*int64(phentsize)
  266. sr.Seek(off, os.SEEK_SET)
  267. p := new(Prog)
  268. switch f.Class {
  269. case ELFCLASS32:
  270. ph := new(Prog32)
  271. if err := binary.Read(sr, f.ByteOrder, ph); err != nil {
  272. return nil, err
  273. }
  274. p.ProgHeader = ProgHeader{
  275. Type: ProgType(ph.Type),
  276. Flags: ProgFlag(ph.Flags),
  277. Off: uint64(ph.Off),
  278. Vaddr: uint64(ph.Vaddr),
  279. Paddr: uint64(ph.Paddr),
  280. Filesz: uint64(ph.Filesz),
  281. Memsz: uint64(ph.Memsz),
  282. Align: uint64(ph.Align),
  283. }
  284. case ELFCLASS64:
  285. ph := new(Prog64)
  286. if err := binary.Read(sr, f.ByteOrder, ph); err != nil {
  287. return nil, err
  288. }
  289. p.ProgHeader = ProgHeader{
  290. Type: ProgType(ph.Type),
  291. Flags: ProgFlag(ph.Flags),
  292. Off: uint64(ph.Off),
  293. Vaddr: uint64(ph.Vaddr),
  294. Paddr: uint64(ph.Paddr),
  295. Filesz: uint64(ph.Filesz),
  296. Memsz: uint64(ph.Memsz),
  297. Align: uint64(ph.Align),
  298. }
  299. }
  300. p.sr = io.NewSectionReader(r, int64(p.Off), int64(p.Filesz))
  301. p.ReaderAt = p.sr
  302. f.Progs[i] = p
  303. }
  304. // Read section headers
  305. f.Sections = make([]*Section, shnum)
  306. names := make([]uint32, shnum)
  307. for i := 0; i < shnum; i++ {
  308. off := shoff + int64(i)*int64(shentsize)
  309. sr.Seek(off, os.SEEK_SET)
  310. s := new(Section)
  311. switch f.Class {
  312. case ELFCLASS32:
  313. sh := new(Section32)
  314. if err := binary.Read(sr, f.ByteOrder, sh); err != nil {
  315. return nil, err
  316. }
  317. names[i] = sh.Name
  318. s.SectionHeader = SectionHeader{
  319. Type: SectionType(sh.Type),
  320. Flags: SectionFlag(sh.Flags),
  321. Addr: uint64(sh.Addr),
  322. Offset: uint64(sh.Off),
  323. Size: uint64(sh.Size),
  324. Link: uint32(sh.Link),
  325. Info: uint32(sh.Info),
  326. Addralign: uint64(sh.Addralign),
  327. Entsize: uint64(sh.Entsize),
  328. }
  329. case ELFCLASS64:
  330. sh := new(Section64)
  331. if err := binary.Read(sr, f.ByteOrder, sh); err != nil {
  332. return nil, err
  333. }
  334. names[i] = sh.Name
  335. s.SectionHeader = SectionHeader{
  336. Type: SectionType(sh.Type),
  337. Flags: SectionFlag(sh.Flags),
  338. Offset: uint64(sh.Off),
  339. Size: uint64(sh.Size),
  340. Addr: uint64(sh.Addr),
  341. Link: uint32(sh.Link),
  342. Info: uint32(sh.Info),
  343. Addralign: uint64(sh.Addralign),
  344. Entsize: uint64(sh.Entsize),
  345. }
  346. }
  347. s.sr = io.NewSectionReader(r, int64(s.Offset), int64(s.Size))
  348. s.ReaderAt = s.sr
  349. f.Sections[i] = s
  350. }
  351. if len(f.Sections) == 0 {
  352. return f, nil
  353. }
  354. // Load section header string table.
  355. shstrtab, err := f.Sections[shstrndx].Data()
  356. if err != nil {
  357. return nil, err
  358. }
  359. for i, s := range f.Sections {
  360. var ok bool
  361. s.Name, ok = getString(shstrtab, int(names[i]))
  362. if !ok {
  363. return nil, &FormatError{shoff + int64(i*shentsize), "bad section name index", names[i]}
  364. }
  365. }
  366. return f, nil
  367. }
  368. // getSymbols returns a slice of Symbols from parsing the symbol table
  369. // with the given type, along with the associated string table.
  370. func (f *File) getSymbols(typ SectionType) ([]Symbol, []byte, error) {
  371. switch f.Class {
  372. case ELFCLASS64:
  373. return f.getSymbols64(typ)
  374. case ELFCLASS32:
  375. return f.getSymbols32(typ)
  376. }
  377. return nil, nil, errors.New("not implemented")
  378. }
  379. func (f *File) getSymbols32(typ SectionType) ([]Symbol, []byte, error) {
  380. symtabSection := f.SectionByType(typ)
  381. if symtabSection == nil {
  382. return nil, nil, errors.New("no symbol section")
  383. }
  384. data, err := symtabSection.Data()
  385. if err != nil {
  386. return nil, nil, errors.New("cannot load symbol section")
  387. }
  388. symtab := bytes.NewReader(data)
  389. if symtab.Len()%Sym32Size != 0 {
  390. return nil, nil, errors.New("length of symbol section is not a multiple of SymSize")
  391. }
  392. strdata, err := f.stringTable(symtabSection.Link)
  393. if err != nil {
  394. return nil, nil, errors.New("cannot load string table section")
  395. }
  396. // The first entry is all zeros.
  397. var skip [Sym32Size]byte
  398. symtab.Read(skip[:])
  399. symbols := make([]Symbol, symtab.Len()/Sym32Size)
  400. i := 0
  401. var sym Sym32
  402. for symtab.Len() > 0 {
  403. binary.Read(symtab, f.ByteOrder, &sym)
  404. str, _ := getString(strdata, int(sym.Name))
  405. symbols[i].Name = str
  406. symbols[i].Info = sym.Info
  407. symbols[i].Other = sym.Other
  408. symbols[i].Section = SectionIndex(sym.Shndx)
  409. symbols[i].Value = uint64(sym.Value)
  410. symbols[i].Size = uint64(sym.Size)
  411. i++
  412. }
  413. return symbols, strdata, nil
  414. }
  415. func (f *File) getSymbols64(typ SectionType) ([]Symbol, []byte, error) {
  416. symtabSection := f.SectionByType(typ)
  417. if symtabSection == nil {
  418. return nil, nil, errors.New("no symbol section")
  419. }
  420. data, err := symtabSection.Data()
  421. if err != nil {
  422. return nil, nil, errors.New("cannot load symbol section")
  423. }
  424. symtab := bytes.NewReader(data)
  425. if symtab.Len()%Sym64Size != 0 {
  426. return nil, nil, errors.New("length of symbol section is not a multiple of Sym64Size")
  427. }
  428. strdata, err := f.stringTable(symtabSection.Link)
  429. if err != nil {
  430. return nil, nil, errors.New("cannot load string table section")
  431. }
  432. // The first entry is all zeros.
  433. var skip [Sym64Size]byte
  434. symtab.Read(skip[:])
  435. symbols := make([]Symbol, symtab.Len()/Sym64Size)
  436. i := 0
  437. var sym Sym64
  438. for symtab.Len() > 0 {
  439. binary.Read(symtab, f.ByteOrder, &sym)
  440. str, _ := getString(strdata, int(sym.Name))
  441. symbols[i].Name = str
  442. symbols[i].Info = sym.Info
  443. symbols[i].Other = sym.Other
  444. symbols[i].Section = SectionIndex(sym.Shndx)
  445. symbols[i].Value = sym.Value
  446. symbols[i].Size = sym.Size
  447. i++
  448. }
  449. return symbols, strdata, nil
  450. }
  451. // getString extracts a string from an ELF string table.
  452. func getString(section []byte, start int) (string, bool) {
  453. if start < 0 || start >= len(section) {
  454. return "", false
  455. }
  456. for end := start; end < len(section); end++ {
  457. if section[end] == 0 {
  458. return string(section[start:end]), true
  459. }
  460. }
  461. return "", false
  462. }
  463. // Section returns a section with the given name, or nil if no such
  464. // section exists.
  465. func (f *File) Section(name string) *Section {
  466. for _, s := range f.Sections {
  467. if s.Name == name {
  468. return s
  469. }
  470. }
  471. return nil
  472. }
  473. // applyRelocations applies relocations to dst. rels is a relocations section
  474. // in RELA format.
  475. func (f *File) applyRelocations(dst []byte, rels []byte) error {
  476. if f.Class == ELFCLASS64 && f.Machine == EM_X86_64 {
  477. return f.applyRelocationsAMD64(dst, rels)
  478. }
  479. return errors.New("not implemented")
  480. }
  481. func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) error {
  482. if len(rels)%Sym64Size != 0 {
  483. return errors.New("length of relocation section is not a multiple of Sym64Size")
  484. }
  485. symbols, _, err := f.getSymbols(SHT_SYMTAB)
  486. if err != nil {
  487. return err
  488. }
  489. b := bytes.NewReader(rels)
  490. var rela Rela64
  491. for b.Len() > 0 {
  492. binary.Read(b, f.ByteOrder, &rela)
  493. symNo := rela.Info >> 32
  494. t := R_X86_64(rela.Info & 0xffff)
  495. if symNo == 0 || symNo > uint64(len(symbols)) {
  496. continue
  497. }
  498. sym := &symbols[symNo-1]
  499. if SymType(sym.Info&0xf) != STT_SECTION {
  500. // We don't handle non-section relocations for now.
  501. continue
  502. }
  503. switch t {
  504. case R_X86_64_64:
  505. if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
  506. continue
  507. }
  508. f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend))
  509. case R_X86_64_32:
  510. if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
  511. continue
  512. }
  513. f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
  514. }
  515. }
  516. return nil
  517. }
  518. func (f *File) DWARF() (*dwarf.Data, error) {
  519. // There are many other DWARF sections, but these
  520. // are the required ones, and the debug/dwarf package
  521. // does not use the others, so don't bother loading them.
  522. // r: added line.
  523. var names = [...]string{"abbrev", "frame", "info", "line", "str"}
  524. var dat [len(names)][]byte
  525. for i, name := range names {
  526. name = ".debug_" + name
  527. s := f.Section(name)
  528. if s == nil {
  529. continue
  530. }
  531. b, err := s.Data()
  532. if err != nil && uint64(len(b)) < s.Size {
  533. return nil, err
  534. }
  535. dat[i] = b
  536. }
  537. // If there's a relocation table for .debug_info, we have to process it
  538. // now otherwise the data in .debug_info is invalid for x86-64 objects.
  539. rela := f.Section(".rela.debug_info")
  540. if rela != nil && rela.Type == SHT_RELA && f.Machine == EM_X86_64 {
  541. data, err := rela.Data()
  542. if err != nil {
  543. return nil, err
  544. }
  545. err = f.applyRelocations(dat[2], data)
  546. if err != nil {
  547. return nil, err
  548. }
  549. }
  550. abbrev, frame, info, line, str := dat[0], dat[1], dat[2], dat[3], dat[4]
  551. d, err := dwarf.New(abbrev, nil, frame, info, line, nil, nil, str)
  552. if err != nil {
  553. return nil, err
  554. }
  555. // Look for DWARF4 .debug_types sections.
  556. for i, s := range f.Sections {
  557. if s.Name == ".debug_types" {
  558. b, err := s.Data()
  559. if err != nil && uint64(len(b)) < s.Size {
  560. return nil, err
  561. }
  562. for _, r := range f.Sections {
  563. if r.Type != SHT_RELA && r.Type != SHT_REL {
  564. continue
  565. }
  566. if int(r.Info) != i {
  567. continue
  568. }
  569. rd, err := r.Data()
  570. if err != nil {
  571. return nil, err
  572. }
  573. err = f.applyRelocations(b, rd)
  574. if err != nil {
  575. return nil, err
  576. }
  577. }
  578. err = d.AddTypes(fmt.Sprintf("types-%d", i), b)
  579. if err != nil {
  580. return nil, err
  581. }
  582. }
  583. }
  584. return d, nil
  585. }
  586. // Symbols returns the symbol table for f.
  587. //
  588. // For compatibility with Go 1.0, Symbols omits the null symbol at index 0.
  589. // After retrieving the symbols as symtab, an externally supplied index x
  590. // corresponds to symtab[x-1], not symtab[x].
  591. func (f *File) Symbols() ([]Symbol, error) {
  592. sym, _, err := f.getSymbols(SHT_SYMTAB)
  593. return sym, err
  594. }
  595. type ImportedSymbol struct {
  596. Name string
  597. Version string
  598. Library string
  599. }
  600. // ImportedSymbols returns the names of all symbols
  601. // referred to by the binary f that are expected to be
  602. // satisfied by other libraries at dynamic load time.
  603. // It does not return weak symbols.
  604. func (f *File) ImportedSymbols() ([]ImportedSymbol, error) {
  605. sym, str, err := f.getSymbols(SHT_DYNSYM)
  606. if err != nil {
  607. return nil, err
  608. }
  609. f.gnuVersionInit(str)
  610. var all []ImportedSymbol
  611. for i, s := range sym {
  612. if ST_BIND(s.Info) == STB_GLOBAL && s.Section == SHN_UNDEF {
  613. all = append(all, ImportedSymbol{Name: s.Name})
  614. f.gnuVersion(i, &all[len(all)-1])
  615. }
  616. }
  617. return all, nil
  618. }
  619. type verneed struct {
  620. File string
  621. Name string
  622. }
  623. // gnuVersionInit parses the GNU version tables
  624. // for use by calls to gnuVersion.
  625. func (f *File) gnuVersionInit(str []byte) {
  626. // Accumulate verneed information.
  627. vn := f.SectionByType(SHT_GNU_VERNEED)
  628. if vn == nil {
  629. return
  630. }
  631. d, _ := vn.Data()
  632. var need []verneed
  633. i := 0
  634. for {
  635. if i+16 > len(d) {
  636. break
  637. }
  638. vers := f.ByteOrder.Uint16(d[i : i+2])
  639. if vers != 1 {
  640. break
  641. }
  642. cnt := f.ByteOrder.Uint16(d[i+2 : i+4])
  643. fileoff := f.ByteOrder.Uint32(d[i+4 : i+8])
  644. aux := f.ByteOrder.Uint32(d[i+8 : i+12])
  645. next := f.ByteOrder.Uint32(d[i+12 : i+16])
  646. file, _ := getString(str, int(fileoff))
  647. var name string
  648. j := i + int(aux)
  649. for c := 0; c < int(cnt); c++ {
  650. if j+16 > len(d) {
  651. break
  652. }
  653. // hash := f.ByteOrder.Uint32(d[j:j+4])
  654. // flags := f.ByteOrder.Uint16(d[j+4:j+6])
  655. other := f.ByteOrder.Uint16(d[j+6 : j+8])
  656. nameoff := f.ByteOrder.Uint32(d[j+8 : j+12])
  657. next := f.ByteOrder.Uint32(d[j+12 : j+16])
  658. name, _ = getString(str, int(nameoff))
  659. ndx := int(other)
  660. if ndx >= len(need) {
  661. a := make([]verneed, 2*(ndx+1))
  662. copy(a, need)
  663. need = a
  664. }
  665. need[ndx] = verneed{file, name}
  666. if next == 0 {
  667. break
  668. }
  669. j += int(next)
  670. }
  671. if next == 0 {
  672. break
  673. }
  674. i += int(next)
  675. }
  676. // Versym parallels symbol table, indexing into verneed.
  677. vs := f.SectionByType(SHT_GNU_VERSYM)
  678. if vs == nil {
  679. return
  680. }
  681. d, _ = vs.Data()
  682. f.gnuNeed = need
  683. f.gnuVersym = d
  684. }
  685. // gnuVersion adds Library and Version information to sym,
  686. // which came from offset i of the symbol table.
  687. func (f *File) gnuVersion(i int, sym *ImportedSymbol) {
  688. // Each entry is two bytes.
  689. i = (i + 1) * 2
  690. if i >= len(f.gnuVersym) {
  691. return
  692. }
  693. j := int(f.ByteOrder.Uint16(f.gnuVersym[i:]))
  694. if j < 2 || j >= len(f.gnuNeed) {
  695. return
  696. }
  697. n := &f.gnuNeed[j]
  698. sym.Library = n.File
  699. sym.Version = n.Name
  700. }
  701. // ImportedLibraries returns the names of all libraries
  702. // referred to by the binary f that are expected to be
  703. // linked with the binary at dynamic link time.
  704. func (f *File) ImportedLibraries() ([]string, error) {
  705. return f.DynString(DT_NEEDED)
  706. }
  707. // DynString returns the strings listed for the given tag in the file's dynamic
  708. // section.
  709. //
  710. // The tag must be one that takes string values: DT_NEEDED, DT_SONAME, DT_RPATH, or
  711. // DT_RUNPATH.
  712. func (f *File) DynString(tag DynTag) ([]string, error) {
  713. switch tag {
  714. case DT_NEEDED, DT_SONAME, DT_RPATH, DT_RUNPATH:
  715. default:
  716. return nil, fmt.Errorf("non-string-valued tag %v", tag)
  717. }
  718. ds := f.SectionByType(SHT_DYNAMIC)
  719. if ds == nil {
  720. // not dynamic, so no libraries
  721. return nil, nil
  722. }
  723. d, err := ds.Data()
  724. if err != nil {
  725. return nil, err
  726. }
  727. str, err := f.stringTable(ds.Link)
  728. if err != nil {
  729. return nil, err
  730. }
  731. var all []string
  732. for len(d) > 0 {
  733. var t DynTag
  734. var v uint64
  735. switch f.Class {
  736. case ELFCLASS32:
  737. t = DynTag(f.ByteOrder.Uint32(d[0:4]))
  738. v = uint64(f.ByteOrder.Uint32(d[4:8]))
  739. d = d[8:]
  740. case ELFCLASS64:
  741. t = DynTag(f.ByteOrder.Uint64(d[0:8]))
  742. v = f.ByteOrder.Uint64(d[8:16])
  743. d = d[16:]
  744. }
  745. if t == tag {
  746. s, ok := getString(str, int(v))
  747. if ok {
  748. all = append(all, s)
  749. }
  750. }
  751. }
  752. return all, nil
  753. }