diff options
Diffstat (limited to 'src/pkg/debug/elf/file.go')
-rw-r--r-- | src/pkg/debug/elf/file.go | 53 |
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 } |