免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4413 | 回复: 5
打印 上一主题 下一主题

ARM 上面运行gdbserver 出错:waitpid:Function not implemented 已解决 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-12-09 19:28 |只看该作者 |倒序浏览
各位有没有人在ARM上用 gdb和gdbserver交叉调试应用程序?我在ARM上用上述工具调试程序,提示: waitpid:Function not implemented  最后google  好像是ARM 上面没有相应的系统调用。不知道有没有人知道该如何解决?

以下是我调试的时候用的hello.c
#include <stdio.h>
main (int argc, char **argv)
{
        int i;
        for (i=0;i<3;i++)
        {
                printf("Hello i=%d\n",i);
        }
        return 0;
}

gdbserver 调试后结果如下

/usr/bin # gdbserver 192.168.11.6:2345 hello
Process hello created; pid = 751
waitpid: Function not implemented.
Exiting
/usr/bin # Hello i=0
Hello i=1
Hello i=2

然后敲一下ENTER才回到 shell.

[ 本帖最后由 jiayinjia198311 于 2008-12-16 08:47 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2008-12-09 22:41 |只看该作者
你用的什么内核?gdbserver已经成功运行起来了吗?

论坛徽章:
0
3 [报告]
发表于 2008-12-09 23:08 |只看该作者
内核为 snapgear-3.4.0开发套件里的自带的kernel, kernel版本为2.6.17,而且我看2.6.23 和2.6.25里面都没有在ARM 上实现关于waitpid的系统调用(我看的是文件是/linux-version/include/asm-arm/unistd.h,不知道我看这个文件对吗?)。而gdbserver里面的确调用了 waitpid,我用以下文件测试确实是我的kernel 没有实现waitpid 的系统调用。 我的gdbserver 的确运行起来了,不过因为出现waitpid:Function not implemented 错误信息,又退出了。
测试程序如下:
#include <stdio.h>
#include <asm/unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>

int main()
{
        pid_t pid, cpid;
        int myerrno;
        int count = 0;
        char keep_going = 1;

        pid = fork();
        switch( pid )
        {
        case -1:
                myerrno = errno;
                printf("fork: %d : %s\n", myerrno, strerror( myerrno ) );
                break;
        case 0:
                printf("This is the child, pid %d\n", getpid() );
                for( count = 0; count < 3; count ++ )
                {
                        printf("child sleeping\n");
                        sleep(1);
                }
                printf("child woke up!\n");
                return 0;
                break;
        default:
                printf("This is the parent, pid %d\n", getpid() );

                while( keep_going )
                {
                        cpid = waitpid(-1,NULL,WNOHANG);
                        switch( cpid )
                        {
                        case -1:
                                myerrno = errno;
                                printf( "waitpid: %d: %s\n", myerrno, strerror( myerrno ) );
                                return myerrno;
                                break;
                        case 0:
                                printf( "parent sleeping\n" );
                                sleep(1);
                                break;
                        default:
                                printf("child %d returned\n", cpid);
                                return 0;
                                break;
                        }
                }

                break;
        }

        return -1;
}

另外我google 的时候发现这篇关于ARM 上没有实现waitpid 的文章https://kerneltrap.org/mailarchive/linux-kernel/2007/3/20/68348

[ 本帖最后由 jiayinjia198311 于 2008-12-9 23:10 编辑 ]

论坛徽章:
0
4 [报告]
发表于 2008-12-10 16:32 |只看该作者
在网上看到好多用 gdb gdbserver 在ARM 上交叉调试程序的例子,难道别人没有碰到像我这样的问题吗?我用相同版本的gdb,在两台X86的机器调试(一台启动nfs 服务,另一台 将 启动nfs服务的机器上的文件夹mount 到本地),就可以的。

论坛徽章:
0
5 [报告]
发表于 2008-12-15 19:35 |只看该作者
问题已经解决,解决方法如下:
1.首先在内核的头文件里声明 waitpid的系统调用。在 kernel-version/include/asm-arm/unistd.h 里面添加如下一行 :
#define __NR_waitpid                    (__NR_SYSCALL_BASE+  7)
  在kernel-version/arch/arm/kernel/calls.S 里,将里面的如下的最后一行注释掉,
/* 5 */         CALL(sys_open)
                CALL(sys_close)
/*              CALL(sys_ni_syscall)            */ /* was sys_waitpid */

然后在下面添加如下的一行
CALL(sys_waitpid)
2. 给编译器传递参数使sys_waitpid对应的代码编译到内核中。
   在内核的Makefile里面的CFLAGS_KERNEL  添加如下的参数 -D__ARCH_WANT_SYS_WAITPID ,为什么要添加这个参数呢?看一下 sys_waitpid 的实现(位于kernel-version/kernel/exit.c里面)就清楚了,为了方便,我把它的实现列出如下:
#ifdef __ARCH_WANT_SYS_WAITPID

/*
* sys_waitpid() remains for compatibility. waitpid() should be
* implemented by calling sys_wait4() from libc.a.
*/
asmlinkage long sys_waitpid(pid_t pid, int __user *stat_addr, int options)
{
        return sys_wait4(pid, stat_addr, options, NULL);
}

#endif

接下来,就是重新编译内核了。再次调用gdbserver, 192.168.11.6是我的开发机host,192.168.11.7是我的目标机的地址。
/usr/bin # gdbserver 192.168.11.6:2345 hello
Process hello created; pid = 745

在主机端调用gdb hello
然后输入 target remote 192.168.11.6:2345

这时查看目标机的控制台,可以看到打印出“Remote debugging from host 192.168.11.6”
终于成功了!

论坛徽章:
0
6 [报告]
发表于 2014-08-07 04:39 |只看该作者
谢谢楼主的帖子,我今天也碰到了这个waitpid问题,查了一下,waitpid()是正统POSIX.1-2001接口,而wait4()是BSD的非标准接口,两者功能一样。
但是在Linux ARM上由于某种原因(x86_64也没有实现),故意没有实现waitpid system call (7),而是推荐在user application里用相似的wait4 system call (114)来代替。
wait4只比waitpid多了一个参数,并且这个参数可以设成NULL,所以有个更简单的办法不需要修改内核,只需要在gdbserver的linux-low.c开头添加3行预定义就行了


添加的代码:
#ifdef __arm__
#define waitpid(pid, status, options) wait4(pid, status, options, NULL)
#endif




ARM9测试结果(Linux 2.6.23.1):
# ./gdbserver-7.6.2-arm-static 127.0.0.1:2300 /tmp/fxinfo
Process /tmp/fxinfo created; pid = 358
Listening on port 2300
Remote debugging from host xx.xx.xx.xx




arm disassembly验证,原gdbserver objdump无wait4跳转:
; ret = waitpid (pid, status, flags);
e3a03000      mov  r3, #0 ; NULL parameter
e1a02005      mov  r2, r5
e1a01007      mov  r1, r7
e1a00008      mov  r0, r8   ; first three parameters move to r0, r1, r2
eb00be9a      bl      500a0 <__wait4>  ; jump to wait4 system call
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP