2020 size_t solist_realpath_offset = 0x174 ;
2121#endif
2222
23+ size_t solist_fini_array_size_offset = 0x0 ;
24+ size_t solist_fini_offset = 0x0 ;
25+
2326static const char * (* get_realpath_sym )(SoInfo * ) = NULL ;
24- static void (* soinfo_free )(SoInfo * ) = NULL ;
27+ static void (* soinfo_unload )(SoInfo * ) = NULL ;
2528static SoInfo * (* find_containing_library )(const void * p ) = NULL ;
2629struct link_map * r_debug_tail = NULL ;
2730
@@ -60,6 +63,8 @@ static SoInfo *somain = NULL;
6063static size_t * g_module_load_counter = NULL ;
6164static size_t * g_module_unload_counter = NULL ;
6265
66+ static struct link_map * find_link_map (SoInfo * si );
67+
6368static bool solist_init () {
6469 #ifdef __LP64__
6570 ElfImg * linker = ElfImg_create ("/system/bin/linker64" , NULL );
@@ -102,37 +107,25 @@ static bool solist_init() {
102107 if (get_realpath_sym == NULL ) {
103108 LOGE ("Failed to find get_realpath __dl__ZNK6soinfo12get_realpathEv" );
104109
105- ElfImg_destroy (linker );
106-
107- somain = NULL ;
108-
109- return false;
110+ goto solist_init_error ;
110111 }
111112
112113 LOGD ("%p is get_realpath" , (void * )get_realpath_sym );
113114
114- soinfo_free = (void (* )(SoInfo * ))getSymbAddressByPrefix (linker , "__dl__ZL11soinfo_freeP6soinfo" );
115- if (soinfo_free == NULL ) {
116- LOGE ("Failed to find soinfo_free __dl__ZL11soinfo_freeP6soinfo*" );
117-
118- ElfImg_destroy (linker );
119-
120- somain = NULL ;
115+ soinfo_unload = (void (* )(SoInfo * ))getSymbAddressByPrefix (linker , "__dl__ZL13soinfo_unloadP6soinfo" );
116+ if (soinfo_unload == NULL ) {
117+ LOGE ("Failed to find soinfo_unload __dl__ZL13soinfo_unloadP6soinfo*" );
121118
122- return false ;
119+ goto solist_init_error ;
123120 }
124121
125- LOGD ("%p is soinfo_free " , (void * )soinfo_free );
122+ LOGD ("%p is soinfo_unload " , (void * )soinfo_unload );
126123
127124 find_containing_library = (SoInfo * (* )(const void * ))getSymbAddress (linker , "__dl__Z23find_containing_libraryPKv" );
128125 if (find_containing_library == NULL ) {
129126 LOGE ("Failed to find find_containing_library __dl__Z23find_containing_libraryPKv" );
130127
131- ElfImg_destroy (linker );
132-
133- somain = NULL ;
134-
135- return false;
128+ goto solist_init_error ;
136129 }
137130
138131 LOGD ("%p is find_containing_library" , (void * )find_containing_library );
@@ -141,54 +134,74 @@ static bool solist_init() {
141134 if (r_debug_tail == NULL ) {
142135 LOGE ("Failed to find r_debug_tail __dl__ZL10r_debug_tail" );
143136
144- ElfImg_destroy (linker );
137+ goto solist_init_error ;
138+ }
145139
146- somain = NULL ;
140+ SoInfo * solinker = (SoInfo * )getSymbValueByPrefix (linker , "__dl__ZL8solinker" );
141+ if (solinker == NULL ) {
142+ LOGE ("Failed to find solinker __dl__ZL8solinker" );
147143
148- return false;
144+ goto solist_init_error ;
145+ }
146+
147+ LOGD ("%p is solinker" , (void * )solinker );
148+
149+ struct link_map * solinker_map = find_link_map (solinker );
150+ if (solinker_map == NULL ) {
151+ LOGE ("Failed to find link_map for solinker" );
152+
153+ goto solist_init_error ;
149154 }
150155
156+ LOGD ("%p is solinker_map" , (void * )solinker_map );
157+
151158 g_module_load_counter = (size_t * )getSymbAddress (linker , "__dl__ZL21g_module_load_counter" );
152159 if (g_module_load_counter != NULL ) LOGD ("found symbol g_module_load_counter" );
153160
154161 g_module_unload_counter = (size_t * )getSymbAddress (linker , "__dl__ZL23g_module_unload_counter" );
155162 if (g_module_unload_counter != NULL ) LOGD ("found symbol g_module_unload_counter" );
156163
164+ ElfImg_destroy (linker );
165+
157166 for (size_t i = 0 ; i < 1024 / sizeof (void * ); i ++ ) {
158167 size_t possible_size_of_somain = * (size_t * )((uintptr_t )somain + i * sizeof (void * ));
159168
160- if (possible_size_of_somain < 0x100000 && possible_size_of_somain > 0x100 ) {
169+ if (solist_size_offset == 0 && possible_size_of_somain < 0x100000 && possible_size_of_somain > 0x100 ) {
161170 solist_size_offset = i * sizeof (void * );
162171
163172 LOGD ("solist_size_offset is %zu * %zu = %p" , i , sizeof (void * ), (void * )solist_size_offset );
173+ }
174+
175+ struct link_map * possible_link_map_head = (struct link_map * )((uintptr_t )solinker + i * sizeof (void * ));
176+ if (possible_link_map_head -> l_name == solinker_map -> l_name ) {
177+
178+ #ifdef __arm__
179+ /* INFO: For arm32, ARM_exidx and ARM_exidx_count is defined between them. */
180+ solist_fini_array_size_offset = (i - 6 ) * sizeof (void * );
181+ solist_fini_offset = (i - 5 ) * sizeof (void * );
182+
183+ LOGD ("solist_fini_array_size_offset is %zu * %zu = %p" , (i - 6 ), sizeof (void * ), (void * )solist_fini_array_size_offset );
184+ LOGD ("solist_fini_offset is %zu * %zu = %p" , (i - 4 ), sizeof (void * ), (void * )solist_fini_offset );
185+ #else
186+ solist_fini_array_size_offset = (i - 4 ) * sizeof (void * );
187+ solist_fini_offset = (i - 2 ) * sizeof (void * );
188+
189+ LOGD ("solist_fini_array_size_offset is %zu * %zu = %p" , (i - 4 ), sizeof (void * ), (void * )solist_fini_array_size_offset );
190+ LOGD ("solist_fini_offset is %zu * %zu = %p" , (i - 2 ), sizeof (void * ), (void * )solist_fini_offset );
191+ #endif
164192
165193 break ;
166194 }
167195 }
168196
169- ElfImg_destroy (linker );
170-
171197 return true;
172- }
173198
174- /* INFO: This is an AOSP function to remove a link map from
175- the link map list.
176-
177- SOURCES:
178- - https://android.googlesource.com/platform/bionic/+/refs/heads/android15-release/linker/linker_gdb_support.cpp#63
179- */
180- static void remove_link_map_from_debug_map (struct link_map * map ) {
181- if (r_debug_tail == map ) {
182- r_debug_tail = map -> l_prev ;
183- }
199+ solist_init_error :
200+ ElfImg_destroy (linker );
184201
185- if (map -> l_prev ) {
186- map -> l_prev -> l_next = map -> l_next ;
187- }
202+ somain = NULL ;
188203
189- if (map -> l_next ) {
190- map -> l_next -> l_prev = map -> l_prev ;
191- }
204+ return false;
192205}
193206
194207static struct link_map * find_link_map (SoInfo * si ) {
@@ -209,13 +222,13 @@ static struct link_map *find_link_map(SoInfo *si) {
209222 SOURCES:
210223 - https://android.googlesource.com/platform/bionic/+/refs/heads/android15-release/linker/linker.cpp#283
211224 */
212- if (map -> l_name && (uintptr_t )map -> l_name == (uintptr_t )path ) {
225+ if ((uintptr_t )map -> l_name == (uintptr_t )path ) {
213226 LOGD ("Found link_map for %s: %p" , path , (void * )map );
214227
215228 return map ;
216229 }
217230
218- map = map -> l_next ;
231+ map = map -> l_prev ;
219232 }
220233
221234 LOGE ("Failed to find link_map for %s" , path );
@@ -275,19 +288,17 @@ bool solist_drop_so_path(void *lib_memory, bool unload) {
275288 We cannot use the notify_gdb_of_unload function as it is static, and not available
276289 in all linker binaries.
277290 */
278- struct link_map * map = find_link_map (found );
279- if (!map ) {
280- LOGE ("Failed to find link map for %s" , path );
291+ /* INFO: unregister_soinfo_tls cannot be used since module might use JNI which may
292+ require TLS, so we cannot remove it. */
293+ size_t tmp_fini_array_size = * (size_t * )((uintptr_t )found + solist_fini_array_size_offset );
294+ void * * tmp_fini_array = * (void * * * )((uintptr_t )found + solist_fini_offset );
281295
282- pdg_protect ( );
296+ LOGD ( "Bypassing call to %zu destructors and deconstructor %p" , tmp_fini_array_size , tmp_fini_array );
283297
284- return false ;
285- }
298+ * ( size_t * )(( uintptr_t ) found + solist_fini_array_size_offset ) = 0 ;
299+ * ( void * * * )(( uintptr_t ) found + solist_fini_offset ) = NULL ;
286300
287- remove_link_map_from_debug_map (map );
288- /* INFO: unregister_soinfo_tls cannot be used since module might use JNI which may
289- require TLS, so we cannot remove it. */
290- soinfo_free (found );
301+ soinfo_unload (found );
291302
292303 pdg_protect ();
293304 }
0 commit comments