[FIX] empty string in sprintf
[platform/core/system/swap-manager.git] / daemon / da_inst.c
1 /*
2  *  DA manager
3  *
4  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:
7  *
8  * Cherepanov Vitaliy <v.cherepanov@samsung.com>
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  * http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  * Contributors:
23  * - Samsung RnD Institute Russia
24  *
25  */
26
27 // TODO check memory (malloc, free)
28
29 #include <stdint.h>
30 #include <sys/types.h>
31
32 #include "da_inst.h"
33 #include "da_protocol.h"
34 #include "da_protocol_inst.h"
35 #include "debug.h"
36
37
38 struct lib_list_t *new_lib_inst_list = NULL;
39
40 uint32_t app_count = 0;
41 char *packed_app_list = NULL;
42 char *packed_lib_list = NULL;
43
44 uint32_t libs_count;
45 // ------------------ prints --------------
46 void print_probe_debug(struct probe_list_t *p)
47 {
48         LOGI("     size<%d> <0x%016llX, %s> <p=0x%08lX c=0x%08lX n=0x%08lX>\n",
49                 p->size,
50                 p->func->func_addr,
51                 p->func->args,
52                 (long unsigned int)p->prev,
53                 (long unsigned int)p,
54                 (long unsigned int)p->next
55                 );
56 }
57
58 void print_probe_inst_list(struct probe_list_t *list)
59 {
60         struct probe_list_t *p;
61
62         for (p = list; p != NULL; p = p->next)
63                 print_probe_debug(p);
64 }
65
66 void print_lib_inst_list(struct lib_list_t *list)
67 {
68         struct lib_list_t *p = list;
69
70         for (p = list; p != NULL; p = p->next) {
71                 LOGI("lib <%s> size<%d> h0x%08lX\n",
72                         p->lib->bin_path,
73                         p->size,
74                         (long unsigned int)p->hash);
75                 print_probe_inst_list(p->list);
76         }
77 }
78
79 void print_app_inst_list(struct app_list_t *list)
80 {
81         struct app_list_t *p;
82         for (p = list; p != NULL; p = p->next) {
83                 LOGI("app <%s> size<%d> h0x%08lX\n",
84                         p->app->exe_path,
85                         p->size,
86                         (long unsigned int)p->hash);
87                 print_probe_inst_list(p->list);
88         }
89 }
90
91
92 //----------------------------------- lists ----------------------------------
93
94 static int data_list_add_probe_to_hash(struct data_list_t *to, struct probe_list_t *probe)
95 {
96         // TODO add hash
97         return 0;
98 }
99
100 // create hash for lib
101 static int data_list_make_hash(struct data_list_t *what)
102 {
103         struct probe_list_t *p;
104
105         for (p = what->list; p != NULL; p = p->next)
106                 data_list_add_probe_to_hash(what, p);
107         return 0;
108 }
109
110 //------------ create - destroy
111 static struct data_list_t *new_data(void)
112 {
113         struct data_list_t *lib = malloc(sizeof(*lib));
114         lib->next = NULL;
115         lib->prev = NULL;
116         lib->hash = 0;
117         lib->size = 0;
118         lib->list = NULL;
119         return lib;
120 }
121
122 struct lib_list_t *new_lib(void)
123 {
124         struct lib_list_t *lib = (struct lib_list_t *)new_data();
125         lib->lib = malloc(sizeof(*lib->lib));
126         memset(lib->lib, 0, sizeof(*lib->lib));
127         return lib;
128 }
129
130 struct app_list_t *new_app(void)
131 {
132         struct app_list_t *app = (struct app_list_t *)new_data();
133         app->app = malloc(sizeof(*app->app));
134         memset(app->app, 0, sizeof(*app->app));
135         return app;
136 }
137
138 struct probe_list_t *new_probe(void)
139 {
140         struct probe_list_t *probe = malloc(sizeof(*probe));
141         probe->next = NULL;
142         probe->prev = NULL;
143         probe->size = 0;
144         probe->func = NULL;
145         return probe;
146 }
147
148 static void free_probe_element(struct probe_list_t *probe)
149 {
150         free(probe->func);
151         free(probe);
152 }
153
154 static void free_data_element(struct data_list_t *lib)
155 {
156         free(lib);
157 }
158
159 static void free_probe_list(struct probe_list_t *probe)
160 {
161         struct probe_list_t *next;
162         while (probe != NULL) {
163                 next = probe->next;
164                 free_probe_element(probe);
165                 probe = next;
166         }
167 }
168
169 static void free_data(struct data_list_t *lib)
170 {
171         free_probe_list(lib->list);
172         free_data_element(lib);
173 }
174
175 void free_data_list(struct data_list_t **data)
176 {
177         while (*data != NULL) {
178                 struct data_list_t *next = (*data)->next;
179                 free_data(*data);
180                 *data = next;
181         }
182 }
183
184 //------------- add - remove
185 int data_list_append(struct data_list_t **to, struct data_list_t *from)
186 {
187         struct data_list_t *p = NULL;
188         if (*to == NULL) {
189                 // empty list
190                 *to = from;
191         } else {
192                 p = *to;
193                 *to = from;
194                 from->next = (void *)p;
195                 p->prev = (void *)from;
196         }
197         return 0;
198 }
199
200
201 static int data_list_append_probes_hash(struct data_list_t *to, struct data_list_t *from)
202 {
203         struct probe_list_t *p = from->list;
204         struct probe_list_t *last = p;
205
206         to->size += p->size;
207         to->func_num += from->func_num;
208         for (p = from->list; p != NULL; p = p->next) {
209                 data_list_add_probe_to_hash(to, p);
210                 last = p;
211         }
212
213         last->next = to->list;
214         to->list->prev = last;
215         to->list = from->list;
216
217         return 1;
218 }
219
220 int probe_list_append(struct data_list_t *to, struct probe_list_t *from)
221 {
222         struct probe_list_t **list = &(to->list);
223         struct probe_list_t *p = NULL;
224         uint32_t num = 0;
225         if (*list == NULL) {
226                 // empty list
227                 *list = from;
228         } else {
229                 p = *list;
230                 *list = from;
231                 from->next = (void *)p;
232                 p->prev = (void *)from;
233         }
234         to->size += from->size;
235
236         num = 0;
237         for (p = from; p != NULL; p = p->next)
238                 num++;
239         to->func_num += num;
240         return 0;
241 }
242
243 static struct probe_list_t *probe_list_rm_element(struct data_list_t *list, struct probe_list_t *element)
244 {
245         struct probe_list_t *prev = element->prev;
246         struct probe_list_t *next = element->next;
247         if (element != NULL) {
248                 if (prev != NULL)
249                         // prev != null, next == null
250                         // prev != null, next != null
251                         prev->next = next;
252                 else
253                         // prev == null, next == null
254                         // prev == null, next != null
255                         list->list = next;
256
257                 if (next != NULL)
258                         next->prev = prev;
259
260                 list->size -= element->size;
261         }
262
263         list->func_num--;
264         free_probe_element(element);
265         return next;
266 }
267
268 static struct data_list_t *data_list_unlink_data(struct data_list_t **list, struct data_list_t *element)
269 {
270         struct data_list_t *prev = element->prev;
271         struct data_list_t *next = element->next;
272         if (element != NULL) {
273                 if (prev != NULL)
274                         // prev != null, next == null
275                         // prev != null, next != null
276                         prev->next = next;
277                 else
278                         // prev == null, next == null
279                         // prev == null, next != null
280                         *list = next;
281
282                 if (next != NULL)
283                         next->prev = (struct lib_list_t *)prev;
284
285         }
286         element->prev = NULL;
287         element->next = NULL;
288
289         return next;
290 }
291
292 static struct data_list_t *data_list_rm_data(struct data_list_t **list, struct data_list_t *element)
293 {
294         struct data_list_t *next = NULL;
295
296         next = data_list_unlink_data(list, element);
297         free_data_element(element);
298
299         return next;
300 }
301
302 // find
303 static struct data_list_t *data_list_find_data(struct data_list_t *whered, struct data_list_t *whatd, cmp_data_f cmp)
304 {
305         struct data_list_t *where;
306         struct data_list_t *what = whatd;
307         for (where = whered; where != NULL; where = where->next) {
308                 if (where->hash == what->hash) {
309                         if (cmp(where, what))
310                                 return where;
311                 }
312         }
313         return NULL;
314 }
315
316 static struct probe_list_t *find_probe(struct data_list_t *where, struct probe_list_t *probe)
317 {
318         struct probe_list_t *p ;
319         for (p = where->list; p != NULL; p = p->next)
320                 if (p->size == probe->size)
321                         if (p->func->func_addr == probe->func->func_addr)
322                                 if (strcmp(p->func->args, probe->func->args) == 0)
323                                         break;
324
325         return p;
326 }
327
328 // "from" will be destroyed after this call
329 static int data_list_move_with_hash(struct data_list_t **to, struct data_list_t **from, cmp_data_f cmp)
330 {
331
332         struct data_list_t *p = *from;
333         struct data_list_t *next = NULL;
334         struct data_list_t *sch = NULL;
335         while (p != NULL) {
336                 sch = data_list_find_data(*to, p, cmp);
337                 next = data_list_unlink_data(from, p);
338                 if (sch == NULL) {
339                         data_list_make_hash(p);
340                         data_list_append(to, p);
341                 } else {
342                         data_list_append_probes_hash(sch, p);
343                 }
344                 p = next;
345         }
346         return 1;
347 }
348
349 //---------------------------- collisions resolve ------------------------------
350
351 static int cmp_libs(struct data_list_t *el_1, struct data_list_t *el_2)
352 {
353         return (strcmp(
354                         ((struct lib_list_t *)el_1)->lib->bin_path,
355                         ((struct lib_list_t *)el_2)->lib->bin_path
356                         ) == 0);
357 }
358
359 // this function for future use
360 static int cmp_apps(struct data_list_t *el_1, struct data_list_t *el_2)
361 {
362         return (strcmp(
363                         ((struct app_list_t *)el_1)->app->exe_path,
364                         ((struct app_list_t *)el_2)->app->exe_path
365                         ) == 0);
366 }
367
368 ///////////////////////////////////////////////////////////////////////////
369 // function removes from new list all probes which are already installed
370 //
371 // cur - current state (lib list with probes)
372 // new - additional probes which were received with MSG_SWAP_INST_ADD msg
373 //       (lib list with probes)
374 // this function removes all probes which are present in cur and new list from
375 // new list so after this function call in new list will be only probes which are
376 // not present in cur list
377 static int resolve_collisions_for_add_msg(struct lib_list_t **cur, struct lib_list_t **new)
378 {
379         struct data_list_t *p = (struct data_list_t *)*new;
380         struct data_list_t *sch = NULL;
381
382         struct probe_list_t *pr = NULL;
383         struct probe_list_t *next_pr = NULL;
384
385         // remove collisions from list "new"
386         while (p != NULL) {
387                 sch = data_list_find_data((struct data_list_t *)*cur, p, cmp_libs);
388                 if (sch == NULL) {
389                         // lib not found in cur config
390                 } else {
391                         // lib found in cur config so resolve collisions
392                         pr = p->list;
393                         while (pr != NULL) {
394                                 // remove collisions
395                                 if (find_probe(sch, pr) != NULL) {
396                                         // probe already exist
397                                         // rm from new config
398                                         next_pr = probe_list_rm_element(p, pr);
399                                         pr = next_pr;
400                                 } else {
401                                         pr = pr->next;
402                                 }
403                         }
404
405                         // rm lib if it is empty
406                         if (p->list == NULL) {
407                                 p = data_list_rm_data((struct data_list_t **)new, p);
408                                 continue;
409                         }
410                 }
411                 p = p->next;
412         }
413         return 1;
414 }
415
416 ///////////////////////////////////////////////////////////////////////////
417 // function removes from cur list all probes which are in list "new"
418 //         and removes from "new" all probes which are not instaled
419 //
420 // cur - current state (lib list with probes)
421 // new - list for probes remove which were received with MSG_SWAP_INST_REMOVE msg
422 //
423 // this function removes all probes which are present in cur and new list from
424 // cur list and removes all probes which are present in new but not present in
425 // cur list so after this function call in new list will be only probes which are
426 // present in cur list
427 static int resolve_collisions_for_rm_msg(struct lib_list_t **cur, struct lib_list_t **new)
428 {
429         struct data_list_t *p = (struct data_list_t *)*new;
430         struct data_list_t *next_l = NULL;
431         struct data_list_t *sch = NULL;
432
433         struct probe_list_t *pr = NULL;
434         struct probe_list_t *next_pr = NULL;
435         struct probe_list_t *tmp = NULL;
436
437         // remove collisions from list "new"
438         while (p != NULL) {
439                 sch = data_list_find_data((struct data_list_t *)*cur, p, cmp_libs);
440                 if (sch == NULL) {
441                         //lib not found so no probes remove
442                         next_l = data_list_rm_data((struct data_list_t **)new, p);
443                 } else {
444                         //lib found so we need remove collisions
445                         pr = p->list;
446                         if (pr == NULL) {
447                                 // if rm probe list is empty that is mean we need
448                                 // to remove all probes on this lib
449                                 data_list_unlink_data((struct data_list_t **)cur, sch);
450                                 data_list_append((struct data_list_t **)new, sch);
451                                 next_l = data_list_rm_data((struct data_list_t **)cur, p);
452                         } else {
453                                 // lib is not empty so merge
454                                 while (pr != NULL) {
455                                         // remove collisions
456                                         if ((tmp = find_probe(sch, pr)) != NULL) {
457                                                 // probe found so remove probe
458                                                 // from cur state
459                                                 probe_list_rm_element(sch, tmp);
460                                                 pr = pr->next;
461                                         } else {
462                                                 // probe no found so remove it
463                                                 // from new state
464                                                 next_pr = probe_list_rm_element(p, pr);
465                                                 pr = next_pr;
466                                         }
467                                 }
468                                 // rm lib if it is empty
469                                 if (sch->list == NULL) {
470                                         data_list_rm_data((struct data_list_t **)cur, sch);
471                                 }
472                                 next_l = p->next;
473                         }
474                 }
475                 p = next_l;
476         }
477         return 1;
478 }
479
480 //--------------------------------------pack ----------------------------------
481
482 static char *pack_lib_head_to_array(char *to, void *data)
483 {
484         struct us_lib_inst_t *lib = data;
485         pack_str(to, lib->bin_path);
486         return to;
487 }
488
489 static char *pack_app_head_to_array(char *to, void *data)
490 {
491         struct app_info_t *app = data;
492         pack_int32(to, app->app_type);
493         pack_str(to, app->app_id);
494         pack_str(to, app->exe_path);
495         return to;
496 }
497
498 static char *pack_data_to_array(struct data_list_t *data, char *to, pack_head_t pack_head)
499 {
500         struct probe_list_t *p;
501
502         to = pack_head(to, data->data);
503         pack_int32(to, data->func_num);
504         for (p = data->list; p != NULL; p = p->next) {
505                 memcpy(to, p->func, p->size);
506                 to += p->size;
507         }
508         return to;
509 }
510
511 static char *pack_data_list_to_array(struct data_list_t *list, uint32_t *len, uint32_t *count, pack_head_t pack)
512 {
513         char *res = NULL;
514         char *to = NULL;
515         uint32_t size = 0;
516         uint32_t cnt = 0;
517         struct data_list_t *p = list;
518
519         for (p = list; p != NULL; p = p->next) {
520                 size += p->size;
521                 cnt++;
522         }
523
524         size += sizeof(uint32_t);
525         *len = size;
526         *count = cnt;
527
528         if (size != 0) {
529                 res = malloc(size);
530                 to = res;
531                 if (to != NULL) {
532                         memset(to, '*', size);
533                         pack_int32(to, cnt);
534                         for (p = list; p != NULL; p = p->next)
535                                 to = pack_data_to_array(p, to, pack);
536                 } else {
537                         LOGE("can not malloc buffer for data list packing\n");
538                 }
539         }
540         return res;
541 }
542
543 static char *pack_lib_list_to_array(struct lib_list_t *list, uint32_t *size, uint32_t *count)
544 {
545         return pack_data_list_to_array((struct data_list_t *)list, size,
546                                         count, pack_lib_head_to_array);
547 }
548
549 static char *pack_app_list_to_array(struct app_list_t *list, uint32_t *size, uint32_t *count)
550 {
551         return pack_data_list_to_array((struct data_list_t *)list, size,
552                                         count,  pack_app_head_to_array);
553 }
554
555 static int generate_msg(struct msg_t **msg, struct lib_list_t *lib_list, struct app_list_t *app_list)
556 {
557         uint32_t i,
558                  size = 0,
559                  libs_size = 0,
560                  apps_size = 0,
561                  libs_count = 0,
562                  apps_count = 0;
563         char     *p = NULL;
564
565
566         // print_lib_inst_list(lib_list);
567         packed_lib_list = pack_lib_list_to_array(lib_list, &libs_size, &libs_count);
568         // print_buf(packed_lib_list, libs_size, "LIBS");
569
570         packed_app_list = pack_app_list_to_array(app_list, &apps_size, &apps_count);
571         // print_buf(packed_app_list, apps_size, "APPS");
572
573         size = apps_count * libs_size + apps_size;
574
575         LOGI("size = %d, apps= %d, libs = %d\n", size, apps_count, libs_count);
576
577         // add header size
578         *msg = malloc(size + sizeof(**msg));
579         memset(*msg, '*', size);
580
581         p = (char *)*msg;
582         pack_int32(p, 0);               // msg id
583         pack_int32(p, size);            // payload size
584         pack_int32(p, apps_count);
585
586         struct app_list_t *app = app_list;
587         char *app_p = packed_app_list + sizeof(((struct user_space_inst_t *)0)->app_num);
588
589         for (i = 0; i < apps_count; i++) {
590                 memcpy(p, app_p, app->size);
591                 p += app->size;
592                 memcpy(p, packed_lib_list, libs_size);
593                 p += libs_size;
594
595                 app_p += app->size;
596                 app = app->next;
597         }
598
599         // print_buf((char *)*msg, size, "ANSWER");
600         return 1;
601 }
602
603 //-----------------------------------------------------------------------------
604 struct app_info_t *app_info_get_first(struct app_list_t **app_list)
605 {
606         *app_list = prof_session.user_space_inst.app_inst_list;
607         if (*app_list == NULL) {
608                 return NULL;
609         }
610
611         return (*app_list)->app;
612 }
613
614 struct app_info_t *app_info_get_next(struct app_list_t **app_list)
615 {
616         if (*app_list == NULL)
617                 return NULL;
618
619         if ((*app_list = (*app_list)->next) == NULL)
620                 return NULL;
621
622         return (*app_list)->app;
623 }
624
625 //-----------------------------------------------------------------------------
626 int msg_start(struct msg_buf_t *data, struct user_space_inst_t *us_inst,
627               struct msg_t **msg, enum ErrorCode *err)
628 {
629         char *p = NULL;
630         *msg = NULL;
631         if (!parse_app_inst_list(data, &us_inst->app_num, &us_inst->app_inst_list)) {
632                 *err = ERR_WRONG_MESSAGE_FORMAT;
633                 LOGE("parse app inst\n");
634                 return 1;
635         }
636         // print_app_inst_list(app_inst_list);
637         generate_msg(msg, us_inst->lib_inst_list, us_inst->app_inst_list);
638
639         if (*msg != NULL) {
640                 p = (char *)*msg;
641                 pack_int32(p, NMSG_START);
642         } else {
643                 *err = ERR_CANNOT_START_PROFILING;
644                 return 1;
645         }
646         return 0;
647 }
648
649 int msg_swap_inst_add(struct msg_buf_t *data, struct user_space_inst_t *us_inst,
650                       struct msg_t **msg, enum ErrorCode *err)
651 {
652         uint32_t lib_num = 0;
653         char *p = NULL;
654
655         *err = ERR_UNKNOWN;
656
657         if (!parse_lib_inst_list(data, &lib_num, &us_inst->lib_inst_list)) {
658                 *err = ERR_WRONG_MESSAGE_FORMAT;
659                 LOGE("parse lib inst list fail\n");
660                 return 1;
661         }
662         // rm probes from new if its presents in cur
663         if (!resolve_collisions_for_add_msg(&us_inst->lib_inst_list, &new_lib_inst_list)) {
664                 LOGE("resolve collision\n");
665                 return 1;
666         };
667
668         // generate msg to send
669         if (us_inst->app_inst_list != NULL) {
670                 generate_msg(msg, new_lib_inst_list, us_inst->app_inst_list);
671                 p = (char *)*msg;
672                 pack_int32(p, NMSG_SWAP_INST_ADD);
673         }
674         // apply changes to cur state
675         if (!data_list_move_with_hash(
676                 (struct data_list_t **)&us_inst->lib_inst_list,
677                 (struct data_list_t **)&new_lib_inst_list,
678                 cmp_libs))
679         {
680                 LOGE("data move\n");
681                 return 1;
682         };
683
684         // free new_list
685         free_data_list((struct data_list_t **)&new_lib_inst_list);
686         new_lib_inst_list = NULL;
687         *err = ERR_NO;
688         return 0;
689 }
690
691 int msg_swap_inst_remove(struct msg_buf_t *data, struct user_space_inst_t *us_inst,
692                          struct msg_t **msg, enum ErrorCode *err)
693 {
694         uint32_t lib_num = 0;
695         char *p = NULL;
696         *err = ERR_UNKNOWN;
697
698         if (!parse_lib_inst_list(data, &lib_num, &new_lib_inst_list)) {
699                 *err = ERR_WRONG_MESSAGE_FORMAT;
700                 LOGE("parse lib inst\n");
701                 return 1;
702         }
703
704         if (!resolve_collisions_for_rm_msg(&us_inst->lib_inst_list, &new_lib_inst_list)) {
705                 LOGE("resolve collisions\n");
706                 return 1;
707         }
708
709         if (us_inst->app_inst_list != NULL) {
710                 if (!generate_msg(msg, new_lib_inst_list, us_inst->app_inst_list)) {
711                         LOGE("generate msg\n");
712                         return 1;
713                 }
714                 p = (char *)*msg;
715                 pack_int32(p, NMSG_SWAP_INST_ADD);
716         }
717
718         free_data_list((struct data_list_t **)&new_lib_inst_list);
719         new_lib_inst_list = NULL;
720         *err = ERR_NO;
721         return 0;
722 }