解决报错:relocation R_AARCH64_ADR_PREL_PG_HI21【ARM64平台编译】

5,232 阅读2分钟

最近在Linux下编译项目时碰到了这个问题,同样的makefile,只要不编译成动态库就不会有这个问题,但要编译成动态库就老是出这个问题.

后来才发现,是-fPIC选项的问题,因为我静态链接了第三方库mupdf库,mupdf库在编译时是没有用到-fPIC选项的,而我自己的项目编译时用了-fPIC选项。之后我修改了mupdf库的makefile,在编译mupdf静态库时,添加了-fPIC选项,编译完成再和自己的项目链接时,就没有这个问题了。

问题

在使用makefile过程中遇到了这样的报错:

/usr/bin/ld: ./obj/libtest.o: relocation R_AARCH64_ADR_PREL_PG_HI21 against symbol _ZNSt8ios_base4InitD1Ev@@GLIBCXX_3.4 which may bind externally can not be used when making a shared object; recompile with -fPIC

/usr/bin/ld: ./obj/libtest.o(.text.startup+0x34): unresolvable R_AARCH64_ADR_PREL_PG_HI21 relocation against symbol _ZNSt8ios_base4InitD1Ev@@GLIBCXX_3.4

make -f LibMakefile_aarch64 
make[1]: 进入目录“/home/huanghe/Desktop/WSDK_Linux/samples”
g++ -std=c++11 -c  -I../include  ./src/libtest.cpp  -Os -D_FX_OS_=_FX_LINUX_DESKTOP_
./src/libtest.cpp: In function ‘int scan_image()’:
./src/libtest.cpp:177:43: warning: ISO C++ forbids converting a string constant to ‘GCH_LPSTR’ {aka ‘char*’} -Wwrite-strings]
     char *devlist = gch_GetDevicesList(";"); //返回 型号1;型号2; 需要自行分隔
                                           ^
./src/libtest.cpp:315:1: warning: control reaches end of non-void function [-Wreturn-type]
 }
 ^
g++ -fPIC -shared -o .//libtest.so ./obj/*.o  -L../lib/aarch64  -Xlinker "-(" -Wl,-rpath=../lib/aarch64/ -lScanImagesdk[aarch64] -Xlinker "-)" -lz -ldl # -fopenmp -lfontconfig 
/usr/bin/ld: ./obj/libtest.o: relocation R_AARCH64_ADR_PREL_PG_HI21 against symbol `_ZNSt8ios_base4InitD1Ev@@GLIBCXX_3.4' which may bind externally can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: ./obj/libtest.o(.text.startup+0x34): unresolvable R_AARCH64_ADR_PREL_PG_HI21 relocation against symbol `_ZNSt8ios_base4InitD1Ev@@GLIBCXX_3.4'
/usr/bin/ld: 最后的链结失败: bad value
collect2: error: ld returned 1 exit status
make[1]: *** [LibMakefile_aarch64:42:all] 错误 1
make[1]: 离开目录“/home/huanghe/Desktop/WSDK_Linux/samples”
make: *** [Makefile:20:default] 错误 2

解决

  1. 加上-mcmodel=large编译选项 -mcmodel=large 使可执行文件使用64位绝对地址访问数据段,这会减慢内核速度并使其更大。

  2. 加上 -O2

#Winmage WSDK project DEMO for aarch64 CPU
#

# Tools.
CC			=	gcc
LD			=	gcc
RM			=	-/bin/rm -f

#
# Parameters for tools.
REL_FLAGS	=	-Os -D_FX_OS_=_FX_LINUX_DESKTOP_

# Parameters for the current project.
SRC_DIR		=	./src

SOURCES         =       $(SRC_DIR)/libtest.cpp $(SRC_DIR)/json.hpp


						
OBJ_DIR		=	./obj
REL_BIN_DIR	=	./
LIB_DIR		=	../lib/aarch64
INC_DIRS	=       -I../include #-I/usr/local/Trolltech/Qt-4.8.7/include
			 

REL_DIRS	=	-L$(LIB_DIR)

REL_LIBS	=   -Xlinker "-(" -Wl,-rpath=../lib/aarch64/ -lScanImagesdk[aarch64] -Xlinker "-)"


REL_OBJ_DIR	=	$(OBJ_DIR)


REL_BIN         =	libtest.so

#
all: $(SOURCES)
	$(CC) -O2 -mcmodel=large -c $(CFLAGS) $(INC_DIRS) $(SOURCES)  $(REL_FLAGS)
	@-mkdir -p $(REL_OBJ_DIR)
	@mv *.o $(REL_OBJ_DIR)
	@-mkdir -p $(REL_BIN_DIR)
	$(LD) -O2 -mcmodel=large -fPIC -shared -o $(REL_BIN_DIR)/$(REL_BIN) $(REL_OBJ_DIR)/*.o  $(REL_DIRS)  $(REL_LIBS) -lz -ldl # -fopenmp -lfontconfig 

#

clean:
	$(RM) $(REL_BIN_DIR)/$(REL_BIN) $(REL_OBJ_DIR)/*.o  *.o		
						

参考:

ARM64平台编译stream、netperf出错解决办法

无法解决R_AARCH64_ADR_PREL_PG_HI21重定向于符号__stack_chk_guard@GLIBC_2.17