免费注册 查看新帖 |

Chinaunix

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

[内核入门] linux内核内联汇编的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2016-10-14 18:08 |只看该作者 |倒序浏览
代码如下:
#define __get_user_asm(x, addr, err, itype, rtype, ltype, errret)        \
        __asm__ __volatile__(                                                \
                "1:        mov"itype" %2,%"rtype"1\n"                        \
                "2:\n"                                                        \
                ".section .fixup,\"ax\"\n"                                \
                "3:        movl %3,%0\n"                                        \
                "        xor"itype" %"rtype"1,%"rtype"1\n"                \
                "        jmp 2b\n"                                        \
                ".previous\n"                                                \
                ".section __ex_table,\"a\"\n"                                \
                "        .align 4\n"                                        \
                "        .long 1b,3b\n"                                        \
                ".previous"                                                \
                : "=r"(err), ltype (x)                                        \
                : "m"(__m(addr)), "i"(errret), "0"(err))


这是linux内核2.6.11.1中一个从用户空间复制数据到内核空间的底层调用函数
问题:
    那有linux内核内联汇编的详细资料,已看过LINUX内核源代码情景分析()》中的1.5节《1.5Linux内核源代码中的汇编语言代码》,内核汇编指令参见《汇编语言程序设计()布鲁姆_,马朝晖_等译》,但不够详细,有的语法很奇特,不知道含义,请大神指导

论坛徽章:
1
15-16赛季CBA联赛之新疆
日期:2017-03-09 12:33:45
2 [报告]
发表于 2016-10-14 19:42 |只看该作者
回复 1# zzuedu2000

  1. #define __get_user_asm(x, addr, err, itype, rtype, ltype, errret)        \
  2.         __asm__ __volatile__(                                                \
  3.                 "1:        mov"itype" %2,%"rtype"1\n"                        \
  4.                 "2:\n"                                                        \
  5.                 ".section .fixup,\"ax\"\n"                                \
  6.                 "3:        movl %3,%0\n"                                        \
  7.                 "        xor"itype" %"rtype"1,%"rtype"1\n"                \
  8.                 "        jmp 2b\n"                                        \
  9.                 ".previous\n"                                                \
  10.                 ".section __ex_table,\"a\"\n"                                \
  11.                 "        .align 4\n"                                        \
  12.                 "        .long 1b,3b\n"                                        \
  13.                 ".previous"                                                \
  14.                 : "=r"(err), ltype (x)                                        \
  15.                 : "m"(__m(addr)), "i"(errret), "0"(err))
复制代码

输入是

  1. #define __get_user_size(x, ptr, size, retval)                           \
  2. do {                                                                    \
  3.          retval = 0;                                                     \
  4.          __chk_user_ptr(ptr);                                            \
  5.          switch (size) {                                                 \
  6.          case 1:                                                         \
  7.                  __get_user_asm(x, ptr, retval, "b", "b", "=q", -EFAULT);\
  8.                  break;                                                  \
  9.          case 2:                                                         \
  10.                  __get_user_asm(x, ptr, retval, "w", "w", "=r", -EFAULT);\
  11.                  break;                                                  \
  12.          case 4:                                                         \
  13.                  __get_user_asm(x, ptr, retval, "l", "k", "=r", -EFAULT);\
  14.                  break;                                                  \
  15.          case 8:                                                         \
  16.                  __get_user_asm(x, ptr, retval, "q", "", "=r", -EFAULT); \
  17.                  break;                                                  \
  18.          default:                                                        \
  19.                  (x) = __get_user_bad();                                 \
  20.          }                                                               \
  21. } while (0)
复制代码

从上面的调入看,就是对于不同的长度,调整参数。

你这里的代码,说白了,只有一句话是实质性的,其它的是修复性的。
  1. "1: mov"itype" %2,%"rtype"1\n" \
复制代码
就是把
  1. mov reg1, ptrtype ptr[reg2];
复制代码
这个很容易理解,
后面的代码其实要解释一下。

  1. ".section .fixup,\"ax\"\n" \
复制代码
这个就是把下面的代码放入 .fixup 的节中。
后面的
  1. ".previous\n" \
复制代码
就是恢复编译到前面保存的节中,
在这个情景中,就是大概率放入到.code 节中,当然,要看具体的情况,有时可能是 .init.code 节中,这个看情况 。

好,下面来解释 .fixup 与  __ex_table的 情况。
.fixup 节是在系统出现异常时进行的修补。
这种情况,说到底,就是前面的输入值是一个非法地址,这个时候
在handle_page_fault函数中(具体,请参看《情景分析》 第二章,讲内存管理)
,这个时候,处理异常的函数,会根据异常的RIP地址来处理,这个地址,与处理对应要
建立对应关系,这个就是现在这里的.fixpu 与 __ex_table

在 __ex_table
  1. " .long 1b,3b\n"
复制代码
这个1b 就是前面
  1. "1: mov"itype" %2,%"rtype"1\n"
复制代码
前面的1的地址

3b就是
  1. "3: movl %3,%0\n"
复制代码

这样处理与异常发生地址建立联系了。

如果查到是由于当前的地址引起的,就跳转到
  1. "3: movl %3,%0\n"
复制代码
开始的来处理。
处理的内容,就是把retval设置为非0

所以,你看整个代码
如果没有出现异常,就是一个命令处理完了。
如果出现异常,则设置返回值为非0,
这样,可以得到copy_from_user 的返回值,知道成功与否。

如果要了解详细的内容,请参看源代码。





评分

参与人数 1信誉积分 +50 收起 理由
zzuedu2000 + 50 很给力,感谢详细分析,帮助很大!

查看全部评分

论坛徽章:
0
3 [报告]
发表于 2016-10-16 10:22 |只看该作者

RE: linux内核内联汇编的问题

回复 2# jeppeter

感谢指导,在你分析的基础上我又理解后分析了一下,请指导:
函数参数:
x=to
addr=from
err=4
itype=”b”/”w”/”l”
rtype=”b”/”w”/””
ltype=”=q”/”=r”/”=r”
errret=4
函数源码:
#define __get_user_asm(x, addr, err,itype, rtype, ltype, errret)  \
    __asm____volatile__(                     \
      /*movb/movw/movl addr, %b/w/“”1*/
       "1: mov"itype"%2,%"rtype"1\n"         \
      /**/
       "2:\n"                       \
      /*把下面的代码放入.fixup 节中*/
       ".section.fixup,\"ax\"\n"             \
      /*err= errret */
       "3: movl %3,%0\n"               \
      /*把reg1即x置0*/
       "   xor"itype"%"rtype"1,%"rtype"1\n"      \
      /**/
       "   jmp 2b\n"                \
      /*恢复编译到前面保存的节中*/
       ".previous\n"                   \
      /*这里指定异常表项,参见“参考文章3”*/
       ".section__ex_table,\"a\"\n"             \
      /**/
       "   .align 4\n"                 \
      /*1b地址的指令引起异常,就跳转到3b*/
       "   .long 1b,3b\n"                  \
      /**/
       ".previous"                     \
       :"=r"(err), ltype (x)                 \
       :"m"(__m(addr)), "i"(errret), "0"(err))
函数处理流程:
输出部:
代码:: "=r"(err), ltype (x)
解释:
%0: err=r0
%1: x=寄存器 (ltype(=q/=r/=r))
输入部:
代码::"m"(__m(addr)), "i"(errret), "0"(err))
解释:
    %2: addr内存单元
    %3: errret直接操作数
    %4: r0=err
损坏部:: 无
指令部:
1、具体指令含义参见代码注释
2、处理流程:执行1处的指令,成功则结束;失败,根据异常表项《.section __ex_table,\"a\"\n"》,跳转到3b处执行,设置寄存器值后跳转到2b处结束

论坛徽章:
0
4 [报告]
发表于 2016-10-16 10:25 |只看该作者
在理解异常表的过程中参考了cnblogs上“在于思考”的博文“Linux异常表”,这里不让发链接,需要详细了解的可以参考一下
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP