diff options
-rw-r--r-- | build/Android.gtest.mk | 1 | ||||
-rw-r--r-- | compiler/dwarf/debug_frame_opcode_writer.h | 282 | ||||
-rw-r--r-- | compiler/dwarf/debug_frame_writer.h | 96 | ||||
-rw-r--r-- | compiler/dwarf/debug_line_opcode_writer.h | 243 | ||||
-rw-r--r-- | compiler/dwarf/debug_line_writer.h | 87 | ||||
-rw-r--r-- | compiler/dwarf/dwarf_test.cc | 232 | ||||
-rw-r--r-- | compiler/dwarf/dwarf_test.h | 186 | ||||
-rw-r--r-- | compiler/dwarf/register.h | 58 | ||||
-rw-r--r-- | compiler/dwarf/writer.h | 159 | ||||
-rw-r--r-- | runtime/leb128.h | 44 |
10 files changed, 17 insertions, 1371 deletions
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk index 7a49062..91998fa 100644 --- a/build/Android.gtest.mk +++ b/build/Android.gtest.mk @@ -188,7 +188,6 @@ COMPILER_GTEST_COMMON_SRC_FILES := \ compiler/dex/local_value_numbering_test.cc \ compiler/dex/mir_graph_test.cc \ compiler/dex/mir_optimization_test.cc \ - compiler/dwarf/dwarf_test.cc \ compiler/driver/compiler_driver_test.cc \ compiler/elf_writer_test.cc \ compiler/image_test.cc \ diff --git a/compiler/dwarf/debug_frame_opcode_writer.h b/compiler/dwarf/debug_frame_opcode_writer.h deleted file mode 100644 index cc4ef8f..0000000 --- a/compiler/dwarf/debug_frame_opcode_writer.h +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * 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 ART_COMPILER_DWARF_DEBUG_FRAME_OPCODE_WRITER_H_ -#define ART_COMPILER_DWARF_DEBUG_FRAME_OPCODE_WRITER_H_ - -#include "dwarf.h" -#include "register.h" -#include "writer.h" - -namespace art { -namespace dwarf { - -// Writer for .debug_frame opcodes (DWARF-3). -// See the DWARF specification for the precise meaning of the opcodes. -// The writer is very light-weight, however it will do the following for you: -// * Choose the most compact encoding of a given opcode. -// * Keep track of current state and convert absolute values to deltas. -// * Divide by header-defined factors as appropriate. -template<typename Allocator = std::allocator<uint8_t> > -class DebugFrameOpCodeWriter : private Writer<Allocator> { - public: - // To save space, DWARF divides most offsets by header-defined factors. - // They are used in integer divisions, so we make them constants. - // We usually subtract from stack base pointer, so making the factor - // negative makes the encoded values positive and thus easier to encode. - static constexpr int kDataAlignmentFactor = -4; - static constexpr int kCodeAlignmentFactor = 1; - - // Explicitely advance the program counter to given location. - void AdvancePC(int absolute_pc) { - DCHECK_GE(absolute_pc, current_pc_); - int delta = FactorCodeOffset(absolute_pc - current_pc_); - if (delta != 0) { - if (delta <= 0x3F) { - this->PushUint8(DW_CFA_advance_loc | delta); - } else if (delta <= UINT8_MAX) { - this->PushUint8(DW_CFA_advance_loc1); - this->PushUint8(delta); - } else if (delta <= UINT16_MAX) { - this->PushUint8(DW_CFA_advance_loc2); - this->PushUint16(delta); - } else { - this->PushUint8(DW_CFA_advance_loc4); - this->PushUint32(delta); - } - } - current_pc_ = absolute_pc; - } - - // Override this method to automatically advance the PC before each opcode. - virtual void ImplicitlyAdvancePC() { } - - // Common alias in assemblers - spill relative to current stack pointer. - void RelOffset(Reg reg, int offset) { - Offset(reg, offset - current_cfa_offset_); - } - - // Common alias in assemblers - increase stack frame size. - void AdjustCFAOffset(int delta) { - DefCFAOffset(current_cfa_offset_ + delta); - } - - // Custom alias - spill many registers based on bitmask. - void RelOffsetForMany(Reg reg_base, int offset, uint32_t reg_mask, - int reg_size) { - DCHECK(reg_size == 4 || reg_size == 8); - for (int i = 0; reg_mask != 0u; reg_mask >>= 1, i++) { - if ((reg_mask & 1) != 0u) { - RelOffset(Reg(reg_base.num() + i), offset); - offset += reg_size; - } - } - } - - // Custom alias - unspill many registers based on bitmask. - void RestoreMany(Reg reg_base, uint32_t reg_mask) { - for (int i = 0; reg_mask != 0u; reg_mask >>= 1, i++) { - if ((reg_mask & 1) != 0u) { - Restore(Reg(reg_base.num() + i)); - } - } - } - - void Nop() { - this->PushUint8(DW_CFA_nop); - } - - void Offset(Reg reg, int offset) { - ImplicitlyAdvancePC(); - int factored_offset = FactorDataOffset(offset); // May change sign. - if (factored_offset >= 0) { - if (0 <= reg.num() && reg.num() <= 0x3F) { - this->PushUint8(DW_CFA_offset | reg.num()); - this->PushUleb128(factored_offset); - } else { - this->PushUint8(DW_CFA_offset_extended); - this->PushUleb128(reg.num()); - this->PushUleb128(factored_offset); - } - } else { - uses_dwarf3_features_ = true; - this->PushUint8(DW_CFA_offset_extended_sf); - this->PushUleb128(reg.num()); - this->PushSleb128(factored_offset); - } - } - - void Restore(Reg reg) { - ImplicitlyAdvancePC(); - if (0 <= reg.num() && reg.num() <= 0x3F) { - this->PushUint8(DW_CFA_restore | reg.num()); - } else { - this->PushUint8(DW_CFA_restore_extended); - this->PushUleb128(reg.num()); - } - } - - void Undefined(Reg reg) { - ImplicitlyAdvancePC(); - this->PushUint8(DW_CFA_undefined); - this->PushUleb128(reg.num()); - } - - void SameValue(Reg reg) { - ImplicitlyAdvancePC(); - this->PushUint8(DW_CFA_same_value); - this->PushUleb128(reg.num()); - } - - // The previous value of "reg" is stored in register "new_reg". - void Register(Reg reg, Reg new_reg) { - ImplicitlyAdvancePC(); - this->PushUint8(DW_CFA_register); - this->PushUleb128(reg.num()); - this->PushUleb128(new_reg.num()); - } - - void RememberState() { - // Note that we do not need to advance the PC. - this->PushUint8(DW_CFA_remember_state); - } - - void RestoreState() { - ImplicitlyAdvancePC(); - this->PushUint8(DW_CFA_restore_state); - } - - void DefCFA(Reg reg, int offset) { - ImplicitlyAdvancePC(); - if (offset >= 0) { - this->PushUint8(DW_CFA_def_cfa); - this->PushUleb128(reg.num()); - this->PushUleb128(offset); // Non-factored. - } else { - uses_dwarf3_features_ = true; - this->PushUint8(DW_CFA_def_cfa_sf); - this->PushUleb128(reg.num()); - this->PushSleb128(FactorDataOffset(offset)); - } - current_cfa_offset_ = offset; - } - - void DefCFARegister(Reg reg) { - ImplicitlyAdvancePC(); - this->PushUint8(DW_CFA_def_cfa_register); - this->PushUleb128(reg.num()); - } - - void DefCFAOffset(int offset) { - if (current_cfa_offset_ != offset) { - ImplicitlyAdvancePC(); - if (offset >= 0) { - this->PushUint8(DW_CFA_def_cfa_offset); - this->PushUleb128(offset); // Non-factored. - } else { - uses_dwarf3_features_ = true; - this->PushUint8(DW_CFA_def_cfa_offset_sf); - this->PushSleb128(FactorDataOffset(offset)); - } - current_cfa_offset_ = offset; - } - } - - void ValOffset(Reg reg, int offset) { - ImplicitlyAdvancePC(); - uses_dwarf3_features_ = true; - int factored_offset = FactorDataOffset(offset); // May change sign. - if (factored_offset >= 0) { - this->PushUint8(DW_CFA_val_offset); - this->PushUleb128(reg.num()); - this->PushUleb128(factored_offset); - } else { - this->PushUint8(DW_CFA_val_offset_sf); - this->PushUleb128(reg.num()); - this->PushSleb128(factored_offset); - } - } - - void DefCFAExpression(void* expr, int expr_size) { - ImplicitlyAdvancePC(); - uses_dwarf3_features_ = true; - this->PushUint8(DW_CFA_def_cfa_expression); - this->PushUleb128(expr_size); - this->PushData(expr, expr_size); - } - - void Expression(Reg reg, void* expr, int expr_size) { - ImplicitlyAdvancePC(); - uses_dwarf3_features_ = true; - this->PushUint8(DW_CFA_expression); - this->PushUleb128(reg.num()); - this->PushUleb128(expr_size); - this->PushData(expr, expr_size); - } - - void ValExpression(Reg reg, void* expr, int expr_size) { - ImplicitlyAdvancePC(); - uses_dwarf3_features_ = true; - this->PushUint8(DW_CFA_val_expression); - this->PushUleb128(reg.num()); - this->PushUleb128(expr_size); - this->PushData(expr, expr_size); - } - - int GetCurrentCFAOffset() const { - return current_cfa_offset_; - } - - void SetCurrentCFAOffset(int offset) { - current_cfa_offset_ = offset; - } - - using Writer<Allocator>::data; - - DebugFrameOpCodeWriter(const Allocator& alloc = Allocator()) - : Writer<Allocator>(&opcodes_), - opcodes_(alloc), - current_cfa_offset_(0), - current_pc_(0), - uses_dwarf3_features_(false) { - } - - virtual ~DebugFrameOpCodeWriter() { } - - protected: - int FactorDataOffset(int offset) const { - DCHECK_EQ(offset % kDataAlignmentFactor, 0); - return offset / kDataAlignmentFactor; - } - - int FactorCodeOffset(int offset) const { - DCHECK_EQ(offset % kCodeAlignmentFactor, 0); - return offset / kCodeAlignmentFactor; - } - - std::vector<uint8_t, Allocator> opcodes_; - int current_cfa_offset_; - int current_pc_; - bool uses_dwarf3_features_; - - private: - DISALLOW_COPY_AND_ASSIGN(DebugFrameOpCodeWriter); -}; - -} // namespace dwarf -} // namespace art - -#endif // ART_COMPILER_DWARF_DEBUG_FRAME_OPCODE_WRITER_H_ diff --git a/compiler/dwarf/debug_frame_writer.h b/compiler/dwarf/debug_frame_writer.h deleted file mode 100644 index 6de45f5..0000000 --- a/compiler/dwarf/debug_frame_writer.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * 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 ART_COMPILER_DWARF_DEBUG_FRAME_WRITER_H_ -#define ART_COMPILER_DWARF_DEBUG_FRAME_WRITER_H_ - -#include "debug_frame_opcode_writer.h" -#include "dwarf.h" -#include "writer.h" - -namespace art { -namespace dwarf { - -// Writer for the .eh_frame section (which extends .debug_frame specification). -template<typename Allocator = std::allocator<uint8_t>> -class DebugFrameWriter FINAL : private Writer<Allocator> { - public: - void WriteCIE(Reg return_address_register, - const uint8_t* initial_opcodes, - int initial_opcodes_size) { - DCHECK(cie_header_start_ == ~0u); - cie_header_start_ = this->data()->size(); - this->PushUint32(0); // Length placeholder. - this->PushUint32(0); // CIE id. - this->PushUint8(1); // Version. - this->PushString("zR"); - this->PushUleb128(DebugFrameOpCodeWriter<Allocator>::kCodeAlignmentFactor); - this->PushSleb128(DebugFrameOpCodeWriter<Allocator>::kDataAlignmentFactor); - this->PushUleb128(return_address_register.num()); // ubyte in DWARF2. - this->PushUleb128(1); // z: Augmentation data size. - if (use_64bit_address_) { - this->PushUint8(0x04); // R: ((DW_EH_PE_absptr << 4) | DW_EH_PE_udata8). - } else { - this->PushUint8(0x03); // R: ((DW_EH_PE_absptr << 4) | DW_EH_PE_udata4). - } - this->PushData(initial_opcodes, initial_opcodes_size); - this->Pad(use_64bit_address_ ? 8 : 4); - this->UpdateUint32(cie_header_start_, this->data()->size() - cie_header_start_ - 4); - } - - void WriteCIE(Reg return_address_register, - const DebugFrameOpCodeWriter<Allocator>& opcodes) { - WriteCIE(return_address_register, opcodes.data()->data(), opcodes.data()->size()); - } - - void WriteFDE(uint64_t initial_address, - uint64_t address_range, - const uint8_t* unwind_opcodes, - int unwind_opcodes_size) { - DCHECK(cie_header_start_ != ~0u); - size_t fde_header_start = this->data()->size(); - this->PushUint32(0); // Length placeholder. - this->PushUint32(this->data()->size() - cie_header_start_); // 'CIE_pointer' - if (use_64bit_address_) { - this->PushUint64(initial_address); - this->PushUint64(address_range); - } else { - this->PushUint32(initial_address); - this->PushUint32(address_range); - } - this->PushUleb128(0); // Augmentation data size. - this->PushData(unwind_opcodes, unwind_opcodes_size); - this->Pad(use_64bit_address_ ? 8 : 4); - this->UpdateUint32(fde_header_start, this->data()->size() - fde_header_start - 4); - } - - DebugFrameWriter(std::vector<uint8_t, Allocator>* buffer, bool use_64bit_address) - : Writer<Allocator>(buffer), - use_64bit_address_(use_64bit_address), - cie_header_start_(~0u) { - } - - private: - bool use_64bit_address_; - size_t cie_header_start_; - - DISALLOW_COPY_AND_ASSIGN(DebugFrameWriter); -}; - -} // namespace dwarf -} // namespace art - -#endif // ART_COMPILER_DWARF_DEBUG_FRAME_WRITER_H_ diff --git a/compiler/dwarf/debug_line_opcode_writer.h b/compiler/dwarf/debug_line_opcode_writer.h deleted file mode 100644 index f34acee..0000000 --- a/compiler/dwarf/debug_line_opcode_writer.h +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * 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 ART_COMPILER_DWARF_DEBUG_LINE_OPCODE_WRITER_H_ -#define ART_COMPILER_DWARF_DEBUG_LINE_OPCODE_WRITER_H_ - -#include "dwarf.h" -#include "writer.h" - -namespace art { -namespace dwarf { - -// Writer for the .debug_line opcodes (DWARF-3). -// The writer is very light-weight, however it will do the following for you: -// * Choose the most compact encoding of a given opcode. -// * Keep track of current state and convert absolute values to deltas. -// * Divide by header-defined factors as appropriate. -template<typename Allocator = std::allocator<uint8_t>> -class DebugLineOpCodeWriter FINAL : private Writer<Allocator> { - public: - static constexpr int kOpcodeBase = 13; - static constexpr bool kDefaultIsStmt = true; - static constexpr int kLineBase = -5; - static constexpr int kLineRange = 14; - - void AddRow() { - this->PushUint8(DW_LNS_copy); - } - - void AdvancePC(uint64_t absolute_address) { - DCHECK_NE(current_address_, 0u); // Use SetAddress for the first advance. - DCHECK_GE(absolute_address, current_address_); - if (absolute_address != current_address_) { - uint64_t delta = FactorCodeOffset(absolute_address - current_address_); - if (delta <= INT32_MAX) { - this->PushUint8(DW_LNS_advance_pc); - this->PushUleb128(static_cast<int>(delta)); - current_address_ = absolute_address; - } else { - SetAddress(absolute_address); - } - } - } - - void AdvanceLine(int absolute_line) { - int delta = absolute_line - current_line_; - if (delta != 0) { - this->PushUint8(DW_LNS_advance_line); - this->PushSleb128(delta); - current_line_ = absolute_line; - } - } - - void SetFile(int file) { - if (current_file_ != file) { - this->PushUint8(DW_LNS_set_file); - this->PushUleb128(file); - current_file_ = file; - } - } - - void SetColumn(int column) { - this->PushUint8(DW_LNS_set_column); - this->PushUleb128(column); - } - - void NegateStmt() { - this->PushUint8(DW_LNS_negate_stmt); - } - - void SetBasicBlock() { - this->PushUint8(DW_LNS_set_basic_block); - } - - void SetPrologueEnd() { - uses_dwarf3_features_ = true; - this->PushUint8(DW_LNS_set_prologue_end); - } - - void SetEpilogueBegin() { - uses_dwarf3_features_ = true; - this->PushUint8(DW_LNS_set_epilogue_begin); - } - - void SetISA(int isa) { - uses_dwarf3_features_ = true; - this->PushUint8(DW_LNS_set_isa); - this->PushUleb128(isa); - } - - void EndSequence() { - this->PushUint8(0); - this->PushUleb128(1); - this->PushUint8(DW_LNE_end_sequence); - current_address_ = 0; - current_file_ = 1; - current_line_ = 1; - } - - // Uncoditionally set address using the long encoding. - // This gives the linker opportunity to relocate the address. - void SetAddress(uint64_t absolute_address) { - DCHECK_GE(absolute_address, current_address_); - FactorCodeOffset(absolute_address); // Check if it is factorable. - this->PushUint8(0); - if (use_64bit_address_) { - this->PushUleb128(1 + 8); - this->PushUint8(DW_LNE_set_address); - this->PushUint64(absolute_address); - } else { - this->PushUleb128(1 + 4); - this->PushUint8(DW_LNE_set_address); - this->PushUint32(absolute_address); - } - current_address_ = absolute_address; - } - - void DefineFile(const char* filename, - int directory_index, - int modification_time, - int file_size) { - int size = 1 + - strlen(filename) + 1 + - UnsignedLeb128Size(directory_index) + - UnsignedLeb128Size(modification_time) + - UnsignedLeb128Size(file_size); - this->PushUint8(0); - this->PushUleb128(size); - size_t start = data()->size(); - this->PushUint8(DW_LNE_define_file); - this->PushString(filename); - this->PushUleb128(directory_index); - this->PushUleb128(modification_time); - this->PushUleb128(file_size); - DCHECK_EQ(start + size, data()->size()); - } - - // Compact address and line opcode. - void AddRow(uint64_t absolute_address, int absolute_line) { - DCHECK_GE(absolute_address, current_address_); - - // If the address is definitely too far, use the long encoding. - uint64_t delta_address = FactorCodeOffset(absolute_address - current_address_); - if (delta_address > UINT8_MAX) { - AdvancePC(absolute_address); - delta_address = 0; - } - - // If the line is definitely too far, use the long encoding. - int delta_line = absolute_line - current_line_; - if (!(kLineBase <= delta_line && delta_line < kLineBase + kLineRange)) { - AdvanceLine(absolute_line); - delta_line = 0; - } - - // Both address and line should be reasonable now. Use the short encoding. - int opcode = kOpcodeBase + (delta_line - kLineBase) + - (static_cast<int>(delta_address) * kLineRange); - if (opcode > UINT8_MAX) { - // If the address is still too far, try to increment it by const amount. - int const_advance = (0xFF - kOpcodeBase) / kLineRange; - opcode -= (kLineRange * const_advance); - if (opcode <= UINT8_MAX) { - this->PushUint8(DW_LNS_const_add_pc); - } else { - // Give up and use long encoding for address. - AdvancePC(absolute_address); - // Still use the opcode to do line advance and copy. - opcode = kOpcodeBase + (delta_line - kLineBase); - } - } - DCHECK(kOpcodeBase <= opcode && opcode <= 0xFF); - this->PushUint8(opcode); // Special opcode. - current_line_ = absolute_line; - current_address_ = absolute_address; - } - - int GetCodeFactorBits() const { - return code_factor_bits_; - } - - uint64_t CurrentAddress() const { - return current_address_; - } - - int CurrentFile() const { - return current_file_; - } - - int CurrentLine() const { - return current_line_; - } - - using Writer<Allocator>::data; - - DebugLineOpCodeWriter(bool use64bitAddress, - int codeFactorBits, - const Allocator& alloc = Allocator()) - : Writer<Allocator>(&opcodes_), - opcodes_(alloc), - uses_dwarf3_features_(false), - use_64bit_address_(use64bitAddress), - code_factor_bits_(codeFactorBits), - current_address_(0), - current_file_(1), - current_line_(1) { - } - - private: - uint64_t FactorCodeOffset(uint64_t offset) const { - DCHECK_GE(code_factor_bits_, 0); - DCHECK_EQ((offset >> code_factor_bits_) << code_factor_bits_, offset); - return offset >> code_factor_bits_; - } - - std::vector<uint8_t, Allocator> opcodes_; - bool uses_dwarf3_features_; - bool use_64bit_address_; - int code_factor_bits_; - uint64_t current_address_; - int current_file_; - int current_line_; - - DISALLOW_COPY_AND_ASSIGN(DebugLineOpCodeWriter); -}; - -} // namespace dwarf -} // namespace art - -#endif // ART_COMPILER_DWARF_DEBUG_LINE_OPCODE_WRITER_H_ diff --git a/compiler/dwarf/debug_line_writer.h b/compiler/dwarf/debug_line_writer.h deleted file mode 100644 index 4b7d8d9..0000000 --- a/compiler/dwarf/debug_line_writer.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * 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 ART_COMPILER_DWARF_DEBUG_LINE_WRITER_H_ -#define ART_COMPILER_DWARF_DEBUG_LINE_WRITER_H_ - -#include "debug_line_opcode_writer.h" -#include "dwarf.h" -#include "writer.h" -#include <string> - -namespace art { -namespace dwarf { - -// Writer for the .debug_line section (DWARF-3). -template<typename Allocator = std::allocator<uint8_t>> -class DebugLineWriter FINAL : private Writer<Allocator> { - public: - struct FileEntry { - std::string file_name; - int directory_index; - int modification_time; - int file_size; - }; - - void WriteTable(const std::vector<std::string>& include_directories, - const std::vector<FileEntry>& files, - const DebugLineOpCodeWriter<Allocator>& opcodes) { - size_t header_start = this->data()->size(); - this->PushUint32(0); // Section-length placeholder. - // Claim DWARF-2 version even though we use some DWARF-3 features. - // DWARF-2 consumers will ignore the unknown opcodes. - // This is what clang currently does. - this->PushUint16(2); // .debug_line version. - size_t header_length_pos = this->data()->size(); - this->PushUint32(0); // Header-length placeholder. - this->PushUint8(1 << opcodes.GetCodeFactorBits()); - this->PushUint8(DebugLineOpCodeWriter<Allocator>::kDefaultIsStmt ? 1 : 0); - this->PushInt8(DebugLineOpCodeWriter<Allocator>::kLineBase); - this->PushUint8(DebugLineOpCodeWriter<Allocator>::kLineRange); - this->PushUint8(DebugLineOpCodeWriter<Allocator>::kOpcodeBase); - static const int opcode_lengths[DebugLineOpCodeWriter<Allocator>::kOpcodeBase] = { - 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 }; - for (int i = 1; i < DebugLineOpCodeWriter<Allocator>::kOpcodeBase; i++) { - this->PushUint8(opcode_lengths[i]); - } - for (const std::string& directory : include_directories) { - this->PushData(directory.data(), directory.size() + 1); - } - this->PushUint8(0); // Terminate include_directories list. - for (const FileEntry& file : files) { - this->PushData(file.file_name.data(), file.file_name.size() + 1); - this->PushUleb128(file.directory_index); - this->PushUleb128(file.modification_time); - this->PushUleb128(file.file_size); - } - this->PushUint8(0); // Terminate file list. - this->UpdateUint32(header_length_pos, this->data()->size() - header_length_pos - 4); - this->PushData(opcodes.data()->data(), opcodes.data()->size()); - this->UpdateUint32(header_start, this->data()->size() - header_start - 4); - } - - explicit DebugLineWriter(std::vector<uint8_t, Allocator>* buffer) - : Writer<Allocator>(buffer) { - } - - private: - DISALLOW_COPY_AND_ASSIGN(DebugLineWriter); -}; - -} // namespace dwarf -} // namespace art - -#endif // ART_COMPILER_DWARF_DEBUG_LINE_WRITER_H_ diff --git a/compiler/dwarf/dwarf_test.cc b/compiler/dwarf/dwarf_test.cc deleted file mode 100644 index 0456e85..0000000 --- a/compiler/dwarf/dwarf_test.cc +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * 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. - */ - -#include "dwarf_test.h" - -#include "dwarf/debug_frame_opcode_writer.h" -#include "dwarf/debug_frame_writer.h" -#include "dwarf/debug_line_opcode_writer.h" -#include "dwarf/debug_line_writer.h" -#include "gtest/gtest.h" - -namespace art { -namespace dwarf { - -// Run the tests only on host since we need objdump. -#ifndef HAVE_ANDROID_OS - -TEST_F(DwarfTest, DebugFrame) { - const bool is64bit = false; - - // Pick offset value which would catch Uleb vs Sleb errors. - const int offset = 40000; - ASSERT_EQ(UnsignedLeb128Size(offset / 4), 2u); - ASSERT_EQ(SignedLeb128Size(offset / 4), 3u); - DW_CHECK("Data alignment factor: -4"); - const Reg reg(6); - - // Test the opcodes in the order mentioned in the spec. - // There are usually several encoding variations of each opcode. - DebugFrameOpCodeWriter<> opcodes; - DW_CHECK("FDE"); - int pc = 0; - for (int i : {0, 1, 0x3F, 0x40, 0xFF, 0x100, 0xFFFF, 0x10000}) { - pc += i; - opcodes.AdvancePC(pc); - } - DW_CHECK_NEXT("DW_CFA_advance_loc: 1 to 01000001"); - DW_CHECK_NEXT("DW_CFA_advance_loc: 63 to 01000040"); - DW_CHECK_NEXT("DW_CFA_advance_loc1: 64 to 01000080"); - DW_CHECK_NEXT("DW_CFA_advance_loc1: 255 to 0100017f"); - DW_CHECK_NEXT("DW_CFA_advance_loc2: 256 to 0100027f"); - DW_CHECK_NEXT("DW_CFA_advance_loc2: 65535 to 0101027e"); - DW_CHECK_NEXT("DW_CFA_advance_loc4: 65536 to 0102027e"); - opcodes.DefCFA(reg, offset); - DW_CHECK_NEXT("DW_CFA_def_cfa: r6 (esi) ofs 40000"); - opcodes.DefCFA(reg, -offset); - DW_CHECK_NEXT("DW_CFA_def_cfa_sf: r6 (esi) ofs -40000"); - opcodes.DefCFARegister(reg); - DW_CHECK_NEXT("DW_CFA_def_cfa_register: r6 (esi)"); - opcodes.DefCFAOffset(offset); - DW_CHECK_NEXT("DW_CFA_def_cfa_offset: 40000"); - opcodes.DefCFAOffset(-offset); - DW_CHECK_NEXT("DW_CFA_def_cfa_offset_sf: -40000"); - uint8_t expr[] = { 0 }; - opcodes.DefCFAExpression(expr, arraysize(expr)); - DW_CHECK_NEXT("DW_CFA_def_cfa_expression"); - opcodes.Undefined(reg); - DW_CHECK_NEXT("DW_CFA_undefined: r6 (esi)"); - opcodes.SameValue(reg); - DW_CHECK_NEXT("DW_CFA_same_value: r6 (esi)"); - opcodes.Offset(Reg(0x3F), -offset); - DW_CHECK_NEXT("DW_CFA_offset: r63 at cfa-40000"); - opcodes.Offset(Reg(0x40), -offset); - DW_CHECK_NEXT("DW_CFA_offset_extended: r64 at cfa-40000"); - opcodes.Offset(Reg(0x40), offset); - DW_CHECK_NEXT("DW_CFA_offset_extended_sf: r64 at cfa+40000"); - opcodes.ValOffset(reg, -offset); - DW_CHECK_NEXT("DW_CFA_val_offset: r6 (esi) at cfa-40000"); - opcodes.ValOffset(reg, offset); - DW_CHECK_NEXT("DW_CFA_val_offset_sf: r6 (esi) at cfa+40000"); - opcodes.Register(reg, Reg(1)); - DW_CHECK_NEXT("DW_CFA_register: r6 (esi) in r1 (ecx)"); - opcodes.Expression(reg, expr, arraysize(expr)); - DW_CHECK_NEXT("DW_CFA_expression: r6 (esi)"); - opcodes.ValExpression(reg, expr, arraysize(expr)); - DW_CHECK_NEXT("DW_CFA_val_expression: r6 (esi)"); - // Bad register likely means that it does not exist on x86, - // but we want to test high register numbers anyway. - opcodes.Restore(Reg(0x3F)); - DW_CHECK_NEXT("DW_CFA_restore: bad register: r63"); - opcodes.Restore(Reg(0x40)); - DW_CHECK_NEXT("DW_CFA_restore_extended: bad register: r64"); - opcodes.Restore(reg); - DW_CHECK_NEXT("DW_CFA_restore: r6 (esi)"); - opcodes.RememberState(); - DW_CHECK_NEXT("DW_CFA_remember_state"); - opcodes.RestoreState(); - DW_CHECK_NEXT("DW_CFA_restore_state"); - opcodes.Nop(); - DW_CHECK_NEXT("DW_CFA_nop"); - - // Also test helpers. - opcodes.DefCFA(Reg(4), 100); // ESP - DW_CHECK_NEXT("DW_CFA_def_cfa: r4 (esp) ofs 100"); - opcodes.AdjustCFAOffset(8); - DW_CHECK_NEXT("DW_CFA_def_cfa_offset: 108"); - opcodes.RelOffset(Reg(0), 0); // push R0 - DW_CHECK_NEXT("DW_CFA_offset: r0 (eax) at cfa-108"); - opcodes.RelOffset(Reg(1), 4); // push R1 - DW_CHECK_NEXT("DW_CFA_offset: r1 (ecx) at cfa-104"); - opcodes.RelOffsetForMany(Reg(2), 8, 1 | (1 << 3), 4); // push R2 and R5 - DW_CHECK_NEXT("DW_CFA_offset: r2 (edx) at cfa-100"); - DW_CHECK_NEXT("DW_CFA_offset: r5 (ebp) at cfa-96"); - opcodes.RestoreMany(Reg(2), 1 | (1 << 3)); // pop R2 and R5 - DW_CHECK_NEXT("DW_CFA_restore: r2 (edx)"); - DW_CHECK_NEXT("DW_CFA_restore: r5 (ebp)"); - - DebugFrameWriter<> eh_frame(&eh_frame_data_, is64bit); - DebugFrameOpCodeWriter<> initial_opcodes; - eh_frame.WriteCIE(Reg(is64bit ? 16 : 8), // Return address register. - initial_opcodes); // Initial opcodes. - eh_frame.WriteFDE(0x01000000, 0x01000000, - opcodes.data()->data(), opcodes.data()->size()); - CheckObjdumpOutput(is64bit, "-W"); -} - -TEST_F(DwarfTest, DebugFrame64) { - const bool is64bit = true; - DebugFrameWriter<> eh_frame(&eh_frame_data_, is64bit); - DebugFrameOpCodeWriter<> no_opcodes; - eh_frame.WriteCIE(Reg(16), no_opcodes); - eh_frame.WriteFDE(0x0100000000000000, 0x0200000000000000, - no_opcodes.data()->data(), no_opcodes.data()->size()); - DW_CHECK("FDE cie=00000000 pc=0100000000000000..0300000000000000"); - CheckObjdumpOutput(is64bit, "-W"); -} - -TEST_F(DwarfTest, DebugLine) { - const bool is64bit = false; - const int code_factor_bits = 1; - DebugLineOpCodeWriter<> opcodes(is64bit, code_factor_bits); - - std::vector<std::string> include_directories; - include_directories.push_back("/path/to/source"); - DW_CHECK("1\t/path/to/source"); - - std::vector<DebugLineWriter<>::FileEntry> files { - { "file0.c", 0, 1000, 2000 }, - { "file1.c", 1, 1000, 2000 }, - { "file2.c", 1, 1000, 2000 }, - }; - DW_CHECK("1\t0\t1000\t2000\tfile0.c"); - DW_CHECK_NEXT("2\t1\t1000\t2000\tfile1.c"); - DW_CHECK_NEXT("3\t1\t1000\t2000\tfile2.c"); - - DW_CHECK("Line Number Statements"); - opcodes.SetAddress(0x01000000); - DW_CHECK_NEXT("Extended opcode 2: set Address to 0x1000000"); - opcodes.AddRow(); - DW_CHECK_NEXT("Copy"); - opcodes.AdvancePC(0x01000100); - DW_CHECK_NEXT("Advance PC by 256 to 0x1000100"); - opcodes.SetFile(2); - DW_CHECK_NEXT("Set File Name to entry 2 in the File Name Table"); - opcodes.AdvanceLine(3); - DW_CHECK_NEXT("Advance Line by 2 to 3"); - opcodes.SetColumn(4); - DW_CHECK_NEXT("Set column to 4"); - opcodes.NegateStmt(); - DW_CHECK_NEXT("Set is_stmt to 0"); - opcodes.SetBasicBlock(); - DW_CHECK_NEXT("Set basic block"); - opcodes.SetPrologueEnd(); - DW_CHECK_NEXT("Set prologue_end to true"); - opcodes.SetEpilogueBegin(); - DW_CHECK_NEXT("Set epilogue_begin to true"); - opcodes.SetISA(5); - DW_CHECK_NEXT("Set ISA to 5"); - opcodes.EndSequence(); - DW_CHECK_NEXT("Extended opcode 1: End of Sequence"); - // TODO: objdump says this opcode has invalid length. I am not convinced. - // opcodes.DefineFile("file.c", 0, 1000, 2000); - // DW_CHECK_NEXT("Extended opcode 3: define new File Table entry"); - // DW_CHECK_NEXT("1\t0\t1000\t2000\tfile.c"); - - DebugLineWriter<> debug_line(&debug_line_data_); - debug_line.WriteTable(include_directories, files, opcodes); - CheckObjdumpOutput(is64bit, "-W"); -} - -// DWARF has special one byte codes which advance PC and line at the same time. -TEST_F(DwarfTest, DebugLineSpecialOpcodes) { - const bool is64bit = false; - const int code_factor_bits = 1; - uint32_t pc = 0x01000000; - int line = 1; - DebugLineOpCodeWriter<> opcodes(is64bit, code_factor_bits); - opcodes.SetAddress(pc); - size_t num_rows = 0; - DW_CHECK("Line Number Statements:"); - DW_CHECK("Special opcode"); - DW_CHECK("Advance PC by constant"); - DW_CHECK("Decoded dump of debug contents of section .debug_line:"); - for (int addr_delta = 0; addr_delta < 80; addr_delta += 2) { - for (int line_delta = 16; line_delta >= -16; --line_delta) { - pc += addr_delta; - line += line_delta; - opcodes.AddRow(pc, line); - num_rows++; - ASSERT_EQ(opcodes.CurrentAddress(), pc); - ASSERT_EQ(opcodes.CurrentLine(), line); - char expected[1024]; - sprintf(expected, "%i 0x%x", line, pc); - DW_CHECK_NEXT(expected); - } - } - EXPECT_LT(opcodes.data()->size(), num_rows * 3); - - std::vector<std::string> directories; - std::vector<DebugLineWriter<>::FileEntry> files; - DebugLineWriter<> debug_line(&debug_line_data_); - debug_line.WriteTable(directories, files, opcodes); - CheckObjdumpOutput(is64bit, "-W -WL"); -} - -#endif // HAVE_ANDROID_OS - -} // namespace dwarf -} // namespace art diff --git a/compiler/dwarf/dwarf_test.h b/compiler/dwarf/dwarf_test.h deleted file mode 100644 index d4e83f8..0000000 --- a/compiler/dwarf/dwarf_test.h +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * 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 ART_COMPILER_DWARF_DWARF_TEST_H_ -#define ART_COMPILER_DWARF_DWARF_TEST_H_ - -#include <cstring> -#include <memory> -#include <stdio.h> -#include <string> - -#include "utils.h" -#include "base/unix_file/fd_file.h" -#include "common_runtime_test.h" -#include "elf_builder.h" -#include "gtest/gtest.h" -#include "os.h" - -namespace art { -namespace dwarf { - -#define DW_CHECK(substring) Check(substring, false, __FILE__, __LINE__) -#define DW_CHECK_NEXT(substring) Check(substring, true, __FILE__, __LINE__) - -class DwarfTest : public CommonRuntimeTest { - public: - static constexpr bool kPrintObjdumpOutput = false; // debugging. - - struct ExpectedLine { - std::string substring; - bool next; - const char* at_file; - int at_line; - }; - - // Check that the objdump output contains given output. - // If next is true, it must be the next line. Otherwise lines are skipped. - void Check(const char* substr, bool next, const char* at_file, int at_line) { - expected_lines_.push_back(ExpectedLine {substr, next, at_file, at_line}); - } - - // Pretty-print the generated DWARF data using objdump. - template<typename Elf_Word, typename Elf_Sword, typename Elf_Addr, typename Elf_Dyn, - typename Elf_Sym, typename Elf_Ehdr, typename Elf_Phdr, typename Elf_Shdr> - std::vector<std::string> Objdump(bool is64bit, const char* args) { - // Write simple elf file with just the DWARF sections. - class NoCode : public CodeOutput { - virtual void SetCodeOffset(size_t) { } - virtual bool Write(OutputStream*) { return true; } - } code; - ScratchFile file; - InstructionSet isa = is64bit ? kX86_64 : kX86; - ElfBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn, - Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr> builder( - &code, file.GetFile(), isa, 0, 0, 0, 0, 0, 0, false, false); - typedef ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> Section; - if (!debug_info_data_.empty()) { - Section debug_info(".debug_info", SHT_PROGBITS, 0, nullptr, 0, 1, 0); - debug_info.SetBuffer(debug_info_data_); - builder.RegisterRawSection(debug_info); - } - if (!debug_abbrev_data_.empty()) { - Section debug_abbrev(".debug_abbrev", SHT_PROGBITS, 0, nullptr, 0, 1, 0); - debug_abbrev.SetBuffer(debug_abbrev_data_); - builder.RegisterRawSection(debug_abbrev); - } - if (!debug_str_data_.empty()) { - Section debug_str(".debug_str", SHT_PROGBITS, 0, nullptr, 0, 1, 0); - debug_str.SetBuffer(debug_str_data_); - builder.RegisterRawSection(debug_str); - } - if (!debug_line_data_.empty()) { - Section debug_line(".debug_line", SHT_PROGBITS, 0, nullptr, 0, 1, 0); - debug_line.SetBuffer(debug_line_data_); - builder.RegisterRawSection(debug_line); - } - if (!eh_frame_data_.empty()) { - Section eh_frame(".eh_frame", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, 4, 0); - eh_frame.SetBuffer(eh_frame_data_); - builder.RegisterRawSection(eh_frame); - } - builder.Init(); - builder.Write(); - - // Read the elf file back using objdump. - std::vector<std::string> lines; - auto cmd = std::string("objdump ") + args + " " + file.GetFilename() + " 2>&1"; - FILE* output = popen(cmd.data(), "r"); - char buffer[1024]; - const char* line; - while ((line = fgets(buffer, sizeof(buffer), output)) != nullptr) { - if (kPrintObjdumpOutput) { - printf("%s", line); - } - if (line[0] != '\0' && line[0] != '\n') { - EXPECT_TRUE(strstr(line, "objdump: Error:") == nullptr) << line; - EXPECT_TRUE(strstr(line, "objdump: Warning:") == nullptr) << line; - std::string str(line); - if (str.back() == '\n') { - str.pop_back(); - } - lines.push_back(str); - } - } - pclose(output); - return lines; - } - - std::vector<std::string> Objdump(bool is64bit, const char* args) { - if (is64bit) { - return Objdump<Elf64_Word, Elf64_Sword, Elf64_Addr, Elf64_Dyn, - Elf64_Sym, Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>(is64bit, args); - } else { - return Objdump<Elf32_Word, Elf32_Sword, Elf32_Addr, Elf32_Dyn, - Elf32_Sym, Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>(is64bit, args); - } - } - - // Compare objdump output to the recorded checks. - void CheckObjdumpOutput(bool is64bit, const char* args) { - std::vector<std::string> actual_lines = Objdump(is64bit, args); - auto actual_line = actual_lines.begin(); - for (const ExpectedLine& expected_line : expected_lines_) { - const std::string& substring = expected_line.substring; - if (actual_line == actual_lines.end()) { - ADD_FAILURE_AT(expected_line.at_file, expected_line.at_line) << - "Expected '" << substring << "'.\n" << - "Seen end of output."; - } else if (expected_line.next) { - if (actual_line->find(substring) == std::string::npos) { - ADD_FAILURE_AT(expected_line.at_file, expected_line.at_line) << - "Expected '" << substring << "'.\n" << - "Seen '" << actual_line->data() << "'."; - } else { - // printf("Found '%s' in '%s'.\n", substring.data(), actual_line->data()); - } - actual_line++; - } else { - bool found = false; - for (auto it = actual_line; it < actual_lines.end(); it++) { - if (it->find(substring) != std::string::npos) { - actual_line = it; - found = true; - break; - } - } - if (!found) { - ADD_FAILURE_AT(expected_line.at_file, expected_line.at_line) << - "Expected '" << substring << "'.\n" << - "Not found anywhere in the rest of the output."; - } else { - // printf("Found '%s' in '%s'.\n", substring.data(), actual_line->data()); - actual_line++; - } - } - } - } - - // Buffers which are going to assembled into ELF file and passed to objdump. - std::vector<uint8_t> eh_frame_data_; - std::vector<uint8_t> debug_info_data_; - std::vector<uint8_t> debug_abbrev_data_; - std::vector<uint8_t> debug_str_data_; - std::vector<uint8_t> debug_line_data_; - - // The expected output of objdump. - std::vector<ExpectedLine> expected_lines_; -}; - -} // namespace dwarf -} // namespace art - -#endif // ART_COMPILER_DWARF_DWARF_TEST_H_ diff --git a/compiler/dwarf/register.h b/compiler/dwarf/register.h deleted file mode 100644 index fa666df..0000000 --- a/compiler/dwarf/register.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * 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 ART_COMPILER_DWARF_REGISTER_H_ -#define ART_COMPILER_DWARF_REGISTER_H_ - -namespace art { -namespace dwarf { - -// Represents DWARF register. -class Reg { - public: - explicit Reg(int reg_num) : num_(reg_num) { } - int num() const { return num_; } - - // TODO: Arm S0–S31 register mapping is obsolescent. - // We should use VFP-v3/Neon D0-D31 mapping instead. - // However, D0 is aliased to pair of S0 and S1, so using that - // mapping we can not easily say S0 is spilled and S1 is not. - // There are ways around this in DWARF but they are complex. - // It would be much simpler to always spill whole D registers. - // Arm64 mapping is correct since we already do this there. - - static Reg ArmCore(int num) { return Reg(num); } - static Reg ArmFp(int num) { return Reg(64 + num); } // S0–S31. - static Reg Arm64Core(int num) { return Reg(num); } - static Reg Arm64Fp(int num) { return Reg(64 + num); } // V0-V31. - static Reg MipsCore(int num) { return Reg(num); } - static Reg Mips64Core(int num) { return Reg(num); } - static Reg X86Core(int num) { return Reg(num); } - static Reg X86Fp(int num) { return Reg(21 + num); } - static Reg X86_64Core(int num) { - static const int map[8] = {0, 2, 1, 3, 7, 6, 4, 5}; - return Reg(num < 8 ? map[num] : num); - } - static Reg X86_64Fp(int num) { return Reg(17 + num); } - - private: - int num_; -}; - -} // namespace dwarf -} // namespace art - -#endif // ART_COMPILER_DWARF_REGISTER_H_ diff --git a/compiler/dwarf/writer.h b/compiler/dwarf/writer.h deleted file mode 100644 index d8e29f0..0000000 --- a/compiler/dwarf/writer.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * 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 ART_COMPILER_DWARF_WRITER_H_ -#define ART_COMPILER_DWARF_WRITER_H_ - -#include <vector> -#include "leb128.h" -#include "base/logging.h" -#include "utils.h" - -namespace art { -namespace dwarf { - -// The base class for all DWARF writers. -template<typename Allocator = std::allocator<uint8_t>> -class Writer { - public: - void PushUint8(int value) { - DCHECK_GE(value, 0); - DCHECK_LE(value, UINT8_MAX); - data_->push_back(value & 0xff); - } - - void PushUint16(int value) { - DCHECK_GE(value, 0); - DCHECK_LE(value, UINT16_MAX); - data_->push_back((value >> 0) & 0xff); - data_->push_back((value >> 8) & 0xff); - } - - void PushUint32(uint32_t value) { - data_->push_back((value >> 0) & 0xff); - data_->push_back((value >> 8) & 0xff); - data_->push_back((value >> 16) & 0xff); - data_->push_back((value >> 24) & 0xff); - } - - void PushUint32(int value) { - DCHECK_GE(value, 0); - PushUint32(static_cast<uint32_t>(value)); - } - - void PushUint32(uint64_t value) { - DCHECK_LE(value, UINT32_MAX); - PushUint32(static_cast<uint32_t>(value)); - } - - void PushUint64(uint64_t value) { - data_->push_back((value >> 0) & 0xff); - data_->push_back((value >> 8) & 0xff); - data_->push_back((value >> 16) & 0xff); - data_->push_back((value >> 24) & 0xff); - data_->push_back((value >> 32) & 0xff); - data_->push_back((value >> 40) & 0xff); - data_->push_back((value >> 48) & 0xff); - data_->push_back((value >> 56) & 0xff); - } - - void PushInt8(int value) { - DCHECK_GE(value, INT8_MIN); - DCHECK_LE(value, INT8_MAX); - PushUint8(static_cast<uint8_t>(value)); - } - - void PushInt16(int value) { - DCHECK_GE(value, INT16_MIN); - DCHECK_LE(value, INT16_MAX); - PushUint16(static_cast<uint16_t>(value)); - } - - void PushInt32(int value) { - PushUint32(static_cast<uint32_t>(value)); - } - - void PushInt64(int64_t value) { - PushUint64(static_cast<uint64_t>(value)); - } - - // Variable-length encoders. - - void PushUleb128(uint32_t value) { - EncodeUnsignedLeb128(data_, value); - } - - void PushUleb128(int value) { - DCHECK_GE(value, 0); - EncodeUnsignedLeb128(data_, value); - } - - void PushSleb128(int value) { - EncodeSignedLeb128(data_, value); - } - - // Miscellaneous functions. - - void PushString(const char* value) { - data_->insert(data_->end(), value, value + strlen(value) + 1); - } - - void PushData(const void* ptr, size_t size) { - const char* p = reinterpret_cast<const char*>(ptr); - data_->insert(data_->end(), p, p + size); - } - - void UpdateUint32(size_t offset, uint32_t value) { - DCHECK_LT(offset + 3, data_->size()); - (*data_)[offset + 0] = (value >> 0) & 0xFF; - (*data_)[offset + 1] = (value >> 8) & 0xFF; - (*data_)[offset + 2] = (value >> 16) & 0xFF; - (*data_)[offset + 3] = (value >> 24) & 0xFF; - } - - void UpdateUint64(size_t offset, uint64_t value) { - DCHECK_LT(offset + 7, data_->size()); - (*data_)[offset + 0] = (value >> 0) & 0xFF; - (*data_)[offset + 1] = (value >> 8) & 0xFF; - (*data_)[offset + 2] = (value >> 16) & 0xFF; - (*data_)[offset + 3] = (value >> 24) & 0xFF; - (*data_)[offset + 4] = (value >> 32) & 0xFF; - (*data_)[offset + 5] = (value >> 40) & 0xFF; - (*data_)[offset + 6] = (value >> 48) & 0xFF; - (*data_)[offset + 7] = (value >> 56) & 0xFF; - } - - void Pad(int alignment) { - DCHECK_NE(alignment, 0); - data_->resize(RoundUp(data_->size(), alignment), 0); - } - - const std::vector<uint8_t, Allocator>* data() const { - return data_; - } - - explicit Writer(std::vector<uint8_t, Allocator>* buffer) : data_(buffer) { } - - private: - std::vector<uint8_t, Allocator>* data_; - - DISALLOW_COPY_AND_ASSIGN(Writer); -}; - -} // namespace dwarf -} // namespace art - -#endif // ART_COMPILER_DWARF_WRITER_H_ diff --git a/runtime/leb128.h b/runtime/leb128.h index d36b690..dfb42b8 100644 --- a/runtime/leb128.h +++ b/runtime/leb128.h @@ -124,18 +124,6 @@ static inline uint8_t* EncodeUnsignedLeb128(uint8_t* dest, uint32_t value) { return dest; } -template<typename Allocator> -static inline void EncodeUnsignedLeb128(std::vector<uint8_t, Allocator>* dest, uint32_t value) { - uint8_t out = value & 0x7f; - value >>= 7; - while (value != 0) { - dest->push_back(out | 0x80); - out = value & 0x7f; - value >>= 7; - } - dest->push_back(out); -} - static inline uint8_t* EncodeSignedLeb128(uint8_t* dest, int32_t value) { uint32_t extra_bits = static_cast<uint32_t>(value ^ (value >> 31)) >> 6; uint8_t out = value & 0x7f; @@ -149,19 +137,6 @@ static inline uint8_t* EncodeSignedLeb128(uint8_t* dest, int32_t value) { return dest; } -template<typename Allocator> -static inline void EncodeSignedLeb128(std::vector<uint8_t, Allocator>* dest, int32_t value) { - uint32_t extra_bits = static_cast<uint32_t>(value ^ (value >> 31)) >> 6; - uint8_t out = value & 0x7f; - while (extra_bits != 0u) { - dest->push_back(out | 0x80); - value >>= 7; - out = value & 0x7f; - extra_bits >>= 7; - } - dest->push_back(out); -} - // An encoder that pushed uint32_t data onto the given std::vector. class Leb128Encoder { public: @@ -174,7 +149,14 @@ class Leb128Encoder { } void PushBackUnsigned(uint32_t value) { - EncodeUnsignedLeb128(data_, value); + uint8_t out = value & 0x7f; + value >>= 7; + while (value != 0) { + data_->push_back(out | 0x80); + out = value & 0x7f; + value >>= 7; + } + data_->push_back(out); } template<typename It> @@ -185,7 +167,15 @@ class Leb128Encoder { } void PushBackSigned(int32_t value) { - EncodeSignedLeb128(data_, value); + uint32_t extra_bits = static_cast<uint32_t>(value ^ (value >> 31)) >> 6; + uint8_t out = value & 0x7f; + while (extra_bits != 0u) { + data_->push_back(out | 0x80); + value >>= 7; + out = value & 0x7f; + extra_bits >>= 7; + } + data_->push_back(out); } template<typename It> |