diff options
author | Robert Mustacchi <rm@fingolfin.org> | 2020-06-25 17:58:31 -0700 |
---|---|---|
committer | Robert Mustacchi <rm@fingolfin.org> | 2020-07-10 12:35:15 -0700 |
commit | 4d9fdb46b215739778ebc12079842c9905586999 (patch) | |
tree | 3771cce63ac88d62941f4174ee3fa58336a95775 /usr/src/lib/libdwarf/common/pro_frame.c | |
parent | 4c60ecf710115cd5ae61f6b97dafc7ff963259f4 (diff) | |
download | illumos-gate-4d9fdb46b215739778ebc12079842c9905586999.tar.gz |
12223 Update libdwarf to libdwarf-20200612
Reviewed by: Richard Lowe <richlowe@richlowe.net>
Approved by: Dan McDonald <danmcd@joyent.com>
Diffstat (limited to 'usr/src/lib/libdwarf/common/pro_frame.c')
-rw-r--r-- | usr/src/lib/libdwarf/common/pro_frame.c | 689 |
1 files changed, 440 insertions, 249 deletions
diff --git a/usr/src/lib/libdwarf/common/pro_frame.c b/usr/src/lib/libdwarf/common/pro_frame.c index bd1ef6a637..40f8c6b792 100644 --- a/usr/src/lib/libdwarf/common/pro_frame.c +++ b/usr/src/lib/libdwarf/common/pro_frame.c @@ -1,76 +1,135 @@ /* Copyright (C) 2000,2004 Silicon Graphics, 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-2017 David Anderson. All Rights Reserved. + Portions Copyright 2012 SN Systems Ltd. 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 <limits.h> #include "pro_incl.h" +#include <stddef.h> +#include "dwarf.h" +#include "libdwarf.h" +#include "pro_opaque.h" +#include "pro_error.h" +#include "pro_alloc.h" +#include "pro_encode_nm.h" #include "pro_frame.h" +#define SIZEOFT16 2 +#define SIZEOFT32 4 +#define SIZEOFT64 8 + +#ifdef WORDS_BIGENDIAN +#define ASNOUT(t,s,l) \ + do { \ + unsigned sbyte = 0; \ + const char *p = 0; \ + if (l > sizeof(s)) { \ + _dwarf_p_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);\ + return DW_DLV_ERROR; \ + } \ + sbyte = sizeof(s) - l; \ + p = (const char *)(&s); \ + dbg->de_copy_word(t,(const void *)(p+sbyte),l);\ + } while (0) +#else /* LITTLEENDIAN */ +#define ASNOUT(t,s,l) \ + do { \ + const char *p = 0; \ + if (l > sizeof(s)) { \ + _dwarf_p_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);\ + return DW_DLV_ERROR; \ + } \ + p = (const char *)(&s); \ + dbg->de_copy_word(t,(const void *)p,l); \ + } while (0) +#endif /* ENDIANNESS */ + + static void _dwarf_pro_add_to_fde(Dwarf_P_Fde fde, - Dwarf_P_Frame_Pgm inst); - -/*------------------------------------------------------------------------- - This function adds a cie struct to the debug pointer. Its in the - form of a linked list. - augmenter: string reps augmentation (implementation defined) - code_align: alignment of code - data_align: alignment of data - init_bytes: byts having initial instructions - init_n_bytes: number of bytes of initial instructions ---------------------------------------------------------------------------*/ + Dwarf_P_Frame_Pgm inst); + +/* This function adds a cie struct to the debug pointer. Its in the + form of a linked list. + augmenter: string reps augmentation (implementation defined) + code_align: alignment of code + data_align: alignment of data + init_bytes: byts having initial instructions + init_n_bytes: number of bytes of initial instructions */ + + Dwarf_Unsigned dwarf_add_frame_cie(Dwarf_P_Debug dbg, - char *augmenter, - Dwarf_Small code_align, - Dwarf_Small data_align, - Dwarf_Small return_reg, - Dwarf_Ptr init_bytes, - Dwarf_Unsigned init_n_bytes, Dwarf_Error * error) + char *augmenter, + Dwarf_Small code_align, + Dwarf_Small data_align, + Dwarf_Small return_reg, + Dwarf_Ptr init_bytes, + Dwarf_Unsigned init_n_bytes, + Dwarf_Error * error) +{ + Dwarf_Unsigned index = 0; + int res = 0; + + res = dwarf_add_frame_cie_a(dbg,augmenter, code_align, + data_align,return_reg,init_bytes, + init_n_bytes, + &index,error); + if (res != DW_DLV_OK) { + return DW_DLV_NOCOUNT; + } + return index; +} + + +int +dwarf_add_frame_cie_a(Dwarf_P_Debug dbg, + char *augmenter, + Dwarf_Small code_align, + Dwarf_Small data_align, + Dwarf_Small return_reg, + Dwarf_Ptr init_bytes, + Dwarf_Unsigned init_n_bytes, + Dwarf_Unsigned * cie_index_out, + Dwarf_Error * error) { Dwarf_P_Cie curcie; + char *tmpaug = 0; if (dbg->de_frame_cies == NULL) { dbg->de_frame_cies = (Dwarf_P_Cie) _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Cie_s)); if (dbg->de_frame_cies == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_ALLOC, DW_DLV_NOCOUNT); + DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_ALLOC, DW_DLV_ERROR); } curcie = dbg->de_frame_cies; dbg->de_n_cie = 1; @@ -80,59 +139,104 @@ dwarf_add_frame_cie(Dwarf_P_Debug dbg, curcie->cie_next = (Dwarf_P_Cie) _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Cie_s)); if (curcie->cie_next == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_ALLOC, DW_DLV_NOCOUNT); + DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_ALLOC, DW_DLV_ERROR); } curcie = curcie->cie_next; dbg->de_n_cie++; dbg->de_last_cie = curcie; } - curcie->cie_version = DW_CIE_VERSION; - curcie->cie_aug = augmenter; + curcie->cie_version = 1; + if (dbg->de_output_version > 2) { + curcie->cie_version = dbg->de_output_version; + } else { + /* V2 dwarf has debug_frame as version 1, there + is no 2 used in this section. */ + curcie->cie_version = 1; + } + tmpaug = (char *)_dwarf_p_get_alloc(dbg,strlen(augmenter)+1); + if (!tmpaug) { + DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_ALLOC, DW_DLV_ERROR); + } + strcpy(tmpaug,augmenter); + curcie->cie_aug = tmpaug; curcie->cie_code_align = code_align; curcie->cie_data_align = data_align; curcie->cie_ret_reg = return_reg; curcie->cie_inst = (char *) init_bytes; curcie->cie_inst_bytes = (long) init_n_bytes; curcie->cie_next = NULL; - return dbg->de_n_cie; + *cie_index_out = dbg->de_n_cie; + return DW_DLV_OK; } -/*------------------------------------------------------------------------- - This functions adds a fde struct to the debug pointer. Its in the - form of a linked list. - die: subprogram/function die corresponding to this fde - cie: cie referred to by this fde, obtained from call to - add_frame_cie() routine. - virt_addr: beginning address - code_len: length of code reps by the fde ---------------------------------------------------------------------------*/ - /*ARGSUSED*/ /* pretend all args used */ - Dwarf_Unsigned +/* This functions adds a fde struct to the debug pointer. Its in the + form of a linked list. + die: subprogram/function die corresponding to this fde + cie: cie referred to by this fde, obtained from call to + add_frame_cie() routine. + virt_addr: beginning address + code_len: length of code reps by the fde */ +/*ARGSUSED*/ /* pretend all args used */ +Dwarf_Unsigned dwarf_add_frame_fde(Dwarf_P_Debug dbg, - Dwarf_P_Fde fde, - Dwarf_P_Die die, - Dwarf_Unsigned cie, - Dwarf_Unsigned virt_addr, - Dwarf_Unsigned code_len, - Dwarf_Unsigned symidx, Dwarf_Error * error) + Dwarf_P_Fde fde, + Dwarf_P_Die die, + Dwarf_Unsigned cie, + Dwarf_Unsigned virt_addr, + Dwarf_Unsigned code_len, + Dwarf_Unsigned symidx, Dwarf_Error * error) { - return dwarf_add_frame_fde_b(dbg, fde, die, cie, virt_addr, - code_len, symidx, 0, 0, error); + Dwarf_Unsigned index = 0; + int res = 0; + + res = dwarf_add_frame_fde_c(dbg, fde, die, cie, virt_addr, + code_len, symidx, 0, 0,&index, error); + if (res != DW_DLV_OK) { + return DW_DLV_NOCOUNT; + } + return index; } +/* There is no dwarf_add_frame_fde_a */ /*ARGSUSED10*/ Dwarf_Unsigned dwarf_add_frame_fde_b(Dwarf_P_Debug dbg, - Dwarf_P_Fde fde, - Dwarf_P_Die die, - Dwarf_Unsigned cie, - Dwarf_Unsigned virt_addr, - Dwarf_Unsigned code_len, - Dwarf_Unsigned symidx, - Dwarf_Unsigned symidx_of_end, - Dwarf_Addr offset_from_end_sym, - Dwarf_Error * error) + Dwarf_P_Fde fde, + Dwarf_P_Die die, + Dwarf_Unsigned cie, + Dwarf_Unsigned virt_addr, + Dwarf_Unsigned code_len, + Dwarf_Unsigned symidx, + Dwarf_Unsigned symidx_of_end, + Dwarf_Addr offset_from_end_sym, + Dwarf_Error * error) +{ + Dwarf_Unsigned index = 0; + int res = 0; + + res = dwarf_add_frame_fde_c(dbg,fde,die,cie, + virt_addr,code_len,symidx,symidx_of_end, + offset_from_end_sym,&index,error); + if (res != DW_DLV_OK) { + return DW_DLV_NOCOUNT; + } + return index; +} + +/* New December 2018 */ +int +dwarf_add_frame_fde_c(Dwarf_P_Debug dbg, + Dwarf_P_Fde fde, + Dwarf_P_Die die, + Dwarf_Unsigned cie, + Dwarf_Unsigned virt_addr, + Dwarf_Unsigned code_len, + Dwarf_Unsigned symidx, + Dwarf_Unsigned symidx_of_end, + Dwarf_Addr offset_from_end_sym, + Dwarf_Unsigned *index_to_fde, + UNUSEDARG Dwarf_Error * error) { Dwarf_P_Fde curfde; @@ -157,66 +261,101 @@ dwarf_add_frame_fde_b(Dwarf_P_Debug dbg, dbg->de_last_fde = fde; dbg->de_n_fde++; } - return dbg->de_n_fde; + *index_to_fde = dbg->de_n_fde; + return DW_DLV_OK; } -/*------------------------------------------------------------------------- - This functions adds information to an fde. The fde is - linked into the linked list of fde's maintained in the Dwarf_P_Debug - structure. - dbg: The debug descriptor. - fde: The fde to be added. - die: subprogram/function die corresponding to this fde - cie: cie referred to by this fde, obtained from call to - add_frame_cie() routine. - virt_addr: beginning address - code_len: length of code reps by the fde - symidx: The symbol id of the symbol wrt to which relocation needs - to be performed for 'virt_addr'. - offset_into_exception_tables: The start of exception tables for - this function (indicated as an offset into the exception - tables). A value of -1 indicates that there is no exception - table entries associated with this function. - exception_table_symbol: The symbol id of the section for exception - tables wrt to which the offset_into_exception_tables will - be relocated. ---------------------------------------------------------------------------*/ +/* This function adds information to an fde. The fde is + linked into the linked list of fde's maintained in the Dwarf_P_Debug + structure. + dbg: The debug descriptor. + fde: The fde to be added. + die: subprogram/function die corresponding to this fde + cie: cie referred to by this fde, obtained from call to + add_frame_cie() routine. + virt_addr: beginning address + code_len: length of code reps by the fde + symidx: The symbol id of the symbol wrt to which relocation needs + to be performed for 'virt_addr'. + offset_into_exception_tables: The start of exception tables for + this function (indicated as an offset into the exception + tables). A value of -1 indicates that there is no exception + table entries associated with this function. + exception_table_symbol: The symbol id of the section for exception + tables wrt to which the offset_into_exception_tables will + be relocated. */ Dwarf_Unsigned dwarf_add_frame_info(Dwarf_P_Debug dbg, - Dwarf_P_Fde fde, - Dwarf_P_Die die, - Dwarf_Unsigned cie, - Dwarf_Unsigned virt_addr, - Dwarf_Unsigned code_len, - Dwarf_Unsigned symidx, - Dwarf_Signed offset_into_exception_tables, - Dwarf_Unsigned exception_table_symbol, - Dwarf_Error * error) + Dwarf_P_Fde fde, + Dwarf_P_Die die, + Dwarf_Unsigned cie, + Dwarf_Unsigned virt_addr, + Dwarf_Unsigned code_len, + Dwarf_Unsigned symidx, + Dwarf_Signed offset_into_exception_tables, + Dwarf_Unsigned exception_table_symbol, + Dwarf_Error * error) { - - return dwarf_add_frame_info_b(dbg, fde, die, cie, virt_addr, - code_len, symidx, - /* end_symbol */ 0, - /* offset_from_end */ 0, - offset_into_exception_tables, - exception_table_symbol, error); - + Dwarf_Unsigned fde_index = 0; + int res = 0; + + res = dwarf_add_frame_info_c(dbg, fde, die, cie, virt_addr, + code_len, symidx, + /* end_symbol */ 0, + /* offset_from_end */ 0, + offset_into_exception_tables, + exception_table_symbol, + &fde_index, error); + if (res != DW_DLV_OK) { + return DW_DLV_NOCOUNT; + } + return fde_index; } - /*ARGSUSED*/ /* pretend all args used */ +/*ARGSUSED*/ /* pretend all args used */ Dwarf_Unsigned dwarf_add_frame_info_b(Dwarf_P_Debug dbg, - Dwarf_P_Fde fde, - Dwarf_P_Die die, - Dwarf_Unsigned cie, - Dwarf_Unsigned virt_addr, - Dwarf_Unsigned code_len, - Dwarf_Unsigned symidx, - Dwarf_Unsigned end_symidx, - Dwarf_Unsigned offset_from_end_symbol, - Dwarf_Signed offset_into_exception_tables, - Dwarf_Unsigned exception_table_symbol, - Dwarf_Error * error) + Dwarf_P_Fde fde, + Dwarf_P_Die die, + Dwarf_Unsigned cie, + Dwarf_Unsigned virt_addr, + Dwarf_Unsigned code_len, + Dwarf_Unsigned symidx, + Dwarf_Unsigned end_symidx, + Dwarf_Unsigned offset_from_end_symbol, + Dwarf_Signed offset_into_exception_tables, + Dwarf_Unsigned exception_table_symbol, + UNUSEDARG Dwarf_Error * error) +{ + Dwarf_Unsigned fde_index = 0; + int res = 0; + + res = dwarf_add_frame_info_c(dbg, fde, die, cie, virt_addr, + code_len, symidx, end_symidx, + offset_from_end_symbol, + offset_into_exception_tables, + exception_table_symbol, + &fde_index, error); + if (res != DW_DLV_OK) { + return DW_DLV_NOCOUNT; + } + return fde_index; +} + +int +dwarf_add_frame_info_c(Dwarf_P_Debug dbg, + Dwarf_P_Fde fde, + Dwarf_P_Die die, + Dwarf_Unsigned cie, + Dwarf_Unsigned virt_addr, + Dwarf_Unsigned code_len, + Dwarf_Unsigned symidx, + Dwarf_Unsigned end_symidx, + Dwarf_Unsigned offset_from_end_symbol, + Dwarf_Signed offset_into_exception_tables, + Dwarf_Unsigned exception_table_symbol, + Dwarf_Unsigned *fde_index_out, + UNUSEDARG Dwarf_Error * error) { Dwarf_P_Fde curfde; @@ -242,7 +381,8 @@ dwarf_add_frame_info_b(Dwarf_P_Debug dbg, dbg->de_last_fde = fde; dbg->de_n_fde++; } - return dbg->de_n_fde; + *fde_index_out = dbg->de_n_fde; + return DW_DLV_OK; } /* This is an alternate to inserting frame instructions @@ -253,12 +393,12 @@ dwarf_insert_fde_inst_bytes(Dwarf_P_Debug dbg, Dwarf_P_Fde fde,Dwarf_Unsigned len, Dwarf_Ptr ibytes, Dwarf_Error *error) { - if( len == 0) { + if (len == 0) { return DW_DLV_OK; } - if(fde->fde_block || fde->fde_inst) { + if (fde->fde_block || fde->fde_inst) { DWARF_P_DBG_ERROR(dbg, DW_DLE_DUPLICATE_INST_BLOCK, - (int)DW_DLV_BADADDR); + DW_DLV_ERROR); } fde->fde_block = (Dwarf_Ptr)_dwarf_p_get_alloc(dbg, len); memcpy(fde->fde_block,ibytes,len); @@ -266,70 +406,94 @@ dwarf_insert_fde_inst_bytes(Dwarf_P_Debug dbg, fde->fde_n_bytes += len; return DW_DLV_OK; } - -/*------------------------------------------------------------------- - Create a new fde. ----------------------------------------------------------------------*/ + +/* Create a new fde. */ Dwarf_P_Fde dwarf_new_fde(Dwarf_P_Debug dbg, Dwarf_Error * error) { + Dwarf_P_Fde fde = 0; + int res = 0; + + res = dwarf_new_fde_a(dbg,&fde,error); + if (res != DW_DLV_OK) { + return (Dwarf_P_Fde) DW_DLV_BADADDR; + } + return fde; +} +int +dwarf_new_fde_a(Dwarf_P_Debug dbg, + Dwarf_P_Fde *fde_out, + Dwarf_Error * error) +{ Dwarf_P_Fde fde; fde = (Dwarf_P_Fde) _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Fde_s)); if (fde == NULL) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_FDE_ALLOC, - (Dwarf_P_Fde) DW_DLV_BADADDR); + DWARF_P_DBG_ERROR(dbg, DW_DLE_FDE_ALLOC, DW_DLV_ERROR); } - - fde->fde_uwordb_size = dbg->de_offset_size; - - return fde; + fde->fde_dbg = dbg; + fde->fde_uwordb_size = dbg->de_dwarf_offset_size; + *fde_out = fde; + return DW_DLV_OK; } -/*------------------------------------------------------------------------ - Add a cfe_offset instruction to the fde passed in. --------------------------------------------------------------------------*/ +/* 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_Unsigned reg, + Dwarf_Signed offset, + Dwarf_Error * error) +{ + int res = 0; + + res = dwarf_fde_cfa_offset_a(fde,reg,offset,error); + if (res != DW_DLV_OK) { + return (Dwarf_P_Fde) DW_DLV_BADADDR; + } + return fde; +} + + +int +dwarf_fde_cfa_offset_a(Dwarf_P_Fde fde, + Dwarf_Unsigned reg, + Dwarf_Signed offset, + Dwarf_Error * error) { Dwarf_Ubyte opc, regno; - char *ptr; + char *ptr = 0; Dwarf_P_Frame_Pgm curinst; - int nbytes; - int res; + 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); + DWARF_P_DBG_ERROR(dbg, DW_DLE_FPGM_ALLOC, DW_DLV_ERROR); } opc = DW_CFA_offset; regno = reg; if (regno & 0xc0) { - DWARF_P_DBG_ERROR(dbg, DW_DLE_REGNO_OVFL, - (Dwarf_P_Fde) DW_DLV_BADADDR); + DWARF_P_DBG_ERROR(dbg, DW_DLE_REGNO_OVFL,DW_DLV_ERROR); } opc = opc | regno; /* lower 6 bits are register number */ curinst->dfp_opcode = opc; res = _dwarf_pro_encode_leb128_nm(offset, &nbytes, - buff1, sizeof(buff1)); + buff1, sizeof(buff1)); if (res != DW_DLV_OK) { _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); - return ((Dwarf_P_Fde) DW_DLV_BADADDR); + return DW_DLV_ERROR; } 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); + return DW_DLV_ERROR; } memcpy(ptr, buff1, nbytes); @@ -338,16 +502,15 @@ dwarf_fde_cfa_offset(Dwarf_P_Fde fde, curinst->dfp_next = NULL; _dwarf_pro_add_to_fde(fde, curinst); - return fde; + return DW_DLV_OK; } -/* - Generic routine to add opcode to fde instructions. val1 and +/* 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) + 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. @@ -357,115 +520,142 @@ dwarf_fde_cfa_offset(Dwarf_P_Fde fde, 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) + Does not check that the frame + version is 3(for dwarf3) or 4 (for dwarf4) or 5 when applying operations that are only valid for - dwarf3 or dwarf4. - -*/ + particular versions. */ Dwarf_P_Fde dwarf_add_fde_inst(Dwarf_P_Fde fde, - Dwarf_Small op, - Dwarf_Unsigned val1, - Dwarf_Unsigned val2, Dwarf_Error * error) + Dwarf_Small op, + Dwarf_Unsigned val1, + Dwarf_Unsigned val2, Dwarf_Error * error) +{ + int res = 0; + + res = dwarf_add_fde_inst_a(fde,op,val1,val2,error); + if (res != DW_DLV_OK) { + return ((Dwarf_P_Fde) DW_DLV_BADADDR); + } + return fde; +} + +/* December 2018. A more sensible return value. */ +int +dwarf_add_fde_inst_a(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; + int nbytes = 0; + int nbytes1 = 0; + int nbytes2 = 0; + Dwarf_Ubyte db = 0; + Dwarf_Half dh = 0; + Dwarf_Unsigned du = 0; + char *ptr = 0; + int res = 0; 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. */ + /* 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; + buff1[0] = 0; + buff2[0] = 0; 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); + return DW_DLV_ERROR; } - switch (op) { - case DW_CFA_advance_loc: + case DW_CFA_advance_loc: { if (val1 <= 0x3f) { db = val1; op |= db; - } - /* test not portable FIX */ - else if (val1 <= UCHAR_MAX) { + } else if (!(val1& ~0xff)) { 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); + return DW_DLV_ERROR; } memcpy((void *) ptr, (const void *) &db, 1); nbytes = 1; - } - /* test not portable FIX */ - else if (val1 <= USHRT_MAX) { + } else if (!(val1& (~(Dwarf_Unsigned)0xffff))) { + if (sizeof(dh) < SIZEOFT16) { + _dwarf_p_error(dbg, error, + DW_DLE_DEBUG_FRAME_LENGTH_BAD); + return DW_DLV_ERROR; + } op = DW_CFA_advance_loc2; dh = val1; - ptr = (char *) _dwarf_p_get_alloc(dbg, 2); + ptr = (char *) _dwarf_p_get_alloc(dbg, SIZEOFT16); if (ptr == NULL) { _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); - return ((Dwarf_P_Fde) DW_DLV_BADADDR); + return DW_DLV_ERROR; + } + /* No byte swapping, assuming running at + target endianness. */ + ASNOUT((void *) ptr, dh, SIZEOFT16); + nbytes = SIZEOFT16; + } else if (!(val1& ~(Dwarf_Unsigned)0xffffffff)) { + if (sizeof(du) < SIZEOFT32) { + _dwarf_p_error(dbg, error, + DW_DLE_DEBUG_FRAME_LENGTH_BAD); + return DW_DLV_ERROR; } - 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); + du = val1; + ptr = (char *) _dwarf_p_get_alloc(dbg, SIZEOFT32); if (ptr == NULL) { _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); - return ((Dwarf_P_Fde) DW_DLV_BADADDR); + return DW_DLV_ERROR; } - memcpy((void *) ptr, (const void *) &dw, 4); - nbytes = 4; + ASNOUT((void *) ptr, du, SIZEOFT32); + nbytes = SIZEOFT32; } else { + if (sizeof(du) < SIZEOFT64) { + _dwarf_p_error(dbg, error, + DW_DLE_DEBUG_FRAME_LENGTH_BAD); + return DW_DLV_ERROR; + } op = DW_CFA_MIPS_advance_loc8; du = val1; - ptr = - (char *) _dwarf_p_get_alloc(dbg, - sizeof(Dwarf_Unsigned)); + ptr = (char *) _dwarf_p_get_alloc(dbg, + SIZEOFT64); if (ptr == NULL) { _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); - return ((Dwarf_P_Fde) DW_DLV_BADADDR); + return DW_DLV_ERROR; } - memcpy((void *) ptr, (const void *) &du, 8); - nbytes = 8; + /* No byte swapping, assuming running at + target endianness. */ + ASNOUT((void *) ptr, du, SIZEOFT64); + nbytes = SIZEOFT64; } 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)); + buff1, sizeof(buff1)); if (res != DW_DLV_OK) { _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); - return ((Dwarf_P_Fde) DW_DLV_BADADDR); + return DW_DLV_ERROR; } 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); + return DW_DLV_ERROR; } memcpy(ptr, buff1, nbytes); @@ -475,52 +665,56 @@ dwarf_add_fde_inst(Dwarf_P_Fde fde, } break; case DW_CFA_offset_extended_sf: /* DWARF3 */ - signed_second = 1; - goto two_leb; + signed_second = 1; + goto two_leb; case DW_CFA_offset_extended: - goto two_leb; + goto two_leb; case DW_CFA_undefined: case DW_CFA_same_value: goto one_leb; case DW_CFA_val_offset: - goto two_leb; + goto two_leb; case DW_CFA_val_offset_sf: - signed_second = 1; - goto two_leb; + signed_second = 1; + goto two_leb; case DW_CFA_def_cfa_sf: - signed_second = 1; - goto two_leb; + 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)); + buff1, sizeof(buff1)); if (res != DW_DLV_OK) { _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); - return ((Dwarf_P_Fde) DW_DLV_BADADDR); + return DW_DLV_ERROR; } if (!signed_second) { - res = _dwarf_pro_encode_leb128_nm(val2, &nbytes2, - buff2, sizeof(buff2)); + 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)); + buff2, sizeof(buff2)); + } + if (res != DW_DLV_OK) { + _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); + return DW_DLV_ERROR; } res = _dwarf_pro_encode_leb128_nm(val2, &nbytes2, - buff2, sizeof(buff2)); + buff2, sizeof(buff2)); if (res != DW_DLV_OK) { _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); - return ((Dwarf_P_Fde) DW_DLV_BADADDR); + return DW_DLV_ERROR; } 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); + return DW_DLV_ERROR; } memcpy(ptr, buff1, nbytes1); memcpy(ptr + nbytes1, buff2, nbytes2); @@ -533,52 +727,49 @@ dwarf_add_fde_inst(Dwarf_P_Fde fde, case DW_CFA_def_cfa_register: case DW_CFA_def_cfa_offset: one_leb: - if(!signed_first) { + if (!signed_first) { res = _dwarf_pro_encode_leb128_nm(val1, &nbytes, - buff1, sizeof(buff1)); + buff1, sizeof(buff1)); } else { Dwarf_Signed val1s = val1; res = _dwarf_pro_encode_signed_leb128_nm(val1s, &nbytes, - buff1, sizeof(buff1)); + buff1, sizeof(buff1)); } if (res != DW_DLV_OK) { _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC); - return ((Dwarf_P_Fde) DW_DLV_BADADDR); + return DW_DLV_ERROR; } 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); + return DW_DLV_ERROR; } memcpy(ptr, buff1, nbytes); break; case DW_CFA_def_cfa_expression: /* DWARF3 */ - /* FIXME: argument is dwarf expr, not handled yet. */ + /* 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. */ + /* 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. */ + /* 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); + return DW_DLV_ERROR; } 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; + return DW_DLV_OK; } -/*------------------------------------------------------------------------ - Instructions are added to an fde in the form of a linked - list. This function manages the linked list. --------------------------------------------------------------------------*/ +/* Instructions are added to an fde in the form of a linked + list. This function manages the linked list. */ void _dwarf_pro_add_to_fde(Dwarf_P_Fde fde, Dwarf_P_Frame_Pgm curinst) { |