首页 > 解决方案 > 链表在执行期间不复合

问题描述

我正在尝试创建一个链接列表,在解析汇编代码文件时存储返回指令。作为对代码的解释,当遇到调用指令时,要保存下一条指令的地址。当遇到返回指令时,应该遍历链表,直到到达下一个节点为 的点NULL。由于某种原因,代码没有保存返回地址。它可能与递归有关吗?

//function to create a node in linked list
struct ret_addr *return_address(cs_insn *insn, struct ret_addr *r) {
    struct ret_addr *ret = malloc(sizeof(*ret));
    ret->address = insn->address + insn->size;
    ret->nxt_ret_addr = r;
    return ret;
}

//retrieve the data from the last node of the linked list
int return_val(struct ret_addr *r) {
    if(r == NULL)
        return 0;
    while(r->nxt_ret_addr != NULL) {
        r = r->nxt_ret_addr;
        return r->address;
    }
}

//parse assembly code
struct bb_data *disassemble_function_cfg(int startAddr, unsigned char *bytes, int end_section) {
    csh handle;
    cs_insn *insn;
    cs_detail *detail;
    size_t count;
    int stop_disasm = 0;

    struct ret_addr *r_data = malloc(sizeof(*r_data));
    count = cs_disasm(handle, bytes, end_section, startAddr, 1, &insn);

    detail = insn->detail;
    for(int n = 0; n < detail->groups_count; n++) {
        if(detail->groups[n] == X86_GRP_CALL) {
            stop_disasm = 1;
            r_data = return_address(insn, r_data);
        }
        else if(detail->groups[n] == X86_GRP_RET) {
            stop_disasm = 1;
            start_edge = return_val(r_data);
        }

    if(!stop_disasm)
        disassemble_function_cfg(insn->address + insn->size, bytes + insn->size, end_section);
    else
        return edges;
}

在初始call指令期间,返回值被保存(通过打印出来检查),但是当到达返回指令时,链表突然为空。我的想法是,这是由对 的不断调用引起的malloc,但我不确定这是否是一个正确的假设。

标签: cdata-structureslinked-list

解决方案


问题出在return_val函数中:它没有修改r_data调用函数的值disassemble_function_cfg

我还假设了一件小事:因为它是一个调用/返回实现,所以链表应该表现为 LIFO(后进先出)。该return_address函数通过插入头部来填充链表,因此该return_val函数应该首先从头部删除地址:在到达之前不需要读取列表NULL

试试这个代码:

//retrieve the data from the last node of the linked list
int return_val(struct ret_addr **r) {
    int ret_val;
    if (*r == NULL)
        return 0;
    ret_val = (*r)->address;
    *r = (*r)->nxt_ret_addr;
    return ret_val;
}

在调用者函数中:

    else if(detail->groups[n] == X86_GRP_RET) {
        stop_disasm = 1;
        start_edge = return_val(&r_data); // address of r_data, so it can be modified
    }

推荐阅读