diff options
Diffstat (limited to 'usr/src/tools/ctf/dwarf/common/dwarf_line.c')
-rw-r--r-- | usr/src/tools/ctf/dwarf/common/dwarf_line.c | 1951 |
1 files changed, 0 insertions, 1951 deletions
diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_line.c b/usr/src/tools/ctf/dwarf/common/dwarf_line.c deleted file mode 100644 index e7e15e7c1a..0000000000 --- a/usr/src/tools/ctf/dwarf/common/dwarf_line.c +++ /dev/null @@ -1,1951 +0,0 @@ -/* - Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2007-2010 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. - - 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 - -*/ -/* The address of the Free Software Foundation is - Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - Boston, MA 02110-1301, USA. - SGI has moved from the Crittenden Lane address. -*/ - - - - -#include "config.h" -#include "dwarf_incl.h" -#include <stdio.h> -#include <stdlib.h> -#include "dwarf_line.h" - -static int -is_path_separator(Dwarf_Small s) -{ - if(s == '/') { - return 1; - } -#ifdef HAVE_WINDOWS_PATH - if(s == '\\') { - return 1; - } -#endif - return 0; -} - -/* Return 0 if false, 1 if true. - If HAVE_WINDOWS_PATH is defined we - attempt to handle windows full paths: - \\something or C:cwdpath.c -*/ -static int -file_name_is_full_path(Dwarf_Small *fname) -{ - Dwarf_Small firstc = *fname; - if(is_path_separator(firstc)) { - /* Full path. */ - return 1; - } - if(!firstc) { - return 0; - } -#ifdef HAVE_WINDOWS_PATH - if((firstc >= 'A' && firstc <= 'Z') || - (firstc >= 'a' && firstc <= 'z')) { - Dwarf_Small secondc = fname[1]; - if (secondc == ':') { - return 1; - } - } -#endif - return 0; -} - -/* - Although source files is supposed to return the - source files in the compilation-unit, it does - not look for any in the statement program. In - other words, it ignores those defined using the - extended opcode DW_LNE_define_file. -*/ -int -dwarf_srcfiles(Dwarf_Die die, - char ***srcfiles, - Dwarf_Signed * srcfilecount, Dwarf_Error * error) -{ - /* This pointer is used to scan the portion of the .debug_line - section for the current cu. */ - Dwarf_Small *line_ptr; - - /* Pointer to a DW_AT_stmt_list attribute in case it exists in the - die. */ - Dwarf_Attribute stmt_list_attr; - - /* Pointer to DW_AT_comp_dir attribute in die. */ - Dwarf_Attribute comp_dir_attr; - - /* Pointer to name of compilation directory. */ - Dwarf_Small *comp_dir = 0; - - /* Offset into .debug_line specified by a DW_AT_stmt_list - attribute. */ - Dwarf_Unsigned line_offset = 0; - - /* This points to a block of char *'s, each of which points to a - file name. */ - char **ret_files = 0; - - /* The Dwarf_Debug this die belongs to. */ - Dwarf_Debug dbg = 0; - - /* Used to chain the file names. */ - Dwarf_Chain curr_chain = NULL; - Dwarf_Chain prev_chain = NULL; - Dwarf_Chain head_chain = NULL; - Dwarf_Half attrform = 0; - int resattr = DW_DLV_ERROR; - int lres = DW_DLV_ERROR; - struct Line_Table_Prefix_s line_prefix; - int i = 0; - int res = DW_DLV_ERROR; - - /* ***** BEGIN CODE ***** */ - /* Reset error. */ - if (error != NULL) - *error = NULL; - - CHECK_DIE(die, DW_DLV_ERROR); - dbg = die->di_cu_context->cc_dbg; - - resattr = dwarf_attr(die, DW_AT_stmt_list, &stmt_list_attr, error); - if (resattr != DW_DLV_OK) { - return resattr; - } - - if (dbg->de_debug_line.dss_index == 0) { - _dwarf_error(dbg, error, DW_DLE_DEBUG_LINE_NULL); - return (DW_DLV_ERROR); - } - - res = _dwarf_load_section(dbg, &dbg->de_debug_line,error); - if (res != DW_DLV_OK) { - return res; - } - - lres = dwarf_whatform(stmt_list_attr,&attrform,error); - if (lres != DW_DLV_OK) { - return lres; - } - if (attrform != DW_FORM_data4 && attrform != DW_FORM_data8 && - attrform != DW_FORM_sec_offset ) { - _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD); - return (DW_DLV_ERROR); - } - lres = dwarf_global_formref(stmt_list_attr, &line_offset, error); - if (lres != DW_DLV_OK) { - return lres; - } - if (line_offset >= dbg->de_debug_line.dss_size) { - _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD); - return (DW_DLV_ERROR); - } - line_ptr = dbg->de_debug_line.dss_data + line_offset; - dwarf_dealloc(dbg, stmt_list_attr, DW_DLA_ATTR); - - /* - If die has DW_AT_comp_dir attribute, get the string that names - the compilation directory. */ - resattr = dwarf_attr(die, DW_AT_comp_dir, &comp_dir_attr, error); - if (resattr == DW_DLV_ERROR) { - return resattr; - } - if (resattr == DW_DLV_OK) { - int cres = DW_DLV_ERROR; - char *cdir = 0; - - cres = dwarf_formstring(comp_dir_attr, &cdir, error); - if (cres == DW_DLV_ERROR) { - return cres; - } else if (cres == DW_DLV_OK) { - comp_dir = (Dwarf_Small *) cdir; - } - } - if (resattr == DW_DLV_OK) { - dwarf_dealloc(dbg, comp_dir_attr, DW_DLA_ATTR); - } - dwarf_init_line_table_prefix(&line_prefix); - { - Dwarf_Small *line_ptr_out = 0; - int dres = dwarf_read_line_table_prefix(dbg, - line_ptr, - dbg->de_debug_line.dss_size, - &line_ptr_out, - &line_prefix, - NULL, NULL,error, - 0); - - if (dres == DW_DLV_ERROR) { - dwarf_free_line_table_prefix(&line_prefix); - return dres; - } - if (dres == DW_DLV_NO_ENTRY) { - dwarf_free_line_table_prefix(&line_prefix); - return dres; - } - - line_ptr = line_ptr_out; - } - - for (i = 0; i < line_prefix.pf_files_count; ++i) { - struct Line_Table_File_Entry_s *fe = - line_prefix.pf_line_table_file_entries + i; - char *file_name = (char *) fe->lte_filename; - char *dir_name = 0; - char *full_name = 0; - Dwarf_Unsigned dir_index = fe->lte_directory_index; - - if (dir_index == 0) { - dir_name = (char *) comp_dir; - } else { - dir_name = - (char *) line_prefix.pf_include_directories[ - fe->lte_directory_index - 1]; - } - - /* dir_name can be NULL if there is no DW_AT_comp_dir */ - if(dir_name == 0 || file_name_is_full_path((unsigned char *)file_name)) { - /* This is safe because dwarf_dealloc is careful to not - dealloc strings which are part of the raw .debug_* data. - */ - full_name = file_name; - } else { - full_name = (char *) _dwarf_get_alloc(dbg, DW_DLA_STRING, - strlen(dir_name) + 1 + - strlen(file_name) + - 1); - if (full_name == NULL) { - dwarf_free_line_table_prefix(&line_prefix); - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - /* This is not careful to avoid // in the output, Nothing - forces a 'canonical' name format here. Unclear if this - needs to be fixed. */ - strcpy(full_name, dir_name); - strcat(full_name, "/"); - strcat(full_name, file_name); - } - curr_chain = - (Dwarf_Chain) _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); - if (curr_chain == NULL) { - dwarf_free_line_table_prefix(&line_prefix); - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - curr_chain->ch_item = full_name; - if (head_chain == NULL) - head_chain = prev_chain = curr_chain; - else { - prev_chain->ch_next = curr_chain; - prev_chain = curr_chain; - } - } - - curr_chain = (Dwarf_Chain) _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); - if (curr_chain == NULL) { - dwarf_free_line_table_prefix(&line_prefix); - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - - - - if (line_prefix.pf_files_count == 0) { - *srcfiles = NULL; - *srcfilecount = 0; - dwarf_free_line_table_prefix(&line_prefix); - return (DW_DLV_NO_ENTRY); - } - - ret_files = (char **) - _dwarf_get_alloc(dbg, DW_DLA_LIST, line_prefix.pf_files_count); - if (ret_files == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - dwarf_free_line_table_prefix(&line_prefix); - return (DW_DLV_ERROR); - } - - curr_chain = head_chain; - for (i = 0; i < line_prefix.pf_files_count; i++) { - *(ret_files + i) = curr_chain->ch_item; - prev_chain = curr_chain; - curr_chain = curr_chain->ch_next; - dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN); - } - - *srcfiles = ret_files; - *srcfilecount = line_prefix.pf_files_count; - dwarf_free_line_table_prefix(&line_prefix); - return (DW_DLV_OK); -} - - -/* - return DW_DLV_OK if ok. else DW_DLV_NO_ENTRY or DW_DLV_ERROR -*/ -int -_dwarf_internal_srclines(Dwarf_Die die, - Dwarf_Line ** linebuf, - Dwarf_Signed * count, - Dwarf_Bool doaddrs, - Dwarf_Bool dolines, Dwarf_Error * error) -{ - /* This pointer is used to scan the portion of the .debug_line - section for the current cu. */ - Dwarf_Small *line_ptr = 0; - - /* This points to the last byte of the .debug_line portion for the - current cu. */ - Dwarf_Small *line_ptr_end = 0; - - /* Pointer to a DW_AT_stmt_list attribute in case it exists in the - die. */ - Dwarf_Attribute stmt_list_attr = 0; - - /* Pointer to DW_AT_comp_dir attribute in die. */ - Dwarf_Attribute comp_dir_attr = 0; - - /* Pointer to name of compilation directory. */ - Dwarf_Small *comp_dir = NULL; - - /* Offset into .debug_line specified by a DW_AT_stmt_list - attribute. */ - Dwarf_Unsigned line_offset = 0; - - Dwarf_File_Entry file_entries = 0; - - /* These are the state machine state variables. */ - Dwarf_Addr address = 0; - Dwarf_Word file = 1; - Dwarf_Word line = 1; - Dwarf_Word column = 0; - - /* Phony init. See below for true initialization. */ - Dwarf_Bool is_stmt = false; - - Dwarf_Bool basic_block = false; - Dwarf_Bool prologue_end = false; - Dwarf_Bool epilogue_begin = false; - Dwarf_Small isa = 0; - Dwarf_Bool end_sequence = false; - - /* These pointers are used to build the list of files names by this - cu. cur_file_entry points to the file name being added, and - prev_file_entry to the previous one. */ - Dwarf_File_Entry cur_file_entry, prev_file_entry; - - Dwarf_Sword i = 0; - Dwarf_Sword file_entry_count = 0; - - /* This is the current opcode read from the statement program. */ - Dwarf_Small opcode = 0; - - /* Pointer to a Dwarf_Line_Context_s structure that contains the - context such as file names and include directories for the set - of lines being generated. */ - Dwarf_Line_Context line_context = 0; - - /* This is a pointer to the current line being added to the line - matrix. */ - Dwarf_Line curr_line = 0; - - /* These variables are used to decode leb128 numbers. Leb128_num - holds the decoded number, and leb128_length is its length in - bytes. */ - Dwarf_Word leb128_num = 0; - Dwarf_Word leb128_length = 0; - Dwarf_Sword advance_line = 0; - - /* This is the operand of the latest fixed_advance_pc extended - opcode. */ - Dwarf_Half fixed_advance_pc = 0; - - /* Counts the number of lines in the line matrix. */ - Dwarf_Sword line_count = 0; - - /* This is the length of an extended opcode instr. */ - Dwarf_Word instr_length = 0; - Dwarf_Small ext_opcode = 0; - struct Line_Table_Prefix_s prefix; - - /* Used to chain together pointers to line table entries that are - later used to create a block of Dwarf_Line entries. */ - Dwarf_Chain chain_line = NULL; - Dwarf_Chain head_chain = NULL; - Dwarf_Chain curr_chain = NULL; - - /* This points to a block of Dwarf_Lines, a pointer to which is - returned in linebuf. */ - Dwarf_Line *block_line = 0; - - /* The Dwarf_Debug this die belongs to. */ - Dwarf_Debug dbg = 0; - int resattr = DW_DLV_ERROR; - int lres = DW_DLV_ERROR; - Dwarf_Half address_size = 0; - - int res = DW_DLV_ERROR; - - /* ***** BEGIN CODE ***** */ - if (error != NULL) - *error = NULL; - - CHECK_DIE(die, DW_DLV_ERROR); - dbg = die->di_cu_context->cc_dbg; - - res = _dwarf_load_section(dbg, &dbg->de_debug_line,error); - if (res != DW_DLV_OK) { - return res; - } - address_size = _dwarf_get_address_size(dbg, die); - resattr = dwarf_attr(die, DW_AT_stmt_list, &stmt_list_attr, error); - if (resattr != DW_DLV_OK) { - return resattr; - } - - lres = dwarf_formudata(stmt_list_attr, &line_offset, error); - if (lres != DW_DLV_OK) { - return lres; - } - - if (line_offset >= dbg->de_debug_line.dss_size) { - _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD); - return (DW_DLV_ERROR); - } - line_ptr = dbg->de_debug_line.dss_data + line_offset; - dwarf_dealloc(dbg, stmt_list_attr, DW_DLA_ATTR); - - /* If die has DW_AT_comp_dir attribute, get the string that names - the compilation directory. */ - resattr = dwarf_attr(die, DW_AT_comp_dir, &comp_dir_attr, error); - if (resattr == DW_DLV_ERROR) { - return resattr; - } - if (resattr == DW_DLV_OK) { - int cres = DW_DLV_ERROR; - char *cdir = 0; - - cres = dwarf_formstring(comp_dir_attr, &cdir, error); - if (cres == DW_DLV_ERROR) { - return cres; - } else if (cres == DW_DLV_OK) { - comp_dir = (Dwarf_Small *) cdir; - } - } - if (resattr == DW_DLV_OK) { - dwarf_dealloc(dbg, comp_dir_attr, DW_DLA_ATTR); - } - dwarf_init_line_table_prefix(&prefix); - - { - Dwarf_Small *newlinep = 0; - int res = dwarf_read_line_table_prefix(dbg, - line_ptr, - dbg->de_debug_line.dss_size, - &newlinep, - &prefix, - NULL,NULL, - error, - 0); - - if (res == DW_DLV_ERROR) { - dwarf_free_line_table_prefix(&prefix); - return res; - } - if (res == DW_DLV_NO_ENTRY) { - dwarf_free_line_table_prefix(&prefix); - return res; - } - line_ptr_end = prefix.pf_line_ptr_end; - line_ptr = newlinep; - } - - - /* Set up context structure for this set of lines. */ - line_context = (Dwarf_Line_Context) - _dwarf_get_alloc(dbg, DW_DLA_LINE_CONTEXT, 1); - if (line_context == NULL) { - dwarf_free_line_table_prefix(&prefix); - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - /* Fill out a Dwarf_File_Entry list as we use that to implement the - define_file operation. */ - file_entries = prev_file_entry = NULL; - for (i = 0; i < prefix.pf_files_count; ++i) { - struct Line_Table_File_Entry_s *pfxfile = - prefix.pf_line_table_file_entries + i; - - cur_file_entry = (Dwarf_File_Entry) - _dwarf_get_alloc(dbg, DW_DLA_FILE_ENTRY, 1); - if (cur_file_entry == NULL) { - dwarf_free_line_table_prefix(&prefix); - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - cur_file_entry->fi_file_name = pfxfile->lte_filename; - cur_file_entry->fi_dir_index = pfxfile->lte_directory_index; - cur_file_entry->fi_time_last_mod = - pfxfile->lte_last_modification_time; - - cur_file_entry->fi_file_length = pfxfile->lte_length_of_file; - - if (file_entries == NULL) - file_entries = cur_file_entry; - else - prev_file_entry->fi_next = cur_file_entry; - prev_file_entry = cur_file_entry; - - file_entry_count++; - } - - - /* Initialize the one state machine variable that depends on the - prefix. */ - is_stmt = prefix.pf_default_is_stmt; - - - /* Start of statement program. */ - while (line_ptr < line_ptr_end) { - int type; - - opcode = *(Dwarf_Small *) line_ptr; - line_ptr++; - - - /* 'type' is the output */ - WHAT_IS_OPCODE(type, opcode, prefix.pf_opcode_base, - prefix.pf_opcode_length_table, line_ptr, - prefix.pf_std_op_count); - - if (type == LOP_DISCARD) { - int oc; - int opcnt = prefix.pf_opcode_length_table[opcode]; - - for (oc = 0; oc < opcnt; oc++) { - /* - ** Read and discard operands we don't - ** understand. - ** arbitrary choice of unsigned read. - ** signed read would work as well. - */ - Dwarf_Unsigned utmp2; - - DECODE_LEB128_UWORD(line_ptr, utmp2); - } - } else if (type == LOP_SPECIAL) { - /* This op code is a special op in the object, no matter - that it might fall into the standard op range in this - compile. That is, these are special opcodes between - opcode_base and MAX_LINE_OP_CODE. (including - opcode_base and MAX_LINE_OP_CODE) */ - - opcode = opcode - prefix.pf_opcode_base; - address = address + prefix.pf_minimum_instruction_length * - (opcode / prefix.pf_line_range); - line = - line + prefix.pf_line_base + - opcode % prefix.pf_line_range; - - if (dolines) { - curr_line = - (Dwarf_Line) _dwarf_get_alloc(dbg, DW_DLA_LINE, 1); - if (curr_line == NULL) { - dwarf_free_line_table_prefix(&prefix); - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - curr_line->li_address = address; - curr_line->li_addr_line.li_l_data.li_file = - (Dwarf_Sword) file; - curr_line->li_addr_line.li_l_data.li_line = - (Dwarf_Sword) line; - curr_line->li_addr_line.li_l_data.li_column = - (Dwarf_Half) column; - curr_line->li_addr_line.li_l_data.li_is_stmt = is_stmt; - curr_line->li_addr_line.li_l_data.li_basic_block = - basic_block; - curr_line->li_addr_line.li_l_data.li_end_sequence = - curr_line->li_addr_line.li_l_data. - li_epilogue_begin = epilogue_begin; - curr_line->li_addr_line.li_l_data.li_prologue_end = - prologue_end; - curr_line->li_addr_line.li_l_data.li_isa = isa; - curr_line->li_context = line_context; - line_count++; - - chain_line = (Dwarf_Chain) - _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); - if (chain_line == NULL) { - dwarf_free_line_table_prefix(&prefix); - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - chain_line->ch_item = curr_line; - - if (head_chain == NULL) - head_chain = curr_chain = chain_line; - else { - curr_chain->ch_next = chain_line; - curr_chain = chain_line; - } - } - - basic_block = false; - } else if (type == LOP_STANDARD) { - switch (opcode) { - - case DW_LNS_copy:{ - if (dolines) { - - curr_line = - (Dwarf_Line) _dwarf_get_alloc(dbg, - DW_DLA_LINE, - 1); - if (curr_line == NULL) { - dwarf_free_line_table_prefix(&prefix); - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - curr_line->li_address = address; - curr_line->li_addr_line.li_l_data.li_file = - (Dwarf_Sword) file; - curr_line->li_addr_line.li_l_data.li_line = - (Dwarf_Sword) line; - curr_line->li_addr_line.li_l_data.li_column = - (Dwarf_Half) column; - curr_line->li_addr_line.li_l_data.li_is_stmt = - is_stmt; - curr_line->li_addr_line.li_l_data. - li_basic_block = basic_block; - curr_line->li_addr_line.li_l_data. - li_end_sequence = end_sequence; - curr_line->li_context = line_context; - curr_line->li_addr_line.li_l_data. - li_epilogue_begin = epilogue_begin; - curr_line->li_addr_line.li_l_data. - li_prologue_end = prologue_end; - curr_line->li_addr_line.li_l_data.li_isa = isa; - line_count++; - - chain_line = (Dwarf_Chain) - _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); - if (chain_line == NULL) { - dwarf_free_line_table_prefix(&prefix); - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - chain_line->ch_item = curr_line; - if (head_chain == NULL) - head_chain = curr_chain = chain_line; - else { - curr_chain->ch_next = chain_line; - curr_chain = chain_line; - } - } - - basic_block = false; - prologue_end = false; - epilogue_begin = false; - break; - } - - case DW_LNS_advance_pc:{ - Dwarf_Unsigned utmp2; - - DECODE_LEB128_UWORD(line_ptr, utmp2); - leb128_num = (Dwarf_Word) utmp2; - address = - address + - prefix.pf_minimum_instruction_length * - leb128_num; - break; - } - - case DW_LNS_advance_line:{ - Dwarf_Signed stmp; - - DECODE_LEB128_SWORD(line_ptr, stmp); - advance_line = (Dwarf_Sword) stmp; - line = line + advance_line; - break; - } - - case DW_LNS_set_file:{ - Dwarf_Unsigned utmp2; - - DECODE_LEB128_UWORD(line_ptr, utmp2); - file = (Dwarf_Word) utmp2; - break; - } - - case DW_LNS_set_column:{ - Dwarf_Unsigned utmp2; - - DECODE_LEB128_UWORD(line_ptr, utmp2); - column = (Dwarf_Word) utmp2; - break; - } - - case DW_LNS_negate_stmt:{ - - is_stmt = !is_stmt; - break; - } - - case DW_LNS_set_basic_block:{ - - basic_block = true; - break; - } - - case DW_LNS_const_add_pc:{ - opcode = MAX_LINE_OP_CODE - prefix.pf_opcode_base; - address = address + - prefix.pf_minimum_instruction_length * (opcode / - prefix. - pf_line_range); - break; - } - - case DW_LNS_fixed_advance_pc:{ - - READ_UNALIGNED(dbg, fixed_advance_pc, Dwarf_Half, - line_ptr, sizeof(Dwarf_Half)); - line_ptr += sizeof(Dwarf_Half); - address = address + fixed_advance_pc; - break; - } - - /* New in DWARF3 */ - case DW_LNS_set_prologue_end:{ - - prologue_end = true; - break; - - - } - /* New in DWARF3 */ - case DW_LNS_set_epilogue_begin:{ - epilogue_begin = true; - break; - } - - /* New in DWARF3 */ - case DW_LNS_set_isa:{ - Dwarf_Unsigned utmp2; - - DECODE_LEB128_UWORD(line_ptr, utmp2); - isa = utmp2; - if (isa != utmp2) { - /* The value of the isa did not fit in our - local so we record it wrong. declare an - error. */ - dwarf_free_line_table_prefix(&prefix); - - _dwarf_error(dbg, error, - DW_DLE_LINE_NUM_OPERANDS_BAD); - return (DW_DLV_ERROR); - } - break; - } - } - - } else if (type == LOP_EXTENDED) { - Dwarf_Unsigned utmp3; - - DECODE_LEB128_UWORD(line_ptr, utmp3); - instr_length = (Dwarf_Word) utmp3; - /* Dwarf_Small is a ubyte and the extended opcode is a - ubyte, though not stated as clearly in the 2.0.0 spec as - one might hope. */ - ext_opcode = *(Dwarf_Small *) line_ptr; - line_ptr++; - switch (ext_opcode) { - - case DW_LNE_end_sequence:{ - end_sequence = true; - - if (dolines) { - curr_line = (Dwarf_Line) - _dwarf_get_alloc(dbg, DW_DLA_LINE, 1); - if (curr_line == NULL) { - dwarf_free_line_table_prefix(&prefix); - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - curr_line->li_address = address; - curr_line->li_addr_line.li_l_data.li_file = - (Dwarf_Sword) file; - curr_line->li_addr_line.li_l_data.li_line = - (Dwarf_Sword) line; - curr_line->li_addr_line.li_l_data.li_column = - (Dwarf_Half) column; - curr_line->li_addr_line.li_l_data.li_is_stmt = - prefix.pf_default_is_stmt; - curr_line->li_addr_line.li_l_data. - li_basic_block = basic_block; - curr_line->li_addr_line.li_l_data. - li_end_sequence = end_sequence; - curr_line->li_context = line_context; - curr_line->li_addr_line.li_l_data. - li_epilogue_begin = epilogue_begin; - curr_line->li_addr_line.li_l_data. - li_prologue_end = prologue_end; - curr_line->li_addr_line.li_l_data.li_isa = isa; - line_count++; - - chain_line = (Dwarf_Chain) - _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); - if (chain_line == NULL) { - dwarf_free_line_table_prefix(&prefix); - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - chain_line->ch_item = curr_line; - - if (head_chain == NULL) - head_chain = curr_chain = chain_line; - else { - curr_chain->ch_next = chain_line; - curr_chain = chain_line; - } - } - - address = 0; - file = 1; - line = 1; - column = 0; - is_stmt = prefix.pf_default_is_stmt; - basic_block = false; - end_sequence = false; - prologue_end = false; - epilogue_begin = false; - - - break; - } - - case DW_LNE_set_address:{ - { - READ_UNALIGNED(dbg, address, Dwarf_Addr, - line_ptr, address_size); - if (doaddrs) { - curr_line = - (Dwarf_Line) _dwarf_get_alloc(dbg, - DW_DLA_LINE, - 1); - if (curr_line == NULL) { - dwarf_free_line_table_prefix(&prefix); - _dwarf_error(dbg, error, - DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - curr_line->li_address = address; - curr_line->li_addr_line.li_offset = - line_ptr - dbg->de_debug_line.dss_data; - - line_count++; - - chain_line = (Dwarf_Chain) - _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); - if (chain_line == NULL) { - dwarf_free_line_table_prefix(&prefix); - _dwarf_error(dbg, error, - DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - chain_line->ch_item = curr_line; - - if (head_chain == NULL) - head_chain = curr_chain = chain_line; - else { - curr_chain->ch_next = chain_line; - curr_chain = chain_line; - } - } - - line_ptr += address_size; - } - - break; - } - - case DW_LNE_define_file:{ - - if (dolines) { - cur_file_entry = (Dwarf_File_Entry) - _dwarf_get_alloc(dbg, DW_DLA_FILE_ENTRY, 1); - if (cur_file_entry == NULL) { - dwarf_free_line_table_prefix(&prefix); - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - cur_file_entry->fi_file_name = - (Dwarf_Small *) line_ptr; - line_ptr = - line_ptr + strlen((char *) line_ptr) + 1; - - cur_file_entry->fi_dir_index = (Dwarf_Sword) - _dwarf_decode_u_leb128(line_ptr, - &leb128_length); - line_ptr = line_ptr + leb128_length; - - cur_file_entry->fi_time_last_mod = - _dwarf_decode_u_leb128(line_ptr, - &leb128_length); - line_ptr = line_ptr + leb128_length; - - cur_file_entry->fi_file_length = - _dwarf_decode_u_leb128(line_ptr, - &leb128_length); - line_ptr = line_ptr + leb128_length; - - if (file_entries == NULL) - file_entries = cur_file_entry; - else - prev_file_entry->fi_next = cur_file_entry; - prev_file_entry = cur_file_entry; - - file_entry_count++; - } - break; - } - - default:{ - /* This is an extended op code we do not know about, - other than we know now many bytes it is - and the op code and the bytes of operand. */ - Dwarf_Unsigned remaining_bytes = instr_length -1; - if(instr_length < 1 || remaining_bytes > DW_LNE_LEN_MAX) { - dwarf_free_line_table_prefix(&prefix); - _dwarf_error(dbg, error, - DW_DLE_LINE_EXT_OPCODE_BAD); - return (DW_DLV_ERROR); - } - line_ptr += remaining_bytes; - break; - } - } - - } - } - - block_line = (Dwarf_Line *) - _dwarf_get_alloc(dbg, DW_DLA_LIST, line_count); - if (block_line == NULL) { - dwarf_free_line_table_prefix(&prefix); - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - curr_chain = head_chain; - for (i = 0; i < line_count; i++) { - *(block_line + i) = curr_chain->ch_item; - head_chain = curr_chain; - curr_chain = curr_chain->ch_next; - dwarf_dealloc(dbg, head_chain, DW_DLA_CHAIN); - } - - line_context->lc_file_entries = file_entries; - line_context->lc_file_entry_count = file_entry_count; - line_context->lc_include_directories_count = - prefix.pf_include_directories_count; - if (prefix.pf_include_directories_count > 0) { - /* This gets a pointer to the *first* include dir. The others - follow directly with the standard DWARF2/3 NUL byte - following the last. */ - line_context->lc_include_directories = - prefix.pf_include_directories[0]; - } - - line_context->lc_line_count = line_count; - line_context->lc_compilation_directory = comp_dir; - line_context->lc_version_number = prefix.pf_version; - line_context->lc_dbg = dbg; - *count = line_count; - - *linebuf = block_line; - dwarf_free_line_table_prefix(&prefix); - return (DW_DLV_OK); -} - -int -dwarf_srclines(Dwarf_Die die, - Dwarf_Line ** linebuf, - Dwarf_Signed * linecount, Dwarf_Error * error) -{ - Dwarf_Signed count = 0; - int res = _dwarf_internal_srclines(die, linebuf, &count, - /* addrlist= */ false, - /* linelist= */ true, error); - if (res != DW_DLV_OK) { - return res; - } - *linecount = count; - return res; -} - - - -/* Every line table entry (except DW_DLE_end_sequence, - which is returned using dwarf_lineendsequence()) - potentially has the begin-statement - flag marked 'on'. This returns thru *return_bool, - the begin-statement flag. -*/ - -int -dwarf_linebeginstatement(Dwarf_Line line, - Dwarf_Bool * return_bool, Dwarf_Error * error) -{ - if (line == NULL || return_bool == 0) { - _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL); - return (DW_DLV_ERROR); - } - - *return_bool = (line->li_addr_line.li_l_data.li_is_stmt); - return DW_DLV_OK; -} - -/* At the end of any contiguous line-table there may be - a DW_LNE_end_sequence operator. - This returns non-zero thru *return_bool - if and only if this 'line' entry was a DW_LNE_end_sequence. - - Within a compilation unit or function there may be multiple - line tables, each ending with a DW_LNE_end_sequence. - Each table describes a contiguous region. - Because compilers may split function code up in arbitrary ways - compilers may need to emit multiple contigous regions (ie - line tables) for a single function. - See the DWARF3 spec section 6.2. -*/ -int -dwarf_lineendsequence(Dwarf_Line line, - Dwarf_Bool * return_bool, Dwarf_Error * error) -{ - if (line == NULL) { - _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL); - return (DW_DLV_ERROR); - } - - *return_bool = (line->li_addr_line.li_l_data.li_end_sequence); - return DW_DLV_OK; -} - - -/* Each 'line' entry has a line-number. - If the entry is a DW_LNE_end_sequence the line-number is - meaningless (see dwarf_lineendsequence(), just above). -*/ -int -dwarf_lineno(Dwarf_Line line, - Dwarf_Unsigned * ret_lineno, Dwarf_Error * error) -{ - if (line == NULL || ret_lineno == 0) { - _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL); - return (DW_DLV_ERROR); - } - - *ret_lineno = (line->li_addr_line.li_l_data.li_line); - return DW_DLV_OK; -} - -/* Each 'line' entry has a file-number, and index into the file table. - If the entry is a DW_LNE_end_sequence the index is - meaningless (see dwarf_lineendsequence(), just above). - The file number returned is an index into the file table - produced by dwarf_srcfiles(), but care is required: the - li_file begins with 1 for real files, so that the li_file returned here - is 1 greater than its index into the dwarf_srcfiles() output array. - And entries from DW_LNE_define_file don't appear in - the dwarf_srcfiles() output so file indexes from here may exceed - the size of the dwarf_srcfiles() output array size. -*/ -int -dwarf_line_srcfileno(Dwarf_Line line, - Dwarf_Unsigned * ret_fileno, Dwarf_Error * error) -{ - if (line == NULL || ret_fileno == 0) { - _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL); - return (DW_DLV_ERROR); - } - /* li_file must be <= line->li_context->lc_file_entry_count else it - is trash. li_file 0 means not attributable to any source file - per dwarf2/3 spec. */ - - *ret_fileno = (line->li_addr_line.li_l_data.li_file); - return DW_DLV_OK; -} - - -/* Each 'line' entry has a line-address. - If the entry is a DW_LNE_end_sequence the adddress - is one-beyond the last address this contigous region - covers, so the address is not inside the region, - but is just outside it. -*/ -int -dwarf_lineaddr(Dwarf_Line line, - Dwarf_Addr * ret_lineaddr, Dwarf_Error * error) -{ - if (line == NULL || ret_lineaddr == 0) { - _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL); - return (DW_DLV_ERROR); - } - - *ret_lineaddr = (line->li_address); - return DW_DLV_OK; -} - - -/* Each 'line' entry has a column-within-line (offset - within the line) where the - source text begins. - If the entry is a DW_LNE_end_sequence the line-number is - meaningless (see dwarf_lineendsequence(), just above). - Lines of text begin at column 1. The value 0 - means the line begins at the left edge of the line. - (See the DWARF3 spec, section 6.2.2). -*/ -int -dwarf_lineoff(Dwarf_Line line, - Dwarf_Signed * ret_lineoff, Dwarf_Error * error) -{ - if (line == NULL || ret_lineoff == 0) { - _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL); - return (DW_DLV_ERROR); - } - - *ret_lineoff = - (line->li_addr_line.li_l_data.li_column == - 0 ? -1 : line->li_addr_line.li_l_data.li_column); - return DW_DLV_OK; -} - - -int -dwarf_linesrc(Dwarf_Line line, char **ret_linesrc, Dwarf_Error * error) -{ - Dwarf_Signed i = 0; - Dwarf_File_Entry file_entry; - Dwarf_Small *name_buffer = 0; - Dwarf_Small *include_directories = 0; - Dwarf_Small include_direc_full_path = 0; - Dwarf_Small file_name_full_path = 0; - Dwarf_Debug dbg = 0; - unsigned int comp_dir_len = 0; - - if (line == NULL) { - _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL); - return (DW_DLV_ERROR); - } - - if (line->li_context == NULL) { - _dwarf_error(NULL, error, DW_DLE_LINE_CONTEXT_NULL); - return (DW_DLV_ERROR); - } - dbg = line->li_context->lc_dbg; - - if (line->li_addr_line.li_l_data.li_file > - line->li_context->lc_file_entry_count) { - _dwarf_error(dbg, error, DW_DLE_LINE_FILE_NUM_BAD); - return (DW_DLV_ERROR); - } - - if (line->li_addr_line.li_l_data.li_file == 0) { - /* No file name known: see dwarf2/3 spec. */ - _dwarf_error(dbg, error, DW_DLE_NO_FILE_NAME); - return (DW_DLV_ERROR); - } - file_entry = line->li_context->lc_file_entries; - /* ASSERT: li_file > 0, dwarf correctness issue, see line table - definition of dwarf2/3 spec. */ - /* Example: if li_file is 2 and lc_file_entry_count is 3, - file_entry is file 3 (1 based), aka 2( 0 based) file_entry->next - is file 2 (1 based), aka 1( 0 based) file_entry->next->next is - file 1 (1 based), aka 0( 0 based) file_entry->next->next->next - is NULL. - - and this loop finds the file_entry we need (2 (1 based) in this - case). Because lc_file_entries are in reverse order and - effectively zero based as a count whereas li_file is 1 based. */ - for (i = line->li_addr_line.li_l_data.li_file - 1; i > 0; i--) - file_entry = file_entry->fi_next; - - if (file_entry->fi_file_name == NULL) { - _dwarf_error(dbg, error, DW_DLE_NO_FILE_NAME); - return (DW_DLV_ERROR); - } - - file_name_full_path = file_name_is_full_path(file_entry->fi_file_name); - if (file_name_full_path) { - *ret_linesrc = ((char *) file_entry->fi_file_name); - return DW_DLV_OK; - } - - if (file_entry->fi_dir_index == 0) { - - /* dir_index of 0 means that the compilation was in the - 'current directory of compilation' */ - if (line->li_context->lc_compilation_directory == NULL) { - /* we don't actually *have* a current directory of - compilation: DW_AT_comp_dir was not present Rather than - emitting DW_DLE_NO_COMP_DIR lets just make an empty name - here. In other words, do the best we can with what we do - have instead of reporting an error. _dwarf_error(dbg, - error, DW_DLE_NO_COMP_DIR); return(DW_DLV_ERROR); */ - comp_dir_len = 0; - } else { - comp_dir_len = strlen((char *) - (line->li_context-> - lc_compilation_directory)); - } - - name_buffer = - _dwarf_get_alloc(line->li_context->lc_dbg, DW_DLA_STRING, - comp_dir_len + 1 + - strlen((char *) file_entry->fi_file_name) + - 1); - if (name_buffer == NULL) { - _dwarf_error(line->li_context->lc_dbg, error, - DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - if (comp_dir_len > 0) { - /* if comp_dir_len is 0 we do not want to put a / in front - of the fi_file_name as we just don't know anything. */ - strcpy((char *) name_buffer, - (char *) (line->li_context-> - lc_compilation_directory)); - strcat((char *) name_buffer, "/"); - } - strcat((char *) name_buffer, (char *) file_entry->fi_file_name); - *ret_linesrc = ((char *) name_buffer); - return DW_DLV_OK; - } - - if (file_entry->fi_dir_index > - line->li_context->lc_include_directories_count) { - _dwarf_error(dbg, error, DW_DLE_INCL_DIR_NUM_BAD); - return (DW_DLV_ERROR); - } - - include_directories = line->li_context->lc_include_directories; - for (i = file_entry->fi_dir_index - 1; i > 0; i--) - include_directories += strlen((char *) include_directories) + 1; - - if (line->li_context->lc_compilation_directory) { - comp_dir_len = strlen((char *) - (line->li_context->lc_compilation_directory)); - } else { - /* No DW_AT_comp_dir present. Do the best we can without it. */ - comp_dir_len = 0; - } - - include_direc_full_path = file_name_is_full_path(include_directories); - name_buffer = _dwarf_get_alloc(dbg, DW_DLA_STRING, - (include_direc_full_path ? 0 : comp_dir_len + 1) + - strlen((char *)include_directories) + 1 + - strlen((char *)file_entry->fi_file_name) + 1); - if (name_buffer == NULL) { - _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - if (!include_direc_full_path) { - if (comp_dir_len > 0) { - strcpy((char *)name_buffer, - (char *)line->li_context->lc_compilation_directory); - /* Who provides the / needed after the compilation - directory? */ - if (!is_path_separator(name_buffer[comp_dir_len - 1])) { - /* Here we provide the / separator. It - should work ok for Windows */ - /* Overwrite previous nul terminator with needed / */ - name_buffer[comp_dir_len] = '/'; - name_buffer[comp_dir_len + 1] = 0; - } - } - } else { - strcpy((char *) name_buffer, ""); - } - strcat((char *) name_buffer, (char *) include_directories); - strcat((char *) name_buffer, "/"); - strcat((char *) name_buffer, (char *) file_entry->fi_file_name); - *ret_linesrc = ((char *) name_buffer); - return DW_DLV_OK; -} - -/* Every line table entry potentially has the basic-block-start - flag marked 'on'. This returns thru *return_bool, - the basic-block-start flag. -*/ -int -dwarf_lineblock(Dwarf_Line line, - Dwarf_Bool * return_bool, Dwarf_Error * error) -{ - if (line == NULL) { - _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL); - return (DW_DLV_ERROR); - } - *return_bool = (line->li_addr_line.li_l_data.li_basic_block); - return DW_DLV_OK; -} - - -#if 0 /* Ignore this. This needs major - re-work. */ -/* - This routine works by looking for exact matches between - the current line address and pc, and crossovers from - from less than pc value to greater than. At each line - that satisfies the above, it records a pointer to the - line, and the difference between the address and pc. - It then scans these pointers and picks out those with - the smallest difference between pc and address. -*/ -int -dwarf_pclines(Dwarf_Debug dbg, - Dwarf_Addr pc, - Dwarf_Line ** linebuf, - Dwarf_Signed slide, - Dwarf_Signed * linecount, Dwarf_Error * error) -{ - /* - Scans the line matrix for the current cu to which a pointer - exists in dbg. */ - Dwarf_Line line; - Dwarf_Line prev_line; - - /* - These flags are for efficiency reasons. Check_line is true - initially, but set false when the address of the current line is - greater than pc. It is set true only when the address of the - current line falls below pc. This assumes that addresses within - the same segment increase, and we are only interested in the - switch from a less than pc address to a greater than. First_line - is set true initially, but set false after the first line is - scanned. This is to prevent looking at the address of previous - line when slide is DW_DLS_BACKWARD, and the first line is being - scanned. */ - Dwarf_Bool check_line, first_line; - - /* - Diff tracks the smallest difference a line address and the input - pc value. */ - Dwarf_Signed diff, i; - - /* - For the slide = DW_DLS_BACKWARD case, pc_less is the value of - the address of the line immediately preceding the first line - that has value greater than pc. For the slide = DW_DLS_FORWARD - case, pc_more is the values of address for the first line that - is greater than pc. Diff is the difference between either of the - these values and pc. */ - Dwarf_Addr pc_less, pc_more; - - /* - Pc_line_buf points to a chain of pointers to lines of which - those with a diff equal to the smallest difference will be - returned. */ - Dwarf_Line *pc_line_buf, *pc_line; - - /* - Chain_count counts the number of lines in the above chain for - which the diff is equal to the smallest difference This is the - number returned by this routine. */ - Dwarf_Signed chain_count; - - chain_head = NULL; - - check_line = true; - first_line = true; - diff = MAX_LINE_DIFF; - - for (i = 0; i < dbg->de_cu_line_count; i++) { - - line = *(dbg->de_cu_line_ptr + i); - prev_line = first_line ? NULL : *(dbg->de_cu_line_ptr + i - 1); - - if (line->li_address == pc) { - chain_ptr = (struct chain *) - _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); - if (chain_ptr == NULL) { - _dwarf_error(NULL, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - chain_ptr->line = line; - chain_ptr->diff = diff = 0; - chain_ptr->next = chain_head; - chain_head = chain_ptr; - } else - /* - Look for crossover from less than pc address to greater - than. */ - if (check_line && line->li_address > pc && - (first_line ? 0 : prev_line->li_address) < pc) - - if (slide == DW_DLS_BACKWARD && !first_line) { - pc_less = prev_line->li_address; - if (pc - pc_less <= diff) { - chain_ptr = (struct chain *) - _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); - if (chain_ptr == NULL) { - _dwarf_error(NULL, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - chain_ptr->line = prev_line; - chain_ptr->diff = diff = pc - pc_less; - chain_ptr->next = chain_head; - chain_head = chain_ptr; - } - check_line = false; - } else if (slide == DW_DLS_FORWARD) { - pc_more = line->li_address; - if (pc_more - pc <= diff) { - chain_ptr = (struct chain *) - _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); - if (chain_ptr == NULL) { - _dwarf_error(NULL, error, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - - chain_ptr->line = line; - chain_ptr->diff = diff = pc_more - pc; - chain_ptr->next = chain_head; - chain_head = chain_ptr; - } - check_line = false; - } else - /* Check addresses only when they go */ - /* below pc. */ - if (line->li_address < pc) - check_line = true; - - first_line = false; - } - - chain_count = 0; - for (chain_ptr = chain_head; chain_ptr != NULL; - chain_ptr = chain_ptr->next) - if (chain_ptr->diff == diff) - chain_count++; - - pc_line_buf = pc_line = (Dwarf_Line) - _dwarf_get_alloc(dbg, DW_DLA_LIST, chain_count); - for (chain_ptr = chain_head; chain_ptr != NULL; - chain_ptr = chain_ptr->next) - if (chain_ptr->diff == diff) { - *pc_line = chain_ptr->line; - pc_line++; - } - - for (chain_ptr = chain_head; chain_ptr != NULL;) { - chain_head = chain_ptr; - chain_ptr = chain_ptr->next; - dwarf_dealloc(dbg, chain_head, DW_DLA_CHAIN); - } - - *linebuf = pc_line_buf; - return (chain_count); -} -#endif - - - -/* - It's impossible for callers of dwarf_srclines() to get to and - free all the resources (in particular, the li_context and its - lc_file_entries). - So this function, new July 2005, does it. -*/ - -void -dwarf_srclines_dealloc(Dwarf_Debug dbg, Dwarf_Line * linebuf, - Dwarf_Signed count) -{ - - Dwarf_Signed i = 0; - struct Dwarf_Line_Context_s *context = 0; - - if (count > 0) { - /* All these entries share a single context */ - context = linebuf[0]->li_context; - } - for (i = 0; i < count; ++i) { - dwarf_dealloc(dbg, linebuf[i], DW_DLA_LINE); - } - dwarf_dealloc(dbg, linebuf, DW_DLA_LIST); - - if (context) { - Dwarf_File_Entry fe = context->lc_file_entries; - - while (fe) { - Dwarf_File_Entry fenext = fe->fi_next; - - dwarf_dealloc(dbg, fe, DW_DLA_FILE_ENTRY); - fe = fenext; - } - dwarf_dealloc(dbg, context, DW_DLA_LINE_CONTEXT); - } - - return; -} - -/* Operand counts per standard operand. - The initial zero is for DW_LNS_copy. - This is an economical way to verify we understand the table - of standard-opcode-lengths in the line table prologue. */ -#define STANDARD_OPERAND_COUNT_DWARF2 9 -#define STANDARD_OPERAND_COUNT_DWARF3 12 -static unsigned char - dwarf_standard_opcode_operand_count[STANDARD_OPERAND_COUNT_DWARF3] = { - /* DWARF2 */ - 0, - 1, 1, 1, 1, - 0, 0, 0, - 1, - /* Following are new for DWARF3. */ - 0, 0, 1 -}; - -/* We have a normal standard opcode base, but - an arm compiler emitted a non-standard table! - This could lead to problems... - ARM C/C++ Compiler, RVCT4.0 [Build 4 - 00] seems to get the table wrong . */ -static unsigned char -dwarf_arm_standard_opcode_operand_count[STANDARD_OPERAND_COUNT_DWARF3] = { - /* DWARF2 */ - 0, - 1, 1, 1, 1, - 0, 0, 0, - 0, /* <<< --- this is wrong */ - /* Following are new for DWARF3. */ - 0, 0, 1 -}; - -static void -print_header_issue(Dwarf_Debug dbg, - char *specific_msg, - Dwarf_Small *data_start, - int *err_count_out) -{ - if(!err_count_out) - return; - printf("*** DWARF CHECK: " - "line table header: %s", - specific_msg); - if( data_start >= dbg->de_debug_line.dss_data && - (data_start < (dbg->de_debug_line.dss_data + - dbg->de_debug_line.dss_size))) { - Dwarf_Unsigned off = data_start - dbg->de_debug_line.dss_data; - printf(" at .debug_line section offset 0x%" DW_PR_DUx - " ( %" DW_PR_DUu " ) ", - off,off); - } else { - printf(" (unknown section location) "); - } - printf("***\n"); - *err_count_out += 1; -} - - - -/* Common line table prefix reading code. - Returns DW_DLV_OK, DW_DLV_ERROR. - DW_DLV_NO_ENTRY cannot be returned, but callers should - assume it is possible. - - The prefix_out area must be initialized properly before calling this. - - Has the side effect of allocating arrays which - must be freed (see the Line_Table_Prefix_s struct which - holds the pointers to space we allocate here). - - bogus_bytes_ptr and bogus_bytes are output values which - let a print-program notify the user of some surprising bytes - after a line table header and before the line table instructions. - These can be ignored unless one is printing. - And are ignored if NULL passed as the pointer. -*/ - -/* err_count_out may be NULL, in which case we - make no attempt to count checking-type errors. - Checking-type errors do not stop us, we just report them. -*/ -int -dwarf_read_line_table_prefix(Dwarf_Debug dbg, - Dwarf_Small * data_start, - Dwarf_Unsigned data_length, - Dwarf_Small ** updated_data_start_out, - struct Line_Table_Prefix_s *prefix_out, - Dwarf_Small ** bogus_bytes_ptr, - Dwarf_Unsigned *bogus_bytes, - Dwarf_Error * err, - int *err_count_out) -{ - Dwarf_Small *line_ptr = data_start; - Dwarf_Unsigned total_length = 0; - int local_length_size = 0; - int local_extension_size = 0; - Dwarf_Unsigned prologue_length = 0; - Dwarf_Half version = 0; - Dwarf_Unsigned directories_count = 0; - Dwarf_Unsigned directories_malloc = 0; - Dwarf_Unsigned files_count = 0; - Dwarf_Unsigned files_malloc = 0; - Dwarf_Small *line_ptr_end = 0; - Dwarf_Small *lp_begin = 0; - if(bogus_bytes_ptr) *bogus_bytes_ptr = 0; - if(bogus_bytes) *bogus_bytes= 0; - - prefix_out->pf_line_ptr_start = line_ptr; - /* READ_AREA_LENGTH updates line_ptr for consumed bytes */ - READ_AREA_LENGTH(dbg, total_length, Dwarf_Unsigned, - line_ptr, local_length_size, local_extension_size); - - - line_ptr_end = line_ptr + total_length; - prefix_out->pf_line_ptr_end = line_ptr_end; - prefix_out->pf_length_field_length = local_length_size + - local_extension_size; - /* ASSERT: prefix_out->pf_length_field_length == line_ptr - -prefix_out->pf_line_ptr_start; */ - if (line_ptr_end > dbg->de_debug_line.dss_data + - dbg->de_debug_line.dss_size) { - _dwarf_error(dbg, err, DW_DLE_DEBUG_LINE_LENGTH_BAD); - return (DW_DLV_ERROR); - } - if (line_ptr_end > data_start + data_length) { - _dwarf_error(dbg, err, DW_DLE_DEBUG_LINE_LENGTH_BAD); - return (DW_DLV_ERROR); - } - prefix_out->pf_total_length = total_length; - - READ_UNALIGNED(dbg, version, Dwarf_Half, - line_ptr, sizeof(Dwarf_Half)); - prefix_out->pf_version = version; - line_ptr += sizeof(Dwarf_Half); - if (version != CURRENT_VERSION_STAMP && - version != CURRENT_VERSION_STAMP3) { - _dwarf_error(dbg, err, DW_DLE_VERSION_STAMP_ERROR); - return (DW_DLV_ERROR); - } - - READ_UNALIGNED(dbg, prologue_length, Dwarf_Unsigned, - line_ptr, local_length_size); - prefix_out->pf_prologue_length = prologue_length; - line_ptr += local_length_size; - prefix_out->pf_line_prologue_start = line_ptr; - - prefix_out->pf_minimum_instruction_length = - *(unsigned char *) line_ptr; - line_ptr = line_ptr + sizeof(Dwarf_Small); - - prefix_out->pf_default_is_stmt = *(unsigned char *) line_ptr; - line_ptr = line_ptr + sizeof(Dwarf_Small); - - prefix_out->pf_line_base = *(signed char *) line_ptr; - line_ptr = line_ptr + sizeof(Dwarf_Sbyte); - - prefix_out->pf_line_range = *(unsigned char *) line_ptr; - line_ptr = line_ptr + sizeof(Dwarf_Small); - - prefix_out->pf_opcode_base = *(unsigned char *) line_ptr; - line_ptr = line_ptr + sizeof(Dwarf_Small); - - /* Set up the array of standard opcode lengths. */ - /* We think this works ok even for cross-endian processing of - objects. It might be wrong, we might need to specially process - the array of ubyte into host order. */ - prefix_out->pf_opcode_length_table = line_ptr; - - /* pf_opcode_base is one greater than the size of the array. */ - line_ptr += prefix_out->pf_opcode_base - 1; - - { - /* Determine (as best we can) whether the - pf_opcode_length_table holds 9 or 12 standard-conforming - entries. gcc4 upped to DWARF3's 12 without updating the - version number. */ - int operand_ck_fail = true; - - if (prefix_out->pf_opcode_base >= STANDARD_OPERAND_COUNT_DWARF3) { - int mismatch = memcmp(dwarf_standard_opcode_operand_count, - prefix_out->pf_opcode_length_table, - STANDARD_OPERAND_COUNT_DWARF3); - if(mismatch) { - if(err_count_out) { - print_header_issue(dbg,"standard-operands did not match", - data_start,err_count_out); - } - mismatch = memcmp(dwarf_arm_standard_opcode_operand_count, - prefix_out->pf_opcode_length_table, - STANDARD_OPERAND_COUNT_DWARF3); - if(!mismatch && err_count_out) { - print_header_issue(dbg,"arm (incorrect) operands in use", - data_start,err_count_out); - } - } - if (!mismatch) { - if (version == 2) { - if(err_count_out) { - print_header_issue(dbg, - "standard DWARF3 operands matched, but is DWARF2 linetable", - data_start,err_count_out); - } - } - operand_ck_fail = false; - prefix_out->pf_std_op_count = - STANDARD_OPERAND_COUNT_DWARF3; - } - } - if (operand_ck_fail) { - if (prefix_out->pf_opcode_base >= - STANDARD_OPERAND_COUNT_DWARF2) { - - int mismatch = - memcmp(dwarf_standard_opcode_operand_count, - prefix_out->pf_opcode_length_table, - STANDARD_OPERAND_COUNT_DWARF2); - if(mismatch) { - if(err_count_out) { - print_header_issue(dbg,"standard-operands-lengths did not match", - data_start,err_count_out); - } - mismatch = memcmp(dwarf_arm_standard_opcode_operand_count, - prefix_out->pf_opcode_length_table, - STANDARD_OPERAND_COUNT_DWARF2); - if(!mismatch && err_count_out) { - print_header_issue(dbg,"arm (incorrect) operand in use", - data_start,err_count_out); - } - } - - if (!mismatch) { - operand_ck_fail = false; - prefix_out->pf_std_op_count = - STANDARD_OPERAND_COUNT_DWARF2; - } - } - } - if (operand_ck_fail) { - /* Here we are not sure what the pf_std_op_count is. */ - _dwarf_error(dbg, err, DW_DLE_LINE_NUM_OPERANDS_BAD); - return (DW_DLV_ERROR); - } - } - /* At this point we no longer need to check operand counts. */ - - - directories_count = 0; - directories_malloc = 5; - prefix_out->pf_include_directories = malloc(sizeof(Dwarf_Small *) * - directories_malloc); - if (prefix_out->pf_include_directories == NULL) { - _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - memset(prefix_out->pf_include_directories, 0, - sizeof(Dwarf_Small *) * directories_malloc); - - while ((*(char *) line_ptr) != '\0') { - if (directories_count >= directories_malloc) { - Dwarf_Unsigned expand = 2 * directories_malloc; - Dwarf_Unsigned bytesalloc = sizeof(Dwarf_Small *) * expand; - Dwarf_Small **newdirs = - realloc(prefix_out->pf_include_directories, - bytesalloc); - - if (!newdirs) { - _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - /* Doubled size, zero out second half. */ - memset(newdirs + directories_malloc, 0, - sizeof(Dwarf_Small *) * directories_malloc); - directories_malloc = expand; - prefix_out->pf_include_directories = newdirs; - } - prefix_out->pf_include_directories[directories_count] = - line_ptr; - line_ptr = line_ptr + strlen((char *) line_ptr) + 1; - directories_count++; - } - prefix_out->pf_include_directories_count = directories_count; - line_ptr++; - - files_count = 0; - files_malloc = 5; - prefix_out->pf_line_table_file_entries = - malloc(sizeof(struct Line_Table_File_Entry_s) * files_malloc); - if (prefix_out->pf_line_table_file_entries == NULL) { - _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - memset(prefix_out->pf_line_table_file_entries, 0, - sizeof(struct Line_Table_File_Entry_s) * files_malloc); - - while (*(char *) line_ptr != '\0') { - Dwarf_Unsigned utmp; - Dwarf_Unsigned dir_index = 0; - Dwarf_Unsigned lastmod = 0; - Dwarf_Unsigned file_length = 0; - struct Line_Table_File_Entry_s *curline; - Dwarf_Word leb128_length = 0; - - - if (files_count >= files_malloc) { - Dwarf_Unsigned expand = 2 * files_malloc; - struct Line_Table_File_Entry_s *newfiles = - realloc(prefix_out->pf_line_table_file_entries, - sizeof(struct Line_Table_File_Entry_s) * - expand); - if (!newfiles) { - _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); - return (DW_DLV_ERROR); - } - memset(newfiles + files_malloc, 0, - sizeof(struct Line_Table_File_Entry_s) * - files_malloc); - files_malloc = expand; - prefix_out->pf_line_table_file_entries = newfiles; - } - curline = prefix_out->pf_line_table_file_entries + files_count; - - curline->lte_filename = line_ptr; - line_ptr = line_ptr + strlen((char *) line_ptr) + 1; - - DECODE_LEB128_UWORD(line_ptr, utmp); - dir_index = (Dwarf_Sword) utmp; - if (dir_index > directories_count) { - _dwarf_error(dbg, err, DW_DLE_DIR_INDEX_BAD); - return (DW_DLV_ERROR); - } - curline->lte_directory_index = dir_index; - - lastmod = _dwarf_decode_u_leb128(line_ptr, &leb128_length); - line_ptr = line_ptr + leb128_length; - curline->lte_last_modification_time = lastmod; - - /* Skip over file length. */ - file_length = _dwarf_decode_u_leb128(line_ptr, &leb128_length); - line_ptr = line_ptr + leb128_length; - curline->lte_length_of_file = file_length; - - ++files_count; - - } - prefix_out->pf_files_count = files_count; - /* Skip trailing nul byte */ - ++line_ptr; - - - lp_begin = prefix_out->pf_line_prologue_start + - prefix_out->pf_prologue_length; - if (line_ptr != lp_begin) { - if(line_ptr > lp_begin) { - _dwarf_error(dbg, err, DW_DLE_LINE_PROLOG_LENGTH_BAD); - return (DW_DLV_ERROR); - } else { - /* Bug in compiler. These - * bytes are really part of the instruction - * stream. The prefix_out->pf_prologue_length is - * wrong (12 too high). */ - if(bogus_bytes_ptr) { - *bogus_bytes_ptr = line_ptr; - } - if(bogus_bytes) { - /* How far off things are. We expect the - value 12 ! */ - *bogus_bytes = (lp_begin - line_ptr); - } - } - /* Ignore the lp_begin calc. Assume line_ptr right. - Making up for compiler bug. */ - lp_begin = line_ptr; - - } - - *updated_data_start_out = lp_begin; - return DW_DLV_OK; -} - - -/* Initialize the Line_Table_Prefix_s struct. - memset is not guaranteed a portable initializer, but works - fine for current architectures. AFAIK. -*/ -void -dwarf_init_line_table_prefix(struct Line_Table_Prefix_s *pf) -{ - memset(pf, 0, sizeof(*pf)); -} - -/* Free any malloc'd area. of the Line_Table_Prefix_s struct. */ -void -dwarf_free_line_table_prefix(struct Line_Table_Prefix_s *pf) -{ - if (pf->pf_include_directories) { - free(pf->pf_include_directories); - pf->pf_include_directories = 0; - } - if (pf->pf_line_table_file_entries) { - free(pf->pf_line_table_file_entries); - pf->pf_line_table_file_entries = 0; - } - return; -} |