Exemplo n.º 1
0
int
_dwarf_internal_get_die_comp_dir(Dwarf_Die die, const char **compdir_out,
    const char **compname_out,
    Dwarf_Error *error)
{
    Dwarf_Attribute comp_dir_attr = 0;
    Dwarf_Attribute comp_name_attr = 0;
    int resattr = 0;
    Dwarf_Debug dbg = 0;

    dbg = die->di_cu_context->cc_dbg;
    resattr = dwarf_attr(die, DW_AT_name, &comp_name_attr, error);
    if (resattr == DW_DLV_ERROR) {
        return resattr;
    }
    if (resattr == DW_DLV_OK) {
        int cres = DW_DLV_ERROR;
        char *name = 0;

        cres = dwarf_formstring(comp_name_attr, &name, error);
        if (cres == DW_DLV_ERROR) {
            dwarf_dealloc(dbg, comp_name_attr, DW_DLA_ATTR);
            return cres;
        } else if (cres == DW_DLV_OK) {
            *compname_out = (const char *)name;
        } else {
            /* FALL thru */
        }
    }
    if (resattr == DW_DLV_OK) {
        dwarf_dealloc(dbg, comp_name_attr, DW_DLA_ATTR);
    }
    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) {
            dwarf_dealloc(dbg, comp_dir_attr, DW_DLA_ATTR);
            return cres;
        } else if (cres == DW_DLV_OK) {
            *compdir_out = (const char *) cdir;
        } else {
            /* FALL thru */
        }
    }
    if (resattr == DW_DLV_OK) {
        dwarf_dealloc(dbg, comp_dir_attr, DW_DLA_ATTR);
    }
    return resattr;
}
static void
print_comp_dir(Dwarf_Debug dbg,Dwarf_Die die,int level, struct srcfilesdata *sf)
{
    int res;
    Dwarf_Error error = 0;
    Dwarf_Attribute *attrbuf = 0;
    Dwarf_Signed attrcount = 0;
    Dwarf_Unsigned i;
    res = dwarf_attrlist(die,&attrbuf,&attrcount,&error);
    if(res != DW_DLV_OK) {
        return;
    }
    sf->srcfilesres = dwarf_srcfiles(die,&sf->srcfiles,&sf->srcfilescount, 
        &error);
    for(i = 0; i < attrcount ; ++i) {
        Dwarf_Half aform;
        res = dwarf_whatattr(attrbuf[i],&aform,&error);
        if(res == DW_DLV_OK) {
            if(aform == DW_AT_comp_dir) {
                char *name = 0;
                res = dwarf_formstring(attrbuf[i],&name,&error);
                if(res == DW_DLV_OK) {
                    printf(    "<%3d> compilation directory : \"%s\"\n",
                        level,name);
                }
            }
            if(aform == DW_AT_stmt_list) {
                /* Offset of stmt list for this CU in .debug_line */
            }
        }
        dwarf_dealloc(dbg,attrbuf[i],DW_DLA_ATTR);
    }
    dwarf_dealloc(dbg,attrbuf,DW_DLA_LIST);
}
Exemplo n.º 3
0
/**
 * cu_get_comp_dir - Get the path of compilation directory
 * @cu_die: a CU DIE
 *
 * Get the path of compilation directory of given @cu_die.
 * Since this depends on DW_AT_comp_dir, older gcc will not
 * embedded it. In that case, this returns NULL.
 */
const char *cu_get_comp_dir(Dwarf_Die *cu_die)
{
	Dwarf_Attribute attr;
	if (dwarf_attr(cu_die, DW_AT_comp_dir, &attr) == NULL)
		return NULL;
	return dwarf_formstring(&attr);
}
Exemplo n.º 4
0
/** \brief Get an attribute of a given DIE as a string
 *
 *  \param die       the DIE
 *  \param attribute attribute
 *  \return value of the given attribute of the given DIE
 */
static const char *MC_dwarf_attr_integrate_string(Dwarf_Die * die,
                                                  int attribute)
{
  Dwarf_Attribute attr;
  if (not dwarf_attr_integrate(die, attribute, &attr))
    return nullptr;
  else
    return dwarf_formstring(&attr);
}
Exemplo n.º 5
0
static int frame_callback(Dwfl_Frame *frame, void *userdata) {
        struct stack_context *c = userdata;
        Dwarf_Addr pc, pc_adjusted, bias = 0;
        _cleanup_free_ Dwarf_Die *scopes = NULL;
        const char *fname = NULL, *symbol = NULL;
        Dwfl_Module *module;
        bool is_activation;

        assert(frame);
        assert(c);

        if (c->n_frame >= FRAMES_MAX)
                return DWARF_CB_ABORT;

        if (!dwfl_frame_pc(frame, &pc, &is_activation))
                return DWARF_CB_ABORT;

        pc_adjusted = pc - (is_activation ? 0 : 1);

        module = dwfl_addrmodule(c->dwfl, pc_adjusted);
        if (module) {
                Dwarf_Die *s, *cudie;
                int n;

                cudie = dwfl_module_addrdie(module, pc_adjusted, &bias);
                if (cudie) {
                        n = dwarf_getscopes(cudie, pc_adjusted - bias, &scopes);
                        for (s = scopes; s < scopes + n; s++) {
                                if (IN_SET(dwarf_tag(s), DW_TAG_subprogram, DW_TAG_inlined_subroutine, DW_TAG_entry_point)) {
                                        Dwarf_Attribute *a, space;

                                        a = dwarf_attr_integrate(s, DW_AT_MIPS_linkage_name, &space);
                                        if (!a)
                                                a = dwarf_attr_integrate(s, DW_AT_linkage_name, &space);
                                        if (a)
                                                symbol = dwarf_formstring(a);
                                        if (!symbol)
                                                symbol = dwarf_diename(s);

                                        if (symbol)
                                                break;
                                }
                        }
                }

                if (!symbol)
                        symbol = dwfl_module_addrname(module, pc_adjusted);

                fname = dwfl_module_info(module, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
        }

        fprintf(c->f, "#%-2u 0x%016" PRIx64 " %s (%s)\n", c->n_frame, (uint64_t) pc, strna(symbol), strna(fname));
        c->n_frame ++;

        return DWARF_CB_OK;
}
Exemplo n.º 6
0
error_t is_right_var(Dwarf_Die var_die, char* var_name, bool* found){
	char* die_name = 0;
	Dwarf_Error err;
	Dwarf_Half tag;
	Dwarf_Attribute* attrs;
	Dwarf_Signed attrcount, i;
	int rc = dwarf_diename(var_die, &die_name, &err);

	if (rc == DW_DLV_ERROR)
		return E_FATAL;
	else if (rc == DW_DLV_NO_ENTRY)
		return E_NONE;

	if (dwarf_tag(var_die, &tag, &err) != DW_DLV_OK)
		return E_FATAL;

	/* Only interested in variable DIEs here */
	if (tag != DW_TAG_variable)
		return E_NONE;


	/* Grab the DIEs attributes for display */
	if (dwarf_attrlist(var_die, &attrs, &attrcount, &err) != DW_DLV_OK)
		return E_FATAL;
	
	for (i = 0; i < attrcount; ++i) {
		Dwarf_Half attrcode;
		if (dwarf_whatattr(attrs[i], &attrcode, &err) != DW_DLV_OK)
			return E_FATAL;

		
		if (attrcode == DW_AT_name){
			char* die_var_name;
			dwarf_formstring(attrs[i], &die_var_name, &err);
			if( strcmp(die_var_name, var_name) == 0 ){
				*found = true;
				return E_NONE;	
			}
		}		
		
	}

	return E_NONE; //Not var_die being searched for
}
Exemplo n.º 7
0
static int
die_string(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, char **strp, int req)
{
	Dwarf_Attribute attr;
	char *str;

	if ((attr = die_attr(dw, die, name, req)) == NULL)
		return (0); /* die_attr will terminate for us if necessary */

	if (dwarf_formstring(attr, &str, &dw->dw_err) != DW_DLV_OK) {
		terminate("die %llu: failed to get string (form 0x%x)\n",
		    die_off(dw, die), die_attr_form(dw, attr));
	}

	*strp = xstrdup(str);
	dwarf_dealloc(dw->dw_dw, str, DW_DLA_STRING);

	return (1);
}
char * dwarf_get_name(Dwarf_Die function_die,  struct dwarf_compilation_unit * unit){
  Dwarf_Error error = 0;
  Dwarf_Attribute *attrbuf = 0;
  Dwarf_Addr highpc = 0;
  Dwarf_Signed attrcount = 0;
  Dwarf_Unsigned i;

  int res = dwarf_attrlist(function_die,&attrbuf,&attrcount,&error);
  if(res != DW_DLV_OK) {
    return 0;
  }
  for(i = 0; i < attrcount ; ++i) {
    Dwarf_Half aform;
    res = dwarf_whatattr(attrbuf[i],&aform,&error);
    if (aform == DW_AT_name) {
      char * tmpName;
      res = dwarf_formstring(attrbuf[i], &tmpName, &error);
      return tmpName;
    }
  }
  return NULL;
}
Exemplo n.º 9
0
QVariant DwarfDie::attributeLocal(Dwarf_Half attributeType) const
{
    Dwarf_Attribute attr;
    auto res = dwarf_attr(m_die, attributeType, &attr, nullptr);
    if (res != DW_DLV_OK)
        return {};

    Dwarf_Half formType;
    res = dwarf_whatform(attr, &formType, nullptr);
    if (res != DW_DLV_OK)
        return {};

    QVariant value;
    switch (formType) {
        case DW_FORM_data1:
        case DW_FORM_data2:
        case DW_FORM_data4:
        case DW_FORM_data8:
        case DW_FORM_udata:
        {
            Dwarf_Unsigned n;
            res = dwarf_formudata(attr, &n, nullptr);
            value = n;
            break;
        }
        case DW_FORM_sdata:
        {
            Dwarf_Signed n;
            res = dwarf_formsdata(attr, &n, nullptr);
            value = n;
            break;
        }
        case DW_FORM_string:
        case DW_FORM_strp:
        {
            char *str;
            res = dwarf_formstring(attr, &str, nullptr);
            value = QByteArray(str);
            break;
        }
        case DW_FORM_flag:
        case DW_FORM_flag_present:
        {
            Dwarf_Bool b;
            res = dwarf_formflag(attr, &b, nullptr);
            value = b ? true : false;
            break;
        }
        case DW_FORM_ref1:
        case DW_FORM_ref2:
        case DW_FORM_ref4:
        case DW_FORM_ref8:
        {
            Dwarf_Off offset;
            res = dwarf_global_formref(attr, &offset, nullptr);
            value = QVariant::fromValue(dwarfInfo()->dieAtOffset(offset));
            break;
        }
        case DW_FORM_sec_offset:
        {
            Dwarf_Off offset;
            res = dwarf_global_formref(attr, &offset, nullptr);
            value = offset;
            break;
        }
        case DW_FORM_addr:
        {
            Dwarf_Addr addr;
            res = dwarf_formaddr(attr, &addr, nullptr);
            value = addr;
            break;
        }
        case DW_FORM_exprloc:
        {
            Dwarf_Unsigned len;
            Dwarf_Ptr block;
            res = dwarf_formexprloc(attr, &len, &block, nullptr);
            value = QVariant::fromValue(DwarfExpression(block, len, dwarfInfo()->elfFile()->addressSize()));
            break;
        }
        default:
        {
            const char* formName;
            res = dwarf_get_FORM_name(formType, &formName);
            if (res != DW_DLV_OK)
                return {};
            value = QStringLiteral("TODO: ") + QString::fromLocal8Bit(formName);
            break;
        }
    }

    // post-process some well-known types
    switch (attributeType) {
        case DW_AT_decl_file:
        case DW_AT_call_file:
        {
            const auto fileIndex = value.value<Dwarf_Unsigned>();
            // index 0 means not present, TODO handle that
            value = compilationUnit()->sourceFileForIndex(fileIndex -1);
            break;
        }
        case DW_AT_ranges:
            value = QVariant::fromValue(DwarfRanges(this, value.toLongLong()));
            break;
        case DW_AT_accessibility:
            stringifyEnum(value, &dwarf_get_ACCESS_name);
            break;
        case DW_AT_language:
            stringifyEnum(value, &dwarf_get_LANG_name);
            break;
        case DW_AT_virtuality:
            value = QVariant::fromValue(static_cast<DwarfVirtuality>(value.toInt()));
            break;
        case DW_AT_visibility:
            stringifyEnum(value, &dwarf_get_VIS_name);
            break;
        case DW_AT_identifier_case:
            stringifyEnum(value, &dwarf_get_ID_name);
            break;
        case DW_AT_inline:
            stringifyEnum(value, &dwarf_get_INL_name);
            break;
        case DW_AT_encoding:
            stringifyEnum(value, &dwarf_get_ATE_name);
            break;
        case DW_AT_ordering:
            stringifyEnum(value, &dwarf_get_ORD_name);
            break;
        case DW_AT_calling_convention:
            stringifyEnum(value, &dwarf_get_CC_name);
            break;
        case DW_AT_discr_list:
            stringifyEnum(value, &dwarf_get_DSC_name);
            break;
        default:
            break;
    }

    return value;
}
Exemplo n.º 10
0
static void
search_func(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Addr addr, char **rlt_func)
{
	Dwarf_Die ret_die, spec_die;
	Dwarf_Error de;
	Dwarf_Half tag;
	Dwarf_Unsigned lopc, hipc;
	Dwarf_Off ref;
	Dwarf_Attribute sub_at, spec_at;
	char *func0;
	const char *func1;
	int ret;

	if (*rlt_func != NULL)
		goto done;

	if (dwarf_tag(die, &tag, &de)) {
		warnx("dwarf_tag: %s", dwarf_errmsg(de));
		goto cont_search;
	}
	if (tag == DW_TAG_subprogram) {
		if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc, &de) ||
		    dwarf_attrval_unsigned(die, DW_AT_high_pc, &hipc, &de))
			goto cont_search;
		if (handle_high_pc(die, lopc, &hipc) != DW_DLV_OK)
			goto cont_search;
		if (addr < lopc || addr >= hipc)
			goto cont_search;

		/* Found it! */

		if ((*rlt_func = strdup(unknown)) == NULL)
			err(EXIT_FAILURE, "strdup");
		ret = dwarf_attr(die, DW_AT_name, &sub_at, &de);
		if (ret == DW_DLV_ERROR)
			goto done;
		if (ret == DW_DLV_OK) {
			if (dwarf_formstring(sub_at, &func0, &de) ==
			    DW_DLV_OK) {
				free(*rlt_func);
				if ((*rlt_func = strdup(func0)) == NULL)
					err(EXIT_FAILURE, "strdup");
			}
			goto done;
		}

		/*
		 * If DW_AT_name is not present, but DW_AT_specification is
		 * present, then probably the actual name is in the DIE
		 * referenced by DW_AT_specification.
		 */
		if (dwarf_attr(die, DW_AT_specification, &spec_at, &de))
			goto done;
		if (dwarf_global_formref(spec_at, &ref, &de))
			goto done;
		if (dwarf_offdie(dbg, ref, &spec_die, &de))
			goto done;
		if (dwarf_attrval_string(spec_die, DW_AT_name, &func1, &de) ==
		    DW_DLV_OK) {
			free(*rlt_func);
			if ((*rlt_func = strdup(func1)) == NULL)
			    err(EXIT_FAILURE, "strdup");
		}

		goto done;
	}

cont_search:

	/* Search children. */
	ret = dwarf_child(die, &ret_die, &de);
	if (ret == DW_DLV_ERROR)
		errx(EXIT_FAILURE, "dwarf_child: %s", dwarf_errmsg(de));
	else if (ret == DW_DLV_OK)
		search_func(dbg, ret_die, addr, rlt_func);

	/* Search sibling. */
	ret = dwarf_siblingof(dbg, die, &ret_die, &de);
	if (ret == DW_DLV_ERROR)
		errx(EXIT_FAILURE, "dwarf_siblingof: %s", dwarf_errmsg(de));
	else if (ret == DW_DLV_OK)
		search_func(dbg, ret_die, addr, rlt_func);

done:
	dwarf_dealloc(dbg, die, DW_DLA_DIE);
}
Exemplo n.º 11
0
/* get_compiler_info */
int get_compiler_info(void) {
    Dwarf_Unsigned   cu_header_length, abbrev_offset, next_cu_header;
    Dwarf_Half       version, address_size;
    Dwarf_Signed     attrcount, i, language;
    Dwarf_Die        no_die = 0, cu_die;
    Dwarf_Attribute *attrs;
    Dwarf_Half       attrcode;
    Dwarf_Debug      dbg = 0;
    Dwarf_Error      err;
    char *compiler = NULL;
    int fd = -1;

    OUTPUT_VERBOSE((5, "%s", _BLUE("Extracting DWARF info")));

    /* Open the binary */
    if (0 > (fd = open(globals.program_full, O_RDONLY))) {
        OUTPUT(("%s [%s]", _ERROR("opening program binary"),
            globals.program_full));
        return PERFEXPERT_ERROR;
    }

    /* Initialize DWARF library  */
    if (DW_DLV_OK != dwarf_init(fd, DW_DLC_READ, 0, 0, &dbg, &err)) {
        OUTPUT(("%s", _ERROR("failed DWARF initialization")));
        return PERFEXPERT_ERROR;
    }

    /* Find compilation unit header */
    if (DW_DLV_ERROR == dwarf_next_cu_header(dbg, &cu_header_length,
        &version, &abbrev_offset, &address_size, &next_cu_header, &err)) {
        OUTPUT(("%s", _ERROR("reading DWARF CU header")));
        return PERFEXPERT_ERROR;
    }

    /* Expect the CU to have a single sibling, a DIE */
    if (DW_DLV_ERROR == dwarf_siblingof(dbg, no_die, &cu_die, &err)) {
        OUTPUT(("%s", _ERROR("getting sibling of CU")));
        return PERFEXPERT_ERROR;
    }

    /* Find the DIEs attributes */
    if (DW_DLV_OK != dwarf_attrlist(cu_die, &attrs, &attrcount, &err)) {
        OUTPUT(("%s", _ERROR("in dwarf_attlist")));
        return PERFEXPERT_ERROR;
    }

    /* For each attribute... */
    for (i = 0; i < attrcount; ++i) {
        if (DW_DLV_OK != dwarf_whatattr(attrs[i], &attrcode, &err)) {
            OUTPUT(("%s [%s]", _ERROR("in dwarf_whatattr")));
            return PERFEXPERT_ERROR;
        }
        if (DW_AT_producer == attrcode) {
            if (DW_DLV_OK != dwarf_formstring(attrs[i], &compiler, &err)) {
                OUTPUT(("%s [%s]", _ERROR("in dwarf_formstring")));
                return PERFEXPERT_ERROR;
            } else {
                OUTPUT_VERBOSE((5, "   Compiler: %s", _CYAN(compiler)));
            }
        }
        if (DW_AT_language == attrcode) {
            if (DW_DLV_OK != dwarf_formsdata(attrs[i], &language, &err)) {
                OUTPUT(("%s [%s]", _ERROR("in dwarf_formsdata")));
                return PERFEXPERT_ERROR;
            } else {
                OUTPUT_VERBOSE((5, "   Language: %d", language));
            }
        }
    }

    if (PERFEXPERT_SUCCESS != database_write(compiler, language)) {
        OUTPUT(("%s", _ERROR("writing to database")));
        return PERFEXPERT_ERROR;
    }

    /* Finalize DWARF library  */
    if (DW_DLV_OK != dwarf_finish(dbg, &err)) {
        OUTPUT(("%s", _ERROR("failed DWARF finalization")));
        return PERFEXPERT_ERROR;
    }

    close(fd);

    return PERFEXPERT_SUCCESS;
}
Exemplo n.º 12
0
/*  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;
}
Exemplo n.º 13
0
/*
	return DW_DLV_OK if ok. else DW_DLV_NO_ENTRY or DW_DLV_ERROR
*/
int
_dwarf_internal_printlines(Dwarf_Die die, Dwarf_Error * error)
{
    /* 
       This pointer is used to scan the portion of the .debug_line
       section for the current cu. */
    Dwarf_Small *line_ptr;
    Dwarf_Small *orig_line_ptr;

    /* 
       This points to the last byte of the .debug_line portion for the 
       current cu. */
    Dwarf_Small *line_ptr_end;

    /* 
       This points to the end of the statement program prologue for the 
       current cu, and serves to check that the prologue was correctly 
       decoded. */
    Dwarf_Small *check_line_ptr;

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

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

    /* 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;

    /* These are the fields of the statement program header. */
    Dwarf_Unsigned total_length;
    Dwarf_Half version;
    Dwarf_Unsigned prologue_length;
    Dwarf_Small minimum_instruction_length;
    Dwarf_Small default_is_stmt;
    Dwarf_Sbyte line_base;
    Dwarf_Small line_range;
    Dwarf_Small opcode_base;

    Dwarf_Small *opcode_length;

    /* These are the state machine state variables. */
    Dwarf_Addr address;
    Dwarf_Word file;
    Dwarf_Word line;
    Dwarf_Word column;
    Dwarf_Bool is_stmt;
    Dwarf_Bool basic_block;
    Dwarf_Bool end_sequence;

    Dwarf_Sword i, file_entry_count, include_directories_count;

    /* 
       This is the current opcode read from the statement program. */
    Dwarf_Small opcode;

    /* 
       Pointer to a Dwarf_Line_Context_s structure that contains the
       context such as file names and include directories for the set
       of lines being generated. */
    Dwarf_Line_Context line_context;


    /* 
       These variables are used to decode leb128 numbers. Leb128_num
       holds the decoded number, and leb128_length is its length in
       bytes. */
    Dwarf_Word leb128_num;
    Dwarf_Word leb128_length;
    Dwarf_Sword advance_line;

    /* 
       This is the operand of the latest fixed_advance_pc extended
       opcode. */
    Dwarf_Half fixed_advance_pc;

    /* This is the length of an extended opcode instr.  */
    Dwarf_Word instr_length;
    Dwarf_Small ext_opcode;
    int local_length_size;
    /*REFERENCED*/ /* Not used in this instance of the macro */
    int local_extension_size;

    /* The Dwarf_Debug this die belongs to. */
    Dwarf_Debug dbg;
    int resattr;
    int lres;

    int res;

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

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

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

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

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



    lres = dwarf_formudata(stmt_list_attr, &line_offset, error);
    if (lres != DW_DLV_OK) {
	return lres;
    }

    if (line_offset >= dbg->de_debug_line_size) {
	_dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD);
	return (DW_DLV_ERROR);
    }
    orig_line_ptr = dbg->de_debug_line;
    line_ptr = dbg->de_debug_line + line_offset;
    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;
	char *cdir;

	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);
    }

    /* 
       Following is a straightforward decoding of the statement
       program prologue information. */

    /* READ_AREA_LENGTH updates line_ptr for consumed bytes */
    READ_AREA_LENGTH(dbg, total_length, Dwarf_Unsigned,
		     line_ptr, local_length_size, local_extension_size);



    line_ptr_end = line_ptr + total_length;
    if (line_ptr_end > dbg->de_debug_line + dbg->de_debug_line_size) {
	_dwarf_error(dbg, error, DW_DLE_DEBUG_LINE_LENGTH_BAD);
	return (DW_DLV_ERROR);
    }

    printf("total line info length %ld bytes, "
	   "line offset 0x%llx %lld\n",
	   (long) total_length,
	   (long long) line_offset, (long long) line_offset);
    printf("compilation_directory %s\n",
	   comp_dir ? ((char *) comp_dir) : "");
    READ_UNALIGNED(dbg, version, Dwarf_Half,
		   line_ptr, sizeof(Dwarf_Half));
    line_ptr += sizeof(Dwarf_Half);
    if (version != CURRENT_VERSION_STAMP) {
	_dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR);
	return (DW_DLV_ERROR);
    }

    READ_UNALIGNED(dbg, prologue_length, Dwarf_Unsigned,
		   line_ptr, local_length_size);
    line_ptr += local_length_size;
    check_line_ptr = line_ptr;

    minimum_instruction_length = *(Dwarf_Small *) line_ptr;
    line_ptr = line_ptr + sizeof(Dwarf_Small);

    default_is_stmt = *(Dwarf_Small *) line_ptr;
    line_ptr = line_ptr + sizeof(Dwarf_Small);

    line_base = *(Dwarf_Sbyte *) line_ptr;
    line_ptr = line_ptr + sizeof(Dwarf_Sbyte);

    line_range = *(Dwarf_Small *) line_ptr;
    line_ptr = line_ptr + sizeof(Dwarf_Small);

    opcode_base = *(Dwarf_Small *) line_ptr;
    line_ptr = line_ptr + sizeof(Dwarf_Small);
    printf("  min instruction length %d\n",
	   (int) minimum_instruction_length);
    printf("  default is stmt        %d\n", (int) default_is_stmt);
    printf("  line base              %d\n", (int) line_base);
    printf("  line_range             %d\n", (int) line_range);

    opcode_length = (Dwarf_Small *)
	alloca(sizeof(Dwarf_Small) * opcode_base);

    for (i = 1; i < opcode_base; i++) {
	opcode_length[i] = *(Dwarf_Small *) line_ptr;
	printf("  opcode[%d] length %d\n", (int) i,
	       (int) opcode_length[i]);
	line_ptr = line_ptr + sizeof(Dwarf_Small);
    }

    include_directories_count = 0;
    while ((*(char *) line_ptr) != '\0') {
	printf("  include dir[%d] %s\n",
	       (int) include_directories_count, line_ptr);
	line_ptr = line_ptr + strlen((char *) line_ptr) + 1;
	include_directories_count++;
    }
    line_ptr++;

    file_entry_count = 0;
    while (*(char *) line_ptr != '\0') {

	Dwarf_Unsigned tlm2;
	Dwarf_Unsigned di;
	Dwarf_Unsigned fl;

	printf("  file[%d]  %s\n",
	       (int) file_entry_count, (char *) line_ptr);

	line_ptr = line_ptr + strlen((char *) line_ptr) + 1;

	di = _dwarf_decode_u_leb128(line_ptr, &leb128_length);
	line_ptr = line_ptr + leb128_length;

	tlm2 = _dwarf_decode_u_leb128(line_ptr, &leb128_length);
	line_ptr = line_ptr + leb128_length;

	fl = _dwarf_decode_u_leb128(line_ptr, &leb128_length);
	line_ptr = line_ptr + leb128_length;

	printf("    dir index %d\n", (int) di);
	{
	    time_t tt = (time_t) tlm2;

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


	file_entry_count++;
    }
    line_ptr++;

    if (line_ptr != check_line_ptr + prologue_length) {
	_dwarf_error(dbg, error, DW_DLE_LINE_PROLOG_LENGTH_BAD);
	return (DW_DLV_ERROR);
    }

    /* Set up context structure for this set of lines. */
    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);
    }

    printf("  statement prog offset in section: %lld 0x%llx\n",
	   (long long) (line_ptr - orig_line_ptr),
	   (long long) (line_ptr - orig_line_ptr));

    /* Initialize the state machine.  */
    address = 0;
    file = 1;
    line = 1;
    column = 0;
    is_stmt = default_is_stmt;
    basic_block = false;
    end_sequence = false;

    print_line_header();
    /* Start of statement program.  */
    while (line_ptr < line_ptr_end) {
	int type;

	printf(" [0x%06llx] ", (long long) (line_ptr - orig_line_ptr));
	opcode = *(Dwarf_Small *) line_ptr;
	line_ptr++;
	/* 'type' is the output */
	WHAT_IS_OPCODE(type, opcode, opcode_base,
		       opcode_length, line_ptr);



	if (type == LOP_DISCARD) {
	    /* do nothing, necessary ops done */
	} else if (type == LOP_SPECIAL) {
	    /* This op code is a special op in the object, no matter
	       that it might fall into the standard op range in this
	       compile Thatis, these are special opcodes between
	       special_opcode_base and MAX_LINE_OP_CODE.  (including
	       special_opcode_base and MAX_LINE_OP_CODE) */
	    char special[50];
	    unsigned origop = opcode;

	    opcode = opcode - opcode_base;
	    address = address + minimum_instruction_length *
		(opcode / line_range);
	    line = line + line_base + opcode % line_range;

	    sprintf(special, "Specialop %3u", origop);
	    print_line_detail(special,
			      opcode, address, (int) file, line, column,
			      is_stmt, basic_block, end_sequence);

	    basic_block = false;

	} else if (type == LOP_STANDARD) {
	    switch (opcode) {

	    case DW_LNS_copy:{
		    if (opcode_length[DW_LNS_copy] != 0) {
			_dwarf_error(dbg, error,
				     DW_DLE_LINE_NUM_OPERANDS_BAD);
			return (DW_DLV_ERROR);
		    }

		    print_line_detail("DW_LNS_copy",
				      opcode, address, file, line,
				      column, is_stmt, basic_block,
				      end_sequence);

		    basic_block = false;
		    break;
		}

	    case DW_LNS_advance_pc:{
		    Dwarf_Unsigned utmp2;

		    if (opcode_length[DW_LNS_advance_pc] != 1) {
			_dwarf_error(dbg, error,
				     DW_DLE_LINE_NUM_OPERANDS_BAD);
			return (DW_DLV_ERROR);
		    }

		    DECODE_LEB128_UWORD(line_ptr, utmp2)
			printf("DW_LNS_advance_pc val %lld 0x%llx\n",
			       (long long) (Dwarf_Word) utmp2,
			       (long long) (Dwarf_Word) utmp2);
		    leb128_num = (Dwarf_Word) utmp2;
		    address =
			address +
			minimum_instruction_length * leb128_num;
		    break;
		}

	    case DW_LNS_advance_line:{
		    Dwarf_Signed stmp;

		    if (opcode_length[DW_LNS_advance_line] != 1) {
			_dwarf_error(dbg, error,
				     DW_DLE_LINE_NUM_OPERANDS_BAD);
			return (DW_DLV_ERROR);
		    }

		    DECODE_LEB128_SWORD(line_ptr, stmp)
			advance_line = (Dwarf_Sword) stmp;
		    printf("DW_LNS_advance_line val %lld 0x%llx\n",
			   (long long) advance_line,
			   (long long) advance_line);
		    line = line + advance_line;
		    break;
		}

	    case DW_LNS_set_file:{
		    Dwarf_Unsigned utmp2;

		    if (opcode_length[DW_LNS_set_file] != 1) {
			_dwarf_error(dbg, error,
				     DW_DLE_LINE_NUM_OPERANDS_BAD);
			return (DW_DLV_ERROR);
		    }

		    DECODE_LEB128_UWORD(line_ptr, utmp2)
			file = (Dwarf_Word) utmp2;
		    printf("DW_LNS_set_file  %ld\n", (long) file);
		    break;
		}

	    case DW_LNS_set_column:{
		    Dwarf_Unsigned utmp2;

		    if (opcode_length[DW_LNS_set_column] != 1) {
			_dwarf_error(dbg, error,
				     DW_DLE_LINE_NUM_OPERANDS_BAD);
			return (DW_DLV_ERROR);
		    }

		    DECODE_LEB128_UWORD(line_ptr, utmp2)
			column = (Dwarf_Word) utmp2;
		    printf("DW_LNS_set_column val %lld 0x%llx\n",
			   (long long) column, (long long) column);
		    break;
		}

	    case DW_LNS_negate_stmt:{
		    if (opcode_length[DW_LNS_negate_stmt] != 0) {
			_dwarf_error(dbg, error,
				     DW_DLE_LINE_NUM_OPERANDS_BAD);
			return (DW_DLV_ERROR);
		    }

		    is_stmt = !is_stmt;
		    printf("DW_LNS_negate_stmt\n");
		    break;
		}

	    case DW_LNS_set_basic_block:{
		    if (opcode_length[DW_LNS_set_basic_block] != 0) {
			_dwarf_error(dbg, error,
				     DW_DLE_LINE_NUM_OPERANDS_BAD);
			return (DW_DLV_ERROR);
		    }

		    printf("DW_LNS_set_basic_block\n");
		    basic_block = true;
		    break;
		}

	    case DW_LNS_const_add_pc:{
		    opcode = MAX_LINE_OP_CODE - opcode_base;
		    address = address + minimum_instruction_length *
			(opcode / line_range);

		    printf("DW_LNS_const_add_pc new address 0x%llx\n",
			   (long long) address);
		    break;
		}

	    case DW_LNS_fixed_advance_pc:{
		    if (opcode_length[DW_LNS_fixed_advance_pc] != 1) {
			_dwarf_error(dbg, error,
				     DW_DLE_LINE_NUM_OPERANDS_BAD);
			return (DW_DLV_ERROR);
		    }

		    READ_UNALIGNED(dbg, fixed_advance_pc, Dwarf_Half,
				   line_ptr, sizeof(Dwarf_Half));
		    line_ptr += sizeof(Dwarf_Half);
		    address = address + fixed_advance_pc;
		    printf("DW_LNS_fixed_advance_pc val %lld 0x%llx"
			   " new address 0x%llx\n",
			   (long long) fixed_advance_pc,
			   (long long) fixed_advance_pc,
			   (long long) address);
		    break;
		}
	    }

	} else if (type == LOP_EXTENDED) {
	    Dwarf_Unsigned utmp3;

	    DECODE_LEB128_UWORD(line_ptr, utmp3)
		instr_length = (Dwarf_Word) utmp3;
	    ext_opcode = *(Dwarf_Small *) line_ptr;
	    line_ptr++;
	    switch (ext_opcode) {

	    case DW_LNE_end_sequence:{
		    end_sequence = true;

		    print_line_detail("DW_LNE_end_sequence extended",
				      opcode, address, file, line,
				      column, is_stmt, basic_block,
				      end_sequence);

		    address = 0;
		    file = 1;
		    line = 1;
		    column = 0;
		    is_stmt = default_is_stmt;
		    basic_block = false;
		    end_sequence = false;

		    break;
		}

	    case DW_LNE_set_address:{
		    if (instr_length - 1 == dbg->de_pointer_size) {
			READ_UNALIGNED(dbg, address, Dwarf_Addr,
				       line_ptr, dbg->de_pointer_size);

			line_ptr += dbg->de_pointer_size;
			printf("DW_LNE_set_address address 0x%llx\n",
			       (long long) address);
		    } else {
			_dwarf_error(dbg, error,
				     DW_DLE_LINE_SET_ADDR_ERROR);
			return (DW_DLV_ERROR);
		    }

		    break;
		}

	    case DW_LNE_define_file:{


		    Dwarf_Small *fn;
		    Dwarf_Signed di;
		    Dwarf_Signed tlm;
		    Dwarf_Unsigned fl;

		    fn = (Dwarf_Small *) line_ptr;
		    line_ptr = line_ptr + strlen((char *) line_ptr) + 1;

		    di = _dwarf_decode_u_leb128(line_ptr,
						&leb128_length);
		    line_ptr = line_ptr + leb128_length;

		    tlm =
			_dwarf_decode_u_leb128(line_ptr,
					       &leb128_length);
		    line_ptr = line_ptr + leb128_length;

		    fl = _dwarf_decode_u_leb128(line_ptr,
						&leb128_length);
		    line_ptr = line_ptr + leb128_length;


		    printf("DW_LNE_define_file %s \n", fn);
		    printf("    dir index %d\n", (int) di);
		    {
			time_t tt3 = (time_t) tlm;

			/* ctime supplies newline */
			printf("    last time 0x%x %s",
			       (unsigned) tlm, ctime(&tt3));
		    }
		    printf("    file length %ld 0x%lx\n",
			   (long) fl, (unsigned long) fl);

		    break;
		}

	    default:{
		    _dwarf_error(dbg, error,
				 DW_DLE_LINE_EXT_OPCODE_BAD);
		    return (DW_DLV_ERROR);
		}
	    }

	}
    }

    return (DW_DLV_OK);
}
Exemplo n.º 14
0
/**
 * Finds a function name in DWARF DIE (Debug Information Entry).
 * For more info on DWARF format, see http://www.dwarfstd.org/Download.php , http://www.ibm.com/developerworks/library/os-debugging/
 *
 * @return true if we need to stop search (i.e. either found it or some error happened)
 */
bool FindFunctionNameInDIE(Dwarf_Debug DebugInfo, Dwarf_Die Die, Dwarf_Addr Addr, const char **OutFuncName)
{
	Dwarf_Error ErrorInfo;
	Dwarf_Half Tag;
	Dwarf_Unsigned LowerPC, HigherPC;
	char *TempFuncName;
	int ReturnCode;

	if (dwarf_tag(Die, &Tag, &ErrorInfo) != DW_DLV_OK || Tag != DW_TAG_subprogram ||
		dwarf_attrval_unsigned(Die, DW_AT_low_pc, &LowerPC, &ErrorInfo) != DW_DLV_OK ||
		dwarf_attrval_unsigned(Die, DW_AT_high_pc, &HigherPC, &ErrorInfo) != DW_DLV_OK ||
		Addr < LowerPC || HigherPC <= Addr
		) 
	{
		return false;
	}
	
	// found it
	*OutFuncName = NULL;
	Dwarf_Attribute SubAt;
	ReturnCode = dwarf_attr(Die, DW_AT_name, &SubAt, &ErrorInfo);
	if (ReturnCode == DW_DLV_ERROR)
	{
		return true;	// error, but stop the search
	}
	else if (ReturnCode == DW_DLV_OK) 
	{
		if (dwarf_formstring(SubAt, &TempFuncName, &ErrorInfo))
		{
			*OutFuncName = NULL;
		}
		else
		{
			*OutFuncName = TempFuncName;
		}
		return true;
	}

	// DW_AT_Name is not present, look in DW_AT_specification
	Dwarf_Attribute SpecAt;
	if (dwarf_attr(Die, DW_AT_specification, &SpecAt, &ErrorInfo))
	{
		// not found, tough luck
		return false;
	}

	Dwarf_Off Offset;
	if (dwarf_global_formref(SpecAt, &Offset, &ErrorInfo))
	{
		return false;
	}

	Dwarf_Die SpecDie;
	if (dwarf_offdie(DebugInfo, Offset, &SpecDie, &ErrorInfo))
	{
		return false;
	}

	if (dwarf_attrval_string(SpecDie, DW_AT_name, OutFuncName, &ErrorInfo))
	{
		*OutFuncName = NULL;
	}

	return true;
}
Exemplo n.º 15
0
static int dwarf_producer(const char *file) {

  FILE *fp = fopen(file, "rb");
  struct stat statbuf;

  if (lstat(file, &statbuf)) {
	  perror(file);
	  return -1;
  }

  size_t size = statbuf.st_size;
  unsigned char *buffer = (unsigned char *)malloc(size);

  if (fread(buffer, size, 1, fp) < sizeof buffer) {

  }

  int sfd = shm_open("something", O_CREAT | O_RDWR, 0);
  if (ftruncate (sfd, size) < 0) {
	  perror(file);
	  return -2;
  }

  // we could do without mmap!
  void *addr = mmap ( NULL , size, PROT_READ | PROT_WRITE, MAP_SHARED , sfd, 0);
  memcpy(addr, buffer, size);

  /* int fd = open(file, O_RDONLY);
  if (fd < 0) {
    error(0, errno, "open '%s' failed", file);
    return -1;
  }

  Dwarf *dw = dwarf_begin(fd, DWARF_C_READ); */

  Dwarf *dw = dwarf_begin(sfd, DWARF_C_READ);
  if (dw == NULL) {
    error(0, 0, "dwarf_begin '%s': %s", file, dwarf_errmsg(-1));
    return -1;
  }

  bool producers_found = false;

  Dwarf_Off cuoffset;
  Dwarf_Off ncuoffset = 0;
  size_t hsize;
  while (dwarf_nextcu(dw, cuoffset = ncuoffset, &ncuoffset, &hsize, NULL, NULL,
                      NULL) == 0) {
    Dwarf_Off cudieoff = cuoffset + hsize;
    Dwarf_Die cudie;
    if (dwarf_offdie(dw, cudieoff, &cudie) == NULL) {
      error(0, 0, "Empty CU in '%s' at offset %" PRIx64 ": %s", file, cudieoff,
            dwarf_errmsg(-1));
      continue;
    }

    const char *name = dwarf_diename(&cudie);
    Dwarf_Attribute attr;
    const char *producer;

    if (dwarf_attr(&cudie, DW_AT_producer, &attr) == NULL)
      continue;

    producer = dwarf_formstring(&attr);
    if (producer == NULL) {
      error(0, 0,
            "Couldn't get producer for CU in '%s' at offset %" PRIx64 ": %s",
            file, cudieoff, dwarf_errmsg(-1));
      continue;
    }

    printf("%s CU [%" PRIx64 "] %s: %s\n", file, cudieoff,
           (name ?: "<unknown>"), producer);
    producers_found = true;
  }

  if (!producers_found) {
    error(0, 0, "no DW_AT_producers found in '%s'", file);
    return -1;
  }

  // cleanup
  munmap(addr, size);
  close(sfd);
  shm_unlink("something");

  fclose(fp);

  return 0;
}
Exemplo n.º 16
0
struct refl_object *
refl_access (struct refl *refl, struct refl_object *obj, char const *lookfor)
{
  assert (refl != NULL);
  assert (obj != NULL);
  assert (lookfor != NULL);

  struct refl_type *type = obj->type;
  assert (type != NULL);

  Dwarf_Die die_mem, *die = &die_mem;
  if (dwarf_child (&type->die, &die_mem))
    {
    err:
      __refl_seterr (REFL_E_DWARF);
      return NULL;
    }

  for (; die != NULL; checked_siblingof (&die, &die_mem))
    {
      if (dwarf_tag (die) != DW_TAG_member)
	continue;

      Dwarf_Attribute attr_mem, *attr = dwarf_attr (die, DW_AT_name, &attr_mem);
      if (attr == NULL)
	goto err;

      char const *name = dwarf_formstring (attr);
      if (name == NULL)
	{
	err2:
	  __refl_seterr (REFL_E_DWARF);
	  return NULL;
	}

      if (strcmp (name, lookfor) != 0)
	continue;

      attr = dwarf_attr (die, DW_AT_data_member_location, &attr_mem);
      if (attr == NULL)
	goto err;

      Dwarf_Word location;
      if (dwarf_formudata (attr, &location) != 0)
	goto err2;

      attr = dwarf_attr (die, DW_AT_type, &attr_mem);
      if (attr == NULL)
	goto err;

      Dwarf_Die tdie_mem, *tdie = dwarf_formref_die (attr, &tdie_mem);
      if (tdie == NULL)
	goto err2;

      struct refl_type *field_type = __refl_type_begin (tdie);
      if (field_type == NULL)
	return NULL;

      struct refl_object *result
	= __refl_object_begin (field_type, (char *)obj->data + location);
      if (result == NULL)
	__refl_type_free (field_type);

      return result;
    }

  return NULL;
}
Exemplo n.º 17
0
static void analyze_type(Dwarf_Die *die, struct type *ty)
{
    int ret;
    Dwarf_Attribute at;

    /* find out the values of name, byte_size and type attributes
     * even though not all of them make sense for all tags
     */
    char *name = NULL;
    if (dwarf_attr(die, DW_AT_name, &at) != NULL)
    {
        name = xstrdup(dwarf_formstring(&at));
    }

    struct type sub_type = { .name = NULL, .width = 0 };
    if (dwarf_attr(die, DW_AT_type, &at) != NULL)
    {
        Dwarf_Die sub_die;
        if (dwarf_formref_die(&at, &sub_die) != NULL)
            analyze_type(&sub_die, &sub_type);
    }

    Dwarf_Word width = 0;
    if (dwarf_attr(die, DW_AT_byte_size, &at) != NULL)
    {
        ret = dwarf_formudata(&at, &width);
        fail_if(ret == -1, "dwarf_formudata");
    }

    switch (dwarf_tag(die))
    {
    case DW_TAG_base_type:
        ty->name = name;
        name = NULL;
        ty->width = (unsigned)width;
        /* TODO: what about encoding? */
        break;

    /* type modifiers */
    case DW_TAG_const_type:
        ty->name = xsprintf("const %s", sub_type.name ?: "void");
        ty->width = sub_type.width;
        break;

    case DW_TAG_pointer_type:
        ty->width = (unsigned)width;
        ty->name = xsprintf("%s*", sub_type.name ?: "void");
        break;

    case DW_TAG_restrict_type:
        ty->name = xsprintf("%s restrict", sub_type.name ?: "void");
        ty->width = sub_type.width;
        break;

    case DW_TAG_volatile_type:
        ty->name = xsprintf("volatile %s", sub_type.name ?: "void");
        ty->width = sub_type.width;
        break;

    case DW_TAG_typedef:
        ty->name = name;
        name = NULL;
        ty->width = sub_type.width;
        break;

    case DW_TAG_array_type:
        ty->name = xsprintf("%s[]", sub_type.name);
        ty->width = POINTER_SIZE;
        break;

    case DW_TAG_structure_type:
        if (name)
            ty->name = xsprintf("struct %s", name);
        else
            ty->name = xstrdup("struct");
        ty->width = (unsigned)width;
        break;

    case DW_TAG_union_type:
        if (name)
            ty->name = xsprintf("union %s", name);
        else
            ty->name = xstrdup("union");
        ty->width = (unsigned)width;
        break;

    case DW_TAG_class_type:
        ty->name = xsprintf("class %s", name);
        ty->width = (unsigned)width;
        break;

    case DW_TAG_enumeration_type:
        ty->name = xsprintf("enum %s", name);
        ty->width = (unsigned)width;
        break;

    case DW_TAG_subroutine_type:
        ty->name = xstrdup("FUNCTION");
        ty->width = 0; /* TODO */
        break;

    default:
        warn("Unknown type 0x%x named %s with width %u", dwarf_tag(die), name, (unsigned)width);
        break;
    }

    free(sub_type.name);
    free(name);
}

void analyze_name_location(Dwarf_Die *die, Dwarf_Files *files,
                           char **name, struct location* loc)
{
    int ret;
    Dwarf_Attribute at;
    Dwarf_Word w;

    if (dwarf_attr_integrate(die, DW_AT_name, &at) != NULL)
    {
        *name = xstrdup(dwarf_formstring(&at));
    }

    if (dwarf_attr_integrate(die, DW_AT_decl_file, &at) != NULL)
    {
        ret = dwarf_formudata(&at, &w);
        fail_if(ret == -1, "dwarf_formudata");
        loc->file = xstrdup(dwarf_filesrc(files, (size_t)w, NULL, NULL));
    }

    if (dwarf_attr_integrate(die, DW_AT_decl_line, &at) != NULL)
    {
        ret = dwarf_formudata(&at, &w);
        fail_if(ret == -1, "dwarf_formudata");
        loc->line = (unsigned)w;
    }
}
Exemplo n.º 18
0
/*
        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.
*/
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;

    /* 
       This points to the last byte of the .debug_line portion for the
       current cu. */
    Dwarf_Small *line_ptr_end = 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;

    struct Line_Table_Prefix_s prefix;


    /* These are the state machine state variables. */
    Dwarf_Addr address = 0;
    Dwarf_Word file = 1;
    Dwarf_Word line = 1;
    Dwarf_Word column = 0;
    Dwarf_Bool is_stmt = false;
    Dwarf_Bool basic_block = false;
    Dwarf_Bool end_sequence = false;
    Dwarf_Bool prologue_end = false;
    Dwarf_Bool epilogue_begin = false;
    Dwarf_Small isa = 0;


    Dwarf_Sword i=0;

    /* 
       This is the current opcode read from the statement program. */
    Dwarf_Small opcode=0;


    /* 
       These variables are used to decode leb128 numbers. Leb128_num
       holds the decoded number, and leb128_length is its length in
       bytes. */
    Dwarf_Word leb128_num=0;
    Dwarf_Word leb128_length=0;
    Dwarf_Sword advance_line=0;
    Dwarf_Half attrform = 0;
    /* 
       This is the operand of the latest fixed_advance_pc extended
       opcode. */
    Dwarf_Half fixed_advance_pc=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;


    /* The Dwarf_Debug this die belongs to. */
    Dwarf_Debug dbg=0;
    int resattr = DW_DLV_ERROR;
    int lres =    DW_DLV_ERROR;
    int res  =    DW_DLV_ERROR;

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

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

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

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

    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);
    }
    orig_line_ptr = dbg->de_debug_line.dss_data;
    line_ptr = dbg->de_debug_line.dss_data + line_offset;
    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);
    }

    dwarf_init_line_table_prefix(&prefix);
    {
        Dwarf_Small *line_ptr_out = 0;
        int dres = dwarf_read_line_table_prefix(dbg,
            line_ptr,dbg->de_debug_line.dss_size - line_offset,
            &line_ptr_out,
            &prefix, 
            &bogus_bytes_ptr,
            &bogus_bytes_count,
            error,
            err_count_out);
        if (dres == DW_DLV_ERROR) {
            dwarf_free_line_table_prefix(&prefix);
            return dres;
        }
        if (dres == DW_DLV_NO_ENTRY) {
            dwarf_free_line_table_prefix(&prefix);
            return dres;
        }
        line_ptr_end = prefix.pf_line_ptr_end;
        line_ptr = line_ptr_out;
    }
    if(only_line_header) {
         /* Just checking for header errors, nothing more here.*/
         dwarf_free_line_table_prefix(&prefix);
         return DW_DLV_OK;
    }


    printf("total line info length %ld bytes, "
           "line offset 0x%" DW_PR_DUx " %" DW_PR_DSd "\n",
           (long) prefix.pf_total_length,
           (Dwarf_Unsigned) line_offset, 
           (Dwarf_Signed) line_offset);
    printf("line table version %d\n",(int) prefix.pf_version);
    printf("line table length field length %d prologue length %d\n",
           (int)prefix.pf_length_field_length,
           (int)prefix.pf_prologue_length);
    printf("compilation_directory %s\n",
           comp_dir ? ((char *) comp_dir) : "");

    printf("  min instruction length %d\n",
           (int) prefix.pf_minimum_instruction_length);
    printf("  default is stmt        %d\n", (int)
           prefix.pf_default_is_stmt);
    printf("  line base              %d\n", (int)
           prefix.pf_line_base);
    printf("  line_range             %d\n", (int)
           prefix.pf_line_range);
    printf("  opcode base            %d\n", (int)
           prefix.pf_opcode_base);
    printf("  standard opcode count  %d\n", (int)
           prefix.pf_std_op_count);

    for (i = 1; i < prefix.pf_opcode_base; i++) {
        printf("  opcode[%2d] length  %d\n", (int) i,
               (int) prefix.pf_opcode_length_table[i - 1]);
    }
    printf("  include directories count %d\n", (int)
           prefix.pf_include_directories_count);

    
    for (i = 0; i < prefix.pf_include_directories_count; ++i) {
        printf("  include dir[%d] %s\n",
               (int) i, prefix.pf_include_directories[i]);
    }
    printf("  files count            %d\n", (int)
           prefix.pf_files_count);

    for (i = 0; i < prefix.pf_files_count; ++i) {
        struct Line_Table_File_Entry_s *lfile =
            prefix.pf_line_table_file_entries + i;

        Dwarf_Unsigned tlm2 = lfile->lte_last_modification_time;
        Dwarf_Unsigned di = lfile->lte_directory_index;
        Dwarf_Unsigned fl = lfile->lte_length_of_file;

        printf("  file[%d]  %s (file-number: %d) \n",
               (int) i, (char *) lfile->lte_filename,
               (int)(i+1));

        printf("    dir index %d\n", (int) di);
        {
            time_t tt = (time_t) tlm2;

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


    }


    {
        Dwarf_Unsigned offset = 0;
        if(bogus_bytes_count > 0) {
            Dwarf_Unsigned wcount = bogus_bytes_count;
            Dwarf_Unsigned boffset = bogus_bytes_ptr - orig_line_ptr;
            printf("*** DWARF CHECK: the line table prologue  header_length "
                " is %" DW_PR_DUu " too high, we pretend it is smaller."
                "Section offset: %" DW_PR_DUu " (0x%" DW_PR_DUx ") ***\n",
                wcount, boffset,boffset);
            *err_count_out += 1;
        }
        offset = line_ptr - orig_line_ptr;

        printf("  statement prog offset in section: %" DW_PR_DUu " 0x%" DW_PR_DUx "\n",
               offset, offset);
    }

    /* Initialize the part of the state machine dependent on the
       prefix.  */
    is_stmt = prefix.pf_default_is_stmt;


    print_line_header();
    /* Start of statement program.  */
    while (line_ptr < line_ptr_end) {
        int type = 0;

        printf(" [0x%06" DW_PR_DSx "] ", 
            (Dwarf_Signed) (line_ptr - orig_line_ptr));
        opcode = *(Dwarf_Small *) line_ptr;
        line_ptr++;
        /* 'type' is the output */
        WHAT_IS_OPCODE(type, opcode, prefix.pf_opcode_base,
                       prefix.pf_opcode_length_table, line_ptr,
                       prefix.pf_std_op_count);

        if (type == LOP_DISCARD) {
            int oc;
            int opcnt = prefix.pf_opcode_length_table[opcode];

            printf("*** DWARF CHECK: DISCARD standard opcode %d "
                "with %d operands: "
                "not understood.", opcode, opcnt);
            *err_count_out += 1;
            for (oc = 0; oc < opcnt; oc++) {
                /* 
                 * Read and discard operands we don't
                 * understand.
                 * Arbitrary choice of unsigned read.
                 * Signed read would work as well.
                 */
                Dwarf_Unsigned utmp2;

                DECODE_LEB128_UWORD(line_ptr, utmp2);
                printf(" %" DW_PR_DUu " (0x%" DW_PR_DUx ")",
                       (Dwarf_Unsigned) utmp2,
                       (Dwarf_Unsigned) utmp2);
            }

            printf("***\n");
            /* do nothing, necessary ops done */
        } else if (type == LOP_SPECIAL) {
            /* This op code is a special op in the object, no matter
               that it might fall into the standard op range in this
               compile Thatis, these are special opcodes between
               special_opcode_base and MAX_LINE_OP_CODE.  (including
               special_opcode_base and MAX_LINE_OP_CODE) */
            char special[50];
            unsigned origop = opcode;

            opcode = opcode - prefix.pf_opcode_base;
            address = address + prefix.pf_minimum_instruction_length *
                (opcode / prefix.pf_line_range);
            line =
                line + prefix.pf_line_base +
                opcode % prefix.pf_line_range;

            sprintf(special, "Specialop %3u", origop);
            print_line_detail(special,
                              opcode, address, (int) file, line, column,
                              is_stmt, basic_block, end_sequence,
                              prologue_end, epilogue_begin, isa);

            basic_block = false;

        } else if (type == LOP_STANDARD) {
            switch (opcode) {

            case DW_LNS_copy:{

                    print_line_detail("DW_LNS_copy",
                                      opcode, address, file, line,
                                      column, is_stmt, basic_block,
                                      end_sequence, prologue_end,
                                      epilogue_begin, isa);

                    basic_block = false;
                    break;
                }

            case DW_LNS_advance_pc:{
                    Dwarf_Unsigned utmp2;


                    DECODE_LEB128_UWORD(line_ptr, utmp2);
                    printf("DW_LNS_advance_pc val %" DW_PR_DSd " 0x%" DW_PR_DUx "\n",
                           (Dwarf_Signed) (Dwarf_Word) utmp2,
                           (Dwarf_Unsigned) (Dwarf_Word) utmp2);
                    leb128_num = (Dwarf_Word) utmp2;
                    address =
                        address +
                        prefix.pf_minimum_instruction_length *
                        leb128_num;
                    break;
                }

            case DW_LNS_advance_line:{
                    Dwarf_Signed stmp;


                    DECODE_LEB128_SWORD(line_ptr, stmp);
                    advance_line = (Dwarf_Sword) stmp;
                    printf("DW_LNS_advance_line val %" DW_PR_DSd " 0x%" DW_PR_DSx "\n",
                           (Dwarf_Signed) advance_line,
                           (Dwarf_Signed) advance_line);
                    line = line + advance_line;
                    break;
                }

            case DW_LNS_set_file:{
                    Dwarf_Unsigned utmp2;


                    DECODE_LEB128_UWORD(line_ptr, utmp2);
                    file = (Dwarf_Word) utmp2;
                    printf("DW_LNS_set_file  %ld\n", (long) file);
                    break;
                }

            case DW_LNS_set_column:{
                    Dwarf_Unsigned utmp2;


                    DECODE_LEB128_UWORD(line_ptr, utmp2);
                    column = (Dwarf_Word) utmp2;
                    printf("DW_LNS_set_column val %" DW_PR_DSd " 0x%" DW_PR_DSx "\n",
                           (Dwarf_Signed) column, (Dwarf_Signed) column);
                    break;
                }

            case DW_LNS_negate_stmt:{
                    is_stmt = !is_stmt;
                    printf("DW_LNS_negate_stmt\n");
                    break;
                }

            case DW_LNS_set_basic_block:{

                    printf("DW_LNS_set_basic_block\n");
                    basic_block = true;
                    break;
                }

            case DW_LNS_const_add_pc:{
                    opcode = MAX_LINE_OP_CODE - prefix.pf_opcode_base;
                    address =
                        address +
                        prefix.pf_minimum_instruction_length * (opcode /
                                                                prefix.
                                                                pf_line_range);

                    printf("DW_LNS_const_add_pc new address 0x%" DW_PR_DSx "\n",
                           (Dwarf_Signed) address);
                    break;
                }

            case DW_LNS_fixed_advance_pc:{

                    READ_UNALIGNED(dbg, fixed_advance_pc, Dwarf_Half,
                                   line_ptr, sizeof(Dwarf_Half));
                    line_ptr += sizeof(Dwarf_Half);
                    address = address + fixed_advance_pc;
                    printf("DW_LNS_fixed_advance_pc val %" DW_PR_DSd 
                       " 0x%" DW_PR_DSx " new address 0x%" DW_PR_DSx "\n",
                           (Dwarf_Signed) fixed_advance_pc,
                           (Dwarf_Signed) fixed_advance_pc,
                           (Dwarf_Signed) address);
                    break;
                }
            case DW_LNS_set_prologue_end:{

                    prologue_end = true;
                    printf("DW_LNS_set_prologue_end set true.\n");
                    break;


                }
                /* New in DWARF3 */
            case DW_LNS_set_epilogue_begin:{
                    epilogue_begin = true;
                    printf("DW_LNS_set_epilogue_begin set true.\n");
                    break;
                }

                /* New in DWARF3 */
            case DW_LNS_set_isa:{
                    Dwarf_Unsigned utmp2;

                    DECODE_LEB128_UWORD(line_ptr, utmp2);
                    isa = utmp2;
                    printf("DW_LNS_set_isa new value 0x%" DW_PR_DUx ".\n",
                           (Dwarf_Unsigned) utmp2);
                    if (isa != utmp2) {
                        /* The value of the isa did not fit in our
                           local so we record it wrong. declare an
                           error. */
                        dwarf_free_line_table_prefix(&prefix);

                        _dwarf_error(dbg, error,
                                     DW_DLE_LINE_NUM_OPERANDS_BAD);
                        return (DW_DLV_ERROR);
                    }
                    break;
                }
            }


        } else if (type == LOP_EXTENDED) {
            Dwarf_Unsigned utmp3 = 0;
            Dwarf_Word instr_length = 0;
            Dwarf_Small ext_opcode = 0;

            DECODE_LEB128_UWORD(line_ptr, utmp3);
            instr_length = (Dwarf_Word) utmp3;
            ext_opcode = *(Dwarf_Small *) line_ptr;
            line_ptr++;
            switch (ext_opcode) {

            case DW_LNE_end_sequence:{
                    end_sequence = true;

                    print_line_detail("DW_LNE_end_sequence extended",
                                      opcode, address, file, line,
                                      column, is_stmt, basic_block,
                                      end_sequence, prologue_end,
                                      epilogue_begin, isa);

                    address = 0;
                    file = 1;
                    line = 1;
                    column = 0;
                    is_stmt = prefix.pf_default_is_stmt;
                    basic_block = false;
                    end_sequence = false;
                    prologue_end = false;
                    epilogue_begin = false;


                    break;
                }

            case DW_LNE_set_address:{
                    {
                        READ_UNALIGNED(dbg, address, Dwarf_Addr,
                                       line_ptr, 
                                       die->di_cu_context->cc_address_size);

                        line_ptr += die->di_cu_context->cc_address_size;
                        printf("DW_LNE_set_address address 0x%" DW_PR_DUx "\n",
                               (Dwarf_Unsigned) address);
                    }

                    break;
                }

            case DW_LNE_define_file:{
                    Dwarf_Unsigned di = 0;
                    Dwarf_Unsigned tlm = 0;
                    Dwarf_Unsigned fl = 0;

                    Dwarf_Small *fn = (Dwarf_Small *) line_ptr;
                    line_ptr = line_ptr + strlen((char *) line_ptr) + 1;

                    di = _dwarf_decode_u_leb128(line_ptr,
                                                &leb128_length);
                    line_ptr = line_ptr + leb128_length;

                    tlm = _dwarf_decode_u_leb128(line_ptr,
                                                 &leb128_length);
                    line_ptr = line_ptr + leb128_length;

                    fl = _dwarf_decode_u_leb128(line_ptr,
                                                &leb128_length);
                    line_ptr = line_ptr + leb128_length;


                    printf("DW_LNE_define_file %s \n", fn);
                    printf("    dir index %d\n", (int) di);
                    {
                        time_t tt3 = (time_t) tlm;

                        /* ctime supplies newline */
                        printf("    last time 0x%x %s",
                               (unsigned) tlm, ctime(&tt3));
                    }
                    printf("    file length %ld 0x%lx\n",
                           (long) fl, (unsigned long) fl);

                    break;
                }

            default:{
                 /* This is an extended op code we do not know about,
                    other than we know now many bytes it is
                    (and the op code and the bytes of operand). */

                 Dwarf_Unsigned remaining_bytes = instr_length -1;
                 if(instr_length < 1 || remaining_bytes > DW_LNE_LEN_MAX) {
                      dwarf_free_line_table_prefix(&prefix);
                      _dwarf_error(dbg, error,
                                 DW_DLE_LINE_EXT_OPCODE_BAD);
                      return (DW_DLV_ERROR);
                 }
                 printf("DW_LNE extended op 0x%x ",ext_opcode);
                 printf("Bytecount: " DW_PR_DUu , instr_length);
                 if(remaining_bytes > 0) {
                     printf(" linedata: 0x");
                     while (remaining_bytes > 0) {
                        printf("%02x",(unsigned char)(*(line_ptr)));
                        line_ptr++;
                        remaining_bytes--;
                     }
                 }
                 printf("\n");
                }
                break;
            }

        }
    }

    dwarf_free_line_table_prefix(&prefix);
    return (DW_DLV_OK);
}
Exemplo n.º 19
0
/*
	return DW_DLV_OK if ok. else DW_DLV_NO_ENTRY or DW_DLV_ERROR
*/
int
_dwarf_internal_srclines(Dwarf_Die die,
			 Dwarf_Line ** linebuf,
			 Dwarf_Signed * count,
			 Dwarf_Bool doaddrs,
			 Dwarf_Bool dolines, Dwarf_Error * error)
{
    /* 
       This pointer is used to scan the portion of the .debug_line
       section for the current cu. */
    Dwarf_Small *line_ptr;

    /* 
       This points to the last byte of the .debug_line portion for the 
       current cu. */
    Dwarf_Small *line_ptr_end;

    /* 
       This points to the end of the statement program prologue for the 
       current cu, and serves to check that the prologue was correctly 
       decoded. */
    Dwarf_Small *check_line_ptr;

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

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

    /* 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;

    /* These are the fields of the statement program header. */
    Dwarf_Unsigned total_length;
    Dwarf_Half version;
    Dwarf_Unsigned prologue_length;
    Dwarf_Small minimum_instruction_length;
    Dwarf_Small default_is_stmt;
    Dwarf_Sbyte line_base;
    Dwarf_Small line_range;
    Dwarf_Small special_opcode_base;

    Dwarf_Small *opcode_length;
    Dwarf_Small *include_directories;
    Dwarf_File_Entry file_entries;

    /* These are the state machine state variables. */
    Dwarf_Addr address;
    Dwarf_Word file;
    Dwarf_Word line;
    Dwarf_Word column;
    Dwarf_Bool is_stmt;
    Dwarf_Bool basic_block;
    Dwarf_Bool end_sequence;

    /* 
       These pointers are used to build the list of files names by
       this cu.  cur_file_entry points to the file name being added,
       and prev_file_entry to the previous one. */
    Dwarf_File_Entry cur_file_entry, prev_file_entry;

    Dwarf_Sword i, file_entry_count, include_directories_count;

    /* 
       This is the current opcode read from the statement program. */
    Dwarf_Small opcode;

    /* 
       Pointer to a Dwarf_Line_Context_s structure that contains the
       context such as file names and include directories for the set
       of lines being generated. */
    Dwarf_Line_Context line_context;

    /* 
       This is a pointer to the current line being added to the line
       matrix. */
    Dwarf_Line curr_line;

    /* 
       These variables are used to decode leb128 numbers. Leb128_num
       holds the decoded number, and leb128_length is its length in
       bytes. */
    Dwarf_Word leb128_num;
    Dwarf_Word leb128_length;
    Dwarf_Sword advance_line;

    /* 
       This is the operand of the latest fixed_advance_pc extended
       opcode. */
    Dwarf_Half fixed_advance_pc;

    /* 
       Counts the number of lines in the line matrix. */
    Dwarf_Sword line_count = 0;

    /* This is the length of an extended opcode instr.  */
    Dwarf_Word instr_length;
    Dwarf_Small ext_opcode;

    /* 
       Used to chain together pointers to line table entries that are
       later used to create a block of Dwarf_Line entries. */
    Dwarf_Chain chain_line, head_chain = NULL, curr_chain;

    /* 
       This points to a block of Dwarf_Lines, a pointer to which is
       returned in linebuf. */
    Dwarf_Line *block_line;

    /* The Dwarf_Debug this die belongs to. */
    Dwarf_Debug dbg;
    int resattr;
    int lres;
    int local_length_size = 0;
    /*REFERENCED*/ /* Not used in this instance of the macro */
    int local_extension_size = 0;

    int res;

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

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

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

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

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



    lres = dwarf_formudata(stmt_list_attr, &line_offset, error);
    if (lres != DW_DLV_OK) {
	return lres;
    }

    if (line_offset >= dbg->de_debug_line_size) {
	_dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD);
	return (DW_DLV_ERROR);
    }
    line_ptr = dbg->de_debug_line + line_offset;
    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;
	char *cdir;

	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);
    }

    /* 
       Following is a straightforward decoding of the statement
       program prologue information. */
    /* READ_AREA_LENGTH updates line_ptr for consumed bytes */
    READ_AREA_LENGTH(dbg, total_length, Dwarf_Unsigned,
		     line_ptr, local_length_size, local_extension_size);

    line_ptr_end = line_ptr + total_length;
    if (line_ptr_end > dbg->de_debug_line + dbg->de_debug_line_size) {
	_dwarf_error(dbg, error, DW_DLE_DEBUG_LINE_LENGTH_BAD);
	return (DW_DLV_ERROR);
    }

    READ_UNALIGNED(dbg, version, Dwarf_Half,
		   line_ptr, sizeof(Dwarf_Half));
    line_ptr += sizeof(Dwarf_Half);
    if (version != CURRENT_VERSION_STAMP &&
	version != CURRENT_VERSION_STAMP3) {
	_dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR);
	return (DW_DLV_ERROR);
    }

    READ_UNALIGNED(dbg, prologue_length, Dwarf_Unsigned,
		   line_ptr, local_length_size);
    line_ptr += local_length_size;
    check_line_ptr = line_ptr;

    minimum_instruction_length = *(Dwarf_Small *) line_ptr;
    line_ptr = line_ptr + sizeof(Dwarf_Small);

    default_is_stmt = *(Dwarf_Small *) line_ptr;
    line_ptr = line_ptr + sizeof(Dwarf_Small);

    line_base = *(Dwarf_Sbyte *) line_ptr;
    line_ptr = line_ptr + sizeof(Dwarf_Sbyte);

    line_range = *(Dwarf_Small *) line_ptr;
    line_ptr = line_ptr + sizeof(Dwarf_Small);

    special_opcode_base = *(Dwarf_Small *) line_ptr;
    line_ptr = line_ptr + sizeof(Dwarf_Small);

    opcode_length = (Dwarf_Small *)
	alloca(sizeof(Dwarf_Small) * special_opcode_base);
    for (i = 1; i < special_opcode_base; i++) {
	opcode_length[i] = *(Dwarf_Small *) line_ptr;
	line_ptr = line_ptr + sizeof(Dwarf_Small);
    }

    include_directories_count = 0;
    include_directories = line_ptr;
    while ((*(char *) line_ptr) != '\0') {
	line_ptr = line_ptr + strlen((char *) line_ptr) + 1;
	include_directories_count++;
    }
    line_ptr++;

    file_entry_count = 0;
    file_entries = prev_file_entry = NULL;
    while (*(char *) line_ptr != '\0') {

	cur_file_entry = (Dwarf_File_Entry)
	    _dwarf_get_alloc(dbg, DW_DLA_FILE_ENTRY, 1);
	if (cur_file_entry == NULL) {
	    _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
	    return (DW_DLV_ERROR);
	}

	cur_file_entry->fi_file_name = (Dwarf_Small *) line_ptr;
	line_ptr = line_ptr + strlen((char *) line_ptr) + 1;

	cur_file_entry->fi_dir_index =
	    (Dwarf_Sword) _dwarf_decode_u_leb128(line_ptr,
						 &leb128_length);
	line_ptr = line_ptr + leb128_length;

	cur_file_entry->fi_time_last_mod =
	    _dwarf_decode_u_leb128(line_ptr, &leb128_length);
	line_ptr = line_ptr + leb128_length;

	cur_file_entry->fi_file_length =
	    _dwarf_decode_u_leb128(line_ptr, &leb128_length);
	line_ptr = line_ptr + leb128_length;

	if (file_entries == NULL)
	    file_entries = cur_file_entry;
	else
	    prev_file_entry->fi_next = cur_file_entry;
	prev_file_entry = cur_file_entry;

	file_entry_count++;
    }
    line_ptr++;

    if (line_ptr != check_line_ptr + prologue_length) {
	_dwarf_error(dbg, error, DW_DLE_LINE_PROLOG_LENGTH_BAD);
	return (DW_DLV_ERROR);
    }

    /* Set up context structure for this set of lines. */
    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);
    }

    /* Initialize the state machine.  */
    address = 0;
    file = 1;
    line = 1;
    column = 0;
    is_stmt = default_is_stmt;
    basic_block = false;
    end_sequence = false;

    /* Start of statement program.  */
    while (line_ptr < line_ptr_end) {
	int type;

	opcode = *(Dwarf_Small *) line_ptr;
	line_ptr++;


	/* 'type' is the output */
	WHAT_IS_OPCODE(type, opcode, special_opcode_base,
		       opcode_length, line_ptr);



	if (type == LOP_DISCARD) {
	    /* do nothing, necessary ops done */
	} else if (type == LOP_SPECIAL) {
	    /* This op code is a special op in the object, no matter
	       that it might fall into the standard op range in this
	       compile Thatis, these are special opcodes between
	       special_opcode_base and MAX_LINE_OP_CODE.  (including
	       special_opcode_base and MAX_LINE_OP_CODE) */

	    opcode = opcode - special_opcode_base;
	    address = address + minimum_instruction_length *
		(opcode / line_range);
	    line = line + line_base + opcode % line_range;

	    if (dolines) {
		curr_line =
		    (Dwarf_Line) _dwarf_get_alloc(dbg, DW_DLA_LINE, 1);
		if (curr_line == NULL) {
		    _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
		    return (DW_DLV_ERROR);
		}

		curr_line->li_address = address;
		curr_line->li_addr_line.li_l_data.li_file =
		    (Dwarf_Sword) file;
		curr_line->li_addr_line.li_l_data.li_line =
		    (Dwarf_Sword) line;
		curr_line->li_addr_line.li_l_data.li_column =
		    (Dwarf_Half) column;
		curr_line->li_addr_line.li_l_data.li_is_stmt = is_stmt;
		curr_line->li_addr_line.li_l_data.li_basic_block =
		    basic_block;
		curr_line->li_addr_line.li_l_data.li_end_sequence =
		    end_sequence;
		curr_line->li_context = line_context;
		line_count++;

		chain_line = (Dwarf_Chain)
		    _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
		if (chain_line == NULL) {
		    _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
		    return (DW_DLV_ERROR);
		}
		chain_line->ch_item = curr_line;

		if (head_chain == NULL)
		    head_chain = curr_chain = chain_line;
		else {
		    curr_chain->ch_next = chain_line;
		    curr_chain = chain_line;
		}
	    }

	    basic_block = false;
	} else if (type == LOP_STANDARD) {
	    switch (opcode) {

	    case DW_LNS_copy:{
		    if (opcode_length[DW_LNS_copy] != 0) {
			_dwarf_error(dbg, error,
				     DW_DLE_LINE_NUM_OPERANDS_BAD);
			return (DW_DLV_ERROR);
		    }

		    if (dolines) {

			curr_line =
			    (Dwarf_Line) _dwarf_get_alloc(dbg,
							  DW_DLA_LINE,
							  1);
			if (curr_line == NULL) {
			    _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
			    return (DW_DLV_ERROR);
			}

			curr_line->li_address = address;
			curr_line->li_addr_line.li_l_data.li_file =
			    (Dwarf_Sword) file;
			curr_line->li_addr_line.li_l_data.li_line =
			    (Dwarf_Sword) line;
			curr_line->li_addr_line.li_l_data.li_column =
			    (Dwarf_Half) column;
			curr_line->li_addr_line.li_l_data.li_is_stmt =
			    is_stmt;
			curr_line->li_addr_line.li_l_data.
			    li_basic_block = basic_block;
			curr_line->li_addr_line.li_l_data.
			    li_end_sequence = end_sequence;
			curr_line->li_context = line_context;
			line_count++;

			chain_line = (Dwarf_Chain)
			    _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
			if (chain_line == NULL) {
			    _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
			    return (DW_DLV_ERROR);
			}
			chain_line->ch_item = curr_line;
			if (head_chain == NULL)
			    head_chain = curr_chain = chain_line;
			else {
			    curr_chain->ch_next = chain_line;
			    curr_chain = chain_line;
			}
		    }

		    basic_block = false;
		    break;
		}

	    case DW_LNS_advance_pc:{
		    Dwarf_Unsigned utmp2;

		    if (opcode_length[DW_LNS_advance_pc] != 1) {
			_dwarf_error(dbg, error,
				     DW_DLE_LINE_NUM_OPERANDS_BAD);
			return (DW_DLV_ERROR);
		    }

		    DECODE_LEB128_UWORD(line_ptr, utmp2)
			leb128_num = (Dwarf_Word) utmp2;
		    address =
			address +
			minimum_instruction_length * leb128_num;
		    break;
		}

	    case DW_LNS_advance_line:{
		    Dwarf_Signed stmp;

		    if (opcode_length[DW_LNS_advance_line] != 1) {
			_dwarf_error(dbg, error,
				     DW_DLE_LINE_NUM_OPERANDS_BAD);
			return (DW_DLV_ERROR);
		    }

		    DECODE_LEB128_SWORD(line_ptr, stmp)
			advance_line = (Dwarf_Sword) stmp;
		    line = line + advance_line;
		    break;
		}

	    case DW_LNS_set_file:{
		    Dwarf_Unsigned utmp2;

		    if (opcode_length[DW_LNS_set_file] != 1) {
			_dwarf_error(dbg, error,
				     DW_DLE_LINE_NUM_OPERANDS_BAD);
			return (DW_DLV_ERROR);
		    }

		    DECODE_LEB128_UWORD(line_ptr, utmp2)
			file = (Dwarf_Word) utmp2;
		    break;
		}

	    case DW_LNS_set_column:{
		    Dwarf_Unsigned utmp2;

		    if (opcode_length[DW_LNS_set_column] != 1) {
			_dwarf_error(dbg, error,
				     DW_DLE_LINE_NUM_OPERANDS_BAD);
			return (DW_DLV_ERROR);
		    }

		    DECODE_LEB128_UWORD(line_ptr, utmp2)
			column = (Dwarf_Word) utmp2;
		    break;
		}

	    case DW_LNS_negate_stmt:{
		    if (opcode_length[DW_LNS_negate_stmt] != 0) {
			_dwarf_error(dbg, error,
				     DW_DLE_LINE_NUM_OPERANDS_BAD);
			return (DW_DLV_ERROR);
		    }

		    is_stmt = !is_stmt;
		    break;
		}

	    case DW_LNS_set_basic_block:{
		    if (opcode_length[DW_LNS_set_basic_block] != 0) {
			_dwarf_error(dbg, error,
				     DW_DLE_LINE_NUM_OPERANDS_BAD);
			return (DW_DLV_ERROR);
		    }

		    basic_block = true;
		    break;
		}

	    case DW_LNS_const_add_pc:{
		    opcode = MAX_LINE_OP_CODE - special_opcode_base;
		    address = address + minimum_instruction_length *
			(opcode / line_range);

		    break;
		}

	    case DW_LNS_fixed_advance_pc:{
		    if (opcode_length[DW_LNS_fixed_advance_pc] != 1) {
			_dwarf_error(dbg, error,
				     DW_DLE_LINE_NUM_OPERANDS_BAD);
			return (DW_DLV_ERROR);
		    }

		    READ_UNALIGNED(dbg, fixed_advance_pc, Dwarf_Half,
				   line_ptr, sizeof(Dwarf_Half));
		    line_ptr += sizeof(Dwarf_Half);
		    address = address + fixed_advance_pc;
		    break;
		}
	    }

	} else if (type == LOP_EXTENDED) {
	    Dwarf_Unsigned utmp3;

	    DECODE_LEB128_UWORD(line_ptr, utmp3)
		instr_length = (Dwarf_Word) utmp3;
	    /* Dwarf_Small is a ubyte and the extended opcode
	       is a ubyte, though not stated as clearly in
	       the 2.0.0 spec as one might hope.
	    */
	    ext_opcode = *(Dwarf_Small *) line_ptr;
	    line_ptr++;
	    switch (ext_opcode) {

	    case DW_LNE_end_sequence:{
		    end_sequence = true;

		    if (dolines) {
			curr_line = (Dwarf_Line)
			    _dwarf_get_alloc(dbg, DW_DLA_LINE, 1);
			if (curr_line == NULL) {
			    _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
			    return (DW_DLV_ERROR);
			}

			curr_line->li_address = address;
			curr_line->li_addr_line.li_l_data.li_file =
			    (Dwarf_Sword) file;
			curr_line->li_addr_line.li_l_data.li_line =
			    (Dwarf_Sword) line;
			curr_line->li_addr_line.li_l_data.li_column =
			    (Dwarf_Half) column;
			curr_line->li_addr_line.li_l_data.li_is_stmt =
			    default_is_stmt;
			curr_line->li_addr_line.li_l_data.
			    li_basic_block = basic_block;
			curr_line->li_addr_line.li_l_data.
			    li_end_sequence = end_sequence;
			curr_line->li_context = line_context;
			line_count++;

			chain_line = (Dwarf_Chain)
			    _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
			if (chain_line == NULL) {
			    _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
			    return (DW_DLV_ERROR);
			}
			chain_line->ch_item = curr_line;

			if (head_chain == NULL)
			    head_chain = curr_chain = chain_line;
			else {
			    curr_chain->ch_next = chain_line;
			    curr_chain = chain_line;
			}
		    }

		    address = 0;
		    file = 1;
		    line = 1;
		    column = 0;
		    is_stmt = default_is_stmt;
		    basic_block = false;
		    end_sequence = false;

		    break;
		}

	    case DW_LNE_set_address:{
		    if (instr_length - 1 == dbg->de_pointer_size) {
			READ_UNALIGNED(dbg, address, Dwarf_Addr,
				       line_ptr, dbg->de_pointer_size);
			if (doaddrs) {
			    curr_line =
				(Dwarf_Line) _dwarf_get_alloc(dbg,
							      DW_DLA_LINE,
							      1);
			    if (curr_line == NULL) {
				_dwarf_error(dbg, error,
					     DW_DLE_ALLOC_FAIL);
				return (DW_DLV_ERROR);
			    }

			    curr_line->li_address = address;
			    curr_line->li_addr_line.li_offset =
				line_ptr - dbg->de_debug_line;

			    line_count++;

			    chain_line = (Dwarf_Chain)
				_dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
			    if (chain_line == NULL) {
				_dwarf_error(dbg, error,
					     DW_DLE_ALLOC_FAIL);
				return (DW_DLV_ERROR);
			    }
			    chain_line->ch_item = curr_line;

			    if (head_chain == NULL)
				head_chain = curr_chain = chain_line;
			    else {
				curr_chain->ch_next = chain_line;
				curr_chain = chain_line;
			    }
			}

			line_ptr += dbg->de_pointer_size;
		    } else {
			_dwarf_error(dbg, error,
				     DW_DLE_LINE_SET_ADDR_ERROR);
			return (DW_DLV_ERROR);
		    }

		    break;
		}

	    case DW_LNE_define_file:{

		    if (dolines) {
			cur_file_entry = (Dwarf_File_Entry)
			    _dwarf_get_alloc(dbg, DW_DLA_FILE_ENTRY, 1);
			if (cur_file_entry == NULL) {
			    _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
			    return (DW_DLV_ERROR);
			}

			cur_file_entry->fi_file_name =
			    (Dwarf_Small *) line_ptr;
			line_ptr =
			    line_ptr + strlen((char *) line_ptr) + 1;

			cur_file_entry->fi_dir_index =
			    (Dwarf_Sword)
			    _dwarf_decode_u_leb128(line_ptr,
						   &leb128_length);
			line_ptr = line_ptr + leb128_length;

			cur_file_entry->fi_time_last_mod =
			    _dwarf_decode_u_leb128(line_ptr,
						   &leb128_length);
			line_ptr = line_ptr + leb128_length;

			cur_file_entry->fi_file_length =
			    _dwarf_decode_u_leb128(line_ptr,
						   &leb128_length);
			line_ptr = line_ptr + leb128_length;

			if (file_entries == NULL)
			    file_entries = cur_file_entry;
			else
			    prev_file_entry->fi_next = cur_file_entry;
			prev_file_entry = cur_file_entry;

			file_entry_count++;
		    }
		    break;
		}

	    default:{
		    _dwarf_error(dbg, error,
				 DW_DLE_LINE_EXT_OPCODE_BAD);
		    return (DW_DLV_ERROR);
		}
	    }

	}
    }

    block_line = (Dwarf_Line *)
	_dwarf_get_alloc(dbg, DW_DLA_LIST, line_count);
    if (block_line == NULL) {
	_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
	return (DW_DLV_ERROR);
    }

    curr_chain = head_chain;
    for (i = 0; i < line_count; i++) {
	*(block_line + i) = curr_chain->ch_item;
	head_chain = curr_chain;
	curr_chain = curr_chain->ch_next;
	dwarf_dealloc(dbg, head_chain, DW_DLA_CHAIN);
    }

    line_context->lc_file_entries = file_entries;
    line_context->lc_file_entry_count = file_entry_count;
    line_context->lc_include_directories = include_directories;
    line_context->lc_include_directories_count =
	include_directories_count;
    line_context->lc_line_count = line_count;
    line_context->lc_compilation_directory = comp_dir;
    line_context->lc_version_number = version;	
    line_context->lc_dbg = dbg;
    *count = line_count;

    *linebuf = block_line;
    return (DW_DLV_OK);
}
Exemplo n.º 20
0
static int
process_cu (Dwarf_Die *cu_die)
{
  Dwarf_Attribute attr;
  const char *name;
  const char *dir = NULL;
  
  Dwarf_Files *files;
  size_t n;
  int i;
  
  if (dwarf_tag (cu_die) != DW_TAG_compile_unit)
    {
      fprintf (stderr, "DIE isn't a compile unit");
      return -1;
    }
  
  if (dwarf_attr (cu_die, DW_AT_name, &attr) == NULL)
    {
      fprintf(stderr, "CU doesn't have a DW_AT_name");
      return -1;
    }
  
  name = dwarf_formstring (&attr);
  if (name == NULL)
    {
      fprintf(stderr, "Couldn't get DW_AT_name as string, %s",
	     dwarf_errmsg (-1));
      return -1;
    }
  
  if (dwarf_attr (cu_die, DW_AT_comp_dir, &attr) != NULL)
    {
      dir = dwarf_formstring (&attr);
      if (dir == NULL)
	{
	  fprintf(stderr, "Couldn't get DW_AT_comp_die as string, %s",
		 dwarf_errmsg (-1));
	  return -1;
	}
    }
  
  if (dir == NULL)
    printf ("%s\n", name);
  else
    printf ("%s/%s\n", dir, name);
  
  if (dwarf_getsrcfiles (cu_die, &files, &n) != 0)
    {
      fprintf(stderr, "Couldn't get CU file table, %s",
	     dwarf_errmsg (-1));
      return -1;
    }
  
  for (i = 1; i < n; i++)
    {
      const char *file = dwarf_filesrc (files, i, NULL, NULL);
      if (dir != NULL && file[0] != '/')
	printf ("\t%s/%s\n", dir, file);
      else
	printf ("\t%s\n", file);
    }
  
  return 0;
}
Exemplo n.º 21
0
static void show_all_attrs(Dwarf_Die die, unsigned long level, void *ndata){
  Dwarf_Error error;
  Dwarf_Half tag; 
  dwarf_tag(die,&tag,&error);

  const char *stag;
  dwarf_get_TAG_name(tag,&stag); 

  Dwarf_Off off = 0x0;
  dwarf_die_CU_offset(die,&off,&error);
  fprintf(stderr,"[%u]<%x>%s\n",level,off,stag);
  
  char **sourceFiles;
  Dwarf_Signed num;
  int res;
  if( (res = dwarf_srcfiles(die,&sourceFiles,&num,&error)) == DW_DLV_OK){
    fprintf(stderr,"Source Files Referenced:\n");
    int i;
    for(i = 0; i < num; i++){
      fprintf(stderr,"%s\n",sourceFiles[i]);
      dwarf_dealloc(d, sourceFiles[i],DW_DLA_STRING);
    } 
    dwarf_dealloc(d, sourceFiles,DW_DLA_LIST);
  }

  Dwarf_Unsigned atcnt;
  Dwarf_Attribute *atlist;
  int errv;
  if((errv = dwarf_attrlist(die, &atlist, &atcnt, &error)) == DW_DLV_OK){
    int i;
    for(i = 0; i < atcnt; i++){
      Dwarf_Half attr;
      if(dwarf_whatattr(atlist[i],&attr,&error) == DW_DLV_OK){
        const char *sattr;
        dwarf_get_AT_name(attr,&sattr); 
        fprintf(stderr,"\t%s => ",sattr);
      }else{
        fprintf(stderr,"\tCouldn't Get Attr Type!\n"); 
        continue;
      }
      Dwarf_Half form;
      if(dwarf_whatform(atlist[i],&form,&error) == DW_DLV_OK){
        //const char *formname;
        //dwarf_get_FORM_name(form,&formname);
        //fprintf(stderr,"[%s] ",formname);
        switch(form){
          case DW_FORM_ref1:
          case DW_FORM_ref2:
          case DW_FORM_ref4:
          case DW_FORM_ref8:
          case DW_FORM_ref_udata:
            {Dwarf_Off offset;
            dwarf_formref(atlist[i],&offset,&error); 
            fprintf(stderr,"%x\n",offset);}
            break;
          case DW_FORM_ref_addr:
            {Dwarf_Off offset;
            dwarf_global_formref(atlist[i],&offset,&error); 
            fprintf(stderr,"%x\n",offset);}
            break;
          case DW_FORM_addr:
            {Dwarf_Addr addr;
            dwarf_formaddr(atlist[i],&addr,&error); 
            fprintf(stderr,"%x\n",addr);}
            break;
          case DW_FORM_flag:
            {Dwarf_Bool flag;
            dwarf_formflag(atlist[i],&flag,&error); 
            fprintf(stderr,"%s\n",flag ? "True" : "False");}
            break;
          case DW_FORM_udata:
          case DW_FORM_data1:
          case DW_FORM_data2:
          case DW_FORM_data4:
          case DW_FORM_data8:
            {Dwarf_Unsigned val;
            dwarf_formudata(atlist[i],&val,&error); 
            fprintf(stderr,"%u\n",val);}
            break;
          case DW_FORM_sdata:
            {Dwarf_Signed val;
            dwarf_formsdata(atlist[i],&val,&error); 
            fprintf(stderr,"%d\n",val);}
            break;
          case DW_FORM_block:
          case DW_FORM_block1:
            if(attr == DW_AT_location ||
               attr == DW_AT_data_member_location ||
               attr == DW_AT_vtable_elem_location ||
               attr == DW_AT_string_length ||
               attr == DW_AT_use_location ||
               attr == DW_AT_return_addr){
              /* 
              Dwarf_Locdesc *locationList;
              Dwarf_Signed listLength;
              int ret = dwarf_loclist( atlist[i], &locationList, &listLength, &error );
              int frameRel = 0;
              long offset = 0;
              decode_location(locationList,listLength,&offset,NULL,&frameRel);
              int i;
              for( i = 0; i < listLength; ++i){
                dwarf_dealloc(d,locationList[i].ld_s,DW_DLA_LOC_BLOCK);               
              }
              dwarf_dealloc(d,locationList,DW_DLA_LOCDESC);               
              */
              DC_location dcl;
              DC_get_location_attr_value(atlist[i],&dcl); 
              fprintf(stderr," %s:",dcl.isFrameOffset ? "FP Offset" : "Address");
              fprintf(stderr," %ld\n",dcl.offset);

            }else{
              fprintf(stderr,"UNSUPPORTED ATTRIBUTE TYPE\n");
            }
            break;
          case DW_FORM_string:
            {char *val;
            dwarf_formstring(atlist[i],&val,&error); 
            fprintf(stderr,"%s\n",val);}
            break;
          
          case DW_FORM_strp:
            {char *str;
            if( (dwarf_formstring(atlist[i],&str,&error) == DW_DLV_OK) ){
              fprintf(stderr,"%s\n",str);
            } }
            break;
          
          default:
            fprintf(stderr,"Unhandled Attribute Form!\n");
            break;
            
        };
      }
      dwarf_dealloc(d, atlist[i], DW_DLA_ATTR);
    }
    dwarf_dealloc(d, atlist, DW_DLA_LIST);
  } 

}
Exemplo n.º 22
0
/* 
    Although source files is supposed to return the
    source files in the compilation-unit, it does
    not look for any in the statement program.  In
    other words, it ignores those defined using the
    extended opcode DW_LNE_define_file.
*/
int
dwarf_srcfiles(Dwarf_Die die,
	       char ***srcfiles,
	       Dwarf_Signed * srcfilecount, Dwarf_Error * error)
{
    /* 
       This pointer is used to scan the portion of the .debug_line
       section for the current cu. */
    Dwarf_Small *line_ptr;

    /* 
       This points to the last byte of the .debug_line portion for the 
       current cu. */
    Dwarf_Small *line_ptr_end;

    /* 
       This points to the end of the statement program prologue for the 
       current cu, and serves to check that the prologue was correctly 
       decoded. */
    Dwarf_Small *check_line_ptr;

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

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

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

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

    /* Some of the fields of the statement program header. */
    Dwarf_Unsigned total_length = 0;
    Dwarf_Half version = 0;
    Dwarf_Unsigned prologue_length = 0;
    Dwarf_Small special_opcode_base= 0;

    /* File name excluding included directory. */
    char *file_name = 0;

    /* Name of directory that the file is in. */
    char *dir_name = 0;

    /* Name concatenating both directory and file name. */
    char *full_name = 0;

    /* 
       This is the directory index for the file. The compilation
       directory is 0, and the first included directory is 1. */
    Dwarf_Sword dir_index = 0;

    Dwarf_Small *include_directories = 0;

    Dwarf_Sword i = 0; 
    Dwarf_Sword file_count = 0; 
    Dwarf_Sword directories_count = 0;

    /* 
       This is the current opcode read from the statement program. */

    Dwarf_Word leb128_length;

    /* This is the length of an extended opcode instr.  */

    /* 
       This points to a block of char *'s, each of which points to a
       file name. */
    char **ret_files = 0;

    /* The Dwarf_Debug this die belongs to. */
    Dwarf_Debug dbg;

    /* Used to chain the file names. */
    Dwarf_Chain curr_chain, prev_chain, head_chain = NULL;
    int resattr;
    int lres;

    int local_length_size = 0;
    /*REFERENCED*/ /* Not used in this instance of the macro */
    int local_extension_size = 0;

    int res;

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

    /* Reset error. */
    if (error != NULL)
	*error = NULL;

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

    resattr = dwarf_attr(die, DW_AT_stmt_list, &stmt_list_attr, error);
    if (resattr != DW_DLV_OK) {
	return resattr;
    }
    
    if (dbg->de_debug_line_index == 0) {
	_dwarf_error(dbg, error, DW_DLE_DEBUG_LINE_NULL);
	return (DW_DLV_ERROR);
    }

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

    lres = dwarf_formudata(stmt_list_attr, &line_offset, error);
    if (lres != DW_DLV_OK) {
	return lres;
    }
    if (line_offset >= dbg->de_debug_line_size) {
	_dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD);
	return (DW_DLV_ERROR);
    }
    line_ptr = dbg->de_debug_line + line_offset;
    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;
	char *cdir;

	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);
    }

    /* 
       Following is a straightforward decoding of the statement
       program prologue information. */
    /* READ_AREA_LENGTH updates line_ptr for consumed bytes */
    READ_AREA_LENGTH(dbg, total_length, Dwarf_Unsigned,
		     line_ptr, local_length_size, local_extension_size);


    line_ptr_end = line_ptr + total_length;
    if (line_ptr_end > dbg->de_debug_line + dbg->de_debug_line_size) {
	_dwarf_error(dbg, error, DW_DLE_DEBUG_LINE_LENGTH_BAD);
	return (DW_DLV_ERROR);
    }

    READ_UNALIGNED(dbg, version, Dwarf_Half,
		   line_ptr, sizeof(Dwarf_Half));
    line_ptr += sizeof(Dwarf_Half);
    if (version != CURRENT_VERSION_STAMP &&
	version != CURRENT_VERSION_STAMP3) {
	_dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR);
	return (DW_DLV_ERROR);
    }

    READ_UNALIGNED(dbg, prologue_length, Dwarf_Unsigned,
		   line_ptr, local_length_size);
    line_ptr += local_length_size;
    check_line_ptr = line_ptr;

    /* Skip over minimum instruction length. */
    line_ptr = line_ptr + sizeof(Dwarf_Small);

    /* Skip over default_is_stmt. */
    line_ptr = line_ptr + sizeof(Dwarf_Small);

    /* Skip over line_base. */
    line_ptr = line_ptr + sizeof(Dwarf_Sbyte);

    /* Skip over line_ptr. */
    line_ptr = line_ptr + sizeof(Dwarf_Small);

    special_opcode_base = *(Dwarf_Small *) line_ptr;
    line_ptr = line_ptr + sizeof(Dwarf_Small);

    for (i = 1; i < special_opcode_base; i++) {
	/* Skip over opcode lengths for standard opcodes. */
	line_ptr = line_ptr + sizeof(Dwarf_Small);
    }

    directories_count = 0;
    include_directories = line_ptr;
    while ((*(char *) line_ptr) != '\0') {
	line_ptr = line_ptr + strlen((char *) line_ptr) + 1;
	directories_count++;
    }
    line_ptr++;

    file_count = 0;
    while (*(char *) line_ptr != '\0') {
	Dwarf_Unsigned utmp;

	file_name = (char *) line_ptr;
	line_ptr = line_ptr + strlen((char *) line_ptr) + 1;

	DECODE_LEB128_UWORD(line_ptr, utmp)
	    dir_index = (Dwarf_Sword) utmp;
	if (dir_index > directories_count) {
	    _dwarf_error(dbg, error, DW_DLE_DIR_INDEX_BAD);
	    return (DW_DLV_ERROR);
	}

	if (dir_index == 0)
	    dir_name = (char *) comp_dir;
	else {
	    dir_name = (char *) include_directories;
	    for (i = 1; i < dir_index; i++)
		/* FIX: this is probably very slow: redoing strlen!
		   davea 9/94 */
		dir_name = dir_name + strlen(dir_name) + 1;
	}

	/* dir_name can be NULL if there is no DW_AT_comp_dir */
	if ((*file_name) == '/' || dir_name == 0)
	    full_name = file_name;
	else {
	    full_name = (char *) _dwarf_get_alloc(dbg, DW_DLA_STRING,
						  strlen(dir_name) + 1 +
						  strlen(file_name) +
						  1);
	    if (full_name == NULL) {
		_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
		return (DW_DLV_ERROR);
	    }

	    strcpy(full_name, dir_name);
	    strcat(full_name, "/");
	    strcat(full_name, file_name);
	}

	/* Skip over time of last modification. */
	_dwarf_decode_u_leb128(line_ptr, &leb128_length);
	line_ptr = line_ptr + leb128_length;

	/* Skip over file length. */
	_dwarf_decode_u_leb128(line_ptr, &leb128_length);
	line_ptr = line_ptr + leb128_length;

	curr_chain =
	    (Dwarf_Chain) _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
	if (curr_chain == NULL) {
	    _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
	    return (DW_DLV_ERROR);
	}

	curr_chain->ch_item = full_name;

	if (head_chain == NULL)
	    head_chain = prev_chain = curr_chain;
	else {
	    prev_chain->ch_next = curr_chain;
	    prev_chain = curr_chain;
	}

	file_count++;
    }
    line_ptr++;

    if (line_ptr != check_line_ptr + prologue_length) {
	_dwarf_error(dbg, error, DW_DLE_LINE_PROLOG_LENGTH_BAD);
	return (DW_DLV_ERROR);
    }

    if (file_count == 0) {
	*srcfiles = NULL;
	*srcfilecount = 0;
	return (DW_DLV_NO_ENTRY);
    }

    ret_files = (char **)
	_dwarf_get_alloc(dbg, DW_DLA_LIST, file_count);
    if (ret_files == NULL) {
	_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
	return (DW_DLV_ERROR);
    }

    curr_chain = head_chain;
    for (i = 0; i < file_count; i++) {
	*(ret_files + i) = curr_chain->ch_item;
	prev_chain = curr_chain;
	curr_chain = curr_chain->ch_next;
	dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN);
    }

    *srcfiles = ret_files;
    *srcfilecount = file_count;
    return (DW_DLV_OK);
}
Exemplo n.º 23
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;
}
Exemplo n.º 24
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;
}
void
handle (Dwarf *dbg, Dwarf_Die *die, int n)
{
  Dwarf_Die child;
  unsigned int tag;
  const char *str;
  char buf[30];
  const char *name;
  Dwarf_Off off;
  Dwarf_Off cuoff;
  size_t cnt;
  Dwarf_Addr addr;
  int i;

  tag = dwarf_tag (die);
  if (tag != DW_TAG_invalid)
    {
      if (tag < ntagnames)
	str = tagnames[tag];
      else
	{
	  snprintf (buf, sizeof buf, "%#x", tag);
	  str = buf;
	}
    }
  else
    str = "* NO TAG *";

  name = dwarf_diename (die);
  if (name == 0)
    name = "* NO NAME *";

  off = dwarf_dieoffset (die);
  cuoff = dwarf_cuoffset (die);

  printf ("%*s%s\n", n * 5, "", str);
  printf ("%*s Name      : %s\n", n * 5, "", name);
  printf ("%*s Offset    : %lld\n", n * 5, "", (long long int) off);
  printf ("%*s CU offset : %lld\n", n * 5, "", (long long int) cuoff);

  printf ("%*s Attrs     :", n * 5, "");
  for (cnt = 0; cnt < nattrs; ++cnt)
    if (dwarf_hasattr (die, attrs[cnt].code))
      printf (" %s", attrs[cnt].name);
  puts ("");

  if (dwarf_hasattr (die, DW_AT_low_pc) && dwarf_lowpc (die, &addr) == 0)
    {
      Dwarf_Attribute attr;
      Dwarf_Addr addr2;
      printf ("%*s low PC    : %#llx\n",
	      n * 5, "", (unsigned long long int) addr);

      if (dwarf_attr (die, DW_AT_low_pc, &attr) == NULL
	  || dwarf_formaddr (&attr, &addr2) != 0
	  || addr != addr2)
	puts ("************* DW_AT_low_pc verify failed ************");
      else if (! dwarf_hasform (&attr, DW_FORM_addr))
	puts ("************* DW_AT_low_pc form failed ************");
      else if (dwarf_whatform (&attr) != DW_FORM_addr)
	puts ("************* DW_AT_low_pc form (2) failed ************");
      else if (dwarf_whatattr (&attr) != DW_AT_low_pc)
	puts ("************* DW_AT_low_pc attr failed ************");
    }
  if (dwarf_hasattr (die, DW_AT_high_pc) && dwarf_highpc (die, &addr) == 0)
    {
      Dwarf_Attribute attr;
      Dwarf_Addr addr2;
      printf ("%*s high PC   : %#llx\n",
	      n * 5, "", (unsigned long long int) addr);
      if (dwarf_attr (die, DW_AT_high_pc, &attr) == NULL
	  || dwarf_formaddr (&attr, &addr2) != 0
	  || addr != addr2)
	puts ("************* DW_AT_high_pc verify failed ************");
      else if (! dwarf_hasform (&attr, DW_FORM_addr))
	puts ("************* DW_AT_high_pc form failed ************");
      else if (dwarf_whatform (&attr) != DW_FORM_addr)
	puts ("************* DW_AT_high_pc form (2) failed ************");
      else if (dwarf_whatattr (&attr) != DW_AT_high_pc)
	puts ("************* DW_AT_high_pc attr failed ************");
    }

  if (dwarf_hasattr (die, DW_AT_byte_size) && (i = dwarf_bytesize (die)) != -1)
    {
      Dwarf_Attribute attr;
      Dwarf_Word u2;
      unsigned int u;
      printf ("%*s byte size : %d\n", n * 5, "", i);
      if (dwarf_attr (die, DW_AT_byte_size, &attr) == NULL
	  || dwarf_formudata (&attr, &u2) != 0
	  || i != (int) u2)
	puts ("************* DW_AT_byte_size verify failed ************");
      else if (! dwarf_hasform (&attr, DW_FORM_data1)
	       && ! dwarf_hasform (&attr, DW_FORM_data2)
	       && ! dwarf_hasform (&attr, DW_FORM_data4)
	       && ! dwarf_hasform (&attr, DW_FORM_data8)
	       && ! dwarf_hasform (&attr, DW_FORM_sdata)
	       && ! dwarf_hasform (&attr, DW_FORM_udata))
	puts ("************* DW_AT_byte_size form failed ************");
      else if ((u = dwarf_whatform (&attr)) == 0
	       || (u != DW_FORM_data1
		   && u != DW_FORM_data2
		   && u != DW_FORM_data4
		   && u != DW_FORM_data8
		   && u != DW_FORM_sdata
		   && u != DW_FORM_udata))
	puts ("************* DW_AT_byte_size form (2) failed ************");
      else if (dwarf_whatattr (&attr) != DW_AT_byte_size)
	puts ("************* DW_AT_byte_size attr failed ************");
    }
  if (dwarf_hasattr (die, DW_AT_bit_size) && (i = dwarf_bitsize (die)) != -1)
    {
      Dwarf_Attribute attr;
      Dwarf_Word u2;
      unsigned int u;
      printf ("%*s bit size  : %d\n", n * 5, "", i);
      if (dwarf_attr (die, DW_AT_bit_size, &attr) == NULL
	  || dwarf_formudata (&attr, &u2) != 0
	  || i != (int) u2)
	puts ("************* DW_AT_bit_size test failed ************");
      else if (! dwarf_hasform (&attr, DW_FORM_data1)
	       && ! dwarf_hasform (&attr, DW_FORM_data2)
	       && ! dwarf_hasform (&attr, DW_FORM_data4)
	       && ! dwarf_hasform (&attr, DW_FORM_data8)
	       && ! dwarf_hasform (&attr, DW_FORM_sdata)
	       && ! dwarf_hasform (&attr, DW_FORM_udata))
	puts ("************* DW_AT_bit_size form failed ************");
      else if ((u = dwarf_whatform (&attr)) == 0
	       || (u != DW_FORM_data1
		   && u != DW_FORM_data2
		   && u != DW_FORM_data4
		   && u != DW_FORM_data8
		   && u != DW_FORM_sdata
		   && u != DW_FORM_udata))
	puts ("************* DW_AT_bit_size form (2) failed ************");
      else if (dwarf_whatattr (&attr) != DW_AT_bit_size)
	puts ("************* DW_AT_bit_size attr failed ************");
    }
  if (dwarf_hasattr (die, DW_AT_bit_offset)
      && (i = dwarf_bitoffset (die)) != -1)
    {
      Dwarf_Attribute attr;
      Dwarf_Word u2;
      unsigned int u;
      printf ("%*s bit offset: %d\n", n * 5, "", i);
      if (dwarf_attr (die, DW_AT_bit_offset, &attr) == NULL
	  || dwarf_formudata (&attr, &u2) != 0
	  || i != (int) u2)
	puts ("************* DW_AT_bit_offset test failed ************");
      else if (! dwarf_hasform (&attr, DW_FORM_data1)
	       && ! dwarf_hasform (&attr, DW_FORM_data2)
	       && ! dwarf_hasform (&attr, DW_FORM_data4)
	       && ! dwarf_hasform (&attr, DW_FORM_data8)
	       && ! dwarf_hasform (&attr, DW_FORM_sdata)
	       && ! dwarf_hasform (&attr, DW_FORM_udata))
	puts ("************* DW_AT_bit_offset form failed ************");
      else if ((u = dwarf_whatform (&attr)) == 0
	       || (u != DW_FORM_data1
		   && u != DW_FORM_data2
		   && u != DW_FORM_data4
		   && u != DW_FORM_data8
		   && u != DW_FORM_sdata
		   && u != DW_FORM_udata))
	puts ("************* DW_AT_bit_offset form (2) failed ************");
      else if (dwarf_whatattr (&attr) != DW_AT_bit_offset)
	puts ("************* DW_AT_bit_offset attr failed ************");
    }

  if (dwarf_hasattr (die, DW_AT_language) && (i = dwarf_srclang (die)) != -1)
    {
      Dwarf_Attribute attr;
      Dwarf_Word u2;
      unsigned int u;
      printf ("%*s language  : %d\n", n * 5, "", i);
      if (dwarf_attr (die, DW_AT_language, &attr) == NULL
	  || dwarf_formudata (&attr, &u2) != 0
	  || i != (int) u2)
	puts ("************* DW_AT_language test failed ************");
      else if (! dwarf_hasform (&attr, DW_FORM_data1)
	       && ! dwarf_hasform (&attr, DW_FORM_data2)
	       && ! dwarf_hasform (&attr, DW_FORM_data4)
	       && ! dwarf_hasform (&attr, DW_FORM_data8)
	       && ! dwarf_hasform (&attr, DW_FORM_sdata)
	       && ! dwarf_hasform (&attr, DW_FORM_udata))
	puts ("************* DW_AT_language form failed ************");
      else if ((u = dwarf_whatform (&attr)) == 0
	       || (u != DW_FORM_data1
		   && u != DW_FORM_data2
		   && u != DW_FORM_data4
		   && u != DW_FORM_data8
		   && u != DW_FORM_sdata
		   && u != DW_FORM_udata))
	puts ("************* DW_AT_language form (2) failed ************");
      else if (dwarf_whatattr (&attr) != DW_AT_language)
	puts ("************* DW_AT_language attr failed ************");
    }

  if (dwarf_hasattr (die, DW_AT_ordering)
      && (i = dwarf_arrayorder (die)) != -1)
    {
      Dwarf_Attribute attr;
      Dwarf_Word u2;
      unsigned int u;
      printf ("%*s ordering  : %d\n", n * 5, "", i);
      if (dwarf_attr (die, DW_AT_ordering, &attr) == NULL
	  || dwarf_formudata (&attr, &u2) != 0
	  || i != (int) u2)
	puts ("************* DW_AT_ordering test failed ************");
      else if (! dwarf_hasform (&attr, DW_FORM_data1)
	       && ! dwarf_hasform (&attr, DW_FORM_data2)
	       && ! dwarf_hasform (&attr, DW_FORM_data4)
	       && ! dwarf_hasform (&attr, DW_FORM_data8)
	       && ! dwarf_hasform (&attr, DW_FORM_sdata)
	       && ! dwarf_hasform (&attr, DW_FORM_udata))
	puts ("************* DW_AT_ordering failed ************");
      else if ((u = dwarf_whatform (&attr)) == 0
	       || (u != DW_FORM_data1
		   && u != DW_FORM_data2
		   && u != DW_FORM_data4
		   && u != DW_FORM_data8
		   && u != DW_FORM_sdata
		   && u != DW_FORM_udata))
	puts ("************* DW_AT_ordering form (2) failed ************");
      else if (dwarf_whatattr (&attr) != DW_AT_ordering)
	puts ("************* DW_AT_ordering attr failed ************");
    }

  if (dwarf_hasattr (die, DW_AT_comp_dir))
    {
      Dwarf_Attribute attr;
      if (dwarf_attr (die, DW_AT_comp_dir, &attr) == NULL
	  || (name = dwarf_formstring (&attr)) == NULL)
	puts ("************* DW_AT_comp_dir attr failed ************");
      else
	printf ("%*s directory : %s\n", n * 5, "", name);
    }

  if (dwarf_hasattr (die, DW_AT_producer))
    {
      Dwarf_Attribute attr;
      if (dwarf_attr (die, DW_AT_producer, &attr) == NULL
	  || (name = dwarf_formstring (&attr)) == NULL)
	puts ("************* DW_AT_comp_dir attr failed ************");
      else
	printf ("%*s producer  : %s\n", n * 5, "", name);
    }

  if (dwarf_haschildren (die) != 0 && dwarf_child (die, &child) == 0)
    handle (dbg, &child, n + 1);
  if (dwarf_siblingof (die, die) == 0)
    handle (dbg, die, n);
}
Exemplo n.º 26
-1
Arquivo: rdwarf.c Projeto: kubo/rdwarf
static VALUE rd_attr_raw_value(VALUE self)
{
    rd_attr_t *attr = GetAttr(self);
    Dwarf_Half form;
    Dwarf_Error err;
    union {
        Dwarf_Addr addr;
        Dwarf_Off off;
        Dwarf_Unsigned udata;
        Dwarf_Signed sdata;
        Dwarf_Bool bool;
        char *str;
    } val;
    VALUE top;

    chkerr1(dwarf_whatform(attr->attr, &form, &err), &err, self);
    switch (form) {
    case DW_FORM_addr:
        chkerr1(dwarf_formaddr(attr->attr, &val.addr, &err), &err, self);
        return ULL2NUM(val.addr);
    case DW_FORM_ref1:
    case DW_FORM_ref2:
    case DW_FORM_ref4:
    case DW_FORM_ref8:
    case DW_FORM_ref_udata:
        chkerr1(dwarf_global_formref(attr->attr, &val.off, &err), &err, self);
        top = rb_ivar_get(self, id_at_top);
        return rdwarf_die_at(top, LL2NUM(val.off));
    case DW_FORM_data1:
    case DW_FORM_data2:
    case DW_FORM_data4:
    case DW_FORM_data8:
    case DW_FORM_udata:
        chkerr1(dwarf_formudata(attr->attr, &val.udata, &err), &err, self);
        return ULL2NUM(val.udata);
    case DW_FORM_sdata:
        chkerr1(dwarf_formsdata(attr->attr, &val.sdata, &err), &err, self);
        return LL2NUM(val.sdata);
    case DW_FORM_flag:
        chkerr1(dwarf_formflag(attr->attr, &val.bool, &err), &err, self);
        return val.bool ? Qtrue : Qfalse;
    case DW_FORM_strp:
    case DW_FORM_string:
        chkerr1(dwarf_formstring(attr->attr, &val.str, &err), &err, self);
        return rb_str_new_cstr(val.str);
    }
    return sym_unsupported_type;
}