main()中的GDB断点无法访问内存 [英] GDB breakpoint in main() cannot access memory

查看:309
本文介绍了main()中的GDB断点无法访问内存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题是为什么当我在main()中用GDB设置一个断点时,我收到错误

 < 0xffffffffffffe550:无法访问地址0xffffffffffffe550处的内存> 

我想在main()中设置一个断点,以便检查堆栈中的内存。我的反汇编代码是这样的:

  0x00000000004008e8< + 0> ;: push%rbp 
0x00000000004008e9< + 1> :mov%rsp,%rbp
0x00000000004008ec< + 4> ;: add $ 0xffffffffffffff80,%rsp
0x00000000004008f0< + 8> ;: mov%edi,-0x74(%rbp)
0x00000000004008f3 < + 11>:mov%rsi,-0x80(%rbp)
=> 0x00000000004008f7< + 15> ;: movl $ 0x1,-0x4(%rbp)
0x00000000004008fe< + 22> ;: cmpl $ 0x1,-0x74(%rbp)
0x0000000000400902< + 26> ;: jle 0x400920< main + 56>
0x0000000000400904< + 28> ;: mov -0x80(%rbp),%rax
0x0000000000400908< + 32> ;: add $ 0x8,%rax
0x000000000040090c< + 36> ;: mov (%rax),%rdx
0x000000000040090f +39:lea -0x70(%rbp),%rax
0x0000000000400913< + 43> ;: mov%rdx,%rsi
0x0000000000400916 < + 46> ;: mov%rax,%rdi
0x0000000000400919< + 49> ;: callq 0x400670< strcpy @ plt>
0x000000000040091e< + 54> ;: jmp 0x400924< main + 60>
0x0000000000400920< + 56> ;: movb $ 0x0,-0x70(%rbp)
0x0000000000400924< + 60> ;: callq 0x4006a0< getuid @ plt>
0x0000000000400929< + 65>:mov%eax,-0x8(%rbp)
0x000000000040092c< + 68> ;: mov $ 0x0,%esi
0x0000000000400931< + 73> ;: mov $ 0x400c6e,%edi
0x0000000000400936< + 78> ;: mov $ 0x0,%eax
0x000000000040093b< + 83> ;: callq 0x400720< open @ plt>
0x0000000000400940 <+ 88>:mov%eax,-0xc(%rbp)
0x0000000000400943< + 91> ;: cmpl $ 0xffffffff,-0xc(%rbp)
0x0000000000400947< 95>:jne 0x40096b< main + 131>
0x0000000000400949< + 97> ;: mov $ 0x400c80,%edi
0x000000000040094e< + 102> ;: callq 0x400856< fatal>
0x0000000000400953< + 107> ;: jmp 0x40096b< main + 131>
0x0000000000400955 <+ 109>:lea -0x70(%rbp),%rdx
0x0000000000400959< + 113> ;: mov -0x8(%rbp),%ecx
0x000000000040095c< 116> ;: mov_0xc(%rbp),%eax
0x000000000040095f< + 119> ;: mov%ecx,%esi
0x0000000000400961< + 121> ;: mov%eax,%edi
0x0000000000400963< + 123> ;: callq 0x40098c< print_notes>
0x0000000000400968 <+ 128>:mov%eax,-0x4(%rbp)
0x000000000040096b< + 131> ;: cmpl $ 0x0,-0x4(%rbp)
0x000000000040096f< 135>:jne 0x400955< main + 109>
0x0000000000400971< + 137> ;: mov $ 0x400cb0,%edi
0x0000000000400976< + 142> ;: callq 0x400680< puts @ plt>
0x000000000040097b< + 147> ;: mov -0xc(%rbp),%eax
0x000000000040097e< + 150> ;: mov%eax,%edi
0x0000000000400980< + 152> ;: callq 0x4006e0< close @ plt>
0x0000000000400985< + 157> ;: mov $ 0x0,%eax
0x000000000040098a< + 162> ;: leaveq
0x000000000040098b< + 163> ;: retq


 

$ c> #include< stdio.h>
#include< fcntl.h>
#include< string.h>
#include< stdlib.h>
#include< unistd.h>
#includeusefullfuncs.h

#define FILENAME/ var / notes

int print_notes(int,int,char *);
int find_user_note(int,int);
int search_note(char *,char *);

int main(int argc,char * argv []){
int userid,printing = 1,fd;
char searchstring [100];

if(argc> 1)
strcpy(searchstring,argv [1]);
else
searchstring [0] = 0;

userid = getuid();

fd = open(FILENAME,O_RDONLY);
if(fd == -1)
fatal(在打开文件时在main()中读取);

while(printing)
printing = print_notes(fd,userid,searchstring);
printf(------- [笔记数据结束] ------- \\\
);
close(fd);


int print_notes(int fd,int uid,char * searchstring){
int note_lenght;
char note_buffer [100];

note_lenght = find_user_note(fd,uid);

if(note_lenght == -1)
return 0;

read(fd,note_buffer,note_lenght);
note_buffer [note_lenght] = 0;

if(search_note(note_buffer,searchstring))
printf(note_buffer);
返回1;
}

int find_user_note(int fd,int user_uid){
int note_uid = -1;
unsigned char byte;
int lenght; (note_uid!= user_uid){
if(read(fd,& note_uid,4)!= 4)
返回-1;
if(read(fd,& byte,1)!= 1)
return -1;

byte = lenght = 0;

while(byte!='\ n'){
if(read(fd,&byte; 1)!= 1)
return -1;
lenght ++;
}
}

lseek(fd,lenght * -1,SEEK_CUR);

printf([DEBUG]为用户标识%d \\\
找到了%d字节的注释,lenght,note_uid);
return lenght;
}

int search_note(char * note,char * keyword){
int i,keyword_lenght,match = 0;

keyword_lenght = strlen(keyword);

if(keyword_lenght == 0)
return 1;

for(i = 0; i< strlen(note); i ++){
if(note [i] == keyword [match])
match ++;
else {
if(note [i] == keyword [0])
match = 1;
else
match = 0;
}
if(match == keyword_lenght)
return 1;
}
返回0;
}

预先致谢

解决方案

 (gdb)x / 24s $ esp 
0xffffffffffffe550:< error:Can not access memory at address 0xffffffffffffe550>

在x86-64目标上, $ rsp 应该被使用。使用 $ esp 会导致错误的结果。

$ esp 取自64位 $ rsp 寄存器的低32位,gdb将其视为类型 int32_t 。在你的例子中 $ rsp 可能是 0x7fffffffe550 。 Gdb的 x 命令要使用64位地址,它将采用 $ rsp 的低32位, 0xffffe550 ,并将其扩展为 0xffffffffffffe550 。这几乎肯定是一个无效的地址; Linux上的典型用户空间地址不会超过 0x7ffffffff000 左右。



尝试 x / 24s $ rsp 。如果您试图从旧书中学习练习,那么您可以通过给gcc -m32 选项来复制他们的32位示例,如果它支持它。然后你可以使用 $ esp


My question is why when i set a breakpoint in main() with GDB i receive the error

    <0xffffffffffffe550: Cannot access memory at address 0xffffffffffffe550>

I wanted to set a breakpoint in main() so i could examine the memory in the stack. My disassembled code is this:

0x00000000004008e8 <+0>:     push   %rbp
0x00000000004008e9 <+1>:     mov    %rsp,%rbp
0x00000000004008ec <+4>:     add    $0xffffffffffffff80,%rsp
0x00000000004008f0 <+8>:     mov    %edi,-0x74(%rbp)
0x00000000004008f3 <+11>:    mov    %rsi,-0x80(%rbp)
=>  0x00000000004008f7 <+15>:    movl   $0x1,-0x4(%rbp)
0x00000000004008fe <+22>:    cmpl   $0x1,-0x74(%rbp)
0x0000000000400902 <+26>:    jle    0x400920 <main+56>
0x0000000000400904 <+28>:    mov    -0x80(%rbp),%rax
0x0000000000400908 <+32>:    add    $0x8,%rax
0x000000000040090c <+36>:    mov    (%rax),%rdx
0x000000000040090f <+39>:    lea    -0x70(%rbp),%rax
0x0000000000400913 <+43>:    mov    %rdx,%rsi
0x0000000000400916 <+46>:    mov    %rax,%rdi
0x0000000000400919 <+49>:    callq  0x400670 <strcpy@plt>
0x000000000040091e <+54>:    jmp    0x400924 <main+60>
0x0000000000400920 <+56>:    movb   $0x0,-0x70(%rbp)
0x0000000000400924 <+60>:    callq  0x4006a0 <getuid@plt>
0x0000000000400929 <+65>:    mov    %eax,-0x8(%rbp)
0x000000000040092c <+68>:    mov    $0x0,%esi
0x0000000000400931 <+73>:    mov    $0x400c6e,%edi
0x0000000000400936 <+78>:    mov    $0x0,%eax
0x000000000040093b <+83>:    callq  0x400720 <open@plt>
0x0000000000400940 <+88>:    mov    %eax,-0xc(%rbp)
0x0000000000400943 <+91>:    cmpl   $0xffffffff,-0xc(%rbp)
0x0000000000400947 <+95>:    jne    0x40096b <main+131>
0x0000000000400949 <+97>:    mov    $0x400c80,%edi
0x000000000040094e <+102>:   callq  0x400856 <fatal>
0x0000000000400953 <+107>:   jmp    0x40096b <main+131>
0x0000000000400955 <+109>:   lea    -0x70(%rbp),%rdx
0x0000000000400959 <+113>:   mov    -0x8(%rbp),%ecx
0x000000000040095c <+116>:   mov    -0xc(%rbp),%eax
0x000000000040095f <+119>:   mov    %ecx,%esi
0x0000000000400961 <+121>:   mov    %eax,%edi
0x0000000000400963 <+123>:   callq  0x40098c <print_notes>
0x0000000000400968 <+128>:   mov    %eax,-0x4(%rbp)
0x000000000040096b <+131>:   cmpl   $0x0,-0x4(%rbp)
0x000000000040096f <+135>:   jne    0x400955 <main+109>
0x0000000000400971 <+137>:   mov    $0x400cb0,%edi
0x0000000000400976 <+142>:   callq  0x400680 <puts@plt>
0x000000000040097b <+147>:   mov    -0xc(%rbp),%eax
0x000000000040097e <+150>:   mov    %eax,%edi
0x0000000000400980 <+152>:   callq  0x4006e0 <close@plt>
0x0000000000400985 <+157>:   mov    $0x0,%eax
0x000000000040098a <+162>:   leaveq 
0x000000000040098b <+163>:   retq   

And the code until my main is this:

#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "usefullfuncs.h"

#define FILENAME "/var/notes"

int print_notes(int, int, char *);
int find_user_note(int,int);
int search_note(char *, char *);

int main(int argc, char *argv[]){
    int userid,printing=1,fd;
    char searchstring[100];

    if(argc>1)
        strcpy(searchstring,argv[1]);
    else
        searchstring[0] = 0;

    userid = getuid();

    fd = open(FILENAME,O_RDONLY);
    if(fd == -1)
        fatal("in main() while opening file for reading");

    while(printing)
        printing = print_notes(fd,userid,searchstring);
    printf("-------[ end of note data ]-------\n");
    close(fd);
}

int print_notes(int fd,int uid,char *searchstring){
    int note_lenght;
    char note_buffer[100];

    note_lenght = find_user_note(fd,uid);

    if(note_lenght == -1)
        return 0;

    read(fd,note_buffer,note_lenght);
    note_buffer[note_lenght] = 0;

    if(search_note(note_buffer,searchstring))
        printf(note_buffer);
    return 1;
}

int find_user_note(int fd,int user_uid){
    int note_uid=-1;
    unsigned char byte;
    int lenght;

    while(note_uid != user_uid){
        if(read(fd,&note_uid,4)!=4)
            return -1;
        if(read(fd,&byte,1)!=1) 
            return -1;

        byte = lenght = 0;

        while(byte != '\n'){ 
            if(read(fd,&byte,1)!=1) 
                return -1;
            lenght++;
        }
    }

    lseek(fd,lenght*-1,SEEK_CUR);

    printf("[DEBUG] found a %d byte note for user id %d\n",lenght,note_uid);
    return lenght;
}

int search_note(char *note, char *keyword){
    int i,keyword_lenght,match=0;

    keyword_lenght = strlen(keyword);

    if(keyword_lenght == 0)
        return 1;

    for(i=0;i < strlen(note);i++){
        if(note[i] == keyword[match])
            match++;
        else{
            if(note[i] == keyword[0])
                match = 1;
            else
                match = 0;
        }
        if(match == keyword_lenght)
            return 1;
    }
    return 0;
}

Thanks in advance.

解决方案

(gdb) x/24s $esp
0xffffffffffffe550: <error: Cannot access memory at address 0xffffffffffffe550>

On an x86-64 target, $rsp should be used. Using $esp will lead to incorrect results.

$esp is taken from the bottom 32 bits of the 64-bit $rsp register, and gdb treats it as type int32_t. $rsp in your example was probably 0x7fffffffe550. Gdb's x command, which wants to use a 64-bit address, will take the bottom 32 bits of $rsp, 0xffffe550, and sign-extend that to 0xffffffffffffe550. That's almost certainly an invalid address; typical user-space addresses on Linux don't go above 0x7ffffffff000 or so.

Try x/24s $rsp. If you're trying to follow exercises out of an old book, you may be able to duplicate their 32-bit examples by giving gcc the -m32 option, if it supports it. Then you can use $esp.

这篇关于main()中的GDB断点无法访问内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆