diff options
| author | Cherry Mui <cherryyz@google.com> | 2025-08-04 10:30:26 -0400 |
|---|---|---|
| committer | Cherry Mui <cherryyz@google.com> | 2025-08-06 12:28:05 -0700 |
| commit | 2747f925dd1f08f9b9a1ef23170ee601519d70c2 (patch) | |
| tree | ff86a3b5b243b0b27f0cd22d5a77770f52e2ea26 /src/debug | |
| parent | 025d36917c8f56baede2f477131bbf08bf1382ca (diff) | |
| download | go-2747f925dd1f08f9b9a1ef23170ee601519d70c2.tar.xz | |
debug/macho: support reading imported symbols without LC_DYSYMTAB
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>
Diffstat (limited to 'src/debug')
| -rw-r--r-- | src/debug/macho/file.go | 19 | ||||
| -rw-r--r-- | src/debug/macho/file_test.go | 38 | ||||
| -rw-r--r-- | src/debug/macho/testdata/clang-amd64-darwin-ld-r.obj.base64 | 1 |
3 files changed, 50 insertions, 8 deletions
diff --git a/src/debug/macho/file.go b/src/debug/macho/file.go index fcf28c4b25..52ff81750c 100644 --- a/src/debug/macho/file.go +++ b/src/debug/macho/file.go @@ -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 } diff --git a/src/debug/macho/file_test.go b/src/debug/macho/file_test.go index 313c376c54..fbcc7bdcb0 100644 --- a/src/debug/macho/file_test.go +++ b/src/debug/macho/file_test.go @@ -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 index 0000000000..036b5746ab --- /dev/null +++ b/src/debug/macho/testdata/clang-amd64-darwin-ld-r.obj.base64 @@ -0,0 +1 @@ +z/rt/gcAAAEDAAAAAQAAAAQAAADAAQAAACAAAAAAAAAZAAAAiAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJgAAAAAAAAAAAIAAAAAAACYAAAAAAAAAAcAAAAHAAAABAAAAAAAAABfX3RleHQAAAAAAAAAAAAAX19URVhUAAAAAAAAAAAAAAAAAAAAAAAAKgAAAAAAAAAAAgAABAAAAJgCAAACAAAAAAQAgAAAAAAAAAAAAAAAAF9fY3N0cmluZwAAAAAAAABfX1RFWFQAAAAAAAAAAAAAKgAAAAAAAAAOAAAAAAAAACoCAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAX19laF9mcmFtZQAAAAAAAF9fVEVYVAAAAAAAAAAAAAA4AAAAAAAAAEAAAAAAAAAAOAIAAAMAAACoAgAABAAAAAAAAAAAAAAAAAAAAAAAAABfX2NvbXBhY3RfdW53aW5kX19MRAAAAAAAAAAAAAAAAHgAAAAAAAAAIAAAAAAAAAB4AgAAAwAAAMgCAAABAAAAAAAAAgAAAAAAAAAAAAAAAAIAAAAYAAAA0AIAAAUAAAAgAwAAKAAAACQAAAAQAAAAAAwKAAAAAAApAAAAEAAAANACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABVSInlSIPsEEiNPQAAAADHRfwAAAAAsADoAAAAADHJiUX4ichIg8QQXcNoZWxsbywgd29ybGQKABQAAAAAAAAAAXpSAAF4EAEQDAcIkAEAACQAAAAEAAAA+P////////8qAAAAAAAAAABBDhCGAkMNBgAAAAAAAAAAAAAAAAAAACoAAAAAAAABAAAAAAAAAAAAAAAAAAAAABkAAAAEAAAtCwAAAAAAAB0cAAAAAQAAXBwAAAACAAAMIAAAAAIAAF4gAAAAAwAADgAAAAADAAAOEAAAAB4CAAAqAAAAAAAAABQAAAAOAwAAOAAAAAAAAAAeAAAADgMAAFAAAAAAAAAAAgAAAA8BAAAAAAAAAAAAAAgAAAABAAAAAAAAAAAAAAAgAF9tYWluAF9wcmludGYATEMxAEVIX0ZyYW1lMQBmdW5jLmVoAAAA |
