about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2017-10-13 10:23:48 -0400
committerRich Felker <dalias@aerifal.cx>2017-10-13 10:28:52 -0400
commite364774d7ca0a78db1b8457d5094b747eb2df318 (patch)
tree64b13e59d66bbb8099d8f4a5b1775ba90fbb9a09
parent48be5b6313d7b827acf555769e93b389fa9f6307 (diff)
downloadmusl-e364774d7ca0a78db1b8457d5094b747eb2df318.tar.gz
musl-e364774d7ca0a78db1b8457d5094b747eb2df318.tar.xz
musl-e364774d7ca0a78db1b8457d5094b747eb2df318.zip
fix access by setjmp and longjmp to __hwcap on arm built as thumb2
this is a subtle issue with how the assembler/linker work. for the adr
pseudo-instruction used to find __hwcap, the assembler in thumb mode
generates a 16-bit thumb add instruction which can only represent
word-aligned addresses, despite not knowing the alignment of the
label. if the setjmp function is assigned a non-multiple-of-4 address
at link time, the load then loads from the wrong address (the last
instruction rather than the data containing the offset) and ends up
reading nonsense instead of the value of __hwcap. this in turn causes
the checks for floating-point/vector register sets (e.g. IWMMX) to
evaluate incorrectly, crashing when setjmp/longjmp try to save/restore
those registers.

fix based on bug report by Felix Hädicke.
-rw-r--r--src/setjmp/arm/longjmp.s1
-rw-r--r--src/setjmp/arm/setjmp.s1
2 files changed, 2 insertions, 0 deletions
diff --git a/src/setjmp/arm/longjmp.s b/src/setjmp/arm/longjmp.s
index 6191ab26..76cc2920 100644
--- a/src/setjmp/arm/longjmp.s
+++ b/src/setjmp/arm/longjmp.s
@@ -39,4 +39,5 @@ longjmp:
 3:	bx lr
 
 .hidden __hwcap
+.align 2
 1:	.word __hwcap-1b
diff --git a/src/setjmp/arm/setjmp.s b/src/setjmp/arm/setjmp.s
index c6fe1bb2..011315b7 100644
--- a/src/setjmp/arm/setjmp.s
+++ b/src/setjmp/arm/setjmp.s
@@ -41,4 +41,5 @@ setjmp:
 3:	bx lr
 
 .hidden __hwcap
+.align 2
 1:	.word __hwcap-1b