ldso.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. // ldso.go - Dynamic linker routines.
  2. // Copyright 2016 Yawning Angel
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a
  5. // copy of this software and associated documentation files (the "Software"),
  6. // to deal in the Software without restriction, including without limitation
  7. // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. // and/or sell copies of the Software, and to permit persons to whom the
  9. // Software is furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included
  12. // in all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  15. // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  17. // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  20. // DEALINGS IN THE SOFTWARE.
  21. package dynlib
  22. import (
  23. "debug/elf"
  24. "errors"
  25. "fmt"
  26. "os"
  27. "path/filepath"
  28. "runtime"
  29. )
  30. var errUnsupported = errors.New("dynlib: unsupported os/architecture")
  31. func getLibraries(fn string) ([]string, error) {
  32. f, err := elf.Open(fn)
  33. if err != nil {
  34. return nil, err
  35. }
  36. defer f.Close()
  37. return f.ImportedLibraries()
  38. }
  39. // ValidateLibraryClass ensures that the library matches the current
  40. // architecture.
  41. func ValidateLibraryClass(fn string) error {
  42. f, err := elf.Open(fn)
  43. if err != nil {
  44. return err
  45. }
  46. defer f.Close()
  47. var expectedClass elf.Class
  48. switch runtime.GOARCH {
  49. case "amd64":
  50. expectedClass = elf.ELFCLASS64
  51. default:
  52. return errUnsupported
  53. }
  54. if f.Class != expectedClass {
  55. return fmt.Errorf("unsupported class: %v: %v", fn, f.Class)
  56. }
  57. return nil
  58. }
  59. // FindLdSo returns the path to the `ld.so` dynamic linker for the current
  60. // architecture, which is usually a symlink
  61. func FindLdSo(cache *Cache) (string, string, error) {
  62. if !IsSupported() {
  63. return "", "", errUnsupported
  64. }
  65. name := ""
  66. searchPaths := []string{}
  67. switch runtime.GOARCH {
  68. case "amd64":
  69. searchPaths = append(searchPaths, "/lib64")
  70. name = "ld-linux-x86-64.so.2"
  71. default:
  72. panic("dynlib: unsupported architecture: " + runtime.GOARCH)
  73. }
  74. searchPaths = append(searchPaths, "/lib")
  75. for _, d := range searchPaths {
  76. candidate := filepath.Join(d, name)
  77. _, err := os.Stat(candidate)
  78. if err != nil {
  79. continue
  80. }
  81. actual := cache.GetLibraryPath(name)
  82. if actual == "" {
  83. continue
  84. }
  85. actual, err = filepath.EvalSymlinks(actual)
  86. return actual, candidate, err
  87. }
  88. return "", "", os.ErrNotExist
  89. }
  90. // IsSupported returns true if the architecture/os combination has dynlib
  91. // sypport.
  92. func IsSupported() bool {
  93. return runtime.GOOS == "linux" && runtime.GOARCH == "amd64"
  94. }