#include <map>
#include <sstream>
#include <cstring>
+#include <cassert>
struct secentry
{
elf_file_init (&file, lint.elf ());
}
+load_sections::~load_sections ()
+{
+ if (file.ebl != NULL)
+ ebl_closebackend (file.ebl);
+ free (file.sec);
+}
+
sec &
section_base::get_sec_or_throw (section_id secid)
{
for (cu *cu = chain; cu != NULL; cu = cu->next)
cus.push_back (*cu);
- // cu_free (chain); xxx
- cu_chain = chain;
+
+ // re-link CUs so that they form a chain again. This is to
+ // interface with C-level code. The last CU's next is null, so we
+ // don't have to re-link it.
+ cu *last = NULL;
+ for (std::vector<cu>::iterator it = cus.begin ();
+ it != cus.end (); ++it)
+ {
+ cu *cur = &*it;
+ if (last != NULL)
+ last->next = cur;
+ last = cur;
+ }
+ if (cus.size () > 0)
+ assert (cus.back ().next == NULL);
+}
+
+check_debug_info::~check_debug_info ()
+{
+ cu_free (&cus.back ());
}
check_debug_ranges::check_debug_ranges (dwarflint &lint)
{
if (!check_loc_or_range_structural (&_m_sec_ranges->file,
&_m_sec_ranges->sect,
- _m_cus->cu_chain,
+ &_m_cus->cus.front (),
&_m_cus->cu_cov))
throw check_base::failed (""); //xxx
}
= _m_cus->cu_cov.need_ranges ? NULL : &_m_cus->cu_cov.cov;
if (!check_aranges_structural (&_m_sec_aranges->file,
&_m_sec_aranges->sect,
- _m_cus->cu_chain, cov))
+ &_m_cus->cus.front (),
+ cov))
throw check_base::failed (""); //xxx
}
{
if (!check_loc_or_range_structural (&_m_sec_loc->file,
&_m_sec_loc->sect,
- _m_cus->cu_chain, NULL))
+ &_m_cus->cus.front (),
+ NULL))
throw check_base::failed (""); //xxx
}
{
if (!check_pub_structural (&_m_sec->file,
&_m_sec->sect,
- _m_cus->cu_chain))
+ &_m_cus->cus.front ()))
throw check_base::failed (""); //xxx
}
};
reg<check_debug_pub<sec_pubnames> > reg_debug_pubnames;
reg<check_debug_pub<sec_pubtypes> > reg_debug_pubtypes;
}
+
+namespace
+{
+ class check_debug_line
+ : public check<check_debug_line>
+ {
+ section<sec_line> *_m_sec;
+
+ public:
+ explicit check_debug_line (dwarflint &lint)
+ : _m_sec (lint.check (_m_sec))
+ {
+ addr_record line_tables;
+ WIPE (line_tables);
+ if (!check_line_structural (&_m_sec->file,
+ &_m_sec->sect,
+ &line_tables))
+ throw check_base::failed (""); //xxx
+
+ check_debug_info *info = NULL;
+ info = toplev_check (lint, info);
+ if (info != NULL)
+ for (std::vector<cu>::iterator it = info->cus.begin ();
+ it != info->cus.end (); ++it)
+ for (size_t i = 0; i < it->line_refs.size; ++i)
+ {
+ struct ref *ref = it->line_refs.refs + i;
+ if (!addr_record_has_addr (&line_tables, ref->addr))
+ {
+ std::stringstream ss;
+ ss << ": unresolved reference to .debug_line table "
+ << "0x" << std::hex << ref->addr << ".";
+ wr_error (&ref->who, "%s\n", ss.str ().c_str ());
+ }
+ }
+ addr_record_free (&line_tables);
+ }
+ };
+
+ reg<check_debug_line> reg_debug_line;
+}
public:
elf_file file;
explicit load_sections (dwarflint &lint);
+ ~load_sections ();
};
class section_base
public:
cu_coverage cu_cov;
std::vector<cu> cus;
- cu *cu_chain; // xxx
explicit check_debug_info (dwarflint &lint);
+ ~check_debug_info ();
};
static reg<check_debug_info> reg_debug_info;
};
template <class T>
-void
-toplev_check (dwarflint &lint)
+T *
+toplev_check (dwarflint &lint,
+ __attribute__ ((unused)) T *tag = NULL)
{
try
{
- lint.check<T> ();
+ return lint.check<T> ();
}
catch (check_base::failed const &f)
{
std::cout << f.what () << std::endl;
+ return NULL;
}
}
bool
check_line_structural (struct elf_file *file,
struct sec *sec,
- struct cu *cu_chain)
+ struct addr_record *line_tables)
{
struct read_ctx ctx;
read_ctx_init (&ctx, sec->data, file->other_byte_order);
bool retval = true;
- struct addr_record line_tables;
- WIPE (line_tables);
-
while (!read_ctx_eof (&ctx))
{
struct where where = WHERE (sec->id, NULL);
uint64_t set_offset = read_ctx_get_offset (&ctx);
where_reset_1 (&where, set_offset);
- addr_record_add (&line_tables, set_offset);
+ addr_record_add (line_tables, set_offset);
const unsigned char *set_begin = ctx.ptr;
/* Size. */
}
if (retval)
- {
- relocation_skip_rest (sec);
-
- for (struct cu *cu = cu_chain; cu != NULL; cu = cu->next)
- for (size_t i = 0; i < cu->line_refs.size; ++i)
- {
- struct ref *ref = cu->line_refs.refs + i;
- if (!addr_record_has_addr (&line_tables, ref->addr))
- wr_error (&ref->who,
- ": unresolved reference to .debug_line table %#" PRIx64 ".\n",
- ref->addr);
- }
- }
+ relocation_skip_rest (sec);
return retval;
}
#include "addr-record.h"
#ifdef __cplusplus
-# include <string>
extern "C"
{
#else
struct cu *cu_chain);
extern bool check_line_structural (struct elf_file *file,
struct sec *sec,
- struct cu *cu_chain);
+ struct addr_record *line_tables);
extern void cu_free (struct cu *cu_chain);
- void section_coverage_init (struct section_coverage *sco,
- struct sec *sec, bool warn);
- bool coverage_map_init (struct coverage_map *coverage_map,
- struct elf_file *elf,
- Elf64_Xword mask,
- Elf64_Xword warn_mask,
- bool allow_overlap);
- void coverage_map_add (struct coverage_map *coverage_map,
- uint64_t address, uint64_t length,
- struct where *where, enum message_category cat);
- bool coverage_map_find_holes (struct coverage_map *coverage_map,
- bool (*cb) (uint64_t, uint64_t,
- struct section_coverage *, void *),
- void *user);
- void coverage_map_free (struct coverage_map *coverage_map);
-
-
struct hole_info
{
enum section_id section;
: _m_elf (a_elf)
{
check_registrar::inst ()->enroll (*this);
-
- struct elf_file file;
- if (!elf_file_init (&file, a_elf))
- return;
-
- check_debug_info *check_info = check (check_info);
- // xxx check_expected_trees
- cu *cu_chain = check_info->cu_chain;
-
-#define SEC(sec) (file.debugsec[sec_##sec])
-#define HAS_SEC(sec) (SEC(sec) != NULL && SEC(sec)->data != NULL)
-
- if (HAS_SEC(line))
- check_line_structural (&file, SEC(line), cu_chain);
- else if (!tolerate_nodebug)
- {
- where wh = WHERE (sec_line, NULL);
- wr_message (mc_impact_4 | mc_acc_suboptimal | mc_elf | mc_loc,
- &wh, ": data not found.\n");
- }
-
- cu_free (cu_chain);
- if (file.ebl != NULL)
- ebl_closebackend (file.ebl);
- free (file.sec);
-
-#undef SEC
-#undef HAS_SEC
}
int