恢复call stack的办法

Question: How to reconstruct call stack?
Answer: There are multiple ways to check the call stack, detail is below
Detail:
This is complete procedure for Stack Recovery, which I want to share. I think most of the skills here might be applicable to HLOS as well.
1)      Using T32 functionality
As all of you know, T32 can restore the call stack automatically if OS awareness module is there.
This is easiest way of doing it.
1.a) Install OS awareness, HLOS may have different procedure but for L4 and QuRT you can do this by below.
For QuRT(Blast)

        TASK.CONFIG modem_proc\core\kernel\blast\install\debugger\Blast_model.t32

        MENU.ReProgram modem_proc\core\kernel\blast\install\debugger\blast_model.men

For L4

       TASK.CONFIG build\ms\l4.t32

       MENU.ReProgram build\ms\l4.men

Please note the location of those files might vary by target.
1.b) You can type var.frame (v.f) and select task name, then you can see the call stack
-000|okl4_sys_notify_wait(asm)

-001|rex_wait(p_sigs = 4294967217)

-002|mcc_wait(requested_mask = 327681)

-003|mccidl_start_sleep(new_state = 515)

-004|mccidl_state(new_state = 515)

-005|mccidl_online(new_state = 515)

-006|cdma_idle()

-007|mcc_subtask(?)

-008|mc_online_digital_state(mmoc_trans_id_ptr = 0x4452A3F8)

-009|mc_cdma_prot_activate(act_reason = PROT_ACT_ONLINE_ACQ)

-010|mc_process_cmd()

-011|mc_task(?)

-012|rex_thread_init(entrypoint = 0x436D8371)

-013|UR:0x43C19AC8(asm)

-014|thread_delete_self()

---|end of frame

    |

 

2)      Using Stack Tracer.
However about procedure many not work if SP(Stack Pointer)/PC(Program Counter) are not known.
This is happening usually when the thread is in running state, as we save register values only when scheduling out.
We can use Stack Tracer for printing values which look like function calls.
1.a) However Before using this, you need to find out  stack range.
1.a.1) You can find the range by symbol.brower (y.b)

 

symbol___________________|type_____________________|address_________________|

mc_SrchStrategyTrigger   |                         |    P:43053018--430530BB

mc_SrchStrategyUpdateDpo.|                         |    P:43053CC4--43053D49

mc_stack                 |(rex_stack_word_type [20.|    D:445287C0--4452A7BF

mc_state                 |(byte ())                |    P:436D8416--436D8445

mc_store_watermark       |(void ())                |    P:436D8552--436D8553

assumption here is we should know the variable name for STACK of the task
1.a.2) otherwise if you know SP roughly, you can search symbol name by symbol.list (y.l)
In this case,  if we already know SP is around 0x4452A278, then you can
y.l 0x4452A278
then you would see mc_stack[] is the name

 

___address___to_________|path\symbol_____________________________|type_____________________|scope_|location|

    D:445287C0--4452A7BF|\\M8660AAABQNSZM3161B\Global\mc_stack   |(rex_stack_word_type [20.|global|static  |

    D:4452A7C0--4452A9BB|\\M8660AAABQNSZM3161B\Global\dh_tcb     |(rex_tcb_type)           |global|static  |

    D:4452A9BC--4452B9BB|\\M8660AAABQNSZM3161B\Global\dh_stack   |(rex_stack_word_type [10.|global|static  |

 

For ARM,

Do staxtract5a.cmm MEMR <stack top> <stack bottom>

 

For QuRT,

Do staxtract5b_q6.cmm MEMR <stack top> <stack bottom>

 

You can find those script in \\ce-crash\tools\stack
You would get result similar to below. The list may have vogus functions as well. so you need to make it reasonable by checking source code.
Only red colored lines are valid. You need to filter out invalid function names from the list.

 

    ___ _           _     _____                          ___

   / __| |_ __ _ __| |__ |_   _| _ __ _ __ ___ _ _  __ _| __|  __ _

   \__ \  _/ _` / _| / /   | || '_/ _` / _/ -_) '_| \ V /__ \_/ _` |

   |___/\__\__,_\__|_\_\   |_||_| \__,_\__\___|_|    \_/|___(_)__,_|

 

SP: 0x4452A278 Lmt: 0x4452A278 Size: 0x547 0x0

0x0

Stack Start : 0x4452A7BF

Stack End   : 0x4452A278

Stack Limit : 0x4452A278

Stack Size  : 0x547

Stack Address   Function Name(?)

=================================================================

0x4452A294      mcc_wait

0x4452A2AC      mccidl_start_sleep

0x4452A2BC      msg_save_3

0x4452A2D4      msg_send_3

0x4452A2FC      mccidl_state

0x4452A314      q_check

0x4452A324      mccreg_update_lists

0x4452A33C      mccreg_idle_check

0x4452A354      q_put

0x4452A374      mccidl_online

0x4452A394      cdma_idle

0x4452A3A4      mcc_subtask

0x4452A3BC      mc_online_digital_state

0x4452A3F4      mc_cdma_prot_activate

0x4452A40C      mc_process_cmd

0x4452A434      time_genoff_get_optimized

0x4452A46C      timetick_sclk64_get

0x4452A494      time_genoff_get_optimized

0x4452A4B4      time_genoff_opr

0x4452A4D4      osal_atomic_compare_and_set

0x4452A4EC      err_f3_trace_secure_offset

0x4452A79C      mc_task

Finishing the analysis

 

 

3)      Using T32 command

 

If both (1) (2) not working properly, there is a T32 command to help us reconstruct stack frame in manual way
DATA.VIEW %SYMBOL.LONG <address of stack>

This command basically prints out all the values around the address, with symbol information.
So we can pick only reasonable function calls from the window.
You will get result similar to below.
DATA.VIEW %SYMBOL.LONG  0x4452A278

breakpoint________address|_data_______|value___________|symbol

              UD:4452A270| 1C 61 A3 45 45A3611C         \\M8660AAABQNSZM3161B\Global\mc_stack+0x1AB0

              UD:4452A274| 8D 8A 6C 43 436C8A8D

              UD:4452A278| 00 00 00 00 0                \\M8660AAABQNSZM3161B\rexl4\rex_wait+0x7F

              UD:4452A27C| 70 8F 45 44 44458F70

              UD:4452A280| 00 00 00 00 0                \\M8660AAABQNSZM3161B\Global\mc_mode_controller_state

              UD:4452A284| 00 00 00 00 0

              UD:4452A288| 01 00 05 00 50001

              UD:4452A28C| 00 00 00 00 0

              UD:4452A290| 00 00 40 00 400000

              UD:4452A294| E7 4D 3D 43 433D4DE7

              UD:4452A298| 05 00 05 00 50005            \\M8660AAABQNSZM3161B\mccdma\mcc_wait+0xFF

              UD:4452A29C| 03 02 00 00 203

              UD:4452A2A0| 3C D8 4A 44 444AD83C

              UD:4452A2A4| 00 00 00 00 0                \\M8660AAABQNSZM3161B\mccidl\mccidl_fast_raho

              UD:4452A2A8| 01 00 00 00 1

              UD:4452A2AC| 3F 45 23 44 4423453F

              UD:4452A2B0| 00 00 00 00 0                \\M8660AAABQNSZM3161B\mccidl\mccidl_start_sleep+0x97

              UD:4452A2B4| 00 00 00 00 0

              UD:4452A2B8| 00 00 00 00 0

              UD:4452A2BC| 43 31 00 43 43003143

              UD:4452A2C0| 00 00 00 00 0                \\M8660AAABQNSZM3161B\msg_api\msg_get_time+0x1

              UD:4452A2C4| 00 00 00 00 0

              UD:4452A2C8| 00 00 00 00 0

              UD:4452A2CC| 00 00 00 00 0

              UD:4452A2D0| 00 00 00 00 0

              UD:4452A2D4| A5 33 00 43 430033A5

              UD:4452A2D8| 00 00 00 00 0                \\M8660AAABQNSZM3161B\msg_api\msg_send_3+0x41

              UD:4452A2DC| 00 00 00 00 0

              UD:4452A2E0| 00 00 00 00 0

              UD:4452A2E4| 00 00 00 00 0

              UD:4452A2E8| A8 64 01 45 450164A8

              UD:4452A2EC| 03 02 00 00 203              \\M8660AAABQNSZM3161B\Global\cdma+0x3E4

              UD:4452A2F0| 02 00 00 00 2

              UD:4452A2F4| A8 64 01 45 450164A8

              UD:4452A2F8| 00 00 00 00 0                \\M8660AAABQNSZM3161B\Global\cdma+0x3E4

              UD:4452A2FC| 83 54 23 44 44235483

              UD:4452A300| 03 02 00 00 203              \\M8660AAABQNSZM3161B\mccidl\mccidl_state+0x67D

              UD:4452A304| 02 00 00 00 2

              UD:4452A308| 90 ED 01 45 4501ED90

 

   4)      Restore Call stack manually
   This is most time consuming procedure, and tricky, too. But this is last method we have if none of above worked.
   You can browse whole stack area, and find possible LR values, and match related source code to check the LR is reasonable or not.
   By that, you could get reasonable call stack from any situation.
   Reconstructing stack frame in ARM and Q6 might be different.
   detail information on this procedure is documented in “Stability debugging Guide” doc# 80-VN752-2 already. So I would skip this part.

posted on 2012-01-27 11:46  不知道  阅读(1933)  评论(0)    收藏  举报

导航