mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-12-01 18:57:38 +01:00
(is_cie_id): New function.
(parse_cie): Adjust for moving DWARF2 extra-info from unw_dyn_dwarf_fde_info_t to dwarf_cie_info. Add support for `S' augmentation ("special frames"). (dwarf_extract_proc_info_from_fde): Rename frm dwarf_parse_fde(). Convert to returning data via dwarf_cie_info rather than unw_dyn-dwarf_fde_info_t. Allow 0-length FDE since those can be used to indicate the end of the FDE-table. Return the end of the FDE via *ADDRP. Ignore CIEs (we may pick them up during linear searches through the FDE-table). Fill in the unwind-info only if really needed. When needed, return the info via a dynamically allocated dwarf_cie_info structure. Add support for `S' augmentation (ABI/tag pairs). (Logical change 1.290)
This commit is contained in:
parent
d9445c1f46
commit
46b7b8196c
1 changed files with 115 additions and 74 deletions
189
src/dwarf/Gfde.c
189
src/dwarf/Gfde.c
|
@ -1,5 +1,5 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (c) 2003 Hewlett-Packard Development Company, L.P.
|
Copyright (c) 2003-2004 Hewlett-Packard Development Company, L.P.
|
||||||
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
@ -28,18 +28,26 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
#include "dwarf_i.h"
|
#include "dwarf_i.h"
|
||||||
#include "tdep.h"
|
#include "tdep.h"
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
is_cie_id (unw_word_t val)
|
||||||
|
{
|
||||||
|
/* DWARF spec says CIE_id is 0xffffffff (for 32-bit ELF) or
|
||||||
|
0xffffffffffffffff (for 64-bit ELF). However, the GNU toolchain
|
||||||
|
uses 0. */
|
||||||
|
return (val == 0 || val == - (unw_word_t) 1);
|
||||||
|
}
|
||||||
|
|
||||||
/* Note: we don't need to keep track of more than the first four
|
/* Note: we don't need to keep track of more than the first four
|
||||||
characters of the augmentation string, because we (a) ignore any
|
characters of the augmentation string, because we (a) ignore any
|
||||||
augmentation string contents once we find an unrecognized character
|
augmentation string contents once we find an unrecognized character
|
||||||
and (b) those characters that we do recognize, can't be
|
and (b) those characters that we do recognize, can't be
|
||||||
repeated. */
|
repeated. */
|
||||||
static inline int
|
static inline int
|
||||||
parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr,
|
||||||
unw_proc_info_t *pi, unw_dyn_dwarf_fde_info_t *dfi,
|
const unw_proc_info_t *pi, struct dwarf_cie_info *dci, void *arg)
|
||||||
int *lsda_encodingp, void *arg)
|
|
||||||
{
|
{
|
||||||
uint8_t version, ch, augstr[5], fde_encoding, handler_encoding;
|
uint8_t version, ch, augstr[5], fde_encoding, handler_encoding;
|
||||||
unw_word_t len, cie_end_addr, aug_size, handler = 0;
|
unw_word_t len, cie_end_addr, aug_size;
|
||||||
uint32_t u32val;
|
uint32_t u32val;
|
||||||
uint64_t u64val;
|
uint64_t u64val;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
@ -59,10 +67,10 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
default: fde_encoding = DW_EH_PE_omit; break;
|
default: fde_encoding = DW_EH_PE_omit; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
*lsda_encodingp = DW_EH_PE_omit;
|
dci->lsda_encoding = DW_EH_PE_omit;
|
||||||
dfi->flags = 0;
|
dci->handler = 0;
|
||||||
|
|
||||||
if ((ret = dwarf_readu32 (as, a, addr, &u32val, arg)) < 0)
|
if ((ret = dwarf_readu32 (as, a, &addr, &u32val, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (u32val != 0xffffffff)
|
if (u32val != 0xffffffff)
|
||||||
|
@ -71,8 +79,8 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
uint32_t cie_id;
|
uint32_t cie_id;
|
||||||
|
|
||||||
len = u32val;
|
len = u32val;
|
||||||
cie_end_addr = *addr + len;
|
cie_end_addr = addr + len;
|
||||||
if ((ret = dwarf_readu32 (as, a, addr, &cie_id, arg)) < 0)
|
if ((ret = dwarf_readu32 (as, a, &addr, &cie_id, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
/* DWARF says CIE id should be 0xffffffff, but in .eh_frame, it's 0 */
|
/* DWARF says CIE id should be 0xffffffff, but in .eh_frame, it's 0 */
|
||||||
if (cie_id != 0)
|
if (cie_id != 0)
|
||||||
|
@ -86,11 +94,11 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
/* the CIE is in the 64-bit DWARF format */
|
/* the CIE is in the 64-bit DWARF format */
|
||||||
uint64_t cie_id;
|
uint64_t cie_id;
|
||||||
|
|
||||||
if ((ret = dwarf_readu64 (as, a, addr, &u64val, arg)) < 0)
|
if ((ret = dwarf_readu64 (as, a, &addr, &u64val, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
len = u64val;
|
len = u64val;
|
||||||
cie_end_addr = *addr + len;
|
cie_end_addr = addr + len;
|
||||||
if ((ret = dwarf_readu64 (as, a, addr, &cie_id, arg)) < 0)
|
if ((ret = dwarf_readu64 (as, a, &addr, &cie_id, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
/* DWARF says CIE id should be 0xffffffffffffffff, but in
|
/* DWARF says CIE id should be 0xffffffffffffffff, but in
|
||||||
.eh_frame, it's 0 */
|
.eh_frame, it's 0 */
|
||||||
|
@ -100,9 +108,9 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
return -UNW_EINVAL;
|
return -UNW_EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dfi->cie_instr_end = cie_end_addr;
|
dci->cie_instr_end = cie_end_addr;
|
||||||
|
|
||||||
if ((ret = dwarf_readu8 (as, a, addr, &version, arg)) < 0)
|
if ((ret = dwarf_readu8 (as, a, &addr, &version, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (version != 1 && version != DWARF_CIE_VERSION)
|
if (version != 1 && version != DWARF_CIE_VERSION)
|
||||||
|
@ -116,7 +124,7 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
memset (augstr, 0, sizeof (augstr));
|
memset (augstr, 0, sizeof (augstr));
|
||||||
for (i = 0;;)
|
for (i = 0;;)
|
||||||
{
|
{
|
||||||
if ((ret = dwarf_readu8 (as, a, addr, &ch, arg)) < 0)
|
if ((ret = dwarf_readu8 (as, a, &addr, &ch, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (!ch)
|
if (!ch)
|
||||||
|
@ -126,26 +134,25 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
augstr[i++] = ch;
|
augstr[i++] = ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = dwarf_read_uleb128 (as, a, addr, &dfi->code_align, arg)) < 0
|
if ((ret = dwarf_read_uleb128 (as, a, &addr, &dci->code_align, arg)) < 0
|
||||||
|| (ret = dwarf_read_sleb128 (as, a, addr, &dfi->data_align, arg)) < 0)
|
|| (ret = dwarf_read_sleb128 (as, a, &addr, &dci->data_align, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Read the return-address column either as a u8 or as a uleb128. */
|
/* Read the return-address column either as a u8 or as a uleb128. */
|
||||||
if (version == 1)
|
if (version == 1)
|
||||||
{
|
{
|
||||||
if ((ret = dwarf_readu8 (as, a, addr, &ch, arg)) < 0)
|
if ((ret = dwarf_readu8 (as, a, &addr, &ch, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
dfi->ret_addr_column = ch;
|
dci->ret_addr_column = ch;
|
||||||
}
|
}
|
||||||
else if ((ret = dwarf_read_uleb128 (as, a, addr, &dfi->ret_addr_column, arg))
|
else if ((ret = dwarf_read_uleb128 (as, a, &addr, &dci->ret_addr_column,
|
||||||
< 0)
|
arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (augstr[0] == 'z')
|
if (augstr[0] == 'z')
|
||||||
{
|
{
|
||||||
dfi->flags |= UNW_DYN_DFI_FLAG_AUGMENTATION_HAS_SIZE;
|
dci->sized_augmentation = 1;
|
||||||
if ((ret = dwarf_read_uleb128 (as, a, addr, &aug_size, arg))
|
if ((ret = dwarf_read_uleb128 (as, a, &addr, &aug_size, arg)) < 0)
|
||||||
< 0)
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,28 +161,34 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
{
|
{
|
||||||
case 'L':
|
case 'L':
|
||||||
/* read the LSDA pointer-encoding format. */
|
/* read the LSDA pointer-encoding format. */
|
||||||
if ((ret = dwarf_readu8 (as, a, addr, &ch, arg)) < 0)
|
if ((ret = dwarf_readu8 (as, a, &addr, &ch, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
*lsda_encodingp = ch;
|
dci->lsda_encoding = ch;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'R':
|
case 'R':
|
||||||
/* read the FDE pointer-encoding format. */
|
/* read the FDE pointer-encoding format. */
|
||||||
if ((ret = dwarf_readu8 (as, a, addr, &fde_encoding, arg)) < 0)
|
if ((ret = dwarf_readu8 (as, a, &addr, &fde_encoding, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'P':
|
case 'P':
|
||||||
/* read the personality-routine pointer-encoding format. */
|
/* read the personality-routine pointer-encoding format. */
|
||||||
if ((ret = dwarf_readu8 (as, a, addr, &handler_encoding, arg)) < 0)
|
if ((ret = dwarf_readu8 (as, a, &addr, &handler_encoding, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
if ((ret = dwarf_read_encoded_pointer (as, a, addr, handler_encoding,
|
if ((ret = dwarf_read_encoded_pointer (as, a, &addr, handler_encoding,
|
||||||
pi, &handler, arg)) < 0)
|
pi, &dci->handler, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'S':
|
||||||
|
/* Temporarily set it to one so dwarf_parse_fde() knows that
|
||||||
|
it should fetch the actual ABI/TAG pair from the FDE. */
|
||||||
|
dci->have_abi_marker = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (dfi->flags & UNW_DYN_DFI_FLAG_AUGMENTATION_HAS_SIZE)
|
if (dci->sized_augmentation)
|
||||||
/* If we have the size of the augmentation body, we can skip
|
/* If we have the size of the augmentation body, we can skip
|
||||||
over the parts that we don't understand, so we're OK. */
|
over the parts that we don't understand, so we're OK. */
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -185,43 +198,56 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
return -UNW_EINVAL;
|
return -UNW_EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dfi->flags |= fde_encoding & UNW_DYN_DFI_FLAG_FDE_PE_MASK;
|
dci->fde_encoding = fde_encoding;
|
||||||
pi->handler = handler;
|
dci->cie_instr_start = addr;
|
||||||
Debug (15, "CIE parsed OK, augmentation = \"%s\", handler=0x%lx\n",
|
Debug (15, "CIE parsed OK, augmentation = \"%s\", handler=0x%lx\n",
|
||||||
augstr, (long) handler);
|
augstr, (long) dci->handler);
|
||||||
dfi->cie_instr_start = *addr;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Extract proc-info from the FDE starting at adress ADDR. */
|
||||||
|
|
||||||
HIDDEN int
|
HIDDEN int
|
||||||
dwarf_parse_fde (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a,
|
||||||
unw_proc_info_t *pi, unw_dyn_dwarf_fde_info_t *dfi, void *arg)
|
unw_word_t *addrp, unw_proc_info_t *pi,
|
||||||
|
int need_unwind_info,
|
||||||
|
void *arg)
|
||||||
{
|
{
|
||||||
unw_word_t fde_end_addr, cie_addr, cie_offset_addr, aug_end_addr = 0;
|
unw_word_t fde_end_addr, cie_addr, cie_offset_addr, aug_end_addr = 0;
|
||||||
int ret, fde_encoding, ip_range_encoding, lsda_encoding;
|
unw_word_t start_ip, ip_range, aug_size, addr = *addrp;
|
||||||
unw_word_t start_ip, ip_range, aug_size;
|
int ret, ip_range_encoding;
|
||||||
|
struct dwarf_cie_info dci;
|
||||||
uint64_t u64val;
|
uint64_t u64val;
|
||||||
uint32_t u32val;
|
uint32_t u32val;
|
||||||
|
|
||||||
Debug (12, "FDE @ 0x%lx\n", (long) *addr);
|
Debug (12, "FDE @ 0x%lx\n", (long) addr);
|
||||||
|
|
||||||
/* Parse enough of the FDE to get the procedure info (LSDA and handler). */
|
memset (&dci, 0, sizeof (dci));
|
||||||
|
|
||||||
if ((ret = dwarf_readu32 (as, a, addr, &u32val, arg)) < 0)
|
if ((ret = dwarf_readu32 (as, a, &addr, &u32val, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (u32val != 0xffffffff)
|
if (u32val != 0xffffffff)
|
||||||
{
|
{
|
||||||
uint32_t cie_offset;
|
uint32_t cie_offset;
|
||||||
|
|
||||||
|
/* In some configurations, an FDE with a 0 length indicates the
|
||||||
|
end of the FDE-table. */
|
||||||
|
if (u32val == 0)
|
||||||
|
return -UNW_ENOINFO;
|
||||||
|
|
||||||
/* the FDE is in the 32-bit DWARF format */
|
/* the FDE is in the 32-bit DWARF format */
|
||||||
|
|
||||||
fde_end_addr = *addr + u32val;
|
*addrp = fde_end_addr = addr + u32val;
|
||||||
cie_offset_addr = *addr;
|
cie_offset_addr = addr;
|
||||||
|
|
||||||
if ((ret = dwarf_reads32 (as, a, addr, &cie_offset, arg)) < 0)
|
if ((ret = dwarf_reads32 (as, a, &addr, &cie_offset, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
if (is_cie_id (cie_offset))
|
||||||
|
/* ignore CIEs (happens during linear searches) */
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* DWARF says that the CIE_pointer in the FDE is a
|
/* DWARF says that the CIE_pointer in the FDE is a
|
||||||
.debug_frame-relative offset, but the GCC-generated .eh_frame
|
.debug_frame-relative offset, but the GCC-generated .eh_frame
|
||||||
sections instead store a "pcrelative" offset, which is just
|
sections instead store a "pcrelative" offset, which is just
|
||||||
|
@ -234,65 +260,80 @@ dwarf_parse_fde (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||||
|
|
||||||
/* the FDE is in the 64-bit DWARF format */
|
/* the FDE is in the 64-bit DWARF format */
|
||||||
|
|
||||||
if ((ret = dwarf_readu64 (as, a, addr, &u64val, arg)) < 0)
|
if ((ret = dwarf_readu64 (as, a, &addr, &u64val, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
fde_end_addr = *addr + u64val;
|
*addrp = fde_end_addr = addr + u64val;
|
||||||
cie_offset_addr = *addr;
|
cie_offset_addr = addr;
|
||||||
|
|
||||||
if ((ret = dwarf_reads64 (as, a, addr, &cie_offset, arg)) < 0)
|
if ((ret = dwarf_reads64 (as, a, &addr, &cie_offset, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
if (is_cie_id (cie_offset))
|
||||||
|
/* ignore CIEs (happens during linear searches) */
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* DWARF says that the CIE_pointer in the FDE is a
|
/* DWARF says that the CIE_pointer in the FDE is a
|
||||||
.debug_frame-relative offset, but the GCC-generated .eh_frame
|
.debug_frame-relative offset, but the GCC-generated .eh_frame
|
||||||
sections instead store a "pcrelative" offset, which is just
|
sections instead store a "pcrelative" offset, which is just
|
||||||
as fine as it's self-contained. */
|
as fine as it's self-contained. */
|
||||||
cie_addr = (unw_word_t) ((uint64_t) cie_offset_addr - cie_offset);
|
cie_addr = (unw_word_t) ((uint64_t) cie_offset_addr - cie_offset);
|
||||||
}
|
}
|
||||||
pi->extra.dwarf_info.fde_instr_end = fde_end_addr;
|
|
||||||
|
|
||||||
if ((ret = parse_cie (as, a, &cie_addr, pi, &pi->extra.dwarf_info,
|
if ((ret = parse_cie (as, a, cie_addr, pi, &dci, arg)) < 0)
|
||||||
&lsda_encoding, arg)) < 0)
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
fde_encoding = pi->extra.dwarf_info.flags & UNW_DYN_DFI_FLAG_FDE_PE_MASK;
|
|
||||||
/* IP-range has same encoding as FDE pointers, except that it's
|
/* IP-range has same encoding as FDE pointers, except that it's
|
||||||
always an absolute value: */
|
always an absolute value: */
|
||||||
ip_range_encoding = fde_encoding & DW_EH_PE_FORMAT_MASK;
|
ip_range_encoding = dci.fde_encoding & DW_EH_PE_FORMAT_MASK;
|
||||||
|
|
||||||
if ((ret = dwarf_read_encoded_pointer (as, a, addr, fde_encoding,
|
if ((ret = dwarf_read_encoded_pointer (as, a, &addr, dci.fde_encoding,
|
||||||
pi, &start_ip, arg)) < 0
|
pi, &start_ip, arg)) < 0
|
||||||
|| (ret = dwarf_read_encoded_pointer (as, a, addr, ip_range_encoding,
|
|| (ret = dwarf_read_encoded_pointer (as, a, &addr, ip_range_encoding,
|
||||||
pi, &ip_range, arg)) < 0)
|
pi, &ip_range, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
pi->start_ip = start_ip;
|
pi->start_ip = start_ip;
|
||||||
pi->end_ip = start_ip + ip_range;
|
pi->end_ip = start_ip + ip_range;
|
||||||
|
pi->handler = dci.handler;
|
||||||
|
|
||||||
if (pi->extra.dwarf_info.flags & UNW_DYN_DFI_FLAG_AUGMENTATION_HAS_SIZE)
|
if (dci.sized_augmentation)
|
||||||
{
|
{
|
||||||
if ((ret = dwarf_read_uleb128 (as, a, addr, &aug_size, arg))
|
if ((ret = dwarf_read_uleb128 (as, a, &addr, &aug_size, arg)) < 0)
|
||||||
< 0)
|
|
||||||
return ret;
|
return ret;
|
||||||
aug_end_addr = *addr + aug_size;
|
aug_end_addr = addr + aug_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = dwarf_read_encoded_pointer (as, a, addr, lsda_encoding,
|
if ((ret = dwarf_read_encoded_pointer (as, a, &addr, dci.lsda_encoding,
|
||||||
pi, &pi->lsda, arg)) < 0)
|
pi, &pi->lsda, arg)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (pi->extra.dwarf_info.flags & UNW_DYN_DFI_FLAG_AUGMENTATION_HAS_SIZE)
|
|
||||||
pi->extra.dwarf_info.fde_instr_start = aug_end_addr;
|
|
||||||
else
|
|
||||||
pi->extra.dwarf_info.fde_instr_start = *addr;
|
|
||||||
|
|
||||||
/* Always set the unwind info, whether or not need_unwind_info is
|
|
||||||
set. We had to do all the work anyhow, so there is no point in
|
|
||||||
not doing so. */
|
|
||||||
pi->format = UNW_INFO_FORMAT_DWARF_FDE;
|
|
||||||
pi->unwind_info_size = sizeof (pi->extra.dwarf_info) / sizeof (unw_word_t);
|
|
||||||
pi->unwind_info = &pi->extra.dwarf_info;
|
|
||||||
|
|
||||||
Debug (15, "FDE covers IP 0x%lx-0x%lx, LSDA=0x%lx\n",
|
Debug (15, "FDE covers IP 0x%lx-0x%lx, LSDA=0x%lx\n",
|
||||||
(long) pi->start_ip, (long) pi->end_ip, (long) pi->lsda);
|
(long) pi->start_ip, (long) pi->end_ip, (long) pi->lsda);
|
||||||
|
|
||||||
|
if (need_unwind_info)
|
||||||
|
{
|
||||||
|
pi->format = UNW_INFO_FORMAT_TABLE;
|
||||||
|
pi->unwind_info_size = sizeof (dci);
|
||||||
|
pi->unwind_info = mempool_alloc (&dwarf_cie_info_pool);
|
||||||
|
if (!pi->unwind_info)
|
||||||
|
return UNW_ENOMEM;
|
||||||
|
|
||||||
|
if (dci.have_abi_marker)
|
||||||
|
{
|
||||||
|
if ((ret = dwarf_readu16 (as, a, &addr, &dci.abi, arg)) < 0
|
||||||
|
|| (ret = dwarf_readu16 (as, a, &addr, &dci.tag, arg)) < 0)
|
||||||
|
return ret;
|
||||||
|
Debug (13, "Found ABI marker = (abi=%u, tag=%u)\n",
|
||||||
|
dci.abi, dci.tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dci.sized_augmentation)
|
||||||
|
dci.fde_instr_start = aug_end_addr;
|
||||||
|
else
|
||||||
|
dci.fde_instr_start = addr;
|
||||||
|
dci.fde_instr_end = fde_end_addr;
|
||||||
|
|
||||||
|
memcpy (pi->unwind_info, &dci, sizeof (dci));
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue