{GNU,}HashSection: Implement symbol lookup (#290)
In super-stripped binaries, symbol tables can not be accessed
directly as we do not have section headers to find them. In
this case, we can already use the mandatory DynamicSegment
which provides methods for individual access and iteration
over symbols via a minimal implementation of symbol hash
sections which only provided the number of symbols so far.
As we can also directly look up symbols via the hash table,
let's implement this functionality as well.
The code is based on @rhelmot's implementation as discussed
in #219, with some changes around reading the hash parameters.
For supporting individual symbol lookup, we also need the
corresponding symbol table to get the Symbol objects if the
matching hash was found in the hash section. In regular ELF
files, the symbol table is denoted by the section index
provided in the sh_link field of the hash section and
automatically created when building the hash section, for
super-stripped binaries we can use the DynamicSegment (which
needs to be present in any case) as the symbol table as it
also provides a get_symbol() method relying on other ways to
determine the list of symbols. Both of these variants can be
seen in the improved test_hash.py file.
The hash tables are implemented in a base class which does not
derive from the Section class in order to allow instantiation
even if no section headers are present in the underlying file.