1
0
mirror of https://github.com/golang/go synced 2024-09-23 11:20:17 -06:00

debug/pe: rework reading of aux symbols to fix endianity problems

This patch reworks CL 394534 to fix things so that reading auxiliary
symbol info works properly in a cross-endian mode (running
debug/pe-based tool on a big-endian system). The previous
implementation read in all symbol records using the primary symbol
format, then just used a pointer cast to convert to the auxiliary
format, which doesn't play well if host and target have different
endianness.

Fixes #52079.

Change-Id: I143d94d9313a265f11ca7befd254bdb150698834
Reviewed-on: https://go-review.googlesource.com/c/go/+/397485
Run-TryBot: Than McIntosh <thanm@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
This commit is contained in:
Than McIntosh 2022-04-01 11:12:22 -04:00
parent f495b36ccd
commit 054323d809
2 changed files with 48 additions and 11 deletions

View File

@ -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
}

View File

@ -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",