Beispiel #1
0
_Unwind_Reason_Code lsda_scan(lsda_t* lsda, _Unwind_Action actions,
  uintptr_t* lp)
{
  (void)actions;
  const uint8_t* p = lsda->call_site_table;

  while(p < lsda->action_table)
  {
    uintptr_t start = read_encoded_ptr(&p, lsda->call_site_encoding);
    uintptr_t length = read_encoded_ptr(&p, lsda->call_site_encoding);
    uintptr_t landing_pad = read_encoded_ptr(&p, lsda->call_site_encoding);

    // Pony ignores the action index, since it uses only cleanup landing pads.
    read_uleb128(&p);

    if((start <= lsda->ip_offset) && (lsda->ip_offset < (start + length)))
    {
      // No landing pad.
      if(landing_pad == 0)
        return _URC_CONTINUE_UNWIND;

      // Pony doesn't read the type index or look up types. We treat cleanup
      // landing pads the same as any other landing pad.
      *lp = lsda->landing_pads + landing_pad;
      return _URC_HANDLER_FOUND;
    }
  }

  return _URC_CONTINUE_UNWIND;
}
Beispiel #2
0
static uintptr_t read_with_encoding(const uint8_t** data, uintptr_t def)
{
  uintptr_t start = (uintptr_t)(*data);
  const uint8_t* p = *data;
  uint8_t encoding = *p++;
  *data = p;

  if(encoding == DW_EH_PE_omit)
    return def;

  uintptr_t result = read_encoded_ptr(data, encoding);

  // Relative offset.
  switch(encoding & 0x70)
  {
    case DW_EH_PE_absptr:
      break;

    case DW_EH_PE_pcrel:
      result += start;
      break;

    case DW_EH_PE_textrel:
    case DW_EH_PE_datarel:
    case DW_EH_PE_funcrel:
    case DW_EH_PE_aligned:
    default:
      abort();
      break;
  }

  // apply indirection
  if(encoding & DW_EH_PE_indirect)
    result = *((uintptr_t*)result);

  return result;
}
int
dwarf_create_fde_from_after_start(Dwarf_Debug dbg,
				  struct cie_fde_prefix_s *prefix,
				  Dwarf_Small * frame_ptr,
				  int use_gnu_cie_calc,
				  Dwarf_Cie cie_ptr_in,
				  Dwarf_Fde * fde_ptr_out,
				  Dwarf_Error * error)
{
    Dwarf_Fde new_fde = 0;
    Dwarf_Cie cieptr = cie_ptr_in;
    Dwarf_Small *saved_frame_ptr = 0;

    Dwarf_Small *initloc = frame_ptr;
    Dwarf_Signed offset_into_exception_tables
	/* must be min dwarf_sfixed in size */
	= (Dwarf_Signed) DW_DLX_NO_EH_OFFSET;
    Dwarf_Small *fde_aug_data = 0;
    Dwarf_Unsigned fde_aug_data_len = 0;
    Dwarf_Addr cie_base_offset = prefix->cf_cie_id;
    Dwarf_Addr initial_location = 0;	/* must be min de_pointer_size
					   bytes in size */
    Dwarf_Addr address_range = 0;	/* must be min de_pointer_size
					   bytes in size */

    enum Dwarf_augmentation_type augt = cieptr->ci_augmentation_type;

    if (augt == aug_gcc_eh_z) {
	/* If z augmentation this is eh_frame, and initial_location and 
	   address_range in the FDE are read according to the CIE
	   augmentation string instructions.  */

	{
	    Dwarf_Small *fp_updated = 0;
	    int res = res = read_encoded_ptr(dbg, frame_ptr,
					     cieptr->
					     ci_gnu_fde_begin_encoding,
					     &initial_location,
					     &fp_updated);

	    if (res != DW_DLV_OK) {
		_dwarf_error(dbg, error,
			     DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
		return DW_DLV_ERROR;
	    }
	    frame_ptr = fp_updated;
	    res = read_encoded_ptr(dbg, frame_ptr,
				   cieptr->ci_gnu_fde_begin_encoding,
				   &address_range, &fp_updated);
	    if (res != DW_DLV_OK) {
		_dwarf_error(dbg, error,
			     DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
		return DW_DLV_ERROR;
	    }
	    frame_ptr = fp_updated;
	}
	{
	    Dwarf_Unsigned adlen = 0;

	    DECODE_LEB128_UWORD(frame_ptr, adlen);
	    fde_aug_data_len = adlen;
	    fde_aug_data = frame_ptr;
	    frame_ptr += adlen;
	}

    } else {
	READ_UNALIGNED(dbg, initial_location, Dwarf_Addr,
		       frame_ptr, dbg->de_pointer_size);
	frame_ptr += dbg->de_pointer_size;

	READ_UNALIGNED(dbg, address_range, Dwarf_Addr,
		       frame_ptr, dbg->de_pointer_size);
	frame_ptr += dbg->de_pointer_size;
    }





    switch (augt) {
    case aug_irix_mti_v1:
    case aug_empty_string:
	break;
    case aug_irix_exception_table:{
	    Dwarf_Unsigned lreg = 0;
	    Dwarf_Word length_of_augmented_fields = 0;

	    DECODE_LEB128_UWORD(frame_ptr, lreg);
	    length_of_augmented_fields = (Dwarf_Word) lreg;

	    saved_frame_ptr = frame_ptr;
	    /* The first word is an offset into exception tables.
	       Defined as a 32bit offset even for CC -64. */
	    READ_UNALIGNED(dbg, offset_into_exception_tables,
			   Dwarf_Addr, frame_ptr, sizeof(Dwarf_sfixed));
	    SIGN_EXTEND(offset_into_exception_tables,
			sizeof(Dwarf_sfixed));
	    frame_ptr = saved_frame_ptr + length_of_augmented_fields;
	}
	break;
    case aug_eh:{
	    Dwarf_Unsigned eh_table_value = 0;

	    if (!use_gnu_cie_calc) {
		/* This should be impossible. */
		_dwarf_error(dbg, error,
			     DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
		return DW_DLV_ERROR;
	    }

	    /* gnu eh fde case. we do not need to do anything */
	     /*REFERENCED*/	/* Not used in this instance of the
				   macro */
		READ_UNALIGNED(dbg, eh_table_value,
			       Dwarf_Unsigned, frame_ptr,
			       dbg->de_pointer_size);
	    frame_ptr += dbg->de_pointer_size;
	}
	break;

    case aug_gcc_eh_z:{
	    /* The Augmentation Data Length is here, followed by the
	       Augmentation Data bytes themselves. */
	}
	break;
    }				/* End switch on augmentation type */
    new_fde = (Dwarf_Fde) _dwarf_get_alloc(dbg, DW_DLA_FDE, 1);
    if (new_fde == NULL) {
	_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
	return (DW_DLV_ERROR);
    }

    new_fde->fd_length = prefix->cf_length;
    new_fde->fd_length_size = prefix->cf_local_length_size;
    new_fde->fd_extension_size = prefix->cf_local_extension_size;
    new_fde->fd_cie_offset = cie_base_offset;
    new_fde->fd_cie_index = cieptr->ci_index;
    new_fde->fd_cie = cieptr;
    new_fde->fd_initial_location = initial_location;
    new_fde->fd_initial_loc_pos = initloc;
    new_fde->fd_address_range = address_range;
    new_fde->fd_fde_start = prefix->cf_start_addr;
    new_fde->fd_fde_instr_start = frame_ptr;
    new_fde->fd_dbg = dbg;
    new_fde->fd_offset_into_exception_tables =
	offset_into_exception_tables;

    new_fde->fd_section_ptr = prefix->cf_section_ptr;
    new_fde->fd_section_index = prefix->cf_section_index;
    new_fde->fd_section_length = prefix->cf_section_length;

    new_fde->fd_gnu_eh_augmentation_bytes = fde_aug_data;
    new_fde->fd_gnu_eh_augmentation_len = fde_aug_data_len;

    *fde_ptr_out = new_fde;
    return DW_DLV_OK;
}
static int
gnu_aug_encodings(Dwarf_Debug dbg, char *augmentation,
		  Dwarf_Small * aug_data, Dwarf_Unsigned aug_data_len,
		  unsigned char *pers_hand_enc_out,
		  unsigned char *lsda_enc_out,
		  unsigned char *fde_begin_enc_out,
		  Dwarf_Addr * gnu_pers_addr_out)
{
    char *nc = 0;
    Dwarf_Small *cur_aug_p = aug_data;
    Dwarf_Small *end_aug_p = aug_data + aug_data_len;

    for (nc = augmentation; *nc; ++nc) {
	char c = *nc;

	switch (c) {
	case 'z':
	    continue;

	case 'L':
	    if (cur_aug_p > end_aug_p) {
		return DW_DLV_ERROR;
	    }
	    *lsda_enc_out = *(unsigned char *) cur_aug_p;
	    ++cur_aug_p;
	    break;
	case 'R':
	    if (cur_aug_p >= end_aug_p) {
		return DW_DLV_ERROR;
	    }
	    *fde_begin_enc_out = *(unsigned char *) cur_aug_p;
	    ++cur_aug_p;
	    break;
	case 'P':{
		int res = 0;
		Dwarf_Small *updated_aug_p = 0;
		unsigned char encoding = 0;

		if (cur_aug_p >= end_aug_p) {
		    return DW_DLV_ERROR;
		}
		encoding = *(unsigned char *) cur_aug_p;
		*pers_hand_enc_out = encoding;
		++cur_aug_p;
		if (cur_aug_p > end_aug_p) {
		    return DW_DLV_ERROR;
		}
		res = read_encoded_ptr(dbg,
				       cur_aug_p,
				       encoding,
				       gnu_pers_addr_out,
				       &updated_aug_p);
		if (res != DW_DLV_OK) {
		    return res;
		}
		cur_aug_p = updated_aug_p;
		if (cur_aug_p > end_aug_p) {
		    return DW_DLV_ERROR;
		}
	    }
	    break;
	default:
	    return DW_DLV_ERROR;

	}
    }

    return DW_DLV_OK;
}