说明

若想调试SGX Enclave,安装SGX PSW时,需安装libsgx-xxx-dbgsym。

从linux-sgx源码DEBUG=1编译安装才能调试SGX SDK和PSW(官网提供的预编译包都不是调试模式编译的)

Enclave调试

普通gdb无法获取Enclave内存,因此无法stop在Enclave内,但sgx-gdb通过开发了gdb插件能够获取Enclave内存。

sgx-gdb一般会装在如下位置

${SGX SDK Path}/bin/sgx-gdb
e.g. /opt/intel/sgxsdk/bin/sgx-gdb

我把SGX SDK装在了如下位置(推荐)

/opt/intel/sgxsdk/

只要你以debug模式编译的Enclave,那么就可以用sgx-gdb单步step进入Enclave,或者可以在Enclave里面下断点,比如(以SampleCode为例)

b Enclave/Enclave.cpp:printf

然后执行run,就会进入到目标断点,很方便。

此外,还可以使用sgx-gdb调试linux-sgx。如果需要调试linux-sgx的pws和sdk,那么就需要以DEBUG=1的参数来编译这两个模块。然后就如前面所说的下断点就行了。

sgx-gdb调试时的函数调用栈信息

Enclave基址信息(DEBUG=1编译会显示此)

[build_secs /home/leone/文档/linux-sgx/psw/urts/loader.cpp:516] Enclave start addr. = 0x7ffff6000000, Size = 0x1000000, 16384 KB

以trts_ecall.cpp:300为例的断点信息

1. 寄存器信息

rax            0x7ffff6003e0e      140737320599054
rbx            0x7ffff65c7bb0      140737326644144
rcx            0x0                 0
rdx            0x1000000           16777216
rsi            0x0                 0
rdi            0x7ffff6003e0e      140737320599054
rbp            0x7ffff65c73d0      0x7ffff65c73d0
rsp            0x7ffff65c7390      0x7ffff65c7390
r8             0x7ffff6026c9a      140737320742042
r9             0x0                 0
r10            0x0                 0
r11            0x0                 0
r12            0x78a               1930
r13            0x0                 0
r14            0x78a               1930
r15            0x0                 0
rip            0x7ffff601bcab      0x7ffff601bcab <trts_ecall(uint32_t, void*)+364>
eflags         0x246               [ PF ZF IF ]
cs             0x33                51
ss             0x2b                43
--Type <RET> for more, q to quit, c to continue without paging--
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0

2. 栈信息

#0  trts_ecall (ordinal=19, ms=0x7fffffffdd00) at trts_ecall.cpp:300
#1  0x00007ffff601c7aa in _random_stack_noinline_wrapper<_status_t, unsigned int, void*, int&, void*&> (f=0x7ffff601bb3f <trts_ecall(uint32_t, void*)>) at /home/leone/文档/linux-sgx/common/inc/sgx_random_buffers.h:83
#2  0x00007ffff601c72c in random_stack_advance<2048u, _status_t, unsigned int, void*, int&, void*&> (f=0x7ffff601bb3f <trts_ecall(uint32_t, void*)>) at /home/leone/文档/linux-sgx/common/inc/sgx_random_buffers.h:102
#3  0x00007ffff601c22c in do_ecall (index=19, ms=0x7fffffffdd00, tcs=0x7ffff65d8000) at trts_ecall.cpp:436
#4  0x00007ffff6045999 in enter_enclave (index=19, ms=0x7fffffffdd00, tcs=0x7ffff65d8000, cssa=0) at trts_nsp.cpp:97
#5  0x00007ffff6045c03 in enclave_entry () at trts_pic.S:181
#6  0x00007ffff7f74edc in __morestack () at enter_enclave.S:77
#7  0x00007ffff7f8aadf in do_ecall (fn=19, ocall_table=0x55555555eb00 <ocall_table_Enclave>, ms=0x7fffffffdd00, trust_thread=0x555555576c90)at sig_handler.cpp:240
#8  0x00007ffff7f7e4d3 in CEnclave::ecall (this=0x55555557f6b0, proc=19, ocall_table=0x55555555eb00 <ocall_table_Enclave>, ms=0x7fffffffdd00, is_switchless=false) at /home/leone/文档/linux-sgx/psw/urts/enclave.cpp:388
#9  0x00007ffff7f8363a in _sgx_ecall (enclave_id=2, proc=19, ocall_table=0x55555555eb00 <ocall_table_Enclave>, ms=0x7fffffffdd00, is_switchless=false) at /home/leone/文档/linux-sgx/psw/urts/routine.cpp:55
#10 0x00007ffff7f83691 in sgx_ecall (enclave_id=2, proc=19, ocall_table=0x55555555eb00 <ocall_table_Enclave>, ms=0x7fffffffdd00)at /home/leone/文档/linux-sgx/psw/urts/routine.cpp:68
#11 0x000055555555743b in ecall_array_user_check (eid=2, arr=0x7fffffffdd40) at App/Enclave_u.c:613
#12 0x00005555555583ea in edger8r_array_attributes () at App/Edger8rSyntax/Arrays.cpp:45
#13 0x0000555555557a61 in main (argc=1, argv=0x7fffffffdec8) at App/App.cpp:195

3. 栈帧信息

Stack level 0, frame at 0x7ffff65c73e0:rip = 0x7ffff601bcab in trts_ecall (trts_ecall.cpp:300); saved rip = 0x7ffff601c7aacalled by frame at 0x7ffff65c7420source language c++.Arglist at 0x7ffff65c7388, args: ordinal=19, ms=0x7fffffffdd00Locals at 0x7ffff65c7388, Previous frame's sp is 0x7ffff65c73e0Saved registers:rbp at 0x7ffff65c73d0, rip at 0x7ffff65c73d8

分析一下。栈帧信息中,记录了当前栈帧frame的基址、当前rip(当前指令的下一条指令的地址)、调用当前函数(此时为trts_ecall)的那个“父”函数(此时为_random_stack_noinline_wrapper)的rip值(存在当前栈帧中)、父函数的栈帧基址(地址高于当前栈帧,栈帧从高地址向低地址扩展)、当前参数信息及其地址(局部变量,传参64位下通过rdi等寄存器传值,地址低于当前栈帧基址)、上一个栈帧的sp、上一个栈帧的rbp、rip所存在当前栈帧的具体地址(当前的rbp指向的位置存了上一个栈帧rbp地址,存上一个栈帧的rip的地址比rbp地址高8字节)。当前的rip值指向当前的下一条指令(可以看到栈地址和代码地址不一样)。

sgx-gdb查看函数调用传参

64位下,普通传参通过rdi, rsi, rdx, rcx, r8, r9传值,然后在当前栈帧分配局部变量保存通过寄存器传过来的值,局部变量存值的过程是按照参数从前往后依次压栈(从高地址往低地址压栈),如果有this指针,那么this指针第一个压栈,如果参数中有结构体,那么等其他传参压栈完之后,把结构体内容从父函数栈帧中的结构体内容复制到当前栈帧。

Breakpoint 4, CheckPoint::trigger (this=0x7ffff6054360 <_check_point>, interface_type=INTERFACE_ECALL, func_index=19, ms=0x7fffffffdd00, is_ocall_allowed=true) at check_point.cpp:38
38          cp_info_t info = {interface_type, func_index, ms};
(gdb) p &interface_type
$8 = (interface_type_t *) 0x7ffff65c7a44
(gdb) x/20x 0x7ffff65c7a44
0x7ffff65c7a44: 0x00000002      0xf6054360      0x00007fff      0xf65c7a98
0x7ffff65c7a54: 0x00007fff      0xf4f4ba0c      0x00000013      0xf65c7a70
0x7ffff65c7a64: 0x00007fff      0xf4f4ba0c      0x38f97f5a      0xf65c7ac0
0x7ffff65c7a74: 0x00007fff      0xf601bccf      0x00007fff      0xffffdd00
0x7ffff65c7a84: 0x00007fff      0x00000000      0x00000013      0xf65c7b38
(gdb) x/20x 0x7ffff65c7a34
0x7ffff65c7a34: 0x00007f01      0xffffdd00      0x00007fff      0x00000013
0x7ffff65c7a44: 0x00000002      0xf6054360      0x00007fff      0xf65c7a98
0x7ffff65c7a54: 0x00007fff      0xf4f4ba0c      0x00000013      0xf65c7a70
0x7ffff65c7a64: 0x00007fff      0xf4f4ba0c      0x38f97f5a      0xf65c7ac0
0x7ffff65c7a74: 0x00007fff      0xf601bccf      0x00007fff      0xffffdd00
(gdb) info stack
#0  CheckPoint::trigger (this=0x7ffff6054360 <_check_point>, interface_type=INTERFACE_ECALL, func_index=19, ms=0x7fffffffdd00, is_ocall_allowed=true) at check_point.cpp:38
#1  0x00007ffff601bccf in trts_ecall (ordinal=19, ms=0x7fffffffdd00) at trts_ecall.cpp:300
#2  0x00007ffff601c7aa in _random_stack_noinline_wrapper<_status_t, unsigned int, void*, int&, void*&> (f=0x7ffff601bb3f <trts_ecall(uint32_t, void*)>) at /home/leone/文档/linux-sgx/common/inc/sgx_random_buffers.h:83
#3  0x00007ffff601c72c in random_stack_advance<2048u, _status_t, unsigned int, void*, int&, void*&> (f=0x7ffff601bb3f <trts_ecall(uint32_t, void*)>) at /home/leone/文档/linux-sgx/common/inc/sgx_random_buffers.h:102
#4  0x00007ffff601c22c in do_ecall (index=19, ms=0x7fffffffdd00, tcs=0x7ffff65d8000) at trts_ecall.cpp:436
#5  0x00007ffff6045999 in enter_enclave (index=19, ms=0x7fffffffdd00, tcs=0x7ffff65d8000, cssa=0) at trts_nsp.cpp:97
#6  0x00007ffff6045c03 in enclave_entry () at trts_pic.S:181
#7  0x00007ffff7f74edc in __morestack () at enter_enclave.S:77
#8  0x00007ffff7f8aadf in do_ecall (fn=19, ocall_table=0x55555555eb00 <ocall_table_Enclave>, ms=0x7fffffffdd00, trust_thread=0x555555576c90)at sig_handler.cpp:240
#9  0x00007ffff7f7e4d3 in CEnclave::ecall (this=0x55555557f6b0, proc=19, ocall_table=0x55555555eb00 <ocall_table_Enclave>, ms=0x7fffffffdd00, is_switchless=false) at /home/leone/文档/linux-sgx/psw/urts/enclave.cpp:388
#10 0x00007ffff7f8363a in _sgx_ecall (enclave_id=2, proc=19, ocall_table=0x55555555eb00 <ocall_table_Enclave>, ms=0x7fffffffdd00, is_switchless=false) at /home/leone/文档/linux-sgx/psw/urts/routine.cpp:55
#11 0x00007ffff7f83691 in sgx_ecall (enclave_id=2, proc=19, ocall_table=0x55555555eb00 <ocall_table_Enclave>, ms=0x7fffffffdd00)at /home/leone/文档/linux-sgx/psw/urts/routine.cpp:68
#12 0x000055555555743b in ecall_array_user_check (eid=2, arr=0x7fffffffdd40) at App/Enclave_u.c:613
--Type <RET> for more, q to quit, c to continue without paging--
#13 0x00005555555583ea in edger8r_array_attributes () at App/Edger8rSyntax/Arrays.cpp:45
#14 0x0000555555557a61 in main (argc=1, argv=0x7fffffffdec8) at App/App.cpp:195
(gdb) info frame
Stack level 0, frame at 0x7ffff65c7a80:rip = 0x7ffff600ac49 in CheckPoint::trigger (check_point.cpp:38); saved rip = 0x7ffff601bccfcalled by frame at 0x7ffff65c7ad0source language c++.Arglist at 0x7ffff65c7a28, args: this=0x7ffff6054360 <_check_point>, interface_type=INTERFACE_ECALL, func_index=19, ms=0x7fffffffdd00, is_ocall_allowed=trueLocals at 0x7ffff65c7a28, Previous frame's sp is 0x7ffff65c7a80Saved registers:rbp at 0x7ffff65c7a70, rip at 0x7ffff65c7a78
(gdb) info reg
rax            0x0                 0
rbx            0x7ffff65c7bb0      140737326644144
rcx            0x7fffffffdd00      140737488346368
rdx            0x13                19
rsi            0x2                 2
rdi            0x7ffff6054360      140737320928096
rbp            0x7ffff65c7a70      0x7ffff65c7a70
rsp            0x7ffff65c7a30      0x7ffff65c7a30
r8             0x1                 1
r9             0x0                 0
r10            0x0                 0
r11            0x0                 0
r12            0x9a                154
r13            0x0                 0
r14            0x9a                154
r15            0x0                 0
rip            0x7ffff600ac49      0x7ffff600ac49 <CheckPoint::trigger(interface_type, int, void*, bool)+47>
eflags         0x246               [ PF ZF IF ]
cs             0x33                51
ss             0x2b                43
--Type <RET> for more, q to quit, c to continue without paging--q
Quit
(gdb) l
33          while (sgx_fclose(m_log_fp) != 0 and errno == EAGAIN);
34      #endif //FILE_MODE
35      };
36
37      int CheckPoint::trigger(interface_type_t interface_type, int func_index, void *ms, bool is_ocall_allowed) {
38          cp_info_t info = {interface_type, func_index, ms};
39          return _trigger(info, is_ocall_allowed);
40      }
41
42      int CheckPoint::_trigger(cp_info_t info, bool is_ocall_allowed) {
(gdb) s
39          return _trigger(info, is_ocall_allowed);
(gdb)
CheckPoint::_trigger (this=0x7ffff601b6c6 <is_ecall_allowed(uint32_t)+48>, info=..., is_ocall_allowed=255) at check_point.cpp:42
42      int CheckPoint::_trigger(cp_info_t info, bool is_ocall_allowed) {
(gdb) n
44          if ((info.interface_type == INTERFACE_OCALL or info.interface_type == INTERFACE_OCALL_RET)
(gdb) info reg
rax            0x1                 1
rbx            0x7ffff65c7bb0      140737326644144
rcx            0x1                 1
rdx            0x7fffffffdd00      140737488346368
rsi            0x7fffffffdd00      140737488346368
rdi            0x7ffff6054360      140737320928096
rbp            0x7ffff65c7a20      0x7ffff65c7a20
rsp            0x7ffff65c79f0      0x7ffff65c79f0
r8             0x1                 1
r9             0x0                 0
r10            0x0                 0
r11            0x0                 0
r12            0x9a                154
r13            0x0                 0
r14            0x9a                154
r15            0x0                 0
rip            0x7ffff600acb2      0x7ffff600acb2 <CheckPoint::_trigger(cp_info, bool)+38>
eflags         0x206               [ PF IF ]
cs             0x33                51
ss             0x2b                43
--Type <RET> for more, q to quit, c to continue without paging--q
Quit
(gdb) p &info
$9 = (cp_info_t *) 0x7ffff65c79f0
(gdb) info frame
Stack level 0, frame at 0x7ffff65c7a30:rip = 0x7ffff600acb2 in CheckPoint::_trigger (check_point.cpp:44); saved rip = 0x7ffff600ac75called by frame at 0x7ffff65c7a80source language c++.Arglist at 0x7ffff65c79e8, args: this=0x7ffff6054360 <_check_point>, info=..., is_ocall_allowed=trueLocals at 0x7ffff65c79e8, Previous frame's sp is 0x7ffff65c7a30Saved registers:rbp at 0x7ffff65c7a20, rip at 0x7ffff65c7a28
(gdb) x/20x 0x7ffff65c79e8
0x7ffff65c79e8: 0xf601a093      0x00007fff      0x00000002      0x00000013
0x7ffff65c79f8: 0xffffdd00      0x00007fff      0xf65c7a10      0x00007f01
0x7ffff65c7a08: 0xf6054360      0x00007fff      0x00000000      0x00000000
0x7ffff65c7a18: 0xf6003e0e      0x00007fff      0xf65c7a70      0x00007fff
0x7ffff65c7a28: 0xf600ac75      0x00007fff      0xf6000000      0x00007f01
(gdb) p &is_ocall_allowed
$10 = (bool *) 0x7ffff65c7a04
(gdb) p this
$11 = (CheckPoint * const) 0x7ffff6054360 <_check_point>
(gdb) p &this
$12 = (CheckPoint * const *) 0x7ffff65c7a08

sgx-gdb调试SGX Enclave相关推荐

  1. 使用 GDB 调试多进程程序

    使用 GDB 调试多进程程序 来源 https://www.ibm.com/developerworks/cn/linux/l-cn-gdbmp/index.html GDB 是 linux 系统上常 ...

  2. GDB调试--以汇编语言为例

    #rpm -qa |grep  gdb 下载: 安装 #tar -zxvf #./configure #make 使用GDB 以汇编语言调试为例 汇编语言实现CPUID指令 CPUID cpuid是I ...

  3. GDB 调试 Mysql 实战(二)GDB 调试打印

    背景 在 https://mengkang.net/1328.html 实验中,我们通过optimizer_trace发现group by会使用intermediate_tmp_table,而且里面的 ...

  4. 用gdb调试mpi程序的一些心得

    Linux下MPI (Message Passage Interface) 的程序不太好调试,在windows下vs2005以上的IDE有集成的简便MPI调试工具,没有用过,有兴趣的可以试验一下.下面 ...

  5. gdb php-fpm,使用 gdb 调试 php-fpm 异常错误

    相关资源下载GDB简介 GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具.如果你是在 UNIX平台下做软件,你会发现GDB这个调试工具有比VC.BCB的图形化调试器更强大的功能. 问题 ...

  6. Linux基础 30分钟GDB调试快速突破

    引言 Linus心灵鸡汤 在*nix开发中有道卡叫gdb调试,不管你怎么搞. 它依然在那丝毫不会松动.今天致敬一个 活着的传奇 Linus Torvalds Unix 始于上个世纪60年代,在70年代 ...

  7. SLAM工具|GDB调试从入门到精通

    前言 对于windows平台下,VS下调试简单又方便,那么在linux系统下,该如何进行代码的调试呢? gdb是linux下非常好用的一个调试工具,虽然它是命令行模式的调试工具,但是它的功能非常强大, ...

  8. gdb调试 print打印不出变量值或者不准确

    编译选项加了 -O,即便是-O0,也不能正常显示,需要加上-gstabs+这个编译选项, -gdwarf-2这个编译选项会与-gstabs+冲突,去掉-gstabs+,只保留-gdwarf-2选项可以 ...

  9. 比较全面的gdb调试命令

    用GDB调试程序  GDB是一个强大的命令行调试工具.大家知道命令行的强大就是在于,其可以形成执行序 列,形成脚本.UNIX下的软件全是命令行的,这给程序开发提代供了极大的便利,命令行 软件的优势在于 ...

最新文章

  1. 微软推出提点神器动态ReLU,可能是最好的ReLU改进
  2. Apache+MySQL+PHP安装指南
  3. 未将对象引用设置到对象的实例
  4. 神器诞生!E3成首个3.50可降级国产电子狗
  5. javascript中的console.log有什么作用?
  6. Spring Injection with @Resource, @Autowired and @Inject
  7. 数字签名与HTTPS详解
  8. Java注释是一个大错误
  9. 关于ttk的使用与安装
  10. esxi root 密码规则_陌陌风控系统静态规则引擎aswan
  11. c#学习之Socket网络编程
  12. 相机视场角和焦距_相机参数一览表
  13. 02 Python元组 字典 数据类型 if while for 迭代
  14. MongoDB几个完整的库表设计实例
  15. [渝粤教育] 同济大学 线性代数学习指导 参考 资料
  16. 数据分析:销售数据怎么分析?简单概述
  17. C语言课程设计报告-菜单设计
  18. stm32cubeide 汉化包_经过两天瞎折腾,分享下STM32CUBE IDE的用法
  19. 20/06/27 charles安装报【User installations are disabled via policy on the machine】解决方法
  20. Mysql基础篇(5)—— 约束

热门文章

  1. 吉布斯采样和梅特罗波利斯-黑斯廷斯算法
  2. 教你创建virtuemart invoice收据 发票
  3. 小程序常见的问题你一定遇到过!
  4. Goland配置goproxy.cn代理
  5. 【音视频】编/解码 - 编码器底层原理学习顺序
  6. 庄子 “天地有大美而不言。”
  7. Wannafly挑战赛3-A-珂学送分(概率dp)
  8. QChart实现ui界面上指定位置饼状图、圆环图的绘制
  9. 从元宇宙婚礼和元宇宙游戏看元宇宙的“史前时代”
  10. GDAL编译报错ogr_sfcgal.h:34:34:fatal error:SFCGAL/capi/sfcgal_c/h:No such file or directory