aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-27 12:59:50 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-27 12:59:50 -0500
commitadf96e6f514a9e87aa3d26c8c9c03eca5be53df0 (patch)
tree36b32a7daaad132c66d7e2d09e922a85d1e2ac5b /drivers
parent09884964335e85e897876d17783c2ad33cf8a2e0 (diff)
sysrq: don't depend on weak undefined arrays to have an address that compares as NULL
When taking an address of an extern array, gcc quite naturally should be able to say "an address of an object can never be NULL" and just optimize away the test entirely. However, the new alternate sysrq reset code (commit 154b7a489a5b: "Input: sysrq - allow specifying alternate reset sequence") did exactly that, and declared platform_sysrq_reset_seq[] as a weak array, and expecting that testing the address of the array would show whether it actually got linked against something or not. And that doesn't work with all gcc versions. Clearly it works with *some* versions of gcc, and maybe it's even supposed to work, but it really is a very fragile concept. So instead of testing the address of the weak variable, just create a weak instance of that array that is empty. If some platform then has a real platform_sysrq_reset_seq[] that overrides our weak one, the linker will switch to that one, and it all works without any run-time conditionals at all. Reported-by: Dave Airlie <airlied@gmail.com> Cc: David Howells <dhowells@redhat.com> Cc: Russell King <rmk+kernel@arm.linux.org.uk> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com> Acked-by: Mathieu Poirier <mathieu.poirier@linaro.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/tty/sysrq.c15
1 files changed, 7 insertions, 8 deletions
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index 814655ee2d61..3687f0cad642 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -870,21 +870,20 @@ static struct input_handler sysrq_handler = {
870 870
871static bool sysrq_handler_registered; 871static bool sysrq_handler_registered;
872 872
873unsigned short platform_sysrq_reset_seq[] __weak = { KEY_RESERVED };
874
873static inline void sysrq_register_handler(void) 875static inline void sysrq_register_handler(void)
874{ 876{
875 extern unsigned short platform_sysrq_reset_seq[] __weak;
876 unsigned short key; 877 unsigned short key;
877 int error; 878 int error;
878 int i; 879 int i;
879 880
880 if (platform_sysrq_reset_seq) { 881 for (i = 0; i < ARRAY_SIZE(sysrq_reset_seq); i++) {
881 for (i = 0; i < ARRAY_SIZE(sysrq_reset_seq); i++) { 882 key = platform_sysrq_reset_seq[i];
882 key = platform_sysrq_reset_seq[i]; 883 if (key == KEY_RESERVED || key > KEY_MAX)
883 if (key == KEY_RESERVED || key > KEY_MAX) 884 break;
884 break;
885 885
886 sysrq_reset_seq[sysrq_reset_seq_len++] = key; 886 sysrq_reset_seq[sysrq_reset_seq_len++] = key;
887 }
888 } 887 }
889 888
890 error = input_register_handler(&sysrq_handler); 889 error = input_register_handler(&sysrq_handler);