Esempio n. 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;
}
Esempio n. 2
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;
}
Esempio n. 3
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;
}
Esempio n. 4
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;
}
Esempio n. 5
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;
}