Compare commits

...

27 Commits

Author SHA1 Message Date
Cary Coutant
83222732f1 Fix crash when section ends with a .lloc directive not followed by an insn.
gas/
	* dwarf2dbg.c (emit_logicals): Handle case where e->label is NULL.
2015-03-25 15:27:52 -07:00
Cary Coutant
c312754797 Improve ODR checking.
2015-02-09  Cary Coutant  <ccoutant@google.com>

gold/
	* dwarf_reader.cc (Sized_dwarf_line_info::read_lines): Fix debug
	output to print correct context.
	(Sized_dwarf_line_info::do_addr2line): Add debug output. Return
	up to 4 more locations at the beginning of the function.
	* symtab.cc (Symbol_table::detect_odr_violations): Get canonical
	result before sorting list of line numbers.
2015-02-22 23:44:29 -08:00
Cary Coutant
76b3c0a533 Support compressed debug in dyn objects.
2015-02-09  Cary Coutant  <ccoutant@google.com>

gold/
	* dwp.cc (Sized_relobj_dwo::do_decompressed_section_contents): Delete.
	(Sized_relobj_dwo::setup): Setup map of compressed sections.
	(print_version): Update copyright.
	* dynobj.cc (Sized_dynobj::base_read_symbols): Set up map of compressed
	sections.
	* object.cc (Sized_relobj_file::compressed_sections): Delete.
	(build_compressed_section_map): Add decompress_if_needed parameter.
	Adjust callers.
	(Sized_relobj_file::do_find_special_sections): Set compressed sections
	map in Object base class.
	(Sized_relobj_file::do_decompressed_section_contents): Rename to
	Object::decompressed_section_contents.
	(Sized_relobj_file::do_discard_decompressed_sections): Rename to
	Object::discard_decompressed_sections.
	* object.h (Object::compressed_sections_): New data member.
	(Object::section_is_compressed): Remove virtual, implement here.
	(Object::decompressed_section_contents): Remove virtual.
	(Object::do_section_is_compressed): Delete.
	(Object::do_decompressed_section_contents): Delete.
	(Object::set_compressed_sections): New method.
	(Object::compressed_sections): New method.
	(Sized_relobj_file::do_section_is_compressed): Delete.
	(Sized_relobj_file::do_decompressed_section_contents): Delete.
	(Sized_relobj_file::do_discard_decompressed_sections): Delete.
	(Sized_relobj_file::compressed_sections): Delete.
2015-02-22 23:44:23 -08:00
Cary Coutant
f0c3f9ad7b Add gold support for two-level line tables.
2015-01-30  Cary Coutant  <ccoutant@google.com>

elfcpp/
	* dwarf.h (enum DW_LNS): Add experimental two-level line table opcodes.
	(enum DW_LNCT): New enum for DWARF-5.

gold/
	* debug.h (DEBUG_LOCATION): New constant.
	(debug_string_to_enum): Add DEBUG_LOCATION.
	* dwarf_reader.cc (struct LineStateMachine): Add context field.
	(ResetLineStateMachine): Likewise.
	(Sized_dwarf_line_info::Sized_dwarf_line_info): Add support for
	two-level line tables.
	(Sized_dwarf_line_info::read_header_prolog): Likewise. Also add
	support for DWARF-3+ line tables.
	(Sized_dwarf_line_info::read_header_tables_v5): New method.
	(Sized_dwarf_line_info::process_one_opcode): Add support for two-level
	line tables.
	(Sized_dwarf_line_info::read_lines): Likewise.
	(Sized_dwarf_line_info::read_line_mappings): Likewise.
	(Sized_dwarf_line_info::do_addr2line): Add debug output.
	* dwarf_reader.h (Sized_dwarf_line_info::~Sized_dwarf_line_info):
	Delete str_buffer_start_.
	(DWARF5_EXPERIMENTAL_LINE_TABLE): New constant.
	(Sized_dwarf_line_info::read_header_tables_v5): New method.
	(Sized_dwarf_line_info::read_lines): Update prototype.
	(Sized_dwarf_line_info::process_one_opcode): Likewise.
	(Sized_dwarf_line_info::max_ops_per_insn): New data member.
	(Sized_dwarf_line_info::str_buffer_): New data member.
	(Sized_dwarf_line_info::str_buffer_end_): New data member.
	(Sized_dwarf_line_info::str_buffer_start_): New data member.
	(Sized_dwarf_line_info::end_of_header_length_): New data member.
	(Sized_dwarf_line_info::logicals_start_): New data member.
	(Sized_dwarf_line_info::actuals_start_): New data member.
	(Sized_dwarf_line_info::end_of_unit_): New data member.
2015-02-22 23:43:57 -08:00
Cary Coutant
589778e030 Fix formatting.
2015-02-06  Cary Coutant  <ccoutant@google.com>

binutils/
	* dwarf.c (display_debug_lines_raw): Fix formatting.
2015-02-22 23:43:48 -08:00
Cary Coutant
b3759731e0 For ODR checking, when we see two .lloc directives in a row, output them both.
2015-01-30  Cary Coutant  <ccoutant@google.com>

gas/
	* dwarf2dbg.c (dwarf2_directive_loc): Always emit extra .lloc.
2015-01-30 04:16:46 -08:00
Cary Coutant
89442fc483 Reformat experimental header for compatibility with old DWARF consumers.
2015-01-28  Cary Coutant  <ccoutant@google.com>

binutils/
	* dwarf.c (read_debug_line_header): Adjust to reformatted header.
	(display_line_program): Add missing space in output.
	(display_debug_lines_raw): Adjust to reformatted header.
	* dwarf.h (DWARF2_Internal_LineInfo): Remove li_actuals_table_offset.
2015-01-28 22:05:06 -08:00
Cary Coutant
05305251ad Reformat experimental header for compatibility with old DWARF consumers.
Old consumers will now see a DWARF-4 header, with new fields added at the
end of the header. The new fields and the entire logicals and actuals
tables are wrapped in a single extended opcode so that old consumers
will see just the single opcode.

2015-01-28  Cary Coutant  <ccoutant@google.com>

gas/
	* dwarf2dbg.c (line_base): New variable.
	(line_range): New variable.
	(DWARF2_EXPERIMENTAL_LINE_OPCODE_BASE): Rename.
	(DWARF2_LINE_BASE): Restore to original value.
	(DWARF2_LINE_RANGE): Likewise.
	(DWARF5_EXPERIMENTAL_LINE_BASE): New macro.
	(DWARF5_EXPERIMENTAL_LINE_RANGE): New macro.
	(SPECIAL_LINE): Use line_base, line_range.
	(size_inc_line_addr): Likewise.
	(emit_inc_line_addr): Likewise.
	(out_debug_line): Reformat header for compatibility with old DWARF
	consumers.
2015-01-28 22:01:38 -08:00
Cary Coutant
d4c40a8552 Some minor cleanups in two-level line table support.
2015-01-28  Cary Coutant  <ccoutant@google.com>

binutils/
	* dwarf.c (free_logicals): Set logicals_table to NULL.
	(fetch_indirect_string): Correct boundary check.
	(fetch_indirect_line_string): Likewise.
	(fetch_indexed_string): Likewise.
	(display_dir_file_table_v5): Print unsigned value.
2015-01-28 11:22:01 -08:00
Cary Coutant
f7318adf46 Fix to read signed LEB128 for operand to DW_LNS_set_address_from_logical.
2015-01-26  Cary Coutant  <ccoutant@google.com>

binutils/
	* dwarf.c (display_line_program): Operand to
	DW_LNS_set_address_from_logical is signed.
2015-01-26 15:02:54 -08:00
Cary Coutant
a38fe6acd2 Reset discriminator after each row.
2015-01-26  Cary Coutant  <ccoutant@google.com>

binutils/
	* dwarf.c (display_line_program): Reset discriminator after each row.
2015-01-26 12:21:11 -08:00
Cary Coutant
e82144ec93 Set entsize for .debug_line_str section.
2015-01-23  Cary Coutant  <ccoutant@google.com>

gas/
	* dwarf2dbg.c (dwarf2_finish): Set entsize for .debug_line_str section.
2015-01-23 16:35:06 -08:00
Cary Coutant
b18ad49bab Emit address_size and segment_size for version 5 line number tables.
2015-01-23  Cary Coutant  <ccoutant@google.com>

gas/
	* dwarf2dbg.c (out_debug_line): Emit address_size and segment_size
	for version 5 line number tables.
2015-01-23 16:35:06 -08:00
Cary Coutant
285d7b5c33 Add address_size and segment_size to line number program header version 5.
2015-01-23  Cary Coutant  <ccoutant@google.com>

binutils/
	* dwarf.h (struct DWARF2_Internal_LineInfo): Add li_address_size and
	li_segment_size.
	* dwarf.c (read_debug_line_header): Read li_address_size and
	li_segment_size.
	(display_debug_lines_raw): Print li_address_size and li_segment_size.
2015-01-23 16:34:56 -08:00
Cary Coutant
2031626eb7 Update DW_LNS_opcodes for two-level line tables.
2015-01-23  Cary Coutant  <ccoutant@google.com>

binutils/
	* dwarf.c (append_logical): Fix format string.
	(display_line_program): Replace DW_LNS_set_context with
	DW_LNS_inlined_call. Fix format strings.
2015-01-23 13:14:41 -08:00
Cary Coutant
dc87246eb9 Update DW_LNS opcodes for two-level line tables.
2015-01-23  Cary Coutant  <ccoutant@google.com>

gas/
	* dwarf2dbg.c (emit_logicals): Increase max number of
	DW_LNS_pop_context opcodes. Change DW_LNS_set_context
	to DW_LNS_inlined_call.
	(out_debug_line): Adjust operand lengths array.
2015-01-23 13:12:29 -08:00
Cary Coutant
49e4ed79b8 Update DW_LNS opcodes.
2015-01-23  Cary Coutant  <ccoutant@google.com>

include/
	* dwarf2.h (enum dwarf_line_number_ops): Remove
	DW_LNS_set_context, add DW_LNS_inlined_call; renumber
	new opcodes.
2015-01-23 13:11:06 -08:00
Cary Coutant
c63bcc5d2d Track discriminator when processing line number table.
2015-01-21  Cary Coutant  <ccoutant@google.com>

binutils/
	* dwarf.c (process_extended_line_op): Track discriminator.
2015-01-21 16:01:18 -08:00
Cary Coutant
361595a3de Ignore line tables whose versions we don't support.
2015-01-21  Cary Coutant  <ccoutant@google.com>

gold/
	* dwarf_reader.cc (Sized_dwarf_line_info::read_header_prolog): Check
	line table version number.
	(Sized_dwarf_line_info::read_line_mappings): Likewise.
2015-01-21 15:45:55 -08:00
Cary Coutant
fc0d0b62cb Silence "may be uninitialized" warnings.
2015-01-21  Cary Coutant  <ccoutant@google.com>

binutils/
	* dwarf.c (display_debug_lines_raw): Silence "may be uninitialized"
	warnings.
2015-01-21 15:43:52 -08:00
Cary Coutant
6a8cf4ce11 Fix bugs displaying DW_LNS_set_context and DW_LNS_pop_context.
2015-01-15  Cary Coutant  <ccoutant@google.com>

binutils/
	* dwarf.c (append_logical): Print summary for each logical row.
	(display_line_program): Remove incorrect consumption of an LEB128
	when reading DW_LNS_set_context and DW_LNS_pop_context.
2015-01-15 13:58:58 -08:00
Cary Coutant
ab071889a9 Fix problems with DW_LNS_pop_context in logicals table.
2015-01-15  Cary Coutant  <ccoutant@google.com>

gas/
	* dwarf2dbg.c (emit_logicals): Fix bug in generating
	DW_LNS_pop_context.
	(process_entries): Don't always emit DW_LNS_set_address_from_logical
	when crossing frag boundaries.
2015-01-15 13:58:47 -08:00
Cary Coutant
af9adba57a Add support for DWARF-5 and experimental two-level line number tables.
http://wiki.dwarfstd.org/index.php?title=TwoLevelLineTables

2015-01-06  Cary Coutant  <ccoutant@google.com>

binutils/
	* dwarf.c (struct State_Machine_Registers): Add discriminator,
	context, and subprogram.
	(reset_state_machine): Likewise.
	(logicals_table, logicals_allocated, logicals_count): New variables.
	(free_logicals): New function.
	(append_logical): New function.
	(process_extended_line_op): Add is_logical parameter.
	(fetch_indirect_line_string): New function.
	(DWARF2_LINE_EXPERIMENTAL_VERSION): New macro.
	(read_debug_line_header): Add pinitial_length_size, poffset_size
	parameters.  Update all callers.  Check for new line table versions.
	(display_directory_table_v4): New function, factored out from
	display_debug_lines_raw.
	(display_file_name_table_v4): Likewise.
	(display_dir_file_table_v5): New function.
	(display_line_program): New function, factored out from
	display_debug_lines_raw.
	(display_debug_lines_raw): Support new line table versions.
	(display_debug_lines_decoded): Add missing newline to warning.
	(display_debug_lines): Load .debug_line_str section.
	(debug_displays): Add .debug_line_str section.
	* dwarf.h (DWARF2_Internal_LineInfo): Add li_actuals_table_offset field.
	(dwarf_section_display_enum): Add line_str.
	* readelf.c (process_section_headers): Add .debug_line_str.
2015-01-06 16:56:43 -08:00
Cary Coutant
c85ff14427 Update support for DWARF-5 and experimental two-level line number tables.
2015-01-06  Cary Coutant  <ccoutant@google.com>

gas/
	* dwarf2dbg.c (emit_logicals): Replace DW_LNS_inlined_call with
	DW_LNS_set_context and DW_LNS_set_subprogram.
	Fix bug where we emit wrong value for line number.
	(process_entries): Don't emit DW_LNS_negate_stmt in actuals table.
	(out_dwarf5_file_list): Fix bug where dir list or file list is empty.
	(out_debug_line): Update table of opcode lengths.
2015-01-06 16:40:43 -08:00
Cary Coutant
e7ca0f8d7d Update experimental DWARF-5 values for two-level line number tables.
http://wiki.dwarfstd.org/index.php?title=TwoLevelLineTables

2015-01-06  Cary Coutant  <ccoutant@google.com>

include/
    * dwarf2.h (enum dwarf_line_number_ops): Replace DW_LNS_inlined_call
    with DW_LNS_set_context and DW_LNS_set_subprogram.  Renumber subsequent
    opcodes.
2015-01-06 16:23:59 -08:00
Cary Coutant
b274bee161 Add support for DWARF-5 and experimental two-level line number tables.
2014-12-23  Cary Coutant  <ccoutant@google.com>

gas/
	* config/obj-elf.c (elf_pseudo_table): Add .lloc and .subprog
	directives.
	* dwarf2dbg.h (struct dwarf2_line_info): Add logical field.
	(dwarf2_directive_subprog): New function.
	(dwarf2_directive_loc): Add is_lloc parameter.
	* dwarf2dbg.c: Include "hash.h".
	(DWARF2_LINE_EXPERIMENTAL_VERSION): New macro.
	(DWARF2_EXPERIMENTAL_LINE_OPCODE_BASE): New macro.
	(opcode_base): New static variable.
	(DWARF2_LINE_BASE, DWARF2_LINE_RANGE): Adjust parameters.
	(DWARF2_LINE_MAX_OPS_PER_INSN): New macro.
	(SPECIAL_LINE, SPECIAL_ADDR): Use opcode_base.
	(struct subprog_entry): New struct.
	(subprogs, subprogs_in_use, subprogs_allocated): New variables.
	(struct logicals_entry): New struct.
	(logicals, logicals_in_use, logicals_allocated, logicals_with_labels):
	New variables.
	(struct string_table): New struct.
	(debug_line_str_table): New variable.
	(current): Add logical field.
	(dwarf2_gen_line_info): Fill in symbol and segment for recent logicals.
	(dwarf2_where): Add logical field.
	(make_subprog_entry): New function.
	(make_logical): New function.
	(dwarf2_directive_subprog): New function.
	(dwarf2_directive_loc): Add is_lloc parameter; add support for .lloc
	directive.
	(out_set_addr_from_logical): New function.
	(size_inc_line_addr): Fix signed/unsigned warnings. Use opcode_base.
	(emit_inc_line_addr): Likewise.
	(emit_logicals): New function.
	(process_entries): Add support for two-level line tables.
	(add_to_string_table): New function.
	(out_string_table): New function.
	(out_dwarf5_file_list): New function.
	(out_subprog_list): New function.
	(out_debug_line): Add support for DWARF-5 line tables and for
	experimental two-level line number tables.
	(dwarf2_finish): Likewise.
2015-01-01 10:59:24 -08:00
Cary Coutant
244e0772d8 Add experimental DWARF-5 values for two-level line number tables.
http://wiki.dwarfstd.org/index.php?title=TwoLevelLineTables

2014-12-23  Cary Coutant  <ccoutant@google.com>

include/
	* dwarf2.def (DW_FORM_line_strp): New constant.
	* dwarf2.h (enum dwarf_line_number_ops): Add DW_LNS_inlined_call,
	DW_LNS_pop_context, DW_LNS_set_address_from_logical.
	(enum dwarf_line_number_content_type): Add new DW_LNCT_ codes.
2015-01-01 10:59:24 -08:00
17 changed files with 2071 additions and 534 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -40,6 +40,8 @@ typedef struct
{
dwarf_vma li_length;
unsigned short li_version;
unsigned char li_address_size;
unsigned char li_segment_size;
unsigned int li_prologue_length;
unsigned char li_min_insn_length;
unsigned char li_max_ops_per_insn;
@@ -123,6 +125,7 @@ enum dwarf_section_display_enum
macinfo,
macro,
str,
line_str,
loc,
pubtypes,
gnu_pubtypes,

View File

@@ -5503,6 +5503,7 @@ process_section_headers (FILE * file)
|| (do_debug_macinfo && const_strneq (name, "macinfo"))
|| (do_debug_macinfo && const_strneq (name, "macro"))
|| (do_debug_str && const_strneq (name, "str"))
|| (do_debug_str && const_strneq (name, "line_str"))
|| (do_debug_loc && const_strneq (name, "loc"))
|| (do_debug_addr && const_strneq (name, "addr"))
|| (do_debug_cu_index && const_strneq (name, "cu_index"))

View File

@@ -147,7 +147,13 @@ enum DW_LINE_OPS
// DWARF 3.
DW_LNS_set_prologue_end = 10,
DW_LNS_set_epilogue_begin = 11,
DW_LNS_set_isa = 12
DW_LNS_set_isa = 12,
/* Experimental DWARF 5 extensions.
See http://wiki.dwarfstd.org/index.php?title=TwoLevelLineTables. */
DW_LNS_set_address_from_logical = 13, /* Actuals table only. */
DW_LNS_set_subprogram = 13, /* Logicals table only. */
DW_LNS_inlined_call = 14, /* Logicals table only. */
DW_LNS_pop_context = 15 /* Logicals table only. */
};
// Line number extended opcodes.
@@ -235,6 +241,20 @@ enum DW_SECT
DW_SECT_MAX = DW_SECT_MACRO,
};
enum DW_LNCT
{
DW_LNCT_path = 1,
DW_LNCT_directory_index = 2,
DW_LNCT_timestamp = 3,
DW_LNCT_size = 4,
DW_LNCT_MD5 = 5,
/* Experimental DWARF 5 extensions.
See http://wiki.dwarfstd.org/index.php?title=TwoLevelLineTables. */
DW_LNCT_subprogram_name = 6,
DW_LNCT_decl_file = 7,
DW_LNCT_decl_line = 8
};
} // End namespace elfcpp.
#endif // !defined(ELFCPP_DWARF_H)

View File

@@ -125,8 +125,10 @@ static const pseudo_typeS elf_pseudo_table[] =
{"8byte", cons, 8},
/* These are used for dwarf2. */
{ "file", (void (*) (int)) dwarf2_directive_file, 0 },
{ "loc", dwarf2_directive_loc, 0 },
{ "loc", dwarf2_directive_loc, 0 },
{ "loc_mark_labels", dwarf2_directive_loc_mark_labels, 0 },
{ "lloc", dwarf2_directive_loc, 1 },
{ "subprog", dwarf2_directive_subprog, 0 },
/* We need to trap the section changing calls to handle .previous. */
{"data", obj_elf_data, 0},

File diff suppressed because it is too large Load Diff

View File

@@ -35,6 +35,7 @@ struct dwarf2_line_info {
unsigned int isa;
unsigned int flags;
unsigned int discriminator;
unsigned int logical;
};
/* Implements the .file FILENO "FILENAME" directive. FILENO can be 0
@@ -42,13 +43,29 @@ struct dwarf2_line_info {
number must be >0. */
extern char *dwarf2_directive_file (int dummy);
/* Experimental DWARF-5 extension:
Implements the .subprog SUBPNO ["SUBPROG" [FILENO LINENO]] directive.
FILENO is the file number, LINENO the line number and the
(optional) COLUMN the column of the source code that the following
instruction corresponds to. FILENO can be 0 to indicate that the
filename specified by the textually most recent .file directive
should be used. */
extern void dwarf2_directive_subprog (int dummy);
/* Implements the .loc FILENO LINENO [COLUMN] directive. FILENO is
the file number, LINENO the line number and the (optional) COLUMN
the column of the source code that the following instruction
corresponds to. FILENO can be 0 to indicate that the filename
specified by the textually most recent .file directive should be
used. */
extern void dwarf2_directive_loc (int dummy);
/* Experimental DWARF-5 extension:
If IS_LLOC is true, implements the .lloc LOGICAL [FILENO LINENO [COLUMN]]
directive. FILENO is the file number, LINENO the line number and the
(optional) COLUMN the column of the source code that the following
instruction corresponds to. FILENO can be 0 to indicate that the
filename specified by the textually most recent .file directive
should be used. */
extern void dwarf2_directive_loc (int is_lloc);
/* Implements the .loc_mark_labels {0,1} directive. */
extern void dwarf2_directive_loc_mark_labels (int dummy);

View File

@@ -38,9 +38,11 @@ const int DEBUG_SCRIPT = 0x2;
const int DEBUG_FILES = 0x4;
const int DEBUG_RELAXATION = 0x8;
const int DEBUG_INCREMENTAL = 0x10;
const int DEBUG_LOCATION = 0x20;
const int DEBUG_ALL = (DEBUG_TASK | DEBUG_SCRIPT | DEBUG_FILES
| DEBUG_RELAXATION | DEBUG_INCREMENTAL);
| DEBUG_RELAXATION | DEBUG_INCREMENTAL
| DEBUG_LOCATION);
// Convert a debug string to the appropriate enum.
inline int
@@ -54,6 +56,7 @@ debug_string_to_enum(const char* arg)
{ "files", DEBUG_FILES },
{ "relaxation", DEBUG_RELAXATION },
{ "incremental", DEBUG_INCREMENTAL },
{ "location", DEBUG_LOCATION },
{ "all", DEBUG_ALL }
};

View File

@@ -26,6 +26,7 @@
#include <utility>
#include <vector>
#include "debug.h"
#include "elfcpp_swap.h"
#include "dwarf.h"
#include "object.h"
@@ -1526,6 +1527,7 @@ struct LineStateMachine
bool is_stmt; // stmt means statement.
bool basic_block;
bool end_sequence;
unsigned int context;
};
static void
@@ -1539,6 +1541,7 @@ ResetLineStateMachine(struct LineStateMachine* lsm, bool default_is_stmt)
lsm->is_stmt = default_is_stmt;
lsm->basic_block = false;
lsm->end_sequence = false;
lsm->context = 0;
}
template<int size, bool big_endian>
@@ -1546,27 +1549,40 @@ Sized_dwarf_line_info<size, big_endian>::Sized_dwarf_line_info(
Object* object,
unsigned int read_shndx)
: data_valid_(false), buffer_(NULL), buffer_start_(NULL),
str_buffer_(NULL), str_buffer_start_(NULL),
reloc_mapper_(NULL), symtab_buffer_(NULL), directories_(), files_(),
current_header_index_(-1)
current_header_index_(-1), reloc_map_(), line_number_map_()
{
unsigned int debug_shndx;
unsigned int debug_line_shndx = 0;
unsigned int debug_line_str_shndx = 0;
for (debug_shndx = 1; debug_shndx < object->shnum(); ++debug_shndx)
for (unsigned int i = 1; i < object->shnum(); ++i)
{
section_size_type buffer_size;
bool is_new = false;
// FIXME: do this more efficiently: section_name() isn't super-fast
std::string name = object->section_name(debug_shndx);
std::string name = object->section_name(i);
if (name == ".debug_line" || name == ".zdebug_line")
{
section_size_type buffer_size;
bool is_new = false;
this->buffer_ = object->decompressed_section_contents(debug_shndx,
&buffer_size,
&is_new);
this->buffer_ =
object->decompressed_section_contents(i, &buffer_size, &is_new);
if (is_new)
this->buffer_start_ = this->buffer_;
this->buffer_end_ = this->buffer_ + buffer_size;
break;
debug_line_shndx = i;
}
else if (name == ".debug_line_str" || name == ".zdebug_line_str")
{
this->str_buffer_ =
object->decompressed_section_contents(i, &buffer_size, &is_new);
if (is_new)
this->str_buffer_start_ = this->str_buffer_;
this->str_buffer_end_ = this->str_buffer_ + buffer_size;
debug_line_str_shndx = i;
}
if (debug_line_shndx > 0 && debug_line_str_shndx > 0)
break;
}
if (this->buffer_ == NULL)
return;
@@ -1579,7 +1595,7 @@ Sized_dwarf_line_info<size, big_endian>::Sized_dwarf_line_info(
unsigned int reloc_sh_type = object->section_type(i);
if ((reloc_sh_type == elfcpp::SHT_REL
|| reloc_sh_type == elfcpp::SHT_RELA)
&& object->section_info(i) == debug_shndx)
&& object->section_info(i) == debug_line_shndx)
{
reloc_shndx = i;
this->track_relocs_type_ = reloc_sh_type;
@@ -1612,6 +1628,8 @@ Sized_dwarf_line_info<size, big_endian>::Sized_dwarf_line_info(
// Now that we have successfully read all the data, parse the debug
// info.
this->data_valid_ = true;
gold_debug(DEBUG_LOCATION, "read_line_mappings: %s shndx %u",
object->name().c_str(), read_shndx);
this->read_line_mappings(read_shndx);
}
@@ -1638,20 +1656,39 @@ Sized_dwarf_line_info<size, big_endian>::read_header_prolog(
header_.total_length = initial_length;
gold_assert(lineptr + header_.total_length <= buffer_end_);
this->end_of_unit_ = lineptr + initial_length;
gold_assert(this->end_of_unit_ <= buffer_end_);
header_.version = elfcpp::Swap_unaligned<16, big_endian>::readval(lineptr);
lineptr += 2;
// We can only read versions 2 and 3 of the DWARF line number table.
// For other versions, just skip the entire line number table.
if ((header_.version < 2 || header_.version > 4)
&& header_.version != DWARF5_EXPERIMENTAL_LINE_TABLE)
return this->end_of_unit_;
if (header_.offset_size == 4)
header_.prologue_length = elfcpp::Swap_unaligned<32, big_endian>::readval(lineptr);
else
header_.prologue_length = elfcpp::Swap_unaligned<64, big_endian>::readval(lineptr);
lineptr += header_.offset_size;
this->end_of_header_length_ = lineptr;
// If this is a two-level line table, we'll adjust these below.
this->logicals_start_ = lineptr + header_.prologue_length;
this->actuals_start_ = NULL;
header_.min_insn_length = *lineptr;
lineptr += 1;
if (header_.version >= 4)
{
header_.max_ops_per_insn = *lineptr;
lineptr += 1;
}
header_.default_is_stmt = *lineptr;
lineptr += 1;
@@ -1672,6 +1709,32 @@ Sized_dwarf_line_info<size, big_endian>::read_header_prolog(
lineptr += 1;
}
if (header_.version == DWARF5_EXPERIMENTAL_LINE_TABLE)
{
// Skip over fake empty directory and filename tables,
// and fake extended opcode that hides the rest of the
// section from old consumers.
lineptr += 7;
// Offsets to logicals and actuals tables.
off_t logicals_offset;
off_t actuals_offset;
if (header_.offset_size == 4)
logicals_offset = elfcpp::Swap_unaligned<32, big_endian>::readval(lineptr);
else
logicals_offset = elfcpp::Swap_unaligned<64, big_endian>::readval(lineptr);
lineptr += header_.offset_size;
if (header_.offset_size == 4)
actuals_offset = elfcpp::Swap_unaligned<32, big_endian>::readval(lineptr);
else
actuals_offset = elfcpp::Swap_unaligned<64, big_endian>::readval(lineptr);
lineptr += header_.offset_size;
this->logicals_start_ = this->end_of_header_length_ + logicals_offset;
if (actuals_offset > 0)
this->actuals_start_ = this->end_of_header_length_ + actuals_offset;
}
return lineptr;
}
@@ -1745,12 +1808,180 @@ Sized_dwarf_line_info<size, big_endian>::read_header_tables(
return lineptr;
}
template<int size, bool big_endian>
const unsigned char*
Sized_dwarf_line_info<size, big_endian>::read_header_tables_v5(
const unsigned char* lineptr)
{
size_t len;
++this->current_header_index_;
// Create a new directories_ entry and a new files_ entry for our new
// header. We initialize each with a single empty element, because
// dwarf indexes directory and filenames starting at 1.
gold_assert(static_cast<int>(this->directories_.size())
== this->current_header_index_);
gold_assert(static_cast<int>(this->files_.size())
== this->current_header_index_);
// Read the directory list.
uint64_t format_count = read_unsigned_LEB_128(lineptr, &len);
lineptr += len;
unsigned int *types = new unsigned int[format_count];
unsigned int *forms = new unsigned int[format_count];
for (unsigned int i = 0; i < format_count; i++)
{
types[i] = read_unsigned_LEB_128(lineptr, &len);
lineptr += len;
forms[i] = read_unsigned_LEB_128(lineptr, &len);
lineptr += len;
}
uint64_t entry_count = read_unsigned_LEB_128(lineptr, &len);
lineptr += len;
this->directories_.push_back(std::vector<std::string>(1));
std::vector<std::string>& dir_list = this->directories_.back();
for (unsigned int j = 0; j < entry_count; j++)
{
std::string dirname;
for (unsigned int i = 0; i < format_count; i++)
{
if (types[i] == elfcpp::DW_LNCT_path)
{
if (forms[i] == elfcpp::DW_FORM_string)
{
dirname = reinterpret_cast<const char*>(lineptr);
lineptr += dirname.size() + 1;
}
else if (forms[i] == elfcpp::DW_FORM_line_strp)
{
uint64_t offset;
if (header_.offset_size == 4)
offset = elfcpp::Swap_unaligned<32, big_endian>::readval(lineptr);
else
offset = elfcpp::Swap_unaligned<64, big_endian>::readval(lineptr);
typename Reloc_map::const_iterator it
= this->reloc_map_.find(lineptr - this->buffer_);
if (it != reloc_map_.end())
{
if (this->track_relocs_type_ == elfcpp::SHT_RELA)
offset = 0;
offset += it->second.second;
}
lineptr += header_.offset_size;
dirname = reinterpret_cast<const char*>(this->str_buffer_
+ offset);
}
else
return lineptr;
}
else
return lineptr;
}
dir_list.push_back(dirname);
}
delete[] types;
delete[] forms;
// Read the filenames list.
format_count = read_unsigned_LEB_128(lineptr, &len);
lineptr += len;
types = new unsigned int[format_count];
forms = new unsigned int[format_count];
for (unsigned int i = 0; i < format_count; i++)
{
types[i] = read_unsigned_LEB_128(lineptr, &len);
lineptr += len;
forms[i] = read_unsigned_LEB_128(lineptr, &len);
lineptr += len;
}
entry_count = read_unsigned_LEB_128(lineptr, &len);
lineptr += len;
this->files_.push_back(
std::vector<std::pair<int, std::string> >(1));
std::vector<std::pair<int, std::string> >& file_list = this->files_.back();
for (unsigned int j = 0; j < entry_count; j++)
{
const char* path = NULL;
int dirindex = 0;
for (unsigned int i = 0; i < format_count; i++)
{
if (types[i] == elfcpp::DW_LNCT_path)
{
if (forms[i] == elfcpp::DW_FORM_string)
{
path = reinterpret_cast<const char*>(lineptr);
lineptr += strlen(path) + 1;
}
else if (forms[i] == elfcpp::DW_FORM_line_strp)
{
uint64_t offset;
if (header_.offset_size == 4)
offset = elfcpp::Swap_unaligned<32, big_endian>::readval(lineptr);
else
offset = elfcpp::Swap_unaligned<64, big_endian>::readval(lineptr);
typename Reloc_map::const_iterator it
= this->reloc_map_.find(lineptr - this->buffer_);
if (it != reloc_map_.end())
{
if (this->track_relocs_type_ == elfcpp::SHT_RELA)
offset = 0;
offset += it->second.second;
}
lineptr += header_.offset_size;
path = reinterpret_cast<const char*>(this->str_buffer_
+ offset);
}
else
return lineptr;
}
else if (types[i] == elfcpp::DW_LNCT_directory_index)
{
if (forms[i] == elfcpp::DW_FORM_udata)
{
dirindex = read_unsigned_LEB_128(lineptr, &len);
lineptr += len;
}
else
return lineptr;
}
else
return lineptr;
}
gold_debug(DEBUG_LOCATION, "File %3d: %s",
static_cast<int>(file_list.size()), path);
file_list.push_back(std::make_pair<int, std::string>(dirindex, path));
}
delete[] types;
delete[] forms;
// Ignore the subprograms table; we don't need it for now.
// Because it's the last thing in the header, we don't need
// to figure out how long it is to skip over it.
return lineptr;
}
// Process a single opcode in the .debug.line structure.
template<int size, bool big_endian>
bool
Sized_dwarf_line_info<size, big_endian>::process_one_opcode(
const unsigned char* start, struct LineStateMachine* lsm, size_t* len)
const unsigned char* start, struct LineStateMachine* lsm, size_t* len,
std::vector<LineStateMachine>* logicals,
bool is_logicals_table, bool is_actuals_table)
{
size_t oplen = 0;
size_t templen;
@@ -1794,7 +2025,7 @@ Sized_dwarf_line_info<size, big_endian>::process_one_opcode(
case elfcpp::DW_LNS_advance_line:
{
const uint64_t advance_line = read_signed_LEB_128(start, &templen);
const int64_t advance_line = read_signed_LEB_128(start, &templen);
oplen += templen;
lsm->line_num += advance_line;
}
@@ -1842,6 +2073,61 @@ Sized_dwarf_line_info<size, big_endian>::process_one_opcode(
}
break;
case elfcpp::DW_LNS_set_subprogram:
// aliased with elfcpp::DW_LNS_set_address_from_logical
if (is_actuals_table)
{
// elfcpp::DW_LNS_set_address_from_logical
const int64_t advance_line = read_signed_LEB_128(start, &templen);
oplen += templen;
lsm->line_num += advance_line;
if (lsm->line_num >= 1
&& lsm->line_num <= static_cast<int64_t>(logicals->size()))
{
const LineStateMachine& logical = (*logicals)[lsm->line_num - 1];
lsm->address = logical.address;
lsm->shndx = logical.shndx;
}
}
else if (is_logicals_table)
{
// elfcpp::DW_LNS_set_subprogram
// Ignore the subprogram number for now.
read_unsigned_LEB_128(start, &templen);
oplen += templen;
lsm->context = 0;
}
break;
case elfcpp::DW_LNS_inlined_call:
if (is_logicals_table)
{
const int64_t advance_line = read_signed_LEB_128(start, &templen);
oplen += templen;
start += templen;
// Ignore the subprogram number for now.
read_unsigned_LEB_128(start, &templen);
oplen += templen;
lsm->context = logicals->size() + advance_line;
}
break;
case elfcpp::DW_LNS_pop_context:
if (is_logicals_table)
{
const unsigned int context = lsm->context;
if (context >= 1 && context <= logicals->size())
{
const LineStateMachine& logical = (*logicals)[context - 1];
lsm->file_num = logical.file_num;
lsm->line_num = logical.line_num;
lsm->column_num = logical.column_num;
lsm->is_stmt = logical.is_stmt;
lsm->context = logical.context;
}
}
break;
case elfcpp::DW_LNS_extended_op:
{
const uint64_t extended_op_len
@@ -1939,54 +2225,92 @@ Sized_dwarf_line_info<size, big_endian>::process_one_opcode(
template<int size, bool big_endian>
unsigned const char*
Sized_dwarf_line_info<size, big_endian>::read_lines(unsigned const char* lineptr,
unsigned int shndx)
Sized_dwarf_line_info<size, big_endian>::read_lines(
unsigned const char* lineptr,
unsigned const char* endptr,
std::vector<LineStateMachine>* logicals,
bool is_logicals_table,
bool is_actuals_table,
unsigned int shndx)
{
struct LineStateMachine lsm;
// LENGTHSTART is the place the length field is based on. It is the
// point in the header after the initial length field.
const unsigned char* lengthstart = buffer_;
// In 64 bit dwarf, the initial length is 12 bytes, because of the
// 0xffffffff at the start.
if (header_.offset_size == 8)
lengthstart += 12;
else
lengthstart += 4;
while (lineptr < lengthstart + header_.total_length)
while (lineptr < endptr)
{
ResetLineStateMachine(&lsm, header_.default_is_stmt);
while (!lsm.end_sequence)
{
size_t oplength;
bool add_line = this->process_one_opcode(lineptr, &lsm, &oplength);
if (add_line
&& (shndx == -1U || lsm.shndx == -1U || shndx == lsm.shndx))
{
Offset_to_lineno_entry entry
= { static_cast<off_t>(lsm.address),
this->current_header_index_,
static_cast<unsigned int>(lsm.file_num),
true, lsm.line_num };
std::vector<Offset_to_lineno_entry>&
map(this->line_number_map_[lsm.shndx]);
// If we see two consecutive entries with the same
// offset and a real line number, then mark the first
// one as non-canonical.
if (!map.empty()
&& (map.back().offset == static_cast<off_t>(lsm.address))
&& lsm.line_num != -1
&& map.back().line_num != -1)
map.back().last_line_for_offset = false;
map.push_back(entry);
}
if (lineptr >= endptr)
break;
bool add_line = this->process_one_opcode(lineptr, &lsm, &oplength,
logicals,
is_logicals_table,
is_actuals_table);
lineptr += oplength;
if (add_line)
{
if (is_logicals_table)
{
logicals->push_back(lsm);
gold_debug(DEBUG_LOCATION, "Logical %d [%3u:%08x]: "
"file %d line %d context %u",
static_cast<int>(logicals->size()),
lsm.shndx, static_cast<int>(lsm.address),
lsm.file_num, lsm.line_num, lsm.context);
}
else if (shndx == -1U || lsm.shndx == -1U || shndx == lsm.shndx)
{
Offset_to_lineno_entry entry;
if (is_actuals_table && lsm.line_num != -1)
{
if (lsm.line_num < 1
|| lsm.line_num > static_cast<int64_t>(logicals->size()))
continue;
const LineStateMachine& logical =
(*logicals)[lsm.line_num - 1];
gold_debug(DEBUG_LOCATION, "Actual [%3u:%08x]: "
"logical %u file %d line %d context %u",
lsm.shndx, static_cast<int>(lsm.address),
lsm.line_num, logical.file_num,
logical.line_num, logical.context);
entry.offset = static_cast<off_t>(lsm.address);
entry.header_num = this->current_header_index_;
entry.file_num =
static_cast<unsigned int>(logical.file_num);
entry.last_line_for_offset = true;
entry.line_num = logical.line_num;
}
else
{
entry.offset = static_cast<off_t>(lsm.address);
entry.header_num = this->current_header_index_;
entry.file_num = static_cast<unsigned int>(lsm.file_num);
entry.last_line_for_offset = true;
entry.line_num = lsm.line_num;
}
std::vector<Offset_to_lineno_entry>&
map(this->line_number_map_[lsm.shndx]);
// If we see two consecutive entries with the same
// offset and a real line number, then mark the first
// one as non-canonical.
if (!map.empty()
&& (map.back().offset == static_cast<off_t>(lsm.address))
&& lsm.line_num != -1
&& map.back().line_num != -1)
map.back().last_line_for_offset = false;
map.push_back(entry);
}
}
}
}
return lengthstart + header_.total_length;
return endptr;
}
// Read the relocations into a Reloc_map.
@@ -2026,10 +2350,48 @@ Sized_dwarf_line_info<size, big_endian>::read_line_mappings(unsigned int shndx)
while (this->buffer_ < this->buffer_end_)
{
const unsigned char* lineptr = this->buffer_;
std::vector<LineStateMachine> logicals;
lineptr = this->read_header_prolog(lineptr);
lineptr = this->read_header_tables(lineptr);
lineptr = this->read_lines(lineptr, shndx);
this->buffer_ = lineptr;
if (header_.version >= 2 && header_.version <= 4)
{
lineptr = this->read_header_tables(lineptr);
lineptr = this->read_lines(this->logicals_start_,
this->end_of_unit_,
NULL,
false,
false,
shndx);
}
else if (header_.version == DWARF5_EXPERIMENTAL_LINE_TABLE)
{
lineptr = this->read_header_tables_v5(lineptr);
if (this->actuals_start_ != NULL)
{
lineptr = this->read_lines(this->logicals_start_,
this->actuals_start_,
&logicals,
true,
false,
shndx);
lineptr = this->read_lines(this->actuals_start_,
this->end_of_unit_,
&logicals,
false,
true,
shndx);
}
else
{
lineptr = this->read_lines(this->logicals_start_,
this->end_of_unit_,
NULL,
false,
false,
shndx);
}
}
this->buffer_ = this->end_of_unit_;
}
// Sort the lines numbers, so addr2line can use binary search.
@@ -2185,6 +2547,9 @@ Sized_dwarf_line_info<size, big_endian>::do_addr2line(
off_t offset,
std::vector<std::string>* other_lines)
{
gold_debug(DEBUG_LOCATION, "do_addr2line: shndx %u offset %08x",
shndx, static_cast<int>(offset));
if (this->data_valid_ == false)
return "";
@@ -2205,13 +2570,33 @@ Sized_dwarf_line_info<size, big_endian>::do_addr2line(
return "";
std::string result = this->format_file_lineno(*it);
gold_debug(DEBUG_LOCATION, "do_addr2line: canonical result: %s",
result.c_str());
if (other_lines != NULL)
for (++it; it != offsets->end() && it->offset == offset; ++it)
{
if (it->line_num == -1)
continue; // The end of a previous function.
other_lines->push_back(this->format_file_lineno(*it));
}
{
unsigned int last_file_num = it->file_num;
int last_line_num = it->line_num;
// Return up to 4 more locations from the beginning of the function
// for fuzzy matching.
for (++it; it != offsets->end(); ++it)
{
if (it->offset == offset && it->line_num == -1)
continue; // The end of a previous function.
if (it->line_num == -1)
break; // The end of the current function.
if (it->file_num != last_file_num || it->line_num != last_line_num)
{
other_lines->push_back(this->format_file_lineno(*it));
gold_debug(DEBUG_LOCATION, "do_addr2line: other: %s",
other_lines->back().c_str());
last_file_num = it->file_num;
last_line_num = it->line_num;
}
if (it->offset > offset && other_lines->size() >= 4)
break;
}
}
return result;
}

View File

@@ -1001,9 +1001,13 @@ class Sized_dwarf_line_info : public Dwarf_line_info
{
if (this->buffer_start_ != NULL)
delete[] this->buffer_start_;
if (this->str_buffer_start_ != NULL)
delete[] this->str_buffer_start_;
}
private:
const static int DWARF5_EXPERIMENTAL_LINE_TABLE = 0xf006;
std::string
do_addr2line(unsigned int shndx, off_t offset,
std::vector<std::string>* other_lines);
@@ -1031,11 +1035,17 @@ class Sized_dwarf_line_info : public Dwarf_line_info
const unsigned char*
read_header_tables(const unsigned char* lineptr);
const unsigned char*
read_header_tables_v5(const unsigned char* lineptr);
// Reads the DWARF2/3 line information. If shndx is non-negative,
// discard all line information that doesn't pertain to the given
// section.
const unsigned char*
read_lines(const unsigned char* lineptr, unsigned int shndx);
read_lines(const unsigned char* lineptr, const unsigned char* endptr,
std::vector<LineStateMachine>* logicals,
bool is_logicals_table, bool is_actuals_table,
unsigned int shndx);
// Process a single line info opcode at START using the state
// machine at LSM. Return true if we should define a line using the
@@ -1043,7 +1053,9 @@ class Sized_dwarf_line_info : public Dwarf_line_info
// opcode in LEN.
bool
process_one_opcode(const unsigned char* start,
struct LineStateMachine* lsm, size_t* len);
struct LineStateMachine* lsm, size_t* len,
std::vector<LineStateMachine>* logicals,
bool is_logicals_table, bool is_actuals_table);
// Some parts of processing differ depending on whether the input
// was a .o file or not.
@@ -1064,6 +1076,7 @@ class Sized_dwarf_line_info : public Dwarf_line_info
int version;
off_t prologue_length;
int min_insn_length; // insn stands for instructin
int max_ops_per_insn;
bool default_is_stmt; // stmt stands for statement
signed char line_base;
int line_range;
@@ -1081,6 +1094,26 @@ class Sized_dwarf_line_info : public Dwarf_line_info
// of the buffer.
const unsigned char* buffer_start_;
// buffer is the buffer for our line info, starting at exactly where
// the line info to read is.
const unsigned char* str_buffer_;
const unsigned char* str_buffer_end_;
// If the buffer was allocated temporarily, and therefore must be
// deallocated in the dtor, this contains a pointer to the start
// of the buffer.
const unsigned char* str_buffer_start_;
// Pointer to the end of the header_length field (aka prologue_length).
// The offsets to the line number programs are relative to this point.
const unsigned char* end_of_header_length_;
// Pointers to the start of the line number programs.
const unsigned char* logicals_start_;
const unsigned char* actuals_start_;
// Pointer to the end of the current compilation unit.
const unsigned char* end_of_unit_;
// This has relocations that point into buffer.
Sized_elf_reloc_mapper<size, big_endian>* reloc_mapper_;
// The type of the reloc section in track_relocs_--SHT_REL or SHT_RELA.

View File

@@ -284,14 +284,6 @@ class Sized_relobj_dwo : public Sized_relobj<size, big_endian>
const unsigned char*
do_section_contents(unsigned int, section_size_type*, bool);
// Return a view of the uncompressed contents of a section. Set *PLEN
// to the size. Set *IS_NEW to true if the contents need to be deleted
// by the caller.
const unsigned char*
do_decompressed_section_contents(unsigned int shndx,
section_size_type* plen,
bool* is_new);
// The following virtual functions are abstract in the base classes,
// but are not used here.
@@ -781,9 +773,36 @@ template <int size, bool big_endian>
void
Sized_relobj_dwo<size, big_endian>::setup()
{
const int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
const off_t shoff = this->elf_file_.shoff();
const unsigned int shnum = this->elf_file_.shnum();
this->set_shnum(shnum);
this->section_offsets().resize(shnum);
// Read the section headers.
const unsigned char* const pshdrs = this->get_view(shoff, shnum * shdr_size,
true, false);
// Read the section names.
const unsigned char* pshdrnames =
pshdrs + this->elf_file_.shstrndx() * shdr_size;
typename elfcpp::Shdr<size, big_endian> shdrnames(pshdrnames);
if (shdrnames.get_sh_type() != elfcpp::SHT_STRTAB)
this->error(_("section name section has wrong type: %u"),
static_cast<unsigned int>(shdrnames.get_sh_type()));
section_size_type section_names_size =
convert_to_section_size_type(shdrnames.get_sh_size());
const unsigned char* namesu = this->get_view(shdrnames.get_sh_offset(),
section_names_size, false,
false);
const char* names = reinterpret_cast<const char*>(namesu);
Compressed_section_map* compressed_sections =
build_compressed_section_map<size, big_endian>(
pshdrs, this->shnum(), names, section_names_size, this, true);
if (compressed_sections != NULL && !compressed_sections->empty())
this->set_compressed_sections(compressed_sections);
}
// Return a view of the contents of a section.
@@ -805,43 +824,6 @@ Sized_relobj_dwo<size, big_endian>::do_section_contents(
return this->get_view(loc.file_offset, *plen, true, cache);
}
// Return a view of the uncompressed contents of a section. Set *PLEN
// to the size. Set *IS_NEW to true if the contents need to be deleted
// by the caller.
template <int size, bool big_endian>
const unsigned char*
Sized_relobj_dwo<size, big_endian>::do_decompressed_section_contents(
unsigned int shndx,
section_size_type* plen,
bool* is_new)
{
section_size_type buffer_size;
const unsigned char* buffer = this->do_section_contents(shndx, &buffer_size,
false);
std::string sect_name = this->do_section_name(shndx);
if (!is_prefix_of(".zdebug_", sect_name.c_str()))
{
*plen = buffer_size;
*is_new = false;
return buffer;
}
section_size_type uncompressed_size = get_uncompressed_size(buffer,
buffer_size);
unsigned char* uncompressed_data = new unsigned char[uncompressed_size];
if (!decompress_input_section(buffer,
buffer_size,
uncompressed_data,
uncompressed_size))
this->error(_("could not decompress section %s"),
this->section_name(shndx).c_str());
*plen = uncompressed_size;
*is_new = true;
return uncompressed_data;
}
// Class Dwo_file.
Dwo_file::~Dwo_file()
@@ -2352,7 +2334,7 @@ print_version()
{
// This output is intended to follow the GNU standards.
printf("GNU dwp %s\n", BFD_VERSION_STRING);
printf(_("Copyright (C) 2014-2015 Free Software Foundation, Inc.\n"));
printf(_("Copyright (C) 2015 Free Software Foundation, Inc.\n"));
printf(_("\
This program is free software; you may redistribute it under the terms of\n\
the GNU General Public License version 3 or (at your option) any later version.\n\

View File

@@ -374,6 +374,17 @@ Sized_dynobj<size, big_endian>::base_read_symbols(Read_symbols_data* sd)
sd->verneed_size = 0;
sd->verneed_info = 0;
const unsigned char* namesu = sd->section_names->data();
const char* names = reinterpret_cast<const char*>(namesu);
if (memmem(names, sd->section_names_size, ".zdebug_", 8) != NULL)
{
Compressed_section_map* compressed_sections =
build_compressed_section_map<size, big_endian>(
pshdrs, this->shnum(), names, sd->section_names_size, this, true);
if (compressed_sections != NULL)
this->set_compressed_sections(compressed_sections);
}
if (this->dynsym_shndx_ != -1U)
{
// Get the dynamic symbols.

View File

@@ -432,8 +432,7 @@ Sized_relobj_file<size, big_endian>::Sized_relobj_file(
discarded_eh_frame_shndx_(-1U),
is_deferred_layout_(false),
deferred_layout_(),
deferred_layout_relocs_(),
compressed_sections_()
deferred_layout_relocs_()
{
this->e_type_ = ehdr.get_e_type();
}
@@ -675,7 +674,8 @@ build_compressed_section_map(
unsigned int shnum,
const char* names,
section_size_type names_size,
Sized_relobj_file<size, big_endian>* obj)
Object* obj,
bool decompress_if_needed)
{
Compressed_section_map* uncompressed_map = new Compressed_section_map();
const unsigned int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
@@ -707,7 +707,7 @@ build_compressed_section_map(
if (uncompressed_size != -1ULL)
{
unsigned char* uncompressed_data = NULL;
if (need_decompressed_section(name))
if (decompress_if_needed && need_decompressed_section(name))
{
uncompressed_data = new unsigned char[uncompressed_size];
if (decompress_input_section(contents, len,
@@ -741,9 +741,14 @@ Sized_relobj_file<size, big_endian>::do_find_special_sections(
this->has_eh_frame_ = true;
if (memmem(names, sd->section_names_size, ".zdebug_", 8) != NULL)
this->compressed_sections_
= build_compressed_section_map(pshdrs, this->shnum(), names,
sd->section_names_size, this);
{
Compressed_section_map* compressed_sections =
build_compressed_section_map<size, big_endian>(
pshdrs, this->shnum(), names, sd->section_names_size, this, true);
if (compressed_sections != NULL)
this->set_compressed_sections(compressed_sections);
}
return (this->has_eh_frame_
|| (!parameters->options().relocatable()
&& parameters->options().gdb_index()
@@ -2804,9 +2809,8 @@ Sized_relobj_file<size, big_endian>::do_get_global_symbol_counts(
// to the size. Set *IS_NEW to true if the contents need to be freed
// by the caller.
template<int size, bool big_endian>
const unsigned char*
Sized_relobj_file<size, big_endian>::do_decompressed_section_contents(
Object::decompressed_section_contents(
unsigned int shndx,
section_size_type* plen,
bool* is_new)
@@ -2860,9 +2864,8 @@ Sized_relobj_file<size, big_endian>::do_decompressed_section_contents(
// Discard any buffers of uncompressed sections. This is done
// at the end of the Add_symbols task.
template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::do_discard_decompressed_sections()
Object::discard_decompressed_sections()
{
if (this->compressed_sections_ == NULL)
return;

View File

@@ -314,6 +314,21 @@ class Got_offset_list
Got_offset_list* got_next_;
};
// Type for mapping section index to uncompressed size and contents.
struct Compressed_section_info
{
section_size_type size;
const unsigned char* contents;
};
typedef std::map<unsigned int, Compressed_section_info> Compressed_section_map;
template<int size, bool big_endian>
Compressed_section_map*
build_compressed_section_map(const unsigned char* pshdrs, unsigned int shnum,
const char* names, section_size_type names_size,
Object* obj, bool decompress_if_needed);
// Object is an abstract base class which represents either a 32-bit
// or a 64-bit input object. This can be a regular object file
// (ET_REL) or a shared object (ET_DYN).
@@ -332,7 +347,8 @@ class Object
: name_(name), input_file_(input_file), offset_(offset), shnum_(-1U),
is_dynamic_(is_dynamic), is_needed_(false), uses_split_stack_(false),
has_no_split_stack_(false), no_export_(false),
is_in_system_directory_(false), as_needed_(false), xindex_(NULL)
is_in_system_directory_(false), as_needed_(false), xindex_(NULL),
compressed_sections_(NULL)
{
if (input_file != NULL)
{
@@ -725,26 +741,34 @@ class Object
set_no_export(bool value)
{ this->no_export_ = value; }
// Return TRUE if the section is a compressed debug section, and set
// *UNCOMPRESSED_SIZE to the size of the uncompressed data.
bool
section_is_compressed(unsigned int shndx,
section_size_type* uncompressed_size) const
{ return this->do_section_is_compressed(shndx, uncompressed_size); }
{
if (this->compressed_sections_ == NULL)
return false;
Compressed_section_map::const_iterator p =
this->compressed_sections_->find(shndx);
if (p != this->compressed_sections_->end())
{
if (uncompressed_size != NULL)
*uncompressed_size = p->second.size;
return true;
}
return false;
}
// Return a view of the decompressed contents of a section. Set *PLEN
// to the size. Set *IS_NEW to true if the contents need to be freed
// by the caller.
const unsigned char*
decompressed_section_contents(unsigned int shndx, section_size_type* plen,
bool* is_cached)
{ return this->do_decompressed_section_contents(shndx, plen, is_cached); }
bool* is_cached);
// Discard any buffers of decompressed sections. This is done
// at the end of the Add_symbols task.
void
discard_decompressed_sections()
{ this->do_discard_decompressed_sections(); }
discard_decompressed_sections();
// Return the index of the first incremental relocation for symbol SYMNDX.
unsigned int
@@ -923,27 +947,6 @@ class Object
bool
handle_split_stack_section(const char* name);
// Return TRUE if the section is a compressed debug section, and set
// *UNCOMPRESSED_SIZE to the size of the uncompressed data.
virtual bool
do_section_is_compressed(unsigned int, section_size_type*) const
{ return false; }
// Return a view of the decompressed contents of a section. Set *PLEN
// to the size. This default implementation simply returns the
// raw section contents and sets *IS_NEW to false to indicate
// that the contents do not need to be freed by the caller.
// This function must be overridden for any types of object files
// that might contain compressed sections.
virtual const unsigned char*
do_decompressed_section_contents(unsigned int shndx,
section_size_type* plen,
bool* is_new)
{
*is_new = false;
return this->do_section_contents(shndx, plen, false);
}
// Discard any buffers of decompressed sections. This is done
// at the end of the Add_symbols task.
virtual void
@@ -962,6 +965,14 @@ class Object
do_get_incremental_reloc_count(unsigned int) const
{ gold_unreachable(); }
void
set_compressed_sections(Compressed_section_map* compressed_sections)
{ this->compressed_sections_ = compressed_sections; }
Compressed_section_map*
compressed_sections()
{ return this->compressed_sections_; }
private:
// This class may not be copied.
Object(const Object&);
@@ -996,6 +1007,9 @@ class Object
bool as_needed_ : 1;
// Many sections for objects with more than SHN_LORESERVE sections.
Xindex* xindex_;
// For compressed debug sections, map section index to uncompressed size
// and contents.
Compressed_section_map* compressed_sections_;
};
// A regular object (ET_REL). This is an abstract base class itself.
@@ -1862,15 +1876,6 @@ class Reloc_symbol_changes
std::vector<Symbol*> vec_;
};
// Type for mapping section index to uncompressed size and contents.
struct Compressed_section_info
{
section_size_type size;
const unsigned char* contents;
};
typedef std::map<unsigned int, Compressed_section_info> Compressed_section_map;
// Abstract base class for a regular object file, either a real object file
// or an incremental (unchanged) object. This is size and endian specific.
@@ -2453,38 +2458,6 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
set_output_local_symbol_count(unsigned int value)
{ this->output_local_symbol_count_ = value; }
// Return TRUE if the section is a compressed debug section, and set
// *UNCOMPRESSED_SIZE to the size of the uncompressed data.
bool
do_section_is_compressed(unsigned int shndx,
section_size_type* uncompressed_size) const
{
if (this->compressed_sections_ == NULL)
return false;
Compressed_section_map::const_iterator p =
this->compressed_sections_->find(shndx);
if (p != this->compressed_sections_->end())
{
if (uncompressed_size != NULL)
*uncompressed_size = p->second.size;
return true;
}
return false;
}
// Return a view of the uncompressed contents of a section. Set *PLEN
// to the size. Set *IS_NEW to true if the contents need to be deleted
// by the caller.
const unsigned char*
do_decompressed_section_contents(unsigned int shndx,
section_size_type* plen,
bool* is_new);
// Discard any buffers of decompressed sections. This is done
// at the end of the Add_symbols task.
void
do_discard_decompressed_sections();
private:
// For convenience.
typedef Sized_relobj_file<size, big_endian> This;
@@ -2751,9 +2724,6 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
std::vector<Deferred_layout> deferred_layout_;
// The list of relocation sections whose layout was deferred.
std::vector<Deferred_layout> deferred_layout_relocs_;
// For compressed debug sections, map section index to uncompressed size
// and contents.
Compressed_section_map* compressed_sections_;
};
// A class to manage the list of all objects.

View File

@@ -3336,8 +3336,11 @@ Symbol_table::detect_odr_violations(const Task* task,
first_object_name = locs->object->name();
first_object_linenos = this->linenos_from_loc(task, *locs);
}
if (first_object_linenos.empty())
continue;
// Sort by Odr_violation_compare to make std::set_intersection work.
std::string first_object_canonical_result = first_object_linenos.back();
std::sort(first_object_linenos.begin(), first_object_linenos.end(),
Odr_violation_compare());
@@ -3349,6 +3352,8 @@ Symbol_table::detect_odr_violations(const Task* task,
if (linenos.empty())
continue;
// Sort by Odr_violation_compare to make std::set_intersection work.
gold_assert(!linenos.empty());
std::string second_object_canonical_result = linenos.back();
std::sort(linenos.begin(), linenos.end(), Odr_violation_compare());
Check_intersection intersection_result =
@@ -3367,13 +3372,11 @@ Symbol_table::detect_odr_violations(const Task* task,
// which may not be the location we expect to intersect
// with another definition. We could print the whole
// set of locations, but that seems too verbose.
gold_assert(!first_object_linenos.empty());
gold_assert(!linenos.empty());
fprintf(stderr, _(" %s from %s\n"),
first_object_linenos[0].c_str(),
first_object_canonical_result.c_str(),
first_object_name.c_str());
fprintf(stderr, _(" %s from %s\n"),
linenos[0].c_str(),
second_object_canonical_result.c_str(),
locs->object->name().c_str());
// Only print one broken pair, to avoid needing to
// compare against a list of the disjoint definition

View File

@@ -200,6 +200,8 @@ DW_FORM (DW_FORM_sec_offset, 0x17)
DW_FORM (DW_FORM_exprloc, 0x18)
DW_FORM (DW_FORM_flag_present, 0x19)
DW_FORM (DW_FORM_ref_sig8, 0x20)
/* DWARF 5. */
DW_FORM (DW_FORM_line_strp, 0x1f)
/* Extensions for Fission. See http://gcc.gnu.org/wiki/DebugFission. */
DW_FORM (DW_FORM_GNU_addr_index, 0x1f01)
DW_FORM (DW_FORM_GNU_str_index, 0x1f02)

View File

@@ -222,7 +222,13 @@ enum dwarf_line_number_ops
/* DWARF 3. */
DW_LNS_set_prologue_end = 10,
DW_LNS_set_epilogue_begin = 11,
DW_LNS_set_isa = 12
DW_LNS_set_isa = 12,
/* Experimental DWARF 5 extensions.
See http://wiki.dwarfstd.org/index.php?title=TwoLevelLineTables. */
DW_LNS_set_address_from_logical = 13, /* Actuals table only. */
DW_LNS_set_subprogram = 13, /* Logicals table only. */
DW_LNS_inlined_call = 14, /* Logicals table only. */
DW_LNS_pop_context = 15 /* Logicals table only. */
};
/* Line number extended opcodes. */
@@ -268,6 +274,22 @@ enum dwarf_location_list_entry_type
DW_LLE_GNU_start_length_entry = 3
};
/* Type codes for line number program content descriptors (DWARF 5). */
enum dwarf_line_number_content_type
{
DW_LNCT_path = 1,
DW_LNCT_directory_index = 2,
DW_LNCT_timestamp = 3,
DW_LNCT_size = 4,
DW_LNCT_MD5 = 5,
/* Experimental DWARF 5 extensions.
See http://wiki.dwarfstd.org/index.php?title=TwoLevelLineTables. */
DW_LNCT_subprogram_name = 6,
DW_LNCT_decl_file = 7,
DW_LNCT_decl_line = 8
};
#define DW_CIE_ID 0xffffffff
#define DW64_CIE_ID 0xffffffffffffffffULL
#define DW_CIE_VERSION 1