sframe_unwind (struct sframest_ctx *sf, void **ra_lst, int *ra_size)
{
uint64_t cfa, return_addr, ra_stack_loc, rfp_stack_loc;
+ struct sframest_info *sfinfo;
sframe_decoder_ctx *dctx;
int cfa_offset, rfp_offset, ra_offset, errnum, i, count;
sframe_frame_row_entry fred, *frep = &fred;
return_addr = ra;
- /* Load and set up the decoder. */
- dctx = sframe_load_ctx (sf, pc);
- if (!dctx)
+ /* Load and set up the SFrame stack trace info for pc. */
+ sfinfo = sframest_get_sfinfo (sf, pc);
+ if (!sfinfo || !sfinfo->dctx)
return sframe_bt_ret_set_errno (&err, SFRAME_BT_ERR_DECODE);
- sframe_vma = sf->prog_sfinfo.sframe_vma;
count = *ra_size;
for (i = 0; i < count; ++i)
{
+ dctx = sfinfo->dctx;
+ sframe_vma = sfinfo->sframe_vma;
+
pc -= sframe_vma;
+
errnum = sframe_find_fre (dctx, pc, frep);
+
if (!errnum)
{
cfa_offset = sframe_fre_get_cfa_offset (dctx, frep, &errnum);
rsp = cfa;
pc = return_addr;
- /* Check if need to update the decoder context and vma. */
- sframe_update_ctx (sf, return_addr, &dctx, &sframe_vma);
- if (!dctx)
+ /* Check if need to update the SFrame stack trace info for the return
+ addr. */
+ sfinfo = sframest_update_sfinfo (sf, sfinfo, return_addr);
+ if (!sfinfo || !sfinfo->dctx)
return sframe_bt_ret_set_errno (&err, SFRAME_BT_ERR_DECODE);
}
else
or one of the DSOs from CF, based on the input RADDR argument. Return the
newly created decode context or NULL. */
-sframe_decoder_ctx *
-sframe_load_ctx (struct sframest_ctx *sf, uint64_t raddr)
+struct sframest_info *
+sframest_get_sfinfo (struct sframest_ctx *sf, uint64_t raddr)
{
- sframe_decoder_ctx *dctx;
- struct sframest_info *sfinfo;
+ struct sframest_info *sfinfo = NULL;
+ int err = 0;
if (!sf)
return NULL;
if (!sfinfo)
return NULL;
+ /* Decode the SFrame section the first time. */
if (!sfinfo->dctx)
- {
- int err;
- dctx = sframe_decode (sfinfo->buf, sfinfo->buflen, &err);
- if (!dctx)
- return NULL;
- sfinfo->dctx = dctx;
- return dctx;
- }
+ sfinfo->dctx = sframe_decode (sfinfo->buf, sfinfo->buflen, &err);
- return NULL;
+ return sfinfo;
}
-/* Check if need to do a decode context switch, based on the input RADDR
- argument, from CF. A new decode context will be created and set up if it
- isn't already done so. Return the new decode context in CTX and vma in
- CFI_VMA. */
-
-void
-sframe_update_ctx (struct sframest_ctx *sf, uint64_t raddr,
- sframe_decoder_ctx **ctx, uint64_t *sframe_vma)
+struct sframest_info *
+sframest_update_sfinfo (struct sframest_ctx *sf,
+ struct sframest_info *cur_sfinfo,
+ uint64_t raddr)
{
- sframe_decoder_ctx *dctx = NULL;
- struct sframest_info *sfinfo;
+ struct sframest_info *sfinfo = NULL;
+ int err = 0;
+
+ if (!sf || !cur_sfinfo)
+ return NULL;
+
+ /* Detect if current SFrame stack trace info object serves for raddr. */
+ if (cur_sfinfo->text_vma < raddr
+ && cur_sfinfo->text_vma + cur_sfinfo->text_size > raddr)
+ return cur_sfinfo;
sfinfo = sframe_find_context (sf, raddr);
- if (sfinfo)
- {
- if (!sfinfo->dctx)
- {
- int err;
- dctx = sframe_decode (sfinfo->buf, sfinfo->buflen, &err);
- if (!dctx)
- return;
+ if (!sfinfo)
+ return NULL;
- sfinfo->dctx = dctx;
- }
- *ctx = sfinfo->dctx;
- *sframe_vma = sfinfo->sframe_vma;
- }
+ /* Decode the SFrame section the first time. */
+ if (!sfinfo->dctx)
+ sfinfo->dctx = sframe_decode (sfinfo->buf, sfinfo->buflen, &err);
+
+ return sfinfo;
}
+
/* Open /proc image associated with the process id and return the file
descriptor. */
static int
-sframe_fd_open (int *errp)
+get_proc_mem_fd (int *errp)
{
int fd;
if (info->dlpi_name[0] == '\0') /* the main module. */
{
- fd = sframe_fd_open (&sframe_err);
+ fd = get_proc_mem_fd (&sframe_err);
if (fd == -1)
return 1;
#if 0
size_t size ATTRIBUTE_UNUSED,
void *data);
-void sframe_update_ctx (struct sframest_ctx *sf, uint64_t raddr,
- sframe_decoder_ctx **ctx, uint64_t *cfi_vma);
+struct sframest_info *sframest_update_sfinfo (struct sframest_ctx *sf,
+ struct sframest_info *cur_sfinfo,
+ uint64_t raddr);
-sframe_decoder_ctx *sframe_load_ctx (struct sframest_ctx *sf, uint64_t raddr);
+struct sframest_info *sframest_get_sfinfo (struct sframest_ctx *sf,
+ uint64_t raddr);
struct sframest_info *sframe_find_context (struct sframest_ctx *sf,
uint64_t addr);