Imported Upstream version 4.8.1
[platform/upstream/gcc48.git] / libgo / go / debug / elf / file.go
index 31895f1..eb3d72f 100644 (file)
@@ -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
 }