Compare commits

...

1 Commits

Author SHA1 Message Date
John Reiser 65b3dd7e52 risc-v 64-bit stubs build successfully in developer environment
This is the "bottom half" to add support for riscv64 to UPX.
Need update to stubtools for: gcc objcopy objdump ld
   Now using local cross tools /usr/bin/riscv64-linux-gnu-* on Ubuntu 24.04.
Need fix for riscv64-linux.elf-fold.h being 224 KB.
TODO: extend p_lx_elf.cpp  linker.cpp
TODO: implement nrv2d_d.S nrv2e_d.S lzma_d.S
TODO: testing  (using qemu-riscv64 and gdb-multiarch on Ubuntu 24.04)

        https://github.com/upx/upx/discussions/793

	modified:   src/stub/Makefile
	modified:   src/stub/scripts/xstrip.py
	modified:   src/stub/src/amd64-linux.elf-main2.c
	modified:   src/stub/src/arch/amd64/macros.S
	new file:   src/stub/src/arch/riscv/64/Makefile
	new file:   src/stub/src/arch/riscv/64/Makefile.extra
	new file:   src/stub/src/arch/riscv/64/macros.S
	new file:   src/stub/src/arch/riscv/64/nrv2b_d.S
	new file:   src/stub/src/arch/riscv/64/regs.h
	new file:   src/stub/src/riscv64-expand.S
	new file:   src/stub/src/riscv64-linux.elf-entry.S
	new file:   src/stub/src/riscv64-linux.elf-fold.S
	new file:   src/stub/src/riscv64-linux.elf-fold.lds
	new file:   src/stub/src/riscv64-linux.elf-help_umf.S
	new file:   src/stub/src/riscv64-linux.elf-main2.c
	modified:   src/stub/src/upxfd_linux.c
2025-11-01 08:59:05 -07:00
16 changed files with 1266 additions and 5 deletions
+69 -1
View File
@@ -42,6 +42,8 @@ endif
# ************************************************************************/
ifndef STUBS
STUBS += riscv64-linux.elf-entry.h
STUBS += riscv64-linux.elf-fold.h
STUBS += amd64-darwin.dylib-entry.h
STUBS += amd64-darwin.macho-entry.h
STUBS += amd64-darwin.macho-fold.h
@@ -320,7 +322,7 @@ define tc.default.f-embed_objinfo_without_xstrip_keep_dot_text
chmod a-x $1
$(call tc,objcopy) -R .data -R .bss $1
$(call tc,objcopy) -R .comment -R .note -R .note.GNU-stack -R .reginfo $1
$(call tc,objcopy) --strip-unneeded --keep-symbol=_start --keep-symbol=upx_so_main $1
$(call tc,objcopy) --strip-unneeded --keep-symbol=_start --keep-symbol=upx_so_main --keep-symbol=str_upx $1
#
# Disassemble for human readability
# objdump
@@ -2182,6 +2184,72 @@ powerpc64-linux.kernel.vmlinux-head.h : $(srcdir)/src/$$T.S
$(call tc,objcopy) --output-target binary --only-section .text tmp/$T.o tmp/$T.bin
$(call tc,bin2h) tmp/$T.bin $@
# =====
# /***********************************************************************
# // riscv64-linux.elf
# ************************************************************************/
riscv64-linux.elf%.h : tc_list = riscv64-linux.elf default
riscv64-linux.elf%.h : tc_bfdname = elf64-littleriscv64
tc.riscv64-linux.elf.gcc = /usr/bin/riscv64-linux-gnu-gcc -nostdinc -MMD -MT $@
tc.riscv64-linux.elf.gcc += -fno-exceptions -fno-asynchronous-unwind-tables # -fno-stack-protector
tc.riscv64-linux.elf.gcc += -Wall -W -Wcast-align -Wcast-qual -Wstrict-prototypes -Wwrite-strings -Werror
tc.riscv64-linux.elf.objcopy = /usr/bin/riscv64-linux-gnu-objcopy
# Override of objcopy is needed because:
# multiarch-objcopy-2.17 -F elf64-littleriscv64 --strip-unneeded --keep-symbol=_start --keep-symbol=upx_so_main tmp/riscv64-linux.elf-entry.bin
# multiarch-objcopy-2.17: tmp/riscv64-linux.elf-entry.bin: Invalid bfd target
tc.riscv64-linux.elf.objdump = /usr/bin/riscv64-linux-gnu-objdump
# Override of objdump is needed because:
# multiarch-objdump-2.17 -b elf64-littleriscv64 -Dr tmp/riscv64-linux.elf-entry.bin | sed -e 's/[ ]*$//' > tmp/riscv64-linux.elf-entry.bin.disasm
# multiarch-objdump-2.17: tmp/riscv64-linux.elf-entry.bin: Invalid bfd target
# multiarch-objdump-2.17 -b elf64-littleriscv64 -htr -w tmp/riscv64-linux.elf-entry.bin | sed -e 's/[ ]*$//' | cat --squeeze-blank | sed -e '1{/^$/d}' -e '${/^$/d}' | sed -e '1s/^.*: *file format/file format/' -e 's/ / /g' -e 's/ 00*/ 0/g' -e 's/CONTENTS.*/CONTENTS/' > tmp/riscv64-linux.elf-entry.bin.dump
# multiarch-objdump-2.17: tmp/riscv64-linux.elf-entry.bin: Invalid bfd target
tc.riscv64-linux.elf.ld = /usr/bin/riscv64-linux-gnu-ld
# Override of ld is needed because:
# multiarch-objcopy-2.17 -F elf64-littleriscv64 --strip-unneeded --keep-symbol=_start --keep-symbol=upx_so_main tmp/riscv64-linux.elf-entry.bin
# multiarch-objcopy-2.17: tmp/riscv64-linux.elf-entry.bin: Invalid bfd target
riscv64-linux.elf-entry.h : $(srcdir)/src/$$T.S
$(call tc,gcc) -c $< -o tmp/$T.bin
$(call tc,f-embed_objinfo,tmp/$T.bin)
$(call tc,bin2h) tmp/$T.bin $@
riscv64-linux.elf-fold.h : $(srcdir)/src/$$T.lds \
tmp/$$T.o \
tmp/riscv64-linux.elf-help_umf.o \
tmp/riscv64-linux.elf-upxfd_linux.o \
tmp/riscv64-expand.o \
tmp/riscv64-linux.elf-main2.o
$(call tc,ld) -r -Map tmp/$T.map $(filter %.o,$^) -o tmp/$T.bin
$(call tc,f-embed_objinfo_without_xstrip_keep_dot_text,tmp/$T.bin)
$(call tc,bin2h) tmp/$T.bin $@
tmp/riscv64-linux.elf-fold.o : $(srcdir)/src/$$T.S
$(call tc,gcc) -c $< -o $@
$(call tc,f-objstrip,$@)
tmp/riscv64-linux.elf-main2.o : $(srcdir)/src/$$T.c $(srcdir)/src/i386-linux.elf-main2.c
$(call tc,gcc) -c $< -o $@
$(call tc,f-objstrip,$@)
tmp/riscv64-linux.elf-help_umf.o: $(srcdir)/src/$$T.S
$(call tc,gcc) -c $< -o $@
tmp/riscv64-linux.elf-upxfd_linux.o : $(srcdir)/src/upxfd_linux.c
$(call tc,gcc) -c -O $< -o $@
$(call tc,objcopy) --strip-unneeded --rename-section .text=UMF_LINUX \
-R .riscv.attributes -R .data -R .bss -R .note.GNU-stack $@
$(call tc,objdump) -Dr $(tc_objdump_disasm_options) $@ | $(RTRIM) > $@.disasm
tmp/riscv64-expand.o: $(srcdir)/src/$$T.S
$(call tc,gcc) -c $< -o $@
# =====
# /***********************************************************************
# // dependencies
+3 -1
View File
@@ -157,7 +157,7 @@ def do_file(fn):
# ELF64 LE
eh, idata = idata[:64], idata[64:]
e_shnum, e_shstrndx = struct.unpack("<HH", eh[60:64])
assert e_shstrndx + 3 == e_shnum
assert e_shstrndx + 3 >= e_shnum
elif idata[4:7] == "\x02\x02\x01":
# ELF64 BE
eh, idata = idata[:64], idata[64:]
@@ -178,6 +178,8 @@ def do_file(fn):
assert pos >= len(odata), ("unexpected strip_with_dump", pos, len(odata))
elif re.search(r"^arm64-", os.path.basename(fn)):
assert pos >= len(odata), ("unexpected strip_with_dump", pos, len(odata))
elif re.search(r"^riscv", os.path.basename(fn)):
assert pos >= len(odata), ("unexpected strip_with_dump", pos, len(odata))
else:
assert pos == len(odata), ("unexpected strip_with_dump", pos, len(odata))
else:
+42 -2
View File
@@ -77,6 +77,16 @@ extern void my_bkpt(void *, ...);
/*und*/ : "x30"); \
str; \
})
#elif defined(__riscv) //}{
#define ANDROID_FRIEND 0
#define addr_string(string) ({ \
char const *str; \
asm("jal 0f; .string \"" string "\"; .balign 4; 0: mv %0,ra" \
/*out*/ : "=r"(str) \
/* in*/ : \
/*und*/ : "x30"); \
str; \
})
#else //}{
#error;
#endif //}
@@ -279,6 +289,36 @@ make_hatch(
DPRINTF("hatch=%%p\\n", hatch);
return hatch;
}
#elif defined(__riscv) //{
static void *
make_hatch(
ElfW(Phdr) const *const phdr,
char *next_unc,
unsigned const frag_mask
)
{
unsigned long a = (unsigned long)next_unc;
int *hatch = (int *)((3u & -a) + a);
int code[3] = {
0,0,0 //NYI illegal instruction
};
DPRINTF("make_hatch %%p %%p %%x\\n", phdr, next_unc, frag_mask);
if (phdr->p_type==PT_LOAD && phdr->p_flags & PF_X) {
if (sizeof(code) <= (unsigned)(frag_mask & -(long)hatch)) {
hatch[0] = code[0];
hatch[1] = code[1];
hatch[2] = code[2];
}
else { // Does not fit at hi end of .text, so must use a new page "permanently"
int mfd = upxfd_create(addr_string("upx"), MFD_EXEC); // the directory entry
write(mfd, &code, sizeof(code));
hatch = mmap(0, sizeof(code), PROT_READ|PROT_EXEC, MAP_SHARED, mfd, 0);
close(mfd);
}
}
DPRINTF("hatch=%%p\\n", hatch);
return hatch;
}
#elif defined(__powerpc64__) //}{
static void *
make_hatch(
@@ -660,7 +700,7 @@ upx_main2( // returns entry address
/*arg4*/ ElfW(auxv_t) *const av
#if defined(__x86_64) //{
/*arg5*/ , ElfW(Addr) elfaddr // In: &ElfW(Ehdr) for stub
#elif defined(__aarch64__) //}{
#elif defined(__aarch64__) || defined(__riscv) //}{
/*arg5*/ , ElfW(Addr) elfaddr
#elif defined(__powerpc64__) //}{
/*arg5*/ , ElfW(Addr) *p_reloc // In: &ElfW(Ehdr) for stub; Out: 'slide' for PT_INTERP
@@ -681,7 +721,7 @@ upx_main2( // returns entry address
// ehdr = Uncompress Ehdr and Phdrs
unpackExtent(&xi2, &xo); // never filtered?
#if defined(__x86_64) || defined(__aarch64__) //{
#if defined(__x86_64) || defined(__aarch64__) || defined(__riscv) //{
ElfW(Addr) *const p_reloc = &elfaddr;
#endif //}
ElfW(Addr) page_mask = get_page_mask(); (void)page_mask;
-1
View File
@@ -34,7 +34,6 @@
#undef x86_64
//.altmacro // not supported by x86_64-linux-as-2.15
.code64
.macro section name
.section \name
+3
View File
@@ -0,0 +1,3 @@
# convenience Makefile
default %:
$(MAKE) -C ../../.. $@
+55
View File
@@ -0,0 +1,55 @@
MAKEFLAGS += -rR
.SUFFIXES:
.SECONDEXPANSION:
ifndef top_srcdir
__dir_list = . .. ../.. ../../.. ../../../.. ../../../../..
__dir_list += ../../../../../.. ../../../../../../.. ../../../../../../../..
__dir_search = $(firstword $(foreach v,$1,$(if $(wildcard $v/$2),$v)) $3)
top_srcdir := $(call __dir_search,$(__dir_list),src/bele.h,NOT_FOUND)
endif
include $(wildcard $(top_srcdir)/Makevars-global.mk ./Makevars-local.mk)
vpath %.c $(top_srcdir)/src/stub/src/c
STUBS =
include $(top_srcdir)/src/stub/src/c/Makevars-lzma.mk
ifneq ($(UPX_LZMA_VERSION),)
STUBS += lzma_d_cf.S lzma_d_cs.S lzma_d_cn.S
endif
default.targets = all
ifeq ($(strip $(STUBS)),)
STUBS = NO_STUBS
all.targets =
endif
include $(top_srcdir)/src/stub/Makefile
# /***********************************************************************
# // method-lzma
# ************************************************************************/
lzma_d_c%.S : tc_list = method-lzma riscv64-linux.elf default
lzma_d_c%.S : tc_bfdname = elf64-riscv64
c := tc.method-lzma.gcc
$c = $(tc.riscv64-linux.elf.gcc)
$c += -Os -fomit-frame-pointer
$c += -fno-unit-at-a-time
$c += -ffunction-sections
$c += -fwrapv
$c += -DWITH_LZMA=$(UPX_LZMA_VERSION)
$c += -I$(UPX_LZMADIR)
$c += -I$(top_srcdir)/src
lzma_d_c%.S : lzma_d_c.c
$(call tc,gcc) $(PP_FLAGS) -c $< -o tmp/$T.o
$(call tc,f-objstrip,tmp/$T.o)
$(call tc,objcopy) -O binary --only-section .text.LzmaDecode tmp/$T.o tmp/$T.bin
head -c-1 tmp/$T.bin > tmp/$T.out
$(call tc,objdump) -b binary -m i386:x86-64 -D tmp/$T.out | $(RTRIM) > tmp/$T.out.disasm
$(call tc,bin2h) --mode=gas tmp/$T.out $@
lzma_d_cf.% : PP_FLAGS = -DFAST
lzma_d_cs.% : PP_FLAGS = -DSMALL
lzma_d_cn.% : PP_FLAGS = -DFAST -mno-red-zone
+96
View File
@@ -0,0 +1,96 @@
/*
; macros.S --
;
; This file is part of the UPX executable compressor.
;
; Copyright (C) 1996-2025 Markus Franz Xaver Johannes Oberhumer
; Copyright (C) 1996-2025 Laszlo Molnar
; All Rights Reserved.
;
; UPX and the UCL library are free software; you can redistribute them
; and/or modify them under the terms of the GNU General Public License as
; published by the Free Software Foundation; either version 2 of
; the License, or (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program; see the file COPYING.
; If not, write to the Free Software Foundation, Inc.,
; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
;
; Markus F.X.J. Oberhumer Laszlo Molnar
; <markus@oberhumer.com> <ezerotven+github@gmail.com>
;
*/
.macro section name
.section \name
.endm
.macro syscall num
li a7,\num; ecall
.endm
NBPW= 8
.macro PUSH4 a,b,c,d
addi sp,sp,-4*NBPW
sd \a,0*NBPW(sp)
sd \b,1*NBPW(sp)
sd \c,2*NBPW(sp)
sd \d,3*NBPW(sp)
.endm
.macro POP4 a,b,c,d
ld \a,0*NBPW(sp)
ld \b,1*NBPW(sp)
ld \c,2*NBPW(sp)
ld \d,3*NBPW(sp)
addi sp,sp,4*NBPW
.endm
.macro PUSH3 a,b,c
addi sp,sp,-4*NBPW
sd \a,0*NBPW(sp)
sd \b,1*NBPW(sp)
sd \c,2*NBPW(sp)
.endm
.macro POP3 a,b,c
ld \a,0*NBPW(sp)
ld \b,1*NBPW(sp)
ld \c,2*NBPW(sp)
addi sp,sp,4*NBPW
.endm
.macro PUSH2 a,b
addi sp,sp,-2*NBPW
sd \a,0*NBPW(sp)
sd \b,1*NBPW(sp)
.endm
.macro POP2 a,b,c
ld \a,0*NBPW(sp)
ld \b,1*NBPW(sp)
addi sp,sp,2*NBPW
.endm
.macro PUSH1 a
addi sp,sp,-2*NBPW
sd \a,0*NBPW(sp)
.endm
.macro POP1 a
ld \a,0*NBPW(sp)
addi sp,sp,2*NBPW
.endm
.macro SUB2 dst,src
sub \dst,\dst,\src
.endm
// vi:ts=8:et:nowrap
+85
View File
@@ -0,0 +1,85 @@
/* riscv64 nrv2b_d.S -- RISCV64 decompressor for NRV2B
This file is part of the UPX executable compressor.
Copyright (C) 1996-2025 Markus Franz Xaver Johannes Oberhumer
Copyright (C) 1996-2025 Laszlo Molnar
Copyright (C) 2000-2025 John F. Reiser
All Rights Reserved.
UPX and the UCL library are free software; you can redistribute them
and/or modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING.
If not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Markus F.X.J. Oberhumer Laszlo Molnar
<markus@oberhumer.com> <ezerotven+github@gmail.com>
John F. Reiser
<jreiser@users.sourceforge.net>
*/
.text
#ifndef NO_METHOD_CHECK
cmpb $ M_NRV2B_LE32,methb; jne not_n2b
#endif
li bits,1<<31 // empty; force refill
li len,0
li disp,-1 // initial displacement
j top_n2b
#undef EOF
#define EOF eof_n2b
lit_n2b:
addi src,src,1; sb bytpre,(dst)
addi dst,dst,1
top_n2b:
lbu bytpre,(src) # prefetch: literal, or bottom 8 bits of offset
jnextb1yp lit_n2b
li off,1
offmore_n2b:
getnextbp(off)
jnextb0np offmore_n2b
addi off,off,-3; blt off,zero,len_n2b # use previous offset
slli off,off,8
or off,off,bytpre; addi src,src,1
xori disp,off,~0; beq disp,zero,EOF
len_n2b:
li off,1
getnextb(len); getnextb(len) # two bits; cc set on result
bne len,zero,gotlen_n2b # raw 1,2,3 ==> 2,3,4
mv len,off # len= 1, the msb
addi off,off,3-1 # raw 2.. ==> 5..
lenmore_n2b:
getnextb(len)
jnextb0n lenmore_n2b
gotlen_n2b:
li t0,0x300; lui t0,0xfffff # -0xd00
sltu retbit,t0,disp
add len,len,off; add len,len,retbit # len += off + (disp < -0xd00)
//NYI call copy@plt; .extern copy
bot_n2b: # In: 0==len
j top_n2b
#ifndef NO_METHOD_CHECK //{
not_n2b:
push %rdi; pop %rsi # src = arg1
#endif //}
# fall into daisy chain
/*
vi:ts=8:et:nowrap
*/
+22
View File
@@ -0,0 +1,22 @@
#if 0 //{ pre-defined
#define ra x1 /* return address */
#define sp x2 /* stack ptr */
#define gp x3 /* global ptr */
#define tp x4 /* thread ptr */
#endif //}
#define t0 x5
#define t1 x6
#define t2 x7
#define s0 x8
#define s1 x9
#define rv a0 /* return value */
/* NOTE: THE FIRST ARGUMENT IS arg1, NOT arg0. */
#define arg1 x10 /* same as rv */
#define arg2 x11
#define arg3 x12
#define arg4 x13
#define arg5 x14
#define arg6 x15
+211
View File
@@ -0,0 +1,211 @@
/*
; riscv64-expand.S -- decompressors for riscv64
;
; This file is part of the UPX executable compressor.
;
; Copyright (C) 1996-2021 Markus Franz Xaver Johannes Oberhumer
; Copyright (C) 1996-2021 Laszlo Molnar
; Copyright (C) 2000-2021 John F. Reiser
; All Rights Reserved.
;
; UPX and the UCL library are free software; you can redistribute them
; and/or modify them under the terms of the GNU General Public License as
; published by the Free Software Foundation; either version 2 of
; the License, or (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program; see the file COPYING.
; If not, write to the Free Software Foundation, Inc.,
; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
;
; Markus F.X.J. Oberhumer Laszlo Molnar
; <markus@oberhumer.com> <ezerotven+github@gmail.com>
;
; John F. Reiser
; <jreiser@users.sourceforge.net>
;
*/
NBPW = 8
#include "arch/riscv/64/macros.S"
.macro call subr; jal \subr; .endm
section EXP_HEAD
sz_unc= 0
sz_cpr= 4
b_method= 8
b_ftid= 9
b_cto8= 10
b_extra= 11
sz_binfo= 12
f_expand: .globl f_expand // f_expand(b_info *, dst, &dstlen)
// Supervisor for de-compression, un-filter, and sync_cache
// Input to supervisor:
#define fx_src a0
#define fx_dst a1
#define fx_dstlen a2
PUSH4 fx_src,fx_dst,fx_dstlen,ra // MATCH_95 params to unfilter and sync_cache
// Input to de-compressor:
#define xsrc a0
#define xsrclen a1
#define xdst a2
#define xdstlen a3
#define meth a4
lbu meth,b_method(fx_src)
mv xdstlen,fx_dstlen // arg4
mv xdst,fx_dst // arg3
lw xsrclen,sz_cpr(xsrc) // arg2
addi xsrc,fx_src,sz_binfo // arg1
call decompress
mv a3,a0 // save retval
POP4 fx_src,fx_dst,fx_dstlen,ra // MATCH_95 fx_src,fx_dst,fx_dstlen,ra
lw fx_dst,(fx_dst) // actual length used by decompressor
PUSH3 fx_src,fx_dst,a2 // MATCH_96 params for sync_cache
lbu a3,b_ftid(sp)
lbu a2,b_cto8(sp)
beqz a3,no_unf
//NYI #include "arch/arm64/v8/bxx.S" // unfilter code; args in registers, fall-through return
no_unf:
POP2 a0,a1 // MATCH_96 dst, len
add a1,a1,a0 // lo, hi
//NYI sync_cache // in macros.S
POP1 a0 // MATCH_96 retval from decompress
ret
#undef fx_src
#undef fx_dst
#undef fx_dstlen
#undef xsrc
#undef xsrclen
#undef xdst
#undef xdstlen
decompress: // (src *, cpr_len, dst *, &dstlen);
// sections NRV2B, etc, inserted here by addLoader() from ::buildLinuxLoader()
section EXP_TAIL
// Fall through: daisy chain had no matching method
li a0,-1
mv a1,meth
ebreak // EXP_TAIL daisy chain fail
#define src a0
#define bits a1
#define dst a2
#define off a3
#define len a4
#define disp a5
#define retbit t0
#define bytpre t1
.globl eof
// sync_cache is done in tail of f_expand, after possible unfilter
// NYI: eof_n2b, eof_n2d, eof_n2e should be unified.
eof_n2b: // .globl eof_n2b .type eof_n2b,%function
eof: // MATCH_90 end of a compressed extent; need sync_cache after unfilter
ld a2,0*NBPW(sp) // &input_eof
sub a0,src,a3 // src -= eof; // return 0: good; else: bad
ld a1,1*NBPW(sp) // original dst
sub dst,dst,a1 // dst -= original dst; actual length of output
ld a1,2*NBPW(sp) // &dstlen
sw dst,(a1) // actual length used at dst XXX: 4GB
ld ra,3*NBPW(sp)
addi sp,sp,4*NBPW
ret
// WINDOWS_BACK compatibility seems to be broken
// if POP3 replaces POP2+POP1 (MATCH_92, MATCH_91)
#define srclim a7
eof_n2d: // .globl eof_n2d
eof_n2e: // .globl eof_n2e
POP2 a3,a4 // MATCH_92 r3= orig_dst; r4= plen_dst
SUB2 src,srclim // 0 if actual src length equals expected length
SUB2 dst,a3 // actual dst length
sw dst,(a4)
POP1 ra // MATCH_91
ret
eof_lzma: .globl eof_lzma
POP4 x2,x3, fp,ra // MATCH_94 x2= orig_dst; x3= plen_dst
ret
upx_mmap_and_fd: .globl upx_mmap_and_fd
// UMF_LINUX goes here
#define M_NRV2B_LE32 2
#define M_NRV2B_8 3
#define M_NRV2D_LE32 5
#define M_NRV2D_8 6
#define M_NRV2E_LE32 8
#define M_NRV2E_8 9
#define M_CL1B_LE32 11
#define M_LZMA 14
#define NO_METHOD_CHECK 1 /* subsumed here by daisy chain */
getbit:
srli retbit,bits,63 # hi bit of 64
slli bits,bits,1; beq bits,zero,refill
ret
/* On refill: prefetch next byte, for latency reduction on literals and offsets. */
refill:
lw bits,(src); addi src,src,4
srli retbit,bits,31 # hi bit of 4 bytes fetched
slli bits,bits,1; lbu bytpre,(src) # prefetch
ori bits,bits,1 # the flag bit
slli bits,bits,32 # hi 32 bits in 64-bit register
ret
/* jump on next bit {0,1} with prediction {y==>likely, n==>unlikely} */
/* Prediction omitted for now. */
#define jnextb0np jnextb0yp
#define jnextb0yp GETBITp; beq retbit,zero,
#define jnextb1np jnextb1yp
#define jnextb1yp GETBITp; bne retbit,zero,
#define GETBITp \
call getbit
/* Same, but without prefetch (not useful for length of match.) */
#define jnextb0n jnextb0y
#define jnextb0y GETBIT; beq retbit,zero,
#define jnextb1n jnextb1y
#define jnextb1y GETBIT; bne retbit,zero,
#define GETBIT \
call getbit
/* rotate next bit into bottom bit of reg */
#define getnextbp(reg) GETBITp; slli reg,reg,1; or reg,reg,retbit
#define getnextb(reg) getnextbp(reg)
section NRV2E
li t0,M_NRV2E_LE32; bne meth,t0,not_nrv2e
//NYI #include "arch/arm64/v8/nrv2e_d.S"
not_nrv2e:
section NRV2D
li t0,M_NRV2D_LE32; bne meth,t0,not_nrv2d
//NYI #include "arch/arm64/v8/nrv2d_d.S"
not_nrv2d:
section NRV2B
li t0,M_NRV2B_LE32; bne meth,t0,not_nrv2b
#include "arch/riscv/64/nrv2b_d.S"
not_nrv2b:
section LZMA_DAISY
li t0,M_LZMA; bne meth,t0,not_lzma
//NYI #include "arch/arm64/v8/lzma_d.S"
not_lzma:
+287
View File
@@ -0,0 +1,287 @@
/* riscv64-linux.elf-entry.S -- Linux program entry point & decompressor (Elf binary)
*
* This file is part of the UPX executable compressor.
*
* Copyright (C) 1996-2025 Markus Franz Xaver Johannes Oberhumer
* Copyright (C) 1996-2025 Laszlo Molnar
* Copyright (C) 2000-2025 John F. Reiser
* All Rights Reserved.
*
* UPX and the UCL library are free software; you can redistribute them
* and/or modify them under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING.
* If not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Markus F.X.J. Oberhumer Laszlo Molnar
* <markus@oberhumer.com> <ezerotven+github@gmail.com>
*
* John F. Reiser
* <jreiser@users.sourceforge.net>
*/
#include "arch/riscv/64/macros.S"
#include "arch/riscv/64/regs.h"
NBPW= 8
/* These from /usr/include/unistd_64.h */
__NR_close= 57
__NR_exit= 93
__NR_ftruncate= 64
__NR_memfd_create= 279
__NR_mmap= 222
__NR_mprotect= 226
__NR_msync= 227
__NR_openat= 56
__NR_write= 64
sz_Ehdr= 64
e_phnum= 56
sz_Phdr= 56
sz_l_info= 12
l_lsize= 8
sz_p_info= 12
sz_b_info= 12
sz_unc= 0
sz_cpr= 4
b_method= 8
AT_PAGESZ= 6
PROT_READ= 1
PROT_WRITE= 2
PROT_EXEC= 4
MAP_SHARED= 1
MAP_PRIVATE= 2
MAP_FIXED= 0x10
MAP_ANONYMOUS= 0x20
MFD_EXEC= 0x0010
SYS_mmap= 9 // 64-bit mode only!
FD_stderr= 2
M_NRV2B_LE32=2 // ../conf.h
M_NRV2D_LE32=5
M_NRV2E_LE32=8
// https://www.uclibc.org/docs/psABI-x86_64.pdf
section ELFMAINX
sz_pack2= .-4
_start: .globl _start
//// nop; int3 # uncomment for debugging
ld s0,0(sp) // argc
addi s1,sp,NBPW // argv
//NYI lea cancel_dummy(%rip),%r15
section ELFMAINX2
// same as in riscv64-linux.elf-fold.S
F_FRAME= 8*NBPW
F_EOF= 7*NBPW
F_ENTR= 6*NBPW; F_PMASK= F_ENTR
F_RDX= 5*NBPW
F_LENU= 4*NBPW
F_ADRU= 3*NBPW
F_ELFA= 2*NBPW
F_LENX= 1*NBPW
F_ADRX= 0*NBPW
D_FOLD= 2*NBPW // .data space at start of unfold
D_PMASK= 0*NBPW
D_XSIGSEGV= 1*NBPW
// find auxv
slli t0,s0,3 // NBPW * argc
add t0,t0,a1 // end argv
0: // find end of env
addi t0,t0,NBPW // &env[k]
ld t1,(t0); bnez t1,0b
// find AT_PAGESZ in auxv
addi t0,t0,NBPW // &auxv
li a7,AT_PAGESZ // desired key
0:
ld t1,(t0); ld t2,NBPW(t0); addi t0,t0,2*NBPW
beq t1,a7,1f // found it
bne t1,zero,0b // keep searching
li t2,0x1000 // default PAGE_SIZE
1:
sub a7,zero,t2 // PAGE_MASK
2:
// Create anonymous temporary file on mfd; like upxfd_create
jal arg1,0f
str_upx:
.asciz "upx"
0:
// lla arg1,str_upx
li arg2,MFD_EXEC // flags
syscall __NR_memfd_create
bne a0,zero,ok_memfd // success
no_memfd: // so try /dev/shm
O_RDWR= 2
O_DIRECTORY= 0200000 // 0x010000
O_TMPFILE= 020000000 // 0x400000
# lla arg1,str_devmem
jal arg1,0f
str_devmem:
.asciz "/dev/mem"
.balign 4
0:
li arg2,0700 // mode
li arg3,O_RDWR | O_TMPFILE | O_DIRECTORY
syscall __NR_openat
ok_memfd:
#define mfd s2
mv mfd,rv
lla t0,sz_pack2
#define elfa s3
lw t1,(t0); sub elfa,t0,t1
#define binf s4
lla binf,4+o_binfo
#define lenu s5
lw lenu,sz_unc(binf)
#define szp2 s6
#define lenx s7
sub lenx,szp2,binf
#define adrx s8
add adrx,elfa,binf
#define old_sp s9
mv old_sp,sp
// alloca()
sub sp,sp,lenu; andi sp,sp,-2*NBPW
// Decompress the rest of this loader, and jump to it.
#define dst a2
#define src a0
#define lsrc a1
mv dst,sp
lw lsrc,sz_cpr(binf)
lbu t0,b_method(binf); li t1,M_NRV2B_LE32|(0<<8); beq t0,t1,0f; ebreak
0:
add t0,lsrc,src; sw t0,F_EOF(old_sp)
//%rsp:
// MATCH_10 old_sp
// MATCH_11 &input_eof
//%rbp === old_sp: array of F_FRAME
#define src a0
#define bits a1
#define dst a2
#define off a3
#define len a4
#define disp a5
#define retbit t0
#define bytpre t1
/* jump on next bit {0,1} with prediction {y==>likely, n==>unlikely} */
/* Prediction omitted for now. */
#define jnextb0np jnextb0yp
#define jnextb0yp GETBITp; beq retbit,zero,
#define jnextb1np jnextb1yp
#define jnextb1yp GETBITp; bne retbit,zero,
#define GETBITp \
call getbit
/* Same, but without prefetch (not useful for length of match.) */
#define jnextb0n jnextb0y
#define jnextb0y GETBIT; beq retbit,zero,
#define jnextb1n jnextb1y
#define jnextb1y GETBIT; bne retbit,zero,
#define GETBIT \
call getbit
/* rotate next bit into bottom bit of reg */
#define getnextbp(reg) GETBITp; slli reg,reg,1; or reg,reg,retbit
#define getnextb(reg) getnextbp(reg)
// We already checked the method and no filter.
#define NO_METHOD_CHECK 1
#include "arch/riscv/64/nrv2b_d.S"
getbit:
srli retbit,bits,63 # hi bit of 64
slli bits,bits,1; beq bits,zero,refill
ret
/* On refill: prefetch next byte, for latency reduction on literals and offsets. */
refill:
lw bits,(src); addi src,src,4
srli retbit,bits,31 # hi bit of 4 bytes fetched
slli bits,bits,1; lbu bytpre,(src) # prefetch
ori bits,bits,1 # the flag bit
slli bits,bits,32 # hi 32 bits in 64-bit register
ret
n2b_EOFbad:
ebreak
eof_n2b:
lw t0,F_EOF(old_sp)
bne t0,src,n2b_EOFbad
// Write de-compressed 'fold' to file
lw t0,F_PMASK(old_sp); sw t0,D_PMASK(sp) // propagate PAGE_MASK
lwu arg3,F_LENU(old_sp)
mv arg2,sp
mv arg1,mfd
mv s2,arg3 // LENU
0: // /dev/shm might be restricted to 8KiB at a time!
syscall __NR_write
add arg2,arg2,rv // ptr += count
sub arg3,arg3,rv // decrement count
bnez arg3,0b // not finished
// de-alloca()
mv sp,old_sp
// Map unfolded code the SELinux way
li arg6,0 // offset
mv arg5,mfd
li arg4,MAP_SHARED
li arg3,PROT_READ|PROT_EXEC // FIXME: add PROT_WRITE for DEBUG only
mv arg2,s2 // LENU
li arg1,0 // (%arg1)dst = 0; // kernel chooses addr
syscall __NR_mmap
sw rv,F_ADRU(old_sp)
mv arg1,mfd
syscall __NR_close
// Use the copy.
ld a0,F_ADRU(sp) //
addi a0,a0,D_FOLD // beyond .data
jr a0 // goto unfolded stub
// IDENTSTR goes here
section ELFMAINZ
.balign 4
o_binfo:
.long O_BINFO // offset of b_info for .text | is_ptinerp | unmap_all_pages
FOLD:
// { b_info={sz_unc, sz_cpr, {4 char}}, folded_loader...}
/*__XTHEENDX__*/
/* vim:set ts=8 sw=8 et: */
+340
View File
@@ -0,0 +1,340 @@
/* riscv64-linux.elf-fold.S -- linkage to C code to process Elf binary
*
* This file is part of the UPX executable compressor.
*
* Copyright (C) 2000-2025 John F. Reiser
* All Rights Reserved.
*
* UPX and the UCL library are free software; you can redistribute them
* and/or modify them under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING.
* If not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Markus F.X.J. Oberhumer Laszlo Molnar
* <markus@oberhumer.com> <ezerotven+github@gmail.com>
*
* John F. Reiser
* <jreiser@users.sourceforge.net>
*/
NBPW= 8
#include "arch/riscv/64/macros.S"
#include "arch/riscv/64/regs.h"
PATH_MAX= 4096 // /usr/include/linux/limits.h
sz_b_info= 12
sz_unc= 0
sz_cpr= 4
sz_l_info= 12
sz_p_info= 12
MAP_PRIVATE= 0x02
MAP_FIXED= 0x10
PROT_READ= 0x1
O_RDONLY= 0
FD_CWD= -100
OVERHEAD=2048
/* 64-bit mode only! */
__NR_read= 0
__NR_write= 1
__NR_openat= 2 //NYI
__NR_close= 3
__NR_mmap= 9
__NR_mprotect= 10
__NR_munmap= 11
__NR_msync= 26 // 0x1a
MS_SYNC= 4
__NR_brk= 12
__NR_memfd_create= 0x13f // 319
__NR_ftruncate= 0x4d // 77
__NR_exit= 60
__NR_readlink= 89
unmap_all_pages= (1<<1)
is_ptinterp= (1<<0)
// same as in riscv64-linux.elf-entry.S
F_FRAME= 8*NBPW
F_EOF= 7*NBPW // sometimes omitted from FRAME
F_ENTR= 6*NBPW; F_PMASK= F_ENTR
F_RDX= 5*NBPW
F_LENU= 4*NBPW
F_ADRU= 3*NBPW
F_ELFA= 2*NBPW
F_LENX= 1*NBPW
F_ADRX= 0*NBPW
D_FOLD= 2*NBPW // .data space at start of unfold
D_PMASK= 0*NBPW
D_XSIGSEGV= 1*NBPW
#define rsp sp /* x2 */
#define rax a0 /* x10 */
#define rbx s1 /* x9 */
#define rbp s0 /* x8 */
#define rcx t2 /* x7 */
#define rdx t1 /* x6 */
#define r12 t0 /* x5 */
#define rdi a5 /* x15 */
#define rsi a4 /* x14 */
#define r15 a3 /* x13 */
#define r14 a2 /* x12 */
#define r13 a1 /* x11 */
#define rfd rbp /* file descriptor for /proc/self/exe */
.balign 8
PAGE_MASK: .quad -1<<12 // default
cancel_sigsegv: .quad 0 // subroutine that cancels sigaction(SIGSEGV,)
// IN: [ADRX,+LENX): compressed data; [ADRU,+LENU): expanded fold (w/ upx_main2)
// %rsp= %rbp= &F_ADRX; %r13= O_BINFO | is_ptinterp | unmap_all_pages
// no 'section', thus '.text'; also loaded first in riscv64-linux.elf-fold.bin.
// Code from riscv64-linux2.elf-main.c is also .text, and is next.
fold_begin:
//// ebreak # DEBUG
// copy is_interp bit from r13 to F_ELFA(rbp)
ld t0,F_ELFA(rbp); andi t1,r13,is_ptinterp; or t0,t0,t1;
sd t0,F_ELFA(rbp)
// if !unmap_all_pages then need space on stack for result of readlink("/proc/self/exe",...)
mv rsi,rsp
andi t0,r13,unmap_all_pages
bnez t0,5f; li t0,PATH_MAX; sub rsp,rsp,t0; 0:
mv rdi,rsp
li rcx,8
0: // copy down ADRX,LDRX,ELFA,ADRU,LENU,rdx,%entry,argc
ld t0,(rsi); addi rsi,rsi,NBPW; addi rcx,rcx,-1
sd t0,(rdi); addi rdi,rdi,NBPW; bnez rcx,0b
5:
0: // copy down argv
ld t0,(rsi); addi rsi,rsi,NBPW
sd t0,(rdi); addi rdi,rdi,NBPW
bnez t0,0b
mv r14,rdi // remember &new_env[0]
andi t0,r13,unmap_all_pages; bnez t0,0f
sd zero,(rdi); addi rdi,rdi,NBPW // space for new_env[0]
0: // find old Elf64_auxv
ld t0,(rsi); sd t0,(rdi); bnez t0,0b
mv t2,rdi # &old Elf64_auxv
0: // find &strings (beyond auxv)
ld t0,(rsi); ld t1,NBPW(rsi); addi rsi,rsi,2*NBPW
sd t0,(rdi); sd t1,NBPW(rdi); addi rdi,rdi,2*NBPW
bnez t0,0b
mv r15,rdi # beyond auxv
mv r13,rsi # beginning of strings
sub rdi,rdi,t2 # -length of auxv
andi t0,r13,unmap_all_pages; beqz t0,env_pse
ori rfd,rfd,~0; mv r14,rdi; j no_env_pse # no fd; beyond auxv
env_pse:
li arg3,0 # O_RdONLY
lla arg2,proc_self_exe
li arg1,FD_CWD
call openat; mv rfd,rv # fd
li arg3,-1+ PATH_MAX # buflen
mv arg2,sp # buffer
lla arg1,proc_self_exe
syscall __NR_readlink; bgez rv,0f
// readlink() failed. Set the result equal to the argument.
lla arg2,proc_self_exe # failure result= "/proc/self/exe"
li rcx,15 # sizeof "/proc/self/exe"
0:
// std
addi rdi,r13,-1 # dst last byte
sb zero,(rdi) # terminate
addi rsi,arg2,-1
add rsi,rsi,rcx # src last byte
0: // slide up (hi end goes first)
lbu t0,(rsi); addi rsi,rsi,-1; addi rcx,rcx,-1
sb t0,(rdi); addi rdi,rdi,-1; bnez rcx,0b
// add new env " =..."
li t0,' '; sb t0,-3(rdi); sb t0,-2(rdi); sb t0,-1(rdi); addi rdi,rdi,-3
sd rdi,(r14) # new_env[0]
andi rdi,rdi,-NBPW # align
mv rcx,r15
sub rsp,rsp,rcx # byte count
addi rdi,rdi,-NBPW # &last qword of new auxv
addi rsi,r15,-NBPW # &last qword of old auxv
// end of auxv must move by even number of NBPW
mv t0,rdi
xor t0,t0,rsi
andi t0,t0,NBPW
sub rdi,rdi,t0
mv r14,rdi # &last qword of new auxv
srl rcx,rcx,3
0:
ld t0,(rsi); addi rsi,rsi,-NBPW; addi rcx,rcx,-1
sd t0,(rdi); addi rdi,rdi,-NBPW; bnez rcx,0b
addi rsp,rdi,NBPW
// cld
add arg4,r14,r12; addi arg4,arg4,NBPW # &new Elf64_auxv %r12 dead
no_env_pse:
ld arg1,F_ADRX(rbp)
ld arg2,F_LENX(rbp)
andi arg1,arg1,~(is_ptinterp | unmap_all_pages)
ld arg5,F_ELFA(rbp) # ELFA | is_ptinterp
andi t0,arg5,is_ptinterp; or arg4,arg4,t0 # transfer is_ptinterp to &new_ELF64_auxv
sub arg5,arg5,t0 # and clear from ELFA
mv r13,arg5 # save ELFA
addi rsp,rsp,-OVERHEAD
mv arg3,rsp # &ELf64_Ehdr temporary space
call upx_main2 # Out: rv= entry
// entry= upx_main2(
// b_info *arg1, {%rdi}
// total_size arg2, {%rsi}
// Elf64_Ehdr *arg3, {%rdx}
// Elf32_Auxv_t *arg4, {%rcx}
// Elf64_Addr elfaddr {%r8}
// )
// rsp/ {OVERHEAD},ADRU,LENU,rdx,%entry, argc,argv,0,envp,0,auxv,0,strings
li t0,OVERHEAD
add rsp,rsp,t0 # remove Elf64_Ehdr temporary space
#define r_fd ebx
ld rfd,(rbp) //NYI
sd rv,3*NBPW(rsp) # entry
//NYI call *cancel_sigsegv(%rip)
sz_Ehdr= 8*NBPW
e_type= 16
ET_EXEC= 2
sz_Phdr= 7*NBPW
p_memsz= 5*NBPW
// Discard pages of compressed data (includes [ADRX,+LENX) )
addi arg2,r13,p_memsz+sz_Phdr+sz_Ehdr # Phdr[C_TEXT= 1].p_memsz
//cmpw $ET_EXEC, e_type(%r13); jne 1f
mv arg1,r13; call brk // also sets the brk
1:
mv arg1,r13; call munmap # discard C_TEXT compressed data
// Map 1 page of /proc/self/exe so that the symlink does not disappear.
bltz rfd,no_pse_map
li arg6,0 # 0 offset
mv arg5,rfd
li arg4,MAP_PRIVATE
li arg3,PROT_READ
li arg2,1<<12
li arg1,0
call mmap
mv arg1,rfd
call close
no_pse_map:
ld arg1,F_ADRU(rbp) # ADRU: unfolded upx_main2 etc.
ld arg2,F_LENU(rbp)
li a7,__NR_munmap
jr r14 # goto: syscall; pop %rdx; ret
get_page_mask: .globl get_page_mask
ld rv,PAGE_MASK
ret
section SYSCALLS
my_bkpt: .globl my_bkpt
ebreak // my_bkpt
ret
proc_self_exe:
.asciz "/proc/self/exe"
.balign 4
upxfd_create: .globl upxfd_create // (char *tag, unsigned flags)
0: // try memfd_create
syscall __NR_memfd_create; j ok_memfd //NYI
O_RDWR= 2
O_DIRECTORY= 0200000 // 0x010000
O_TMPFILE= 020000000 // 0x400000
li arg4,0700 # mode
li arg3,O_RDWR|O_DIRECTORY|O_TMPFILE
la arg3,dev_shm
li arg1,FD_CWD
syscall __NR_openat
ok_memfd:
ret
Pmap: .globl Pmap // page-align the lo end
ld t0,PAGE_MASK; xori t0,t0,~0 // frag mask
and arg1,arg1,t0 // frag
sub arg1,arg1,t0
add arg2,arg2,t0
mmap: .globl mmap
li a7,__NR_mmap
sysgo:
sys_check:
ebreak // sys_check
syscall 0 //NYI
//NYI syscall error checking
ret
Psync: .globl Psync
li a7,__NR_msync
j 5f
Pprotect: .globl Pprotect
li a7,__NR_mprotect
j 5f
Punmap: .globl Punmap // page-align the lo end
li a7,__NR_munmap
5:
ld t0,PAGE_MASK; xori t0,t0,~0 // frag mask
and t0,t0,arg1 // frag
sub arg1,arg1,t0
add arg2,arg2,t0
j sysgo
munmap: .globl munmap
li a7,__NR_munmap; 5: j 5f
exit: .globl exit
li a7,__NR_exit; 5: j 5f
brk: .globl brk
li a7,__NR_brk; 5: j 5f
close: .globl close
li a7,__NR_close; 5: j 5f
ftruncate: .globl ftruncate
li a7,__NR_ftruncate; 5: j 5f
open: .globl openat
li a7,__NR_openat; 5: j 5f
mprotect: .globl mprotect
li a7,__NR_mprotect; 5: j 5f
msync: .globl msync
li a7,__NR_msync; 5: j 5f
Pwrite: .globl Pwrite
write: .globl write
li a7,__NR_write; 5: j 5f
read: .globl read
li a7,__NR_read; 5: j sysgo
// vim:set ts=8 sw=8 et:
+37
View File
@@ -0,0 +1,37 @@
/* riscv64-linux.elf-fold.lds -- static linker script to build riscv64-linux.elf-fold.bin
This file is part of the UPX executable compressor.
Copyright (C) 2000-2025 John F. Reiser
All Rights Reserved.
UPX and the UCL library are free software; you can redistribute them
and/or modify them under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING.
If not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Markus F.X.J. Oberhumer Laszlo Molnar
<markus@oberhumer.com> <ezerotven+github@gmail.com>
John F. Reiser
<jreiser@users.sourceforge.net>
*/
OUTPUT_FORMAT("elf64-littleriscv64", "elf64-littleriscv64", "elf64-littleriscv64")
OUTPUT_ARCH(riscv64)
SECTIONS
{
. = SIZEOF_HEADERS;
}
@@ -0,0 +1,5 @@
.section HUMF_A, "ax"
j upx_mmap_and_fd_android
.section HUMF_L, "ax"
j upx_mmap_and_fd_linux
+1
View File
@@ -0,0 +1 @@
#include "amd64-linux.elf-main2.c"
+10
View File
@@ -74,6 +74,16 @@ extern void my_bkpt(void const *, ...);
/*und*/ : "x30"); \
str; \
})
#elif defined(__riscv) //}{
#define ANDROID_FRIEND 0
#define addr_string(string) ({ \
char const *str; \
asm("jal 0f; .string \"" string "\"; .balign 4; 0: mv %0,ra" \
/*out*/ : "=r"(str) \
/* in*/ : \
/*und*/ : "x30"); \
str; \
})
#else //}{
#define ANDROID_FRIEND 0
#error addr_string