예제 #1
0
/* Similar to dwarf_add_fde_inst, except that the offset denoted by VAL2
   is signed.
*/
Dwarf_P_Fde
dwarf_add_fde_inst_with_signed_offset(Dwarf_P_Fde fde,
                                      Dwarf_Small op,
                                      Dwarf_Unsigned val1,
                                      Dwarf_Signed val2, Dwarf_Error * error)
{
    Dwarf_P_Frame_Pgm curinst;
    int nbytes, nbytes1, nbytes2;
    char *ptr;
    int res;
    char buff1[ENCODE_SPACE_NEEDED];
    char buff2[ENCODE_SPACE_NEEDED];


    nbytes = 0;
    ptr = NULL;
    curinst = (Dwarf_P_Frame_Pgm)
        _dwarf_p_get_alloc(NULL, sizeof(struct Dwarf_P_Frame_Pgm_s));
    if (curinst == NULL) {
        _dwarf_p_error(NULL, error, DW_DLE_FPGM_ALLOC);
        return ((Dwarf_P_Fde) DW_DLV_BADADDR);
    }

    if (op == DW_CFA_offset_extended_sf)
    {
      res = _dwarf_pro_encode_leb128_nm(val1, &nbytes1,
                                        buff1, sizeof(buff1));
      if (res != DW_DLV_OK) {
        _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
        return ((Dwarf_P_Fde) DW_DLV_BADADDR);
      }
      res = _dwarf_pro_encode_signed_leb128_nm(val2, &nbytes2,
                                               buff2, sizeof(buff2));
      if (res != DW_DLV_OK) {
        _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
        return ((Dwarf_P_Fde) DW_DLV_BADADDR);
      }
      ptr = (char *) _dwarf_p_get_alloc(NULL, nbytes1 + nbytes2);
      if (ptr == NULL) {
        _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
        return ((Dwarf_P_Fde) DW_DLV_BADADDR);
      }
      memcpy(ptr, buff1, nbytes1);
      memcpy(ptr + nbytes1, buff2, nbytes2);
      nbytes = nbytes1 + nbytes2;
    }
    curinst->dfp_opcode = op;
    curinst->dfp_args = ptr;
    curinst->dfp_nbytes = nbytes;
    curinst->dfp_next = NULL;

    _dwarf_pro_add_to_fde(fde, curinst);
    return fde;
}
예제 #2
0
Dwarf_P_Attribute
dwarf_add_AT_any_value_sleb(Dwarf_P_Die ownerdie,
    Dwarf_Half attrnum,
    Dwarf_Signed signed_value,
    Dwarf_Error * error)
{
    Dwarf_P_Attribute new_attr = 0;
    int leb_size = 0;
    char encode_buffer[ENCODE_SPACE_NEEDED];
    int res = 0;

    if (ownerdie == NULL) {
        _dwarf_p_error(NULL, error, DW_DLE_DIE_NULL);
        return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }

    new_attr = (Dwarf_P_Attribute)
        _dwarf_p_get_alloc(ownerdie->di_dbg, sizeof(struct Dwarf_P_Attribute_s));
    if (new_attr == NULL) {
        _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL);
        return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }

    new_attr->ar_attribute = attrnum;
    new_attr->ar_attribute_form = DW_FORM_sdata;
    new_attr->ar_rel_type = R_MIPS_NONE;
    new_attr->ar_reloc_len = 0; /* unused for R_MIPS_NONE */
    new_attr->ar_next = 0;

    res = _dwarf_pro_encode_signed_leb128_nm(signed_value, &leb_size,
        encode_buffer,
        sizeof(encode_buffer));
    if (res != DW_DLV_OK) {
        _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL);
        return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }
    new_attr->ar_data = (char *)
        _dwarf_p_get_alloc(ownerdie->di_dbg, leb_size);
    if (new_attr->ar_data == NULL) {
        _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL);
        return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }
    memcpy(new_attr->ar_data, encode_buffer, leb_size);
    new_attr->ar_nbytes = leb_size;

    /* add attribute to the die */
    _dwarf_pro_add_at_to_die(ownerdie, new_attr);
    return new_attr;
}
예제 #3
0
static unsigned
signedtest(unsigned len)
{
    unsigned errcnt = 0;
    unsigned t = 0;
    char bufferspace[BUFFERLEN];

    for ( ; t < len; ++t) {
        int res = 0;
        int encodelen = 0;
        Dwarf_Word decodelen = 0;
        Dwarf_Signed decodeval = 0;

        res = _dwarf_pro_encode_signed_leb128_nm(
            stest[t],&encodelen,bufferspace,BUFFERLEN);
        if (res != DW_DLV_OK) {
            printf("FAIL signed encode index %u val 0x%llx\n",
                t,stest[t]);
            ++errcnt;
        }
        res = _dwarf_decode_s_leb128_chk(
            (Dwarf_Small *)bufferspace,
            &decodelen,
            &decodeval,
            (Dwarf_Byte_Ptr)(&bufferspace[BUFFERLEN-1]));
        if (res != DW_DLV_OK) {
            printf("FAIL signed decode index %u val 0x%llx\n",
                t,stest[t]);
            ++errcnt;
        }
        if (stest[t] != decodeval) {
            printf("FAIL signed decode val index %u val 0x%llx vs 0x%llx\n",
                t,stest[t],decodeval);
            ++errcnt;
        }
        if ((Dwarf_Word)encodelen != decodelen) {
            printf("FAIL signed decodelen val index %u val 0x%llx\n",
                t,stest[t]);
            ++errcnt;
        }
    }
    return errcnt;
}
예제 #4
0
파일: dwarf_util.c 프로젝트: finik/libdwarf
/* Encode val as a signed LEB128. */
int dwarf_encode_signed_leb128(Dwarf_Signed val, int *nbytes,
    char *space, int splen)
{
    /* Encode val as a signed LEB128. */
    return _dwarf_pro_encode_signed_leb128_nm(val,nbytes,space,splen);
}
예제 #5
0
Dwarf_Unsigned
dwarf_add_expr_gen (
    Dwarf_P_Expr	expr,
    Dwarf_Small		opcode,
    Dwarf_Unsigned	val1,
    Dwarf_Unsigned	val2,
    Dwarf_Error		*error
)
{
    char encode_buffer[2*ENCODE_SPACE_NEEDED]; /* 2* since used
		to concatenate 2 leb's below */
    char encode_buffer2[ENCODE_SPACE_NEEDED];
    int  res;
    Dwarf_P_Debug dbg = expr->ex_dbg;
	/* 
	    Give the buffer where the operands are first
	    going to be assembled the largest alignment.
	*/
    Dwarf_Unsigned	operand_buffer[10];

	/* 
	    Size of the byte stream buffer that needs 
	    to be memcpy-ed.
	*/
    int			operand_size;

	/* 
	    Points to the byte stream for the first operand,
	    and finally to the buffer that is memcp-ed into
	    the Dwarf_P_Expr_s struct.
	*/
    Dwarf_Small		*operand;

	/* Size of the byte stream for second operand. */
    int			operand2_size;

	/* Points to next byte to be written in Dwarf_P_Expr_s struct. */
    Dwarf_Small		*next_byte_ptr;

	/* Offset past the last byte written into Dwarf_P_Expr_s. */
    int			next_byte_offset;

    /* ***** BEGIN CODE ***** */

    if (expr == NULL) {
	_dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL);
	return(DW_DLV_NOCOUNT);
    }

    if (expr->ex_dbg == NULL) {
	_dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
	return(DW_DLV_NOCOUNT);
    }

    operand = NULL;
    operand_size = 0;

    switch (opcode) {
        case DW_OP_reg0 :
	case DW_OP_reg1 :
	case DW_OP_reg2 :
	case DW_OP_reg3 :
	case DW_OP_reg4 :
	case DW_OP_reg5 :
	case DW_OP_reg6 :
	case DW_OP_reg7 :
	case DW_OP_reg8 :
	case DW_OP_reg9 :
	case DW_OP_reg10 :
	case DW_OP_reg11 :
	case DW_OP_reg12 :
	case DW_OP_reg13 :
	case DW_OP_reg14 :
	case DW_OP_reg15 :
	case DW_OP_reg16 :
	case DW_OP_reg17 :
	case DW_OP_reg18 :
	case DW_OP_reg19 :
	case DW_OP_reg20 :
	case DW_OP_reg21 :
	case DW_OP_reg22 :
	case DW_OP_reg23 :
	case DW_OP_reg24 :
	case DW_OP_reg25 :
	case DW_OP_reg26 :
	case DW_OP_reg27 :
	case DW_OP_reg28 :
	case DW_OP_reg29 :
	case DW_OP_reg30 :
	case DW_OP_reg31 :
	    break;

	case DW_OP_breg0 :
	case DW_OP_breg1 :
	case DW_OP_breg2 :
	case DW_OP_breg3 :
	case DW_OP_breg4 :
	case DW_OP_breg5 :
	case DW_OP_breg6 :
	case DW_OP_breg7 :
	case DW_OP_breg8 :
	case DW_OP_breg9 :
	case DW_OP_breg10 :
	case DW_OP_breg11 :
	case DW_OP_breg12 :
	case DW_OP_breg13 :
	case DW_OP_breg14 :
	case DW_OP_breg15 :
	case DW_OP_breg16 :
	case DW_OP_breg17 :
	case DW_OP_breg18 :
	case DW_OP_breg19 :
	case DW_OP_breg20 :
	case DW_OP_breg21 :
	case DW_OP_breg22 :
	case DW_OP_breg23 :
	case DW_OP_breg24 :
	case DW_OP_breg25 :
	case DW_OP_breg26 :
	case DW_OP_breg27 :
	case DW_OP_breg28 :
	case DW_OP_breg29 :
	case DW_OP_breg30 :
	case DW_OP_breg31 :
	    res = _dwarf_pro_encode_signed_leb128_nm(val1, 
			&operand_size,encode_buffer,sizeof(encode_buffer));
	    if(res != DW_DLV_OK) {
	        _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
	        return(DW_DLV_NOCOUNT);
	    }
	    operand = (Dwarf_Small *)encode_buffer;
	    break;

        case DW_OP_regx :
	    res = _dwarf_pro_encode_leb128_nm(val1, &operand_size,
			encode_buffer, sizeof(encode_buffer));
	    if(res != DW_DLV_OK) {
	        _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
	        return(DW_DLV_NOCOUNT);
	    }
	    operand = (Dwarf_Small *)encode_buffer;
	    break;

	case DW_OP_lit0 :
	case DW_OP_lit1 :
	case DW_OP_lit2 :
	case DW_OP_lit3 :
	case DW_OP_lit4 :
	case DW_OP_lit5 :
	case DW_OP_lit6 :
	case DW_OP_lit7 :
	case DW_OP_lit8 :
	case DW_OP_lit9 :
	case DW_OP_lit10 :
	case DW_OP_lit11 :
	case DW_OP_lit12 :
	case DW_OP_lit13 :
	case DW_OP_lit14 :
	case DW_OP_lit15 :
	case DW_OP_lit16 :
	case DW_OP_lit17 :
	case DW_OP_lit18 :
	case DW_OP_lit19 :
	case DW_OP_lit20 :
	case DW_OP_lit21 :
	case DW_OP_lit22 :
	case DW_OP_lit23 :
	case DW_OP_lit24 :
	case DW_OP_lit25 :
	case DW_OP_lit26 :
	case DW_OP_lit27 :
	case DW_OP_lit28 :
	case DW_OP_lit29 :
	case DW_OP_lit30 :
	case DW_OP_lit31 :
	    break;
        
	case DW_OP_addr :
	    _dwarf_p_error(expr->ex_dbg, error, DW_DLE_BAD_EXPR_OPCODE);
	    return(DW_DLV_NOCOUNT);

	case DW_OP_const1u :
	case DW_OP_const1s :
            operand = (Dwarf_Small *)&operand_buffer[0];
	    WRITE_UNALIGNED(dbg,operand,&val1,sizeof(val1),1);
	    operand_size = 1;
	    break;

	case DW_OP_const2u :
	case DW_OP_const2s :
	    operand = (Dwarf_Small *)&operand_buffer[0];
	    WRITE_UNALIGNED(dbg,operand,&val1,sizeof(val1),2);
	    operand_size = 2;
	    break;

	case DW_OP_const4u :
	case DW_OP_const4s :
	    operand = (Dwarf_Small *)&operand_buffer[0];
	    WRITE_UNALIGNED(dbg,operand,&val1,sizeof(val1),4);
	    operand_size = 4;
	    break;

	case DW_OP_const8u :
	case DW_OP_const8s :
	    operand = (Dwarf_Small *)&operand_buffer[0];
	    WRITE_UNALIGNED(dbg,operand,&val1,sizeof(val1),8);
	    operand_size = 8;
	    break;

        case DW_OP_constu :
	    res = _dwarf_pro_encode_leb128_nm(val1, 
			&operand_size,
			encode_buffer, sizeof(encode_buffer));
	    if(res != DW_DLV_OK) {
	        _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
	        return(DW_DLV_NOCOUNT);
	    }
	    operand = (Dwarf_Small *)encode_buffer;
	    break;

	case DW_OP_consts :
	    res = _dwarf_pro_encode_signed_leb128_nm(val1, 
			&operand_size,
			encode_buffer, sizeof(encode_buffer));
	    if(res != DW_DLV_OK) {
	        _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
	        return(DW_DLV_NOCOUNT);
	    }
	    operand = (Dwarf_Small *)encode_buffer;
	    break;

	case DW_OP_fbreg :
	    res = _dwarf_pro_encode_signed_leb128_nm(val1, 
			&operand_size,
			encode_buffer, sizeof(encode_buffer));
	    if(res != DW_DLV_OK) {
	        _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
	        return(DW_DLV_NOCOUNT);
	    }
	    operand = (Dwarf_Small *)encode_buffer;
	    break;

	case DW_OP_bregx :
	    res = _dwarf_pro_encode_leb128_nm(val1, &operand_size,
			encode_buffer, sizeof(encode_buffer));
	    if(res != DW_DLV_OK) {
	        _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
	        return(DW_DLV_NOCOUNT);
	    }
	    operand = (Dwarf_Small *)encode_buffer;
		/* put this one directly into 'operand' at tail of
		   prev value
	 	*/
	    res =  _dwarf_pro_encode_signed_leb128_nm(val2, &operand2_size,
			((char *)operand)+operand_size, sizeof(encode_buffer2));
	    if(res != DW_DLV_OK) {
	        _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
	        return(DW_DLV_NOCOUNT);
	    }
	    operand_size += operand2_size;

	case DW_OP_dup :
	case DW_OP_drop :
	    break;

	case DW_OP_pick :
	    operand = (Dwarf_Small *)&operand_buffer[0];
	    WRITE_UNALIGNED(dbg,operand,(const void *)val1,
			sizeof(val1),1);
	    operand_size = 1;
	    break;

	case DW_OP_over :
	case DW_OP_swap :
	case DW_OP_rot :
	case DW_OP_deref :
	case DW_OP_xderef :
            break;

	case DW_OP_deref_size :
	case DW_OP_xderef_size :
	    operand = (Dwarf_Small *)&operand_buffer[0];
	    WRITE_UNALIGNED(dbg,operand,(const void *)val1,
			sizeof(val1),1);
	    operand_size = 1;
	    break;

        case DW_OP_abs :
	case DW_OP_and :
	case DW_OP_div :
	case DW_OP_minus :
	case DW_OP_mod :
	case DW_OP_mul :
	case DW_OP_neg :
	case DW_OP_not :
	case DW_OP_or :
	case DW_OP_plus :
	    break;

	case DW_OP_plus_uconst :
	    res = _dwarf_pro_encode_leb128_nm(val1, &operand_size,
			encode_buffer, sizeof(encode_buffer));
	    if(res != DW_DLV_OK) {
	        _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
	        return(DW_DLV_NOCOUNT);
	    }
	    operand = (Dwarf_Small *)encode_buffer;
	    break;

	case DW_OP_shl :
	case DW_OP_shr :
	case DW_OP_shra :
	case DW_OP_xor :
	    break;

	case DW_OP_le :
	case DW_OP_ge :
	case DW_OP_eq :
	case DW_OP_lt :
	case DW_OP_gt :
	case DW_OP_ne :
	    break;

	case DW_OP_skip :
	case DW_OP_bra :
            /* FIX: unhandled! OP_bra, OP_skip! */
	    _dwarf_p_error(expr->ex_dbg, error, DW_DLE_BAD_EXPR_OPCODE);
	    return(DW_DLV_NOCOUNT);

	case DW_OP_piece :
	    res = _dwarf_pro_encode_leb128_nm(val1, &operand_size,
			encode_buffer, sizeof(encode_buffer));
	    if(res != DW_DLV_OK) {
	        _dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
	        return(DW_DLV_NOCOUNT);
	    }
	    operand = (Dwarf_Small *)encode_buffer;
	    break;

	case DW_OP_nop :
	    break;

	default :
	    _dwarf_p_error(expr->ex_dbg, error, DW_DLE_BAD_EXPR_OPCODE);
	    return(DW_DLV_NOCOUNT);
    }

    next_byte_offset = expr->ex_next_byte_offset + operand_size + 1;

    if (next_byte_offset > MAXIMUM_LOC_EXPR_LENGTH) {
	_dwarf_p_error(expr->ex_dbg, error, DW_DLE_EXPR_LENGTH_BAD);
	return(DW_DLV_NOCOUNT);
    }

    next_byte_ptr = &(expr->ex_byte_stream[0]) + expr->ex_next_byte_offset;

    *next_byte_ptr = opcode;
    next_byte_ptr++;
    memcpy(next_byte_ptr, operand, operand_size);

    expr->ex_next_byte_offset = next_byte_offset;
    return(next_byte_offset);
}
예제 #6
0
/*
    This function adds attributes whose value
    is an signed constant.  It determines the 
    size of the value field from the value of 
    the constant.
*/
Dwarf_P_Attribute
dwarf_add_AT_signed_const(Dwarf_P_Debug dbg,
			  Dwarf_P_Die ownerdie,
			  Dwarf_Half attr,
			  Dwarf_Signed value, Dwarf_Error * error)
{
    Dwarf_P_Attribute new_attr;
    Dwarf_Half attr_form;
    Dwarf_Small size;

    if (dbg == NULL) {
	_dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
	return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }

    if (ownerdie == NULL) {
	_dwarf_p_error(dbg, error, DW_DLE_DIE_NULL);
	return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }

    switch (attr) {
    case DW_AT_upper_bound:
    case DW_AT_lower_bound:
	break;

    default:{
	    _dwarf_p_error(dbg, error, DW_DLE_INPUT_ATTR_BAD);
	    return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
	}
    }

    /* Compute the number of bytes needed to hold constant.
       gdb seems to treat all the DW_FORM_data forms as unsigned, so
       if we have a negative number we need to encode it as signed
       data. */
    new_attr = (Dwarf_P_Attribute)
	_dwarf_p_get_alloc(NULL, sizeof(struct Dwarf_P_Attribute_s));
    if (new_attr == NULL) {
	_dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL);
	return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }

    if (value < 0) {
	attr_form = DW_FORM_sdata;
    } else if (value >= SCHAR_MIN && value <= SCHAR_MAX) {
	attr_form = DW_FORM_data1;
	size = 1;
    } else if (value >= SHRT_MIN && value <= SHRT_MAX) {
	attr_form = DW_FORM_data2;
	size = 2;
    } else if (value >= INT_MIN && value <= INT_MAX) {
	attr_form = DW_FORM_data4;
	size = 4;
    } else {
	attr_form = DW_FORM_data8;
	size = 8;
    }

    new_attr->ar_attribute = attr;
    new_attr->ar_attribute_form = attr_form;
    new_attr->ar_rel_type = R_MIPS_NONE;
    new_attr->ar_reloc_len = 0;	/* irrelevant: unused with R_MIPS_NONE 
				 */
    new_attr->ar_nbytes = size;
    new_attr->ar_next = 0;

    if (attr_form == DW_FORM_sdata) {
        int leb_size;
        char encode_buffer[ENCODE_SPACE_NEEDED];
        int res;

        res = _dwarf_pro_encode_signed_leb128_nm(
	    value, &leb_size,
	    encode_buffer,sizeof(encode_buffer));
        if (res != DW_DLV_OK) {
            _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL);
            return (Dwarf_P_Attribute) DW_DLV_BADADDR;
        }
        new_attr->ar_data = (char *) _dwarf_p_get_alloc(NULL, leb_size);
        if (new_attr->ar_data == NULL) {
            _dwarf_p_error(NULL, error, DW_DLE_ALLOC_FAIL);
            return (Dwarf_P_Attribute) DW_DLV_BADADDR;
        }
        memcpy(new_attr->ar_data,encode_buffer,leb_size);
        new_attr->ar_nbytes = leb_size;
    } else {
	new_attr->ar_data = (char *) _dwarf_p_get_alloc(dbg, size);
	if (new_attr->ar_data == NULL) {
	    _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
	    return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
	}
	WRITE_UNALIGNED(dbg, new_attr->ar_data,
			(const void *) &value, sizeof(value), size);
    }


    /* add attribute to the die */
    _dwarf_pro_add_at_to_die(ownerdie, new_attr);
    return new_attr;
}
예제 #7
0
/*  Generic routine to add opcode to fde instructions. val1 and
    val2 are parameters whose interpretation depends on the 'op'.

    This does not work properly for  DW_DLC_SYMBOLIC_RELOCATIONS
    for DW_CFA_set_loc or DW_DVA_advance_loc* 'op', as
    these ops normally are addresses or (DW_CFA_set_loc)
    or code lengths (DW_DVA_advance_loc*) and such must be
    represented with relocations and symbol indices for
    DW_DLC_SYMBOLIC_RELOCATIONS.

    This does not treat all DW_CFA instructions yet.

    For certain operations a val? value must be
    signed (though passed in as unsigned here).

    Currently this does not check that the frame
    version is 3(for dwarf3) or 4 (for dwarf4)
    when applying operations that are only valid for
    dwarf3 or dwarf4. */
Dwarf_P_Fde
dwarf_add_fde_inst(Dwarf_P_Fde fde,
    Dwarf_Small op,
    Dwarf_Unsigned val1,
    Dwarf_Unsigned val2, Dwarf_Error * error)
{
    Dwarf_P_Frame_Pgm curinst;
    int nbytes, nbytes1, nbytes2;
    Dwarf_Ubyte db;
    Dwarf_Half dh;
    Dwarf_Word dw;
    Dwarf_Unsigned du;
    char *ptr;
    int res;
    char buff1[ENCODE_SPACE_NEEDED];
    char buff2[ENCODE_SPACE_NEEDED];
    Dwarf_P_Debug dbg = fde->fde_dbg;
    /*  This is a hack telling the code when to transform
        a value to a signed leb number. */
    int signed_second = 0;
    int signed_first = 0;


    nbytes = 0;
    ptr = NULL;
    curinst = (Dwarf_P_Frame_Pgm)
        _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Frame_Pgm_s));
    if (curinst == NULL) {
        _dwarf_p_error(dbg, error, DW_DLE_FPGM_ALLOC);
        return ((Dwarf_P_Fde) DW_DLV_BADADDR);
    }

    switch (op) {

    case DW_CFA_advance_loc:
        if (val1 <= 0x3f) {
            db = val1;
            op |= db;
        }
        /* test not portable FIX */
        else if (val1 <= UCHAR_MAX) {
            op = DW_CFA_advance_loc1;
            db = val1;
            ptr = (char *) _dwarf_p_get_alloc(dbg, 1);
            if (ptr == NULL) {
                _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
                return ((Dwarf_P_Fde) DW_DLV_BADADDR);
            }
            memcpy((void *) ptr, (const void *) &db, 1);
            nbytes = 1;
        }
        /* test not portable FIX */
        else if (val1 <= USHRT_MAX) {
            op = DW_CFA_advance_loc2;
            dh = val1;
            ptr = (char *) _dwarf_p_get_alloc(dbg, 2);
            if (ptr == NULL) {
                _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
                return ((Dwarf_P_Fde) DW_DLV_BADADDR);
            }
            memcpy((void *) ptr, (const void *) &dh, 2);
            nbytes = 2;
        }
        /* test not portable FIX */
        else if (val1 <= ULONG_MAX) {
            op = DW_CFA_advance_loc4;
            dw = (Dwarf_Word) val1;
            ptr = (char *) _dwarf_p_get_alloc(dbg, 4);
            if (ptr == NULL) {
                _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
                return ((Dwarf_P_Fde) DW_DLV_BADADDR);
            }
            memcpy((void *) ptr, (const void *) &dw, 4);
            nbytes = 4;
        } else {
            op = DW_CFA_MIPS_advance_loc8;
            du = val1;
            ptr =
                (char *) _dwarf_p_get_alloc(dbg,
                    sizeof(Dwarf_Unsigned));
            if (ptr == NULL) {
                _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
                return ((Dwarf_P_Fde) DW_DLV_BADADDR);
            }
            memcpy((void *) ptr, (const void *) &du, 8);
            nbytes = 8;
        }
        break;

    case DW_CFA_offset:
        if (val1 <= MAX_6_BIT_VALUE) {
            db = val1;
            op |= db;
            res = _dwarf_pro_encode_leb128_nm(val2, &nbytes,
                buff1, sizeof(buff1));
            if (res != DW_DLV_OK) {
                _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
                return ((Dwarf_P_Fde) DW_DLV_BADADDR);
            }
            ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes);
            if (ptr == NULL) {
                _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
                return ((Dwarf_P_Fde) DW_DLV_BADADDR);
            }
            memcpy(ptr, buff1, nbytes);

        } else {
            op = DW_CFA_offset_extended;
            goto two_leb;
        }
        break;
    case DW_CFA_offset_extended_sf: /* DWARF3 */
        signed_second = 1;
        goto two_leb;
    case DW_CFA_offset_extended:
        goto two_leb;

    case DW_CFA_undefined:
    case DW_CFA_same_value:
        goto one_leb;

    case DW_CFA_val_offset:
        goto two_leb;
    case DW_CFA_val_offset_sf:
        signed_second = 1;
        goto two_leb;
    case DW_CFA_def_cfa_sf:
        signed_second = 1;
        goto two_leb;
    case DW_CFA_register:
    case DW_CFA_def_cfa:
    two_leb:
        res = _dwarf_pro_encode_leb128_nm(val1, &nbytes1,
            buff1, sizeof(buff1));
        if (res != DW_DLV_OK) {
            _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
            return ((Dwarf_P_Fde) DW_DLV_BADADDR);
        }
        if (!signed_second) {
            res = _dwarf_pro_encode_leb128_nm(val2, &nbytes2,
                buff2, sizeof(buff2));
        } else {
            Dwarf_Signed val2s = val2;
            res = _dwarf_pro_encode_signed_leb128_nm(val2s, &nbytes2,
                buff2, sizeof(buff2));
        }

        res = _dwarf_pro_encode_leb128_nm(val2, &nbytes2,
            buff2, sizeof(buff2));
        if (res != DW_DLV_OK) {
            _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
            return ((Dwarf_P_Fde) DW_DLV_BADADDR);
        }

        ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes1 + nbytes2);
        if (ptr == NULL) {
            _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
            return ((Dwarf_P_Fde) DW_DLV_BADADDR);
        }
        memcpy(ptr, buff1, nbytes1);
        memcpy(ptr + nbytes1, buff2, nbytes2);
        nbytes = nbytes1 + nbytes2;
        break;

    case DW_CFA_def_cfa_offset_sf: /* DWARF3 */
        signed_first = 1;
        goto one_leb;
    case DW_CFA_def_cfa_register:
    case DW_CFA_def_cfa_offset:
    one_leb:
        if (!signed_first) {
            res = _dwarf_pro_encode_leb128_nm(val1, &nbytes,
                buff1, sizeof(buff1));
        } else {
            Dwarf_Signed val1s = val1;
            res = _dwarf_pro_encode_signed_leb128_nm(val1s, &nbytes,
                buff1, sizeof(buff1));
        }
        if (res != DW_DLV_OK) {
            _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
            return ((Dwarf_P_Fde) DW_DLV_BADADDR);
        }
        ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes);
        if (ptr == NULL) {
            _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
            return ((Dwarf_P_Fde) DW_DLV_BADADDR);
        }
        memcpy(ptr, buff1, nbytes);
        break;
    case DW_CFA_def_cfa_expression: /* DWARF3 */
        /*  FIXME: argument is dwarf expr, not handled yet. */
    case DW_CFA_expression: /* DWARF3 */
        /*  First arg: ULEB reg num. 2nd arg dwarf expr in form block.
            FIXME: not handled yet. */
    case DW_CFA_val_expression: /* DWARF3f */
        /*  First arg: ULEB reg num. 2nd arg dwarf expr in form block.
            FIXME: not handled yet. */
    default:
        _dwarf_p_error(dbg, error, DW_DLE_DEBUGFRAME_ERROR);
        return ((Dwarf_P_Fde) DW_DLV_BADADDR);
    }

    curinst->dfp_opcode = op;
    curinst->dfp_args = ptr;
    curinst->dfp_nbytes = nbytes;
    curinst->dfp_next = NULL;

    _dwarf_pro_add_to_fde(fde, curinst);
    return fde;
}
예제 #8
0
void *
dwarf_compress_integer_block(
    Dwarf_P_Debug    dbg,
    Dwarf_Bool       unit_is_signed,
    Dwarf_Small      unit_length_in_bits,
    void*            input_block,
    Dwarf_Unsigned   input_length_in_units,
    Dwarf_Unsigned*  output_length_in_bytes_ptr,
    Dwarf_Error*     error
)
{
    Dwarf_Unsigned output_length_in_bytes = 0;
    char * output_block = 0;
    char encode_buffer[ENCODE_SPACE_NEEDED];
    unsigned u = 0;
    char * ptr = 0;
    int remain = 0;
    int result = 0;

    if (dbg == NULL) {
        _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
        return((void *)DW_DLV_BADADDR);
    }

    if (unit_is_signed == false ||
        unit_length_in_bits != 32 ||
        input_block == NULL ||
        input_length_in_units == 0 ||
        output_length_in_bytes_ptr == NULL) {
        _dwarf_p_error(NULL, error, DW_DLE_BADBITC);
        return ((void *) DW_DLV_BADADDR);
    }

    /* At this point we assume the format is: signed 32 bit */

    /* First compress everything to find the total size. */

    output_length_in_bytes = 0;
    for (u=0; u<input_length_in_units; u++) {
        int unit_encoded_size;
        Dwarf_sfixed unit; /* this is fixed at signed-32-bits */

        unit = ((Dwarf_sfixed*)input_block)[u];

        result = _dwarf_pro_encode_signed_leb128_nm(unit, &unit_encoded_size,
            encode_buffer,sizeof(encode_buffer));
        if (result !=  DW_DLV_OK) {
            _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
            return((Dwarf_P_Attribute)DW_DLV_BADADDR);
        }
        output_length_in_bytes += unit_encoded_size;
    }


    /* Then alloc */

    output_block = (void *)
        _dwarf_p_get_alloc(dbg, output_length_in_bytes);
    if (output_block == NULL) {
        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
        return((void*)DW_DLV_BADADDR);
    }

    /* Then compress again and copy into new buffer */

    ptr = output_block;
    remain = output_length_in_bytes;
    for (u=0; u<input_length_in_units; u++) {
        int unit_encoded_size;
        Dwarf_sfixed unit; /* this is fixed at signed-32-bits */

        unit = ((Dwarf_sfixed*)input_block)[u];

        result = _dwarf_pro_encode_signed_leb128_nm(unit, &unit_encoded_size,
            ptr, remain);
        if (result !=  DW_DLV_OK) {
            _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
            return((Dwarf_P_Attribute)DW_DLV_BADADDR);
        }
        remain -= unit_encoded_size;
        ptr += unit_encoded_size;
    }

    if (remain != 0) {
        _dwarf_p_dealloc(dbg, (unsigned char *)output_block);
        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
        return((Dwarf_P_Attribute)DW_DLV_BADADDR);
    }

    *output_length_in_bytes_ptr = output_length_in_bytes;
    return (void*) output_block;

}