From: Roland McGrath Date: Wed, 23 Jun 2010 10:19:44 +0000 (-0700) Subject: Merge branch 'master' into roland/cfi X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ec2863e7ce75ecf16418172e5546bc88c7c01464;p=thirdparty%2Felfutils.git Merge branch 'master' into roland/cfi Conflicts: libdw/cfi.c --- ec2863e7ce75ecf16418172e5546bc88c7c01464 diff --cc libdw/ChangeLog index c22540aa8,7aca37950..b671da8ff --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@@ -1,27 -1,9 +1,33 @@@ + 2010-06-23 Roland McGrath + + * cfi.c (dwarf_cfi_validate_fde): Function removed. + * libdw.h: Remove it. + * libdw.map: Likewise. + +2010-06-23 Roland McGrath + + * cfi.c (dwarf_cfi_frames): New function. + * libdw.h: Declare it. + + * fde.c (__libdw_fde_by_offset): Take new argument NEXTOFF. + If non-null, return -1 marker without error at end of section, + skip CIEs, and store next offset. Maintain fde_tailp and next. + * cfi.h: Update decl. + + * cfi.h (struct dwarf_fde): New member next. + (struct Dwarf_CFI_s): New members first_fde, fde_tailp. + * dwarf_getcfi.c (dwarf_getcfi): Initialize them. + * dwarf_getcfi_elf.c (allocate_cfi): Likewise. + * fde.c (intern_fde): Initialize next. + + * cfi.c (clear_prev): New function, broken out of ... + (execute_cfi): ... here. Call it. Take new flag argument; when + false, stop at the first PC change and don't clear_prev. + (cie_cache_initial_state, __libdw_frame_at_address): Update callers. + + * cfi.h (struct Dwarf_Frame_s): New member fde_pc. + * cfi.c (execute_cfi): Set it to pending PROGRAM pointer at return. + 2010-06-22 Roland McGrath * dwarf_getlocation.c (check_constant_offset): data[48] are constant. diff --cc libdw/cfi.c index 2ea7cfdd9,aeb48e697..7dacfc8b3 --- a/libdw/cfi.c +++ b/libdw/cfi.c @@@ -512,148 -504,3 +512,109 @@@ __libdw_frame_at_address (Dwarf_CFI *ca } return result; } + +ptrdiff_t +dwarf_cfi_frames (Dwarf_CFI *cache, ptrdiff_t offset, + void **state, Dwarf_Frame **framep) +{ + if (cache == NULL) + return -1; + + if (offset < 0) + { + /* Special case call for cleanup. */ + + if (*state != NULL) + { + clear_prev (*state); + free (*state); + *state = NULL; + } + return 0; + } + + Dwarf_Frame *fs = *state; + + struct dwarf_fde *fde; + if (offset == 0) + { + /* Start at the beginning. */ + assert (fs == NULL); + fde = cache->first_fde ?: (void *) -1l; + } + else + { + /* Resume from the last iteration. */ + assert (fs != NULL); + fde = fs->fde; + if (fs->fde_pc == fde->instructions_end) + { + /* We've hit the end of this FDE. Move to the next one. */ + clear_prev (fs); + free (fs); + *state = fs = NULL; + fde = fde->next; + } + } + + if (fs == NULL) + { + /* We're starting fresh on a new FDE. */ + + if (fde == (void *) -1l) + { + /* No cached next FDE. We have to intern the next one. */ + + fde = __libdw_fde_by_offset (cache, offset, &offset); + if (fde == (void *) -1l) + /* End of the line. */ + return 0; + } + + /* Start from this FDE's CIE's initial state. */ + int result = cie_cache_initial_state (cache, fde->cie); + if (likely (result == DWARF_E_NOERROR)) + { + fs = duplicate_frame_state (fde->cie->initial_state, NULL); + if (unlikely (fs == NULL)) + result = DWARF_E_NOMEM; + } + if (unlikely (result != DWARF_E_NOERROR)) + { + __libdw_seterrno (result); + return -1; + } + + fs->fde_pc = fde->instructions; + *state = fs; + } + + /* Now play forward from the last position in the FDE. */ + + assert (fs->fde == fde); + assert (fs->fde_pc < fde->instructions_end); + int result = execute_cfi (cache, fde->cie, &fs, false, + fs->fde_pc, fde->instructions_end, false, + fs->end, 0); + if (likely (result == DWARF_E_NOERROR)) + { + *framep = duplicate_frame_state (fs, NULL); + if (unlikely (*framep == NULL)) + { + clear_prev (fs); + free (fs); + fs = NULL; + result = DWARF_E_NOMEM; + } + } + + *state = fs; + + if (unlikely (result != DWARF_E_NOERROR)) + { + __libdw_seterrno (result); + offset = -1; + } + + return offset; +} - - int - dwarf_cfi_validate_fde (cache, offset, start, end, signalp, encoding) - Dwarf_CFI *cache; - Dwarf_Off offset; - Dwarf_Addr *start; - Dwarf_Addr *end; - bool *signalp; - uint8_t *encoding; - { - if (cache == NULL) - return -1; - - struct dwarf_fde *fde = __libdw_fde_by_offset (cache, offset, NULL); - if (unlikely (fde == NULL)) - return -1; - - Dwarf_Frame *fs; - int result = __libdw_frame_at_address (cache, fde, fde->end, &fs); - if (unlikely (result != DWARF_E_NOERROR)) - { - __libdw_seterrno (result); - return -1; - } - - result = fs->nregs + 1; - free (fs); - - if (start != NULL) - *start = fde->start; - if (end != NULL) - *end = fde->end; - if (signalp != NULL) - *signalp = fde->cie->signal_frame; - if (encoding != NULL) - *encoding = fde->cie->fde_encoding; - - return result; - }