if (a >= ar->size () || (*ar)[a] != addr)
ar->insert (ar->begin () + a, addr);
}
+
+ref::ref ()
+ : addr (-1)
+ , who (NULL)
+{}
+
+ref::ref (uint64_t a_addr, locus const &a_who)
+ : addr (a_addr)
+ , who (a_who.clone ())
+{}
+
+ref::ref (ref const ©)
+ : who (NULL)
+{
+ *this = copy;
+}
+
+ref &
+ref::operator= (ref const ©)
+{
+ if (© != this)
+ {
+ addr = copy.addr;
+ delete who;
+ who = copy.who ? copy.who->clone () : NULL;
+ }
+ return *this;
+}
+
+ref::~ref ()
+{
+ delete who;
+}
struct ref
{
- uint64_t addr; // Referree address
- ::where who; // Referrer
-
- ref ()
- : addr (-1)
- , who ()
- {}
-
- ref (uint64_t a_addr, where const &a_who)
- : addr (a_addr)
- , who (a_who)
- {}
+ uint64_t addr; // Referee address
+ locus *who; // Referrer
+
+ ref ();
+ ref (uint64_t a_addr, locus const &a_who);
+ ref (ref const ©);
+ ~ref ();
+ ref &operator= (ref const ©);
};
class ref_record
struct relocation *rel;
if ((rel = relocation_next (&sec->rel, ctx_offset,
- &where, skip_mismatched)))
+ where, skip_mismatched)))
relocate_one (file, &sec->rel, rel, offset_size,
- &cu_offset, &where, sec_info, NULL);
+ &cu_offset, where, sec_info, NULL);
else if (file->ehdr.e_type == ET_REL)
wr_message (mc_impact_2 | mc_aranges | mc_reloc | mc_header, &where,
PRI_LACK_RELOCATION, "debug info offset");
ss << "unknown CU";
return ss.str ();
}
+
+ locus *
+ clone () const
+ {
+ return new cudie_locus (*this);
+ }
};
cudie_locus cudie_loc (cu != NULL ? cu->cudie_offset : -1);
}
if ((rel = relocation_next (&sec->rel, ctx_offset,
- &where, skip_mismatched)))
+ where, skip_mismatched)))
{
address_relocated = true;
relocate_one (file, &sec->rel, rel, address_size,
- &address, &where, rel_address, NULL);
+ &address, where, rel_address, NULL);
}
else if (file->ehdr.e_type == ET_REL && address != 0)
wr_message (mc_impact_2 | mc_aranges | mc_reloc, &where,
it != die_refs->end (); ++it)
if (!addr_record_has_addr (&cu->die_addrs, it->addr))
{
- wr_error (it->who)
+ wr_error (*it->who)
<< "unresolved reference to " << pri::DIE (it->addr)
<< '.' << std::endl;
retval = false;
if (ref_cu == NULL)
{
- wr_error (rt->who)
+ wr_error (*rt->who)
<< "unresolved (non-CU-local) reference to "
<< pri::hex (rt->addr) << '.' << std::endl;
retval = false;
reference is valid, which it is. But warn about this
anyway, perhaps local reference could be formed on
smaller number of bytes. */
- wr_message (rt->who, mc_impact_2 | mc_acc_suboptimal | mc_die_rel)
+ wr_message (*rt->who, mc_impact_2 | mc_acc_suboptimal | mc_die_rel)
<< "local reference to " << pri::DIE (rt->addr)
<< " formed as global." << std::endl;
}
}
struct relocation *rel
- = relocation_next (reloc, ctx_offset, &head.where, skip_ok);
+ = relocation_next (reloc, ctx_offset, head.where, skip_ok);
if (rel != NULL)
{
relocate_one (file, reloc, rel, head.offset_size,
- &head.abbrev_offset, &head.where, sec_abbrev, NULL);
+ &head.abbrev_offset, head.where, sec_abbrev, NULL);
rel->invalid = true; // mark as invalid so it's skipped
// next time we pass by this
}
if (ctx->cu->stmt_list.addr != (uint64_t)-1)
wr_error (*ctx->where)
<< "DW_AT_stmt_list mentioned twice in a CU." << std::endl;
- ctx->cu->stmt_list.addr = value;
- ctx->cu->stmt_list.who = *ctx->where;
+ ctx->cu->stmt_list = ref (value, *ctx->where);
}
/* Callback for locptr values. */
/* Relocate the value if appropriate. */
struct relocation *rel;
if ((rel = relocation_next (reloc, ctx_offset,
- &where, skip_mismatched)))
+ where, skip_mismatched)))
{
if (relocate == rel_no)
wr_message (where, (mc_impact_4 | mc_die_other
if (attribute != NULL)
{
form_width_t width = form->width (cu->head);
- relocate_one (&file, reloc, rel, width, &value, &where,
+ relocate_one (&file, reloc, rel, width, &value, where,
reloc_target (form, attribute), symbolp);
}
if (it->stmt_list.addr == (uint64_t)-1)
for (ref_record::const_iterator jt = it->decl_file_refs.begin ();
jt != it->decl_file_refs.end (); ++jt)
- wr_error (jt->who)
+ wr_error (*jt->who)
<< "references .debug_line table, but CU DIE lacks DW_AT_stmt_list."
<< std::endl;
else if (_m_line == NULL
|| !_m_line->has_line_table (it->stmt_list.addr))
- wr_error (it->stmt_list.who)
+ wr_error (*it->stmt_list.who)
<< "unresolved reference to .debug_line table "
<< pri::hex (it->stmt_list.addr) << '.' << std::endl;
bool
use_file (files_t &files, uint64_t file_idx,
- where const &where, char const *msg = "")
+ locus const &loc, char const *msg = "")
{
if (file_idx == 0 || file_idx > files.size ())
{
- wr_error (where)
+ wr_error (loc)
<< msg << "invalid file index " << file_idx << '.'
<< std::endl;
return false;
for (ref_record::const_iterator
jt = it->decl_file_refs.begin ();
jt != it->decl_file_refs.end (); ++jt)
- if (!use_file (files, jt->addr, jt->who))
+ if (!use_file (files, jt->addr, *jt->who))
success = false;
}
if (!found)
struct relocation *rel;
if ((rel = relocation_next (&_m_sec->sect.rel, ctx_offset,
- &where, skip_mismatched)))
+ where, skip_mismatched)))
relocate_one (&_m_sec->file, &_m_sec->sect.rel, rel,
addr_64 ? 8 : 4,
- &addr, &where, rel_address, NULL);
+ &addr, where, rel_address, NULL);
else if (_m_sec->file.ehdr.e_type == ET_REL)
{
wr_message (where, mc_impact_2 | mc_line | mc_reloc)
struct coverage_map *coverage_map,
struct coverage *pc_coverage,
uint64_t addr,
- struct where const *wh,
+ locus const &loc,
enum message_category cat)
{
char buf[128]; // messages
read_ctx_init (&ctx, parent_ctx->data, file->other_byte_order);
if (!read_ctx_skip (&ctx, addr))
{
- wr_error (wh, ": invalid reference outside the section "
+ wr_error (&loc, ": invalid reference outside the section "
"%#" PRIx64 ", size only %#tx.\n",
addr, ctx.end - ctx.begin);
return false;
if (coverage->is_covered (addr, 1))
{
- wr_error (wh, ": reference to %#" PRIx64
+ wr_error (&loc, ": reference to %#" PRIx64
" points into another location or range list.\n", addr);
retval = false;
}
uint64_t base = cu->low_pc;
while (!read_ctx_eof (&ctx))
{
- struct where where = WHERE (sec->id, wh);
+ struct where where = WHERE (sec->id, &loc);
uint64_t offset = read_ctx_get_offset (&ctx);
where_reset_1 (&where, offset);
struct relocation *rel;
if ((rel = relocation_next (&sec->rel, begin_off,
- &where, skip_mismatched)))
+ where, skip_mismatched)))
{
begin_relocated = true;
relocate_one (file, &sec->rel, rel, cu->head->address_size,
- &begin_addr, &where, rel_value, &begin_symbol);
+ &begin_addr, where, rel_value, &begin_symbol);
}
/* end address */
}
if ((rel = relocation_next (&sec->rel, end_off,
- &where, skip_mismatched)))
+ where, skip_mismatched)))
{
end_relocated = true;
relocate_one (file, &sec->rel, rel, cu->head->address_size,
- &end_addr, &where, rel_value, &end_symbol);
+ &end_addr, where, rel_value, &end_symbol);
if (begin_addr != escape)
{
if (!begin_relocated)
Perhaps that's undesirable. */
if (!check_loc_or_range_ref (ver, file, &ctx, it->cu, sec,
&coverage, coverage_map, pc_coverage,
- off, &it->ref.who, cat))
+ off, *it->ref.who, cat))
retval = false;
last_off = off;
}
form const *form,
uint64_t *valuep,
char const *str,
- struct where const &where)
+ locus const &where)
{
if (form == NULL)
return true;
struct relocation *rel;
if ((rel = relocation_next (reloc, off,
- &where, skip_mismatched)))
+ where, skip_mismatched)))
{
if (storclass != sc_block)
relocate_one (&file, reloc, rel,
- cu->head->address_size, valuep, &where,
+ cu->head->address_size, valuep, where,
reloc_target_loc (opcode), NULL);
else
wr_error (where) << "relocation relocates a length field.\n";
if (storclass == sc_block)
{
uint64_t off_block_end = read_ctx_get_offset (ctx) + init_off - 1;
- relocation_next (reloc, off_block_end, &where, skip_ok);
+ relocation_next (reloc, off_block_end, where, skip_ok);
}
return true;
}
}
+class locexpr_locus
+ : public locus
+{
+ uint64_t const _m_offset;
+ locus const *const _m_context;
+
+public:
+ explicit locexpr_locus (uint64_t offset, locus const *context)
+ : _m_offset (offset)
+ , _m_context (context)
+ {}
+
+ std::string
+ format (bool) const
+ {
+ std::stringstream ss;
+ ss << "location expression offset 0x" << std::hex << _m_offset;
+ return ss.str ();
+ }
+
+ locus *
+ clone () const
+ {
+ return new locexpr_locus (*this);
+ }
+
+ virtual locus const *next () const
+ {
+ return _m_context;
+ }
+};
+
bool
check_location_expression (dwarf_version const *ver,
elf_file const &file,
while (!read_ctx_eof (&ctx))
{
- struct where where = WHERE (sec_locexpr, wh);
uint64_t opcode_off = read_ctx_get_offset (&ctx) + init_off;
- where_reset_1 (&where, opcode_off);
+ locexpr_locus where (opcode_off, wh);
addr_record_add (&opaddrs, opcode_off);
uint8_t opcode;
for (ref_record::const_iterator it = oprefs.begin ();
it != oprefs.end (); ++it)
if (!addr_record_has_addr (&opaddrs, it->addr))
- wr_error (it->who) << "unresolved reference to opcode at "
- << pri::hex (it->addr) << ".\n";
+ wr_error (*it->who) << "unresolved reference to opcode at "
+ << pri::hex (it->addr) << ".\n";
return true;
}
struct relocation *rel;
if ((rel = relocation_next (&_m_sec->sect.rel, ctx_offset,
- &where, skip_mismatched)))
+ where, skip_mismatched)))
relocate_one (&_m_file, &_m_sec->sect.rel, rel, offset_size,
- &cu_offset, &where, sec_info, NULL);
+ &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");
ss << " of " << _m_ref.format ();
return ss.str ();
}
+
+ locus *
+ clone () const
+ {
+ return new reloc_locus (*this);
+ }
};
}
relocation *
relocation_next (relocation_data *reloc, uint64_t offset,
- struct where const *where, enum skip_type st)
+ locus const &loc, enum skip_type st)
{
if (reloc == NULL || reloc->rel == NULL)
return NULL;
{
if (st != skip_ok)
{
- reloc_locus reloc_where (reloc->type, *where, rel->offset);
+ reloc_locus reloc_where (reloc->type, loc, rel->offset);
wr_error (reloc_where)
<< (st == skip_unref
? "relocation targets unreferenced portion of the section."
struct where const *where, enum skip_type st)
{
if (reloc != NULL && reloc->rel != NULL)
- relocation_next (reloc, offset - 1, where, st);
+ relocation_next (reloc, offset - 1, *where, st);
}
void
if (reloc->rel != NULL)
{
where wh = WHERE (id, NULL);
- relocation_next (reloc, (uint64_t)-1, &wh,
+ relocation_next (reloc, (uint64_t)-1, wh,
skip_mismatched);
}
}
struct relocation_data *reloc,
struct relocation *rel,
unsigned width, uint64_t *value,
- struct where const *where,
+ locus const &loc,
enum section_id offset_into, GElf_Sym **symptr)
{
if (rel->invalid)
return;
- reloc_locus reloc_where (reloc->type, *where, rel->offset);
+ reloc_locus reloc_where (reloc->type, loc, rel->offset);
GElf_Sym symbol_mem, *symbol;
if (symptr != NULL)
relocation *relocation_next (struct relocation_data *reloc,
uint64_t offset,
- struct where const *where,
+ locus const &loc,
enum skip_type st);
void relocation_reset (struct relocation_data *reloc);
struct relocation_data *reloc,
struct relocation *rel,
unsigned width, uint64_t *value,
- struct where const *where,
+ locus const &loc,
enum section_id offset_into, GElf_Sym **symptr);
#define PRI_LACK_RELOCATION ": %s seems to lack a relocation.\n"
// XXX the following should really be split out to different enum
/* Non-sections: */
- sec_locexpr, /* Not a section, but a portion of file that
- contains a location expression. */
rel_value, /* For relocations, this denotes that the
relocation is applied to taget value, not a
section offset. */
add (sec_mac, ".debug_mac");
add (sec_ranges, ".debug_ranges", "rangelist %#"PRIx64, "offset %#"PRIx64);
-
- add (sec_locexpr, "location expression", "offset %#"PRIx64);
}
} const section_names;
}
}
where
-WHERE (section_id sec, where const *next)
+WHERE (section_id sec, locus const *next)
{
where::formatter const *fmt = wf_for_section (sec);
return where (fmt, next);
{
public:
virtual std::string format (bool brief = false) const = 0;
+ virtual locus *clone () const = 0;
virtual locus const *next () const
{
return _m_next;
}
+ locus *
+ clone () const
+ {
+ return new where (*this);
+ }
+
void
set_next (locus const *nxt)
{
wh->reset_3 (addr);
}
-where WHERE (section_id sec, where const *next = NULL);
+where WHERE (section_id sec, locus const *next = NULL);
inline std::ostream &
operator << (std::ostream &os, where const &wh)