#include "misc.hh"
#include "pri.hh"
+std::string
+arange_locus::format (bool brief) const
+{
+ std::stringstream ss;
+ if (!brief)
+ ss << section_name[sec_aranges] << ": ";
+
+ if (_m_arange_offset != (Dwarf_Off)-1)
+ ss << "arange 0x" << std::hex << _m_arange_offset;
+ else if (_m_table_offset != (Dwarf_Off)-1)
+ ss << "table " << std::dec << _m_table_offset;
+ else
+ ss << "arange";
+
+ if (_m_cudie_locus != NULL)
+ ss << " (" << _m_cudie_locus->format (true) << ')';
+
+ return ss.str ();
+}
+
checkdescriptor const *
check_debug_aranges::descriptor ()
{
inline static void
aranges_coverage_add (struct coverage *aranges_coverage,
uint64_t begin, uint64_t length,
- struct where *where)
+ locus const &loc)
{
if (aranges_coverage->is_overlap (begin, length))
{
char buf[128];
/* Not a show stopper, this shouldn't derail high-level. */
- wr_message (*where, mc_aranges | mc_impact_2 | mc_error)
+ wr_message (loc, mc_aranges | mc_impact_2 | mc_error)
<< "the range " << range_fmt (buf, sizeof buf, begin, begin + length)
<< " overlaps with another one." << std::endl;
}
aranges_coverage->add (begin, length);
}
-namespace
-{
- struct cudie_locus_n {
- static char const *name () { return "CU DIE"; }
- };
-
- typedef fixed_locus<sec_info,
- cudie_locus_n::name,
- locus_simple_fmt::dec> cudie_locus;
-}
-
/* COVERAGE is portion of address space covered by CUs (either via
low_pc/high_pc pairs, or via DW_AT_ranges references). If
non-NULL, analysis of arange coverage is done against that set. */
while (!read_ctx_eof (&ctx))
{
- section_id const sec_id = sec_aranges;
- struct where where = WHERE (sec_id, NULL);
- where_reset_1 (&where, read_ctx_get_offset (&ctx));
+ arange_locus where (read_ctx_get_offset (&ctx));
const unsigned char *atab_begin = ctx.ptr;
/* Size. */
wr_error (&where, ": unresolved reference to " PRI_CU ".\n", cu_offset);
cudie_locus cudie_loc (cu != NULL ? cu->cudie_offset : -1);
- where.ref = &cudie_loc;
if (cu != NULL)
{
+ where.set_cudie (&cudie_loc);
if (cu->has_arange)
wr_error (where)
<< "there has already been arange section for this CU."
way, the better to catch structural errors accurately.
So report arange offset instead. If this becomes a
problem, we will achieve this by two-pass analysis. */
- where_reset_2 (&where, read_ctx_get_offset (&sub_ctx));
+ where.set_arange (read_ctx_get_offset (&sub_ctx));
/* Record address. */
uint64_t address;
wr_error (&where, ": zero-length address range.\n");
/* Skip coverage analysis if we have errors. */
else if (retval && aranges_coverage != NULL)
- aranges_coverage_add (aranges_coverage, address, length, &where);
+ aranges_coverage_add (aranges_coverage, address, length, where);
}
if (sub_ctx.ptr != sub_ctx.end)
{
uint64_t start, end;
- section_locus wh (sec_id);
+ section_locus wh (sec_aranges);
if (read_check_zero_padding (&sub_ctx, &start, &end))
wr_message_padding_0 (mc_aranges, wh, start, end);
else
/* Low-level checking of .debug_aranges.
- Copyright (C) 2009, 2010 Red Hat, Inc.
+ Copyright (C) 2009, 2010, 2011 Red Hat, Inc.
This file is part of Red Hat elfutils.
Red Hat elfutils is free software; you can redistribute it and/or modify
#include "check_debug_info_i.hh"
#include "cu_coverage_i.hh"
+struct cudie_locus_n {
+ static char const *name () { return "CU DIE"; }
+};
+
+class cudie_locus
+ : public fixed_locus<sec_info,
+ cudie_locus_n::name,
+ locus_simple_fmt::dec>
+{
+public:
+ template <class T>
+ cudie_locus (T const &die)
+ : fixed_locus<sec_info, cudie_locus_n::name,
+ locus_simple_fmt::dec> (die.offset ())
+ {}
+
+ cudie_locus (Dwarf_Off offset)
+ : fixed_locus<sec_info, cudie_locus_n::name,
+ locus_simple_fmt::dec> (offset)
+ {}
+};
+
+class arange_locus
+ : public clonable_locus<arange_locus>
+{
+ Dwarf_Off _m_table_offset;
+ Dwarf_Off _m_arange_offset;
+ locus const *_m_cudie_locus;
+
+public:
+ explicit arange_locus (Dwarf_Off table_offset = -1,
+ Dwarf_Off arange_offset = -1)
+ : _m_table_offset (table_offset)
+ , _m_arange_offset (arange_offset)
+ , _m_cudie_locus (NULL)
+ {}
+
+ explicit arange_locus (locus const &cudie_locus)
+ : _m_table_offset (-1)
+ , _m_arange_offset (-1)
+ , _m_cudie_locus (&cudie_locus)
+ {}
+
+ void
+ set_cudie (locus const *cudie_locus)
+ {
+ _m_cudie_locus = cudie_locus;
+ }
+
+ void
+ set_arange (Dwarf_Off arange_offset)
+ {
+ _m_arange_offset = arange_offset;
+ }
+
+ std::string format (bool brief = false) const;
+};
+
class check_debug_aranges
: public check<check_debug_aranges>
{
try
{
- struct where where_ar = WHERE (sec_aranges, NULL);
char buf[128];
-
const dwarf::aranges_map &aranges = dw.aranges ();
for (dwarf::aranges_map::const_iterator i = aranges.begin ();
i != aranges.end (); ++i)
{
const dwarf::compile_unit &cu = i->first;
- die_locus where_ref (cu);
- where_ar.ref = &where_ref;
+ cudie_locus where_ref (cu);
loc_range_locus where_r (sec_ranges, where_ref);
+ arange_locus where_ar (where_ref);
std::set<dwarf::ranges::key_type>
cu_aranges = i->second,
#include "where.hh"
#include "section_id.hh"
-#include <cinttypes>
-#include <assert.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <string.h>
-#include <array>
-#include <sstream>
-
-class where::simple_formatter
- : public where::formatter
-{
- char const *_m_name;
- char const *_m_fmt1;
- char const *_m_fmt2;
- char const *_m_fmt3;
-
-public:
- simple_formatter (char const *name = NULL,
- char const *fmt1 = NULL,
- char const *fmt2 = NULL,
- char const *fmt3 = NULL)
- : _m_name (name)
- , _m_fmt1 (fmt1)
- , _m_fmt2 (fmt2)
- , _m_fmt3 (fmt3)
- {}
-
- virtual std::string
- format (where const &wh, bool brief) const
- {
- std::string ret;
-
- brief = brief || _m_name == NULL;
- if (!brief)
- ret += _m_name;
-
- char const *const *formats = &_m_fmt1;
- uint64_t const *addrs = &wh._m_addr1;
-
- for (size_t i = 3; i > 0; --i)
- {
- size_t idx = i - 1;
- if (addrs[idx] == (uint64_t)-1)
- continue;
-
- assert (formats[idx] != NULL);
-
- /* GCC insists on checking format parameters and emits a warning
- when we don't use string literal. With -Werror this ends up
- being hard error. So instead we walk around this warning by
- using function pointer. */
- int (*x_asprintf)(char **strp, const char *fmt, ...) = asprintf;
-
- if (!brief)
- ret += ": ";
- char *buf;
- if (x_asprintf (&buf, formats[idx], addrs[idx]) >= 0)
- {
- ret += buf;
- free (buf);
- }
- else
- ret += formats[idx];
-
- break;
- }
-
- if (wh.ref != NULL)
- {
- ret += " (";
- ret += wh.ref->format (true);
- ret += ')';
- }
-
- return ret;
- }
-};
-
-namespace
-{
- template<size_t size>
- class simple_formatters
- : public std::array<where::simple_formatter, size>
- {
- protected:
- void
- add (section_id id, char const *name,
- char const *addr1f = NULL,
- char const *addr2f = NULL,
- char const *addr3f = NULL)
- {
- (*this)[id] = where::simple_formatter (name, addr1f, addr2f, addr3f);
- }
- };
-
- class section_formatters
- : public simple_formatters<count_debuginfo_sections>
- {
- public:
- section_formatters ()
- {
- add (sec_aranges, ".debug_aranges",
- "table %"PRId64, "arange %#"PRIx64);
-
- add (sec_mac, ".debug_mac");
- }
- } const section_fmts;
-}
-
-namespace
-{
- where::formatter const *
- wf_for_section (section_id sec)
- {
- return §ion_fmts[sec];
- }
-}
-
std::string
format_simple_locus (char const *(*N) (),
void (*F) (std::stringstream &, uint64_t),
}
return ss.str ();
}
-
-where
-WHERE (section_id sec, locus const *next)
-{
- assert (sec != sec_abbrev);
- assert (sec != sec_str);
- assert (sec != sec_info);
- assert (sec != sec_loc);
- assert (sec != sec_ranges);
- assert (sec != sec_pubtypes);
- assert (sec != sec_pubnames);
- assert (sec != sec_line);
- where::formatter const *fmt = wf_for_section (sec);
- return where (fmt, next);
-}
-
-where::where (formatter const *fmt, locus const *nxt)
- : _m_formatter (fmt)
- , _m_addr1 ((uint64_t)-1)
- , _m_addr2 ((uint64_t)-1)
- , _m_addr3 ((uint64_t)-1)
- , ref (NULL)
- , _m_next (nxt)
-{
-}
-
-where &
-where::operator= (where const ©)
-{
- _m_formatter = copy._m_formatter;
-
- _m_addr1 = copy._m_addr1;
- _m_addr2 = copy._m_addr2;
- _m_addr3 = copy._m_addr3;
-
- ref = copy.ref;
- _m_next = copy._m_next;
-
- return *this;
-}
-
-std::string
-where::format (bool brief) const
-{
- assert (_m_formatter != NULL);
- return _m_formatter->format (*this, brief);
-}
-
-void
-where::reset_1 (uint64_t addr)
-{
- _m_addr1 = addr;
- _m_addr2 = _m_addr3 = (uint64_t)-1;
-}
-
-void
-where::reset_2 (uint64_t addr)
-{
- _m_addr2 = addr;
- _m_addr3 = (uint64_t)-1;
-}
-
-void
-where::reset_3 (uint64_t addr)
-{
- _m_addr3 = addr;
-}
typedef simple_locus<locus_simple_fmt::offset,
locus_simple_fmt::hex> section_locus;
-struct where
- : public clonable_locus<where>
-{
- class formatter
- {
- public:
- virtual ~formatter () {}
- virtual std::string format (where const &wh, bool brief = false) const = 0;
- };
-
- class simple_formatter;
-
-private:
- formatter const *_m_formatter;
-
- uint64_t _m_addr1; // E.g. a CU offset.
- uint64_t _m_addr2; // E.g. a DIE address.
- uint64_t _m_addr3; // E.g. an attribute.
-
-public:
- locus const *ref; // Related reference, e.g. an abbrev related to
- // given DIE.
- locus const *_m_next; // For forming "caused-by" chains.
-
- explicit where (formatter const *fmt = NULL,
- locus const *nxt = NULL);
-
- where &operator= (where const ©);
-
- std::string format (bool brief = false) const;
-
- locus const *
- next () const
- {
- return _m_next;
- }
-
- void
- set_next (locus const *nxt)
- {
- assert (_m_next == NULL);
- _m_next = nxt;
- }
-
- void reset_1 (uint64_t addr);
- void reset_2 (uint64_t addr);
- void reset_3 (uint64_t addr);
-};
-
-inline void
-where_reset_1 (struct where *wh, uint64_t addr)
-{
- wh->reset_1 (addr);
-}
-
-inline void
-where_reset_2 (struct where *wh, uint64_t addr)
-{
- wh->reset_2 (addr);
-}
-
-inline void
-where_reset_3 (struct where *wh, uint64_t addr)
-{
- wh->reset_3 (addr);
-}
-
-where WHERE (section_id sec, locus const *next = NULL);
-
inline std::ostream &
operator << (std::ostream &os, locus const &loc)
{