int dwarf_end_macro_file(Dwarf_P_Debug dbg, Dwarf_Error * error) { size_t length_est; int res; int compose_error_type; if (dbg == NULL) { _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); return (DW_DLV_ERROR); } length_est = COMMAND_LEN; res = libdwarf_compose_begin(dbg, DW_MACINFO_end_file, length_est, &compose_error_type); if (res != DW_DLV_OK) { _dwarf_p_error(NULL, error, compose_error_type); return (DW_DLV_ERROR); } res = libdwarf_compose_complete(dbg, &compose_error_type); if (res != DW_DLV_OK) { _dwarf_p_error(NULL, error, compose_error_type); return (DW_DLV_ERROR); } res = libdwarf_compose_complete(dbg, &compose_error_type); if (res != DW_DLV_OK) { _dwarf_p_error(NULL, error, compose_error_type); return(DW_DLV_ERROR); } return DW_DLV_OK; }
/* FIXME: Add stats for debug_line_str. */ int dwarf_pro_get_string_stats(Dwarf_P_Debug dbg, Dwarf_Unsigned * str_count, Dwarf_Unsigned * str_total_length, Dwarf_Unsigned * strp_count_debug_str, Dwarf_Unsigned * strp_len_debug_str, Dwarf_Unsigned * strp_reused_count, Dwarf_Unsigned * strp_reused_len, Dwarf_Error * error) { struct Dwarf_P_Str_stats_s* ps = 0; if (!dbg) { _dwarf_p_error(dbg, error, DW_DLE_IA); return DW_DLV_ERROR; } if (dbg->de_version_magic_number !=PRO_VERSION_MAGIC ) { _dwarf_p_error(dbg, error, DW_DLE_VMM); return DW_DLV_ERROR; } *str_count = dbg->de_stats.ps_str_count; *str_total_length = dbg->de_stats.ps_str_total_length; ps = &dbg->de_stats.ps_strp; *strp_count_debug_str = ps->ps_strp_count_debug_str; *strp_len_debug_str = ps->ps_strp_len_debug_str; *strp_reused_count = ps->ps_strp_reused_count; *strp_reused_len = ps->ps_strp_reused_len; return DW_DLV_OK; }
int dwarf_fixup_AT_reference_die(Dwarf_P_Debug dbg, Dwarf_Half attrnum, Dwarf_P_Die sourcedie, Dwarf_P_Die targetdie, Dwarf_Error *error) { Dwarf_P_Attribute a = 0; Dwarf_P_Attribute cur = 0; if (dbg == NULL) { _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); return DW_DLV_ERROR; } for(cur = sourcedie->di_attrs; cur; cur = cur->ar_next) { if (attrnum == cur->ar_attribute) { a = cur; break; } } if(!a) { _dwarf_p_error(dbg, error, DW_DLE_AT_FIXUP_NULL); return DW_DLV_ERROR; } if(a->ar_ref_die) { _dwarf_p_error(dbg, error, DW_DLE_AT_FIXUP_DUP); return DW_DLV_ERROR; } a->ar_ref_die = targetdie; return DW_DLV_OK; }
Dwarf_P_Attribute dwarf_add_AT_with_ref_sig8(Dwarf_P_Die ownerdie, Dwarf_Half attrnum, const Dwarf_Sig8 *sig8_in, Dwarf_Error * error) { Dwarf_P_Attribute new_attr = 0; if (ownerdie == NULL) { _dwarf_p_error(NULL, error, DW_DLE_DIE_NULL); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } new_attr = (Dwarf_P_Attribute) _dwarf_p_get_alloc(ownerdie->di_dbg, sizeof(struct Dwarf_P_Attribute_s)); if (new_attr == NULL) { _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } new_attr->ar_attribute = attrnum; new_attr->ar_attribute_form = DW_FORM_ref_sig8; new_attr->ar_nbytes = sizeof (Dwarf_Sig8); new_attr->ar_next = 0; new_attr->ar_data = (char *) _dwarf_p_get_alloc(ownerdie->di_dbg, sizeof(Dwarf_Sig8)); if (new_attr->ar_data == NULL) { _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } memcpy(new_attr->ar_data,sig8_in,sizeof(Dwarf_Sig8)); new_attr->ar_rel_type = R_MIPS_NONE; new_attr->ar_reloc_len = 0; /* unused for R_MIPS_NONE */ _dwarf_pro_add_at_to_die(ownerdie, new_attr); return new_attr; }
int dwarf_force_debug_names(Dwarf_P_Debug dbg, Dwarf_Error * error) { Dwarf_P_Dnames dn; if (dbg == NULL) { _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); return DW_DLV_ERROR; } dn = (Dwarf_P_Dnames) _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Dnames_s)); if (dn == NULL) { _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); return DW_DLV_ERROR; } if (!dbg->de_dnames) { dbg->de_dnames = dn; } dn->dn_create_section = TRUE; return DW_DLV_OK; }
/* Make sure attribute types are checked before entering here. */ static Dwarf_P_Attribute local_add_AT_address(Dwarf_P_Debug dbg, Dwarf_P_Die ownerdie, Dwarf_Half attr, Dwarf_Signed form, Dwarf_Unsigned pc_value, Dwarf_Unsigned sym_index, Dwarf_Error * error) { Dwarf_P_Attribute new_attr; int upointer_size = 0; if (dbg == NULL) { _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } upointer_size = dbg->de_pointer_size; if (ownerdie == NULL) { _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } /* attribute types have already been checked */ /* switch (attr) { ... } */ new_attr = (Dwarf_P_Attribute) _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s)); if (new_attr == NULL) { _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } new_attr->ar_attribute = attr; new_attr->ar_attribute_form = form; new_attr->ar_nbytes = upointer_size; new_attr->ar_rel_symidx = sym_index; new_attr->ar_reloc_len = upointer_size; new_attr->ar_next = 0; if (sym_index != NO_ELF_SYM_INDEX) { new_attr->ar_rel_type = dbg->de_ptr_reloc; } else { new_attr->ar_rel_type = R_MIPS_NONE; } new_attr->ar_data = (char *) _dwarf_p_get_alloc(dbg, upointer_size); if (new_attr->ar_data == NULL) { _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } WRITE_UNALIGNED(dbg, new_attr->ar_data, (const void *) &pc_value, sizeof(pc_value), upointer_size); /* add attribute to the die */ _dwarf_pro_add_at_to_die(ownerdie, new_attr); return new_attr; }
/* This function adds values of attributes belonging to the string class. */ Dwarf_P_Attribute dwarf_add_AT_string(Dwarf_P_Debug dbg, Dwarf_P_Die ownerdie, Dwarf_Half attr, char *string, Dwarf_Error * error) { Dwarf_P_Attribute new_attr; if (dbg == NULL) { _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } if (ownerdie == NULL) { _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } new_attr = (Dwarf_P_Attribute) _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s)); if (new_attr == NULL) { _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } switch (attr) { case DW_AT_name: case DW_AT_comp_dir: case DW_AT_const_value: case DW_AT_producer: case DW_AT_MIPS_linkage_name: case DW_AT_MIPS_abstract_name: break; default:{ _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } } new_attr->ar_attribute = attr; new_attr->ar_attribute_form = DW_FORM_string; new_attr->ar_nbytes = strlen(string) + 1; new_attr->ar_next = 0; new_attr->ar_data = (char *) _dwarf_p_get_alloc(NULL, strlen(string) + 1); if (new_attr->ar_data == NULL) { _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } strcpy(new_attr->ar_data, string); new_attr->ar_rel_type = R_MIPS_NONE; new_attr->ar_reloc_len = 0; /* unused for R_MIPS_NONE */ /* add attribute to the die */ _dwarf_pro_add_at_to_die(ownerdie, new_attr); return new_attr; }
/* The following is the generic 'add a simple name entry' for any of the simple name sections. See enum dwarf_sn_kind in pro_opaque.h */ Dwarf_Unsigned _dwarf_add_simple_name_entry(Dwarf_P_Debug dbg, Dwarf_P_Die die, char *entry_name, enum dwarf_sn_kind entrykind, Dwarf_Error * error) { Dwarf_P_Simple_nameentry nameentry; Dwarf_P_Simple_name_header hdr; char *name; int uword_size; if (dbg == NULL) { _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); return (0); } if (die == NULL) { _dwarf_p_error(NULL, error, DW_DLE_DIE_NULL); return (0); } nameentry = (Dwarf_P_Simple_nameentry) _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Simple_nameentry_s)); if (nameentry == NULL) { _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); return (0); } name = _dwarf_p_get_alloc(dbg, strlen(entry_name) + 1); if (name == NULL) { _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); return (0); } strcpy(name, entry_name); nameentry->sne_die = die; nameentry->sne_name = name; nameentry->sne_name_len = strlen(name); uword_size = dbg->de_offset_size; hdr = &dbg->de_simple_name_headers[entrykind]; if (hdr->sn_head == NULL) hdr->sn_head = hdr->sn_tail = nameentry; else { hdr->sn_tail->sne_next = nameentry; hdr->sn_tail = nameentry; } hdr->sn_count++; hdr->sn_net_len += uword_size + nameentry->sne_name_len + 1; return (1); }
/* Similar to dwarf_add_fde_inst, except that the offset denoted by VAL2 is signed. */ Dwarf_P_Fde dwarf_add_fde_inst_with_signed_offset(Dwarf_P_Fde fde, Dwarf_Small op, Dwarf_Unsigned val1, Dwarf_Signed val2, Dwarf_Error * error) { Dwarf_P_Frame_Pgm curinst; int nbytes, nbytes1, nbytes2; char *ptr; int res; char buff1[ENCODE_SPACE_NEEDED]; char buff2[ENCODE_SPACE_NEEDED]; nbytes = 0; ptr = NULL; curinst = (Dwarf_P_Frame_Pgm) _dwarf_p_get_alloc(NULL, sizeof(struct Dwarf_P_Frame_Pgm_s)); if (curinst == NULL) { _dwarf_p_error(NULL, error, DW_DLE_FPGM_ALLOC); return ((Dwarf_P_Fde) DW_DLV_BADADDR); } if (op == DW_CFA_offset_extended_sf) { res = _dwarf_pro_encode_leb128_nm(val1, &nbytes1, buff1, sizeof(buff1)); if (res != DW_DLV_OK) { _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); return ((Dwarf_P_Fde) DW_DLV_BADADDR); } res = _dwarf_pro_encode_signed_leb128_nm(val2, &nbytes2, buff2, sizeof(buff2)); if (res != DW_DLV_OK) { _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); return ((Dwarf_P_Fde) DW_DLV_BADADDR); } ptr = (char *) _dwarf_p_get_alloc(NULL, nbytes1 + nbytes2); if (ptr == NULL) { _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); return ((Dwarf_P_Fde) DW_DLV_BADADDR); } memcpy(ptr, buff1, nbytes1); memcpy(ptr + nbytes1, buff2, nbytes2); nbytes = nbytes1 + nbytes2; } curinst->dfp_opcode = op; curinst->dfp_args = ptr; curinst->dfp_nbytes = nbytes; curinst->dfp_next = NULL; _dwarf_pro_add_to_fde(fde, curinst); return fde; }
Dwarf_Unsigned dwarf_add_expr_addr_b ( Dwarf_P_Expr expr, Dwarf_Unsigned addr, Dwarf_Unsigned sym_index, Dwarf_Error *error ) { Dwarf_P_Debug dbg; Dwarf_Small *next_byte_ptr; Dwarf_Unsigned next_byte_offset; int upointer_size; if (expr == NULL) { _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL); return(DW_DLV_NOCOUNT); } dbg = expr->ex_dbg; if (dbg == NULL) { _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); return(DW_DLV_NOCOUNT); } upointer_size = dbg->de_pointer_size; next_byte_offset = expr->ex_next_byte_offset + upointer_size + 1; if (next_byte_offset > MAXIMUM_LOC_EXPR_LENGTH) { _dwarf_p_error(dbg, error, DW_DLE_EXPR_LENGTH_BAD); return(DW_DLV_NOCOUNT); } next_byte_ptr = &(expr->ex_byte_stream[0]) + expr->ex_next_byte_offset; *next_byte_ptr = DW_OP_addr; next_byte_ptr++; WRITE_UNALIGNED (dbg,next_byte_ptr,(const void *)&addr, sizeof(addr),upointer_size); if (expr->ex_reloc_offset != 0) { _dwarf_p_error(dbg, error, DW_DLE_MULTIPLE_RELOC_IN_EXPR); return(DW_DLV_NOCOUNT); } expr->ex_reloc_sym_index = sym_index; expr->ex_reloc_offset = expr->ex_next_byte_offset + 1; expr->ex_next_byte_offset = next_byte_offset; return(next_byte_offset); }
Dwarf_P_Attribute dwarf_add_AT_any_value_uleb(Dwarf_P_Die ownerdie, Dwarf_Half attrnum, Dwarf_Unsigned unsigned_value, Dwarf_Error * error) { Dwarf_P_Attribute new_attr; int leb_size; char encode_buffer[ENCODE_SPACE_NEEDED]; int res; if (ownerdie == NULL) { _dwarf_p_error(NULL, error, DW_DLE_DIE_NULL); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } new_attr = (Dwarf_P_Attribute) _dwarf_p_get_alloc(ownerdie->di_dbg, sizeof(struct Dwarf_P_Attribute_s)); if (new_attr == NULL) { _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } new_attr->ar_attribute = attrnum; new_attr->ar_attribute_form = DW_FORM_udata; new_attr->ar_rel_type = R_MIPS_NONE; new_attr->ar_reloc_len = 0; /* unused for R_MIPS_NONE */ new_attr->ar_next = 0; res = _dwarf_pro_encode_leb128_nm(unsigned_value, &leb_size, encode_buffer, sizeof(encode_buffer)); if (res != DW_DLV_OK) { _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } new_attr->ar_data = (char *) _dwarf_p_get_alloc(ownerdie->di_dbg, leb_size); if (new_attr->ar_data == NULL) { _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } memcpy(new_attr->ar_data, encode_buffer, leb_size); new_attr->ar_nbytes = leb_size; /* add attribute to the die */ _dwarf_pro_add_at_to_die(ownerdie, new_attr); return new_attr; }
Dwarf_Unsigned dwarf_expr_current_offset(Dwarf_P_Expr expr, Dwarf_Error * error) { if (expr == NULL) { _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL); return (DW_DLV_NOCOUNT); } if (expr->ex_dbg == NULL) { _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); return (DW_DLV_NOCOUNT); } return (expr->ex_next_byte_offset); }
Dwarf_P_Attribute dwarf_add_AT_ref_address(Dwarf_P_Debug dbg, Dwarf_P_Die ownerdie, Dwarf_Half attr, Dwarf_Unsigned pc_value, Dwarf_Unsigned sym_index, Dwarf_Error * error) { switch (attr) { case DW_AT_type: case DW_AT_import: break; default: if (attr < DW_AT_lo_user || attr > DW_AT_hi_user ) { _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } break; } /* FIXME: For DWARF3 and later this call is problematic as DW_FORM_ref_addr is really an offset in .debug_info , not an address. */ return local_add_AT_address(dbg, ownerdie, attr, DW_FORM_ref_addr, pc_value, sym_index, error); }
/* Add a cfe_offset instruction to the fde passed in. */ Dwarf_P_Fde dwarf_fde_cfa_offset(Dwarf_P_Fde fde, Dwarf_Unsigned reg, Dwarf_Signed offset, Dwarf_Error * error) { Dwarf_Ubyte opc, regno; char *ptr = 0; Dwarf_P_Frame_Pgm curinst; int nbytes = 0; int res = 0; char buff1[ENCODE_SPACE_NEEDED]; Dwarf_P_Debug dbg = fde->fde_dbg; curinst = (Dwarf_P_Frame_Pgm) _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Frame_Pgm_s)); if (curinst == NULL) { DWARF_P_DBG_ERROR(dbg, DW_DLE_FPGM_ALLOC, (Dwarf_P_Fde) DW_DLV_BADADDR); } opc = DW_CFA_offset; regno = reg; if (regno & 0xc0) { DWARF_P_DBG_ERROR(dbg, DW_DLE_REGNO_OVFL, (Dwarf_P_Fde) DW_DLV_BADADDR); } opc = opc | regno; /* lower 6 bits are register number */ curinst->dfp_opcode = opc; res = _dwarf_pro_encode_leb128_nm(offset, &nbytes, buff1, sizeof(buff1)); if (res != DW_DLV_OK) { _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); return ((Dwarf_P_Fde) DW_DLV_BADADDR); } ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes); if (ptr == NULL) { _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); return ((Dwarf_P_Fde) DW_DLV_BADADDR); } memcpy(ptr, buff1, nbytes); curinst->dfp_args = ptr; curinst->dfp_nbytes = nbytes; curinst->dfp_next = NULL; _dwarf_pro_add_to_fde(fde, curinst); return fde; }
void dwarf_expr_reset(Dwarf_P_Expr expr, Dwarf_Error * error) { if (expr == NULL) { _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL); return; } expr->ex_next_byte_offset=0; }
/* This function adds attributes of the flag class. */ Dwarf_P_Attribute dwarf_add_AT_flag(Dwarf_P_Debug dbg, Dwarf_P_Die ownerdie, Dwarf_Half attr, Dwarf_Small flag, Dwarf_Error * error) { Dwarf_P_Attribute new_attr = 0; if (dbg == NULL) { _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } if (ownerdie == NULL) { _dwarf_p_error(dbg, error, DW_DLE_DIE_NULL); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } new_attr = (Dwarf_P_Attribute) _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s)); if (new_attr == NULL) { _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } new_attr->ar_attribute = attr; new_attr->ar_attribute_form = DW_FORM_flag; new_attr->ar_nbytes = 1; new_attr->ar_reloc_len = 0; /* not used */ new_attr->ar_rel_type = R_MIPS_NONE; new_attr->ar_next = 0; new_attr->ar_data = (char *) _dwarf_p_get_alloc(dbg, 1); if (new_attr->ar_data == NULL) { _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } memcpy(new_attr->ar_data, &flag, 1); /* Add attribute to the die */ _dwarf_pro_add_at_to_die(ownerdie, new_attr); return new_attr; }
int _dwarf_pro_transform_macro_info_to_disk(Dwarf_P_Debug dbg, Dwarf_Error * error) { /* Total num of bytes in .debug_macinfo section. */ Dwarf_Unsigned mac_num_bytes; /* Points to first byte of .debug_macinfo buffer. */ Dwarf_Small *macinfo; /* Fills in the .debug_macinfo buffer. */ Dwarf_Small *macinfo_ptr; /* Used to scan the section data buffers. */ struct dw_macinfo_block_s *m_prev; struct dw_macinfo_block_s *m_sect; /* Get the size of the debug_macinfo data */ mac_num_bytes = 0; for (m_sect = dbg->de_first_macinfo; m_sect != NULL; m_sect = m_sect->mb_next) { mac_num_bytes += m_sect->mb_used_len; } /* Tthe final entry has a type code of 0 to indicate It is final for this CU Takes just 1 byte. */ mac_num_bytes += 1; GET_CHUNK(dbg, dbg->de_elf_sects[DEBUG_MACINFO], macinfo, (unsigned long) mac_num_bytes, error); if (macinfo == NULL) { _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); return (0); } macinfo_ptr = macinfo; m_prev = 0; for (m_sect = dbg->de_first_macinfo; m_sect != NULL; m_sect = m_sect->mb_next) { memcpy(macinfo_ptr, m_sect->mb_data, m_sect->mb_used_len); macinfo_ptr += m_sect->mb_used_len; if (m_prev) { _dwarf_p_dealloc(dbg, (Dwarf_Small *) m_prev); m_prev = 0; } m_prev = m_sect; } *macinfo_ptr = 0; /* the type code of 0 as last entry */ if (m_prev) { _dwarf_p_dealloc(dbg, (Dwarf_Small *) m_prev); m_prev = 0; } return (int) dbg->de_n_debug_sect; }
Dwarf_Addr dwarf_expr_into_block ( Dwarf_P_Expr expr, Dwarf_Unsigned *length, Dwarf_Error *error ) { if (expr == NULL) { _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL); return(DW_DLV_BADADDR); } if (expr->ex_dbg == NULL) { _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); return(DW_DLV_BADADDR); } if (length != NULL) *length = expr->ex_next_byte_offset; return((Dwarf_Addr)&(expr->ex_byte_stream[0])); }
/* This function creates a new expression struct that can be used to build up a location expression. */ Dwarf_P_Expr dwarf_new_expr(Dwarf_P_Debug dbg, Dwarf_Error * error) { Dwarf_P_Expr ret_expr; if (dbg == NULL) { _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); return (NULL); } ret_expr = (Dwarf_P_Expr) _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Expr_s)); if (ret_expr == NULL) { _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); return (NULL); } ret_expr->ex_dbg = dbg; return (ret_expr); }
/* Write line number first, then file index. */ int dwarf_start_macro_file(Dwarf_P_Debug dbg, Dwarf_Unsigned fileindex, Dwarf_Unsigned linenumber, Dwarf_Error * error) { size_t length_est; int res; int compose_error_type; if (dbg == NULL) { _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); return (DW_DLV_ERROR); } length_est = COMMAND_LEN + LINE_LEN + LINE_LEN; res = libdwarf_compose_begin(dbg, DW_MACINFO_start_file, length_est, &compose_error_type); if (res != DW_DLV_OK) { _dwarf_p_error(NULL, error, compose_error_type); return (DW_DLV_ERROR); } res = libdwarf_compose_add_line(dbg, linenumber, &compose_error_type); if (res != DW_DLV_OK) { _dwarf_p_error(NULL, error, compose_error_type); return (DW_DLV_ERROR); } res = libdwarf_compose_add_line(dbg, fileindex, &compose_error_type); if (res != DW_DLV_OK) { _dwarf_p_error(NULL, error, compose_error_type); return (DW_DLV_ERROR); } res = libdwarf_compose_complete(dbg, &compose_error_type); if (res != DW_DLV_OK) { _dwarf_p_error(NULL, error, compose_error_type); return (DW_DLV_ERROR); } return DW_DLV_OK; }
Dwarf_Addr dwarf_expr_into_block(Dwarf_P_Expr expr, Dwarf_Unsigned * length, Dwarf_Error * error) { if (expr == NULL) { _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL); return (DW_DLV_BADADDR); } if (expr->ex_dbg == NULL) { _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); return (DW_DLV_BADADDR); } if (length != NULL) *length = expr->ex_next_byte_offset; /* The following cast from pointer to integer is ok as long as Dwarf_Addr is at least as large as a pointer. Which is a requirement of libdwarf so must be satisfied (some compilers emit a warning about the following line). */ return ((Dwarf_Addr) (unsigned long) & (expr->ex_byte_stream[0])); }
/* This function adds another address range to the list of address ranges for the given Dwarf_P_Debug. It returns 0 on error, and 1 otherwise. */ Dwarf_Unsigned dwarf_add_arange_b(Dwarf_P_Debug dbg, Dwarf_Addr begin_address, Dwarf_Unsigned length, Dwarf_Unsigned symbol_index, Dwarf_Unsigned end_symbol_index, Dwarf_Addr offset_from_end_sym, Dwarf_Error * error) { Dwarf_P_Arange arange; if (dbg == NULL) { _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); return (0); } arange = (Dwarf_P_Arange) _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Arange_s)); if (arange == NULL) { _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); return (0); } arange->ag_begin_address = begin_address; arange->ag_length = length; arange->ag_symbol_index = symbol_index; arange->ag_end_symbol_index = end_symbol_index; arange->ag_end_symbol_offset = offset_from_end_sym; if (dbg->de_arange == NULL) dbg->de_arange = dbg->de_last_arange = arange; else { dbg->de_last_arange->ag_next = arange; dbg->de_last_arange = arange; } dbg->de_arange_count++; return (1); }
Dwarf_P_Attribute dwarf_add_AT_producer(Dwarf_P_Die ownerdie, char *producer_string, Dwarf_Error * error) { Dwarf_P_Attribute new_attr; if (ownerdie == NULL) { _dwarf_p_error(NULL, error, DW_DLE_DIE_NULL); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } new_attr = (Dwarf_P_Attribute) _dwarf_p_get_alloc(NULL, sizeof(struct Dwarf_P_Attribute_s)); if (new_attr == NULL) { _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } new_attr->ar_attribute = DW_AT_producer; new_attr->ar_attribute_form = DW_FORM_string; new_attr->ar_nbytes = strlen(producer_string) + 1; new_attr->ar_next = 0; new_attr->ar_data = (char *) _dwarf_p_get_alloc(NULL, strlen(producer_string) + 1); if (new_attr->ar_data == NULL) { _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } strcpy(new_attr->ar_data, producer_string); new_attr->ar_rel_type = R_MIPS_NONE; new_attr->ar_reloc_len = 0; /* unused for R_MIPS_NONE */ /* add attribute to the die */ _dwarf_pro_add_at_to_die(ownerdie, new_attr); return new_attr; }
int dwarf_undef_macro(Dwarf_P_Debug dbg, Dwarf_Unsigned line, char *macname, Dwarf_Error * error) { size_t len; size_t length_est; int res; int compose_error_type; if (dbg == NULL) { _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); return (DW_DLV_ERROR); } if (macname == 0) { _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_NULL); return (DW_DLV_ERROR); } #ifdef TARG_IA64 len = strlen(macname) + 1; #else len = strlen(macname); #endif if (len == 0) { _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_EMPTY); return (DW_DLV_ERROR); } #ifdef TARG_IA64 length_est = COMMAND_LEN + LINE_LEN + len; #else length_est = COMMAND_LEN + LINE_LEN + len + 1; #endif res = libdwarf_compose_begin(dbg, DW_MACINFO_undef, length_est, &compose_error_type); if (res != DW_DLV_OK) { _dwarf_p_error(NULL, error, compose_error_type); return (DW_DLV_ERROR); } res = libdwarf_compose_add_line(dbg, line, &compose_error_type); if (res != DW_DLV_OK) { _dwarf_p_error(NULL, error, compose_error_type); return (DW_DLV_ERROR); } libdwarf_compose_add_string(dbg, macname, len); res = libdwarf_compose_complete(dbg, &compose_error_type); if (res != DW_DLV_OK) { _dwarf_p_error(NULL, error, compose_error_type); return (DW_DLV_ERROR); } return DW_DLV_OK; }
/* New interface, replacing dwarf_add_AT_targ_address. Essentially just makes sym_index a Dwarf_Unsigned so for symbolic relocations it can be a full address. */ Dwarf_P_Attribute dwarf_add_AT_targ_address_b(Dwarf_P_Debug dbg, Dwarf_P_Die ownerdie, Dwarf_Half attr, Dwarf_Unsigned pc_value, Dwarf_Unsigned sym_index, Dwarf_Error * error) { switch (attr) { case DW_AT_low_pc: case DW_AT_high_pc: /* added to support location lists */ /* no way to check that this is a loclist-style address though */ case DW_AT_location: case DW_AT_string_length: case DW_AT_return_addr: case DW_AT_frame_base: case DW_AT_segment: case DW_AT_static_link: case DW_AT_use_location: case DW_AT_vtable_elem_location: case DW_AT_const_value: /* Gcc can generate this as address. */ case DW_AT_entry_pc: break; default: if (attr < DW_AT_lo_user || attr > DW_AT_hi_user ) { _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } break; } return local_add_AT_address(dbg, ownerdie, attr, DW_FORM_addr, pc_value, sym_index, error); }
int _dwarf_transform_arange_to_disk(Dwarf_P_Debug dbg, Dwarf_Signed *nbufs, Dwarf_Error * error) { /* Total num of bytes in .debug_aranges section. */ Dwarf_Unsigned arange_num_bytes = 0; /* Adjustment to align the start of the actual address ranges on a boundary aligned with twice the address size. */ Dwarf_Small remainder = 0; /* Total number of bytes excluding the length field. */ Dwarf_Unsigned adjusted_length = 0; /* Points to first byte of .debug_aranges buffer. */ Dwarf_Small *arange = 0; /* Fills in the .debug_aranges buffer. */ Dwarf_Small *arange_ptr = 0; /* Scans the list of address ranges provided by user. */ Dwarf_P_Arange given_arange = 0; /* Used to fill in 0. */ const Dwarf_Signed big_zero = 0; int extension_word_size = dbg->de_64bit_extension ? 4 : 0; int offset_size = dbg->de_offset_size; int upointer_size = dbg->de_pointer_size; /* All dwarf versions so far use 2 here. */ Dwarf_Half version = 2; int res = 0; /* ***** BEGIN CODE ***** */ /* Size of the .debug_aranges section header. */ arange_num_bytes = extension_word_size + offset_size + /* Size of length field. */ DWARF_HALF_SIZE + /* Size of version field. */ offset_size + /* Size of .debug_info offset. */ sizeof(Dwarf_Small) + /* Size of address size field. */ sizeof(Dwarf_Small); /* Size of segment size field. */ /* Adjust the size so that the set of aranges begins on a boundary that aligned with twice the address size. This is a Libdwarf requirement. */ remainder = arange_num_bytes % (2 * upointer_size); if (remainder != 0) arange_num_bytes += (2 * upointer_size) - remainder; /* Add the bytes for the actual address ranges. */ arange_num_bytes += upointer_size * 2 * (dbg->de_arange_count + 1); GET_CHUNK(dbg, dbg->de_elf_sects[DEBUG_ARANGES], arange, (unsigned long) arange_num_bytes, error); arange_ptr = arange; if (extension_word_size) { Dwarf_Word x = DISTINGUISHED_VALUE; WRITE_UNALIGNED(dbg, (void *) arange_ptr, (const void *) &x, sizeof(x), extension_word_size); arange_ptr += extension_word_size; } /* Write the total length of .debug_aranges section. */ adjusted_length = arange_num_bytes - offset_size - extension_word_size; { Dwarf_Unsigned du = adjusted_length; WRITE_UNALIGNED(dbg, (void *) arange_ptr, (const void *) &du, sizeof(du), offset_size); arange_ptr += offset_size; } /* Write the version as 2 bytes. */ { Dwarf_Half verstamp = version; WRITE_UNALIGNED(dbg, (void *) arange_ptr, (const void *) &verstamp, sizeof(verstamp), DWARF_HALF_SIZE); arange_ptr += DWARF_HALF_SIZE; } /* Write the .debug_info offset. This is always 0. */ WRITE_UNALIGNED(dbg, (void *) arange_ptr, (const void *) &big_zero, sizeof(big_zero), offset_size); arange_ptr += offset_size; { unsigned long count = dbg->de_arange_count + 1; int res2 = 0; Dwarf_P_Per_Reloc_Sect p_reloc = &dbg->de_reloc_sect[DEBUG_ARANGES]; if (dbg->de_relocate_pair_by_symbol) { count = (3 * dbg->de_arange_count) + 1; } /* The following is a small optimization: not needed for correctness. Does nothing if preloc->pr_first_block is non-null */ res2 = _dwarf_pro_pre_alloc_specific_reloc_slots(dbg, p_reloc, count); if (res2 != DW_DLV_OK) { _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); return DW_DLV_ERROR; } } /* reloc for .debug_info */ res = dbg->de_relocate_by_name_symbol(dbg, DEBUG_ARANGES, extension_word_size + offset_size + DWARF_HALF_SIZE, dbg->de_sect_name_idx[DEBUG_INFO], dwarf_drt_data_reloc, offset_size); /* Write the size of addresses. */ *arange_ptr = dbg->de_pointer_size; arange_ptr++; /* Write the size of segment addresses. This is zero for MIPS architectures. */ *arange_ptr = 0; arange_ptr++; /* Skip over the padding to align the start of the actual address ranges to twice the address size. */ if (remainder != 0) arange_ptr += (2 * upointer_size) - remainder; /* The arange address, length are pointer-size fields of the target machine. */ for (given_arange = dbg->de_arange; given_arange != NULL; given_arange = given_arange->ag_next) { /* Write relocation record for beginning of address range. */ res = dbg->de_relocate_by_name_symbol(dbg, DEBUG_ARANGES, arange_ptr - arange, /* r_offset */ (long) given_arange->ag_symbol_index, dwarf_drt_data_reloc, upointer_size); if (res != DW_DLV_OK) { _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); return DW_DLV_ERROR; } /* Copy beginning address of range. */ WRITE_UNALIGNED(dbg, (void *) arange_ptr, (const void *) &given_arange->ag_begin_address, sizeof(given_arange->ag_begin_address), upointer_size); arange_ptr += upointer_size; if (dbg->de_relocate_pair_by_symbol && given_arange->ag_end_symbol_index != 0 && given_arange->ag_length == 0) { /* symbolic reloc, need reloc for length What if we really know the length? If so, should use the other part of 'if'. */ Dwarf_Unsigned val; res = dbg->de_relocate_pair_by_symbol(dbg, DEBUG_ARANGES, arange_ptr - arange, /* r_offset */ given_arange->ag_symbol_index, given_arange->ag_end_symbol_index, dwarf_drt_first_of_length_pair, upointer_size); if (res != DW_DLV_OK) { _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); return DW_DLV_ERROR; } /* arange pre-calc so assem text can do .word end - begin + val (gets val from stream) */ val = given_arange->ag_end_symbol_offset - given_arange->ag_begin_address; WRITE_UNALIGNED(dbg, (void *) arange_ptr, (const void *) &val, sizeof(val), upointer_size); arange_ptr += upointer_size; } else { /* plain old length to copy, no relocation at all */ WRITE_UNALIGNED(dbg, (void *) arange_ptr, (const void *) &given_arange->ag_length, sizeof(given_arange->ag_length), upointer_size); arange_ptr += upointer_size; } } WRITE_UNALIGNED(dbg, (void *) arange_ptr, (const void *) &big_zero, sizeof(big_zero), upointer_size); arange_ptr += upointer_size; WRITE_UNALIGNED(dbg, (void *) arange_ptr, (const void *) &big_zero, sizeof(big_zero), upointer_size); *nbufs = dbg->de_n_debug_sect; return DW_DLV_OK; }
/* Generic routine to add opcode to fde instructions. val1 and val2 are parameters whose interpretation depends on the 'op'. This does not work properly for DW_DLC_SYMBOLIC_RELOCATIONS for DW_CFA_set_loc or DW_DVA_advance_loc* 'op', as these ops normally are addresses or (DW_CFA_set_loc) or code lengths (DW_DVA_advance_loc*) and such must be represented with relocations and symbol indices for DW_DLC_SYMBOLIC_RELOCATIONS. */ Dwarf_P_Fde dwarf_add_fde_inst(Dwarf_P_Fde fde, Dwarf_Small op, Dwarf_Unsigned val1, Dwarf_Unsigned val2, Dwarf_Error * error) { Dwarf_P_Frame_Pgm curinst; int nbytes, nbytes1, nbytes2; Dwarf_Ubyte db; Dwarf_Half dh; Dwarf_Word dw; Dwarf_Unsigned du; char *ptr; int res; char buff1[ENCODE_SPACE_NEEDED]; char buff2[ENCODE_SPACE_NEEDED]; nbytes = 0; ptr = NULL; curinst = (Dwarf_P_Frame_Pgm) _dwarf_p_get_alloc(NULL, sizeof(struct Dwarf_P_Frame_Pgm_s)); if (curinst == NULL) { _dwarf_p_error(NULL, error, DW_DLE_FPGM_ALLOC); return ((Dwarf_P_Fde) DW_DLV_BADADDR); } switch (op) { #ifdef TARG_X8664 case DW_CFA_advance_loc4: // We will use 2 half-words to copy the labels; cg will later // fix the relocatable symbols. dh = val1; ptr = (char *) _dwarf_p_get_alloc(NULL, 4); if (ptr == NULL) { _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); return((Dwarf_P_Fde)DW_DLV_BADADDR); } memcpy((void *)ptr, (const void *)&dh,2); dh = val2; memcpy((void *)ptr+2, (const void *)&dh,2); nbytes = 4; break; #endif // TARG_X8664 case DW_CFA_advance_loc: if (val1 <= 0x3f) { db = val1; op |= db; } /* test not portable FIX */ else if (val1 <= UCHAR_MAX) { op = DW_CFA_advance_loc1; db = val1; ptr = (char *) _dwarf_p_get_alloc(NULL, 1); if (ptr == NULL) { _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); return ((Dwarf_P_Fde) DW_DLV_BADADDR); } memcpy((void *) ptr, (const void *) &db, 1); nbytes = 1; } /* test not portable FIX */ else if (val1 <= USHRT_MAX) { op = DW_CFA_advance_loc2; dh = val1; ptr = (char *) _dwarf_p_get_alloc(NULL, 2); if (ptr == NULL) { _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); return ((Dwarf_P_Fde) DW_DLV_BADADDR); } memcpy((void *) ptr, (const void *) &dh, 2); nbytes = 2; } /* test not portable FIX */ else if (val1 <= ULONG_MAX) { op = DW_CFA_advance_loc4; dw = (Dwarf_Word) val1; ptr = (char *) _dwarf_p_get_alloc(NULL, 4); if (ptr == NULL) { _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); return ((Dwarf_P_Fde) DW_DLV_BADADDR); } memcpy((void *) ptr, (const void *) &dw, 4); nbytes = 4; } else { op = DW_CFA_MIPS_advance_loc8; du = val1; ptr = (char *) _dwarf_p_get_alloc(NULL, sizeof(Dwarf_Unsigned)); if (ptr == NULL) { _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); return ((Dwarf_P_Fde) DW_DLV_BADADDR); } memcpy((void *) ptr, (const void *) &du, 8); nbytes = 8; } break; case DW_CFA_offset: if (val1 <= MAX_6_BIT_VALUE) { db = val1; op |= db; res = _dwarf_pro_encode_leb128_nm(val2, &nbytes, buff1, sizeof(buff1)); if (res != DW_DLV_OK) { _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); return ((Dwarf_P_Fde) DW_DLV_BADADDR); } ptr = (char *) _dwarf_p_get_alloc(NULL, nbytes); if (ptr == NULL) { _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); return ((Dwarf_P_Fde) DW_DLV_BADADDR); } memcpy(ptr, buff1, nbytes); } else { op = DW_CFA_offset_extended; res = _dwarf_pro_encode_leb128_nm(val1, &nbytes1, buff1, sizeof(buff1)); if (res != DW_DLV_OK) { _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); return ((Dwarf_P_Fde) DW_DLV_BADADDR); } res = _dwarf_pro_encode_leb128_nm(val2, &nbytes2, buff2, sizeof(buff2)); if (res != DW_DLV_OK) { _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); return ((Dwarf_P_Fde) DW_DLV_BADADDR); } ptr = (char *) _dwarf_p_get_alloc(NULL, nbytes1 + nbytes2); if (ptr == NULL) { _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); return ((Dwarf_P_Fde) DW_DLV_BADADDR); } memcpy(ptr, buff1, nbytes1); memcpy(ptr + nbytes1, buff2, nbytes2); nbytes = nbytes1 + nbytes2; } break; case DW_CFA_undefined: case DW_CFA_same_value: res = _dwarf_pro_encode_leb128_nm(val1, &nbytes, buff1, sizeof(buff1)); if (res != DW_DLV_OK) { _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); return ((Dwarf_P_Fde) DW_DLV_BADADDR); } ptr = (char *) _dwarf_p_get_alloc(NULL, nbytes); if (ptr == NULL) { _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); return ((Dwarf_P_Fde) DW_DLV_BADADDR); } memcpy(ptr, buff1, nbytes); break; case DW_CFA_register: case DW_CFA_def_cfa: res = _dwarf_pro_encode_leb128_nm(val1, &nbytes1, buff1, sizeof(buff1)); if (res != DW_DLV_OK) { _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); return ((Dwarf_P_Fde) DW_DLV_BADADDR); } res = _dwarf_pro_encode_leb128_nm(val2, &nbytes2, buff2, sizeof(buff2)); if (res != DW_DLV_OK) { _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); return ((Dwarf_P_Fde) DW_DLV_BADADDR); } ptr = (char *) _dwarf_p_get_alloc(NULL, nbytes1 + nbytes2); if (ptr == NULL) { _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); return ((Dwarf_P_Fde) DW_DLV_BADADDR); } memcpy(ptr, buff1, nbytes1); memcpy(ptr + nbytes1, buff2, nbytes2); nbytes = nbytes1 + nbytes2; break; case DW_CFA_def_cfa_register: case DW_CFA_def_cfa_offset: res = _dwarf_pro_encode_leb128_nm(val1, &nbytes, buff1, sizeof(buff1)); if (res != DW_DLV_OK) { _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); return ((Dwarf_P_Fde) DW_DLV_BADADDR); } ptr = (char *) _dwarf_p_get_alloc(NULL, nbytes); if (ptr == NULL) { _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC); return ((Dwarf_P_Fde) DW_DLV_BADADDR); } memcpy(ptr, buff1, nbytes); break; default: break; } curinst->dfp_opcode = op; curinst->dfp_args = ptr; curinst->dfp_nbytes = nbytes; curinst->dfp_next = NULL; _dwarf_pro_add_to_fde(fde, curinst); return fde; }
/* Ensure each stream is a single buffer and add that single buffer to the set of stream buffers. By creating a new buffer and copying if necessary. Free the input set of buffers if we consolidate. Return -1 on error (malloc failure) Return DW_DLV_OK on success. Any other return indicates malloc failed. */ int _dwarf_stream_relocs_to_disk(Dwarf_P_Debug dbg, Dwarf_Signed * new_sec_count) { unsigned long total_size = 0; Dwarf_Small *data = 0; int sec_index = 0; unsigned long i = 0; Dwarf_Error err = 0; Dwarf_Error *error = &err; Dwarf_Signed sec_count = 0; Dwarf_P_Per_Reloc_Sect p_reloc = &dbg->de_reloc_sect[0]; for (i = 0; i < NUM_DEBUG_SECTIONS; ++i, ++p_reloc) { unsigned long ct = p_reloc->pr_reloc_total_count; unsigned len = 0; struct Dwarf_P_Relocation_Block_s *p_blk = 0; struct Dwarf_P_Relocation_Block_s *p_blk_last = 0; Dwarf_P_Per_Reloc_Sect prb = 0; if (ct == 0) { continue; } prb = &dbg->de_reloc_sect[i]; len = dbg->de_relocation_record_size; ++sec_count; total_size = ct * len; sec_index = prb->pr_sect_num_of_reloc_sect; if (sec_index == 0) { /* call de_func or de_func_b, getting section number of reloc sec */ int rel_section_index = 0; Dwarf_Unsigned name_idx = 0; int int_name = 0; int err = 0; if (dbg->de_func_b) { rel_section_index = dbg->de_func_b(_dwarf_rel_section_names[i], /* size */ dbg->de_relocation_record_size, /* type */ SHT_REL, /* flags */ 0, /* link to symtab, which we cannot know */ 0, /* info == link to sec rels apply to */ dbg->de_elf_sects[i], &name_idx, &err); } else { rel_section_index = dbg->de_func(_dwarf_rel_section_names[i], /* size */ dbg->de_relocation_record_size, /* type */ SHT_REL, /* flags */ 0, /* link to symtab, which we cannot know */ 0, /* info == link to sec rels apply to */ dbg->de_elf_sects[i], &int_name, &err); name_idx = int_name; } if (rel_section_index == -1) { { _dwarf_p_error(dbg, error, DW_DLE_ELF_SECT_ERR); return (DW_DLV_ERROR); } } prb->pr_sect_num_of_reloc_sect = rel_section_index; sec_index = rel_section_index; } GET_CHUNK(dbg, sec_index, data, total_size, &err); p_blk = p_reloc->pr_first_block; /* following loop executes at least once. Effects the consolidation to a single block or, if already a single block, simply copies to the output buffer. And frees the input block. The new block is in the de_debug_sects list. */ while (p_blk) { unsigned long len = p_blk->rb_where_to_add_next - p_blk->rb_data; memcpy(data, p_blk->rb_data, len); data += len; p_blk_last = p_blk; p_blk = p_blk->rb_next; _dwarf_p_dealloc(dbg, (Dwarf_Small *) p_blk_last); } /* ASSERT: sum of len copied == total_size */ /* We have copied the input, now drop the pointers to it. For debugging, leave the other data untouched. */ p_reloc->pr_first_block = 0; p_reloc->pr_last_block = 0; } *new_sec_count = sec_count; return DW_DLV_OK; }
int dwarf_def_macro(Dwarf_P_Debug dbg, Dwarf_Unsigned line, char *macname, char *macvalue, Dwarf_Error * error) { size_t len; size_t len2; size_t length_est; int res; int compose_error_type; if (dbg == NULL) { _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); return (DW_DLV_ERROR); } if (macname == 0) { _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_NULL); return (DW_DLV_ERROR); } #ifdef TARG_IA64 len = strlen(macname) + 1; #else len = strlen(macname); #endif if (len == 0) { _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_EMPTY); return (DW_DLV_ERROR); } #ifdef TARG_IA64 if (macvalue) { len2 = strlen(macvalue) + 1; } else { len2 = 0; } length_est = COMMAND_LEN + LINE_LEN + len + len2 + 1; /* 1 */ #else len2 = macvalue ? strlen(macvalue) : 0; length_est = COMMAND_LEN + LINE_LEN + len + len2 + 1; if (len2 > 0) length_est += 1; /* add one for space */ #endif res = libdwarf_compose_begin(dbg, DW_MACINFO_define, length_est, &compose_error_type); if (res != DW_DLV_OK) { _dwarf_p_error(NULL, error, compose_error_type); return (DW_DLV_ERROR); } res = libdwarf_compose_add_line(dbg, line, &compose_error_type); if (res != DW_DLV_OK) { _dwarf_p_error(NULL, error, compose_error_type); return (DW_DLV_ERROR); } #ifdef TARG_IA64 libdwarf_compose_add_string(dbg, macname, len); libdwarf_compose_add_string(dbg, " ", 1); if (macvalue) { libdwarf_compose_add_string(dbg, " ", 1); libdwarf_compose_add_string(dbg, macvalue, len2); } #else if (macvalue) { libdwarf_compose_add_bytes(dbg, macname, len); libdwarf_compose_add_bytes(dbg, " ", 1); libdwarf_compose_add_string(dbg, macvalue, len2); } else { libdwarf_compose_add_string(dbg, macname, len); } #endif res = libdwarf_compose_complete(dbg, &compose_error_type); if (res != DW_DLV_OK) { _dwarf_p_error(NULL, error, compose_error_type); return (DW_DLV_ERROR); } return DW_DLV_OK; }
Dwarf_Unsigned dwarf_add_expr_gen ( Dwarf_P_Expr expr, Dwarf_Small opcode, Dwarf_Unsigned val1, Dwarf_Unsigned val2, Dwarf_Error *error ) { char encode_buffer[2*ENCODE_SPACE_NEEDED]; /* 2* since used to concatenate 2 leb's below */ char encode_buffer2[ENCODE_SPACE_NEEDED]; int res; Dwarf_P_Debug dbg = expr->ex_dbg; /* Give the buffer where the operands are first going to be assembled the largest alignment. */ Dwarf_Unsigned operand_buffer[10]; /* Size of the byte stream buffer that needs to be memcpy-ed. */ int operand_size; /* Points to the byte stream for the first operand, and finally to the buffer that is memcp-ed into the Dwarf_P_Expr_s struct. */ Dwarf_Small *operand; /* Size of the byte stream for second operand. */ int operand2_size; /* Points to next byte to be written in Dwarf_P_Expr_s struct. */ Dwarf_Small *next_byte_ptr; /* Offset past the last byte written into Dwarf_P_Expr_s. */ int next_byte_offset; /* ***** BEGIN CODE ***** */ if (expr == NULL) { _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL); return(DW_DLV_NOCOUNT); } if (expr->ex_dbg == NULL) { _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); return(DW_DLV_NOCOUNT); } operand = NULL; operand_size = 0; switch (opcode) { case DW_OP_reg0 : case DW_OP_reg1 : case DW_OP_reg2 : case DW_OP_reg3 : case DW_OP_reg4 : case DW_OP_reg5 : case DW_OP_reg6 : case DW_OP_reg7 : case DW_OP_reg8 : case DW_OP_reg9 : case DW_OP_reg10 : case DW_OP_reg11 : case DW_OP_reg12 : case DW_OP_reg13 : case DW_OP_reg14 : case DW_OP_reg15 : case DW_OP_reg16 : case DW_OP_reg17 : case DW_OP_reg18 : case DW_OP_reg19 : case DW_OP_reg20 : case DW_OP_reg21 : case DW_OP_reg22 : case DW_OP_reg23 : case DW_OP_reg24 : case DW_OP_reg25 : case DW_OP_reg26 : case DW_OP_reg27 : case DW_OP_reg28 : case DW_OP_reg29 : case DW_OP_reg30 : case DW_OP_reg31 : break; case DW_OP_breg0 : case DW_OP_breg1 : case DW_OP_breg2 : case DW_OP_breg3 : case DW_OP_breg4 : case DW_OP_breg5 : case DW_OP_breg6 : case DW_OP_breg7 : case DW_OP_breg8 : case DW_OP_breg9 : case DW_OP_breg10 : case DW_OP_breg11 : case DW_OP_breg12 : case DW_OP_breg13 : case DW_OP_breg14 : case DW_OP_breg15 : case DW_OP_breg16 : case DW_OP_breg17 : case DW_OP_breg18 : case DW_OP_breg19 : case DW_OP_breg20 : case DW_OP_breg21 : case DW_OP_breg22 : case DW_OP_breg23 : case DW_OP_breg24 : case DW_OP_breg25 : case DW_OP_breg26 : case DW_OP_breg27 : case DW_OP_breg28 : case DW_OP_breg29 : case DW_OP_breg30 : case DW_OP_breg31 : res = _dwarf_pro_encode_signed_leb128_nm(val1, &operand_size,encode_buffer,sizeof(encode_buffer)); if(res != DW_DLV_OK) { _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); return(DW_DLV_NOCOUNT); } operand = (Dwarf_Small *)encode_buffer; break; case DW_OP_regx : res = _dwarf_pro_encode_leb128_nm(val1, &operand_size, encode_buffer, sizeof(encode_buffer)); if(res != DW_DLV_OK) { _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); return(DW_DLV_NOCOUNT); } operand = (Dwarf_Small *)encode_buffer; break; case DW_OP_lit0 : case DW_OP_lit1 : case DW_OP_lit2 : case DW_OP_lit3 : case DW_OP_lit4 : case DW_OP_lit5 : case DW_OP_lit6 : case DW_OP_lit7 : case DW_OP_lit8 : case DW_OP_lit9 : case DW_OP_lit10 : case DW_OP_lit11 : case DW_OP_lit12 : case DW_OP_lit13 : case DW_OP_lit14 : case DW_OP_lit15 : case DW_OP_lit16 : case DW_OP_lit17 : case DW_OP_lit18 : case DW_OP_lit19 : case DW_OP_lit20 : case DW_OP_lit21 : case DW_OP_lit22 : case DW_OP_lit23 : case DW_OP_lit24 : case DW_OP_lit25 : case DW_OP_lit26 : case DW_OP_lit27 : case DW_OP_lit28 : case DW_OP_lit29 : case DW_OP_lit30 : case DW_OP_lit31 : break; case DW_OP_addr : _dwarf_p_error(expr->ex_dbg, error, DW_DLE_BAD_EXPR_OPCODE); return(DW_DLV_NOCOUNT); case DW_OP_const1u : case DW_OP_const1s : operand = (Dwarf_Small *)&operand_buffer[0]; WRITE_UNALIGNED(dbg,operand,&val1,sizeof(val1),1); operand_size = 1; break; case DW_OP_const2u : case DW_OP_const2s : operand = (Dwarf_Small *)&operand_buffer[0]; WRITE_UNALIGNED(dbg,operand,&val1,sizeof(val1),2); operand_size = 2; break; case DW_OP_const4u : case DW_OP_const4s : operand = (Dwarf_Small *)&operand_buffer[0]; WRITE_UNALIGNED(dbg,operand,&val1,sizeof(val1),4); operand_size = 4; break; case DW_OP_const8u : case DW_OP_const8s : operand = (Dwarf_Small *)&operand_buffer[0]; WRITE_UNALIGNED(dbg,operand,&val1,sizeof(val1),8); operand_size = 8; break; case DW_OP_constu : res = _dwarf_pro_encode_leb128_nm(val1, &operand_size, encode_buffer, sizeof(encode_buffer)); if(res != DW_DLV_OK) { _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); return(DW_DLV_NOCOUNT); } operand = (Dwarf_Small *)encode_buffer; break; case DW_OP_consts : res = _dwarf_pro_encode_signed_leb128_nm(val1, &operand_size, encode_buffer, sizeof(encode_buffer)); if(res != DW_DLV_OK) { _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); return(DW_DLV_NOCOUNT); } operand = (Dwarf_Small *)encode_buffer; break; case DW_OP_fbreg : res = _dwarf_pro_encode_signed_leb128_nm(val1, &operand_size, encode_buffer, sizeof(encode_buffer)); if(res != DW_DLV_OK) { _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); return(DW_DLV_NOCOUNT); } operand = (Dwarf_Small *)encode_buffer; break; case DW_OP_bregx : res = _dwarf_pro_encode_leb128_nm(val1, &operand_size, encode_buffer, sizeof(encode_buffer)); if(res != DW_DLV_OK) { _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); return(DW_DLV_NOCOUNT); } operand = (Dwarf_Small *)encode_buffer; /* put this one directly into 'operand' at tail of prev value */ res = _dwarf_pro_encode_signed_leb128_nm(val2, &operand2_size, ((char *)operand)+operand_size, sizeof(encode_buffer2)); if(res != DW_DLV_OK) { _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); return(DW_DLV_NOCOUNT); } operand_size += operand2_size; case DW_OP_dup : case DW_OP_drop : break; case DW_OP_pick : operand = (Dwarf_Small *)&operand_buffer[0]; WRITE_UNALIGNED(dbg,operand,(const void *)val1, sizeof(val1),1); operand_size = 1; break; case DW_OP_over : case DW_OP_swap : case DW_OP_rot : case DW_OP_deref : case DW_OP_xderef : break; case DW_OP_deref_size : case DW_OP_xderef_size : operand = (Dwarf_Small *)&operand_buffer[0]; WRITE_UNALIGNED(dbg,operand,(const void *)val1, sizeof(val1),1); operand_size = 1; break; case DW_OP_abs : case DW_OP_and : case DW_OP_div : case DW_OP_minus : case DW_OP_mod : case DW_OP_mul : case DW_OP_neg : case DW_OP_not : case DW_OP_or : case DW_OP_plus : break; case DW_OP_plus_uconst : res = _dwarf_pro_encode_leb128_nm(val1, &operand_size, encode_buffer, sizeof(encode_buffer)); if(res != DW_DLV_OK) { _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); return(DW_DLV_NOCOUNT); } operand = (Dwarf_Small *)encode_buffer; break; case DW_OP_shl : case DW_OP_shr : case DW_OP_shra : case DW_OP_xor : break; case DW_OP_le : case DW_OP_ge : case DW_OP_eq : case DW_OP_lt : case DW_OP_gt : case DW_OP_ne : break; case DW_OP_skip : case DW_OP_bra : /* FIX: unhandled! OP_bra, OP_skip! */ _dwarf_p_error(expr->ex_dbg, error, DW_DLE_BAD_EXPR_OPCODE); return(DW_DLV_NOCOUNT); case DW_OP_piece : res = _dwarf_pro_encode_leb128_nm(val1, &operand_size, encode_buffer, sizeof(encode_buffer)); if(res != DW_DLV_OK) { _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); return(DW_DLV_NOCOUNT); } operand = (Dwarf_Small *)encode_buffer; break; case DW_OP_nop : break; default : _dwarf_p_error(expr->ex_dbg, error, DW_DLE_BAD_EXPR_OPCODE); return(DW_DLV_NOCOUNT); } next_byte_offset = expr->ex_next_byte_offset + operand_size + 1; if (next_byte_offset > MAXIMUM_LOC_EXPR_LENGTH) { _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD); return(DW_DLV_NOCOUNT); } next_byte_ptr = &(expr->ex_byte_stream[0]) + expr->ex_next_byte_offset; *next_byte_ptr = opcode; next_byte_ptr++; memcpy(next_byte_ptr, operand, operand_size); expr->ex_next_byte_offset = next_byte_offset; return(next_byte_offset); }