diff options
Diffstat (limited to 'usr/src/lib/libdwarf/common/pro_expr.c')
-rw-r--r-- | usr/src/lib/libdwarf/common/pro_expr.c | 386 |
1 files changed, 233 insertions, 153 deletions
diff --git a/usr/src/lib/libdwarf/common/pro_expr.c b/usr/src/lib/libdwarf/common/pro_expr.c index ad40eb762a..6933b18e5e 100644 --- a/usr/src/lib/libdwarf/common/pro_expr.c +++ b/usr/src/lib/libdwarf/common/pro_expr.c @@ -1,51 +1,56 @@ /* - Copyright (C) 2000,2004,2006 Silicon Graphics, Inc. All Rights Reserved. Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2.1 of the GNU Lesser General Public License - as published by the Free Software Foundation. - - This program is distributed in the hope that it would be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - Further, this software is distributed without any warranty that it is - free of the rightful claim of any third person regarding infringement - or the like. Any license provided herein, whether implied or - otherwise, applies only to this software file. Patent licenses, if - any, provided herein do not apply to combinations of this program with - other software, or any other product whatsoever. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, - USA. - - Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - Mountain View, CA 94043, or: - - http://www.sgi.com - - For further information regarding this notice, see: - - http://oss.sgi.com/projects/GenInfo/NoticeExplan + Portions Copyright 2011-2019 David Anderson. All rights reserved. + + This program is free software; you can redistribute it + and/or modify it under the terms of version 2.1 of the + GNU Lesser General Public License as published by the Free + Software Foundation. + + This program is distributed in the hope that it would be + useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. + + Further, this software is distributed without any warranty + that it is free of the rightful claim of any third person + regarding infringement or the like. Any license provided + herein, whether implied or otherwise, applies only to this + software file. Patent licenses, if any, provided herein + do not apply to combinations of this program with other + software, or any other product whatsoever. + + You should have received a copy of the GNU Lesser General + Public License along with this program; if not, write the + Free Software Foundation, Inc., 51 Franklin Street - Fifth + Floor, Boston MA 02110-1301, USA. */ - - #include "config.h" #include "libdwarfdefs.h" #include <stdio.h> #include <string.h> -#include <sys/types.h> +#include <stddef.h> +#ifdef HAVE_STDINT_H +#include <stdint.h> /* For uintptr_t */ +#endif /* HAVE_STDINT_H */ #include "pro_incl.h" +#include "dwarf.h" +#include "libdwarf.h" +#include "pro_opaque.h" +#include "pro_error.h" +#include "pro_encode_nm.h" +#include "pro_alloc.h" #include "pro_expr.h" +#define SIZEOFT16 2 +#define SIZEOFT32 4 +#define SIZEOFT64 8 + /* - This function creates a new expression + This function creates a new expression struct that can be used to build up a location expression. */ @@ -71,55 +76,70 @@ dwarf_new_expr(Dwarf_P_Debug dbg, Dwarf_Error * error) return (ret_expr); } - Dwarf_Unsigned dwarf_add_expr_gen(Dwarf_P_Expr expr, - Dwarf_Small opcode, - Dwarf_Unsigned val1, - Dwarf_Unsigned val2, Dwarf_Error * error) + Dwarf_Small opcode, + Dwarf_Unsigned val1, + Dwarf_Unsigned val2, Dwarf_Error * error) +{ + Dwarf_Unsigned len = 0; + int res = 0; + + res = dwarf_add_expr_gen_a(expr,opcode, + val1,val2,&len,error); + if (res != DW_DLV_OK) { + return DW_DLV_NOCOUNT; + } + return len; + +} + +int +dwarf_add_expr_gen_a(Dwarf_P_Expr expr, + Dwarf_Small opcode, + Dwarf_Unsigned val1, + Dwarf_Unsigned val2, + Dwarf_Unsigned *stream_length_out, + Dwarf_Error * error) { - char encode_buffer[2 * ENCODE_SPACE_NEEDED]; /* 2* since - used to - concatenate - 2 leb's - below */ + /* 2* since used to concatenate 2 leb's below */ + char encode_buffer[2 * ENCODE_SPACE_NEEDED]; + char encode_buffer2[ENCODE_SPACE_NEEDED]; - int res; - Dwarf_P_Debug dbg = expr->ex_dbg; + int res = 0; + Dwarf_P_Debug dbg = 0; - /* - Give the buffer where the operands are first going to be - assembled the largest alignment. */ + /* 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; + /* Size of the byte stream buffer that needs to be memcpy-ed. */ + int operand_size = 0; - /* - 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; + /* 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 = 0; - /* Size of the byte stream for second operand. */ - int operand2_size; + /* Size of the byte stream for second operand. */ + int operand2_size = 0; - /* Points to next byte to be written in Dwarf_P_Expr_s struct. */ - Dwarf_Small *next_byte_ptr; + /* Points to next byte to be written in Dwarf_P_Expr_s struct. */ + Dwarf_Small *next_byte_ptr = 0; - /* Offset past the last byte written into Dwarf_P_Expr_s. */ - int next_byte_offset; + /* Offset past the last byte written into Dwarf_P_Expr_s. */ + int next_byte_offset = 0; /* ***** BEGIN CODE ***** */ if (expr == NULL) { _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL); - return (DW_DLV_NOCOUNT); + return DW_DLV_ERROR; } + dbg = expr->ex_dbg; if (expr->ex_dbg == NULL) { _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); - return (DW_DLV_NOCOUNT); + return DW_DLV_ERROR; } operand = NULL; @@ -193,23 +213,20 @@ dwarf_add_expr_gen(Dwarf_P_Expr expr, case DW_OP_breg30: case DW_OP_breg31: res = _dwarf_pro_encode_signed_leb128_nm(val1, - &operand_size, - encode_buffer, - sizeof(encode_buffer)); + &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); + return DW_DLV_ERROR; } operand = (Dwarf_Small *) encode_buffer; break; case DW_OP_regx: res = _dwarf_pro_encode_leb128_nm(val1, &operand_size, - encode_buffer, - sizeof(encode_buffer)); + 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); + return DW_DLV_ERROR; } operand = (Dwarf_Small *) encode_buffer; break; @@ -250,7 +267,7 @@ dwarf_add_expr_gen(Dwarf_P_Expr expr, case DW_OP_addr: _dwarf_p_error(expr->ex_dbg, error, DW_DLE_BAD_EXPR_OPCODE); - return (DW_DLV_NOCOUNT); + return DW_DLV_ERROR; case DW_OP_const1u: case DW_OP_const1s: @@ -269,8 +286,9 @@ dwarf_add_expr_gen(Dwarf_P_Expr expr, 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; + WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), + SIZEOFT32); + operand_size = SIZEOFT32; break; case DW_OP_const8u: @@ -282,58 +300,55 @@ dwarf_add_expr_gen(Dwarf_P_Expr expr, case DW_OP_constu: res = _dwarf_pro_encode_leb128_nm(val1, - &operand_size, - encode_buffer, - sizeof(encode_buffer)); + &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); + return DW_DLV_ERROR; } 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)); + &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); + return DW_DLV_ERROR; } 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)); + &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); + return DW_DLV_ERROR; } operand = (Dwarf_Small *) encode_buffer; break; case DW_OP_bregx: res = _dwarf_pro_encode_leb128_nm(val1, &operand_size, - encode_buffer, - sizeof(encode_buffer)); + 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); + return DW_DLV_ERROR; } 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)); + ((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); + return DW_DLV_ERROR; } operand_size += operand2_size; @@ -344,7 +359,7 @@ dwarf_add_expr_gen(Dwarf_P_Expr expr, case DW_OP_pick: operand = (Dwarf_Small *) & operand_buffer[0]; WRITE_UNALIGNED(dbg, operand, (const void *) &val1, - sizeof(val1), 1); + sizeof(val1), 1); operand_size = 1; break; @@ -359,7 +374,7 @@ dwarf_add_expr_gen(Dwarf_P_Expr expr, case DW_OP_xderef_size: operand = (Dwarf_Small *) & operand_buffer[0]; WRITE_UNALIGNED(dbg, operand, (const void *) &val1, - sizeof(val1), 1); + sizeof(val1), 1); operand_size = 1; break; @@ -377,11 +392,11 @@ dwarf_add_expr_gen(Dwarf_P_Expr expr, case DW_OP_plus_uconst: res = _dwarf_pro_encode_leb128_nm(val1, &operand_size, - encode_buffer, - sizeof(encode_buffer)); + 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); + return DW_DLV_ERROR; } operand = (Dwarf_Small *) encode_buffer; break; @@ -404,15 +419,15 @@ dwarf_add_expr_gen(Dwarf_P_Expr expr, 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); + return DW_DLV_ERROR; case DW_OP_piece: res = _dwarf_pro_encode_leb128_nm(val1, &operand_size, - encode_buffer, - sizeof(encode_buffer)); + 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); + return DW_DLV_ERROR; } operand = (Dwarf_Small *) encode_buffer; break; @@ -423,21 +438,21 @@ dwarf_add_expr_gen(Dwarf_P_Expr expr, break; case DW_OP_call2: /* DWARF3 */ operand = (Dwarf_Small *) & operand_buffer[0]; - WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 2); - operand_size = 2; + WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), SIZEOFT16); + operand_size = SIZEOFT16; break; case DW_OP_call4: /* DWARF3 */ operand = (Dwarf_Small *) & operand_buffer[0]; - WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), 4); - operand_size = 4; + WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), SIZEOFT32); + operand_size = SIZEOFT32; break; case DW_OP_call_ref: /* DWARF3 */ operand = (Dwarf_Small *) & operand_buffer[0]; WRITE_UNALIGNED(dbg, operand, &val1, sizeof(val1), - dbg->de_offset_size); - operand_size = dbg->de_offset_size; + dbg->de_dwarf_offset_size); + operand_size = dbg->de_dwarf_offset_size; break; case DW_OP_form_tls_address: /* DWARF3f */ break; @@ -445,35 +460,34 @@ dwarf_add_expr_gen(Dwarf_P_Expr expr, break; case DW_OP_bit_piece: /* DWARF3f */ res = _dwarf_pro_encode_leb128_nm(val1, &operand_size, - encode_buffer, - sizeof(encode_buffer)); + 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); + return DW_DLV_ERROR; } operand = (Dwarf_Small *) encode_buffer; /* put this one directly into 'operand' at tail of prev value */ res = _dwarf_pro_encode_leb128_nm(val2, &operand2_size, - ((char *) operand) + - operand_size, - sizeof(encode_buffer2)); + ((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); + return DW_DLV_ERROR; } operand_size += operand2_size; - break; - + break; default: _dwarf_p_error(expr->ex_dbg, error, DW_DLE_BAD_EXPR_OPCODE); - return (DW_DLV_NOCOUNT); + return DW_DLV_ERROR; } 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); + return DW_DLV_ERROR; } next_byte_ptr = @@ -481,16 +495,38 @@ dwarf_add_expr_gen(Dwarf_P_Expr expr, *next_byte_ptr = opcode; next_byte_ptr++; - memcpy(next_byte_ptr, operand, operand_size); + if (operand) { + memcpy(next_byte_ptr, operand, operand_size); + } expr->ex_next_byte_offset = next_byte_offset; - return (next_byte_offset); + *stream_length_out = next_byte_offset; + return DW_DLV_OK; } Dwarf_Unsigned dwarf_add_expr_addr_b(Dwarf_P_Expr expr, - Dwarf_Unsigned addr, - Dwarf_Unsigned sym_index, Dwarf_Error * error) + Dwarf_Unsigned addr, + Dwarf_Unsigned sym_index, + Dwarf_Error * error) +{ + Dwarf_Unsigned length = 0; + int res = 0; + + res = dwarf_add_expr_addr_c(expr,addr,sym_index, + &length,error); + if (res != DW_DLV_OK) { + return DW_DLV_NOCOUNT; + } + return length; + +} +int +dwarf_add_expr_addr_c(Dwarf_P_Expr expr, + Dwarf_Unsigned addr, + Dwarf_Unsigned sym_index, + Dwarf_Unsigned *stream_length_out, + Dwarf_Error * error) { Dwarf_P_Debug dbg; Dwarf_Small *next_byte_ptr; @@ -499,20 +535,20 @@ dwarf_add_expr_addr_b(Dwarf_P_Expr expr, if (expr == NULL) { _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL); - return (DW_DLV_NOCOUNT); + return (DW_DLV_ERROR); } dbg = expr->ex_dbg; if (dbg == NULL) { _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); - return (DW_DLV_NOCOUNT); + return (DW_DLV_ERROR); } upointer_size = dbg->de_pointer_size; next_byte_offset = expr->ex_next_byte_offset + upointer_size + 1; if (next_byte_offset > MAXIMUM_LOC_EXPR_LENGTH) { _dwarf_p_error(dbg, error, DW_DLE_EXPR_LENGTH_BAD); - return (DW_DLV_NOCOUNT); + return (DW_DLV_ERROR); } next_byte_ptr = @@ -521,77 +557,121 @@ dwarf_add_expr_addr_b(Dwarf_P_Expr expr, *next_byte_ptr = DW_OP_addr; next_byte_ptr++; WRITE_UNALIGNED(dbg, next_byte_ptr, (const void *) &addr, - sizeof(addr), upointer_size); + sizeof(addr), upointer_size); if (expr->ex_reloc_offset != 0) { _dwarf_p_error(dbg, error, DW_DLE_MULTIPLE_RELOC_IN_EXPR); - return (DW_DLV_NOCOUNT); + return (DW_DLV_ERROR); } expr->ex_reloc_sym_index = sym_index; expr->ex_reloc_offset = expr->ex_next_byte_offset + 1; expr->ex_next_byte_offset = next_byte_offset; - return (next_byte_offset); + *stream_length_out = next_byte_offset; + return DW_DLV_OK; } Dwarf_Unsigned dwarf_add_expr_addr(Dwarf_P_Expr expr, - Dwarf_Unsigned addr, - Dwarf_Signed sym_index, Dwarf_Error * error) + Dwarf_Unsigned addr, + Dwarf_Signed sym_index, + Dwarf_Error * error) { - return - dwarf_add_expr_addr_b(expr, addr, (Dwarf_Unsigned) sym_index, - error); + Dwarf_Unsigned length = 0; + int res = 0; + Dwarf_P_Debug dbg = 0; + + if (sym_index < 0) { + _dwarf_p_error(dbg, error, + DW_DLE_RELOC_SECTION_SYMBOL_INDEX_BAD); + return DW_DLV_NOCOUNT; + } + res = dwarf_add_expr_addr_c(expr, + (Dwarf_Unsigned)addr, + (Dwarf_Unsigned)sym_index, + &length,error); + if (res != DW_DLV_OK) { + return (Dwarf_Unsigned)DW_DLV_NOCOUNT; + } + return length; } - Dwarf_Unsigned dwarf_expr_current_offset(Dwarf_P_Expr expr, Dwarf_Error * error) { + Dwarf_Unsigned l = 0; + int res = 0; + + res = dwarf_expr_current_offset_a(expr,&l,error); + if (res != DW_DLV_OK) { + return (DW_DLV_NOCOUNT); + } + return l; +} + +int +dwarf_expr_current_offset_a(Dwarf_P_Expr expr, + Dwarf_Unsigned * stream_length_out, + Dwarf_Error * error) +{ if (expr == NULL) { _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL); - return (DW_DLV_NOCOUNT); + return DW_DLV_ERROR; } if (expr->ex_dbg == NULL) { _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); - return (DW_DLV_NOCOUNT); + return DW_DLV_ERROR; } - - return (expr->ex_next_byte_offset); + *stream_length_out = expr->ex_next_byte_offset; + return DW_DLV_OK; } void dwarf_expr_reset(Dwarf_P_Expr expr, Dwarf_Error * error) { - if (expr == NULL) { - _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL); - return; - } - expr->ex_next_byte_offset=0; + if (expr == NULL) { + _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL); + return; + } + expr->ex_next_byte_offset=0; } - Dwarf_Addr dwarf_expr_into_block(Dwarf_P_Expr expr, - Dwarf_Unsigned * length, Dwarf_Error * error) + Dwarf_Unsigned * length, + Dwarf_Error * error) +{ + Dwarf_Small *addr = 0; + int res = 0; + + res = dwarf_expr_into_block_a(expr,length,&addr,error); + if (res != DW_DLV_OK) { + return (DW_DLV_BADADDR); + } + return (Dwarf_Addr)(uintptr_t)addr; +} + + +int +dwarf_expr_into_block_a(Dwarf_P_Expr expr, + Dwarf_Unsigned * length, + Dwarf_Small ** address, + Dwarf_Error * error) { if (expr == NULL) { _dwarf_p_error(NULL, error, DW_DLE_EXPR_NULL); - return (DW_DLV_BADADDR); + return DW_DLV_ERROR; } if (expr->ex_dbg == NULL) { _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL); - return (DW_DLV_BADADDR); + return DW_DLV_ERROR; } if (length != NULL) *length = expr->ex_next_byte_offset; - /* The following cast from pointer to integer is ok as long as - Dwarf_Addr is at least as large as a pointer. Which is a - requirement of libdwarf so must be satisfied (some compilers - emit a warning about the following line). */ - return ((Dwarf_Addr)(uintptr_t) &(expr->ex_byte_stream[0])); + *address = &(expr->ex_byte_stream[0]); + return DW_DLV_OK; } |