Пример #1
0
static void handle_die(
        struct dwarf_subprogram_t **subprograms,
        Dwarf_Debug dbg, Dwarf_Die cu_die, Dwarf_Die the_die, Dwarf_Unsigned language)
{
    int rc;
    Dwarf_Error err;
    Dwarf_Die current_die = the_die;
    Dwarf_Die child_die = NULL;
    Dwarf_Die next_die;

    do {
        *subprograms = read_cu_entry(*subprograms, dbg, cu_die, current_die, language);

        /* Recursive call handle_die with child, to continue searching within child dies */
        rc = dwarf_child(current_die, &child_die, &err);
        DWARF_ASSERT(rc, err);
        if (rc == DW_DLV_OK && child_die)
            handle_die(subprograms, dbg, cu_die, child_die, language);    

        rc = dwarf_siblingof(dbg, current_die, &next_die, &err);
        DWARF_ASSERT(rc, err);

        dwarf_dealloc(dbg, current_die, DW_DLA_DIE);

        current_die = next_die;
    } while (rc != DW_DLV_NO_ENTRY);
}
Пример #2
0
static struct dwarf_subprogram_t *read_from_cus(Dwarf_Debug dbg)
{
    Dwarf_Unsigned cu_header_length, abbrev_offset, next_cu_header;
    Dwarf_Half version_stamp, address_size;
    Dwarf_Error err;
    Dwarf_Die no_die = 0, cu_die, child_die, next_die;
    int ret = DW_DLV_OK;
    int rc;
    struct dwarf_subprogram_t *subprograms = NULL;

    while (ret == DW_DLV_OK) {
        ret = dwarf_next_cu_header(
                dbg,
                &cu_header_length,
                &version_stamp,
                &abbrev_offset,
                &address_size,
                &next_cu_header,
                &err);
        DWARF_ASSERT(ret, err);

        if (ret == DW_DLV_NO_ENTRY)
            continue;

        /* TODO: If the CU can provide an address range then we can skip over
         * all the entire die if none of our addresses match */

        /* Expect the CU to have a single sibling - a DIE */
        ret = dwarf_siblingof(dbg, no_die, &cu_die, &err);
        if (ret == DW_DLV_ERROR) {
            continue;
        }
        DWARF_ASSERT(ret, err);

        /* Expect the CU DIE to have children */
        ret = dwarf_child(cu_die, &child_die, &err);
        DWARF_ASSERT(ret, err);

        next_die = child_die;

        /* Now go over all children DIEs */
        do {
            subprograms = read_cu_entry(subprograms, dbg, cu_die, child_die);

            rc = dwarf_siblingof(dbg, child_die, &next_die, &err);
            DWARF_ASSERT(rc, err);

            dwarf_dealloc(dbg, child_die, DW_DLA_DIE);

            child_die = next_die;
        } while (rc != DW_DLV_NO_ENTRY);

        dwarf_dealloc(dbg, cu_die, DW_DLA_DIE);
    }

    return subprograms;
}
Пример #3
0
static struct dwarf_subprogram_t *read_from_cus(Dwarf_Debug dbg)
{
    Dwarf_Unsigned cu_header_length, abbrev_offset, next_cu_header;
    Dwarf_Half version_stamp, address_size;
    Dwarf_Error err;
    Dwarf_Die no_die = 0, cu_die, child_die;
    int ret = DW_DLV_OK;
    struct dwarf_subprogram_t *subprograms = NULL;
    Dwarf_Unsigned language = 0;
    Dwarf_Attribute language_attr = 0;

    while (ret == DW_DLV_OK) {
        ret = dwarf_next_cu_header(
                dbg,
                &cu_header_length,
                &version_stamp,
                &abbrev_offset,
                &address_size,
                &next_cu_header,
                &err);
        DWARF_ASSERT(ret, err);

        if (ret == DW_DLV_NO_ENTRY)
            continue;

        /* TODO: If the CU can provide an address range then we can skip over
         * all the entire die if none of our addresses match */

        /* Expect the CU to have a single sibling - a DIE */
        ret = dwarf_siblingof(dbg, no_die, &cu_die, &err);
        if (ret == DW_DLV_ERROR) {
            continue;
        }
        DWARF_ASSERT(ret, err);

        /* Get compilation unit language attribute */
        ret = dwarf_attr(cu_die, DW_AT_language, &language_attr, &err);
        DWARF_ASSERT(ret, err);
        if (ret != DW_DLV_NO_ENTRY) {
            /* Get language attribute data */
            ret = dwarf_formudata(language_attr, &language, &err);
            DWARF_ASSERT(ret, err);
            dwarf_dealloc(dbg, language_attr, DW_DLA_ATTR);
        }

        /* Expect the CU DIE to have children */
        ret = dwarf_child(cu_die, &child_die, &err);
        DWARF_ASSERT(ret, err);

        handle_die(&subprograms, dbg, cu_die, child_die, language);  

        dwarf_dealloc(dbg, cu_die, DW_DLA_DIE);
    }

    return subprograms;
}
Пример #4
0
/* List a function if it's in the given DIE.
*/
static struct dwarf_subprogram_t *read_cu_entry(
        struct dwarf_subprogram_t *subprograms,
        Dwarf_Debug dbg, Dwarf_Die cu_die, Dwarf_Die the_die)
{
    char* die_name = 0;
    Dwarf_Error err;
    Dwarf_Half tag;
    Dwarf_Addr lowpc = 0;
    Dwarf_Addr highpc = 0;
    char *filename;
    struct dwarf_subprogram_t *subprogram = NULL;
    int rc;
    Dwarf_Attribute attrib = 0;

    rc = dwarf_tag(the_die, &tag, &err);
    if (rc != DW_DLV_OK)
        fatal("unable to parse dwarf tag");

    /* Only interested in subprogram DIEs here */
    if (tag != DW_TAG_subprogram)
        return subprograms;

    rc = dwarf_diename(the_die, &die_name, &err);
    if (rc == DW_DLV_ERROR)
        fatal("unable to parse dwarf diename");

    if (rc == DW_DLV_NO_ENTRY)
        return subprograms;

    rc = dwarf_attr(cu_die, DW_AT_name, &attrib, &err);
    DWARF_ASSERT(rc, err);

    if (rc != DW_DLV_NO_ENTRY) {
        rc = dwarf_formstring(attrib, &filename, &err);
        DWARF_ASSERT(rc, err);

        dwarf_dealloc(dbg, attrib, DW_DLA_ATTR);
    }

    rc = dwarf_lowpc(the_die, &lowpc, &err);
    DWARF_ASSERT(rc, err);

    rc = dwarf_highpc(the_die, &highpc, &err);
    DWARF_ASSERT(rc, err);

    /* TODO: when would these not be defined? */
    if (lowpc && highpc) {
        subprogram = malloc(sizeof(*subprogram));
        if (!subprogram)
            fatal("unable to allocate memory");
        memset(subprogram, 0, sizeof(*subprogram));

        subprogram->lowpc = lowpc;
        subprogram->highpc = highpc;
        subprogram->name = die_name;

        subprogram->next = subprograms;
        subprograms = subprogram;
    }

    return subprograms;
}
Пример #5
0
/* simple but too slow */
struct dwarf_subprogram_t *read_from_globals(Dwarf_Debug dbg)
{
    Dwarf_Global *globals = NULL;
    Dwarf_Signed nglobals;
    Dwarf_Off offset;
    Dwarf_Die die;
    Dwarf_Addr lowpc = 0;
    Dwarf_Addr highpc = 0;
    Dwarf_Error err;
    Dwarf_Attribute attrib = 0;
    struct dwarf_subprogram_t *subprograms = NULL;
    struct dwarf_subprogram_t *subprogram = NULL;
    char *name;
    int i;
    int ret;

    ret = dwarf_get_globals(dbg, &globals, &nglobals, &err);
    DWARF_ASSERT(ret, err);

    if (ret != DW_DLV_OK)
        fatal("unable to get dwarf globals");

    for (i = 0; i < nglobals; i++) {
        ret = dwarf_global_die_offset(globals[i], &offset, &err);
        DWARF_ASSERT(ret, err);

        /* TODO: this function does a linear search, making it pretty damn
         * slow.. see libdwarf/dwarf_die_deliv.c:_dwarf_find_CU_Context
         * for details */
        ret = dwarf_offdie(dbg, offset, &die, &err);
        DWARF_ASSERT(ret, err);

        ret = dwarf_lowpc(die, &lowpc, &err);
        DWARF_ASSERT(ret, err);

        ret = dwarf_highpc(die, &highpc, &err);
        DWARF_ASSERT(ret, err);

        /* TODO: when would these not be defined? */
        if (lowpc && highpc) {
            subprogram = malloc(sizeof(*subprogram));
            if (!subprogram)
                fatal("unable to allocate memory for subprogram");
            memset(subprogram, 0, sizeof(*subprogram));

            ret = dwarf_attr(die, DW_AT_MIPS_linkage_name, &attrib, &err);
            if (ret == DW_DLV_OK) {
                ret = dwarf_formstring(attrib, &name, &err);
                DWARF_ASSERT(ret, err);

                dwarf_dealloc(dbg, attrib, DW_DLA_ATTR);
            } else {
                ret = dwarf_globname(globals[i], &name, &err);
                DWARF_ASSERT(ret, err);
            }

            subprogram->lowpc = lowpc;
            subprogram->highpc = highpc;
            subprogram->name = name;

            subprogram->next = subprograms;
            subprograms = subprogram;
        }

        dwarf_dealloc(dbg, die, DW_DLA_DIE);
    }

    return subprograms;
}
Пример #6
0
/* The following function concatenates function parameters to the function name.
 in case we symbolicate a Swift compilation unit, since Swift enables mutliple overloads for the same function name */
static char* get_function_name_with_params(char *die_name, Dwarf_Die the_die, Dwarf_Debug dbg)
{
    int rc;
    Dwarf_Error err;

    /* Allocate symbol name string buffer */
    int symbol_name_buffer_length = (strlen(die_name) + 2) * 32; /* Buffer size */
    char *symbol_name = malloc(symbol_name_buffer_length);
    if (!symbol_name)
        fatal("unable to allocate memory");
    
    /* Concatenate subprogram name and " (" */
    strcpy(symbol_name, die_name);
    strcat(symbol_name, " (");
    int symbol_name_length = strlen(symbol_name); /* Actual string length */

    /* Get subprogram children */
    Dwarf_Die child_die = NULL;
    Dwarf_Die next_die;
    rc = dwarf_child(the_die, &child_die, &err);
    DWARF_ASSERT(rc, err);
    
    if (rc == DW_DLV_OK && child_die){
        do {
            /* Get child tag */
            Dwarf_Half child_tag;
            rc = dwarf_tag(child_die, &child_tag, &err);
            if (rc != DW_DLV_OK)
                fatal("unable to parse dwarf tag");
            
            /* Check if child is a parameter */
            if (child_tag == DW_TAG_formal_parameter) {
                char* param_name = 0;

                /* Get param name (child die name), ignoring the "self" parameter */
                rc = dwarf_diename(child_die, &param_name, &err);
                if (rc == DW_DLV_OK && strcmp(param_name, "self") != 0) {
                
                    /* Update actual symbol name string length */
                    symbol_name_length += strlen(param_name) + 2;
                    
                    /* Check if symbol name string buffer needs expansion */
                    if (symbol_name_length >= symbol_name_buffer_length - 1)
                        
                    /* Expand (reallocate) symbol name string buffer */
                        symbol_name = realloc(symbol_name, symbol_name_buffer_length *= 2);
                    
                    /* Concatenate param name and ", " */
                    strcat(symbol_name, param_name);
                    strcat(symbol_name, ", ");
                }
            }
            
            /* Move to next sibling (param) */
            rc = dwarf_siblingof(dbg, child_die, &next_die, &err);
            DWARF_ASSERT(rc, err);
            dwarf_dealloc(dbg, child_die, DW_DLA_DIE);
            
            child_die = next_die;
        } while (rc != DW_DLV_NO_ENTRY);
    }

    /* Remove trailing ", " if needed */
    int len = strlen(symbol_name);
    if (symbol_name[len - 1] == ' ') {
        symbol_name[len - 1] = 0;
        symbol_name[len - 2] = 0;
    }
    
    strcat (symbol_name, ")");

    return symbol_name;
}