summaryrefslogtreecommitdiff
path: root/src/pkg/debug/elf/file.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/debug/elf/file.go')
-rw-r--r--src/pkg/debug/elf/file.go53
1 files changed, 33 insertions, 20 deletions
diff --git a/src/pkg/debug/elf/file.go b/src/pkg/debug/elf/file.go
index 184ca8375..acb9817af 100644
--- a/src/pkg/debug/elf/file.go
+++ b/src/pkg/debug/elf/file.go
@@ -31,6 +31,7 @@ type FileHeader struct {
ByteOrder binary.ByteOrder
Type Type
Machine Machine
+ Entry uint64
}
// A File represents an open ELF file.
@@ -240,6 +241,7 @@ func NewFile(r io.ReaderAt) (*File, error) {
}
f.Type = Type(hdr.Type)
f.Machine = Machine(hdr.Machine)
+ f.Entry = uint64(hdr.Entry)
if v := Version(hdr.Version); v != f.Version {
return nil, &FormatError{0, "mismatched ELF version", v}
}
@@ -258,6 +260,7 @@ func NewFile(r io.ReaderAt) (*File, error) {
}
f.Type = Type(hdr.Type)
f.Machine = Machine(hdr.Machine)
+ f.Entry = uint64(hdr.Entry)
if v := Version(hdr.Version); v != f.Version {
return nil, &FormatError{0, "mismatched ELF version", v}
}
@@ -269,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}
}
@@ -364,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 {
@@ -414,10 +422,6 @@ func (f *File) getSymbols32(typ SectionType) ([]Symbol, []byte, error) {
return nil, nil, errors.New("cannot load string table section")
}
- // The first entry is all zeros.
- var skip [Sym32Size]byte
- symtab.Read(skip[0:])
-
symbols := make([]Symbol, symtab.Len()/Sym32Size)
i := 0
@@ -457,10 +461,6 @@ func (f *File) getSymbols64(typ SectionType) ([]Symbol, []byte, error) {
return nil, nil, errors.New("cannot load string table section")
}
- // The first entry is all zeros.
- var skip [Sym64Size]byte
- symtab.Read(skip[0:])
-
symbols := make([]Symbol, symtab.Len()/Sym64Size)
i := 0
@@ -705,8 +705,8 @@ func (f *File) gnuVersionInit(str []byte) {
// gnuVersion adds Library and Version information to sym,
// which came from offset i of the symbol table.
func (f *File) gnuVersion(i int, sym *ImportedSymbol) {
- // Each entry is two bytes; skip undef entry at beginning.
- i = (i + 1) * 2
+ // Each entry is two bytes.
+ i = i * 2
if i >= len(f.gnuVersym) {
return
}
@@ -723,6 +723,20 @@ func (f *File) gnuVersion(i int, sym *ImportedSymbol) {
// referred to by the binary f that are expected to be
// linked with the binary at dynamic link time.
func (f *File) ImportedLibraries() ([]string, error) {
+ return f.DynString(DT_NEEDED)
+}
+
+// DynString returns the strings listed for the given tag in the file's dynamic
+// section.
+//
+// The tag must be one that takes string values: DT_NEEDED, DT_SONAME, DT_RPATH, or
+// DT_RUNPATH.
+func (f *File) DynString(tag DynTag) ([]string, error) {
+ switch tag {
+ case DT_NEEDED, DT_SONAME, DT_RPATH, DT_RUNPATH:
+ default:
+ return nil, fmt.Errorf("non-string-valued tag %v", tag)
+ }
ds := f.SectionByType(SHT_DYNAMIC)
if ds == nil {
// not dynamic, so no libraries
@@ -738,25 +752,24 @@ func (f *File) ImportedLibraries() ([]string, error) {
}
var all []string
for len(d) > 0 {
- var tag DynTag
- var value uint64
+ var t DynTag
+ var v uint64
switch f.Class {
case ELFCLASS32:
- tag = DynTag(f.ByteOrder.Uint32(d[0:4]))
- value = uint64(f.ByteOrder.Uint32(d[4:8]))
+ t = DynTag(f.ByteOrder.Uint32(d[0:4]))
+ v = uint64(f.ByteOrder.Uint32(d[4:8]))
d = d[8:]
case ELFCLASS64:
- tag = DynTag(f.ByteOrder.Uint64(d[0:8]))
- value = f.ByteOrder.Uint64(d[8:16])
+ t = DynTag(f.ByteOrder.Uint64(d[0:8]))
+ v = f.ByteOrder.Uint64(d[8:16])
d = d[16:]
}
- if tag == DT_NEEDED {
- s, ok := getString(str, int(value))
+ if t == tag {
+ s, ok := getString(str, int(v))
if ok {
all = append(all, s)
}
}
}
-
return all, nil
}