如何最快找出复杂代码运行时的函数调用流程

 

 

概述

最近在使用freeswitch测试发送DTMF码的时候,碰到一个函数调用流程的问题。

fs本身的模块较多,注册回调函数也比较多且复杂,有时候看到一条日志,却不知道流程的发起端在哪里。

通常我们在梳理代码调用流程的时候有几种方法。

1, 梳理源代码流程,代码太复杂的时候效果差。

2, 在调用函数中打印日志,代码太复杂的时候效果差。

3, 通过backtrace函数追踪当前堆栈,改动多,细节多。

4, gdb调试,命令复杂难记。

今天突然想到一个偷懒的办法,比上面几种方法都要快速简单。

 

环境

centos7

freeswitch 1.6.19

gcc version 4.8.5

 

起源

fs的日志如下,简单来看,在dialplan中调用了sleep之后,rtp流程开始发送DTMF。

EXECUTE sofia/external/1001@10.55.55.138:5080 sleep(5000)

2022-06-17 14:42:54.890047 [DEBUG] switch_rtp.c:5237 Send start packet for [1] ts=160 dur=160/160/2000 seq=8238 lw=160

 

但是rtp的调用过程隔的太远,源代码看了好久也没看出来所以然,主要是菜。

 

修改源代码

首先找到“switch_rtp.c:5237”的位置,修改源代码,增加一行断言判定。

switch_assert(FALSE);

 

重新对fs编译安装。

 

测试

启动fs,并执行测试命令,日志如下。

freeswitch@localhost.localdomain> originate {originator_codec=PCMA,origination_caller_id_number=0755110}sofia/external/sip:1001@10.55.55.138:5080 1001 XML ext_test

EXECUTE sofia/external/1001@10.55.55.138:5080 sleep(5000)

freeswitch: src/switch_rtp.c:5236: do_2833: Assertion `0' failed.

Aborted

 

哈,和设想的一样,fs程序coredump了

 

core堆栈

在bin目录下找到core文件

-rw-------. 1 root root 71778304 Jun 17 15:24 core.14650

 

使用gdb打开core文件,并显示堆栈。

sudo gdb freeswitch core.14650

(gdb) bt

#0  0x00007f0b9e371387 in raise () from /lib64/libc.so.6

#1  0x00007f0b9e372a78 in abort () from /lib64/libc.so.6

#2  0x00007f0b9e36a1a6 in __assert_fail_base () from /lib64/libc.so.6

#3  0x00007f0b9e36a252 in __assert_fail () from /lib64/libc.so.6

#4  0x00007f0ba0e8be2a in do_2833 (rtp_session=rtp_session@entry=0x7f0b1c012d98) at src/switch_rtp.c:5236

#5  0x00007f0ba0e8d4fb in rtp_common_read (rtp_session=rtp_session@entry=0x7f0b1c012d98, payload_type=payload_type@entry=0x7f0b34040aa4 "", pmapP=pmapP@entry=0x7f0b34040ac8, flags=flags@entry=0x7f0b34040ab8, io_flags=io_flags@entry=0) at src/switch_rtp.c:7321

#6  0x00007f0ba0e8e59f in switch_rtp_zerocopy_read_frame (rtp_session=0x7f0b1c012d98, frame=frame@entry=0x7f0b34040a60, io_flags=io_flags@entry=0) at src/switch_rtp.c:7617

#7  0x00007f0ba0e41990 in switch_core_media_read_frame (session=session@entry=0x7f0b3402f3b8, frame=frame@entry=0x7f0b482795d8, flags=flags@entry=0, stream_id=stream_id@entry=0, type=type@entry=SWITCH_MEDIA_TYPE_AUDIO) at src/switch_core_media.c:2219

#8  0x00007f0b984f1298 in sofia_read_frame (session=0x7f0b3402f3b8, frame=0x7f0b482795d8, flags=0, stream_id=0) at mod_sofia.c:1044

#9  0x00007f0ba0e2a5d6 in switch_core_session_read_frame (session=session@entry=0x7f0b3402f3b8, frame=frame@entry=0x7f0b482795d8, flags=flags@entry=0, stream_id=stream_id@entry=0) at src/switch_core_io.c:188

#10 0x00007f0ba0ec426d in switch_ivr_sleep (session=session@entry=0x7f0b3402f3b8, ms=ms@entry=5000, sync=sync@entry=SWITCH_TRUE, args=args@entry=0x7f0b48279850) at src/switch_ivr.c:294

#11 0x00007f0b7273d5c4 in sleep_function (session=0x7f0b3402f3b8, data=<optimized out>) at mod_dptools.c:2288

#12 0x00007f0ba0e2472b in switch_core_session_exec (session=session@entry=0x7f0b3402f3b8, application_interface=application_interface@entry=0x1ccfcd8, arg=arg@entry=0x7f0b34053240 "5000") at src/switch_core_session.c:2802

#13 0x00007f0ba0e24cb9 in switch_core_session_execute_application_get_flags (session=session@entry=0x7f0b3402f3b8, app=0x7f0b34053238 "sleep", arg=0x7f0b34053240 "5000", flags=flags@entry=0x0) at src/switch_core_session.c:2672

#14 0x00007f0ba0e28ae4 in switch_core_standard_on_execute (session=0x7f0b3402f3b8) at src/switch_core_state_machine.c:353

#15 switch_core_session_run (session=0x7f0b3402f3b8) at src/switch_core_state_machine.c:650

#16 0x00007f0ba0e21f7e in switch_core_session_thread (thread=<optimized out>, obj=0x7f0b3402f3b8) at src/switch_core_session.c:1648

#17 0x00007f0ba0e1dc73 in switch_core_session_thread_pool_worker (thread=0x7f0b3404f340, obj=<optimized out>) at src/switch_core_session.c:1711

#18 0x00007f0ba10d8b10 in dummy_worker (opaque=0x7f0b3404f340) at threadproc/unix/thread.c:151

#19 0x00007f0b9ede5ea5 in start_thread () from /lib64/libpthread.so.0

#20 0x00007f0b9e439b0d in clone () from /lib64/libc.so.6

(gdb)

 

啧啧,清晰的函数调用流程,一览无余。

 

总结

fs的模块比较多,代码调用链大都比较长,涉及到媒体方面流程更是复杂难以跟踪。

剑走偏锋,独辟蹊径。

 

空空如常

求真得真

posted @ 2022-07-21 18:04  求真得真  阅读(101)  评论(1编辑  收藏  举报