[CRIU] [PATCHv2 06/12] arm: Provide aeabi helpers in ARM format
Dmitry Safonov
dima at arista.com
Wed May 29 19:15:09 MSK 2019
From: Dmitry Safonov <0x7f454c46 at gmail.com>
We're building PIEs in arm format rather than in thumb.
Copy helpers from libgcc, provide a proper define and
link them into blobs.
Also substitute tabs by spaces, how it should have been
in pie/Makefile - tabs are for recipes.
Fixes:
LINK criu/pie/parasite.built-in.o
criu/pie/pie.lib.a(util-vdso.o): In function `elf_hash':
/criu/criu/pie/util-vdso.c:61: undefined reference to `__aeabi_uidivmod'
/criu/scripts/nmk/scripts/build.mk:209: recipe for target 'criu/pie/parasite.built-in.o' failed
Signed-off-by: Dmitry Safonov <0x7f454c46 at gmail.com>
---
criu/arch/arm/aeabi-helpers.S | 96 +++++++++++++
criu/arch/arm/uidiv.S | 186 --------------------------
criu/pie/Makefile | 4 +-
criu/pie/Makefile.library | 4 +
include/common/arch/arm/asm/linkage.h | 4 +
5 files changed, 106 insertions(+), 188 deletions(-)
create mode 100644 criu/arch/arm/aeabi-helpers.S
delete mode 100644 criu/arch/arm/uidiv.S
diff --git a/criu/arch/arm/aeabi-helpers.S b/criu/arch/arm/aeabi-helpers.S
new file mode 100644
index 000000000000..ea8561d48fe4
--- /dev/null
+++ b/criu/arch/arm/aeabi-helpers.S
@@ -0,0 +1,96 @@
+/*
+ * Code borrowed from gcc, arm/lib1funcs.S
+ * and adapted to CRIU macros.
+ */
+
+#if defined(__thumb__)
+/*
+ * We don't support compiling PIEs in Thumb mode,
+ * see top Makefile for details (ARM CFLAGS_PIE section).
+*/
+#error Unsupported Thumb mode
+#endif
+
+#include "common/asm/linkage.h"
+
+#define RET bx lr
+#define RETc(x) bx##x lr
+#define LSYM(x) .x
+
+.macro do_it cond, suffix=""
+.endm
+
+.macro ARM_DIV2_ORDER divisor, order
+ clz \order, \divisor
+ rsb \order, \order, #31
+.endm
+
+.macro ARM_DIV_BODY dividend, divisor, result, curbit
+ clz \curbit, \dividend
+ clz \result, \divisor
+ sub \curbit, \result, \curbit
+ rsbs \curbit, \curbit, #31
+ addne \curbit, \curbit, \curbit, lsl #1
+ mov \result, #0
+ addne pc, pc, \curbit, lsl #2
+ nop
+ .set shift, 32
+ .rept 32
+ .set shift, shift - 1
+ cmp \dividend, \divisor, lsl #shift
+ adc \result, \result, \result
+ subcs \dividend, \dividend, \divisor, lsl #shift
+ .endr
+.endm
+
+/*
+ * XXX: as an optimization add udiv instruction based version.
+ * It's possible to check if CPU supports the instruction by
+ * reading Instruction Set Attribute Register (ID_ISAR0)
+ * and checking fields "Divide_instrs".
+ */
+ENTRY(__aeabi_uidiv)
+ /* Note: if called via udivsi3_skip_div0_test, this will unnecessarily
+ check for division-by-zero a second time. */
+LSYM(udivsi3_skip_div0_test):
+ subs r2, r1, #1
+ do_it eq
+ RETc(eq)
+ bcc LSYM(Ldiv0)
+ cmp r0, r1
+ bls 11f
+ tst r1, r2
+ beq 12f
+
+ ARM_DIV_BODY r0, r1, r2, r3
+
+ mov r0, r2
+ RET
+
+11: do_it eq, e
+ moveq r0, #1
+ movne r0, #0
+ RET
+
+12: ARM_DIV2_ORDER r1, r2
+
+ mov r0, r0, lsr r2
+ RET
+
+LSYM(Ldiv0):
+ .byte 0xf0, 0x01, 0xf0, 0xe7 @ the instruction UDF #32 generates the signal SIGTRAP in Linux
+
+END(__aeabi_uidiv)
+ALIAS(__udivsi3, __aeabi_uidiv)
+
+ENTRY(__aeabi_uidivmod)
+ cmp r1, #0
+ beq LSYM(Ldiv0)
+ stmfd sp!, { r0, r1, lr }
+ bl LSYM(udivsi3_skip_div0_test)
+ ldmfd sp!, { r1, r2, lr }
+ mul r3, r2, r0
+ sub r1, r1, r3
+ RET
+END(__aeabi_uidivmod)
+ALIAS(__umodsi3, __aeabi_uidiv)
diff --git a/criu/arch/arm/uidiv.S b/criu/arch/arm/uidiv.S
deleted file mode 100644
index e77f6100c784..000000000000
--- a/criu/arch/arm/uidiv.S
+++ /dev/null
@@ -1,186 +0,0 @@
-.globl __aeabi_uidiv
-
-work .req r4 @ XXXX is this safe ?
-dividend .req r0
-divisor .req r1
-overdone .req r2
-result .req r2
-curbit .req r3
-
-#define LSYM(x) x
-
-.macro THUMB_DIV_MOD_BODY modulo
- @ Load the constant 0x10000000 into our work register.
- mov work, #1
- lsl work, #28
-LSYM(Loop1):
- @ Unless the divisor is very big, shift it up in multiples of
- @ four bits, since this is the amount of unwinding in the main
- @ division loop. Continue shifting until the divisor is
- @ larger than the dividend.
- cmp divisor, work
- bhs LSYM(Lbignum)
- cmp divisor, dividend
- bhs LSYM(Lbignum)
- lsl divisor, #4
- lsl curbit, #4
- b LSYM(Loop1)
-LSYM(Lbignum):
- @ Set work to 0x80000000
- lsl work, #3
-LSYM(Loop2):
- @ For very big divisors, we must shift it a bit at a time, or
- @ we will be in danger of overflowing.
- cmp divisor, work
- bhs LSYM(Loop3)
- cmp divisor, dividend
- bhs LSYM(Loop3)
- lsl divisor, #1
- lsl curbit, #1
- b LSYM(Loop2)
-LSYM(Loop3):
- @ Test for possible subtractions ...
- .if \modulo
- @ ... On the final pass, this may subtract too much from the dividend,
- @ so keep track of which subtractions are done, we can fix them up
- @ afterwards.
- mov overdone, #0
- cmp dividend, divisor
- blo LSYM(Lover1)
- sub dividend, dividend, divisor
-LSYM(Lover1):
- lsr work, divisor, #1
- cmp dividend, work
- blo LSYM(Lover2)
- sub dividend, dividend, work
- mov ip, curbit
- mov work, #1
- ror curbit, work
- orr overdone, curbit
- mov curbit, ip
-LSYM(Lover2):
- lsr work, divisor, #2
- cmp dividend, work
- blo LSYM(Lover3)
- sub dividend, dividend, work
- mov ip, curbit
- mov work, #2
- ror curbit, work
- orr overdone, curbit
- mov curbit, ip
-LSYM(Lover3):
- lsr work, divisor, #3
- cmp dividend, work
- blo LSYM(Lover4)
- sub dividend, dividend, work
- mov ip, curbit
- mov work, #3
- ror curbit, work
- orr overdone, curbit
- mov curbit, ip
-LSYM(Lover4):
- mov ip, curbit
- .else
- @ ... and note which bits are done in the result. On the final pass,
- @ this may subtract too much from the dividend, but the result will be ok,
- @ since the "bit" will have been shifted out at the bottom.
- cmp dividend, divisor
- blo LSYM(Lover1)
- sub dividend, dividend, divisor
- orr result, result, curbit
-LSYM(Lover1):
- lsr work, divisor, #1
- cmp dividend, work
- blo LSYM(Lover2)
- sub dividend, dividend, work
- lsr work, curbit, #1
- orr result, work
-LSYM(Lover2):
- lsr work, divisor, #2
- cmp dividend, work
- blo LSYM(Lover3)
- sub dividend, dividend, work
- lsr work, curbit, #2
- orr result, work
-LSYM(Lover3):
- lsr work, divisor, #3
- cmp dividend, work
- blo LSYM(Lover4)
- sub dividend, dividend, work
- lsr work, curbit, #3
- orr result, work
-LSYM(Lover4):
- .endif
-
- cmp dividend, #0 @ Early termination?
- beq LSYM(Lover5)
- lsr curbit, #4 @ No, any more bits to do?
- beq LSYM(Lover5)
- lsr divisor, #4
- b LSYM(Loop3)
-LSYM(Lover5):
- .if \modulo
- @ Any subtractions that we should not have done will be recorded in
- @ the top three bits of "overdone". Exactly which were not needed
- @ are governed by the position of the bit, stored in ip.
- mov work, #0xe
- lsl work, #28
- and overdone, work
- beq LSYM(Lgot_result)
-
- @ If we terminated early, because dividend became zero, then the
- @ bit in ip will not be in the bottom nibble, and we should not
- @ perform the additions below. We must test for this though
- @ (rather relying upon the TSTs to prevent the additions) since
- @ the bit in ip could be in the top two bits which might then match
- @ with one of the smaller RORs.
- mov curbit, ip
- mov work, #0x7
- tst curbit, work
- beq LSYM(Lgot_result)
-
- mov curbit, ip
- mov work, #3
- ror curbit, work
- tst overdone, curbit
- beq LSYM(Lover6)
- lsr work, divisor, #3
- add dividend, work
-LSYM(Lover6):
- mov curbit, ip
- mov work, #2
- ror curbit, work
- tst overdone, curbit
- beq LSYM(Lover7)
- lsr work, divisor, #2
- add dividend, work
-LSYM(Lover7):
- mov curbit, ip
- mov work, #1
- ror curbit, work
- tst overdone, curbit
- beq LSYM(Lgot_result)
- lsr work, divisor, #1
- add dividend, work
- .endif
-LSYM(Lgot_result):
-.endm
-
-
- .thumb
- .text
-
-__aeabi_uidiv:
- mov curbit, #1
- mov result, #0
-
- push { work }
- cmp dividend, divisor
- blo LSYM(Lgot_result)
-
- THUMB_DIV_MOD_BODY 0
-
- mov r0, result
- pop { work }
-
- bx lr
diff --git a/criu/pie/Makefile b/criu/pie/Makefile
index bdff44816c79..ade186346524 100644
--- a/criu/pie/Makefile
+++ b/criu/pie/Makefile
@@ -10,8 +10,8 @@ ccflags-y += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0
ccflags-y += -Wp,-U_FORTIFY_SOURCE -Wp,-D_FORTIFY_SOURCE=0
ifneq ($(filter-out clean mrproper,$(MAKECMDGOALS)),)
- LDFLAGS += $(shell $(COMPEL_BIN) ldflags)
- compel_plugins := $(shell $(COMPEL_BIN) plugins)
+ LDFLAGS += $(shell $(COMPEL_BIN) ldflags)
+ compel_plugins := $(shell $(COMPEL_BIN) plugins)
endif
LDS := compel/arch/$(SRCARCH)/scripts/compel-pack.lds.S
diff --git a/criu/pie/Makefile.library b/criu/pie/Makefile.library
index 0a33a8861791..2d2d1faf1bd7 100644
--- a/criu/pie/Makefile.library
+++ b/criu/pie/Makefile.library
@@ -23,5 +23,9 @@ ifeq ($(SRCARCH),x86)
CFLAGS_util-vdso-elf32.o += -DCONFIG_VDSO_32
endif
+ifeq ($(SRCARCH),arm)
+ lib-y += ./$(ARCH_DIR)/aeabi-helpers.o
+endif
+
CFLAGS := $(filter-out -pg $(CFLAGS-GCOV) $(CFLAGS-ASAN),$(CFLAGS))
ccflags-y += $(CFLAGS_PIE)
diff --git a/include/common/arch/arm/asm/linkage.h b/include/common/arch/arm/asm/linkage.h
index 7380642337a0..a93898be5470 100644
--- a/include/common/arch/arm/asm/linkage.h
+++ b/include/common/arch/arm/asm/linkage.h
@@ -19,6 +19,10 @@
#define END(sym) \
.size sym, . - sym
+#define ALIAS(sym_new, sym_old) \
+ .globl sym_new; \
+ .set sym_new, sym_old
+
#endif /* __ASSEMBLY__ */
#endif /* __CR_LINKAGE_H__ */
--
2.21.0
More information about the CRIU
mailing list