1*6777b538SAndroid Build Coastguard Worker // Copyright 2021 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_DEBUG_BUFFERED_DWARF_READER_H_ 6*6777b538SAndroid Build Coastguard Worker #define BASE_DEBUG_BUFFERED_DWARF_READER_H_ 7*6777b538SAndroid Build Coastguard Worker 8*6777b538SAndroid Build Coastguard Worker #include <cstddef> 9*6777b538SAndroid Build Coastguard Worker #include <cstdint> 10*6777b538SAndroid Build Coastguard Worker 11*6777b538SAndroid Build Coastguard Worker #ifdef USE_SYMBOLIZE 12*6777b538SAndroid Build Coastguard Worker 13*6777b538SAndroid Build Coastguard Worker namespace base { 14*6777b538SAndroid Build Coastguard Worker namespace debug { 15*6777b538SAndroid Build Coastguard Worker 16*6777b538SAndroid Build Coastguard Worker class BufferedDwarfReader { 17*6777b538SAndroid Build Coastguard Worker public: 18*6777b538SAndroid Build Coastguard Worker // Constructs a BufferedDwarfReader for a given `fd` starting 19*6777b538SAndroid Build Coastguard Worker // `position` bytes from the start of the file. 20*6777b538SAndroid Build Coastguard Worker // 21*6777b538SAndroid Build Coastguard Worker // BufferedDwarfReader does not affect the `fd` state so it is completely 22*6777b538SAndroid Build Coastguard Worker // okay to have multiple BufferedDwarfReader attached to one `fd` to act 23*6777b538SAndroid Build Coastguard Worker // as cursors into different parts of the file. 24*6777b538SAndroid Build Coastguard Worker BufferedDwarfReader(int fd, uint64_t position); 25*6777b538SAndroid Build Coastguard Worker 26*6777b538SAndroid Build Coastguard Worker // Gets and Sets the absolute position from the start of the file. position()27*6777b538SAndroid Build Coastguard Worker uint64_t position() const { return last_chunk_start_ + cursor_in_buffer_; } 28*6777b538SAndroid Build Coastguard Worker set_position(uint64_t position)29*6777b538SAndroid Build Coastguard Worker void set_position(uint64_t position) { 30*6777b538SAndroid Build Coastguard Worker last_chunk_start_ = next_chunk_start_ = position; 31*6777b538SAndroid Build Coastguard Worker 32*6777b538SAndroid Build Coastguard Worker // Invalidate buffer. 33*6777b538SAndroid Build Coastguard Worker cursor_in_buffer_ = 0; 34*6777b538SAndroid Build Coastguard Worker unconsumed_amount_ = 0; 35*6777b538SAndroid Build Coastguard Worker } 36*6777b538SAndroid Build Coastguard Worker ReadChar(char & value)37*6777b538SAndroid Build Coastguard Worker bool ReadChar(char& value) { return ReadInt(value); } ReadInt8(uint8_t & value)38*6777b538SAndroid Build Coastguard Worker bool ReadInt8(uint8_t& value) { return ReadInt(value); } ReadInt8(int8_t & value)39*6777b538SAndroid Build Coastguard Worker bool ReadInt8(int8_t& value) { return ReadInt(value); } ReadInt16(uint16_t & value)40*6777b538SAndroid Build Coastguard Worker bool ReadInt16(uint16_t& value) { return ReadInt(value); } ReadInt32(uint32_t & value)41*6777b538SAndroid Build Coastguard Worker bool ReadInt32(uint32_t& value) { return ReadInt(value); } ReadInt64(uint64_t & value)42*6777b538SAndroid Build Coastguard Worker bool ReadInt64(uint64_t& value) { return ReadInt(value); } 43*6777b538SAndroid Build Coastguard Worker 44*6777b538SAndroid Build Coastguard Worker // Helper to read a null-terminated sequence of bytes. 45*6777b538SAndroid Build Coastguard Worker // 46*6777b538SAndroid Build Coastguard Worker // Reads at most `max_position - position()` bytes. 47*6777b538SAndroid Build Coastguard Worker // 48*6777b538SAndroid Build Coastguard Worker // Returns the number of bytes written into `out`. 49*6777b538SAndroid Build Coastguard Worker // On a read error, the internal position of the BufferedDwarfReader may 50*6777b538SAndroid Build Coastguard Worker // still be advanced. This should only happen if something funky 51*6777b538SAndroid Build Coastguard Worker // happens at the OS layer at which case it's all best-effort 52*6777b538SAndroid Build Coastguard Worker // recovery afterwards anyways. 53*6777b538SAndroid Build Coastguard Worker size_t ReadCString(uint64_t max_position, char* out, size_t out_size); 54*6777b538SAndroid Build Coastguard Worker 55*6777b538SAndroid Build Coastguard Worker // Leb128 is a variable-length integer encoding format. This reads 56*6777b538SAndroid Build Coastguard Worker // both the signed and unsigned variants of this field. 57*6777b538SAndroid Build Coastguard Worker bool ReadLeb128(uint64_t& value); 58*6777b538SAndroid Build Coastguard Worker bool ReadLeb128(int64_t& value); 59*6777b538SAndroid Build Coastguard Worker 60*6777b538SAndroid Build Coastguard Worker // Headers in DWARF often start with a length field of type "initial length." 61*6777b538SAndroid Build Coastguard Worker // This is a variable-length field that both indicates if the entry is in 62*6777b538SAndroid Build Coastguard Worker // 32-bit or 64-bit DWARF format and the length of the entry. 63*6777b538SAndroid Build Coastguard Worker // 64*6777b538SAndroid Build Coastguard Worker // Note: is_64bit refers to the DWARF format, not the target architecture. 65*6777b538SAndroid Build Coastguard Worker // Most 64-bit binaries use 32-bit DWARF so is_64bit is frequently false. 66*6777b538SAndroid Build Coastguard Worker bool ReadInitialLength(bool& is_64bit, uint64_t& length); 67*6777b538SAndroid Build Coastguard Worker 68*6777b538SAndroid Build Coastguard Worker // Offsets inside DWARF are encoded at different sizes based on if it is 69*6777b538SAndroid Build Coastguard Worker // 32-bit DWARF or 64-bit DWARF. The value of `is_64bit` is usually retrieved 70*6777b538SAndroid Build Coastguard Worker // by a prior ReadInitialLength() call. 71*6777b538SAndroid Build Coastguard Worker bool ReadOffset(bool is_64bit, uint64_t& offset); 72*6777b538SAndroid Build Coastguard Worker 73*6777b538SAndroid Build Coastguard Worker // Addresses in DWARF are stored based on address size of the 74*6777b538SAndroid Build Coastguard Worker // target architecture. This helper reads the correct sized field 75*6777b538SAndroid Build Coastguard Worker // but then up-converts to a uint64_t type. It does an unsigned 76*6777b538SAndroid Build Coastguard Worker // extension so 0xffffffff on a 32-bit system will still read out 77*6777b538SAndroid Build Coastguard Worker // as 0xffffffff. 78*6777b538SAndroid Build Coastguard Worker bool ReadAddress(uint8_t address_size, uint64_t& address); 79*6777b538SAndroid Build Coastguard Worker 80*6777b538SAndroid Build Coastguard Worker // Many DWARF headers seem to start with 81*6777b538SAndroid Build Coastguard Worker // length (initial length) 82*6777b538SAndroid Build Coastguard Worker // version (ushort) 83*6777b538SAndroid Build Coastguard Worker // offset (32bit or 64-bit dependent on initial length parsing) 84*6777b538SAndroid Build Coastguard Worker // address_size (ubyte) 85*6777b538SAndroid Build Coastguard Worker // 86*6777b538SAndroid Build Coastguard Worker // The initial length also encodes if this is 32-bit or 64-bit dwarf. 87*6777b538SAndroid Build Coastguard Worker // This function parses the above sequence of fields. 88*6777b538SAndroid Build Coastguard Worker // 89*6777b538SAndroid Build Coastguard Worker // It also returns `end_position` which is the first position after `length`. 90*6777b538SAndroid Build Coastguard Worker bool ReadCommonHeader(bool& is_64bit, 91*6777b538SAndroid Build Coastguard Worker uint64_t& length, 92*6777b538SAndroid Build Coastguard Worker uint16_t& version, 93*6777b538SAndroid Build Coastguard Worker uint64_t& offset, 94*6777b538SAndroid Build Coastguard Worker uint8_t& address_size, 95*6777b538SAndroid Build Coastguard Worker uint64_t& end_position); 96*6777b538SAndroid Build Coastguard Worker 97*6777b538SAndroid Build Coastguard Worker private: 98*6777b538SAndroid Build Coastguard Worker // Generic helper to read an integral value. The size read is determined by 99*6777b538SAndroid Build Coastguard Worker // the width of `value` 100*6777b538SAndroid Build Coastguard Worker template <typename IntType> ReadInt(IntType & value)101*6777b538SAndroid Build Coastguard Worker bool ReadInt(IntType& value) { 102*6777b538SAndroid Build Coastguard Worker return BufferedRead(&value, sizeof(value)); 103*6777b538SAndroid Build Coastguard Worker } 104*6777b538SAndroid Build Coastguard Worker 105*6777b538SAndroid Build Coastguard Worker bool BufferedRead(void* buf, const size_t count); 106*6777b538SAndroid Build Coastguard Worker 107*6777b538SAndroid Build Coastguard Worker // The buffer and counters. In local testing, buffer sizes larger than 4096 108*6777b538SAndroid Build Coastguard Worker // bytes provides negligible benefit, while buffer sizes less than 4096 bytes 109*6777b538SAndroid Build Coastguard Worker // incur a significant performance penalty: compared to the original buffer 110*6777b538SAndroid Build Coastguard Worker // size of 256 bytes, 4096 bytes is 2x faster. 111*6777b538SAndroid Build Coastguard Worker char buf_[4096]; 112*6777b538SAndroid Build Coastguard Worker size_t unconsumed_amount_ = 0; 113*6777b538SAndroid Build Coastguard Worker size_t cursor_in_buffer_ = 0; 114*6777b538SAndroid Build Coastguard Worker 115*6777b538SAndroid Build Coastguard Worker // The file descriptor for the file being read. 116*6777b538SAndroid Build Coastguard Worker const int fd_; 117*6777b538SAndroid Build Coastguard Worker 118*6777b538SAndroid Build Coastguard Worker // The position of the next chunk to read. 119*6777b538SAndroid Build Coastguard Worker uint64_t next_chunk_start_; 120*6777b538SAndroid Build Coastguard Worker 121*6777b538SAndroid Build Coastguard Worker // The position of the last chunk read. 122*6777b538SAndroid Build Coastguard Worker uint64_t last_chunk_start_; 123*6777b538SAndroid Build Coastguard Worker }; 124*6777b538SAndroid Build Coastguard Worker 125*6777b538SAndroid Build Coastguard Worker } // namespace debug 126*6777b538SAndroid Build Coastguard Worker } // namespace base 127*6777b538SAndroid Build Coastguard Worker 128*6777b538SAndroid Build Coastguard Worker #endif 129*6777b538SAndroid Build Coastguard Worker 130*6777b538SAndroid Build Coastguard Worker #endif // BASE_DEBUG_BUFFERED_DWARF_READER_H_ 131