Skip to content

Commit 0d20886

Browse files
feat: optimize soinfo set/get functions, symbol lookup and implement so relocation
1 parent fcf240b commit 0d20886

19 files changed

+2546
-710
lines changed

library/src/main/cpp/include/fake_linker.h

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ typedef struct {
267267
FunPtr(SymbolAddress *, soinfo_get_import_symbol_address, SoinfoPtr soinfo_ptr, const char *name, int *out_error);
268268

269269
/**
270-
* @briefSpecify the soinfo pointer to get the export symbol address of the
270+
* @brief Specify the soinfo pointer to get the export symbol address of the
271271
* specified name
272272
*
273273
* @param soinfo_ptr Specify the soinfo pointer
@@ -414,11 +414,22 @@ typedef struct {
414414
*/
415415
FunPtr(bool, call_manual_relocation_by_names, SoinfoPtr global_lib, int len, const char *target_names[]);
416416

417+
/**
418+
* @brief Specify the soinfo pointer to get the first export symbol address of the
419+
* specified name prefix
420+
*
421+
* @param soinfo_ptr Specify the soinfo pointer
422+
* @param name Export symbol name
423+
* @param[out] out_error Write error code on error exists
424+
* @return Symbolic address or nullptr
425+
*/
426+
FunPtr(SymbolAddress, soinfo_get_export_symbol_address_by_prefix, SoinfoPtr soinfo_ptr, const char *name,
427+
int *out_error);
428+
417429
/**
418430
* @brief New version expansion reserved slot
419431
*
420432
*/
421-
FunPtr(void, unused0);
422433
FunPtr(void, unused1);
423434
FunPtr(void, unused2);
424435
FunPtr(void, unused3);
@@ -816,10 +827,21 @@ typedef struct {
816827
* LINKER_VERBOSITY_TRACE 1
817828
* LINKER_VERBOSITY_DEBUG 2
818829
*
830+
* Android 15+ new debug config
831+
* calls : 1 << 0
832+
* cfi : 1 << 1
833+
* dynamic : 1 << 2
834+
* lookup : 1 << 3
835+
* reloc : 1 << 4
836+
* props : 1 << 5
837+
*
819838
* @param level log level, the larger the value, the more logs
820839
*/
821840
FunPtr(bool, set_ld_debug_verbosity, int level);
822841

842+
FunPtr(uint64_t, find_library_symbol_by_prefix, const char *library_name, const char *symbol_name,
843+
const FindSymbolType symbol_type);
844+
823845
} FakeLinker;
824846

825847
#undef FunPtr
@@ -836,23 +858,50 @@ extern void fakelinker_module_init(JNIEnv *env, SoinfoPtr fake_soinfo, const Fak
836858

837859
enum FakeLinkerMode {
838860
/**
839-
* Initialize soinfo, namespace feature
861+
* Initialize soinfo, initialize all linker functions by default,
862+
* if only some functions are needed, please add kInitLinkerXXXX flag
840863
*/
841864
kFMSoinfo = 1,
842865
/**
843866
* Initialize android native hook feature
844867
*/
845-
kFMNativeHook = 2,
868+
kFMNativeHook = 1 << 1,
846869

847870
/**
848871
* Register the Java functions, by default, the FakeLinker class will return success even if the registration fails,
849872
* whereas non-default classes will only return success if the registration is successful.
850873
*/
851-
kFMJavaRegister = 4,
874+
kFMJavaRegister = 1 << 2,
852875
/**
853876
* The default FakeLinker class or non-default classes must return success only if the registration is successful.
854877
*/
855-
kFMForceJavaRegister = 8,
878+
kFMForceJavaRegister = 1 << 3,
879+
/**
880+
* Initialize only linker debug symbols
881+
*
882+
*/
883+
kInitLinkerDebug = 1 << 4,
884+
/**
885+
* Initialize only linker dlopen/dlsym to use symbols
886+
*
887+
*/
888+
kInitLinkerDlopenDlSym = 1 << 5,
889+
/**
890+
* Initialize only linker namespace symbols
891+
*
892+
*/
893+
kInitLinkerNamespace = 1 << 6,
894+
/**
895+
* Initialize only linker handler symbols
896+
*
897+
*/
898+
kInitLinkerHandler = 1 << 7,
899+
/**
900+
* Initialize only linker memory symbols
901+
*
902+
*/
903+
kInitLinkerMemory = 1 << 8,
904+
856905
};
857906

858907
/**

library/src/main/cpp/include/linker_macros.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#define ANDROID_GE_V
1818
#define ANDROID_LE_M
1919
#define ANDROID_LE_L1
20+
#define ANDROID_LE_N1
21+
#define ANDROID_LE_O
2022
#define ANDROID_LE_O1
2123
#define ANDROID_LE_S
2224
#define ANDROID_LE_U

library/src/main/cpp/include/scoped_local_ref.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ class ScopedLocalRef {
5252

5353
T get() const { return mLocalRef; }
5454

55+
operator bool() const { return mLocalRef != nullptr; }
56+
5557
private:
5658
JNIEnv *const mEnv;
5759
T mLocalRef;

library/src/main/cpp/include/type.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,18 @@ struct return_type_trait<Return (*)(Args...)> {
1010
using type = Return;
1111
};
1212

13+
template <typename P>
14+
using return_type_trait_t = typename return_type_trait<P>::type;
15+
1316
template <typename P>
1417
struct return_type_object_trait;
1518

1619
template <typename Object, typename Return, typename... Args>
1720
struct return_type_object_trait<Return (Object::*)(Args...)> {
1821
using type = Return;
1922
};
23+
template <typename P>
24+
using return_type_object_trait_t = typename return_type_object_trait<P>::type;
2025

2126
template <typename P>
2227
struct member_type_trait;
@@ -36,10 +41,27 @@ struct member_type_trait<const char (Object::*)[N]> {
3641
using type = const char *;
3742
};
3843

44+
template <typename P>
45+
using member_type_trait_t = typename member_type_trait<P>::type;
46+
3947
template <typename P>
4048
struct member_ref_type_trait;
4149

4250
template <typename Type, typename Object>
4351
struct member_ref_type_trait<Type Object::*> {
44-
using type = typename std::add_lvalue_reference<Type>::type;
52+
using type = typename std::add_lvalue_reference_t<Type>;
53+
};
54+
55+
template <typename P>
56+
using member_ref_type_trait_t = typename member_ref_type_trait<P>::type;
57+
58+
template <typename P>
59+
struct const_member_ref_type_trait;
60+
61+
template <typename Type, typename Object>
62+
struct const_member_ref_type_trait<Type Object::*> {
63+
using type = std::add_lvalue_reference_t<std::add_const_t<Type>>;
4564
};
65+
66+
template <typename P>
67+
using const_member_ref_type_trait_t = typename const_member_ref_type_trait<P>::type;

library/src/main/cpp/linker/linker_export.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,17 @@ static SymbolAddress soinfo_get_export_symbol_address_impl(SoinfoPtr soinfo_ptr,
216216
CHECK_PARAM_PTR(soinfo_ptr, kErrorSoinfoNull);
217217
CHECK_PARAM_PTR(name, kErrorParameterNull);
218218
auto *info = static_cast<soinfo *>(soinfo_ptr);
219+
void *result = info->find_export_symbol_by_prefix(name);
220+
CHECK_ERROR(result, kErrorSymbolNotFoundInSoinfo);
221+
return result;
222+
}
223+
224+
static SymbolAddress soinfo_get_export_symbol_address_prefix_impl(SoinfoPtr soinfo_ptr, const char *name,
225+
int *out_error) {
226+
RET_SUCCESS();
227+
CHECK_PARAM_PTR(soinfo_ptr, kErrorSoinfoNull);
228+
CHECK_PARAM_PTR(name, kErrorParameterNull);
229+
auto *info = static_cast<soinfo *>(soinfo_ptr);
219230
void *result = info->find_export_symbol_address(name);
220231
CHECK_ERROR(result, kErrorSymbolNotFoundInSoinfo);
221232
return result;
@@ -681,6 +692,7 @@ static uint64_t find_library_symbol_impl(const char *library_name, const char *s
681692
return 0;
682693
}
683694

695+
684696
static MEMORY_FREE uint64_t *find_library_symbols_impl(const char *library_name, const FindSymbolUnit *symbols,
685697
int size) {
686698
if (!library_name || !symbols || size < 1) {
@@ -780,7 +792,7 @@ C_API API_PUBLIC FakeLinker g_fakelinker_export = {
780792
call_manual_relocation_by_soinfos_impl,
781793
call_manual_relocation_by_name_impl,
782794
call_manual_relocation_by_names_impl,
783-
nullptr, /* unused0 */
795+
soinfo_get_export_symbol_address_prefix_impl,
784796
nullptr, /* unused1 */
785797
nullptr, /* unused2 */
786798
nullptr, /* unused3 */
@@ -841,6 +853,7 @@ C_API API_PUBLIC FakeLinker g_fakelinker_export = {
841853
find_library_symbol_impl,
842854
find_library_symbols_impl,
843855
set_ld_debug_verbosity_impl,
856+
nullptr,
844857
};
845858

846859
C_API const FakeLinker *get_fakelinker() { return &g_fakelinker_export; }

library/src/main/cpp/linker/linker_globals.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ void ProxyLinker::ChangeSoinfoOfNamespace(soinfo *so, android_namespace_t *np) {
168168
}
169169
LinkerBlockLock lock;
170170
so->get_primary_namespace()->remove_soinfo(so);
171-
so->get_primary_namespace() = np;
171+
so->set_primary_namespace(np);
172172
np->add_soinfo(so);
173173
}
174174

@@ -183,7 +183,7 @@ void ProxyLinker::AddSoinfoToDefaultNamespace(soinfo *si) {
183183
for (auto &np : ProxyLinker::GetAllNamespace(true)) {
184184
if (strcmp(np->get_name(), DEFAULT_NAMESPACE_NAME) == 0) {
185185
si->get_primary_namespace()->remove_soinfo(si);
186-
si->get_primary_namespace() = np;
186+
si->set_primary_namespace(np);
187187
np->add_soinfo(si);
188188
break;
189189
}
@@ -546,7 +546,13 @@ bool ProxyLinker::SetLdDebugVerbosity(int level) {
546546
*p = level;
547547
return true;
548548
} else if (auto *config = linker_symbol.g_linker_debug_config.Get()) {
549-
config->any = true;
549+
config->calls = level & 1;
550+
config->cfi = level & (1 << 1);
551+
config->dynamic = level & (1 << 2);
552+
config->lookup = level & (1 << 3);
553+
config->reloc = level & (1 << 4);
554+
config->props = level & (1 << 5);
555+
config->any = level & (0b111111);
550556
return true;
551557
}
552558
return false;
@@ -659,7 +665,7 @@ bool ProxyLinker::ManualRelinkLibraries(soinfo *global, const std::vector<std::s
659665
if (__predict_false(global == nullptr) || __predict_false(sonames.empty())) {
660666
return false;
661667
}
662-
symbol_relocations rels = global->get_global_soinfo_export_symbols(filters);
668+
symbol_relocations rels = global->get_global_soinfo_export_symbols(false, filters);
663669
if (rels.empty()) {
664670
LOGW("Function symbols not exported by the global library : %s",
665671
global->get_soname() == nullptr ? "(null)" : global->get_soname());
@@ -682,7 +688,7 @@ bool ProxyLinker::ManualRelinkLibraries(soinfo *global, int len, const std::vect
682688
if (__predict_false(global == nullptr) || __predict_false(targets.empty())) {
683689
return false;
684690
}
685-
symbol_relocations rels = global->get_global_soinfo_export_symbols(filters);
691+
symbol_relocations rels = global->get_global_soinfo_export_symbols(false, filters);
686692
if (rels.empty()) {
687693
LOGW("Function symbols not exported by the global library : %s",
688694
global->get_soname() == nullptr ? "(null)" : global->get_soname());
@@ -704,7 +710,7 @@ bool ProxyLinker::ManualRelinkLibrary(soinfo *global, soinfo *child, std::vector
704710
if (__predict_false(global == nullptr)) {
705711
return false;
706712
}
707-
symbol_relocations rels = global->get_global_soinfo_export_symbols(filters);
713+
symbol_relocations rels = global->get_global_soinfo_export_symbols(false, filters);
708714
if (rels.empty()) {
709715
LOGW("Function symbols not exported by the global library : %s",
710716
global->get_soname() == nullptr ? "(null)" : global->get_soname());

library/src/main/cpp/linker/linker_globals.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,11 +127,11 @@ class ProxyLinker {
127127

128128
bool SystemRelinkLibraries(const std::vector<std::string> &sonames);
129129

130+
soinfo_list_t GetSoinfoGlobalGroup(soinfo *root);
131+
130132
private:
131133
ANDROID_LE_M soinfo_list_t GetGlobalGroupM();
132134

133-
soinfo_list_t GetSoinfoGlobalGroup(soinfo *root);
134-
135135
ANDROID_GE_M bool RelinkSoinfoImplM(soinfo *si);
136136

137137
ANDROID_LE_L1 bool RelinkSoinfoImplL(soinfo *si);

library/src/main/cpp/linker/linker_main.cpp

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,14 @@ bool init_success = false;
2424

2525
using FakeLinkerModulePtr = void (*)(JNIEnv *, SoinfoPtr, const FakeLinker *);
2626

27-
static void Init() {
27+
static void Init(fakelinker::LinkerSymbolCategory category) {
2828
static bool initialized = false;
2929
if (!initialized) {
3030
soinfo::Init();
3131
android_namespace_t::Init();
32-
fakelinker::linker_symbol.InitSymbolName();
3332
}
3433
if (!init_success) {
35-
init_success = fakelinker::linker_symbol.LoadSymbol();
34+
init_success = fakelinker::linker_symbol.LoadSymbol(category);
3635
}
3736
initialized = true;
3837
}
@@ -133,7 +132,30 @@ C_API int init_fakelinker(JNIEnv *env, FakeLinkerMode mode, const char *java_cla
133132
static bool native_hook_initialized = false;
134133
static bool java_register_initialized = false;
135134
if (mode & FakeLinkerMode::kFMSoinfo) {
136-
Init();
135+
int symbol_type = fakelinker::LinkerSymbolCategory::kLinkerAll;
136+
if (mode &
137+
(FakeLinkerMode::kInitLinkerDebug | FakeLinkerMode::kInitLinkerDlopenDlSym |
138+
FakeLinkerMode::kInitLinkerNamespace | FakeLinkerMode::kInitLinkerHandler |
139+
FakeLinkerMode::kInitLinkerMemory)) {
140+
symbol_type = 0;
141+
if (mode & FakeLinkerMode::kInitLinkerDebug) {
142+
symbol_type |= fakelinker::LinkerSymbolCategory::kLinkerDebug;
143+
}
144+
if (mode & FakeLinkerMode::kInitLinkerDlopenDlSym) {
145+
symbol_type |= fakelinker::LinkerSymbolCategory::kDlopenDlSym;
146+
}
147+
if (mode & FakeLinkerMode::kInitLinkerNamespace) {
148+
symbol_type |= fakelinker::LinkerSymbolCategory::kNamespace;
149+
}
150+
if (mode & FakeLinkerMode::kInitLinkerHandler) {
151+
symbol_type |= fakelinker::LinkerSymbolCategory::kSoinfoHandler;
152+
}
153+
if (mode & FakeLinkerMode::kInitLinkerMemory) {
154+
symbol_type |= fakelinker::LinkerSymbolCategory::kSoinfoMemory;
155+
}
156+
}
157+
158+
Init(static_cast<fakelinker::LinkerSymbolCategory>(symbol_type));
137159
if (!init_success) {
138160
return 1;
139161
}

0 commit comments

Comments
 (0)