Linux x86_64汇编套接字编程 [英] Linux x86_64 assembly socket programming

查看:27
本文介绍了Linux x86_64汇编套接字编程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好。

所以我正在学习汇编语言。
按照我通常学习的任何新语言的学习步骤,我已经达到了与汇编语言联网的地步。

遗憾的是,这不是很顺利,因为我在步骤0几乎失败了,这将是获得一个套接字,通过它可以开始通信。

汇编代码应大致等于以下C代码:

#include <stdio.h>
#include <sys/socket.h>

int main(){
        int sock;
        sock = socket(AF_INET, SOCK_STREAM, 0);
}

(让我们忽略它目前没有关闭套接字这一事实。)

以下是我到目前为止所做的工作:

  • 已选中the manual。这意味着我需要做一个socketcall(),这一切都很好。问题开始于它需要一个int来描述它应该进行哪种类型的socketcall。调用manpage对此也没有太大帮助,因为它只描述:
在某些体系结构(例如x86-64和ARM)上没有 socketcall()系统调用;而不是Socket(2)、Accept(2)、Bind(2)和 因此,On实际上是作为单独的系统调用实现的。

  • 但是在最初的syscall列表中没有这样的调用-据我所知,socket()accept()bind()listen()等都是来自libnet的调用,而不是来自内核的调用。这让我非常困惑,所以我决定编译上面的C代码,并用strace检查它。这产生了以下结果:

    套接字(PF_INET,SOCK_STREAM,IPPROTO_IP)=3

  • 虽然这并没有让我更深入地了解socket()是什么,但它确实解释了它的参数。对于WITCH,我似乎(再一次)找不到合适的文档。我以为PF_INETSOCK_STREAMIPPROTO_IP会在<sys/socket.h>中定义,但是我对它们的grep似乎没有什么用处。因此,我决定临时使用gdbdisass main来查找值。这将产生以下输出:

    转储函数main的汇编器代码: 0x00000000004004fd<;+0>:推流RBP 0x00000000004004fe<;+1>:MOV RBP,RSP 0x0000000000400501<;+4>:子RSP,0x10 0x0000000000400505<;+8>:MOV edX,0x0 0x000000000040050a<;+13>:MOV ESI,0x1 0x000000000040050f<;+18>:MOV EDI,0x2 0x0000000000400514<;+23>:呼叫0x400400 0x0000000000400519<;+28>:MOV双字PTR[RBP-0x4],EAX 0x000000000040051c<;+31>:离开
    0x000000000040051d<;+32>:返回
    汇编程序转储结束。

  • 根据我的经验,这意味着socket()EDX(PF_INET)、ESI(SOCK_STREAM)和EDI(IPPROTO_IP)获取参数。这对于系统调用来说是奇怪的(因为Linux系统调用的惯例是以递增的顺序使用EAX/RAX作为呼叫号,使用其他寄存器作为参数,例如。RBXRCXRDX.)。这是由CALL而不是INT 0x80执行的这一事实也意味着这实际上不是一个系统调用,而是从共享对象调用的某个东西。

  • 然后再说一遍。对于CALL-ed的东西,在寄存器中传递参数是非常奇怪的。正常情况下,据我所知,调用对象的参数应该PUSH放到堆栈上,因为编译器不知道它们会尝试使用什么寄存器。

  • 当使用ldd

    检查生成的二进制文件时,此行为变得更加奇怪

    linux-vdso.so.1(0x00007fff4a7fc000) libc.so.6=>/lib/x86_64-linux-gnu/libc.so.6(0x00007f56b0c61000) /lib64/ld-linux-x86-64.so.2(0x00007f56b1037000)

  • 似乎没有链接的网络库。

这就是我没有主意的地方。

所以我有以下要求:

  • 描述x86-64Linux内核的实际系统调用及其相关编号的文档。(最好作为C的头文件。)
  • 定义PF_INETSOCK_STREAMIPPROTO_IP的头文件,因为在我自己的系统上找不到它们真的很让我头疼。
  • 可能是关于x86-64Linux上的汇编联网的教程。(对于x86-32很容易找到材料,但是由于某种原因,我没有找到64位的内容。)

谢谢!

推荐答案

64位调用约定确实使用寄存器在用户空间和系统调用中传递参数。如您所见,用户空间约定是rdirsirdxrcxr8r9。对于系统调用,使用r10而不是被syscall指令销毁的rcx。有关详细信息,请参阅wikipedia或ABI文档。

各种常量的定义隐藏在头文件中,假设您安装了必要的开发包,则可以通过文件系统搜索轻松找到这些头文件。您应该查看/usr/include/x86_64-linux-gnu/bits/socket.h/usr/include/linux/in.h

对于系统调用列表,Google one是微不足道的,比如this。当然,您也可以随时查看内核源代码。

这篇关于Linux x86_64汇编套接字编程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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