*(uint32_t *)ptr = gen_endbr64();
}
+/*
+ * After clobbering ENDBR64, we may need to confirm that the site used to
+ * contain an ENDBR64 instruction. Use an encoding which isn't the default
+ * P6_NOP4. Specifically, nopw (%rcx)
+ */
+static inline uint32_t __attribute_const__ gen_endbr64_poison(void)
+{
+ uint32_t res;
+
+ asm ( "mov $~0x011f0f66, %[res]\n\t"
+ "not %[res]\n\t"
+ : [res] "=&r" (res) );
+
+ return res;
+}
+
+static inline bool is_endbr64_poison(const void *ptr)
+{
+ return *(const uint32_t *)ptr == gen_endbr64_poison();
+}
+
+static inline void place_endbr64_poison(void *ptr)
+{
+ *(uint32_t *)ptr = gen_endbr64_poison();
+}
+
#endif /* XEN_ASM_ENDBR_H */
# Check whether grep supports Perl regexps. Older GNU grep doesn't reliably
# find binary patterns otherwise.
perl_re=true
-echo "X" | grep -aobP "\130" -q 2>/dev/null || perl_re=false
+echo "X" | grep -aobP "\x58" -q 2>/dev/null || perl_re=false
#
# First, look for all the valid endbr64 instructions.
${OBJDUMP} -j .text $1 -d -w | grep ' endbr64 *$' | cut -f 1 -d ':' > $VALID &
#
-# Second, look for any endbr64 byte sequence
+# Second, look for all endbr64, endbr32 and nop poison byte sequences
# This has a couple of complications:
#
# 1) Grep binary search isn't VMA aware. Copy .text out as binary, causing
# the grep offset to be from the start of .text.
#
# 2) dash's printf doesn't understand hex escapes, hence the use of octal.
+# `grep -P` on the other hand has various ambiguities with octal-like
+# escapes, so use hex escapes instead which are unambiguous.
#
# 3) AWK can't add 64bit integers, because internally all numbers are doubles.
# When the upper bits are set, the exponents worth of precision is lost in
awk '$2 == ".text" {printf "vma_hi=%s\nvma_lo=%s\n", substr($4, 1, 8), substr($4, 9, 16)}')
${OBJCOPY} -j .text $1 -O binary $TEXT_BIN
+
+# instruction: hex: oct:
+# endbr64 f3 0f 1e fa 363 017 036 372
+# endbr32 f3 0f 1e fb 363 017 036 373
+# nopw (%rcx) 66 0f 1f 01 146 017 037 001
if $perl_re
then
- LC_ALL=C grep -aobP '\363\17\36\372' $TEXT_BIN
+ LC_ALL=C grep -aobP '\xf3\x0f\x1e(\xfa|\xfb)|\x66\x0f\x1f\x01' $TEXT_BIN
else
- grep -aob "$(printf '\363\17\36\372')" $TEXT_BIN
+ grep -aob -e "$(printf '\363\17\36\372')" -e "$(printf '\363\17\36\373')" \
+ -e "$(printf '\146\17\37\1')" $TEXT_BIN
fi | awk -F':' '{printf "%s%x\n", "'$vma_hi'", int(0x'$vma_lo') + $1}' > $ALL
# Wait for $VALID to become complete
[ "$nr_bad" -eq 0 ] && exit 0
# Failure
-echo "$MSG_PFX Fail: Found ${nr_bad} embedded endbr64 instructions" >&2
+echo "$MSG_PFX Fail: Found ${nr_bad} endb32, nop poison, or embedded endbr64 instructions" >&2
${ADDR2LINE} -afip -e $1 < $BAD >&2
exit 1