コード例 #1
0
ファイル: dwarf_print_lines.c プロジェクト: jrfonseca/drmingw
/*  return DW_DLV_OK if ok. else DW_DLV_NO_ENTRY or DW_DLV_ERROR
    If err_count_out is non-NULL, this is a special 'check'
    call.  */
static int
_dwarf_internal_printlines(Dwarf_Die die,
    Dwarf_Error * error,
    int * err_count_out,
    int only_line_header)
{
    /*  This pointer is used to scan the portion of the .debug_line
        section for the current cu. */
    Dwarf_Small *line_ptr = 0;
    Dwarf_Small *orig_line_ptr = 0;

    /*  Pointer to a DW_AT_stmt_list attribute in case it exists in the
        die. */
    Dwarf_Attribute stmt_list_attr = 0;

    /*  Pointer to DW_AT_comp_dir attribute in die. */
    Dwarf_Attribute comp_dir_attr = 0;

    /*  Pointer to name of compilation directory. */
    Dwarf_Small *comp_dir = NULL;

    /*  Offset into .debug_line specified by a DW_AT_stmt_list
        attribute. */
    Dwarf_Unsigned line_offset = 0;

    Dwarf_Sword i=0;
    Dwarf_Word u=0;

    /*  These variables are used to decode leb128 numbers. Leb128_num
        holds the decoded number, and leb128_length is its length in
        bytes. */
    Dwarf_Half attrform = 0;

    /*  In case there are wierd bytes 'after' the line table
        prologue this lets us print something. This is a gcc
        compiler bug and we expect the bytes count to be 12.  */
    Dwarf_Small* bogus_bytes_ptr = 0;
    Dwarf_Unsigned bogus_bytes_count = 0;
    Dwarf_Half address_size = 0;
    Dwarf_Unsigned fission_offset = 0;


    /* The Dwarf_Debug this die belongs to. */
    Dwarf_Debug dbg=0;
    Dwarf_CU_Context cu_context = 0;
    Dwarf_Line_Context line_context = 0;
    int resattr = DW_DLV_ERROR;
    int lres =    DW_DLV_ERROR;
    int res  =    DW_DLV_ERROR;
    Dwarf_Small *line_ptr_actuals  = 0;
    Dwarf_Small *line_ptr_end = 0;
    Dwarf_Small *section_start = 0;

    /* ***** BEGIN CODE ***** */

    if (error != NULL) {
        *error = NULL;
    }

    CHECK_DIE(die, DW_DLV_ERROR);
    cu_context = die->di_cu_context;
    dbg = cu_context->cc_dbg;

    res = _dwarf_load_section(dbg, &dbg->de_debug_line,error);
    if (res != DW_DLV_OK) {
        return res;
    }
    if (!dbg->de_debug_line.dss_size) {
        return (DW_DLV_NO_ENTRY);
    }

    address_size = _dwarf_get_address_size(dbg, die);
    resattr = dwarf_attr(die, DW_AT_stmt_list, &stmt_list_attr, error);
    if (resattr != DW_DLV_OK) {
        return resattr;
    }


    /*  The list of relevant FORMs is small.
        DW_FORM_data4, DW_FORM_data8, DW_FORM_sec_offset
    */
    lres = dwarf_whatform(stmt_list_attr,&attrform,error);
    if (lres != DW_DLV_OK) {
        return lres;
    }
    if (attrform != DW_FORM_data4 && attrform != DW_FORM_data8 &&
        attrform != DW_FORM_sec_offset ) {
        _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD);
        return (DW_DLV_ERROR);
    }
    lres = dwarf_global_formref(stmt_list_attr, &line_offset, error);
    if (lres != DW_DLV_OK) {
        return lres;
    }

    if (line_offset >= dbg->de_debug_line.dss_size) {
        _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD);
        return (DW_DLV_ERROR);
    }
    section_start =  dbg->de_debug_line.dss_data;
    {
        Dwarf_Unsigned fission_size = 0;
        int resfis = _dwarf_get_fission_addition_die(die, DW_SECT_LINE,
            &fission_offset,&fission_size,error);
        if(resfis != DW_DLV_OK) {
            return resfis;
        }
    }

    orig_line_ptr = section_start + line_offset + fission_offset;
    line_ptr = orig_line_ptr;
    dwarf_dealloc(dbg, stmt_list_attr, DW_DLA_ATTR);

    /*  If die has DW_AT_comp_dir attribute, get the string that names
        the compilation directory. */
    resattr = dwarf_attr(die, DW_AT_comp_dir, &comp_dir_attr, error);
    if (resattr == DW_DLV_ERROR) {
        return resattr;
    }
    if (resattr == DW_DLV_OK) {
        int cres = DW_DLV_ERROR;
        char *cdir = 0;

        cres = dwarf_formstring(comp_dir_attr, &cdir, error);
        if (cres == DW_DLV_ERROR) {
            return cres;
        } else if (cres == DW_DLV_OK) {
            comp_dir = (Dwarf_Small *) cdir;
        }
    }
    if (resattr == DW_DLV_OK) {
        dwarf_dealloc(dbg, comp_dir_attr, DW_DLA_ATTR);
    }
    line_context = (Dwarf_Line_Context)
        _dwarf_get_alloc(dbg, DW_DLA_LINE_CONTEXT, 1);
    if (line_context == NULL) {
        _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
        return (DW_DLV_ERROR);
    }
    {
        Dwarf_Small *newlinep = 0;
        int dres = _dwarf_read_line_table_header(dbg,
            cu_context,
            section_start,
            line_ptr,
            dbg->de_debug_line.dss_size,
            &newlinep,
            line_context,
            &bogus_bytes_ptr,
            &bogus_bytes_count,
            error,
            err_count_out);
        if (dres == DW_DLV_ERROR) {
            dwarf_srclines_dealloc_b(line_context);
            return dres;
        }
        if (dres == DW_DLV_NO_ENTRY) {
            dwarf_srclines_dealloc_b(line_context);
            return dres;
        }
        line_ptr_end = line_context->lc_line_ptr_end;
        line_ptr = newlinep;
        if (line_context->lc_actuals_table_offset > 0) {
            line_ptr_actuals = line_context->lc_line_prologue_start +
                line_context->lc_actuals_table_offset;
        }
    }
    line_context->lc_compilation_directory = comp_dir;
    if (only_line_header) {
        /* Just checking for header errors, nothing more here.*/
        dwarf_srclines_dealloc_b(line_context);
        return DW_DLV_OK;
    }

    dwarf_printf(dbg,
        "total line info length %ld bytes,"
        " line offset 0x%" DW_PR_XZEROS DW_PR_DUx
        " %" DW_PR_DUu "\n",
        (long) line_context->lc_total_length,
        line_context->lc_section_offset,
        line_context->lc_section_offset);
    if (line_context->lc_version_number <= DW_LINE_VERSION5) {
        dwarf_printf(dbg,
            "line table version %d\n",(int) line_context->lc_version_number);
    } else {
        dwarf_printf(dbg,
            "line table version 0x%x\n",(int) line_context->lc_version_number);
    }
    dwarf_printf(dbg,
        "line table length field length %d prologue length %d\n",
        (int)line_context->lc_length_field_length,
        (int)line_context->lc_prologue_length);
    dwarf_printf(dbg,
        "compilation_directory %s\n",
        comp_dir ? ((char *) comp_dir) : "");

    dwarf_printf(dbg,
        "  min instruction length %d\n",
        (int) line_context->lc_minimum_instruction_length);
    if (line_context->lc_version_number == EXPERIMENTAL_LINE_TABLES_VERSION) {
        dwarf_printf(dbg, "  actuals table offset "
            "0x%" DW_PR_XZEROS DW_PR_DUx
            " logicals table offset "
            "0x%" DW_PR_XZEROS DW_PR_DUx "\n",
            line_context->lc_actuals_table_offset,
            line_context->lc_logicals_table_offset);
    }
    if (line_context->lc_version_number == DW_LINE_VERSION5) {
        dwarf_printf(dbg,
            "  segment selector size %d\n",
            (int) line_context->lc_segment_selector_size);
        dwarf_printf(dbg,
            "  address    size       %d\n",
            (int) line_context->lc_address_size);
    }
    dwarf_printf(dbg,
        "  default is stmt        %d\n",(int)line_context->lc_default_is_stmt);
    dwarf_printf(dbg,
        "  line base              %d\n",(int)line_context->lc_line_base);
    dwarf_printf(dbg,
        "  line_range             %d\n",(int)line_context->lc_line_range);
    dwarf_printf(dbg,
        "  opcode base            %d\n",(int)line_context->lc_opcode_base);
    dwarf_printf(dbg,
        "  standard opcode count  %d\n",(int)line_context->lc_std_op_count);

    for (i = 1; i < line_context->lc_opcode_base; i++) {
        dwarf_printf(dbg,
            "  opcode[%2d] length  %d\n", (int) i,
            (int) line_context->lc_opcode_length_table[i - 1]);
    }
    dwarf_printf(dbg,
        "  include directories count %d\n",
        (int) line_context->lc_include_directories_count);
    for (u = 0; u < line_context->lc_include_directories_count; ++u) {
        dwarf_printf(dbg,
            "  include dir[%u] %s\n",
            (int) u, line_context->lc_include_directories[u]);
    }
    dwarf_printf(dbg,
        "  files count            %d\n",
        (int) line_context->lc_file_entry_count);

    if (line_context->lc_file_entry_count) {
        Dwarf_File_Entry fe = line_context->lc_file_entries;
        Dwarf_File_Entry fe2 = fe;
        unsigned fiu = 0;

        for (fiu = 0 ; fe2 ; fe2 = fe->fi_next,++fiu ) {
            Dwarf_Unsigned tlm2 = 0;
            Dwarf_Unsigned di = 0;
            Dwarf_Unsigned fl = 0;

            fe = fe2;
            tlm2 = fe->fi_time_last_mod;
            di = fe->fi_dir_index;
            fl = fe->fi_file_length;

            dwarf_printf(dbg,
                "  file[%u]  %s (file-number: %u) \n",
                (unsigned) fiu, (char *) fe->fi_file_name,
                (unsigned)(fiu+1));
            dwarf_printf(dbg,
                "    dir index %d\n", (int) di);
            {
                time_t tt = (time_t) tlm2;

                /* ctime supplies newline */
                dwarf_printf(dbg,
                    "    last time 0x%x %s",
                    (unsigned) tlm2, ctime(&tt));
                }
            dwarf_printf(dbg,
                "    file length %ld 0x%lx\n",
                (long) fl, (unsigned long) fl);
        }
    }

    if (line_context->lc_version_number == EXPERIMENTAL_LINE_TABLES_VERSION) {
        /*  Print the subprograms list. */
        Dwarf_Unsigned count = line_context->lc_subprogs_count;
        Dwarf_Unsigned exu = 0;
        Dwarf_Subprog_Entry sub = line_context->lc_subprogs;
        dwarf_printf(dbg,"  subprograms count"
            " %" DW_PR_DUu "\n",count);
        if (count > 0) {
            dwarf_printf(dbg,"    indx  file   line   name\n");
        }
        for (exu = 0 ; exu < count ; exu++,sub++) {
            dwarf_printf(dbg,"    [%2" DW_PR_DUu "] %4" DW_PR_DUu
                "    %4" DW_PR_DUu " %s\n",
                exu+1,
                sub->ds_decl_file,
                sub->ds_decl_line,
                sub->ds_subprog_name);
        }
    }
    {
        Dwarf_Unsigned offset = 0;
        if (bogus_bytes_count > 0) {
            Dwarf_Unsigned wcount = bogus_bytes_count;
            Dwarf_Unsigned boffset = bogus_bytes_ptr - section_start;
            dwarf_printf(dbg,
                "*** DWARF CHECK: the line table prologue  header_length "
                " is %" DW_PR_DUu " too high, we pretend it is smaller."
                "Section offset: 0x%" DW_PR_XZEROS DW_PR_DUx
                " (%" DW_PR_DUu ") ***\n",
                wcount, boffset,boffset);
            *err_count_out += 1;
        }
        offset = line_ptr - section_start;
        dwarf_printf(dbg,
            "  statement prog offset in section: 0x%"
            DW_PR_XZEROS DW_PR_DUx " (%" DW_PR_DUu ")\n",
            offset, offset);
    }

    {
        Dwarf_Bool doaddrs = false;
        Dwarf_Bool dolines = true;

        _dwarf_print_line_context_record(dbg,line_context);
        if (!line_ptr_actuals) {
            /* Normal single level line table. */

            Dwarf_Bool is_single_table = true;
            Dwarf_Bool is_actuals_table = false;
            print_line_header(dbg, is_single_table, is_actuals_table);
            res = read_line_table_program(dbg,
                line_ptr, line_ptr_end, orig_line_ptr,
                section_start,
                line_context,
                address_size, doaddrs, dolines,
                is_single_table,
                is_actuals_table,
                error,
                err_count_out);
            if (res != DW_DLV_OK) {
                dwarf_srclines_dealloc_b(line_context);
                return res;
            }
        } else {
            Dwarf_Bool is_single_table = false;
            Dwarf_Bool is_actuals_table = false;
            if (line_context->lc_version_number !=
                EXPERIMENTAL_LINE_TABLES_VERSION) {
                dwarf_srclines_dealloc_b(line_context);
                _dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR);
                return (DW_DLV_ERROR);
            }
            /* Read Logicals */
            print_line_header(dbg, is_single_table, is_actuals_table);
            res = read_line_table_program(dbg,
                line_ptr, line_ptr_actuals, orig_line_ptr,
                section_start,
                line_context,
                address_size, doaddrs, dolines,
                is_single_table,
                is_actuals_table,
                error,err_count_out);
            if (res != DW_DLV_OK) {
                dwarf_srclines_dealloc_b(line_context);
                return res;
            }
            if (line_context->lc_actuals_table_offset > 0) {
                is_actuals_table = true;
                /* Read Actuals */

                print_line_header(dbg, is_single_table, is_actuals_table);
                res = read_line_table_program(dbg,
                    line_ptr_actuals, line_ptr_end, orig_line_ptr,
                    section_start,
                    line_context,
                    address_size, doaddrs, dolines,
                    is_single_table,
                    is_actuals_table,
                    error,
                    err_count_out);
                if (res != DW_DLV_OK) {
                    dwarf_srclines_dealloc_b(line_context);
                    return res;
                }
            }
        }
    }
    dwarf_srclines_dealloc_b(line_context);
    return DW_DLV_OK;
}
コード例 #2
0
ファイル: dwarf_ranges.c プロジェクト: tomhughes/libdwarf
int dwarf_get_ranges_a(Dwarf_Debug dbg,
    Dwarf_Off rangesoffset,
    Dwarf_Die die,
    Dwarf_Ranges ** rangesbuf,
    Dwarf_Signed * listlen,
    Dwarf_Unsigned * bytecount,
    Dwarf_Error * error)
{
    Dwarf_Small *rangeptr = 0;
    Dwarf_Small *beginrangeptr = 0;
    Dwarf_Small *section_end = 0;
    unsigned entry_count = 0;
    struct ranges_entry *base = 0;
    struct ranges_entry *last = 0;
    struct ranges_entry *curre = 0;
    Dwarf_Ranges * ranges_data_out = 0;
    unsigned copyindex = 0;
    Dwarf_Half address_size = 0;
    int res = DW_DLV_ERROR;
    Dwarf_Unsigned rangebase = 0;
    Dwarf_Debug localdbg = dbg;
    Dwarf_Error localerror = 0;

    if (die &&localdbg->de_tied_data.td_tied_object) {
        /*  ASSERT: localdbg->de_debug_ranges is missing: DW_DLV_NO_ENTRY.
            So lets not look in dbg. */
        Dwarf_CU_Context context = 0;
        int restied = 0;

        context = die->di_cu_context;
        restied = _dwarf_get_ranges_base_attr_from_tied(localdbg,
            context,
            &rangebase,
            error);
        if (restied == DW_DLV_ERROR ) {
            if(!error) {
                return restied;
            }
            dwarf_dealloc(localdbg,*error,DW_DLA_ERROR);
            *error = 0;
            /* Nothing else to do. Look in original dbg. */
        } else if (restied == DW_DLV_NO_ENTRY ) {
            /* Nothing else to do. Look in original dbg. */
        } else {
            /*  Ranges are never in a split dwarf object.
                In the base object
                instead. Use the tied_object */
            localdbg = dbg->de_tied_data.td_tied_object;
        }
    }


    res = _dwarf_load_section(localdbg, &localdbg->de_debug_ranges,&localerror);
    if (res == DW_DLV_ERROR) {
        _dwarf_error_mv_s_to_t(localdbg,&localerror,dbg,error);
        return res;
    } else if (res == DW_DLV_NO_ENTRY) {
        return res;
    }

    if ((rangesoffset +rangebase) >= localdbg->de_debug_ranges.dss_size) {
        _dwarf_error(dbg, error, DW_DLE_DEBUG_RANGES_OFFSET_BAD);
        return (DW_DLV_ERROR);

    }
    address_size = _dwarf_get_address_size(localdbg, die);
    section_end = localdbg->de_debug_ranges.dss_data +
        localdbg->de_debug_ranges.dss_size;
    rangeptr = localdbg->de_debug_ranges.dss_data + rangesoffset+rangebase;
    beginrangeptr = rangeptr;

    for (;;) {
        struct ranges_entry * re = 0;

        if (rangeptr == section_end) {
            break;
        }
        if (rangeptr  > section_end) {
            free_allocated_ranges(base);
            _dwarf_error(dbg, error, DW_DLE_DEBUG_RANGES_OFFSET_BAD);
            return (DW_DLV_ERROR);
            break;
        }
        re = calloc(sizeof(struct ranges_entry),1);
        if (!re) {
            free_allocated_ranges(base);
            _dwarf_error(dbg, error, DW_DLE_DEBUG_RANGES_OUT_OF_MEM);
            return (DW_DLV_ERROR);
        }
        if ((rangeptr + (2*address_size)) > section_end) {
            free(re);
            free_allocated_ranges(base);
            _dwarf_error(dbg, error, DW_DLE_DEBUG_RANGES_OFFSET_BAD);
            return (DW_DLV_ERROR);
        }
        entry_count++;
        res = read_unaligned_addr_check(localdbg,&re->cur.dwr_addr1,
            rangeptr, address_size,error,section_end);
        if (res != DW_DLV_OK) {
            free(re);
            free_allocated_ranges(base);
            return res;
        }
        rangeptr +=  address_size;
        res = read_unaligned_addr_check(localdbg,&re->cur.dwr_addr2,
            rangeptr, address_size,error,section_end);
        if (res != DW_DLV_OK) {
            free(re);
            free_allocated_ranges(base);
            return res;
        }
        rangeptr +=  address_size;
        if (!base) {
            base = re;
            last = re;
        } else {
            last->next = re;
            last = re;
        }
        if (re->cur.dwr_addr1 == 0 && re->cur.dwr_addr2 == 0) {
            re->cur.dwr_type =  DW_RANGES_END;
            break;
        } else if (re->cur.dwr_addr1 == MAX_ADDR) {
            re->cur.dwr_type =  DW_RANGES_ADDRESS_SELECTION;
        } else {
            re->cur.dwr_type =  DW_RANGES_ENTRY;
        }
    }

    /* We return ranges on dbg, so use that to allocate. */
    ranges_data_out =   (Dwarf_Ranges *)
        _dwarf_get_alloc(dbg,DW_DLA_RANGES,entry_count);
    if (!ranges_data_out) {
        /* Error, apply to original, not local dbg. */
        free_allocated_ranges(base);
        _dwarf_error(dbg, error, DW_DLE_DEBUG_RANGES_OUT_OF_MEM);
        return (DW_DLV_ERROR);
    }
    curre = base;
    *rangesbuf = ranges_data_out;
    *listlen = entry_count;
    for (copyindex = 0; curre && (copyindex < entry_count);
        ++copyindex,++ranges_data_out) {

        *ranges_data_out = curre->cur;
        curre = curre->next;
    }
    /* ASSERT: curre == NULL */
    free_allocated_ranges(base);
    base = 0;
    /* Callers will often not care about the bytes used. */
    if (bytecount) {
        *bytecount = rangeptr - beginrangeptr;
    }
    return DW_DLV_OK;
}
コード例 #3
0
ファイル: dwarf_ranges.c プロジェクト: ESLab/rtdl
int dwarf_get_ranges_a(Dwarf_Debug dbg,
    Dwarf_Off rangesoffset,
    Dwarf_Die die,
    Dwarf_Ranges ** rangesbuf,
    Dwarf_Signed * listlen,
    Dwarf_Unsigned * bytecount,
    Dwarf_Error * error)
{
    Dwarf_Small *rangeptr = 0;
    Dwarf_Small *beginrangeptr = 0;
    Dwarf_Small *section_end = 0;
    unsigned entry_count = 0;
    struct ranges_entry *base = 0;
    struct ranges_entry *last = 0;
    struct ranges_entry *curre = 0;
    Dwarf_Ranges * ranges_data_out = 0;
    unsigned copyindex = 0;
    Dwarf_Half address_size = 0;
    int res = DW_DLV_ERROR;

    res = _dwarf_load_section(dbg, &dbg->de_debug_ranges,error);
    if (res != DW_DLV_OK) {
        return res;
    }

    if(rangesoffset >= dbg->de_debug_ranges.dss_size) {
        _dwarf_error(dbg, error, DW_DLE_DEBUG_RANGES_OFFSET_BAD);
        return (DW_DLV_ERROR);

    }
    address_size = _dwarf_get_address_size(dbg, die);
    section_end = dbg->de_debug_ranges.dss_data + 
        dbg->de_debug_ranges.dss_size;
    rangeptr = dbg->de_debug_ranges.dss_data + rangesoffset;
    beginrangeptr = rangeptr;

    for(;;) {
        struct ranges_entry * re = calloc(sizeof(struct ranges_entry),1);
        if(!re) {
            _dwarf_error(dbg, error, DW_DLE_DEBUG_RANGES_OUT_OF_MEM);
            return (DW_DLV_ERROR);
        }
        if(rangeptr  >= section_end) {
            return (DW_DLV_NO_ENTRY);
        }
        if((rangeptr + (2*address_size)) > section_end) {
            _dwarf_error(dbg, error, DW_DLE_DEBUG_RANGES_OFFSET_BAD);
            return (DW_DLV_ERROR);
        }
        entry_count++;
        READ_UNALIGNED(dbg,re->cur.dwr_addr1,
            Dwarf_Addr, rangeptr,
            address_size);
        rangeptr +=  address_size;
        READ_UNALIGNED(dbg,re->cur.dwr_addr2 ,
            Dwarf_Addr, rangeptr,
            address_size);
        rangeptr +=  address_size;
        if(!base) {
            base = re;
            last = re;
        } else {
            last->next = re;
            last = re;
        }
        if(re->cur.dwr_addr1 == 0 && re->cur.dwr_addr2 == 0) {
            re->cur.dwr_type =  DW_RANGES_END;
            break;
        } else if ( re->cur.dwr_addr1 == MAX_ADDR) {
            re->cur.dwr_type =  DW_RANGES_ADDRESS_SELECTION;
        } else {
            re->cur.dwr_type =  DW_RANGES_ENTRY;
        }
    }

    ranges_data_out =   (Dwarf_Ranges *)
    _dwarf_get_alloc(dbg,DW_DLA_RANGES,entry_count);
    if(!ranges_data_out) {
        _dwarf_error(dbg, error, DW_DLE_DEBUG_RANGES_OUT_OF_MEM);
        return (DW_DLV_ERROR);
    }
    curre = base;
    *rangesbuf = ranges_data_out;
    *listlen = entry_count;
    for( copyindex = 0; curre && (copyindex < entry_count); 
        ++copyindex,++ranges_data_out) {

        struct ranges_entry *r = curre;
        *ranges_data_out = curre->cur;
        curre = curre->next;
        free(r);
    }
    /* Callers will often not care about the bytes used. */
    if(bytecount) {
        *bytecount = rangeptr - beginrangeptr;
    }
    return DW_DLV_OK; 
}