Ejemplo n.º 1
0
Archivo: elf32.c Proyecto: TDKPS/rdis
struct _graph * elf32_graph_functions (struct _elf32 * elf32,
                                       struct _map *   memory,
                                       struct _map *   functions)
{
    struct _graph  * graph;
    struct _wqueue * wqueue;

    // disassemble from entry point
    graph = x86_graph(elf32_entry(elf32), memory);

    struct _map_it * it;

    wqueue = wqueue_create();
    for (it  = map_iterator(functions);
            it != NULL;
            it  = map_it_next(it)) {
        struct _function * function = map_it_data(it);

        struct _x86_wqueue * x86w;
        x86w = x86_wqueue_create(function->address, memory);
        wqueue_push(wqueue, WQUEUE_CALLBACK(x86_graph_wqueue), x86w);
        object_delete(x86w);
    }

    wqueue_wait(wqueue);

    while (wqueue_peek(wqueue) != NULL) {
        graph_merge(graph, wqueue_peek(wqueue));
        wqueue_pop(wqueue);
    }

    object_delete(wqueue);

    remove_function_predecessors(graph, functions);
    graph_reduce(graph);

    return graph;
}
Ejemplo n.º 2
0
int rdis_user_function (struct _rdis * rdis, uint64_t address)
{
    // get a tree of all functions reachable at this address
    struct _map * functions = loader_function_address(rdis->loader,
                                                      rdis->memory,
                                                      address);

    // add in this address as a new function as well
    struct _function * function = function_create(address);
    map_insert(functions, function->address, function);
    object_delete(function);

    // for each newly reachable function
    struct _map_it * mit;
    for (mit = map_iterator(functions); mit != NULL; mit = map_it_next(mit)) {
        struct _function * function = map_it_data(mit);
        uint64_t fitaddress = function->address;

        // if we already have this function, skip it
        if (map_fetch(rdis->functions, function->address) != NULL)
            continue;

        // add this function to the rdis->function_tree
        map_insert(rdis->functions, function->address, function);

        // add label
        struct _label * label = loader_label_address(rdis->loader,
                                                     rdis->memory,
                                                     fitaddress);
        map_insert(rdis->labels, fitaddress, label);
        object_delete(label);

        // if this function is already in our graph, all we need to do is make
        // sure its a separate node and then remove function predecessors
        struct _graph_node * node = graph_fetch_node_max(rdis->graph, fitaddress);
        if (node != NULL) {

            // already a node, remove function predecessors
            if (node->index == address) {
                remove_function_predecessors(rdis->graph, rdis->functions);
                continue;
            }

            // search for instruction with given address
            struct _list    * ins_list = node->data;
            struct _list_it * it;
            for (it = list_iterator(ins_list); it != NULL; it = it->next) {
                struct _ins * ins = it->data;
                // found instruction
                if (ins->address == fitaddress) {
                    // create a new instruction list.
                    // add remaining instructions to new list while removing them from
                    // the current list
                    struct _list * new_ins_list = list_create();
                    while (1) {
                        list_append(new_ins_list, it->data);
                        it = list_remove(ins_list, it);
                        if (it == NULL)
                            break;
                    }
                    // create a new graph node for this new function
                    graph_add_node(rdis->graph, fitaddress, new_ins_list);
                    // all graph successors from old node are added to new node
                    struct _queue   * queue      = queue_create();
                    struct _list    * successors = graph_node_successors(node);
                    struct _list_it * sit;
                    for (sit = list_iterator(successors);
                         sit != NULL;
                         sit = sit->next) {
                        struct _graph_edge * edge = sit->data;
                        graph_add_edge(rdis->graph,
                                       fitaddress,
                                       edge->tail,
                                       edge->data);
                        queue_push(queue, edge);
                    }
                    object_delete(successors);

                    // and removed from old node
                    while (queue->size > 0) {
                        struct _graph_edge * edge = queue_peek(queue);
                        graph_remove_edge(rdis->graph, edge->head, edge->tail);
                        queue_pop(queue);
                    }
                    object_delete(queue);

                    // that was easy
                    break;
                }
            }
            if (it != NULL)
                continue;
        }

        // we need to create a new graph for this node
        struct _graph * graph = loader_graph_address(rdis->loader,
                                                     rdis->memory,
                                                     fitaddress);
        graph_merge(rdis->graph, graph);
        object_delete(graph);
    }

    object_delete(functions);

    rdis_callback(rdis, RDIS_CALLBACK_ALL);

    return 0;
}