سؤال

وأنا باستخدام برنامج تشغيل نشرت لي في الوصول المباشر إلى الذاكرة في لينكس لmmap بعض كبش المادي إلى عنوان مساحة المستخدم. ومع ذلك، لا يمكنني استخدام GDB للنظر في أي من العنوان؛ أي س 0x12345678 (حيث 0x12345678 هو قيمة الإرجاع mmap) يفشل مع وجود خطأ "لا يمكن الوصول إلى الذاكرة في عنوان 0x12345678".

هل هناك أي طريقة لمعرفة GDB أن هذه الذاكرة ويمكن الاطلاع؟ بدلا من ذلك، هناك شيء مختلف يمكن أن أفعله في mmap (إما المكالمة أو تنفيذ foo_mmap هناك) من شأنها أن تسمح لها بالحصول على هذه الذاكرة؟

ملاحظة أنني لا يسأل عن / ديف / الفنزويلية (كما في المقتطف الأول هناك) ولكن عن mmap إلى الذاكرة المكتسبة عبر ioremap ()، virt_to_phys () وremap_pfn_range ()

هل كانت مفيدة؟

المحلول

وأعتقد أن لينكس لا يجعل I / O الذاكرة يمكن الوصول إليها عبر ptrace (). هل يمكن كتابة دالة الذي يقرأ ببساطة عنوان mmap'ed ووجدب الاحتجاج عليه. وفيما يلي نسخة معدلة بشكل طفيف من برنامج فو user.c الخاص جنبا إلى جنب مع الإخراج من جلسة جدب.

#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'

نصائح أخرى

ولدي الإجابة على اللغز الخاص بك :) لقد فتشت في كل مكان على الانترنت دون الكثير من المساعدة وأخيرا تصحيحه بنفسي.

وكانت هذه آخر نقطة انطلاق جيدة بالنسبة لي. كنت أرغب في تحقيق شيء في خطوط مماثلة، وأنا نفذت سائق شار مع MMAP إلى خريطة عادتي ذاكرة تمكن من عملية مساحة المستخدم. عند استخدام GDB، ptrace نظرة خاطفة تدعو access_process_vm () للوصول إلى أي ذاكرة في VMA الخاص بك. هذا يؤدي إلى خطأ EIO منذ وصول عامة لا يمكن الحصول على السلطة الفلسطينية من الذاكرة الخاصة بك. كما تبين، لديك لتنفيذ وظيفة الوصول لهذه الذاكرة من خلال تنفيذ .access من vm_operations_struct VMA الخاص بك. فيما يلي مثال:

//Below code needs to be implemented by your driver:
static struct vm_operations_struct custom_vm_ops = {
    .access = custom_vma_access,
};

static inline int custom_vma_access(struct vm_area_struct *vma, unsigned long addr,
          void *buf, int len, int write)
{
    return custom_generic_access_phys(vma, addr, buf, len, write);
}

static int custom_generic_access_phys(struct vm_area_struct *vma, unsigned long addr,
            void *buf, int len, int write)
{
    void __iomem *maddr;
    //int offset = (addr & (PAGE_SIZE-1)) - vma->vm_start;
    int offset = (addr) - vma->vm_start;

    maddr = phys_to_virt(__pa(custom_mem_VA));
    if (write)
        memcpy_toio(maddr + offset, buf, len);
    else
        memcpy_fromio(buf, maddr + offset, len);

    return len;
}

ووأفهم أن GDB سوف تستخدم ptrace لكزة حول في ذكرى عملية الخاص بك. ربما يجب عليك كتابة برنامج بسيط هو أن تعلق فقط لعملية ويستخدم ptrace القراءة من تلك الذاكرة. وهذا قد يساعد تضييق ما هي المشكلة الأساسية. وإذا كان هذا لا يوجد لديه مشاكل، ثم تعرف إما أنا :) الخطأ، أو أي شيء آخر مريب يحدث مع GDB.

وتذهب "معلومات ملفات"

(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

وإذا تعذر ذلك، يمكنك استخدام "ذاكرة" لتكوين نطاقات الذاكرة.

(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

لالوصول إلى الذاكرة mmapped، سوف GDB استدعاء ptrace، والتي سوف ثم استدعاء __access_remote_vm () للوصول إلى الذاكرة mmapped. إذا تم تعيين الذاكرة مع الأعلام مثل VMIO | VM_PFNMAP (على سبيل المثال، remap_pfn_range () يحدد لهم)، GDB سيتم الوصول إلى الذاكرة على الرغم من أسلوب الوصول VM في تعريفها من قبل المستخدمين.

وبدلا من كتابة التنفيذ الخاصة بنا من أجل الوصول ()، نواة يوفر بالفعل إصدار عام دعا generic_access_phys ()، وهذه الطريقة يمكن أن تكون مرتبطة بسهولة عبر vm_operations_struct كما فعل الجهاز / ديف / الفنزويلية:

static const struct vm_operations_struct mmap_mem_ops = {
        .access = generic_access_phys };

int mmap_mem()
{
    .... ....
    vma->vm_ops = &mmap_mem_ops;
    .... ....
}

وأعتقد أنه إذا أن الذاكرة لا يمكن الوصول إليها من قبل GDB ثم لم يتم تعيينه في مساحة عنوان العملية وحتى تحصل على "لا يمكن الوصول إلى الذاكرة في 0x12345678 معالجة مشكلة". إذا تم تشغيل هذا التطبيق عادة سوف تحصل على خطأ تجزئة. أيضا، ربما هو مشدود السائق الخاص بك ويجب عليك مراجعة كنت في الواقع يمكن الوصول إلى الذاكرة من داخل النواة. محاولة مع مثال هنا:

#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;
}

إذا فتح مقبس AF_PACKET وmmap ذلك، جدب لا يمكن الوصول إلى هذه الذاكرة. لذلك ليس هناك مشكلة مع برنامج التشغيل الخاص بك. انها إما مشكلة مع ptrace أو مع جدب.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top