Documentation Index
Fetch the complete documentation index at: https://mintlify.com/golang/go/llms.txt
Use this file to discover all available pages before exploring further.
The debug package provides debugging facilities for Go programs. It contains subpackages for examining binaries, reading DWARF debugging information, and runtime debugging.
Subpackages
debug/dwarf
Access to DWARF debugging information from executable files.
import (
"debug/dwarf"
"debug/elf"
"fmt"
)
func readDWARF(filename string) error {
// Open ELF file
f, err := elf.Open(filename)
if err != nil {
return err
}
defer f.Close()
// Get DWARF data
dwarfData, err := f.DWARF()
if err != nil {
return err
}
// Read entries
reader := dwarfData.Reader()
for {
entry, err := reader.Next()
if err != nil {
return err
}
if entry == nil {
break
}
if entry.Tag == dwarf.TagSubprogram {
name := entry.Val(dwarf.AttrName)
fmt.Printf("Function: %v\n", name)
}
}
return nil
}
debug/elf
Access to ELF (Executable and Linkable Format) object files.
import "debug/elf"
func examineELF(filename string) error {
f, err := elf.Open(filename)
if err != nil {
return err
}
defer f.Close()
fmt.Printf("Class: %v\n", f.Class)
fmt.Printf("Data: %v\n", f.Data)
fmt.Printf("Machine: %v\n", f.Machine)
fmt.Printf("Type: %v\n", f.Type)
// List sections
for _, section := range f.Sections {
fmt.Printf("Section: %s (type %v)\n", section.Name, section.Type)
}
// List symbols
symbols, err := f.Symbols()
if err != nil {
return err
}
for _, sym := range symbols {
fmt.Printf("Symbol: %s\n", sym.Name)
}
return nil
}
debug/macho
Access to Mach-O object files (macOS and iOS).
import "debug/macho"
func examineMachO(filename string) error {
f, err := macho.Open(filename)
if err != nil {
return err
}
defer f.Close()
fmt.Printf("CPU: %v\n", f.Cpu)
fmt.Printf("Type: %v\n", f.Type)
// List sections
for _, section := range f.Sections {
fmt.Printf("Section: %s\n", section.Name)
}
return nil
}
debug/pe
Access to PE (Portable Executable) files (Windows).
import "debug/pe"
func examinePE(filename string) error {
f, err := pe.Open(filename)
if err != nil {
return err
}
defer f.Close()
fmt.Printf("Machine: %v\n", f.Machine)
// List sections
for _, section := range f.Sections {
fmt.Printf("Section: %s\n", section.Name)
}
// List imported DLLs
imports, err := f.ImportedLibraries()
if err != nil {
return err
}
for _, dll := range imports {
fmt.Printf("Import: %s\n", dll)
}
return nil
}
debug/plan9obj
Access to Plan 9 a.out object files.
import "debug/plan9obj"
func examinePlan9(filename string) error {
f, err := plan9obj.Open(filename)
if err != nil {
return err
}
defer f.Close()
fmt.Printf("Magic: %v\n", f.Magic)
// List sections
for _, section := range f.Sections {
fmt.Printf("Section: %s\n", section.Name)
}
return nil
}
debug/buildinfo
Read build information embedded in Go binaries.
import (
"debug/buildinfo"
"fmt"
)
func readBuildInfo(filename string) error {
info, err := buildinfo.ReadFile(filename)
if err != nil {
return err
}
fmt.Printf("Go version: %s\n", info.GoVersion)
fmt.Printf("Path: %s\n", info.Path)
fmt.Printf("Main module: %s %s\n", info.Main.Path, info.Main.Version)
// List dependencies
for _, dep := range info.Deps {
fmt.Printf("Dependency: %s %s\n", dep.Path, dep.Version)
}
// Build settings
for _, setting := range info.Settings {
fmt.Printf("%s=%s\n", setting.Key, setting.Value)
}
return nil
}
Runtime Debugging
runtime/debug Package
import (
"fmt"
"runtime/debug"
)
// Print stack trace
func printStack() {
debug.PrintStack()
}
// Get stack trace as string
func getStack() string {
return string(debug.Stack())
}
// Control garbage collector
func controlGC() {
// Disable GC
debug.SetGCPercent(-1)
// Re-enable with 100% target
debug.SetGCPercent(100)
// Force GC
debug.FreeOSMemory()
}
// Read GC stats
func readGCStats() {
var stats debug.GCStats
debug.ReadGCStats(&stats)
fmt.Printf("Last GC: %v\n", stats.LastGC)
fmt.Printf("Num GC: %d\n", stats.NumGC)
fmt.Printf("Pause total: %v\n", stats.PauseTotal)
}
// Read memory stats
func readMemStats() {
var m runtime.MemStats
runtime.ReadMemStats(&m)
fmt.Printf("Alloc: %d MB\n", m.Alloc/1024/1024)
fmt.Printf("TotalAlloc: %d MB\n", m.TotalAlloc/1024/1024)
fmt.Printf("Sys: %d MB\n", m.Sys/1024/1024)
fmt.Printf("NumGC: %d\n", m.NumGC)
}
Build Info at Runtime
import "runtime/debug"
func printRuntimeBuildInfo() {
info, ok := debug.ReadBuildInfo()
if !ok {
fmt.Println("Build info not available")
return
}
fmt.Printf("Go version: %s\n", info.GoVersion)
fmt.Printf("Main module: %s\n", info.Main.Path)
for _, dep := range info.Deps {
fmt.Printf("%s@%s\n", dep.Path, dep.Version)
}
}
Practical Examples
Crash Recovery with Stack Trace
import "runtime/debug"
func recoverFromPanic() {
if r := recover(); r != nil {
fmt.Printf("Panic: %v\n", r)
fmt.Printf("Stack trace:\n%s\n", debug.Stack())
}
}
func riskyOperation() {
defer recoverFromPanic()
// Code that might panic
panic("something went wrong")
}
Memory Profiling
import (
"os"
"runtime/pprof"
)
func profileMemory(filename string) error {
f, err := os.Create(filename)
if err != nil {
return err
}
defer f.Close()
runtime.GC() // Run GC before profiling
if err := pprof.WriteHeapProfile(f); err != nil {
return err
}
return nil
}
import "debug/buildinfo"
func getVersion(binaryPath string) (string, error) {
info, err := buildinfo.ReadFile(binaryPath)
if err != nil {
return "", err
}
// Look for version in build settings
for _, setting := range info.Settings {
if setting.Key == "vcs.revision" {
return setting.Value[:7], nil // Short commit hash
}
}
return "unknown", nil
}
Binary Analysis
func analyzeBinary(filename string) error {
// Try to open as different formats
if f, err := elf.Open(filename); err == nil {
defer f.Close()
fmt.Println("Format: ELF")
return examineELF(filename)
}
if f, err := pe.Open(filename); err == nil {
defer f.Close()
fmt.Println("Format: PE")
return examinePE(filename)
}
if f, err := macho.Open(filename); err == nil {
defer f.Close()
fmt.Println("Format: Mach-O")
return examineMachO(filename)
}
return fmt.Errorf("unknown binary format")
}
Common Use Cases
- Binary inspection: Examine compiled binaries and their structure
- Debugging information: Extract debug symbols and line information
- Dependency analysis: List dependencies of a compiled binary
- Version tracking: Embed and extract version information
- Memory debugging: Track memory usage and garbage collection
- Crash analysis: Capture and analyze stack traces
- Build validation: Verify build settings and dependencies
Best Practices
- Always close file handles - Use
defer f.Close() when opening binaries
- Handle format variations - Different platforms use different executable formats
- Check error returns - Binary parsing can fail in various ways
- Use runtime/debug for production - Safer than debug/elf etc. at runtime
- Embed build info - Use
-ldflags to embed version information during build