struct Frame_Chunk *next;
unsigned char *chunk_start;
int ncols;
- /* DW_CFA_{undefined,same_value,offset,register} */
- unsigned char *col_type;
+ /* DW_CFA_{undefined,same_value,offset,register,unreferenced} */
+ short int *col_type;
int *col_offset;
char *augmentation;
unsigned int code_factor;
}
Frame_Chunk;
+/* A marker for a col_type that means this column was never referenced
+ in the frame info. */
+#define DW_CFA_unreferenced (-1)
+
static void
frame_need_space (fc, reg)
Frame_Chunk *fc;
if (reg < fc->ncols)
return;
fc->ncols = reg + 1;
- fc->col_type = (unsigned char *) xrealloc (fc->col_type,
- fc->ncols * sizeof (unsigned char));
+ fc->col_type = (short int *) xrealloc (fc->col_type,
+ fc->ncols * sizeof (short int));
fc->col_offset = (int *) xrealloc (fc->col_offset,
fc->ncols * sizeof (int));
while (prev < fc->ncols)
{
- fc->col_type[prev] = DW_CFA_undefined;
+ fc->col_type[prev] = DW_CFA_unreferenced;
fc->col_offset[prev] = 0;
prev++;
}
*need_col_headers = 0;
printf (" LOC CFA ");
for (r=0; r<*max_regs; r++)
- if (r == fc->ra)
- printf ("ra ");
- else
- printf ("r%-4d", r);
+ if (fc->col_type[r] != DW_CFA_unreferenced)
+ {
+ if (r == fc->ra)
+ printf ("ra ");
+ else
+ printf ("r%-4d", r);
+ }
printf ("\n");
}
printf ("%08x ", (unsigned int) fc->pc_begin);
printf ("%-8s ", tmp);
for (r=0; r<fc->ncols; r++)
{
- switch (fc->col_type[r])
+ if (fc->col_type[r] != DW_CFA_unreferenced)
{
- case DW_CFA_undefined:
- strcpy (tmp, "u");
- break;
- case DW_CFA_same_value:
- strcpy (tmp, "s");
- break;
- case DW_CFA_offset:
- sprintf (tmp, "c%+d", fc->col_offset[r]);
- break;
- case DW_CFA_register:
- sprintf (tmp, "r%d", fc->col_offset[r]);
- break;
- default:
- strcpy (tmp, "n/a");
- break;
+ switch (fc->col_type[r])
+ {
+ case DW_CFA_undefined:
+ strcpy (tmp, "u");
+ break;
+ case DW_CFA_same_value:
+ strcpy (tmp, "s");
+ break;
+ case DW_CFA_offset:
+ sprintf (tmp, "c%+d", fc->col_offset[r]);
+ break;
+ case DW_CFA_register:
+ sprintf (tmp, "r%d", fc->col_offset[r]);
+ break;
+ default:
+ strcpy (tmp, "n/a");
+ break;
+ }
+ printf ("%-5s", tmp);
}
- printf ("%-5s", tmp);
}
printf ("\n");
}
chunks = fc;
fc->chunk_start = saved_start;
fc->ncols = 0;
- fc->col_type = (unsigned char *) xmalloc (sizeof (unsigned char));
+ fc->col_type = (short int *) xmalloc (sizeof (short int));
fc->col_offset = (int *) xmalloc (sizeof (int));
frame_need_space (fc, max_regs-1);
warn ("Invalid CIE pointer %08x in FDE at %08x\n", cie_id, saved_start);
start = block_end;
fc->ncols = 0;
- fc->col_type = (unsigned char *) xmalloc (sizeof (unsigned char));
+ fc->col_type = (short int *) xmalloc (sizeof (short int));
fc->col_offset = (int *) xmalloc (sizeof (int));
frame_need_space (fc, max_regs-1);
cie = fc;
else
{
fc->ncols = cie->ncols;
- fc->col_type = (unsigned char *) xmalloc (fc->ncols * sizeof (unsigned char));
+ fc->col_type = (short int *) xmalloc (fc->ncols * sizeof (short int));
fc->col_offset = (int *) xmalloc (fc->ncols * sizeof (int));
- memcpy (fc->col_type, cie->col_type, fc->ncols);
+ memcpy (fc->col_type, cie->col_type, fc->ncols * sizeof (short int));
memcpy (fc->col_offset, cie->col_offset, fc->ncols * sizeof (int));
fc->augmentation = cie->augmentation;
fc->code_factor = cie->code_factor;
/* This exists for readelf maintainers. */
#define FDEBUG 0
+ {
+ /* Start by making a pass over the chunk, allocating storage
+ and taking note of what registers are used. */
+
+ unsigned char *tmp = start;
+ while (start < block_end)
+ {
+ unsigned op, opa;
+ unsigned long reg;
+ bfd_vma vma;
+
+ op = *start++;
+ opa = op & 0x3f;
+ if (op & 0xc0)
+ op &= 0xc0;
+
+ /* Warning: if you add any more cases to this switch, be
+ sure to add them to the corresponding switch below. */
+ switch (op)
+ {
+ case DW_CFA_advance_loc:
+ break;
+ case DW_CFA_offset:
+ LEB ();
+ frame_need_space (fc, opa);
+ fc->col_type[opa] = DW_CFA_undefined;
+ break;
+ case DW_CFA_restore:
+ frame_need_space (fc, opa);
+ fc->col_type[opa] = DW_CFA_undefined;
+ break;
+ case DW_CFA_set_loc:
+ start += sizeof (vma);
+ break;
+ case DW_CFA_advance_loc1:
+ start += 1;
+ break;
+ case DW_CFA_advance_loc2:
+ start += 2;
+ break;
+ case DW_CFA_advance_loc4:
+ start += 4;
+ break;
+ case DW_CFA_offset_extended:
+ reg = LEB (); LEB ();
+ frame_need_space (fc, reg);
+ fc->col_type[reg] = DW_CFA_undefined;
+ break;
+ case DW_CFA_restore_extended:
+ reg = LEB ();
+ frame_need_space (fc, reg);
+ fc->col_type[reg] = DW_CFA_undefined;
+ break;
+ case DW_CFA_undefined:
+ reg = LEB ();
+ frame_need_space (fc, reg);
+ fc->col_type[reg] = DW_CFA_undefined;
+ break;
+ case DW_CFA_same_value:
+ reg = LEB ();
+ frame_need_space (fc, reg);
+ fc->col_type[reg] = DW_CFA_undefined;
+ break;
+ case DW_CFA_register:
+ reg = LEB (); LEB ();
+ frame_need_space (fc, reg);
+ fc->col_type[reg] = DW_CFA_undefined;
+ break;
+ case DW_CFA_def_cfa:
+ LEB (); LEB ();
+ break;
+ case DW_CFA_def_cfa_register:
+ LEB ();
+ break;
+ case DW_CFA_def_cfa_offset:
+ LEB ();
+ break;
+#ifndef DW_CFA_GNU_args_size
+#define DW_CFA_GNU_args_size 0x2e
+#endif
+ case DW_CFA_GNU_args_size:
+ LEB ();
+ break;
+#ifndef DW_CFA_GNU_negative_offset_extended
+#define DW_CFA_GNU_negative_offset_extended 0x2f
+#endif
+ case DW_CFA_GNU_negative_offset_extended:
+ reg = LEB (); LEB ();
+ frame_need_space (fc, reg);
+ fc->col_type[reg] = DW_CFA_undefined;
+
+ default:
+ break;
+ }
+ }
+ start = tmp;
+ }
+
+ /* Now we know what registers are used, make a second pass over
+ the chunk, this time actually printing out the info. */
+
while (start < block_end)
{
unsigned op, opa;
if (op & 0xc0)
op &= 0xc0;
+ /* Warning: if you add any more cases to this switch, be
+ sure to add them to the corresponding switch above. */
switch (op)
{
case DW_CFA_advance_loc:
break;
case DW_CFA_offset:
- frame_need_space (fc, opa);
roffs = LEB ();
#if FDEBUG
printf (" DW_CFA_offset: r%d = cfa[%d*%d]\n", opa, roffs, fc->data_factor);
break;
case DW_CFA_restore:
- frame_need_space (fc, opa);
#if FDEBUG
printf (" DW_CFA_restore: r%d\n", opa);
#endif
case DW_CFA_offset_extended:
reg = LEB ();
roffs = LEB ();
- frame_need_space (fc, reg);
#if FDEBUG
printf (" DW_CFA_offset_extended: r%d = cfa[%d*%d]\n", reg, roffs, fc->data_factor);
#endif
case DW_CFA_restore_extended:
reg = LEB ();
- frame_need_space (fc, reg);
#if FDEBUG
printf (" DW_CFA_restore_extended: r%d\n", reg);
#endif
case DW_CFA_undefined:
reg = LEB ();
- frame_need_space (fc, reg);
#if FDEBUG
printf (" DW_CFA_undefined: r%d\n", reg);
#endif
case DW_CFA_same_value:
reg = LEB ();
- frame_need_space (fc, reg);
#if FDEBUG
printf (" DW_CFA_same_value: r%d\n", reg);
#endif
case DW_CFA_register:
reg = LEB ();
roffs = LEB ();
- frame_need_space (fc, reg);
#if FDEBUG
- printf (" DW_CFA_ame_value: r%d\n", reg);
+ printf (" DW_CFA_register: r%d\n", reg);
#endif
fc->col_type[reg] = DW_CFA_register;
fc->col_offset[reg] = roffs;
#endif
rs = (Frame_Chunk *) xmalloc (sizeof (Frame_Chunk));
rs->ncols = fc->ncols;
- rs->col_type = (unsigned char *) xmalloc (rs->ncols);
+ rs->col_type = (short int *) xmalloc (rs->ncols * sizeof (short int));
rs->col_offset = (int *) xmalloc (rs->ncols * sizeof (int));
memcpy (rs->col_type, fc->col_type, rs->ncols);
memcpy (rs->col_offset, fc->col_offset, rs->ncols * sizeof (int));