From 7e9d9eb17bb2e4bd34e79c9a780d4992ed2ab041 Mon Sep 17 00:00:00 2001 From: Dave Cheney Date: Tue, 18 Dec 2012 07:58:22 +1100 Subject: [PATCH] debug/elf: handle missing shstrndx in core files Fixes #4481. hello-world-core.gz was generated with a simple hello world c program and core dumped as suggested in the issue. Also: add support for gz compressed test fixtures. R=minux.ma, rsc, iant CC=golang-dev https://golang.org/cl/6936058 --- src/pkg/debug/elf/file.go | 7 ++- src/pkg/debug/elf/file_test.go | 59 +++++++++++++++++- .../debug/elf/testdata/hello-world-core.gz | Bin 0 -> 12678 bytes 3 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 src/pkg/debug/elf/testdata/hello-world-core.gz diff --git a/src/pkg/debug/elf/file.go b/src/pkg/debug/elf/file.go index b030b043df..acb9817af0 100644 --- a/src/pkg/debug/elf/file.go +++ b/src/pkg/debug/elf/file.go @@ -272,7 +272,8 @@ func NewFile(r io.ReaderAt) (*File, error) { shnum = int(hdr.Shnum) shstrndx = int(hdr.Shstrndx) } - if shstrndx < 0 || shstrndx >= shnum { + + if shnum > 0 && shoff > 0 && (shstrndx < 0 || shstrndx >= shnum) { return nil, &FormatError{0, "invalid ELF shstrndx", shstrndx} } @@ -367,6 +368,10 @@ func NewFile(r io.ReaderAt) (*File, error) { f.Sections[i] = s } + if len(f.Sections) == 0 { + return f, nil + } + // Load section header string table. shstrtab, err := f.Sections[shstrndx].Data() if err != nil { diff --git a/src/pkg/debug/elf/file_test.go b/src/pkg/debug/elf/file_test.go index 810a2f9b9a..f9aa7265af 100644 --- a/src/pkg/debug/elf/file_test.go +++ b/src/pkg/debug/elf/file_test.go @@ -5,10 +5,14 @@ package elf import ( + "bytes" + "compress/gzip" "debug/dwarf" "encoding/binary" + "io" "net" "os" + "path" "reflect" "runtime" "testing" @@ -121,15 +125,49 @@ var fileTests = []fileTest{ }, []string{"libc.so.6"}, }, + { + "testdata/hello-world-core.gz", + FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0x0, binary.LittleEndian, ET_CORE, EM_X86_64, 0x0}, + []SectionHeader{}, + []ProgHeader{ + {Type: PT_NOTE, Flags: 0x0, Off: 0x3f8, Vaddr: 0x0, Paddr: 0x0, Filesz: 0x8ac, Memsz: 0x0, Align: 0x0}, + {Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x1000, Vaddr: 0x400000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x1000, Align: 0x1000}, + {Type: PT_LOAD, Flags: PF_R, Off: 0x1000, Vaddr: 0x401000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000}, + {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x2000, Vaddr: 0x402000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000}, + {Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x3000, Vaddr: 0x7f54078b8000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x1b5000, Align: 0x1000}, + {Type: PT_LOAD, Flags: 0x0, Off: 0x3000, Vaddr: 0x7f5407a6d000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x1ff000, Align: 0x1000}, + {Type: PT_LOAD, Flags: PF_R, Off: 0x3000, Vaddr: 0x7f5407c6c000, Paddr: 0x0, Filesz: 0x4000, Memsz: 0x4000, Align: 0x1000}, + {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x7000, Vaddr: 0x7f5407c70000, Paddr: 0x0, Filesz: 0x2000, Memsz: 0x2000, Align: 0x1000}, + {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x9000, Vaddr: 0x7f5407c72000, Paddr: 0x0, Filesz: 0x5000, Memsz: 0x5000, Align: 0x1000}, + {Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0xe000, Vaddr: 0x7f5407c77000, Paddr: 0x0, Filesz: 0x0, Memsz: 0x22000, Align: 0x1000}, + {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0xe000, Vaddr: 0x7f5407e81000, Paddr: 0x0, Filesz: 0x3000, Memsz: 0x3000, Align: 0x1000}, + {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x11000, Vaddr: 0x7f5407e96000, Paddr: 0x0, Filesz: 0x3000, Memsz: 0x3000, Align: 0x1000}, + {Type: PT_LOAD, Flags: PF_R, Off: 0x14000, Vaddr: 0x7f5407e99000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000}, + {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x15000, Vaddr: 0x7f5407e9a000, Paddr: 0x0, Filesz: 0x2000, Memsz: 0x2000, Align: 0x1000}, + {Type: PT_LOAD, Flags: PF_W + PF_R, Off: 0x17000, Vaddr: 0x7fff79972000, Paddr: 0x0, Filesz: 0x23000, Memsz: 0x23000, Align: 0x1000}, + {Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x3a000, Vaddr: 0x7fff799f8000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000}, + {Type: PT_LOAD, Flags: PF_X + PF_R, Off: 0x3b000, Vaddr: 0xffffffffff600000, Paddr: 0x0, Filesz: 0x1000, Memsz: 0x1000, Align: 0x1000}, + }, + nil, + }, } func TestOpen(t *testing.T) { for i := range fileTests { tt := &fileTests[i] - f, err := Open(tt.file) + var f *File + var err error + if path.Ext(tt.file) == ".gz" { + var r io.ReaderAt + if r, err = decompress(tt.file); err == nil { + f, err = NewFile(r) + } + } else { + f, err = Open(tt.file) + } if err != nil { - t.Error(err) + t.Errorf("cannot open file %s: %v", tt.file, err) continue } if !reflect.DeepEqual(f.FileHeader, tt.hdr) { @@ -175,6 +213,23 @@ func TestOpen(t *testing.T) { } } +// elf.NewFile requires io.ReaderAt, which compress/gzip cannot +// provide. Decompress the file to a bytes.Reader. +func decompress(gz string) (io.ReaderAt, error) { + in, err := os.Open(gz) + if err != nil { + return nil, err + } + defer in.Close() + r, err := gzip.NewReader(in) + if err != nil { + return nil, err + } + var out bytes.Buffer + _, err = io.Copy(&out, r) + return bytes.NewReader(out.Bytes()), err +} + type relocationTestEntry struct { entryNumber int entry *dwarf.Entry diff --git a/src/pkg/debug/elf/testdata/hello-world-core.gz b/src/pkg/debug/elf/testdata/hello-world-core.gz new file mode 100644 index 0000000000000000000000000000000000000000..806af6edbc23bd0db45a9b1adfae9418ca6a969a GIT binary patch literal 12678 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 Y-g)s?BF`+qef#Ve(D~239)f%S3*17p82|tP literal 0 HcmV?d00001