From: Cherry Mui Date: Mon, 4 Aug 2025 14:30:26 +0000 (-0400) Subject: debug/macho: support reading imported symbols without LC_DYSYMTAB X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=2747f925dd1f08f9b9a1ef23170ee601519d70c2;p=gostls13.git 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 Reviewed-by: David Chase --- 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