debug/elf: fix arm build

This change adds the minimum necessary to implement applyRelocations.

For adg, this code uses the switch statement.

Change-Id: I0989daab8d0e36c2a4f6a315ced258b832744616
Reviewed-on: https://go-review.googlesource.com/7266
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/src/debug/elf/file.go b/src/debug/elf/file.go
index b2174d4..7e0dcc5 100644
--- a/src/debug/elf/file.go
+++ b/src/debug/elf/file.go
@@ -524,20 +524,20 @@
 // 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 == ELFCLASS64 && f.Machine == EM_PPC64 {
+	case f.Class == ELFCLASS64 && f.Machine == EM_PPC64:
 		return f.applyRelocationsPPC64(dst, rels)
+	default:
+		return errors.New("applyRelocations: not implemented")
 	}
-
-	return errors.New("not implemented")
 }
 
 func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) error {
@@ -626,6 +626,44 @@
 	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_REL32:
+			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 {
diff --git a/src/debug/elf/file_test.go b/src/debug/elf/file_test.go
index d57aaab..3e908bb 100644
--- a/src/debug/elf/file_test.go
+++ b/src/debug/elf/file_test.go
@@ -267,6 +267,12 @@
 		},
 	},
 	{
+		"testdata/go-relocation-test-gcc492-arm.obj",
+		[]relocationTestEntry{
+			{0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{{Attr: dwarf.AttrProducer, Val: "GNU C 4.9.2 20141224 (prerelease) -march=armv7-a -mfloat-abi=hard -mfpu=vfpv3-d16 -mtls-dialect=gnu -g"}, {Attr: dwarf.AttrLanguage, Val: int64(1)}, {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc492.c"}, {Attr: dwarf.AttrCompDir, Val: "/root/go/src/debug/elf/testdata"}, {Attr: dwarf.AttrLowpc, Val: uint64(0x0)}, {Attr: dwarf.AttrHighpc, Val: int64(0x28)}, {Attr: dwarf.AttrStmtList, Val: int64(0)}}}},
+		},
+	},
+	{
 		"testdata/go-relocation-test-gcc482-ppc64le.obj",
 		[]relocationTestEntry{
 			{0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{dwarf.Field{Attr: dwarf.AttrProducer, Val: "GNU C 4.8.2 -Asystem=linux -Asystem=unix -Asystem=posix -msecure-plt -mtune=power8 -mcpu=power7 -gdwarf-2 -fstack-protector"}, dwarf.Field{Attr: dwarf.AttrLanguage, Val: int64(1)}, dwarf.Field{Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482-ppc64le.c"}, dwarf.Field{Attr: dwarf.AttrCompDir, Val: "/tmp"}, dwarf.Field{Attr: dwarf.AttrLowpc, Val: uint64(0x0)}, dwarf.Field{Attr: dwarf.AttrHighpc, Val: uint64(0x24)}, dwarf.Field{Attr: dwarf.AttrStmtList, Val: int64(0)}}}},
diff --git a/src/debug/elf/testdata/go-relocation-test-gcc492-arm.obj b/src/debug/elf/testdata/go-relocation-test-gcc492-arm.obj
new file mode 100644
index 0000000..ed45be2
--- /dev/null
+++ b/src/debug/elf/testdata/go-relocation-test-gcc492-arm.obj
Binary files differ