#include "config.h"
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include "dwarf_incl.h"
#include "dwarf_alloc.h"
#include "dwarf_error.h"
#include "dwarf_util.h"
#include "dwarf_frame.h"
#include "dwarf_arange.h"
#include "dwarfstring.h"
#define TRUE 1
#define FALSE 0
#if 0
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");
}
#endif
static int dwarf_find_existing_cie_ptr(Dwarf_Small * cie_ptr,
Dwarf_Cie cur_cie_ptr,
Dwarf_Cie * cie_ptr_to_use_out,
Dwarf_Cie head_cie_ptr);
static void dealloc_fde_cie_list_internal(Dwarf_Fde head_fde_ptr,
Dwarf_Cie head_cie_ptr);
static int dwarf_create_cie_from_start(Dwarf_Debug dbg,
Dwarf_Small * cie_ptr_val,
Dwarf_Small * section_ptr,
Dwarf_Unsigned section_index,
Dwarf_Unsigned section_length,
Dwarf_Small * section_ptr_end,
Dwarf_Unsigned cie_id_value,
Dwarf_Unsigned cie_count,
int use_gnu_cie_calc,
Dwarf_Cie * cie_ptr_to_use_out,
Dwarf_Error * error);
static int get_gcc_eh_augmentation(Dwarf_Debug dbg,
Dwarf_Small * frame_ptr,
unsigned long
*size_of_augmentation_data,
enum Dwarf_augmentation_type augtype,
Dwarf_Small * section_end_pointer,
char *augmentation,
Dwarf_Error *error);
static int
gnu_aug_encodings(Dwarf_Debug dbg, char *augmentation,
Dwarf_Small * aug_data, Dwarf_Unsigned aug_data_len,
Dwarf_Half address_size,
unsigned char *pers_hand_enc_out,
unsigned char *lsda_enc_out,
unsigned char *fde_begin_enc_out,
Dwarf_Addr * gnu_pers_addr_out,
Dwarf_Error *error);
static int read_encoded_ptr(Dwarf_Debug dbg,
Dwarf_Small * section_pointer,
Dwarf_Small * input_field,
int gnu_encoding,
Dwarf_Small * section_ptr_end,
Dwarf_Half address_size,
Dwarf_Unsigned * addr,
Dwarf_Small ** input_field_out,
Dwarf_Error *error);
static int
qsort_compare(const void *elem1, const void *elem2)
{
const Dwarf_Fde fde1 = *(const Dwarf_Fde *) elem1;
const Dwarf_Fde fde2 = *(const Dwarf_Fde *) elem2;
Dwarf_Addr addr1 = fde1->fd_initial_location;
Dwarf_Addr addr2 = fde2->fd_initial_location;
if (addr1 < addr2) {
return -1;
} else if (addr1 > addr2) {
return 1;
}
return 0;
}
static void
chain_up_fde(Dwarf_Fde newone, Dwarf_Fde * head, Dwarf_Fde * cur)
{
if (*head == NULL)
*head = newone;
else {
(*cur)->fd_next = newone;
}
*cur = newone;
}
static void
chain_up_cie(Dwarf_Cie newone, Dwarf_Cie * head, Dwarf_Cie * cur)
{
if (*head == NULL) {
*head = newone;
} else {
(*cur)->ci_next = newone;
}
*cur = newone;
}
static void
validate_length(Dwarf_Debug dbg,
Dwarf_Cie cieptr, Dwarf_Unsigned length,
Dwarf_Unsigned length_size,
Dwarf_Unsigned extension_size,
Dwarf_Small * section_ptr,
Dwarf_Small * ciefde_start,
const char * cieorfde)
{
Dwarf_Unsigned address_size = 0;
Dwarf_Unsigned length_field_summed = length_size + extension_size;
Dwarf_Unsigned total_len = length + length_field_summed;
Dwarf_Unsigned mod = 0;
if (cieptr) {
address_size = cieptr->ci_address_size;
} else {
address_size = dbg->de_pointer_size;
}
mod = total_len % address_size;
if (mod != 0) {
dwarfstring harm;
Dwarf_Unsigned sectionoffset = ciefde_start - section_ptr;
dwarfstring_constructor(&harm);
if (!cieorfde || (strlen(cieorfde) > 3)) {
cieorfde = "ERROR!";
}
dwarfstring_append_printf_u(&harm,
"DW_DLE_DEBUG_FRAME_LENGTH_NOT_MULTIPLE"
" len=0x%" DW_PR_XZEROS DW_PR_DUx,
length);
dwarfstring_append_printf_u(&harm,
", len size=0x%" DW_PR_XZEROS DW_PR_DUx,
length_size);
dwarfstring_append_printf_u(&harm,
", extn size=0x%" DW_PR_XZEROS DW_PR_DUx,
extension_size);
dwarfstring_append_printf_u(&harm,
", totl length=0x%" DW_PR_XZEROS DW_PR_DUx,
total_len);
dwarfstring_append_printf_u(&harm,
", addr size=0x%" DW_PR_XZEROS DW_PR_DUx,
address_size);
dwarfstring_append_printf_u(&harm,
", mod=0x%" DW_PR_XZEROS DW_PR_DUx " must be zero",
mod);
dwarfstring_append_printf_s(&harm,
" in %s",(char *)cieorfde);
dwarfstring_append_printf_u(&harm,
", offset 0x%" DW_PR_XZEROS DW_PR_DUx ".",
sectionoffset);
dwarf_insert_harmless_error(dbg,
dwarfstring_string(&harm));
dwarfstring_destructor(&harm);
}
return;
}
#if 0
static void
print_prefix(struct cie_fde_prefix_s *prefix, int line)
{
printf("prefix-print, prefix at 0x%lx, line %d\n",
(unsigned long) prefix, line);
printf(" start addr 0x%lx after prefix 0x%lx\n",
(unsigned long) prefix->cf_start_addr,
(unsigned long) prefix->cf_addr_after_prefix);
printf(" length 0x%" DW_PR_DUx ", len size %d ext size %d\n",
(Dwarf_Unsigned) prefix->cf_length,
prefix->cf_local_length_size,
prefix->cf_local_extension_size);
printf(" cie_id 0x%" DW_PR_DUx " cie_id cie_id_addr 0x%lx\n",
(Dwarf_Unsigned) prefix->cf_cie_id,
(long) prefix->cf_cie_id_addr);
printf
(" sec ptr 0x%lx sec index %" DW_PR_DSd " sec len 0x%" DW_PR_DUx " sec past end 0x%lx\n",
(unsigned long) prefix->cf_section_ptr,
(Dwarf_Signed) prefix->cf_section_index,
(Dwarf_Unsigned) prefix->cf_section_length,
(unsigned long) prefix->cf_section_ptr +
(unsigned long)prefix->cf_section_length);
}
#endif
static Dwarf_Small *
get_cieptr_given_offset(Dwarf_Unsigned cie_id_value,
int use_gnu_cie_calc,
Dwarf_Small * section_ptr,
Dwarf_Small * cie_id_addr)
{
Dwarf_Small *cieptr = 0;
if (use_gnu_cie_calc) {
cieptr = cie_id_addr - cie_id_value;
} else {
cieptr = section_ptr + cie_id_value;
}
return cieptr;
}
int
_dwarf_get_fde_list_internal(Dwarf_Debug dbg, Dwarf_Cie ** cie_data,
Dwarf_Signed * cie_element_count,
Dwarf_Fde ** fde_data,
Dwarf_Signed * fde_element_count,
Dwarf_Small * section_ptr,
Dwarf_Unsigned section_index,
Dwarf_Unsigned section_length,
Dwarf_Unsigned cie_id_value,
int use_gnu_cie_calc, Dwarf_Error * error)
{
Dwarf_Small *frame_ptr = section_ptr;
Dwarf_Small *section_ptr_end = section_ptr + section_length;
Dwarf_Cie head_cie_ptr = NULL;
Dwarf_Cie cur_cie_ptr = NULL;
Dwarf_Cie tail_cie_ptr = NULL;
Dwarf_Unsigned cie_count = 0;
Dwarf_Cie *cie_list_ptr = 0;
Dwarf_Fde head_fde_ptr = NULL;
Dwarf_Fde cur_fde_ptr = NULL;
Dwarf_Unsigned fde_count = 0;
Dwarf_Fde *fde_list_ptr = NULL;
Dwarf_Unsigned i = 0;
int res = DW_DLV_ERROR;
if (frame_ptr == 0) {
return DW_DLV_NO_ENTRY;
}
while (frame_ptr < section_ptr_end) {
struct cie_fde_prefix_s prefix;
memset(&prefix, 0, sizeof(prefix));
res = dwarf_read_cie_fde_prefix(dbg,
frame_ptr, section_ptr,
section_index,
section_length, &prefix, error);
if (res == DW_DLV_ERROR) {
dealloc_fde_cie_list_internal(head_fde_ptr,
head_cie_ptr);
return res;
}
if (res == DW_DLV_NO_ENTRY) {
break;
}
frame_ptr = prefix.cf_addr_after_prefix;
if (frame_ptr >= section_ptr_end) {
dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
_dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
return DW_DLV_ERROR;
}
if (prefix.cf_cie_id == cie_id_value) {
Dwarf_Cie cie_ptr_to_use = 0;
int resc = 0;
resc = dwarf_find_existing_cie_ptr(prefix.cf_start_addr,
cur_cie_ptr,
&cie_ptr_to_use,
head_cie_ptr);
if (resc == DW_DLV_OK) {
cur_cie_ptr = cie_ptr_to_use;
} else if (resc == DW_DLV_NO_ENTRY) {
resc = dwarf_create_cie_from_after_start(dbg,
&prefix,
section_ptr,
frame_ptr,
section_ptr_end,
cie_count,
use_gnu_cie_calc,
&cie_ptr_to_use,
error);
if (resc != DW_DLV_OK) {
dealloc_fde_cie_list_internal(head_fde_ptr,
head_cie_ptr);
return resc;
}
cie_count++;
chain_up_cie(cie_ptr_to_use, &head_cie_ptr,
&tail_cie_ptr);
cur_cie_ptr = tail_cie_ptr;
} else {
dealloc_fde_cie_list_internal(head_fde_ptr,
head_cie_ptr);
return resc;
}
frame_ptr = cie_ptr_to_use->ci_cie_start +
cie_ptr_to_use->ci_length +
cie_ptr_to_use->ci_length_size +
cie_ptr_to_use->ci_extension_size;
continue;
} else {
int resf = DW_DLV_ERROR;
Dwarf_Cie cie_ptr_to_use = 0;
Dwarf_Fde fde_ptr_to_use = 0;
Dwarf_Small *cieptr_val = 0;
cieptr_val = get_cieptr_given_offset(prefix.cf_cie_id,
use_gnu_cie_calc,
section_ptr,
prefix.cf_cie_id_addr);
resf = dwarf_find_existing_cie_ptr(cieptr_val,
cur_cie_ptr,
&cie_ptr_to_use,
head_cie_ptr);
if (resf == DW_DLV_OK) {
cur_cie_ptr = cie_ptr_to_use;
} else if (resf == DW_DLV_NO_ENTRY) {
resf = dwarf_create_cie_from_start(dbg,
cieptr_val,
section_ptr,
section_index,
section_length,
section_ptr_end,
cie_id_value,
cie_count,
use_gnu_cie_calc,
&cie_ptr_to_use,
error);
if (resf == DW_DLV_ERROR) {
dealloc_fde_cie_list_internal(head_fde_ptr,
head_cie_ptr);
return resf;
} else if (resf == DW_DLV_NO_ENTRY) {
return resf;
}
++cie_count;
chain_up_cie(cie_ptr_to_use, &head_cie_ptr,
&tail_cie_ptr);
cur_cie_ptr = tail_cie_ptr;
} else {
return resf;
}
resf = dwarf_create_fde_from_after_start(dbg,
&prefix,
section_ptr,
frame_ptr,
section_ptr_end,
use_gnu_cie_calc,
cie_ptr_to_use,
&fde_ptr_to_use,
error);
if (resf == DW_DLV_ERROR) {
dealloc_fde_cie_list_internal(head_fde_ptr,
head_cie_ptr);
return resf;
} else if (resf == DW_DLV_NO_ENTRY) {
return resf;
}
chain_up_fde(fde_ptr_to_use, &head_fde_ptr, &cur_fde_ptr);
fde_count++;
frame_ptr = cur_fde_ptr->fd_fde_start +
cur_fde_ptr->fd_length +
cur_fde_ptr->fd_length_size +
cur_fde_ptr->fd_extension_size;
if (frame_ptr < fde_ptr_to_use->fd_fde_instr_start) {
dealloc_fde_cie_list_internal(head_fde_ptr,
head_cie_ptr);
_dwarf_error(dbg,error,
DW_DLE_DEBUG_FRAME_POSSIBLE_ADDRESS_BOTCH);
return DW_DLV_ERROR;
}
continue;
}
}
if (cie_count > 0) {
cie_list_ptr = (Dwarf_Cie *)
_dwarf_get_alloc(dbg, DW_DLA_LIST, cie_count);
} else {
if (fde_count > 0) {
dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
_dwarf_error(dbg, error, DW_DLE_ORPHAN_FDE);
return DW_DLV_ERROR;
}
dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
return DW_DLV_NO_ENTRY;
}
if (cie_list_ptr == NULL) {
dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
return DW_DLV_ERROR;
}
if (!head_cie_ptr) {
_dwarf_error(dbg, error,DW_DLE_DEBUGFRAME_ERROR);
return DW_DLV_ERROR;
}
cur_cie_ptr = head_cie_ptr;
for (i = 0; i < cie_count; i++) {
*(cie_list_ptr + i) = cur_cie_ptr;
cur_cie_ptr = cur_cie_ptr->ci_next;
}
if (fde_count > 0) {
fde_list_ptr = (Dwarf_Fde *)
_dwarf_get_alloc(dbg, DW_DLA_LIST, fde_count);
}
cur_fde_ptr = head_fde_ptr;
for (i = 0; i < fde_count; i++) {
*(fde_list_ptr + i) = cur_fde_ptr;
cur_fde_ptr = cur_fde_ptr->fd_next;
}
*cie_data = cie_list_ptr;
*cie_element_count = cie_count;
*fde_data = fde_list_ptr;
*fde_element_count = fde_count;
if (use_gnu_cie_calc) {
dbg->de_fde_data_eh = fde_list_ptr;
dbg->de_fde_count_eh = fde_count;
dbg->de_cie_data_eh = cie_list_ptr;
dbg->de_cie_count_eh = cie_count;
} else {
dbg->de_fde_data = fde_list_ptr;
dbg->de_fde_count = fde_count;
dbg->de_cie_data = cie_list_ptr;
dbg->de_cie_count = cie_count;
}
if (fde_count > 0) {
qsort((void *) fde_list_ptr, fde_count, sizeof(Dwarf_Ptr),
qsort_compare);
}
return (DW_DLV_OK);
}
int
dwarf_create_cie_from_after_start(Dwarf_Debug dbg,
struct cie_fde_prefix_s *prefix,
Dwarf_Small * section_pointer,
Dwarf_Small * frame_ptr,
Dwarf_Small * section_ptr_end,
Dwarf_Unsigned cie_count,
int use_gnu_cie_calc,
Dwarf_Cie * cie_ptr_out,
Dwarf_Error * error)
{
Dwarf_Cie new_cie = 0;
Dwarf_Half address_size = dbg->de_pointer_size;
Dwarf_Small *augmentation = 0;
Dwarf_Half segment_size = 0;
Dwarf_Signed data_alignment_factor = -1;
Dwarf_Unsigned code_alignment_factor = 4;
Dwarf_Unsigned return_address_register = 31;
int local_length_size = 0;
Dwarf_Unsigned leb128_length = 0;
Dwarf_Unsigned cie_aug_data_len = 0;
Dwarf_Small *cie_aug_data = 0;
Dwarf_Addr gnu_personality_handler_addr = 0;
unsigned char gnu_personality_handler_encoding = 0;
unsigned char gnu_lsda_encoding = 0;
unsigned char gnu_fde_begin_encoding = 0;
int res = 0;
Dwarf_Small version = 0;
enum Dwarf_augmentation_type augt = aug_unknown;
if (frame_ptr >= section_ptr_end) {
_dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
return DW_DLV_ERROR;
}
version = *(Dwarf_Small *) frame_ptr;
if ((frame_ptr+2) >= section_ptr_end) {
_dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
return DW_DLV_ERROR;
}
frame_ptr++;
if (version != DW_CIE_VERSION && version != DW_CIE_VERSION3 &&
version != DW_CIE_VERSION4 && version != DW_CIE_VERSION5) {
_dwarf_error(dbg, error, DW_DLE_FRAME_VERSION_BAD);
return (DW_DLV_ERROR);
}
augmentation = frame_ptr;
res = _dwarf_check_string_valid(dbg,section_pointer,
frame_ptr,section_ptr_end,
DW_DLE_AUGMENTATION_STRING_OFF_END,error);
if (res != DW_DLV_OK) {
return res;
}
frame_ptr = frame_ptr + strlen((char *) frame_ptr) + 1;
if (frame_ptr >= section_ptr_end) {
_dwarf_error_string(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD,
"DW_DLE_DEBUG_FRAME_LENGTH_BAD: following any "
"augmentation field we have run off the end of the section "
"with the CIE incomplete. Corrupt Dwarf");
return DW_DLV_ERROR;
}
augt = _dwarf_get_augmentation_type(dbg,
augmentation, use_gnu_cie_calc);
if (augt == aug_eh) {
UNUSEDARG Dwarf_Unsigned exception_table_addr;
if ((frame_ptr+local_length_size) >= section_ptr_end) {
_dwarf_error_string(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD,
"DW_DLE_DEBUG_FRAME_LENGTH_BAD: following "
"type field we have run off the end of the section "
"with the CIE incomplete. Corrupt Dwarf");
return DW_DLV_ERROR;
}
READ_UNALIGNED_CK(dbg, exception_table_addr,
Dwarf_Unsigned, frame_ptr, local_length_size,
error,section_ptr_end);
frame_ptr += local_length_size;
}
{
Dwarf_Unsigned lreg = 0;
unsigned long size = 0;
if (version == DW_CIE_VERSION4) {
if ((frame_ptr+2) >= section_ptr_end) {
_dwarf_error_string(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD,
"DW_DLE_DEBUG_FRAME_LENGTH_BAD: "
"We would run off the end of the section "
"in a DWARF4 cie header. Corrupt Dwarf");
return DW_DLV_ERROR;
}
address_size = *((unsigned char *)frame_ptr);
if (address_size < 1) {
_dwarf_error_string(dbg, error, DW_DLE_ADDRESS_SIZE_ZERO,
"DW_DLE_ADDRESS_SIZE_ZERO: bad addres size "
"for a DWARF4 cie header");
return (DW_DLV_ERROR);
}
if (address_size > sizeof(Dwarf_Addr)) {
_dwarf_create_address_size_dwarf_error(dbg,
error,address_size,
DW_DLE_ADDRESS_SIZE_ERROR,
"DW_DLE_ADDRESS_SIZE_ERROR..:");
return DW_DLV_ERROR;
}
if ((frame_ptr+2) >= section_ptr_end) {
_dwarf_error_string(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD,
"DW_DLE_DEBUG_FRAME_LENGTH_BAD: Running off the end "
" of a CIE header. Corrupt DWARF4");
return DW_DLV_ERROR;
}
++frame_ptr;
segment_size = *((unsigned char *)frame_ptr);
++frame_ptr;
if (segment_size > sizeof(Dwarf_Addr)) {
_dwarf_error(dbg, error, DW_DLE_SEGMENT_SIZE_BAD);
return (DW_DLV_ERROR);
}
}
if ((frame_ptr+2) >= section_ptr_end) {
_dwarf_error_string(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD,
"DW_DLE_DEBUG_FRAME_LENGTH_BAD: Running off the end "
" of a CIE header before the code alignment value "
"read. Corrupt DWARF");
return DW_DLV_ERROR;
}
DECODE_LEB128_UWORD_CK(frame_ptr, lreg,dbg,error,section_ptr_end);
code_alignment_factor = (Dwarf_Unsigned) lreg;
res = (Dwarf_Signed) _dwarf_decode_s_leb128_chk(frame_ptr,
&leb128_length,&data_alignment_factor,section_ptr_end);
if(res != DW_DLV_OK) {
return res;
}
frame_ptr = frame_ptr + leb128_length;
if ((frame_ptr+1) >= section_ptr_end) {
_dwarf_error_string(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD,
"DW_DLE_DEBUG_FRAME_LENGTH_BAD: Running off the end "
"of a CIE header before the return address register "
"number read. Corrupt DWARF");
return DW_DLV_ERROR;
}
res = _dwarf_get_return_address_reg(frame_ptr, version,
dbg,section_ptr_end, &size,&return_address_register,error);
if(res != DW_DLV_OK) {
return res;
}
if (return_address_register > dbg->de_frame_reg_rules_entry_count) {
_dwarf_error(dbg, error, DW_DLE_CIE_RET_ADDR_REG_ERROR);
return (DW_DLV_ERROR);
}
frame_ptr += size;
if ((frame_ptr) > section_ptr_end) {
_dwarf_error_string(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD,
"DW_DLE_DEBUG_FRAME_LENGTH_BAD: Past the end "
"of a CIE header before reading the augmentation string."
" Corrupt DWARF");
return DW_DLV_ERROR;
}
}
switch (augt) {
case aug_empty_string:
break;
case aug_irix_mti_v1:
break;
case aug_irix_exception_table:{
Dwarf_Unsigned lreg = 0;
Dwarf_Unsigned length_of_augmented_fields;
DECODE_LEB128_UWORD_CK(frame_ptr, lreg,dbg,error,section_ptr_end);
length_of_augmented_fields = (Dwarf_Unsigned) lreg;
frame_ptr += length_of_augmented_fields;
}
break;
case aug_eh:{
int err = 0;
unsigned long increment = 0;
if (!use_gnu_cie_calc) {
_dwarf_error(dbg, error,DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
return DW_DLV_ERROR;
}
err = get_gcc_eh_augmentation(dbg, frame_ptr, &increment,
augt,
section_ptr_end,
(char *) augmentation,error);
if (err == DW_DLV_ERROR) {
_dwarf_error(dbg, error,DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
return DW_DLV_ERROR;
}
frame_ptr += increment;
}
break;
case aug_gcc_eh_z:{
int resz = DW_DLV_ERROR;
Dwarf_Unsigned adlen = 0;
if ((frame_ptr+1) > section_ptr_end) {
_dwarf_error_string(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD,
"DW_DLE_AUG_DATA_LENGTH_BAD: The "
"gcc .eh_frame augmentation data "
"cannot be read. Out of room in the section."
" Corrupt DWARF.");
return DW_DLV_ERROR;
}
DECODE_LEB128_UWORD_CK(frame_ptr, adlen,
dbg,error,section_ptr_end);
cie_aug_data_len = adlen;
cie_aug_data = frame_ptr;
if (adlen) {
Dwarf_Small *cie_aug_data_end = cie_aug_data+adlen;
if (cie_aug_data_end < cie_aug_data ||
cie_aug_data_end > section_ptr_end) {
dwarfstring m;
dwarfstring_constructor(&m);
dwarfstring_append_printf_u(&m,
"DW_DLE_AUG_DATA_LENGTH_BAD: The "
"gcc .eh_frame augmentation data "
"length of %" DW_PR_DUu " is too long to"
" fit in the section.",adlen);
_dwarf_error_string(dbg, error,
DW_DLE_AUG_DATA_LENGTH_BAD,
dwarfstring_string(&m));
dwarfstring_destructor(&m);
return DW_DLV_ERROR;
}
}
resz = gnu_aug_encodings(dbg,
(char *) augmentation,
cie_aug_data,
cie_aug_data_len,
address_size,
&gnu_personality_handler_encoding,
&gnu_lsda_encoding,
&gnu_fde_begin_encoding,
&gnu_personality_handler_addr,
error);
if (resz != DW_DLV_OK) {
_dwarf_error(dbg, error,
DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
return resz;
}
frame_ptr += adlen;
}
break;
case aug_armcc:
break;
default:{
frame_ptr = prefix->cf_start_addr +
prefix->cf_length + prefix->cf_local_length_size
+ prefix->cf_local_extension_size;
}
if ((frame_ptr) > section_ptr_end) {
_dwarf_error_string(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD,
"DW_DLE_DEBUG_FRAME_LENGTH_BAD: "
"Reading an unknown type of augmentation string "
"run off the end of the section. Corrupt DWARF.");
return DW_DLV_ERROR;
}
break;
}
new_cie = (Dwarf_Cie) _dwarf_get_alloc(dbg, DW_DLA_CIE, 1);
if (new_cie == NULL) {
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
return (DW_DLV_ERROR);
}
new_cie->ci_cie_version_number = version;
new_cie->ci_initial_table = NULL;
new_cie->ci_length = (Dwarf_Unsigned) prefix->cf_length;
new_cie->ci_length_size = prefix->cf_local_length_size;
new_cie->ci_extension_size = prefix->cf_local_extension_size;
new_cie->ci_augmentation = (char *) augmentation;
new_cie->ci_data_alignment_factor =
(Dwarf_Sbyte) data_alignment_factor;
new_cie->ci_code_alignment_factor =
(Dwarf_Small) code_alignment_factor;
new_cie->ci_return_address_register = return_address_register;
new_cie->ci_cie_start = prefix->cf_start_addr;
if ( frame_ptr > section_ptr_end) {
_dwarf_error(dbg, error, DW_DLE_DF_FRAME_DECODING_ERROR);
return (DW_DLV_ERROR);
}
new_cie->ci_cie_instr_start = frame_ptr;
new_cie->ci_dbg = dbg;
new_cie->ci_augmentation_type = augt;
new_cie->ci_gnu_eh_augmentation_len = cie_aug_data_len;
new_cie->ci_gnu_eh_augmentation_bytes = cie_aug_data;
new_cie->ci_gnu_personality_handler_encoding =
gnu_personality_handler_encoding;
new_cie->ci_gnu_personality_handler_addr =
gnu_personality_handler_addr;
new_cie->ci_gnu_lsda_encoding = gnu_lsda_encoding;
new_cie->ci_gnu_fde_begin_encoding = gnu_fde_begin_encoding;
new_cie->ci_index = cie_count;
new_cie->ci_section_ptr = prefix->cf_section_ptr;
new_cie->ci_section_end = section_ptr_end;
new_cie->ci_cie_end = new_cie->ci_cie_start + new_cie->ci_length +
new_cie->ci_length_size+ new_cie->ci_extension_size;
if ( new_cie->ci_cie_end > section_ptr_end) {
_dwarf_error(dbg, error, DW_DLE_DF_FRAME_DECODING_ERROR);
return (DW_DLV_ERROR);
}
new_cie->ci_address_size = address_size;
new_cie->ci_segment_size = segment_size;
validate_length(dbg,new_cie,new_cie->ci_length,
new_cie->ci_length_size, new_cie->ci_extension_size,
new_cie->ci_section_ptr,
new_cie->ci_cie_start,"cie");
*cie_ptr_out = new_cie;
return DW_DLV_OK;
}
int
dwarf_create_fde_from_after_start(Dwarf_Debug dbg,
struct cie_fde_prefix_s *prefix,
Dwarf_Small * section_pointer,
Dwarf_Small * frame_ptr,
Dwarf_Small * section_ptr_end,
int use_gnu_cie_calc,
Dwarf_Cie cie_ptr_in,
Dwarf_Fde * fde_ptr_out,
Dwarf_Error * error)
{
Dwarf_Fde new_fde = 0;
Dwarf_Cie cieptr = 0;
Dwarf_Small *saved_frame_ptr = 0;
Dwarf_Small *initloc = frame_ptr;
Dwarf_Signed offset_into_exception_tables
= (Dwarf_Signed) DW_DLX_NO_EH_OFFSET;
Dwarf_Small *fde_aug_data = 0;
Dwarf_Unsigned fde_aug_data_len = 0;
Dwarf_Addr cie_base_offset = prefix->cf_cie_id;
Dwarf_Addr initial_location = 0;
Dwarf_Addr address_range = 0;
Dwarf_Half address_size = 0;
Dwarf_Unsigned eh_table_value = 0;
Dwarf_Bool eh_table_value_set = FALSE;
enum Dwarf_augmentation_type augt = aug_empty_string;
if (cie_ptr_in) {
cieptr = cie_ptr_in;
address_size = cieptr->ci_address_size;
augt = cieptr->ci_augmentation_type;
}
if (augt == aug_gcc_eh_z) {
{
Dwarf_Small *fp_updated = 0;
int res = read_encoded_ptr(dbg,
section_pointer,
frame_ptr,
cieptr-> ci_gnu_fde_begin_encoding,
section_ptr_end,
address_size,
&initial_location,
&fp_updated,error);
if (res != DW_DLV_OK) {
return res;
}
frame_ptr = fp_updated;
res = read_encoded_ptr(dbg, (Dwarf_Small *) NULL,
frame_ptr,
cieptr->ci_gnu_fde_begin_encoding,
section_ptr_end,
address_size,
&address_range, &fp_updated,error);
if (res != DW_DLV_OK) {
return res;
}
frame_ptr = fp_updated;
}
{
Dwarf_Unsigned adlen = 0;
DECODE_LEB128_UWORD_CK(frame_ptr, adlen,
dbg,error,section_ptr_end);
fde_aug_data_len = adlen;
fde_aug_data = frame_ptr;
frame_ptr += adlen;
if (adlen) {
if (frame_ptr < fde_aug_data ||
frame_ptr >= section_ptr_end ) {
dwarfstring m;
dwarfstring_constructor(&m);
dwarfstring_append_printf_u(&m,
"DW_DLE_AUG_DATA_LENGTH_BAD: The "
"gcc .eh_frame augmentation data "
"length of %" DW_PR_DUu " is too long to"
" fit in the section.",adlen);
_dwarf_error_string(dbg, error,
DW_DLE_AUG_DATA_LENGTH_BAD,
dwarfstring_string(&m));
dwarfstring_destructor(&m);
return DW_DLV_ERROR;
}
}
}
} else {
if ((frame_ptr + 2*address_size) > section_ptr_end) {
_dwarf_error(dbg,error,DW_DLE_DEBUG_FRAME_LENGTH_BAD);
return DW_DLV_ERROR;
}
READ_UNALIGNED_CK(dbg, initial_location, Dwarf_Addr,
frame_ptr, address_size,
error,section_ptr_end);
frame_ptr += address_size;
READ_UNALIGNED_CK(dbg, address_range, Dwarf_Addr,
frame_ptr, address_size,
error,section_ptr_end);
frame_ptr += address_size;
}
switch (augt) {
case aug_irix_mti_v1:
case aug_empty_string:
break;
case aug_irix_exception_table:{
Dwarf_Unsigned lreg = 0;
Dwarf_Unsigned length_of_augmented_fields = 0;
DECODE_LEB128_UWORD_CK(frame_ptr, lreg,
dbg,error,section_ptr_end);
length_of_augmented_fields = (Dwarf_Unsigned) lreg;
saved_frame_ptr = frame_ptr;
if ((frame_ptr + DWARF_32BIT_SIZE) > section_ptr_end) {
_dwarf_error(dbg,error,DW_DLE_DEBUG_FRAME_LENGTH_BAD);
return DW_DLV_ERROR;
}
READ_UNALIGNED_CK(dbg, offset_into_exception_tables,
Dwarf_Addr, frame_ptr, DWARF_32BIT_SIZE,
error,section_ptr_end);
SIGN_EXTEND(offset_into_exception_tables,
DWARF_32BIT_SIZE);
frame_ptr = saved_frame_ptr + length_of_augmented_fields;
}
break;
case aug_eh:{
if (!use_gnu_cie_calc) {
_dwarf_error(dbg, error,DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
return DW_DLV_ERROR;
}
if ((frame_ptr + address_size) > section_ptr_end) {
_dwarf_error(dbg,error,DW_DLE_DEBUG_FRAME_LENGTH_BAD);
return DW_DLV_ERROR;
}
READ_UNALIGNED_CK(dbg, eh_table_value,
Dwarf_Unsigned, frame_ptr,
address_size,
error,section_ptr_end);
eh_table_value_set = TRUE;
frame_ptr += address_size;
}
break;
case aug_gcc_eh_z:{
}
break;
case aug_armcc:
break;
case aug_past_last:
break;
case aug_metaware:
break;
case aug_unknown:
_dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
return DW_DLV_ERROR;
}
if ( frame_ptr > section_ptr_end) {
_dwarf_error(dbg, error, DW_DLE_DF_FRAME_DECODING_ERROR);
return (DW_DLV_ERROR);
}
new_fde = (Dwarf_Fde) _dwarf_get_alloc(dbg, DW_DLA_FDE, 1);
if (new_fde == NULL) {
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
return (DW_DLV_ERROR);
}
new_fde->fd_length = prefix->cf_length;
new_fde->fd_length_size = prefix->cf_local_length_size;
new_fde->fd_extension_size = prefix->cf_local_extension_size;
new_fde->fd_is_eh = use_gnu_cie_calc;
new_fde->fd_cie_offset = cie_base_offset;
if (cieptr) {
new_fde->fd_cie_index = cieptr->ci_index;
}
new_fde->fd_cie = cieptr;
new_fde->fd_initial_location = initial_location;
new_fde->fd_initial_loc_pos = initloc;
new_fde->fd_address_range = address_range;
new_fde->fd_fde_start = prefix->cf_start_addr;
new_fde->fd_fde_instr_start = frame_ptr;
new_fde->fd_fde_end = prefix->cf_start_addr +
prefix->cf_length + prefix->cf_local_length_size +
prefix->cf_local_extension_size;
if ( new_fde->fd_fde_end > section_ptr_end) {
_dwarf_error(dbg, error, DW_DLE_DF_FRAME_DECODING_ERROR);
return (DW_DLV_ERROR);
}
new_fde->fd_dbg = dbg;
new_fde->fd_offset_into_exception_tables =
offset_into_exception_tables;
new_fde->fd_eh_table_value = eh_table_value;
new_fde->fd_eh_table_value_set = eh_table_value_set;
new_fde->fd_section_ptr = prefix->cf_section_ptr;
new_fde->fd_section_index = prefix->cf_section_index;
new_fde->fd_section_length = prefix->cf_section_length;
new_fde->fd_section_end = section_ptr_end;
if (augt == aug_gcc_eh_z) {
new_fde->fd_gnu_eh_aug_present = TRUE;
}
new_fde->fd_gnu_eh_augmentation_bytes = fde_aug_data;
new_fde->fd_gnu_eh_augmentation_len = fde_aug_data_len;
validate_length(dbg,cieptr,new_fde->fd_length,
new_fde->fd_length_size, new_fde->fd_extension_size,
new_fde->fd_section_ptr,new_fde->fd_fde_start,"fde");
*fde_ptr_out = new_fde;
return DW_DLV_OK;
}
int
dwarf_read_cie_fde_prefix(Dwarf_Debug dbg,
Dwarf_Small * frame_ptr_in,
Dwarf_Small * section_ptr_in,
Dwarf_Unsigned section_index_in,
Dwarf_Unsigned section_length_in,
struct cie_fde_prefix_s *data_out,
Dwarf_Error * error)
{
Dwarf_Unsigned length = 0;
int local_length_size = 0;
int local_extension_size = 0;
Dwarf_Small *frame_ptr = frame_ptr_in;
Dwarf_Small *cie_ptr_addr = 0;
Dwarf_Unsigned cie_id = 0;
Dwarf_Small *section_end = section_ptr_in + section_length_in;
if(section_end < (frame_ptr +4)) {
dwarfstring m;
Dwarf_Unsigned u = (Dwarf_Unsigned)(uintptr_t)(frame_ptr+4) -
(Dwarf_Unsigned)(uintptr_t)section_end;
dwarfstring_constructor(&m);
dwarfstring_append_printf_u(&m,
"DW_DLE_DEBUG_FRAME_LENGTH_BAD: "
"Reading the cie/fde prefix would "
"put us %u bytes past the end of the "
"frame section. Corrupt Dwarf.",u);
_dwarf_error_string(dbg,error,DW_DLE_DEBUG_FRAME_LENGTH_BAD,
dwarfstring_string(&m));
dwarfstring_destructor(&m);
return DW_DLV_ERROR;
}
READ_AREA_LENGTH_CK(dbg, length, Dwarf_Unsigned,
frame_ptr, local_length_size,
local_extension_size,error,
section_length_in,section_end);
if (length == 0) {
return DW_DLV_NO_ENTRY;
}
if((frame_ptr + local_length_size) >= section_end) {
_dwarf_error(dbg,error,DW_DLE_DEBUG_FRAME_LENGTH_BAD);
return DW_DLV_ERROR;
}
cie_ptr_addr = frame_ptr;
READ_UNALIGNED_CK(dbg, cie_id, Dwarf_Unsigned,
frame_ptr, local_length_size,error,section_end);
SIGN_EXTEND(cie_id, local_length_size);
frame_ptr += local_length_size;
data_out->cf_start_addr = frame_ptr_in;
data_out->cf_addr_after_prefix = frame_ptr;
data_out->cf_length = length;
if (length > section_length_in) {
_dwarf_error(dbg,error,DW_DLE_DEBUG_FRAME_LENGTH_BAD);
return DW_DLV_ERROR;
}
if (cie_ptr_addr+length > section_end) {
_dwarf_error(dbg,error,DW_DLE_DEBUG_FRAME_LENGTH_BAD);
return DW_DLV_ERROR;
}
data_out->cf_local_length_size = local_length_size;
data_out->cf_local_extension_size = local_extension_size;
data_out->cf_cie_id = cie_id;
data_out->cf_cie_id_addr = cie_ptr_addr;
data_out->cf_section_ptr = section_ptr_in;
data_out->cf_section_index = section_index_in;
data_out->cf_section_length = section_length_in;
return DW_DLV_OK;
}
static void
dealloc_fde_cie_list_internal(Dwarf_Fde head_fde_ptr,
Dwarf_Cie head_cie_ptr)
{
Dwarf_Fde curfde = 0;
Dwarf_Cie curcie = 0;
Dwarf_Fde nextfde = 0;
Dwarf_Cie nextcie = 0;
for (curfde = head_fde_ptr; curfde; curfde = nextfde) {
nextfde = curfde->fd_next;
dwarf_dealloc(curfde->fd_dbg, curfde, DW_DLA_FDE);
}
for (curcie = head_cie_ptr; curcie; curcie = nextcie) {
Dwarf_Frame frame = curcie->ci_initial_table;
nextcie = curcie->ci_next;
if (frame)
dwarf_dealloc(curcie->ci_dbg, frame, DW_DLA_FRAME);
dwarf_dealloc(curcie->ci_dbg, curcie, DW_DLA_CIE);
}
}
static int
dwarf_find_existing_cie_ptr(Dwarf_Small * cie_ptr,
Dwarf_Cie cur_cie_ptr,
Dwarf_Cie * cie_ptr_to_use_out,
Dwarf_Cie head_cie_ptr)
{
Dwarf_Cie next = 0;
if (cur_cie_ptr && cie_ptr == cur_cie_ptr->ci_cie_start) {
*cie_ptr_to_use_out = cur_cie_ptr;
return DW_DLV_OK;
}
for (next = head_cie_ptr; next; next = next->ci_next) {
if (cie_ptr == next->ci_cie_start) {
*cie_ptr_to_use_out = next;
return DW_DLV_OK;
}
}
return DW_DLV_NO_ENTRY;
}
static int
dwarf_create_cie_from_start(Dwarf_Debug dbg,
Dwarf_Small * cie_ptr_val,
Dwarf_Small * section_ptr,
Dwarf_Unsigned section_index,
Dwarf_Unsigned section_length,
Dwarf_Small * section_ptr_end,
Dwarf_Unsigned cie_id_value,
Dwarf_Unsigned cie_count,
int use_gnu_cie_calc,
Dwarf_Cie * cie_ptr_to_use_out,
Dwarf_Error * error)
{
struct cie_fde_prefix_s prefix;
int res = DW_DLV_ERROR;
Dwarf_Small *frame_ptr = cie_ptr_val;
if (frame_ptr < section_ptr || frame_ptr >= section_ptr_end) {
_dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
return DW_DLV_ERROR;
}
memset(&prefix, 0, sizeof(prefix));
res = dwarf_read_cie_fde_prefix(dbg, frame_ptr, section_ptr,
section_index, section_length,
&prefix, error);
if (res == DW_DLV_ERROR) {
return res;
}
if (res == DW_DLV_NO_ENTRY) {
_dwarf_error(dbg, error, DW_DLE_FRAME_CIE_DECODE_ERROR);
return DW_DLV_ERROR;
}
if (prefix.cf_cie_id != cie_id_value) {
_dwarf_error(dbg, error, DW_DLE_FRAME_CIE_DECODE_ERROR);
return DW_DLV_ERROR;
}
frame_ptr = prefix.cf_addr_after_prefix;
res = dwarf_create_cie_from_after_start(dbg,
&prefix,
section_ptr,
frame_ptr,
section_ptr_end,
cie_count,
use_gnu_cie_calc,
cie_ptr_to_use_out, error);
return res;
}
static int
gnu_aug_encodings(Dwarf_Debug dbg, char *augmentation,
Dwarf_Small * aug_data, Dwarf_Unsigned aug_data_len,
Dwarf_Half address_size,
unsigned char *pers_hand_enc_out,
unsigned char *lsda_enc_out,
unsigned char *fde_begin_enc_out,
Dwarf_Addr * gnu_pers_addr_out,
Dwarf_Error * error)
{
char *nc = 0;
Dwarf_Small *cur_aug_p = aug_data;
Dwarf_Small *end_aug_p = aug_data + aug_data_len;
for (nc = augmentation; *nc; ++nc) {
char c = *nc;
switch (c) {
case 'z':
continue;
case 'S':
break;
case 'L':
if (cur_aug_p > end_aug_p) {
_dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
return DW_DLV_ERROR;
}
*lsda_enc_out = *(unsigned char *) cur_aug_p;
++cur_aug_p;
break;
case 'R':
if (cur_aug_p >= end_aug_p) {
_dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
return DW_DLV_ERROR;
}
*fde_begin_enc_out = *(unsigned char *) cur_aug_p;
++cur_aug_p;
break;
case 'P':{
int res = DW_DLV_ERROR;
Dwarf_Small *updated_aug_p = 0;
unsigned char encoding = 0;
if (cur_aug_p >= end_aug_p) {
_dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
return DW_DLV_ERROR;
}
encoding = *(unsigned char *) cur_aug_p;
*pers_hand_enc_out = encoding;
++cur_aug_p;
if (cur_aug_p > end_aug_p) {
_dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
return DW_DLV_ERROR;
}
res = read_encoded_ptr(dbg,
(Dwarf_Small *) NULL,
cur_aug_p,
encoding,
end_aug_p,
address_size,
gnu_pers_addr_out,
&updated_aug_p,
error);
if (res != DW_DLV_OK) {
return res;
}
cur_aug_p = updated_aug_p;
if (cur_aug_p > end_aug_p) {
_dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
return DW_DLV_ERROR;
}
}
break;
default:
_dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
return DW_DLV_ERROR;
}
}
return DW_DLV_OK;
}
static int
read_encoded_ptr(Dwarf_Debug dbg,
Dwarf_Small * section_pointer,
Dwarf_Small * input_field,
int gnu_encoding,
Dwarf_Small * section_end,
Dwarf_Half address_size,
Dwarf_Unsigned * addr,
Dwarf_Small ** input_field_updated,
Dwarf_Error *error)
{
int value_type = gnu_encoding & 0xf;
Dwarf_Small *input_field_original = input_field;
if (gnu_encoding == 0xff) {
*addr = 0;
*input_field_updated = input_field;
return DW_DLV_OK;
}
switch (value_type) {
case DW_EH_PE_absptr:{
Dwarf_Unsigned ret_value = 0;
READ_UNALIGNED_CK(dbg, ret_value, Dwarf_Unsigned,
input_field, address_size,error,section_end);
*addr = ret_value;
*input_field_updated = input_field + address_size;
}
break;
case DW_EH_PE_uleb128:{
Dwarf_Unsigned val = 0;
DECODE_LEB128_UWORD_CK(input_field,val,dbg,error,section_end);
*addr = val;
*input_field_updated = input_field;
}
break;
case DW_EH_PE_udata2:{
Dwarf_Unsigned ret_value = 0;
READ_UNALIGNED_CK(dbg, ret_value, Dwarf_Unsigned,
input_field, 2,error,section_end);
*addr = ret_value;
*input_field_updated = input_field + 2;
}
break;
case DW_EH_PE_udata4:{
Dwarf_Unsigned ret_value = 0;
READ_UNALIGNED_CK(dbg, ret_value, Dwarf_Unsigned,
input_field, DWARF_32BIT_SIZE,error,section_end);
*addr = ret_value;
*input_field_updated = input_field + DWARF_32BIT_SIZE;
}
break;
case DW_EH_PE_udata8:{
Dwarf_Unsigned ret_value = 0;
READ_UNALIGNED_CK(dbg, ret_value, Dwarf_Unsigned,
input_field, DWARF_64BIT_SIZE,error,section_end);
*addr = ret_value;
*input_field_updated = input_field + DWARF_64BIT_SIZE;
}
break;
case DW_EH_PE_sleb128:{
Dwarf_Signed val = 0;
DECODE_LEB128_SWORD_CK(input_field,val,dbg,error,section_end);
*addr = (Dwarf_Unsigned) val;
*input_field_updated = input_field;
}
break;
case DW_EH_PE_sdata2:{
Dwarf_Unsigned val = 0;
READ_UNALIGNED_CK(dbg, val, Dwarf_Unsigned, input_field, 2,
error,section_end);
SIGN_EXTEND(val, 2);
*addr = (Dwarf_Unsigned) val;
*input_field_updated = input_field + 2;
}
break;
case DW_EH_PE_sdata4:{
Dwarf_Unsigned val = 0;
READ_UNALIGNED_CK(dbg, val,
Dwarf_Unsigned, input_field,
DWARF_32BIT_SIZE,error,section_end);
SIGN_EXTEND(val, DWARF_32BIT_SIZE);
*addr = (Dwarf_Unsigned) val;
*input_field_updated = input_field + DWARF_32BIT_SIZE;
}
break;
case DW_EH_PE_sdata8:{
Dwarf_Unsigned val = 0;
READ_UNALIGNED_CK(dbg, val,
Dwarf_Unsigned, input_field,
DWARF_64BIT_SIZE,error,section_end);
*addr = (Dwarf_Unsigned) val;
*input_field_updated = input_field + DWARF_64BIT_SIZE;
}
break;
default:
_dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
return DW_DLV_ERROR;
};
if (section_pointer && ((gnu_encoding & 0x70) == DW_EH_PE_pcrel)) {
Dwarf_Unsigned distance =
input_field_original - section_pointer;
*addr += dbg->de_debug_frame_eh_gnu.dss_addr + distance;
}
return DW_DLV_OK;
}
enum Dwarf_augmentation_type
_dwarf_get_augmentation_type(UNUSEDARG Dwarf_Debug dbg,
Dwarf_Small * augmentation_string,
int is_gcc_eh_frame)
{
enum Dwarf_augmentation_type t = aug_unknown;
char *ag_string = (char *) augmentation_string;
if (ag_string[0] == 0) {
t = aug_empty_string;
} else if (strcmp(ag_string, DW_DEBUG_FRAME_AUGMENTER_STRING) == 0) {
t = aug_irix_mti_v1;
} else if (ag_string[0] == 'z') {
if (is_gcc_eh_frame) {
t = aug_gcc_eh_z;
} else if (ag_string[1] == 0) {
t = aug_irix_exception_table;
}
} else if (strncmp(ag_string, "eh", 2) == 0) {
t = aug_eh;
} else if (strcmp(ag_string, "armcc+") == 0) {
t = aug_armcc;
} else if (strcmp(ag_string, "HC") == 0) {
t = aug_metaware;
} else {
}
return t;
}
static int
get_gcc_eh_augmentation(Dwarf_Debug dbg, Dwarf_Small * frame_ptr,
unsigned long *size_of_augmentation_data,
enum Dwarf_augmentation_type augtype,
Dwarf_Small * section_ptr_end,
char *augmentation,
Dwarf_Error *error)
{
char *suffix = 0;
unsigned long augdata_size = 0;
if (augtype == aug_gcc_eh_z) {
UNUSEDARG Dwarf_Unsigned val = 0;
Dwarf_Unsigned leb128_length = 0;
DECODE_LEB128_UWORD_LEN_CK(frame_ptr,val,leb128_length,
dbg,error,section_ptr_end);
augdata_size += leb128_length;
suffix = augmentation + 1;
} else {
suffix = augmentation + 2;
}
if (*suffix) {
_dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
return DW_DLV_ERROR;
}
*size_of_augmentation_data = augdata_size;
return DW_DLV_OK;
}
void
dwarf_fde_cie_list_dealloc(Dwarf_Debug dbg,
Dwarf_Cie * cie_data,
Dwarf_Signed cie_element_count,
Dwarf_Fde * fde_data,
Dwarf_Signed fde_element_count)
{
Dwarf_Signed i = 0;
for (i = 0; i < cie_element_count; ++i) {
Dwarf_Frame frame = cie_data[i]->ci_initial_table;
if (frame) {
dwarf_dealloc(dbg, frame, DW_DLA_FRAME);
}
dwarf_dealloc(dbg, cie_data[i], DW_DLA_CIE);
}
for (i = 0; i < fde_element_count; ++i) {
dwarf_dealloc(dbg, fde_data[i], DW_DLA_FDE);
}
if (cie_data) {
dwarf_dealloc(dbg, cie_data, DW_DLA_LIST);
}
if (fde_data) {
dwarf_dealloc(dbg, fde_data, DW_DLA_LIST);
}
}