// dwarf_reader.cc -- parse dwarf2/3 debug information
-// Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
+// Copyright 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
#include "reloc.h"
#include "dwarf_reader.h"
#include "int_encoding.h"
+#include "compressed_output.h"
namespace gold {
directories_(), files_(), current_header_index_(-1)
{
unsigned int debug_shndx;
- for (debug_shndx = 0; debug_shndx < object->shnum(); ++debug_shndx)
- // FIXME: do this more efficiently: section_name() isn't super-fast
- if (object->section_name(debug_shndx) == ".debug_line")
- {
- section_size_type buffer_size;
- this->buffer_ = object->section_contents(debug_shndx, &buffer_size,
- false);
- this->buffer_end_ = this->buffer_ + buffer_size;
- break;
- }
+ for (debug_shndx = 1; debug_shndx < object->shnum(); ++debug_shndx)
+ {
+ // FIXME: do this more efficiently: section_name() isn't super-fast
+ std::string name = object->section_name(debug_shndx);
+ if (name == ".debug_line" || name == ".zdebug_line")
+ {
+ section_size_type buffer_size;
+ this->buffer_ = object->section_contents(debug_shndx, &buffer_size,
+ false);
+ this->buffer_end_ = this->buffer_ + buffer_size;
+ break;
+ }
+ }
if (this->buffer_ == NULL)
return;
+ section_size_type uncompressed_size = 0;
+ unsigned char* uncompressed_data = NULL;
+ if (object->section_is_compressed(debug_shndx, &uncompressed_size))
+ {
+ uncompressed_data = new unsigned char[uncompressed_size];
+ if (!decompress_input_section(this->buffer_,
+ this->buffer_end_ - this->buffer_,
+ uncompressed_data,
+ uncompressed_size))
+ object->error(_("could not decompress section %s"),
+ object->section_name(debug_shndx).c_str());
+ this->buffer_ = uncompressed_data;
+ this->buffer_end_ = this->buffer_ + uncompressed_size;
+ }
+
// Find the relocation section for ".debug_line".
// We expect these for relobjs (.o's) but not dynobjs (.so's).
bool got_relocs = false;
{
got_relocs = this->track_relocs_.initialize(object, reloc_shndx,
reloc_sh_type);
+ this->track_relocs_type_ = reloc_sh_type;
break;
}
}
// Process a single opcode in the .debug.line structure.
-// Templating on size and big_endian would yield more efficient (and
-// simpler) code, but would bloat the binary. Speed isn't important
-// here.
-
template<int size, bool big_endian>
bool
Sized_dwarf_line_info<size, big_endian>::process_one_opcode(
case elfcpp::DW_LNS_advance_pc:
{
const uint64_t advance_address
- = read_unsigned_LEB_128(start, &templen);
+ = read_unsigned_LEB_128(start, &templen);
oplen += templen;
lsm->address += header_.min_insn_length * advance_address;
}
case elfcpp::DW_LNS_extended_op:
{
const uint64_t extended_op_len
- = read_unsigned_LEB_128(start, &templen);
+ = read_unsigned_LEB_128(start, &templen);
start += templen;
oplen += templen + extended_op_len;
case elfcpp::DW_LNE_set_address:
{
- lsm->address = elfcpp::Swap_unaligned<size, big_endian>::readval(start);
+ lsm->address =
+ elfcpp::Swap_unaligned<size, big_endian>::readval(start);
typename Reloc_map::const_iterator it
- = reloc_map_.find(start - this->buffer_);
+ = this->reloc_map_.find(start - this->buffer_);
if (it != reloc_map_.end())
{
- // value + addend.
- lsm->address += it->second.second;
+ // If this is a SHT_RELA section, then ignore the
+ // section contents. This assumes that this is a
+ // straight reloc which just uses the reloc addend.
+ // The reloc addend has already been included in the
+ // symbol value.
+ if (this->track_relocs_type_ == elfcpp::SHT_RELA)
+ lsm->address = 0;
+ // Add in the symbol value.
+ lsm->address += it->second.second;
lsm->shndx = it->second.first;
}
else
default:
{
- // Ignore unknown opcode silently.
+ // Ignore unknown opcode silently
for (int i = 0; i < header_.std_opcode_lengths[opcode]; i++)
{
+ size_t templen;
read_unsigned_LEB_128(start, &templen);
start += templen;
oplen += templen;
}
}
break;
- }
+ }
*len = oplen;
return false;
}
Offset_to_lineno_entry entry
= { lsm.address, this->current_header_index_,
lsm.file_num, lsm.line_num };
- line_number_map_[lsm.shndx].push_back(entry);
+ 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 always use the
+ // second one.
+ if (!map.empty()
+ && (map.back().offset == static_cast<off_t>(lsm.address))
+ && lsm.line_num != -1
+ && map.back().line_num != -1)
+ map.back() = entry;
+ else
+ map.push_back(entry);
}
lineptr += oplength;
}
// There is no reason to record non-ordinary section indexes, or
// SHN_UNDEF, because they will never match the real section.
if (is_ordinary && shndx != elfcpp::SHN_UNDEF)
- this->reloc_map_[reloc_offset] = std::make_pair(shndx, value);
+ {
+ value += this->track_relocs_.next_addend();
+ this->reloc_map_[reloc_offset] = std::make_pair(shndx, value);
+ }
this->track_relocs_.advance(reloc_offset + 1);
}