|
Packit |
cdaae3 |
/*
|
|
Packit |
cdaae3 |
Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
|
|
Packit |
cdaae3 |
Portions Copyright (C) 2007-2017 David Anderson. All Rights Reserved.
|
|
Packit |
cdaae3 |
Portions Copyright (C) 2010-2012 SN Systems Ltd. All Rights Reserved.
|
|
Packit |
cdaae3 |
Portions Copyright (C) 2015-2015 Google, Inc. All Rights Reserved.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
This program is free software; you can redistribute it and/or modify it
|
|
Packit |
cdaae3 |
under the terms of version 2.1 of the GNU Lesser General Public License
|
|
Packit |
cdaae3 |
as published by the Free Software Foundation.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
This program is distributed in the hope that it would be useful, but
|
|
Packit |
cdaae3 |
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
cdaae3 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
Further, this software is distributed without any warranty that it is
|
|
Packit |
cdaae3 |
free of the rightful claim of any third person regarding infringement
|
|
Packit |
cdaae3 |
or the like. Any license provided herein, whether implied or
|
|
Packit |
cdaae3 |
otherwise, applies only to this software file. Patent licenses, if
|
|
Packit |
cdaae3 |
any, provided herein do not apply to combinations of this program with
|
|
Packit |
cdaae3 |
other software, or any other product whatsoever.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
You should have received a copy of the GNU Lesser General Public
|
|
Packit |
cdaae3 |
License along with this program; if not, write the Free Software
|
|
Packit |
cdaae3 |
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
|
|
Packit |
cdaae3 |
USA.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
*/
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* This is #included twice. Once for
|
|
Packit |
cdaae3 |
libdwarf callers and one for dwarfdump which prints
|
|
Packit |
cdaae3 |
the internals.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
This way we have just one blob of code that reads
|
|
Packit |
cdaae3 |
the table operations. */
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
#define TRUE 1
|
|
Packit |
cdaae3 |
#define FALSE 0
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
static unsigned char
|
|
Packit |
cdaae3 |
dwarf_standard_opcode_operand_count[STANDARD_OPERAND_COUNT_TWO_LEVEL] = {
|
|
Packit |
cdaae3 |
/* DWARF2 */
|
|
Packit |
cdaae3 |
0,
|
|
Packit |
cdaae3 |
1, 1, 1, 1,
|
|
Packit |
cdaae3 |
0, 0, 0,
|
|
Packit |
cdaae3 |
1,
|
|
Packit |
cdaae3 |
/* Following are new for DWARF3. */
|
|
Packit |
cdaae3 |
0, 0, 1,
|
|
Packit |
cdaae3 |
/* Experimental opcodes. */
|
|
Packit |
cdaae3 |
1, 2, 0,
|
|
Packit |
cdaae3 |
};
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* We have a normal standard opcode base, but
|
|
Packit |
cdaae3 |
an arm compiler emitted a non-standard table!
|
|
Packit |
cdaae3 |
This could lead to problems...
|
|
Packit |
cdaae3 |
ARM C/C++ Compiler, RVCT4.0 [Build 4
|
|
Packit |
cdaae3 |
00] seems to get the table wrong . */
|
|
Packit |
cdaae3 |
static unsigned char
|
|
Packit |
cdaae3 |
dwarf_arm_standard_opcode_operand_count[STANDARD_OPERAND_COUNT_DWARF3] = {
|
|
Packit |
cdaae3 |
/* DWARF2 */
|
|
Packit |
cdaae3 |
0,
|
|
Packit |
cdaae3 |
1, 1, 1, 1,
|
|
Packit |
cdaae3 |
0, 0, 0,
|
|
Packit |
cdaae3 |
0, /* <<< --- this is wrong */
|
|
Packit |
cdaae3 |
/* Following are new for DWARF3. */
|
|
Packit |
cdaae3 |
0, 0, 1
|
|
Packit |
cdaae3 |
};
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Rather like memcmp but identifies which value pair
|
|
Packit |
cdaae3 |
mismatches (the return value is non-zero if mismatch,
|
|
Packit |
cdaae3 |
zero if match)..
|
|
Packit |
cdaae3 |
mismatch_entry returns the table index that mismatches.
|
|
Packit |
cdaae3 |
tabval returns the table byte value.
|
|
Packit |
cdaae3 |
lineval returns the value from the line table header. */
|
|
Packit |
cdaae3 |
static int
|
|
Packit |
cdaae3 |
operandmismatch(unsigned char * table,unsigned table_length,
|
|
Packit |
cdaae3 |
unsigned char *linetable,
|
|
Packit |
cdaae3 |
unsigned check_count,
|
|
Packit |
cdaae3 |
unsigned * mismatch_entry, unsigned * tabval,unsigned *lineval)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
unsigned i = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* check_count better be <= table_length */
|
|
Packit |
cdaae3 |
for (i = 0; i
|
|
Packit |
cdaae3 |
if (i > table_length) {
|
|
Packit |
cdaae3 |
*mismatch_entry = i;
|
|
Packit |
cdaae3 |
*lineval = linetable[i];
|
|
Packit |
cdaae3 |
*tabval = 0; /* No entry present. */
|
|
Packit |
cdaae3 |
/* A kind of mismatch */
|
|
Packit |
cdaae3 |
return TRUE;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if (table[i] == linetable[i]) {
|
|
Packit |
cdaae3 |
continue;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
*mismatch_entry = i;
|
|
Packit |
cdaae3 |
*tabval = table[i];
|
|
Packit |
cdaae3 |
*lineval = linetable[i];
|
|
Packit |
cdaae3 |
return TRUE;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
/* Matches. */
|
|
Packit |
cdaae3 |
return FALSE;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Common line table header reading code.
|
|
Packit |
cdaae3 |
Returns DW_DLV_OK, DW_DLV_ERROR.
|
|
Packit |
cdaae3 |
DW_DLV_NO_ENTRY cannot be returned, but callers should
|
|
Packit |
cdaae3 |
assume it is possible.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
The line_context area must be initialized properly before calling this.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
Has the side effect of allocating arrays which
|
|
Packit |
cdaae3 |
must be freed (see the Line_Table_Context which
|
|
Packit |
cdaae3 |
holds the pointers to space we allocate here).
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
bogus_bytes_ptr and bogus_bytes are output values which
|
|
Packit |
cdaae3 |
let a print-program notify the user of some surprising bytes
|
|
Packit |
cdaae3 |
after a line table header and before the line table instructions.
|
|
Packit |
cdaae3 |
These can be ignored unless one is printing.
|
|
Packit |
cdaae3 |
And are ignored if NULL passed as the pointer.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
err_count_out may be NULL, in which case we
|
|
Packit |
cdaae3 |
make no attempt to count checking-type errors.
|
|
Packit |
cdaae3 |
Checking-type errors do not stop us, we just report them.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
See dw-linetableheader.txt for the ordering of text fields
|
|
Packit |
cdaae3 |
across the various dwarf versions. The code
|
|
Packit |
cdaae3 |
follows this ordering closely.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
Some of the arguments remaining are in line_context
|
|
Packit |
cdaae3 |
so can be deleted from the
|
|
Packit |
cdaae3 |
argument list (after a close look for correctness).
|
|
Packit |
cdaae3 |
*/
|
|
Packit |
cdaae3 |
static int
|
|
Packit |
cdaae3 |
_dwarf_read_line_table_header(Dwarf_Debug dbg,
|
|
Packit |
cdaae3 |
Dwarf_CU_Context cu_context,
|
|
Packit |
cdaae3 |
Dwarf_Small * section_start,
|
|
Packit |
cdaae3 |
Dwarf_Small * data_start,
|
|
Packit |
cdaae3 |
Dwarf_Unsigned section_length,
|
|
Packit |
cdaae3 |
Dwarf_Small ** updated_data_start_out,
|
|
Packit |
cdaae3 |
Dwarf_Line_Context line_context,
|
|
Packit |
cdaae3 |
Dwarf_Small ** bogus_bytes_ptr,
|
|
Packit |
cdaae3 |
Dwarf_Unsigned *bogus_bytes,
|
|
Packit |
cdaae3 |
Dwarf_Error * err,
|
|
Packit |
cdaae3 |
int *err_count_out)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
Dwarf_Small *line_ptr = data_start;
|
|
Packit |
cdaae3 |
Dwarf_Small *starting_line_ptr = data_start;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned total_length = 0;
|
|
Packit |
cdaae3 |
int local_length_size = 0;
|
|
Packit |
cdaae3 |
int local_extension_size = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned prologue_length = 0;
|
|
Packit |
cdaae3 |
Dwarf_Half version = 0;
|
|
Packit |
cdaae3 |
Dwarf_Small *section_end = section_start + section_length;
|
|
Packit |
cdaae3 |
Dwarf_Small *line_ptr_end = 0;
|
|
Packit |
cdaae3 |
Dwarf_Small *lp_begin = 0;
|
|
Packit |
cdaae3 |
int res = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (bogus_bytes_ptr) *bogus_bytes_ptr = 0;
|
|
Packit |
cdaae3 |
if (bogus_bytes) *bogus_bytes= 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
line_context->lc_line_ptr_start = starting_line_ptr;
|
|
Packit |
cdaae3 |
/* READ_AREA_LENGTH updates line_ptr for consumed bytes */
|
|
Packit |
cdaae3 |
READ_AREA_LENGTH_CK(dbg, total_length, Dwarf_Unsigned,
|
|
Packit |
cdaae3 |
line_ptr, local_length_size, local_extension_size,
|
|
Packit |
cdaae3 |
err, section_length,section_end);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
line_ptr_end = line_ptr + total_length;
|
|
Packit |
cdaae3 |
line_context->lc_line_ptr_end = line_ptr_end;
|
|
Packit |
cdaae3 |
line_context->lc_length_field_length = local_length_size +
|
|
Packit |
cdaae3 |
local_extension_size;
|
|
Packit |
cdaae3 |
line_context->lc_section_offset = starting_line_ptr -
|
|
Packit |
cdaae3 |
dbg->de_debug_line.dss_data;
|
|
Packit |
cdaae3 |
/* ASSERT: line_context->lc_length_field_length == line_ptr
|
|
Packit |
cdaae3 |
-line_context->lc_line_ptr_start; */
|
|
Packit |
cdaae3 |
if (line_ptr_end > section_end) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_DEBUG_LINE_LENGTH_BAD);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
line_context->lc_total_length = total_length;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
READ_UNALIGNED_CK(dbg, version, Dwarf_Half,
|
|
Packit |
cdaae3 |
line_ptr, sizeof(Dwarf_Half),
|
|
Packit |
cdaae3 |
err,line_ptr_end);
|
|
Packit |
cdaae3 |
line_context->lc_version_number = version;
|
|
Packit |
cdaae3 |
line_ptr += sizeof(Dwarf_Half);
|
|
Packit |
cdaae3 |
if (version != DW_LINE_VERSION2 &&
|
|
Packit |
cdaae3 |
version != DW_LINE_VERSION3 &&
|
|
Packit |
cdaae3 |
version != DW_LINE_VERSION4 &&
|
|
Packit |
cdaae3 |
version != DW_LINE_VERSION5 &&
|
|
Packit |
cdaae3 |
version != EXPERIMENTAL_LINE_TABLES_VERSION) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_VERSION_STAMP_ERROR);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if (version == DW_LINE_VERSION5) {
|
|
Packit |
cdaae3 |
if (line_ptr >= line_ptr_end) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_DEBUG_LINE_LENGTH_BAD);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
line_context->lc_address_size = *(unsigned char *) line_ptr;
|
|
Packit |
cdaae3 |
line_ptr = line_ptr + sizeof(Dwarf_Small);
|
|
Packit |
cdaae3 |
if (line_ptr >= line_ptr_end) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_DEBUG_LINE_LENGTH_BAD);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
line_context->lc_segment_selector_size =
|
|
Packit |
cdaae3 |
*(unsigned char *) line_ptr;
|
|
Packit |
cdaae3 |
line_ptr = line_ptr + sizeof(Dwarf_Small);
|
|
Packit |
cdaae3 |
} else {
|
|
Packit |
cdaae3 |
line_context->lc_address_size = cu_context->cc_address_size;
|
|
Packit |
cdaae3 |
line_context->lc_segment_selector_size =
|
|
Packit |
cdaae3 |
cu_context->cc_segment_selector_size;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
READ_UNALIGNED_CK(dbg, prologue_length, Dwarf_Unsigned,
|
|
Packit |
cdaae3 |
line_ptr, local_length_size,
|
|
Packit |
cdaae3 |
err,line_ptr_end);
|
|
Packit |
cdaae3 |
line_context->lc_prologue_length = prologue_length;
|
|
Packit |
cdaae3 |
line_ptr += local_length_size;
|
|
Packit |
cdaae3 |
line_context->lc_line_prologue_start = line_ptr;
|
|
Packit |
cdaae3 |
if (line_ptr >= line_ptr_end) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_DEBUG_LINE_LENGTH_BAD);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
line_context->lc_minimum_instruction_length =
|
|
Packit |
cdaae3 |
*(unsigned char *) line_ptr;
|
|
Packit |
cdaae3 |
line_ptr = line_ptr + sizeof(Dwarf_Small);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (version == DW_LINE_VERSION4 ||
|
|
Packit |
cdaae3 |
version == DW_LINE_VERSION5 ||
|
|
Packit |
cdaae3 |
version == EXPERIMENTAL_LINE_TABLES_VERSION) {
|
|
Packit |
cdaae3 |
if (line_ptr >= line_ptr_end) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_DEBUG_LINE_LENGTH_BAD);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
line_context->lc_maximum_ops_per_instruction =
|
|
Packit |
cdaae3 |
*(unsigned char *) line_ptr;
|
|
Packit |
cdaae3 |
line_ptr = line_ptr + sizeof(Dwarf_Small);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if (line_ptr >= line_ptr_end) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_DEBUG_LINE_LENGTH_BAD);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
line_context->lc_default_is_stmt = *(unsigned char *) line_ptr;
|
|
Packit |
cdaae3 |
line_ptr = line_ptr + sizeof(Dwarf_Small);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (line_ptr >= line_ptr_end) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_DEBUG_LINE_LENGTH_BAD);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
line_context->lc_line_base = *(signed char *) line_ptr;
|
|
Packit |
cdaae3 |
line_ptr = line_ptr + sizeof(Dwarf_Sbyte);
|
|
Packit |
cdaae3 |
if(line_ptr >= line_ptr_end) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_LINE_OFFSET_BAD);
|
|
Packit |
cdaae3 |
return DW_DLV_ERROR;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
line_context->lc_line_range = *(unsigned char *) line_ptr;
|
|
Packit |
cdaae3 |
if (!line_context->lc_line_range) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_DEBUG_LINE_RANGE_ZERO);
|
|
Packit |
cdaae3 |
return DW_DLV_ERROR;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
line_ptr = line_ptr + sizeof(Dwarf_Small);
|
|
Packit |
cdaae3 |
if(line_ptr >= line_ptr_end) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_LINE_OFFSET_BAD);
|
|
Packit |
cdaae3 |
return DW_DLV_ERROR;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
line_context->lc_opcode_base = *(unsigned char *) line_ptr;
|
|
Packit |
cdaae3 |
line_ptr = line_ptr + sizeof(Dwarf_Small);
|
|
Packit |
cdaae3 |
/* Set up the array of standard opcode lengths. */
|
|
Packit |
cdaae3 |
/* We think this works ok even for cross-endian processing of
|
|
Packit |
cdaae3 |
objects. It might be wrong, we might need to specially process
|
|
Packit |
cdaae3 |
the array of ubyte into host order. */
|
|
Packit |
cdaae3 |
line_context->lc_opcode_length_table = line_ptr;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* lc_opcode_base is one greater than the size of the array. */
|
|
Packit |
cdaae3 |
line_ptr += line_context->lc_opcode_base - 1;
|
|
Packit |
cdaae3 |
line_context->lc_std_op_count = line_context->lc_opcode_base -1;
|
|
Packit |
cdaae3 |
if(line_ptr >= line_ptr_end) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_LINE_OFFSET_BAD);
|
|
Packit |
cdaae3 |
return DW_DLV_ERROR;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
/* Determine (as best we can) whether the
|
|
Packit |
cdaae3 |
lc_opcode_length_table holds 9 or 12 standard-conforming
|
|
Packit |
cdaae3 |
entries. gcc4 upped to DWARF3's 12 without updating the
|
|
Packit |
cdaae3 |
version number.
|
|
Packit |
cdaae3 |
EXPERIMENTAL_LINE_TABLES_VERSION upped to 15. */
|
|
Packit |
cdaae3 |
unsigned check_count = line_context->lc_std_op_count;
|
|
Packit |
cdaae3 |
unsigned tab_count = sizeof(dwarf_standard_opcode_operand_count);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
int operand_ck_fail = true;
|
|
Packit |
cdaae3 |
if (line_context->lc_std_op_count > tab_count) {
|
|
Packit |
cdaae3 |
_dwarf_print_header_issue(dbg,
|
|
Packit |
cdaae3 |
"Too many standard operands in linetable header: ",
|
|
Packit |
cdaae3 |
data_start,
|
|
Packit |
cdaae3 |
line_context->lc_std_op_count,
|
|
Packit |
cdaae3 |
0,0,0,
|
|
Packit |
cdaae3 |
err_count_out);
|
|
Packit |
cdaae3 |
check_count = tab_count;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
unsigned entrynum = 0;
|
|
Packit |
cdaae3 |
unsigned tabv = 0;
|
|
Packit |
cdaae3 |
unsigned linetabv = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
int mismatch = operandmismatch(
|
|
Packit |
cdaae3 |
dwarf_standard_opcode_operand_count,
|
|
Packit |
cdaae3 |
tab_count,
|
|
Packit |
cdaae3 |
line_context->lc_opcode_length_table,
|
|
Packit |
cdaae3 |
check_count,&entrynum,&tabv,&linetabv);
|
|
Packit |
cdaae3 |
if (mismatch) {
|
|
Packit |
cdaae3 |
if (err_count_out) {
|
|
Packit |
cdaae3 |
_dwarf_print_header_issue(dbg,
|
|
Packit |
cdaae3 |
"standard-operands did not match, checked",
|
|
Packit |
cdaae3 |
data_start,
|
|
Packit |
cdaae3 |
check_count,
|
|
Packit |
cdaae3 |
entrynum,tabv,linetabv,err_count_out);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if (check_count >
|
|
Packit |
cdaae3 |
sizeof(dwarf_arm_standard_opcode_operand_count)) {
|
|
Packit |
cdaae3 |
check_count =
|
|
Packit |
cdaae3 |
sizeof(dwarf_arm_standard_opcode_operand_count);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
mismatch = operandmismatch(
|
|
Packit |
cdaae3 |
dwarf_arm_standard_opcode_operand_count,
|
|
Packit |
cdaae3 |
sizeof(dwarf_arm_standard_opcode_operand_count),
|
|
Packit |
cdaae3 |
line_context->lc_opcode_length_table,
|
|
Packit |
cdaae3 |
check_count,&entrynum,&tabv,&linetabv);
|
|
Packit |
cdaae3 |
if (!mismatch && err_count_out) {
|
|
Packit |
cdaae3 |
_dwarf_print_header_issue(dbg,
|
|
Packit |
cdaae3 |
"arm (incorrect) operands in use: ",
|
|
Packit |
cdaae3 |
data_start,
|
|
Packit |
cdaae3 |
check_count,
|
|
Packit |
cdaae3 |
entrynum,tabv,linetabv,err_count_out);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if (!mismatch) {
|
|
Packit |
cdaae3 |
if (version == 2) {
|
|
Packit |
cdaae3 |
if (line_context->lc_std_op_count ==
|
|
Packit |
cdaae3 |
STANDARD_OPERAND_COUNT_DWARF3) {
|
|
Packit |
cdaae3 |
_dwarf_print_header_issue(dbg,
|
|
Packit |
cdaae3 |
"standard DWARF3 operands matched,"
|
|
Packit |
cdaae3 |
" but is DWARF2 linetable: count",
|
|
Packit |
cdaae3 |
data_start,
|
|
Packit |
cdaae3 |
check_count,
|
|
Packit |
cdaae3 |
0,0,0, err_count_out);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
operand_ck_fail = false;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if (operand_ck_fail) {
|
|
Packit |
cdaae3 |
/* Here we are not sure what the lc_std_op_count is. */
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_LINE_NUM_OPERANDS_BAD);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
/* At this point we no longer need to check operand counts. */
|
|
Packit |
cdaae3 |
if(line_ptr >= line_ptr_end) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_LINE_OFFSET_BAD);
|
|
Packit |
cdaae3 |
return DW_DLV_ERROR;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (version < DW_LINE_VERSION5){
|
|
Packit |
cdaae3 |
Dwarf_Unsigned directories_count = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned directories_malloc = 5;
|
|
Packit |
cdaae3 |
line_context->lc_include_directories = malloc(sizeof(Dwarf_Small *) *
|
|
Packit |
cdaae3 |
directories_malloc);
|
|
Packit |
cdaae3 |
if (line_context->lc_include_directories == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
memset(line_context->lc_include_directories, 0,
|
|
Packit |
cdaae3 |
sizeof(Dwarf_Small *) * directories_malloc);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (line_ptr >= line_ptr_end) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
while ((*(char *) line_ptr) != '\0') {
|
|
Packit |
cdaae3 |
if (directories_count >= directories_malloc) {
|
|
Packit |
cdaae3 |
Dwarf_Unsigned expand = 2 * directories_malloc;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned bytesalloc = sizeof(Dwarf_Small *) * expand;
|
|
Packit |
cdaae3 |
Dwarf_Small **newdirs =
|
|
Packit |
cdaae3 |
realloc(line_context->lc_include_directories,
|
|
Packit |
cdaae3 |
bytesalloc);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (!newdirs) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
/* Doubled size, zero out second half. */
|
|
Packit |
cdaae3 |
memset(newdirs + directories_malloc, 0,
|
|
Packit |
cdaae3 |
sizeof(Dwarf_Small *) * directories_malloc);
|
|
Packit |
cdaae3 |
directories_malloc = expand;
|
|
Packit |
cdaae3 |
line_context->lc_include_directories = newdirs;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
line_context->lc_include_directories[directories_count] =
|
|
Packit |
cdaae3 |
line_ptr;
|
|
Packit |
cdaae3 |
res = _dwarf_check_string_valid(dbg,
|
|
Packit |
cdaae3 |
data_start,line_ptr,line_ptr_end,
|
|
Packit |
cdaae3 |
DW_DLE_LINE_STRING_BAD,err);
|
|
Packit |
cdaae3 |
if (res != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
return res;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
line_ptr = line_ptr + strlen((char *) line_ptr) + 1;
|
|
Packit |
cdaae3 |
directories_count++;
|
|
Packit |
cdaae3 |
if (line_ptr >= line_ptr_end) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
line_ptr++;
|
|
Packit |
cdaae3 |
line_context->lc_include_directories_count = directories_count;
|
|
Packit |
cdaae3 |
} else if (version == EXPERIMENTAL_LINE_TABLES_VERSION) {
|
|
Packit |
cdaae3 |
/* Empty old style dir entry list. */
|
|
Packit |
cdaae3 |
line_ptr++;
|
|
Packit |
cdaae3 |
} else if (version == 5) {
|
|
Packit |
cdaae3 |
/* handled below */
|
|
Packit |
cdaae3 |
} else {
|
|
Packit |
cdaae3 |
/* No old style directory entries. */
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if(line_ptr > line_ptr_end) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_LINE_OFFSET_BAD);
|
|
Packit |
cdaae3 |
return DW_DLV_ERROR;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if (version < DW_LINE_VERSION5) {
|
|
Packit |
cdaae3 |
if (line_ptr >= line_ptr_end) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
while (*(char *) line_ptr != '\0') {
|
|
Packit |
cdaae3 |
Dwarf_Unsigned utmp;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned dir_index = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned lastmod = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned file_length = 0;
|
|
Packit |
cdaae3 |
int resl = 0;
|
|
Packit |
cdaae3 |
Dwarf_File_Entry currfile = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
currfile = (Dwarf_File_Entry)
|
|
Packit |
cdaae3 |
malloc(sizeof(struct Dwarf_File_Entry_s));
|
|
Packit |
cdaae3 |
if (currfile == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
memset(currfile,0,sizeof(struct Dwarf_File_Entry_s));
|
|
Packit |
cdaae3 |
/* Insert early so in case of error we can find
|
|
Packit |
cdaae3 |
and free the record. */
|
|
Packit |
cdaae3 |
_dwarf_add_to_files_list(line_context,currfile);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
currfile->fi_file_name = line_ptr;
|
|
Packit |
cdaae3 |
resl = _dwarf_check_string_valid(dbg,
|
|
Packit |
cdaae3 |
data_start,line_ptr,line_ptr_end,
|
|
Packit |
cdaae3 |
DW_DLE_LINE_STRING_BAD,err);
|
|
Packit |
cdaae3 |
if (resl != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
return resl;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
line_ptr = line_ptr + strlen((char *) line_ptr) + 1;
|
|
Packit |
cdaae3 |
DECODE_LEB128_UWORD_CK(line_ptr, utmp,dbg,err,line_ptr_end);
|
|
Packit |
cdaae3 |
dir_index = (Dwarf_Word) utmp;
|
|
Packit |
cdaae3 |
if (dir_index > line_context->lc_include_directories_count) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_DIR_INDEX_BAD);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
currfile->fi_dir_index = dir_index;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
DECODE_LEB128_UWORD_CK(line_ptr,lastmod,
|
|
Packit |
cdaae3 |
dbg,err, line_ptr_end);
|
|
Packit |
cdaae3 |
currfile->fi_time_last_mod = lastmod;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Skip over file length. */
|
|
Packit |
cdaae3 |
DECODE_LEB128_UWORD_CK(line_ptr,file_length,
|
|
Packit |
cdaae3 |
dbg,err, line_ptr_end);
|
|
Packit |
cdaae3 |
currfile->fi_file_length = file_length;
|
|
Packit |
cdaae3 |
if (line_ptr >= line_ptr_end) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
/* Skip trailing nul byte */
|
|
Packit |
cdaae3 |
++line_ptr;
|
|
Packit |
cdaae3 |
} else if (version == EXPERIMENTAL_LINE_TABLES_VERSION) {
|
|
Packit |
cdaae3 |
if (line_ptr >= line_ptr_end) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if (*line_ptr != 0) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
line_ptr++;
|
|
Packit |
cdaae3 |
} else if (version == 5) {
|
|
Packit |
cdaae3 |
/* handled below */
|
|
Packit |
cdaae3 |
} else {
|
|
Packit |
cdaae3 |
/* No old style filenames entries. */
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if(line_ptr > line_ptr_end) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_LINE_OFFSET_BAD);
|
|
Packit |
cdaae3 |
return DW_DLV_ERROR;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (version == EXPERIMENTAL_LINE_TABLES_VERSION) {
|
|
Packit |
cdaae3 |
static unsigned char expbytes[5] = {0,0xff,0xff,0x7f, 0x7f };
|
|
Packit |
cdaae3 |
Dwarf_Unsigned logicals_table_offset = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned actuals_table_offset = 0;
|
|
Packit |
cdaae3 |
unsigned i = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
for ( ; i < 5; ++i) {
|
|
Packit |
cdaae3 |
if (line_ptr >= line_ptr_end) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if (*line_ptr != expbytes[i]) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
line_ptr++;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
READ_UNALIGNED_CK(dbg, logicals_table_offset, Dwarf_Unsigned,
|
|
Packit |
cdaae3 |
line_ptr, local_length_size,err,line_ptr_end);
|
|
Packit |
cdaae3 |
line_context->lc_logicals_table_offset = logicals_table_offset;
|
|
Packit |
cdaae3 |
line_ptr += local_length_size;
|
|
Packit |
cdaae3 |
READ_UNALIGNED_CK(dbg, actuals_table_offset, Dwarf_Unsigned,
|
|
Packit |
cdaae3 |
line_ptr, local_length_size,err,line_ptr_end);
|
|
Packit |
cdaae3 |
line_context->lc_actuals_table_offset = actuals_table_offset;
|
|
Packit |
cdaae3 |
line_ptr += local_length_size;
|
|
Packit |
cdaae3 |
if(line_ptr > line_ptr_end) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_LINE_OFFSET_BAD);
|
|
Packit |
cdaae3 |
return DW_DLV_ERROR;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (version == DW_LINE_VERSION5 ||
|
|
Packit |
cdaae3 |
version == EXPERIMENTAL_LINE_TABLES_VERSION) {
|
|
Packit |
cdaae3 |
/* DWARF 5. directory names.*/
|
|
Packit |
cdaae3 |
Dwarf_Unsigned directory_format_count = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned *directory_entry_types = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned *directory_entry_forms = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned directories_count = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned i = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned j = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (line_ptr >= line_ptr_end) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
directory_format_count = *(unsigned char *) line_ptr;
|
|
Packit |
cdaae3 |
line_ptr = line_ptr + sizeof(Dwarf_Small);
|
|
Packit |
cdaae3 |
if (directory_format_count > 0) {
|
|
Packit |
cdaae3 |
directory_entry_types = malloc(sizeof(Dwarf_Unsigned) *
|
|
Packit |
cdaae3 |
directory_format_count);
|
|
Packit |
cdaae3 |
if (directory_entry_types == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
directory_entry_forms = malloc(sizeof(Dwarf_Unsigned) *
|
|
Packit |
cdaae3 |
directory_format_count);
|
|
Packit |
cdaae3 |
if (directory_entry_forms == NULL) {
|
|
Packit |
cdaae3 |
free(directory_entry_types);
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
for (i = 0; i < directory_format_count; i++) {
|
|
Packit |
cdaae3 |
DECODE_LEB128_UWORD_CK(line_ptr, directory_entry_types[i],
|
|
Packit |
cdaae3 |
dbg,err,line_ptr_end);
|
|
Packit |
cdaae3 |
DECODE_LEB128_UWORD_CK(line_ptr, directory_entry_forms[i],
|
|
Packit |
cdaae3 |
dbg,err,line_ptr_end);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
DECODE_LEB128_UWORD_CK(line_ptr, directories_count,
|
|
Packit |
cdaae3 |
dbg,err,line_ptr_end);
|
|
Packit |
cdaae3 |
line_context->lc_include_directories =
|
|
Packit |
cdaae3 |
malloc(sizeof(Dwarf_Small *) * directories_count);
|
|
Packit |
cdaae3 |
if (line_context->lc_include_directories == NULL) {
|
|
Packit |
cdaae3 |
free(directory_entry_types);
|
|
Packit |
cdaae3 |
free(directory_entry_forms);
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if (directory_format_count ==0 &&
|
|
Packit |
cdaae3 |
directories_count > 0) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_DIRECTORY_FORMAT_COUNT_VS_DIRECTORIES_MISMATCH);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
memset(line_context->lc_include_directories, 0,
|
|
Packit |
cdaae3 |
sizeof(Dwarf_Small *) * directories_count);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
for(i = 0; i < directories_count; i++) {
|
|
Packit |
cdaae3 |
for (j = 0; j < directory_format_count; j++) {
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
switch (directory_entry_types[j]) {
|
|
Packit |
cdaae3 |
case DW_LNCT_path: {
|
|
Packit |
cdaae3 |
char *inc_dir_ptr = 0;
|
|
Packit |
cdaae3 |
res = _dwarf_decode_line_string_form(dbg,
|
|
Packit |
cdaae3 |
directory_entry_forms[j],
|
|
Packit |
cdaae3 |
local_length_size,
|
|
Packit |
cdaae3 |
&line_ptr,
|
|
Packit |
cdaae3 |
line_ptr_end,
|
|
Packit |
cdaae3 |
&inc_dir_ptr,
|
|
Packit |
cdaae3 |
err);
|
|
Packit |
cdaae3 |
if (res != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
free(directory_entry_types);
|
|
Packit |
cdaae3 |
free(directory_entry_forms);
|
|
Packit |
cdaae3 |
return res;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
line_context->lc_include_directories[i] =
|
|
Packit |
cdaae3 |
(unsigned char *)inc_dir_ptr;
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
default:
|
|
Packit |
cdaae3 |
free(directory_entry_types);
|
|
Packit |
cdaae3 |
free(directory_entry_forms);
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if (line_ptr > line_ptr_end) {
|
|
Packit |
cdaae3 |
free(directory_entry_types);
|
|
Packit |
cdaae3 |
free(directory_entry_forms);
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err,
|
|
Packit |
cdaae3 |
DW_DLE_LINE_NUMBER_HEADER_ERROR);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
free(directory_entry_types);
|
|
Packit |
cdaae3 |
free(directory_entry_forms);
|
|
Packit |
cdaae3 |
line_context->lc_include_directories_count = directories_count;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (version == DW_LINE_VERSION5 ||
|
|
Packit |
cdaae3 |
version == EXPERIMENTAL_LINE_TABLES_VERSION) {
|
|
Packit |
cdaae3 |
/* DWARF 5. file names.*/
|
|
Packit |
cdaae3 |
Dwarf_Unsigned filename_format_count = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned *filename_entry_types = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned *filename_entry_forms = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned files_count = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned i = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned j = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (line_ptr >= line_ptr_end) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
filename_format_count = *(unsigned char *) line_ptr;
|
|
Packit |
cdaae3 |
line_ptr = line_ptr + sizeof(Dwarf_Small);
|
|
Packit |
cdaae3 |
filename_entry_types = malloc(sizeof(Dwarf_Unsigned) *
|
|
Packit |
cdaae3 |
filename_format_count);
|
|
Packit |
cdaae3 |
if (filename_entry_types == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
filename_entry_forms = malloc(sizeof(Dwarf_Unsigned) *
|
|
Packit |
cdaae3 |
filename_format_count);
|
|
Packit |
cdaae3 |
if (filename_entry_forms == NULL) {
|
|
Packit |
cdaae3 |
free(filename_entry_types);
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
for (i = 0; i < filename_format_count; i++) {
|
|
Packit |
cdaae3 |
DECODE_LEB128_UWORD_CK(line_ptr, filename_entry_types[i],
|
|
Packit |
cdaae3 |
dbg,err,line_ptr_end);
|
|
Packit |
cdaae3 |
DECODE_LEB128_UWORD_CK(line_ptr, filename_entry_forms[i],
|
|
Packit |
cdaae3 |
dbg,err,line_ptr_end);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
DECODE_LEB128_UWORD_CK(line_ptr, files_count,
|
|
Packit |
cdaae3 |
dbg,err,line_ptr_end);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
for (i = 0; i < files_count; i++) {
|
|
Packit |
cdaae3 |
Dwarf_File_Entry curline = 0;
|
|
Packit |
cdaae3 |
curline = (Dwarf_File_Entry)
|
|
Packit |
cdaae3 |
malloc(sizeof(struct Dwarf_File_Entry_s));
|
|
Packit |
cdaae3 |
if (curline == NULL) {
|
|
Packit |
cdaae3 |
free(filename_entry_types);
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
memset(curline,0,sizeof(*curline));
|
|
Packit |
cdaae3 |
_dwarf_add_to_files_list(line_context,curline);
|
|
Packit |
cdaae3 |
for(j = 0; j < filename_format_count; j++) {
|
|
Packit |
cdaae3 |
Dwarf_Unsigned dirindex = 0;
|
|
Packit |
cdaae3 |
switch (filename_entry_types[j]) {
|
|
Packit |
cdaae3 |
case DW_LNCT_path:
|
|
Packit |
cdaae3 |
res = _dwarf_decode_line_string_form(dbg,
|
|
Packit |
cdaae3 |
filename_entry_forms[j],
|
|
Packit |
cdaae3 |
local_length_size,
|
|
Packit |
cdaae3 |
&line_ptr,
|
|
Packit |
cdaae3 |
line_ptr_end,
|
|
Packit |
cdaae3 |
(char **)&curline->fi_file_name,
|
|
Packit |
cdaae3 |
err);
|
|
Packit |
cdaae3 |
if (res != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
free(filename_entry_types);
|
|
Packit |
cdaae3 |
free(filename_entry_forms);
|
|
Packit |
cdaae3 |
return res;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
case DW_LNCT_directory_index:
|
|
Packit |
cdaae3 |
res = _dwarf_decode_line_udata_form(dbg,
|
|
Packit |
cdaae3 |
filename_entry_forms[j],
|
|
Packit |
cdaae3 |
&line_ptr,
|
|
Packit |
cdaae3 |
&dirindex,
|
|
Packit |
cdaae3 |
line_ptr_end,
|
|
Packit |
cdaae3 |
err);
|
|
Packit |
cdaae3 |
if (res != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
free(filename_entry_types);
|
|
Packit |
cdaae3 |
free(filename_entry_forms);
|
|
Packit |
cdaae3 |
return res;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
curline->fi_dir_index = dirindex;
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
case DW_LNCT_timestamp:
|
|
Packit |
cdaae3 |
res = _dwarf_decode_line_udata_form(dbg,
|
|
Packit |
cdaae3 |
filename_entry_forms[j],
|
|
Packit |
cdaae3 |
&line_ptr,
|
|
Packit |
cdaae3 |
&curline->fi_time_last_mod,
|
|
Packit |
cdaae3 |
line_ptr_end,
|
|
Packit |
cdaae3 |
err);
|
|
Packit |
cdaae3 |
if (res != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
free(filename_entry_types);
|
|
Packit |
cdaae3 |
free(filename_entry_forms);
|
|
Packit |
cdaae3 |
return res;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
case DW_LNCT_size:
|
|
Packit |
cdaae3 |
res = _dwarf_decode_line_udata_form(dbg,
|
|
Packit |
cdaae3 |
filename_entry_forms[j],
|
|
Packit |
cdaae3 |
&line_ptr,
|
|
Packit |
cdaae3 |
&curline->fi_file_length,
|
|
Packit |
cdaae3 |
line_ptr_end,
|
|
Packit |
cdaae3 |
err);
|
|
Packit |
cdaae3 |
if (res != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
free(filename_entry_types);
|
|
Packit |
cdaae3 |
free(filename_entry_forms);
|
|
Packit |
cdaae3 |
return res;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
case DW_LNCT_MD5: /* Not yet implemented */
|
|
Packit |
cdaae3 |
default:
|
|
Packit |
cdaae3 |
free(filename_entry_types);
|
|
Packit |
cdaae3 |
free(filename_entry_forms);
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if (line_ptr > line_ptr_end) {
|
|
Packit |
cdaae3 |
free(filename_entry_types);
|
|
Packit |
cdaae3 |
free(filename_entry_forms);
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
free(filename_entry_types);
|
|
Packit |
cdaae3 |
free(filename_entry_forms);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
/* For two-level line tables, read the subprograms table. */
|
|
Packit |
cdaae3 |
if (version == EXPERIMENTAL_LINE_TABLES_VERSION) {
|
|
Packit |
cdaae3 |
Dwarf_Unsigned subprog_format_count = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned *subprog_entry_types = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned *subprog_entry_forms = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned subprogs_count = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned i = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned j = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (line_ptr > line_ptr_end) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
subprog_format_count = *(unsigned char *) line_ptr;
|
|
Packit |
cdaae3 |
line_ptr = line_ptr + sizeof(Dwarf_Small);
|
|
Packit |
cdaae3 |
subprog_entry_types = malloc(sizeof(Dwarf_Unsigned) *
|
|
Packit |
cdaae3 |
subprog_format_count);
|
|
Packit |
cdaae3 |
if (subprog_entry_types == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
subprog_entry_forms = malloc(sizeof(Dwarf_Unsigned) *
|
|
Packit |
cdaae3 |
subprog_format_count);
|
|
Packit |
cdaae3 |
if (subprog_entry_forms == NULL) {
|
|
Packit |
cdaae3 |
free(subprog_entry_types);
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
for (i = 0; i < subprog_format_count; i++) {
|
|
Packit |
cdaae3 |
DECODE_LEB128_UWORD_CK(line_ptr, subprog_entry_types[i],
|
|
Packit |
cdaae3 |
dbg,err,line_ptr_end);
|
|
Packit |
cdaae3 |
DECODE_LEB128_UWORD_CK(line_ptr, subprog_entry_forms[i],
|
|
Packit |
cdaae3 |
dbg,err,line_ptr_end);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
DECODE_LEB128_UWORD_CK(line_ptr, subprogs_count,
|
|
Packit |
cdaae3 |
dbg,err,line_ptr_end);
|
|
Packit |
cdaae3 |
line_context->lc_subprogs =
|
|
Packit |
cdaae3 |
malloc(sizeof(struct Dwarf_Subprog_Entry_s) * subprogs_count);
|
|
Packit |
cdaae3 |
if (line_context->lc_subprogs == NULL) {
|
|
Packit |
cdaae3 |
free(subprog_entry_types);
|
|
Packit |
cdaae3 |
free(subprog_entry_forms);
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
memset(line_context->lc_subprogs, 0,
|
|
Packit |
cdaae3 |
sizeof(struct Dwarf_Subprog_Entry_s) * subprogs_count);
|
|
Packit |
cdaae3 |
for (i = 0; i < subprogs_count; i++) {
|
|
Packit |
cdaae3 |
struct Dwarf_Subprog_Entry_s *curline =
|
|
Packit |
cdaae3 |
line_context->lc_subprogs + i;
|
|
Packit |
cdaae3 |
for (j = 0; j < subprog_format_count; j++) {
|
|
Packit |
cdaae3 |
switch (subprog_entry_types[j]) {
|
|
Packit |
cdaae3 |
case DW_LNCT_GNU_subprogram_name:
|
|
Packit |
cdaae3 |
res = _dwarf_decode_line_string_form(dbg,
|
|
Packit |
cdaae3 |
subprog_entry_forms[j],
|
|
Packit |
cdaae3 |
local_length_size,
|
|
Packit |
cdaae3 |
&line_ptr,
|
|
Packit |
cdaae3 |
line_ptr_end,
|
|
Packit |
cdaae3 |
(char **)&curline->ds_subprog_name,
|
|
Packit |
cdaae3 |
err);
|
|
Packit |
cdaae3 |
if (res != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
free(subprog_entry_types);
|
|
Packit |
cdaae3 |
free(subprog_entry_forms);
|
|
Packit |
cdaae3 |
return res;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
case DW_LNCT_GNU_decl_file:
|
|
Packit |
cdaae3 |
res = _dwarf_decode_line_udata_form(dbg,
|
|
Packit |
cdaae3 |
subprog_entry_forms[j],
|
|
Packit |
cdaae3 |
&line_ptr,
|
|
Packit |
cdaae3 |
&curline->ds_decl_file,
|
|
Packit |
cdaae3 |
line_ptr_end,
|
|
Packit |
cdaae3 |
err);
|
|
Packit |
cdaae3 |
if (res != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
free(subprog_entry_forms);
|
|
Packit |
cdaae3 |
free(subprog_entry_types);
|
|
Packit |
cdaae3 |
return res;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
case DW_LNCT_GNU_decl_line:
|
|
Packit |
cdaae3 |
res = _dwarf_decode_line_udata_form(dbg,
|
|
Packit |
cdaae3 |
subprog_entry_forms[j],
|
|
Packit |
cdaae3 |
&line_ptr,
|
|
Packit |
cdaae3 |
&curline->ds_decl_line,
|
|
Packit |
cdaae3 |
line_ptr_end,
|
|
Packit |
cdaae3 |
err);
|
|
Packit |
cdaae3 |
if (res != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
free(subprog_entry_forms);
|
|
Packit |
cdaae3 |
free(subprog_entry_types);
|
|
Packit |
cdaae3 |
return res;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
default:
|
|
Packit |
cdaae3 |
free(subprog_entry_forms);
|
|
Packit |
cdaae3 |
free(subprog_entry_types);
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if (line_ptr >= line_ptr_end) {
|
|
Packit |
cdaae3 |
free(subprog_entry_types);
|
|
Packit |
cdaae3 |
free(subprog_entry_forms);
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_LINE_NUMBER_HEADER_ERROR);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
free(subprog_entry_types);
|
|
Packit |
cdaae3 |
free(subprog_entry_forms);
|
|
Packit |
cdaae3 |
line_context->lc_subprogs_count = subprogs_count;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if (version == EXPERIMENTAL_LINE_TABLES_VERSION) {
|
|
Packit |
cdaae3 |
lp_begin = line_context->lc_line_prologue_start +
|
|
Packit |
cdaae3 |
line_context->lc_logicals_table_offset;
|
|
Packit |
cdaae3 |
} else {
|
|
Packit |
cdaae3 |
lp_begin = line_context->lc_line_prologue_start +
|
|
Packit |
cdaae3 |
line_context->lc_prologue_length;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if(line_ptr > line_ptr_end) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_LINE_OFFSET_BAD);
|
|
Packit |
cdaae3 |
return DW_DLV_ERROR;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if (line_ptr != lp_begin) {
|
|
Packit |
cdaae3 |
if (line_ptr > lp_begin) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, err, DW_DLE_LINE_PROLOG_LENGTH_BAD);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
} else {
|
|
Packit |
cdaae3 |
/* Bug in compiler. These
|
|
Packit |
cdaae3 |
bytes are really part of the instruction
|
|
Packit |
cdaae3 |
stream. The line_context->lc_prologue_length is
|
|
Packit |
cdaae3 |
wrong (12 too high). */
|
|
Packit |
cdaae3 |
if (bogus_bytes_ptr) {
|
|
Packit |
cdaae3 |
*bogus_bytes_ptr = line_ptr;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if (bogus_bytes) {
|
|
Packit |
cdaae3 |
/* How far off things are. We expect the
|
|
Packit |
cdaae3 |
value 12 ! */
|
|
Packit |
cdaae3 |
*bogus_bytes = (lp_begin - line_ptr);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
/* Ignore the lp_begin calc. Assume line_ptr right.
|
|
Packit |
cdaae3 |
Making up for compiler bug. */
|
|
Packit |
cdaae3 |
lp_begin = line_ptr;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
line_context->lc_line_ptr_start = lp_begin;
|
|
Packit |
cdaae3 |
if (line_context->lc_actuals_table_offset) {
|
|
Packit |
cdaae3 |
/* This means two tables. */
|
|
Packit |
cdaae3 |
line_context->lc_table_count = 2;
|
|
Packit |
cdaae3 |
} else {
|
|
Packit |
cdaae3 |
if (line_context->lc_line_ptr_end > lp_begin) {
|
|
Packit |
cdaae3 |
line_context->lc_table_count = 1;
|
|
Packit |
cdaae3 |
} else {
|
|
Packit |
cdaae3 |
line_context->lc_table_count = 0;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
*updated_data_start_out = lp_begin;
|
|
Packit |
cdaae3 |
return DW_DLV_OK;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Read one line table program. For two-level line tables, this
|
|
Packit |
cdaae3 |
function is called once for each table. */
|
|
Packit |
cdaae3 |
static int
|
|
Packit |
cdaae3 |
read_line_table_program(Dwarf_Debug dbg,
|
|
Packit |
cdaae3 |
Dwarf_Small *line_ptr,
|
|
Packit |
cdaae3 |
Dwarf_Small *line_ptr_end,
|
|
Packit |
cdaae3 |
UNUSEDARG Dwarf_Small *orig_line_ptr,
|
|
Packit |
cdaae3 |
UNUSEDARG Dwarf_Small *section_start,
|
|
Packit |
cdaae3 |
Dwarf_Line_Context line_context,
|
|
Packit |
cdaae3 |
Dwarf_Half address_size,
|
|
Packit |
cdaae3 |
Dwarf_Bool doaddrs, /* Only true if SGI IRIX rqs calling. */
|
|
Packit |
cdaae3 |
Dwarf_Bool dolines,
|
|
Packit |
cdaae3 |
Dwarf_Bool is_single_table,
|
|
Packit |
cdaae3 |
Dwarf_Bool is_actuals_table,
|
|
Packit |
cdaae3 |
Dwarf_Error *error,
|
|
Packit |
cdaae3 |
UNUSEDARG int *err_count_out)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
Dwarf_Word i = 0;
|
|
Packit |
cdaae3 |
Dwarf_File_Entry cur_file_entry = 0;
|
|
Packit |
cdaae3 |
Dwarf_Line *logicals = line_context->lc_linebuf_logicals;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned logicals_count = line_context->lc_linecount_logicals;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
struct Dwarf_Line_Registers_s regs;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* This is a pointer to the current line being added to the line
|
|
Packit |
cdaae3 |
matrix. */
|
|
Packit |
cdaae3 |
Dwarf_Line curr_line = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* These variables are used to decode leb128 numbers. Leb128_num
|
|
Packit |
cdaae3 |
holds the decoded number, and leb128_length is its length in
|
|
Packit |
cdaae3 |
bytes. */
|
|
Packit |
cdaae3 |
Dwarf_Word leb128_num = 0;
|
|
Packit |
cdaae3 |
Dwarf_Sword advance_line = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* This is the operand of the latest fixed_advance_pc extended
|
|
Packit |
cdaae3 |
opcode. */
|
|
Packit |
cdaae3 |
Dwarf_Half fixed_advance_pc = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Counts the number of lines in the line matrix. */
|
|
Packit |
cdaae3 |
Dwarf_Word line_count = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* This is the length of an extended opcode instr. */
|
|
Packit |
cdaae3 |
Dwarf_Word instr_length = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Used to chain together pointers to line table entries that are
|
|
Packit |
cdaae3 |
later used to create a block of Dwarf_Line entries. */
|
|
Packit |
cdaae3 |
Dwarf_Chain chain_line = NULL;
|
|
Packit |
cdaae3 |
Dwarf_Chain head_chain = NULL;
|
|
Packit |
cdaae3 |
Dwarf_Chain curr_chain = NULL;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* This points to a block of Dwarf_Lines, a pointer to which is
|
|
Packit |
cdaae3 |
returned in linebuf. */
|
|
Packit |
cdaae3 |
Dwarf_Line *block_line = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Mark a line record as being DW_LNS_set_address */
|
|
Packit |
cdaae3 |
Dwarf_Bool is_addr_set = false;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Initialize the one state machine variable that depends on the
|
|
Packit |
cdaae3 |
prefix. */
|
|
Packit |
cdaae3 |
_dwarf_set_line_table_regs_default_values(®s,
|
|
Packit |
cdaae3 |
line_context->lc_default_is_stmt);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Start of statement program. */
|
|
Packit |
cdaae3 |
while (line_ptr < line_ptr_end) {
|
|
Packit |
cdaae3 |
int type = 0;
|
|
Packit |
cdaae3 |
Dwarf_Small opcode = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
#ifdef PRINTING_DETAILS
|
|
Packit |
cdaae3 |
dwarf_printf(dbg,
|
|
Packit |
cdaae3 |
" [0x%06" DW_PR_DSx "] ",
|
|
Packit |
cdaae3 |
(Dwarf_Signed) (line_ptr - section_start));
|
|
Packit |
cdaae3 |
#endif /* PRINTING_DETAILS */
|
|
Packit |
cdaae3 |
opcode = *(Dwarf_Small *) line_ptr;
|
|
Packit |
cdaae3 |
line_ptr++;
|
|
Packit |
cdaae3 |
/* 'type' is the output */
|
|
Packit |
cdaae3 |
WHAT_IS_OPCODE(type, opcode, line_context->lc_opcode_base,
|
|
Packit |
cdaae3 |
line_context->lc_opcode_length_table, line_ptr,
|
|
Packit |
cdaae3 |
line_context->lc_std_op_count);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (type == LOP_DISCARD) {
|
|
Packit |
cdaae3 |
int oc = 0;
|
|
Packit |
cdaae3 |
int opcnt = line_context->lc_opcode_length_table[opcode];
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
#ifdef PRINTING_DETAILS
|
|
Packit |
cdaae3 |
dwarf_printf(dbg,
|
|
Packit |
cdaae3 |
"*** DWARF CHECK: DISCARD standard opcode %d "
|
|
Packit |
cdaae3 |
"with %d operands: "
|
|
Packit |
cdaae3 |
"not understood.", opcode, opcnt);
|
|
Packit |
cdaae3 |
*err_count_out += 1;
|
|
Packit |
cdaae3 |
#endif /* PRINTING_DETAILS */
|
|
Packit |
cdaae3 |
for (oc = 0; oc < opcnt; oc++) {
|
|
Packit |
cdaae3 |
/* Read and discard operands we don't
|
|
Packit |
cdaae3 |
understand.
|
|
Packit |
cdaae3 |
arbitrary choice of unsigned read.
|
|
Packit |
cdaae3 |
signed read would work as well. */
|
|
Packit |
cdaae3 |
UNUSEDARG Dwarf_Unsigned utmp2 = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
DECODE_LEB128_UWORD_CK(line_ptr, utmp2,
|
|
Packit |
cdaae3 |
dbg,error,line_ptr_end);
|
|
Packit |
cdaae3 |
#ifdef PRINTING_DETAILS
|
|
Packit |
cdaae3 |
dwarf_printf(dbg,
|
|
Packit |
cdaae3 |
" %" DW_PR_DUu
|
|
Packit |
cdaae3 |
" (0x%" DW_PR_XZEROS DW_PR_DUx ")",
|
|
Packit |
cdaae3 |
(Dwarf_Unsigned) utmp2,
|
|
Packit |
cdaae3 |
(Dwarf_Unsigned) utmp2);
|
|
Packit |
cdaae3 |
#endif /* PRINTING_DETAILS */
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
#ifdef PRINTING_DETAILS
|
|
Packit |
cdaae3 |
dwarf_printf(dbg,"***\n");
|
|
Packit |
cdaae3 |
#endif /* PRINTING_DETAILS */
|
|
Packit |
cdaae3 |
} else if (type == LOP_SPECIAL) {
|
|
Packit |
cdaae3 |
/* This op code is a special op in the object, no matter
|
|
Packit |
cdaae3 |
that it might fall into the standard op range in this
|
|
Packit |
cdaae3 |
compile. That is, these are special opcodes between
|
|
Packit |
cdaae3 |
opcode_base and MAX_LINE_OP_CODE. (including
|
|
Packit |
cdaae3 |
opcode_base and MAX_LINE_OP_CODE) */
|
|
Packit |
cdaae3 |
#ifdef PRINTING_DETAILS
|
|
Packit |
cdaae3 |
char special[50];
|
|
Packit |
cdaae3 |
unsigned origop = opcode;
|
|
Packit |
cdaae3 |
#endif /* PRINTING_DETAILS */
|
|
Packit |
cdaae3 |
Dwarf_Unsigned operation_advance = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
opcode = opcode - line_context->lc_opcode_base;
|
|
Packit |
cdaae3 |
operation_advance = (opcode / line_context->lc_line_range);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (line_context->lc_maximum_ops_per_instruction < 2) {
|
|
Packit |
cdaae3 |
regs.lr_address = regs.lr_address + (operation_advance *
|
|
Packit |
cdaae3 |
line_context->lc_minimum_instruction_length);
|
|
Packit |
cdaae3 |
} else {
|
|
Packit |
cdaae3 |
regs.lr_address = regs.lr_address +
|
|
Packit |
cdaae3 |
(line_context->lc_minimum_instruction_length *
|
|
Packit |
cdaae3 |
((regs.lr_op_index + operation_advance)/
|
|
Packit |
cdaae3 |
line_context->lc_maximum_ops_per_instruction));
|
|
Packit |
cdaae3 |
regs.lr_op_index = (regs.lr_op_index +operation_advance)%
|
|
Packit |
cdaae3 |
line_context->lc_maximum_ops_per_instruction;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
regs.lr_line = regs.lr_line + line_context->lc_line_base +
|
|
Packit |
cdaae3 |
opcode % line_context->lc_line_range;
|
|
Packit |
cdaae3 |
#ifdef PRINTING_DETAILS
|
|
Packit |
cdaae3 |
sprintf(special, "Specialop %3u", origop);
|
|
Packit |
cdaae3 |
print_line_detail(dbg,special,
|
|
Packit |
cdaae3 |
opcode,line_count+1, ®s,is_single_table, is_actuals_table);
|
|
Packit |
cdaae3 |
#endif /* PRINTING_DETAILS */
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (dolines) {
|
|
Packit |
cdaae3 |
curr_line =
|
|
Packit |
cdaae3 |
(Dwarf_Line) _dwarf_get_alloc(dbg, DW_DLA_LINE, 1);
|
|
Packit |
cdaae3 |
if (curr_line == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_free_chain_entries(dbg,head_chain,line_count);
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Mark a line record as being DW_LNS_set_address */
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.li_is_addr_set = is_addr_set;
|
|
Packit |
cdaae3 |
is_addr_set = false;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
curr_line->li_address = regs.lr_address;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.li_file =
|
|
Packit |
cdaae3 |
(Dwarf_Sword) regs.lr_file;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.li_line =
|
|
Packit |
cdaae3 |
(Dwarf_Sword) regs.lr_line;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.li_column =
|
|
Packit |
cdaae3 |
(Dwarf_Half) regs.lr_column;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.li_is_stmt =
|
|
Packit |
cdaae3 |
regs.lr_is_stmt;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.li_basic_block =
|
|
Packit |
cdaae3 |
regs.lr_basic_block;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.li_end_sequence =
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.
|
|
Packit |
cdaae3 |
li_epilogue_begin = regs.lr_epilogue_begin;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.li_prologue_end =
|
|
Packit |
cdaae3 |
regs.lr_prologue_end;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.li_isa = regs.lr_isa;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.li_discriminator =
|
|
Packit |
cdaae3 |
regs.lr_discriminator;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.li_call_context =
|
|
Packit |
cdaae3 |
regs.lr_call_context;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.li_subprogram =
|
|
Packit |
cdaae3 |
regs.lr_subprogram;
|
|
Packit |
cdaae3 |
curr_line->li_context = line_context;
|
|
Packit |
cdaae3 |
curr_line->li_is_actuals_table = is_actuals_table;
|
|
Packit |
cdaae3 |
line_count++;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
chain_line = (Dwarf_Chain)
|
|
Packit |
cdaae3 |
_dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
|
|
Packit |
cdaae3 |
if (chain_line == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_free_chain_entries(dbg,head_chain,line_count);
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
chain_line->ch_item = curr_line;
|
|
Packit |
cdaae3 |
_dwarf_update_chain_list(chain_line,&head_chain,&curr_chain);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
regs.lr_basic_block = false;
|
|
Packit |
cdaae3 |
regs.lr_prologue_end = false;
|
|
Packit |
cdaae3 |
regs.lr_epilogue_begin = false;
|
|
Packit |
cdaae3 |
regs.lr_discriminator = 0;
|
|
Packit |
cdaae3 |
} else if (type == LOP_STANDARD) {
|
|
Packit |
cdaae3 |
switch (opcode) {
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
case DW_LNS_copy:{
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
#ifdef PRINTING_DETAILS
|
|
Packit |
cdaae3 |
print_line_detail(dbg,"DW_LNS_copy",
|
|
Packit |
cdaae3 |
opcode,line_count+1, ®s,is_single_table, is_actuals_table);
|
|
Packit |
cdaae3 |
#endif /* PRINTING_DETAILS */
|
|
Packit |
cdaae3 |
if (dolines) {
|
|
Packit |
cdaae3 |
curr_line = (Dwarf_Line) _dwarf_get_alloc(dbg,
|
|
Packit |
cdaae3 |
DW_DLA_LINE, 1);
|
|
Packit |
cdaae3 |
if (curr_line == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_free_chain_entries(dbg,head_chain,line_count);
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Mark a line record as being DW_LNS_set_address */
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.li_is_addr_set =
|
|
Packit |
cdaae3 |
is_addr_set;
|
|
Packit |
cdaae3 |
is_addr_set = false;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
curr_line->li_address = regs.lr_address;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.li_file =
|
|
Packit |
cdaae3 |
(Dwarf_Sword) regs.lr_file;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.li_line =
|
|
Packit |
cdaae3 |
(Dwarf_Sword) regs.lr_line;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.li_column =
|
|
Packit |
cdaae3 |
(Dwarf_Half) regs.lr_column;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.li_is_stmt =
|
|
Packit |
cdaae3 |
regs.lr_is_stmt;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.
|
|
Packit |
cdaae3 |
li_basic_block = regs.lr_basic_block;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.
|
|
Packit |
cdaae3 |
li_end_sequence = regs.lr_end_sequence;
|
|
Packit |
cdaae3 |
curr_line->li_context = line_context;
|
|
Packit |
cdaae3 |
curr_line->li_is_actuals_table = is_actuals_table;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.
|
|
Packit |
cdaae3 |
li_epilogue_begin = regs.lr_epilogue_begin;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.
|
|
Packit |
cdaae3 |
li_prologue_end = regs.lr_prologue_end;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.li_isa = regs.lr_isa;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.li_discriminator =
|
|
Packit |
cdaae3 |
regs.lr_discriminator;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.li_call_context =
|
|
Packit |
cdaae3 |
regs.lr_call_context;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.li_subprogram =
|
|
Packit |
cdaae3 |
regs.lr_subprogram;
|
|
Packit |
cdaae3 |
line_count++;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
chain_line = (Dwarf_Chain)
|
|
Packit |
cdaae3 |
_dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
|
|
Packit |
cdaae3 |
if (chain_line == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_free_chain_entries(dbg,head_chain,line_count);
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
chain_line->ch_item = curr_line;
|
|
Packit |
cdaae3 |
_dwarf_update_chain_list(chain_line,&head_chain,&curr_chain);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
regs.lr_basic_block = false;
|
|
Packit |
cdaae3 |
regs.lr_prologue_end = false;
|
|
Packit |
cdaae3 |
regs.lr_epilogue_begin = false;
|
|
Packit |
cdaae3 |
regs.lr_discriminator = 0;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
case DW_LNS_advance_pc:{
|
|
Packit |
cdaae3 |
Dwarf_Unsigned utmp2 = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
DECODE_LEB128_UWORD_CK(line_ptr, utmp2,
|
|
Packit |
cdaae3 |
dbg,error,line_ptr_end);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
#ifdef PRINTING_DETAILS
|
|
Packit |
cdaae3 |
dwarf_printf(dbg,
|
|
Packit |
cdaae3 |
"DW_LNS_advance_pc val %"
|
|
Packit |
cdaae3 |
DW_PR_DSd " 0x%"
|
|
Packit |
cdaae3 |
DW_PR_XZEROS DW_PR_DUx "\n",
|
|
Packit |
cdaae3 |
(Dwarf_Signed) (Dwarf_Word) utmp2,
|
|
Packit |
cdaae3 |
(Dwarf_Unsigned) (Dwarf_Word) utmp2);
|
|
Packit |
cdaae3 |
#endif /* PRINTING_DETAILS */
|
|
Packit |
cdaae3 |
leb128_num = (Dwarf_Word) utmp2;
|
|
Packit |
cdaae3 |
regs.lr_address = regs.lr_address +
|
|
Packit |
cdaae3 |
line_context->lc_minimum_instruction_length *
|
|
Packit |
cdaae3 |
leb128_num;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
case DW_LNS_advance_line:{
|
|
Packit |
cdaae3 |
Dwarf_Signed stmp = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
DECODE_LEB128_SWORD_CK(line_ptr, stmp,
|
|
Packit |
cdaae3 |
dbg,error,line_ptr_end);
|
|
Packit |
cdaae3 |
advance_line = (Dwarf_Sword) stmp;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
#ifdef PRINTING_DETAILS
|
|
Packit |
cdaae3 |
dwarf_printf(dbg,
|
|
Packit |
cdaae3 |
"DW_LNS_advance_line val %" DW_PR_DSd " 0x%"
|
|
Packit |
cdaae3 |
DW_PR_XZEROS DW_PR_DSx "\n",
|
|
Packit |
cdaae3 |
(Dwarf_Signed) advance_line,
|
|
Packit |
cdaae3 |
(Dwarf_Signed) advance_line);
|
|
Packit |
cdaae3 |
#endif /* PRINTING_DETAILS */
|
|
Packit |
cdaae3 |
regs.lr_line = regs.lr_line + advance_line;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
case DW_LNS_set_file:{
|
|
Packit |
cdaae3 |
Dwarf_Unsigned utmp2 = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
DECODE_LEB128_UWORD_CK(line_ptr, utmp2,
|
|
Packit |
cdaae3 |
dbg,error,line_ptr_end);
|
|
Packit |
cdaae3 |
regs.lr_file = (Dwarf_Word) utmp2;
|
|
Packit |
cdaae3 |
#ifdef PRINTING_DETAILS
|
|
Packit |
cdaae3 |
dwarf_printf(dbg,
|
|
Packit |
cdaae3 |
"DW_LNS_set_file %ld\n", (long) regs.lr_file);
|
|
Packit |
cdaae3 |
#endif /* PRINTING_DETAILS */
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
case DW_LNS_set_column:{
|
|
Packit |
cdaae3 |
Dwarf_Unsigned utmp2 = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
DECODE_LEB128_UWORD_CK(line_ptr, utmp2,
|
|
Packit |
cdaae3 |
dbg,error,line_ptr_end);
|
|
Packit |
cdaae3 |
regs.lr_column = (Dwarf_Word) utmp2;
|
|
Packit |
cdaae3 |
#ifdef PRINTING_DETAILS
|
|
Packit |
cdaae3 |
dwarf_printf(dbg,
|
|
Packit |
cdaae3 |
"DW_LNS_set_column val %" DW_PR_DSd " 0x%"
|
|
Packit |
cdaae3 |
DW_PR_XZEROS DW_PR_DSx "\n",
|
|
Packit |
cdaae3 |
(Dwarf_Signed) regs.lr_column,
|
|
Packit |
cdaae3 |
(Dwarf_Signed) regs.lr_column);
|
|
Packit |
cdaae3 |
#endif /* PRINTING_DETAILS */
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
case DW_LNS_negate_stmt:{
|
|
Packit |
cdaae3 |
regs.lr_is_stmt = !regs.lr_is_stmt;
|
|
Packit |
cdaae3 |
#ifdef PRINTING_DETAILS
|
|
Packit |
cdaae3 |
dwarf_printf(dbg,
|
|
Packit |
cdaae3 |
"DW_LNS_negate_stmt\n");
|
|
Packit |
cdaae3 |
#endif /* PRINTING_DETAILS */
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
case DW_LNS_set_basic_block:{
|
|
Packit |
cdaae3 |
regs.lr_basic_block = true;
|
|
Packit |
cdaae3 |
#ifdef PRINTING_DETAILS
|
|
Packit |
cdaae3 |
dwarf_printf(dbg,
|
|
Packit |
cdaae3 |
"DW_LNS_set_basic_block\n");
|
|
Packit |
cdaae3 |
#endif /* PRINTING_DETAILS */
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
case DW_LNS_const_add_pc:{
|
|
Packit |
cdaae3 |
opcode = MAX_LINE_OP_CODE - line_context->lc_opcode_base;
|
|
Packit |
cdaae3 |
if (line_context->lc_maximum_ops_per_instruction < 2) {
|
|
Packit |
cdaae3 |
Dwarf_Unsigned operation_advance =
|
|
Packit |
cdaae3 |
(opcode / line_context->lc_line_range);
|
|
Packit |
cdaae3 |
regs.lr_address = regs.lr_address +
|
|
Packit |
cdaae3 |
line_context->lc_minimum_instruction_length *
|
|
Packit |
cdaae3 |
operation_advance;
|
|
Packit |
cdaae3 |
} else {
|
|
Packit |
cdaae3 |
Dwarf_Unsigned operation_advance =
|
|
Packit |
cdaae3 |
(opcode / line_context->lc_line_range);
|
|
Packit |
cdaae3 |
regs.lr_address = regs.lr_address +
|
|
Packit |
cdaae3 |
line_context->lc_minimum_instruction_length *
|
|
Packit |
cdaae3 |
((regs.lr_op_index + operation_advance)/
|
|
Packit |
cdaae3 |
line_context->lc_maximum_ops_per_instruction);
|
|
Packit |
cdaae3 |
regs.lr_op_index = (regs.lr_op_index +operation_advance)%
|
|
Packit |
cdaae3 |
line_context->lc_maximum_ops_per_instruction;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
#ifdef PRINTING_DETAILS
|
|
Packit |
cdaae3 |
dwarf_printf(dbg,
|
|
Packit |
cdaae3 |
"DW_LNS_const_add_pc new address 0x%"
|
|
Packit |
cdaae3 |
DW_PR_XZEROS DW_PR_DSx "\n",
|
|
Packit |
cdaae3 |
(Dwarf_Signed) regs.lr_address);
|
|
Packit |
cdaae3 |
#endif /* PRINTING_DETAILS */
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
case DW_LNS_fixed_advance_pc:{
|
|
Packit |
cdaae3 |
READ_UNALIGNED_CK(dbg, fixed_advance_pc, Dwarf_Half,
|
|
Packit |
cdaae3 |
line_ptr, sizeof(Dwarf_Half),error,line_ptr_end);
|
|
Packit |
cdaae3 |
line_ptr += sizeof(Dwarf_Half);
|
|
Packit |
cdaae3 |
if (line_ptr > line_ptr_end) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error,
|
|
Packit |
cdaae3 |
DW_DLE_LINE_TABLE_BAD);
|
|
Packit |
cdaae3 |
return DW_DLV_ERROR;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
regs.lr_address = regs.lr_address + fixed_advance_pc;
|
|
Packit |
cdaae3 |
regs.lr_op_index = 0;
|
|
Packit |
cdaae3 |
#ifdef PRINTING_DETAILS
|
|
Packit |
cdaae3 |
dwarf_printf(dbg,
|
|
Packit |
cdaae3 |
"DW_LNS_fixed_advance_pc val %" DW_PR_DSd
|
|
Packit |
cdaae3 |
" 0x%" DW_PR_XZEROS DW_PR_DSx
|
|
Packit |
cdaae3 |
" new address 0x%" DW_PR_XZEROS DW_PR_DSx "\n",
|
|
Packit |
cdaae3 |
(Dwarf_Signed) fixed_advance_pc,
|
|
Packit |
cdaae3 |
(Dwarf_Signed) fixed_advance_pc,
|
|
Packit |
cdaae3 |
(Dwarf_Signed) regs.lr_address);
|
|
Packit |
cdaae3 |
#endif /* PRINTING_DETAILS */
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* New in DWARF3 */
|
|
Packit |
cdaae3 |
case DW_LNS_set_prologue_end:{
|
|
Packit |
cdaae3 |
regs.lr_prologue_end = true;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
/* New in DWARF3 */
|
|
Packit |
cdaae3 |
case DW_LNS_set_epilogue_begin:{
|
|
Packit |
cdaae3 |
regs.lr_epilogue_begin = true;
|
|
Packit |
cdaae3 |
#ifdef PRINTING_DETAILS
|
|
Packit |
cdaae3 |
dwarf_printf(dbg,
|
|
Packit |
cdaae3 |
"DW_LNS_set_prologue_end set true.\n");
|
|
Packit |
cdaae3 |
#endif /* PRINTING_DETAILS */
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* New in DWARF3 */
|
|
Packit |
cdaae3 |
case DW_LNS_set_isa:{
|
|
Packit |
cdaae3 |
Dwarf_Unsigned utmp2 = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
DECODE_LEB128_UWORD_CK(line_ptr, utmp2,
|
|
Packit |
cdaae3 |
dbg,error,line_ptr_end);
|
|
Packit |
cdaae3 |
regs.lr_isa = utmp2;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
#ifdef PRINTING_DETAILS
|
|
Packit |
cdaae3 |
dwarf_printf(dbg,
|
|
Packit |
cdaae3 |
"DW_LNS_set_isa new value 0x%"
|
|
Packit |
cdaae3 |
DW_PR_XZEROS DW_PR_DUx ".\n",
|
|
Packit |
cdaae3 |
(Dwarf_Unsigned) utmp2);
|
|
Packit |
cdaae3 |
#endif /* PRINTING_DETAILS */
|
|
Packit |
cdaae3 |
if (regs.lr_isa != utmp2) {
|
|
Packit |
cdaae3 |
/* The value of the isa did not fit in our
|
|
Packit |
cdaae3 |
local so we record it wrong. declare an
|
|
Packit |
cdaae3 |
error. */
|
|
Packit |
cdaae3 |
_dwarf_free_chain_entries(dbg,head_chain,line_count);
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error,
|
|
Packit |
cdaae3 |
DW_DLE_LINE_NUM_OPERANDS_BAD);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Experimental two-level line tables */
|
|
Packit |
cdaae3 |
/* DW_LNS_set_address_from_logical and
|
|
Packit |
cdaae3 |
DW_LNS_set_subprogram
|
|
Packit |
cdaae3 |
share the same opcode. Disambiguate by checking
|
|
Packit |
cdaae3 |
is_actuals_table. */
|
|
Packit |
cdaae3 |
case DW_LNS_set_subprogram:
|
|
Packit |
cdaae3 |
if (is_actuals_table) {
|
|
Packit |
cdaae3 |
/* DW_LNS_set_address_from_logical */
|
|
Packit |
cdaae3 |
Dwarf_Signed stmp = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
DECODE_LEB128_SWORD_CK(line_ptr, stmp,
|
|
Packit |
cdaae3 |
dbg,error,line_ptr_end);
|
|
Packit |
cdaae3 |
advance_line = (Dwarf_Sword) stmp;
|
|
Packit |
cdaae3 |
regs.lr_line = regs.lr_line + advance_line;
|
|
Packit |
cdaae3 |
if (regs.lr_line >= 1 &&
|
|
Packit |
cdaae3 |
regs.lr_line - 1 < logicals_count) {
|
|
Packit |
cdaae3 |
regs.lr_address =
|
|
Packit |
cdaae3 |
logicals[regs.lr_line - 1]->li_address;
|
|
Packit |
cdaae3 |
regs.lr_op_index = 0;
|
|
Packit |
cdaae3 |
#ifdef PRINTING_DETAILS
|
|
Packit |
cdaae3 |
dwarf_printf(dbg,"DW_LNS_set_address_from_logical "
|
|
Packit |
cdaae3 |
"%" DW_PR_DSd " 0x%" DW_PR_XZEROS DW_PR_DSx,
|
|
Packit |
cdaae3 |
stmp,stmp);
|
|
Packit |
cdaae3 |
dwarf_printf(dbg," newaddr="
|
|
Packit |
cdaae3 |
" 0x%" DW_PR_XZEROS DW_PR_DUx ".\n",
|
|
Packit |
cdaae3 |
regs.lr_address);
|
|
Packit |
cdaae3 |
#endif /* PRINTING_DETAILS */
|
|
Packit |
cdaae3 |
} else {
|
|
Packit |
cdaae3 |
#ifdef PRINTING_DETAILS
|
|
Packit |
cdaae3 |
dwarf_printf(dbg,"DW_LNS_set_address_from_logical line is "
|
|
Packit |
cdaae3 |
"%" DW_PR_DSd " 0x%" DW_PR_XZEROS DW_PR_DSx ".\n",
|
|
Packit |
cdaae3 |
(Dwarf_Signed)regs.lr_line,
|
|
Packit |
cdaae3 |
(Dwarf_Signed)regs.lr_line);
|
|
Packit |
cdaae3 |
#endif /* PRINTING_DETAILS */
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
} else {
|
|
Packit |
cdaae3 |
/* DW_LNS_set_subprogram, building logicals table. */
|
|
Packit |
cdaae3 |
Dwarf_Unsigned utmp2 = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
regs.lr_call_context = 0;
|
|
Packit |
cdaae3 |
DECODE_LEB128_UWORD_CK(line_ptr, utmp2,
|
|
Packit |
cdaae3 |
dbg,error,line_ptr_end);
|
|
Packit |
cdaae3 |
regs.lr_subprogram = (Dwarf_Word) utmp2;
|
|
Packit |
cdaae3 |
#ifdef PRINTING_DETAILS
|
|
Packit |
cdaae3 |
dwarf_printf(dbg,"DW_LNS_set_subprogram "
|
|
Packit |
cdaae3 |
"%" DW_PR_DSd " 0x%" DW_PR_XZEROS DW_PR_DSx "\n",
|
|
Packit |
cdaae3 |
(Dwarf_Signed)utmp2,(Dwarf_Signed)utmp2);
|
|
Packit |
cdaae3 |
#endif /* PRINTING_DETAILS */
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Experimental two-level line tables */
|
|
Packit |
cdaae3 |
case DW_LNS_inlined_call: {
|
|
Packit |
cdaae3 |
Dwarf_Signed stmp = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
DECODE_LEB128_SWORD_CK(line_ptr, stmp,
|
|
Packit |
cdaae3 |
dbg,error,line_ptr_end);
|
|
Packit |
cdaae3 |
regs.lr_call_context = line_count + stmp;
|
|
Packit |
cdaae3 |
DECODE_LEB128_UWORD_CK(line_ptr, regs.lr_subprogram,
|
|
Packit |
cdaae3 |
dbg,error,line_ptr_end);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
#ifdef PRINTING_DETAILS
|
|
Packit |
cdaae3 |
dwarf_printf(dbg,"DW_LNS_inlined_call "
|
|
Packit |
cdaae3 |
"%" DW_PR_DSd " (0x%" DW_PR_XZEROS DW_PR_DSx "),"
|
|
Packit |
cdaae3 |
"%" DW_PR_DSd " (0x%" DW_PR_XZEROS DW_PR_DSx ")",
|
|
Packit |
cdaae3 |
stmp,stmp,
|
|
Packit |
cdaae3 |
(Dwarf_Signed)regs.lr_subprogram,
|
|
Packit |
cdaae3 |
(Dwarf_Signed)regs.lr_subprogram);
|
|
Packit |
cdaae3 |
dwarf_printf(dbg," callcontext="
|
|
Packit |
cdaae3 |
"%" DW_PR_DSd " (0x%" DW_PR_XZEROS DW_PR_DSx ")\n",
|
|
Packit |
cdaae3 |
(Dwarf_Signed)regs.lr_call_context,
|
|
Packit |
cdaae3 |
(Dwarf_Signed)regs.lr_call_context);
|
|
Packit |
cdaae3 |
#endif /* PRINTING_DETAILS */
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Experimental two-level line tables */
|
|
Packit |
cdaae3 |
case DW_LNS_pop_context: {
|
|
Packit |
cdaae3 |
Dwarf_Unsigned logical_num = regs.lr_call_context;
|
|
Packit |
cdaae3 |
Dwarf_Chain logical_chain = head_chain;
|
|
Packit |
cdaae3 |
Dwarf_Line logical_line = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (logical_num > 0 && logical_num <= line_count) {
|
|
Packit |
cdaae3 |
for (i = 1; i < logical_num; i++) {
|
|
Packit |
cdaae3 |
logical_chain = logical_chain->ch_next;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
logical_line = (Dwarf_Line) logical_chain->ch_item;
|
|
Packit |
cdaae3 |
regs.lr_file =
|
|
Packit |
cdaae3 |
logical_line->li_addr_line.li_l_data.li_file;
|
|
Packit |
cdaae3 |
regs.lr_line =
|
|
Packit |
cdaae3 |
logical_line->li_addr_line.li_l_data.li_line;
|
|
Packit |
cdaae3 |
regs.lr_column =
|
|
Packit |
cdaae3 |
logical_line->li_addr_line.li_l_data.li_column;
|
|
Packit |
cdaae3 |
regs.lr_discriminator =
|
|
Packit |
cdaae3 |
logical_line->li_addr_line.li_l_data.li_discriminator;
|
|
Packit |
cdaae3 |
regs.lr_is_stmt =
|
|
Packit |
cdaae3 |
logical_line->li_addr_line.li_l_data.li_is_stmt;
|
|
Packit |
cdaae3 |
regs.lr_call_context =
|
|
Packit |
cdaae3 |
logical_line->li_addr_line.li_l_data.li_call_context;
|
|
Packit |
cdaae3 |
regs.lr_subprogram =
|
|
Packit |
cdaae3 |
logical_line->li_addr_line.li_l_data.li_subprogram;
|
|
Packit |
cdaae3 |
#ifdef PRINTING_DETAILS
|
|
Packit |
cdaae3 |
dwarf_printf(dbg,"DW_LNS_pop_context set from logical "
|
|
Packit |
cdaae3 |
"%" DW_PR_DUu " (0x%" DW_PR_XZEROS DW_PR_DUx ")\n",
|
|
Packit |
cdaae3 |
logical_num,logical_num);
|
|
Packit |
cdaae3 |
} else {
|
|
Packit |
cdaae3 |
dwarf_printf(dbg,"DW_LNS_pop_context does nothing, logical"
|
|
Packit |
cdaae3 |
"%" DW_PR_DUu " (0x%" DW_PR_XZEROS DW_PR_DUx ")\n",
|
|
Packit |
cdaae3 |
logical_num,logical_num);
|
|
Packit |
cdaae3 |
#endif /* PRINTING_DETAILS */
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
} /* End switch (opcode) */
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
} else if (type == LOP_EXTENDED) {
|
|
Packit |
cdaae3 |
Dwarf_Unsigned utmp3 = 0;
|
|
Packit |
cdaae3 |
Dwarf_Small ext_opcode = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
DECODE_LEB128_UWORD_CK(line_ptr, utmp3,
|
|
Packit |
cdaae3 |
dbg,error,line_ptr_end);
|
|
Packit |
cdaae3 |
instr_length = (Dwarf_Word) utmp3;
|
|
Packit |
cdaae3 |
/* Dwarf_Small is a ubyte and the extended opcode is a
|
|
Packit |
cdaae3 |
ubyte, though not stated as clearly in the 2.0.0 spec as
|
|
Packit |
cdaae3 |
one might hope. */
|
|
Packit |
cdaae3 |
if (line_ptr >= line_ptr_end) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error,
|
|
Packit |
cdaae3 |
DW_DLE_LINE_TABLE_BAD);
|
|
Packit |
cdaae3 |
return DW_DLV_ERROR;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
ext_opcode = *(Dwarf_Small *) line_ptr;
|
|
Packit |
cdaae3 |
line_ptr++;
|
|
Packit |
cdaae3 |
if (line_ptr > line_ptr_end) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error,
|
|
Packit |
cdaae3 |
DW_DLE_LINE_TABLE_BAD);
|
|
Packit |
cdaae3 |
return DW_DLV_ERROR;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
switch (ext_opcode) {
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
case DW_LNE_end_sequence:{
|
|
Packit |
cdaae3 |
regs.lr_end_sequence = true;
|
|
Packit |
cdaae3 |
if (dolines) {
|
|
Packit |
cdaae3 |
curr_line = (Dwarf_Line)
|
|
Packit |
cdaae3 |
_dwarf_get_alloc(dbg, DW_DLA_LINE, 1);
|
|
Packit |
cdaae3 |
if (curr_line == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_free_chain_entries(dbg,head_chain,line_count);
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
#ifdef PRINTING_DETAILS
|
|
Packit |
cdaae3 |
print_line_detail(dbg,"DW_LNE_end_sequence extended",
|
|
Packit |
cdaae3 |
ext_opcode, line_count+1,®s,
|
|
Packit |
cdaae3 |
is_single_table, is_actuals_table);
|
|
Packit |
cdaae3 |
#endif /* PRINTING_DETAILS */
|
|
Packit |
cdaae3 |
curr_line->li_address = regs.lr_address;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.li_file =
|
|
Packit |
cdaae3 |
(Dwarf_Sword) regs.lr_file;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.li_line =
|
|
Packit |
cdaae3 |
(Dwarf_Sword) regs.lr_line;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.li_column =
|
|
Packit |
cdaae3 |
(Dwarf_Half) regs.lr_column;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.li_is_stmt =
|
|
Packit |
cdaae3 |
regs.lr_is_stmt;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.
|
|
Packit |
cdaae3 |
li_basic_block = regs.lr_basic_block;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.
|
|
Packit |
cdaae3 |
li_end_sequence = regs.lr_end_sequence;
|
|
Packit |
cdaae3 |
curr_line->li_context = line_context;
|
|
Packit |
cdaae3 |
curr_line->li_is_actuals_table = is_actuals_table;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.
|
|
Packit |
cdaae3 |
li_epilogue_begin = regs.lr_epilogue_begin;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.
|
|
Packit |
cdaae3 |
li_prologue_end = regs.lr_prologue_end;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.li_isa = regs.lr_isa;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.li_discriminator =
|
|
Packit |
cdaae3 |
regs.lr_discriminator;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.li_call_context =
|
|
Packit |
cdaae3 |
regs.lr_call_context;
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.li_subprogram =
|
|
Packit |
cdaae3 |
regs.lr_subprogram;
|
|
Packit |
cdaae3 |
line_count++;
|
|
Packit |
cdaae3 |
chain_line = (Dwarf_Chain)
|
|
Packit |
cdaae3 |
_dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
|
|
Packit |
cdaae3 |
if (chain_line == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_free_chain_entries(dbg,head_chain,line_count);
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
chain_line->ch_item = curr_line;
|
|
Packit |
cdaae3 |
_dwarf_update_chain_list(chain_line,&head_chain,&curr_chain);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
_dwarf_set_line_table_regs_default_values(®s,
|
|
Packit |
cdaae3 |
line_context->lc_default_is_stmt);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
case DW_LNE_set_address:{
|
|
Packit |
cdaae3 |
READ_UNALIGNED_CK(dbg, regs.lr_address, Dwarf_Addr,
|
|
Packit |
cdaae3 |
line_ptr, address_size,error,line_ptr_end);
|
|
Packit |
cdaae3 |
/* Mark a line record as being DW_LNS_set_address */
|
|
Packit |
cdaae3 |
is_addr_set = true;
|
|
Packit |
cdaae3 |
#ifdef PRINTING_DETAILS
|
|
Packit |
cdaae3 |
dwarf_printf(dbg,
|
|
Packit |
cdaae3 |
"DW_LNE_set_address address 0x%"
|
|
Packit |
cdaae3 |
DW_PR_XZEROS DW_PR_DUx "\n",
|
|
Packit |
cdaae3 |
(Dwarf_Unsigned) regs.lr_address);
|
|
Packit |
cdaae3 |
#endif /* PRINTING_DETAILS */
|
|
Packit |
cdaae3 |
if (doaddrs) {
|
|
Packit |
cdaae3 |
/* SGI IRIX rqs processing only. */
|
|
Packit |
cdaae3 |
curr_line = (Dwarf_Line) _dwarf_get_alloc(dbg,
|
|
Packit |
cdaae3 |
DW_DLA_LINE, 1);
|
|
Packit |
cdaae3 |
if (curr_line == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_free_chain_entries(dbg,head_chain,line_count);
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Mark a line record as being DW_LNS_set_address */
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_l_data.li_is_addr_set =
|
|
Packit |
cdaae3 |
is_addr_set;
|
|
Packit |
cdaae3 |
is_addr_set = false;
|
|
Packit |
cdaae3 |
curr_line->li_address = regs.lr_address;
|
|
Packit |
cdaae3 |
#ifdef __sgi /* SGI IRIX ONLY */
|
|
Packit |
cdaae3 |
curr_line->li_addr_line.li_offset =
|
|
Packit |
cdaae3 |
line_ptr - dbg->de_debug_line.dss_data;
|
|
Packit |
cdaae3 |
#endif /* __sgi */
|
|
Packit |
cdaae3 |
line_count++;
|
|
Packit |
cdaae3 |
chain_line = (Dwarf_Chain)
|
|
Packit |
cdaae3 |
_dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
|
|
Packit |
cdaae3 |
if (chain_line == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_free_chain_entries(dbg,head_chain,line_count);
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
chain_line->ch_item = curr_line;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
_dwarf_update_chain_list(chain_line,&head_chain,&curr_chain);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
regs.lr_op_index = 0;
|
|
Packit |
cdaae3 |
line_ptr += address_size;
|
|
Packit |
cdaae3 |
if (line_ptr > line_ptr_end) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error,
|
|
Packit |
cdaae3 |
DW_DLE_LINE_TABLE_BAD);
|
|
Packit |
cdaae3 |
return DW_DLV_ERROR;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
case DW_LNE_define_file:
|
|
Packit |
cdaae3 |
if (dolines) {
|
|
Packit |
cdaae3 |
int res = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned value = 0;
|
|
Packit |
cdaae3 |
cur_file_entry = (Dwarf_File_Entry)
|
|
Packit |
cdaae3 |
malloc(sizeof(struct Dwarf_File_Entry_s));
|
|
Packit |
cdaae3 |
if (cur_file_entry == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
memset(cur_file_entry,0,sizeof(struct Dwarf_File_Entry_s));
|
|
Packit |
cdaae3 |
_dwarf_add_to_files_list(line_context,cur_file_entry);
|
|
Packit |
cdaae3 |
cur_file_entry->fi_file_name = (Dwarf_Small *) line_ptr;
|
|
Packit |
cdaae3 |
res = _dwarf_check_string_valid(dbg,
|
|
Packit |
cdaae3 |
line_ptr,line_ptr,line_ptr_end,
|
|
Packit |
cdaae3 |
DW_DLE_DEFINE_FILE_STRING_BAD,error);
|
|
Packit |
cdaae3 |
if (res != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
_dwarf_free_chain_entries(dbg,head_chain,line_count);
|
|
Packit |
cdaae3 |
return res;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
line_ptr = line_ptr + strlen((char *) line_ptr) + 1;
|
|
Packit |
cdaae3 |
DECODE_LEB128_UWORD_CK(line_ptr,value,
|
|
Packit |
cdaae3 |
dbg,error,line_ptr_end);
|
|
Packit |
cdaae3 |
cur_file_entry->fi_dir_index = (Dwarf_Sword)value;
|
|
Packit |
cdaae3 |
DECODE_LEB128_UWORD_CK(line_ptr,value,
|
|
Packit |
cdaae3 |
dbg,error,line_ptr_end);
|
|
Packit |
cdaae3 |
cur_file_entry->fi_time_last_mod = value;
|
|
Packit |
cdaae3 |
DECODE_LEB128_UWORD_CK(line_ptr,value,
|
|
Packit |
cdaae3 |
dbg,error,line_ptr_end);
|
|
Packit |
cdaae3 |
cur_file_entry->fi_file_length = value;
|
|
Packit |
cdaae3 |
#ifdef PRINTING_DETAILS
|
|
Packit |
cdaae3 |
dwarf_printf(dbg,
|
|
Packit |
cdaae3 |
"DW_LNE_define_file %s \n", cur_file_entry->fi_file_name);
|
|
Packit |
cdaae3 |
dwarf_printf(dbg,
|
|
Packit |
cdaae3 |
" dir index %d\n", (int) cur_file_entry->fi_dir_index);
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
time_t tt3 = (time_t) cur_file_entry->fi_time_last_mod;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* ctime supplies newline */
|
|
Packit |
cdaae3 |
dwarf_printf(dbg,
|
|
Packit |
cdaae3 |
" last time 0x%x %s",
|
|
Packit |
cdaae3 |
(unsigned)tt3, ctime(&tt3));
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
dwarf_printf(dbg,
|
|
Packit |
cdaae3 |
" file length %ld 0x%lx\n",
|
|
Packit |
cdaae3 |
(long) cur_file_entry->fi_file_length,
|
|
Packit |
cdaae3 |
(unsigned long) cur_file_entry->fi_file_length);
|
|
Packit |
cdaae3 |
#endif /* PRINTING_DETAILS */
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
case DW_LNE_set_discriminator:{
|
|
Packit |
cdaae3 |
/* New in DWARF4 */
|
|
Packit |
cdaae3 |
Dwarf_Unsigned utmp2 = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
DECODE_LEB128_UWORD_CK(line_ptr, utmp2,
|
|
Packit |
cdaae3 |
dbg,error,line_ptr_end);
|
|
Packit |
cdaae3 |
regs.lr_discriminator = (Dwarf_Word) utmp2;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
#ifdef PRINTING_DETAILS
|
|
Packit |
cdaae3 |
dwarf_printf(dbg,
|
|
Packit |
cdaae3 |
"DW_LNE_set_discriminator 0x%"
|
|
Packit |
cdaae3 |
DW_PR_XZEROS DW_PR_DUx "\n",utmp2);
|
|
Packit |
cdaae3 |
#endif /* PRINTING_DETAILS */
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
default:{
|
|
Packit |
cdaae3 |
/* This is an extended op code we do not know about,
|
|
Packit |
cdaae3 |
other than we know now many bytes it is
|
|
Packit |
cdaae3 |
and the op code and the bytes of operand. */
|
|
Packit |
cdaae3 |
Dwarf_Unsigned remaining_bytes = instr_length -1;
|
|
Packit |
cdaae3 |
if (instr_length < 1 || remaining_bytes > DW_LNE_LEN_MAX) {
|
|
Packit |
cdaae3 |
_dwarf_free_chain_entries(dbg,head_chain,line_count);
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error,
|
|
Packit |
cdaae3 |
DW_DLE_LINE_TABLE_BAD);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
#ifdef PRINTING_DETAILS
|
|
Packit |
cdaae3 |
dwarf_printf(dbg,
|
|
Packit |
cdaae3 |
"DW_LNE extended op 0x%x ",ext_opcode);
|
|
Packit |
cdaae3 |
dwarf_printf(dbg,
|
|
Packit |
cdaae3 |
"Bytecount: %" DW_PR_DUu , (Dwarf_Unsigned)instr_length);
|
|
Packit |
cdaae3 |
if (remaining_bytes > 0) {
|
|
Packit |
cdaae3 |
dwarf_printf(dbg,
|
|
Packit |
cdaae3 |
" linedata: 0x");
|
|
Packit |
cdaae3 |
while (remaining_bytes > 0) {
|
|
Packit |
cdaae3 |
dwarf_printf(dbg,
|
|
Packit |
cdaae3 |
"%02x",(unsigned char)(*(line_ptr)));
|
|
Packit |
cdaae3 |
line_ptr++;
|
|
Packit |
cdaae3 |
if (line_ptr > line_ptr_end) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error,
|
|
Packit |
cdaae3 |
DW_DLE_LINE_TABLE_BAD);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
remaining_bytes--;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
#else /* ! PRINTING_DETAILS */
|
|
Packit |
cdaae3 |
line_ptr += remaining_bytes;
|
|
Packit |
cdaae3 |
if (line_ptr > line_ptr_end) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error, DW_DLE_LINE_TABLE_BAD);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
#endif /* PRINTING_DETAILS */
|
|
Packit |
cdaae3 |
dwarf_printf(dbg,"\n");
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
break;
|
|
Packit |
cdaae3 |
} /* End switch. */
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
block_line = (Dwarf_Line *)
|
|
Packit |
cdaae3 |
_dwarf_get_alloc(dbg, DW_DLA_LIST, line_count);
|
|
Packit |
cdaae3 |
if (block_line == NULL) {
|
|
Packit |
cdaae3 |
curr_chain = head_chain;
|
|
Packit |
cdaae3 |
/* FIXME: chain cleanup should be a function and called at
|
|
Packit |
cdaae3 |
more places in this function. */
|
|
Packit |
cdaae3 |
_dwarf_free_chain_entries(dbg,head_chain,line_count);
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
curr_chain = head_chain;
|
|
Packit |
cdaae3 |
for (i = 0; i < line_count; i++) {
|
|
Packit |
cdaae3 |
Dwarf_Chain t = 0;
|
|
Packit |
cdaae3 |
*(block_line + i) = curr_chain->ch_item;
|
|
Packit |
cdaae3 |
t = curr_chain;
|
|
Packit |
cdaae3 |
curr_chain = curr_chain->ch_next;
|
|
Packit |
cdaae3 |
dwarf_dealloc(dbg, t, DW_DLA_CHAIN);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (is_single_table || !is_actuals_table) {
|
|
Packit |
cdaae3 |
line_context->lc_linebuf_logicals = block_line;
|
|
Packit |
cdaae3 |
line_context->lc_linecount_logicals = line_count;
|
|
Packit |
cdaae3 |
} else {
|
|
Packit |
cdaae3 |
line_context->lc_linebuf_actuals = block_line;
|
|
Packit |
cdaae3 |
line_context->lc_linecount_actuals = line_count;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
#ifdef PRINTING_DETAILS
|
|
Packit |
cdaae3 |
if (is_single_table) {
|
|
Packit |
cdaae3 |
if(!line_count) {
|
|
Packit |
cdaae3 |
dwarf_printf(dbg," Line table is present (offset 0x%"
|
|
Packit |
cdaae3 |
DW_PR_XZEROS DW_PR_DUx
|
|
Packit |
cdaae3 |
") but no lines present\n",
|
|
Packit |
cdaae3 |
line_context->lc_section_offset);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
} else if (is_actuals_table) {
|
|
Packit |
cdaae3 |
if(!line_count) {
|
|
Packit |
cdaae3 |
dwarf_printf(dbg," Line table present (offset 0x%"
|
|
Packit |
cdaae3 |
DW_PR_XZEROS DW_PR_DUx
|
|
Packit |
cdaae3 |
") but no actuals lines present\n",
|
|
Packit |
cdaae3 |
line_context->lc_section_offset);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
} else {
|
|
Packit |
cdaae3 |
if(!line_count) {
|
|
Packit |
cdaae3 |
dwarf_printf(dbg," Line table present (offset 0x%"
|
|
Packit |
cdaae3 |
DW_PR_XZEROS DW_PR_DUx
|
|
Packit |
cdaae3 |
") but no logicals lines present\n",
|
|
Packit |
cdaae3 |
line_context->lc_section_offset);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
#endif /* PRINTING_DETAILS */
|
|
Packit |
cdaae3 |
return DW_DLV_OK;
|
|
Packit |
cdaae3 |
}
|