mirror of
https://github.com/davea42/libdwarf-code.git
synced 2025-10-23 10:27:48 +08:00

standard tables: header says lno now, for line number (row was incorrect). dwarfdump/dwarfdump.c dwarfdump/print_die.c dwarfdump/print_lines.c New checks for correctness and section overrun. Fixed duplicate free due to bug in DWARF5 macro handling. libdwarf/dwarf_arange.c libdwarf/dwarf_die_deliv.c libdwarf/dwarf_elf_access.c libdwarf/dwarf_errmsg_list.c libdwarf/dwarf_frame2.c libdwarf/dwarf_leb.c libdwarf/dwarf_line.c libdwarf/dwarf_line.h libdwarf/dwarf_line_table_reader_common.c libdwarf/dwarf_macro5.c libdwarf/dwarf_util.h libdwarf/libdwarf.h.in
452 lines
16 KiB
C
452 lines
16 KiB
C
/*
|
|
Copyright (C) 2000, 2004, 2006 Silicon Graphics, Inc. All Rights Reserved.
|
|
Portions Copyright (C) 2009-2015 David Anderson. All Rights Reserved.
|
|
Portions Copyright (C) 2010-2012 SN Systems Ltd. All Rights Reserved.
|
|
|
|
This program is free software; you can redistribute it and/or modify it
|
|
under the terms of version 2.1 of the GNU Lesser General Public License
|
|
as published by the Free Software Foundation.
|
|
|
|
This program is distributed in the hope that it would be useful, but
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
Further, this software is distributed without any warranty that it is
|
|
free of the rightful claim of any third person regarding infringement
|
|
or the like. Any license provided herein, whether implied or
|
|
otherwise, applies only to this software file. Patent licenses, if
|
|
any, provided herein do not apply to combinations of this program with
|
|
other software, or any other product whatsoever.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this program; if not, write the Free Software
|
|
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
|
|
USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define DW_EXTENDED_OPCODE 0
|
|
|
|
/*
|
|
This is used as the starting value for an algorithm
|
|
to get the minimum difference between 2 values.
|
|
UINT_MAX is used as our approximation to infinity.
|
|
*/
|
|
#define MAX_LINE_DIFF UINT_MAX
|
|
|
|
/* This is for a sanity check on line
|
|
table extended opcodes.
|
|
It is entirely arbitrary, and 100 is surely too small if
|
|
someone was inserting strings in the opcode. */
|
|
#define DW_LNE_LEN_MAX 100
|
|
|
|
|
|
/*
|
|
This structure is used to build a list of all the
|
|
files that are used in the current compilation unit.
|
|
All of the fields execpt fi_next have meanings that
|
|
are obvious from section 6.2.4 of the Libdwarf Doc.
|
|
Because of DW_LNE_define_file we
|
|
make this a list, not an array.
|
|
*/
|
|
struct Dwarf_File_Entry_s {
|
|
struct Dwarf_File_Entry_s *fi_next;
|
|
|
|
/* Points to string naming the file. */
|
|
Dwarf_Small *fi_file_name;
|
|
|
|
/* Index into the list of directories of the directory in which
|
|
this file exits. */
|
|
Dwarf_Word fi_dir_index;
|
|
|
|
/* Time of last modification of the file. */
|
|
Dwarf_Unsigned fi_time_last_mod;
|
|
|
|
/* Length in bytes of the file. */
|
|
Dwarf_Unsigned fi_file_length;
|
|
};
|
|
|
|
/* Part of two-level line tables support. */
|
|
struct Dwarf_Subprog_Entry_s {
|
|
Dwarf_Small *ds_subprog_name;
|
|
Dwarf_Unsigned ds_decl_file;
|
|
Dwarf_Unsigned ds_decl_line;
|
|
};
|
|
|
|
typedef struct Dwarf_Subprog_Entry_s *Dwarf_Subprog_Entry;
|
|
|
|
|
|
/*
|
|
This structure provides the context in which the fields of
|
|
a Dwarf_Line structure are interpreted. They come from the
|
|
statement program prologue. **Updated by dwarf_srclines in
|
|
dwarf_line.c.
|
|
|
|
lc_magic will be DW_CONTEXT_MAGIC unless there is a serious
|
|
programming error somewhere.
|
|
It's set zero when a Line_Context is deallocated.
|
|
Any other value indicates there is bug somewhere.
|
|
*/
|
|
#define DW_CONTEXT_MAGIC 0xd00d1111
|
|
struct Dwarf_Line_Context_s {
|
|
unsigned lc_magic;
|
|
|
|
/* lc_new_style_access is non-zero if this was allocated
|
|
via a dwarf_srclines_b() call or equivalent.
|
|
Otherwise this is 0. */
|
|
unsigned char lc_new_style_access;
|
|
|
|
/* The section offset (in .debug_line
|
|
or .debug_line.dwo of the line table */
|
|
Dwarf_Unsigned lc_section_offset;
|
|
|
|
/* 2 for DWARF2, 3 for DWARF3, 4 for DWARF4, 5 for DWARF5.
|
|
0xf006 for experimental two-level line tables. */
|
|
Dwarf_Half lc_version_number;
|
|
|
|
/* Total length of the line data for this CU */
|
|
Dwarf_Unsigned lc_total_length;
|
|
|
|
/* Length of the initial length field itself. */
|
|
Dwarf_Half lc_length_field_length;
|
|
|
|
/* address size and segment sizefields new in DWARF5 header. */
|
|
Dwarf_Small lc_address_size;
|
|
Dwarf_Small lc_segment_selector_size;
|
|
|
|
Dwarf_Unsigned lc_prologue_length;
|
|
Dwarf_Unsigned lc_actuals_table_offset;
|
|
Dwarf_Unsigned lc_logicals_table_offset;
|
|
Dwarf_Small lc_minimum_instruction_length;
|
|
|
|
/* Start and end of this CU line area. pf_line_ptr_start +
|
|
pf_total_length + pf_length_field_length == pf_line_ptr_end.
|
|
Meaning lc_line_ptr_start is before the length info. */
|
|
Dwarf_Small *lc_line_ptr_start;
|
|
Dwarf_Small *lc_line_ptr_end;
|
|
/* Start of the lines themselves. */
|
|
Dwarf_Small *lc_line_ptr_lines;
|
|
|
|
/* Used to check that decoding of the line prologue is done right. */
|
|
Dwarf_Small *lc_line_prologue_start;
|
|
|
|
Dwarf_Small lc_default_is_stmt;
|
|
Dwarf_Ubyte lc_maximum_ops_per_instruction; /*DWARF5*/
|
|
Dwarf_Sbyte lc_line_base;
|
|
Dwarf_Small lc_line_range;
|
|
|
|
/* Highest std opcode (+1). */
|
|
Dwarf_Small lc_opcode_base;
|
|
/* pf_opcode_base -1 entries (each a count, normally the value of
|
|
each entry is 0 or 1). */
|
|
Dwarf_Small *lc_opcode_length_table;
|
|
|
|
/* The number to treat as standard ops. This is a special
|
|
accomodation of gcc using the new standard opcodes but not
|
|
updating the version number. It's legal dwarf2, but much better
|
|
for the user to understand as dwarf3 when 'it looks ok'. */
|
|
Dwarf_Small lc_std_op_count;
|
|
|
|
/* Points to a singly-linked list of entries providing info
|
|
about source files
|
|
for the current set of Dwarf_Line structures.
|
|
The initial entry on the list is 'file 1' per DWARF rules.
|
|
And so on. lc_last_entry points at the last entry
|
|
in the list (so we can easily expand the list).
|
|
It's a list (not a table) since we may encounter
|
|
DW_LNE_define_file entries. */
|
|
Dwarf_File_Entry lc_file_entries;
|
|
Dwarf_File_Entry lc_last_entry;
|
|
/* Count of number of source files for this set of Dwarf_Line
|
|
structures. */
|
|
Dwarf_Word lc_file_entry_count;
|
|
|
|
|
|
/* Points to the portion of .debug_line section that
|
|
contains a list of strings naming the included
|
|
directories. Do not free().
|
|
An array of pointers to strings. */
|
|
Dwarf_Small **lc_include_directories;
|
|
/* Count of the number of included directories. */
|
|
Dwarf_Word lc_include_directories_count;
|
|
|
|
|
|
/* Points to an array of subprogram entries.
|
|
With Two level line tables this may be non-zero.
|
|
An array of Dwarf_Subprogram_Entry_s structs. */
|
|
Dwarf_Subprog_Entry lc_subprogs;
|
|
|
|
/* Count of the number of subprogram entries
|
|
With Two level line tables this may be non-zero. */
|
|
Dwarf_Word lc_subprogs_count;
|
|
|
|
/* Count of the number of lines for this cu. */
|
|
Dwarf_Word lc_line_count;
|
|
|
|
/* Points to name of compilation directory.
|
|
That string is in a .debug section so
|
|
do not free this. */
|
|
Dwarf_Small *lc_compilation_directory;
|
|
|
|
Dwarf_Debug lc_dbg;
|
|
|
|
/* zero table count is skeleton, or just missing names.
|
|
1 is standard table.
|
|
2 means two-level table (experimantal)
|
|
Other is a bug somewhere. */
|
|
Dwarf_Small lc_table_count;
|
|
Dwarf_Bool lc_is_single_table;
|
|
|
|
/* For standard line tables the logicals are
|
|
the only tables and linecount_actuals is 0. */
|
|
Dwarf_Line *lc_linebuf_logicals;
|
|
Dwarf_Unsigned lc_linecount_logicals;
|
|
|
|
/* Non-zero only if two-level table with actuals */
|
|
Dwarf_Line *lc_linebuf_actuals;
|
|
Dwarf_Unsigned lc_linecount_actuals;
|
|
};
|
|
|
|
|
|
|
|
/* The line table set of registers.
|
|
The state machine state variables.
|
|
Using names from the DWARF documentation
|
|
but preceded by lr_. */
|
|
struct Dwarf_Line_Registers_s {
|
|
Dwarf_Addr lr_address; /* DWARF2 */
|
|
Dwarf_Word lr_file ; /* DWARF2 */
|
|
Dwarf_Word lr_line ; /* DWARF2 */
|
|
Dwarf_Word lr_column ; /* DWARF2 */
|
|
Dwarf_Bool lr_is_stmt; /* DWARF2 */
|
|
Dwarf_Bool lr_basic_block; /* DWARF2 */
|
|
Dwarf_Bool lr_end_sequence; /* DWARF2 */
|
|
Dwarf_Bool lr_prologue_end; /* DWARF3 */
|
|
Dwarf_Bool lr_epilogue_begin; /* DWARF3 */
|
|
Dwarf_Small lr_isa; /* DWARF3 */
|
|
Dwarf_Unsigned lr_op_index; /* DWARF4, operation within VLIW instruction. */
|
|
Dwarf_Unsigned lr_discriminator; /* DWARF4 */
|
|
Dwarf_Unsigned lr_call_context; /* EXPERIMENTAL */
|
|
Dwarf_Unsigned lr_subprogram; /* EXPERIMENTAL */
|
|
};
|
|
typedef struct Dwarf_Line_Registers_s *Dwarf_Line_Registers;
|
|
void _dwarf_set_line_table_regs_default_values(Dwarf_Line_Registers regs,
|
|
Dwarf_Bool is_stmt);
|
|
|
|
|
|
|
|
/*
|
|
This structure defines a row of the line table.
|
|
All of the fields except li_offset have the exact
|
|
same meaning that is defined in Section 6.2.2
|
|
of the Libdwarf Document.
|
|
|
|
li_offset is used by _dwarf_addr_finder() which is called
|
|
by rqs(1), an sgi utility for 'moving' shared libraries
|
|
as if the static linker (ld) had linked the shared library
|
|
at the newly-specified address. Most libdwarf-using
|
|
apps will ignore li_offset and _dwarf_addr_finder().
|
|
|
|
*/
|
|
struct Dwarf_Line_s {
|
|
Dwarf_Addr li_address; /* pc value of machine instr */
|
|
union addr_or_line_s {
|
|
struct li_inner_s {
|
|
/* New as of DWARF4 */
|
|
Dwarf_Unsigned li_discriminator;
|
|
|
|
/* int identifying src file
|
|
li_file is a number 1-N, indexing into a conceptual
|
|
source file table as described in dwarf2/3 spec line
|
|
table doc. (see Dwarf_File_Entry lc_file_entries; and
|
|
Dwarf_Word lc_file_entry_count;) */
|
|
Dwarf_Word li_file;
|
|
|
|
/* In single-level table is line number in source file. 1-N
|
|
In logicals table is not used.
|
|
In actuals table is index into logicals table. 1-N*/
|
|
Dwarf_Word li_line;
|
|
|
|
Dwarf_Half li_column; /* source file column number 1-N */
|
|
Dwarf_Small li_isa; /* New as of DWARF4. */
|
|
|
|
/* Two-level line tables.
|
|
Is index from logicals table
|
|
into logicals table. 1-N */
|
|
Dwarf_Unsigned li_call_context;
|
|
|
|
/* Two-level line tables.
|
|
is index into subprograms table. 1-N */
|
|
Dwarf_Unsigned li_subprogram;
|
|
|
|
/* To save space, use bit flags. */
|
|
/* indicate start of stmt */
|
|
unsigned li_is_stmt:1;
|
|
|
|
/* indicate start basic block */
|
|
unsigned li_basic_block:1;
|
|
|
|
/* first post sequence instr */
|
|
unsigned li_end_sequence:1;
|
|
|
|
unsigned li_prologue_end:1;
|
|
unsigned li_epilogue_begin:1;
|
|
|
|
/* Mark a line record as being DW_LNS_set_address. */
|
|
unsigned li_is_addr_set:1;
|
|
} li_l_data;
|
|
#ifdef __sgi /* SGI IRIX ONLY */
|
|
Dwarf_Off li_offset; /* for SGI IRIX rqs only*/
|
|
#endif /* __sgi */
|
|
} li_addr_line;
|
|
Dwarf_Line_Context li_context; /* assoc Dwarf_Line_Context_s */
|
|
|
|
/* Set only on the actuals table of a two-level line table.
|
|
Assists in the dealloc code.
|
|
*/
|
|
Dwarf_Bool li_is_actuals_table;
|
|
};
|
|
|
|
|
|
int _dwarf_line_address_offsets(Dwarf_Debug dbg,
|
|
Dwarf_Die die,
|
|
Dwarf_Addr ** addrs,
|
|
Dwarf_Off ** offs,
|
|
Dwarf_Unsigned * returncount,
|
|
Dwarf_Error * err);
|
|
int _dwarf_internal_srclines(Dwarf_Die die,
|
|
Dwarf_Bool old_interface,
|
|
Dwarf_Unsigned * version,
|
|
Dwarf_Small * table_count,
|
|
Dwarf_Line_Context *line_context,
|
|
Dwarf_Line ** linebuf,
|
|
Dwarf_Signed * count,
|
|
Dwarf_Line ** linebuf_actuals,
|
|
Dwarf_Signed * count_actuals,
|
|
Dwarf_Bool doaddrs,
|
|
Dwarf_Bool dolines,
|
|
Dwarf_Error * error);
|
|
|
|
/* The LOP, WHAT_IS_OPCODE stuff is here so it can
|
|
be reused in 3 places. Seemed hard to keep
|
|
the 3 places the same without an inline func or
|
|
a macro.
|
|
|
|
Handling the line section where the header and the
|
|
file being processed do not match (unusual, but
|
|
planned for in the design of .debug_line)
|
|
is too tricky to recode this several times and keep
|
|
it right.
|
|
|
|
As it is the code starting up line-reading is duplicated
|
|
and that is just wrong to do. FIXME!
|
|
*/
|
|
#define LOP_EXTENDED 1
|
|
#define LOP_DISCARD 2
|
|
#define LOP_STANDARD 3
|
|
#define LOP_SPECIAL 4
|
|
|
|
#define WHAT_IS_OPCODE(type,opcode,base,opcode_length,line_ptr,highest_std) \
|
|
if ((opcode) < (base)) { \
|
|
/* we know we must treat as a standard op \
|
|
or a special case. */ \
|
|
if ((opcode) == DW_EXTENDED_OPCODE) { \
|
|
type = LOP_EXTENDED; \
|
|
} else if ((highest_std+1) >= (base)) { \
|
|
/* == Standard case: compile of \
|
|
dwarf_line.c and object \
|
|
have same standard op codes set. \
|
|
== Special case: compile of dwarf_line.c \
|
|
has things in standard op codes list \
|
|
in dwarf.h header not \
|
|
in the object: handle this as a standard \
|
|
op code in switch below. \
|
|
The header special ops overlap the \
|
|
object standard ops. \
|
|
The new standard op codes will not \
|
|
appear in the object. */ \
|
|
type = LOP_STANDARD; \
|
|
} else { \
|
|
/* These are standard opcodes in the object \
|
|
** that were not defined in the header \
|
|
** at the time dwarf_line.c \
|
|
** was compiled. Provides the ability of \
|
|
** out-of-date dwarf reader to read newer \
|
|
** line table data transparently. \
|
|
*/ \
|
|
type = LOP_DISCARD; \
|
|
} \
|
|
} else { \
|
|
/* Is a special op code. */ \
|
|
type = LOP_SPECIAL; \
|
|
}
|
|
|
|
/* The following is from the dwarf definition of 'ubyte'
|
|
and is specifically mentioned in section 6.2.5.1, page 54
|
|
of the Rev 2.0.0 dwarf specification.
|
|
*/
|
|
|
|
#define MAX_LINE_OP_CODE 255
|
|
|
|
|
|
# if 0
|
|
/* The following structs (Line_Table_File_Entry_s,Dwarf_Line_Context_s)
|
|
and functions allow refactoring common code into a single
|
|
reader routine.
|
|
*/
|
|
Not used once Prefix struct folded into line context struct.
|
|
/* There can be zero of more of these needed for 1 line prologue. */
|
|
struct Line_Table_File_Entry_s {
|
|
Dwarf_Small *lte_filename;
|
|
Dwarf_Unsigned lte_directory_index;
|
|
Dwarf_Unsigned lte_last_modification_time;
|
|
Dwarf_Unsigned lte_length_of_file;
|
|
};
|
|
#endif
|
|
|
|
|
|
/* Operand counts per standard operand.
|
|
The initial zero is for DW_LNS_copy.
|
|
This is an economical way to verify we understand the table
|
|
of standard-opcode-lengths in the line table prologue. */
|
|
#define STANDARD_OPERAND_COUNT_DWARF2 9
|
|
#define STANDARD_OPERAND_COUNT_DWARF3 12
|
|
/* For two-level line tables, we have three additional standard opcodes. */
|
|
#define STANDARD_OPERAND_COUNT_TWO_LEVEL 15
|
|
|
|
void _dwarf_print_header_issue(Dwarf_Debug dbg,
|
|
const char *specific_msg,
|
|
Dwarf_Small *data_start,
|
|
Dwarf_Signed value,
|
|
unsigned index,
|
|
unsigned tabv,
|
|
unsigned linetabv,
|
|
int *err_count_out);
|
|
int _dwarf_decode_line_string_form(Dwarf_Debug dbg,
|
|
Dwarf_Unsigned form,
|
|
Dwarf_Unsigned offset_size,
|
|
Dwarf_Small **line_ptr,
|
|
Dwarf_Small *line_ptr_end,
|
|
char **return_str,
|
|
Dwarf_Error * error);
|
|
int _dwarf_decode_line_udata_form(Dwarf_Debug dbg,
|
|
Dwarf_Unsigned form,
|
|
Dwarf_Small **line_ptr,
|
|
Dwarf_Unsigned *return_val,
|
|
Dwarf_Small *line_end_ptr,
|
|
Dwarf_Error * error);
|
|
|
|
void _dwarf_update_chain_list( Dwarf_Chain chain_line,
|
|
Dwarf_Chain *head_chain, Dwarf_Chain *curr_chain);
|
|
void _dwarf_free_chain_entries(Dwarf_Debug dbg,Dwarf_Chain head,int count);
|
|
|
|
int _dwarf_line_context_constructor(Dwarf_Debug dbg, void *m);
|
|
void _dwarf_line_context_destructor(void *m);
|
|
|
|
void _dwarf_print_line_context_record(Dwarf_Debug dbg,
|
|
Dwarf_Line_Context line_context);
|
|
void _dwarf_context_src_files_destroy(Dwarf_Line_Context context);
|
|
int _dwarf_add_to_files_list(Dwarf_Line_Context context, Dwarf_File_Entry fe);
|