Home | History | Annotate | Line # | Download | only in modules
      1   1.1  kamil /*
      2   1.1  kamil  * SPDX-License-Identifier: BSD-2-Clause
      3   1.1  kamil  *
      4   1.1  kamil  * Copyright (c) 2018, 2019 Andrew Turner
      5   1.1  kamil  *
      6   1.1  kamil  * This software was developed by SRI International and the University of
      7   1.1  kamil  * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
      8   1.1  kamil  * ("CTSRD"), as part of the DARPA CRASH research programme.
      9   1.1  kamil  *
     10   1.1  kamil  * Redistribution and use in source and binary forms, with or without
     11   1.1  kamil  * modification, are permitted provided that the following conditions
     12   1.1  kamil  * are met:
     13   1.1  kamil  * 1. Redistributions of source code must retain the above copyright
     14   1.1  kamil  *    notice, this list of conditions and the following disclaimer.
     15   1.1  kamil  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.1  kamil  *    notice, this list of conditions and the following disclaimer in the
     17   1.1  kamil  *    documentation and/or other materials provided with the distribution.
     18   1.1  kamil  *
     19   1.1  kamil  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     20   1.1  kamil  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21   1.1  kamil  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22   1.1  kamil  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     23   1.1  kamil  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24   1.1  kamil  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25   1.1  kamil  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26   1.1  kamil  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27   1.1  kamil  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28   1.1  kamil  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29   1.1  kamil  * SUCH DAMAGE.
     30   1.1  kamil  */
     31   1.1  kamil #include <sys/cdefs.h>
     32   1.1  kamil 
     33   1.1  kamil #include <sys/param.h>
     34   1.1  kamil #include <sys/ioctl.h>
     35   1.1  kamil #include <sys/kcov.h>
     36   1.1  kamil #include <sys/mman.h>
     37   1.1  kamil 
     38   1.5  kamil #include <errno.h>
     39   1.1  kamil #include <fcntl.h>
     40   1.1  kamil #include <pthread.h>
     41   1.1  kamil #include <semaphore.h>
     42   1.7  kamil #include <unistd.h>
     43   1.1  kamil 
     44   1.1  kamil #include <atf-c.h>
     45   1.1  kamil 
     46   1.1  kamil #define PAGE_SIZE sysconf(_SC_PAGESIZE)
     47   1.1  kamil 
     48   1.1  kamil static int
     49   1.1  kamil open_kcov(void)
     50   1.1  kamil {
     51   1.1  kamil 	int fd;
     52   1.1  kamil 
     53   1.1  kamil 	fd = open("/dev/kcov", O_RDWR);
     54   1.1  kamil 	if (fd == -1)
     55   1.1  kamil 		atf_tc_skip("Failed to open /dev/kcov");
     56   1.1  kamil 
     57   1.1  kamil 	return fd;
     58   1.1  kamil }
     59   1.1  kamil 
     60   1.8  kamil static int
     61   1.8  kamil pick_unassigned_fd(int greater_than_fd)
     62   1.8  kamil {
     63   1.8  kamil 	int fd2;
     64   1.8  kamil 
     65   1.8  kamil 	fd2 = greater_than_fd;
     66   1.8  kamil 	do {
     67   1.8  kamil 		++fd2;
     68   1.8  kamil 	} while (fcntl(fd2, F_GETFL) != -1 || errno != EBADF);
     69   1.8  kamil 
     70   1.8  kamil 	return fd2;
     71   1.8  kamil }
     72   1.8  kamil 
     73   1.8  kamil ATF_TC_WITHOUT_HEAD(kcov_dup2);
     74   1.8  kamil ATF_TC_BODY(kcov_dup2, tc)
     75   1.8  kamil {
     76   1.8  kamil 	int fd1, fd2;
     77   1.8  kamil 	fd1 = open_kcov();
     78   1.8  kamil 
     79   1.8  kamil 	fd2 = pick_unassigned_fd(fd1);
     80   1.8  kamil 
     81   1.8  kamil 	/* Test the dup2(2) trick used by syzkaller */
     82   1.8  kamil 	ATF_REQUIRE_EQ(dup2(fd1, fd2), fd2);
     83   1.8  kamil 
     84   1.8  kamil 	close(fd1);
     85   1.8  kamil 	close(fd2);
     86   1.8  kamil }
     87   1.8  kamil 
     88   1.5  kamil ATF_TC_WITHOUT_HEAD(kcov_multiopen);
     89   1.5  kamil ATF_TC_BODY(kcov_multiopen, tc)
     90   1.5  kamil {
     91   1.5  kamil 	int fd1, fd2;
     92   1.5  kamil 	fd1 = open_kcov();
     93   1.5  kamil 
     94   1.5  kamil 	fd2 = open("/dev/kcov", O_RDWR);
     95   1.5  kamil 	ATF_REQUIRE(fd2 != -1);
     96   1.5  kamil 
     97   1.5  kamil 	close(fd1);
     98   1.5  kamil 	close(fd2);
     99   1.5  kamil }
    100   1.5  kamil 
    101   1.5  kamil ATF_TC_WITHOUT_HEAD(kcov_open_close_open);
    102   1.5  kamil ATF_TC_BODY(kcov_open_close_open, tc)
    103   1.5  kamil {
    104   1.5  kamil 	int fd;
    105   1.5  kamil 
    106   1.5  kamil 	fd = open_kcov();
    107   1.5  kamil 	close(fd);
    108   1.5  kamil 	fd = open("/dev/kcov", O_RDWR);
    109   1.5  kamil 	ATF_REQUIRE(fd != -1);
    110   1.5  kamil 
    111   1.5  kamil 	close(fd);
    112   1.5  kamil }
    113   1.5  kamil 
    114   1.1  kamil ATF_TC_WITHOUT_HEAD(kcov_bufsize);
    115   1.1  kamil ATF_TC_BODY(kcov_bufsize, tc)
    116   1.1  kamil {
    117   1.1  kamil 	int fd;
    118   1.5  kamil 	uint64_t size;
    119   1.1  kamil 	fd = open_kcov();
    120   1.1  kamil 
    121   1.1  kamil 	size = 0;
    122   1.1  kamil 	ATF_CHECK(ioctl(fd, KCOV_IOC_SETBUFSIZE, &size) == -1);
    123   1.1  kamil 	size = 2;
    124   1.1  kamil 	ATF_CHECK(ioctl(fd, KCOV_IOC_SETBUFSIZE, &size) == 0);
    125   1.1  kamil 
    126   1.1  kamil 	close(fd);
    127   1.1  kamil }
    128   1.1  kamil 
    129   1.1  kamil ATF_TC_WITHOUT_HEAD(kcov_mmap);
    130   1.1  kamil ATF_TC_BODY(kcov_mmap, tc)
    131   1.1  kamil {
    132   1.1  kamil 	void *data;
    133   1.1  kamil 	int fd;
    134   1.5  kamil 	uint64_t size = 2 * PAGE_SIZE / KCOV_ENTRY_SIZE;
    135   1.1  kamil 
    136   1.1  kamil 	fd = open_kcov();
    137   1.1  kamil 
    138   1.1  kamil 	ATF_CHECK(mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
    139   1.1  kamil 	    fd, 0) == MAP_FAILED);
    140   1.1  kamil 
    141   1.1  kamil 	ATF_REQUIRE(ioctl(fd, KCOV_IOC_SETBUFSIZE, &size) == 0);
    142   1.1  kamil 
    143   1.1  kamil 	ATF_REQUIRE((data = mmap(NULL, 2 * PAGE_SIZE, PROT_READ | PROT_WRITE,
    144   1.1  kamil 	    MAP_SHARED, fd, 0)) != MAP_FAILED);
    145   1.1  kamil 
    146   1.1  kamil 	munmap(data, 2 * PAGE_SIZE);
    147   1.1  kamil 
    148   1.1  kamil 	close(fd);
    149   1.1  kamil }
    150   1.1  kamil 
    151   1.1  kamil /* This shouldn't panic */
    152   1.1  kamil ATF_TC_WITHOUT_HEAD(kcov_mmap_no_munmap);
    153   1.1  kamil ATF_TC_BODY(kcov_mmap_no_munmap, tc)
    154   1.1  kamil {
    155   1.1  kamil 	int fd;
    156   1.5  kamil 	uint64_t size = PAGE_SIZE / KCOV_ENTRY_SIZE;
    157   1.1  kamil 
    158   1.1  kamil 	fd = open_kcov();
    159   1.1  kamil 
    160   1.1  kamil 	ATF_REQUIRE(ioctl(fd, KCOV_IOC_SETBUFSIZE, &size) ==0);
    161   1.1  kamil 
    162   1.1  kamil 	ATF_CHECK(mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
    163   1.1  kamil 	    fd, 0) != MAP_FAILED);
    164   1.1  kamil 
    165   1.1  kamil 	close(fd);
    166   1.1  kamil }
    167   1.1  kamil 
    168   1.1  kamil ATF_TC_WITHOUT_HEAD(kcov_mmap_no_munmap_no_close);
    169   1.1  kamil ATF_TC_BODY(kcov_mmap_no_munmap_no_close, tc)
    170   1.1  kamil {
    171   1.1  kamil 	int fd;
    172   1.5  kamil 	uint64_t size = PAGE_SIZE / KCOV_ENTRY_SIZE;
    173   1.1  kamil 
    174   1.1  kamil 	fd = open_kcov();
    175   1.1  kamil 
    176   1.1  kamil 	ATF_REQUIRE(ioctl(fd, KCOV_IOC_SETBUFSIZE, &size) ==0);
    177   1.1  kamil 
    178   1.1  kamil 	ATF_CHECK(mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
    179   1.1  kamil 	    fd, 0) != MAP_FAILED);
    180   1.1  kamil }
    181   1.1  kamil 
    182   1.1  kamil static sem_t sem1, sem2;
    183   1.1  kamil 
    184   1.1  kamil static void *
    185   1.1  kamil kcov_mmap_enable_thread(void *data)
    186   1.1  kamil {
    187   1.1  kamil 	int fd;
    188   1.5  kamil 	uint64_t size = PAGE_SIZE / KCOV_ENTRY_SIZE;
    189   1.7  kamil 	int mode;
    190   1.1  kamil 
    191   1.1  kamil 	fd = open_kcov();
    192   1.1  kamil 	*(int *)data = fd;
    193   1.1  kamil 
    194   1.1  kamil 	ATF_REQUIRE(ioctl(fd, KCOV_IOC_SETBUFSIZE, &size) ==0);
    195   1.1  kamil 	ATF_CHECK(mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
    196   1.1  kamil 	    fd, 0) != MAP_FAILED);
    197   1.7  kamil 	mode = KCOV_MODE_NONE;
    198   1.7  kamil 	ATF_CHECK(ioctl(fd, KCOV_IOC_ENABLE, &mode) == 0);
    199   1.1  kamil 
    200   1.1  kamil 	sem_post(&sem1);
    201   1.1  kamil 	sem_wait(&sem2);
    202   1.1  kamil 
    203   1.1  kamil 	return NULL;
    204   1.1  kamil }
    205   1.1  kamil 
    206   1.1  kamil ATF_TC_WITHOUT_HEAD(kcov_mmap_enable_thread_close);
    207   1.1  kamil ATF_TC_BODY(kcov_mmap_enable_thread_close, tc)
    208   1.1  kamil {
    209   1.1  kamil 	pthread_t thread;
    210   1.1  kamil 	int fd;
    211   1.1  kamil 
    212   1.1  kamil 	sem_init(&sem1, 0, 0);
    213   1.1  kamil 	sem_init(&sem2, 0, 0);
    214   1.1  kamil 	pthread_create(&thread, NULL,
    215   1.1  kamil 	    kcov_mmap_enable_thread, &fd);
    216   1.1  kamil 	sem_wait(&sem1);
    217   1.1  kamil 	close(fd);
    218   1.1  kamil 	sem_post(&sem2);
    219   1.1  kamil 	pthread_join(thread, NULL);
    220   1.1  kamil }
    221   1.1  kamil 
    222   1.1  kamil ATF_TC_WITHOUT_HEAD(kcov_enable);
    223   1.1  kamil ATF_TC_BODY(kcov_enable, tc)
    224   1.1  kamil {
    225   1.1  kamil 	int fd;
    226   1.5  kamil 	uint64_t size = PAGE_SIZE / KCOV_ENTRY_SIZE;
    227   1.7  kamil 	int mode;
    228   1.1  kamil 
    229   1.1  kamil 	fd = open_kcov();
    230   1.1  kamil 
    231   1.7  kamil 	mode = KCOV_MODE_NONE;
    232   1.7  kamil 	ATF_CHECK(ioctl(fd, KCOV_IOC_ENABLE, &mode) == -1);
    233   1.1  kamil 
    234   1.1  kamil 	ATF_REQUIRE(ioctl(fd, KCOV_IOC_SETBUFSIZE, &size) ==0);
    235   1.1  kamil 
    236   1.1  kamil 	/* We need to enable before disable */
    237   1.1  kamil 	ATF_CHECK(ioctl(fd, KCOV_IOC_DISABLE) == -1);
    238   1.1  kamil 
    239   1.1  kamil 	/* Check enabling works only with a valid trace method */
    240   1.7  kamil 	ATF_CHECK(ioctl(fd, KCOV_IOC_ENABLE, &mode) == 0);
    241   1.7  kamil 	ATF_CHECK(ioctl(fd, KCOV_IOC_ENABLE, &mode) == -1);
    242   1.1  kamil 
    243   1.1  kamil 	/* Disable should only be called once */
    244   1.1  kamil 	ATF_CHECK(ioctl(fd, KCOV_IOC_DISABLE) == 0);
    245   1.1  kamil 	ATF_CHECK(ioctl(fd, KCOV_IOC_DISABLE) == -1);
    246   1.1  kamil 
    247   1.8  kamil 	/* Re-enabling and changing mode should also work */
    248   1.7  kamil 	mode = KCOV_MODE_NONE;
    249   1.7  kamil 	ATF_CHECK(ioctl(fd, KCOV_IOC_ENABLE, &mode) == 0);
    250   1.7  kamil 	ATF_CHECK(ioctl(fd, KCOV_IOC_DISABLE) == 0);
    251   1.7  kamil 	mode = KCOV_MODE_TRACE_PC;
    252   1.7  kamil 	ATF_CHECK(ioctl(fd, KCOV_IOC_ENABLE, &mode) == 0);
    253   1.7  kamil 	ATF_CHECK(ioctl(fd, KCOV_IOC_DISABLE) == 0);
    254   1.7  kamil 	mode = KCOV_MODE_TRACE_CMP;
    255   1.7  kamil 	ATF_CHECK(ioctl(fd, KCOV_IOC_ENABLE, &mode) == 0);
    256   1.1  kamil 	ATF_CHECK(ioctl(fd, KCOV_IOC_DISABLE) == 0);
    257   1.1  kamil 
    258   1.1  kamil 	close(fd);
    259   1.1  kamil }
    260   1.1  kamil 
    261   1.1  kamil ATF_TC_WITHOUT_HEAD(kcov_enable_no_disable);
    262   1.1  kamil ATF_TC_BODY(kcov_enable_no_disable, tc)
    263   1.1  kamil {
    264   1.1  kamil 	int fd;
    265   1.5  kamil 	uint64_t size = PAGE_SIZE / KCOV_ENTRY_SIZE;
    266   1.7  kamil 	int mode;
    267   1.1  kamil 
    268   1.1  kamil 	fd = open_kcov();
    269   1.1  kamil 	ATF_REQUIRE(ioctl(fd, KCOV_IOC_SETBUFSIZE, &size) ==0);
    270   1.7  kamil 	mode = KCOV_MODE_NONE;
    271   1.7  kamil 	ATF_CHECK(ioctl(fd, KCOV_IOC_ENABLE, &mode) == 0);
    272   1.1  kamil 	close(fd);
    273   1.1  kamil }
    274   1.1  kamil 
    275   1.1  kamil ATF_TC_WITHOUT_HEAD(kcov_enable_no_disable_no_close);
    276   1.1  kamil ATF_TC_BODY(kcov_enable_no_disable_no_close, tc)
    277   1.1  kamil {
    278   1.1  kamil 	int fd;
    279   1.5  kamil 	uint64_t size = PAGE_SIZE / KCOV_ENTRY_SIZE;
    280   1.7  kamil 	int mode;
    281   1.1  kamil 
    282   1.1  kamil 	fd = open_kcov();
    283   1.1  kamil 	ATF_REQUIRE(ioctl(fd, KCOV_IOC_SETBUFSIZE, &size) ==0);
    284   1.7  kamil 	mode = KCOV_MODE_NONE;
    285   1.7  kamil 	ATF_CHECK(ioctl(fd, KCOV_IOC_ENABLE, &mode) == 0);
    286   1.1  kamil }
    287   1.1  kamil 
    288   1.1  kamil static void *
    289   1.8  kamil common_head_raw(bool fd_dup, int *fdp)
    290   1.1  kamil {
    291   1.1  kamil 	void *data;
    292   1.8  kamil 	int fd, fd2;
    293   1.5  kamil 	uint64_t size = PAGE_SIZE / KCOV_ENTRY_SIZE;
    294   1.1  kamil 
    295   1.1  kamil 	fd = open_kcov();
    296   1.1  kamil 
    297   1.8  kamil 	/* Test the dup2(2) trick used by syzkaller */
    298   1.8  kamil 	if (fd_dup) {
    299   1.8  kamil 		fd2 = pick_unassigned_fd(fd);
    300   1.8  kamil 		ATF_REQUIRE_EQ(dup2(fd, fd2), fd2);
    301   1.8  kamil 		close(fd);
    302   1.8  kamil 		fd = fd2;
    303   1.8  kamil 	}
    304   1.8  kamil 
    305   1.1  kamil 	ATF_REQUIRE_MSG(ioctl(fd, KCOV_IOC_SETBUFSIZE, &size) == 0,
    306   1.1  kamil 	    "Unable to set the kcov buffer size");
    307   1.1  kamil 
    308   1.1  kamil 	data = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    309   1.1  kamil 	ATF_REQUIRE_MSG(data != MAP_FAILED, "Unable to mmap the kcov buffer");
    310   1.1  kamil 
    311   1.1  kamil 	*fdp = fd;
    312   1.1  kamil 	return data;
    313   1.1  kamil }
    314   1.1  kamil 
    315   1.8  kamil static void *
    316   1.8  kamil common_head(int *fdp)
    317   1.8  kamil {
    318   1.8  kamil 
    319   1.8  kamil 	return common_head_raw(false, fdp);
    320   1.8  kamil }
    321   1.8  kamil 
    322   1.1  kamil static void
    323   1.1  kamil common_tail(int fd, kcov_int_t *data)
    324   1.1  kamil {
    325   1.1  kamil 
    326   1.1  kamil 	ATF_REQUIRE_MSG(munmap(__UNVOLATILE(data), PAGE_SIZE) == 0,
    327   1.1  kamil 	    "Unable to unmap the kcov buffer");
    328   1.1  kamil 
    329   1.1  kamil 	close(fd);
    330   1.1  kamil }
    331   1.1  kamil 
    332   1.7  kamil static void
    333   1.8  kamil kcov_basic(bool fd_dup, int mode)
    334   1.1  kamil {
    335   1.1  kamil 	kcov_int_t *buf;
    336   1.1  kamil 	int fd;
    337   1.1  kamil 
    338   1.8  kamil 	buf = common_head_raw(fd_dup, &fd);
    339   1.7  kamil 	ATF_REQUIRE_MSG(ioctl(fd, KCOV_IOC_ENABLE, &mode) == 0,
    340   1.1  kamil 	    "Unable to enable kcov ");
    341   1.1  kamil 
    342  1.10  kamil 	buf[0] = 0;
    343   1.1  kamil 
    344   1.7  kamil 	sleep(0); /* XXX: Is it enough for all trace types? */
    345  1.10  kamil 	ATF_REQUIRE_MSG(buf[0] != 0, "No records found");
    346   1.1  kamil 
    347   1.1  kamil 	ATF_REQUIRE_MSG(ioctl(fd, KCOV_IOC_DISABLE) == 0,
    348   1.1  kamil 	    "Unable to disable kcov");
    349   1.1  kamil 
    350   1.1  kamil 	common_tail(fd, buf);
    351   1.1  kamil }
    352   1.1  kamil 
    353   1.7  kamil ATF_TC_WITHOUT_HEAD(kcov_basic_pc);
    354   1.7  kamil ATF_TC_BODY(kcov_basic_pc, tc)
    355   1.7  kamil {
    356   1.7  kamil 
    357   1.8  kamil 	kcov_basic(false, KCOV_MODE_TRACE_PC);
    358   1.7  kamil }
    359   1.7  kamil 
    360   1.7  kamil ATF_TC_WITHOUT_HEAD(kcov_basic_cmp);
    361   1.7  kamil ATF_TC_BODY(kcov_basic_cmp, tc)
    362   1.7  kamil {
    363   1.7  kamil 
    364   1.7  kamil 	atf_tc_skip("XXX: GCC8 needed");
    365   1.7  kamil 
    366   1.8  kamil 	kcov_basic(false, KCOV_MODE_TRACE_CMP);
    367   1.8  kamil }
    368   1.8  kamil 
    369   1.8  kamil ATF_TC_WITHOUT_HEAD(kcov_basic_dup2_pc);
    370   1.8  kamil ATF_TC_BODY(kcov_basic_dup2_pc, tc)
    371   1.8  kamil {
    372   1.8  kamil 
    373   1.8  kamil 	kcov_basic(true, KCOV_MODE_TRACE_PC);
    374   1.8  kamil }
    375   1.8  kamil 
    376   1.8  kamil ATF_TC_WITHOUT_HEAD(kcov_basic_dup2_cmp);
    377   1.8  kamil ATF_TC_BODY(kcov_basic_dup2_cmp, tc)
    378   1.8  kamil {
    379   1.8  kamil 
    380   1.8  kamil 	atf_tc_skip("XXX: GCC8 needed");
    381   1.8  kamil 
    382   1.8  kamil 	kcov_basic(true, KCOV_MODE_TRACE_CMP);
    383   1.7  kamil }
    384   1.7  kamil 
    385   1.5  kamil ATF_TC_WITHOUT_HEAD(kcov_multienable_on_the_same_thread);
    386   1.5  kamil ATF_TC_BODY(kcov_multienable_on_the_same_thread, tc)
    387   1.5  kamil {
    388   1.5  kamil 	kcov_int_t *buf1, *buf2;
    389   1.5  kamil 	int fd1, fd2;
    390   1.7  kamil 	int mode;
    391   1.5  kamil 
    392   1.5  kamil 	buf1 = common_head(&fd1);
    393   1.5  kamil 	buf2 = common_head(&fd2);
    394   1.7  kamil 	mode = KCOV_MODE_NONE;
    395   1.7  kamil 	ATF_REQUIRE_MSG(ioctl(fd1, KCOV_IOC_ENABLE, &mode) == 0,
    396   1.5  kamil 	    "Unable to enable kcov");
    397   1.7  kamil 	ATF_REQUIRE_ERRNO(EBUSY, ioctl(fd2, KCOV_IOC_ENABLE, &mode) != 0);
    398   1.5  kamil 
    399   1.5  kamil 	ATF_REQUIRE_MSG(ioctl(fd1, KCOV_IOC_DISABLE) == 0,
    400   1.5  kamil 	    "Unable to disable kcov");
    401   1.5  kamil 
    402   1.5  kamil 	common_tail(fd1, buf1);
    403   1.5  kamil 	common_tail(fd2, buf2);
    404   1.5  kamil }
    405   1.5  kamil 
    406   1.5  kamil static void *
    407   1.5  kamil thread_buffer_access_test_helper(void *ptr)
    408   1.5  kamil {
    409   1.5  kamil 	kcov_int_t *buf = ptr;
    410   1.5  kamil 
    411   1.5  kamil 	/* Test mapped buffer access from a custom thread */
    412  1.10  kamil 	buf[0] = buf[0];
    413   1.5  kamil 
    414   1.5  kamil 	return NULL;
    415   1.5  kamil }
    416   1.5  kamil 
    417   1.5  kamil ATF_TC_WITHOUT_HEAD(kcov_buffer_access_from_custom_thread);
    418   1.5  kamil ATF_TC_BODY(kcov_buffer_access_from_custom_thread, tc)
    419   1.5  kamil {
    420   1.5  kamil 	pthread_t thread;
    421   1.5  kamil 	kcov_int_t *buf;
    422   1.5  kamil 	int fd;
    423   1.7  kamil 	int mode;
    424   1.5  kamil 
    425   1.5  kamil 	buf = common_head(&fd);
    426   1.5  kamil 
    427   1.7  kamil 	mode = KCOV_MODE_TRACE_PC;
    428   1.7  kamil 	ATF_REQUIRE_MSG(ioctl(fd, KCOV_IOC_ENABLE, &mode) == 0,
    429   1.5  kamil 	    "Unable to enable kcov ");
    430   1.5  kamil 
    431   1.5  kamil 	pthread_create(&thread, NULL, thread_buffer_access_test_helper,
    432   1.5  kamil 	    __UNVOLATILE(buf));
    433   1.5  kamil 	pthread_join(thread, NULL);
    434   1.5  kamil 
    435   1.5  kamil 	ATF_REQUIRE_MSG(ioctl(fd, KCOV_IOC_DISABLE) == 0,
    436   1.5  kamil 	    "Unable to disable kcov");
    437   1.5  kamil 
    438   1.5  kamil 	common_tail(fd, buf);
    439   1.5  kamil }
    440   1.5  kamil 
    441   1.1  kamil static void *
    442   1.1  kamil thread_test_helper(void *ptr)
    443   1.1  kamil {
    444   1.5  kamil 	volatile int i;
    445   1.1  kamil 
    446   1.5  kamil 	/* It does not matter what operation is in action. */
    447   1.5  kamil 	for (i = 0; i < 1000; i++) {
    448   1.5  kamil 		if (getpid() == 0)
    449   1.5  kamil 			break;
    450   1.5  kamil 	}
    451   1.1  kamil 
    452   1.1  kamil 	return NULL;
    453   1.1  kamil }
    454   1.1  kamil 
    455   1.1  kamil ATF_TC_WITHOUT_HEAD(kcov_thread);
    456   1.1  kamil ATF_TC_BODY(kcov_thread, tc)
    457   1.1  kamil {
    458   1.1  kamil 	pthread_t thread;
    459   1.1  kamil 	kcov_int_t *buf;
    460   1.1  kamil 	int fd;
    461   1.7  kamil 	int mode;
    462   1.5  kamil 	volatile int i;
    463   1.1  kamil 
    464   1.1  kamil 	buf = common_head(&fd);
    465   1.1  kamil 
    466   1.7  kamil 	mode = KCOV_MODE_TRACE_PC;
    467   1.7  kamil 	ATF_REQUIRE_MSG(ioctl(fd, KCOV_IOC_ENABLE, &mode) == 0,
    468   1.1  kamil 	    "Unable to enable kcov ");
    469   1.1  kamil 
    470   1.5  kamil 	/* The thread does something, does not matter what exactly. */
    471   1.1  kamil 	pthread_create(&thread, NULL, thread_test_helper, __UNVOLATILE(buf));
    472   1.5  kamil 
    473  1.10  kamil 	buf[0] = 0;
    474   1.5  kamil 	for (i = 0; i < 10000; i++)
    475   1.5  kamil 		continue;
    476  1.10  kamil 	ATF_REQUIRE_EQ_MSG(buf[0], 0,
    477   1.5  kamil 	    "Records changed in blocked thread");
    478   1.5  kamil 
    479   1.1  kamil 	pthread_join(thread, NULL);
    480   1.1  kamil 
    481   1.5  kamil 	ATF_REQUIRE_EQ_MSG(ioctl(fd, KCOV_IOC_DISABLE), 0,
    482   1.5  kamil 	    "Unable to disable kcov");
    483   1.5  kamil 
    484   1.5  kamil 	common_tail(fd, buf);
    485   1.5  kamil }
    486   1.5  kamil 
    487   1.5  kamil static void *
    488   1.5  kamil multiple_threads_helper(void *ptr __unused)
    489   1.5  kamil {
    490   1.5  kamil 	kcov_int_t *buf;
    491   1.5  kamil 	int fd;
    492   1.7  kamil 	int mode;
    493   1.5  kamil 
    494   1.5  kamil 	buf = common_head(&fd);
    495   1.7  kamil 	mode = KCOV_MODE_TRACE_PC;
    496   1.7  kamil 	ATF_REQUIRE_MSG(ioctl(fd, KCOV_IOC_ENABLE, &mode) == 0,
    497   1.5  kamil 	    "Unable to enable kcov ");
    498   1.5  kamil 
    499  1.10  kamil 	buf[0] = 0;
    500   1.5  kamil 
    501   1.5  kamil 	sleep(0);
    502  1.10  kamil 	ATF_REQUIRE_MSG(buf[0] != 0, "No records found");
    503   1.5  kamil 
    504   1.1  kamil 	ATF_REQUIRE_MSG(ioctl(fd, KCOV_IOC_DISABLE) == 0,
    505   1.1  kamil 	    "Unable to disable kcov");
    506   1.1  kamil 
    507   1.1  kamil 	common_tail(fd, buf);
    508   1.5  kamil 
    509   1.5  kamil 	return NULL;
    510   1.1  kamil }
    511   1.1  kamil 
    512   1.5  kamil static void
    513   1.5  kamil kcov_multiple_threads(size_t N)
    514   1.5  kamil {
    515   1.5  kamil 	pthread_t thread[32];
    516   1.5  kamil 	size_t i;
    517   1.9  kamil 	int fd;
    518   1.9  kamil 
    519   1.9  kamil 	/*
    520   1.9  kamil 	 * Check if /dev/kcov is available, if not bail out.
    521   1.9  kamil 	 * Verifying it on a per-thread basis is flaky.
    522   1.9  kamil 	 */
    523   1.9  kamil 	fd = open_kcov();
    524   1.9  kamil 	ATF_REQUIRE(close(fd) == 0);
    525   1.5  kamil 
    526   1.5  kamil 	ATF_REQUIRE(__arraycount(thread) >= N);
    527   1.5  kamil 
    528   1.6  kamil 	for (i = 0; i < N; i++)
    529   1.5  kamil 		pthread_create(&thread[i], NULL, multiple_threads_helper, NULL);
    530   1.5  kamil 
    531   1.6  kamil 	for (i = 0; i < N; i++)
    532   1.5  kamil 		pthread_join(thread[i], NULL);
    533   1.5  kamil }
    534   1.5  kamil 
    535   1.5  kamil #define KCOV_MULTIPLE_THREADS(n)		\
    536   1.5  kamil ATF_TC_WITHOUT_HEAD(kcov_multiple_threads##n);	\
    537   1.5  kamil ATF_TC_BODY(kcov_multiple_threads##n, tc)	\
    538   1.5  kamil {						\
    539   1.5  kamil 						\
    540   1.5  kamil 	kcov_multiple_threads(n);		\
    541   1.5  kamil }
    542   1.5  kamil 
    543   1.5  kamil KCOV_MULTIPLE_THREADS(2)
    544   1.5  kamil KCOV_MULTIPLE_THREADS(4)
    545   1.5  kamil KCOV_MULTIPLE_THREADS(8)
    546   1.5  kamil KCOV_MULTIPLE_THREADS(16)
    547   1.5  kamil KCOV_MULTIPLE_THREADS(32)
    548   1.5  kamil 
    549   1.1  kamil ATF_TP_ADD_TCS(tp)
    550   1.1  kamil {
    551   1.1  kamil 
    552   1.8  kamil 	ATF_TP_ADD_TC(tp, kcov_dup2);
    553   1.5  kamil 	ATF_TP_ADD_TC(tp, kcov_multiopen);
    554   1.5  kamil 	ATF_TP_ADD_TC(tp, kcov_open_close_open);
    555   1.1  kamil 	ATF_TP_ADD_TC(tp, kcov_bufsize);
    556   1.1  kamil 	ATF_TP_ADD_TC(tp, kcov_mmap);
    557   1.1  kamil 	ATF_TP_ADD_TC(tp, kcov_mmap_no_munmap);
    558   1.1  kamil 	ATF_TP_ADD_TC(tp, kcov_mmap_no_munmap_no_close);
    559   1.1  kamil 	ATF_TP_ADD_TC(tp, kcov_enable);
    560   1.1  kamil 	ATF_TP_ADD_TC(tp, kcov_enable_no_disable);
    561   1.1  kamil 	ATF_TP_ADD_TC(tp, kcov_enable_no_disable_no_close);
    562   1.1  kamil 	ATF_TP_ADD_TC(tp, kcov_mmap_enable_thread_close);
    563   1.7  kamil 	ATF_TP_ADD_TC(tp, kcov_basic_pc);
    564   1.7  kamil 	ATF_TP_ADD_TC(tp, kcov_basic_cmp);
    565   1.8  kamil 	ATF_TP_ADD_TC(tp, kcov_basic_dup2_pc);
    566   1.8  kamil 	ATF_TP_ADD_TC(tp, kcov_basic_dup2_cmp);
    567   1.5  kamil 	ATF_TP_ADD_TC(tp, kcov_multienable_on_the_same_thread);
    568   1.5  kamil 	ATF_TP_ADD_TC(tp, kcov_buffer_access_from_custom_thread);
    569   1.1  kamil 	ATF_TP_ADD_TC(tp, kcov_thread);
    570   1.5  kamil 	ATF_TP_ADD_TC(tp, kcov_multiple_threads2);
    571   1.5  kamil 	ATF_TP_ADD_TC(tp, kcov_multiple_threads4);
    572   1.5  kamil 	ATF_TP_ADD_TC(tp, kcov_multiple_threads8);
    573   1.5  kamil 	ATF_TP_ADD_TC(tp, kcov_multiple_threads16);
    574   1.5  kamil 	ATF_TP_ADD_TC(tp, kcov_multiple_threads32);
    575   1.1  kamil 	return atf_no_error();
    576   1.1  kamil }
    577