以调试ffmpeg为例,演示gdb如何定位内存被修改

本文演示了使用gdb定位avformat_find_stream_info函数破坏codecpar变量的问题

1.查看音频或视频stream index【以下以视频为例】

./ffprobe demo.avi 2>&1 | grep Stream

Stream #0:0: Video: h264 (High) (H264 / 0x34363248), yuv420p(progressive), 1920x1080, 4021 kb/s, 25 fps, 25 tbr, 25 tbn, 50 tbc

以上视频的stream index=0

2.修改ffmpeg,在avformat_find_stream_info中将codecpar置NULL

vim libavformat/utils.c -> avformat_find_stream_info

av_opt_set(ic, "skip_clear", "1", AV_OPT_SEARCH_CHILDREN);
ic->streams[0]->codecpar=NULL;  //*破坏 codecpar
max_stream_analyze_duration = max_analyze_duration;

3.编译ffmpeg debug版本

./configure --enable-debug
make -j

4.启动gdb

bash 复制代码
gdb --args ./ffmpeg_g -i demo.avi  -qp 10  out.avi -y

5.在avformat_find_stream_info下断点

(gdb) b avformat_find_stream_info

Breakpoint 1 at 0x7ce180: file libavformat/utils.c, line 3623.

6.运行

(gdb) r

Starting program: ./ffmpeg_g -i demo.avi -qp 10 out.avi -y
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
ffmpeg version n4.3.4 Copyright (c) 2000-2021 the FFmpeg developers
  built with gcc 4.8.5 (GCC) 20150623 (Red Hat 4.8.5-44)
  configuration: --enable-debug
  libavutil      56. 51.100 / 56. 51.100
  libavcodec     58. 91.100 / 58. 91.100
  libavformat    58. 45.100 / 58. 45.100
  libavdevice    58. 10.100 / 58. 10.100
  libavfilter     7. 85.100 /  7. 85.100
  libswscale      5.  7.100 /  5.  7.100
  libswresample   3.  7.100 /  3.  7.100

Breakpoint 1, avformat_find_stream_info (ic=0x22ca500, options=0x22cc500) at libavformat/utils.c:3623
warning: Source file is more recent than executable.
3623    {
Missing separate debuginfos, use: debuginfo-install bzip2-libs-1.0.6-13.el7.x86_64 glibc-2.17-326.el7_9.x86_64 libXau-1.0.8-2.1.el7.x86_64 libdrm-2.4.91-3.el7.x86_64 libva-1.8.3-1.el7.x86_64 libxcb-1.13-1.el7.x86_64 zlib-1.2.7-19.el7_9.x86_64

7.查看变量

 (gdb) print(*(AVFormatContext*)ic)

$1 = {av_class = 0x128d300 <av_format_context_class>, iformat = 0x1892fe0 <ff_avi_demuxer>, oformat = 0x0, priv_data = 0x22cb040, pb = 0x22d31c0, ctx_flags = 0, nb_streams = 1, streams = 0x22cb100,
  filename = "demo.avi", '\000' <repeats 1009 times>, url = 0x22cacc0 "demo.avi", start_time = -9223372036854775808, duration = -9223372036854775808, bit_rate = 0, packet_size = 0, max_delay = -1, flags = 2097156,
  probesize = 5000000, max_analyze_duration = 0, key = 0x0, keylen = 0, nb_programs = 0, programs = 0x0, video_codec_id = AV_CODEC_ID_NONE, audio_codec_id = AV_CODEC_ID_NONE, subtitle_codec_id = AV_CODEC_ID_NONE,
  max_index_size = 1048576, max_picture_buffer = 3041280, nb_chapters = 0, chapters = 0x0, metadata = 0x22cc440, start_time_realtime = -9223372036854775808, fps_probe_size = -1, error_recognition = 1, interrupt_callback = {
    callback = 0x4a5fa0 <decode_interrupt_cb>, opaque = 0x0}, debug = 0, max_interleave_delta = 10000000, strict_std_compliance = 0, event_flags = 0, max_ts_probe = 50, avoid_negative_ts = -1, ts_id = 0, audio_preload = 0,
  max_chunk_duration = 0, max_chunk_size = 0, use_wallclock_as_timestamps = 0, avio_flags = 0, duration_estimation_method = AVFMT_DURATION_FROM_PTS, skip_initial_bytes = 0, correct_ts_overflow = 1, seek2any = 0,
  flush_packets = -1, probe_score = 100, format_probesize = 1048576, codec_whitelist = 0x0, format_whitelist = 0x0, internal = 0x22cab80, io_repositioned = 0, video_codec = 0x0, audio_codec = 0x0, subtitle_codec = 0x0,
  data_codec = 0x0, metadata_header_padding = -1, opaque = 0x0, control_message_cb = 0x0, output_ts_offset = 0, dump_separator = 0x22ca010 ", ", data_codec_id = AV_CODEC_ID_NONE, open_cb = 0x0,
  protocol_whitelist = 0x22ca2b0 "file,crypto,data", io_open = 0x77bdf0 <io_open_default>, io_close = 0x77bde0 <io_close_default>, protocol_blacklist = 0x0, max_streams = 1000, skip_estimate_duration_from_pts = 0,
  max_probe_packets = 2500}

(gdb) print(*(AVStream *)((*(AVFormatContext*)ic)->streams[0]))

$2 = {index = 0, id = 0, codec = 0x22cb580, priv_data = 0x22cbf00, time_base = {num = 1, den = 25}, start_time = 0, duration = 1656, nb_frames = 1656, disposition = 0, discard = AVDISCARD_DEFAULT, sample_aspect_ratio = {num = 0,
    den = 1}, metadata = 0x0, avg_frame_rate = {num = 25, den = 1}, attached_pic = {buf = 0x0, pts = 0, dts = 0, data = 0x0, size = 0, stream_index = 0, flags = 0, side_data = 0x0, side_data_elems = 0, duration = 0, pos = 0,
    convergence_duration = 0}, side_data = 0x0, nb_side_data = 0, event_flags = 0, r_frame_rate = {num = 0, den = 0}, recommended_encoder_configuration = 0x0, codecpar = 0x22cba00, info = 0x22cb4c0, pts_wrap_bits = 64,
  first_dts = -9223372036854775808, cur_dts = 9223090561878065151, last_IP_pts = -9223372036854775808, last_IP_duration = 0, probe_packets = 2500, codec_info_nb_frames = 0, need_parsing = AVSTREAM_PARSE_HEADERS, parser = 0x0,
  last_in_packet_buffer = 0x0, probe_data = {filename = 0x0, buf = 0x0, buf_size = 0, mime_type = 0x0}, pts_buffer = {-9223372036854775808 <repeats 17 times>}, index_entries = 0x22db2e0, nb_index_entries = 1656,
  index_entries_allocated_size = 41495, stream_identifier = 0, program_num = 0, pmt_version = 0, pmt_stream_idx = 0, interleaver_chunk_size = 0, interleaver_chunk_duration = 0, request_probe = 0, skip_to_keyframe = 0,
  skip_samples = 0, start_skip_samples = 0, first_discard_sample = 0, last_discard_sample = 0, nb_decoded_frames = 0, mux_ts_offset = 0, pts_wrap_reference = -9223372036854775808, pts_wrap_behavior = 0,
  update_initial_durations_done = 0, pts_reorder_error = {0 <repeats 17 times>}, pts_reorder_error_count = '\000' <repeats 16 times>, last_dts_for_order_check = -9223372036854775808, dts_ordered = 0 '\000',
  dts_misordered = 0 '\000', inject_global_side_data = 0, display_aspect_ratio = {num = 0, den = 0}, internal = 0x22cad00}

(gdb) print ((*(AVStream *)((*(AVFormatContext*)ic)->streams[0]))->codecpar)

$3 = (AVCodecParameters *) 0x22cba00

(gdb) print *(AVCodecParameters*)((*(AVStream *)((*(AVFormatContext*)ic)->streams[0]))->codecpar)

$4 = {codec_type = AVMEDIA_TYPE_VIDEO, codec_id = AV_CODEC_ID_H264, codec_tag = 875967048, extradata = 0x0, extradata_size = 0, format = -1, bit_rate = 4021700, bits_per_coded_sample = 24, bits_per_raw_sample = 0, profile = -99,
  level = -99, width = 1920, height = 1080, sample_aspect_ratio = {num = 0, den = 1}, field_order = AV_FIELD_UNKNOWN, color_range = AVCOL_RANGE_UNSPECIFIED, color_primaries = AVCOL_PRI_UNSPECIFIED,
  color_trc = AVCOL_TRC_UNSPECIFIED, color_space = AVCOL_SPC_UNSPECIFIED, chroma_location = AVCHROMA_LOC_UNSPECIFIED, video_delay = 0, channel_layout = 0, channels = 0, sample_rate = 0, block_align = 0, frame_size = 0,
  initial_padding = 0, trailing_padding = 0, seek_preroll = 0}

8.监控 codecpar 变量

(gdb) watch ((*(AVStream *)((*(AVFormatContext*)ic)->streams[0]))->codecpar)

Watchpoint 2: ((*(AVStream *)((*(AVFormatContext*)ic)->streams[0]))->codecpar)

9.继续运行【如果变量被修改,程序会停住】

(gdb) c

Continuing.
Watchpoint 2: ((*(AVStream *)((*(AVFormatContext*)ic)->streams[0]))->codecpar)

Old value = (AVCodecParameters *) 0x22cba00
New value = (AVCodecParameters *) 0x0
avformat_find_stream_info (ic=0x22ca500, options=0x22cc500) at libavformat/utils.c:3646
3646        if (!max_analyze_duration) {

10.查看调用栈

(gdb) bt

#0  avformat_find_stream_info (ic=0x22ca500, options=0x22cc500) at libavformat/utils.c:3646
#1  0x0000000000496e7b in open_input_file (o=o@entry=0x7fffffffe0a0, filename=<optimized out>) at fftools/ffmpeg_opt.c:1184
#2  0x000000000049b9cf in open_files (inout=0x1298fb1 "input", open_file=0x496290 <open_input_file>, l=<optimized out>, l=<optimized out>) at fftools/ffmpeg_opt.c:3299
#3  ffmpeg_parse_options (argc=argc@entry=7, argv=argv@entry=0x7fffffffe5a8) at fftools/ffmpeg_opt.c:3339
#4  0x000000000048f5fd in main (argc=7, argv=0x7fffffffe5a8) at fftools/ffmpeg.c:4849

10.查看代码上下文

(gdb) list

3641
3642        av_opt_set(ic, "skip_clear", "1", AV_OPT_SEARCH_CHILDREN);
3643        ic->streams[0]->codecpar=NULL;
3644        max_stream_analyze_duration = max_analyze_duration;
3645        max_subtitle_analyze_duration = max_analyze_duration;
3646        if (!max_analyze_duration) {
3647            max_stream_analyze_duration =
3648            max_analyze_duration        = 5*AV_TIME_BASE;
3649            max_subtitle_analyze_duration = 30*AV_TIME_BASE;
3650            if (!strcmp(ic->iformat->name, "flv"))

11.修复BUG

相关推荐
lxkj_202410 小时前
使用线程局部存储解决ffmpeg中多实例调用下自定义日志回调问题
ffmpeg
runing_an_min14 小时前
ffmpeg视频滤镜:替换部分帧-freezeframes
ffmpeg·音视频·freezeframes
ruizhenggang14 小时前
ffmpeg本地编译不容易发现的问题 — Error:xxxxx not found!
ffmpeg
runing_an_min16 小时前
ffmpeg视频滤镜:提取缩略图-framestep
ffmpeg·音视频·framestep
韩曙亮1 天前
【FFmpeg】FFmpeg 内存结构 ③ ( AVPacket 函数简介 | av_packet_ref 函数 | av_packet_clone 函数 )
ffmpeg·音视频·avpacket·av_packet_clone·av_packet_ref·ffmpeg内存结构
oushaojun21 天前
ubuntu中使用ffmpeg和nginx推流rtmp视频
nginx·ubuntu·ffmpeg·rtmp
莫固执,朋友1 天前
网络抓包工具tcpdump 在海思平台上的编译使用
网络·ffmpeg·音视频·tcpdump
lxkj_20241 天前
修改ffmpeg实现https-flv内容加密
网络协议·https·ffmpeg
cuijiecheng20181 天前
音视频入门基础:MPEG2-TS专题(6)——FFmpeg源码中,获取MPEG2-TS传输流每个transport packet长度的实现
ffmpeg·音视频
XiaoCCCcCCccCcccC1 天前
Linux环境下的基础开发工具 -- 包管理器,vim,gcc/g++,make/makefile,git,gdb/cgdb
linux·c语言·gdb