#include <config.h>
#include <stdlib.h> /* calloc() free() */
#include <string.h> /* memset() */
#include <stdio.h> /* memset() */
#include <limits.h> /* MAX/MIN() */
#if defined(_WIN32) && defined(HAVE_STDAFX_H)
#include "stdafx.h"
#endif /* HAVE_STDAFX_H */
#ifdef HAVE_STDINT_H
#include <stdint.h> /* uintptr_t */
#endif /* HAVE_STDINT_H */
#include "dwarf.h"
#include "libdwarf.h"
#include "libdwarf_private.h"
#include "dwarf_base_types.h"
#include "dwarf_opaque.h"
#include "dwarf_alloc.h"
#include "dwarf_error.h"
#include "dwarf_util.h"
#include "dwarf_frame.h"
#include "dwarf_arange.h" /* Using Arange as a way to build a list */
#include "dwarf_string.h"
#include "dwarf_safe_arithmetic.h"
#define INVALIDUNSIGNED(x) ((x) & (((Dwarf_Unsigned)1) << 63))
#define FDE_NULL_CHECKS_AND_SET_DBG(fde,dbg ) \
do
{ \
if
((fde) == NULL) { \
_dwarf_error(NULL, error, DW_DLE_FDE_NULL);\
return
DW_DLV_ERROR; \
} \
(dbg)= (fde)->fd_dbg; \
if
(IS_INVALID_DBG((dbg))) { \
_dwarf_error_string(NULL, error, DW_DLE_FDE_DBG_NULL,\
"DW_DLE_FDE_DBG_NULL: An fde contains a stale "
\
"Dwarf_Debug "
); \
return
DW_DLV_ERROR; \
} \
}
while
(0)
#define MIN(a,b) (((a) < (b))? (a):(b))
#if 0 /* dump_bytes FOR DEBUGGING */
static
void
dump_bytes(
const
char
*msg,Dwarf_Small * start,
long
len)
{
Dwarf_Small *end = start + len;
Dwarf_Small *cur = start;
printf
(
"%s (0x%lx) "
,msg,(unsigned
long
)start);
for
(; cur < end; cur++) {
printf
(
"%02x"
, *cur);
}
printf
(
"\n"
);
}
static
void
dump_frame_rule(
char
*msg,
struct
Dwarf_Reg_Rule_s *reg_rule);
#endif /*0*/
static
int
_dwarf_initialize_fde_table(Dwarf_Debug dbg,
struct
Dwarf_Frame_s *fde_table,
Dwarf_Unsigned table_real_data_size,
Dwarf_Error * error);
static
void
_dwarf_free_fde_table(
struct
Dwarf_Frame_s *fde_table);
static
void
_dwarf_init_reg_rules_ru(
struct
Dwarf_Reg_Rule_s *base,
Dwarf_Unsigned first, Dwarf_Unsigned last,
Dwarf_Unsigned initial_value);
static
void
_dwarf_init_reg_rules_dw3(
Dwarf_Regtable_Entry3_i *base,
Dwarf_Unsigned, Dwarf_Unsigned last,
Dwarf_Unsigned initial_value);
static
int
regerror(Dwarf_Debug dbg,Dwarf_Error *error,
int
enumber,
const
char
*msg)
{
_dwarf_error_string(dbg,error,enumber,(
char
*)msg);
return
DW_DLV_ERROR;
}
int
_dwarf_validate_register_numbers(
Dwarf_Debug dbg,
Dwarf_Error *error)
{
if
(dbg->de_frame_same_value_number ==
dbg->de_frame_undefined_value_number) {
return
regerror(dbg,error,DW_DLE_DEBUGFRAME_ERROR,
"DW_DLE_DEBUGFRAME_ERROR "
"same_value == undefined_value"
);
}
if
(dbg->de_frame_cfa_col_number ==
dbg->de_frame_same_value_number) {
return
regerror(dbg,error,DW_DLE_DEBUGFRAME_ERROR,
"DW_DLE_DEBUGFRAME_ERROR "
"same_value == cfa_column_number "
);
}
if
(dbg->de_frame_cfa_col_number ==
dbg->de_frame_undefined_value_number) {
return
regerror(dbg,error,DW_DLE_DEBUGFRAME_ERROR,
"DW_DLE_DEBUGFRAME_ERROR "
"undefined_value == cfa_column_number "
);
}
if
((dbg->de_frame_rule_initial_value !=
dbg->de_frame_same_value_number) &&
(dbg->de_frame_rule_initial_value !=
dbg->de_frame_undefined_value_number)) {
return
regerror(dbg,error,DW_DLE_DEBUGFRAME_ERROR,
"DW_DLE_DEBUGFRAME_ERROR "
"initial_value not set to "
" same_value or undefined_value"
);
}
if
(dbg->de_frame_undefined_value_number <=
dbg->de_frame_reg_rules_entry_count) {
return
regerror(dbg,error,DW_DLE_DEBUGFRAME_ERROR,
"DW_DLE_DEBUGFRAME_ERROR "
"undefined_value less than number of registers"
);
}
if
(dbg->de_frame_same_value_number <=
dbg->de_frame_reg_rules_entry_count) {
return
regerror(dbg,error,DW_DLE_DEBUGFRAME_ERROR,
"DW_DLE_DEBUGFRAME_ERROR "
"same_value <= number of registers"
);
}
if
(dbg->de_frame_cfa_col_number <=
dbg->de_frame_reg_rules_entry_count) {
return
regerror(dbg,error,DW_DLE_DEBUGFRAME_ERROR,
"DW_DLE_DEBUGFRAME_ERROR "
"cfa_column <= number of registers"
);
}
return
DW_DLV_OK;
}
int
dwarf_get_frame_section_name(Dwarf_Debug dbg,
const
char
**sec_name,
Dwarf_Error *error)
{
struct
Dwarf_Section_s *sec = 0;
CHECK_DBG(dbg,error,
"dwarf_get_frame_section_name()"
);
if
(error != NULL) {
*error = NULL;
}
sec = &dbg->de_debug_frame;
if
(sec->dss_size == 0) {
return
DW_DLV_NO_ENTRY;
}
*sec_name = sec->dss_name;
return
DW_DLV_OK;
}
int
dwarf_get_frame_section_name_eh_gnu(Dwarf_Debug dbg,
const
char
**sec_name,
Dwarf_Error *error)
{
struct
Dwarf_Section_s *sec = 0;
CHECK_DBG(dbg,error,
"dwarf_get_frame_section_name_eh_gnu()"
);
if
(error != NULL) {
*error = NULL;
}
sec = &dbg->de_debug_frame_eh_gnu;
if
(sec->dss_size == 0) {
return
DW_DLV_NO_ENTRY;
}
*sec_name = sec->dss_name;
return
DW_DLV_OK;
}
static
void
_dwarf_free_dfi_list(Dwarf_Frame_Instr fr)
{
Dwarf_Frame_Instr cur = fr;
Dwarf_Frame_Instr next = 0;
for
( ; cur ; cur = next) {
next = cur->fi_next;
free
(cur);
}
}
#if 0 /* printlist() for debugging */
static
void
printlist(Dwarf_Frame_Instr x)
{
int
i = 0;
Dwarf_Frame_Instr nxt = 0;
printf
(
"=========== print cur list of ptrs\n"
);
for
( ; x ; x = nxt,++i) {
printf
(
"%d inst 0x%lx nxt 0x%lx\n"
,
i,(unsigned
long
)x,
(unsigned
long
)x->fi_next);
nxt = x->fi_next;
}
printf
(
"=========== done cur list of ptrs\n"
);
}
#endif /*0*/
int
_dwarf_exec_frame_instr(Dwarf_Bool make_instr,
Dwarf_Bool search_pc,
Dwarf_Addr search_pc_val,
Dwarf_Addr initial_loc,
Dwarf_Small * start_instr_ptr,
Dwarf_Small * final_instr_ptr,
Dwarf_Frame table,
Dwarf_Cie cie,
Dwarf_Debug dbg,
Dwarf_Unsigned reg_num_of_cfa,
Dwarf_Bool * has_more_rows,
Dwarf_Addr * subsequent_pc,
Dwarf_Frame_Instr_Head *ret_frame_instr_head,
Dwarf_Unsigned * returned_frame_instr_count,
Dwarf_Error *error)
{
#define ERROR_IF_REG_NUM_TOO_HIGH(macreg,machigh_reg) \
do
{ \
if
((macreg) >= (machigh_reg)) { \
SER(DW_DLE_DF_REG_NUM_TOO_HIGH); \
} \
}
while
(0)
#define FREELOCALMALLOC \
_dwarf_free_dfi_list(ilisthead); \
ilisthead =0; \
free
(dfi); dfi = 0; \
free
(localregtab); localregtab = 0;
#define SER(code) \
FREELOCALMALLOC; \
_dwarf_error(dbg,error,(code)); \
return
DW_DLV_ERROR
#define SERSTRING(code,m) \
FREELOCALMALLOC; \
_dwarf_error_string(dbg,error,(code),m); \
return
DW_DLV_ERROR
#define SERINST(m) \
FREELOCALMALLOC; \
_dwarf_error_string(dbg,error,DW_DLE_ALLOC_FAIL, \
"DW_DLE_ALLOC_FAIL: "
m); \
return
DW_DLV_ERROR
Dwarf_Small *instr_ptr = 0;
Dwarf_Frame_Instr dfi = 0;
typedef
Dwarf_Unsigned reg_num_type;
Dwarf_Unsigned factored_N_value = 0;
Dwarf_Signed signed_factored_N_value = 0;
Dwarf_Addr current_loc = initial_loc;
Dwarf_Unsigned adv_loc = 0;
Dwarf_Unsigned reg_count = dbg->de_frame_reg_rules_entry_count;
struct
Dwarf_Reg_Rule_s *localregtab =
calloc
(reg_count,
sizeof
(
struct
Dwarf_Reg_Rule_s));
struct
Dwarf_Reg_Rule_s cfa_reg;
Dwarf_Bool search_over = FALSE;
Dwarf_Addr possible_subsequent_pc = 0;
Dwarf_Half address_size = (cie)? cie->ci_address_size:
dbg->de_pointer_size;
Dwarf_Frame stack_table = NULL;
Dwarf_Frame top_stack = NULL;
Dwarf_Frame_Instr ilisthead = 0;
Dwarf_Frame_Instr *ilistlastptr = &ilisthead;
Dwarf_Unsigned instr_count = 0;
Dwarf_Signed code_alignment_factor = 1;
Dwarf_Signed data_alignment_factor = 1;
Dwarf_Bool need_augmentation = FALSE;
Dwarf_Unsigned instr_area_length = 0;
Dwarf_Unsigned i = 0;
if
(!localregtab) {
SER(DW_DLE_ALLOC_FAIL);
}
{
struct
Dwarf_Reg_Rule_s *t1reg = localregtab;
if
(cie != NULL && cie->ci_initial_table != NULL) {
unsigned minregcount = 0;
unsigned curreg = 0;
struct
Dwarf_Reg_Rule_s *t2reg =
cie->ci_initial_table->fr_reg;
if
(reg_count != cie->ci_initial_table->fr_reg_count) {
SER(DW_DLE_FRAME_REGISTER_COUNT_MISMATCH);
}
minregcount =
(unsigned)MIN(reg_count,
cie->ci_initial_table->fr_reg_count);
for
( ; curreg < minregcount ;
curreg++, t1reg++, t2reg++) {
*t1reg = *t2reg;
} cfa_reg =
cie->ci_initial_table->fr_cfa_rule;
}
else
{
_dwarf_init_reg_rules_ru(localregtab,0,reg_count,
dbg->de_frame_rule_initial_value);
_dwarf_init_reg_rules_ru(&cfa_reg,0, 1,
dbg->de_frame_rule_initial_value);
}
}
if
(cie != NULL && cie->ci_augmentation != NULL) {
code_alignment_factor = cie->ci_code_alignment_factor;
data_alignment_factor = cie->ci_data_alignment_factor;
}
else
{
need_augmentation = !make_instr;
}
instr_ptr = start_instr_ptr;
instr_area_length = (
uintptr_t
)
(final_instr_ptr - start_instr_ptr);
while
((instr_ptr < final_instr_ptr) && (!search_over)) {
Dwarf_Small instr = 0;
Dwarf_Small opcode = 0;
reg_num_type reg_no = 0;
Dwarf_Unsigned adv_pc = 0;
Dwarf_Off fp_instr_offset = 0;
Dwarf_Small * base_instr_ptr = 0;
if
(instr_ptr < start_instr_ptr) {
SERINST(
"DW_DLE_DF_NEW_LOC_LESS_OLD_LOC: "
"Following instruction bytes we find impossible "
"decrease in a pointer"
);
}
fp_instr_offset = instr_ptr - start_instr_ptr;
if
(instr_ptr >= final_instr_ptr) {
_dwarf_error(NULL, error, DW_DLE_DF_FRAME_DECODING_ERROR);
return
DW_DLV_ERROR;
}
instr = *(Dwarf_Small *) instr_ptr;
instr_ptr +=
sizeof
(Dwarf_Small);
base_instr_ptr = instr_ptr;
if
((instr & 0xc0) == 0x00) {
opcode = instr;
}
else
{
opcode = instr & 0xc0;
}
if
(make_instr) {
dfi =
calloc
(1,
sizeof
(*dfi));
if
(!dfi) {
SERINST(
"DW_CFA_advance_loc out of memory"
);
}
dfi->fi_op = opcode;
dfi->fi_instr_offset = fp_instr_offset;
dfi->fi_fields =
""
;
}
switch
(opcode) {
case
DW_CFA_lo_user: {
if
(make_instr) {
dfi->fi_fields =
""
;
}
}
break
;
case
DW_CFA_advance_loc: {
Dwarf_Unsigned adv_pc_val = 0;
int
alres = 0;
adv_pc_val = instr &DW_FRAME_INSTR_OFFSET_MASK;
if
(need_augmentation) {
SER(DW_DLE_DF_NO_CIE_AUGMENTATION);
}
alres = _dwarf_uint64_mult(adv_pc_val,
code_alignment_factor,&adv_pc,dbg,error);
if
(alres == DW_DLV_ERROR) {
FREELOCALMALLOC;
return
DW_DLV_ERROR;
}
if
(INVALIDUNSIGNED(adv_pc)) {
SERSTRING(DW_DLE_ARITHMETIC_OVERFLOW,
"DW_DLE_ARITHMETIC_OVERFLOW "
"negative new location"
);
}
possible_subsequent_pc = current_loc +
(Dwarf_Unsigned)adv_pc;
if
(possible_subsequent_pc < current_loc &&
possible_subsequent_pc < adv_pc) {
SERSTRING(DW_DLE_ARITHMETIC_OVERFLOW,
"DW_DLE_ARITHMETIC_OVERFLOW "
"add overflowed"
);
}
search_over = search_pc &&
(possible_subsequent_pc > search_pc_val);
if
(!search_over) {
current_loc = possible_subsequent_pc;
}
if
(make_instr) {
dfi->fi_fields =
"uc"
;
dfi->fi_u0 = adv_pc_val;
dfi->fi_code_align_factor = code_alignment_factor;
}
}
break
;
case
DW_CFA_offset: {
int
adres = 0;
Dwarf_Signed result = 0;
reg_no = (reg_num_type) (instr &
DW_FRAME_INSTR_OFFSET_MASK);
ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
adres = _dwarf_leb128_uword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&factored_N_value,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
if
(need_augmentation) {
SER( DW_DLE_DF_NO_CIE_AUGMENTATION);
}
if
(INVALIDUNSIGNED(factored_N_value)) {
SERSTRING(DW_DLE_ARITHMETIC_OVERFLOW,
"DW_DLE_ARITHMETIC_OVERFLOW "
"negative factored_N_value location"
);
}
adres = _dwarf_int64_mult(
(Dwarf_Signed)factored_N_value,
data_alignment_factor,
&result,dbg, error);
if
(adres == DW_DLV_ERROR) {
FREELOCALMALLOC;
return
DW_DLV_ERROR;
}
localregtab[reg_no].ru_offset = result;
localregtab[reg_no].ru_is_offset = 1;
localregtab[reg_no].ru_register = reg_num_of_cfa;
localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET;
if
(make_instr) {
dfi->fi_fields =
"rud"
;
dfi->fi_u0 = reg_no;
dfi->fi_u1 = factored_N_value;
dfi->fi_data_align_factor =
data_alignment_factor;
}
}
break
;
case
DW_CFA_restore: {
reg_no = (instr & DW_FRAME_INSTR_OFFSET_MASK);
ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
if
(cie != NULL && cie->ci_initial_table != NULL) {
localregtab[reg_no] =
cie->ci_initial_table->fr_reg[reg_no];
}
else
if
(!make_instr) {
SER(DW_DLE_DF_MAKE_INSTR_NO_INIT);
}
if
(make_instr) {
dfi->fi_fields =
"r"
;
dfi->fi_u0 = reg_no;
}
}
break
;
case
DW_CFA_set_loc: {
Dwarf_Addr new_loc = 0;
int
adres = 0;
adres=_dwarf_read_unaligned_ck_wrapper(dbg,
&new_loc,
instr_ptr, address_size,
final_instr_ptr,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
instr_ptr += address_size;
if
(new_loc != 0 && current_loc != 0) {
if
(new_loc <= current_loc) {
SER(DW_DLE_DF_NEW_LOC_LESS_OLD_LOC);
}
}
search_over = search_pc && (new_loc > search_pc_val);
possible_subsequent_pc = new_loc;
if
(!search_over) {
current_loc = possible_subsequent_pc;
}
if
(make_instr) {
dfi->fi_fields =
"u"
;
dfi->fi_u0 = new_loc;
}
}
break
;
case
DW_CFA_advance_loc1:
{
int
adres = 0;
Dwarf_Unsigned advloc_val = 0;
adres=_dwarf_read_unaligned_ck_wrapper(dbg,
&advloc_val,
instr_ptr,
sizeof
(Dwarf_Small),
final_instr_ptr,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
instr_ptr +=
sizeof
(Dwarf_Small);
if
(need_augmentation) {
SER(DW_DLE_DF_NO_CIE_AUGMENTATION);
}
adres = _dwarf_uint64_mult(
advloc_val,
code_alignment_factor,
&adv_loc,dbg,error);
if
(adres == DW_DLV_ERROR) {
FREELOCALMALLOC;
return
adres;
}
possible_subsequent_pc = current_loc + adv_loc;
if
(possible_subsequent_pc < current_loc &&
possible_subsequent_pc < adv_loc) {
SERSTRING(DW_DLE_ARITHMETIC_OVERFLOW,
"DW_DLE_ARITHMETIC_OVERFLOW "
"add overflowed calcating subsequent pc"
);
}
search_over = search_pc &&
(possible_subsequent_pc > search_pc_val);
if
(!search_over) {
current_loc = possible_subsequent_pc;
}
if
(make_instr) {
dfi->fi_fields =
"uc"
;
dfi->fi_u0 = advloc_val;
dfi->fi_code_align_factor =
code_alignment_factor;
}
break
;
}
case
DW_CFA_advance_loc2:
{
int
adres = 0;
Dwarf_Unsigned advloc_val = 0;
adres=_dwarf_read_unaligned_ck_wrapper(dbg, &advloc_val,
instr_ptr, DWARF_HALF_SIZE,
final_instr_ptr,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
instr_ptr += DWARF_HALF_SIZE;
if
(need_augmentation) {
SER(DW_DLE_DF_NO_CIE_AUGMENTATION);
}
adres = _dwarf_uint64_mult(
advloc_val,
code_alignment_factor,
&adv_loc,dbg,error);
if
(adres == DW_DLV_ERROR) {
FREELOCALMALLOC;
return
adres;
}
if
(INVALIDUNSIGNED(adv_loc)) {
SERSTRING( DW_DLE_ARITHMETIC_OVERFLOW,
"DW_DLE_ARITHMETIC_OVERFLOW "
"negative new location"
);
}
possible_subsequent_pc = current_loc + adv_loc;
if
(possible_subsequent_pc < current_loc &&
possible_subsequent_pc < adv_loc) {
SERSTRING(DW_DLE_ARITHMETIC_OVERFLOW,
"DW_DLE_ARITHMETIC_OVERFLOW "
"add overflowed"
);
}
search_over = search_pc &&
(possible_subsequent_pc > search_pc_val);
if
(!search_over) {
current_loc = possible_subsequent_pc;
}
if
(make_instr) {
dfi->fi_fields =
"uc"
;
dfi->fi_u0 = advloc_val;
dfi->fi_code_align_factor =
code_alignment_factor;
}
break
;
}
case
DW_CFA_advance_loc4:
{
int
adres = 0;
Dwarf_Unsigned advloc_val = 0;
adres=_dwarf_read_unaligned_ck_wrapper(dbg, &advloc_val,
instr_ptr, DWARF_32BIT_SIZE,
final_instr_ptr,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
instr_ptr += DWARF_32BIT_SIZE;
if
(need_augmentation) {
SER(DW_DLE_DF_NO_CIE_AUGMENTATION);
}
adres = _dwarf_uint64_mult(
advloc_val,
code_alignment_factor,
&adv_loc,dbg,error);
if
(adres == DW_DLV_ERROR) {
FREELOCALMALLOC;
return
adres;
}
possible_subsequent_pc = current_loc + adv_loc;
if
(possible_subsequent_pc < current_loc &&
possible_subsequent_pc < adv_loc) {
SERSTRING(DW_DLE_ARITHMETIC_OVERFLOW,
"DW_DLE_ARITHMETIC_OVERFLOW "
"unsigned add overflowed"
);
}
search_over = search_pc &&
(possible_subsequent_pc > search_pc_val);
if
(!search_over) {
current_loc = possible_subsequent_pc;
}
if
(make_instr) {
dfi->fi_fields =
"uc"
;
dfi->fi_u0 = advloc_val;
dfi->fi_code_align_factor =
code_alignment_factor;
}
break
;
}
case
DW_CFA_MIPS_advance_loc8:
{
int
adres = 0;
Dwarf_Unsigned advloc_val = 0;
adres=_dwarf_read_unaligned_ck_wrapper(dbg, &advloc_val,
instr_ptr, DWARF_64BIT_SIZE,
final_instr_ptr,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
instr_ptr += DWARF_64BIT_SIZE;
if
(need_augmentation) {
SER(DW_DLE_DF_NO_CIE_AUGMENTATION);
}
adres = _dwarf_uint64_mult(advloc_val,
code_alignment_factor,&adv_loc,
dbg,error);
if
(adres == DW_DLV_ERROR) {
FREELOCALMALLOC;
return
adres;
}
possible_subsequent_pc = current_loc + adv_loc;
if
(possible_subsequent_pc < current_loc &&
possible_subsequent_pc < adv_loc) {
SERSTRING(DW_DLE_ARITHMETIC_OVERFLOW,
"DW_DLE_ARITHMETIC_OVERFLOW "
"unsigned add overflowed"
);
}
search_over = search_pc &&
(possible_subsequent_pc > search_pc_val);
if
(!search_over) {
current_loc = possible_subsequent_pc;
}
if
(make_instr) {
dfi->fi_fields =
"u"
;
dfi->fi_u0 = advloc_val;
dfi->fi_code_align_factor =
code_alignment_factor;
}
break
;
}
case
DW_CFA_offset_extended:
{
Dwarf_Unsigned lreg = 0;
Dwarf_Signed result = 0;
int
adres = 0;
adres = _dwarf_leb128_uword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&lreg,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
reg_no = (reg_num_type) lreg;
ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
adres = _dwarf_leb128_uword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&factored_N_value,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
if
(need_augmentation) {
SER(DW_DLE_DF_NO_CIE_AUGMENTATION);
}
if
(INVALIDUNSIGNED(factored_N_value)) {
SERSTRING(DW_DLE_ARITHMETIC_OVERFLOW,
"DW_DLE_ARITHMETIC_OVERFLOW "
"negative new location"
);
}
adres = _dwarf_int64_mult((Dwarf_Signed)factored_N_value,
data_alignment_factor, &result,
dbg,error);
if
(adres == DW_DLV_ERROR) {
FREELOCALMALLOC;
return
adres;
}
localregtab[reg_no].ru_is_offset = 1;
localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET;
localregtab[reg_no].ru_register = reg_num_of_cfa;
localregtab[reg_no].ru_offset = result;
if
(make_instr) {
dfi->fi_fields =
"rud"
;
dfi->fi_u0 = lreg;
dfi->fi_u1 = factored_N_value;
dfi->fi_data_align_factor =
data_alignment_factor;
}
break
;
}
case
DW_CFA_restore_extended:
{
Dwarf_Unsigned lreg = 0;
int
adres = 0;
adres = _dwarf_leb128_uword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&lreg,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
reg_no = (reg_num_type) lreg;
ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
if
(cie != NULL && cie->ci_initial_table != NULL) {
localregtab[reg_no] =
cie->ci_initial_table->fr_reg[reg_no];
}
else
{
if
(!make_instr) {
SER(DW_DLE_DF_MAKE_INSTR_NO_INIT);
}
}
if
(make_instr) {
dfi->fi_fields =
"r"
;
dfi->fi_u0 = lreg;
}
break
;
}
case
DW_CFA_undefined:
{
Dwarf_Unsigned lreg = 0;
int
adres = 0;
adres = _dwarf_leb128_uword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&lreg,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
reg_no = (reg_num_type) lreg;
ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
localregtab[reg_no].ru_is_offset = 0;
localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET;
localregtab[reg_no].ru_register =
dbg->de_frame_undefined_value_number;
localregtab[reg_no].ru_offset = 0;
if
(make_instr) {
dfi->fi_fields =
"r"
;
dfi->fi_u0 = lreg;
}
break
;
}
case
DW_CFA_same_value:
{
Dwarf_Unsigned lreg = 0;
int
adres = 0;
adres = _dwarf_leb128_uword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&lreg,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
reg_no = (reg_num_type) lreg;
ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
localregtab[reg_no].ru_is_offset = 0;
localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET;
localregtab[reg_no].ru_register =
dbg->de_frame_same_value_number;
localregtab[reg_no].ru_offset = 0;
if
(make_instr) {
dfi->fi_fields =
"r"
;
dfi->fi_u0 = lreg;
}
break
;
}
case
DW_CFA_register:
{
Dwarf_Unsigned lreg;
reg_num_type reg_noA = 0;
reg_num_type reg_noB = 0;
int
adres = 0;
adres = _dwarf_leb128_uword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&lreg,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
reg_noA = (reg_num_type) lreg;
ERROR_IF_REG_NUM_TOO_HIGH(reg_noA, reg_count);
adres = _dwarf_leb128_uword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&lreg,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
reg_noB = (reg_num_type) lreg;
if
(reg_noB > reg_count) {
SER(DW_DLE_DF_REG_NUM_TOO_HIGH);
}
localregtab[reg_noA].ru_is_offset = 0;
localregtab[reg_noA].ru_value_type = DW_EXPR_OFFSET;
localregtab[reg_noA].ru_register = reg_noB;
localregtab[reg_noA].ru_offset = 0;
if
(make_instr) {
dfi->fi_fields =
"rr"
;
dfi->fi_u0 = reg_noA;
dfi->fi_u1 = reg_noB;
}
break
;
}
case
DW_CFA_remember_state:
{
stack_table = (Dwarf_Frame)
_dwarf_get_alloc(dbg, DW_DLA_FRAME, 1);
if
(stack_table == NULL) {
SER(DW_DLE_DF_ALLOC_FAIL);
}
for
(i = 0; i < reg_count; i++) {
stack_table->fr_reg[i] = localregtab[i];
}
stack_table->fr_cfa_rule = cfa_reg;
if
(top_stack != NULL) {
stack_table->fr_next = top_stack;
}
top_stack = stack_table;
if
(make_instr) {
dfi->fi_fields =
""
;
}
}
break
;
case
DW_CFA_restore_state:
{
if
(top_stack == NULL) {
SER(DW_DLE_DF_POP_EMPTY_STACK);
}
stack_table = top_stack;
top_stack = stack_table->fr_next;
for
(i = 0; i < reg_count; i++) {
localregtab[i] = stack_table->fr_reg[i];
}
cfa_reg = stack_table->fr_cfa_rule;
dwarf_dealloc(dbg, stack_table, DW_DLA_FRAME);
if
(make_instr) {
dfi->fi_fields =
""
;
}
break
;
}
case
DW_CFA_def_cfa:
{
Dwarf_Unsigned lreg = 0;
int
adres = 0;
Dwarf_Off nonfactoredoffset = 0;
adres = _dwarf_leb128_uword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&lreg,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
reg_no = lreg;
ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
adres = _dwarf_leb128_uword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&nonfactoredoffset,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
if
(need_augmentation) {
SER(DW_DLE_DF_NO_CIE_AUGMENTATION);
}
cfa_reg.ru_is_offset = 1;
cfa_reg.ru_value_type = DW_EXPR_OFFSET;
cfa_reg.ru_register = reg_no;
if
(INVALIDUNSIGNED(nonfactoredoffset)) {
SERSTRING(DW_DLE_ARITHMETIC_OVERFLOW,
"DW_DLE_ARITHMETIC_OVERFLOW "
"DW_CFA_def_cfa offset unrepresantable "
"as signed"
);
}
cfa_reg.ru_offset = (Dwarf_Signed)nonfactoredoffset;
if
(make_instr) {
dfi->fi_fields =
"ru"
;
dfi->fi_u0 = lreg;
dfi->fi_u1 = nonfactoredoffset;
}
break
;
}
case
DW_CFA_def_cfa_register:
{
Dwarf_Unsigned lreg = 0;
int
adres = 0;
adres = _dwarf_leb128_uword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&lreg,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
reg_no = (reg_num_type) lreg;
ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
cfa_reg.ru_register = (Dwarf_Half)reg_no;
if
(make_instr) {
dfi->fi_fields =
"r"
;
dfi->fi_u0 = lreg;
}
break
;
}
case
DW_CFA_def_cfa_offset:
{
int
adres = 0;
adres = _dwarf_leb128_uword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&factored_N_value,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
if
(need_augmentation) {
SER(DW_DLE_DF_NO_CIE_AUGMENTATION);
}
cfa_reg.ru_is_offset = 1;
cfa_reg.ru_value_type = DW_EXPR_OFFSET;
if
(INVALIDUNSIGNED(factored_N_value)) {
SERSTRING(DW_DLE_ARITHMETIC_OVERFLOW,
"DW_DLE_ARITHMETIC_OVERFLOW "
"DW_CFA_def_cfa_offset unrepresantable "
"as signed"
);
}
cfa_reg.ru_offset = (Dwarf_Signed)factored_N_value;
if
(make_instr) {
dfi->fi_fields =
"u"
;
dfi->fi_u0 = factored_N_value;
}
break
;
}
case
DW_CFA_METAWARE_info:
{
int
adres = 0;
adres = _dwarf_leb128_uword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&factored_N_value,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
cfa_reg.ru_is_offset = 1;
cfa_reg.ru_value_type = DW_EXPR_OFFSET;
if
(INVALIDUNSIGNED(factored_N_value)) {
SERSTRING(DW_DLE_ARITHMETIC_OVERFLOW,
"DW_DLE_ARITHMETIC_OVERFLOW "
"DW_CFA_METAWARE_info unrepresantable as signed"
);
}
cfa_reg.ru_offset = (Dwarf_Signed)factored_N_value;
if
(make_instr) {
dfi->fi_fields =
"u"
;
dfi->fi_u0 = factored_N_value;
}
break
;
}
case
DW_CFA_nop:
{
if
(make_instr) {
dfi->fi_fields =
""
;
}
break
;
}
case
DW_CFA_def_cfa_expression: {
Dwarf_Unsigned block_len = 0;
int
adres = 0;
adres = _dwarf_leb128_uword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&block_len,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
cfa_reg.ru_is_offset = 0;
cfa_reg.ru_value_type = DW_EXPR_EXPRESSION;
cfa_reg.ru_block.bl_len = block_len;
cfa_reg.ru_block.bl_data = instr_ptr;
if
(make_instr) {
dfi->fi_fields =
"b"
;
dfi->fi_expr.bl_len = block_len;
dfi->fi_expr.bl_data = instr_ptr;
}
if
(block_len >= instr_area_length) {
SERSTRING(DW_DLE_DF_FRAME_DECODING_ERROR,
"DW_DLE_DF_FRAME_DECODING_ERROR: "
"DW_CFA_def_cfa_expression "
"block len overflows instructions "
"available range."
);
}
instr_ptr += block_len;
if
(instr_area_length < block_len ||
instr_ptr < base_instr_ptr) {
SERSTRING(DW_DLE_DF_FRAME_DECODING_ERROR,
"DW_DLE_DF_FRAME_DECODING_ERROR: "
"DW_CFA_def_cfa_expression "
"block len overflows instructions "
"available range."
);
}
}
break
;
case
DW_CFA_expression: {
Dwarf_Unsigned lreg = 0;
Dwarf_Unsigned block_len = 0;
int
adres = 0;
adres = _dwarf_leb128_uword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&lreg,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
reg_no = (reg_num_type) lreg;
ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
adres = _dwarf_leb128_uword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&block_len,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
localregtab[lreg].ru_is_offset = 0;
localregtab[lreg].ru_value_type = DW_EXPR_EXPRESSION;
localregtab[lreg].ru_block.bl_data = instr_ptr;
localregtab[lreg].ru_block.bl_len = block_len;
if
(make_instr) {
dfi->fi_fields =
"rb"
;
dfi->fi_u0 = lreg;
dfi->fi_expr.bl_len = block_len;
dfi->fi_expr.bl_data = instr_ptr;
}
instr_ptr += block_len;
if
(instr_area_length < block_len ||
instr_ptr < base_instr_ptr) {
SERSTRING(DW_DLE_DF_FRAME_DECODING_ERROR,
"DW_DLE_DF_FRAME_DECODING_ERROR: "
"DW_CFA_expression "
"block len overflows instructions "
"available range."
);
}
}
break
;
case
DW_CFA_offset_extended_sf: {
Dwarf_Unsigned lreg = 0;
int
adres = 0;
Dwarf_Signed result = 0;
adres = _dwarf_leb128_uword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&lreg,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
reg_no = (reg_num_type) lreg;
ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
adres = _dwarf_leb128_sword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&signed_factored_N_value,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
if
(need_augmentation) {
SER(DW_DLE_DF_NO_CIE_AUGMENTATION);
}
adres = _dwarf_int64_mult(signed_factored_N_value,
data_alignment_factor,
&result,dbg,error);
if
(adres == DW_DLV_ERROR) {
FREELOCALMALLOC;
return
adres;
}
localregtab[reg_no].ru_is_offset = 1;
localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET;
localregtab[reg_no].ru_register = reg_num_of_cfa;
localregtab[reg_no].ru_offset = result;
if
(make_instr) {
dfi->fi_fields =
"rsd"
;
dfi->fi_u0 = lreg;
dfi->fi_s1 = signed_factored_N_value;
dfi->fi_data_align_factor =
data_alignment_factor;
}
}
break
;
case
DW_CFA_def_cfa_sf: {
Dwarf_Unsigned lreg = 0;
int
adres = 0;
Dwarf_Signed result =0;
adres = _dwarf_leb128_uword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&lreg,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
reg_no = lreg;
ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
adres = _dwarf_leb128_sword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&signed_factored_N_value,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
if
(need_augmentation) {
SER(DW_DLE_DF_NO_CIE_AUGMENTATION);
}
adres = _dwarf_int64_mult(signed_factored_N_value,
data_alignment_factor,
&result,dbg,error);
if
(adres == DW_DLV_ERROR) {
FREELOCALMALLOC;
return
adres;
}
cfa_reg.ru_is_offset = 1;
cfa_reg.ru_value_type = DW_EXPR_OFFSET;
cfa_reg.ru_register = reg_no;
cfa_reg.ru_offset = result;
if
(make_instr) {
dfi->fi_fields =
"rsd"
;
dfi->fi_u0 = lreg;
dfi->fi_s1 = signed_factored_N_value;
dfi->fi_data_align_factor =
data_alignment_factor;
}
}
break
;
case
DW_CFA_def_cfa_offset_sf: {
int
adres = 0;
Dwarf_Signed result = 0;
adres = _dwarf_leb128_sword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&signed_factored_N_value,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
if
(need_augmentation) {
SER(DW_DLE_DF_NO_CIE_AUGMENTATION);
}
adres = _dwarf_int64_mult(signed_factored_N_value,
data_alignment_factor,
&result,dbg,error);
if
(adres == DW_DLV_ERROR) {
FREELOCALMALLOC;
return
adres;
}
cfa_reg.ru_is_offset = 1;
cfa_reg.ru_value_type = DW_EXPR_OFFSET;
cfa_reg.ru_offset = result;
if
(make_instr) {
dfi->fi_fields =
"sd"
;
dfi->fi_s0 = signed_factored_N_value;
dfi->fi_data_align_factor =
data_alignment_factor;
}
}
break
;
case
DW_CFA_val_offset: {
Dwarf_Unsigned lreg = 0;
int
adres = 0;
Dwarf_Signed result = 0;
adres = _dwarf_leb128_uword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&lreg,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
reg_no = (reg_num_type) lreg;
ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
adres = _dwarf_leb128_uword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&factored_N_value,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
if
(INVALIDUNSIGNED(factored_N_value) ) {
SERSTRING(DW_DLE_ARITHMETIC_OVERFLOW,
"DW_DLE_ARITHMETIC_OVERFLOW "
"in DW_CFA_val_offset factored value"
);
}
if
(need_augmentation) {
SER(DW_DLE_DF_NO_CIE_AUGMENTATION);
}
adres = _dwarf_int64_mult(
(Dwarf_Signed)factored_N_value,
data_alignment_factor,
&result,dbg,error);
if
(adres == DW_DLV_ERROR) {
FREELOCALMALLOC;
return
adres;
}
localregtab[reg_no].ru_is_offset = 1;
localregtab[reg_no].ru_register = reg_num_of_cfa;
localregtab[reg_no].ru_value_type =
DW_EXPR_VAL_OFFSET;
localregtab[reg_no].ru_offset = result;
if
(make_instr) {
dfi->fi_fields =
"rud"
;
dfi->fi_u0 = lreg;
dfi->fi_u1 = factored_N_value;
dfi->fi_data_align_factor =
data_alignment_factor;
}
break
;
}
case
DW_CFA_val_offset_sf: {
Dwarf_Unsigned lreg = 0;
Dwarf_Signed result = 0;
int
adres = 0;
adres = _dwarf_leb128_uword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&lreg,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
adres = _dwarf_leb128_sword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&signed_factored_N_value,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
if
(need_augmentation) {
SER(DW_DLE_DF_NO_CIE_AUGMENTATION);
}
adres = _dwarf_int64_mult(signed_factored_N_value,
data_alignment_factor,&result,
dbg,error);
if
(adres == DW_DLV_ERROR) {
FREELOCALMALLOC;
return
adres;
}
localregtab[reg_no].ru_is_offset = 1;
localregtab[reg_no].ru_value_type =
DW_EXPR_VAL_OFFSET;
localregtab[reg_no].ru_offset = result;
if
(make_instr) {
dfi->fi_fields =
"rsd"
;
dfi->fi_u0 = lreg;
dfi->fi_s1 = signed_factored_N_value;
dfi->fi_data_align_factor =
data_alignment_factor;
}
}
break
;
case
DW_CFA_val_expression: {
Dwarf_Unsigned lreg = 0;
Dwarf_Unsigned block_len = 0;
int
adres = 0;
adres = _dwarf_leb128_uword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&lreg,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
reg_no = (reg_num_type) lreg;
ERROR_IF_REG_NUM_TOO_HIGH(reg_no, reg_count);
adres = _dwarf_leb128_uword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&block_len,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
localregtab[lreg].ru_is_offset = 0;
localregtab[lreg].ru_value_type =
DW_EXPR_VAL_EXPRESSION;
localregtab[lreg].ru_offset = 0;
localregtab[lreg].ru_block.bl_data = instr_ptr;
localregtab[lreg].ru_block.bl_len = block_len;
if
(make_instr) {
dfi->fi_fields =
"rb"
;
dfi->fi_u0 = lreg;
dfi->fi_expr.bl_len = block_len;
dfi->fi_expr.bl_data = instr_ptr;
}
instr_ptr += block_len;
if
(instr_area_length < block_len ||
instr_ptr < base_instr_ptr) {
SERSTRING(DW_DLE_DF_FRAME_DECODING_ERROR,
"DW_DLE_DF_FRAME_DECODING_ERROR: "
"DW_CFA_val_expression "
"block len overflows instructions "
"available range."
);
}
}
break
;
#ifdef DW_CFA_GNU_window_save
case
DW_CFA_GNU_window_save: {
if
(make_instr) {
dfi->fi_fields =
""
;
}
}
break
;
#endif
#ifdef DW_CFA_GNU_args_size
case
DW_CFA_GNU_args_size: {
Dwarf_Unsigned asize = 0;
int
adres = 0;
adres = _dwarf_leb128_uword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&asize,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
if
(make_instr) {
dfi->fi_fields =
"u"
;
dfi->fi_u0 = asize;
}
}
break
;
#endif
case
DW_CFA_LLVM_def_aspace_cfa: {
Dwarf_Unsigned lreg = 0;
Dwarf_Unsigned offset = 0;
Dwarf_Unsigned addrspace = 0;
int
adres = 0;
adres = _dwarf_leb128_uword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&lreg,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
ERROR_IF_REG_NUM_TOO_HIGH(lreg, reg_count);
adres = _dwarf_leb128_uword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&offset,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
adres = _dwarf_leb128_uword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&addrspace,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
if
(make_instr) {
dfi->fi_fields =
"rua"
;
dfi->fi_u0 = lreg;
dfi->fi_u1 = offset;
dfi->fi_u2 = addrspace;
}
}
break
;
case
DW_CFA_LLVM_def_aspace_cfa_sf: {
Dwarf_Unsigned lreg = 0;
Dwarf_Signed offset = 0;
Dwarf_Signed result = 0;
Dwarf_Unsigned addrspace = 0;
int
adres = 0;
adres = _dwarf_leb128_uword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&lreg,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
ERROR_IF_REG_NUM_TOO_HIGH(lreg, reg_count);
adres = _dwarf_leb128_sword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&offset,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
adres = _dwarf_leb128_uword_wrapper(dbg,
&instr_ptr,final_instr_ptr,
&addrspace,error);
if
(adres != DW_DLV_OK) {
FREELOCALMALLOC;
return
adres;
}
adres = _dwarf_int64_mult(
(Dwarf_Signed)offset,
data_alignment_factor,
&result,dbg, error);
if
(adres == DW_DLV_ERROR) {
FREELOCALMALLOC;
return
DW_DLV_ERROR;
}
localregtab[reg_no].ru_is_offset = 1;
localregtab[reg_no].ru_value_type = DW_EXPR_OFFSET;
localregtab[reg_no].ru_register = reg_num_of_cfa;
localregtab[reg_no].ru_offset = result;
if
(make_instr) {
dfi->fi_fields =
"rsda"
;
dfi->fi_u0 = lreg;
dfi->fi_s1 = offset;
dfi->fi_u2 = addrspace;
dfi->fi_data_align_factor =
data_alignment_factor;
}
}
break
;
default
: {
dwarfstring ms;
dwarfstring_constructor(&ms);
dwarfstring_append_printf_u(&ms,
"DW_DLE_DF_FRAME_DECODING_ERROR: "
"instr opcode 0x%x unknown"
,opcode);
_dwarf_error_string(dbg,error,
DW_DLE_DF_FRAME_DECODING_ERROR,
dwarfstring_string(&ms));
dwarfstring_destructor(&ms);
FREELOCALMALLOC;
return
DW_DLV_ERROR;
}
}
if
(make_instr) {
instr_count++;
(*ilistlastptr) = dfi;
ilistlastptr = &dfi->fi_next;
dfi = 0;
}
}
if
(instr_ptr > final_instr_ptr) {
SER(DW_DLE_DF_FRAME_DECODING_ERROR);
}
if
((instr_ptr == final_instr_ptr) && !search_over) {
if
(has_more_rows) {
*has_more_rows = FALSE;
}
if
(subsequent_pc) {
*subsequent_pc = 0;
}
}
else
{
if
(has_more_rows) {
*has_more_rows = TRUE;
}
if
(subsequent_pc) {
*subsequent_pc = possible_subsequent_pc;
}
}
if
(table) {
struct
Dwarf_Reg_Rule_s *t2reg = table->fr_reg;
struct
Dwarf_Reg_Rule_s *t3reg = localregtab;
unsigned minregcount = (unsigned)MIN(table->fr_reg_count,
reg_count);
unsigned curreg = 0;
table->fr_loc = current_loc;
for
(; curreg < minregcount ; curreg++, t3reg++, t2reg++) {
*t2reg = *t3reg;
}
table->fr_cfa_rule = cfa_reg;
}
for
(; top_stack != NULL;) {
stack_table = top_stack;
top_stack = top_stack->fr_next;
dwarf_dealloc(dbg, stack_table, DW_DLA_FRAME);
}
if
(make_instr) {
Dwarf_Frame_Instr_Head head = 0;
Dwarf_Frame_Instr *instrptrs = 0;
Dwarf_Frame_Instr *curinstrptr = 0;
Dwarf_Frame_Instr cur = 0;
Dwarf_Frame_Instr next = 0;
Dwarf_Unsigned ic = 0;
head= (Dwarf_Frame_Instr_Head)
_dwarf_get_alloc(dbg, DW_DLA_FRAME_INSTR_HEAD,1);
if
(!head) {
SER(DW_DLE_DF_ALLOC_FAIL);
}
instrptrs= (Dwarf_Frame_Instr *)
_dwarf_get_alloc(dbg, DW_DLA_LIST,instr_count);
if
(!instrptrs) {
dwarf_dealloc(dbg,head,DW_DLA_FRAME_INSTR_HEAD);
SER(DW_DLE_DF_ALLOC_FAIL);
}
head->fh_array = instrptrs;
head->fh_array_count = instr_count;
head->fh_dbg = dbg;
head->fh_cie = cie;
cur = ilisthead;
curinstrptr = instrptrs;
for
( ; cur ; ic++,cur = next,++curinstrptr) {
*curinstrptr = cur;
next = cur->fi_next;
cur->fi_next = 0;
}
ilisthead = 0;
if
(ic != instr_count) {
dwarfstring m;
FREELOCALMALLOC;
dwarf_dealloc(dbg,head,DW_DLA_FRAME_INSTR_HEAD);
dwarfstring_constructor(&m);
dwarfstring_append_printf_u(&m,
"DW_DLE_DF_FRAME_DECODING_ERROR: "
"Instruction array build, instr count %u"
,
instr_count);
dwarfstring_append_printf_u(&m,
" index i %u. Impossible error."
,ic);
_dwarf_error_string(dbg,error,
DW_DLE_DF_FRAME_DECODING_ERROR,
dwarfstring_string(&m));
dwarfstring_destructor(&m);
return
DW_DLV_ERROR;
}
*ret_frame_instr_head = head;
*returned_frame_instr_count = instr_count;
}
else
{
if
(ret_frame_instr_head) {
*ret_frame_instr_head = 0;
}
if
(returned_frame_instr_count) {
*returned_frame_instr_count = 0;
}
}
FREELOCALMALLOC;
return
DW_DLV_OK;
#undef ERROR_IF_REG_NUM_TOO_HIGH
#undef FREELOCALMALLOC
#undef SER
}
int
_dwarf_get_return_address_reg(Dwarf_Small *frame_ptr,
int
version,
Dwarf_Debug dbg,
Dwarf_Byte_Ptr section_end,
unsigned
long
*size,
Dwarf_Unsigned *return_address_register,
Dwarf_Error *error)
{
Dwarf_Unsigned uvalue = 0;
Dwarf_Unsigned leb128_length = 0;
if
(version == 1) {
if
(frame_ptr >= section_end) {
_dwarf_error(NULL, error, DW_DLE_DF_FRAME_DECODING_ERROR);
return
DW_DLV_ERROR;
}
*size = 1;
uvalue = *(unsigned
char
*) frame_ptr;
*return_address_register = uvalue;
return
DW_DLV_OK;
}
DECODE_LEB128_UWORD_LEN_CK(frame_ptr,uvalue,leb128_length,
dbg,error,section_end);
*size = (unsigned
long
)leb128_length;
*return_address_register = uvalue;
return
DW_DLV_OK;
}
int
dwarf_get_cie_of_fde(Dwarf_Fde fde,
Dwarf_Cie * cie_returned, Dwarf_Error * error)
{
if
(!fde) {
_dwarf_error(NULL, error, DW_DLE_FDE_NULL);
return
DW_DLV_ERROR;
}
*cie_returned = fde->fd_cie;
return
DW_DLV_OK;
}
int
dwarf_get_cie_index(
Dwarf_Cie cie,
Dwarf_Signed* indx,
Dwarf_Error* error )
{
if
(cie == NULL)
{
_dwarf_error(NULL, error, DW_DLE_CIE_NULL);
return
DW_DLV_ERROR;
}
*indx = cie->ci_index;
return
DW_DLV_OK;
}
int
dwarf_get_fde_list_eh(Dwarf_Debug dbg,
Dwarf_Cie ** cie_data,
Dwarf_Signed * cie_element_count,
Dwarf_Fde ** fde_data,
Dwarf_Signed * fde_element_count,
Dwarf_Error * error)
{
int
res = 0;
CHECK_DBG(dbg,error,
"dwarf_get_fde_list_eh()"
);
res = _dwarf_load_section(dbg,
&dbg->de_debug_frame_eh_gnu,error);
if
(res != DW_DLV_OK) {
return
res;
}
res = _dwarf_get_fde_list_internal(dbg,
cie_data,
cie_element_count,
fde_data,
fde_element_count,
dbg->de_debug_frame_eh_gnu.dss_data,
dbg->de_debug_frame_eh_gnu.dss_index,
dbg->de_debug_frame_eh_gnu.dss_size,
0,
1,
error);
return
res;
}
int
dwarf_get_fde_list(Dwarf_Debug dbg,
Dwarf_Cie ** cie_data,
Dwarf_Signed * cie_element_count,
Dwarf_Fde ** fde_data,
Dwarf_Signed * fde_element_count,
Dwarf_Error * error)
{
int
res = 0;
CHECK_DBG(dbg,error,
"dwarf_get_fde_list()"
);
res = _dwarf_load_section(dbg, &dbg->de_debug_frame,error);
if
(res != DW_DLV_OK) {
return
res;
}
res = _dwarf_get_fde_list_internal(dbg, cie_data,
cie_element_count,
fde_data,
fde_element_count,
dbg->de_debug_frame.dss_data,
dbg->de_debug_frame.dss_index,
dbg->de_debug_frame.dss_size,
(Dwarf_Unsigned)DW_CIE_ID,
0,
error);
return
res;
}
int
dwarf_get_fde_for_die(Dwarf_Debug dbg,
Dwarf_Die die,
Dwarf_Fde * ret_fde, Dwarf_Error * error)
{
Dwarf_Attribute attr;
Dwarf_Unsigned fde_offset = 0;
Dwarf_Signed signdval = 0;
Dwarf_Fde new_fde = 0;
unsigned
char
*fde_ptr = 0;
unsigned
char
*fde_start_ptr = 0;
unsigned
char
*fde_end_ptr = 0;
unsigned
char
*cie_ptr = 0;
Dwarf_Unsigned cie_id = 0;
Dwarf_Half address_size = 0;
int
res = 0;
int
resattr = 0;
int
sdatares = 0;
struct
cie_fde_prefix_s prefix;
struct
cie_fde_prefix_s prefix_c;
CHECK_DBG(dbg,error,
"dwarf_get_fde_for_die()"
);
if
(!die ) {
_dwarf_error_string(NULL, error, DW_DLE_DIE_NULL,
"DW_DLE_DIE_NUL: in dwarf_get_fde_for_die(): "
"Called with Dwarf_Die argument null"
);
return
DW_DLV_ERROR;
}
resattr = dwarf_attr(die, DW_AT_MIPS_fde, &attr, error);
if
(resattr != DW_DLV_OK) {
return
resattr;
}
sdatares = dwarf_formsdata(attr, &signdval, error);
if
(sdatares != DW_DLV_OK) {
dwarf_dealloc_attribute(attr);
return
sdatares;
}
res = dwarf_get_die_address_size(die,&address_size,error);
if
(res != DW_DLV_OK) {
dwarf_dealloc_attribute(attr);
return
res;
}
dwarf_dealloc_attribute(attr);
res = _dwarf_load_section(dbg, &dbg->de_debug_frame,error);
if
(res != DW_DLV_OK) {
return
res;
}
fde_offset = signdval;
fde_start_ptr = dbg->de_debug_frame.dss_data;
fde_ptr = fde_start_ptr + fde_offset;
fde_end_ptr = fde_start_ptr + dbg->de_debug_frame.dss_size;
res = _dwarf_validate_register_numbers(dbg,error);
if
(res == DW_DLV_ERROR) {
return
res;
}
memset
(&prefix_c, 0,
sizeof
(prefix_c));
memset
(&prefix, 0,
sizeof
(prefix));
res = _dwarf_read_cie_fde_prefix(dbg, fde_ptr,
dbg->de_debug_frame.dss_data,
dbg->de_debug_frame.dss_index,
dbg->de_debug_frame.dss_size,
&prefix,
error);
if
(res == DW_DLV_ERROR) {
return
res;
}
if
(res == DW_DLV_NO_ENTRY) {
return
res;
}
fde_ptr = prefix.cf_addr_after_prefix;
cie_id = prefix.cf_cie_id;
if
(cie_id >= dbg->de_debug_frame.dss_size ) {
_dwarf_error_string(dbg, error, DW_DLE_NO_CIE_FOR_FDE,
"DW_DLE_NO_CIE_FOR_FDE: "
"dwarf_get_fde_for_die fails as the CIE id "
"offset is impossibly large"
);
return
DW_DLV_ERROR;
}
res = _dwarf_create_fde_from_after_start(dbg, &prefix,
fde_start_ptr,
dbg->de_debug_frame.dss_size,
fde_ptr,
fde_end_ptr,
0,
0,
address_size,
&new_fde, error);
if
(res == DW_DLV_ERROR) {
return
res;
}
if
(res == DW_DLV_NO_ENTRY) {
return
res;
}
new_fde->fd_fde_owns_cie = TRUE;
if
(cie_id >= dbg->de_debug_frame.dss_size ) {
_dwarf_error_string(dbg, error, DW_DLE_NO_CIE_FOR_FDE,
"DW_DLE_NO_CIE_FOR_FDE: "
"dwarf_get_fde_for_die fails as the CIE id "
"offset is impossibly large"
);
return
DW_DLV_ERROR;
}
cie_ptr = new_fde->fd_section_ptr + cie_id;
if
((Dwarf_Unsigned)(
uintptr_t
)cie_ptr <
(Dwarf_Unsigned)(
uintptr_t
)new_fde->fd_section_ptr ||
(Dwarf_Unsigned)(
uintptr_t
)cie_ptr < cie_id) {
dwarf_dealloc(dbg,new_fde,DW_DLA_FDE);
new_fde = 0;
_dwarf_error_string(dbg, error, DW_DLE_NO_CIE_FOR_FDE,
"DW_DLE_NO_CIE_FOR_FDE: "
"dwarf_get_fde_for_die fails as the CIE id "
"offset is impossibly large"
);
return
DW_DLV_ERROR;
}
res = _dwarf_read_cie_fde_prefix(dbg, cie_ptr,
dbg->de_debug_frame.dss_data,
dbg->de_debug_frame.dss_index,
dbg->de_debug_frame.dss_size,
&prefix_c, error);
if
(res == DW_DLV_ERROR) {
dwarf_dealloc(dbg,new_fde,DW_DLA_FDE);
new_fde = 0;
return
res;
}
if
(res == DW_DLV_NO_ENTRY) {
dwarf_dealloc(dbg,new_fde,DW_DLA_FDE);
new_fde = 0;
return
res;
}
cie_ptr = prefix_c.cf_addr_after_prefix;
cie_id = prefix_c.cf_cie_id;
if
(cie_id == (Dwarf_Unsigned)DW_CIE_ID) {
int
res2 = 0;
Dwarf_Cie new_cie = 0;
res2 = _dwarf_create_cie_from_after_start(dbg,
&prefix_c,
fde_start_ptr,
cie_ptr,
fde_end_ptr,
0,
0, &new_cie, error);
if
(res2 != DW_DLV_OK) {
dwarf_dealloc(dbg, new_fde, DW_DLA_FDE);
return
res;
}
new_fde->fd_cie = new_cie;
}
else
{
dwarf_dealloc(dbg,new_fde,DW_DLA_FDE);
new_fde = 0;
_dwarf_error_string(dbg, error, DW_DLE_NO_CIE_FOR_FDE,
"DW_DLE_NO_CIE_FOR_FDE: "
"The CIE id is not a true cid id. Corrupt DWARF."
);
return
DW_DLV_ERROR;
}
*ret_fde = new_fde;
return
DW_DLV_OK;
}
int
dwarf_get_fde_range(Dwarf_Fde fde,
Dwarf_Addr * low_pc,
Dwarf_Unsigned * func_length,
Dwarf_Byte_Ptr * fde_bytes,
Dwarf_Unsigned * fde_byte_length,
Dwarf_Off * cie_offset,
Dwarf_Signed * cie_index,
Dwarf_Off * fde_offset, Dwarf_Error * error)
{
Dwarf_Debug dbg;
if
(fde == NULL) {
_dwarf_error(NULL, error, DW_DLE_FDE_NULL);
return
DW_DLV_ERROR;
}
dbg = fde->fd_dbg;
if
(IS_INVALID_DBG(dbg)) {
_dwarf_error_string(NULL, error, DW_DLE_FDE_DBG_NULL,
"DW_DLE_FDE_DBG_NULL: Either null or it contains"
"a stale Dwarf_Debug pointer"
);
return
DW_DLV_ERROR;
}
if
(low_pc != NULL)
*low_pc = fde->fd_initial_location;
if
(func_length != NULL)
*func_length = fde->fd_address_range;
if
(fde_bytes != NULL)
*fde_bytes = fde->fd_fde_start;
if
(fde_byte_length != NULL)
*fde_byte_length = fde->fd_length;
if
(cie_offset != NULL)
*cie_offset = fde->fd_cie_offset;
if
(cie_index != NULL)
*cie_index = fde->fd_cie_index;
if
(fde_offset != NULL)
*fde_offset = fde->fd_fde_start - fde->fd_section_ptr;
return
DW_DLV_OK;
}
int
dwarf_get_fde_exception_info(Dwarf_Fde fde,
Dwarf_Signed *
offset_into_exception_tables,
Dwarf_Error * error)
{
Dwarf_Debug dbg;
dbg = fde->fd_dbg;
if
(IS_INVALID_DBG(dbg)) {
_dwarf_error_string(NULL, error, DW_DLE_FDE_DBG_NULL,
"DW_DLE_FDE_DBG_NULL: Either null or it contains"
"a stale Dwarf_Debug pointer"
);
return
DW_DLV_ERROR;
}
*offset_into_exception_tables =
fde->fd_offset_into_exception_tables;
return
DW_DLV_OK;
}
int
dwarf_get_cie_info_b(Dwarf_Cie cie,
Dwarf_Unsigned *bytes_in_cie,
Dwarf_Small *ptr_to_version,
char
**augmenter,
Dwarf_Unsigned *code_alignment_factor,
Dwarf_Signed *data_alignment_factor,
Dwarf_Half *return_address_register,
Dwarf_Byte_Ptr *initial_instructions,
Dwarf_Unsigned *initial_instructions_length,
Dwarf_Half *offset_size,
Dwarf_Error *error)
{
Dwarf_Debug dbg = 0;
if
(!cie) {
_dwarf_error(NULL, error, DW_DLE_CIE_NULL);
return
DW_DLV_ERROR;
}
dbg = cie->ci_dbg;
if
(IS_INVALID_DBG(dbg)) {
_dwarf_error_string(NULL, error, DW_DLE_CIE_DBG_NULL,
"DW_DLE_CIE_DBG_NULL: Either null or it contains"
"a stale Dwarf_Debug pointer"
);
return
DW_DLV_ERROR;
}
if
(ptr_to_version != NULL)
*ptr_to_version =
(Dwarf_Small)cie->ci_cie_version_number;
if
(augmenter != NULL)
*augmenter = cie->ci_augmentation;
if
(code_alignment_factor != NULL)
*code_alignment_factor = cie->ci_code_alignment_factor;
if
(data_alignment_factor != NULL)
*data_alignment_factor = cie->ci_data_alignment_factor;
if
(return_address_register != NULL)
*return_address_register =
(Dwarf_Half)cie->ci_return_address_register;
if
(initial_instructions != NULL)
*initial_instructions = cie->ci_cie_instr_start;
if
(initial_instructions_length != NULL) {
*initial_instructions_length = cie->ci_length +
cie->ci_length_size +
cie->ci_extension_size -
(cie->ci_cie_instr_start - cie->ci_cie_start);
}
if
(offset_size) {
*offset_size = cie->ci_length_size;
}
*bytes_in_cie = (cie->ci_length);
return
DW_DLV_OK;
}
static
int
_dwarf_get_fde_info_for_a_pc_row(Dwarf_Fde fde,
Dwarf_Addr pc_requested,
Dwarf_Frame table,
Dwarf_Unsigned cfa_reg_col_num,
Dwarf_Bool * has_more_rows,
Dwarf_Addr * subsequent_pc,
Dwarf_Error * error)
{
Dwarf_Debug dbg = 0;
Dwarf_Cie cie = 0;
int
res = 0;
if
(fde == NULL) {
_dwarf_error(NULL, error, DW_DLE_FDE_NULL);
return
DW_DLV_ERROR;
}
dbg = fde->fd_dbg;
if
(IS_INVALID_DBG(dbg)) {
_dwarf_error(NULL, error, DW_DLE_FDE_DBG_NULL);
return
DW_DLV_ERROR;
}
if
(pc_requested < fde->fd_initial_location ||
pc_requested >=
fde->fd_initial_location + fde->fd_address_range) {
_dwarf_error(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE);
return
DW_DLV_ERROR;
}
cie = fde->fd_cie;
if
(cie->ci_initial_table == NULL) {
Dwarf_Small *instrstart = cie->ci_cie_instr_start;
Dwarf_Small *instrend = instrstart +cie->ci_length +
cie->ci_length_size +
cie->ci_extension_size -
(cie->ci_cie_instr_start -
cie->ci_cie_start);
if
(instrend > cie->ci_cie_end) {
_dwarf_error(dbg, error,DW_DLE_CIE_INSTR_PTR_ERROR);
return
DW_DLV_ERROR;
}
cie->ci_initial_table = (Dwarf_Frame)_dwarf_get_alloc(dbg,
DW_DLA_FRAME, 1);
if
(cie->ci_initial_table == NULL) {
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
return
DW_DLV_ERROR;
}
_dwarf_init_reg_rules_ru(cie->ci_initial_table->fr_reg,
0, cie->ci_initial_table->fr_reg_count,
dbg->de_frame_rule_initial_value);
_dwarf_init_reg_rules_ru(&cie->ci_initial_table->fr_cfa_rule,
0,1,dbg->de_frame_rule_initial_value);
res = _dwarf_exec_frame_instr(
FALSE,
FALSE,
0,
0,
instrstart,
instrend,
cie->ci_initial_table,
cie, dbg,
cfa_reg_col_num,
has_more_rows,
subsequent_pc,
NULL,NULL,
error);
if
(res != DW_DLV_OK) {
return
res;
}
}
{
Dwarf_Small *instr_end = fde->fd_length +
fde->fd_length_size +
fde->fd_extension_size + fde->fd_fde_start;
if
(instr_end > fde->fd_fde_end) {
_dwarf_error(dbg, error,DW_DLE_FDE_INSTR_PTR_ERROR);
return
DW_DLV_ERROR;
}
res = _dwarf_exec_frame_instr(
FALSE,
TRUE,
pc_requested,
fde->fd_initial_location,
fde->fd_fde_instr_start,
instr_end,
table,
cie,dbg,
cfa_reg_col_num,
has_more_rows,
subsequent_pc,
NULL,NULL,
error);
}
if
(res != DW_DLV_OK) {
return
res;
}
return
DW_DLV_OK;
}
int
dwarf_get_fde_info_for_all_regs3_b(Dwarf_Fde fde,
Dwarf_Addr pc_requested,
Dwarf_Regtable3 * reg_table,
Dwarf_Addr * row_pc,
Dwarf_Bool * has_more_rows,
Dwarf_Addr * subsequent_pc,
Dwarf_Error * error)
{
struct
Dwarf_Frame_s fde_table;
Dwarf_Unsigned i = 0;
int
res = 0;
struct
Dwarf_Reg_Rule_s *rule = NULL;
Dwarf_Regtable_Entry3_i *rule_i = NULL;
Dwarf_Debug dbg = 0;
Dwarf_Unsigned output_table_real_data_size = 0;
Dwarf_Regtable3_i reg_table_i;
memset
(®_table_i,0,
sizeof
(reg_table_i));
memset
(&fde_table,0,
sizeof
(fde_table));
FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg);
output_table_real_data_size = reg_table->rt3_reg_table_size;
reg_table_i.rt3_reg_table_size = output_table_real_data_size;
output_table_real_data_size =
MIN(output_table_real_data_size,
dbg->de_frame_reg_rules_entry_count);
res = _dwarf_initialize_fde_table(dbg, &fde_table,
output_table_real_data_size,
error);
if
(res != DW_DLV_OK) {
return
res;
}
reg_table_i.rt3_rules =
calloc
(reg_table->rt3_reg_table_size,
sizeof
(Dwarf_Regtable_Entry3_i));
if
(!reg_table_i.rt3_rules) {
_dwarf_free_fde_table(&fde_table);
_dwarf_error_string(dbg,error,
DW_DLE_ALLOC_FAIL,
"Failure allocating Dwarf_Regtable_Entry3_i "
"in dwarf_get_fde_info_for_all_regs3()"
);
return
DW_DLV_ERROR;
}
res = _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested,
&fde_table,
dbg->de_frame_cfa_col_number,
has_more_rows,subsequent_pc,
error);
if
(res != DW_DLV_OK) {
free
(reg_table_i.rt3_rules);
reg_table_i.rt3_rules = 0;
_dwarf_free_fde_table(&fde_table);
return
res;
}
rule_i = ®_table_i.rt3_rules[0];
rule = &fde_table.fr_reg[0];
for
(i = 0; i < output_table_real_data_size;
i++, ++rule_i, ++rule) {
rule_i->dw_offset_relevant = rule->ru_is_offset;
rule_i->dw_args_size = rule->ru_args_size;
rule_i->dw_value_type = rule->ru_value_type;
rule_i->dw_regnum = rule->ru_register;
rule_i->dw_offset = (Dwarf_Unsigned)rule->ru_offset;
rule_i->dw_block = rule->ru_block;
}
_dwarf_init_reg_rules_dw3(®_table_i.rt3_rules[0],
i, reg_table_i.rt3_reg_table_size,
dbg->de_frame_undefined_value_number);
{
Dwarf_Unsigned j = 0;
Dwarf_Regtable_Entry3 *targ = ®_table->rt3_rules[0];
Dwarf_Regtable_Entry3_i *src = ®_table_i.rt3_rules[0];
for
( ; j < reg_table->rt3_reg_table_size;
++j, targ++,src++) {
targ->dw_offset_relevant = src->dw_offset_relevant;
targ->dw_args_size = src->dw_args_size;
targ->dw_value_type = src->dw_value_type;
targ->dw_regnum = (Dwarf_Half)src->dw_regnum;
targ->dw_offset= (Dwarf_Unsigned)src->dw_offset;
targ->dw_block = src->dw_block;
}
}
reg_table->rt3_cfa_rule.dw_offset_relevant =
fde_table.fr_cfa_rule.ru_is_offset;
reg_table->rt3_cfa_rule.dw_value_type =
fde_table.fr_cfa_rule.ru_value_type;
reg_table->rt3_cfa_rule.dw_regnum =
(Dwarf_Half)fde_table.fr_cfa_rule.ru_register;
reg_table->rt3_cfa_rule.dw_offset =
(Dwarf_Unsigned)fde_table.fr_cfa_rule.ru_offset;
reg_table->rt3_cfa_rule.dw_block =
fde_table.fr_cfa_rule.ru_block;
reg_table->rt3_cfa_rule.dw_args_size =
fde_table.fr_cfa_rule.ru_args_size;
if
(row_pc != NULL) {
*row_pc = fde_table.fr_loc;
}
free
(reg_table_i.rt3_rules);
reg_table_i.rt3_rules = 0;
reg_table_i.rt3_reg_table_size = 0;
_dwarf_free_fde_table(&fde_table);
return
DW_DLV_OK;
}
int
dwarf_get_fde_info_for_all_regs3(Dwarf_Fde fde,
Dwarf_Addr pc_requested,
Dwarf_Regtable3 * reg_table,
Dwarf_Addr * row_pc,
Dwarf_Error * error)
{
int
res = dwarf_get_fde_info_for_all_regs3_b(fde,pc_requested,
reg_table,row_pc,NULL,NULL,error);
return
res;
}
int
dwarf_get_fde_info_for_reg3_b(Dwarf_Fde fde,
Dwarf_Half table_column,
Dwarf_Addr requested,
Dwarf_Small *value_type,
Dwarf_Unsigned *offset_relevant,
Dwarf_Unsigned *register_num,
Dwarf_Unsigned *offset,
Dwarf_Block *block,
Dwarf_Addr *row_pc_out,
Dwarf_Bool *has_more_rows,
Dwarf_Addr *subsequent_pc,
Dwarf_Error *error)
{
Dwarf_Signed soff = 0;
int
res = 0;
res = dwarf_get_fde_info_for_reg3_c(
fde,table_column,requested,
value_type,offset_relevant,
register_num,&soff,
block,row_pc_out,has_more_rows,
subsequent_pc,error);
if
(offset) {
*offset = (Dwarf_Unsigned)soff;
}
return
res;
}
int
dwarf_get_fde_info_for_reg3_c(Dwarf_Fde fde,
Dwarf_Half table_column,
Dwarf_Addr pc_requested,
Dwarf_Small *value_type,
Dwarf_Unsigned *offset_relevant,
Dwarf_Unsigned *register_num,
Dwarf_Signed *offset,
Dwarf_Block *block,
Dwarf_Addr *row_pc_out,
Dwarf_Bool *has_more_rows,
Dwarf_Addr *subsequent_pc,
Dwarf_Error *error)
{
struct
Dwarf_Frame_s * fde_table = &(fde->fd_fde_table);
int
res = DW_DLV_ERROR;
Dwarf_Debug dbg = 0;
Dwarf_Unsigned table_real_data_size = 0;
FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg);
if
(!fde->fd_have_fde_tab ||
fde->fd_fde_pc_requested != pc_requested) {
if
(fde->fd_have_fde_tab) {
_dwarf_free_fde_table(fde_table);
fde->fd_have_fde_tab = FALSE;
}
table_real_data_size = dbg->de_frame_reg_rules_entry_count;
res = _dwarf_initialize_fde_table(dbg, fde_table,
table_real_data_size, error);
if
(res != DW_DLV_OK) {
return
res;
}
if
(table_column >= table_real_data_size) {
_dwarf_free_fde_table(fde_table);
fde->fd_have_fde_tab = FALSE;
_dwarf_error(dbg, error, DW_DLE_FRAME_TABLE_COL_BAD);
return
DW_DLV_ERROR;
}
res = _dwarf_get_fde_info_for_a_pc_row(fde,
pc_requested, fde_table,
dbg->de_frame_cfa_col_number,
has_more_rows,subsequent_pc,
error);
if
(res != DW_DLV_OK) {
_dwarf_free_fde_table(fde_table);
fde->fd_have_fde_tab = FALSE;
return
res;
}
}
if
(register_num) {
*register_num = fde_table->fr_reg[table_column].ru_register;
}
if
(offset) {
*offset = fde_table->fr_reg[table_column].ru_offset;
}
if
(row_pc_out != NULL) {
*row_pc_out = fde_table->fr_loc;
}
if
(block) {
*block = fde_table->fr_reg[table_column].ru_block;
}
*value_type = fde_table->fr_reg[table_column].ru_value_type;
*offset_relevant = (fde_table->fr_reg[table_column].ru_is_offset);
fde->fd_have_fde_tab = TRUE;
fde->fd_fde_pc_requested = pc_requested;
return
DW_DLV_OK;
}
int
dwarf_get_fde_info_for_cfa_reg3_b(Dwarf_Fde fde,
Dwarf_Addr pc_requested,
Dwarf_Small *value_type,
Dwarf_Unsigned *offset_relevant,
Dwarf_Unsigned *register_num,
Dwarf_Unsigned *offset,
Dwarf_Block *block,
Dwarf_Addr *row_pc_out,
Dwarf_Bool *has_more_rows,
Dwarf_Addr *subsequent_pc,
Dwarf_Error *error)
{
Dwarf_Signed soff = 0;
int
res = 0;
res = dwarf_get_fde_info_for_cfa_reg3_c(fde,
pc_requested, value_type,offset_relevant,
register_num,&soff,block, row_pc_out,
has_more_rows,subsequent_pc,error);
if
(offset) {
*offset = (Dwarf_Unsigned)soff;
}
return
res;
}
int
dwarf_get_fde_info_for_cfa_reg3_c(Dwarf_Fde fde,
Dwarf_Addr pc_requested,
Dwarf_Small *value_type,
Dwarf_Unsigned *offset_relevant,
Dwarf_Unsigned *register_num,
Dwarf_Signed *offset,
Dwarf_Block *block,
Dwarf_Addr *row_pc_out,
Dwarf_Bool *has_more_rows,
Dwarf_Addr *subsequent_pc,
Dwarf_Error *error)
{
struct
Dwarf_Frame_s fde_table;
int
res = DW_DLV_ERROR;
Dwarf_Debug dbg = 0;
Dwarf_Unsigned table_real_data_size = 0;
FDE_NULL_CHECKS_AND_SET_DBG(fde, dbg);
table_real_data_size = dbg->de_frame_reg_rules_entry_count;
res = _dwarf_initialize_fde_table(dbg, &fde_table,
table_real_data_size, error);
if
(res != DW_DLV_OK)
return
res;
res = _dwarf_get_fde_info_for_a_pc_row(fde, pc_requested,
&fde_table,
dbg->de_frame_cfa_col_number,has_more_rows,
subsequent_pc,error);
if
(res != DW_DLV_OK) {
_dwarf_free_fde_table(&fde_table);
return
res;
}
if
(register_num) {
*register_num = fde_table.fr_cfa_rule.ru_register;
}
if
(offset) {
*offset = fde_table.fr_cfa_rule.ru_offset;
}
if
(row_pc_out != NULL) {
*row_pc_out = fde_table.fr_loc;
}
if
(block) {
*block = fde_table.fr_cfa_rule.ru_block;
}
*value_type = fde_table.fr_cfa_rule.ru_value_type;
*offset_relevant = fde_table.fr_cfa_rule.ru_is_offset;
_dwarf_free_fde_table(&fde_table);
return
DW_DLV_OK;
}
int
dwarf_get_fde_instr_bytes(Dwarf_Fde inFde,
Dwarf_Small ** outinstrs,
Dwarf_Unsigned * outinstrslen,
Dwarf_Error * error)
{
Dwarf_Unsigned len = 0;
Dwarf_Small *instrs = 0;
Dwarf_Debug dbg = 0;
if
(!inFde) {
_dwarf_error(dbg, error, DW_DLE_FDE_NULL);
return
DW_DLV_ERROR;
}
dbg = inFde->fd_dbg;
if
(IS_INVALID_DBG(dbg)) {
_dwarf_error_string(NULL, error, DW_DLE_FDE_DBG_NULL,
"DW_DLE_FDE_DBG_NULL: Either null or it contains"
"a stale Dwarf_Debug pointer"
);
return
DW_DLV_ERROR;
}
instrs = inFde->fd_fde_instr_start;
len = inFde->fd_fde_end - inFde->fd_fde_instr_start;
*outinstrs = instrs;
*outinstrslen = len;
return
DW_DLV_OK;
}
int
dwarf_get_fde_n(Dwarf_Fde * fde_data,
Dwarf_Unsigned fde_index,
Dwarf_Fde * returned_fde, Dwarf_Error * error)
{
Dwarf_Debug dbg = 0;
Dwarf_Unsigned fdecount = 0;
if
(fde_data == NULL) {
_dwarf_error(dbg, error, DW_DLE_FDE_PTR_NULL);
return
DW_DLV_ERROR;
}
FDE_NULL_CHECKS_AND_SET_DBG(*fde_data, dbg);
fdecount = fde_data[0]->fd_is_eh?
dbg->de_fde_count_eh:dbg->de_fde_count;
if
(fde_index >= fdecount) {
return
DW_DLV_NO_ENTRY;
}
*returned_fde = (*(fde_data + fde_index));
return
DW_DLV_OK;
}
int
dwarf_get_fde_at_pc(Dwarf_Fde * fde_data,
Dwarf_Addr pc_of_interest,
Dwarf_Fde * returned_fde,
Dwarf_Addr * lopc,
Dwarf_Addr * hipc, Dwarf_Error * error)
{
Dwarf_Debug dbg = NULL;
Dwarf_Fde fde = NULL;
Dwarf_Fde entryfde = NULL;
Dwarf_Signed fdecount = 0;
if
(fde_data == NULL) {
_dwarf_error(NULL, error, DW_DLE_FDE_PTR_NULL);
return
DW_DLV_ERROR;
}
entryfde = *fde_data;
FDE_NULL_CHECKS_AND_SET_DBG(entryfde, dbg);
fdecount = entryfde->fd_is_eh?
dbg->de_fde_count_eh:dbg->de_fde_count;
{
Dwarf_Signed low = 0;
Dwarf_Signed high = fdecount - 1L;
Dwarf_Signed middle = 0;
Dwarf_Fde cur_fde;
while
(low <= high) {
middle = (low + high) / 2;
cur_fde = fde_data[middle];
if
(pc_of_interest < cur_fde->fd_initial_location) {
high = middle - 1;
}
else
if
(pc_of_interest >=
(cur_fde->fd_initial_location +
cur_fde->fd_address_range)) {
low = middle + 1;
}
else
{
fde = fde_data[middle];
break
;
}
}
}
if
(fde) {
if
(lopc != NULL)
*lopc = fde->fd_initial_location;
if
(hipc != NULL)
*hipc =
fde->fd_initial_location + fde->fd_address_range - 1;
*returned_fde = fde;
return
DW_DLV_OK;
}
return
DW_DLV_NO_ENTRY;
}
int
dwarf_expand_frame_instructions(Dwarf_Cie cie,
Dwarf_Small *instruction,
Dwarf_Unsigned i_length,
Dwarf_Frame_Instr_Head * returned_instr_head,
Dwarf_Unsigned * returned_instr_count,
Dwarf_Error * error)
{
int
res = DW_DLV_ERROR;
Dwarf_Debug dbg = 0;
Dwarf_Small * instr_start = instruction;
Dwarf_Small * instr_end = (Dwarf_Small *)instruction + i_length;;
if
(cie == 0) {
_dwarf_error(NULL, error, DW_DLE_DBG_NULL);
return
DW_DLV_ERROR;
}
dbg = cie->ci_dbg;
if
(!returned_instr_head || !returned_instr_count) {
_dwarf_error_string(dbg, error, DW_DLE_RET_OP_LIST_NULL,
"DW_DLE_RET_OP_LIST_NULL: "
"Calling dwarf_expand_frame_instructions without "
"a non-NULL Dwarf_Frame_Instr_Head pointer and "
"count pointer seems wrong."
);
return
DW_DLV_ERROR;
}
if
( instr_end < instr_start) {
_dwarf_error(dbg, error,DW_DLE_FDE_INSTR_PTR_ERROR);
return
DW_DLV_ERROR;
}
res = _dwarf_exec_frame_instr(
TRUE,
FALSE,
0,
0,
instr_start,
instr_end,
NULL,
cie,
dbg,
dbg->de_frame_cfa_col_number,
0,
0,
returned_instr_head,
returned_instr_count,
error);
if
(res != DW_DLV_OK) {
return
res;
}
return
DW_DLV_OK;
}
int
dwarf_get_frame_instruction(Dwarf_Frame_Instr_Head head,
Dwarf_Unsigned instr_index,
Dwarf_Unsigned * instr_offset_in_instrs,
Dwarf_Small * cfa_operation,
const
char
** fields_description,
Dwarf_Unsigned * u0,
Dwarf_Unsigned * u1,
Dwarf_Signed * s0,
Dwarf_Signed * s1,
Dwarf_Unsigned * code_alignment_factor,
Dwarf_Signed * data_alignment_factor,
Dwarf_Block * expression_block,
Dwarf_Error * error)
{
Dwarf_Unsigned aspace = 0;
return
dwarf_get_frame_instruction_a(head,
instr_index,
instr_offset_in_instrs,
cfa_operation,
fields_description,
u0,
u1,
& aspace,
s0,
s1,
code_alignment_factor,
data_alignment_factor,
expression_block,
error);
}
int
dwarf_get_frame_instruction_a(Dwarf_Frame_Instr_Head head,
Dwarf_Unsigned instr_index,
Dwarf_Unsigned * instr_offset_in_instrs,
Dwarf_Small * cfa_operation,
const
char
** fields_description,
Dwarf_Unsigned * u0,
Dwarf_Unsigned * u1,
Dwarf_Unsigned * u2,
Dwarf_Signed * s0,
Dwarf_Signed * s1,
Dwarf_Unsigned * code_alignment_factor,
Dwarf_Signed * data_alignment_factor,
Dwarf_Block * expression_block,
Dwarf_Error * error)
{
Dwarf_Frame_Instr ip = 0;
Dwarf_Debug dbg = 0;
if
(!head) {
_dwarf_error_string(dbg, error,DW_DLE_CFA_INSTRUCTION_ERROR,
"DW_DLE_CFA_INSTRUCTION_ERROR: Head argument NULL "
" calling dwarf_get_frame_instruction"
);
return
DW_DLV_ERROR;
}
if
(!head->fh_dbg) {
_dwarf_error_string(dbg, error,DW_DLE_CFA_INSTRUCTION_ERROR,
"DW_DLE_CFA_INSTRUCTION_ERROR: Head missing "
"Dwarf_Debug field "
" calling dwarf_get_frame_instruction"
);
return
DW_DLV_ERROR;
}
dbg = head->fh_dbg;
if
(instr_index >= head->fh_array_count) {
return
DW_DLV_NO_ENTRY;
}
ip = head->fh_array[instr_index];
if
(!ip) {
_dwarf_error_string(dbg, error,DW_DLE_CFA_INSTRUCTION_ERROR,
"DW_DLE_CFA_INSTRUCTION_ERROR: instr array missing "
"calling dwarf_get_frame_instruction"
);
return
DW_DLV_ERROR;
}
*instr_offset_in_instrs = ip->fi_instr_offset;
*cfa_operation = ip->fi_op;
*fields_description = ip->fi_fields;
*u0 = ip->fi_u0;
*u1 = ip->fi_u1;
*u2 = ip->fi_u2;
*s0 = ip->fi_s0;
*s1 = ip->fi_s1;
if
(code_alignment_factor) {
*code_alignment_factor = ip->fi_code_align_factor;
}
if
(data_alignment_factor) {
*data_alignment_factor = ip->fi_data_align_factor;
}
*expression_block = ip->fi_expr;
return
DW_DLV_OK;
}
int
_dwarf_fde_section_offset(Dwarf_Debug dbg, Dwarf_Fde in_fde,
Dwarf_Off * fde_off, Dwarf_Off * cie_off,
Dwarf_Error * error)
{
return
dwarf_fde_section_offset(dbg,in_fde,fde_off,
cie_off,error);
}
int
dwarf_fde_section_offset(Dwarf_Debug dbg, Dwarf_Fde in_fde,
Dwarf_Off * fde_off, Dwarf_Off * cie_off,
Dwarf_Error * error)
{
char
*start = 0;
char
*loc = 0;
CHECK_DBG(dbg,error,
"dwarf_fde_section_offset()"
);
if
(!in_fde) {
_dwarf_error(dbg, error, DW_DLE_FDE_NULL);
return
DW_DLV_ERROR;
}
start = (
char
*) in_fde->fd_section_ptr;
loc = (
char
*) in_fde->fd_fde_start;
*fde_off = (loc - start);
*cie_off = in_fde->fd_cie_offset;
return
DW_DLV_OK;
}
int
_dwarf_cie_section_offset(Dwarf_Debug dbg, Dwarf_Cie in_cie,
Dwarf_Off * cie_off, Dwarf_Error * error)
{
return
dwarf_cie_section_offset(dbg,in_cie,cie_off,error);
}
int
dwarf_cie_section_offset(Dwarf_Debug dbg, Dwarf_Cie in_cie,
Dwarf_Off * cie_off, Dwarf_Error * error)
{
char
*start = 0;
char
*loc = 0;
CHECK_DBG(dbg,error,
"dwarf_cie_section_offset()"
);
if
(!in_cie) {
_dwarf_error(dbg, error, DW_DLE_CIE_NULL);
return
DW_DLV_ERROR;
}
start = (
char
*) in_cie->ci_section_ptr;
loc = (
char
*) in_cie->ci_cie_start;
*cie_off = (loc - start);
return
DW_DLV_OK;
}
int
dwarf_get_cie_augmentation_data(Dwarf_Cie cie,
Dwarf_Small ** augdata,
Dwarf_Unsigned * augdata_len,
Dwarf_Error * error)
{
if
(cie == NULL) {
_dwarf_error(NULL, error, DW_DLE_CIE_NULL);
return
DW_DLV_ERROR;
}
if
(cie->ci_gnu_eh_augmentation_len == 0) {
return
DW_DLV_NO_ENTRY;
}
*augdata = (Dwarf_Small *) (cie->ci_gnu_eh_augmentation_bytes);
*augdata_len = cie->ci_gnu_eh_augmentation_len;
return
DW_DLV_OK;
}
int
dwarf_get_fde_augmentation_data(Dwarf_Fde fde,
Dwarf_Small * *augdata,
Dwarf_Unsigned * augdata_len,
Dwarf_Error * error)
{
Dwarf_Cie cie = 0;
if
(fde == NULL) {
_dwarf_error(NULL, error, DW_DLE_FDE_NULL);
return
DW_DLV_ERROR;
}
if
(!fde->fd_gnu_eh_aug_present) {
return
DW_DLV_NO_ENTRY;
}
cie = fde->fd_cie;
if
(cie == NULL) {
_dwarf_error(NULL, error, DW_DLE_CIE_NULL);
return
DW_DLV_ERROR;
}
*augdata = (Dwarf_Small *) fde->fd_gnu_eh_augmentation_bytes;
*augdata_len = fde->fd_gnu_eh_augmentation_len;
return
DW_DLV_OK;
}
#if 0 /* dump_frame_rule() FOR DEBUGGING */
static
void
dump_frame_rule(
char
*msg,
struct
Dwarf_Reg_Rule_s *reg_rule)
{
printf
(
"%s type %s (0x%"
DW_PR_XZEROS DW_PR_DUx
"), is_off %"
DW_PR_DUu
" reg %"
DW_PR_DUu
" offset 0x%"
DW_PR_XZEROS DW_PR_DUx
" blockp 0x%"
DW_PR_XZEROS DW_PR_DUx
"\n"
,
msg,
(reg_rule->ru_value_type == DW_EXPR_OFFSET) ?
"DW_EXPR_OFFSET"
:
(reg_rule->ru_value_type == DW_EXPR_VAL_OFFSET) ?
"DW_EXPR_VAL_OFFSET"
:
(reg_rule->ru_value_type == DW_EXPR_VAL_EXPRESSION) ?
"DW_EXPR_VAL_EXPRESSION"
:
(reg_rule->ru_value_type == DW_EXPR_EXPRESSION) ?
"DW_EXPR_EXPRESSION"
:
"Unknown"
,
(Dwarf_Unsigned) reg_rule->ru_value_type,
(Dwarf_Unsigned) reg_rule->ru_is_off,
(Dwarf_Unsigned) reg_rule->ru_register,
(Dwarf_Unsigned) reg_rule->ru_offset_or_block_len,
(Dwarf_Unsigned) reg_rule->ru_block);
return
;
}
#endif /*0*/
Dwarf_Half
dwarf_set_frame_rule_initial_value(Dwarf_Debug dbg,
Dwarf_Half value)
{
Dwarf_Half orig =
(Dwarf_Half)dbg->de_frame_rule_initial_value;
dbg->de_frame_rule_initial_value = value;
return
orig;
}
Dwarf_Half
dwarf_set_frame_rule_table_size(Dwarf_Debug dbg, Dwarf_Half value)
{
Dwarf_Half orig =
(Dwarf_Half)dbg->de_frame_reg_rules_entry_count;
dbg->de_frame_reg_rules_entry_count = value;
if
(value < DW_FRAME_LAST_REG_NUM) {
dbg->de_frame_reg_rules_entry_count = DW_FRAME_LAST_REG_NUM;
}
return
orig;
}
Dwarf_Half
dwarf_set_frame_cfa_value(Dwarf_Debug dbg, Dwarf_Half value)
{
Dwarf_Half orig = (Dwarf_Half)dbg->de_frame_cfa_col_number;
dbg->de_frame_cfa_col_number = value;
return
orig;
}
Dwarf_Half
dwarf_set_frame_same_value(Dwarf_Debug dbg, Dwarf_Half value)
{
Dwarf_Half orig =
(Dwarf_Half)dbg->de_frame_same_value_number;
dbg->de_frame_same_value_number = value;
return
orig;
}
Dwarf_Half
dwarf_set_frame_undefined_value(Dwarf_Debug dbg, Dwarf_Half value)
{
Dwarf_Half orig =
(Dwarf_Half)dbg->de_frame_same_value_number;
dbg->de_frame_undefined_value_number = value;
return
orig;
}
Dwarf_Small
dwarf_set_default_address_size(Dwarf_Debug dbg,
Dwarf_Small value )
{
Dwarf_Small orig = dbg->de_pointer_size;
if
(value > 0 && value <=
sizeof
(Dwarf_Addr)) {
dbg->de_pointer_size = value;
}
return
orig;
}
static
int
init_reg_rules_alloc(Dwarf_Debug dbg,
struct
Dwarf_Frame_s *f,
Dwarf_Unsigned count, Dwarf_Error * error)
{
f->fr_reg_count = count;
f->fr_reg = (
struct
Dwarf_Reg_Rule_s *)
calloc
((
size_t
)count,
sizeof
(
struct
Dwarf_Reg_Rule_s));
if
(f->fr_reg == 0) {
if
(error) {
_dwarf_error(dbg, error, DW_DLE_DF_ALLOC_FAIL);
}
return
DW_DLV_ERROR;
}
_dwarf_init_reg_rules_ru(f->fr_reg,0, count,
dbg->de_frame_rule_initial_value);
return
DW_DLV_OK;
}
static
int
_dwarf_initialize_fde_table(Dwarf_Debug dbg,
struct
Dwarf_Frame_s *fde_table,
Dwarf_Unsigned table_real_data_size,
Dwarf_Error * error)
{
unsigned entry_size =
sizeof
(
struct
Dwarf_Frame_s);
memset
(fde_table,0,entry_size);
fde_table->fr_loc = 0;
fde_table->fr_next = 0;
return
init_reg_rules_alloc(dbg,fde_table,
table_real_data_size,error);
}
static
void
_dwarf_free_fde_table(
struct
Dwarf_Frame_s *fde_table)
{
free
(fde_table->fr_reg);
fde_table->fr_reg_count = 0;
fde_table->fr_reg = 0;
}
int
_dwarf_frame_constructor(Dwarf_Debug dbg,
void
*frame)
{
struct
Dwarf_Frame_s *fp = frame;
if
(IS_INVALID_DBG(dbg)) {
return
DW_DLV_ERROR;
}
return
init_reg_rules_alloc(dbg,fp,
dbg->de_frame_reg_rules_entry_count, 0);
}
void
_dwarf_frame_destructor(
void
*frame)
{
struct
Dwarf_Frame_s *fp = frame;
_dwarf_free_fde_table(fp);
}
void
_dwarf_fde_destructor(
void
*f)
{
struct
Dwarf_Fde_s *fde = f;
if
(fde->fd_fde_owns_cie) {
Dwarf_Debug dbg = fde->fd_dbg;
if
(!dbg->de_in_tdestroy) {
dwarf_dealloc(fde->fd_dbg,fde->fd_cie,DW_DLA_CIE);
fde->fd_cie = 0;
}
}
if
(fde->fd_have_fde_tab) {
_dwarf_free_fde_table(&fde->fd_fde_table);
fde->fd_have_fde_tab = FALSE;
}
}
void
_dwarf_frame_instr_destructor(
void
*f)
{
Dwarf_Frame_Instr_Head head = f;
Dwarf_Debug dbg = head->fh_dbg;
Dwarf_Unsigned count = head->fh_array_count;
Dwarf_Unsigned i = 0;
for
( ; i < count ; ++i) {
free
(head->fh_array[i]);
head->fh_array[i] = 0;
}
dwarf_dealloc(dbg,head->fh_array,DW_DLA_LIST);
head->fh_array = 0;
head->fh_array_count = 0;
}
void
dwarf_dealloc_frame_instr_head(Dwarf_Frame_Instr_Head h)
{
if
(!h) {
return
;
}
dwarf_dealloc(h->fh_dbg,h,DW_DLA_FRAME_INSTR_HEAD);
}
static
void
_dwarf_init_reg_rules_ru(
struct
Dwarf_Reg_Rule_s *base,
Dwarf_Unsigned first, Dwarf_Unsigned last,
Dwarf_Unsigned initial_value)
{
struct
Dwarf_Reg_Rule_s *r = base+first;
Dwarf_Unsigned i = first;
for
(; i < last; ++i,++r) {
r->ru_is_offset = 0;
r->ru_value_type = DW_EXPR_OFFSET;
r->ru_register = (Dwarf_Unsigned)initial_value;
r->ru_offset = 0;
r->ru_args_size = 0;
r->ru_block.bl_data = 0;
r->ru_block.bl_len = 0;
}
}
static
void
_dwarf_init_reg_rules_dw3(
Dwarf_Regtable_Entry3_i *base,
Dwarf_Unsigned first, Dwarf_Unsigned last,
Dwarf_Unsigned initial_value)
{
Dwarf_Regtable_Entry3_i *r = base+first;
Dwarf_Unsigned i = first;
for
(; i < last; ++i,++r) {
r->dw_offset_relevant = 0;
r->dw_value_type = DW_EXPR_OFFSET;
r->dw_regnum = initial_value;
r->dw_offset = 0;
r->dw_args_size = 0;
r->dw_block.bl_data = 0;
r->dw_block.bl_len = 0;
}
}