#include <stdint.h>
#include <sys/types.h>
+#include <linux/limits.h>
#include "da_inst.h"
#include "da_protocol.h"
#include "da_protocol_inst.h"
#include "debug.h"
-
+#include "daemon.h"
struct lib_list_t *new_lib_inst_list = NULL;
char *packed_app_list = NULL;
char *packed_lib_list = NULL;
+static struct _msg_target_t *lib_maps_message = NULL;
+static pthread_mutex_t lib_inst_list_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t lib_maps_message_mutex = PTHREAD_MUTEX_INITIALIZER;
+
uint32_t libs_count;
//----------------------------------- lists ----------------------------------
static void free_data_element(struct data_list_t *lib)
{
+ free(lib->data);
free(lib);
}
void free_data_list(struct data_list_t **data)
{
+ struct data_list_t *next;
while (*data != NULL) {
- struct data_list_t *next = (*data)->next;
+ next = (*data)->next;
free_data(*data);
*data = next;
}
{
struct probe_list_t *prev = element->prev;
struct probe_list_t *next = element->next;
- if (element != NULL) {
- if (prev != NULL)
- // prev != null, next == null
- // prev != null, next != null
- prev->next = next;
- else
- // prev == null, next == null
- // prev == null, next != null
- list->list = next;
-
- if (next != NULL)
- next->prev = prev;
-
- list->size -= element->size;
- }
+
+ if (prev != NULL)
+ prev->next = next;
+ else
+ list->list = next;
+
+ if (next != NULL)
+ next->prev = prev;
+
+ list->size -= element->size;
list->func_num--;
free_probe_element(element);
{
struct data_list_t *prev = element->prev;
struct data_list_t *next = element->next;
- if (element != NULL) {
- if (prev != NULL)
- // prev != null, next == null
- // prev != null, next != null
- prev->next = next;
- else
- // prev == null, next == null
- // prev == null, next != null
- *list = next;
-
- if (next != NULL)
- next->prev = (struct lib_list_t *)prev;
- }
+ if (prev != NULL)
+ /* prev != null, next == null */
+ /* prev != null, next != null */
+ prev->next = next;
+ else
+ /* prev == null, next == null */
+ /* prev == null, next != null */
+ *list = next;
+
+ if (next != NULL)
+ next->prev = (struct lib_list_t *)prev;
+
element->prev = NULL;
element->next = NULL;
return NULL;
}
+// Check whether functions are equal. If so, returns first argument, otherwise - NULL
+static struct probe_list_t *probes_equal(struct probe_list_t *first, struct probe_list_t *second)
+{
+ if (first->size != second->size)
+ return NULL;
+
+ if (first->func->func_addr != second->func->func_addr)
+ return NULL;
+
+ if (first->func->probe_type != second->func->probe_type)
+ return NULL;
+
+ return first;
+}
+
static struct probe_list_t *find_probe(struct data_list_t *where, struct probe_list_t *probe)
{
struct probe_list_t *p ;
for (p = where->list; p != NULL; p = p->next)
- if (p->size == probe->size)
- if (p->func->func_addr == probe->func->func_addr)
- if (strcmp(p->func->args, probe->func->args) == 0)
- break;
+ if (probes_equal(p, probe))
+ break;
return p;
}
res = malloc(size);
to = res;
if (to != NULL) {
- memset(to, '*', size);
pack_int32(to, cnt);
for (p = list; p != NULL; p = p->next)
to = pack_data_to_array(p, to, pack);
app = app->next;
}
+ free(packed_lib_list);
+ free(packed_app_list);
+
// print_buf((char *)*msg, size, "ANSWER");
return 1;
}
+static void lock_lib_maps_message()
+{
+ pthread_mutex_lock(&lib_inst_list_mutex);
+}
+
+static void unlock_lib_maps_message()
+{
+ pthread_mutex_unlock(&lib_inst_list_mutex);
+}
+
+static void lock_lib_list()
+{
+ pthread_mutex_lock(&lib_maps_message_mutex);
+}
+
+static void unlock_lib_list()
+{
+ pthread_mutex_unlock(&lib_maps_message_mutex);
+}
+
+static void generate_maps_inst_msg(struct user_space_inst_t *us_inst)
+{
+ lock_lib_maps_message();
+
+ struct lib_list_t *lib = us_inst->lib_inst_list;
+ struct app_list_t *app = us_inst->app_inst_list;
+ char *p, *resolved;
+ uint32_t total_maps_count = 0;
+ uint32_t total_len = sizeof(total_maps_count) + sizeof(*lib_maps_message);
+ char real_path_buf[PATH_MAX];
+
+ /* total message len calculate */
+ while (lib != NULL) {
+ p = lib->lib->bin_path;
+ total_len += strlen(p) + 1;
+ total_maps_count++;
+ LOGI("lib #%u <%s>\n", total_maps_count, p);
+ lib = (struct lib_list_t *)lib->next;
+ }
+
+ while (app != NULL) {
+ p = app->app->exe_path;
+ resolved = realpath((const char *)p, real_path_buf);
+ if (resolved != NULL) {
+ total_len += strlen(real_path_buf) + 1;
+ total_maps_count++;
+ LOGI("app #%u <%s>\n", total_maps_count, resolved);
+ } else {
+ LOGE("cannot resolve bin path <%s>\n", p);
+ }
+
+ app = (struct app_list_t *)app->next;
+ }
+
+ if (lib_maps_message != NULL)
+ free(lib_maps_message);
+
+ lib_maps_message = malloc(total_len);
+ lib_maps_message->type = MSG_MAPS_INST_LIST;
+ lib_maps_message->length = total_len;
+
+ /* pack data */
+ p = lib_maps_message->data;
+ pack_int32(p, total_maps_count);
+
+ lib = us_inst->lib_inst_list;
+ while (lib != NULL) {
+ pack_str(p, lib->lib->bin_path);
+ lib = (struct lib_list_t *)lib->next;
+ }
+
+ app = us_inst->app_inst_list;
+ while (app != NULL) {
+ resolved = realpath(app->app->exe_path, real_path_buf);
+ if (resolved != NULL)
+ pack_str(p, real_path_buf);
+ app = (struct app_list_t *)app->next;
+ }
+
+ LOGI("total_len = %u\n", total_len);
+ print_buf((char *)lib_maps_message, total_len, "lib_maps_message");
+
+ unlock_lib_maps_message();
+}
+
+void send_maps_inst_msg_to(struct target *t)
+{
+ lock_lib_maps_message();
+ target_send_msg(t, (struct msg_target_t *)lib_maps_message);
+ unlock_lib_maps_message();
+}
+
+static void send_maps_inst_msg_to_all_targets()
+{
+ lock_lib_maps_message();
+ target_send_msg_to_all(lib_maps_message);
+ unlock_lib_maps_message();
+}
+
//-----------------------------------------------------------------------------
struct app_info_t *app_info_get_first(struct app_list_t **app_list)
{
int msg_start(struct msg_buf_t *data, struct user_space_inst_t *us_inst,
struct msg_t **msg, enum ErrorCode *err)
{
+ int res = 0;
char *p = NULL;
*msg = NULL;
+
+ /* lock list access */
+ lock_lib_list();
+
if (!parse_app_inst_list(data, &us_inst->app_num, &us_inst->app_inst_list)) {
*err = ERR_WRONG_MESSAGE_FORMAT;
LOGE("parse app inst\n");
- return 1;
+ res = 1;
+ goto msg_start_exit;
}
generate_msg(msg, us_inst->lib_inst_list, us_inst->app_inst_list);
pack_int32(p, NMSG_START);
} else {
*err = ERR_CANNOT_START_PROFILING;
- return 1;
+ res = 1;
+ goto msg_start_exit;
}
- return 0;
+
+ generate_maps_inst_msg(us_inst);
+
+msg_start_exit:
+ /* unlock list access */
+ unlock_lib_list();
+
+ return res;
}
int msg_swap_inst_add(struct msg_buf_t *data, struct user_space_inst_t *us_inst,
struct msg_t **msg, enum ErrorCode *err)
{
+ int res = 0;
uint32_t lib_num = 0;
char *p = NULL;
*err = ERR_UNKNOWN;
+ /* lock list access */
+ lock_lib_list();
+
if (!parse_lib_inst_list(data, &lib_num, &us_inst->lib_inst_list)) {
*err = ERR_WRONG_MESSAGE_FORMAT;
LOGE("parse lib inst list fail\n");
- return 1;
+ res = 1;
+ goto msg_swap_inst_add_exit;
}
// rm probes from new if its presents in cur
if (!resolve_collisions_for_add_msg(&us_inst->lib_inst_list, &new_lib_inst_list)) {
LOGE("resolve collision\n");
- return 1;
+ res = 1;
+ goto msg_swap_inst_add_exit;
};
// generate msg to send
cmp_libs))
{
LOGE("data move\n");
- return 1;
+ res = 1;
+ goto msg_swap_inst_add_exit;
};
// free new_list
free_data_list((struct data_list_t **)&new_lib_inst_list);
new_lib_inst_list = NULL;
*err = ERR_NO;
- return 0;
+
+ generate_maps_inst_msg(us_inst);
+ send_maps_inst_msg_to_all_targets();
+
+msg_swap_inst_add_exit:
+ /* unlock list access */
+ unlock_lib_list();
+
+ return res;
}
int msg_swap_inst_remove(struct msg_buf_t *data, struct user_space_inst_t *us_inst,
struct msg_t **msg, enum ErrorCode *err)
{
+ int res = 0;
uint32_t lib_num = 0;
char *p = NULL;
*err = ERR_UNKNOWN;
+ /* lock list access */
+ lock_lib_list();
+
if (!parse_lib_inst_list(data, &lib_num, &new_lib_inst_list)) {
*err = ERR_WRONG_MESSAGE_FORMAT;
LOGE("parse lib inst\n");
- return 1;
+ res = 1;
+ goto msg_swap_inst_remove_exit;
}
if (!resolve_collisions_for_rm_msg(&us_inst->lib_inst_list, &new_lib_inst_list)) {
LOGE("resolve collisions\n");
- return 1;
+ res = 1;
+ goto msg_swap_inst_remove_exit;
}
if (us_inst->app_inst_list != NULL) {
if (!generate_msg(msg, new_lib_inst_list, us_inst->app_inst_list)) {
LOGE("generate msg\n");
- return 1;
+ res = 1;
+ goto msg_swap_inst_remove_exit;
}
p = (char *)*msg;
pack_int32(p, NMSG_SWAP_INST_ADD);
free_data_list((struct data_list_t **)&new_lib_inst_list);
new_lib_inst_list = NULL;
*err = ERR_NO;
- return 0;
+
+ generate_maps_inst_msg(us_inst);
+ send_maps_inst_msg_to_all_targets();
+
+msg_swap_inst_remove_exit:
+ /* unlock list access */
+ unlock_lib_list();
+
+ return res;
+}
+
+void msg_swap_free_all_data(struct user_space_inst_t *us_inst)
+{
+ LOGI("new_lib_inst_list %p\n", new_lib_inst_list);
+ if (new_lib_inst_list != NULL) {
+ LOGI("free new_lib_inst_list start\n");
+ free_data_list(&new_lib_inst_list);
+ new_lib_inst_list = NULL;
+ LOGI("free new_lib_inst_list finish\n");
+ }
+
+ LOGI("us_inst->lib_inst_list %p\n", us_inst->lib_inst_list);
+ if (us_inst->lib_inst_list != NULL) {
+ LOGI("free us_inst->lib_inst_list start\n");
+ free_data_list(&us_inst->lib_inst_list);
+ us_inst->lib_inst_list = NULL;
+ LOGI("free us_isnt->lib_inst_list finish\n");
+ }
+
+ LOGI("us_inst->app_inst_list %p\n", us_inst->app_inst_list);
+ if (us_inst->app_inst_list != NULL) {
+ LOGI("free us_inst->app_inst_list start\n");
+ free_data_list(&us_inst->app_inst_list);
+ LOGI("free us_inst->app_isnt_list finish\n");
+ }
}