Reviewers: golang-dev_googlegroups.com,
Message:
Hello golang-dev@googlegroups.com,
I'd like you to review this change to
https://code.google.com/p/go
Description:
debug/elf: handle missing shstrndx in core files
Fixes issue 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.
Please review this at https://codereview.appspot.com/6936058/
Affected files:
M src/pkg/debug/elf/file.go
M src/pkg/debug/elf/file_test.go
A src/pkg/debug/elf/testdata/hello-world-core.gz
Index: src/pkg/debug/elf/file.go
===================================================================
--- a/src/pkg/debug/elf/file.go
+++ b/src/pkg/debug/elf/file.go
@@ -272,7 +272,7 @@
shnum = int(hdr.Shnum)
shstrndx = int(hdr.Shstrndx)
}
- if shstrndx < 0 || shstrndx >= shnum {
+ if shstrndx < 0 || shstrndx > shnum {
return nil, &FormatError{0, "invalid ELF shstrndx", shstrndx}
}
@@ -367,6 +367,10 @@
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 {
Index: src/pkg/debug/elf/file_test.go
===================================================================
--- a/src/pkg/debug/elf/file_test.go
+++ b/src/pkg/debug/elf/file_test.go
@@ -5,10 +5,14 @@
package elf
import (
+ "compress/gzip"
"debug/dwarf"
"encoding/binary"
+ "io"
+ "io/ioutil"
"net"
"os"
+ "path"
"reflect"
"runtime"
"testing"
@@ -121,15 +125,50 @@
},
[]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)
+ file := tt.file
+ if path.Ext(file) == ".gz" {
+ var err error
+ file, err = decompress(file)
+ if err != nil {
+ t.Error(err)
+ continue
+ }
+ defer os.Remove(file)
+ }
+ f, err := Open(file)
if err != nil {
- t.Error(err)
+ t.Errorf("cannot open file %s: %v", file, err)
continue
}
if !reflect.DeepEqual(f.FileHeader, tt.hdr) {
@@ -175,6 +214,28 @@
}
}
+// elf.NewFile requires io.ReaderAt, which compress/gzip cannot
+// provide. Temporarily decompress the compressed file to a
+// temporary file and return the name of that file.
+func decompress(gz string) (string, error) {
+ in, err := os.Open(gz)
+ if err != nil {
+ return "", err
+ }
+ defer in.Close()
+ r, err := gzip.NewReader(in)
+ if err != nil {
+ return "", err
+ }
+ out, err := ioutil.TempFile("", "elftest")
+ if err != nil {
+ return "", err
+ }
+ defer out.Close()
+ _, err = io.Copy(out, r)
+ return out.Name(), err
+}
+
type relocationTestEntry struct {
entryNumber int
entry *dwarf.Entry
Index: 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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
EFWf@282|tP