summaryrefslogtreecommitdiff
path: root/tests/pc.c
diff options
context:
space:
mode:
authorDmitry V. Levin <ldv@altlinux.org>2015-02-15 15:52:02 +0000
committerDmitry V. Levin <ldv@altlinux.org>2015-02-16 02:39:21 +0000
commite96cb621fa7dc898f83d8afdaa7579cc54a115b0 (patch)
tree52be10caa4aeb7003397e04b20ac577cc9095321 /tests/pc.c
parent4f2d1ae243d4351209fca26599f81c7e6ca39e40 (diff)
downloadstrace-e96cb621fa7dc898f83d8afdaa7579cc54a115b0.tar.gz
print_pc: fix multiple personalities support
* syscall.c (print_pc): Choose instruction pointer format depending on current_wordsize, not the size of long integer type. * tests/pc.c: New file. * tests/pc.test: New test. * tests/Makefile.am (check_PROGRAMS): Add pc. (TESTS): Add pc.test. * tests/.gitignore: Add pc.
Diffstat (limited to 'tests/pc.c')
-rw-r--r--tests/pc.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/tests/pc.c b/tests/pc.c
new file mode 100644
index 000000000..909a2ef1a
--- /dev/null
+++ b/tests/pc.c
@@ -0,0 +1,35 @@
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+
+int main(void)
+{
+ const unsigned long size = sysconf(_SC_PAGESIZE);
+ const unsigned long mask = ~(size - 1);
+
+ /* write instruction pointer length to the log */
+ if (write(-1, NULL, 2 * sizeof(void *)) >= 0)
+ return 77;
+ /* just a noticeable line in the log */
+ if (munmap(&munmap, 0) >= 0)
+ return 77;
+
+ int pid = fork();
+ if (pid < 0)
+ return 77;
+
+ if (!pid) {
+ munmap((void *) ((unsigned long) &munmap & mask), size);
+ /* SIGSEGV is expected */
+ munmap((void *) (((unsigned long) &munmap & mask) + size), size);
+ return 77;
+ }
+
+ int status;
+ if (wait(&status) != pid ||
+ !WIFSIGNALED(status) ||
+ WTERMSIG(status) != SIGSEGV)
+ return 77;
+
+ return 0;
+}