• VxWorks函数栈帧剖析


    VxWorks任务内存地址空间布局

    VxWorks系统中,所有Tasks(包括系统任务和用户任务)都工作在特权模式,共享所有内存。A任务可以直接访问B任务的内存地址空间而不会触发任何“异常”。下图为单个任务的内存地址空间布局,任务ID(Task ID)分割任务控制块(TCB)和任务栈,任务栈中压栈函数栈帧,从高地址向低地址增长。

    首先,我们查看任务列表

    -> i
    
      NAME        ENTRY       TID    PRI   STATUS      PC       SP     ERRNO  DELAY
    ---------- ------------ -------- --- ---------- -------- -------- ------- -----
    ^@tExcTask   excTask      87df85b0   0 PEND       8178f244 87df8490   3006b     0
    tLogTask   logTask      87df5a00   0 PEND       8178f244 87df58e8       0     0
    tCPUIdlCaptmeasureCPUId 57beefb0   1 DELAY      8173ad78 57beef28       0    17
    tShell     shell        878aea90   1 READY      8173c008 878ae6a8       0     0
    active_shelshell_task   57b5ac40   2 PEND       80168bec 57b5abc8       0     0
    tWdbTask   wdbTask      878d1700   3 PEND       80168bec 878d1470  3d0002     0
    Timer      8175f730     57bed110   5 DELAY      8173ad78 57bed088       0    55
    keep_alive 810f90a4     5ee7e900   6 PEND       8178f244 5ee7e1b8       0     0
    oind       810f829c     5eeaf260   7 PEND+T     80168bec 5eeaef08  3d0002    30
    hind       810f8d64     5ee9eea0   8 PEND       8178f244 5ee9e1d0  3d0002     0
    Co00       810f960c     5ee6e630   9 PEND       8178f244 5ee6e4f0  3d0002     0

    我们以Timer为例,分析函数栈帧结构

    -> ti Timer
    ^@
      NAME        ENTRY       TID    PRI   STATUS      PC       SP     ERRNO  DELAY
    ---------- ------------ -------- --- ---------- -------- -------- ------- -----
    Timer      8175f730     57bed110   5 DELAY      8173ad78 57bed088       0    22
    
    stack: base 0x57bed110  end 0x57beb110  size 8176   high 292    margin 7884 
    
    options: 0xc
    VX_DEALLOC_STACK    VX_FP_TASK          
    
    VxWorks Events
    --------------
    Events Pended on    : Not Pended
    Received Events     : 0x0
    Options             : N/A
    
    $0    =        0   t0    =        0   s0    =        0   t8    =        0
    at    =        0   t1    =        0   s1    =        0   t9    =        0
    v0    =        0   t2    =        0   s2    =        0   k0    =        0
    v1    =        0   t3    =        0   s3    =        0   k1    =        0
    a0    =        0   t4    =        0   s4    =        0   gp    = 82d6cba0
    a1    =        0   t5    =        0   s5    = 57bed110   sp    = 57bed088
    a2    =        0   t6    =        0   s6    =       3c   s8    = 57bed0d0
    a3    =        0   t7    =        0   s7    = 832bb500   ra    =        0
    divlo =        0   divhi =        0   sr    = 1000fc01   pc    = 8173ad78
    value = 0 = 0x0

    从上面可以看出,tLogTask任务的栈空间为0x57bed110~0x57beb110地址段,栈顶指针SP值为0x57bed088。

    继续查看函数调用栈

    -> tt Timer
    ^@80169604 vxTaskEntry    +c  : TmrStopTimer (0, 0, 0, 0)
    8175f768 TmrStopTimer   +410: taskDelay (eeeeeeee, eeeeeeee, eeeeeeee, eeeeeeee)
    value = 0 = 0x0

    此处,分析TmrStopTimer函数的栈帧

    -> l TmrStopTimer,20
    ^@                      TmrStopTimer:
    0x8175f358  27bdffd8    addiu           sp,sp,65496(-40)                   // sp = sp - 40
    0x8175f35c  afbf0024    sw              ra,36(sp)                          // [sp + 36] = ra
    0x8175f360  afbe0020    sw              s8,32(sp)                          // [sp + 32] = s8
    0x8175f364  03a0f025    move            s8,sp                              // s8 = sp
    0x8175f368  afc40028    sw              a0,40(s8)                          // [s8 + 40] = a0   第一个参数
    0x8175f36c  afc5002c    sw              a1,44(s8)                          // [s8 + 44] = a1   第二个参数
    0x8175f370  8fc20028    lw              v0,40(s8)                          // v0 = [s8 + 40]
    0x8175f374  afc20014    sw              v0,20(s8)                          // [s8 + 20] = v0
    0x8175f378  afc00010    sw              zero,16(s8)                        // [s8 + 16] = 0
    0x8175f37c  3c0282ca    lui             v0,0x82ca
    0x8175f380  8c422088    lw              v0,8328(v0)
    0x8175f384  10400008    beqz            v0,0x8175f3a8
    0x8175f388  00000000    nop     
    0x8175f38c  3c0482ca    lui             a0,0x82ca
    0x8175f390  8c842088    lw              a0,8328(a0)
    0x8175f394  2405ffff    li              a1,65535
    0x8175f398  0c05a189    jal             semTake
    0x8175f39c  00000000    nop     
    0x8175f3a0  085d7ced    j               0x8175f3b4
    0x8175f3a4  00000000    nop     
    value = -2122976344 = 0x8175f3a8 = TmrStopTimer + 0x50

    第一行指令表示把栈顶指针sp下移40个字节,表示TmrStopTimer函数的栈帧大小为40字节。

    如上所示,TmrStopTimer函数栈帧的底部压栈返回地址ra和返回函数的栈顶指针。

    对于叶子函数(不调用其他函数的函数),可能不会压栈ra,因为ra寄存器值不会被改写。此外,编译器的优化选项-O指定的优化级别,也会影响栈帧结构。

    打印从sp~s8地址空间的栈数据:

    -> d 0x57bed088,20,4
    ^@57bed080:                    eeeeeeee eeeeeeee   *            ....*
    57bed090:  57bed098 8175f834 82eaa780 0000001d   *W....u.4........*
    57bed0a0:  eeeeeeee eeeeeeee 0000000f 00000001   *................*
    57bed0b0:  0000001d 82eaaff8 eeeeeeee 8175f770   *.............u.p*
    57bed0c0:  00000000 00000000 00000000 57bed0d0   *............W...*

    可以看到,s8为0x57bed0d0,ra为0。(此处有点诡异,居然是反的,有可能函数汇编代码中移位了sp指针,待商榷)

  • 相关阅读:
    报表自动化: 商业智能背后的秘密
    谈谈个人对 TDD (测试驱动开发) 的理解
    初识 Inception
    从软件生命周期看应用安全(网络安全)
    Spring JPA save 实现主键重复抛异常
    QMdiArea及QMdiSubWindow实现父子窗口及布局方法
    QTcpServer实现多客户端连接
    C++设计模式
    QTreeView/QTableView中利用QStandardItem实现复选框三种形态变化
    Qt富文本编辑器QTextDocument
  • 原文地址:https://www.cnblogs.com/justin-y-lin/p/15750608.html
Copyright © 2020-2023  润新知