summaryrefslogtreecommitdiff
path: root/libgo/go/debug/elf/file.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/debug/elf/file.go')
-rw-r--r--libgo/go/debug/elf/file.go149
1 files changed, 84 insertions, 65 deletions
diff --git a/libgo/go/debug/elf/file.go b/libgo/go/debug/elf/file.go
index 0135f7f8dbf..370c5e6437c 100644
--- a/libgo/go/debug/elf/file.go
+++ b/libgo/go/debug/elf/file.go
@@ -13,6 +13,7 @@ import (
"fmt"
"io"
"os"
+ "strings"
)
// TODO: error reporting detail
@@ -523,26 +524,24 @@ func (f *File) Section(name string) *Section {
// applyRelocations applies relocations to dst. rels is a relocations section
// in RELA format.
func (f *File) applyRelocations(dst []byte, rels []byte) error {
- if f.Class == ELFCLASS64 && f.Machine == EM_X86_64 {
+ switch {
+ case f.Class == ELFCLASS64 && f.Machine == EM_X86_64:
return f.applyRelocationsAMD64(dst, rels)
- }
- if f.Class == ELFCLASS32 && f.Machine == EM_386 {
+ case f.Class == ELFCLASS32 && f.Machine == EM_386:
return f.applyRelocations386(dst, rels)
- }
- if f.Class == ELFCLASS64 && f.Machine == EM_AARCH64 {
+ case f.Class == ELFCLASS32 && f.Machine == EM_ARM:
+ return f.applyRelocationsARM(dst, rels)
+ case f.Class == ELFCLASS64 && f.Machine == EM_AARCH64:
return f.applyRelocationsARM64(dst, rels)
- }
- if f.Class == ELFCLASS32 && f.Machine == EM_PPC {
+ case f.Class == ELFCLASS32 && f.Machine == EM_PPC:
return f.applyRelocationsPPC(dst, rels)
- }
- if f.Class == ELFCLASS64 && f.Machine == EM_PPC64 {
+ case f.Class == ELFCLASS64 && f.Machine == EM_PPC64:
return f.applyRelocationsPPC64(dst, rels)
- }
- if f.Class == ELFCLASS64 && f.Machine == EM_S390 {
+ case f.Class == ELFCLASS64 && f.Machine == EM_S390:
return f.applyRelocationsS390x(dst, rels)
+ default:
+ return errors.New("applyRelocations: not implemented")
}
-
- return errors.New("not implemented")
}
func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) error {
@@ -631,6 +630,44 @@ func (f *File) applyRelocations386(dst []byte, rels []byte) error {
return nil
}
+func (f *File) applyRelocationsARM(dst []byte, rels []byte) error {
+ // 8 is the size of Rel32.
+ if len(rels)%8 != 0 {
+ return errors.New("length of relocation section is not a multiple of 8")
+ }
+
+ symbols, _, err := f.getSymbols(SHT_SYMTAB)
+ if err != nil {
+ return err
+ }
+
+ b := bytes.NewReader(rels)
+ var rel Rel32
+
+ for b.Len() > 0 {
+ binary.Read(b, f.ByteOrder, &rel)
+ symNo := rel.Info >> 8
+ t := R_ARM(rel.Info & 0xff)
+
+ if symNo == 0 || symNo > uint32(len(symbols)) {
+ continue
+ }
+ sym := &symbols[symNo-1]
+
+ switch t {
+ case R_ARM_ABS32:
+ if rel.Off+4 >= uint32(len(dst)) {
+ continue
+ }
+ val := f.ByteOrder.Uint32(dst[rel.Off : rel.Off+4])
+ val += uint32(sym.Value)
+ f.ByteOrder.PutUint32(dst[rel.Off:rel.Off+4], val)
+ }
+ }
+
+ return nil
+}
+
func (f *File) applyRelocationsARM64(dst []byte, rels []byte) error {
// 24 is the size of Rela64.
if len(rels)%24 != 0 {
@@ -807,53 +844,52 @@ func (f *File) applyRelocationsS390x(dst []byte, rels []byte) error {
}
func (f *File) DWARF() (*dwarf.Data, error) {
- // There are many other DWARF sections, but these
- // are the required ones, and the debug/dwarf package
- // does not use the others, so don't bother loading them.
- var names = [...]string{"abbrev", "info", "line", "ranges", "str"}
- var dat [len(names)][]byte
- for i, name := range names {
- name = ".debug_" + name
- s := f.Section(name)
- if s == nil {
- continue
- }
+ // sectionData gets the data for s, checks its size, and
+ // applies any applicable relations.
+ sectionData := func(i int, s *Section) ([]byte, error) {
b, err := s.Data()
if err != nil && uint64(len(b)) < s.Size {
return nil, err
}
- dat[i] = b
- }
- // If there's a relocation table for .debug_info, we have to process it
- // now otherwise the data in .debug_info is invalid for x86-64 objects.
- rela := f.Section(".rela.debug_info")
- if rela != nil && rela.Type == SHT_RELA && (f.Machine == EM_X86_64 || f.Machine == EM_AARCH64 || f.Machine == EM_PPC || f.Machine == EM_PPC64 || f.Machine == EM_S390) {
- data, err := rela.Data()
- if err != nil {
- return nil, err
- }
- err = f.applyRelocations(dat[1], data)
- if err != nil {
- return nil, err
+ for _, r := range f.Sections {
+ if r.Type != SHT_RELA && r.Type != SHT_REL {
+ continue
+ }
+ if int(r.Info) != i {
+ continue
+ }
+ rd, err := r.Data()
+ if err != nil {
+ return nil, err
+ }
+ err = f.applyRelocations(b, rd)
+ if err != nil {
+ return nil, err
+ }
}
+ return b, nil
}
- // When using clang we need to process relocations even for 386.
- rel := f.Section(".rel.debug_info")
- if rel != nil && rel.Type == SHT_REL && f.Machine == EM_386 {
- data, err := rel.Data()
- if err != nil {
- return nil, err
+ // There are many other DWARF sections, but these
+ // are the ones the debug/dwarf package uses.
+ // Don't bother loading others.
+ var dat = map[string][]byte{"abbrev": nil, "info": nil, "str": nil, "line": nil, "ranges": nil}
+ for i, s := range f.Sections {
+ if !strings.HasPrefix(s.Name, ".debug_") {
+ continue
+ }
+ if _, ok := dat[s.Name[7:]]; !ok {
+ continue
}
- err = f.applyRelocations(dat[1], data)
+ b, err := sectionData(i, s)
if err != nil {
return nil, err
}
+ dat[s.Name[7:]] = b
}
- abbrev, info, line, ranges, str := dat[0], dat[1], dat[2], dat[3], dat[4]
- d, err := dwarf.New(abbrev, nil, nil, info, line, nil, ranges, str)
+ d, err := dwarf.New(dat["abbrev"], nil, nil, dat["info"], dat["line"], nil, dat["ranges"], dat["str"])
if err != nil {
return nil, err
}
@@ -861,28 +897,11 @@ func (f *File) DWARF() (*dwarf.Data, error) {
// Look for DWARF4 .debug_types sections.
for i, s := range f.Sections {
if s.Name == ".debug_types" {
- b, err := s.Data()
- if err != nil && uint64(len(b)) < s.Size {
+ b, err := sectionData(i, s)
+ if err != nil {
return nil, err
}
- for _, r := range f.Sections {
- if r.Type != SHT_RELA && r.Type != SHT_REL {
- continue
- }
- if int(r.Info) != i {
- continue
- }
- rd, err := r.Data()
- if err != nil {
- return nil, err
- }
- err = f.applyRelocations(b, rd)
- if err != nil {
- return nil, err
- }
- }
-
err = d.AddTypes(fmt.Sprintf("types-%d", i), b)
if err != nil {
return nil, err