Cleaning environment from systemd flags.
[platform/core/security/key-manager.git] / tools / 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     if (of.bad()) {
46         cerr << "Cache clearing failed: " << strerror(errno) << endl;
47         return;
48     }
49     of << "3";
50 }
51
52 void test(int flags, const string& library, const string& symbol)
53 {
54     bool lazy = (flags & LAZY);
55     if (flags & CLEAR_CACHE)
56         clear_cache();
57
58     chrono::time_point<chrono::high_resolution_clock> tp[4];
59
60     tp[0] = chrono::high_resolution_clock::now();
61     void* handle = dlopen(library.c_str(), (lazy?RTLD_LAZY:RTLD_NOW));
62     tp[1] = chrono::high_resolution_clock::now();
63     if (!handle) {
64         cerr << "dlopen failed: " << dlerror() << endl;
65         exit(1);
66     }
67
68     if (!symbol.empty())
69     {
70         tp[2] = chrono::high_resolution_clock::now();
71         void* sym = dlsym(handle, symbol.c_str());
72         tp[3] = chrono::high_resolution_clock::now();
73         if (!sym) {
74             cerr << "dlsym failed: " << dlerror() << endl;
75             exit(1);
76         }
77     }
78     dlclose(handle);
79
80     cout << (tp[1] - tp[0]).count() << ";" << (tp[3] - tp[2]).count() << endl;
81 }
82
83 int main(int argc, char* argv[])
84 {
85     if (argc < 5) {
86         cerr << "Usage: ckm_so_loader [flags] [repeats] [library] [symbol]" << endl;
87         cerr << " flags: 1-clear cache, 2-lazy binding" << endl;
88         cerr << "Example: ckm_so_loader 3 100 /usr/lib/libkey-manager-client.so ckmc_save_key" << endl;
89         return -1;
90     }
91
92     int flags = stoi(argv[1]); // let it throw
93     int repeats = stoi(argv[2]); // let it throw
94     string so_path(argv[3]);
95     string symbol(argv[4]);
96
97     cout << "dlopen[us];dlsym[us]" << endl;
98     for (int cnt = 0 ; cnt < repeats; cnt++)
99     {
100         /*
101          * It has to be a different process each time. Glibc somehow caches the library information
102          * and consecutive calls are faster
103          */
104         pid_t pid = fork();
105         if (pid < 0) {
106             cerr << "fork failed: " << strerror(errno) << endl;
107             return -1;
108         }
109         if (pid == 0) {
110             test(flags, so_path, symbol);
111             exit(0);
112         }
113         else
114         {
115             int status;
116             pid_t ret = waitpid(pid,&status, 0);
117             if (ret != pid) {
118                 cerr << "waitpid failed: " << strerror(errno) << endl;
119                 exit(1);
120             }
121         }
122     }
123     return 0;
124 }