MonoDebugMethodAddressList * mono_debug_lookup_method_addresses (MonoMethod *method) { MonoDebugMethodAddressList *info; MonoDebugMethodHeader *header = NULL; struct LookupMethodAddressData data; MonoMethod *declaring; int count, size; GSList *list; guint8 *ptr; g_assert ((mono_debug_debugger_version == 4) || (mono_debug_debugger_version == 5)); mono_debugger_lock (); declaring = method->is_inflated ? ((MonoMethodInflated *) method)->declaring : method; data.method = declaring; data.result = NULL; g_hash_table_foreach (data_table_hash, lookup_method_address_func, &data); header = data.result; if (!header) { mono_debugger_unlock (); return NULL; } count = g_slist_length (header->address_list) + 1; size = sizeof (MonoDebugMethodAddressList) + count * sizeof (gpointer); info = g_malloc0 (size); info->size = size; info->count = count; ptr = info->data; WRITE_UNALIGNED (gpointer, ptr, header); ptr += sizeof (gpointer); for (list = header->address_list; list; list = list->next) { WRITE_UNALIGNED (gpointer, ptr, list->data); ptr += sizeof (gpointer); } mono_debugger_unlock (); return info; }
/* 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; }
static void mono_debug_add_type (MonoClass *klass) { MonoDebugHandle *handle; MonoDebugClassEntry *entry; guint8 buffer [BUFSIZ]; guint8 *ptr, *oldptr; guint32 size, total_size, max_size; int base_offset = 0; if (klass->generic_class || klass->rank || (klass->byval_arg.type == MONO_TYPE_VAR) || (klass->byval_arg.type == MONO_TYPE_MVAR)) return; mono_debugger_lock (); handle = _mono_debug_get_image (klass->image); if (!handle) { mono_debugger_unlock (); return; } max_size = 12 + sizeof (gpointer); if (max_size > BUFSIZ) ptr = oldptr = g_malloc (max_size); else ptr = oldptr = buffer; if (klass->valuetype) base_offset = - (int)(sizeof (MonoObject)); write_leb128 (klass->type_token, ptr, &ptr); write_leb128 (klass->instance_size + base_offset, ptr, &ptr); WRITE_UNALIGNED (gpointer, ptr, klass); ptr += sizeof (gpointer); size = ptr - oldptr; g_assert (size < max_size); total_size = size + sizeof (MonoDebugClassEntry); g_assert (total_size + 9 < DATA_TABLE_CHUNK_SIZE); entry = (MonoDebugClassEntry *) allocate_data_item ( handle->type_table, MONO_DEBUG_DATA_ITEM_CLASS, total_size); entry->size = total_size; memcpy (&entry->data, oldptr, size); write_data_item (handle->type_table, (guint8 *) entry); if (max_size > BUFSIZ) g_free (oldptr); mono_debugger_unlock (); }
static void write_variable (MonoDebugVarInfo *var, guint8 *ptr, guint8 **rptr) { write_leb128 (var->index, ptr, &ptr); write_sleb128 (var->offset, ptr, &ptr); write_leb128 (var->size, ptr, &ptr); write_leb128 (var->begin_scope, ptr, &ptr); write_leb128 (var->end_scope, ptr, &ptr); WRITE_UNALIGNED (gpointer, ptr, var->type); ptr += sizeof (gpointer); *rptr = ptr; }
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); }
int _dwarf_pro_add_AT_macro_info(Dwarf_P_Debug dbg, Dwarf_P_Die die, Dwarf_Unsigned offset, Dwarf_Error * error) { Dwarf_P_Attribute new_attr; int uwordb_size = dbg->de_offset_size; if (die == NULL) { DWARF_P_DBG_ERROR(NULL, DW_DLE_DIE_NULL, -1); } new_attr = (Dwarf_P_Attribute) _dwarf_p_get_alloc(dbg,sizeof(struct Dwarf_P_Attribute_s)); if (new_attr == NULL) { DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, -1); } /* fill in the information */ new_attr->ar_attribute = DW_AT_macro_info; new_attr->ar_attribute_form = dbg->de_ar_data_attribute_form; new_attr->ar_rel_type = dbg->de_offset_reloc; new_attr->ar_nbytes = uwordb_size; new_attr->ar_next = NULL; new_attr->ar_reloc_len = uwordb_size; new_attr->ar_data = (char *) _dwarf_p_get_alloc(dbg, uwordb_size); if (new_attr->ar_data == NULL) { DWARF_P_DBG_ERROR(NULL, DW_DLE_ADDR_ALLOC, DW_DLV_NOCOUNT); } { Dwarf_Unsigned du = offset; WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data, (const void *) &du, sizeof(du), uwordb_size); } _dwarf_pro_add_at_to_die(die, new_attr); return 0; }
int _dwarf_pro_add_AT_stmt_list(Dwarf_P_Debug dbg, Dwarf_P_Die first_die, Dwarf_Error * error) { Dwarf_P_Attribute new_attr; int uwordb_size = dbg->de_offset_size; /* Add AT_stmt_list attribute */ new_attr = (Dwarf_P_Attribute) _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s)); if (new_attr == NULL) { DWARF_P_DBG_ERROR(NULL, DW_DLE_ATTR_ALLOC, DW_DLV_NOCOUNT); } new_attr->ar_attribute = DW_AT_stmt_list; new_attr->ar_attribute_form = dbg->de_ar_data_attribute_form; new_attr->ar_rel_type = dbg->de_offset_reloc; new_attr->ar_nbytes = uwordb_size; new_attr->ar_next = NULL; new_attr->ar_reloc_len = uwordb_size; new_attr->ar_data = (char *) _dwarf_p_get_alloc(dbg, uwordb_size); if (new_attr->ar_data == NULL) { DWARF_P_DBG_ERROR(NULL, DW_DLE_ADDR_ALLOC, DW_DLV_NOCOUNT); } { Dwarf_Unsigned du = 0; WRITE_UNALIGNED(dbg, (void *) new_attr->ar_data, (const void *) &du, sizeof(du), uwordb_size); } _dwarf_pro_add_at_to_die(first_die, new_attr); return 0; }
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; }
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); }
/* new interface */ 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) { Dwarf_P_Attribute new_attr; int upointer_size = dbg->de_pointer_size; 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); } if (attr != DW_AT_low_pc && attr != DW_AT_high_pc && attr != DW_AT_MIPS_loop_begin && attr != DW_AT_MIPS_tail_loop_begin && attr != DW_AT_MIPS_epilog_begin) { _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD); 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_addr; 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 attributes whose value is a location expression. */ Dwarf_P_Attribute dwarf_add_AT_location_expr(Dwarf_P_Debug dbg, Dwarf_P_Die ownerdie, Dwarf_Half attr, Dwarf_P_Expr loc_expr, Dwarf_Error * error) { char encode_buffer[ENCODE_SPACE_NEEDED]; int res; Dwarf_P_Attribute new_attr; Dwarf_Half attr_form; char *len_str; int len_size; int block_size; char *block_dest_ptr; int do_len_as_int = 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); } if (loc_expr == NULL) { _dwarf_p_error(dbg, error, DW_DLE_EXPR_NULL); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } if (loc_expr->ex_dbg != dbg) { _dwarf_p_error(dbg, error, DW_DLE_LOC_EXPR_BAD); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } block_size = loc_expr->ex_next_byte_offset; switch (attr) { case DW_AT_location: case DW_AT_string_length: case DW_AT_const_value: case DW_AT_use_location: case DW_AT_return_addr: case DW_AT_data_member_location: case DW_AT_frame_base: case DW_AT_static_link: case DW_AT_vtable_elem_location: break; default:{ _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } } /* Compute the number of bytes needed to hold constant. */ if (block_size <= UCHAR_MAX) { attr_form = DW_FORM_block1; len_size = 1; do_len_as_int = 1; } else if (block_size <= USHRT_MAX) { attr_form = DW_FORM_block2; len_size = 2; do_len_as_int = 1; } else if (block_size <= UINT_MAX) { attr_form = DW_FORM_block4; len_size = 4; do_len_as_int = 1; } else { attr_form = DW_FORM_block; res = _dwarf_pro_encode_leb128_nm(block_size, &len_size, encode_buffer, sizeof(encode_buffer)); if (res != DW_DLV_OK) { _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } len_str = (char *) encode_buffer; } 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 = attr_form; new_attr->ar_reloc_len = dbg->de_pointer_size; if (loc_expr->ex_reloc_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_rel_symidx = loc_expr->ex_reloc_sym_index; new_attr->ar_rel_offset = (Dwarf_Word) loc_expr->ex_reloc_offset + len_size; new_attr->ar_nbytes = block_size + len_size; new_attr->ar_next = 0; new_attr->ar_data = block_dest_ptr = (char *) _dwarf_p_get_alloc(dbg, block_size + len_size); if (new_attr->ar_data == NULL) { _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } if (do_len_as_int) { WRITE_UNALIGNED(dbg, block_dest_ptr, (const void *) &block_size, sizeof(block_size), len_size); } else { /* is uleb number form */ memcpy(block_dest_ptr, len_str, len_size); } block_dest_ptr += len_size; memcpy(block_dest_ptr, &(loc_expr->ex_byte_stream[0]), block_size); /* add attribute to the die */ _dwarf_pro_add_at_to_die(ownerdie, new_attr); return new_attr; }
/* This function adds attributes whose value is an signed constant. It determines the size of the value field from the value of the constant. */ Dwarf_P_Attribute dwarf_add_AT_signed_const(Dwarf_P_Debug dbg, Dwarf_P_Die ownerdie, Dwarf_Half attr, Dwarf_Signed value, Dwarf_Error * error) { Dwarf_P_Attribute new_attr; Dwarf_Half attr_form; Dwarf_Small size; 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); } switch (attr) { case DW_AT_upper_bound: case DW_AT_lower_bound: break; default:{ _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } } /* Compute the number of bytes needed to hold constant. gdb seems to treat all the DW_FORM_data forms as unsigned, so if we have a negative number we need to encode it as signed data. */ 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); } if (value < 0) { attr_form = DW_FORM_sdata; } else if (value >= SCHAR_MIN && value <= SCHAR_MAX) { attr_form = DW_FORM_data1; size = 1; } else if (value >= SHRT_MIN && value <= SHRT_MAX) { attr_form = DW_FORM_data2; size = 2; } else if (value >= INT_MIN && value <= INT_MAX) { attr_form = DW_FORM_data4; size = 4; } else { attr_form = DW_FORM_data8; size = 8; } new_attr->ar_attribute = attr; new_attr->ar_attribute_form = attr_form; new_attr->ar_rel_type = R_MIPS_NONE; new_attr->ar_reloc_len = 0; /* irrelevant: unused with R_MIPS_NONE */ new_attr->ar_nbytes = size; new_attr->ar_next = 0; if (attr_form == DW_FORM_sdata) { int leb_size; char encode_buffer[ENCODE_SPACE_NEEDED]; int res; res = _dwarf_pro_encode_signed_leb128_nm( 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(NULL, 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; } else { new_attr->ar_data = (char *) _dwarf_p_get_alloc(dbg, 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 *) &value, sizeof(value), size); } /* add attribute to the die */ _dwarf_pro_add_at_to_die(ownerdie, new_attr); return new_attr; }
/* This function adds attributes whose value is an unsigned constant. It determines the size of the value field from the value of the constant. */ Dwarf_P_Attribute dwarf_add_AT_unsigned_const(Dwarf_P_Debug dbg, Dwarf_P_Die ownerdie, Dwarf_Half attr, Dwarf_Unsigned value, Dwarf_Error * error) { Dwarf_P_Attribute new_attr; Dwarf_Half attr_form; Dwarf_Small size; 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); } switch (attr) { case DW_AT_ordering: case DW_AT_byte_size: case DW_AT_bit_offset: case DW_AT_bit_size: case DW_AT_inline: case DW_AT_language: case DW_AT_visibility: case DW_AT_virtuality: case DW_AT_accessibility: case DW_AT_address_class: case DW_AT_calling_convention: case DW_AT_encoding: case DW_AT_identifier_case: case DW_AT_MIPS_loop_unroll_factor: case DW_AT_MIPS_software_pipeline_depth: break; case DW_AT_decl_column: case DW_AT_decl_file: case DW_AT_decl_line: case DW_AT_const_value: case DW_AT_start_scope: case DW_AT_stride_size: case DW_AT_count: break; default:{ _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD); return ((Dwarf_P_Attribute) DW_DLV_BADADDR); } } /* Compute the number of bytes needed to hold constant. */ if (value <= UCHAR_MAX) { attr_form = DW_FORM_data1; size = 1; } else if (value <= USHRT_MAX) { attr_form = DW_FORM_data2; size = 2; } else if (value <= UINT_MAX) { attr_form = DW_FORM_data4; size = 4; } else { attr_form = DW_FORM_data8; size = 8; } 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 = attr_form; new_attr->ar_rel_type = R_MIPS_NONE; new_attr->ar_reloc_len = 0; /* irrelevant: unused with R_MIPS_NONE */ new_attr->ar_nbytes = size; new_attr->ar_next = 0; new_attr->ar_data = (char *) _dwarf_p_get_alloc(dbg, 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 *) &value, sizeof(value), size); /* add attribute to the die */ _dwarf_pro_add_at_to_die(ownerdie, new_attr); return new_attr; }
/* _dwarf_transform_simplename_to_disk writes ".rel.debug_pubnames", ".rel.debug_funcnames", sgi extension ".rel.debug_typenames", sgi extension ".rel.debug_varnames", sgi extension ".rel.debug_weaknames", sgi extension to disk. section_index indexes one of those sections. entrykind is one of those 'kind's. */ int _dwarf_transform_simplename_to_disk(Dwarf_P_Debug dbg, enum dwarf_sn_kind entrykind, int section_index, /* in de_elf_sects etc */ Dwarf_Error * error) { /* Used to fill in 0. */ const Dwarf_Signed big_zero = 0; /* Used to scan the section data buffers. */ Dwarf_P_Section_Data debug_sect; Dwarf_Signed debug_info_size; Dwarf_P_Simple_nameentry nameentry_original; Dwarf_P_Simple_nameentry nameentry; Dwarf_Small *stream_bytes; Dwarf_Small *cur_stream_bytes_ptr; Dwarf_Unsigned stream_bytes_count; Dwarf_Unsigned adjusted_length; /* count excluding length field */ int uword_size = dbg->de_offset_size; int extension_size = dbg->de_64bit_extension ? 4 : 0; Dwarf_P_Simple_name_header hdr; /* ***** BEGIN CODE ***** */ debug_info_size = 0; for (debug_sect = dbg->de_debug_sects; debug_sect != NULL; debug_sect = debug_sect->ds_next) { /* We want the size of the .debug_info section for this CU because the dwarf spec requires us to output it below so we look for it specifically. */ if (debug_sect->ds_elf_sect_no == dbg->de_elf_sects[DEBUG_INFO]) { debug_info_size += debug_sect->ds_nbytes; } } hdr = &dbg->de_simple_name_headers[entrykind]; /* Size of the .debug_typenames (or similar) section header. */ stream_bytes_count = extension_size + uword_size + /* Size of length field. */ sizeof(Dwarf_Half) + /* Size of version field. */ uword_size + /* Size of .debug_info offset. */ uword_size; /* Size of .debug_names. */ nameentry_original = hdr->sn_head; nameentry = nameentry_original; /* add in the content size */ stream_bytes_count += hdr->sn_net_len; /* Size of the last 0 offset. */ stream_bytes_count += uword_size; /* Now we know how long the entire section is */ GET_CHUNK(dbg, dbg->de_elf_sects[section_index], stream_bytes, (unsigned long) stream_bytes_count, error); if (stream_bytes == NULL) { _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); return (0); } cur_stream_bytes_ptr = stream_bytes; if (extension_size) { Dwarf_Unsigned x = DISTINGUISHED_VALUE; WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr, (const void *) &x, sizeof(x), extension_size); cur_stream_bytes_ptr += extension_size; } /* Write the adjusted length of .debug_*names section. */ adjusted_length = stream_bytes_count - uword_size - extension_size; WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr, (const void *) &adjusted_length, sizeof(adjusted_length), uword_size); cur_stream_bytes_ptr += uword_size; /* Write the version as 2 bytes. */ { Dwarf_Half verstamp = CURRENT_VERSION_STAMP; WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr, (const void *) &verstamp, sizeof(verstamp), sizeof(Dwarf_Half)); cur_stream_bytes_ptr += sizeof(Dwarf_Half); } /* Write the offset of the compile-unit. */ WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr, (const void *) &big_zero, sizeof(big_zero), uword_size); cur_stream_bytes_ptr += uword_size; /* now create the relocation for the compile_unit offset */ { int res = dbg->de_reloc_name(dbg, section_index, extension_size + uword_size + sizeof(Dwarf_Half) /* r_offset */ , /* debug_info section name symbol */ dbg->de_sect_name_idx[DEBUG_INFO], dwarf_drt_data_reloc, uword_size); if (res != DW_DLV_OK) { { _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL); return (0); } } } /* Write the size of .debug_info section. */ WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr, (const void *) &debug_info_size, sizeof(debug_info_size), uword_size); cur_stream_bytes_ptr += uword_size; for (nameentry = nameentry_original; nameentry != NULL; nameentry = nameentry->sne_next) { /* Copy offset of die from start of compile-unit. */ WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr, (const void *) &nameentry->sne_die->di_offset, sizeof(nameentry->sne_die->di_offset), uword_size); cur_stream_bytes_ptr += uword_size; /* Copy the type name. */ strcpy((char *) cur_stream_bytes_ptr, nameentry->sne_name); cur_stream_bytes_ptr += nameentry->sne_name_len + 1; } WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr, (const void *) &big_zero, sizeof(big_zero), uword_size); return (int) dbg->de_n_debug_sect; }
/* This function adds attributes whose value is an signed constant. It determines the size of the value field from the value of the constant. */ Dwarf_P_Attribute dwarf_add_AT_signed_const(Dwarf_P_Debug dbg, Dwarf_P_Die ownerdie, Dwarf_Half attr, Dwarf_Signed value, Dwarf_Error * error) { Dwarf_P_Attribute new_attr = 0; Dwarf_Half attr_form = 0; Dwarf_Small size = 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); } switch (attr) { case DW_AT_lower_bound: case DW_AT_upper_bound: case DW_AT_const_value: case DW_AT_bit_offset: case DW_AT_bit_size: case DW_AT_byte_size: case DW_AT_count: case DW_AT_byte_stride: case DW_AT_bit_stride: case DW_AT_allocated: case DW_AT_associated: 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; } /* Compute the number of bytes needed to hold constant. */ if (value >= SCHAR_MIN && value <= SCHAR_MAX) { attr_form = DW_FORM_data1; size = 1; } else if (value >= SHRT_MIN && value <= SHRT_MAX) { attr_form = DW_FORM_data2; size = 2; } else if (value >= INT_MIN && value <= INT_MAX) { attr_form = DW_FORM_data4; size = 4; } else { attr_form = DW_FORM_data8; size = 8; } 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 = attr_form; new_attr->ar_rel_type = R_MIPS_NONE; new_attr->ar_reloc_len = 0; /* irrelevant: unused with R_MIPS_NONE */ new_attr->ar_nbytes = size; new_attr->ar_next = 0; new_attr->ar_data = (char *) _dwarf_p_get_alloc(dbg, 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 *) &value, sizeof(value), size); /* add attribute to the die */ _dwarf_pro_add_at_to_die(ownerdie, new_attr); return new_attr; }
/* Returns DW_DLV_OK if it works, else DW_DLV_ERROR. The caller may decide to ignore the errors or report them. */ static int update_entry(Dwarf_Debug dbg, Dwarf_Bool is_64bit, Dwarf_Endianness endianess, Dwarf_Half machine, struct Dwarf_Elf_Rela *rela, Dwarf_Small *target_section, Dwarf_Small *symtab_section_data, Dwarf_Unsigned symtab_section_size, Dwarf_Unsigned symtab_section_entrysize, int *error) { unsigned int type = 0; unsigned int sym_idx = 0; #ifdef HAVE_ELF64_SYM Elf64_Sym sym_buf; Elf64_Sym *sym = 0; #else Elf32_Sym sym_buf; Elf32_Sym *sym = 0; #endif Elf32_Sym *sym32 = 0; Dwarf_ufixed64 offset = 0; Dwarf_sfixed64 addend = 0; Dwarf_Unsigned reloc_size = 0; Dwarf_Unsigned symtab_entry_count = 0; if (symtab_section_entrysize == 0) { *error = DW_DLE_SYMTAB_SECTION_ENTRYSIZE_ZERO; return DW_DLV_ERROR; } symtab_entry_count = symtab_section_size/symtab_section_entrysize; /* Dwarf_Elf_Rela dereferencing */ offset = rela->r_offset; addend = rela->r_addend; type = rela->r_type; sym_idx = rela->r_symidx; if (sym_idx >= symtab_entry_count) { *error = DW_DLE_RELOC_SECTION_SYMBOL_INDEX_BAD; return DW_DLV_ERROR; } if (is_64bit) { #ifdef HAVE_ELF64_SYM sym = &((Elf64_Sym*)symtab_section_data)[sym_idx]; #endif } else { sym32 = &((Elf32_Sym*)symtab_section_data)[sym_idx]; /* Convert Elf32_Sym struct to Elf64_Sym struct. We point at an Elf64_Sym local variable (sym_buf) to allow us to use the same pointer (sym) for both 32-bit and 64-bit instances. */ sym = &sym_buf; sym->st_name = sym32->st_name; sym->st_info = sym32->st_info; sym->st_other = sym32->st_other; sym->st_shndx = sym32->st_shndx; sym->st_value = sym32->st_value; sym->st_size = sym32->st_size; } /* Determine relocation size */ if (is_32bit_abs_reloc(type, machine)) { reloc_size = 4; } else if (is_64bit_abs_reloc(type, machine)) { reloc_size = 8; } else { *error = DW_DLE_RELOC_SECTION_RELOC_TARGET_SIZE_UNKNOWN; return DW_DLV_ERROR; } { /* Assuming we do not need to do a READ_UNALIGNED here at target_section + offset and add its value to outval. Some ABIs say no read (for example MIPS), but if some do then which ones? */ Dwarf_Unsigned outval = sym->st_value + addend; WRITE_UNALIGNED(dbg,target_section + offset, &outval,sizeof(outval),reloc_size); } return DW_DLV_OK; }