aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar David Leverton <levertond@googlemail.com> 2008-01-03 00:26:32 +0000
committerAvatar David Leverton <levertond@googlemail.com> 2008-01-03 00:26:32 +0000
commit7aaaf13f6075ed1f6755d4047981b3be26355ba8 (patch)
tree071bc9fda225d6a750c64ceab2fbd5bc45f3c98a
parent1e252d613eaaa4fa8630266d7506c0f43aa8ae08 (diff)
downloadpaludis-7aaaf13f6075ed1f6755d4047981b3be26355ba8.tar.gz
paludis-7aaaf13f6075ed1f6755d4047981b3be26355ba8.tar.xz
Make reconcilio display more detailed messages for bad ELF files, and not allocate huge amounts of memory for files wih bad section header counts.
-rw-r--r--src/clients/reconcilio/broken_linkage_finder/elf_linkage_checker.cc8
-rw-r--r--src/clients/reconcilio/littlelf/elf.cc70
-rw-r--r--src/clients/reconcilio/littlelf/elf.hh2
-rw-r--r--src/clients/reconcilio/littlelf/elf_dynamic_section.cc62
-rw-r--r--src/clients/reconcilio/littlelf/elf_dynamic_section.hh15
-rw-r--r--src/clients/reconcilio/littlelf/elf_relocation_section.cc9
-rw-r--r--src/clients/reconcilio/littlelf/elf_relocation_section.hh2
-rw-r--r--src/clients/reconcilio/littlelf/elf_sections.cc20
-rw-r--r--src/clients/reconcilio/littlelf/elf_sections.hh17
-rw-r--r--src/clients/reconcilio/littlelf/elf_symbol_section.cc42
-rw-r--r--src/clients/reconcilio/littlelf/elf_symbol_section.hh2
11 files changed, 165 insertions, 84 deletions
diff --git a/src/clients/reconcilio/broken_linkage_finder/elf_linkage_checker.cc b/src/clients/reconcilio/broken_linkage_finder/elf_linkage_checker.cc
index 8303d90..19491e0 100644
--- a/src/clients/reconcilio/broken_linkage_finder/elf_linkage_checker.cc
+++ b/src/clients/reconcilio/broken_linkage_finder/elf_linkage_checker.cc
@@ -206,9 +206,9 @@ Implementation<ElfLinkageChecker>::check_elf(const FSEntry & file, std::ifstream
}
}
}
- catch (const InvalidElfFileError &)
+ catch (const InvalidElfFileError & e)
{
- Log::get_instance()->message(ll_warning, lc_no_context, "'" + stringify(file) + "' appears to be invalid or corrupted");
+ Log::get_instance()->message(ll_warning, lc_no_context, "'" + stringify(file) + "' appears to be invalid or corrupted: " + e.message());
}
return true;
@@ -345,9 +345,9 @@ Implementation<ElfLinkageChecker>::check_extra_elf(const FSEntry & file, std::is
else
Log::get_instance()->message(ll_debug, lc_context, "'" + stringify(file) + "' is not a library");
}
- catch (const InvalidElfFileError &)
+ catch (const InvalidElfFileError & e)
{
- Log::get_instance()->message(ll_warning, lc_no_context, "'" + stringify(file) + "' appears to be invalid or corrupted");
+ Log::get_instance()->message(ll_warning, lc_no_context, "'" + stringify(file) + "' appears to be invalid or corrupted: " + e.message());
}
return true;
diff --git a/src/clients/reconcilio/littlelf/elf.cc b/src/clients/reconcilio/littlelf/elf.cc
index bc66bee..069e536 100644
--- a/src/clients/reconcilio/littlelf/elf.cc
+++ b/src/clients/reconcilio/littlelf/elf.cc
@@ -33,6 +33,7 @@
#include <paludis/util/visitor-impl.hh>
#include <paludis/util/wrapped_forward_iterator-impl.hh>
#include <paludis/util/iterator_funcs.hh>
+#include <paludis/util/stringify.hh>
#include <string>
#include <exception>
@@ -150,7 +151,9 @@ namespace
{
typename ElfObject<ElfType_>::SectionIterator sec(_elf_object->get_section_by_index(section.get_link_index()));
if (_elf_object->section_end() == sec)
- throw InvalidElfFileError();
+ throw InvalidElfFileError(
+ section.description() + " references non-existent section " +
+ stringify(section.get_link_index()) + " in sh_link");
section.resolve_symbols(*sec);
}
@@ -158,7 +161,9 @@ namespace
{
typename ElfObject<ElfType_>::SectionIterator sec(_elf_object->get_section_by_index(section.get_link_index()));
if (_elf_object->section_end() == sec)
- throw InvalidElfFileError();
+ throw InvalidElfFileError(
+ section.description() + " references non-existent section " +
+ stringify(section.get_link_index()) + " in sh_link");
section.resolve_entry_names(*sec);
}
};
@@ -184,15 +189,18 @@ namespace littlelf_internals
virtual void visit(const StringSection<ElfType_> & section)
{
- try
- {
- for (typename ElfObject<ElfType_>::SectionIterator i = _begin; i != _end; ++i)
+ for (typename ElfObject<ElfType_>::SectionIterator i = _begin; i != _end; ++i)
+ try
+ {
i->resolve_section_name(section.get_string(i->get_name_index()));
- }
- catch (std::out_of_range &)
- {
- throw InvalidElfFileError();
- }
+ }
+ catch (std::out_of_range &)
+ {
+ throw InvalidElfFileError(
+ i->description() + " has out-of-range name index " +
+ stringify(i->get_name_index()) + " for " + section.description() +
+ " (max " + stringify(section.get_max_string()) + ")");
+ }
}
};
}
@@ -202,8 +210,8 @@ InvalidElfFileError::InvalidElfFileError(const InvalidElfFileError & other) :
{
}
-InvalidElfFileError::InvalidElfFileError() throw ():
- Exception("Invalid ELF file")
+InvalidElfFileError::InvalidElfFileError(const std::string & s) throw ():
+ Exception(s)
{
}
@@ -263,12 +271,23 @@ ElfObject<ElfType_>::ElfObject(std::istream & stream) :
if (_hdr.e_shoff)
{
if (sizeof(typename ElfType_::SectionHeader) != _hdr.e_shentsize)
- throw InvalidElfFileError();
+ throw InvalidElfFileError(
+ "bad e_shentsize: got " + stringify(_hdr.e_shentsize) + ", expected " +
+ stringify(sizeof(typename ElfType_::SectionHeader)));
+
+ stream.seekg(0, std::ios::end);
+ typename ElfType_::Word max_shdrs(
+ (typename ElfType_::Word(stream.tellg()) - _hdr.e_shoff) / sizeof(typename ElfType_::SectionHeader));
stream.seekg(_hdr.e_shoff, std::ios::beg);
if (_hdr.e_shnum)
{
+ if (_hdr.e_shnum > max_shdrs)
+ throw InvalidElfFileError(
+ "file claims to contain " + stringify(_hdr.e_shnum) +
+ " section headers, but is only big enough to contain " + stringify(max_shdrs));
std::vector<typename ElfType_::SectionHeader> my_shdrs(_hdr.e_shnum);
+
stream.read(reinterpret_cast<char *>(&my_shdrs.front()), sizeof(typename ElfType_::SectionHeader) * _hdr.e_shnum);
if (need_byte_swap)
std::for_each(my_shdrs.begin(), my_shdrs.end(),
@@ -282,9 +301,14 @@ ElfObject<ElfType_>::ElfObject(std::istream & stream) :
if (need_byte_swap)
ByteSwapSectionHeader<ElfType_>::swap_in_place(first_shdr);
if (0 == first_shdr.sh_size)
- throw InvalidElfFileError();
+ throw InvalidElfFileError("got non-zero e_shoff and zero e_shnum, but sh_size of the first section is zero");
+ if (first_shdr.sh_size > max_shdrs)
+ throw InvalidElfFileError(
+ "file claims to contain " + stringify(first_shdr.sh_size) +
+ " section headers, but is only big enough to contain " + stringify(max_shdrs));
std::vector<typename ElfType_::SectionHeader> my_shdrs(first_shdr.sh_size);
+
my_shdrs[0] = first_shdr;
stream.read(reinterpret_cast<char *>(&my_shdrs[1]), sizeof(typename ElfType_::SectionHeader) * (first_shdr.sh_size - 1));
if (need_byte_swap)
@@ -297,31 +321,33 @@ ElfObject<ElfType_>::ElfObject(std::istream & stream) :
for (typename std::vector<typename ElfType_::SectionHeader>::iterator i = shdrs.begin(); i != shdrs.end(); ++i)
{
if (i->sh_type == SHT_STRTAB)
- _imp->sections.push_back(make_shared_ptr(new StringSection<ElfType_>(*i, stream, need_byte_swap)));
+ _imp->sections.push_back(make_shared_ptr(new StringSection<ElfType_>(_imp->sections.size(), *i, stream, need_byte_swap)));
else if ( (i->sh_type == SHT_SYMTAB) || (i->sh_type == SHT_DYNSYM) )
- _imp->sections.push_back(make_shared_ptr(new SymbolSection<ElfType_>(*i, stream, need_byte_swap)));
+ _imp->sections.push_back(make_shared_ptr(new SymbolSection<ElfType_>(_imp->sections.size(), *i, stream, need_byte_swap)));
else if (i->sh_type == SHT_DYNAMIC)
- _imp->sections.push_back(make_shared_ptr(new DynamicSection<ElfType_>(*i, stream, need_byte_swap)));
+ _imp->sections.push_back(make_shared_ptr(new DynamicSection<ElfType_>(_imp->sections.size(), *i, stream, need_byte_swap)));
else if (i->sh_type == SHT_REL)
- _imp->sections.push_back(make_shared_ptr(new RelocationSection<ElfType_, Relocation<ElfType_> >(*i, stream, need_byte_swap)));
+ _imp->sections.push_back(make_shared_ptr(new RelocationSection<ElfType_, Relocation<ElfType_> >(_imp->sections.size(), *i, stream, need_byte_swap)));
else if (i->sh_type == SHT_RELA)
- _imp->sections.push_back(make_shared_ptr(new RelocationSection<ElfType_, RelocationA<ElfType_> >(*i, stream, need_byte_swap)));
+ _imp->sections.push_back(make_shared_ptr(new RelocationSection<ElfType_, RelocationA<ElfType_> >(_imp->sections.size(), *i, stream, need_byte_swap)));
else
- _imp->sections.push_back(make_shared_ptr(new GenericSection<ElfType_>(*i)));
+ _imp->sections.push_back(make_shared_ptr(new GenericSection<ElfType_>(_imp->sections.size(), *i)));
}
if (! _hdr.e_shstrndx)
return;
typename ElfType_::Half shstrndx(SHN_XINDEX == _hdr.e_shstrndx ? shdrs[0].sh_link : _hdr.e_shstrndx);
if (_imp->sections.size() <= shstrndx)
- throw InvalidElfFileError();
+ throw InvalidElfFileError(
+ "section name table has index " + stringify(shstrndx) +
+ ", but only found " + stringify(_imp->sections.size()) + " sections");
littlelf_internals::SectionNameResolvingVisitor<ElfType_> res(section_begin(), section_end());
_imp->sections[shstrndx]->accept(res);
}
catch (const std::ios_base::failure &)
{
- throw InvalidElfFileError();
+ throw InvalidElfFileError("file is truncated, or an offset points past the end of the file");
}
}
diff --git a/src/clients/reconcilio/littlelf/elf.hh b/src/clients/reconcilio/littlelf/elf.hh
index a42b6e7..1459393 100644
--- a/src/clients/reconcilio/littlelf/elf.hh
+++ b/src/clients/reconcilio/littlelf/elf.hh
@@ -35,7 +35,7 @@ class InvalidElfFileError :
{
public:
InvalidElfFileError(const InvalidElfFileError &);
- InvalidElfFileError() throw ();
+ InvalidElfFileError(const std::string &) throw ();
};
template <typename ElfType_>
diff --git a/src/clients/reconcilio/littlelf/elf_dynamic_section.cc b/src/clients/reconcilio/littlelf/elf_dynamic_section.cc
index 3ad6ac3..1bb282d 100644
--- a/src/clients/reconcilio/littlelf/elf_dynamic_section.cc
+++ b/src/clients/reconcilio/littlelf/elf_dynamic_section.cc
@@ -62,10 +62,14 @@ namespace littlelf_internals
using DynamicEntriesVisitor<ElfType_>::visit;
private:
+ const DynamicSection<ElfType_> & _dyn_section;
const StringSection<ElfType_> & _string_section;
public:
- DynEntriesStringResolvingVisitor(const StringSection<ElfType_> & string_section) :
+ DynEntriesStringResolvingVisitor(
+ const DynamicSection<ElfType_> & dyn_section,
+ const StringSection<ElfType_> & string_section) :
+ _dyn_section(dyn_section),
_string_section(string_section)
{
}
@@ -78,7 +82,10 @@ namespace littlelf_internals
}
catch (std::out_of_range &)
{
- throw InvalidElfFileError();
+ throw InvalidElfFileError(
+ entry.description() + " in " + _dyn_section.description() + " has out-of-range string index " +
+ stringify(entry.get_string_index()) + " for " + _string_section.description() +
+ " (max " + stringify(_string_section.get_max_string()) + ")");
}
}
};
@@ -103,20 +110,23 @@ namespace
using SectionVisitor<ElfType_>::visit;
private:
+ const DynamicSection<ElfType_> & _dyn_section;
typename std::vector<tr1::shared_ptr<DynamicEntry<ElfType_> > >::iterator _begin, _end;
public:
- DynamicSectionStringResolvingVisitor(
+ DynamicSectionStringResolvingVisitor(const DynamicSection<ElfType_> & dyn_section,
typename std::vector<tr1::shared_ptr<DynamicEntry<ElfType_> > >::iterator begin,
typename std::vector<tr1::shared_ptr<DynamicEntry<ElfType_> > >::iterator end) :
+ _dyn_section(dyn_section),
_begin(begin),
_end(end)
+
{
}
virtual void visit(StringSection<ElfType_> & section)
{
- littlelf_internals::DynEntriesStringResolvingVisitor<ElfType_> v(section);
+ littlelf_internals::DynEntriesStringResolvingVisitor<ElfType_> v(_dyn_section, section);
for(typename std::vector<tr1::shared_ptr<DynamicEntry<ElfType_> > >::iterator i = _begin; i != _end; ++i)
(*i)->accept(v);
}
@@ -135,36 +145,38 @@ DynamicEntry<ElfType_>::~DynamicEntry()
}
template <typename ElfType_>
-DynamicEntryUnknown<ElfType_>::DynamicEntryUnknown() :
- DynamicEntry<ElfType_>("unknown")
+void
+DynamicEntry<ElfType_>::initialize(typename ElfType_::Word index, const typename ElfType_::DynamicEntry &)
{
+ _index = index;
}
template <typename ElfType_>
-DynamicEntryUnknown<ElfType_>::~DynamicEntryUnknown()
+std::string
+DynamicEntry<ElfType_>::description() const
{
+ return tag_name() + " dynamic entry " + stringify(_index);
}
template <typename ElfType_>
-void
-DynamicEntryUnknown<ElfType_>::initialize(const typename ElfType_::DynamicEntry &)
+DynamicEntryUnknown<ElfType_>::DynamicEntryUnknown() :
+ DynamicEntry<ElfType_>("unknown")
{
}
template <typename ElfType_>
-DynamicEntryFlag<ElfType_>::DynamicEntryFlag(const std::string & name) :
- DynamicEntry<ElfType_>(name)
+DynamicEntryUnknown<ElfType_>::~DynamicEntryUnknown()
{
}
template <typename ElfType_>
-DynamicEntryFlag<ElfType_>::~DynamicEntryFlag()
+DynamicEntryFlag<ElfType_>::DynamicEntryFlag(const std::string & name) :
+ DynamicEntry<ElfType_>(name)
{
}
template <typename ElfType_>
-void
-DynamicEntryFlag<ElfType_>::initialize(const typename ElfType_::DynamicEntry &)
+DynamicEntryFlag<ElfType_>::~DynamicEntryFlag()
{
}
@@ -181,8 +193,9 @@ DynamicEntryValue<ElfType_>::~DynamicEntryValue()
template <typename ElfType_>
void
-DynamicEntryValue<ElfType_>::initialize(const typename ElfType_::DynamicEntry & entry)
+DynamicEntryValue<ElfType_>::initialize(typename ElfType_::Word index, const typename ElfType_::DynamicEntry & entry)
{
+ DynamicEntry<ElfType_>::initialize(index, entry);
_value = entry.d_un.d_val;
}
@@ -199,8 +212,9 @@ DynamicEntryPointer<ElfType_>::~DynamicEntryPointer()
template <typename ElfType_>
void
-DynamicEntryPointer<ElfType_>::initialize(const typename ElfType_::DynamicEntry & entry)
+DynamicEntryPointer<ElfType_>::initialize(typename ElfType_::Word index, const typename ElfType_::DynamicEntry & entry)
{
+ DynamicEntry<ElfType_>::initialize(index, entry);
_pointer = entry.d_un.d_ptr;
}
@@ -218,8 +232,9 @@ DynamicEntryString<ElfType_>::~DynamicEntryString()
template <typename ElfType_>
void
-DynamicEntryString<ElfType_>::initialize(const typename ElfType_::DynamicEntry & entry)
+DynamicEntryString<ElfType_>::initialize(typename ElfType_::Word index, const typename ElfType_::DynamicEntry & entry)
{
+ DynamicEntry<ElfType_>::initialize(index, entry);
_value = entry.d_un.d_val;
}
@@ -267,12 +282,14 @@ DynamicEntries<ElfType_>::has_entry(typename ElfType_::DynamicTag identifier) co
}
template <typename ElfType_>
-DynamicSection<ElfType_>::DynamicSection(const typename ElfType_::SectionHeader & shdr, std::istream & stream, bool need_byte_swap) :
- Section<ElfType_>(shdr),
+DynamicSection<ElfType_>::DynamicSection(typename ElfType_::Word index, const typename ElfType_::SectionHeader & shdr, std::istream & stream, bool need_byte_swap) :
+ Section<ElfType_>(index, shdr),
PrivateImplementationPattern<DynamicSection>(new Implementation<DynamicSection>)
{
if (sizeof(typename ElfType_::DynamicEntry) != shdr.sh_entsize)
- throw InvalidElfFileError();
+ throw InvalidElfFileError(
+ "bad sh_entsize for " + this->description() + ": got " + stringify(shdr.sh_entsize) + ", expected " +
+ stringify(sizeof(typename ElfType_::DynamicEntry)));
stream.seekg(shdr.sh_offset, std::ios::beg);
std::vector<typename ElfType_::DynamicEntry> tmp_entries(shdr.sh_size / sizeof(typename ElfType_::DynamicEntry));
@@ -284,7 +301,7 @@ DynamicSection<ElfType_>::DynamicSection(const typename ElfType_::SectionHeader
for (typename std::vector<typename ElfType_::DynamicEntry>::iterator i = tmp_entries.begin(); i != tmp_entries.end(); ++i)
{
paludis::tr1::shared_ptr<DynamicEntry<ElfType_> > instance(DynamicEntries<ElfType_>::get_instance()->get_entry(i->d_tag));
- instance->initialize(*i);
+ instance->initialize(_imp->dynamic_entries.size(), *i);
_imp->dynamic_entries.push_back(instance);
}
}
@@ -306,7 +323,8 @@ template <typename ElfType_>
void
DynamicSection<ElfType_>::resolve_entry_names(Section<ElfType_> & string_section)
{
- DynamicSectionStringResolvingVisitor<ElfType_> v(_imp->dynamic_entries.begin(), _imp->dynamic_entries.end());
+ DynamicSectionStringResolvingVisitor<ElfType_> v(
+ *this, _imp->dynamic_entries.begin(), _imp->dynamic_entries.end());
string_section.accept(v);
}
diff --git a/src/clients/reconcilio/littlelf/elf_dynamic_section.hh b/src/clients/reconcilio/littlelf/elf_dynamic_section.hh
index acc1803..9736860 100644
--- a/src/clients/reconcilio/littlelf/elf_dynamic_section.hh
+++ b/src/clients/reconcilio/littlelf/elf_dynamic_section.hh
@@ -73,16 +73,19 @@ class DynamicEntry :
{
private:
std::string _tag_name;
+ typename ElfType_::Word _index;
public:
DynamicEntry(const std::string &);
~DynamicEntry();
- virtual void initialize(const typename ElfType_::DynamicEntry & entry) = 0;
+ virtual void initialize(typename ElfType_::Word, const typename ElfType_::DynamicEntry & entry);
std::string tag_name() const
{
return _tag_name;
}
+
+ std::string description() const;
};
template <typename ElfType_>
@@ -94,7 +97,6 @@ class DynamicEntryUnknown :
public:
DynamicEntryUnknown();
virtual ~DynamicEntryUnknown();
- virtual void initialize(const typename ElfType_::DynamicEntry &);
};
template <typename ElfType_>
@@ -106,7 +108,6 @@ class DynamicEntryFlag :
public:
DynamicEntryFlag(const std::string &);
~DynamicEntryFlag();
- virtual void initialize(const typename ElfType_::DynamicEntry &);
};
template <typename ElfType_>
@@ -121,7 +122,7 @@ class DynamicEntryValue :
public:
DynamicEntryValue(const std::string &);
virtual ~DynamicEntryValue();
- virtual void initialize(const typename ElfType_::DynamicEntry & entry);
+ virtual void initialize(typename ElfType_::Word, const typename ElfType_::DynamicEntry & entry);
typename ElfType_::DynamicValue operator() () const
{
@@ -141,7 +142,7 @@ class DynamicEntryPointer :
public:
DynamicEntryPointer(const std::string &);
virtual ~DynamicEntryPointer();
- virtual void initialize(const typename ElfType_::DynamicEntry &);
+ virtual void initialize(typename ElfType_::Word, const typename ElfType_::DynamicEntry &);
typename ElfType_::DynamicPointer operator() () const
{
@@ -169,7 +170,7 @@ class DynamicEntryString :
public:
DynamicEntryString(const std::string &);
virtual ~DynamicEntryString();
- virtual void initialize(const typename ElfType_::DynamicEntry &);
+ virtual void initialize(typename ElfType_::Word, const typename ElfType_::DynamicEntry &);
std::string operator() () const
{
@@ -216,7 +217,7 @@ class DynamicSection :
using paludis::PrivateImplementationPattern<DynamicSection>::_imp;
public:
- DynamicSection(const typename ElfType_::SectionHeader &, std::istream &, bool);
+ DynamicSection(typename ElfType_::Word, const typename ElfType_::SectionHeader &, std::istream &, bool);
virtual ~DynamicSection();
virtual std::string get_type() const;
diff --git a/src/clients/reconcilio/littlelf/elf_relocation_section.cc b/src/clients/reconcilio/littlelf/elf_relocation_section.cc
index 7233e27..3bc72c3 100644
--- a/src/clients/reconcilio/littlelf/elf_relocation_section.cc
+++ b/src/clients/reconcilio/littlelf/elf_relocation_section.cc
@@ -27,6 +27,7 @@
#include <paludis/util/private_implementation_pattern-impl.hh>
#include <paludis/util/visitor-impl.hh>
#include <paludis/util/wrapped_forward_iterator-impl.hh>
+#include <paludis/util/stringify.hh>
#include <istream>
#include <vector>
@@ -95,12 +96,14 @@ template <typename ElfType_> const std::string RelocationA<ElfType_>::type_name
template <typename ElfType_, typename Relocation_>
RelocationSection<ElfType_, Relocation_>::RelocationSection(
- const typename ElfType_::SectionHeader & shdr, std::istream & stream, bool need_byte_swap) :
- Section<ElfType_>(shdr),
+ typename ElfType_::Word index, const typename ElfType_::SectionHeader & shdr, std::istream & stream, bool need_byte_swap) :
+ Section<ElfType_>(index, shdr),
PrivateImplementationPattern<RelocationSection>(new Implementation<RelocationSection>)
{
if (sizeof(typename Relocation_::Type) != shdr.sh_entsize)
- throw InvalidElfFileError();
+ throw InvalidElfFileError(
+ "bad sh_entsize for " + this->description() + ": got " + stringify(shdr.sh_entsize) + ", expected " +
+ stringify(sizeof(typename Relocation_::Type)));
std::vector<typename Relocation_::Type> relocations(shdr.sh_size / sizeof(typename Relocation_::Type));
stream.seekg(shdr.sh_offset, std::ios::beg);
diff --git a/src/clients/reconcilio/littlelf/elf_relocation_section.hh b/src/clients/reconcilio/littlelf/elf_relocation_section.hh
index 7b63997..751f4be 100644
--- a/src/clients/reconcilio/littlelf/elf_relocation_section.hh
+++ b/src/clients/reconcilio/littlelf/elf_relocation_section.hh
@@ -100,7 +100,7 @@ class RelocationSection :
using paludis::PrivateImplementationPattern<RelocationSection>::_imp;
public:
- RelocationSection(const typename ElfType_::SectionHeader &, std::istream &, bool);
+ RelocationSection(typename ElfType_::Word, const typename ElfType_::SectionHeader &, std::istream &, bool);
virtual ~RelocationSection();
virtual std::string get_type() const
diff --git a/src/clients/reconcilio/littlelf/elf_sections.cc b/src/clients/reconcilio/littlelf/elf_sections.cc
index e93159b..bb68066 100644
--- a/src/clients/reconcilio/littlelf/elf_sections.cc
+++ b/src/clients/reconcilio/littlelf/elf_sections.cc
@@ -22,6 +22,7 @@
#include "elf_types.hh"
#include <paludis/util/visitor-impl.hh>
+#include <paludis/util/stringify.hh>
#include <istream>
#include <algorithm>
@@ -29,7 +30,8 @@
using namespace paludis;
template <typename ElfType_>
-Section<ElfType_>::Section(const typename ElfType_::SectionHeader & shdr) :
+Section<ElfType_>::Section(typename ElfType_::Word index, const typename ElfType_::SectionHeader & shdr) :
+ _index(index),
_shdr(shdr),
_name("")
{
@@ -41,8 +43,16 @@ Section<ElfType_>::~Section()
}
template <typename ElfType_>
-GenericSection<ElfType_>::GenericSection(const typename ElfType_::SectionHeader & shdr) :
- Section<ElfType_>(shdr)
+std::string
+Section<ElfType_>::description() const
+{
+ return get_type() + " section " + (get_name().empty() ? "[name not yet resolved]" : get_name())
+ + " " + stringify(get_index());
+}
+
+template <typename ElfType_>
+GenericSection<ElfType_>::GenericSection(typename ElfType_::Word index, const typename ElfType_::SectionHeader & shdr) :
+ Section<ElfType_>(index, shdr)
{
}
@@ -60,8 +70,8 @@ GenericSection<ElfType_>::get_type() const
}
template <typename ElfType_>
-StringSection<ElfType_>::StringSection(const typename ElfType_::SectionHeader & shdr, std::istream & stream, bool) :
- Section<ElfType_>(shdr),
+StringSection<ElfType_>::StringSection(typename ElfType_::Word index, const typename ElfType_::SectionHeader & shdr, std::istream & stream, bool) :
+ Section<ElfType_>(index, shdr),
_stringTable(shdr.sh_size, ' ')
{
std::string tmp_table(shdr.sh_size, '\0');
diff --git a/src/clients/reconcilio/littlelf/elf_sections.hh b/src/clients/reconcilio/littlelf/elf_sections.hh
index 0540423..a16abb3 100644
--- a/src/clients/reconcilio/littlelf/elf_sections.hh
+++ b/src/clients/reconcilio/littlelf/elf_sections.hh
@@ -90,6 +90,7 @@ class Section :
friend class littlelf_internals::SectionNameResolvingVisitor<ElfType_>;
private:
+ typename ElfType_::Word _index;
typename ElfType_::SectionHeader _shdr;
std::string _name;
@@ -105,7 +106,7 @@ class Section :
}
public:
- Section(const typename ElfType_::SectionHeader &);
+ Section(typename ElfType_::Word, const typename ElfType_::SectionHeader &);
virtual ~Section();
virtual typename ElfType_::Offset get_data_offset() const
@@ -118,6 +119,10 @@ class Section :
return _name;
}
virtual std::string get_type() const = 0;
+ typename ElfType_::Word get_index() const
+ {
+ return _index;
+ }
typename ElfType_::Word get_link_index() const
{
@@ -133,6 +138,8 @@ class Section :
{
return _shdr.sh_size;
}
+
+ std::string description() const;
};
@@ -142,7 +149,7 @@ class GenericSection :
public paludis::AcceptInterfaceVisitsThis<SectionVisitorTypes<ElfType_> , GenericSection<ElfType_> >
{
public:
- GenericSection(const typename ElfType_::SectionHeader &);
+ GenericSection(typename ElfType_::Word, const typename ElfType_::SectionHeader &);
virtual ~GenericSection();
virtual std::string get_type() const;
};
@@ -156,10 +163,14 @@ class StringSection :
std::string _stringTable;
public:
- StringSection(const typename ElfType_::SectionHeader &, std::istream &, bool);
+ StringSection(typename ElfType_::Word, const typename ElfType_::SectionHeader &, std::istream &, bool);
virtual ~StringSection();
std::string get_string(typename ElfType_::Word) const;
+ typename ElfType_::Word get_max_string() const
+ {
+ return _stringTable.length();
+ }
virtual std::string get_type() const;
};
diff --git a/src/clients/reconcilio/littlelf/elf_symbol_section.cc b/src/clients/reconcilio/littlelf/elf_symbol_section.cc
index 296a3db..7cb08d5 100644
--- a/src/clients/reconcilio/littlelf/elf_symbol_section.cc
+++ b/src/clients/reconcilio/littlelf/elf_symbol_section.cc
@@ -27,6 +27,7 @@
#include <paludis/util/private_implementation_pattern-impl.hh>
#include <paludis/util/visitor-impl.hh>
#include <paludis/util/wrapped_forward_iterator-impl.hh>
+#include <paludis/util/stringify.hh>
#include <istream>
#include <vector>
@@ -69,26 +70,33 @@ namespace littlelf_internals
using SectionVisitor<ElfType_>::visit;
private:
+ const SymbolSection<ElfType_> & _sym_section;
typename std::vector<Symbol<ElfType_> >::iterator _begin, _end;
public:
- SymbolStringResolvingVisitor(typename std::vector<Symbol<ElfType_> >::iterator begin, typename std::vector<Symbol<ElfType_> >::iterator end) :
+ SymbolStringResolvingVisitor(const SymbolSection<ElfType_> & sym_section,
+ typename std::vector<Symbol<ElfType_> >::iterator begin,
+ typename std::vector<Symbol<ElfType_> >::iterator end) :
+ _sym_section(sym_section),
_begin(begin),
_end(end)
{
}
- virtual void visit(StringSection<ElfType_> & section)
+ virtual void visit(StringSection<ElfType_> & string_section)
{
- try
- {
- for (typename std::vector<Symbol<ElfType_> >::iterator i = _begin; i != _end; ++i)
- i->resolve_symbol(section.get_string(i->get_symbol_index()));
- }
- catch (std::out_of_range &)
- {
- throw InvalidElfFileError();
- }
+ for (typename std::vector<Symbol<ElfType_> >::iterator i = _begin; i != _end; ++i)
+ try
+ {
+ i->resolve_symbol(string_section.get_string(i->get_symbol_index()));
+ }
+ catch (std::out_of_range &)
+ {
+ throw InvalidElfFileError(
+ "symbol " + stringify(i - _begin) + " in " + _sym_section.description() + " has out-of-range string index " +
+ stringify(i->get_symbol_index()) + " for " + string_section.description() +
+ " (max " + stringify(string_section.get_max_string()) + ")");
+ }
}
};
}
@@ -151,8 +159,8 @@ Symbol<ElfType_>::~Symbol()
}
template <typename ElfType_>
-SymbolSection<ElfType_>::SymbolSection(const typename ElfType_::SectionHeader & shdr, std::istream & stream, bool need_byte_swap) :
- Section<ElfType_>(shdr),
+SymbolSection<ElfType_>::SymbolSection(typename ElfType_::Word index, const typename ElfType_::SectionHeader & shdr, std::istream & stream, bool need_byte_swap) :
+ Section<ElfType_>(index, shdr),
PrivateImplementationPattern<SymbolSection>(new Implementation<SymbolSection>),
_type("invalid")
{
@@ -162,7 +170,10 @@ SymbolSection<ElfType_>::SymbolSection(const typename ElfType_::SectionHeader &
_type = "SYMTAB";
if (sizeof(typename ElfType_::Symbol) != shdr.sh_entsize)
- throw InvalidElfFileError();
+ throw InvalidElfFileError(
+ "bad sh_entsize for " + this->description() + ": got " + stringify(shdr.sh_entsize) + ", expected " +
+ stringify(sizeof(typename ElfType_::Symbol)));
+
std::vector<typename ElfType_::Symbol> symbols(shdr.sh_size / sizeof(typename ElfType_::Symbol));
stream.seekg(shdr.sh_offset, std::ios::beg);
stream.read( reinterpret_cast<char *>(&symbols.front()), shdr.sh_size );
@@ -183,7 +194,8 @@ template <typename ElfType_>
void
SymbolSection<ElfType_>::resolve_symbols(Section<ElfType_> & string_section)
{
- littlelf_internals::SymbolStringResolvingVisitor<ElfType_> v(_imp->symbols.begin(), _imp->symbols.end());
+ littlelf_internals::SymbolStringResolvingVisitor<ElfType_> v(
+ *this, _imp->symbols.begin(), _imp->symbols.end());
string_section.accept(v);
}
diff --git a/src/clients/reconcilio/littlelf/elf_symbol_section.hh b/src/clients/reconcilio/littlelf/elf_symbol_section.hh
index 1e65763..66d6fee 100644
--- a/src/clients/reconcilio/littlelf/elf_symbol_section.hh
+++ b/src/clients/reconcilio/littlelf/elf_symbol_section.hh
@@ -86,7 +86,7 @@ class SymbolSection :
std::string _type;
public:
- SymbolSection(const typename ElfType_::SectionHeader &, std::istream &, bool);
+ SymbolSection(typename ElfType_::Word, const typename ElfType_::SectionHeader &, std::istream &, bool);
virtual ~SymbolSection();
virtual std::string get_type() const