dwarflint/check_debug_abbrev.cc dwarflint/check_debug_abbrev.hh dwarflint/check_debug_abbrev.ii \
dwarflint/check_debug_info.cc dwarflint/check_debug_info.hh dwarflint/check_debug_info.ii \
dwarflint/check_debug_line.cc \
+ dwarflint/check_debug_pub.cc \
dwarflint/check_debug_loc_range.cc dwarflint/check_debug_loc_range.hh \
dwarflint/check_matching_ranges.cc \
dwarflint/check_range_out_of_scope.cc \
}
coverage_free (&cu_cov.cov);
}
+
+cu *
+check_debug_info::find_cu (::Dwarf_Off offset)
+{
+ for (std::vector<cu>::iterator it = cus.begin ();
+ it != cus.end (); ++it)
+ if (it->head->offset == offset)
+ return &*it;
+
+ return NULL;
+}
explicit check_debug_info (dwarflint &lint);
~check_debug_info ();
+
+ cu *find_cu (::Dwarf_Off offset);
};
static reg<check_debug_info> reg_debug_info;
--- /dev/null
+#include "checks-low.hh"
+#include "check_debug_info.hh"
+#include "pri.hh"
+
+namespace
+{
+ template<section_id sec_id>
+ class check_debug_pub
+ : public check<check_debug_pub<sec_id> >
+ {
+ section<sec_id> *_m_sec;
+ elf_file const &_m_file;
+
+ bool check_pub_structural (check_debug_info *cus);
+
+ public:
+ explicit check_debug_pub (dwarflint &lint)
+ : _m_sec (lint.check (_m_sec))
+ , _m_file (_m_sec->file)
+ {
+ check_pub_structural (lint.toplev_check<check_debug_info> ());
+ }
+ };
+
+ template <class A, class B>
+ struct where xwhere (A a, B b)
+ {
+ return WHERE (a, b);
+ }
+}
+
+template <section_id sec_id>
+bool
+check_debug_pub<sec_id>::check_pub_structural (check_debug_info *cus)
+{
+ struct read_ctx ctx;
+ read_ctx_init (&ctx, _m_sec->sect.data, _m_file.other_byte_order);
+ bool retval = true;
+
+ while (!read_ctx_eof (&ctx))
+ {
+ struct where where = WHERE (_m_sec->sect.id, NULL);
+ where_reset_1 (&where, read_ctx_get_offset (&ctx));
+ const unsigned char *set_begin = ctx.ptr;
+
+ /* Size. */
+ uint32_t size32;
+ uint64_t size;
+ int offset_size;
+ if (!read_ctx_read_4ubyte (&ctx, &size32))
+ {
+ wr_error (&where, ": can't read table length.\n");
+ return false;
+ }
+ if (!read_size_extra (&ctx, size32, &size, &offset_size, &where))
+ return false;
+
+ {
+ struct read_ctx sub_ctx;
+ const unsigned char *set_end = ctx.ptr + size;
+ if (!read_ctx_init_sub (&sub_ctx, &ctx, set_begin, set_end))
+ goto not_enough;
+ sub_ctx.ptr = ctx.ptr;
+
+ /* Version. */
+ uint16_t version;
+ if (!read_ctx_read_2ubyte (&sub_ctx, &version))
+ {
+ wr_error (&where, ": can't read set version.\n");
+ retval = false;
+ goto next;
+ }
+ if (!supported_version (version, 1, &where, 2))
+ {
+ retval = false;
+ goto next;
+ }
+
+ /* CU offset. */
+ uint64_t cu_offset; /* Offset of related CU. */
+ uint64_t ctx_offset = sub_ctx.ptr - ctx.begin;
+ if (!read_ctx_read_offset (&sub_ctx, offset_size == 8, &cu_offset))
+ {
+ wr_error (&where, ": can't read debug info offset.\n");
+ retval = false;
+ goto next;
+ }
+
+ struct relocation *rel;
+ if ((rel = relocation_next (&_m_sec->sect.rel, ctx_offset,
+ &where, skip_mismatched)))
+ relocate_one (&_m_file, &_m_sec->sect.rel, rel, offset_size,
+ &cu_offset, &where, sec_info, NULL);
+ else if (_m_file.ehdr.e_type == ET_REL)
+ wr_message (mc_impact_2 | mc_pubtables | mc_reloc | mc_header, &where,
+ PRI_LACK_RELOCATION, "debug info offset");
+
+ struct cu *cu = NULL;
+ if (cus != NULL && (cu = cus->find_cu (cu_offset)) == NULL)
+ wr_error (where)
+ << "unresolved reference to " << pri::CU (cu_offset)
+ << '.' << std::endl;
+ if (cu != NULL)
+ {
+ where.ref = &cu->head->where;
+ bool *has = _m_sec->sect.id == sec_pubnames
+ ? &cu->has_pubnames : &cu->has_pubtypes;
+ if (*has)
+ wr_message (mc_impact_2 | mc_pubtables | mc_header, &where,
+ ": there has already been section for this CU.\n");
+ else
+ *has = true;
+ }
+
+ /* Covered length. */
+ uint64_t cu_len;
+ if (!read_ctx_read_offset (&sub_ctx, offset_size == 8, &cu_len))
+ {
+ wr_error (&where, ": can't read covered length.\n");
+ retval = false;
+ goto next;
+ }
+ if (cu != NULL && cu_len != cu->head->total_size)
+ {
+ wr_error (where)
+ << "the table covers length " << cu_len << " but CU has length "
+ << cu->head->total_size << '.' << std::endl;
+ retval = false;
+ goto next;
+ }
+
+ /* Records... */
+ while (!read_ctx_eof (&sub_ctx))
+ {
+ ctx_offset = sub_ctx.ptr - ctx.begin;
+ where_reset_2 (&where, ctx_offset);
+
+ uint64_t offset;
+ if (!read_ctx_read_offset (&sub_ctx, offset_size == 8, &offset))
+ {
+ wr_error (&where, ": can't read offset field.\n");
+ retval = false;
+ goto next;
+ }
+ if (offset == 0)
+ break;
+
+ if (cu != NULL
+ && !addr_record_has_addr (&cu->die_addrs,
+ offset + cu->head->offset))
+ {
+ wr_error (where)
+ << "unresolved reference to " << pri::DIE (offset)
+ << '.' << std::endl;
+ retval = false;
+ goto next;
+ }
+
+ uint8_t c;
+ do
+ if (!read_ctx_read_ubyte (&sub_ctx, &c))
+ {
+ wr_error (&where, ": can't read symbol name.\n");
+ retval = false;
+ goto next;
+ }
+ while (c);
+ }
+
+ struct where wh = WHERE (_m_sec->sect.id, NULL);
+ if (sub_ctx.ptr != sub_ctx.end
+ && !check_zero_padding (&sub_ctx, mc_pubtables, &wh))
+ {
+ wh = WHERE (_m_sec->sect.id, NULL);
+ wr_message_padding_n0 (mc_pubtables | mc_error, &wh,
+ read_ctx_get_offset (&sub_ctx),
+ read_ctx_get_offset (&sub_ctx) + size);
+ retval = false;
+ }
+ }
+
+ next:
+ if (read_ctx_skip (&ctx, size))
+ continue;
+
+ not_enough:
+ wr_error (&where, PRI_NOT_ENOUGH, "next set");
+ return false;
+ }
+
+ if (retval)
+ relocation_skip_rest (&_m_sec->sect.rel, _m_sec->sect.id);
+
+ return retval;
+}
+
+namespace
+{
+ reg<check_debug_pub<sec_pubnames> > reg_debug_pubnames;
+ reg<check_debug_pub<sec_pubtypes> > reg_debug_pubtypes;
+}
cov))
throw check_base::failed ();
}
-
-namespace
-{
- template<section_id sec_id>
- class check_debug_pub
- : public check<check_debug_pub<sec_id> >
- {
- section<sec_id> *_m_sec;
- check_debug_info *_m_cus;
-
- public:
- explicit check_debug_pub (dwarflint &lint)
- : _m_sec (lint.check (_m_sec))
- , _m_cus (lint.check (_m_cus))
- {
- if (!check_pub_structural (&_m_sec->file,
- &_m_sec->sect,
- &_m_cus->cus.front ()))
- throw check_base::failed ();
- }
- };
-
- reg<check_debug_pub<sec_pubnames> > reg_debug_pubnames;
- reg<check_debug_pub<sec_pubtypes> > reg_debug_pubtypes;
-}
return retval;
}
-bool
-check_pub_structural (struct elf_file *file,
- struct sec *sec,
- struct cu *cu_chain)
-{
- struct read_ctx ctx;
- read_ctx_init (&ctx, sec->data, file->other_byte_order);
- bool retval = true;
-
- while (!read_ctx_eof (&ctx))
- {
- struct where where = WHERE (sec->id, NULL);
- where_reset_1 (&where, read_ctx_get_offset (&ctx));
- const unsigned char *set_begin = ctx.ptr;
-
- /* Size. */
- uint32_t size32;
- uint64_t size;
- int offset_size;
- if (!read_ctx_read_4ubyte (&ctx, &size32))
- {
- wr_error (&where, ": can't read table length.\n");
- return false;
- }
- if (!read_size_extra (&ctx, size32, &size, &offset_size, &where))
- return false;
-
- struct read_ctx sub_ctx;
- const unsigned char *set_end = ctx.ptr + size;
- if (!read_ctx_init_sub (&sub_ctx, &ctx, set_begin, set_end))
- {
- not_enough:
- wr_error (&where, PRI_NOT_ENOUGH, "next set");
- return false;
- }
- sub_ctx.ptr = ctx.ptr;
-
- /* Version. */
- uint16_t version;
- if (!read_ctx_read_2ubyte (&sub_ctx, &version))
- {
- wr_error (&where, ": can't read set version.\n");
- retval = false;
- goto next;
- }
- if (!supported_version (version, 1, &where, 2))
- {
- retval = false;
- goto next;
- }
-
- /* CU offset. */
- uint64_t cu_offset; /* Offset of related CU. */
- uint64_t ctx_offset = sub_ctx.ptr - ctx.begin;
- if (!read_ctx_read_offset (&sub_ctx, offset_size == 8, &cu_offset))
- {
- wr_error (&where, ": can't read debug info offset.\n");
- retval = false;
- goto next;
- }
-
- struct relocation *rel;
- if ((rel = relocation_next (&sec->rel, ctx_offset,
- &where, skip_mismatched)))
- relocate_one (file, &sec->rel, rel, offset_size,
- &cu_offset, &where, sec_info, NULL);
- else if (file->ehdr.e_type == ET_REL)
- wr_message (mc_impact_2 | mc_pubtables | mc_reloc | mc_header, &where,
- PRI_LACK_RELOCATION, "debug info offset");
-
- struct cu *cu = NULL;
- if (cu_chain != NULL && (cu = cu_find_cu (cu_chain, cu_offset)) == NULL)
- wr_error (&where, ": unresolved reference to " PRI_CU ".\n", cu_offset);
- if (cu != NULL)
- {
- where.ref = &cu->head->where;
- bool *has = sec->id == sec_pubnames
- ? &cu->has_pubnames : &cu->has_pubtypes;
- if (*has)
- wr_message (mc_impact_2 | mc_pubtables | mc_header, &where,
- ": there has already been section for this CU.\n");
- else
- *has = true;
- }
-
- /* Covered length. */
- uint64_t cu_len;
- if (!read_ctx_read_offset (&sub_ctx, offset_size == 8, &cu_len))
- {
- wr_error (&where, ": can't read covered length.\n");
- retval = false;
- goto next;
- }
- if (cu != NULL && cu_len != cu->head->total_size)
- {
- wr_error (&where,
- ": the table covers length %" PRId64
- " but CU has length %" PRId64 ".\n",
- cu_len, cu->head->total_size);
- retval = false;
- goto next;
- }
-
- /* Records... */
- while (!read_ctx_eof (&sub_ctx))
- {
- ctx_offset = sub_ctx.ptr - ctx.begin;
- where_reset_2 (&where, ctx_offset);
-
- uint64_t offset;
- if (!read_ctx_read_offset (&sub_ctx, offset_size == 8, &offset))
- {
- wr_error (&where, ": can't read offset field.\n");
- retval = false;
- goto next;
- }
- if (offset == 0)
- break;
-
- if (cu != NULL
- && !addr_record_has_addr (&cu->die_addrs,
- offset + cu->head->offset))
- {
- wr_error (&where,
- ": unresolved reference to " PRI_DIE ".\n", offset);
- retval = false;
- goto next;
- }
-
- uint8_t c;
- do
- if (!read_ctx_read_ubyte (&sub_ctx, &c))
- {
- wr_error (&where, ": can't read symbol name.\n");
- retval = false;
- goto next;
- }
- while (c);
- }
-
- if (sub_ctx.ptr != sub_ctx.end
- && !check_zero_padding (&sub_ctx, mc_pubtables,
- &WHERE (sec->id, NULL)))
- {
- wr_message_padding_n0 (mc_pubtables | mc_error,
- &WHERE (sec->id, NULL),
- read_ctx_get_offset (&sub_ctx),
- read_ctx_get_offset (&sub_ctx) + size);
- retval = false;
- }
-
- next:
- if (!read_ctx_skip (&ctx, size))
- goto not_enough;
- }
-
- if (retval)
- relocation_skip_rest (&sec->rel, sec->id);
-
- return retval;
-}
-
static GElf_Rela *
get_rel_or_rela (Elf_Data *data, int ndx,
GElf_Rela *dst, size_t type)
struct sec *sec,
struct cu *cu_chain,
struct coverage *coverage);
- extern bool check_pub_structural (struct elf_file *file,
- struct sec *sec,
- struct cu *cu_chain);
extern bool check_line_structural (struct elf_file *file,
struct sec *sec,
struct addr_record *line_tables);
DIE (Dwarf_Off off) : hex (off, "DIE ") {}
};
+ struct CU: public hex {
+ CU (Dwarf_Off off) : hex (off, "CU ") {}
+ };
+
class range
{
Dwarf_Off start;