/* Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. Portions Copyright (C) 2007-2018 David Anderson. All Rights Reserved. Portions Copyright (C) 2010-2012 SN Systems Ltd. All Rights Reserved. Portions Copyright (C) 2015-2015 Google, 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. */ /* This is #included twice. Once for libdwarf callers and one for dwarfdump which prints the internals. This way we have just one blob of code that reads the table operations. */ #define TRUE 1 #define FALSE 0 static unsigned char dwarf_standard_opcode_operand_count[STANDARD_OPERAND_COUNT_TWO_LEVEL] = { /* DWARF2 */ 0, 1, 1, 1, 1, 0, 0, 0, 1, /* Following are new for DWARF3. */ 0, 0, 1, /* Experimental opcodes. */ 1, 2, 0, }; /* 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 }; /* Rather like memcmp but identifies which value pair mismatches (the return value is non-zero if mismatch, zero if match).. mismatch_entry returns the table index that mismatches. tabval returns the table byte value. lineval returns the value from the line table header. */ static int operandmismatch(unsigned char * table,unsigned table_length, unsigned char *linetable, unsigned check_count, unsigned * mismatch_entry, unsigned * tabval,unsigned *lineval) { unsigned i = 0; /* check_count better be <= table_length */ for (i = 0; i table_length) { *mismatch_entry = i; *lineval = linetable[i]; *tabval = 0; /* No entry present. */ /* A kind of mismatch */ return TRUE; } if (table[i] == linetable[i]) { continue; } *mismatch_entry = i; *tabval = table[i]; *lineval = linetable[i]; return TRUE; } /* Matches. */ return FALSE; } /* Encapsulates DECODE_LEB128_UWORD_CK so the caller can free resources in case of problems. */ static int read_uword_de(Dwarf_Small **lp, Dwarf_Unsigned *out_p, Dwarf_Debug dbg, Dwarf_Error *err, Dwarf_Small *lpend) { Dwarf_Small *inptr = *lp; Dwarf_Unsigned out = 0; DECODE_LEB128_UWORD_CK(inptr, out, dbg,err,lpend); *lp = inptr; *out_p = out; return DW_DLV_OK; } static int read_sword_de(Dwarf_Small **lp, Dwarf_Signed *out_p, Dwarf_Debug dbg, Dwarf_Error *err, Dwarf_Small *lpend) { Dwarf_Small *inptr = *lp; Dwarf_Signed out = 0; DECODE_LEB128_SWORD_CK(inptr, out, dbg,err,lpend); *lp = inptr; *out_p = out; return DW_DLV_OK; } /* Common line table header reading code. Returns DW_DLV_OK, DW_DLV_ERROR. DW_DLV_NO_ENTRY cannot be returned, but callers should assume it is possible. The line_context area must be initialized properly before calling this. Has the side effect of allocating arrays which must be freed (see the Line_Table_Context 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. See dw-linetableheader.txt for the ordering of text fields across the various dwarf versions. The code follows this ordering closely. Some of the arguments remaining are in line_context so can be deleted from the argument list (after a close look for correctness). */ static int _dwarf_read_line_table_header(Dwarf_Debug dbg, Dwarf_CU_Context cu_context, Dwarf_Small * section_start, Dwarf_Small * data_start, Dwarf_Unsigned section_length, Dwarf_Small ** updated_data_start_out, Dwarf_Line_Context line_context, Dwarf_Small ** bogus_bytes_ptr, Dwarf_Unsigned *bogus_bytes, Dwarf_Error * err, int *err_count_out) { Dwarf_Small *line_ptr = data_start; Dwarf_Small *starting_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_Small *section_end = section_start + section_length; Dwarf_Small *line_ptr_end = 0; Dwarf_Small *lp_begin = 0; int res = 0; Dwarf_Unsigned htmp = 0; if (bogus_bytes_ptr) *bogus_bytes_ptr = 0; if (bogus_bytes) *bogus_bytes= 0; line_context->lc_line_ptr_start = starting_line_ptr; /* READ_AREA_LENGTH updates line_ptr for consumed bytes */ READ_AREA_LENGTH_CK(dbg, total_length, Dwarf_Unsigned, line_ptr, local_length_size, local_extension_size, err, section_length,section_end); line_ptr_end = line_ptr + total_length; line_context->lc_line_ptr_end = line_ptr_end; line_context->lc_length_field_length = local_length_size + local_extension_size; line_context->lc_section_offset = starting_line_ptr - dbg->de_debug_line.dss_data; /* ASSERT: line_context->lc_length_field_length == line_ptr -line_context->lc_line_ptr_start; */ if (line_ptr_end > section_end) { _dwarf_error(dbg, err, DW_DLE_DEBUG_LINE_LENGTH_BAD); return (DW_DLV_ERROR); } line_context->lc_total_length = total_length; /* READ_UNALIGNED_CK(dbg, version, Dwarf_Half, line_ptr, DWARF_HALF_SIZE, err,line_ptr_end); */ res = _dwarf_read_unaligned_ck_wrapper(dbg, &htmp,line_ptr,DWARF_HALF_SIZE,line_ptr_end,err); if (res == DW_DLV_ERROR) { return res; } version = htmp; line_context->lc_version_number = version; line_ptr += DWARF_HALF_SIZE; if (version != DW_LINE_VERSION2 && version != DW_LINE_VERSION3 && version != DW_LINE_VERSION4 && version != DW_LINE_VERSION5 && version != EXPERIMENTAL_LINE_TABLES_VERSION) { _dwarf_error(dbg, err, DW_DLE_VERSION_STAMP_ERROR); return (DW_DLV_ERROR); } if (version == DW_LINE_VERSION5) { if (line_ptr >= line_ptr_end) { _dwarf_error(dbg, err, DW_DLE_DEBUG_LINE_LENGTH_BAD); return (DW_DLV_ERROR); } line_context->lc_address_size = *(unsigned char *) line_ptr; line_ptr = line_ptr + sizeof(Dwarf_Small); if (line_ptr >= line_ptr_end) { _dwarf_error(dbg, err, DW_DLE_DEBUG_LINE_LENGTH_BAD); return (DW_DLV_ERROR); } line_context->lc_segment_selector_size = *(unsigned char *) line_ptr; line_ptr = line_ptr + sizeof(Dwarf_Small); } else { line_context->lc_address_size = cu_context->cc_address_size; line_context->lc_segment_selector_size = cu_context->cc_segment_selector_size; } READ_UNALIGNED_CK(dbg, prologue_length, Dwarf_Unsigned, line_ptr, local_length_size, err,line_ptr_end); line_context->lc_prologue_length = prologue_length; line_ptr += local_length_size; line_context->lc_line_prologue_start = line_ptr; if (line_ptr >= line_ptr_end) { _dwarf_error(dbg, err, DW_DLE_DEBUG_LINE_LENGTH_BAD); return (DW_DLV_ERROR); } line_context->lc_minimum_instruction_length = *(unsigned char *) line_ptr; line_ptr = line_ptr + sizeof(Dwarf_Small); if (version == DW_LINE_VERSION4 || version == DW_LINE_VERSION5 || version == EXPERIMENTAL_LINE_TABLES_VERSION) { if (line_ptr >= line_ptr_end) { _dwarf_error(dbg, err, DW_DLE_DEBUG_LINE_LENGTH_BAD); return (DW_DLV_ERROR); } line_context->lc_maximum_ops_per_instruction = *(unsigned char *) line_ptr; line_ptr = line_ptr + sizeof(Dwarf_Small); } if (line_ptr >= line_ptr_end) { _dwarf_error(dbg, err, DW_DLE_DEBUG_LINE_LENGTH_BAD); return (DW_DLV_ERROR); } line_context->lc_default_is_stmt = *(unsigned char *) line_ptr; line_ptr = line_ptr + sizeof(Dwarf_Small); if (line_ptr >= line_ptr_end) { _dwarf_error(dbg, err, DW_DLE_DEBUG_LINE_LENGTH_BAD); return (DW_DLV_ERROR); } line_context->lc_line_base = *(signed char *) line_ptr; line_ptr = line_ptr + sizeof(Dwarf_Sbyte); if(line_ptr >= line_ptr_end) { _dwarf_error(dbg, err, DW_DLE_LINE_OFFSET_BAD); return DW_DLV_ERROR; } line_context->lc_line_range = *(unsigned char *) line_ptr; if (!line_context->lc_line_range) { _dwarf_error(dbg, err, DW_DLE_DEBUG_LINE_RANGE_ZERO); return DW_DLV_ERROR; } line_ptr = line_ptr + sizeof(Dwarf_Small); if(line_ptr >= line_ptr_end) { _dwarf_error(dbg, err, DW_DLE_LINE_OFFSET_BAD); return DW_DLV_ERROR; } line_context->lc_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. */ line_context->lc_opcode_length_table = line_ptr; /* lc_opcode_base is one greater than the size of the array. */ line_ptr += line_context->lc_opcode_base - 1; line_context->lc_std_op_count = line_context->lc_opcode_base -1; if(line_ptr >= line_ptr_end) { _dwarf_error(dbg, err, DW_DLE_LINE_OFFSET_BAD); return DW_DLV_ERROR; } { /* Determine (as best we can) whether the lc_opcode_length_table holds 9 or 12 standard-conforming entries. gcc4 upped to DWARF3's 12 without updating the version number. EXPERIMENTAL_LINE_TABLES_VERSION upped to 15. */ unsigned check_count = line_context->lc_std_op_count; unsigned tab_count = sizeof(dwarf_standard_opcode_operand_count); int operand_ck_fail = true; if (line_context->lc_std_op_count > tab_count) { _dwarf_print_header_issue(dbg, "Too many standard operands in linetable header: ", data_start, line_context->lc_std_op_count, 0,0,0, err_count_out); check_count = tab_count; } { unsigned entrynum = 0; unsigned tabv = 0; unsigned linetabv = 0; int mismatch = operandmismatch( dwarf_standard_opcode_operand_count, tab_count, line_context->lc_opcode_length_table, check_count,&entrynum,&tabv,&linetabv); if (mismatch) { if (err_count_out) { _dwarf_print_header_issue(dbg, "standard-operands did not match, checked", data_start, check_count, entrynum,tabv,linetabv,err_count_out); } if (check_count > sizeof(dwarf_arm_standard_opcode_operand_count)) { check_count = sizeof(dwarf_arm_standard_opcode_operand_count); } mismatch = operandmismatch( dwarf_arm_standard_opcode_operand_count, sizeof(dwarf_arm_standard_opcode_operand_count), line_context->lc_opcode_length_table, check_count,&entrynum,&tabv,&linetabv); if (!mismatch && err_count_out) { _dwarf_print_header_issue(dbg, "arm (incorrect) operands in use: ", data_start, check_count, entrynum,tabv,linetabv,err_count_out); } } if (!mismatch) { if (version == 2) { if (line_context->lc_std_op_count == STANDARD_OPERAND_COUNT_DWARF3) { _dwarf_print_header_issue(dbg, "standard DWARF3 operands matched," " but is DWARF2 linetable: count", data_start, check_count, 0,0,0, err_count_out); } } operand_ck_fail = false; } } if (operand_ck_fail) { /* Here we are not sure what the lc_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. */ if(line_ptr >= line_ptr_end) { _dwarf_error(dbg, err, DW_DLE_LINE_OFFSET_BAD); return DW_DLV_ERROR; } if (version < DW_LINE_VERSION5){ Dwarf_Unsigned directories_count = 0; Dwarf_Unsigned directories_malloc = 5; line_context->lc_include_directories = malloc(sizeof(Dwarf_Small *) * directories_malloc); if (line_context->lc_include_directories == NULL) { _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } memset(line_context->lc_include_directories, 0, sizeof(Dwarf_Small *) * directories_malloc); if (line_ptr >= line_ptr_end) { _dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR); return (DW_DLV_ERROR); } 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(line_context->lc_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; line_context->lc_include_directories = newdirs; } line_context->lc_include_directories[directories_count] = line_ptr; res = _dwarf_check_string_valid(dbg, data_start,line_ptr,line_ptr_end, DW_DLE_LINE_STRING_BAD,err); if (res != DW_DLV_OK) { return res; } line_ptr = line_ptr + strlen((char *) line_ptr) + 1; directories_count++; if (line_ptr >= line_ptr_end) { _dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR); return (DW_DLV_ERROR); } } line_ptr++; line_context->lc_include_directories_count = directories_count; } else if (version == EXPERIMENTAL_LINE_TABLES_VERSION) { /* Empty old style dir entry list. */ line_ptr++; } else if (version == DW_LINE_VERSION5) { /* handled below */ } else { /* No old style directory entries. */ } if(line_ptr > line_ptr_end) { _dwarf_error(dbg, err, DW_DLE_LINE_OFFSET_BAD); return DW_DLV_ERROR; } if (version < DW_LINE_VERSION5) { if (line_ptr >= line_ptr_end) { _dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR); return (DW_DLV_ERROR); } while (*(char *) line_ptr != '\0') { Dwarf_Unsigned utmp; Dwarf_Unsigned dir_index = 0; Dwarf_Unsigned lastmod = 0; Dwarf_Unsigned file_length = 0; int resl = 0; Dwarf_File_Entry currfile = 0; currfile = (Dwarf_File_Entry) malloc(sizeof(struct Dwarf_File_Entry_s)); if (currfile == NULL) { _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } memset(currfile,0,sizeof(struct Dwarf_File_Entry_s)); /* Insert early so in case of error we can find and free the record. */ _dwarf_add_to_files_list(line_context,currfile); currfile->fi_file_name = line_ptr; resl = _dwarf_check_string_valid(dbg, data_start,line_ptr,line_ptr_end, DW_DLE_LINE_STRING_BAD,err); if (resl != DW_DLV_OK) { return resl; } line_ptr = line_ptr + strlen((char *) line_ptr) + 1; /* DECODE_LEB128_UWORD_CK(line_ptr, utmp,dbg, err,line_ptr_end); */ res = read_uword_de(&line_ptr,&utmp, dbg,err,line_ptr_end); if (res == DW_DLV_ERROR) { return DW_DLV_ERROR; } dir_index = (Dwarf_Unsigned) utmp; if (dir_index > line_context->lc_include_directories_count) { _dwarf_error(dbg, err, DW_DLE_DIR_INDEX_BAD); return (DW_DLV_ERROR); } currfile->fi_dir_index = dir_index; currfile->fi_dir_index_present = TRUE; /*DECODE_LEB128_UWORD_CK(line_ptr,lastmod, dbg,err, line_ptr_end); */ res = read_uword_de( &line_ptr,&lastmod, dbg,err,line_ptr_end); if (res == DW_DLV_ERROR) { return DW_DLV_ERROR; } currfile->fi_time_last_mod = lastmod; currfile->fi_time_last_mod_present = TRUE; DECODE_LEB128_UWORD_CK(line_ptr,file_length, dbg,err, line_ptr_end); currfile->fi_file_length = file_length; currfile->fi_file_length_present = TRUE; if (line_ptr >= line_ptr_end) { _dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR); return (DW_DLV_ERROR); } } /* Skip trailing nul byte */ ++line_ptr; } else if (version == EXPERIMENTAL_LINE_TABLES_VERSION) { if (line_ptr >= line_ptr_end) { _dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR); return (DW_DLV_ERROR); } if (*line_ptr != 0) { _dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR); return (DW_DLV_ERROR); } line_ptr++; } else if (version == 5) { /* handled below */ } else { /* No old style filenames entries. */ } if(line_ptr > line_ptr_end) { _dwarf_error(dbg, err, DW_DLE_LINE_OFFSET_BAD); return DW_DLV_ERROR; } if (version == EXPERIMENTAL_LINE_TABLES_VERSION) { static unsigned char expbytes[5] = {0,0xff,0xff,0x7f, 0x7f }; Dwarf_Unsigned logicals_table_offset = 0; Dwarf_Unsigned actuals_table_offset = 0; unsigned i = 0; for ( ; i < 5; ++i) { if (line_ptr >= line_ptr_end) { _dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR); return (DW_DLV_ERROR); } if (*line_ptr != expbytes[i]) { _dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR); return (DW_DLV_ERROR); } line_ptr++; } READ_UNALIGNED_CK(dbg, logicals_table_offset, Dwarf_Unsigned, line_ptr, local_length_size,err,line_ptr_end); line_context->lc_logicals_table_offset = logicals_table_offset; line_ptr += local_length_size; READ_UNALIGNED_CK(dbg, actuals_table_offset, Dwarf_Unsigned, line_ptr, local_length_size,err,line_ptr_end); line_context->lc_actuals_table_offset = actuals_table_offset; line_ptr += local_length_size; if(line_ptr > line_ptr_end) { _dwarf_error(dbg, err, DW_DLE_LINE_OFFSET_BAD); return DW_DLV_ERROR; } } if (version == DW_LINE_VERSION5 || version == EXPERIMENTAL_LINE_TABLES_VERSION) { /* DWARF 5. directory names.*/ Dwarf_Unsigned directory_format_count = 0; struct Dwarf_Unsigned_Pair_s * format_values = 0; Dwarf_Unsigned directories_count = 0; Dwarf_Unsigned i = 0; Dwarf_Unsigned j = 0; int dres = 0; if (line_ptr >= line_ptr_end) { _dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR); return (DW_DLV_ERROR); } directory_format_count = *(unsigned char *) line_ptr; line_context->lc_directory_entry_format_count = directory_format_count; line_ptr = line_ptr + sizeof(Dwarf_Small); if (directory_format_count > 0) { format_values = malloc(sizeof(struct Dwarf_Unsigned_Pair_s) * directory_format_count); if (format_values == NULL) { _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } for (i = 0; i < directory_format_count; i++) { dres=read_uword_de(&line_ptr, &format_values[i].up_first, dbg,err,line_ptr_end); if (dres != DW_DLV_OK) { free(format_values); format_values = 0; return dres; } dres=read_uword_de(&line_ptr, &format_values[i].up_second, dbg,err,line_ptr_end); if (dres != DW_DLV_OK) { free(format_values); format_values = 0; return dres; } } } dres = read_uword_de(&line_ptr,&directories_count, dbg,err,line_ptr_end); if (dres != DW_DLV_OK) { free(format_values); format_values = 0; return dres; } line_context->lc_include_directories = malloc(sizeof(Dwarf_Small *) * directories_count); if (line_context->lc_include_directories == NULL) { free(format_values); format_values = 0; _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } if (directory_format_count == 0 && directories_count > 0) { free(format_values); format_values = 0; _dwarf_error_string(dbg, err, DW_DLE_DIRECTORY_FORMAT_COUNT_VS_DIRECTORIES_MISMATCH, "DW_DLE_DIRECTORY_FORMAT_COUNT_VS_DIRECTORIES_MISMATCH" ": format count is zero yet directories count > 0"); return (DW_DLV_ERROR); } memset(line_context->lc_include_directories, 0, sizeof(Dwarf_Small *) * directories_count); for(i = 0; i < directories_count; i++) { for (j = 0; j < directory_format_count; j++) { switch (format_values[j].up_first) { case DW_LNCT_path: { char *inc_dir_ptr = 0; res = _dwarf_decode_line_string_form(dbg, format_values[j].up_second, local_length_size, &line_ptr, line_ptr_end, &inc_dir_ptr, err); if (res != DW_DLV_OK) { free(format_values); format_values = 0; return res; } line_context->lc_include_directories[i] = (unsigned char *)inc_dir_ptr; break; } default: free(format_values); format_values = 0; _dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR); return (DW_DLV_ERROR); } } if (line_ptr > line_ptr_end) { free(format_values); format_values = 0; _dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR); return (DW_DLV_ERROR); } } line_context->lc_directory_format_values = format_values; format_values = 0; line_context->lc_include_directories_count = directories_count; } if (version == DW_LINE_VERSION5 || version == EXPERIMENTAL_LINE_TABLES_VERSION) { /* DWARF 5. file names.*/ struct Dwarf_Unsigned_Pair_s * filename_entry_pairs = 0; Dwarf_Unsigned filename_format_count = 0; Dwarf_Unsigned files_count = 0; Dwarf_Unsigned i = 0; Dwarf_Unsigned j = 0; int dres = 0; if (line_ptr >= line_ptr_end) { _dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR); return (DW_DLV_ERROR); } filename_format_count = *(unsigned char *) line_ptr; line_context->lc_file_name_format_count = filename_format_count; line_ptr = line_ptr + sizeof(Dwarf_Small); filename_entry_pairs = malloc( sizeof(struct Dwarf_Unsigned_Pair_s) * filename_format_count); if (!filename_entry_pairs) { _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); return DW_DLV_ERROR; } for (i = 0; i < filename_format_count; i++) { dres=read_uword_de(&line_ptr,&filename_entry_pairs[i].up_first, dbg,err,line_ptr_end); if (dres != DW_DLV_OK) { free(filename_entry_pairs); return dres; } dres=read_uword_de(&line_ptr,&filename_entry_pairs[i].up_second, dbg,err,line_ptr_end); if (dres != DW_DLV_OK) { free(filename_entry_pairs); return dres; } } /* DECODE_LEB128_UWORD_CK(line_ptr, files_count, dbg,err,line_ptr_end); */ dres=read_uword_de(&line_ptr,&files_count, dbg,err,line_ptr_end); if (dres != DW_DLV_OK) { free(filename_entry_pairs); return dres; } for (i = 0; i < files_count; i++) { Dwarf_File_Entry curline = 0; curline = (Dwarf_File_Entry) malloc(sizeof(struct Dwarf_File_Entry_s)); if (curline == NULL) { free(filename_entry_pairs); _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } memset(curline,0,sizeof(*curline)); _dwarf_add_to_files_list(line_context,curline); for(j = 0; j < filename_format_count; j++) { Dwarf_Unsigned dirindex = 0; switch (filename_entry_pairs[j].up_first) { case DW_LNCT_path: res = _dwarf_decode_line_string_form(dbg, filename_entry_pairs[j].up_second, local_length_size, &line_ptr, line_ptr_end, (char **)&curline->fi_file_name, err); if (res != DW_DLV_OK) { free(filename_entry_pairs); return res; } break; case DW_LNCT_directory_index: res = _dwarf_decode_line_udata_form(dbg, filename_entry_pairs[j].up_second, &line_ptr, &dirindex, line_ptr_end, err); if (res != DW_DLV_OK) { free(filename_entry_pairs); return res; } curline->fi_dir_index = dirindex; curline->fi_dir_index_present = TRUE; break; case DW_LNCT_timestamp: res = _dwarf_decode_line_udata_form(dbg, filename_entry_pairs[j].up_second, &line_ptr, &curline->fi_time_last_mod, line_ptr_end, err); if (res != DW_DLV_OK) { free(filename_entry_pairs); return res; } curline->fi_time_last_mod_present = TRUE; break; case DW_LNCT_size: res = _dwarf_decode_line_udata_form(dbg, filename_entry_pairs[j].up_second, &line_ptr, &curline->fi_file_length, line_ptr_end, err); if (res != DW_DLV_OK) { free(filename_entry_pairs); return res; } curline->fi_file_length_present = TRUE; break; case DW_LNCT_MD5: { /* form DW_FORM_data16 */ if (filename_entry_pairs[j].up_second != DW_FORM_data16) { free(filename_entry_pairs); _dwarf_error(dbg, err,DW_DLE_LNCT_MD5_WRONG_FORM); return DW_DLV_ERROR; } res = _dwarf_extract_data16(dbg, line_ptr, line_ptr, line_ptr_end, &curline->fi_md5_value, err); if (res != DW_DLV_OK) { free(filename_entry_pairs); return res; } curline->fi_md5_present = TRUE; line_ptr = line_ptr + sizeof(curline->fi_md5_value); } break; default: free(filename_entry_pairs); _dwarf_error(dbg, err,DW_DLE_LINE_NUMBER_HEADER_ERROR); return (DW_DLV_ERROR); } if (line_ptr > line_ptr_end) { free(filename_entry_pairs); _dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR); return (DW_DLV_ERROR); } } } line_context->lc_file_format_values = filename_entry_pairs; filename_entry_pairs = 0; } /* For two-level line tables, read the subprograms table. */ if (version == EXPERIMENTAL_LINE_TABLES_VERSION) { Dwarf_Unsigned subprog_format_count = 0; Dwarf_Unsigned *subprog_entry_types = 0; Dwarf_Unsigned *subprog_entry_forms = 0; Dwarf_Unsigned subprogs_count = 0; Dwarf_Unsigned i = 0; Dwarf_Unsigned j = 0; int dres = 0; if (line_ptr > line_ptr_end) { _dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR); return (DW_DLV_ERROR); } subprog_format_count = *(unsigned char *) line_ptr; line_ptr = line_ptr + sizeof(Dwarf_Small); subprog_entry_types = malloc(sizeof(Dwarf_Unsigned) * subprog_format_count); if (subprog_entry_types == NULL) { _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } subprog_entry_forms = malloc(sizeof(Dwarf_Unsigned) * subprog_format_count); if (subprog_entry_forms == NULL) { free(subprog_entry_types); _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } for (i = 0; i < subprog_format_count; i++) { dres=read_uword_de(&line_ptr,subprog_entry_types+i, dbg,err,line_ptr_end); if (dres != DW_DLV_OK) { free(subprog_entry_types); free(subprog_entry_forms); return dres; } /* DECODE_LEB128_UWORD_CK(line_ptr, subprog_entry_types[i], dbg,err,line_ptr_end); */ dres=read_uword_de(&line_ptr,subprog_entry_forms+i, dbg,err,line_ptr_end); if (dres != DW_DLV_OK) { free(subprog_entry_types); free(subprog_entry_forms); return dres; } /* DECODE_LEB128_UWORD_CK(line_ptr, subprog_entry_forms[i], dbg,err,line_ptr_end); */ } /* DECODE_LEB128_UWORD_CK(line_ptr, subprogs_count, dbg,err,line_ptr_end); */ dres=read_uword_de(&line_ptr,&subprogs_count, dbg,err,line_ptr_end); if (dres != DW_DLV_OK) { free(subprog_entry_types); free(subprog_entry_forms); return dres; } line_context->lc_subprogs = malloc(sizeof(struct Dwarf_Subprog_Entry_s) * subprogs_count); if (line_context->lc_subprogs == NULL) { free(subprog_entry_types); free(subprog_entry_forms); _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } memset(line_context->lc_subprogs, 0, sizeof(struct Dwarf_Subprog_Entry_s) * subprogs_count); for (i = 0; i < subprogs_count; i++) { struct Dwarf_Subprog_Entry_s *curline = line_context->lc_subprogs + i; for (j = 0; j < subprog_format_count; j++) { switch (subprog_entry_types[j]) { case DW_LNCT_GNU_subprogram_name: res = _dwarf_decode_line_string_form(dbg, subprog_entry_forms[j], local_length_size, &line_ptr, line_ptr_end, (char **)&curline->ds_subprog_name, err); if (res != DW_DLV_OK) { free(subprog_entry_types); free(subprog_entry_forms); return res; } break; case DW_LNCT_GNU_decl_file: res = _dwarf_decode_line_udata_form(dbg, subprog_entry_forms[j], &line_ptr, &curline->ds_decl_file, line_ptr_end, err); if (res != DW_DLV_OK) { free(subprog_entry_forms); free(subprog_entry_types); return res; } break; case DW_LNCT_GNU_decl_line: res = _dwarf_decode_line_udata_form(dbg, subprog_entry_forms[j], &line_ptr, &curline->ds_decl_line, line_ptr_end, err); if (res != DW_DLV_OK) { free(subprog_entry_forms); free(subprog_entry_types); return res; } break; default: free(subprog_entry_forms); free(subprog_entry_types); _dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR); return (DW_DLV_ERROR); } if (line_ptr >= line_ptr_end) { free(subprog_entry_types); free(subprog_entry_forms); _dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR); return (DW_DLV_ERROR); } } } free(subprog_entry_types); free(subprog_entry_forms); line_context->lc_subprogs_count = subprogs_count; } if (version == EXPERIMENTAL_LINE_TABLES_VERSION) { lp_begin = line_context->lc_line_prologue_start + line_context->lc_logicals_table_offset; } else { lp_begin = line_context->lc_line_prologue_start + line_context->lc_prologue_length; } if(line_ptr > line_ptr_end) { _dwarf_error(dbg, err, DW_DLE_LINE_OFFSET_BAD); return DW_DLV_ERROR; } 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 line_context->lc_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; } line_context->lc_line_ptr_start = lp_begin; if (line_context->lc_actuals_table_offset) { /* This means two tables. */ line_context->lc_table_count = 2; } else { if (line_context->lc_line_ptr_end > lp_begin) { line_context->lc_table_count = 1; } else { line_context->lc_table_count = 0; } } *updated_data_start_out = lp_begin; return DW_DLV_OK; } /* Read one line table program. For two-level line tables, this function is called once for each table. */ static int read_line_table_program(Dwarf_Debug dbg, Dwarf_Small *line_ptr, Dwarf_Small *line_ptr_end, UNUSEDARG Dwarf_Small *orig_line_ptr, Dwarf_Small *section_start, Dwarf_Line_Context line_context, Dwarf_Half address_size, Dwarf_Bool doaddrs, /* Only true if SGI IRIX rqs calling. */ Dwarf_Bool dolines, Dwarf_Bool is_single_table, Dwarf_Bool is_actuals_table, Dwarf_Error *error, UNUSEDARG int *err_count_out) { Dwarf_Unsigned i = 0; Dwarf_File_Entry cur_file_entry = 0; Dwarf_Line *logicals = line_context->lc_linebuf_logicals; Dwarf_Unsigned logicals_count = line_context->lc_linecount_logicals; struct Dwarf_Line_Registers_s regs; /* 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_Unsigned leb128_num = 0; Dwarf_Signed 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_Unsigned line_count = 0; /* This is the length of an extended opcode instr. */ Dwarf_Unsigned instr_length = 0; /* 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; /* Mark a line record as being DW_LNS_set_address */ Dwarf_Bool is_addr_set = false; /* Initialize the one state machine variable that depends on the prefix. */ _dwarf_set_line_table_regs_default_values(®s, line_context->lc_version_number, line_context->lc_default_is_stmt); /* Start of statement program. */ while (line_ptr < line_ptr_end) { int type = 0; Dwarf_Small opcode = 0; #ifdef PRINTING_DETAILS { dwarfstring m9a; dwarfstring_constructor(&m9a); dwarfstring_append_printf_u(&m9a, " [0x%06" DW_PR_DSx "] ", (line_ptr - section_start)); _dwarf_printf(dbg,dwarfstring_string(&m9a)); dwarfstring_destructor(&m9a); } #endif /* PRINTING_DETAILS */ opcode = *(Dwarf_Small *) line_ptr; line_ptr++; /* 'type' is the output */ WHAT_IS_OPCODE(type, opcode, line_context->lc_opcode_base, line_context->lc_opcode_length_table, line_ptr, line_context->lc_std_op_count); if (type == LOP_DISCARD) { int oc = 0; int opcnt = line_context->lc_opcode_length_table[opcode]; #ifdef PRINTING_DETAILS { dwarfstring m9b; dwarfstring_constructor(&m9b); dwarfstring_append_printf_i(&m9b, "*** DWARF CHECK: DISCARD standard opcode %d ", opcode); dwarfstring_append_printf_i(&m9b, "with %d operands: not understood.", opcnt); _dwarf_printf(dbg,dwarfstring_string(&m9b)); *err_count_out += 1; dwarfstring_destructor(&m9b); } #endif /* PRINTING_DETAILS */ for (oc = 0; oc < opcnt; oc++) { int ocres = 0; /* Read and discard operands we don't understand. arbitrary choice of unsigned read. signed read would work as well. */ UNUSEDARG Dwarf_Unsigned utmp2 = 0; /* DECODE_LEB128_UWORD_CK(line_ptr, utmp2, dbg,error,line_ptr_end); */ ocres = read_uword_de( &line_ptr,&utmp2, dbg,error,line_ptr_end); if (ocres == DW_DLV_ERROR) { _dwarf_free_chain_entries(dbg,head_chain, line_count); if(curr_line) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); curr_line = 0; } return DW_DLV_ERROR; } #ifdef PRINTING_DETAILS { dwarfstring m9e; dwarfstring_constructor(&m9e); dwarfstring_append_printf_u(&m9e, " %" DW_PR_DUu, utmp2); dwarfstring_append_printf_u(&m9e, " (0x%" DW_PR_XZEROS DW_PR_DUx ")", utmp2); _dwarf_printf(dbg,dwarfstring_string(&m9e)); dwarfstring_destructor(&m9e); } #endif /* PRINTING_DETAILS */ } #ifdef PRINTING_DETAILS _dwarf_printf(dbg,"***\n"); #endif /* PRINTING_DETAILS */ } 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) */ #ifdef PRINTING_DETAILS unsigned origop = opcode; #endif /* PRINTING_DETAILS */ Dwarf_Unsigned operation_advance = 0; opcode = opcode - line_context->lc_opcode_base; operation_advance = (opcode / line_context->lc_line_range); if (line_context->lc_maximum_ops_per_instruction < 2) { regs.lr_address = regs.lr_address + (operation_advance * line_context->lc_minimum_instruction_length); } else { regs.lr_address = regs.lr_address + (line_context->lc_minimum_instruction_length * ((regs.lr_op_index + operation_advance)/ line_context->lc_maximum_ops_per_instruction)); regs.lr_op_index = (regs.lr_op_index +operation_advance)% line_context->lc_maximum_ops_per_instruction; } regs.lr_line = regs.lr_line + line_context->lc_line_base + opcode % line_context->lc_line_range; if ((Dwarf_Signed)regs.lr_line < 0) { /* Something is badly wrong */ dwarfstring m; dwarfstring_constructor(&m); dwarfstring_append_printf_i(&m, "\nERROR: DW_DLE_LINE_TABLE_LINENO_ERROR " "The line number computes as %d " "and negative line numbers " "are not correct.",(Dwarf_Signed)regs.lr_line); _dwarf_error_string(dbg, error, DW_DLE_LINE_TABLE_LINENO_ERROR, dwarfstring_string(&m)); dwarfstring_destructor(&m); regs.lr_line = 0; return DW_DLV_ERROR; } #ifdef PRINTING_DETAILS { dwarfstring ma; dwarfstring mb; dwarfstring_constructor(&ma); dwarfstring_constructor(&mb); dwarfstring_append_printf_u(&mb,"Specialop %3u", origop); _dwarf_printf(dbg,dwarfstring_string(&ma)); dwarfstring_destructor(&ma); print_line_detail(dbg,dwarfstring_string(&mb), opcode,line_count+1, ®s,is_single_table, is_actuals_table); dwarfstring_destructor(&mb); dwarfstring_destructor(&ma); } #endif /* PRINTING_DETAILS */ if (dolines) { curr_line = (Dwarf_Line) _dwarf_get_alloc(dbg, DW_DLA_LINE, 1); if (curr_line == NULL) { _dwarf_free_chain_entries(dbg,head_chain,line_count); _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } /* Mark a line record as being DW_LNS_set_address */ curr_line->li_addr_line.li_l_data.li_is_addr_set = is_addr_set; is_addr_set = false; curr_line->li_address = regs.lr_address; curr_line->li_addr_line.li_l_data.li_file = (Dwarf_Signed) regs.lr_file; curr_line->li_addr_line.li_l_data.li_line = (Dwarf_Signed) regs.lr_line; curr_line->li_addr_line.li_l_data.li_column = (Dwarf_Half) regs.lr_column; curr_line->li_addr_line.li_l_data.li_is_stmt = regs.lr_is_stmt; curr_line->li_addr_line.li_l_data.li_basic_block = regs.lr_basic_block; curr_line->li_addr_line.li_l_data.li_end_sequence = curr_line->li_addr_line.li_l_data. li_epilogue_begin = regs.lr_epilogue_begin; curr_line->li_addr_line.li_l_data.li_prologue_end = regs.lr_prologue_end; curr_line->li_addr_line.li_l_data.li_isa = regs.lr_isa; curr_line->li_addr_line.li_l_data.li_discriminator = regs.lr_discriminator; curr_line->li_addr_line.li_l_data.li_call_context = regs.lr_call_context; curr_line->li_addr_line.li_l_data.li_subprogram = regs.lr_subprogram; curr_line->li_context = line_context; curr_line->li_is_actuals_table = is_actuals_table; line_count++; chain_line = (Dwarf_Chain) _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); if (chain_line == NULL) { if(curr_line) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); } _dwarf_free_chain_entries(dbg,head_chain,line_count); _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } chain_line->ch_itemtype = DW_DLA_LINE; chain_line->ch_item = curr_line; _dwarf_update_chain_list(chain_line,&head_chain,&curr_chain); curr_line = 0; } regs.lr_basic_block = false; regs.lr_prologue_end = false; regs.lr_epilogue_begin = false; regs.lr_discriminator = 0; #ifdef PRINTING_DETAILS #endif /* PRINTING_DETAILS */ } else if (type == LOP_STANDARD) { #ifdef PRINTING_DETAILS dwarfstring mb; #endif /* PRINTING_DETAILS */ switch (opcode) { case DW_LNS_copy:{ #ifdef PRINTING_DETAILS print_line_detail(dbg,"DW_LNS_copy", opcode,line_count+1, ®s,is_single_table, is_actuals_table); #endif /* PRINTING_DETAILS */ if (dolines) { curr_line = (Dwarf_Line) _dwarf_get_alloc(dbg, DW_DLA_LINE, 1); if (curr_line == NULL) { _dwarf_free_chain_entries(dbg,head_chain,line_count); _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } /* Mark a line record as DW_LNS_set_address */ curr_line->li_addr_line.li_l_data.li_is_addr_set = is_addr_set; is_addr_set = false; curr_line->li_address = regs.lr_address; curr_line->li_addr_line.li_l_data.li_file = (Dwarf_Signed) regs.lr_file; curr_line->li_addr_line.li_l_data.li_line = (Dwarf_Signed) regs.lr_line; curr_line->li_addr_line.li_l_data.li_column = (Dwarf_Half) regs.lr_column; curr_line->li_addr_line.li_l_data.li_is_stmt = regs.lr_is_stmt; curr_line->li_addr_line.li_l_data. li_basic_block = regs.lr_basic_block; curr_line->li_addr_line.li_l_data. li_end_sequence = regs.lr_end_sequence; curr_line->li_context = line_context; curr_line->li_is_actuals_table = is_actuals_table; curr_line->li_addr_line.li_l_data. li_epilogue_begin = regs.lr_epilogue_begin; curr_line->li_addr_line.li_l_data. li_prologue_end = regs.lr_prologue_end; curr_line->li_addr_line.li_l_data.li_isa = regs.lr_isa; curr_line->li_addr_line.li_l_data.li_discriminator = regs.lr_discriminator; curr_line->li_addr_line.li_l_data.li_call_context = regs.lr_call_context; curr_line->li_addr_line.li_l_data.li_subprogram = regs.lr_subprogram; line_count++; chain_line = (Dwarf_Chain) _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); if (chain_line == NULL) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); _dwarf_free_chain_entries(dbg,head_chain, line_count); _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } chain_line->ch_itemtype = DW_DLA_LINE; chain_line->ch_item = curr_line; _dwarf_update_chain_list(chain_line,&head_chain, &curr_chain); curr_line = 0; } regs.lr_basic_block = false; regs.lr_prologue_end = false; regs.lr_epilogue_begin = false; regs.lr_discriminator = 0; } break; case DW_LNS_advance_pc:{ Dwarf_Unsigned utmp2 = 0; int advres = 0; /* DECODE_LEB128_UWORD_CK(line_ptr, utmp2, dbg,error,line_ptr_end); */ advres = read_uword_de( &line_ptr,&utmp2, dbg,error,line_ptr_end); if (advres == DW_DLV_ERROR) { _dwarf_free_chain_entries(dbg,head_chain, line_count); if(curr_line) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); } return DW_DLV_ERROR; } #ifdef PRINTING_DETAILS dwarfstring_constructor(&mb); dwarfstring_append_printf_i(&mb, "DW_LNS_advance_pc val %" DW_PR_DSd, utmp2); dwarfstring_append_printf_u(&mb, " 0x%" DW_PR_XZEROS DW_PR_DUx "\n", utmp2); _dwarf_printf(dbg,dwarfstring_string(&mb)); dwarfstring_destructor(&mb); #endif /* PRINTING_DETAILS */ leb128_num = utmp2; regs.lr_address = regs.lr_address + line_context->lc_minimum_instruction_length * leb128_num; } break; case DW_LNS_advance_line:{ Dwarf_Signed stmp = 0; int alres = 0; /* DECODE_LEB128_SWORD_CK(line_ptr, stmp, dbg,error,line_ptr_end); */ alres = read_sword_de( &line_ptr,&stmp, dbg,error,line_ptr_end); if (alres == DW_DLV_ERROR) { _dwarf_free_chain_entries(dbg,head_chain, line_count); if(curr_line) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); } return DW_DLV_ERROR; } advance_line = (Dwarf_Signed) stmp; #ifdef PRINTING_DETAILS dwarfstring_constructor(&mb); dwarfstring_append_printf_i(&mb, "DW_LNS_advance_line val %" DW_PR_DSd, advance_line); dwarfstring_append_printf_u(&mb, " 0x%" DW_PR_XZEROS DW_PR_DSx "\n", advance_line); _dwarf_printf(dbg,dwarfstring_string(&mb)); dwarfstring_destructor(&mb); #endif /* PRINTING_DETAILS */ regs.lr_line = regs.lr_line + advance_line; if ((Dwarf_Signed)regs.lr_line < 0) { dwarfstring m; dwarfstring_constructor(&m); dwarfstring_append_printf_i(&m, "\nERROR: DW_DLE_LINE_TABLE_LINENO_ERROR" " The line number is %d " "and negative line numbers after " "DW_LNS_ADVANCE_LINE ", (Dwarf_Signed)regs.lr_line); dwarfstring_append_printf_i(&m, " of %d " "are not correct.",stmp); _dwarf_error_string(dbg, error, DW_DLE_LINE_TABLE_LINENO_ERROR, dwarfstring_string(&m)); dwarfstring_destructor(&m); regs.lr_line = 0; if(curr_line) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); } _dwarf_free_chain_entries(dbg,head_chain,line_count); return DW_DLV_ERROR; } } break; case DW_LNS_set_file:{ Dwarf_Unsigned utmp2 = 0; int sfres = 0; /* DECODE_LEB128_UWORD_CK(line_ptr, utmp2, dbg,error,line_ptr_end); */ sfres = read_uword_de( &line_ptr,&utmp2, dbg,error,line_ptr_end); if (sfres == DW_DLV_ERROR) { _dwarf_free_chain_entries(dbg,head_chain, line_count); if(curr_line) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); } return DW_DLV_ERROR; } regs.lr_file = utmp2; #ifdef PRINTING_DETAILS dwarfstring_constructor(&mb); dwarfstring_append_printf_i(&mb, "DW_LNS_set_file %ld\n", regs.lr_file); _dwarf_printf(dbg,dwarfstring_string(&mb)); dwarfstring_destructor(&mb); #endif /* PRINTING_DETAILS */ } break; case DW_LNS_set_column:{ Dwarf_Unsigned utmp2 = 0; int scres = 0; /* DECODE_LEB128_UWORD_CK(line_ptr, utmp2, dbg,error,line_ptr_end); */ scres = read_uword_de( &line_ptr,&utmp2, dbg,error,line_ptr_end); if (scres == DW_DLV_ERROR) { _dwarf_free_chain_entries(dbg,head_chain, line_count); if(curr_line) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); } return DW_DLV_ERROR; } regs.lr_column = utmp2; #ifdef PRINTING_DETAILS dwarfstring_constructor(&mb); dwarfstring_append_printf_i(&mb, "DW_LNS_set_column val %" DW_PR_DSd , regs.lr_column); dwarfstring_append_printf_u(&mb, " 0x%" DW_PR_XZEROS DW_PR_DSx "\n", regs.lr_column); _dwarf_printf(dbg,dwarfstring_string(&mb)); dwarfstring_destructor(&mb); #endif /* PRINTING_DETAILS */ } break; case DW_LNS_negate_stmt:{ regs.lr_is_stmt = !regs.lr_is_stmt; #ifdef PRINTING_DETAILS _dwarf_printf(dbg, "DW_LNS_negate_stmt\n"); #endif /* PRINTING_DETAILS */ } break; case DW_LNS_set_basic_block:{ regs.lr_basic_block = true; #ifdef PRINTING_DETAILS _dwarf_printf(dbg, "DW_LNS_set_basic_block\n"); #endif /* PRINTING_DETAILS */ } break; case DW_LNS_const_add_pc:{ opcode = MAX_LINE_OP_CODE - line_context->lc_opcode_base; if (line_context->lc_maximum_ops_per_instruction < 2) { Dwarf_Unsigned operation_advance = (opcode / line_context->lc_line_range); regs.lr_address = regs.lr_address + line_context->lc_minimum_instruction_length * operation_advance; } else { Dwarf_Unsigned operation_advance = (opcode / line_context->lc_line_range); regs.lr_address = regs.lr_address + line_context->lc_minimum_instruction_length * ((regs.lr_op_index + operation_advance)/ line_context->lc_maximum_ops_per_instruction); regs.lr_op_index = (regs.lr_op_index +operation_advance)% line_context->lc_maximum_ops_per_instruction; } #ifdef PRINTING_DETAILS dwarfstring_constructor(&mb); dwarfstring_append_printf_u(&mb, "DW_LNS_const_add_pc new address 0x%" DW_PR_XZEROS DW_PR_DSx "\n", regs.lr_address); _dwarf_printf(dbg,dwarfstring_string(&mb)); dwarfstring_destructor(&mb); #endif /* PRINTING_DETAILS */ } break; case DW_LNS_fixed_advance_pc:{ Dwarf_Unsigned fpc = 0; int apres = 0; /*READ_UNALIGNED_CK(dbg, fixed_advance_pc, Dwarf_Half, line_ptr, DWARF_HALF_SIZE,error,line_ptr_end); */ apres = _dwarf_read_unaligned_ck_wrapper(dbg, &fpc,line_ptr,DWARF_HALF_SIZE,line_ptr_end, error); fixed_advance_pc = fpc; if (apres == DW_DLV_ERROR) { if(curr_line) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); } _dwarf_free_chain_entries(dbg,head_chain, line_count); return apres; } line_ptr += DWARF_HALF_SIZE; if (line_ptr > line_ptr_end) { dwarfstring g; ptrdiff_t d = 0; d = line_ptr - section_start; dwarfstring_constructor(&g); dwarfstring_append_printf_u(&g, "DW_DLE_LINE_TABLE_BAD reading " "DW_LNS_fixed_advance_pc we are " "off this line table at section " "offset. 0x%x .", d); _dwarf_error_string(dbg, error, DW_DLE_LINE_TABLE_BAD, dwarfstring_string(&g)); dwarfstring_destructor(&g); if(curr_line) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); } _dwarf_free_chain_entries(dbg,head_chain,line_count); return DW_DLV_ERROR; } regs.lr_address = regs.lr_address + fixed_advance_pc; regs.lr_op_index = 0; #ifdef PRINTING_DETAILS dwarfstring_constructor(&mb); dwarfstring_append_printf_i(&mb, "DW_LNS_fixed_advance_pc val %" DW_PR_DSd, fixed_advance_pc); dwarfstring_append_printf_u(&mb, " 0x%" DW_PR_XZEROS DW_PR_DSx, fixed_advance_pc); dwarfstring_append_printf_u(&mb, " new address 0x%" DW_PR_XZEROS DW_PR_DSx "\n", regs.lr_address); _dwarf_printf(dbg, dwarfstring_string(&mb)); dwarfstring_destructor(&mb); #endif /* PRINTING_DETAILS */ } break; /* New in DWARF3 */ case DW_LNS_set_prologue_end:{ regs.lr_prologue_end = true; } break; /* New in DWARF3 */ case DW_LNS_set_epilogue_begin:{ regs.lr_epilogue_begin = true; #ifdef PRINTING_DETAILS _dwarf_printf(dbg, "DW_LNS_set_prologue_end set true.\n"); #endif /* PRINTING_DETAILS */ } break; /* New in DWARF3 */ case DW_LNS_set_isa:{ Dwarf_Unsigned utmp2 = 0; int sires = 0; /* DECODE_LEB128_UWORD_CK(line_ptr, utmp2, dbg,error,line_ptr_end); */ sires = read_uword_de( &line_ptr,&utmp2, dbg,error,line_ptr_end); if (sires == DW_DLV_ERROR) { _dwarf_free_chain_entries(dbg,head_chain, line_count); if(curr_line) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); } return DW_DLV_ERROR; } regs.lr_isa = utmp2; #ifdef PRINTING_DETAILS dwarfstring_constructor(&mb); dwarfstring_append_printf_u(&mb, "DW_LNS_set_isa new value 0x%" DW_PR_XZEROS DW_PR_DUx ".\n", utmp2); _dwarf_printf(dbg,dwarfstring_string(&mb)); dwarfstring_destructor(&mb); #endif /* PRINTING_DETAILS */ if (regs.lr_isa != utmp2) { /* The value of the isa did not fit in our local so we record it wrong. declare an error. */ if(curr_line) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); } _dwarf_free_chain_entries(dbg,head_chain,line_count); _dwarf_error(dbg, error, DW_DLE_LINE_NUM_OPERANDS_BAD); return (DW_DLV_ERROR); } } break; /* Experimental two-level line tables */ /* DW_LNS_set_address_from_logical and DW_LNS_set_subprogram share the same opcode. Disambiguate by checking is_actuals_table. */ case DW_LNS_set_subprogram: if (is_actuals_table) { /* DW_LNS_set_address_from_logical */ Dwarf_Signed stmp = 0; int atres = 0; /* DECODE_LEB128_SWORD_CK(line_ptr, stmp, dbg,error,line_ptr_end); */ atres = read_sword_de( &line_ptr,&stmp, dbg,error,line_ptr_end); if (atres == DW_DLV_ERROR) { _dwarf_free_chain_entries(dbg,head_chain, line_count); if(curr_line) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); } return DW_DLV_ERROR; } advance_line = (Dwarf_Signed) stmp; regs.lr_line = regs.lr_line + advance_line; if ((Dwarf_Signed)regs.lr_line < 0) { dwarfstring m; dwarfstring_constructor(&m); dwarfstring_append_printf_i(&m, "\nERROR: DW_DLE_LINE_TABLE_LINENO_ERROR" " The line number is %d " "and negative line numbers after " "DW_LNS_set_subprogram ", (Dwarf_Signed)regs.lr_line); dwarfstring_append_printf_i(&m, " of %d applied " "are not correct.",stmp); _dwarf_error_string(dbg, error, DW_DLE_LINE_TABLE_LINENO_ERROR, dwarfstring_string(&m)); dwarfstring_destructor(&m); regs.lr_line = 0; _dwarf_free_chain_entries(dbg,head_chain,line_count); if(curr_line) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); } return DW_DLV_ERROR; } if (regs.lr_line >= 1 && regs.lr_line - 1 < logicals_count) { regs.lr_address = logicals[regs.lr_line - 1]->li_address; regs.lr_op_index = 0; #ifdef PRINTING_DETAILS /* block 1 print */ dwarfstring_constructor(&mb); dwarfstring_append_printf_i(&mb, "DW_LNS_set_address_from" "_logical " "%" DW_PR_DSd, stmp); dwarfstring_append_printf_u(&mb, " 0x%" DW_PR_XZEROS DW_PR_DSx, stmp); dwarfstring_append_printf_u(&mb, " newaddr=" " 0x%" DW_PR_XZEROS DW_PR_DUx ".\n", regs.lr_address); _dwarf_printf(dbg, dwarfstring_string(&mb)); dwarfstring_destructor(&mb); #endif /* PRINTING_DETAILS */ } else { #ifdef PRINTING_DETAILS /* block 2 print */ dwarfstring_constructor(&mb); dwarfstring_append_printf_i(&mb, "DW_LNS_set_address_from_logical line" " is %" DW_PR_DSd , regs.lr_line); dwarfstring_append_printf_u(&mb, " 0x%" DW_PR_XZEROS DW_PR_DSx ".\n", regs.lr_line); _dwarf_printf(dbg, dwarfstring_string(&mb)); dwarfstring_destructor(&mb); #endif /* PRINTING_DETAILS */ } } else { /* DW_LNS_set_subprogram, building logicals table. */ Dwarf_Unsigned utmp2 = 0; int spres = 0; regs.lr_call_context = 0; /* DECODE_LEB128_UWORD_CK(line_ptr, utmp2, dbg,error,line_ptr_end); */ spres = read_uword_de( &line_ptr,&utmp2, dbg,error,line_ptr_end); if (spres == DW_DLV_ERROR) { _dwarf_free_chain_entries(dbg,head_chain, line_count); if(curr_line) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); } return DW_DLV_ERROR; } regs.lr_subprogram = utmp2; #ifdef PRINTING_DETAILS /* block 3 print */ dwarfstring_constructor(&mb); dwarfstring_append_printf_i(&mb, "DW_LNS_set_subprogram " "%" DW_PR_DSd, utmp2); dwarfstring_append_printf_u(&mb, " 0x%" DW_PR_XZEROS DW_PR_DSx "\n", utmp2); _dwarf_printf(dbg, dwarfstring_string(&mb)); #endif /* PRINTING_DETAILS */ } break; /* Experimental two-level line tables */ case DW_LNS_inlined_call: { Dwarf_Signed stmp = 0; Dwarf_Unsigned ilcuw = 0; int icres = 0; /* DECODE_LEB128_SWORD_CK(line_ptr, stmp, dbg,error,line_ptr_end); */ icres = read_sword_de( &line_ptr,&stmp, dbg,error,line_ptr_end); if (icres == DW_DLV_ERROR) { _dwarf_free_chain_entries(dbg,head_chain, line_count); if(curr_line) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); } return DW_DLV_ERROR; } regs.lr_call_context = line_count + stmp; /* DECODE_LEB128_UWORD_CK(line_ptr, regs.lr_subprogram, dbg,error,line_ptr_end); */ icres = read_uword_de(&line_ptr,&ilcuw, dbg,error,line_ptr_end); regs.lr_subprogram = ilcuw; if (icres == DW_DLV_ERROR) { _dwarf_free_chain_entries(dbg,head_chain, line_count); if(curr_line) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); } return DW_DLV_ERROR; } #ifdef PRINTING_DETAILS dwarfstring_constructor(&mb); dwarfstring_append_printf_i(&mb, "DW_LNS_inlined_call " "%" DW_PR_DSd ,stmp); dwarfstring_append_printf_u(&mb, " (0x%" DW_PR_XZEROS DW_PR_DSx "),", stmp); dwarfstring_append_printf_i(&mb, "%" DW_PR_DSd, regs.lr_subprogram); dwarfstring_append_printf_u(&mb, " (0x%" DW_PR_XZEROS DW_PR_DSx ")", regs.lr_subprogram); dwarfstring_append_printf_i(&mb, " callcontext=" "%" DW_PR_DSd , regs.lr_call_context); dwarfstring_append_printf_u(&mb, " (0x%" DW_PR_XZEROS DW_PR_DSx ")\n", regs.lr_call_context); _dwarf_printf(dbg, dwarfstring_string(&mb)); dwarfstring_destructor(&mb); #endif /* PRINTING_DETAILS */ } break; /* Experimental two-level line tables */ case DW_LNS_pop_context: { Dwarf_Unsigned logical_num = regs.lr_call_context; Dwarf_Chain logical_chain = head_chain; Dwarf_Line logical_line = 0; if (logical_num > 0 && logical_num <= line_count) { for (i = 1; i < logical_num; i++) { logical_chain = logical_chain->ch_next; } logical_line = (Dwarf_Line) logical_chain->ch_item; regs.lr_file = logical_line->li_addr_line.li_l_data.li_file; regs.lr_line = logical_line->li_addr_line.li_l_data.li_line; regs.lr_column = logical_line->li_addr_line.li_l_data.li_column; regs.lr_discriminator = logical_line->li_addr_line.li_l_data.li_discriminator; regs.lr_is_stmt = logical_line->li_addr_line.li_l_data.li_is_stmt; regs.lr_call_context = logical_line->li_addr_line.li_l_data.li_call_context; regs.lr_subprogram = logical_line->li_addr_line.li_l_data.li_subprogram; #ifdef PRINTING_DETAILS { dwarfstring pcon; dwarfstring_constructor(&pcon); dwarfstring_append_printf_u(&pcon, "DW_LNS_pop_context set" " from logical " "%" DW_PR_DUu ,logical_num); dwarfstring_append_printf_u(&pcon, " (0x%" DW_PR_XZEROS DW_PR_DUx ")\n", logical_num); _dwarf_printf(dbg, dwarfstring_string(&pcon)); dwarfstring_destructor(&pcon); } } else { dwarfstring pcon; dwarfstring_constructor(&pcon); dwarfstring_append_printf_u(&pcon, "DW_LNS_pop_context does nothing, logical" "%" DW_PR_DUu , logical_num); dwarfstring_append_printf_u(&pcon, " (0x%" DW_PR_XZEROS DW_PR_DUx ")\n", logical_num); _dwarf_printf(dbg, dwarfstring_string(&pcon)); dwarfstring_destructor(&pcon); #endif /* PRINTING_DETAILS */ } } break; } /* End switch (opcode) */ } else if (type == LOP_EXTENDED) { Dwarf_Unsigned utmp3 = 0; Dwarf_Small ext_opcode = 0; int leres = 0; /* DECODE_LEB128_UWORD_CK(line_ptr, utmp3, dbg,error,line_ptr_end); */ leres = read_uword_de( &line_ptr,&utmp3, dbg,error,line_ptr_end); if (leres == DW_DLV_ERROR) { _dwarf_free_chain_entries(dbg,head_chain, line_count); if(curr_line) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); } return DW_DLV_ERROR; } instr_length = 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. */ if (line_ptr >= line_ptr_end) { dwarfstring g; ptrdiff_t d = 0; d = line_ptr - section_start; dwarfstring_constructor(&g); dwarfstring_append_printf_u(&g, "DW_DLE_LINE_TABLE_BAD reading " "extended op we are " "off this line table at section " "offset 0x%x .", d); _dwarf_error_string(dbg, error, DW_DLE_LINE_TABLE_BAD, dwarfstring_string(&g)); dwarfstring_destructor(&g); if(curr_line) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); } _dwarf_free_chain_entries(dbg,head_chain,line_count); return DW_DLV_ERROR; } ext_opcode = *(Dwarf_Small *) line_ptr; line_ptr++; if (line_ptr > line_ptr_end) { dwarfstring g; ptrdiff_t d = 0; d = line_ptr - section_start; dwarfstring_constructor(&g); dwarfstring_append_printf_u(&g, "DW_DLE_LINE_TABLE_BAD reading " "extended op opcode we are " "off this line table at section " "offset 0x%x .", d); _dwarf_error_string(dbg, error, DW_DLE_LINE_TABLE_BAD, dwarfstring_string(&g)); dwarfstring_destructor(&g); _dwarf_free_chain_entries(dbg,head_chain,line_count); if(curr_line) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); } return DW_DLV_ERROR; } switch (ext_opcode) { case DW_LNE_end_sequence:{ regs.lr_end_sequence = true; if (dolines) { curr_line = (Dwarf_Line) _dwarf_get_alloc(dbg, DW_DLA_LINE, 1); if (!curr_line) { _dwarf_free_chain_entries(dbg,head_chain, line_count); _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } #ifdef PRINTING_DETAILS print_line_detail(dbg, "DW_LNE_end_sequence extended", ext_opcode, line_count+1,®s, is_single_table, is_actuals_table); #endif /* PRINTING_DETAILS */ curr_line->li_address = regs.lr_address; curr_line->li_addr_line.li_l_data.li_file = (Dwarf_Signed) regs.lr_file; curr_line->li_addr_line.li_l_data.li_line = (Dwarf_Signed) regs.lr_line; curr_line->li_addr_line.li_l_data.li_column = (Dwarf_Half) regs.lr_column; curr_line->li_addr_line.li_l_data.li_is_stmt = regs.lr_is_stmt; curr_line->li_addr_line.li_l_data. li_basic_block = regs.lr_basic_block; curr_line->li_addr_line.li_l_data. li_end_sequence = regs.lr_end_sequence; curr_line->li_context = line_context; curr_line->li_is_actuals_table = is_actuals_table; curr_line->li_addr_line.li_l_data. li_epilogue_begin = regs.lr_epilogue_begin; curr_line->li_addr_line.li_l_data. li_prologue_end = regs.lr_prologue_end; curr_line->li_addr_line.li_l_data.li_isa = regs.lr_isa; curr_line->li_addr_line.li_l_data.li_discriminator = regs.lr_discriminator; curr_line->li_addr_line.li_l_data.li_call_context = regs.lr_call_context; curr_line->li_addr_line.li_l_data.li_subprogram = regs.lr_subprogram; line_count++; chain_line = (Dwarf_Chain) _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); if (chain_line == NULL) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); _dwarf_free_chain_entries(dbg,head_chain,line_count); _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } chain_line->ch_itemtype = DW_DLA_LINE; chain_line->ch_item = curr_line; _dwarf_update_chain_list(chain_line, &head_chain,&curr_chain); curr_line = 0; } _dwarf_set_line_table_regs_default_values(®s, line_context->lc_version_number, line_context->lc_default_is_stmt); } break; case DW_LNE_set_address:{ int sares = 0; /* READ_UNALIGNED_CK(dbg, regs.lr_address, Dwarf_Addr, line_ptr, address_size,error,line_ptr_end); */ sares = _dwarf_read_unaligned_ck_wrapper(dbg, ®s.lr_address,line_ptr, address_size,line_ptr_end, error); if (sares == DW_DLV_ERROR) { if(curr_line) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); } _dwarf_free_chain_entries(dbg,head_chain, line_count); return sares; } /* Mark a line record as being DW_LNS_set_address */ is_addr_set = true; #ifdef PRINTING_DETAILS { dwarfstring sadd; dwarfstring_constructor(&sadd); dwarfstring_append_printf_u(&sadd, "DW_LNE_set_address address 0x%" DW_PR_XZEROS DW_PR_DUx "\n", regs.lr_address); _dwarf_printf(dbg,dwarfstring_string(&sadd)); dwarfstring_destructor(&sadd); } #endif /* PRINTING_DETAILS */ if (doaddrs) { /* SGI IRIX rqs processing only. */ curr_line = (Dwarf_Line) _dwarf_get_alloc(dbg, DW_DLA_LINE, 1); if (!curr_line) { _dwarf_free_chain_entries(dbg,head_chain,line_count); _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } /* Mark a line record as being DW_LNS_set_address */ curr_line->li_addr_line.li_l_data.li_is_addr_set = is_addr_set; is_addr_set = false; curr_line->li_address = regs.lr_address; #ifdef __sgi /* SGI IRIX ONLY */ curr_line->li_addr_line.li_offset = line_ptr - dbg->de_debug_line.dss_data; #endif /* __sgi */ line_count++; chain_line = (Dwarf_Chain) _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1); if (chain_line == NULL) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); _dwarf_free_chain_entries(dbg,head_chain,line_count); _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } chain_line->ch_itemtype = DW_DLA_LINE; chain_line->ch_item = curr_line; _dwarf_update_chain_list(chain_line,&head_chain,&curr_chain); curr_line = 0; } regs.lr_op_index = 0; line_ptr += address_size; if (line_ptr > line_ptr_end) { dwarfstring g; ptrdiff_t d = 0; d = line_ptr - section_start; dwarfstring_constructor(&g); dwarfstring_append_printf_u(&g, "DW_DLE_LINE_TABLE_BAD reading " "DW_LNE_set_address we are " "off this line table at section " "offset 0x%x .", d); _dwarf_error_string(dbg, error, DW_DLE_LINE_TABLE_BAD, dwarfstring_string(&g)); dwarfstring_destructor(&g); if(curr_line) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); } _dwarf_free_chain_entries(dbg,head_chain,line_count); return DW_DLV_ERROR; } } break; case DW_LNE_define_file: if (dolines) { int dlres = 0; Dwarf_Unsigned value = 0; cur_file_entry = (Dwarf_File_Entry) malloc(sizeof(struct Dwarf_File_Entry_s)); if (cur_file_entry == NULL) { _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); if(curr_line) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); } _dwarf_free_chain_entries(dbg,head_chain,line_count); return DW_DLV_ERROR; } memset(cur_file_entry,0, sizeof(struct Dwarf_File_Entry_s)); _dwarf_add_to_files_list(line_context, cur_file_entry); cur_file_entry->fi_file_name = (Dwarf_Small *) line_ptr; dlres = _dwarf_check_string_valid(dbg, line_ptr,line_ptr,line_ptr_end, DW_DLE_DEFINE_FILE_STRING_BAD,error); if (dlres != DW_DLV_OK) { _dwarf_free_chain_entries(dbg,head_chain, line_count); if(curr_line) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); } return dlres; } line_ptr = line_ptr + strlen((char *) line_ptr) + 1; /*DECODE_LEB128_UWORD_CK(line_ptr,value, dbg,error,line_ptr_end); */ dlres = read_uword_de( &line_ptr,&value, dbg,error,line_ptr_end); if (dlres == DW_DLV_ERROR) { _dwarf_free_chain_entries(dbg,head_chain, line_count); if(curr_line) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); } return DW_DLV_ERROR; } cur_file_entry->fi_dir_index = (Dwarf_Signed)value; cur_file_entry->fi_dir_index_present = TRUE; /* DECODE_LEB128_UWORD_CK(line_ptr,value, dbg,error,line_ptr_end); */ dlres = read_uword_de( &line_ptr,&value, dbg,error,line_ptr_end); if (dlres == DW_DLV_ERROR) { _dwarf_free_chain_entries(dbg,head_chain, line_count); if(curr_line) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); } return DW_DLV_ERROR; } cur_file_entry->fi_time_last_mod = value; /*DECODE_LEB128_UWORD_CK(line_ptr,value, dbg,error,line_ptr_end); */ dlres = read_uword_de( &line_ptr,&value, dbg,error,line_ptr_end); if (dlres == DW_DLV_ERROR) { _dwarf_free_chain_entries(dbg,head_chain, line_count); dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); return DW_DLV_ERROR; } cur_file_entry->fi_file_length = value; cur_file_entry->fi_dir_index_present = TRUE; cur_file_entry->fi_time_last_mod_present = TRUE; cur_file_entry->fi_file_length_present = TRUE; #ifdef PRINTING_DETAILS { dwarfstring m9c; dwarfstring_constructor(&m9c); dwarfstring_append_printf_s(&m9c, "DW_LNE_define_file %s \n", (char *)cur_file_entry->fi_file_name); dwarfstring_append_printf_i(&m9c, " dir index %d\n", (int) cur_file_entry->fi_dir_index); { time_t tt3 = (time_t) cur_file_entry-> fi_time_last_mod; /* ctime supplies newline */ dwarfstring_append_printf_u(&m9c, " last time 0x%x ", (Dwarf_Unsigned)tt3); dwarfstring_append_printf_s(&m9c, "%s", ctime(&tt3)); } dwarfstring_append_printf_i(&m9c, " file length %ld ", cur_file_entry->fi_file_length); dwarfstring_append_printf_u(&m9c, "0x%lx\n", cur_file_entry->fi_file_length); _dwarf_printf(dbg,dwarfstring_string(&m9c)); dwarfstring_destructor(&m9c); } #endif /* PRINTING_DETAILS */ } break; case DW_LNE_set_discriminator:{ /* New in DWARF4 */ int sdres = 0; Dwarf_Unsigned utmp2 = 0; /*DECODE_LEB128_UWORD_CK(line_ptr, utmp2, dbg,error,line_ptr_end); */ sdres = read_uword_de( &line_ptr,&utmp2, dbg,error,line_ptr_end); if (sdres == DW_DLV_ERROR) { _dwarf_free_chain_entries(dbg,head_chain, line_count); if(curr_line) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); } return DW_DLV_ERROR; } regs.lr_discriminator = utmp2; #ifdef PRINTING_DETAILS { dwarfstring mk; dwarfstring_constructor(&mk); dwarfstring_append_printf_u(&mk, "DW_LNE_set_discriminator 0x%" DW_PR_XZEROS DW_PR_DUx "\n", utmp2); _dwarf_printf(dbg,dwarfstring_string(&mk)); dwarfstring_destructor(&mk); } #endif /* PRINTING_DETAILS */ } 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) { dwarfstring g; ptrdiff_t d = 0; _dwarf_free_chain_entries(dbg,head_chain, line_count); d = line_ptr - section_start; dwarfstring_constructor(&g); dwarfstring_append_printf_u(&g, "DW_DLE_LINE_TABLE_BAD reading " "unknown DW_LNE_extended op opcode 0x%x ", ext_opcode); dwarfstring_append_printf_u(&g, "we are " "off this line table at section " "offset 0x%x and ", d); dwarfstring_append_printf_u(&g,"instruction length" "%u.",instr_length); _dwarf_error_string(dbg, error, DW_DLE_LINE_TABLE_BAD, dwarfstring_string(&g)); dwarfstring_destructor(&g); if(curr_line) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); } _dwarf_free_chain_entries(dbg,head_chain,line_count); return DW_DLV_ERROR; } #ifdef PRINTING_DETAILS { dwarfstring m9d; dwarfstring_constructor(&m9d); dwarfstring_append_printf_u(&m9d, "DW_LNE extended op 0x%x ", ext_opcode); dwarfstring_append_printf_u(&m9d, "Bytecount: %" DW_PR_DUu , (Dwarf_Unsigned)instr_length); if (remaining_bytes > 0) { dwarfstring_append(&m9d," linedata: 0x"); while (remaining_bytes > 0) { dwarfstring_append_printf_u(&m9d, "%02x", (unsigned char)(*(line_ptr))); line_ptr++; if (line_ptr > line_ptr_end) { dwarfstring g; ptrdiff_t d = 0; d = line_ptr - section_start; dwarfstring_constructor(&g); dwarfstring_append_printf_u(&g, "DW_DLE_LINE_TABLE_BAD reading " "DW_LNE extended op remaining bytes " "we are " "off this line table at section " "offset 0x%x .", d); _dwarf_error_string(dbg, error, DW_DLE_LINE_TABLE_BAD, dwarfstring_string(&g)); dwarfstring_destructor(&g); dwarfstring_destructor(&m9d); if(curr_line) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); } _dwarf_free_chain_entries(dbg,head_chain,line_count); return DW_DLV_ERROR; } remaining_bytes--; } } _dwarf_printf(dbg,dwarfstring_string(&m9d)); dwarfstring_destructor(&m9d); } #else /* ! PRINTING_DETAILS */ line_ptr += remaining_bytes; if (line_ptr > line_ptr_end) { dwarfstring g; ptrdiff_t d = 0; d = line_ptr - section_start; dwarfstring_constructor(&g); dwarfstring_append_printf_u(&g, "DW_DLE_LINE_TABLE_BAD reading " "DW_LNE extended op remaining bytes " "we are " "off this line table at section " "offset 0x%x .", d); _dwarf_error_string(dbg, error, DW_DLE_LINE_TABLE_BAD, dwarfstring_string(&g)); dwarfstring_destructor(&g); if(curr_line) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); } _dwarf_free_chain_entries(dbg,head_chain,line_count); return DW_DLV_ERROR; } #endif /* PRINTING_DETAILS */ _dwarf_printf(dbg,"\n"); } break; } /* End switch. */ } } block_line = (Dwarf_Line *) _dwarf_get_alloc(dbg, DW_DLA_LIST, line_count); if (block_line == NULL) { curr_chain = head_chain; _dwarf_free_chain_entries(dbg,head_chain,line_count); if(curr_line) { dwarf_dealloc(dbg,curr_line,DW_DLA_LINE); curr_line = 0; } _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); return (DW_DLV_ERROR); } curr_chain = head_chain; for (i = 0; i < line_count; i++) { Dwarf_Chain t = 0; *(block_line + i) = curr_chain->ch_item; curr_chain->ch_item = 0; curr_chain->ch_itemtype = 0; t = curr_chain; curr_chain = curr_chain->ch_next; dwarf_dealloc(dbg, t, DW_DLA_CHAIN); } if (is_single_table || !is_actuals_table) { line_context->lc_linebuf_logicals = block_line; line_context->lc_linecount_logicals = line_count; } else { line_context->lc_linebuf_actuals = block_line; line_context->lc_linecount_actuals = line_count; } #ifdef PRINTING_DETAILS { dwarfstring mc; dwarfstring_constructor(&mc); if (is_single_table) { if(!line_count) { dwarfstring_append_printf_u(&mc, " Line table is present (offset 0x%" DW_PR_XZEROS DW_PR_DUx ") but no lines present\n", line_context->lc_section_offset); } } else if (is_actuals_table) { if(!line_count) { dwarfstring_append_printf_u(&mc, " Line table present (offset 0x%" DW_PR_XZEROS DW_PR_DUx ") but no actuals lines present\n", line_context->lc_section_offset); } } else { if(!line_count) { dwarfstring_append_printf_u(&mc, " Line table present (offset 0x%" DW_PR_XZEROS DW_PR_DUx ") but no logicals lines present\n", line_context->lc_section_offset); } } if (dwarfstring_strlen(&mc)) { _dwarf_printf(dbg,dwarfstring_string(&mc)); } dwarfstring_destructor(&mc); } #endif /* PRINTING_DETAILS */ return DW_DLV_OK; }