77 lines
2 KiB
Go
77 lines
2 KiB
Go
|
package pe
|
||
|
|
||
|
import (
|
||
|
"encoding/binary"
|
||
|
"io"
|
||
|
)
|
||
|
|
||
|
// ExportTable is a table of module exports.
|
||
|
type ExportTable struct {
|
||
|
symbols map[string]uint64
|
||
|
ordinals map[uint16]uint64
|
||
|
}
|
||
|
|
||
|
// Proc returns an exported function address by symbol, or 0 if it is not found.
|
||
|
func (t *ExportTable) Proc(symbol string) (addr uint64) {
|
||
|
return t.symbols[symbol]
|
||
|
}
|
||
|
|
||
|
// Ordinal returns an exported function address by ordinal, or 0 if it is not found.
|
||
|
func (t *ExportTable) Ordinal(ordinal uint16) (addr uint64) {
|
||
|
return t.ordinals[ordinal]
|
||
|
}
|
||
|
|
||
|
// LoadExports returns a symbol table.
|
||
|
func LoadExports(m *Module, mem io.ReadWriteSeeker, base uint64) (*ExportTable, error) {
|
||
|
table := &ExportTable{
|
||
|
symbols: map[string]uint64{},
|
||
|
ordinals: map[uint16]uint64{},
|
||
|
}
|
||
|
|
||
|
dir := m.Header.OptionalHeader.DataDirectory[ImageDirectoryEntryExport]
|
||
|
if dir.Size == 0 {
|
||
|
return table, nil
|
||
|
}
|
||
|
|
||
|
// Load export directory header
|
||
|
header := ImageExportDirectory{}
|
||
|
mem.Seek(int64(dir.VirtualAddress), io.SeekStart)
|
||
|
binary.Read(mem, binary.LittleEndian, &header)
|
||
|
|
||
|
// Load addresses
|
||
|
addresses := make([]uint32, header.NumberOfFunctions)
|
||
|
mem.Seek(int64(header.AddressOfFunctions), io.SeekStart)
|
||
|
for i := range addresses {
|
||
|
b := [4]byte{}
|
||
|
mem.Read(b[:])
|
||
|
addresses[i] = binary.LittleEndian.Uint32(b[:])
|
||
|
table.ordinals[uint16(i)] = base + uint64(addresses[i])
|
||
|
}
|
||
|
|
||
|
// Load name ordinals
|
||
|
nameords := make([]uint16, header.NumberOfNames)
|
||
|
mem.Seek(int64(header.AddressOfNameOrdinals), io.SeekStart)
|
||
|
for i := range nameords {
|
||
|
b := [2]byte{}
|
||
|
mem.Read(b[:])
|
||
|
nameords[i] = binary.LittleEndian.Uint16(b[:])
|
||
|
}
|
||
|
|
||
|
// Load name addresses
|
||
|
nameaddrs := make([]uint32, header.NumberOfNames)
|
||
|
mem.Seek(int64(header.AddressOfNames), io.SeekStart)
|
||
|
for i := range nameaddrs {
|
||
|
b := [4]byte{}
|
||
|
mem.Read(b[:])
|
||
|
nameaddrs[i] = binary.LittleEndian.Uint32(b[:])
|
||
|
}
|
||
|
|
||
|
// Load names
|
||
|
for i, nameaddr := range nameaddrs {
|
||
|
mem.Seek(int64(nameaddr), io.SeekStart)
|
||
|
table.symbols[readsz(mem)] = base + uint64(addresses[nameords[i]])
|
||
|
}
|
||
|
|
||
|
return table, nil
|
||
|
}
|