package pe
 
 import (
+       "debug/dwarf"
+       "io/ioutil"
+       "os"
+       "os/exec"
+       "path/filepath"
        "reflect"
+       "runtime"
        "testing"
 )
 
 type fileTest struct {
-       file     string
-       hdr      FileHeader
-       opthdr   interface{}
-       sections []*SectionHeader
-       symbols  []*Symbol
+       file           string
+       hdr            FileHeader
+       opthdr         interface{}
+       sections       []*SectionHeader
+       symbols        []*Symbol
+       hasNoDwarfInfo bool
 }
 
 var fileTests = []fileTest{
        {
-               "testdata/gcc-386-mingw-obj",
-               FileHeader{0x014c, 0x000c, 0x0, 0x64a, 0x1e, 0x0, 0x104},
-               nil,
-               []*SectionHeader{
+               file: "testdata/gcc-386-mingw-obj",
+               hdr:  FileHeader{0x014c, 0x000c, 0x0, 0x64a, 0x1e, 0x0, 0x104},
+               sections: []*SectionHeader{
                        {".text", 0, 0, 36, 500, 1440, 0, 3, 0, 0x60300020},
                        {".data", 0, 0, 0, 0, 0, 0, 0, 0, 3224371264},
                        {".bss", 0, 0, 0, 0, 0, 0, 0, 0, 3224371328},
                        {".debug_pubtypes", 0, 0, 38, 1370, 1580, 0, 1, 0, 1108344832},
                        {".debug_aranges", 0, 0, 32, 1408, 1590, 0, 2, 0, 1108344832},
                },
-               []*Symbol{
+               symbols: []*Symbol{
                        {".file", 0x0, -2, 0x0, 0x67},
                        {"_main", 0x0, 1, 0x20, 0x2},
                        {".text", 0x0, 1, 0x0, 0x3},
                },
        },
        {
-               "testdata/gcc-386-mingw-exec",
-               FileHeader{0x014c, 0x000f, 0x4c6a1b60, 0x3c00, 0x282, 0xe0, 0x107},
-               &OptionalHeader32{
+               file: "testdata/gcc-386-mingw-exec",
+               hdr:  FileHeader{0x014c, 0x000f, 0x4c6a1b60, 0x3c00, 0x282, 0xe0, 0x107},
+               opthdr: &OptionalHeader32{
                        0x10b, 0x2, 0x38, 0xe00, 0x1a00, 0x200, 0x1160, 0x1000, 0x2000, 0x400000, 0x1000, 0x200, 0x4, 0x0, 0x1, 0x0, 0x4, 0x0, 0x0, 0x10000, 0x400, 0x14abb, 0x3, 0x0, 0x200000, 0x1000, 0x100000, 0x1000, 0x0, 0x10,
                        [16]DataDirectory{
                                {0x0, 0x0},
                                {0x0, 0x0},
                        },
                },
-               []*SectionHeader{
+               sections: []*SectionHeader{
                        {".text", 0xcd8, 0x1000, 0xe00, 0x400, 0x0, 0x0, 0x0, 0x0, 0x60500060},
                        {".data", 0x10, 0x2000, 0x200, 0x1200, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
                        {".rdata", 0x120, 0x3000, 0x200, 0x1400, 0x0, 0x0, 0x0, 0x0, 0x40300040},
                        {".debug_frame", 0x34, 0xe000, 0x200, 0x3800, 0x0, 0x0, 0x0, 0x0, 0x42300000},
                        {".debug_loc", 0x38, 0xf000, 0x200, 0x3a00, 0x0, 0x0, 0x0, 0x0, 0x42100000},
                },
-               []*Symbol{},
        },
        {
-               "testdata/gcc-amd64-mingw-obj",
-               FileHeader{0x8664, 0x6, 0x0, 0x198, 0x12, 0x0, 0x4},
-               nil,
-               []*SectionHeader{
+               file: "testdata/gcc-amd64-mingw-obj",
+               hdr:  FileHeader{0x8664, 0x6, 0x0, 0x198, 0x12, 0x0, 0x4},
+               sections: []*SectionHeader{
                        {".text", 0x0, 0x0, 0x30, 0x104, 0x15c, 0x0, 0x3, 0x0, 0x60500020},
                        {".data", 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0500040},
                        {".bss", 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0500080},
                        {".xdata", 0x0, 0x0, 0xc, 0x144, 0x0, 0x0, 0x0, 0x0, 0x40300040},
                        {".pdata", 0x0, 0x0, 0xc, 0x150, 0x17a, 0x0, 0x3, 0x0, 0x40300040},
                },
-               []*Symbol{
+               symbols: []*Symbol{
                        {".file", 0x0, -2, 0x0, 0x67},
                        {"main", 0x0, 1, 0x20, 0x2},
                        {".text", 0x0, 1, 0x0, 0x3},
                        {"__main", 0x0, 0, 0x20, 0x2},
                        {"puts", 0x0, 0, 0x20, 0x2},
                },
+               hasNoDwarfInfo: true,
        },
        {
-               "testdata/gcc-amd64-mingw-exec",
-               FileHeader{0x8664, 0x11, 0x53e4364f, 0x39600, 0x6fc, 0xf0, 0x27},
-               &OptionalHeader64{
+               file: "testdata/gcc-amd64-mingw-exec",
+               hdr:  FileHeader{0x8664, 0x11, 0x53e4364f, 0x39600, 0x6fc, 0xf0, 0x27},
+               opthdr: &OptionalHeader64{
                        0x20b, 0x2, 0x16, 0x6a00, 0x2400, 0x1600, 0x14e0, 0x1000, 0x400000, 0x1000, 0x200, 0x4, 0x0, 0x0, 0x0, 0x5, 0x2, 0x0, 0x45000, 0x600, 0x46f19, 0x3, 0x0, 0x200000, 0x1000, 0x100000, 0x1000, 0x0, 0x10,
                        [16]DataDirectory{
                                {0x0, 0x0},
                                {0x0, 0x0},
                                {0x0, 0x0},
                        }},
-               []*SectionHeader{
+               sections: []*SectionHeader{
                        {".text", 0x6860, 0x1000, 0x6a00, 0x600, 0x0, 0x0, 0x0, 0x0, 0x60500020},
                        {".data", 0xe0, 0x8000, 0x200, 0x7000, 0x0, 0x0, 0x0, 0x0, 0xc0500040},
                        {".rdata", 0x6b0, 0x9000, 0x800, 0x7200, 0x0, 0x0, 0x0, 0x0, 0x40600040},
                        {".debug_loc", 0x13240, 0x30000, 0x13400, 0x25600, 0x0, 0x0, 0x0, 0x0, 0x42100040},
                        {".debug_ranges", 0xa70, 0x44000, 0xc00, 0x38a00, 0x0, 0x0, 0x0, 0x0, 0x42100040},
                },
-               []*Symbol{},
        },
 }
 
                                t.Errorf("open %s, symbol %d:\n\thave %#v\n\twant %#v\n", tt.file, i, have, want)
                        }
                }
+               if !tt.hasNoDwarfInfo {
+                       _, err = f.DWARF()
+                       if err != nil {
+                               t.Errorf("fetching %s dwarf details failed: %v", tt.file, err)
+                       }
+               }
        }
 }
 
                t.Errorf("open %s: succeeded unexpectedly", filename)
        }
 }
+
+func TestDWARF(t *testing.T) {
+       if runtime.GOOS != "windows" {
+               t.Skip("skipping windows only test")
+       }
+
+       tmpdir, err := ioutil.TempDir("", "TestDWARF")
+       if err != nil {
+               t.Fatal("TempDir failed: ", err)
+       }
+       defer os.RemoveAll(tmpdir)
+
+       prog := `
+package main
+func main() {
+}
+`
+       src := filepath.Join(tmpdir, "a.go")
+       exe := filepath.Join(tmpdir, "a.exe")
+       err = ioutil.WriteFile(src, []byte(prog), 0644)
+       output, err := exec.Command("go", "build", "-o", exe, src).CombinedOutput()
+       if err != nil {
+               t.Fatalf("building test executable failed: %s %s", err, output)
+       }
+
+       f, err := Open(exe)
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer f.Close()
+
+       d, err := f.DWARF()
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       // look for main.main
+       r := d.Reader()
+       for {
+               e, err := r.Next()
+               if err != nil {
+                       t.Fatal("r.Next:", err)
+               }
+               if e == nil {
+                       break
+               }
+               if e.Tag == dwarf.TagSubprogram {
+                       for _, f := range e.Field {
+                               if f.Attr == dwarf.AttrName && e.Val(dwarf.AttrName) == "main.main" {
+                                       return
+                               }
+                       }
+               }
+       }
+       t.Fatal("main.main not found")
+}