tags:

views:

1163

answers:

5

I'm using the driver I posted at http://stackoverflow.com/questions/647783/direct-memory-access-in-linux/ to mmap some physical ram into a userspace address. However, I can't use GDB to look at any of the address; i.e., x 0x12345678 (where 0x12345678 is the return value of mmap) fails with an error "Cannot access memory at address 0x12345678".

Is there any way to tell GDB that this memory can be viewed? Alternatively, is there something different I can do in the mmap (either the call or the implementation of foo_mmap there) that will allow it to access this memory?

Note that I'm not asking about /dev/mem (as in the first snippet there) but amount a mmap to memory acquired via ioremap(), virt_to_phys() and remap_pfn_range()

A: 

I think that if that memory is not accessible by GDB then it is not mapped into your process address space and so you get "Cannot access memory at addresss 0x12345678". If that application were run normally you would get a segmentation fault. Also, maybe your driver is screwed and you should check you actually can access the memory from within the kernel. Try with example here:

#include <cstdio>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>

int main() {
    int fd = open("/dev/zero", O_RDONLY);
    void* addr = mmap(NULL, 1024, PROT_READ, MAP_PRIVATE, fd, 0);
    for (int x = 0; x < 10; x++) {
        printf("%X\n", ((char*)addr)[x]);
    }
    close(fd);
    return 0;
}
kyku
Nope, the mmap succeeded, and a printf on the next line successfully reads the variable.
Mikeage
Could you provide current sources of your code?
kyku
See the linked question; not the first little snippet, but the long module and short user space application.Note that in the module, I added virt_to_phys(pt) >> PAGE_SHIFT as suggested in the comments.
Mikeage
+2  A: 

It is my understanding that GDB will be using ptrace to poke around in your process's memory. Perhaps you should write a simple program that just attaches to your process and uses ptrace to read from that memory. This might help narrow down what the underlying problem is. If that has no issues, then you know either I'm wrong :), or something else fishy is happening with GDB.

Logan Capaldo
GDB does use ptrace, and ptrace calls GDB uses must be failing for some reason. The simplest way to prove that's what's happening is to run GDB under strace.I am pretty sure the problem is that the kernel driver doesn't implement ptrace support properly (or at all).
Employed Russian
probably not; I wrote the kernel module :)What do I have to do to make sure ptrace works? You can see the sources in the linked question.
Mikeage
+4  A: 

I believe Linux does not make I/O memory accessible via ptrace(). You could write a function that simply reads the mmap'ed address and have gdb invoke it. Here's a slightly modified version of your foo-user.c program along with the output from a gdb session.

#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/mman.h>

char *mptr;

char peek(int offset)
{
    return mptr[offset];
}

int main(void)
{
    int fd;
    fd = open("/dev/foo", O_RDWR | O_SYNC);
    if (fd == -1) {
        printf("open error...\n");
        return 1;
    }
    mptr = mmap(0, 1 * 1024 * 1024, PROT_READ | PROT_WRITE,
             MAP_FILE | MAP_SHARED, fd, 4096);
    printf("On start, mptr points to 0x%lX.\n", (unsigned long) mptr);
    printf("mptr points to 0x%lX. *mptr = 0x%X\n", (unsigned long) mptr,
           *mptr);
    mptr[0] = 'a';
    mptr[1] = 'b';
    printf("mptr points to 0x%lX. *mptr = 0x%X\n", (unsigned long) mptr,
           *mptr);
    close(fd);
    return 0;
}



$ make foo-user CFLAGS=-g
$ gdb -q foo-user
(gdb) break 27
Breakpoint 1 at 0x804855f: file foo-user.c, line 27.
(gdb) run
Starting program: /home/me/foo/foo-user 
On start, mptr points to 0xB7E1E000.
mptr points to 0xB7E1E000. *mptr = 0x61

Breakpoint 1, main () at foo-user.c:27
27          mptr[0] = 'a';
(gdb) n
28          mptr[1] = 'b';
(gdb) print peek(0)
$1 = 97 'a'
(gdb) print peek(1)
$2 = 98 'b'
sigjuice
Good idea. I was hoping to avoid this (core dumps, identical use of the debugger whether or not the module is used (or even if we're using linux)), but this might be the only possible option. If I can't find a way to get ptrace to work, I'll accept this solution.
Mikeage
+1  A: 

you go "info files"

(gdb) help info files
Names of targets and files being debugged.
Shows the entire stack of targets currently in use (including the exec-file,
core-file, and process, if any), as well as the symbol file name.
(gdb) info files
Symbols from "/bin/ls".
Unix child process:
        Using the running image of child Thread 4160418656 (LWP 10729).
        While running this, GDB does not access memory from...
Local exec file:
        `/bin/ls', file type elf32-powerpc.
        Entry point: 0x10002a10
        0x10000134 - 0x10000141 is .interp
        0x10000144 - 0x10000164 is .note.ABI-tag
        0x10000164 - 0x100008f8 is .gnu.hash
        0x100008f8 - 0x10001728 is .dynsym
        0x10001728 - 0x100021f3 is .dynstr
        0x100021f4 - 0x100023ba is .gnu.version
...
        0x0ffa8300 - 0x0ffad8c0 is .text in /lib/libacl.so.1
        0x0ffad8c0 - 0x0ffad8f8 is .fini in /lib/libacl.so.1
        0x0ffad8f8 - 0x0ffadbac is .rodata in /lib/libacl.so.1
        0x0ffadbac - 0x0ffadd58 is .eh_frame_hdr in /lib/libacl.so.1
        0x0ffadd58 - 0x0ffae4d8 is .eh_frame in /lib/libacl.so.1
        0x0ffbe4d8 - 0x0ffbe4e0 is .ctors in /lib/libacl.so.1
        0x0ffbe4e0 - 0x0ffbe4e8 is .dtors in /lib/libacl.so.1
...

(gdb) info sh
From        To          Syms Read   Shared Object Library
0xf7fcf960  0xf7fe81a0  Yes         /lib/ld.so.1
0x0ffd0820  0x0ffd5d10  Yes         /lib/librt.so.1
0x0ffa8300  0x0ffad8c0  Yes         /lib/libacl.so.1
0x0ff6a840  0x0ff7f4f0  Yes         /lib/libselinux.so.1
0x0fdfe920  0x0ff1ae70  Yes         /lib/libc.so.6
0x0fda23d0  0x0fdb0db0  Yes         /lib/libpthread.so.0

Failing this, you can use "mem" to configure memory ranges.

(gdb) mem 1 1414
(gdb) info mem
Num Enb Low Addr   High Addr  Attrs
1   y   0x00000001 0x00000586 rw nocache
(gdb) disable mem 1
(gdb) info mem
Num Enb Low Addr   High Addr  Attrs
1   n   0x00000001 0x00000586 rw nocache
RandomNickName42
A: 

If you open an AF_PACKET socket and mmap it, gdb can't access this memory. So there isn't a problem with your driver. It's either a problem with ptrace or with gdb.

Unai Uribarri