恢复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.
浙公网安备 33010602011771号