blob: 8a5f3f9362f28e0a60801ad474f365c874534354 [file] [log] [blame]
// Copyright (c) 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_DEBUG_BUFFERED_DWARF_READER_H_
#define BASE_DEBUG_BUFFERED_DWARF_READER_H_
#include <cstddef>
#include <cstdint>
#ifdef USE_SYMBOLIZE
namespace base {
namespace debug {
class BufferedDwarfReader {
public:
// Constructs a BufferedDwarfReader for a given `fd` starting
// `position` bytes from the start of the file.
//
// BufferedDwarfReader does not affect the `fd` state so it is completely
// okay to have multiple BufferedDwarfReader attached to one `fd` to act
// as cursors into different parts of the file.
BufferedDwarfReader(int fd, uint64_t position);
// Gets and Sets the absolute position from the start of the file.
uint64_t position() const { return last_chunk_start_ + cursor_in_buffer_; }
void set_position(uint64_t position) {
last_chunk_start_ = next_chunk_start_ = position;
// Invalidate buffer.
cursor_in_buffer_ = 0;
unconsumed_amount_ = 0;
}
bool ReadInt8(uint8_t& value) { return ReadInt(value); }
bool ReadInt8(int8_t& value) { return ReadInt(value); }
bool ReadInt16(uint16_t& value) { return ReadInt(value); }
bool ReadInt32(uint32_t& value) { return ReadInt(value); }
bool ReadInt64(uint64_t& value) { return ReadInt(value); }
// Helper to read a null-terminated sequence of bytes.
//
// Reads at most `max_position - position()` bytes.
//
// Returns the number of bytes written into `out`.
// On a read error, the internal position of the BufferedDwarfReader may
// still be advanced. This should only happen if something funky
// happens at the OS layer at which case it's all best-effort
// recovery afterwards anyways.
size_t ReadCString(uint64_t max_position, char* out, size_t out_size);
// Leb128 is a variable-length integer encoding format. This reads
// both the signed and unsigned variants of this field.
bool ReadLeb128(uint64_t& value);
bool ReadLeb128(int64_t& value);
// Headers in DWARF often start with a length field of type "initial length."
// This is a variable-length field that both indicates if the entry is in
// 32-bit or 64-bit DWARF format and the length of the entry.
//
// Note: is_64bit refers to the DWARF format, not the target architecture.
// Most 64-bit binaries use 32-bit DWARF so is_64bit is frequently false.
bool ReadInitialLength(bool& is_64bit, uint64_t& length);
// Offsets inside DWARF are encoded at different sizes based on if it is
// 32-bit DWARF or 64-bit DWARF. The value of `is_64bit` is usually retrieved
// by a prior ReadInitialLength() call.
bool ReadOffset(bool is_64bit, uint64_t& offset);
// Addresses in DWARF are stored based on address size of the
// target architecture. This helper reads the correct sized field
// but then up-converts to a uint64_t type. It does an unsigned
// extension so 0xffffffff on a 32-bit system will still read out
// as 0xffffffff.
bool ReadAddress(uint8_t address_size, uint64_t& address);
// Many DWARF headers seem to start with
// length (initial length)
// version (ushort)
// offset (32bit or 64-bit dependent on initial length parsing)
// address_size (ubyte)
//
// The initial length also encodes if this is 32-bit or 64-bit dwarf.
// This function parses the above sequence of fields.
//
// It also returns `end_position` which is the first position after `length`.
bool ReadCommonHeader(bool& is_64bit,
uint64_t& length,
uint16_t& version,
uint64_t& offset,
uint8_t& address_size,
uint64_t& end_position);
private:
// Generic helper to read an integral value. The size read is determined by
// the width of `value`
template <typename IntType>
bool ReadInt(IntType& value) {
return BufferedRead(&value, sizeof(value));
}
bool BufferedRead(void* buf, const size_t count);
// The buffer and counters
char buf_[256];
size_t unconsumed_amount_ = 0;
int cursor_in_buffer_ = 0;
// The file descriptor for the file being read.
const int fd_;
// The position of the next chunk to read.
uint64_t next_chunk_start_;
// The position of the last chunk read.
uint64_t last_chunk_start_;
};
} // namespace debug
} // namespace base
#endif
#endif // BASE_DEBUG_BUFFERED_DWARF_READER_H_