diff --git a/src/debug/pe/symbol.go b/src/debug/pe/symbol.go index 323fa8c3df..dfbeb11414 100644 --- a/src/debug/pe/symbol.go +++ b/src/debug/pe/symbol.go @@ -23,6 +23,29 @@ type COFFSymbol struct { NumberOfAuxSymbols uint8 } +// readCOFFSymbols reads in the symbol table for a PE file, returning +// a slice of COFFSymbol objects. The PE format includes both primary +// symbols (whose fields are described by COFFSymbol above) and +// auxiliary symbols; all symbols are 18 bytes in size. The auxiliary +// symbols for a given primary symbol are placed following it in the +// array, e.g. +// +// ... +// k+0: regular sym k +// k+1: 1st aux symbol for k +// k+2: 2nd aux symbol for k +// k+3: regular sym k+3 +// k+4: 1st aux symbol for k+3 +// k+5: regular sym k+5 +// k+6: regular sym k+6 +// +// The PE format allows for several possible aux symbol formats. For +// more info see: +// +// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#auxiliary-symbol-records +// +// At the moment this package only provides APIs for looking at +// aux symbols of format 5 (associated with section definition symbols). func readCOFFSymbols(fh *FileHeader, r io.ReadSeeker) ([]COFFSymbol, error) { if fh.PointerToSymbolTable == 0 { return nil, nil @@ -35,9 +58,31 @@ func readCOFFSymbols(fh *FileHeader, r io.ReadSeeker) ([]COFFSymbol, error) { return nil, fmt.Errorf("fail to seek to symbol table: %v", err) } syms := make([]COFFSymbol, fh.NumberOfSymbols) - err = binary.Read(r, binary.LittleEndian, syms) - if err != nil { - return nil, fmt.Errorf("fail to read symbol table: %v", err) + naux := 0 + for k := range syms { + if naux == 0 { + // Read a primary symbol. + err = binary.Read(r, binary.LittleEndian, &syms[k]) + if err != nil { + return nil, fmt.Errorf("fail to read symbol table: %v", err) + } + // Record how many auxiliary symbols it has. + naux = int(syms[k].NumberOfAuxSymbols) + } else { + // Read an aux symbol. At the moment we assume all + // aux symbols are format 5 (obviously this doesn't always + // hold; more cases will be needed below if more aux formats + // are supported in the future). + naux-- + aux := (*COFFSymbolAuxFormat5)(unsafe.Pointer(&syms[k])) + err = binary.Read(r, binary.LittleEndian, aux) + if err != nil { + return nil, fmt.Errorf("fail to read symbol table: %v", err) + } + } + } + if naux != 0 { + return nil, fmt.Errorf("fail to read symbol table: %d aux symbols unread", naux) } return syms, nil } diff --git a/src/debug/pe/symbols_test.go b/src/debug/pe/symbols_test.go index 5ccf635830..c4dcd95391 100644 --- a/src/debug/pe/symbols_test.go +++ b/src/debug/pe/symbols_test.go @@ -6,7 +6,6 @@ package pe import ( "fmt" - "runtime" "testing" ) @@ -18,13 +17,6 @@ type testpoint struct { } func TestReadCOFFSymbolAuxInfo(t *testing.T) { - - switch runtime.GOARCH { - case "mips", "mips64", "ppc64", "s390x": - t.Skipf("Skipping on %s (big endian) until issue #52079 fixed", - runtime.GOARCH) - } - testpoints := map[int]testpoint{ 39: testpoint{ name: ".rdata$.refptr.__native_startup_lock",