]> Cypherpunks repositories - gostls13.git/commitdiff
debug/macho: support reading imported symbols without LC_DYSYMTAB
authorCherry Mui <cherryyz@google.com>
Mon, 4 Aug 2025 14:30:26 +0000 (10:30 -0400)
committerCherry Mui <cherryyz@google.com>
Wed, 6 Aug 2025 19:28:05 +0000 (12:28 -0700)
Currently, the ImportedSymbols method requires an LC_DYSYMTAB load
command to exist. However, a Mach-O object file may not have an
LC_DYSYMTAB load command, e.g. the one produced by "ld -r".
Support this case by just reading the symbol table and gathers
undefined symbols.

Updates #61229.

Change-Id: I8b4761ac7d99e1f1f378e883e9be75ee4049ffbb
Reviewed-on: https://go-review.googlesource.com/c/go/+/692995
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
src/debug/macho/file.go
src/debug/macho/file_test.go
src/debug/macho/testdata/clang-amd64-darwin-ld-r.obj.base64 [new file with mode: 0644]

index fcf28c4b25edaf6632bd2af23e24a8a901fb6b58..52ff81750cc4c1da1af12f380bbddbe0aa609301 100644 (file)
@@ -719,15 +719,28 @@ func (f *File) DWARF() (*dwarf.Data, error) {
 // referred to by the binary f that are expected to be
 // satisfied by other libraries at dynamic load time.
 func (f *File) ImportedSymbols() ([]string, error) {
-       if f.Dysymtab == nil || f.Symtab == nil {
+       if f.Symtab == nil {
                return nil, &FormatError{0, "missing symbol table", nil}
        }
 
        st := f.Symtab
        dt := f.Dysymtab
        var all []string
-       for _, s := range st.Syms[dt.Iundefsym : dt.Iundefsym+dt.Nundefsym] {
-               all = append(all, s.Name)
+       if dt != nil {
+               for _, s := range st.Syms[dt.Iundefsym : dt.Iundefsym+dt.Nundefsym] {
+                       all = append(all, s.Name)
+               }
+       } else {
+               // From Darwin's include/mach-o/nlist.h
+               const (
+                       N_TYPE = 0x0e
+                       N_UNDF = 0x0
+               )
+               for _, s := range st.Syms {
+                       if s.Type&N_TYPE == N_UNDF && s.Sect == 0 {
+                               all = append(all, s.Name)
+                       }
+               }
        }
        return all, nil
 }
index 313c376c54a27f9cb9e6f91ba3e9e2f1d5228aa5..fbcc7bdcb01e96ada08534c4cbf47d837c0f9752 100644 (file)
@@ -9,15 +9,17 @@ import (
        "internal/obscuretestdata"
        "io"
        "reflect"
+       "slices"
        "testing"
 )
 
 type fileTest struct {
-       file        string
-       hdr         FileHeader
-       loads       []any
-       sections    []*SectionHeader
-       relocations map[string][]Reloc
+       file         string
+       hdr          FileHeader
+       loads        []any
+       sections     []*SectionHeader
+       relocations  map[string][]Reloc
+       importedSyms []string
 }
 
 var fileTests = []fileTest{
@@ -46,6 +48,7 @@ var fileTests = []fileTest{
                        {"__jump_table", "__IMPORT", 0x3000, 0xa, 0x2000, 0x6, 0x0, 0x0, 0x4000008},
                },
                nil,
+               nil,
        },
        {
                "testdata/gcc-amd64-darwin-exec.base64",
@@ -74,6 +77,7 @@ var fileTests = []fileTest{
                        {"__la_symbol_ptr", "__DATA", 0x100001058, 0x10, 0x1058, 0x2, 0x0, 0x0, 0x7},
                },
                nil,
+               nil,
        },
        {
                "testdata/gcc-amd64-darwin-exec-debug.base64",
@@ -102,6 +106,7 @@ var fileTests = []fileTest{
                        {"__debug_str", "__DWARF", 0x10000215c, 0x60, 0x115c, 0x0, 0x0, 0x0, 0x0},
                },
                nil,
+               nil,
        },
        {
                "testdata/clang-386-darwin-exec-with-rpath.base64",
@@ -126,6 +131,7 @@ var fileTests = []fileTest{
                },
                nil,
                nil,
+               nil,
        },
        {
                "testdata/clang-amd64-darwin-exec-with-rpath.base64",
@@ -150,6 +156,7 @@ var fileTests = []fileTest{
                },
                nil,
                nil,
+               nil,
        },
        {
                "testdata/clang-386-darwin.obj.base64",
@@ -185,6 +192,7 @@ var fileTests = []fileTest{
                                },
                        },
                },
+               nil,
        },
        {
                "testdata/clang-amd64-darwin.obj.base64",
@@ -221,6 +229,15 @@ var fileTests = []fileTest{
                                },
                        },
                },
+               []string{"_printf"},
+       },
+       {
+               "testdata/clang-amd64-darwin-ld-r.obj.base64",
+               FileHeader{0xfeedfacf, CpuAmd64, 0x3, 0x1, 0x4, 0x1c0, 0x2000},
+               nil,
+               nil,
+               nil,
+               []string{"_printf"},
        },
 }
 
@@ -345,6 +362,17 @@ func TestOpen(t *testing.T) {
                                }
                        }
                }
+
+               if tt.importedSyms != nil {
+                       ss, err := f.ImportedSymbols()
+                       if err != nil {
+                               t.Errorf("open %s: fail to read imported symbols: %v", tt.file, err)
+                       }
+                       want := tt.importedSyms
+                       if !slices.Equal(ss, want) {
+                               t.Errorf("open %s: imported symbols differ:\n\thave %v\n\twant %v", tt.file, ss, want)
+                       }
+               }
        }
 }
 
diff --git a/src/debug/macho/testdata/clang-amd64-darwin-ld-r.obj.base64 b/src/debug/macho/testdata/clang-amd64-darwin-ld-r.obj.base64
new file mode 100644 (file)
index 0000000..036b574
--- /dev/null
@@ -0,0 +1 @@
+z/rt/gcAAAEDAAAAAQAAAAQAAADAAQAAACAAAAAAAAAZAAAAiAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJgAAAAAAAAAAAIAAAAAAACYAAAAAAAAAAcAAAAHAAAABAAAAAAAAABfX3RleHQAAAAAAAAAAAAAX19URVhUAAAAAAAAAAAAAAAAAAAAAAAAKgAAAAAAAAAAAgAABAAAAJgCAAACAAAAAAQAgAAAAAAAAAAAAAAAAF9fY3N0cmluZwAAAAAAAABfX1RFWFQAAAAAAAAAAAAAKgAAAAAAAAAOAAAAAAAAACoCAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAX19laF9mcmFtZQAAAAAAAF9fVEVYVAAAAAAAAAAAAAA4AAAAAAAAAEAAAAAAAAAAOAIAAAMAAACoAgAABAAAAAAAAAAAAAAAAAAAAAAAAABfX2NvbXBhY3RfdW53aW5kX19MRAAAAAAAAAAAAAAAAHgAAAAAAAAAIAAAAAAAAAB4AgAAAwAAAMgCAAABAAAAAAAAAgAAAAAAAAAAAAAAAAIAAAAYAAAA0AIAAAUAAAAgAwAAKAAAACQAAAAQAAAAAAwKAAAAAAApAAAAEAAAANACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABVSInlSIPsEEiNPQAAAADHRfwAAAAAsADoAAAAADHJiUX4ichIg8QQXcNoZWxsbywgd29ybGQKABQAAAAAAAAAAXpSAAF4EAEQDAcIkAEAACQAAAAEAAAA+P////////8qAAAAAAAAAABBDhCGAkMNBgAAAAAAAAAAAAAAAAAAACoAAAAAAAABAAAAAAAAAAAAAAAAAAAAABkAAAAEAAAtCwAAAAAAAB0cAAAAAQAAXBwAAAACAAAMIAAAAAIAAF4gAAAAAwAADgAAAAADAAAOEAAAAB4CAAAqAAAAAAAAABQAAAAOAwAAOAAAAAAAAAAeAAAADgMAAFAAAAAAAAAAAgAAAA8BAAAAAAAAAAAAAAgAAAABAAAAAAAAAAAAAAAgAF9tYWluAF9wcmludGYATEMxAEVIX0ZyYW1lMQBmdW5jLmVoAAAA