Exemplo n.º 1
0
static int
libdwarf_compose_add_line(Dwarf_P_Debug dbg,
			  Dwarf_Unsigned line, int *compose_error_type)
{
    struct dw_macinfo_block_s *curblk = dbg->de_current_macinfo;
    unsigned char *nextchar;
    int res;
    int nbytes;

    nextchar =
	(unsigned char *) (curblk->mb_data + dbg->de_compose_used_len);

    /* Put the created leb number directly into the macro buffer If
       dbg->de_compose_avail is > INT_MAX this will not work as the
       'int' will look negative to _dwarf_pro_encode_leb128_nm! */

    res = _dwarf_pro_encode_leb128_nm(line, &nbytes,
				      (char *) nextchar,
				      (int) dbg->de_compose_avail);
    if (res != DW_DLV_OK) {
	*compose_error_type = DW_DLE_MACINFO_INTERNAL_ERROR_SPACE;
	return DW_DLV_ERROR;
    }

    dbg->de_compose_avail -= nbytes;
    dbg->de_compose_used_len += nbytes;
    return DW_DLV_OK;
}
Exemplo n.º 2
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;
}
Exemplo n.º 3
0
Dwarf_P_Attribute
dwarf_add_AT_any_value_uleb(Dwarf_P_Die ownerdie,
    Dwarf_Half attrnum,
    Dwarf_Unsigned unsigned_value,
    Dwarf_Error * error)
{
    Dwarf_P_Attribute new_attr;
    int leb_size;
    char encode_buffer[ENCODE_SPACE_NEEDED];
    int res;

    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_udata;
    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_leb128_nm(unsigned_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;
}
Exemplo n.º 4
0
/*  Add a cfe_offset instruction to the fde passed in. */
Dwarf_P_Fde
dwarf_fde_cfa_offset(Dwarf_P_Fde fde,
    Dwarf_Unsigned reg,
    Dwarf_Signed offset, Dwarf_Error * error)
{
    Dwarf_Ubyte opc, regno;
    char *ptr = 0;
    Dwarf_P_Frame_Pgm curinst;
    int nbytes = 0;
    int res = 0;
    char buff1[ENCODE_SPACE_NEEDED];
    Dwarf_P_Debug dbg = fde->fde_dbg;

    curinst = (Dwarf_P_Frame_Pgm)
        _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Frame_Pgm_s));
    if (curinst == NULL) {
        DWARF_P_DBG_ERROR(dbg, DW_DLE_FPGM_ALLOC,
            (Dwarf_P_Fde) DW_DLV_BADADDR);
    }
    opc = DW_CFA_offset;
    regno = reg;
    if (regno & 0xc0) {
        DWARF_P_DBG_ERROR(dbg, DW_DLE_REGNO_OVFL,
            (Dwarf_P_Fde) DW_DLV_BADADDR);
    }
    opc = opc | regno;          /* lower 6 bits are register number */
    curinst->dfp_opcode = opc;
    res = _dwarf_pro_encode_leb128_nm(offset, &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);

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

    _dwarf_pro_add_to_fde(fde, curinst);
    return fde;
}
Exemplo n.º 5
0
static  unsigned
unsignedtest(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_Unsigned decodeval = 0;

        res = _dwarf_pro_encode_leb128_nm(
            utest[t],&encodelen,bufferspace,BUFFERLEN);
        if (res != DW_DLV_OK) {
            printf("FAIL signed encode index %u val 0x%llx",
                t,utest[t]);
            ++errcnt;
        }
        res = _dwarf_decode_u_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,utest[t]);
            ++errcnt;
        }
        if (utest[t] != decodeval) {
            printf("FAIL signed decode val index %u val 0x%llx vs 0x%llx\n",
                t,utest[t],decodeval);
            ++errcnt;
        }
        if ((Dwarf_Word)encodelen != decodelen) {
            printf("FAIL signed decodelen val index %u val 0x%llx\n",
                t,utest[t]);
            ++errcnt;
        }
    }
    return errcnt;
}
Exemplo n.º 6
0
/* Encode val as an unsigned LEB128. */
int dwarf_encode_leb128(Dwarf_Unsigned val, int *nbytes,
    char *space, int splen)
{
    /* Encode val as an unsigned LEB128. */
    return _dwarf_pro_encode_leb128_nm(val,nbytes,space,splen);
}
Exemplo n.º 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.

*/
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];


    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);
    }

    switch (op) {

#ifdef TARG_X8664
	case DW_CFA_advance_loc4:
	    // We will use 2 half-words to copy the labels; cg will later
	    // fix the relocatable symbols.
	    dh = val1;
	    ptr = (char *) _dwarf_p_get_alloc(NULL, 4);
	    if (ptr == NULL) {
	      _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
	      return((Dwarf_P_Fde)DW_DLV_BADADDR);
	    }
	    memcpy((void *)ptr, (const void *)&dh,2);
	    dh = val2;
	    memcpy((void *)ptr+2, (const void *)&dh,2);
	    nbytes = 4;
	    break;
#endif // TARG_X8664
    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(NULL, 1);
	    if (ptr == NULL) {
		_dwarf_p_error(NULL, 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(NULL, 2);
	    if (ptr == NULL) {
		_dwarf_p_error(NULL, 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(NULL, 4);
	    if (ptr == NULL) {
		_dwarf_p_error(NULL, 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(NULL,
					    sizeof(Dwarf_Unsigned));
	    if (ptr == NULL) {
		_dwarf_p_error(NULL, 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(NULL, error, DW_DLE_STRING_ALLOC);
		return ((Dwarf_P_Fde) DW_DLV_BADADDR);
	    }
	    ptr = (char *) _dwarf_p_get_alloc(NULL, nbytes);
	    if (ptr == NULL) {
		_dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
		return ((Dwarf_P_Fde) DW_DLV_BADADDR);
	    }
	    memcpy(ptr, buff1, nbytes);

	} else {
	    op = DW_CFA_offset_extended;

	    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_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;
	}
	break;

    case DW_CFA_undefined:
    case DW_CFA_same_value:
	res = _dwarf_pro_encode_leb128_nm(val1, &nbytes,
					  buff1, sizeof(buff1));
	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, nbytes);
	if (ptr == NULL) {
	    _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
	    return ((Dwarf_P_Fde) DW_DLV_BADADDR);
	}
	memcpy(ptr, buff1, nbytes);
	break;

    case DW_CFA_register:
    case DW_CFA_def_cfa:
	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_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;
	break;

    case DW_CFA_def_cfa_register:
    case DW_CFA_def_cfa_offset:
	res = _dwarf_pro_encode_leb128_nm(val1, &nbytes,
					  buff1, sizeof(buff1));
	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, nbytes);
	if (ptr == NULL) {
	    _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
	    return ((Dwarf_P_Fde) DW_DLV_BADADDR);
	}
	memcpy(ptr, buff1, nbytes);
	break;

    default:
	break;
    }

    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;
}
Exemplo n.º 8
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);
}
Exemplo n.º 9
0
/*
    This function adds attributes whose value
    is a location expression.
*/
Dwarf_P_Attribute
dwarf_add_AT_location_expr(Dwarf_P_Debug dbg,
			   Dwarf_P_Die ownerdie,
			   Dwarf_Half attr,
			   Dwarf_P_Expr loc_expr, Dwarf_Error * error)
{
    char encode_buffer[ENCODE_SPACE_NEEDED];
    int res;
    Dwarf_P_Attribute new_attr;
    Dwarf_Half attr_form;
    char *len_str;
    int len_size;
    int block_size;
    char *block_dest_ptr;
    int do_len_as_int = 0;

    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);
    }

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

    if (loc_expr->ex_dbg != dbg) {
	_dwarf_p_error(dbg, error, DW_DLE_LOC_EXPR_BAD);
	return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }
    block_size = loc_expr->ex_next_byte_offset;

    switch (attr) {
    case DW_AT_location:
    case DW_AT_string_length:
    case DW_AT_const_value:
    case DW_AT_use_location:
    case DW_AT_return_addr:
    case DW_AT_data_member_location:
    case DW_AT_frame_base:
    case DW_AT_static_link:
    case DW_AT_vtable_elem_location:
	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. */
    if (block_size <= UCHAR_MAX) {
	attr_form = DW_FORM_block1;
	len_size = 1;
	do_len_as_int = 1;
    } else if (block_size <= USHRT_MAX) {
	attr_form = DW_FORM_block2;
	len_size = 2;
	do_len_as_int = 1;
    } else if (block_size <= UINT_MAX) {
	attr_form = DW_FORM_block4;
	len_size = 4;
	do_len_as_int = 1;
    } else {
	attr_form = DW_FORM_block;
	res = _dwarf_pro_encode_leb128_nm(block_size, &len_size,
					  encode_buffer,
					  sizeof(encode_buffer));
	if (res != DW_DLV_OK) {
	    _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
	    return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
	}
	len_str = (char *) encode_buffer;
    }

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

    new_attr->ar_attribute = attr;
    new_attr->ar_attribute_form = attr_form;
    new_attr->ar_reloc_len = dbg->de_pointer_size;
    if (loc_expr->ex_reloc_sym_index != NO_ELF_SYM_INDEX) {
	new_attr->ar_rel_type = dbg->de_ptr_reloc;
    } else {
	new_attr->ar_rel_type = R_MIPS_NONE;
    }
    new_attr->ar_rel_symidx = loc_expr->ex_reloc_sym_index;
    new_attr->ar_rel_offset =
	(Dwarf_Word) loc_expr->ex_reloc_offset + len_size;

    new_attr->ar_nbytes = block_size + len_size;

    new_attr->ar_next = 0;
    new_attr->ar_data = block_dest_ptr =
	(char *) _dwarf_p_get_alloc(dbg, block_size + len_size);
    if (new_attr->ar_data == NULL) {
	_dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
	return ((Dwarf_P_Attribute) DW_DLV_BADADDR);
    }

    if (do_len_as_int) {
	WRITE_UNALIGNED(dbg, block_dest_ptr, (const void *) &block_size,
			sizeof(block_size), len_size);
    } else {
	/* is uleb number form */
	memcpy(block_dest_ptr, len_str, len_size);
    }
    block_dest_ptr += len_size;
    memcpy(block_dest_ptr, &(loc_expr->ex_byte_stream[0]), block_size);

    /* add attribute to the die */
    _dwarf_pro_add_at_to_die(ownerdie, new_attr);
    return new_attr;
}
Exemplo n.º 10
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;
}
Exemplo n.º 11
0
Dwarf_P_Attribute
dwarf_add_AT_block(
    Dwarf_P_Debug       dbg,
    Dwarf_P_Die         ownerdie,
    Dwarf_Half          attr,
    Dwarf_Small         *block_data,
    Dwarf_Unsigned      block_size,
    Dwarf_Error         *error
)
{
    Dwarf_P_Attribute   new_attr = 0;
    int result = 0;
    char encode_buffer[ENCODE_SPACE_NEEDED];
    int len_size = 0;
    char * attrdata = 0;

    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);
    }

    /* I don't mess with block1, block2, block4, not worth the effort */

    /* So, encode the length into LEB128 */
    result = _dwarf_pro_encode_leb128_nm(block_size, &len_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);
    }

    /* Allocate the new attribute */
    new_attr = (Dwarf_P_Attribute)
        _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Attribute_s));
    if (new_attr == NULL) {
        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
        return((Dwarf_P_Attribute)DW_DLV_BADADDR);
    }

    /* Fill in the attribute */
    new_attr->ar_attribute = attr;
    new_attr->ar_attribute_form = DW_FORM_block;
    new_attr->ar_nbytes = len_size + block_size;
    new_attr->ar_next = 0;

    new_attr->ar_data = attrdata = (char *)
        _dwarf_p_get_alloc(dbg, len_size + block_size);
    if (new_attr->ar_data == NULL) {
        /* free the block we got earlier */
        _dwarf_p_dealloc(dbg, (unsigned char *) new_attr);
        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
        return((Dwarf_P_Attribute)DW_DLV_BADADDR);
    }

    /* write length and data to attribute data buffer */
    memcpy(attrdata, encode_buffer, len_size);
    attrdata += len_size;
    memcpy(attrdata, block_data, block_size);

    /* add attribute to the die */
    _dwarf_pro_add_at_to_die(ownerdie, new_attr);

    return new_attr;
}
Exemplo n.º 12
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.

*/
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];


    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);
    }

    switch (op) {
#if defined TARG_X8664
    	// This does not seem specific to x8664, but I will leave it for now.
 	// The previous code here apparently assumed the labels for this "op"
	// need to be encoded in 4 bytes --- that is not the case. This "op"
	// limits to 4 bytes whatever follows it. And whatever follows it is
	// the subtraction between the 2 labels, i.e., each label may need
	// more number of bytes.
	// Use Dwarf_Unsigned for each label (bugs 4071, 4490, 9729), also
	// affects code in pro_section.c and dwf_section.c.
	case DW_CFA_advance_loc4:
	    du = val1;
    	    ptr = (char *) _dwarf_p_get_alloc(NULL, 2 * sizeof(Dwarf_Unsigned));
    	    if (ptr == NULL) {
    	      _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
      	      return((Dwarf_P_Fde)DW_DLV_BADADDR);
    	    }
    	    memcpy((void *)ptr, (const void *)&du, sizeof(Dwarf_Unsigned));
  	    du = val2;
    	    memcpy((void *)ptr + sizeof(Dwarf_Unsigned), (const void *)&du,
                       sizeof(Dwarf_Unsigned));
      	    nbytes = 4;
    	    break;
#endif // TARG_X8664
    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(NULL, 1);
	    if (ptr == NULL) {
		_dwarf_p_error(NULL, 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(NULL, 2);
	    if (ptr == NULL) {
		_dwarf_p_error(NULL, 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(NULL, 4);
	    if (ptr == NULL) {
		_dwarf_p_error(NULL, 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(NULL,
					    sizeof(Dwarf_Unsigned));
	    if (ptr == NULL) {
		_dwarf_p_error(NULL, 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(NULL, error, DW_DLE_STRING_ALLOC);
		return ((Dwarf_P_Fde) DW_DLV_BADADDR);
	    }
	    ptr = (char *) _dwarf_p_get_alloc(NULL, nbytes);
	    if (ptr == NULL) {
		_dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
		return ((Dwarf_P_Fde) DW_DLV_BADADDR);
	    }
	    memcpy(ptr, buff1, nbytes);

	} else {
	    op = DW_CFA_offset_extended;

	    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_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;
	}
	break;

    case DW_CFA_undefined:
    case DW_CFA_same_value:
	res = _dwarf_pro_encode_leb128_nm(val1, &nbytes,
					  buff1, sizeof(buff1));
	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, nbytes);
	if (ptr == NULL) {
	    _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
	    return ((Dwarf_P_Fde) DW_DLV_BADADDR);
	}
	memcpy(ptr, buff1, nbytes);
	break;

    case DW_CFA_register:
    case DW_CFA_def_cfa:
	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_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;
	break;

    case DW_CFA_def_cfa_register:
    case DW_CFA_def_cfa_offset:
	res = _dwarf_pro_encode_leb128_nm(val1, &nbytes,
					  buff1, sizeof(buff1));
	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, nbytes);
	if (ptr == NULL) {
	    _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
	    return ((Dwarf_P_Fde) DW_DLV_BADADDR);
	}
	memcpy(ptr, buff1, nbytes);
	break;

#ifdef TARG_SL
    case DW_CFA_SL_gpr_reginfo:
    case DW_CFA_SL_cr_reginfo:
    case DW_CFA_SL_sr_reginfo:
    nbytes = 4;
	res = _dwarf_pro_encode_leb128_nm(val1, &nbytes,
					  buff1, sizeof(buff1));
	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, nbytes);
	if (ptr == NULL) {
	    _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
	    return ((Dwarf_P_Fde) DW_DLV_BADADDR);
	}
	memcpy(ptr, buff1, nbytes);
	break;
#endif

    default:
	break;
    }

    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;
}
Exemplo n.º 13
0
/*-----------------------------------------------------------------------
        Add a file entry declaration to the debug_line section. Stored
        in linked list. The data is immediately encodes as leb128
        and stored in Dwarf_P_F_Entry_s struct.
------------------------------------------------------------------------*/
Dwarf_Unsigned
dwarf_add_file_decl(Dwarf_P_Debug dbg,
                    char *name,
                    Dwarf_Unsigned dir_idx,
                    Dwarf_Unsigned time_mod,
                    Dwarf_Unsigned length, Dwarf_Error * error)
{
    Dwarf_P_F_Entry cur;
    char *ptr;
    int nbytes_idx, nbytes_time, nbytes_len;
    char buffidx[ENCODE_SPACE_NEEDED];
    char bufftime[ENCODE_SPACE_NEEDED];
    char bufflen[ENCODE_SPACE_NEEDED];
    int res;

    if (dbg->de_file_entries == NULL) {
        dbg->de_file_entries = (Dwarf_P_F_Entry)
            _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_F_Entry_s));
        if (dbg->de_file_entries == NULL) {
            DWARF_P_DBG_ERROR(dbg, DW_DLE_FILE_ENTRY_ALLOC,
                              DW_DLV_NOCOUNT);
        }
        cur = dbg->de_file_entries;
        dbg->de_last_file_entry = cur;
        dbg->de_n_file_entries = 1;
    } else {
        cur = dbg->de_last_file_entry;
        cur->dfe_next = (Dwarf_P_F_Entry)
            _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_F_Entry_s));
        if (cur->dfe_next == NULL) {
            DWARF_P_DBG_ERROR(dbg, DW_DLE_FILE_ENTRY_ALLOC,
                              DW_DLV_NOCOUNT);
        }
        cur = cur->dfe_next;
        dbg->de_last_file_entry = cur;
        dbg->de_n_file_entries++;
    }
    cur->dfe_name = (char *) _dwarf_p_get_alloc(dbg, strlen(name) + 1);
    if (cur->dfe_name == NULL) {
        DWARF_P_DBG_ERROR(dbg, DW_DLE_ALLOC_FAIL, DW_DLV_NOCOUNT);
    }
    strcpy((char *) cur->dfe_name, name);
    res = _dwarf_pro_encode_leb128_nm(dir_idx, &nbytes_idx,
                                      buffidx, sizeof(buffidx));
    if (res != DW_DLV_OK) {
        DWARF_P_DBG_ERROR(dbg, DW_DLE_ALLOC_FAIL, DW_DLV_NOCOUNT);
    }
    res = _dwarf_pro_encode_leb128_nm(time_mod, &nbytes_time,
                                      bufftime, sizeof(bufftime));
    if (res != DW_DLV_OK) {
        DWARF_P_DBG_ERROR(dbg, DW_DLE_ALLOC_FAIL, DW_DLV_NOCOUNT);
    }
    res = _dwarf_pro_encode_leb128_nm(length, &nbytes_len,
                                      bufflen, sizeof(bufflen));
    cur->dfe_args = (char *)
        _dwarf_p_get_alloc(dbg, nbytes_idx + nbytes_time + nbytes_len);
    if (cur->dfe_args == NULL) {
        DWARF_P_DBG_ERROR(dbg, DW_DLE_ALLOC_FAIL, DW_DLV_NOCOUNT);
    }
    ptr = cur->dfe_args;
    memcpy((void *) ptr, buffidx, nbytes_idx);
    ptr += nbytes_idx;
    memcpy((void *) ptr, bufftime, nbytes_time);
    ptr += nbytes_time;
    memcpy((void *) ptr, bufflen, nbytes_len);
    ptr += nbytes_len;
    cur->dfe_nbytes = nbytes_idx + nbytes_time + nbytes_len;
    cur->dfe_next = NULL;

    return dbg->de_n_file_entries;
}