]> Cypherpunks repositories - gostls13.git/commitdiff
debug/elf: add riscv64 relocations
authorTobias Klauser <tklauser@distanz.ch>
Thu, 12 Apr 2018 14:35:51 +0000 (16:35 +0200)
committerTobias Klauser <tobias.klauser@gmail.com>
Wed, 18 Apr 2018 13:19:31 +0000 (13:19 +0000)
Based on the code from https://github.com/riscv/riscv-go/ originally
written by Amol Bhave.

Change-Id: I8d5377096d4ff8b198dadb630511f9a0347f9797
Reviewed-on: https://go-review.googlesource.com/107339
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/debug/elf/elf.go
src/debug/elf/file.go
src/debug/elf/file_test.go
src/debug/elf/testdata/go-relocation-test-gcc720-riscv64.obj [new file with mode: 0644]

index 6f96b3e3bccde209f7f9d860a67950be5487d791..4bf118ec73dcb0f7373ad5f0626b00e08dda70e8 100644 (file)
@@ -12,6 +12,7 @@
  * $FreeBSD: src/sys/powerpc/include/elf.h,v 1.7 2004/11/02 09:47:01 ssouhlal Exp $
  * $FreeBSD: src/sys/sparc64/include/elf.h,v 1.12 2003/09/25 01:10:26 peter Exp $
  * "ELF for the ARMĀ® 64-bit Architecture (AArch64)" (ARM IHI 0056B)
+ * "RISC-V ELF psABI specification" (https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md)
  *
  * Copyright (c) 1996-1998 John D. Polstra.  All rights reserved.
  * Copyright (c) 2001 David E. O'Brien
@@ -237,6 +238,7 @@ const (
        EM_TINYJ       Machine = 61  /* Advanced Logic Corp. TinyJ processor. */
        EM_X86_64      Machine = 62  /* Advanced Micro Devices x86-64 */
        EM_AARCH64     Machine = 183 /* ARM 64-bit Architecture (AArch64) */
+       EM_RISCV       Machine = 243 /* RISC-V */
 
        /* Non-standard or deprecated. */
        EM_486         Machine = 6      /* Intel i486. */
@@ -290,6 +292,7 @@ var machineStrings = []intName{
        {61, "EM_TINYJ"},
        {62, "EM_X86_64"},
        {183, "EM_AARCH64"},
+       {243, "EM_RISCV"},
 
        /* Non-standard or deprecated. */
        {6, "EM_486"},
@@ -2082,6 +2085,124 @@ var rppc64Strings = []intName{
 func (i R_PPC64) String() string   { return stringName(uint32(i), rppc64Strings, false) }
 func (i R_PPC64) GoString() string { return stringName(uint32(i), rppc64Strings, true) }
 
+// Relocation types for RISC-V processors.
+type R_RISCV int
+
+const (
+       R_RISCV_NONE          R_RISCV = 0  /* No relocation. */
+       R_RISCV_32            R_RISCV = 1  /* Add 32 bit zero extended symbol value */
+       R_RISCV_64            R_RISCV = 2  /* Add 64 bit symbol value. */
+       R_RISCV_RELATIVE      R_RISCV = 3  /* Add load address of shared object. */
+       R_RISCV_COPY          R_RISCV = 4  /* Copy data from shared object. */
+       R_RISCV_JUMP_SLOT     R_RISCV = 5  /* Set GOT entry to code address. */
+       R_RISCV_TLS_DTPMOD32  R_RISCV = 6  /* 32 bit ID of module containing symbol */
+       R_RISCV_TLS_DTPMOD64  R_RISCV = 7  /* ID of module containing symbol */
+       R_RISCV_TLS_DTPREL32  R_RISCV = 8  /* 32 bit relative offset in TLS block */
+       R_RISCV_TLS_DTPREL64  R_RISCV = 9  /* Relative offset in TLS block */
+       R_RISCV_TLS_TPREL32   R_RISCV = 10 /* 32 bit relative offset in static TLS block */
+       R_RISCV_TLS_TPREL64   R_RISCV = 11 /* Relative offset in static TLS block */
+       R_RISCV_BRANCH        R_RISCV = 16 /* PC-relative branch */
+       R_RISCV_JAL           R_RISCV = 17 /* PC-relative jump */
+       R_RISCV_CALL          R_RISCV = 18 /* PC-relative call */
+       R_RISCV_CALL_PLT      R_RISCV = 19 /* PC-relative call (PLT) */
+       R_RISCV_GOT_HI20      R_RISCV = 20 /* PC-relative GOT reference */
+       R_RISCV_TLS_GOT_HI20  R_RISCV = 21 /* PC-relative TLS IE GOT offset */
+       R_RISCV_TLS_GD_HI20   R_RISCV = 22 /* PC-relative TLS GD reference */
+       R_RISCV_PCREL_HI20    R_RISCV = 23 /* PC-relative reference */
+       R_RISCV_PCREL_LO12_I  R_RISCV = 24 /* PC-relative reference */
+       R_RISCV_PCREL_LO12_S  R_RISCV = 25 /* PC-relative reference */
+       R_RISCV_HI20          R_RISCV = 26 /* Absolute address */
+       R_RISCV_LO12_I        R_RISCV = 27 /* Absolute address */
+       R_RISCV_LO12_S        R_RISCV = 28 /* Absolute address */
+       R_RISCV_TPREL_HI20    R_RISCV = 29 /* TLS LE thread offset */
+       R_RISCV_TPREL_LO12_I  R_RISCV = 30 /* TLS LE thread offset */
+       R_RISCV_TPREL_LO12_S  R_RISCV = 31 /* TLS LE thread offset */
+       R_RISCV_TPREL_ADD     R_RISCV = 32 /* TLS LE thread usage */
+       R_RISCV_ADD8          R_RISCV = 33 /* 8-bit label addition */
+       R_RISCV_ADD16         R_RISCV = 34 /* 16-bit label addition */
+       R_RISCV_ADD32         R_RISCV = 35 /* 32-bit label addition */
+       R_RISCV_ADD64         R_RISCV = 36 /* 64-bit label addition */
+       R_RISCV_SUB8          R_RISCV = 37 /* 8-bit label subtraction */
+       R_RISCV_SUB16         R_RISCV = 38 /* 16-bit label subtraction */
+       R_RISCV_SUB32         R_RISCV = 39 /* 32-bit label subtraction */
+       R_RISCV_SUB64         R_RISCV = 40 /* 64-bit label subtraction */
+       R_RISCV_GNU_VTINHERIT R_RISCV = 41 /* GNU C++ vtable hierarchy */
+       R_RISCV_GNU_VTENTRY   R_RISCV = 42 /* GNU C++ vtable member usage */
+       R_RISCV_ALIGN         R_RISCV = 43 /* Alignment statement */
+       R_RISCV_RVC_BRANCH    R_RISCV = 44 /* PC-relative branch offset */
+       R_RISCV_RVC_JUMP      R_RISCV = 45 /* PC-relative jump offset */
+       R_RISCV_RVC_LUI       R_RISCV = 46 /* Absolute address */
+       R_RISCV_GPREL_I       R_RISCV = 47 /* GP-relative reference */
+       R_RISCV_GPREL_S       R_RISCV = 48 /* GP-relative reference */
+       R_RISCV_TPREL_I       R_RISCV = 49 /* TP-relative TLS LE load */
+       R_RISCV_TPREL_S       R_RISCV = 50 /* TP-relative TLS LE store */
+       R_RISCV_RELAX         R_RISCV = 51 /* Instruction pair can be relaxed */
+       R_RISCV_SUB6          R_RISCV = 52 /* Local label subtraction */
+       R_RISCV_SET6          R_RISCV = 53 /* Local label subtraction */
+       R_RISCV_SET8          R_RISCV = 54 /* Local label subtraction */
+       R_RISCV_SET16         R_RISCV = 55 /* Local label subtraction */
+       R_RISCV_SET32         R_RISCV = 56 /* Local label subtraction */
+)
+
+var rriscvStrings = []intName{
+       {0, "R_RISCV_NONE"},
+       {1, "R_RISCV_32"},
+       {2, "R_RISCV_64"},
+       {3, "R_RISCV_RELATIVE"},
+       {4, "R_RISCV_COPY"},
+       {5, "R_RISCV_JUMP_SLOT"},
+       {6, "R_RISCV_TLS_DTPMOD32"},
+       {7, "R_RISCV_TLS_DTPMOD64"},
+       {8, "R_RISCV_TLS_DTPREL32"},
+       {9, "R_RISCV_TLS_DTPREL64"},
+       {10, "R_RISCV_TLS_TPREL32"},
+       {11, "R_RISCV_TLS_TPREL64"},
+       {16, "R_RISCV_BRANCH"},
+       {17, "R_RISCV_JAL"},
+       {18, "R_RISCV_CALL"},
+       {19, "R_RISCV_CALL_PLT"},
+       {20, "R_RISCV_GOT_HI20"},
+       {21, "R_RISCV_TLS_GOT_HI20"},
+       {22, "R_RISCV_TLS_GD_HI20"},
+       {23, "R_RISCV_PCREL_HI20"},
+       {24, "R_RISCV_PCREL_LO12_I"},
+       {25, "R_RISCV_PCREL_LO12_S"},
+       {26, "R_RISCV_HI20"},
+       {27, "R_RISCV_LO12_I"},
+       {28, "R_RISCV_LO12_S"},
+       {29, "R_RISCV_TPREL_HI20"},
+       {30, "R_RISCV_TPREL_LO12_I"},
+       {31, "R_RISCV_TPREL_LO12_S"},
+       {32, "R_RISCV_TPREL_ADD"},
+       {33, "R_RISCV_ADD8"},
+       {34, "R_RISCV_ADD16"},
+       {35, "R_RISCV_ADD32"},
+       {36, "R_RISCV_ADD64"},
+       {37, "R_RISCV_SUB8"},
+       {38, "R_RISCV_SUB16"},
+       {39, "R_RISCV_SUB32"},
+       {40, "R_RISCV_SUB64"},
+       {41, "R_RISCV_GNU_VTINHERIT"},
+       {42, "R_RISCV_GNU_VTENTRY"},
+       {43, "R_RISCV_ALIGN"},
+       {44, "R_RISCV_RVC_BRANCH"},
+       {45, "R_RISCV_RVC_JUMP"},
+       {46, "R_RISCV_RVC_LUI"},
+       {47, "R_RISCV_GPREL_I"},
+       {48, "R_RISCV_GPREL_S"},
+       {49, "R_RISCV_TPREL_I"},
+       {50, "R_RISCV_TPREL_S"},
+       {51, "R_RISCV_RELAX"},
+       {52, "R_RISCV_SUB6"},
+       {53, "R_RISCV_SET6"},
+       {54, "R_RISCV_SET8"},
+       {55, "R_RISCV_SET16"},
+       {56, "R_RISCV_SET32"},
+}
+
+func (i R_RISCV) String() string   { return stringName(uint32(i), rriscvStrings, false) }
+func (i R_RISCV) GoString() string { return stringName(uint32(i), rriscvStrings, true) }
+
 // Relocation types for s390x processors.
 type R_390 int
 
index 95c0606f8022ee33b39a59a78e185d025a613abb..25b72642d8c7b9aabc6ce12bd5ec02635ffcb205 100644 (file)
@@ -609,6 +609,8 @@ func (f *File) applyRelocations(dst []byte, rels []byte) error {
                return f.applyRelocationsMIPS(dst, rels)
        case f.Class == ELFCLASS64 && f.Machine == EM_MIPS:
                return f.applyRelocationsMIPS64(dst, rels)
+       case f.Class == ELFCLASS64 && f.Machine == EM_RISCV:
+               return f.applyRelocationsRISCV64(dst, rels)
        case f.Class == ELFCLASS64 && f.Machine == EM_S390:
                return f.applyRelocationss390x(dst, rels)
        case f.Class == ELFCLASS64 && f.Machine == EM_SPARCV9:
@@ -966,6 +968,55 @@ func (f *File) applyRelocationsMIPS64(dst []byte, rels []byte) error {
        return nil
 }
 
+func (f *File) applyRelocationsRISCV64(dst []byte, rels []byte) error {
+       // 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)
+       if err != nil {
+               return err
+       }
+
+       b := bytes.NewReader(rels)
+       var rela Rela64
+
+       for b.Len() > 0 {
+               binary.Read(b, f.ByteOrder, &rela)
+               symNo := rela.Info >> 32
+               t := R_RISCV(rela.Info & 0xffff)
+
+               if symNo == 0 || symNo > uint64(len(symbols)) {
+                       continue
+               }
+               sym := &symbols[symNo-1]
+               switch SymType(sym.Info & 0xf) {
+               case STT_SECTION, STT_NOTYPE:
+                       break
+               default:
+                       continue
+               }
+
+               switch t {
+               case R_RISCV_64:
+                       if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
+                               continue
+                       }
+                       val := sym.Value + uint64(rela.Addend)
+                       f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val)
+               case R_RISCV_32:
+                       if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
+                               continue
+                       }
+                       val := uint32(sym.Value) + uint32(rela.Addend)
+                       f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val)
+               }
+       }
+
+       return nil
+}
+
 func (f *File) applyRelocationss390x(dst []byte, rels []byte) error {
        // 24 is the size of Rela64.
        if len(rels)%24 != 0 {
index ce27abb064de8153661f1153323b1450686a3646..880b66e7970d1d1f23dd34f41b3f78296aca112f 100644 (file)
@@ -567,6 +567,25 @@ var relocationTests = []relocationTest{
                        }},
                },
        },
+       {
+               "testdata/go-relocation-test-gcc720-riscv64.obj",
+               []relocationTestEntry{
+                       {0, &dwarf.Entry{
+                               Offset:   0xb,
+                               Tag:      dwarf.TagCompileUnit,
+                               Children: true,
+                               Field: []dwarf.Field{
+                                       {Attr: dwarf.AttrProducer, Val: "GNU C11 7.2.0 -march=rv64imafdc -mabi=lp64d -g -gdwarf-2", Class: dwarf.ClassString},
+                                       {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
+                                       {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
+                                       {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
+                                       {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
+                                       {Attr: dwarf.AttrHighpc, Val: uint64(0x2c), Class: dwarf.ClassAddress},
+                                       {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
+                               },
+                       }},
+               },
+       },
        {
                "testdata/go-relocation-test-clang-x86.obj",
                []relocationTestEntry{
diff --git a/src/debug/elf/testdata/go-relocation-test-gcc720-riscv64.obj b/src/debug/elf/testdata/go-relocation-test-gcc720-riscv64.obj
new file mode 100644 (file)
index 0000000..91ae648
Binary files /dev/null and b/src/debug/elf/testdata/go-relocation-test-gcc720-riscv64.obj differ