Create libelffile library for ELF file manipulation.
Move some of our tooling to library to make it reusable.
Remove MIPS support from the ELF builder. This is slightly
easier than making it independent of the runtime.
Bug: 110133331
Test: test.py -b --host
Change-Id: I93343808d0e27ee8e1117e713a2503e8179fc245
diff --git a/compiler/Android.bp b/compiler/Android.bp
index 341727d..4ad59e1 100644
--- a/compiler/Android.bp
+++ b/compiler/Android.bp
@@ -26,17 +26,12 @@
srcs: [
"compiled_method.cc",
"debug/elf_debug_writer.cc",
- "debug/xz_utils.cc",
"dex/inline_method_analyser.cc",
"dex/verified_method.cc",
"dex/verification_results.cc",
"driver/compiled_method_storage.cc",
"driver/compiler_options.cc",
"driver/dex_compilation_unit.cc",
- "linker/buffered_output_stream.cc",
- "linker/file_output_stream.cc",
- "linker/output_stream.cc",
- "linker/vector_output_stream.cc",
"jit/jit_compiler.cc",
"jit/jit_logger.cc",
"jni/quick/calling_convention.cc",
@@ -254,6 +249,7 @@
"libprofile",
"libdexfile",
],
+ whole_static_libs: ["libelffile"],
target: {
android: {
@@ -317,6 +313,7 @@
"libprofiled",
"libdexfiled",
],
+ whole_static_libs: ["libelffiled"],
}
cc_defaults {
diff --git a/compiler/cfi_test.h b/compiler/cfi_test.h
index 2fc81c9..9755ef1 100644
--- a/compiler/cfi_test.h
+++ b/compiler/cfi_test.h
@@ -23,10 +23,10 @@
#include "arch/instruction_set.h"
#include "base/enums.h"
-#include "debug/dwarf/dwarf_constants.h"
#include "debug/dwarf/dwarf_test.h"
-#include "debug/dwarf/headers.h"
#include "disassembler.h"
+#include "dwarf/dwarf_constants.h"
+#include "dwarf/headers.h"
#include "gtest/gtest.h"
#include "thread.h"
diff --git a/compiler/debug/dwarf/debug_abbrev_writer.h b/compiler/debug/dwarf/debug_abbrev_writer.h
deleted file mode 100644
index 63a049b..0000000
--- a/compiler/debug/dwarf/debug_abbrev_writer.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2016 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_DEBUG_DWARF_DEBUG_ABBREV_WRITER_H_
-#define ART_COMPILER_DEBUG_DWARF_DEBUG_ABBREV_WRITER_H_
-
-#include <cstdint>
-#include <type_traits>
-#include <unordered_map>
-
-#include "base/casts.h"
-#include "base/leb128.h"
-#include "base/stl_util.h"
-#include "debug/dwarf/dwarf_constants.h"
-#include "debug/dwarf/writer.h"
-
-namespace art {
-namespace dwarf {
-
-// Writer for the .debug_abbrev.
-//
-// Abbreviations specify the format of entries in .debug_info.
-// Each entry specifies abbreviation code, which in turns
-// determines all the attributes and their format.
-// It is possible to think of them as type definitions.
-template <typename Vector = std::vector<uint8_t>>
-class DebugAbbrevWriter final : private Writer<Vector> {
- static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type");
-
- public:
- explicit DebugAbbrevWriter(Vector* buffer)
- : Writer<Vector>(buffer),
- current_abbrev_(buffer->get_allocator()) {
- this->PushUint8(0); // Add abbrev table terminator.
- }
-
- // Start abbreviation declaration.
- void StartAbbrev(Tag tag) {
- DCHECK(current_abbrev_.empty());
- EncodeUnsignedLeb128(¤t_abbrev_, tag);
- has_children_offset_ = current_abbrev_.size();
- current_abbrev_.push_back(0); // Place-holder for DW_CHILDREN.
- }
-
- // Add attribute specification.
- void AddAbbrevAttribute(Attribute name, Form type) {
- EncodeUnsignedLeb128(¤t_abbrev_, name);
- EncodeUnsignedLeb128(¤t_abbrev_, type);
- }
-
- // End abbreviation declaration and return its code.
- // This will deduplicate abbreviations.
- uint32_t EndAbbrev(Children has_children) {
- DCHECK(!current_abbrev_.empty());
- current_abbrev_[has_children_offset_] = has_children;
- auto it = abbrev_codes_.insert(std::make_pair(std::move(current_abbrev_), NextAbbrevCode()));
- uint32_t abbrev_code = it.first->second;
- if (UNLIKELY(it.second)) { // Inserted new entry.
- const Vector& abbrev = it.first->first;
- this->Pop(); // Remove abbrev table terminator.
- this->PushUleb128(abbrev_code);
- this->PushData(abbrev.data(), abbrev.size());
- this->PushUint8(0); // Attribute list end.
- this->PushUint8(0); // Attribute list end.
- this->PushUint8(0); // Add abbrev table terminator.
- }
- current_abbrev_.clear();
- return abbrev_code;
- }
-
- // Get the next free abbrev code.
- uint32_t NextAbbrevCode() {
- return dchecked_integral_cast<uint32_t>(1 + abbrev_codes_.size());
- }
-
- private:
- Vector current_abbrev_;
- size_t has_children_offset_ = 0;
- std::unordered_map<Vector, uint32_t, FNVHash<Vector> > abbrev_codes_;
-};
-
-} // namespace dwarf
-} // namespace art
-
-#endif // ART_COMPILER_DEBUG_DWARF_DEBUG_ABBREV_WRITER_H_
diff --git a/compiler/debug/dwarf/debug_frame_opcode_writer.h b/compiler/debug/dwarf/debug_frame_opcode_writer.h
deleted file mode 100644
index 7c75c9b..0000000
--- a/compiler/debug/dwarf/debug_frame_opcode_writer.h
+++ /dev/null
@@ -1,341 +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_DEBUG_DWARF_DEBUG_FRAME_OPCODE_WRITER_H_
-#define ART_COMPILER_DEBUG_DWARF_DEBUG_FRAME_OPCODE_WRITER_H_
-
-#include "base/bit_utils.h"
-#include "debug/dwarf/dwarf_constants.h"
-#include "debug/dwarf/register.h"
-#include "debug/dwarf/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 Vector = std::vector<uint8_t> >
-class DebugFrameOpCodeWriter : private Writer<Vector> {
- static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type");
-
- 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 ALWAYS_INLINE AdvancePC(int absolute_pc) {
- DCHECK_GE(absolute_pc, current_pc_);
- if (UNLIKELY(enabled_)) {
- 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 ALWAYS_INLINE RelOffset(Reg reg, int offset) {
- Offset(reg, offset - current_cfa_offset_);
- }
-
- // Common alias in assemblers - increase stack frame size.
- void ALWAYS_INLINE AdjustCFAOffset(int delta) {
- DefCFAOffset(current_cfa_offset_ + delta);
- }
-
- // Custom alias - spill many registers based on bitmask.
- void ALWAYS_INLINE RelOffsetForMany(Reg reg_base, int offset,
- uint32_t reg_mask, int reg_size) {
- DCHECK(reg_size == 4 || reg_size == 8);
- if (UNLIKELY(enabled_)) {
- for (int i = 0; reg_mask != 0u; reg_mask >>= 1, i++) {
- // Skip zero bits and go to the set bit.
- int num_zeros = CTZ(reg_mask);
- i += num_zeros;
- reg_mask >>= num_zeros;
- RelOffset(Reg(reg_base.num() + i), offset);
- offset += reg_size;
- }
- }
- }
-
- // Custom alias - unspill many registers based on bitmask.
- void ALWAYS_INLINE RestoreMany(Reg reg_base, uint32_t reg_mask) {
- if (UNLIKELY(enabled_)) {
- for (int i = 0; reg_mask != 0u; reg_mask >>= 1, i++) {
- // Skip zero bits and go to the set bit.
- int num_zeros = CTZ(reg_mask);
- i += num_zeros;
- reg_mask >>= num_zeros;
- Restore(Reg(reg_base.num() + i));
- }
- }
- }
-
- void ALWAYS_INLINE Nop() {
- if (UNLIKELY(enabled_)) {
- this->PushUint8(DW_CFA_nop);
- }
- }
-
- void ALWAYS_INLINE Offset(Reg reg, int offset) {
- if (UNLIKELY(enabled_)) {
- 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 ALWAYS_INLINE Restore(Reg reg) {
- if (UNLIKELY(enabled_)) {
- 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 ALWAYS_INLINE Undefined(Reg reg) {
- if (UNLIKELY(enabled_)) {
- ImplicitlyAdvancePC();
- this->PushUint8(DW_CFA_undefined);
- this->PushUleb128(reg.num());
- }
- }
-
- void ALWAYS_INLINE SameValue(Reg reg) {
- if (UNLIKELY(enabled_)) {
- ImplicitlyAdvancePC();
- this->PushUint8(DW_CFA_same_value);
- this->PushUleb128(reg.num());
- }
- }
-
- // The previous value of "reg" is stored in register "new_reg".
- void ALWAYS_INLINE Register(Reg reg, Reg new_reg) {
- if (UNLIKELY(enabled_)) {
- ImplicitlyAdvancePC();
- this->PushUint8(DW_CFA_register);
- this->PushUleb128(reg.num());
- this->PushUleb128(new_reg.num());
- }
- }
-
- void ALWAYS_INLINE RememberState() {
- if (UNLIKELY(enabled_)) {
- ImplicitlyAdvancePC();
- this->PushUint8(DW_CFA_remember_state);
- }
- }
-
- void ALWAYS_INLINE RestoreState() {
- if (UNLIKELY(enabled_)) {
- ImplicitlyAdvancePC();
- this->PushUint8(DW_CFA_restore_state);
- }
- }
-
- void ALWAYS_INLINE DefCFA(Reg reg, int offset) {
- if (UNLIKELY(enabled_)) {
- 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 ALWAYS_INLINE DefCFARegister(Reg reg) {
- if (UNLIKELY(enabled_)) {
- ImplicitlyAdvancePC();
- this->PushUint8(DW_CFA_def_cfa_register);
- this->PushUleb128(reg.num());
- }
- }
-
- void ALWAYS_INLINE DefCFAOffset(int offset) {
- if (UNLIKELY(enabled_)) {
- 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));
- }
- }
- }
- // Uncoditional so that the user can still get and check the value.
- current_cfa_offset_ = offset;
- }
-
- void ALWAYS_INLINE ValOffset(Reg reg, int offset) {
- if (UNLIKELY(enabled_)) {
- 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 ALWAYS_INLINE DefCFAExpression(uint8_t* expr, int expr_size) {
- if (UNLIKELY(enabled_)) {
- ImplicitlyAdvancePC();
- uses_dwarf3_features_ = true;
- this->PushUint8(DW_CFA_def_cfa_expression);
- this->PushUleb128(expr_size);
- this->PushData(expr, expr_size);
- }
- }
-
- void ALWAYS_INLINE Expression(Reg reg, uint8_t* expr, int expr_size) {
- if (UNLIKELY(enabled_)) {
- ImplicitlyAdvancePC();
- uses_dwarf3_features_ = true;
- this->PushUint8(DW_CFA_expression);
- this->PushUleb128(reg.num());
- this->PushUleb128(expr_size);
- this->PushData(expr, expr_size);
- }
- }
-
- void ALWAYS_INLINE ValExpression(Reg reg, uint8_t* expr, int expr_size) {
- if (UNLIKELY(enabled_)) {
- ImplicitlyAdvancePC();
- uses_dwarf3_features_ = true;
- this->PushUint8(DW_CFA_val_expression);
- this->PushUleb128(reg.num());
- this->PushUleb128(expr_size);
- this->PushData(expr, expr_size);
- }
- }
-
- bool IsEnabled() const { return enabled_; }
-
- void SetEnabled(bool value) {
- enabled_ = value;
- if (enabled_ && opcodes_.capacity() == 0u) {
- opcodes_.reserve(kDefaultCapacity);
- }
- }
-
- int GetCurrentPC() const { return current_pc_; }
-
- int GetCurrentCFAOffset() const { return current_cfa_offset_; }
-
- void SetCurrentCFAOffset(int offset) { current_cfa_offset_ = offset; }
-
- using Writer<Vector>::data;
-
- explicit DebugFrameOpCodeWriter(bool enabled = true,
- const typename Vector::allocator_type& alloc =
- typename Vector::allocator_type())
- : Writer<Vector>(&opcodes_),
- enabled_(false),
- opcodes_(alloc),
- current_cfa_offset_(0),
- current_pc_(0),
- uses_dwarf3_features_(false) {
- SetEnabled(enabled);
- }
-
- virtual ~DebugFrameOpCodeWriter() { }
-
- protected:
- // Best guess based on couple of observed outputs.
- static constexpr size_t kDefaultCapacity = 32u;
-
- 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;
- }
-
- bool enabled_; // If disabled all writes are no-ops.
- Vector 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_DEBUG_DWARF_DEBUG_FRAME_OPCODE_WRITER_H_
diff --git a/compiler/debug/dwarf/debug_info_entry_writer.h b/compiler/debug/dwarf/debug_info_entry_writer.h
deleted file mode 100644
index b198178..0000000
--- a/compiler/debug/dwarf/debug_info_entry_writer.h
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Copyright (C) 2014 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_DEBUG_DWARF_DEBUG_INFO_ENTRY_WRITER_H_
-#define ART_COMPILER_DEBUG_DWARF_DEBUG_INFO_ENTRY_WRITER_H_
-
-#include <cstdint>
-#include <unordered_map>
-
-#include "base/casts.h"
-#include "base/leb128.h"
-#include "debug/dwarf/debug_abbrev_writer.h"
-#include "debug/dwarf/dwarf_constants.h"
-#include "debug/dwarf/expression.h"
-#include "debug/dwarf/writer.h"
-
-namespace art {
-namespace dwarf {
-
-/*
- * Writer for debug information entries (DIE).
- *
- * Usage:
- * StartTag(DW_TAG_compile_unit);
- * WriteStrp(DW_AT_producer, "Compiler name", debug_str);
- * StartTag(DW_TAG_subprogram);
- * WriteStrp(DW_AT_name, "Foo", debug_str);
- * EndTag();
- * EndTag();
- */
-template <typename Vector = std::vector<uint8_t>>
-class DebugInfoEntryWriter final : private Writer<Vector> {
- static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type");
-
- public:
- static constexpr size_t kCompilationUnitHeaderSize = 11;
-
- // Start debugging information entry.
- // Returns offset of the entry in compilation unit.
- size_t StartTag(Tag tag) {
- if (inside_entry_) {
- // Write abbrev code for the previous entry.
- // Parent entry is finalized before any children are written.
- this->UpdateUleb128(abbrev_code_offset_, debug_abbrev_->EndAbbrev(DW_CHILDREN_yes));
- inside_entry_ = false;
- }
- debug_abbrev_->StartAbbrev(tag);
- // Abbrev code placeholder of sufficient size.
- abbrev_code_offset_ = this->data()->size();
- this->PushUleb128(debug_abbrev_->NextAbbrevCode());
- depth_++;
- inside_entry_ = true;
- return abbrev_code_offset_ + kCompilationUnitHeaderSize;
- }
-
- // End debugging information entry.
- void EndTag() {
- DCHECK_GT(depth_, 0);
- if (inside_entry_) {
- // Write abbrev code for this entry.
- this->UpdateUleb128(abbrev_code_offset_, debug_abbrev_->EndAbbrev(DW_CHILDREN_no));
- inside_entry_ = false;
- // This entry has no children and so there is no terminator.
- } else {
- // The entry has been already finalized so it must be parent entry
- // and we need to write the terminator required by DW_CHILDREN_yes.
- this->PushUint8(0);
- }
- depth_--;
- }
-
- void WriteAddr(Attribute attrib, uint64_t value) {
- debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_addr);
- patch_locations_.push_back(this->data()->size());
- if (is64bit_) {
- this->PushUint64(value);
- } else {
- this->PushUint32(value);
- }
- }
-
- void WriteBlock(Attribute attrib, const uint8_t* ptr, size_t num_bytes) {
- debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_block);
- this->PushUleb128(num_bytes);
- this->PushData(ptr, num_bytes);
- }
-
- void WriteExprLoc(Attribute attrib, const Expression& expr) {
- debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_exprloc);
- this->PushUleb128(dchecked_integral_cast<uint32_t>(expr.size()));
- this->PushData(expr.data());
- }
-
- void WriteData1(Attribute attrib, uint8_t value) {
- debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_data1);
- this->PushUint8(value);
- }
-
- void WriteData2(Attribute attrib, uint16_t value) {
- debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_data2);
- this->PushUint16(value);
- }
-
- void WriteData4(Attribute attrib, uint32_t value) {
- debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_data4);
- this->PushUint32(value);
- }
-
- void WriteData8(Attribute attrib, uint64_t value) {
- debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_data8);
- this->PushUint64(value);
- }
-
- void WriteSecOffset(Attribute attrib, uint32_t offset) {
- debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_sec_offset);
- this->PushUint32(offset);
- }
-
- void WriteSdata(Attribute attrib, int value) {
- debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_sdata);
- this->PushSleb128(value);
- }
-
- void WriteUdata(Attribute attrib, int value) {
- debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_udata);
- this->PushUleb128(value);
- }
-
- void WriteUdata(Attribute attrib, uint32_t value) {
- debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_udata);
- this->PushUleb128(value);
- }
-
- void WriteFlag(Attribute attrib, bool value) {
- debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_flag);
- this->PushUint8(value ? 1 : 0);
- }
-
- void WriteFlagPresent(Attribute attrib) {
- debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_flag_present);
- }
-
- void WriteRef4(Attribute attrib, uint32_t cu_offset) {
- debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_ref4);
- this->PushUint32(cu_offset);
- }
-
- void WriteRef(Attribute attrib, uint32_t cu_offset) {
- debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_ref_udata);
- this->PushUleb128(cu_offset);
- }
-
- void WriteString(Attribute attrib, const char* value) {
- debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_string);
- this->PushString(value);
- }
-
- void WriteStrp(Attribute attrib, size_t debug_str_offset) {
- debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_strp);
- this->PushUint32(dchecked_integral_cast<uint32_t>(debug_str_offset));
- }
-
- void WriteStrp(Attribute attrib, const char* str, size_t len,
- std::vector<uint8_t>* debug_str) {
- debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_strp);
- this->PushUint32(debug_str->size());
- debug_str->insert(debug_str->end(), str, str + len);
- debug_str->push_back(0);
- }
-
- void WriteStrp(Attribute attrib, const char* str, std::vector<uint8_t>* debug_str) {
- WriteStrp(attrib, str, strlen(str), debug_str);
- }
-
- bool Is64bit() const { return is64bit_; }
-
- const std::vector<uintptr_t>& GetPatchLocations() const {
- return patch_locations_;
- }
-
- int Depth() const { return depth_; }
-
- using Writer<Vector>::data;
- using Writer<Vector>::size;
- using Writer<Vector>::UpdateUint32;
-
- DebugInfoEntryWriter(bool is64bitArch,
- DebugAbbrevWriter<Vector>* debug_abbrev,
- const typename Vector::allocator_type& alloc =
- typename Vector::allocator_type())
- : Writer<Vector>(&entries_),
- debug_abbrev_(debug_abbrev),
- entries_(alloc),
- is64bit_(is64bitArch) {
- }
-
- ~DebugInfoEntryWriter() {
- DCHECK(!inside_entry_);
- DCHECK_EQ(depth_, 0);
- }
-
- private:
- DebugAbbrevWriter<Vector>* debug_abbrev_;
- Vector entries_;
- bool is64bit_;
- int depth_ = 0;
- size_t abbrev_code_offset_ = 0; // Location to patch once we know the code.
- bool inside_entry_ = false; // Entry ends at first child (if any).
- std::vector<uintptr_t> patch_locations_;
-};
-
-} // namespace dwarf
-} // namespace art
-
-#endif // ART_COMPILER_DEBUG_DWARF_DEBUG_INFO_ENTRY_WRITER_H_
diff --git a/compiler/debug/dwarf/debug_line_opcode_writer.h b/compiler/debug/dwarf/debug_line_opcode_writer.h
deleted file mode 100644
index bb4e87f..0000000
--- a/compiler/debug/dwarf/debug_line_opcode_writer.h
+++ /dev/null
@@ -1,261 +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_DEBUG_DWARF_DEBUG_LINE_OPCODE_WRITER_H_
-#define ART_COMPILER_DEBUG_DWARF_DEBUG_LINE_OPCODE_WRITER_H_
-
-#include <cstdint>
-
-#include "debug/dwarf/dwarf_constants.h"
-#include "debug/dwarf/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 Vector = std::vector<uint8_t>>
-class DebugLineOpCodeWriter final : private Writer<Vector> {
- static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type");
-
- public:
- static constexpr int kOpcodeBase = 13;
- static constexpr bool kDefaultIsStmt = false;
- 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 SetIsStmt(bool is_stmt) {
- if (is_stmt_ != is_stmt) {
- this->PushUint8(DW_LNS_negate_stmt);
- is_stmt_ = is_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;
- is_stmt_ = kDefaultIsStmt;
- }
-
- // 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);
- patch_locations_.push_back(this->data()->size());
- this->PushUint64(absolute_address);
- } else {
- this->PushUleb128(1 + 4);
- this->PushUint8(DW_LNE_set_address);
- patch_locations_.push_back(this->data()->size());
- 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_;
- }
-
- const std::vector<uintptr_t>& GetPatchLocations() const {
- return patch_locations_;
- }
-
- using Writer<Vector>::data;
-
- DebugLineOpCodeWriter(bool use64bitAddress,
- int codeFactorBits,
- const typename Vector::allocator_type& alloc =
- typename Vector::allocator_type())
- : Writer<Vector>(&opcodes_),
- opcodes_(alloc),
- uses_dwarf3_features_(false),
- use_64bit_address_(use64bitAddress),
- code_factor_bits_(codeFactorBits),
- current_address_(0),
- current_file_(1),
- current_line_(1),
- is_stmt_(kDefaultIsStmt) {
- }
-
- 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_;
- }
-
- Vector opcodes_;
- bool uses_dwarf3_features_;
- bool use_64bit_address_;
- int code_factor_bits_;
- uint64_t current_address_;
- int current_file_;
- int current_line_;
- bool is_stmt_;
- std::vector<uintptr_t> patch_locations_;
-
- DISALLOW_COPY_AND_ASSIGN(DebugLineOpCodeWriter);
-};
-
-} // namespace dwarf
-} // namespace art
-
-#endif // ART_COMPILER_DEBUG_DWARF_DEBUG_LINE_OPCODE_WRITER_H_
diff --git a/compiler/debug/dwarf/dwarf_constants.h b/compiler/debug/dwarf/dwarf_constants.h
deleted file mode 100644
index 7beb1fa..0000000
--- a/compiler/debug/dwarf/dwarf_constants.h
+++ /dev/null
@@ -1,686 +0,0 @@
-/*
- * Copyright (C) 2014 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_DEBUG_DWARF_DWARF_CONSTANTS_H_
-#define ART_COMPILER_DEBUG_DWARF_DWARF_CONSTANTS_H_
-
-namespace art {
-namespace dwarf {
-
-// Based on the Dwarf 4 specification at dwarfstd.com and issues marked
-// for inclusion in Dwarf 5 on same. Values not specified in the Dwarf 4
-// standard might change or be removed in the future and may be different
-// than the values used currently by other implementations for the same trait,
-// use at your own risk.
-
-enum Tag {
- DW_TAG_array_type = 0x01,
- DW_TAG_class_type = 0x02,
- DW_TAG_entry_point = 0x03,
- DW_TAG_enumeration_type = 0x04,
- DW_TAG_formal_parameter = 0x05,
- DW_TAG_imported_declaration = 0x08,
- DW_TAG_label = 0x0a,
- DW_TAG_lexical_block = 0x0b,
- DW_TAG_member = 0x0d,
- DW_TAG_pointer_type = 0x0f,
- DW_TAG_reference_type = 0x10,
- DW_TAG_compile_unit = 0x11,
- DW_TAG_string_type = 0x12,
- DW_TAG_structure_type = 0x13,
- DW_TAG_subroutine_type = 0x15,
- DW_TAG_typedef = 0x16,
- DW_TAG_union_type = 0x17,
- DW_TAG_unspecified_parameters = 0x18,
- DW_TAG_variant = 0x19,
- DW_TAG_common_block = 0x1a,
- DW_TAG_common_inclusion = 0x1b,
- DW_TAG_inheritance = 0x1c,
- DW_TAG_inlined_subroutine = 0x1d,
- DW_TAG_module = 0x1e,
- DW_TAG_ptr_to_member_type = 0x1f,
- DW_TAG_set_type = 0x20,
- DW_TAG_subrange_type = 0x21,
- DW_TAG_with_stmt = 0x22,
- DW_TAG_access_declaration = 0x23,
- DW_TAG_base_type = 0x24,
- DW_TAG_catch_block = 0x25,
- DW_TAG_const_type = 0x26,
- DW_TAG_constant = 0x27,
- DW_TAG_enumerator = 0x28,
- DW_TAG_file_type = 0x29,
- DW_TAG_friend = 0x2a,
- DW_TAG_namelist = 0x2b,
- DW_TAG_namelist_item = 0x2c,
- DW_TAG_packed_type = 0x2d,
- DW_TAG_subprogram = 0x2e,
- DW_TAG_template_type_parameter = 0x2f,
- DW_TAG_template_value_parameter = 0x30,
- DW_TAG_thrown_type = 0x31,
- DW_TAG_try_block = 0x32,
- DW_TAG_variant_part = 0x33,
- DW_TAG_variable = 0x34,
- DW_TAG_volatile_type = 0x35,
- DW_TAG_dwarf_procedure = 0x36,
- DW_TAG_restrict_type = 0x37,
- DW_TAG_interface_type = 0x38,
- DW_TAG_namespace = 0x39,
- DW_TAG_imported_module = 0x3a,
- DW_TAG_unspecified_type = 0x3b,
- DW_TAG_partial_unit = 0x3c,
- DW_TAG_imported_unit = 0x3d,
- DW_TAG_condition = 0x3f,
- DW_TAG_shared_type = 0x40,
- DW_TAG_type_unit = 0x41,
- DW_TAG_rvalue_reference_type = 0x42,
- DW_TAG_template_alias = 0x43,
-#ifdef INCLUDE_DWARF5_VALUES
- // Values to be added in Dwarf 5. Final value not yet specified. Values listed
- // may be different than other implementations. Use with caution.
- // TODO Update these values when Dwarf 5 is released.
- DW_TAG_coarray_type = 0x44,
- DW_TAG_call_site = 0x45,
- DW_TAG_call_site_parameter = 0x46,
- DW_TAG_generic_subrange = 0x47,
- DW_TAG_atomic_type = 0x48,
- DW_TAG_dynamic_type = 0x49,
- DW_TAG_aligned_type = 0x50,
-#endif
- DW_TAG_lo_user = 0x4080,
- DW_TAG_hi_user = 0xffff
-};
-
-enum Children : uint8_t {
- DW_CHILDREN_no = 0x00,
- DW_CHILDREN_yes = 0x01
-};
-
-enum Attribute {
- DW_AT_sibling = 0x01,
- DW_AT_location = 0x02,
- DW_AT_name = 0x03,
- DW_AT_ordering = 0x09,
- DW_AT_byte_size = 0x0b,
- DW_AT_bit_offset = 0x0c,
- DW_AT_bit_size = 0x0d,
- DW_AT_stmt_list = 0x10,
- DW_AT_low_pc = 0x11,
- DW_AT_high_pc = 0x12,
- DW_AT_language = 0x13,
- DW_AT_discr = 0x15,
- DW_AT_discr_value = 0x16,
- DW_AT_visibility = 0x17,
- DW_AT_import = 0x18,
- DW_AT_string_length = 0x19,
- DW_AT_common_reference = 0x1a,
- DW_AT_comp_dir = 0x1b,
- DW_AT_const_value = 0x1c,
- DW_AT_containing_type = 0x1d,
- DW_AT_default_value = 0x1e,
- DW_AT_inline = 0x20,
- DW_AT_is_optional = 0x21,
- DW_AT_lower_bound = 0x22,
- DW_AT_producer = 0x25,
- DW_AT_prototyped = 0x27,
- DW_AT_return_addr = 0x2a,
- DW_AT_start_scope = 0x2c,
- DW_AT_bit_stride = 0x2e,
- DW_AT_upper_bound = 0x2f,
- DW_AT_abstract_origin = 0x31,
- DW_AT_accessibility = 0x32,
- DW_AT_address_class = 0x33,
- DW_AT_artificial = 0x34,
- DW_AT_base_types = 0x35,
- DW_AT_calling_convention = 0x36,
- DW_AT_count = 0x37,
- DW_AT_data_member_location = 0x38,
- DW_AT_decl_column = 0x39,
- DW_AT_decl_file = 0x3a,
- DW_AT_decl_line = 0x3b,
- DW_AT_declaration = 0x3c,
- DW_AT_discr_list = 0x3d,
- DW_AT_encoding = 0x3e,
- DW_AT_external = 0x3f,
- DW_AT_frame_base = 0x40,
- DW_AT_friend = 0x41,
- DW_AT_identifier_case = 0x42,
- DW_AT_macro_info = 0x43,
- DW_AT_namelist_item = 0x44,
- DW_AT_priority = 0x45,
- DW_AT_segment = 0x46,
- DW_AT_specification = 0x47,
- DW_AT_static_link = 0x48,
- DW_AT_type = 0x49,
- DW_AT_use_location = 0x4a,
- DW_AT_variable_parameter = 0x4b,
- DW_AT_virtuality = 0x4c,
- DW_AT_vtable_elem_location = 0x4d,
- DW_AT_allocated = 0x4e,
- DW_AT_associated = 0x4f,
- DW_AT_data_location = 0x50,
- DW_AT_byte_stride = 0x51,
- DW_AT_entry_pc = 0x52,
- DW_AT_use_UTF8 = 0x53,
- DW_AT_extension = 0x54,
- DW_AT_ranges = 0x55,
- DW_AT_trampoline = 0x56,
- DW_AT_call_column = 0x57,
- DW_AT_call_file = 0x58,
- DW_AT_call_line = 0x59,
- DW_AT_description = 0x5a,
- DW_AT_binary_scale = 0x5b,
- DW_AT_decimal_scale = 0x5c,
- DW_AT_small = 0x5d,
- DW_AT_decimal_sign = 0x5e,
- DW_AT_digit_count = 0x5f,
- DW_AT_picture_string = 0x60,
- DW_AT_mutable = 0x61,
- DW_AT_threads_scaled = 0x62,
- DW_AT_explicit = 0x63,
- DW_AT_object_pointer = 0x64,
- DW_AT_endianity = 0x65,
- DW_AT_elemental = 0x66,
- DW_AT_pure = 0x67,
- DW_AT_recursive = 0x68,
- DW_AT_signature = 0x69,
- DW_AT_main_subprogram = 0x6a,
- DW_AT_data_bit_offset = 0x6b,
- DW_AT_const_expr = 0x6c,
- DW_AT_enum_class = 0x6d,
- DW_AT_linkage_name = 0x6e,
-#ifdef INCLUDE_DWARF5_VALUES
- // Values to be added in Dwarf 5. Final value not yet specified. Values listed
- // may be different than other implementations. Use with caution.
- // TODO Update these values when Dwarf 5 is released.
- DW_AT_call_site_value = 0x6f,
- DW_AT_call_site_data_value = 0x70,
- DW_AT_call_site_target = 0x71,
- DW_AT_call_site_target_clobbered = 0x72,
- DW_AT_tail_call = 0x73,
- DW_AT_all_tail_call_sites = 0x74,
- DW_AT_all_call_sites = 0x75,
- DW_AT_all_source_call_sites = 0x76,
- DW_AT_call_site_parameter = 0x77,
- DW_AT_tail_call = 0x78,
- DW_AT_all_tail_call_sites = 0x79,
- DW_AT_all_call_sites = 0x7a,
- DW_AT_all_source_call_sites = 0x7b,
- DW_AT_rank = 0x7c,
- DW_AT_string_bitsize = 0x7d,
- DW_AT_string_byte_size = 0x7e,
- DW_AT_reference = 0x7f,
- DW_AT_rvalue_reference = 0x80,
- DW_AT_noreturn = 0x81,
- DW_AT_alignment = 0x82,
-#endif
- DW_AT_lo_user = 0x2000,
- DW_AT_hi_user = 0xffff
-};
-
-enum Form : uint8_t {
- DW_FORM_addr = 0x01,
- DW_FORM_block2 = 0x03,
- DW_FORM_block4 = 0x04,
- DW_FORM_data2 = 0x05,
- DW_FORM_data4 = 0x06,
- DW_FORM_data8 = 0x07,
- DW_FORM_string = 0x08,
- DW_FORM_block = 0x09,
- DW_FORM_block1 = 0x0a,
- DW_FORM_data1 = 0x0b,
- DW_FORM_flag = 0x0c,
- DW_FORM_sdata = 0x0d,
- DW_FORM_strp = 0x0e,
- DW_FORM_udata = 0x0f,
- DW_FORM_ref_addr = 0x10,
- DW_FORM_ref1 = 0x11,
- DW_FORM_ref2 = 0x12,
- DW_FORM_ref4 = 0x13,
- DW_FORM_ref8 = 0x14,
- DW_FORM_ref_udata = 0x15,
- DW_FORM_indirect = 0x16,
- DW_FORM_sec_offset = 0x17,
- DW_FORM_exprloc = 0x18,
- DW_FORM_flag_present = 0x19,
- DW_FORM_ref_sig8 = 0x20
-};
-
-enum Operation : uint16_t {
- DW_OP_addr = 0x03,
- DW_OP_deref = 0x06,
- DW_OP_const1u = 0x08,
- DW_OP_const1s = 0x09,
- DW_OP_const2u = 0x0a,
- DW_OP_const2s = 0x0b,
- DW_OP_const4u = 0x0c,
- DW_OP_const4s = 0x0d,
- DW_OP_const8u = 0x0e,
- DW_OP_const8s = 0x0f,
- DW_OP_constu = 0x10,
- DW_OP_consts = 0x11,
- DW_OP_dup = 0x12,
- DW_OP_drop = 0x13,
- DW_OP_over = 0x14,
- DW_OP_pick = 0x15,
- DW_OP_swap = 0x16,
- DW_OP_rot = 0x17,
- DW_OP_xderef = 0x18,
- DW_OP_abs = 0x19,
- DW_OP_and = 0x1a,
- DW_OP_div = 0x1b,
- DW_OP_minus = 0x1c,
- DW_OP_mod = 0x1d,
- DW_OP_mul = 0x1e,
- DW_OP_neg = 0x1f,
- DW_OP_not = 0x20,
- DW_OP_or = 0x21,
- DW_OP_plus = 0x22,
- DW_OP_plus_uconst = 0x23,
- DW_OP_shl = 0x24,
- DW_OP_shr = 0x25,
- DW_OP_shra = 0x26,
- DW_OP_xor = 0x27,
- DW_OP_skip = 0x2f,
- DW_OP_bra = 0x28,
- DW_OP_eq = 0x29,
- DW_OP_ge = 0x2a,
- DW_OP_gt = 0x2b,
- DW_OP_le = 0x2c,
- DW_OP_lt = 0x2d,
- DW_OP_ne = 0x2e,
- DW_OP_lit0 = 0x30,
- DW_OP_lit1 = 0x31,
- DW_OP_lit2 = 0x32,
- DW_OP_lit3 = 0x33,
- DW_OP_lit4 = 0x34,
- DW_OP_lit5 = 0x35,
- DW_OP_lit6 = 0x36,
- DW_OP_lit7 = 0x37,
- DW_OP_lit8 = 0x38,
- DW_OP_lit9 = 0x39,
- DW_OP_lit10 = 0x3a,
- DW_OP_lit11 = 0x3b,
- DW_OP_lit12 = 0x3c,
- DW_OP_lit13 = 0x3d,
- DW_OP_lit14 = 0x3e,
- DW_OP_lit15 = 0x3f,
- DW_OP_lit16 = 0x40,
- DW_OP_lit17 = 0x41,
- DW_OP_lit18 = 0x42,
- DW_OP_lit19 = 0x43,
- DW_OP_lit20 = 0x44,
- DW_OP_lit21 = 0x45,
- DW_OP_lit22 = 0x46,
- DW_OP_lit23 = 0x47,
- DW_OP_lit24 = 0x48,
- DW_OP_lit25 = 0x49,
- DW_OP_lit26 = 0x4a,
- DW_OP_lit27 = 0x4b,
- DW_OP_lit28 = 0x4c,
- DW_OP_lit29 = 0x4d,
- DW_OP_lit30 = 0x4e,
- DW_OP_lit31 = 0x4f,
- DW_OP_reg0 = 0x50,
- DW_OP_reg1 = 0x51,
- DW_OP_reg2 = 0x52,
- DW_OP_reg3 = 0x53,
- DW_OP_reg4 = 0x54,
- DW_OP_reg5 = 0x55,
- DW_OP_reg6 = 0x56,
- DW_OP_reg7 = 0x57,
- DW_OP_reg8 = 0x58,
- DW_OP_reg9 = 0x59,
- DW_OP_reg10 = 0x5a,
- DW_OP_reg11 = 0x5b,
- DW_OP_reg12 = 0x5c,
- DW_OP_reg13 = 0x5d,
- DW_OP_reg14 = 0x5e,
- DW_OP_reg15 = 0x5f,
- DW_OP_reg16 = 0x60,
- DW_OP_reg17 = 0x61,
- DW_OP_reg18 = 0x62,
- DW_OP_reg19 = 0x63,
- DW_OP_reg20 = 0x64,
- DW_OP_reg21 = 0x65,
- DW_OP_reg22 = 0x66,
- DW_OP_reg23 = 0x67,
- DW_OP_reg24 = 0x68,
- DW_OP_reg25 = 0x69,
- DW_OP_reg26 = 0x6a,
- DW_OP_reg27 = 0x6b,
- DW_OP_reg28 = 0x6c,
- DW_OP_reg29 = 0x6d,
- DW_OP_reg30 = 0x6e,
- DW_OP_reg31 = 0x6f,
- DW_OP_breg0 = 0x70,
- DW_OP_breg1 = 0x71,
- DW_OP_breg2 = 0x72,
- DW_OP_breg3 = 0x73,
- DW_OP_breg4 = 0x74,
- DW_OP_breg5 = 0x75,
- DW_OP_breg6 = 0x76,
- DW_OP_breg7 = 0x77,
- DW_OP_breg8 = 0x78,
- DW_OP_breg9 = 0x79,
- DW_OP_breg10 = 0x7a,
- DW_OP_breg11 = 0x7b,
- DW_OP_breg12 = 0x7c,
- DW_OP_breg13 = 0x7d,
- DW_OP_breg14 = 0x7e,
- DW_OP_breg15 = 0x7f,
- DW_OP_breg16 = 0x80,
- DW_OP_breg17 = 0x81,
- DW_OP_breg18 = 0x82,
- DW_OP_breg19 = 0x83,
- DW_OP_breg20 = 0x84,
- DW_OP_breg21 = 0x85,
- DW_OP_breg22 = 0x86,
- DW_OP_breg23 = 0x87,
- DW_OP_breg24 = 0x88,
- DW_OP_breg25 = 0x89,
- DW_OP_breg26 = 0x8a,
- DW_OP_breg27 = 0x8b,
- DW_OP_breg28 = 0x8c,
- DW_OP_breg29 = 0x8d,
- DW_OP_breg30 = 0x8e,
- DW_OP_breg31 = 0x8f,
- DW_OP_regx = 0x90,
- DW_OP_fbreg = 0x91,
- DW_OP_bregx = 0x92,
- DW_OP_piece = 0x93,
- DW_OP_deref_size = 0x94,
- DW_OP_xderef_size = 0x95,
- DW_OP_nop = 0x96,
- DW_OP_push_object_address = 0x97,
- DW_OP_call2 = 0x98,
- DW_OP_call4 = 0x99,
- DW_OP_call_ref = 0x9a,
- DW_OP_form_tls_address = 0x9b,
- DW_OP_call_frame_cfa = 0x9c,
- DW_OP_bit_piece = 0x9d,
- DW_OP_implicit_value = 0x9e,
- DW_OP_stack_value = 0x9f,
-#ifdef INCLUDE_DWARF5_VALUES
- // Values to be added in Dwarf 5. Final value not yet specified. Values listed
- // may be different than other implementations. Use with caution.
- // TODO Update these values when Dwarf 5 is released.
- DW_OP_entry_value = 0xa0,
- DW_OP_const_type = 0xa1,
- DW_OP_regval_type = 0xa2,
- DW_OP_deref_type = 0xa3,
- DW_OP_xderef_type = 0xa4,
- DW_OP_convert = 0xa5,
- DW_OP_reinterpret = 0xa6,
-#endif
- DW_OP_lo_user = 0xe0,
- DW_OP_hi_user = 0xff
-};
-
-enum BaseTypeEncoding : uint8_t {
- DW_ATE_address = 0x01,
- DW_ATE_boolean = 0x02,
- DW_ATE_complex_float = 0x03,
- DW_ATE_float = 0x04,
- DW_ATE_signed = 0x05,
- DW_ATE_signed_char = 0x06,
- DW_ATE_unsigned = 0x07,
- DW_ATE_unsigned_char = 0x08,
- DW_ATE_imaginary_float = 0x09,
- DW_ATE_packed_decimal = 0x0a,
- DW_ATE_numeric_string = 0x0b,
- DW_ATE_edited = 0x0c,
- DW_ATE_signed_fixed = 0x0d,
- DW_ATE_unsigned_fixed = 0x0e,
- DW_ATE_decimal_float = 0x0f,
- DW_ATE_UTF = 0x10,
- DW_ATE_lo_user = 0x80,
- DW_ATE_hi_user = 0xff
-};
-
-enum DecimalSign : uint8_t {
- DW_DS_unsigned = 0x01,
- DW_DS_leading_overpunch = 0x02,
- DW_DS_trailing_overpunch = 0x03,
- DW_DS_leading_separate = 0x04,
- DW_DS_trailing_separate = 0x05
-};
-
-enum Endianity : uint8_t {
- DW_END_default = 0x00,
- DW_END_big = 0x01,
- DW_END_little = 0x02,
- DW_END_lo_user = 0x40,
- DW_END_hi_user = 0xff
-};
-
-enum Accessibility : uint8_t {
- DW_ACCESS_public = 0x01,
- DW_ACCESS_protected = 0x02,
- DW_ACCESS_private = 0x03
-};
-
-enum Visibility : uint8_t {
- DW_VIS_local = 0x01,
- DW_VIS_exported = 0x02,
- DW_VIS_qualified = 0x03
-};
-
-enum Virtuality : uint8_t {
- DW_VIRTUALITY_none = 0x00,
- DW_VIRTUALITY_virtual = 0x01,
- DW_VIRTUALITY_pure_virtual = 0x02
-};
-
-enum Language {
- DW_LANG_C89 = 0x01,
- DW_LANG_C = 0x02,
- DW_LANG_Ada83 = 0x03,
- DW_LANG_C_plus_plus = 0x04,
- DW_LANG_Cobol74 = 0x05,
- DW_LANG_Cobol85 = 0x06,
- DW_LANG_Fortran77 = 0x07,
- DW_LANG_Fortran90 = 0x08,
- DW_LANG_Pascal83 = 0x09,
- DW_LANG_Modula2 = 0x0a,
- DW_LANG_Java = 0x0b,
- DW_LANG_C99 = 0x0c,
- DW_LANG_Ada95 = 0x0d,
- DW_LANG_Fortran95 = 0x0e,
- DW_LANG_PLI = 0x0f,
- DW_LANG_ObjC = 0x10,
- DW_LANG_ObjC_plus_plus = 0x11,
- DW_LANG_UPC = 0x12,
- DW_LANG_D = 0x13,
- DW_LANG_Python = 0x14,
-#ifdef INCLUDE_DWARF5_VALUES
- // Values to be added in Dwarf 5. Final value not yet specified. Values listed
- // may be different than other implementations. Use with caution.
- // TODO Update these values when Dwarf 5 is released.
- DW_LANG_OpenCL = 0x15,
- DW_LANG_Go = 0x16,
- DW_LANG_Modula3 = 0x17,
- DW_LANG_Haskell = 0x18,
- DW_LANG_C_plus_plus_03 = 0x19,
- DW_LANG_C_plus_plus_11 = 0x1a,
- DW_LANG_OCaml = 0x1b,
- DW_LANG_Rust = 0x1c,
- DW_LANG_C11 = 0x1d,
- DW_LANG_Swift = 0x1e,
- DW_LANG_Julia = 0x1f,
-#endif
- DW_LANG_lo_user = 0x8000,
- DW_LANG_hi_user = 0xffff
-};
-
-enum Identifier : uint8_t {
- DW_ID_case_sensitive = 0x00,
- DW_ID_up_case = 0x01,
- DW_ID_down_case = 0x02,
- DW_ID_case_insensitive = 0x03
-};
-
-enum CallingConvention : uint8_t {
- DW_CC_normal = 0x01,
- DW_CC_program = 0x02,
- DW_CC_nocall = 0x03,
- DW_CC_lo_user = 0x40,
- DW_CC_hi_user = 0xff
-};
-
-enum Inline : uint8_t {
- DW_INL_not_inlined = 0x00,
- DW_INL_inlined = 0x01,
- DW_INL_declared_not_inlined = 0x02,
- DW_INL_declared_inlined = 0x03
-};
-
-enum ArrayOrdering : uint8_t {
- DW_ORD_row_major = 0x00,
- DW_ORD_col_major = 0x01
-};
-
-enum DiscriminantList : uint8_t {
- DW_DSC_label = 0x00,
- DW_DSC_range = 0x01
-};
-
-enum LineNumberOpcode : uint8_t {
- DW_LNS_copy = 0x01,
- DW_LNS_advance_pc = 0x02,
- DW_LNS_advance_line = 0x03,
- DW_LNS_set_file = 0x04,
- DW_LNS_set_column = 0x05,
- DW_LNS_negate_stmt = 0x06,
- DW_LNS_set_basic_block = 0x07,
- DW_LNS_const_add_pc = 0x08,
- DW_LNS_fixed_advance_pc = 0x09,
- DW_LNS_set_prologue_end = 0x0a,
- DW_LNS_set_epilogue_begin = 0x0b,
- DW_LNS_set_isa = 0x0c
-};
-
-enum LineNumberExtendedOpcode : uint8_t {
- DW_LNE_end_sequence = 0x01,
- DW_LNE_set_address = 0x02,
- DW_LNE_define_file = 0x03,
- DW_LNE_set_discriminator = 0x04,
- DW_LNE_lo_user = 0x80,
- DW_LNE_hi_user = 0xff
-};
-
-#ifdef INCLUDE_DWARF5_VALUES
-enum LineNumberFormat : uint8_t {
- // Values to be added in Dwarf 5. Final value not yet specified. Values listed
- // may be different than other implementations. Use with caution.
- // TODO Update these values when Dwarf 5 is released.
- //
- DW_LNF_path = 0x1,
- DW_LNF_include_index = 0x2,
- DW_LNF_timestamp = 0x3,
- DW_LNF_size = 0x4,
- DW_LNF_MD5 = 0x5,
- DW_LNF_lo_user = 0x2000,
- DW_LNF_hi_user = 0x3fff
-};
-#endif
-
-enum MacroInfo : uint8_t {
- DW_MACINFO_define = 0x01,
- DW_MACINFO_undef = 0x02,
- DW_MACINFO_start_file = 0x03,
- DW_MACINFO_end_file = 0x04,
- DW_MACINFO_vendor_ext = 0xff
-};
-
-#ifdef INCLUDE_DWARF5_VALUES
-enum Macro : uint8_t {
- // Values to be added in Dwarf 5. Final value not yet specified. Values listed
- // may be different than other implementations. Use with caution.
- // TODO Update these values when Dwarf 5 is released.
- DW_MACRO_define = 0x01,
- DW_MACRO_undef = 0x02,
- DW_MACRO_start_file = 0x03,
- DW_MACRO_end_file = 0x04,
- DW_MACRO_define_indirect = 0x05,
- DW_MACRO_undef_indirect = 0x06,
- DW_MACRO_transparent_include = 0x07,
- DW_MACRO_define_indirectx = 0x0b,
- DW_MACRO_undef_indirectx = 0x0c,
- DW_MACRO_lo_user = 0xe0,
- DW_MACRO_hi_user = 0xff
-};
-#endif
-
-const uint32_t CIE_ID_32 = 0xffffffff;
-const uint64_t CIE_ID_64 = 0xffffffffffffffff;
-
-enum CallFrameInstruction : uint8_t {
- DW_CFA_advance_loc = 0x40,
- DW_CFA_offset = 0x80,
- DW_CFA_restore = 0xc0,
- DW_CFA_nop = 0x00,
- DW_CFA_set_loc = 0x01,
- DW_CFA_advance_loc1 = 0x02,
- DW_CFA_advance_loc2 = 0x03,
- DW_CFA_advance_loc4 = 0x04,
- DW_CFA_offset_extended = 0x05,
- DW_CFA_restore_extended = 0x06,
- DW_CFA_undefined = 0x07,
- DW_CFA_same_value = 0x08,
- DW_CFA_register = 0x09,
- DW_CFA_remember_state = 0x0a,
- DW_CFA_restore_state = 0x0b,
- DW_CFA_def_cfa = 0x0c,
- DW_CFA_def_cfa_register = 0x0d,
- DW_CFA_def_cfa_offset = 0x0e,
- DW_CFA_def_cfa_expression = 0x0f,
- DW_CFA_expression = 0x10,
- DW_CFA_offset_extended_sf = 0x11,
- DW_CFA_def_cfa_sf = 0x12,
- DW_CFA_def_cfa_offset_sf = 0x13,
- DW_CFA_val_offset = 0x14,
- DW_CFA_val_offset_sf = 0x15,
- DW_CFA_val_expression = 0x16,
- DW_CFA_lo_user = 0x1c,
- DW_CFA_hi_user = 0x3f
-};
-
-enum ExceptionHeaderValueFormat : uint8_t {
- DW_EH_PE_native = 0x00,
- DW_EH_PE_uleb128 = 0x01,
- DW_EH_PE_udata2 = 0x02,
- DW_EH_PE_udata4 = 0x03,
- DW_EH_PE_udata8 = 0x04,
- DW_EH_PE_sleb128 = 0x09,
- DW_EH_PE_sdata2 = 0x0A,
- DW_EH_PE_sdata4 = 0x0B,
- DW_EH_PE_sdata8 = 0x0C,
- DW_EH_PE_omit = 0xFF,
-};
-
-enum ExceptionHeaderValueApplication : uint8_t {
- DW_EH_PE_absptr = 0x00,
- DW_EH_PE_pcrel = 0x10,
- DW_EH_PE_textrel = 0x20,
- DW_EH_PE_datarel = 0x30,
- DW_EH_PE_funcrel = 0x40,
- DW_EH_PE_aligned = 0x50,
-};
-
-} // namespace dwarf
-} // namespace art
-
-#endif // ART_COMPILER_DEBUG_DWARF_DWARF_CONSTANTS_H_
diff --git a/compiler/debug/dwarf/dwarf_test.cc b/compiler/debug/dwarf/dwarf_test.cc
index 5491596..5946af8 100644
--- a/compiler/debug/dwarf/dwarf_test.cc
+++ b/compiler/debug/dwarf/dwarf_test.cc
@@ -16,11 +16,11 @@
#include "dwarf_test.h"
-#include "debug/dwarf/debug_frame_opcode_writer.h"
-#include "debug/dwarf/debug_info_entry_writer.h"
-#include "debug/dwarf/debug_line_opcode_writer.h"
-#include "debug/dwarf/dwarf_constants.h"
-#include "debug/dwarf/headers.h"
+#include "dwarf/debug_frame_opcode_writer.h"
+#include "dwarf/debug_info_entry_writer.h"
+#include "dwarf/debug_line_opcode_writer.h"
+#include "dwarf/dwarf_constants.h"
+#include "dwarf/headers.h"
#include "gtest/gtest.h"
namespace art {
diff --git a/compiler/debug/dwarf/dwarf_test.h b/compiler/debug/dwarf/dwarf_test.h
index 6b039a7..e51f807 100644
--- a/compiler/debug/dwarf/dwarf_test.h
+++ b/compiler/debug/dwarf/dwarf_test.h
@@ -29,9 +29,9 @@
#include "base/os.h"
#include "base/unix_file/fd_file.h"
#include "common_compiler_test.h"
+#include "elf/elf_builder.h"
#include "gtest/gtest.h"
-#include "linker/elf_builder.h"
-#include "linker/file_output_stream.h"
+#include "stream/file_output_stream.h"
namespace art {
namespace dwarf {
@@ -63,8 +63,8 @@
InstructionSet isa =
(sizeof(typename ElfTypes::Addr) == 8) ? InstructionSet::kX86_64 : InstructionSet::kX86;
ScratchFile file;
- linker::FileOutputStream output_stream(file.GetFile());
- linker::ElfBuilder<ElfTypes> builder(isa, nullptr, &output_stream);
+ FileOutputStream output_stream(file.GetFile());
+ ElfBuilder<ElfTypes> builder(isa, &output_stream);
builder.Start();
if (!debug_info_data_.empty()) {
builder.WriteSection(".debug_info", &debug_info_data_);
diff --git a/compiler/debug/dwarf/expression.h b/compiler/debug/dwarf/expression.h
deleted file mode 100644
index fafc046..0000000
--- a/compiler/debug/dwarf/expression.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2016 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_DEBUG_DWARF_EXPRESSION_H_
-#define ART_COMPILER_DEBUG_DWARF_EXPRESSION_H_
-
-#include <cstddef>
-#include <cstdint>
-
-#include "debug/dwarf/dwarf_constants.h"
-#include "debug/dwarf/writer.h"
-
-namespace art {
-namespace dwarf {
-
-// Writer for DWARF expressions which are used in .debug_info and .debug_loc sections.
-// See the DWARF specification for the precise meaning of the opcodes.
-// If multiple equivalent encodings are possible, it will choose the most compact one.
-// The writer is not exhaustive - it only implements opcodes we have needed so far.
-class Expression : private Writer<> {
- public:
- using Writer<>::data;
- using Writer<>::size;
-
- // Push signed integer on the stack.
- void WriteOpConsts(int32_t value) {
- if (0 <= value && value < 32) {
- PushUint8(DW_OP_lit0 + value);
- } else {
- PushUint8(DW_OP_consts);
- PushSleb128(value);
- }
- }
-
- // Push unsigned integer on the stack.
- void WriteOpConstu(uint32_t value) {
- if (value < 32) {
- PushUint8(DW_OP_lit0 + value);
- } else {
- PushUint8(DW_OP_constu);
- PushUleb128(value);
- }
- }
-
- // Variable is stored in given register.
- void WriteOpReg(uint32_t dwarf_reg_num) {
- if (dwarf_reg_num < 32) {
- PushUint8(DW_OP_reg0 + dwarf_reg_num);
- } else {
- PushUint8(DW_OP_regx);
- PushUleb128(dwarf_reg_num);
- }
- }
-
- // Variable is stored on stack. Also see DW_AT_frame_base.
- void WriteOpFbreg(int32_t stack_offset) {
- PushUint8(DW_OP_fbreg);
- PushSleb128(stack_offset);
- }
-
- // The variable is stored in multiple locations (pieces).
- void WriteOpPiece(uint32_t num_bytes) {
- PushUint8(DW_OP_piece);
- PushUleb128(num_bytes);
- }
-
- // Loads 32-bit or 64-bit value depending on architecture.
- void WriteOpDeref() { PushUint8(DW_OP_deref); }
-
- // Loads value of given byte size.
- void WriteOpDerefSize(uint8_t num_bytes) {
- PushUint8(DW_OP_deref_size);
- PushUint8(num_bytes);
- }
-
- // Pop two values and push their sum.
- void WriteOpPlus() { PushUint8(DW_OP_plus); }
-
- // Add constant value to value on top of stack.
- void WriteOpPlusUconst(uint32_t offset) {
- PushUint8(DW_OP_plus_uconst);
- PushUleb128(offset);
- }
-
- // Negate top of stack.
- void WriteOpNeg() { PushUint8(DW_OP_neg); }
-
- // Pop two values and push their bitwise-AND.
- void WriteOpAnd() { PushUint8(DW_OP_and); }
-
- // Push stack base pointer as determined from .debug_frame.
- void WriteOpCallFrameCfa() { PushUint8(DW_OP_call_frame_cfa); }
-
- // Push address of the variable we are working with.
- void WriteOpPushObjectAddress() { PushUint8(DW_OP_push_object_address); }
-
- // Return the top stack as the value of the variable.
- // Otherwise, the top of stack is the variable's location.
- void WriteOpStackValue() { PushUint8(DW_OP_stack_value); }
-
- explicit Expression(std::vector<uint8_t>* buffer) : Writer<>(buffer) {
- buffer->clear();
- }
-};
-} // namespace dwarf
-} // namespace art
-
-#endif // ART_COMPILER_DEBUG_DWARF_EXPRESSION_H_
diff --git a/compiler/debug/dwarf/headers.h b/compiler/debug/dwarf/headers.h
deleted file mode 100644
index 3cc8ad8..0000000
--- a/compiler/debug/dwarf/headers.h
+++ /dev/null
@@ -1,162 +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_DEBUG_DWARF_HEADERS_H_
-#define ART_COMPILER_DEBUG_DWARF_HEADERS_H_
-
-#include <cstdint>
-
-#include "base/array_ref.h"
-#include "debug/dwarf/debug_frame_opcode_writer.h"
-#include "debug/dwarf/debug_info_entry_writer.h"
-#include "debug/dwarf/debug_line_opcode_writer.h"
-#include "debug/dwarf/dwarf_constants.h"
-#include "debug/dwarf/register.h"
-#include "debug/dwarf/writer.h"
-
-namespace art {
-namespace dwarf {
-
-// Note that all headers start with 32-bit length.
-// DWARF also supports 64-bit lengths, but we never use that.
-// It is intended to support very large debug sections (>4GB),
-// and compilers are expected *not* to use it by default.
-// In particular, it is not related to machine architecture.
-
-// Write common information entry (CIE) to .debug_frame or .eh_frame section.
-template<typename Vector>
-void WriteCIE(bool is64bit,
- Reg return_address_register,
- const DebugFrameOpCodeWriter<Vector>& opcodes,
- std::vector<uint8_t>* buffer) {
- static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type");
-
- Writer<> writer(buffer);
- size_t cie_header_start_ = writer.data()->size();
- writer.PushUint32(0); // Length placeholder.
- writer.PushUint32(0xFFFFFFFF); // CIE id.
- writer.PushUint8(1); // Version.
- writer.PushString("zR");
- writer.PushUleb128(DebugFrameOpCodeWriter<Vector>::kCodeAlignmentFactor);
- writer.PushSleb128(DebugFrameOpCodeWriter<Vector>::kDataAlignmentFactor);
- writer.PushUleb128(return_address_register.num()); // ubyte in DWARF2.
- writer.PushUleb128(1); // z: Augmentation data size.
- if (is64bit) {
- writer.PushUint8(DW_EH_PE_absptr | DW_EH_PE_udata8); // R: Pointer encoding.
- } else {
- writer.PushUint8(DW_EH_PE_absptr | DW_EH_PE_udata4); // R: Pointer encoding.
- }
- writer.PushData(opcodes.data());
- writer.Pad(is64bit ? 8 : 4);
- writer.UpdateUint32(cie_header_start_, writer.data()->size() - cie_header_start_ - 4);
-}
-
-// Write frame description entry (FDE) to .debug_frame or .eh_frame section.
-inline
-void WriteFDE(bool is64bit,
- uint64_t cie_pointer, // Offset of relevant CIE in debug_frame setcion.
- uint64_t code_address,
- uint64_t code_size,
- const ArrayRef<const uint8_t>& opcodes,
- /*inout*/ std::vector<uint8_t>* buffer) {
- Writer<> writer(buffer);
- size_t fde_header_start = writer.data()->size();
- writer.PushUint32(0); // Length placeholder.
- writer.PushUint32(cie_pointer);
- // Relocate code_address if it has absolute value.
- if (is64bit) {
- writer.PushUint64(code_address);
- writer.PushUint64(code_size);
- } else {
- writer.PushUint32(code_address);
- writer.PushUint32(code_size);
- }
- writer.PushUleb128(0); // Augmentation data size.
- writer.PushData(opcodes.data(), opcodes.size());
- writer.Pad(is64bit ? 8 : 4);
- writer.UpdateUint32(fde_header_start, writer.data()->size() - fde_header_start - 4);
-}
-
-// Write compilation unit (CU) to .debug_info section.
-template<typename Vector>
-void WriteDebugInfoCU(uint32_t debug_abbrev_offset,
- const DebugInfoEntryWriter<Vector>& entries,
- std::vector<uint8_t>* debug_info) {
- static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type");
-
- Writer<> writer(debug_info);
- size_t start = writer.data()->size();
- writer.PushUint32(0); // Length placeholder.
- writer.PushUint16(4); // Version.
- writer.PushUint32(debug_abbrev_offset);
- writer.PushUint8(entries.Is64bit() ? 8 : 4);
- size_t entries_offset = writer.data()->size();
- DCHECK_EQ(entries_offset, DebugInfoEntryWriter<Vector>::kCompilationUnitHeaderSize);
- writer.PushData(entries.data());
- writer.UpdateUint32(start, writer.data()->size() - start - 4);
-}
-
-struct FileEntry {
- std::string file_name;
- int directory_index;
- int modification_time;
- int file_size;
-};
-
-// Write line table to .debug_line section.
-template<typename Vector>
-void WriteDebugLineTable(const std::vector<std::string>& include_directories,
- const std::vector<FileEntry>& files,
- const DebugLineOpCodeWriter<Vector>& opcodes,
- std::vector<uint8_t>* debug_line) {
- static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type");
-
- Writer<> writer(debug_line);
- size_t header_start = writer.data()->size();
- writer.PushUint32(0); // Section-length placeholder.
- writer.PushUint16(3); // .debug_line version.
- size_t header_length_pos = writer.data()->size();
- writer.PushUint32(0); // Header-length placeholder.
- writer.PushUint8(1 << opcodes.GetCodeFactorBits());
- writer.PushUint8(DebugLineOpCodeWriter<Vector>::kDefaultIsStmt ? 1 : 0);
- writer.PushInt8(DebugLineOpCodeWriter<Vector>::kLineBase);
- writer.PushUint8(DebugLineOpCodeWriter<Vector>::kLineRange);
- writer.PushUint8(DebugLineOpCodeWriter<Vector>::kOpcodeBase);
- static const int opcode_lengths[DebugLineOpCodeWriter<Vector>::kOpcodeBase] = {
- 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 };
- for (int i = 1; i < DebugLineOpCodeWriter<Vector>::kOpcodeBase; i++) {
- writer.PushUint8(opcode_lengths[i]);
- }
- for (const std::string& directory : include_directories) {
- writer.PushData(directory.data(), directory.size() + 1);
- }
- writer.PushUint8(0); // Terminate include_directories list.
- for (const FileEntry& file : files) {
- writer.PushData(file.file_name.data(), file.file_name.size() + 1);
- writer.PushUleb128(file.directory_index);
- writer.PushUleb128(file.modification_time);
- writer.PushUleb128(file.file_size);
- }
- writer.PushUint8(0); // Terminate file list.
- writer.UpdateUint32(header_length_pos, writer.data()->size() - header_length_pos - 4);
- writer.PushData(opcodes.data());
- writer.UpdateUint32(header_start, writer.data()->size() - header_start - 4);
-}
-
-} // namespace dwarf
-} // namespace art
-
-#endif // ART_COMPILER_DEBUG_DWARF_HEADERS_H_
diff --git a/compiler/debug/dwarf/register.h b/compiler/debug/dwarf/register.h
deleted file mode 100644
index 24bacac..0000000
--- a/compiler/debug/dwarf/register.h
+++ /dev/null
@@ -1,62 +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_DEBUG_DWARF_REGISTER_H_
-#define ART_COMPILER_DEBUG_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 cannot 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.
- // libunwind might struggle with the new mapping as well.
-
- static Reg ArmCore(int num) { return Reg(num); } // R0-R15.
- static Reg ArmFp(int num) { return Reg(64 + num); } // S0–S31.
- static Reg ArmDp(int num) { return Reg(256 + num); } // D0–D31.
- static Reg Arm64Core(int num) { return Reg(num); } // X0-X31.
- 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 MipsFp(int num) { return Reg(32 + num); }
- static Reg Mips64Fp(int num) { return Reg(32 + 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_DEBUG_DWARF_REGISTER_H_
diff --git a/compiler/debug/dwarf/writer.h b/compiler/debug/dwarf/writer.h
deleted file mode 100644
index c09d97a..0000000
--- a/compiler/debug/dwarf/writer.h
+++ /dev/null
@@ -1,184 +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_DEBUG_DWARF_WRITER_H_
-#define ART_COMPILER_DEBUG_DWARF_WRITER_H_
-
-#include <type_traits>
-#include <vector>
-
-#include <android-base/logging.h>
-
-#include "base/bit_utils.h"
-#include "base/leb128.h"
-
-namespace art {
-namespace dwarf {
-
-// The base class for all DWARF writers.
-template <typename Vector = std::vector<uint8_t>>
-class Writer {
- static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type");
-
- 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 uint8_t* ptr, size_t num_bytes) {
- data_->insert(data_->end(), ptr, ptr + num_bytes);
- }
-
- void PushData(const char* ptr, size_t num_bytes) {
- data_->insert(data_->end(), ptr, ptr + num_bytes);
- }
-
- void PushData(const Vector* buffer) {
- data_->insert(data_->end(), buffer->begin(), buffer->end());
- }
-
- 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 UpdateUleb128(size_t offset, uint32_t value) {
- DCHECK_LE(offset + UnsignedLeb128Size(value), data_->size());
- UpdateUnsignedLeb128(data_->data() + offset, value);
- }
-
- void Pop() {
- return data_->pop_back();
- }
-
- void Pad(int alignment) {
- DCHECK_NE(alignment, 0);
- data_->resize(RoundUp(data_->size(), alignment), 0);
- }
-
- const Vector* data() const {
- return data_;
- }
-
- size_t size() const {
- return data_->size();
- }
-
- explicit Writer(Vector* buffer) : data_(buffer) { }
-
- private:
- Vector* const data_;
-
- DISALLOW_COPY_AND_ASSIGN(Writer);
-};
-
-} // namespace dwarf
-} // namespace art
-
-#endif // ART_COMPILER_DEBUG_DWARF_WRITER_H_
diff --git a/compiler/debug/elf_debug_frame_writer.h b/compiler/debug/elf_debug_frame_writer.h
index 1f827ea..44b70ff 100644
--- a/compiler/debug/elf_debug_frame_writer.h
+++ b/compiler/debug/elf_debug_frame_writer.h
@@ -20,11 +20,11 @@
#include <vector>
#include "arch/instruction_set.h"
-#include "debug/dwarf/debug_frame_opcode_writer.h"
-#include "debug/dwarf/dwarf_constants.h"
-#include "debug/dwarf/headers.h"
#include "debug/method_debug_info.h"
-#include "linker/elf_builder.h"
+#include "dwarf/debug_frame_opcode_writer.h"
+#include "dwarf/dwarf_constants.h"
+#include "dwarf/headers.h"
+#include "elf/elf_builder.h"
namespace art {
namespace debug {
@@ -166,7 +166,7 @@
}
template<typename ElfTypes>
-void WriteCFISection(linker::ElfBuilder<ElfTypes>* builder,
+void WriteCFISection(ElfBuilder<ElfTypes>* builder,
const ArrayRef<const MethodDebugInfo>& method_infos) {
typedef typename ElfTypes::Addr Elf_Addr;
diff --git a/compiler/debug/elf_debug_info_writer.h b/compiler/debug/elf_debug_info_writer.h
index 05a4a3e..8eead4e 100644
--- a/compiler/debug/elf_debug_info_writer.h
+++ b/compiler/debug/elf_debug_info_writer.h
@@ -22,17 +22,17 @@
#include <vector>
#include "art_field-inl.h"
-#include "debug/dwarf/debug_abbrev_writer.h"
-#include "debug/dwarf/debug_info_entry_writer.h"
#include "debug/elf_compilation_unit.h"
#include "debug/elf_debug_loc_writer.h"
#include "debug/method_debug_info.h"
#include "dex/code_item_accessors-inl.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file.h"
+#include "dwarf/debug_abbrev_writer.h"
+#include "dwarf/debug_info_entry_writer.h"
+#include "elf/elf_builder.h"
#include "heap_poisoning.h"
#include "linear_alloc.h"
-#include "linker/elf_builder.h"
#include "mirror/array.h"
#include "mirror/class-inl.h"
#include "mirror/class.h"
@@ -59,7 +59,7 @@
using Elf_Addr = typename ElfTypes::Addr;
public:
- explicit ElfDebugInfoWriter(linker::ElfBuilder<ElfTypes>* builder)
+ explicit ElfDebugInfoWriter(ElfBuilder<ElfTypes>* builder)
: builder_(builder),
debug_abbrev_(&debug_abbrev_buffer_) {
}
@@ -80,7 +80,7 @@
}
private:
- linker::ElfBuilder<ElfTypes>* builder_;
+ ElfBuilder<ElfTypes>* builder_;
std::vector<uint8_t> debug_abbrev_buffer_;
dwarf::DebugAbbrevWriter<> debug_abbrev_;
std::vector<uint8_t> debug_loc_;
diff --git a/compiler/debug/elf_debug_line_writer.h b/compiler/debug/elf_debug_line_writer.h
index f95912a..479725b 100644
--- a/compiler/debug/elf_debug_line_writer.h
+++ b/compiler/debug/elf_debug_line_writer.h
@@ -20,12 +20,12 @@
#include <unordered_set>
#include <vector>
-#include "debug/dwarf/debug_line_opcode_writer.h"
-#include "debug/dwarf/headers.h"
#include "debug/elf_compilation_unit.h"
#include "debug/src_map_elem.h"
#include "dex/dex_file-inl.h"
-#include "linker/elf_builder.h"
+#include "dwarf/debug_line_opcode_writer.h"
+#include "dwarf/headers.h"
+#include "elf/elf_builder.h"
#include "oat_file.h"
#include "stack_map.h"
@@ -39,7 +39,7 @@
using Elf_Addr = typename ElfTypes::Addr;
public:
- explicit ElfDebugLineWriter(linker::ElfBuilder<ElfTypes>* builder) : builder_(builder) {
+ explicit ElfDebugLineWriter(ElfBuilder<ElfTypes>* builder) : builder_(builder) {
}
void Start() {
@@ -273,7 +273,7 @@
}
private:
- linker::ElfBuilder<ElfTypes>* builder_;
+ ElfBuilder<ElfTypes>* builder_;
};
} // namespace debug
diff --git a/compiler/debug/elf_debug_loc_writer.h b/compiler/debug/elf_debug_loc_writer.h
index b663291..a5a84bb 100644
--- a/compiler/debug/elf_debug_loc_writer.h
+++ b/compiler/debug/elf_debug_loc_writer.h
@@ -22,9 +22,9 @@
#include "arch/instruction_set.h"
#include "compiled_method.h"
-#include "debug/dwarf/debug_info_entry_writer.h"
-#include "debug/dwarf/register.h"
#include "debug/method_debug_info.h"
+#include "dwarf/debug_info_entry_writer.h"
+#include "dwarf/register.h"
#include "stack_map.h"
namespace art {
diff --git a/compiler/debug/elf_debug_reader.h b/compiler/debug/elf_debug_reader.h
deleted file mode 100644
index 1820e7c..0000000
--- a/compiler/debug/elf_debug_reader.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (C) 2018 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_DEBUG_ELF_DEBUG_READER_H_
-#define ART_COMPILER_DEBUG_ELF_DEBUG_READER_H_
-
-#include "base/array_ref.h"
-#include "debug/dwarf/headers.h"
-#include "elf.h"
-#include "xz_utils.h"
-
-#include <map>
-#include <string_view>
-
-namespace art {
-namespace debug {
-
-// Trivial ELF file reader.
-//
-// It is the bare minimum needed to read mini-debug-info symbols for unwinding.
-// We use it to merge JIT mini-debug-infos together or to prune them after GC.
-template <typename ElfTypes>
-class ElfDebugReader {
- public:
- // Note that the input buffer might be misaligned.
- typedef typename ElfTypes::Ehdr ALIGNED(1) Elf_Ehdr;
- typedef typename ElfTypes::Shdr ALIGNED(1) Elf_Shdr;
- typedef typename ElfTypes::Sym ALIGNED(1) Elf_Sym;
- typedef typename ElfTypes::Addr ALIGNED(1) Elf_Addr;
-
- // Call Frame Information.
- struct CFI {
- uint32_t length; // Length excluding the size of this field.
- int32_t cie_pointer; // Offset in the section or -1 for CIE.
-
- const uint8_t* data() const { return reinterpret_cast<const uint8_t*>(this); }
- size_t size() const { return sizeof(uint32_t) + length; }
- } PACKED(1);
-
- // Common Information Entry.
- struct CIE : public CFI {
- } PACKED(1);
-
- // Frame Description Entry.
- struct FDE : public CFI {
- Elf_Addr sym_addr;
- Elf_Addr sym_size;
- } PACKED(1);
-
- explicit ElfDebugReader(ArrayRef<const uint8_t> file) : file_(file) {
- header_ = Read<Elf_Ehdr>(/*offset=*/ 0);
- CHECK(header_->checkMagic());
- CHECK_EQ(header_->e_ehsize, sizeof(Elf_Ehdr));
- CHECK_EQ(header_->e_shentsize, sizeof(Elf_Shdr));
-
- // Find all ELF sections.
- sections_ = Read<Elf_Shdr>(header_->e_shoff, header_->e_shnum);
- for (const Elf_Shdr& section : sections_) {
- const char* name = Read<char>(sections_[header_->e_shstrndx].sh_offset + section.sh_name);
- section_map_[std::string_view(name)] = §ion;
- }
-
- // Decompressed embedded debug symbols, if any.
- const Elf_Shdr* gnu_debugdata = section_map_[".gnu_debugdata"];
- if (gnu_debugdata != nullptr) {
- auto compressed = Read<uint8_t>(gnu_debugdata->sh_offset, gnu_debugdata->sh_size);
- XzDecompress(compressed, &decompressed_gnu_debugdata_);
- gnu_debugdata_reader_.reset(new ElfDebugReader(decompressed_gnu_debugdata_));
- }
- }
-
- explicit ElfDebugReader(std::vector<uint8_t>& file)
- : ElfDebugReader(ArrayRef<const uint8_t>(file)) {
- }
-
- const Elf_Ehdr* GetHeader() { return header_; }
-
- ArrayRef<Elf_Shdr> GetSections() { return sections_; }
-
- const Elf_Shdr* GetSection(const char* name) { return section_map_[name]; }
-
- template <typename VisitSym>
- void VisitFunctionSymbols(VisitSym visit_sym) {
- const Elf_Shdr* symtab = GetSection(".symtab");
- const Elf_Shdr* strtab = GetSection(".strtab");
- const Elf_Shdr* text = GetSection(".text");
- if (symtab != nullptr && strtab != nullptr) {
- CHECK_EQ(symtab->sh_entsize, sizeof(Elf_Sym));
- size_t count = symtab->sh_size / sizeof(Elf_Sym);
- for (const Elf_Sym& symbol : Read<Elf_Sym>(symtab->sh_offset, count)) {
- if (symbol.getType() == STT_FUNC && §ions_[symbol.st_shndx] == text) {
- visit_sym(symbol, Read<char>(strtab->sh_offset + symbol.st_name));
- }
- }
- }
- if (gnu_debugdata_reader_ != nullptr) {
- gnu_debugdata_reader_->VisitFunctionSymbols(visit_sym);
- }
- }
-
- template <typename VisitSym>
- void VisitDynamicSymbols(VisitSym visit_sym) {
- const Elf_Shdr* dynsym = GetSection(".dynsym");
- const Elf_Shdr* dynstr = GetSection(".dynstr");
- if (dynsym != nullptr && dynstr != nullptr) {
- CHECK_EQ(dynsym->sh_entsize, sizeof(Elf_Sym));
- size_t count = dynsym->sh_size / sizeof(Elf_Sym);
- for (const Elf_Sym& symbol : Read<Elf_Sym>(dynsym->sh_offset, count)) {
- visit_sym(symbol, Read<char>(dynstr->sh_offset + symbol.st_name));
- }
- }
- }
-
- template <typename VisitCIE, typename VisitFDE>
- void VisitDebugFrame(VisitCIE visit_cie, VisitFDE visit_fde) {
- const Elf_Shdr* debug_frame = GetSection(".debug_frame");
- if (debug_frame != nullptr) {
- for (size_t offset = 0; offset < debug_frame->sh_size;) {
- const CFI* entry = Read<CFI>(debug_frame->sh_offset + offset);
- DCHECK_LE(entry->size(), debug_frame->sh_size - offset);
- if (entry->cie_pointer == -1) {
- visit_cie(Read<CIE>(debug_frame->sh_offset + offset));
- } else {
- const FDE* fde = Read<FDE>(debug_frame->sh_offset + offset);
- visit_fde(fde, Read<CIE>(debug_frame->sh_offset + fde->cie_pointer));
- }
- offset += entry->size();
- }
- }
- if (gnu_debugdata_reader_ != nullptr) {
- gnu_debugdata_reader_->VisitDebugFrame(visit_cie, visit_fde);
- }
- }
-
- private:
- template<typename T>
- const T* Read(size_t offset) {
- DCHECK_LE(offset + sizeof(T), file_.size());
- return reinterpret_cast<const T*>(file_.data() + offset);
- }
-
- template<typename T>
- ArrayRef<const T> Read(size_t offset, size_t count) {
- DCHECK_LE(offset + count * sizeof(T), file_.size());
- return ArrayRef<const T>(Read<T>(offset), count);
- }
-
- ArrayRef<const uint8_t> const file_;
- const Elf_Ehdr* header_;
- ArrayRef<const Elf_Shdr> sections_;
- std::unordered_map<std::string_view, const Elf_Shdr*> section_map_;
- std::vector<uint8_t> decompressed_gnu_debugdata_;
- std::unique_ptr<ElfDebugReader> gnu_debugdata_reader_;
-
- DISALLOW_COPY_AND_ASSIGN(ElfDebugReader);
-};
-
-} // namespace debug
-} // namespace art
-#endif // ART_COMPILER_DEBUG_ELF_DEBUG_READER_H_
diff --git a/compiler/debug/elf_debug_writer.cc b/compiler/debug/elf_debug_writer.cc
index 3b7363b..cc74717 100644
--- a/compiler/debug/elf_debug_writer.cc
+++ b/compiler/debug/elf_debug_writer.cc
@@ -22,20 +22,20 @@
#include "base/array_ref.h"
#include "base/stl_util.h"
-#include "debug/dwarf/dwarf_constants.h"
#include "debug/elf_compilation_unit.h"
#include "debug/elf_debug_frame_writer.h"
#include "debug/elf_debug_info_writer.h"
#include "debug/elf_debug_line_writer.h"
#include "debug/elf_debug_loc_writer.h"
-#include "debug/elf_debug_reader.h"
#include "debug/elf_symtab_writer.h"
#include "debug/method_debug_info.h"
-#include "debug/xz_utils.h"
-#include "elf.h"
-#include "linker/elf_builder.h"
-#include "linker/vector_output_stream.h"
+#include "dwarf/dwarf_constants.h"
+#include "elf/elf.h"
+#include "elf/elf_builder.h"
+#include "elf/elf_debug_reader.h"
+#include "elf/xz_utils.h"
#include "oat.h"
+#include "stream/vector_output_stream.h"
namespace art {
namespace debug {
@@ -43,7 +43,7 @@
using ElfRuntimeTypes = std::conditional<sizeof(void*) == 4, ElfTypes32, ElfTypes64>::type;
template <typename ElfTypes>
-void WriteDebugInfo(linker::ElfBuilder<ElfTypes>* builder,
+void WriteDebugInfo(ElfBuilder<ElfTypes>* builder,
const DebugInfo& debug_info) {
// Write .strtab and .symtab.
WriteDebugSymbols(builder, /* mini-debug-info= */ false, debug_info);
@@ -112,7 +112,7 @@
template <typename ElfTypes>
static std::vector<uint8_t> MakeMiniDebugInfoInternal(
InstructionSet isa,
- const InstructionSetFeatures* features,
+ const InstructionSetFeatures* features ATTRIBUTE_UNUSED,
typename ElfTypes::Addr text_section_address,
size_t text_section_size,
typename ElfTypes::Addr dex_section_address,
@@ -120,9 +120,8 @@
const DebugInfo& debug_info) {
std::vector<uint8_t> buffer;
buffer.reserve(KB);
- linker::VectorOutputStream out("Mini-debug-info ELF file", &buffer);
- std::unique_ptr<linker::ElfBuilder<ElfTypes>> builder(
- new linker::ElfBuilder<ElfTypes>(isa, features, &out));
+ VectorOutputStream out("Mini-debug-info ELF file", &buffer);
+ std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, &out));
builder->Start(/* write_program_headers= */ false);
// Mirror ELF sections as NOBITS since the added symbols will reference them.
if (text_section_size != 0) {
@@ -174,7 +173,7 @@
std::vector<uint8_t> MakeElfFileForJIT(
InstructionSet isa,
- const InstructionSetFeatures* features,
+ const InstructionSetFeatures* features ATTRIBUTE_UNUSED,
bool mini_debug_info,
const MethodDebugInfo& method_info) {
using ElfTypes = ElfRuntimeTypes;
@@ -184,9 +183,8 @@
debug_info.compiled_methods = ArrayRef<const MethodDebugInfo>(&method_info, 1);
std::vector<uint8_t> buffer;
buffer.reserve(KB);
- linker::VectorOutputStream out("Debug ELF file", &buffer);
- std::unique_ptr<linker::ElfBuilder<ElfTypes>> builder(
- new linker::ElfBuilder<ElfTypes>(isa, features, &out));
+ VectorOutputStream out("Debug ELF file", &buffer);
+ std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, &out));
// No program headers since the ELF file is not linked and has no allocated sections.
builder->Start(/* write_program_headers= */ false);
builder->GetText()->AllocateVirtualMemory(method_info.code_address, method_info.code_size);
@@ -230,7 +228,7 @@
// Combine several mini-debug-info ELF files into one, while filtering some symbols.
std::vector<uint8_t> PackElfFileForJIT(
InstructionSet isa,
- const InstructionSetFeatures* features,
+ const InstructionSetFeatures* features ATTRIBUTE_UNUSED,
std::vector<ArrayRef<const uint8_t>>& added_elf_files,
std::vector<const void*>& removed_symbols,
/*out*/ size_t* num_symbols) {
@@ -250,9 +248,8 @@
std::vector<uint8_t> inner_elf_file;
{
inner_elf_file.reserve(1 * KB); // Approximate size of ELF file with a single symbol.
- linker::VectorOutputStream out("Mini-debug-info ELF file for JIT", &inner_elf_file);
- std::unique_ptr<linker::ElfBuilder<ElfTypes>> builder(
- new linker::ElfBuilder<ElfTypes>(isa, features, &out));
+ VectorOutputStream out("Mini-debug-info ELF file for JIT", &inner_elf_file);
+ std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, &out));
builder->Start(/*write_program_headers=*/ false);
auto* text = builder->GetText();
auto* strtab = builder->GetStrTab();
@@ -328,9 +325,8 @@
XzCompress(ArrayRef<const uint8_t>(inner_elf_file), &gnu_debugdata);
outer_elf_file.reserve(KB + gnu_debugdata.size());
- linker::VectorOutputStream out("Mini-debug-info ELF file for JIT", &outer_elf_file);
- std::unique_ptr<linker::ElfBuilder<ElfTypes>> builder(
- new linker::ElfBuilder<ElfTypes>(isa, features, &out));
+ VectorOutputStream out("Mini-debug-info ELF file for JIT", &outer_elf_file);
+ std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, &out));
builder->Start(/*write_program_headers=*/ false);
if (max_address > min_address) {
builder->GetText()->AllocateVirtualMemory(min_address, max_address - min_address);
@@ -345,16 +341,15 @@
std::vector<uint8_t> WriteDebugElfFileForClasses(
InstructionSet isa,
- const InstructionSetFeatures* features,
+ const InstructionSetFeatures* features ATTRIBUTE_UNUSED,
const ArrayRef<mirror::Class*>& types)
REQUIRES_SHARED(Locks::mutator_lock_) {
using ElfTypes = ElfRuntimeTypes;
CHECK_EQ(sizeof(ElfTypes::Addr), static_cast<size_t>(GetInstructionSetPointerSize(isa)));
std::vector<uint8_t> buffer;
buffer.reserve(KB);
- linker::VectorOutputStream out("Debug ELF file", &buffer);
- std::unique_ptr<linker::ElfBuilder<ElfTypes>> builder(
- new linker::ElfBuilder<ElfTypes>(isa, features, &out));
+ VectorOutputStream out("Debug ELF file", &buffer);
+ std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, &out));
// No program headers since the ELF file is not linked and has no allocated sections.
builder->Start(/* write_program_headers= */ false);
ElfDebugInfoWriter<ElfTypes> info_writer(builder.get());
@@ -370,10 +365,10 @@
// Explicit instantiations
template void WriteDebugInfo<ElfTypes32>(
- linker::ElfBuilder<ElfTypes32>* builder,
+ ElfBuilder<ElfTypes32>* builder,
const DebugInfo& debug_info);
template void WriteDebugInfo<ElfTypes64>(
- linker::ElfBuilder<ElfTypes64>* builder,
+ ElfBuilder<ElfTypes64>* builder,
const DebugInfo& debug_info);
} // namespace debug
diff --git a/compiler/debug/elf_debug_writer.h b/compiler/debug/elf_debug_writer.h
index 90580b4..14a5edb 100644
--- a/compiler/debug/elf_debug_writer.h
+++ b/compiler/debug/elf_debug_writer.h
@@ -19,12 +19,13 @@
#include <vector>
+#include "arch/instruction_set_features.h"
#include "base/array_ref.h"
#include "base/macros.h"
#include "base/mutex.h"
-#include "debug/dwarf/dwarf_constants.h"
#include "debug/debug_info.h"
-#include "linker/elf_builder.h"
+#include "dwarf/dwarf_constants.h"
+#include "elf/elf_builder.h"
namespace art {
class OatHeader;
@@ -36,7 +37,7 @@
template <typename ElfTypes>
void WriteDebugInfo(
- linker::ElfBuilder<ElfTypes>* builder,
+ ElfBuilder<ElfTypes>* builder,
const DebugInfo& debug_info);
std::vector<uint8_t> MakeMiniDebugInfo(
diff --git a/compiler/debug/elf_symtab_writer.h b/compiler/debug/elf_symtab_writer.h
index 7a8e291..2ed3a4b 100644
--- a/compiler/debug/elf_symtab_writer.h
+++ b/compiler/debug/elf_symtab_writer.h
@@ -25,7 +25,7 @@
#include "debug/method_debug_info.h"
#include "dex/dex_file-inl.h"
#include "dex/code_item_accessors.h"
-#include "linker/elf_builder.h"
+#include "elf/elf_builder.h"
namespace art {
namespace debug {
@@ -45,7 +45,7 @@
constexpr const char* kDexFileSymbolName = "$dexfile";
template <typename ElfTypes>
-static void WriteDebugSymbols(linker::ElfBuilder<ElfTypes>* builder,
+static void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder,
bool mini_debug_info,
const DebugInfo& debug_info) {
uint64_t mapping_symbol_address = std::numeric_limits<uint64_t>::max();
diff --git a/compiler/debug/xz_utils.cc b/compiler/debug/xz_utils.cc
deleted file mode 100644
index 5b36209..0000000
--- a/compiler/debug/xz_utils.cc
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2018 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 "xz_utils.h"
-
-#include <vector>
-#include <mutex>
-
-#include "base/array_ref.h"
-#include "base/bit_utils.h"
-#include "base/leb128.h"
-#include "dwarf/writer.h"
-
-// liblzma.
-#include "7zCrc.h"
-#include "Xz.h"
-#include "XzCrc64.h"
-#include "XzEnc.h"
-
-namespace art {
-namespace debug {
-
-constexpr size_t kChunkSize = kPageSize;
-
-static void XzInitCrc() {
- static std::once_flag crc_initialized;
- std::call_once(crc_initialized, []() {
- CrcGenerateTable();
- Crc64GenerateTable();
- });
-}
-
-void XzCompress(ArrayRef<const uint8_t> src, std::vector<uint8_t>* dst) {
- // Configure the compression library.
- XzInitCrc();
- CLzma2EncProps lzma2Props;
- Lzma2EncProps_Init(&lzma2Props);
- lzma2Props.lzmaProps.level = 1; // Fast compression.
- lzma2Props.lzmaProps.reduceSize = src.size(); // Size of data that will be compressed.
- lzma2Props.blockSize = kChunkSize;
- Lzma2EncProps_Normalize(&lzma2Props);
- CXzProps props;
- XzProps_Init(&props);
- props.lzma2Props = lzma2Props;
- // Implement the required interface for communication (written in C so no virtual methods).
- struct XzCallbacks : public ISeqInStream, public ISeqOutStream, public ICompressProgress {
- static SRes ReadImpl(const ISeqInStream* p, void* buf, size_t* size) {
- auto* ctx = static_cast<XzCallbacks*>(const_cast<ISeqInStream*>(p));
- *size = std::min(*size, ctx->src_.size() - ctx->src_pos_);
- memcpy(buf, ctx->src_.data() + ctx->src_pos_, *size);
- ctx->src_pos_ += *size;
- return SZ_OK;
- }
- static size_t WriteImpl(const ISeqOutStream* p, const void* buf, size_t size) {
- auto* ctx = static_cast<const XzCallbacks*>(p);
- const uint8_t* buffer = reinterpret_cast<const uint8_t*>(buf);
- ctx->dst_->insert(ctx->dst_->end(), buffer, buffer + size);
- return size;
- }
- static SRes ProgressImpl(const ICompressProgress* , UInt64, UInt64) {
- return SZ_OK;
- }
- size_t src_pos_;
- ArrayRef<const uint8_t> src_;
- std::vector<uint8_t>* dst_;
- };
- XzCallbacks callbacks;
- callbacks.Read = XzCallbacks::ReadImpl;
- callbacks.Write = XzCallbacks::WriteImpl;
- callbacks.Progress = XzCallbacks::ProgressImpl;
- callbacks.src_pos_ = 0;
- callbacks.src_ = src;
- callbacks.dst_ = dst;
- // Compress.
- SRes res = Xz_Encode(&callbacks, &callbacks, &props, &callbacks);
- CHECK_EQ(res, SZ_OK);
-
- // Decompress the data back and check that we get the original.
- if (kIsDebugBuild) {
- std::vector<uint8_t> decompressed;
- XzDecompress(ArrayRef<const uint8_t>(*dst), &decompressed);
- DCHECK_EQ(decompressed.size(), src.size());
- DCHECK_EQ(memcmp(decompressed.data(), src.data(), src.size()), 0);
- }
-}
-
-void XzDecompress(ArrayRef<const uint8_t> src, std::vector<uint8_t>* dst) {
- XzInitCrc();
- std::unique_ptr<CXzUnpacker> state(new CXzUnpacker());
- ISzAlloc alloc;
- alloc.Alloc = [](ISzAllocPtr, size_t size) { return malloc(size); };
- alloc.Free = [](ISzAllocPtr, void* ptr) { return free(ptr); };
- XzUnpacker_Construct(state.get(), &alloc);
-
- size_t src_offset = 0;
- size_t dst_offset = 0;
- ECoderStatus status;
- do {
- dst->resize(RoundUp(dst_offset + kPageSize / 4, kPageSize));
- size_t src_remaining = src.size() - src_offset;
- size_t dst_remaining = dst->size() - dst_offset;
- int return_val = XzUnpacker_Code(state.get(),
- dst->data() + dst_offset,
- &dst_remaining,
- src.data() + src_offset,
- &src_remaining,
- true,
- CODER_FINISH_ANY,
- &status);
- CHECK_EQ(return_val, SZ_OK);
- src_offset += src_remaining;
- dst_offset += dst_remaining;
- } while (status == CODER_STATUS_NOT_FINISHED);
- CHECK_EQ(src_offset, src.size());
- CHECK(XzUnpacker_IsStreamWasFinished(state.get()));
- XzUnpacker_Free(state.get());
- dst->resize(dst_offset);
-}
-
-} // namespace debug
-} // namespace art
diff --git a/compiler/debug/xz_utils.h b/compiler/debug/xz_utils.h
deleted file mode 100644
index 731b03c..0000000
--- a/compiler/debug/xz_utils.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2018 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_DEBUG_XZ_UTILS_H_
-#define ART_COMPILER_DEBUG_XZ_UTILS_H_
-
-#include <vector>
-
-#include "base/array_ref.h"
-
-namespace art {
-namespace debug {
-
-void XzCompress(ArrayRef<const uint8_t> src, std::vector<uint8_t>* dst);
-void XzDecompress(ArrayRef<const uint8_t> src, std::vector<uint8_t>* dst);
-
-} // namespace debug
-} // namespace art
-
-#endif // ART_COMPILER_DEBUG_XZ_UTILS_H_
diff --git a/compiler/jni/quick/jni_compiler.cc b/compiler/jni/quick/jni_compiler.cc
index bdbf429..7054078 100644
--- a/compiler/jni/quick/jni_compiler.cc
+++ b/compiler/jni/quick/jni_compiler.cc
@@ -32,7 +32,7 @@
#include "base/utils.h"
#include "calling_convention.h"
#include "class_linker.h"
-#include "debug/dwarf/debug_frame_opcode_writer.h"
+#include "dwarf/debug_frame_opcode_writer.h"
#include "dex/dex_file-inl.h"
#include "driver/compiler_options.h"
#include "entrypoints/quick/quick_entrypoints.h"
diff --git a/compiler/linker/buffered_output_stream.cc b/compiler/linker/buffered_output_stream.cc
deleted file mode 100644
index 07066b7..0000000
--- a/compiler/linker/buffered_output_stream.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2013 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 "buffered_output_stream.h"
-
-#include <string.h>
-
-namespace art {
-namespace linker {
-
-BufferedOutputStream::BufferedOutputStream(std::unique_ptr<OutputStream> out)
- : OutputStream(out->GetLocation()), // Before out is moved to out_.
- out_(std::move(out)),
- used_(0) {}
-
-BufferedOutputStream::~BufferedOutputStream() {
- FlushBuffer();
-}
-
-bool BufferedOutputStream::WriteFully(const void* buffer, size_t byte_count) {
- if (byte_count > kBufferSize) {
- if (!FlushBuffer()) {
- return false;
- }
- return out_->WriteFully(buffer, byte_count);
- }
- if (used_ + byte_count > kBufferSize) {
- if (!FlushBuffer()) {
- return false;
- }
- }
- const uint8_t* src = reinterpret_cast<const uint8_t*>(buffer);
- memcpy(&buffer_[used_], src, byte_count);
- used_ += byte_count;
- return true;
-}
-
-bool BufferedOutputStream::Flush() {
- return FlushBuffer() && out_->Flush();
-}
-
-bool BufferedOutputStream::FlushBuffer() {
- bool success = true;
- if (used_ > 0) {
- success = out_->WriteFully(&buffer_[0], used_);
- used_ = 0;
- }
- return success;
-}
-
-off_t BufferedOutputStream::Seek(off_t offset, Whence whence) {
- if (!FlushBuffer()) {
- return -1;
- }
- return out_->Seek(offset, whence);
-}
-
-} // namespace linker
-} // namespace art
diff --git a/compiler/linker/buffered_output_stream.h b/compiler/linker/buffered_output_stream.h
deleted file mode 100644
index cb1c44b..0000000
--- a/compiler/linker/buffered_output_stream.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2013 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_LINKER_BUFFERED_OUTPUT_STREAM_H_
-#define ART_COMPILER_LINKER_BUFFERED_OUTPUT_STREAM_H_
-
-#include <memory>
-
-#include "output_stream.h"
-
-#include "base/globals.h"
-
-namespace art {
-namespace linker {
-
-class BufferedOutputStream final : public OutputStream {
- public:
- explicit BufferedOutputStream(std::unique_ptr<OutputStream> out);
-
- ~BufferedOutputStream() override;
-
- bool WriteFully(const void* buffer, size_t byte_count) override;
-
- off_t Seek(off_t offset, Whence whence) override;
-
- bool Flush() override;
-
- private:
- static const size_t kBufferSize = 8 * KB;
-
- bool FlushBuffer();
-
- std::unique_ptr<OutputStream> const out_;
- uint8_t buffer_[kBufferSize];
- size_t used_;
-
- DISALLOW_COPY_AND_ASSIGN(BufferedOutputStream);
-};
-
-} // namespace linker
-} // namespace art
-
-#endif // ART_COMPILER_LINKER_BUFFERED_OUTPUT_STREAM_H_
diff --git a/compiler/linker/elf_builder.h b/compiler/linker/elf_builder.h
deleted file mode 100644
index 33e1866..0000000
--- a/compiler/linker/elf_builder.h
+++ /dev/null
@@ -1,1079 +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_LINKER_ELF_BUILDER_H_
-#define ART_COMPILER_LINKER_ELF_BUILDER_H_
-
-#include <vector>
-#include <deque>
-
-#include "arch/instruction_set.h"
-#include "arch/mips/instruction_set_features_mips.h"
-#include "base/array_ref.h"
-#include "base/bit_utils.h"
-#include "base/casts.h"
-#include "base/leb128.h"
-#include "base/unix_file/fd_file.h"
-#include "elf_utils.h"
-#include "linker/error_delaying_output_stream.h"
-
-namespace art {
-namespace linker {
-
-// Writes ELF file.
-//
-// The basic layout of the elf file:
-// Elf_Ehdr - The ELF header.
-// Elf_Phdr[] - Program headers for the linker.
-// .note.gnu.build-id - Optional build ID section (SHA-1 digest).
-// .rodata - Oat metadata.
-// .text - Compiled code.
-// .bss - Zero-initialized writeable section.
-// .dex - Reserved NOBITS space for dex-related data.
-// .MIPS.abiflags - MIPS specific section.
-// .dynstr - Names for .dynsym.
-// .dynsym - A few oat-specific dynamic symbols.
-// .hash - Hash-table for .dynsym.
-// .dynamic - Tags which let the linker locate .dynsym.
-// .strtab - Names for .symtab.
-// .symtab - Debug symbols.
-// .debug_frame - Unwind information (CFI).
-// .debug_info - Debug information.
-// .debug_abbrev - Decoding information for .debug_info.
-// .debug_str - Strings for .debug_info.
-// .debug_line - Line number tables.
-// .shstrtab - Names of ELF sections.
-// Elf_Shdr[] - Section headers.
-//
-// Some section are optional (the debug sections in particular).
-//
-// We try write the section data directly into the file without much
-// in-memory buffering. This means we generally write sections based on the
-// dependency order (e.g. .dynamic points to .dynsym which points to .text).
-//
-// In the cases where we need to buffer, we write the larger section first
-// and buffer the smaller one (e.g. .strtab is bigger than .symtab).
-//
-// The debug sections are written last for easier stripping.
-//
-template <typename ElfTypes>
-class ElfBuilder final {
- public:
- static constexpr size_t kMaxProgramHeaders = 16;
- // SHA-1 digest. Not using SHA_DIGEST_LENGTH from openssl/sha.h to avoid
- // spreading this header dependency for just this single constant.
- static constexpr size_t kBuildIdLen = 20;
-
- using Elf_Addr = typename ElfTypes::Addr;
- using Elf_Off = typename ElfTypes::Off;
- using Elf_Word = typename ElfTypes::Word;
- using Elf_Sword = typename ElfTypes::Sword;
- using Elf_Ehdr = typename ElfTypes::Ehdr;
- using Elf_Shdr = typename ElfTypes::Shdr;
- using Elf_Sym = typename ElfTypes::Sym;
- using Elf_Phdr = typename ElfTypes::Phdr;
- using Elf_Dyn = typename ElfTypes::Dyn;
-
- // Base class of all sections.
- class Section : public OutputStream {
- public:
- Section(ElfBuilder<ElfTypes>* owner,
- const std::string& name,
- Elf_Word type,
- Elf_Word flags,
- const Section* link,
- Elf_Word info,
- Elf_Word align,
- Elf_Word entsize)
- : OutputStream(name),
- owner_(owner),
- header_(),
- section_index_(0),
- name_(name),
- link_(link),
- phdr_flags_(PF_R),
- phdr_type_(0) {
- DCHECK_GE(align, 1u);
- header_.sh_type = type;
- header_.sh_flags = flags;
- header_.sh_info = info;
- header_.sh_addralign = align;
- header_.sh_entsize = entsize;
- }
-
- // Allocate chunk of virtual memory for this section from the owning ElfBuilder.
- // This must be done at the start for all SHF_ALLOC sections (i.e. mmaped by linker).
- // It is fine to allocate section but never call Start/End() (e.g. the .bss section).
- void AllocateVirtualMemory(Elf_Word size) {
- AllocateVirtualMemory(owner_->virtual_address_, size);
- }
-
- void AllocateVirtualMemory(Elf_Addr addr, Elf_Word size) {
- CHECK_NE(header_.sh_flags & SHF_ALLOC, 0u);
- Elf_Word align = AddSection();
- CHECK_EQ(header_.sh_addr, 0u);
- header_.sh_addr = RoundUp(addr, align);
- CHECK(header_.sh_size == 0u || header_.sh_size == size);
- header_.sh_size = size;
- CHECK_LE(owner_->virtual_address_, header_.sh_addr);
- owner_->virtual_address_ = header_.sh_addr + header_.sh_size;
- }
-
- // Start writing file data of this section.
- void Start() {
- CHECK(owner_->current_section_ == nullptr);
- Elf_Word align = AddSection();
- CHECK_EQ(header_.sh_offset, 0u);
- header_.sh_offset = owner_->AlignFileOffset(align);
- owner_->current_section_ = this;
- }
-
- // Finish writing file data of this section.
- void End() {
- CHECK(owner_->current_section_ == this);
- Elf_Word position = GetPosition();
- CHECK(header_.sh_size == 0u || header_.sh_size == position);
- header_.sh_size = position;
- owner_->current_section_ = nullptr;
- }
-
- // Get the number of bytes written so far.
- // Only valid while writing the section.
- Elf_Word GetPosition() const {
- CHECK(owner_->current_section_ == this);
- off_t file_offset = owner_->stream_.Seek(0, kSeekCurrent);
- DCHECK_GE(file_offset, (off_t)header_.sh_offset);
- return file_offset - header_.sh_offset;
- }
-
- // Get the location of this section in virtual memory.
- Elf_Addr GetAddress() const {
- DCHECK_NE(header_.sh_flags & SHF_ALLOC, 0u);
- DCHECK_NE(header_.sh_addr, 0u);
- return header_.sh_addr;
- }
-
- // This function always succeeds to simplify code.
- // Use builder's Good() to check the actual status.
- bool WriteFully(const void* buffer, size_t byte_count) override {
- CHECK(owner_->current_section_ == this);
- return owner_->stream_.WriteFully(buffer, byte_count);
- }
-
- // This function always succeeds to simplify code.
- // Use builder's Good() to check the actual status.
- off_t Seek(off_t offset, Whence whence) override {
- // Forward the seek as-is and trust the caller to use it reasonably.
- return owner_->stream_.Seek(offset, whence);
- }
-
- // This function flushes the output and returns whether it succeeded.
- // If there was a previous failure, this does nothing and returns false, i.e. failed.
- bool Flush() override {
- return owner_->stream_.Flush();
- }
-
- Elf_Word GetSectionIndex() const {
- DCHECK_NE(section_index_, 0u);
- return section_index_;
- }
-
- // Returns true if this section has been added.
- bool Exists() const {
- return section_index_ != 0;
- }
-
- protected:
- // Add this section to the list of generated ELF sections (if not there already).
- // It also ensures the alignment is sufficient to generate valid program headers,
- // since that depends on the previous section. It returns the required alignment.
- Elf_Word AddSection() {
- if (section_index_ == 0) {
- std::vector<Section*>& sections = owner_->sections_;
- Elf_Word last = sections.empty() ? PF_R : sections.back()->phdr_flags_;
- if (phdr_flags_ != last) {
- header_.sh_addralign = kPageSize; // Page-align if R/W/X flags changed.
- }
- sections.push_back(this);
- section_index_ = sections.size(); // First ELF section has index 1.
- }
- return owner_->write_program_headers_ ? header_.sh_addralign : 1;
- }
-
- ElfBuilder<ElfTypes>* owner_;
- Elf_Shdr header_;
- Elf_Word section_index_;
- const std::string name_;
- const Section* const link_;
- Elf_Word phdr_flags_;
- Elf_Word phdr_type_;
-
- friend class ElfBuilder;
-
- DISALLOW_COPY_AND_ASSIGN(Section);
- };
-
- class CachedSection : public Section {
- public:
- CachedSection(ElfBuilder<ElfTypes>* owner,
- const std::string& name,
- Elf_Word type,
- Elf_Word flags,
- const Section* link,
- Elf_Word info,
- Elf_Word align,
- Elf_Word entsize)
- : Section(owner, name, type, flags, link, info, align, entsize), cache_() { }
-
- Elf_Word Add(const void* data, size_t length) {
- Elf_Word offset = cache_.size();
- const uint8_t* d = reinterpret_cast<const uint8_t*>(data);
- cache_.insert(cache_.end(), d, d + length);
- return offset;
- }
-
- Elf_Word GetCacheSize() {
- return cache_.size();
- }
-
- void Write() {
- this->WriteFully(cache_.data(), cache_.size());
- cache_.clear();
- cache_.shrink_to_fit();
- }
-
- void WriteCachedSection() {
- this->Start();
- Write();
- this->End();
- }
-
- private:
- std::vector<uint8_t> cache_;
- };
-
- // Writer of .dynstr section.
- class CachedStringSection final : public CachedSection {
- public:
- CachedStringSection(ElfBuilder<ElfTypes>* owner,
- const std::string& name,
- Elf_Word flags,
- Elf_Word align)
- : CachedSection(owner,
- name,
- SHT_STRTAB,
- flags,
- /* link= */ nullptr,
- /* info= */ 0,
- align,
- /* entsize= */ 0) { }
-
- Elf_Word Add(const std::string& name) {
- if (CachedSection::GetCacheSize() == 0u) {
- DCHECK(name.empty());
- }
- return CachedSection::Add(name.c_str(), name.length() + 1);
- }
- };
-
- // Writer of .strtab and .shstrtab sections.
- class StringSection final : public Section {
- public:
- StringSection(ElfBuilder<ElfTypes>* owner,
- const std::string& name,
- Elf_Word flags,
- Elf_Word align)
- : Section(owner,
- name,
- SHT_STRTAB,
- flags,
- /* link= */ nullptr,
- /* info= */ 0,
- align,
- /* entsize= */ 0) {
- Reset();
- }
-
- void Reset() {
- current_offset_ = 0;
- last_name_ = "";
- last_offset_ = 0;
- }
-
- Elf_Word Write(const std::string& name) {
- if (current_offset_ == 0) {
- DCHECK(name.empty());
- } else if (name == last_name_) {
- return last_offset_; // Very simple string de-duplication.
- }
- last_name_ = name;
- last_offset_ = current_offset_;
- this->WriteFully(name.c_str(), name.length() + 1);
- current_offset_ += name.length() + 1;
- return last_offset_;
- }
-
- private:
- Elf_Word current_offset_;
- std::string last_name_;
- Elf_Word last_offset_;
- };
-
- // Writer of .dynsym and .symtab sections.
- class SymbolSection final : public Section {
- public:
- SymbolSection(ElfBuilder<ElfTypes>* owner,
- const std::string& name,
- Elf_Word type,
- Elf_Word flags,
- Section* strtab)
- : Section(owner,
- name,
- type,
- flags,
- strtab,
- /* info= */ 1,
- sizeof(Elf_Off),
- sizeof(Elf_Sym)) {
- syms_.push_back(Elf_Sym()); // The symbol table always has to start with NULL symbol.
- }
-
- // Buffer symbol for this section. It will be written later.
- void Add(Elf_Word name,
- const Section* section,
- Elf_Addr addr,
- Elf_Word size,
- uint8_t binding,
- uint8_t type) {
- Elf_Sym sym = Elf_Sym();
- sym.st_name = name;
- sym.st_value = addr;
- sym.st_size = size;
- sym.st_other = 0;
- sym.st_info = (binding << 4) + (type & 0xf);
- Add(sym, section);
- }
-
- // Buffer symbol for this section. It will be written later.
- void Add(Elf_Sym sym, const Section* section) {
- DCHECK(section != nullptr);
- DCHECK_LE(section->GetAddress(), sym.st_value);
- DCHECK_LE(sym.st_value, section->GetAddress() + section->header_.sh_size);
- sym.st_shndx = section->GetSectionIndex();
-
- // The sh_info file must be set to index one-past the last local symbol.
- if (sym.getBinding() == STB_LOCAL) {
- DCHECK_EQ(syms_.back().getBinding(), STB_LOCAL);
- this->header_.sh_info = syms_.size() + 1;
- }
-
- syms_.push_back(sym);
- }
-
- Elf_Word GetCacheSize() { return syms_.size() * sizeof(Elf_Sym); }
-
- void WriteCachedSection() {
- this->Start();
- for (; !syms_.empty(); syms_.pop_front()) {
- this->WriteFully(&syms_.front(), sizeof(Elf_Sym));
- }
- this->End();
- }
-
- private:
- std::deque<Elf_Sym> syms_; // Buffered/cached content of the whole section.
- };
-
- class AbiflagsSection final : public Section {
- public:
- // Section with Mips abiflag info.
- static constexpr uint8_t MIPS_AFL_REG_NONE = 0; // no registers
- static constexpr uint8_t MIPS_AFL_REG_32 = 1; // 32-bit registers
- static constexpr uint8_t MIPS_AFL_REG_64 = 2; // 64-bit registers
- static constexpr uint32_t MIPS_AFL_FLAGS1_ODDSPREG = 1; // Uses odd single-prec fp regs
- static constexpr uint8_t MIPS_ABI_FP_DOUBLE = 1; // -mdouble-float
- static constexpr uint8_t MIPS_ABI_FP_XX = 5; // -mfpxx
- static constexpr uint8_t MIPS_ABI_FP_64A = 7; // -mips32r* -mfp64 -mno-odd-spreg
-
- AbiflagsSection(ElfBuilder<ElfTypes>* owner,
- const std::string& name,
- Elf_Word type,
- Elf_Word flags,
- const Section* link,
- Elf_Word info,
- Elf_Word align,
- Elf_Word entsize,
- InstructionSet isa,
- const InstructionSetFeatures* features)
- : Section(owner, name, type, flags, link, info, align, entsize) {
- if (isa == InstructionSet::kMips || isa == InstructionSet::kMips64) {
- bool fpu32 = false; // assume mips64 values
- uint8_t isa_rev = 6; // assume mips64 values
- if (isa == InstructionSet::kMips) {
- // adjust for mips32 values
- fpu32 = features->AsMipsInstructionSetFeatures()->Is32BitFloatingPoint();
- isa_rev = features->AsMipsInstructionSetFeatures()->IsR6()
- ? 6
- : features->AsMipsInstructionSetFeatures()->IsMipsIsaRevGreaterThanEqual2()
- ? (fpu32 ? 2 : 5)
- : 1;
- }
- abiflags_.version = 0; // version of flags structure
- abiflags_.isa_level = (isa == InstructionSet::kMips) ? 32 : 64;
- abiflags_.isa_rev = isa_rev;
- abiflags_.gpr_size = (isa == InstructionSet::kMips) ? MIPS_AFL_REG_32 : MIPS_AFL_REG_64;
- abiflags_.cpr1_size = fpu32 ? MIPS_AFL_REG_32 : MIPS_AFL_REG_64;
- abiflags_.cpr2_size = MIPS_AFL_REG_NONE;
- // Set the fp_abi to MIPS_ABI_FP_64A for mips32 with 64-bit FPUs (ie: mips32 R5 and R6).
- // Otherwise set to MIPS_ABI_FP_DOUBLE.
- abiflags_.fp_abi =
- (isa == InstructionSet::kMips && !fpu32) ? MIPS_ABI_FP_64A : MIPS_ABI_FP_DOUBLE;
- abiflags_.isa_ext = 0;
- abiflags_.ases = 0;
- // To keep the code simple, we are not using odd FP reg for single floats for both
- // mips32 and mips64 ART. Therefore we are not setting the MIPS_AFL_FLAGS1_ODDSPREG bit.
- abiflags_.flags1 = 0;
- abiflags_.flags2 = 0;
- }
- }
-
- Elf_Word GetSize() const {
- return sizeof(abiflags_);
- }
-
- void Write() {
- this->WriteFully(&abiflags_, sizeof(abiflags_));
- }
-
- private:
- struct {
- uint16_t version; // version of this structure
- uint8_t isa_level, isa_rev, gpr_size, cpr1_size, cpr2_size;
- uint8_t fp_abi;
- uint32_t isa_ext, ases, flags1, flags2;
- } abiflags_;
- };
-
- class BuildIdSection final : public Section {
- public:
- BuildIdSection(ElfBuilder<ElfTypes>* owner,
- const std::string& name,
- Elf_Word type,
- Elf_Word flags,
- const Section* link,
- Elf_Word info,
- Elf_Word align,
- Elf_Word entsize)
- : Section(owner, name, type, flags, link, info, align, entsize),
- digest_start_(-1) {
- }
-
- Elf_Word GetSize() {
- return 16 + kBuildIdLen;
- }
-
- void Write() {
- // The size fields are 32-bit on both 32-bit and 64-bit systems, confirmed
- // with the 64-bit linker and libbfd code. The size of name and desc must
- // be a multiple of 4 and it currently is.
- this->WriteUint32(4); // namesz.
- this->WriteUint32(kBuildIdLen); // descsz.
- this->WriteUint32(3); // type = NT_GNU_BUILD_ID.
- this->WriteFully("GNU", 4); // name.
- digest_start_ = this->Seek(0, kSeekCurrent);
- static_assert(kBuildIdLen % 4 == 0, "expecting a mutliple of 4 for build ID length");
- this->WriteFully(std::string(kBuildIdLen, '\0').c_str(), kBuildIdLen); // desc.
- DCHECK_EQ(this->GetPosition(), GetSize());
- }
-
- off_t GetDigestStart() {
- CHECK_GT(digest_start_, 0);
- return digest_start_;
- }
-
- private:
- bool WriteUint32(uint32_t v) {
- return this->WriteFully(&v, sizeof(v));
- }
-
- // File offset where the build ID digest starts.
- // Populated with zeros first, then updated with the actual value as the
- // very last thing in the output file creation.
- off_t digest_start_;
- };
-
- ElfBuilder(InstructionSet isa, const InstructionSetFeatures* features, OutputStream* output)
- : isa_(isa),
- features_(features),
- stream_(output),
- rodata_(this, ".rodata", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, kPageSize, 0),
- text_(this, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR, nullptr, 0, kPageSize, 0),
- data_bimg_rel_ro_(
- this, ".data.bimg.rel.ro", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, kPageSize, 0),
- bss_(this, ".bss", SHT_NOBITS, SHF_ALLOC, nullptr, 0, kPageSize, 0),
- dex_(this, ".dex", SHT_NOBITS, SHF_ALLOC, nullptr, 0, kPageSize, 0),
- dynstr_(this, ".dynstr", SHF_ALLOC, kPageSize),
- dynsym_(this, ".dynsym", SHT_DYNSYM, SHF_ALLOC, &dynstr_),
- hash_(this, ".hash", SHT_HASH, SHF_ALLOC, &dynsym_, 0, sizeof(Elf_Word), sizeof(Elf_Word)),
- dynamic_(this, ".dynamic", SHT_DYNAMIC, SHF_ALLOC, &dynstr_, 0, kPageSize, sizeof(Elf_Dyn)),
- strtab_(this, ".strtab", 0, 1),
- symtab_(this, ".symtab", SHT_SYMTAB, 0, &strtab_),
- debug_frame_(this, ".debug_frame", SHT_PROGBITS, 0, nullptr, 0, sizeof(Elf_Addr), 0),
- debug_frame_hdr_(
- this, ".debug_frame_hdr.android", SHT_PROGBITS, 0, nullptr, 0, sizeof(Elf_Addr), 0),
- debug_info_(this, ".debug_info", SHT_PROGBITS, 0, nullptr, 0, 1, 0),
- debug_line_(this, ".debug_line", SHT_PROGBITS, 0, nullptr, 0, 1, 0),
- shstrtab_(this, ".shstrtab", 0, 1),
- abiflags_(this, ".MIPS.abiflags", SHT_MIPS_ABIFLAGS, SHF_ALLOC, nullptr, 0, kPageSize, 0,
- isa, features),
- build_id_(this, ".note.gnu.build-id", SHT_NOTE, SHF_ALLOC, nullptr, 0, 4, 0),
- current_section_(nullptr),
- started_(false),
- finished_(false),
- write_program_headers_(false),
- loaded_size_(0u),
- virtual_address_(0) {
- text_.phdr_flags_ = PF_R | PF_X;
- data_bimg_rel_ro_.phdr_flags_ = PF_R | PF_W; // Shall be made read-only at run time.
- bss_.phdr_flags_ = PF_R | PF_W;
- dex_.phdr_flags_ = PF_R;
- dynamic_.phdr_flags_ = PF_R | PF_W;
- dynamic_.phdr_type_ = PT_DYNAMIC;
- abiflags_.phdr_type_ = PT_MIPS_ABIFLAGS;
- build_id_.phdr_type_ = PT_NOTE;
- }
- ~ElfBuilder() {}
-
- InstructionSet GetIsa() { return isa_; }
- BuildIdSection* GetBuildId() { return &build_id_; }
- Section* GetRoData() { return &rodata_; }
- Section* GetText() { return &text_; }
- Section* GetDataBimgRelRo() { return &data_bimg_rel_ro_; }
- Section* GetBss() { return &bss_; }
- Section* GetDex() { return &dex_; }
- StringSection* GetStrTab() { return &strtab_; }
- SymbolSection* GetSymTab() { return &symtab_; }
- Section* GetDebugFrame() { return &debug_frame_; }
- Section* GetDebugFrameHdr() { return &debug_frame_hdr_; }
- Section* GetDebugInfo() { return &debug_info_; }
- Section* GetDebugLine() { return &debug_line_; }
-
- void WriteSection(const char* name, const std::vector<uint8_t>* buffer) {
- std::unique_ptr<Section> s(new Section(this, name, SHT_PROGBITS, 0, nullptr, 0, 1, 0));
- s->Start();
- s->WriteFully(buffer->data(), buffer->size());
- s->End();
- other_sections_.push_back(std::move(s));
- }
-
- // Reserve space for ELF header and program headers.
- // We do not know the number of headers until later, so
- // it is easiest to just reserve a fixed amount of space.
- // Program headers are required for loading by the linker.
- // It is possible to omit them for ELF files used for debugging.
- void Start(bool write_program_headers = true) {
- int size = sizeof(Elf_Ehdr);
- if (write_program_headers) {
- size += sizeof(Elf_Phdr) * kMaxProgramHeaders;
- }
- stream_.Seek(size, kSeekSet);
- started_ = true;
- virtual_address_ += size;
- write_program_headers_ = write_program_headers;
- }
-
- off_t End() {
- DCHECK(started_);
- DCHECK(!finished_);
- finished_ = true;
-
- // Note: loaded_size_ == 0 for tests that don't write .rodata, .text, .bss,
- // .dynstr, dynsym, .hash and .dynamic. These tests should not read loaded_size_.
- CHECK(loaded_size_ == 0 || loaded_size_ == RoundUp(virtual_address_, kPageSize))
- << loaded_size_ << " " << virtual_address_;
-
- // Write section names and finish the section headers.
- shstrtab_.Start();
- shstrtab_.Write("");
- for (auto* section : sections_) {
- section->header_.sh_name = shstrtab_.Write(section->name_);
- if (section->link_ != nullptr) {
- section->header_.sh_link = section->link_->GetSectionIndex();
- }
- if (section->header_.sh_offset == 0) {
- section->header_.sh_type = SHT_NOBITS;
- }
- }
- shstrtab_.End();
-
- // Write section headers at the end of the ELF file.
- std::vector<Elf_Shdr> shdrs;
- shdrs.reserve(1u + sections_.size());
- shdrs.push_back(Elf_Shdr()); // NULL at index 0.
- for (auto* section : sections_) {
- shdrs.push_back(section->header_);
- }
- Elf_Off section_headers_offset;
- section_headers_offset = AlignFileOffset(sizeof(Elf_Off));
- stream_.WriteFully(shdrs.data(), shdrs.size() * sizeof(shdrs[0]));
- off_t file_size = stream_.Seek(0, kSeekCurrent);
-
- // Flush everything else before writing the program headers. This should prevent
- // the OS from reordering writes, so that we don't end up with valid headers
- // and partially written data if we suddenly lose power, for example.
- stream_.Flush();
-
- // The main ELF header.
- Elf_Ehdr elf_header = MakeElfHeader(isa_, features_);
- elf_header.e_shoff = section_headers_offset;
- elf_header.e_shnum = shdrs.size();
- elf_header.e_shstrndx = shstrtab_.GetSectionIndex();
-
- // Program headers (i.e. mmap instructions).
- std::vector<Elf_Phdr> phdrs;
- if (write_program_headers_) {
- phdrs = MakeProgramHeaders();
- CHECK_LE(phdrs.size(), kMaxProgramHeaders);
- elf_header.e_phoff = sizeof(Elf_Ehdr);
- elf_header.e_phnum = phdrs.size();
- }
-
- stream_.Seek(0, kSeekSet);
- stream_.WriteFully(&elf_header, sizeof(elf_header));
- stream_.WriteFully(phdrs.data(), phdrs.size() * sizeof(phdrs[0]));
- stream_.Flush();
-
- return file_size;
- }
-
- // This has the same effect as running the "strip" command line tool.
- // It removes all debugging sections (but it keeps mini-debug-info).
- // It returns the ELF file size (as the caller needs to truncate it).
- off_t Strip() {
- DCHECK(finished_);
- finished_ = false;
- Elf_Off end = 0;
- std::vector<Section*> non_debug_sections;
- for (Section* section : sections_) {
- if (section == &shstrtab_ || // Section names will be recreated.
- section == &symtab_ ||
- section == &strtab_ ||
- section->name_.find(".debug_") == 0) {
- section->header_.sh_offset = 0;
- section->header_.sh_size = 0;
- section->section_index_ = 0;
- } else {
- if (section->header_.sh_type != SHT_NOBITS) {
- DCHECK_LE(section->header_.sh_offset, end + kPageSize) << "Large gap between sections";
- end = std::max<off_t>(end, section->header_.sh_offset + section->header_.sh_size);
- }
- non_debug_sections.push_back(section);
- }
- }
- shstrtab_.Reset();
- // Write the non-debug section headers, program headers, and ELF header again.
- sections_ = std::move(non_debug_sections);
- stream_.Seek(end, kSeekSet);
- return End();
- }
-
- // The running program does not have access to section headers
- // and the loader is not supposed to use them either.
- // The dynamic sections therefore replicates some of the layout
- // information like the address and size of .rodata and .text.
- // It also contains other metadata like the SONAME.
- // The .dynamic section is found using the PT_DYNAMIC program header.
- void PrepareDynamicSection(const std::string& elf_file_path,
- Elf_Word rodata_size,
- Elf_Word text_size,
- Elf_Word data_bimg_rel_ro_size,
- Elf_Word bss_size,
- Elf_Word bss_methods_offset,
- Elf_Word bss_roots_offset,
- Elf_Word dex_size) {
- std::string soname(elf_file_path);
- size_t directory_separator_pos = soname.rfind('/');
- if (directory_separator_pos != std::string::npos) {
- soname = soname.substr(directory_separator_pos + 1);
- }
-
- // Allocate all pre-dynamic sections.
- rodata_.AllocateVirtualMemory(rodata_size);
- text_.AllocateVirtualMemory(text_size);
- if (data_bimg_rel_ro_size != 0) {
- data_bimg_rel_ro_.AllocateVirtualMemory(data_bimg_rel_ro_size);
- }
- if (bss_size != 0) {
- bss_.AllocateVirtualMemory(bss_size);
- }
- if (dex_size != 0) {
- dex_.AllocateVirtualMemory(dex_size);
- }
- if (isa_ == InstructionSet::kMips || isa_ == InstructionSet::kMips64) {
- abiflags_.AllocateVirtualMemory(abiflags_.GetSize());
- }
-
- // Cache .dynstr, .dynsym and .hash data.
- dynstr_.Add(""); // dynstr should start with empty string.
- Elf_Word oatdata = dynstr_.Add("oatdata");
- dynsym_.Add(oatdata, &rodata_, rodata_.GetAddress(), rodata_size, STB_GLOBAL, STT_OBJECT);
- if (text_size != 0u) {
- // The runtime does not care about the size of this symbol (it uses the "lastword" symbol).
- // We use size 0 (meaning "unknown size" in ELF) to prevent overlap with the debug symbols.
- Elf_Word oatexec = dynstr_.Add("oatexec");
- dynsym_.Add(oatexec, &text_, text_.GetAddress(), /* size= */ 0, STB_GLOBAL, STT_OBJECT);
- Elf_Word oatlastword = dynstr_.Add("oatlastword");
- Elf_Word oatlastword_address = text_.GetAddress() + text_size - 4;
- dynsym_.Add(oatlastword, &text_, oatlastword_address, 4, STB_GLOBAL, STT_OBJECT);
- } else if (rodata_size != 0) {
- // rodata_ can be size 0 for dwarf_test.
- Elf_Word oatlastword = dynstr_.Add("oatlastword");
- Elf_Word oatlastword_address = rodata_.GetAddress() + rodata_size - 4;
- dynsym_.Add(oatlastword, &rodata_, oatlastword_address, 4, STB_GLOBAL, STT_OBJECT);
- }
- if (data_bimg_rel_ro_size != 0u) {
- Elf_Word oatdatabimgrelro = dynstr_.Add("oatdatabimgrelro");
- dynsym_.Add(oatdatabimgrelro,
- &data_bimg_rel_ro_,
- data_bimg_rel_ro_.GetAddress(),
- data_bimg_rel_ro_size,
- STB_GLOBAL,
- STT_OBJECT);
- Elf_Word oatdatabimgrelrolastword = dynstr_.Add("oatdatabimgrelrolastword");
- Elf_Word oatdatabimgrelrolastword_address =
- data_bimg_rel_ro_.GetAddress() + data_bimg_rel_ro_size - 4;
- dynsym_.Add(oatdatabimgrelrolastword,
- &data_bimg_rel_ro_,
- oatdatabimgrelrolastword_address,
- 4,
- STB_GLOBAL,
- STT_OBJECT);
- }
- DCHECK_LE(bss_roots_offset, bss_size);
- if (bss_size != 0u) {
- Elf_Word oatbss = dynstr_.Add("oatbss");
- dynsym_.Add(oatbss, &bss_, bss_.GetAddress(), bss_roots_offset, STB_GLOBAL, STT_OBJECT);
- DCHECK_LE(bss_methods_offset, bss_roots_offset);
- DCHECK_LE(bss_roots_offset, bss_size);
- // Add a symbol marking the start of the methods part of the .bss, if not empty.
- if (bss_methods_offset != bss_roots_offset) {
- Elf_Word bss_methods_address = bss_.GetAddress() + bss_methods_offset;
- Elf_Word bss_methods_size = bss_roots_offset - bss_methods_offset;
- Elf_Word oatbssroots = dynstr_.Add("oatbssmethods");
- dynsym_.Add(
- oatbssroots, &bss_, bss_methods_address, bss_methods_size, STB_GLOBAL, STT_OBJECT);
- }
- // Add a symbol marking the start of the GC roots part of the .bss, if not empty.
- if (bss_roots_offset != bss_size) {
- Elf_Word bss_roots_address = bss_.GetAddress() + bss_roots_offset;
- Elf_Word bss_roots_size = bss_size - bss_roots_offset;
- Elf_Word oatbssroots = dynstr_.Add("oatbssroots");
- dynsym_.Add(
- oatbssroots, &bss_, bss_roots_address, bss_roots_size, STB_GLOBAL, STT_OBJECT);
- }
- Elf_Word oatbsslastword = dynstr_.Add("oatbsslastword");
- Elf_Word bsslastword_address = bss_.GetAddress() + bss_size - 4;
- dynsym_.Add(oatbsslastword, &bss_, bsslastword_address, 4, STB_GLOBAL, STT_OBJECT);
- }
- if (dex_size != 0u) {
- Elf_Word oatdex = dynstr_.Add("oatdex");
- dynsym_.Add(oatdex, &dex_, dex_.GetAddress(), /* size= */ 0, STB_GLOBAL, STT_OBJECT);
- Elf_Word oatdexlastword = dynstr_.Add("oatdexlastword");
- Elf_Word oatdexlastword_address = dex_.GetAddress() + dex_size - 4;
- dynsym_.Add(oatdexlastword, &dex_, oatdexlastword_address, 4, STB_GLOBAL, STT_OBJECT);
- }
-
- Elf_Word soname_offset = dynstr_.Add(soname);
-
- // We do not really need a hash-table since there is so few entries.
- // However, the hash-table is the only way the linker can actually
- // determine the number of symbols in .dynsym so it is required.
- int count = dynsym_.GetCacheSize() / sizeof(Elf_Sym); // Includes NULL.
- std::vector<Elf_Word> hash;
- hash.push_back(1); // Number of buckets.
- hash.push_back(count); // Number of chains.
- // Buckets. Having just one makes it linear search.
- hash.push_back(1); // Point to first non-NULL symbol.
- // Chains. This creates linked list of symbols.
- hash.push_back(0); // Dummy entry for the NULL symbol.
- for (int i = 1; i < count - 1; i++) {
- hash.push_back(i + 1); // Each symbol points to the next one.
- }
- hash.push_back(0); // Last symbol terminates the chain.
- hash_.Add(hash.data(), hash.size() * sizeof(hash[0]));
-
- // Allocate all remaining sections.
- dynstr_.AllocateVirtualMemory(dynstr_.GetCacheSize());
- dynsym_.AllocateVirtualMemory(dynsym_.GetCacheSize());
- hash_.AllocateVirtualMemory(hash_.GetCacheSize());
-
- Elf_Dyn dyns[] = {
- { DT_HASH, { hash_.GetAddress() } },
- { DT_STRTAB, { dynstr_.GetAddress() } },
- { DT_SYMTAB, { dynsym_.GetAddress() } },
- { DT_SYMENT, { sizeof(Elf_Sym) } },
- { DT_STRSZ, { dynstr_.GetCacheSize() } },
- { DT_SONAME, { soname_offset } },
- { DT_NULL, { 0 } },
- };
- dynamic_.Add(&dyns, sizeof(dyns));
- dynamic_.AllocateVirtualMemory(dynamic_.GetCacheSize());
-
- loaded_size_ = RoundUp(virtual_address_, kPageSize);
- }
-
- void WriteDynamicSection() {
- dynstr_.WriteCachedSection();
- dynsym_.WriteCachedSection();
- hash_.WriteCachedSection();
- dynamic_.WriteCachedSection();
- }
-
- Elf_Word GetLoadedSize() {
- CHECK_NE(loaded_size_, 0u);
- return loaded_size_;
- }
-
- void WriteMIPSabiflagsSection() {
- abiflags_.Start();
- abiflags_.Write();
- abiflags_.End();
- }
-
- void WriteBuildIdSection() {
- build_id_.Start();
- build_id_.Write();
- build_id_.End();
- }
-
- void WriteBuildId(uint8_t build_id[kBuildIdLen]) {
- stream_.Seek(build_id_.GetDigestStart(), kSeekSet);
- stream_.WriteFully(build_id, kBuildIdLen);
- stream_.Flush();
- }
-
- // Returns true if all writes and seeks on the output stream succeeded.
- bool Good() {
- return stream_.Good();
- }
-
- // Returns the builder's internal stream.
- OutputStream* GetStream() {
- return &stream_;
- }
-
- off_t AlignFileOffset(size_t alignment) {
- return stream_.Seek(RoundUp(stream_.Seek(0, kSeekCurrent), alignment), kSeekSet);
- }
-
- private:
- static Elf_Ehdr MakeElfHeader(InstructionSet isa, const InstructionSetFeatures* features) {
- Elf_Ehdr elf_header = Elf_Ehdr();
- switch (isa) {
- case InstructionSet::kArm:
- // Fall through.
- case InstructionSet::kThumb2: {
- elf_header.e_machine = EM_ARM;
- elf_header.e_flags = EF_ARM_EABI_VER5;
- break;
- }
- case InstructionSet::kArm64: {
- elf_header.e_machine = EM_AARCH64;
- elf_header.e_flags = 0;
- break;
- }
- case InstructionSet::kX86: {
- elf_header.e_machine = EM_386;
- elf_header.e_flags = 0;
- break;
- }
- case InstructionSet::kX86_64: {
- elf_header.e_machine = EM_X86_64;
- elf_header.e_flags = 0;
- break;
- }
- case InstructionSet::kMips: {
- elf_header.e_machine = EM_MIPS;
- elf_header.e_flags = (EF_MIPS_NOREORDER |
- EF_MIPS_PIC |
- EF_MIPS_CPIC |
- EF_MIPS_ABI_O32 |
- (features->AsMipsInstructionSetFeatures()->IsR6()
- ? EF_MIPS_ARCH_32R6
- : EF_MIPS_ARCH_32R2));
- break;
- }
- case InstructionSet::kMips64: {
- elf_header.e_machine = EM_MIPS;
- elf_header.e_flags = (EF_MIPS_NOREORDER |
- EF_MIPS_PIC |
- EF_MIPS_CPIC |
- EF_MIPS_ARCH_64R6);
- break;
- }
- case InstructionSet::kNone: {
- LOG(FATAL) << "No instruction set";
- break;
- }
- default: {
- LOG(FATAL) << "Unknown instruction set " << isa;
- }
- }
-
- elf_header.e_ident[EI_MAG0] = ELFMAG0;
- elf_header.e_ident[EI_MAG1] = ELFMAG1;
- elf_header.e_ident[EI_MAG2] = ELFMAG2;
- elf_header.e_ident[EI_MAG3] = ELFMAG3;
- elf_header.e_ident[EI_CLASS] = (sizeof(Elf_Addr) == sizeof(Elf32_Addr))
- ? ELFCLASS32 : ELFCLASS64;
- elf_header.e_ident[EI_DATA] = ELFDATA2LSB;
- elf_header.e_ident[EI_VERSION] = EV_CURRENT;
- elf_header.e_ident[EI_OSABI] = ELFOSABI_LINUX;
- elf_header.e_ident[EI_ABIVERSION] = 0;
- elf_header.e_type = ET_DYN;
- elf_header.e_version = 1;
- elf_header.e_entry = 0;
- elf_header.e_ehsize = sizeof(Elf_Ehdr);
- elf_header.e_phentsize = sizeof(Elf_Phdr);
- elf_header.e_shentsize = sizeof(Elf_Shdr);
- return elf_header;
- }
-
- // Create program headers based on written sections.
- std::vector<Elf_Phdr> MakeProgramHeaders() {
- CHECK(!sections_.empty());
- std::vector<Elf_Phdr> phdrs;
- {
- // The program headers must start with PT_PHDR which is used in
- // loaded process to determine the number of program headers.
- Elf_Phdr phdr = Elf_Phdr();
- phdr.p_type = PT_PHDR;
- phdr.p_flags = PF_R;
- phdr.p_offset = phdr.p_vaddr = phdr.p_paddr = sizeof(Elf_Ehdr);
- phdr.p_filesz = phdr.p_memsz = 0; // We need to fill this later.
- phdr.p_align = sizeof(Elf_Off);
- phdrs.push_back(phdr);
- // Tell the linker to mmap the start of file to memory.
- Elf_Phdr load = Elf_Phdr();
- load.p_type = PT_LOAD;
- load.p_flags = PF_R;
- load.p_offset = load.p_vaddr = load.p_paddr = 0;
- load.p_filesz = load.p_memsz = sizeof(Elf_Ehdr) + sizeof(Elf_Phdr) * kMaxProgramHeaders;
- load.p_align = kPageSize;
- phdrs.push_back(load);
- }
- // Create program headers for sections.
- for (auto* section : sections_) {
- const Elf_Shdr& shdr = section->header_;
- if ((shdr.sh_flags & SHF_ALLOC) != 0 && shdr.sh_size != 0) {
- DCHECK(shdr.sh_addr != 0u) << "Allocate virtual memory for the section";
- // PT_LOAD tells the linker to mmap part of the file.
- // The linker can only mmap page-aligned sections.
- // Single PT_LOAD may contain several ELF sections.
- Elf_Phdr& prev = phdrs.back();
- Elf_Phdr load = Elf_Phdr();
- load.p_type = PT_LOAD;
- load.p_flags = section->phdr_flags_;
- load.p_offset = shdr.sh_offset;
- load.p_vaddr = load.p_paddr = shdr.sh_addr;
- load.p_filesz = (shdr.sh_type != SHT_NOBITS ? shdr.sh_size : 0u);
- load.p_memsz = shdr.sh_size;
- load.p_align = shdr.sh_addralign;
- if (prev.p_type == load.p_type &&
- prev.p_flags == load.p_flags &&
- prev.p_filesz == prev.p_memsz && // Do not merge .bss
- load.p_filesz == load.p_memsz) { // Do not merge .bss
- // Merge this PT_LOAD with the previous one.
- Elf_Word size = shdr.sh_offset + shdr.sh_size - prev.p_offset;
- prev.p_filesz = size;
- prev.p_memsz = size;
- } else {
- // If we are adding new load, it must be aligned.
- CHECK_EQ(shdr.sh_addralign, (Elf_Word)kPageSize);
- phdrs.push_back(load);
- }
- }
- }
- for (auto* section : sections_) {
- const Elf_Shdr& shdr = section->header_;
- if ((shdr.sh_flags & SHF_ALLOC) != 0 && shdr.sh_size != 0) {
- // Other PT_* types allow the program to locate interesting
- // parts of memory at runtime. They must overlap with PT_LOAD.
- if (section->phdr_type_ != 0) {
- Elf_Phdr phdr = Elf_Phdr();
- phdr.p_type = section->phdr_type_;
- phdr.p_flags = section->phdr_flags_;
- phdr.p_offset = shdr.sh_offset;
- phdr.p_vaddr = phdr.p_paddr = shdr.sh_addr;
- phdr.p_filesz = phdr.p_memsz = shdr.sh_size;
- phdr.p_align = shdr.sh_addralign;
- phdrs.push_back(phdr);
- }
- }
- }
- // Set the size of the initial PT_PHDR.
- CHECK_EQ(phdrs[0].p_type, (Elf_Word)PT_PHDR);
- phdrs[0].p_filesz = phdrs[0].p_memsz = phdrs.size() * sizeof(Elf_Phdr);
-
- return phdrs;
- }
-
- InstructionSet isa_;
- const InstructionSetFeatures* features_;
-
- ErrorDelayingOutputStream stream_;
-
- Section rodata_;
- Section text_;
- Section data_bimg_rel_ro_;
- Section bss_;
- Section dex_;
- CachedStringSection dynstr_;
- SymbolSection dynsym_;
- CachedSection hash_;
- CachedSection dynamic_;
- StringSection strtab_;
- SymbolSection symtab_;
- Section debug_frame_;
- Section debug_frame_hdr_;
- Section debug_info_;
- Section debug_line_;
- StringSection shstrtab_;
- AbiflagsSection abiflags_;
- BuildIdSection build_id_;
- std::vector<std::unique_ptr<Section>> other_sections_;
-
- // List of used section in the order in which they were written.
- std::vector<Section*> sections_;
- Section* current_section_; // The section which is currently being written.
-
- bool started_;
- bool finished_;
- bool write_program_headers_;
-
- // The size of the memory taken by the ELF file when loaded.
- size_t loaded_size_;
-
- // Used for allocation of virtual address space.
- Elf_Addr virtual_address_;
-
- DISALLOW_COPY_AND_ASSIGN(ElfBuilder);
-};
-
-} // namespace linker
-} // namespace art
-
-#endif // ART_COMPILER_LINKER_ELF_BUILDER_H_
diff --git a/compiler/linker/error_delaying_output_stream.h b/compiler/linker/error_delaying_output_stream.h
deleted file mode 100644
index cadd71c..0000000
--- a/compiler/linker/error_delaying_output_stream.h
+++ /dev/null
@@ -1,105 +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_LINKER_ERROR_DELAYING_OUTPUT_STREAM_H_
-#define ART_COMPILER_LINKER_ERROR_DELAYING_OUTPUT_STREAM_H_
-
-#include "output_stream.h"
-
-#include <android-base/logging.h>
-
-#include "base/macros.h"
-
-namespace art {
-namespace linker {
-
-// OutputStream wrapper that delays reporting an error until Flush().
-class ErrorDelayingOutputStream final : public OutputStream {
- public:
- explicit ErrorDelayingOutputStream(OutputStream* output)
- : OutputStream(output->GetLocation()),
- output_(output),
- output_good_(true),
- output_offset_(0) { }
-
- // This function always succeeds to simplify code.
- // Use Good() to check the actual status of the output stream.
- bool WriteFully(const void* buffer, size_t byte_count) override {
- if (output_good_) {
- if (!output_->WriteFully(buffer, byte_count)) {
- PLOG(ERROR) << "Failed to write " << byte_count
- << " bytes to " << GetLocation() << " at offset " << output_offset_;
- output_good_ = false;
- }
- }
- output_offset_ += byte_count;
- return true;
- }
-
- // This function always succeeds to simplify code.
- // Use Good() to check the actual status of the output stream.
- off_t Seek(off_t offset, Whence whence) override {
- // We keep shadow copy of the offset so that we return
- // the expected value even if the output stream failed.
- off_t new_offset;
- switch (whence) {
- case kSeekSet:
- new_offset = offset;
- break;
- case kSeekCurrent:
- new_offset = output_offset_ + offset;
- break;
- default:
- LOG(FATAL) << "Unsupported seek type: " << whence;
- UNREACHABLE();
- }
- if (output_good_) {
- off_t actual_offset = output_->Seek(offset, whence);
- if (actual_offset == static_cast<off_t>(-1)) {
- PLOG(ERROR) << "Failed to seek in " << GetLocation() << ". Offset=" << offset
- << " whence=" << whence << " new_offset=" << new_offset;
- output_good_ = false;
- }
- DCHECK_EQ(actual_offset, new_offset);
- }
- output_offset_ = new_offset;
- return new_offset;
- }
-
- // Flush the output and return whether all operations have succeeded.
- // Do nothing if we already have a pending error.
- bool Flush() override {
- if (output_good_) {
- output_good_ = output_->Flush();
- }
- return output_good_;
- }
-
- // Check (without flushing) whether all operations have succeeded so far.
- bool Good() const {
- return output_good_;
- }
-
- private:
- OutputStream* output_;
- bool output_good_; // True if all writes to output succeeded.
- off_t output_offset_; // Keep track of the current position in the stream.
-};
-
-} // namespace linker
-} // namespace art
-
-#endif // ART_COMPILER_LINKER_ERROR_DELAYING_OUTPUT_STREAM_H_
diff --git a/compiler/linker/file_output_stream.cc b/compiler/linker/file_output_stream.cc
deleted file mode 100644
index 477846e..0000000
--- a/compiler/linker/file_output_stream.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2013 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 "file_output_stream.h"
-
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "base/unix_file/fd_file.h"
-
-namespace art {
-namespace linker {
-
-FileOutputStream::FileOutputStream(File* file) : OutputStream(file->GetPath()), file_(file) {}
-
-bool FileOutputStream::WriteFully(const void* buffer, size_t byte_count) {
- return file_->WriteFully(buffer, byte_count);
-}
-
-off_t FileOutputStream::Seek(off_t offset, Whence whence) {
- return lseek(file_->Fd(), offset, static_cast<int>(whence));
-}
-
-bool FileOutputStream::Flush() {
- return file_->Flush() == 0;
-}
-
-} // namespace linker
-} // namespace art
diff --git a/compiler/linker/file_output_stream.h b/compiler/linker/file_output_stream.h
deleted file mode 100644
index 1417132..0000000
--- a/compiler/linker/file_output_stream.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2013 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_LINKER_FILE_OUTPUT_STREAM_H_
-#define ART_COMPILER_LINKER_FILE_OUTPUT_STREAM_H_
-
-#include "base/os.h"
-
-#include "output_stream.h"
-
-namespace art {
-namespace linker {
-
-class FileOutputStream final : public OutputStream {
- public:
- explicit FileOutputStream(File* file);
-
- ~FileOutputStream() override {}
-
- bool WriteFully(const void* buffer, size_t byte_count) override;
-
- off_t Seek(off_t offset, Whence whence) override;
-
- bool Flush() override;
-
- private:
- File* const file_;
-
- DISALLOW_COPY_AND_ASSIGN(FileOutputStream);
-};
-
-} // namespace linker
-} // namespace art
-
-#endif // ART_COMPILER_LINKER_FILE_OUTPUT_STREAM_H_
diff --git a/compiler/linker/output_stream.cc b/compiler/linker/output_stream.cc
deleted file mode 100644
index f5a1913..0000000
--- a/compiler/linker/output_stream.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2014 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 "output_stream.h"
-
-namespace art {
-namespace linker {
-
-std::ostream& operator<<(std::ostream& os, const Whence& rhs) {
- switch (rhs) {
- case kSeekSet: os << "SEEK_SET"; break;
- case kSeekCurrent: os << "SEEK_CUR"; break;
- case kSeekEnd: os << "SEEK_END"; break;
- default: UNREACHABLE();
- }
- return os;
-}
-
-} // namespace linker
-} // namespace art
diff --git a/compiler/linker/output_stream.h b/compiler/linker/output_stream.h
deleted file mode 100644
index 5310e2f..0000000
--- a/compiler/linker/output_stream.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2013 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_LINKER_OUTPUT_STREAM_H_
-#define ART_COMPILER_LINKER_OUTPUT_STREAM_H_
-
-#include <ostream>
-#include <string>
-
-#include "base/macros.h"
-
-namespace art {
-namespace linker {
-
-enum Whence {
- kSeekSet = SEEK_SET,
- kSeekCurrent = SEEK_CUR,
- kSeekEnd = SEEK_END,
-};
-std::ostream& operator<<(std::ostream& os, const Whence& rhs);
-
-class OutputStream {
- public:
- explicit OutputStream(const std::string& location) : location_(location) {}
-
- virtual ~OutputStream() {}
-
- const std::string& GetLocation() const {
- return location_;
- }
-
- virtual bool WriteFully(const void* buffer, size_t byte_count) = 0;
-
- virtual off_t Seek(off_t offset, Whence whence) = 0;
-
- /*
- * Flushes the stream. Returns whether the operation was successful.
- *
- * An OutputStream may delay reporting errors from WriteFully() or
- * Seek(). In that case, Flush() shall report any pending error.
- */
- virtual bool Flush() = 0;
-
- private:
- const std::string location_;
-
- DISALLOW_COPY_AND_ASSIGN(OutputStream);
-};
-
-} // namespace linker
-} // namespace art
-
-#endif // ART_COMPILER_LINKER_OUTPUT_STREAM_H_
diff --git a/compiler/linker/output_stream_test.cc b/compiler/linker/output_stream_test.cc
index bcb129c..00231b1 100644
--- a/compiler/linker/output_stream_test.cc
+++ b/compiler/linker/output_stream_test.cc
@@ -14,15 +14,14 @@
* limitations under the License.
*/
-#include "file_output_stream.h"
-#include "vector_output_stream.h"
-
#include <android-base/logging.h>
#include "base/macros.h"
#include "base/unix_file/fd_file.h"
-#include "buffered_output_stream.h"
#include "common_runtime_test.h"
+#include "stream/buffered_output_stream.h"
+#include "stream/file_output_stream.h"
+#include "stream/vector_output_stream.h"
namespace art {
namespace linker {
diff --git a/compiler/linker/vector_output_stream.cc b/compiler/linker/vector_output_stream.cc
deleted file mode 100644
index f2cae5b..0000000
--- a/compiler/linker/vector_output_stream.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2013 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 "vector_output_stream.h"
-
-#include <android-base/logging.h>
-
-namespace art {
-namespace linker {
-
-VectorOutputStream::VectorOutputStream(const std::string& location, std::vector<uint8_t>* vector)
- : OutputStream(location), offset_(vector->size()), vector_(vector) {}
-
-off_t VectorOutputStream::Seek(off_t offset, Whence whence) {
- CHECK(whence == kSeekSet || whence == kSeekCurrent || whence == kSeekEnd) << whence;
- off_t new_offset = 0;
- switch (whence) {
- case kSeekSet: {
- new_offset = offset;
- break;
- }
- case kSeekCurrent: {
- new_offset = offset_ + offset;
- break;
- }
- case kSeekEnd: {
- new_offset = vector_->size() + offset;
- break;
- }
- }
- EnsureCapacity(new_offset);
- offset_ = new_offset;
- return offset_;
-}
-
-} // namespace linker
-} // namespace art
diff --git a/compiler/linker/vector_output_stream.h b/compiler/linker/vector_output_stream.h
deleted file mode 100644
index 0d34da6..0000000
--- a/compiler/linker/vector_output_stream.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2013 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_LINKER_VECTOR_OUTPUT_STREAM_H_
-#define ART_COMPILER_LINKER_VECTOR_OUTPUT_STREAM_H_
-
-#include "output_stream.h"
-
-#include <string.h>
-#include <string>
-#include <vector>
-
-namespace art {
-namespace linker {
-
-class VectorOutputStream final : public OutputStream {
- public:
- VectorOutputStream(const std::string& location, std::vector<uint8_t>* vector);
-
- ~VectorOutputStream() override {}
-
- bool WriteFully(const void* buffer, size_t byte_count) override {
- if (static_cast<size_t>(offset_) == vector_->size()) {
- const uint8_t* start = reinterpret_cast<const uint8_t*>(buffer);
- vector_->insert(vector_->end(), &start[0], &start[byte_count]);
- offset_ += byte_count;
- } else {
- off_t new_offset = offset_ + byte_count;
- EnsureCapacity(new_offset);
- memcpy(&(*vector_)[offset_], buffer, byte_count);
- offset_ = new_offset;
- }
- return true;
- }
-
- off_t Seek(off_t offset, Whence whence) override;
-
- bool Flush() override {
- return true;
- }
-
- private:
- void EnsureCapacity(off_t new_offset) {
- if (new_offset > static_cast<off_t>(vector_->size())) {
- vector_->resize(new_offset);
- }
- }
-
- off_t offset_;
- std::vector<uint8_t>* const vector_;
-
- DISALLOW_COPY_AND_ASSIGN(VectorOutputStream);
-};
-
-} // namespace linker
-} // namespace art
-
-#endif // ART_COMPILER_LINKER_VECTOR_OUTPUT_STREAM_H_
diff --git a/compiler/optimizing/common_arm.h b/compiler/optimizing/common_arm.h
index 356ff9f..7d3af95 100644
--- a/compiler/optimizing/common_arm.h
+++ b/compiler/optimizing/common_arm.h
@@ -17,7 +17,7 @@
#ifndef ART_COMPILER_OPTIMIZING_COMMON_ARM_H_
#define ART_COMPILER_OPTIMIZING_COMMON_ARM_H_
-#include "debug/dwarf/register.h"
+#include "dwarf/register.h"
#include "instruction_simplifier_shared.h"
#include "locations.h"
#include "nodes.h"
diff --git a/compiler/utils/assembler.h b/compiler/utils/assembler.h
index 0537225..aa21f86 100644
--- a/compiler/utils/assembler.h
+++ b/compiler/utils/assembler.h
@@ -30,7 +30,7 @@
#include "base/enums.h"
#include "base/macros.h"
#include "base/memory_region.h"
-#include "debug/dwarf/debug_frame_opcode_writer.h"
+#include "dwarf/debug_frame_opcode_writer.h"
#include "label.h"
#include "managed_register.h"
#include "mips/constants_mips.h"