首先编译好 ffmpeg
静态库,在libsav
链接时提示
/usr/bin/ld: /opt/data/data/work/source/library/libSAV/../../public/lib/ffmpeg-94a52417/x64/lib/libavcodec.a(h264.o): relocation R_X86_64_PC32 against symbol `ff_h264_cabac_tables' can not be used when making a shared object; recompile with -fPIC
但是经查询,其实 ffmpeg
编译时是加了-fPIC
选项的。继续查找 在libavcodec/h264.c
文件中引用了头文件libavcodec/cabac_functions.h
,头文件中定义了如下字段
extern uint8_t ff_h264_cabac_tables[512 + 4*2*64 + 4*64 + 63];
static uint8_t * const ff_h264_norm_shift = ff_h264_cabac_tables + H264_NORM_SHIFT_OFFSET;
static uint8_t * const ff_h264_lps_range = ff_h264_cabac_tables + H264_LPS_RANGE_OFFSET;
static uint8_t * const ff_h264_mlps_state = ff_h264_cabac_tables + H264_MLPS_STATE_OFFSET;
static uint8_t * const ff_h264_last_coeff_flag_offset_8x8 = ff_h264_cabac_tables + H264_LAST_COEFF_FLAG_OFFSET_8x8_OFFSET;
h264.c
引用此头文件但并没有使用此定义的变量
通过readelf -r libavcodec/h264.o
查询到变量ff_h264_cabac_tables
在.rela.text
中,经单文件模拟测试,发现应该有.rela.data.rel.ro
段,但此h264.o
中并没有,于在编译flags
中进行查找测试,发现-O
选项使用此段不存在,故将其去除,有了此段,如下所示
Relocation section '.rela.data.rel.ro' at offset 0xa7550 contains 10 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000000000 00a000000001 R_X86_64_64 0000000000000000 ff_h264_cabac_tables + 0
000000000008 00a000000001 R_X86_64_64 0000000000000000 ff_h264_cabac_tables + 200
000000000010 00a000000001 R_X86_64_64 0000000000000000 ff_h264_cabac_tables + 400
000000000018 00a000000001 R_X86_64_64 0000000000000000 ff_h264_cabac_tables + 500
但是这并没有解决问题,依然有提示,因为在此h264.o
中存在
Relocation section '.rela.text' at offset 0xa2b10 contains 792 entries:
Offset Info Type Sym. Value Sym. Name + Addend
00000000003e 009f00000004 R_X86_64_PLT32 0000000000000000 av_mallocz - 4
00000000038d 00a000000002 R_X86_64_PC32 0000000000000000 ff_h264_cabac_tables - 4
00000000047b 00a000000002 R_X86_64_PC32 0000000000000000 ff_h264_cabac_tables - 4
这个信息,其中R_X86_64_PC32
为相对地址重定位,并非动态链接所用,怀疑是否是此问题。因为自测模拟程序中并没有.rela.text
此段。
在编译ffmpeg
时加入--disable-asm
选项可以修正这个问题,使ff_h264_cabac_tables
可重定位。
当使能 asm
的时候,会包含并没有文件libavcodec/x86/cabac.h
,其中有部分与此变量有关的汇编代码
#ifdef BROKEN_RELOCATIONS
void *tables;
__asm__ volatile(
"lea "MANGLE(ff_h264_cabac_tables)", %0 \n\t"
: "=&r"(tables)
);
#endif
在 64bit 中 MANGLE(X) 被定义为 #define MANGLE(X) #X "(%%rip)"
, 其中 %%rip
是intel 针对64bit的特殊功能,用于地址重定位等作用。 目前到此为止,猜测是否是此汇编代码强制将此变量的重定位信息改变。