Commit 5373e8a8 authored by Joel Sing's avatar Joel Sing

debug/pe: add symbol support

Add support for processing the COFF symbol table.

R=alex.brainman
CC=golang-dev
https://golang.org/cl/6551045
parent c29f4e00
...@@ -19,6 +19,7 @@ import ( ...@@ -19,6 +19,7 @@ import (
type File struct { type File struct {
FileHeader FileHeader
Sections []*Section Sections []*Section
Symbols []*Symbol
closer io.Closer closer io.Closer
} }
...@@ -49,6 +50,14 @@ type Section struct { ...@@ -49,6 +50,14 @@ type Section struct {
sr *io.SectionReader sr *io.SectionReader
} }
type Symbol struct {
Name string
Value uint32
SectionNumber int16
Type uint16
StorageClass uint8
}
type ImportDirectory struct { type ImportDirectory struct {
OriginalFirstThunk uint32 OriginalFirstThunk uint32
TimeDateStamp uint32 TimeDateStamp uint32
...@@ -138,16 +147,49 @@ func NewFile(r io.ReaderAt) (*File, error) { ...@@ -138,16 +147,49 @@ func NewFile(r io.ReaderAt) (*File, error) {
if f.FileHeader.Machine != IMAGE_FILE_MACHINE_UNKNOWN && f.FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64 && f.FileHeader.Machine != IMAGE_FILE_MACHINE_I386 { if f.FileHeader.Machine != IMAGE_FILE_MACHINE_UNKNOWN && f.FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64 && f.FileHeader.Machine != IMAGE_FILE_MACHINE_I386 {
return nil, errors.New("Invalid PE File Format.") return nil, errors.New("Invalid PE File Format.")
} }
// get symbol string table
sr.Seek(int64(f.FileHeader.PointerToSymbolTable+18*f.FileHeader.NumberOfSymbols), os.SEEK_SET) // Get COFF string table, which is located at the end of the COFF symbol table.
sr.Seek(int64(f.FileHeader.PointerToSymbolTable+COFFSymbolSize*f.FileHeader.NumberOfSymbols), os.SEEK_SET)
var l uint32 var l uint32
if err := binary.Read(sr, binary.LittleEndian, &l); err != nil { if err := binary.Read(sr, binary.LittleEndian, &l); err != nil {
return nil, err return nil, err
} }
ss := make([]byte, l) ss := make([]byte, l)
if _, err := r.ReadAt(ss, int64(f.FileHeader.PointerToSymbolTable+18*f.FileHeader.NumberOfSymbols)); err != nil { if _, err := r.ReadAt(ss, int64(f.FileHeader.PointerToSymbolTable+COFFSymbolSize*f.FileHeader.NumberOfSymbols)); err != nil {
return nil, err return nil, err
} }
// Process COFF symbol table.
sr.Seek(int64(f.FileHeader.PointerToSymbolTable), os.SEEK_SET)
aux := uint8(0)
for i := 0; i < int(f.FileHeader.NumberOfSymbols); i++ {
cs := new(COFFSymbol)
if err := binary.Read(sr, binary.LittleEndian, cs); err != nil {
return nil, err
}
if aux > 0 {
aux--
continue
}
var name string
if cs.Name[0] == 0 && cs.Name[1] == 0 && cs.Name[2] == 0 && cs.Name[3] == 0 {
si := int(binary.LittleEndian.Uint32(cs.Name[4:]))
name, _ = getString(ss, si)
} else {
name = cstring(cs.Name[:])
}
aux = cs.NumberOfAuxSymbols
s := &Symbol{
Name: name,
Value: cs.Value,
SectionNumber: cs.SectionNumber,
Type: cs.Type,
StorageClass: cs.StorageClass,
}
f.Symbols = append(f.Symbols, s)
}
// Process sections.
sr.Seek(base, os.SEEK_SET) sr.Seek(base, os.SEEK_SET)
binary.Read(sr, binary.LittleEndian, &f.FileHeader) binary.Read(sr, binary.LittleEndian, &f.FileHeader)
sr.Seek(int64(f.FileHeader.SizeOfOptionalHeader), os.SEEK_CUR) //Skip OptionalHeader sr.Seek(int64(f.FileHeader.SizeOfOptionalHeader), os.SEEK_CUR) //Skip OptionalHeader
......
...@@ -13,6 +13,7 @@ type fileTest struct { ...@@ -13,6 +13,7 @@ type fileTest struct {
file string file string
hdr FileHeader hdr FileHeader
sections []*SectionHeader sections []*SectionHeader
symbols []*Symbol
} }
var fileTests = []fileTest{ var fileTests = []fileTest{
...@@ -33,6 +34,24 @@ var fileTests = []fileTest{ ...@@ -33,6 +34,24 @@ var fileTests = []fileTest{
{".debug_pubtypes", 0, 0, 38, 1370, 1580, 0, 1, 0, 1108344832}, {".debug_pubtypes", 0, 0, 38, 1370, 1580, 0, 1, 0, 1108344832},
{".debug_aranges", 0, 0, 32, 1408, 1590, 0, 2, 0, 1108344832}, {".debug_aranges", 0, 0, 32, 1408, 1590, 0, 2, 0, 1108344832},
}, },
[]*Symbol{
{".file", 0x0, -2, 0x0, 0x67},
{"_main", 0x0, 1, 0x20, 0x2},
{".text", 0x0, 1, 0x0, 0x3},
{".data", 0x0, 2, 0x0, 0x3},
{".bss", 0x0, 3, 0x0, 0x3},
{".debug_abbrev", 0x0, 4, 0x0, 0x3},
{".debug_info", 0x0, 5, 0x0, 0x3},
{".debug_line", 0x0, 6, 0x0, 0x3},
{".rdata", 0x0, 7, 0x0, 0x3},
{".debug_frame", 0x0, 8, 0x0, 0x3},
{".debug_loc", 0x0, 9, 0x0, 0x3},
{".debug_pubnames", 0x0, 10, 0x0, 0x3},
{".debug_pubtypes", 0x0, 11, 0x0, 0x3},
{".debug_aranges", 0x0, 12, 0x0, 0x3},
{"___main", 0x0, 0, 0x20, 0x2},
{"_puts", 0x0, 0, 0x20, 0x2},
},
}, },
{ {
"testdata/gcc-386-mingw-exec", "testdata/gcc-386-mingw-exec",
...@@ -54,6 +73,7 @@ var fileTests = []fileTest{ ...@@ -54,6 +73,7 @@ var fileTests = []fileTest{
{Name: ".debug_frame", VirtualSize: 0x34, VirtualAddress: 0xe000, Size: 0x200, Offset: 0x3800, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42300000}, {Name: ".debug_frame", VirtualSize: 0x34, VirtualAddress: 0xe000, Size: 0x200, Offset: 0x3800, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42300000},
{Name: ".debug_loc", VirtualSize: 0x38, VirtualAddress: 0xf000, Size: 0x200, Offset: 0x3a00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000}, {Name: ".debug_loc", VirtualSize: 0x38, VirtualAddress: 0xf000, Size: 0x200, Offset: 0x3a00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
}, },
[]*Symbol{},
}, },
} }
...@@ -86,7 +106,15 @@ func TestOpen(t *testing.T) { ...@@ -86,7 +106,15 @@ func TestOpen(t *testing.T) {
if tn != fn { if tn != fn {
t.Errorf("open %s: len(Sections) = %d, want %d", tt.file, fn, tn) t.Errorf("open %s: len(Sections) = %d, want %d", tt.file, fn, tn)
} }
for i, have := range f.Symbols {
if i >= len(tt.symbols) {
break
}
want := tt.symbols[i]
if !reflect.DeepEqual(have, want) {
t.Errorf("open %s, symbol %d:\n\thave %#v\n\twant %#v\n", tt.file, i, have, want)
}
}
} }
} }
......
...@@ -27,6 +27,17 @@ type SectionHeader32 struct { ...@@ -27,6 +27,17 @@ type SectionHeader32 struct {
Characteristics uint32 Characteristics uint32
} }
const COFFSymbolSize = 18
type COFFSymbol struct {
Name [8]uint8
Value uint32
SectionNumber int16
Type uint16
StorageClass uint8
NumberOfAuxSymbols uint8
}
const ( const (
IMAGE_FILE_MACHINE_UNKNOWN = 0x0 IMAGE_FILE_MACHINE_UNKNOWN = 0x0
IMAGE_FILE_MACHINE_AM33 = 0x1d3 IMAGE_FILE_MACHINE_AM33 = 0x1d3
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment