RK3399E Android 11 将自己的库放到系统库方法

1.系统库的准备

1.1 检查库

检查需要放入系统的系统库libxxx.so是否非TLS 64, 在命令行中输入:

bash 复制代码
/home/xxx/Android/Sdk/ndk/27.3.13750724/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-readelf -l libxxx.so  | grep -A5 TLS

命令行输出:

bash 复制代码
  TLS            0x12f0440 0x00000000012f1440 0x00000000012f1440 0x000000 0x000028 R   0x40
  DYNAMIC        0x13777b8 0x00000000013787b8 0x00000000013787b8 0x0001c0 0x0001c0 RW  0x8
  GNU_RELRO      0x12f1430 0x00000000012f2430 0x00000000012f2430 0x0a7280 0x0a7bd0 R   0x1
  GNU_EH_FRAME   0x64b810 0x000000000064b810 0x000000000064b810 0x04526c 0x04526c R   0x4
  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0x0
  NOTE           0x0002a8 0x00000000000002a8 0x00000000000002a8 0x0000bc 0x0000bc R   0x4

可以看到第一行最后一列为: 0x40, 如果不为0x40, 则需要重新编译so。

另外一种方法是在将libxxx.so 库放到/system/lib64 目录下,然后运行如下命令:

bash 复制代码
adb shell ldd /system/lib64/libxxx.so  # 检查依赖

如果输出如下:

bash 复制代码
	linux-vdso.so.1 => [vdso] (0x7bc9149000)
error: "linker64": executable's TLS segment is underaligned: alignment is 8, needs to be at least 64 for ARM64 Bionic
Aborted

说明该库没有64位对齐, 需要重新编译so库

如果输出为:

cpp 复制代码
	linux-vdso.so.1 => [vdso] (0x78fca6c000)
	liblog.so => /system/lib64/liblog.so (0x78fb726000)
	libdl.so => /apex/com.android.runtime/lib64/bionic/libdl.so (0x78fa2a0000)
	libm.so => /apex/com.android.runtime/lib64/bionic/libm.so (0x78fb748000)
	libc.so => /apex/com.android.runtime/lib64/bionic/libc.so (0x78fa195000)
	libc++.so => /system/lib64/libc++.so (0x78fb786000)

则该库正常。

1.2 重新编译库

在libxxx.so 的任意C++文件中添加如下代码:注意只需要添加一次:

cpp 复制代码
#if defined(__ANDROID__) && defined(__aarch64__)
// 放在任意一个参与编译的 .cpp 文件中即可
extern "C" {
    __attribute__((visibility("default"))) 
    __attribute__((aligned(64)))
    thread_local int _android_tls_alignment_fix = 0;
}
#endif

为了确保它能成功修复对齐问题,请注意以下几点:

  1. 必须被链接进目标库

这个代码片段必须放在会被编译并链接进 librosa.so 的源文件中。你把它放在 rosa/RosaLinux.cc 是完美的,因为你的 CMakeLists.txt 中明确把这个文件编译进了 rosa 库。

  1. 每个动态库(.so)只需要一个

链接器(linker)在生成 librosa.so 时,会扫描所有参与链接的 .o 文件(对象文件)。它会找到所有 thread_local 变量,并取其中最大的对齐值作为整个 PT_TLS 段的对齐属性。只要有一个地方定义了 alignas(64) 的 TLS 变量,整个库的 TLS 就会变成 64 字节对齐。不要在同一个库的多个源文件中放置同名的变量,否则会触发"重定义(multiple definition)"错误。

  1. 不要放在 .h 头文件中

千万不要放在 .h 文件中(除非使用了 static 或 inline 修饰),原因有二:

如果头文件被多个 .cpp 包含,会导致重定义错误。如果头文件没被任何 .cpp 包含,代码就不会被编译,也就没法生效。

cpp 复制代码
adb root
adb remount
# 确认是 lib64 还是 lib
adb push librosa.so /system/lib64/
adb shell chmod 644 /system/lib64/libxxx.so
# 恢复 SELinux 标签
adb shell restorecon /system/lib64/libxx.so
adb reboot
  1. 为什么这个代码能"隔空"生效?

你可能会奇怪:我只是在 RosaLinux.cc 里加了一个没被用到的变量,为什么能解决 spdlog 或其他代码里的错误?

物理结构决定:在一个 ELF 文件(.so)中,所有的线程本地变量(来自不同的 .cpp)最终都会被挤在同一个物理段(Segment)里,这个段叫 PT_TLS。

整体属性:PT_TLS 段作为一个整体,在文件头中只有一个"对齐(Alignment)"属性。链接器必须满足该段内要求最严格(对齐值最大)的那个变量。

木桶效应反转:这就像木桶效应的反面------只要有一块木板足够长,整个木桶的额定长度就会被标记为那个长度。

重新编译后,记得用 llvm-readelf -l librosa.so | grep TLS 确认最后那一列是否变成了 0x40。如果是,你的 adb shell ldd 报错就彻底解决了。

2. 将SO库设置为系统库

2.1 部署SO库

在命令行中依次输入如下命令:

cpp 复制代码
adb root
adb remount
# 确认是 lib64 还是 lib
adb push libxxx.so /system/lib64/
adb shell chmod 644 /system/lib64/libxxx.so
# 恢复 SELinux 标签
adb shell restorecon /system/lib64/libxxx.so
adb reboot

重启后,如果系统正常起来,说明设置成功。

2.2 如何正确测试库是否能加载?

如果你想验证这个库是否能被系统正确识别(且不再报 TLS 对齐错误),你应该使用 Android 链接器 来"追踪"加载过程,而不是直接运行它。

请在终端执行:

bash 复制代码
# 验证库的依赖和对齐是否通过

adb shell LD_TRACE_LOADED_OBJECTS=1 /system/bin/linker64 /system/lib64/libxxx.so

终端输出为:

bash 复制代码
Segmentation fault 

3.公开系统库

通过 public.libraries.txt 公开(推荐系统开发者使用)

如果你希望这个库像 liblog.solibc.so 一样,让所有 App 都能通过 System.loadLibrary 访问,确实需要在 public.libraries.txt 中添加它。

3.1 remount 系统

bash 复制代码
adb root

adb remount

3.2 修改文件:

在 /system/etc/public.libraries.txt 的末尾添加一行

bash 复制代码
libxxx.so

注意(非常重要):

格式:只写库的文件名,不要写路径。

换行符:必须使用 Unix 格式的换行符(LF)。

末尾:确保最后一行后有一个换行符,且没有多余的空格或乱码。

3.3 SELinux 检查:

确保 /system/lib64/libxxx.so 的标签是正确的,否则 App 在加载时会报 Permission Denied:

bash 复制代码
adb shell restorecon /system/lib64/libxxx.so

adb shell restorecon /system/etc/public.libraries.txt

3.4 重启系统:

bash 复制代码
adb reboot

修改该文件后必须重启,Android 的库管理服务才会重新加载配置。

相关推荐
美狐美颜sdk10 小时前
Android直播美颜SDK:选择指南与开发方案
android·人工智能·计算机视觉·第三方美颜sdk·视频美颜sdk·人脸美型sdk
我命由我1234510 小时前
Kotlin 面向对象 - 装箱与拆箱
android·java·开发语言·kotlin·android studio·android jetpack·android-studio
tangweiguo0305198710 小时前
在Windows上编译OpenCV Android原生库全记录
android
我命由我1234510 小时前
Android Jetpack Compose - Snackbar、Box
android·java·java-ee·kotlin·android studio·android jetpack·android-studio
stevenzqzq10 小时前
android 日志过滤说明
android·日志过滤
游戏开发爱好者811 小时前
如何使用 AppUploader 提交上传 iOS 应用
android·ios·小程序·https·uni-app·iphone·webview
非凡ghost11 小时前
3C一体工具箱安卓版(手机维护工具箱)
android·学习·智能手机·软件需求
Jennifer33K11 小时前
AndroidStudio报错:minSdk(APl 33)> deviceSdk(APl 30)
android·gradle·android studio
alexhilton20 小时前
Jetpack Compose内部的不同节点类型
android·kotlin·android jetpack