/* get_coverage - program to get coverage informations from Xen * * Copyright (C) 2013 - Citrix Systems * ----- * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include #include typedef struct privcmd_hypercall { uint64_t op; uint64_t arg[5]; } privcmd_hypercall_t; #define IOCTL_PRIVCMD_HYPERCALL \ _IOC(_IOC_NONE, 'P', 0, sizeof(privcmd_hypercall_t)) #define PAGE_SIZE 4096u static int privcmd_fd = -1; int get_gcov_info(int op, void *ptr) { privcmd_hypercall_t hc[1]; int ret; hc->op = 40; // TODO hc->arg[0] = op; hc->arg[1] = (intptr_t) ptr; ret = ioctl(privcmd_fd, IOCTL_PRIVCMD_HYPERCALL, hc); if (ret >= 0) return ret; return -errno; } int main(void) { // open priv command privcmd_fd = open("/proc/xen/privcmd", O_RDWR); if (privcmd_fd < 0) err(1, "opening privcmd"); // check support if (get_gcov_info(0, NULL) < 0) err(1, "checking coverage support"); // allocate uint8_t *p = mmap(0, PAGE_SIZE, PROT_WRITE|PROT_READ, MAP_PRIVATE|MAP_ANON|MAP_LOCKED, -1, 0); if (p == (uint8_t *) -1) err(1, "allocating memory"); // get total length uint32_t *ui = (uint32_t *) p; *ui = 0; if (get_gcov_info(1, ui) < 0) err(1, "getting total length"); printf("returned %u bytes\n", (unsigned) *ui); // safe check uint32_t total_len = *ui; if (total_len > 16u * 1024u * 1024u) errx(1, "coverage size too big %u bytes\n", total_len); // reallocate munmap(p, PAGE_SIZE); size_t size = total_len + PAGE_SIZE; size -= (size % PAGE_SIZE); p = mmap(0, size, PROT_WRITE|PROT_READ, MAP_PRIVATE|MAP_ANON|MAP_LOCKED, -1, 0); if (p == (uint8_t *) -1) err(1, "mapping memory for coverage"); // get data if (get_gcov_info(2, p) < 0) err(1, "getting coverage information"); // write to a file FILE *f = fopen("gcda.dat", "w"); if (!f) err(1, "opening output file"); if (fwrite(p, 1, total_len, f) != total_len) err(1, "writing coverage to file"); fclose(f); return 0; }