前几篇都是讲述了使用GDK7和NanoCode来调试内核的方法,本篇继续学习:

  • 使用NanoCode来远程调试目标机GDK7的应用程序

  • 分别通过“附加到进程”和“创建新进程”的方式来调试

注:

  1. 请将主机和目标机连接在同一个局域网内。

  2. 由于受限于tty进制,通过“创建新进程”的方式无法调试交互式或者带UI的程序。(本篇调试自己编译的readelf程序)

准备工作:

  1. 目标价GDK7需要使用新版本的ndsrv模块,请至http://advdbg.org/gdk/resource.aspx下载新版本,安装到目标机(使用systemctl status | grep ndsrv 查询服务是否在运行);

  2. 主机NanoCode需要使用1.1.0或以上版本;

  3. 准备被调试的程序(如果没有,这里使用了一个简单c++程序来调试,请复制出来保存到main.cpp,然后编译:g++ -g main.cpp -o main),请使用-g编译,带调试信息。

  4. 将执行程序main复制在目标机上,

  5. 同时将main放置在主机c:\temp\app下(目录可换),main.cpp放置在主机d:\dbg-source\main下(目录可换),用于解析符号和定位源代码。

#include <stdio.h>

#include <iostream>
#include <string>
#include <vector>

int sub(int a, int b) {
   return a - b;
}

int add(int a, int b) {
   return a + b;
}

void split_string(const std::string& input, char splitter, std::vector<std::string>& vec){
    vec.clear();

    if(input.empty())
        return;

    std::string::size_type begin = 0, pos =input.find(splitter);
    while(pos != std::string::npos){
        std::string tmp = input.substr(begin, pos - begin);
        if(!tmp.empty()){
            vec.push_back(tmp);
        }

        begin = pos + 1;
        pos = input.find(splitter, begin);
    }

    if(begin < input.size()){
        vec.push_back(input.substr(begin));
    }
}

void usage() {
    std::cout << "Usage:" << std::endl;
    std::cout << "q - Exit app" << std::endl;
    std::cout << "h - Show usage" << std::endl;
    std::cout << "sub - Execute sub(a, b) function" << std::endl;
    std::cout << "add - Execute add(a, b) function" << std::endl;
}

static const char* s_ver = "1.0";
int main() {
    std::cout << "c++ example version:" << s_ver << std::endl;
    usage();

    int result = 0;

    std::string input;
    std::vector<std::string> vec;
    for(; ;) {
        std::cout << "Please input commnd:";
        getline(std::cin, input);

        split_string(input, ' ', vec);
        if(vec[0] == "q"){
            break;
        } else if(vec[0] == "h"){
            usage();
        }else if (vec[0] == "add"){
            if(vec.size() < 3){
                std::cout << "Err: less paramter(add x y)" << std::endl;
                continue;
            }
            int x = atoi(vec[1].c_str());
            int y = atoi(vec[2].c_str());
            result = add(x, y);
            std::cout << "Add Result:" << result << std::endl;    
        } else if (vec[0] == "sub"){
            if(vec.size() < 3){
                std::cout << "Err: less paramter(sub x y)" << std::endl;
                continue;
            }
            int x = atoi(vec[1].c_str());
            int y= atoi(vec[2].c_str());
            result = sub(x, y);
            std::cout << "Sub Result:" << result << std::endl;    
        } else {
            std::cout << "Err: Unknown command:" << vec[0] << std::endl;        
            usage();
        }       
    }

    std::cout << "App exits, bye." << std::endl;
    return 0;
}

开始调试:

调试正在运行的进程

  1. 查看目标机ip地址;

    在目标机控制台启动main程序,显示如下:

  1. 在主机端启动NanoCode;

  2. 在NanoCode里设置目标机的ip和port,并且连接到目标机(如果没有连接成功,将会报错),操作如下:

    输入(tcp:port=200,server=目标ip)端口固定,点击“Connect”;

  1. 在NanoCode里选择被调试的远程程序,操作如下:

  1. 至此,已经挂上并中断下远端Ubuntu的main程序了;

  1. 此时,main程序已被挂起;

  2. 下面,开始设置符号路径和源文件路径;

    .sympath+ c:\temp\app

    .srcpath+ d:\dbg-source\main

  1. 查询main的符号

    x main!*

    可以看出,列出了好多stl的很多符号

  1. 调试main的sub函数

    x main!sub // 查找函数地址

    bp 地址 // 对函数地址下断点

  1. 重新g起来;

  2. 在目标机main程序下触发sub函数,输入sub 2 1,然后回车,成功断下,并且源代码也自动打开;

  1. 然后可以单步执行,查看寄存器,变量来调试了~

调试新创建的进程–调试readelf

  1. 下载binutils,从https://ftp.gnu.org/gnu/binutils/下载,在ubuntu上编译,然后将readelf和源码复制一份到主机端,用于解析符号和源码调试

  2. 主机NanoCode连接到目标机,如上步骤1,重新设置:在NanoCode里设置目标机的ip和port,并且连接到目标机(如果没有连接成功,将会报错)。

  3. 在NanoCode里File->Open Executable…输入远程程序命令,或者使用历史记录,这里没有带任何参数,readelf打印帮助之后,就会自动退出了。

  1. 点击确认,然后设置符合和源码路径

  1. 然后查找函数,下断点,我们在main函数下断点

  1. 然后输入g,重新跑起来,程序自动断下,同时源码也自动打开

  1. 查看一下寄存器和临时变量

  1. 至此,可以继续调试其他了。

总结:

  1. 主要使用NanoCode远程调试Ubuntu上的应用程序;

  2. 不足:当调试完一个实例之后,下次调试又需要重新连接一次目标机;

  3. 不足:使用“创建新进程”的方式,暂时无法调试交互式或者带UI的程序;

  4. 待续。。。

作者:沈根成  创建时间:2024-03-20 14:23
最后编辑:沈根成  更新时间:2024-04-26 11:30