crashpad/snapshot/elf/elf_symbol_table_reader.h

90 lines
3.0 KiB
C
Raw Normal View History

// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_SNAPSHOT_ELF_ELF_SYMBOL_TABLE_READER_H_
#define CRASHPAD_SNAPSHOT_ELF_ELF_SYMBOL_TABLE_READER_H_
#include <stdint.h>
#include <string>
#include "base/macros.h"
#include "util/misc/address_types.h"
#include "util/process/process_memory_range.h"
namespace crashpad {
class ElfImageReader;
//! \brief A reader for symbol tables in ELF images mapped into another process.
class ElfSymbolTableReader {
public:
//! \brief Information about a symbol in a module's symbol table.
struct SymbolInformation {
//! \brief The address of the symbol as it exists in the symbol table, not
//! adjusted for any load bias.
VMAddress address;
//! \brief The size of the symbol.
VMSize size;
//! \brief The section index that the symbol definition is in relation to.
uint16_t shndx;
//! \brief Specifies the type of symbol. Possible values include
//! `STT_OBJECT`, `STT_FUNC`, etc.
uint8_t type;
//! \brief Specifies the default scope at which a symbol takes precedence.
//! Possible values include `STB_LOCAL`, `STB_GLOBAL`, `STB_WEAK`, or
//! OS/processor specific values.
uint8_t binding;
//! \brief Together with binding, can limit the visibility of a symbol to
//! the module that defines it. Possible values include `STV_DEFAULT`,
//! `STV_INTERNAL`, `STV_HIDDEN`, and `STV_PROTECTED`.
uint8_t visibility;
};
// TODO(jperaza): Support using .hash and .gnu.hash sections to improve symbol
// lookup.
ElfSymbolTableReader(const ProcessMemoryRange* memory,
ElfImageReader* elf_reader,
Read either DT_HASH or DT_GNU_HASH to determine the size of DT_SYMTAB Without the section headers for the symbol table, there's no direct way to calculate the number of entries in the table. DT_HASH and DT_GNU_HASH are auxiliary tables that are designed to make symbol lookup faster. DT_HASH is the original and is theoretically mandatory. DT_GNU_HASH is the new-and-improved, but is more complex. In practice, however, an Android build (at least vs. API 16) has only DT_HASH, and not DT_GNU_HASH, and a Fuchsia build has only DT_GNU_HASH but not DT_HASH. So, both are tried. This change does not actually use the data in these tables to improve the speed of symbol lookup, but instead only uses them to correctly terminate the linear search. DT_HASH contains the total number of symbols in the symbol table fairly directly because there is an entry for each symbol table entry in the hash table, so the number is the same. DT_GNU_HASH regrettably does not. Instead, it's necessary to walk the buckets and chain structure to find the largest entry. DT_GNU_HASH doesn't appear in any "real" documentation that I'm aware of, other than the binutils code (at least as far as I know). Some more-and-less-useful references: - https://flapenguin.me/2017/04/24/elf-lookup-dt-hash/ - https://flapenguin.me/2017/05/10/elf-lookup-dt-gnu-hash/ - http://deroko.phearless.org/dt_gnu_hash.txt - https://sourceware.org/ml/binutils/2006-10/msg00377.html Change-Id: I7cfc4372f29efc37446f0931d22a1f790e44076f Bug: crashpad:213, crashpad:196 Reviewed-on: https://chromium-review.googlesource.com/876879 Commit-Queue: Scott Graham <scottmg@chromium.org> Reviewed-by: Mark Mentovai <mark@chromium.org> Reviewed-by: Joshua Peraza <jperaza@chromium.org>
2018-01-30 14:30:50 -08:00
VMAddress address,
VMSize num_entries);
~ElfSymbolTableReader();
//! \brief Lookup information about a symbol.
//!
//! \param[in] name The name of the symbol to search for.
//! \param[out] info The symbol information, if found.
//! \return `true` if the symbol is found.
bool GetSymbol(const std::string& name, SymbolInformation* info);
private:
template <typename SymEnt>
bool ScanSymbolTable(const std::string& name, SymbolInformation* info);
const ProcessMemoryRange* const memory_; // weak
ElfImageReader* const elf_reader_; // weak
const VMAddress base_address_;
Read either DT_HASH or DT_GNU_HASH to determine the size of DT_SYMTAB Without the section headers for the symbol table, there's no direct way to calculate the number of entries in the table. DT_HASH and DT_GNU_HASH are auxiliary tables that are designed to make symbol lookup faster. DT_HASH is the original and is theoretically mandatory. DT_GNU_HASH is the new-and-improved, but is more complex. In practice, however, an Android build (at least vs. API 16) has only DT_HASH, and not DT_GNU_HASH, and a Fuchsia build has only DT_GNU_HASH but not DT_HASH. So, both are tried. This change does not actually use the data in these tables to improve the speed of symbol lookup, but instead only uses them to correctly terminate the linear search. DT_HASH contains the total number of symbols in the symbol table fairly directly because there is an entry for each symbol table entry in the hash table, so the number is the same. DT_GNU_HASH regrettably does not. Instead, it's necessary to walk the buckets and chain structure to find the largest entry. DT_GNU_HASH doesn't appear in any "real" documentation that I'm aware of, other than the binutils code (at least as far as I know). Some more-and-less-useful references: - https://flapenguin.me/2017/04/24/elf-lookup-dt-hash/ - https://flapenguin.me/2017/05/10/elf-lookup-dt-gnu-hash/ - http://deroko.phearless.org/dt_gnu_hash.txt - https://sourceware.org/ml/binutils/2006-10/msg00377.html Change-Id: I7cfc4372f29efc37446f0931d22a1f790e44076f Bug: crashpad:213, crashpad:196 Reviewed-on: https://chromium-review.googlesource.com/876879 Commit-Queue: Scott Graham <scottmg@chromium.org> Reviewed-by: Mark Mentovai <mark@chromium.org> Reviewed-by: Joshua Peraza <jperaza@chromium.org>
2018-01-30 14:30:50 -08:00
const VMSize num_entries_;
DISALLOW_COPY_AND_ASSIGN(ElfSymbolTableReader);
};
} // namespace crashpad
#endif // CRASHPAD_SNAPSHOT_ELF_ELF_SYMBOL_TABLE_READER_H_