Пример #1
0
Файл: elf32.c Проект: 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;
}
Пример #2
0
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;
}
Пример #3
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;
}