Commit 96f6cc15 authored by Tobias Klauser's avatar Tobias Klauser Committed by Tobias Klauser

debug/elf: add riscv64 relocations

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: default avatarIan Lance Taylor <iant@golang.org>
parent 47435b1d
......@@ -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
......
......@@ -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 {
......
......@@ -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{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment