1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *  * Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  *  * Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in
12  *    the documentation and/or other materials provided with the
13  *    distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include "private/icu.h"
30 
31 #include <dirent.h>
32 #include <dlfcn.h>
33 #include <pthread.h>
34 #include <stdlib.h>
35 #include <string.h>
36 
37 #include <async_safe/log.h>
38 
39 static void* g_libicuuc_handle = nullptr;
40 
__find_icu()41 static bool __find_icu() {
42   g_libicuuc_handle = dlopen("libandroidicu.so", RTLD_LOCAL);
43   if (g_libicuuc_handle == nullptr) {
44     async_safe_format_log(ANDROID_LOG_ERROR, "bionic-icu", "couldn't open libandroidicu.so: %s",
45                           dlerror());
46     return false;
47   }
48 
49   return true;
50 }
51 
__find_icu_symbol(const char * symbol_name)52 void* __find_icu_symbol(const char* symbol_name) {
53   static bool found_icu = __find_icu();
54   if (!found_icu) return nullptr;
55 
56   char versioned_symbol_name[strlen(symbol_name) + strlen("_android") + 1];
57   snprintf(versioned_symbol_name, sizeof(versioned_symbol_name), "%s_android",
58            symbol_name);
59 
60   void* symbol = dlsym(g_libicuuc_handle, versioned_symbol_name);
61   if (symbol == nullptr) {
62     async_safe_format_log(ANDROID_LOG_ERROR, "bionic-icu", "couldn't find %s",
63                           versioned_symbol_name);
64   }
65   return symbol;
66 }
67