Release 0.1.66
[platform/core/security/key-manager.git] / misc / ckm_so_loader.cpp
1 /*
2  *  Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License
15  */
16 /*
17  * @file       ckm_so_loader.cpp
18  * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
19  * @version    1.0
20  */
21
22 #include <dlfcn.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <sys/types.h>
27 #include <sys/wait.h>
28
29 #include <iostream>
30 #include <fstream>
31 #include <string>
32 #include <chrono>
33
34 using namespace std;
35
36 enum {
37         CLEAR_CACHE = 1,
38         LAZY = 2
39 };
40
41 void clear_cache()
42 {
43         sync();
44         ofstream of("/proc/sys/vm/drop_caches");
45
46         if (of.bad()) {
47                 cerr << "Cache clearing failed with errno: " << errno << endl;
48                 return;
49         }
50
51         of << "3";
52 }
53
54 void test(int flags, const string &library, const string &symbol)
55 {
56         bool lazy = (flags & LAZY);
57
58         if (flags & CLEAR_CACHE)
59                 clear_cache();
60
61         chrono::time_point<chrono::high_resolution_clock> tp[4];
62
63         tp[0] = chrono::high_resolution_clock::now();
64         void *handle = dlopen(library.c_str(), (lazy ? RTLD_LAZY : RTLD_NOW));
65         tp[1] = chrono::high_resolution_clock::now();
66
67         if (!handle) {
68                 cerr << "dlopen failed: " << dlerror() << endl;
69                 exit(1);
70         }
71
72         if (!symbol.empty()) {
73                 tp[2] = chrono::high_resolution_clock::now();
74                 void *sym = dlsym(handle, symbol.c_str());
75                 tp[3] = chrono::high_resolution_clock::now();
76
77                 if (!sym) {
78                         cerr << "dlsym failed: " << dlerror() << endl;
79                         exit(1);
80                 }
81         }
82
83         dlclose(handle);
84
85         cout << (tp[1] - tp[0]).count() << ";" << (tp[3] - tp[2]).count() << endl;
86 }
87
88 int main(int argc, char *argv[])
89 {
90         if (argc < 5) {
91                 cerr << "Usage: ckm_so_loader [flags] [repeats] [library] [symbol]" << endl;
92                 cerr << " flags: 1-clear cache, 2-lazy binding" << endl;
93                 cerr << "Example: ckm_so_loader 3 100 /usr/lib/libkey-manager-client.so ckmc_save_key"
94                          << endl;
95                 return -1;
96         }
97
98         try {
99                 int flags = stoi(argv[1]); // let it throw
100                 int repeats = stoi(argv[2]); // let it throw
101                 string so_path(argv[3]);
102                 string symbol(argv[4]);
103
104                 cout << "dlopen[us];dlsym[us]" << endl;
105
106                 for (int cnt = 0 ; cnt < repeats; cnt++) {
107                         /*
108                          * It has to be a different process each time. Glibc somehow caches the library information
109                          * and consecutive calls are faster
110                          */
111                         pid_t pid = fork();
112
113                         if (pid < 0) {
114                                 cerr << "fork failed with errno: " << errno << endl;
115                                 return -1;
116                         } else if (pid == 0) {
117                                 test(flags, so_path, symbol);
118                                 exit(0);
119                         } else {
120                                 int status;
121                                 pid_t ret = waitpid(pid, &status, 0);
122
123                                 if (ret != pid) {
124                                         cerr << "waitpid failed with errno: " << errno << endl;
125                                         exit(1);
126                                 }
127                         }
128                 }
129
130                 return 0;
131         } catch (...) {
132                 cerr << "Unexpected exception occured" << endl;
133                 return -1;
134         }
135 }