winsym

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 30, 2026 License: MIT Imports: 17 Imported by: 0

README

go-winsym

Go


Symbol resolution for native Windows crashes: read minidumps, find PDBs on symbol servers and name the function an address lies in. Package winsym, module github.com/Rethunk-Tech/go-winsym.

It works without dbghelp or Windows, on files and servers it does not trust, using only the standard library. Every format it reads is Microsoft's and documented.

Quick start

go get github.com/Rethunk-Tech/go-winsym

A worked example and the contracts: HUMANS.md.

Features

  • Minidump reader: exception code, address, faulting module and offset, and the module's CodeView record.
  • CodeView from a PE file on disk, with the symbol-store key for its PDB.
  • PDB lookup: the public function at or below an address, partly undecorated.
  • Symbol-server fetch into a size-capped cache in the standard symbol-store layout, downloaded once however many callers wait.
  • Crash discovery (crashdump): the minidumps WER and Unity crash folders leave, Application Error and .NET faults from the Windows event log, and systemd core dumps, each as one Fault naming the module, offset and exception.
  • Server lists you choose, so a module's name goes only to servers that publish it.

Documentation

Doc Audience
HUMANS.md Running and using the package
AGENTS.md Internals, invariants, and why
CONTRIBUTING.md Process — commits, tests, docs
SECURITY.md Vulnerability disclosure
CHANGELOG.md Release notes

License

MIT — see LICENSE. © 2026 Rethunk.Tech, LLC.

Documentation

Overview

Package winsym resolves native Windows crashes to function names: it reads the faulting module and offset from a minidump, a module's CodeView record from a dump or a PE file, fetches the matching PDB from a symbol server into a size-capped cache, and names the public function an address lies in by reading the PDB's MSF container.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Lookup

func Lookup(r io.ReaderAt, size int64, rva uint64) (name string, offset uint64, err error)

Lookup names the public function symbol nearest at or below rva in the Windows PDB r holds, undecorated, and rva's offset into it.

Types

type CodeView

type CodeView struct {
	// PDB is a base name only and always matches ^[A-Za-z0-9_.-]+\.pdb$ when non-empty.
	PDB  string
	GUID [16]byte
	Age  uint32
}

CodeView is a module's RSDS debug record: the PDB it was linked with and that PDB's identity.

func PECodeView

func PECodeView(path string) (CodeView, bool)

PECodeView reads the CodeView record of the PE file at path. The path is the caller's to vet: the file is opened as given and only its debug directory is read.

func (CodeView) Key

func (cv CodeView) Key() string

Key is the folder a symbol server files the PDB under: the GUID as 32 upper-case hex digits, its first three fields little-endian as Windows stores them, then the age in hex.

type Fault

type Fault struct {
	// Code is the exception code, such as 0xc0000005.
	Code    uint32
	Address uint64
	// Module is the faulting image's path as the dump records it, empty when no listed module holds Address.
	Module string
	// Offset is Address minus that module's base; meaningful only when Module is not empty.
	Offset uint64
	// CodeView is the module's debug record, zero when the dump carries no valid one.
	CodeView CodeView
}

Fault is where a minidump's exception happened.

func ParseMinidump

func ParseMinidump(r io.ReaderAt, size int64) (Fault, error)

ParseMinidump finds the faulting module of a Windows minidump: the exception stream gives the address and the module list says which loaded image holds it. The dump is another program's file: counts, offsets and sizes in it are bounded before they size an allocation or a read.

type Resolver

type Resolver struct {
	// Dir must belong to this Resolver alone: prune deletes every *.pdb under it, least recently read first,
	// and every *.pdb.part older than an hour, whoever wrote them.
	Dir string
	// HTTP is the client for downloads; nil means http.DefaultClient. Each download also carries a 10-minute context.
	HTTP *http.Client
	// Servers are asked in order; nil means DefaultServers().
	Servers []Server
	// Online says whether to try the network; nil means always. A cached PDB is read either way.
	Online func() bool
	// Wait is how long Name waits for a download before answering without it; the download carries on, so the next
	// call has the name.
	Wait time.Duration
	// MaxCacheBytes caps the cache folder; zero means 2 GiB. The least recently read PDBs go first.
	MaxCacheBytes int64
	// contains filtered or unexported fields
}

Resolver fetches PDBs into Dir in the symbol-store layout <Dir>/<pdb>/<key>/<pdb> and reads them. Name reads the cache only for a PDB some Server serves: the name is validated and the server list consulted before any path is built, so a PDB placed in Dir by hand for a module no Server serves is never read; use Lookup, or add a Server, for those.

func (*Resolver) Name

func (r *Resolver) Name(ctx context.Context, cv CodeView, rva uint64) (name string, offset uint64, ok bool)

Name is the public symbol the address rva of the module cv identifies lies in and the offset into it, such as "GfxDeviceD3D11::DrawBuffers". ok is false when no server publishes its PDB, the PDB is not cached and cannot be fetched now, or no symbol covers rva.

type Server

type Server struct {
	// URL is the base, ending in "/"; "<pdb>/<key>/<pdb>" is appended.
	URL string
	// Serves gets the lower-cased PDB name and says whether this server publishes it. Nil asks for every name.
	Serves func(pdb string) bool
}

Server is a symbol server and the PDB names it is asked for.

func DefaultServers

func DefaultServers() []Server

DefaultServers is Unity's symbol server (https, then http: Unity documents only the http address) for unityplayer_, windowsplayer_ and baselib_ PDBs, and Microsoft's for the system and runtime PDBs a crash in a Windows process passes through. A PDB no listed server publishes is never requested, so a private module's name does not reach a third party. Each call returns a fresh slice.

Directories

Path Synopsis
Package crashdump finds what a native crash left behind (a Windows minidump, a Unity crash folder, the Windows event log, a systemd coredump report) and reads it just far enough to name the module the process died in.
Package crashdump finds what a native crash left behind (a Windows minidump, a Unity crash folder, the Windows event log, a systemd coredump report) and reads it just far enough to name the module the process died in.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL