From 8d4cb500507b019b24b0b7ccba39b37c6a0efcfc Mon Sep 17 00:00:00 2001
From: Peiwei Hu <jlu.hpw@foxmail.com>
Date: Mon, 15 Jan 2024 21:33:54 +0800
Subject: [PATCH] v850 support for getting main offset

---
 librz/bin/format/elf/elf_info.c | 28 +++++++++++++++++++++++++
 test/db/analysis/v850           | 37 +++++++++++++++++++++++++++++++--
 2 files changed, 63 insertions(+), 2 deletions(-)

diff --git a/librz/bin/format/elf/elf_info.c b/librz/bin/format/elf/elf_info.c
index 26bf3d6b498..0d07844ef41 100644
--- a/librz/bin/format/elf/elf_info.c
+++ b/librz/bin/format/elf/elf_info.c
@@ -442,6 +442,29 @@ static ut64 get_main_offset_mips(ELFOBJ *bin, ut64 entry, ut8 *buf, size_t size)
 	return 0;
 }
 
+static ut64 get_main_offset_v850(ELFOBJ *bin, ut64 entry, ut8 *buf) {
+	size_t delta = 0;
+
+	/* distinguish by the first two instructions */
+
+	if (!memcmp(buf, "\x20\xa6\xff\x00\x35\x06\xff\xff\x00\x00", 10)) {
+		/* movea 0xFF, r0, r20; mov 0xFFFF, r21 */
+		delta = 0x64;
+	} else if (!memcmp(buf, "\x20\xa6\xff\x00\x00\xa8", 6)) {
+		/* movea 0xFF, r0, r20 ; mov r0, r21 */
+		delta = 0x4e;
+	}
+
+	if (!delta) {
+		return UT64_MAX;
+	}
+
+	ut16 jmp_offset = rz_read_le16(buf + delta);
+	ut64 entry_vaddr = Elf_(rz_bin_elf_p2v)(bin, entry);
+	ut64 vaddr = (entry_vaddr + (delta - 2) + jmp_offset) & ~1;
+	return Elf_(rz_bin_elf_v2p)(bin, vaddr);
+}
+
 static ut64 get_main_offset_arm_glibc_thumb(ELFOBJ *bin, ut64 entry, ut8 *buf) {
 	size_t delta = 0;
 
@@ -1964,5 +1987,10 @@ ut64 Elf_(rz_bin_elf_get_main_offset)(RZ_NONNULL ELFOBJ *bin) {
 		return main_addr;
 	}
 
+	main_addr = get_main_offset_v850(bin, entry, buf);
+	if (main_addr != UT64_MAX) {
+		return main_addr;
+	}
+
 	return get_main_offset_from_symbol(bin);
 }
diff --git a/test/db/analysis/v850 b/test/db/analysis/v850
index 26309a3cab8..3e022e98662 100644
--- a/test/db/analysis/v850
+++ b/test/db/analysis/v850
@@ -7,7 +7,7 @@ EOF
 EXPECT=<<EOF
 0x00100018    3 84           fcn.00100018
 0x0010006c    1 36           sym._compute
-0x00100090    1 64           sym._main
+0x00100090    1 64           main
 0x001000d0    5 74           sym.___main
 0x0010011a    3 34           sym._exit
 0x0010013c   18 768          sym.__printf_r
@@ -354,7 +354,7 @@ EXPECT=<<EOF
 0x001045d4    4 128  -> 80   sym._red_prompt
 0x001048ea    1 66           sym._red_open
 0x00104ab0    1 44           sym._red_help
-0x00104adc    1 150          sym._main
+0x00104adc    1 150          main
 EOF
 RUN
 
@@ -396,3 +396,36 @@ r25 = (byte) *(r8805 + 0x5)
 r9 = r0
 EOF
 RUN
+
+NAME=v850 s main hello-v850e
+FILE=bins/v850/hello-v850e
+CMDS=<<EOF
+s main
+s
+EOF
+EXPECT=<<EOF
+0x100090
+EOF
+RUN
+
+NAME=v850 s main hello-v850e_stripped
+FILE=bins/v850/hello-v850e_stripped
+CMDS=<<EOF
+s main
+s
+EOF
+EXPECT=<<EOF
+0x100090
+EOF
+RUN
+
+NAME=v850 s main ired_v850
+FILE=bins/v850/ired_v850
+CMDS=<<EOF
+s main
+s
+EOF
+EXPECT=<<EOF
+0x104adc
+EOF
+RUN