+ 2010-06-23 Roland McGrath <roland@redhat.com>
+
+ * cfi.c (dwarf_cfi_validate_fde): Function removed.
+ * libdw.h: Remove it.
+ * libdw.map: Likewise.
+
+2010-06-23 Roland McGrath <roland@redhat.com>
+
+ * 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 <roland@redhat.com>
* dwarf_getlocation.c (check_constant_offset): data[48] are constant.
}
return result;
}
-
- 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;
- }
+
+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;
+}