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