int rdis_remove_function (struct _rdis * rdis, uint64_t address) { map_remove(rdis->functions, address); map_remove(rdis->labels, address); struct _graph * family = graph_family(rdis->graph, address); if (family == NULL) return -1; struct _graph_it * it; for (it = graph_iterator(family); it != NULL; it = graph_it_next(it)) { struct _graph_node * node = graph_it_node(it); printf("rdis_remove_function %p %p %p %llx\n", node, node->data, node->edges, (unsigned long long) node->index); graph_remove_node(rdis->graph, node->index); } object_delete(family); rdis_callback(rdis, RDIS_CALLBACK_GRAPH | RDIS_CALLBACK_FUNCTION | RDIS_CALLBACK_LABEL); return 0; }
// Free self, regardless of reference count. void graph_free (Graph *self) { // Remove all the edges. gint ii; for ( ii = 0 ; ii < self->edges->len ; ii++ ) { graph_remove_edge (self, g_ptr_array_index (self->edges, ii)); } // Remove all the nodes. for ( ii = 0 ; ii < self->nodes->len ; ii++ ) { graph_remove_node (self, g_ptr_array_index (self->nodes, ii)); } g_free (self); }
int rdis_update_memory (struct _rdis * rdis, uint64_t address, struct _buffer * buffer) { if (buffer == NULL) return -1; mem_map_set (rdis->memory, address, buffer); // we will regraph functions whose bounds fall within this updated memory, // and all functions whose bounds fall within the bounds of functions to be // regraphed (step 2 simplifies things later on) struct _queue * queue = queue_create(); struct _map_it * it; for (it = map_iterator(rdis->functions); it != NULL; it = map_it_next(it)) { struct _function * function = map_it_data(it); if ( ( (function->bounds.lower >= address) && (function->bounds.lower < address + buffer->size)) || ( (function->bounds.upper >= address) && (function->bounds.upper < address + buffer->size)) || ( (function->bounds.lower <= address) && (function->bounds.upper >= address + buffer->size))) { queue_push(queue, function); } } struct _map * regraph_functions = map_create(); while (queue->size > 0) { struct _function * function = queue_peek(queue); if (map_fetch(regraph_functions, function->address) != NULL) { queue_pop(queue); continue; } printf("adding regraph function %llx\n", (unsigned long long) function->address); map_insert(regraph_functions, function->address, function); for (it = map_iterator(rdis->functions); it != NULL; it = map_it_next(it)) { struct _function * cmp_function = map_it_data(it); if ( ( (cmp_function->bounds.lower >= function->bounds.lower) && (cmp_function->bounds.lower < function->bounds.upper)) || ( (cmp_function->bounds.upper >= function->bounds.lower) && (cmp_function->bounds.upper < function->bounds.upper)) || ( (cmp_function->bounds.lower <= function->bounds.lower) && (cmp_function->bounds.upper >= function->bounds.upper))) queue_push(queue, cmp_function); } } // regraph dem functions struct _graph * new_graph; new_graph = loader_graph_functions(rdis->loader, rdis->memory, regraph_functions); // We are now going to go through all nodes in our regraph functions. We // will copy over comments to the new instructions and then remove the // regraph function nodes from the original graph for (it = map_iterator(regraph_functions); it != NULL; it = map_it_next(it)) { struct _function * function = map_it_data(it); struct _graph * family = graph_family(rdis->graph, function->address); if (family == NULL) continue; struct _graph_it * git; for (git = graph_iterator(family); git != NULL; git = graph_it_next(git)) { struct _list * ins_list = graph_it_data(git); struct _list_it * iit; for (iit = list_iterator(ins_list); iit != NULL; iit = iit->next) { struct _ins * ins = iit->data; if (ins->comment == NULL) continue; struct _ins * new_ins = graph_fetch_ins(new_graph, ins->address); if (ins->size != new_ins->size) continue; if (memcmp(ins->bytes, new_ins->bytes, ins->size) == 0) { printf("copy over comment from instruction at %llx\n", (unsigned long long) ins->address); ins_s_comment(new_ins, ins->comment); } } // add node for deletion struct _index * index = index_create(graph_it_index(git)); queue_push(queue, index); object_delete(index); } object_delete(family); while (queue->size > 0) { struct _index * index = queue_peek(queue); graph_remove_node(rdis->graph, index->index); queue_pop(queue); } } // merge the new graph with the old graph graph_merge(rdis->graph, new_graph); // reset bounds of these functions for (it = map_iterator(regraph_functions); it != NULL; it = map_it_next(it)) { struct _function * function = map_it_data(it); rdis_function_bounds(rdis, function->address); } objects_delete(queue, new_graph, regraph_functions, NULL); rdis_callback(rdis, RDIS_CALLBACK_ALL); return 0; }
static void handle_graph_message(UiConnection *self, const gchar *command, JsonObject *payload, SoupWebsocketConnection *ws) { g_return_if_fail(payload); Graph *graph = NULL; if (g_strcmp0(command, "clear") != 0) { // All other commands must have graph // TODO: change FBP protocol to use 'graph' instead of 'id'? const gchar *graph_id = json_object_get_string_member(payload, "graph"); Network *net = (graph_id) ? g_hash_table_lookup(self->network_map, graph_id) : NULL; graph = (net) ? net->graph : NULL; g_return_if_fail(graph); } if (g_strcmp0(command, "clear") == 0) { const gchar *graph_id = json_object_get_string_member(payload, "id"); Graph *graph = graph_new(graph_id, self->component_lib); Network *network = network_new(graph); ui_connection_add_network(self, graph_id, network); } else if (g_strcmp0(command, "addnode") == 0) { graph_add_node(graph, json_object_get_string_member(payload, "id"), json_object_get_string_member(payload, "component") ); } else if (g_strcmp0(command, "removenode") == 0) { graph_remove_node(graph, json_object_get_string_member(payload, "id") ); } else if (g_strcmp0(command, "changenode") == 0) { // Just metadata, ignored } else if (g_strcmp0(command, "addinitial") == 0) { JsonObject *tgt = json_object_get_object_member(payload, "tgt"); JsonObject *src = json_object_get_object_member(payload, "src"); GValue data = G_VALUE_INIT; json_node_get_value(json_object_get_member(src, "data"), &data); graph_add_iip(graph, json_object_get_string_member(tgt, "node"), json_object_get_string_member(tgt, "port"), &data ); g_value_unset(&data); } else if (g_strcmp0(command, "removeinitial") == 0) { JsonObject *tgt = json_object_get_object_member(payload, "tgt"); graph_remove_iip(graph, json_object_get_string_member(tgt, "node"), json_object_get_string_member(tgt, "port") ); } else if (g_strcmp0(command, "addedge") == 0) { JsonObject *src = json_object_get_object_member(payload, "src"); JsonObject *tgt = json_object_get_object_member(payload, "tgt"); graph_add_edge(graph, json_object_get_string_member(src, "node"), json_object_get_string_member(src, "port"), json_object_get_string_member(tgt, "node"), json_object_get_string_member(tgt, "port") ); } else if (g_strcmp0(command, "removeedge") == 0) { JsonObject *src = json_object_get_object_member(payload, "src"); JsonObject *tgt = json_object_get_object_member(payload, "tgt"); graph_remove_edge(graph, json_object_get_string_member(src, "node"), json_object_get_string_member(src, "port"), json_object_get_string_member(tgt, "node"), json_object_get_string_member(tgt, "port") ); } else if (g_strcmp0(command, "changeedge") == 0) { // Just metadata, ignored } else { imgflo_warning("Unhandled message on protocol 'graph', command='%s'", command); } }