Add minimal riscv64 elf support to allow create_minidebuginfo on riscv64 binaries
This adds support for riscv64 elf files so that create_minidebuginfo
can be used strip riscv64 binaries.
Test: m create_minidebuginfo
Change-Id: I0cb0348d46ffb216af2f5c61701406504fae3b22
diff --git a/build/art.go b/build/art.go
index 7b06353..970af8a 100644
--- a/build/art.go
+++ b/build/art.go
@@ -95,12 +95,14 @@
cflags = append(cflags,
"-DART_STACK_OVERFLOW_GAP_arm=16384",
"-DART_STACK_OVERFLOW_GAP_arm64=16384",
+ "-DART_STACK_OVERFLOW_GAP_riscv64=16384",
"-DART_STACK_OVERFLOW_GAP_x86=16384",
"-DART_STACK_OVERFLOW_GAP_x86_64=20480")
} else {
cflags = append(cflags,
"-DART_STACK_OVERFLOW_GAP_arm=8192",
"-DART_STACK_OVERFLOW_GAP_arm64=8192",
+ "-DART_STACK_OVERFLOW_GAP_riscv64=8192",
"-DART_STACK_OVERFLOW_GAP_x86=8192",
"-DART_STACK_OVERFLOW_GAP_x86_64=8192")
}
diff --git a/compiler/debug/elf_debug_frame_writer.h b/compiler/debug/elf_debug_frame_writer.h
index 094e887..269e3c6 100644
--- a/compiler/debug/elf_debug_frame_writer.h
+++ b/compiler/debug/elf_debug_frame_writer.h
@@ -88,6 +88,10 @@
WriteCIE(is64bit, return_reg, opcodes, buffer);
return;
}
+ case InstructionSet::kRiscv64: {
+ UNIMPLEMENTED(FATAL);
+ return;
+ }
case InstructionSet::kX86: {
// FIXME: Add fp registers once libunwind adds support for them. Bug: 20491296
constexpr bool generate_opcodes_for_x86_fp = false;
diff --git a/compiler/debug/elf_debug_line_writer.h b/compiler/debug/elf_debug_line_writer.h
index 8d62747..7df301a 100644
--- a/compiler/debug/elf_debug_line_writer.h
+++ b/compiler/debug/elf_debug_line_writer.h
@@ -73,6 +73,7 @@
code_factor_bits_ = 2; // 32-bit instructions
break;
case InstructionSet::kNone:
+ case InstructionSet::kRiscv64:
case InstructionSet::kX86:
case InstructionSet::kX86_64:
break;
diff --git a/compiler/debug/elf_debug_loc_writer.h b/compiler/debug/elf_debug_loc_writer.h
index 9be1e24..3742081 100644
--- a/compiler/debug/elf_debug_loc_writer.h
+++ b/compiler/debug/elf_debug_loc_writer.h
@@ -37,6 +37,8 @@
return Reg::ArmCore(machine_reg);
case InstructionSet::kArm64:
return Reg::Arm64Core(machine_reg);
+ case InstructionSet::kRiscv64:
+ return Reg::Riscv64Core(machine_reg);
case InstructionSet::kX86:
return Reg::X86Core(machine_reg);
case InstructionSet::kX86_64:
@@ -54,6 +56,8 @@
return Reg::ArmFp(machine_reg);
case InstructionSet::kArm64:
return Reg::Arm64Fp(machine_reg);
+ case InstructionSet::kRiscv64:
+ return Reg::Riscv64Fp(machine_reg);
case InstructionSet::kX86:
return Reg::X86Fp(machine_reg);
case InstructionSet::kX86_64:
diff --git a/libartbase/arch/instruction_set.cc b/libartbase/arch/instruction_set.cc
index 7f1e4c7..811e723 100644
--- a/libartbase/arch/instruction_set.cc
+++ b/libartbase/arch/instruction_set.cc
@@ -29,6 +29,7 @@
case InstructionSet::kArm:
case InstructionSet::kThumb2:
case InstructionSet::kArm64:
+ case InstructionSet::kRiscv64:
case InstructionSet::kX86:
case InstructionSet::kX86_64:
case InstructionSet::kNone:
@@ -46,6 +47,8 @@
return "arm";
case InstructionSet::kArm64:
return "arm64";
+ case InstructionSet::kRiscv64:
+ return "riscv64";
case InstructionSet::kX86:
return "x86";
case InstructionSet::kX86_64:
@@ -64,6 +67,8 @@
return InstructionSet::kArm;
} else if (strcmp("arm64", isa_str) == 0) {
return InstructionSet::kArm64;
+ } else if (strcmp("riscv64", isa_str) == 0) {
+ return InstructionSet::kRiscv64;
} else if (strcmp("x86", isa_str) == 0) {
return InstructionSet::kX86;
} else if (strcmp("x86_64", isa_str) == 0) {
@@ -93,6 +98,8 @@
*error_msg = android::base::StringPrintf("Unknown Zygote kinds '%s'", zygote_kinds.c_str());
return {};
}
+ case InstructionSet::kRiscv64:
+ return {InstructionSet::kRiscv64};
case InstructionSet::kX86:
case InstructionSet::kX86_64:
if (zygote_kinds == "zygote64_32" || zygote_kinds == "zygote32_64") {
diff --git a/libartbase/arch/instruction_set.h b/libartbase/arch/instruction_set.h
index e68ff08..8d59f1b 100644
--- a/libartbase/arch/instruction_set.h
+++ b/libartbase/arch/instruction_set.h
@@ -31,6 +31,7 @@
kArm,
kArm64,
kThumb2,
+ kRiscv64,
kX86,
kX86_64,
kLast = kX86_64
@@ -41,6 +42,8 @@
static constexpr InstructionSet kRuntimeISA = InstructionSet::kArm;
#elif defined(__aarch64__)
static constexpr InstructionSet kRuntimeISA = InstructionSet::kArm64;
+#elif defined (__riscv)
+static constexpr InstructionSet kRuntimeISA = InstructionSet::kRiscv64;
#elif defined(__i386__)
static constexpr InstructionSet kRuntimeISA = InstructionSet::kX86;
#elif defined(__x86_64__)
@@ -52,6 +55,7 @@
// Architecture-specific pointer sizes
static constexpr PointerSize kArmPointerSize = PointerSize::k32;
static constexpr PointerSize kArm64PointerSize = PointerSize::k64;
+static constexpr PointerSize kRiscv64PointerSize = PointerSize::k64;
static constexpr PointerSize kX86PointerSize = PointerSize::k32;
static constexpr PointerSize kX86_64PointerSize = PointerSize::k64;
@@ -63,12 +67,17 @@
// ARM processors require code to be 4-byte aligned, but ARM ELF requires 8.
static constexpr size_t kArmCodeAlignment = 8;
static constexpr size_t kArm64CodeAlignment = 16;
+static constexpr size_t kRiscv64CodeAlignment = 16;
static constexpr size_t kX86CodeAlignment = 16;
// Instruction alignment (every instruction must be aligned at this boundary). This differs from
// code alignment, which applies only to the first instruction of a subroutine.
+// Android requires the RISC-V compressed instruction extension, and that allows
+// *all* instructions (not just compressed ones) to be 2-byte aligned rather
+// than the usual 4-byte alignment requirement.
static constexpr size_t kThumb2InstructionAlignment = 2;
static constexpr size_t kArm64InstructionAlignment = 4;
+static constexpr size_t kRiscv64InstructionAlignment = 2;
static constexpr size_t kX86InstructionAlignment = 1;
static constexpr size_t kX86_64InstructionAlignment = 1;
@@ -88,6 +97,8 @@
return kArmPointerSize;
case InstructionSet::kArm64:
return kArm64PointerSize;
+ case InstructionSet::kRiscv64:
+ return kRiscv64PointerSize;
case InstructionSet::kX86:
return kX86PointerSize;
case InstructionSet::kX86_64:
@@ -104,6 +115,7 @@
case InstructionSet::kArm:
case InstructionSet::kThumb2:
case InstructionSet::kArm64:
+ case InstructionSet::kRiscv64:
case InstructionSet::kX86:
case InstructionSet::kX86_64:
return true;
@@ -122,6 +134,8 @@
return kThumb2InstructionAlignment;
case InstructionSet::kArm64:
return kArm64InstructionAlignment;
+ case InstructionSet::kRiscv64:
+ return kRiscv64InstructionAlignment;
case InstructionSet::kX86:
return kX86InstructionAlignment;
case InstructionSet::kX86_64:
@@ -141,6 +155,8 @@
return kArmCodeAlignment;
case InstructionSet::kArm64:
return kArm64CodeAlignment;
+ case InstructionSet::kRiscv64:
+ return kRiscv64CodeAlignment;
case InstructionSet::kX86:
// Fall-through.
case InstructionSet::kX86_64:
@@ -158,6 +174,7 @@
switch (isa) {
case InstructionSet::kArm:
case InstructionSet::kArm64:
+ case InstructionSet::kRiscv64:
case InstructionSet::kX86:
case InstructionSet::kX86_64:
return 0;
@@ -180,6 +197,7 @@
return false;
case InstructionSet::kArm64:
+ case InstructionSet::kRiscv64:
case InstructionSet::kX86_64:
return true;
@@ -201,6 +219,8 @@
return 4;
case InstructionSet::kArm64:
return 8;
+ case InstructionSet::kRiscv64:
+ return 8;
case InstructionSet::kX86:
return 4;
case InstructionSet::kX86_64:
@@ -220,6 +240,8 @@
return 4;
case InstructionSet::kArm64:
return 8;
+ case InstructionSet::kRiscv64:
+ return 8;
case InstructionSet::kX86:
return 8;
case InstructionSet::kX86_64:
@@ -237,14 +259,16 @@
namespace instruction_set_details {
#if !defined(ART_STACK_OVERFLOW_GAP_arm) || !defined(ART_STACK_OVERFLOW_GAP_arm64) || \
+ !defined(ART_STACK_OVERFLOW_GAP_riscv64) || \
!defined(ART_STACK_OVERFLOW_GAP_x86) || !defined(ART_STACK_OVERFLOW_GAP_x86_64)
#error "Missing defines for stack overflow gap"
#endif
-static constexpr size_t kArmStackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_arm;
-static constexpr size_t kArm64StackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_arm64;
-static constexpr size_t kX86StackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_x86;
-static constexpr size_t kX86_64StackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_x86_64;
+static constexpr size_t kArmStackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_arm;
+static constexpr size_t kArm64StackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_arm64;
+static constexpr size_t kRiscv64StackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_riscv64;
+static constexpr size_t kX86StackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_x86;
+static constexpr size_t kX86_64StackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_x86_64;
NO_RETURN void GetStackOverflowReservedBytesFailure(const char* error_msg);
@@ -260,6 +284,9 @@
case InstructionSet::kArm64:
return instruction_set_details::kArm64StackOverflowReservedBytes;
+ case InstructionSet::kRiscv64:
+ return instruction_set_details::kRiscv64StackOverflowReservedBytes;
+
case InstructionSet::kX86:
return instruction_set_details::kX86StackOverflowReservedBytes;
diff --git a/libelffile/dwarf/register.h b/libelffile/dwarf/register.h
index 7742ec4..33c6795 100644
--- a/libelffile/dwarf/register.h
+++ b/libelffile/dwarf/register.h
@@ -40,6 +40,8 @@
static Reg ArmDp(int num) { return Reg(256 + num); } // D0–D31.
static Reg Arm64Core(int num) { return Reg(num); } // X0-X31.
static Reg Arm64Fp(int num) { return Reg(64 + num); } // V0-V31.
+ static Reg Riscv64Core(int num) { return Reg(num); } // X0-X31
+ static Reg Riscv64Fp(int num) { return Reg(32 + num); } // F0-F31
static Reg X86Core(int num) { return Reg(num); }
static Reg X86Fp(int num) { return Reg(21 + num); }
static Reg X86_64Core(int num) {
diff --git a/libelffile/elf/elf_builder.h b/libelffile/elf/elf_builder.h
index 086bd41..6720569 100644
--- a/libelffile/elf/elf_builder.h
+++ b/libelffile/elf/elf_builder.h
@@ -814,6 +814,8 @@
return InstructionSet::kThumb2;
case EM_AARCH64:
return InstructionSet::kArm64;
+ case EM_RISCV:
+ return InstructionSet::kRiscv64;
case EM_386:
return InstructionSet::kX86;
case EM_X86_64:
@@ -839,6 +841,11 @@
elf_header.e_flags = 0;
break;
}
+ case InstructionSet::kRiscv64: {
+ elf_header.e_machine = EM_RISCV;
+ elf_header.e_flags = EF_RISCV_RVC | EF_RISCV_FLOAT_ABI_DOUBLE;
+ break;
+ }
case InstructionSet::kX86: {
elf_header.e_machine = EM_386;
elf_header.e_flags = 0;
diff --git a/libelffile/elf/elf_utils.h b/libelffile/elf/elf_utils.h
index da67b8c..46b25b0 100644
--- a/libelffile/elf/elf_utils.h
+++ b/libelffile/elf/elf_utils.h
@@ -71,6 +71,15 @@
#define EM_AARCH64 183
+#ifndef EM_RISCV
+#define EM_RISCV 243
+#endif
+
+#ifndef EF_RISCV_RVC
+#define EF_RISCV_RVC 0x1
+#define EF_RISCV_FLOAT_ABI_DOUBLE 0x4
+#endif
+
#define DT_BIND_NOW 24
#define DT_INIT_ARRAY 25
#define DT_FINI_ARRAY 26
diff --git a/odrefresh/odr_config.h b/odrefresh/odr_config.h
index b262130..420f680 100644
--- a/odrefresh/odr_config.h
+++ b/odrefresh/odr_config.h
@@ -267,6 +267,7 @@
case art::InstructionSet::kX86:
case art::InstructionSet::kX86_64:
return std::make_pair(art::InstructionSet::kX86, art::InstructionSet::kX86_64);
+ case art::InstructionSet::kRiscv64:
case art::InstructionSet::kThumb2:
case art::InstructionSet::kNone:
LOG(FATAL) << "Invalid instruction set " << isa_;
diff --git a/runtime/metrics/statsd.cc b/runtime/metrics/statsd.cc
index 78c3622..203b72e 100644
--- a/runtime/metrics/statsd.cc
+++ b/runtime/metrics/statsd.cc
@@ -220,6 +220,8 @@
return statsd::ART_DATUM_REPORTED__ISA__ART_ISA_ARM;
case InstructionSet::kArm64:
return statsd::ART_DATUM_REPORTED__ISA__ART_ISA_ARM64;
+ case InstructionSet::kRiscv64:
+ return statsd::ART_DATUM_REPORTED__ISA__ART_ISA_RISCV64;
case InstructionSet::kX86:
return statsd::ART_DATUM_REPORTED__ISA__ART_ISA_X86;
case InstructionSet::kX86_64: