+2010-06-24 Roland McGrath <roland@redhat.com>
+
+ * encoded-value.h (encoded_value_size): Replace E_IDENT parameter
+ with ADDRESS_SIZE.
+ (read_encoded_value): Update caller.
+ * fde.c (binary_search_fde): Likewise.
+ * dwarf_next_cfi.c: Likewise.
+ * cfi.h (struct dwarf_cie): New member address_size.
+ (CFI_ADDRSIZE): New macro.
+ * cie.c (intern_new_cie): Initialize and use CIE->address_size.
+ (canonicalize_encoding): New function.
+ (intern_new_cie): Call it, do both FDE and LSDA encodings.
+
2010-06-23 Roland McGrath <roland@redhat.com>
* cfi.c (dwarf_cfi_validate_fde): Function removed.
const Dwarf_Frame *initial_state;
- uint8_t fde_encoding; /* DW_EH_PE_* for addresses in FDEs. */
+ uint8_t address_size; /* Address size used here. */
+
+ /* These encodings are canonicalized from DW_EH_PE_absptr
+ to a particular size DW_EH_PE_udata[48]. */
+ uint8_t fde_encoding; /* DW_EH_PE_* for addresses in FDEs. */
uint8_t lsda_encoding; /* DW_EH_PE_* for LSDA in FDE augmentation. */
bool sized_augmentation_data; /* Saw 'z': FDEs have self-sized data. */
bool default_same_value;
};
+#define CFI_ADDRSIZE(cache) (cache->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8)
+
enum dwarf_frame_rule
{
return 0;
}
+/* Canonicalize encoding to a specific size. */
+static bool
+canonicalize_encoding (uint8_t *encoding, uint8_t address_size)
+{
+ if ((*encoding & 0x07) == DW_EH_PE_absptr)
+ {
+ assert (DW_EH_PE_absptr == 0);
+
+ switch (address_size)
+ {
+ case 8:
+ *encoding |= DW_EH_PE_udata8;
+ break;
+ case 4:
+ *encoding |= DW_EH_PE_udata4;
+ break;
+ default:
+ return true;
+ }
+ }
+ return false;
+}
+
/* There is no CIE at OFFSET in the tree. Add it. */
static struct dwarf_cie *
intern_new_cie (Dwarf_CFI *cache, Dwarf_Off offset, const Dwarf_CIE *info)
cie->sized_augmentation_data = false;
cie->signal_frame = false;
+ /* XXX should get from dwarf_next_cfi with v4 header. */
+ cie->address_size = CFI_ADDRSIZE (cache);
+
cie->fde_encoding = DW_EH_PE_absptr;
cie->lsda_encoding = DW_EH_PE_omit;
cie->lsda_encoding = *data++;
if (!cie->sized_augmentation_data)
cie->fde_augmentation_data_size
- += encoded_value_size (&cache->data->d, cache->e_ident,
+ += encoded_value_size (&cache->data->d, cie->address_size,
cie->lsda_encoding, NULL);
continue;
case 'P': /* Skip personality routine. */
encoding = *data++;
- data += encoded_value_size (&cache->data->d, cache->e_ident,
+ data += encoded_value_size (&cache->data->d, cie->address_size,
encoding, data);
continue;
break;
}
- if ((cie->fde_encoding & 0x0f) == DW_EH_PE_absptr)
+ if (canonicalize_encoding (&cie->fde_encoding, cie->address_size)
+ || canonicalize_encoding (&cie->lsda_encoding, cie->address_size))
{
- /* Canonicalize encoding to a specific size. */
- assert (DW_EH_PE_absptr == 0);
-
- /* XXX should get from dwarf_next_cfi with v4 header. */
- uint_fast8_t address_size
- = cache->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
- switch (address_size)
- {
- case 8:
- cie->fde_encoding |= DW_EH_PE_udata8;
- break;
- case 4:
- cie->fde_encoding |= DW_EH_PE_udata4;
- break;
- default:
- free (cie);
- __libdw_seterrno (DWARF_E_INVALID_DWARF);
- return NULL;
- }
+ free (cie);
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return NULL;
}
/* Save the initial instructions to be played out into initial state. */
case 'R': /* Skip FDE address encoding byte. */
encoding = *bytes++;
entry->cie.fde_augmentation_data_size
- += encoded_value_size (data, e_ident, encoding, NULL);
+ += encoded_value_size (data, address_size, encoding, NULL);
continue;
case 'P': /* Skip encoded personality routine pointer. */
encoding = *bytes++;
- bytes += encoded_value_size (data, e_ident, encoding, bytes);
+ bytes += encoded_value_size (data, address_size,
+ encoding, bytes);
continue;
case 'S': /* Skip signal-frame flag. */
continue;
static size_t __attribute__ ((unused))
-encoded_value_size (const Elf_Data *data, const unsigned char e_ident[],
+encoded_value_size (const Elf_Data *data, uint8_t address_size,
uint8_t encoding, const uint8_t *p)
{
if (encoding == DW_EH_PE_omit)
return 8;
case DW_EH_PE_absptr:
- return e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
+ return address_size;
case DW_EH_PE_uleb128:
if (p != NULL)
}
default:
- abort ();
return 0;
}
}
break;
case DW_EH_PE_aligned:
{
- const size_t size = encoded_value_size (&cache->data->d, cache->e_ident,
+ const size_t size = encoded_value_size (&cache->data->d,
+ CFI_ADDRSIZE (cache),
encoding, *p);
size_t align = ((cache->frame_vaddr
+ (*p - (const uint8_t *) cache->data->d.d_buf))
return true;
*result -= cache->frame_vaddr;
if (unlikely (*result > (cache->data->d.d_size
- - encoded_value_size (NULL, cache->e_ident,
+ - encoded_value_size (NULL, CFI_ADDRSIZE (cache),
DW_EH_PE_absptr, NULL))))
return true;
const uint8_t *ptr = cache->data->d.d_buf + *result;
static Dwarf_Off
binary_search_fde (Dwarf_CFI *cache, Dwarf_Addr address)
{
- const size_t size = 2 * encoded_value_size (&cache->data->d, cache->e_ident,
+ const size_t size = 2 * encoded_value_size (&cache->data->d,
+ CFI_ADDRSIZE (cache),
cache->search_table_encoding,
NULL);