Dtrace oddity
Christopher Bowman
crb at chrisbowman.com
Tue Apr 11 07:17:02 UTC 2017
Apologies if I’m sending to the wrong list. I have a small test program shown at the bottom. It tries to mmap a device for which I’ve written (a possibly incorrect) driver. When I run the program I get the following output:
crb at retread:63> ./test /dev/sp6050
argc = 2
argv[0] = ./test
argv[1] = /dev/sp6050
opening device /dev/sp6050
open returned non-zero value
mmap failed: EINVAL
The man page lists a bunch of reasons for EINVAL so I want to investigate this and I don’t quite know good strategies to debug the kernel (yet) so I thought I’d experiment with Dtrace a bit. Here is the oddity: when I run Dtrace and then run my test program I get the following output from Dtrace:
crb at retread:60> dtrace -n 'syscall:freebsd:mmap:entry /execname == "test"/ {}'
dtrace: description 'syscall:freebsd:mmap:entry ' matched 1 probe
CPU ID FUNCTION:NAME
0 63401 mmap:entry
0 63401 mmap:entry
0 63401 mmap:entry
0 63401 mmap:entry
0 63401 mmap:entry
0 63401 mmap:entry
0 63401 mmap:entry
0 63401 mmap:entry
0 63401 mmap:entry
0 63401 mmap:entry
0 63401 mmap:entry
0 63401 mmap:entry
I think Dtrace is indicating that the mmap syscall was called 12 times by my test program yet I can see how the program below would have done that.
Here is my program:
/*
Copyright (c) 2011 by Christopher R. Bowman. All rights reserved.
*/
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
int main (int argc, char ** argv) {
int i;
printf("argc = %d\n", argc);
for (i=0; i < argc; i++)
printf ("argv[%i] = %s\n", i, argv[i]);
if (argc < 2) {
printf("usage: test device\n");
return 0;
}
printf("opening device %s\n", argv[1]);
int device = open (argv[1], O_RDWR);
if (device == 0) {
printf ("open of device %s failed\n", argv[1]);
return 0;
}
printf("open returned non-zero value\n");
void *pa = mmap (0, 4095, PROT_READ | PROT_WRITE, 0, device, 0);
if (pa == MAP_FAILED) {
printf ("mmap failed: ");
switch (errno) {
case EACCES: printf("EACCESS\n"); break;
case EBADF: printf("EBADF\n"); break;
case EINVAL: printf("EINVAL\n"); break;
case ENODEV: printf("ENODEV\n"); break;
case ENOMEM: printf("ENOMEM\n"); break;
}
return 0;
}
printf("mmap returned non-zero value: %lx\n", (unsigned long)pa);
unsigned int *p = (unsigned int *) pa;
unsigned char *c = (unsigned char *) pa;
#define NUM_ITERATIONS 16
for (i=0; i < NUM_ITERATIONS; i++){ //BARs are 2Kbytes
//*p++ = (0xa5a5 + i);
*p++ = (0x5aa5a5a5);
}
p = (unsigned int *) pa;
for (i=0; i < NUM_ITERATIONS; i++){
printf("i = %d, read_val = %x\n", i, *p++);
}
}
Thanks in advance for comments on Dtrace or perhaps program corrections or ideas why the mmap failed or places to read on kernel debugging or pointers to a better list to which to send this.
Thanks
Christopher
More information about the freebsd-hackers
mailing list