]> Cypherpunks repositories - gostls13.git/commitdiff
debug/elf: support DWARF that needs relocs for 386
authorIan Lance Taylor <iant@golang.org>
Tue, 3 Jun 2014 23:39:40 +0000 (16:39 -0700)
committerIan Lance Taylor <iant@golang.org>
Tue, 3 Jun 2014 23:39:40 +0000 (16:39 -0700)
It's not clear how widespread this issue is, but we do have a
test case generated by a development version of clang.

I don't know whether this should go into 1.3 or not; happy to
hear arguments either way.

LGTM=rsc
R=golang-codereviews, bradfitz, rsc
CC=golang-codereviews
https://golang.org/cl/96680045

src/pkg/debug/elf/file.go
src/pkg/debug/elf/file_test.go
src/pkg/debug/elf/testdata/go-relocation-test-clang-x86.obj [new file with mode: 0644]

index 2840f07674a3678d63cee68b8bcd155b577565a0..423932fe0ffed7943b71221801075602b3ef725c 100644 (file)
@@ -522,13 +522,17 @@ func (f *File) applyRelocations(dst []byte, rels []byte) error {
        if f.Class == ELFCLASS64 && f.Machine == EM_X86_64 {
                return f.applyRelocationsAMD64(dst, rels)
        }
+       if f.Class == ELFCLASS32 && f.Machine == EM_386 {
+               return f.applyRelocations386(dst, rels)
+       }
 
        return errors.New("not implemented")
 }
 
 func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) error {
-       if len(rels)%Sym64Size != 0 {
-               return errors.New("length of relocation section is not a multiple of Sym64Size")
+       // 24 is the size of Rela64.
+       if len(rels)%24 != 0 {
+               return errors.New("length of relocation section is not a multiple of 24")
        }
 
        symbols, _, err := f.getSymbols(SHT_SYMTAB)
@@ -570,6 +574,43 @@ func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) error {
        return nil
 }
 
+func (f *File) applyRelocations386(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_386(rel.Info & 0xff)
+
+               if symNo == 0 || symNo > uint32(len(symbols)) {
+                       continue
+               }
+               sym := &symbols[symNo-1]
+
+               if t == R_386_32 {
+                       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) DWARF() (*dwarf.Data, error) {
        // There are many other DWARF sections, but these
        // are the required ones, and the debug/dwarf package
@@ -603,6 +644,19 @@ func (f *File) DWARF() (*dwarf.Data, error) {
                }
        }
 
+       // 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
+               }
+               err = f.applyRelocations(dat[1], data)
+               if err != nil {
+                       return nil, err
+               }
+       }
+
        abbrev, info, str := dat[0], dat[1], dat[2]
        d, err := dwarf.New(abbrev, nil, nil, info, nil, nil, nil, str)
        if err != nil {
index 38b5f9e70756b6f304d0bb7ea1fd5114cebba3e1..7f88a54bcd6dec74359f46bddd29cd219f665d64 100644 (file)
@@ -260,6 +260,12 @@ var relocationTests = []relocationTest{
                        {0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{{Attr: dwarf.AttrProducer, Val: "GNU C 4.2.4 (Ubuntu 4.2.4-1ubuntu4)"}, {Attr: dwarf.AttrLanguage, Val: int64(1)}, {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc424.c"}, {Attr: dwarf.AttrCompDir, Val: "/tmp"}, {Attr: dwarf.AttrLowpc, Val: uint64(0x0)}, {Attr: dwarf.AttrHighpc, Val: uint64(0x6)}, {Attr: dwarf.AttrStmtList, Val: int64(0)}}}},
                },
        },
+       {
+               "testdata/go-relocation-test-clang-x86.obj",
+               []relocationTestEntry{
+                       {0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{{Attr: dwarf.AttrProducer, Val: "clang version google3-trunk (trunk r209387)"}, {Attr: dwarf.AttrLanguage, Val: int64(12)}, {Attr: dwarf.AttrName, Val: "go-relocation-test-clang.c"}, {Attr: dwarf.AttrStmtList, Val: int64(0)}, {Attr: dwarf.AttrCompDir, Val: "/tmp"}}}},
+               },
+       },
        {
                "testdata/gcc-amd64-openbsd-debug-with-rela.obj",
                []relocationTestEntry{
diff --git a/src/pkg/debug/elf/testdata/go-relocation-test-clang-x86.obj b/src/pkg/debug/elf/testdata/go-relocation-test-clang-x86.obj
new file mode 100644 (file)
index 0000000..e909cf4
Binary files /dev/null and b/src/pkg/debug/elf/testdata/go-relocation-test-clang-x86.obj differ