Examining mmaped addresses using GDB

后端 未结 7 1925
[愿得一人]
[愿得一人] 2020-12-13 21:19

I\'m using the driver I posted at 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;

相关标签:
7条回答
  • 2020-12-13 21:25

    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.

    0 讨论(0)
  • 2020-12-13 21:37

    To access the mmapped memory, GDB will call ptrace, which will then call __access_remote_vm() to access the mmapped memory. If the memory is mapped with flags such as VMIO | VM_PFNMAP (for example, remap_pfn_range() sets them), GDB will access the memory though vm's access method defined by users.

    Instead of writing our own implementation for access(), kernel already provides a generic version called generic_access_phys(), and this method could be easily linked via vm_operations_struct as the /dev/mem device did:

    static const struct vm_operations_struct mmap_mem_ops = {
            .access = generic_access_phys };
    
    int mmap_mem()
    {
        .... ....
        vma->vm_ops = &mmap_mem_ops;
        .... ....
    }
    
    0 讨论(0)
  • 2020-12-13 21:42

    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
    
    0 讨论(0)
  • 2020-12-13 21:43

    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;
    }
    
    0 讨论(0)
  • 2020-12-13 21:45

    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.

    0 讨论(0)
  • 2020-12-13 21:49

    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'
    
    0 讨论(0)
提交回复
热议问题