解決ffmpegの静的ライブラリシンボルの競合とMp4V2

まず、なぜ静的シンボルを競合します

  特定の形式で格納されたプログラムやデータのコードに従っているマッチョバイナリ型、またはWindows上のPE形式、またはLinux上のELF形式か

  おおよそ次のセグメントに分割Linuxなどの実行可能ファイル形式

  参考:https://www.ibm.com/developerworks/cn/linux/l-excutff/    

 

  異なるオペレーティングシステムのサポートの実行可能ファイル形式は同じではありませんが、実行可能ファイル上の異なるプロセスの実行プラットフォームは同じです。実行可能ファイルを読んだ後、異なるセグメントを解決し、解決し、プロセスにマップされ、

  メモリの配布プロセスは、データおよび権利管理を整理するために、そう簡単にセグメント化されています。

  静的ライブラリファイル異なる、その後のプロセスにマッピングされ、当然のことながら柔軟な接続があり、どのように呼び出し、B、時間は、使用する他のライブラリで実現される機能を想像してみてください。

  まだ方法Bのアドレスを知っている方法。

  プロセスにマッピングされたBライブラリ、メソッド呼び出し、この関数(シンボル)の前に、オペレーティング・システムはシンボルを確立するプロセスにおけるシンボルアドレスを発見した - >プロセスの際の関数のエントリポイントは、シンボル・テーブル・マッピングのプロセスであり、

  また、これは釣り針原理である、上記の私の理解です。

 

第二に、分析ツールを導入します

  ツールNMは、バイナリファイル、シンボルをスキャンする実行可能ファイル、および関連情報を分析するために使用することができます。

NAME
       nm - list symbols from object files

SYNOPSIS
       nm [-A|-o|--print-file-name] [-a|--debug-syms]
          [-B|--format=bsd] [-C|--demangle[=style]]
          [-D|--dynamic] [-fformat|--format=format]
          [-g|--extern-only] [-h|--help]
          [-l|--line-numbers] [-n|-v|--numeric-sort]
          [-P|--portability] [-p|--no-sort]
          [-r|--reverse-sort] [-S|--print-size]
          [-s|--print-armap] [-t radix|--radix=radix]
          [-u|--undefined-only] [-V|--version]
          [-X 32_64] [--defined-only] [--no-demangle]
          [--plugin name] [--size-sort] [--special-syms]
          [--synthetic] [--target=bfdname]
          [objfile...]

DESCRIPTION
       GNU nm lists the symbols from object files objfile....  If no object
       files are listed as arguments, nm assumes the file a.out.

       For each symbol, nm shows:
        # ... run man nm for detials.

  不同符号的不同类型

Value Descripition Note
A The symbol's value is absolute, and will not be changed by further linking. 符号绝对,链接过程不会改变
B/b The symbol is in the uninitialized data section (known as BSS). 非初始化符号
C The symbol is common. 公有符号,链接时会被同名符号覆盖
D/d The symbol is in the initialized data section. 初始化符号
G/g The symbol is in an initialized data section for small objects. 初始化符号,面向小数据访问优化
I The symbol is an indirect reference to another symbol. 其它符号的间接引用
N The symbol is a debugging symbol. 调试符号
P The symbols is in a stack unwind section. 栈区符号(清空)
R/r The symbol is in a read only data section. 符号只读
S/s The symbol is in an uninitialized data section for small objects. 非初始化符号,面向小数据访问优化
T/t The symbol is in the text (code) section. 代码区符号
U The symbol is undefined. 未定义或在外部定义的符号
u The symbol is a unique global symbol. 全局唯一,GNU保留符
V/v The symbol is a weak object. 弱定义符(详见C++强弱符号定义)
W/w The symbol is a weak symbol that has not been specifically tagged as a weak object symbol. emm...绕口令符号
- The symbol is a stabs symbol in an a.out object file. stabs格式符号
? The symbol type is unknown, or object file format specific. NM也不认识的符号

  比如:(参考 https://www.jianshu.com/p/a86bd1b8e4a5
  
rew@rew:/usr/lib64$ nm libpthread.a

nptl-init.o:
                 U __default_pthread_attr
                 U __default_pthread_attr_lock
                 U _dl_cpuclock_offset
                 U _dl_get_tls_static_info
                 U _dl_init_static_tls
                 U _dl_pagesize
                 U _dl_wait_lookup_done
                 U __fork_generation
                 U __getrlimit
                 U __is_smp
                 U __libc_fatal
0000000000000008 C __libc_multiple_threads_ptr
                 U __libc_pthread_init
                 U __libc_setup_tls
                 U __libc_sigaction
                 U __libc_stack_end
                 U __lll_lock_wait_private
                 U __lll_unlock_wake_private
0000000000000000 b __nptl_initial_report_events
00000000000001b0 T __nptl_set_robust
                 U __nptl_setxid_error
0000000000000000 r nptl_version
00000000000004b0 T __pthread_get_minstack
00000000000001d0 T __pthread_initialize_minimal
00000000000001d0 T __pthread_initialize_minimal_internal

  

三、问题解决过程

  最近发现,米家App中新引入了一个Mp4V2的.a静态库后,ffmpeg工作不正常了,Xcode调试过程中没有任何信息,只能看到crash  

  

  经过一番思索,猜测可能是这个库和ffmpeg本来的库存在符号冲突,使用nm工具导出所有符号

  在静态库libmp4v2.a同级目录下面执行 命令

nm -U libmp4v2.a  | grep  -v ' t ' | grep -v ' s ' | grep -v ' d ' |  grep -v ' b ' | awk '{print $3}' | tr -s '\n' > symbol.txt

  看下symbol.txt的结果

 cat symbol.txt

  

  生成的符号结果很多,其中因为.a是fat结构,很多符号是冲突的。

  一些符号明显带有mp4v2的标记,不可能跟ffmpeg冲突,所以,要对结果过滤下

  编写一段脚本代码,过滤这个文本

  过滤掉Mp4相关,并且去重

#!/usr/bin/env python3
# _*_ coding:utf-8 _*_
#
# @Version : 1.0
# @Time    : 2019/6/29 3:13
# @Author  : ddyt
# @File    : LessSymbol.py
#
# 符号表处理

import cxxfilt

if __name__ == '__main__':
    s = set()
    file = open("symbol.txt")
    fileLines = file.readlines()
    for line in fileLines:
        if "mp4" not in line and line.rstrip() not in s and "MP4" not in line:
            print(cxxfilt.demangle(line.rstrip()))
            s.add(line.rstrip())

 

 过滤结果  

   

  部分符号看起来很复杂,这个是C++类的方法经过编译器mangle之后生成的

  将所有内容进行demangle,打开 https://demangler.com/,输入脚本生成的结果,demangle

  可以看到一些复杂的符号,是C++ string的符号产生的,忽略掉这些符号

  

  可以看到一些特殊的方法

_av_free
_av_freep
_av_log2
_av_log2_16bit
_av_malloc
_av_mallocz
_av_realloc
_av_realloc_array
_av_realloc_f
_av_reallocp
_av_reallocp_array
_avio_w8
_avio_wb16
_avio_wb32
_avio_write
_ff_avc_find_startcode
_ff_avc_parse_nal_units
_ff_avc_parse_nal_units_buf
_ff_golomb_vlc_len
_ff_interleaved_dirac_golomb_vlc_code
_ff_interleaved_golomb_vlc_len
_ff_interleaved_se_golomb_vlc_code
_ff_interleaved_ue_golomb_vlc_code
_ff_isom_write_hvcc
_ff_se_golomb_vlc_code
_ff_ue_golomb_len
_ff_ue_golomb_vlc_code
_mov_assm_hvcc_data
_mov_hvcc_add_nal_unit
_mov_write_hev1_tag
_mov_write_hvcc_tag

  这些带有ff前缀和av前缀的,就是来自ffmpeg,这些符号就是冲突的根源

再看下crash时候的堆栈,最后一个方法avio_write在上面的符号中

 

 

  现在冲突的原因找到了,处理思路分为两种

  1、修改冲突的函数的名字

  2、使用宏定义来修改函数的名字

  这里采用第一种,使用Visual Code打开代码目录

  

  然后,针对可能冲突的符号,逐一全局查找替换

  

  

  到此,工作基本完成

  修改完毕之后,合并测试

 

 

おすすめ

転載: www.cnblogs.com/doudouyoutang/p/11106725.html