rum-goggles/vendor/github.com/jchv/go-winloader/internal/pe/export.go

77 lines
2 KiB
Go
Raw Permalink Normal View History

2024-02-23 16:39:16 +00:00
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
}