summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Vladimir Marko <vmarko@google.com> 2015-11-25 14:33:36 +0000
committer Vladimir Marko <vmarko@google.com> 2015-11-30 18:19:44 +0000
commit10c13565474de2786aad7c2e79757ea250747a15 (patch)
tree759bdf7aab97ab45e1a3e09f5d627e568f6e7084
parente928dc587718d00d234768f76d1efb2ffe74e885 (diff)
Refactor oat file writing to give Dex2Oat more control.
This is the first step towards writing dex files to oat file and mapping them from there for the actual AOT compilation. Change-Id: Icb0d27487eaf6ba3a66c157e695f9bdc5bb9cf9a
-rw-r--r--compiler/buffered_output_stream.cc20
-rw-r--r--compiler/buffered_output_stream.h19
-rw-r--r--compiler/driver/compiler_driver.cc17
-rw-r--r--compiler/driver/compiler_driver.h7
-rw-r--r--compiler/dwarf/method_debug_info.h41
-rw-r--r--compiler/elf_builder.h23
-rw-r--r--compiler/elf_writer.h33
-rw-r--r--compiler/elf_writer_debug.cc33
-rw-r--r--compiler/elf_writer_debug.h7
-rw-r--r--compiler/elf_writer_quick.cc190
-rw-r--r--compiler/elf_writer_quick.h45
-rw-r--r--compiler/elf_writer_test.cc3
-rw-r--r--compiler/file_output_stream.cc4
-rw-r--r--compiler/file_output_stream.h8
-rw-r--r--compiler/image_test.cc39
-rw-r--r--compiler/oat_test.cc38
-rw-r--r--compiler/oat_writer.cc3
-rw-r--r--compiler/oat_writer.h20
-rw-r--r--compiler/output_stream.h8
-rw-r--r--compiler/output_stream_test.cc41
-rw-r--r--compiler/vector_output_stream.h10
-rw-r--r--dex2oat/dex2oat.cc35
-rw-r--r--oatdump/oatdump.cc5
23 files changed, 431 insertions, 218 deletions
diff --git a/compiler/buffered_output_stream.cc b/compiler/buffered_output_stream.cc
index 3ca518b686..4c66c764a9 100644
--- a/compiler/buffered_output_stream.cc
+++ b/compiler/buffered_output_stream.cc
@@ -20,18 +20,24 @@
namespace art {
-BufferedOutputStream::BufferedOutputStream(OutputStream* out)
- : OutputStream(out->GetLocation()), out_(out), used_(0) {}
+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 (!Flush()) {
+ if (!FlushBuffer()) {
return false;
}
return out_->WriteFully(buffer, byte_count);
}
if (used_ + byte_count > kBufferSize) {
- if (!Flush()) {
+ if (!FlushBuffer()) {
return false;
}
}
@@ -42,6 +48,10 @@ bool BufferedOutputStream::WriteFully(const void* buffer, size_t byte_count) {
}
bool BufferedOutputStream::Flush() {
+ return FlushBuffer() && out_->Flush();
+}
+
+bool BufferedOutputStream::FlushBuffer() {
bool success = true;
if (used_ > 0) {
success = out_->WriteFully(&buffer_[0], used_);
@@ -51,7 +61,7 @@ bool BufferedOutputStream::Flush() {
}
off_t BufferedOutputStream::Seek(off_t offset, Whence whence) {
- if (!Flush()) {
+ if (!FlushBuffer()) {
return -1;
}
return out_->Seek(offset, whence);
diff --git a/compiler/buffered_output_stream.h b/compiler/buffered_output_stream.h
index b447f41e21..1da3a6932f 100644
--- a/compiler/buffered_output_stream.h
+++ b/compiler/buffered_output_stream.h
@@ -17,6 +17,8 @@
#ifndef ART_COMPILER_BUFFERED_OUTPUT_STREAM_H_
#define ART_COMPILER_BUFFERED_OUTPUT_STREAM_H_
+#include <memory>
+
#include "output_stream.h"
#include "globals.h"
@@ -25,26 +27,23 @@ namespace art {
class BufferedOutputStream FINAL : public OutputStream {
public:
- explicit BufferedOutputStream(OutputStream* out);
+ explicit BufferedOutputStream(std::unique_ptr<OutputStream> out);
- virtual ~BufferedOutputStream() {
- Flush();
- delete out_;
- }
+ ~BufferedOutputStream() OVERRIDE;
- virtual bool WriteFully(const void* buffer, size_t byte_count);
+ bool WriteFully(const void* buffer, size_t byte_count) OVERRIDE;
- virtual off_t Seek(off_t offset, Whence whence);
+ off_t Seek(off_t offset, Whence whence) OVERRIDE;
- bool Flush();
+ bool Flush() OVERRIDE;
private:
static const size_t kBufferSize = 8 * KB;
- OutputStream* const out_;
+ bool FlushBuffer();
+ std::unique_ptr<OutputStream> const out_;
uint8_t buffer_[kBufferSize];
-
size_t used_;
DISALLOW_COPY_AND_ASSIGN(BufferedOutputStream);
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index d67087edd9..9d3af1681a 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -45,7 +45,6 @@
#include "dex/quick/dex_file_method_inliner.h"
#include "dex/quick/dex_file_to_method_inliner_map.h"
#include "driver/compiler_options.h"
-#include "elf_writer_quick.h"
#include "jni_internal.h"
#include "object_lock.h"
#include "profiler.h"
@@ -77,9 +76,6 @@ namespace art {
static constexpr bool kTimeCompileMethod = !kIsDebugBuild;
-// Whether to produce 64-bit ELF files for 64-bit targets.
-static constexpr bool kProduce64BitELFFiles = true;
-
// Whether classes-to-compile and methods-to-compile are only applied to the boot image, or, when
// given, too all compilations.
static constexpr bool kRestrictCompilationFiltersToImage = true;
@@ -2514,19 +2510,6 @@ bool CompilerDriver::RequiresConstructorBarrier(Thread* self, const DexFile* dex
return freezing_constructor_classes_.count(ClassReference(dex_file, class_def_index)) != 0;
}
-bool CompilerDriver::WriteElf(const std::string& android_root,
- bool is_host,
- const std::vector<const art::DexFile*>& dex_files,
- OatWriter* oat_writer,
- art::File* file)
- SHARED_REQUIRES(Locks::mutator_lock_) {
- if (kProduce64BitELFFiles && Is64BitInstructionSet(GetInstructionSet())) {
- return art::ElfWriterQuick64::Create(file, oat_writer, dex_files, android_root, is_host, *this);
- } else {
- return art::ElfWriterQuick32::Create(file, oat_writer, dex_files, android_root, is_host, *this);
- }
-}
-
bool CompilerDriver::SkipCompilation(const std::string& method_name) {
if (!profile_present_) {
return false;
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index d90d6100b9..1347b37fa0 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -59,7 +59,6 @@ class DexCompilationUnit;
class DexFileToMethodInlinerMap;
struct InlineIGetIPutData;
class InstructionSetFeatures;
-class OatWriter;
class ParallelCompilationManager;
class ScopedObjectAccess;
template <class Allocator> class SrcMap;
@@ -398,12 +397,6 @@ class CompilerDriver {
support_boot_image_fixup_ = support_boot_image_fixup;
}
- bool WriteElf(const std::string& android_root,
- bool is_host,
- const std::vector<const DexFile*>& dex_files,
- OatWriter* oat_writer,
- File* file);
-
void SetCompilerContext(void* compiler_context) {
compiler_context_ = compiler_context;
}
diff --git a/compiler/dwarf/method_debug_info.h b/compiler/dwarf/method_debug_info.h
new file mode 100644
index 0000000000..a391e4d08a
--- /dev/null
+++ b/compiler/dwarf/method_debug_info.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_COMPILER_DWARF_METHOD_DEBUG_INFO_H_
+#define ART_COMPILER_DWARF_METHOD_DEBUG_INFO_H_
+
+#include "dex_file.h"
+
+namespace art {
+class CompiledMethod;
+namespace dwarf {
+
+struct MethodDebugInfo {
+ const DexFile* dex_file_;
+ size_t class_def_index_;
+ uint32_t dex_method_index_;
+ uint32_t access_flags_;
+ const DexFile::CodeItem* code_item_;
+ bool deduped_;
+ uint32_t low_pc_;
+ uint32_t high_pc_;
+ CompiledMethod* compiled_method_;
+};
+
+} // namespace dwarf
+} // namespace art
+
+#endif // ART_COMPILER_DWARF_METHOD_DEBUG_INFO_H_
diff --git a/compiler/elf_builder.h b/compiler/elf_builder.h
index 6e8dfd60fb..c19bc3db5c 100644
--- a/compiler/elf_builder.h
+++ b/compiler/elf_builder.h
@@ -27,6 +27,7 @@
#include "elf_utils.h"
#include "file_output_stream.h"
#include "leb128.h"
+#include "utils/array_ref.h"
namespace art {
@@ -100,7 +101,7 @@ class ElfBuilder FINAL {
header_.sh_entsize = entsize;
}
- virtual ~Section() {
+ ~Section() OVERRIDE {
if (started_) {
CHECK(finished_);
}
@@ -187,6 +188,12 @@ class ElfBuilder FINAL {
return owner_->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_->Flush();
+ }
+
Elf_Word GetSectionIndex() const {
DCHECK(started_);
DCHECK_NE(section_index_, 0u);
@@ -312,7 +319,7 @@ class ElfBuilder FINAL {
// Encode patch locations as LEB128 list of deltas between consecutive addresses.
// (exposed publicly for tests)
- static void EncodeOatPatches(const std::vector<uintptr_t>& locations,
+ static void EncodeOatPatches(const ArrayRef<const uintptr_t>& locations,
std::vector<uint8_t>* buffer) {
buffer->reserve(buffer->size() + locations.size() * 2); // guess 2 bytes per ULEB128.
uintptr_t address = 0; // relative to start of section.
@@ -323,9 +330,9 @@ class ElfBuilder FINAL {
}
}
- void WritePatches(const char* name, const std::vector<uintptr_t>* patch_locations) {
+ void WritePatches(const char* name, const ArrayRef<const uintptr_t>& patch_locations) {
std::vector<uint8_t> buffer;
- EncodeOatPatches(*patch_locations, &buffer);
+ EncodeOatPatches(patch_locations, &buffer);
std::unique_ptr<Section> s(new Section(this, name, SHT_OAT_PATCH, 0, nullptr, 0, 1, 0));
s->Start();
s->WriteFully(buffer.data(), buffer.size());
@@ -385,6 +392,7 @@ class ElfBuilder FINAL {
Seek(0, kSeekSet);
WriteFully(&elf_header, sizeof(elf_header));
WriteFully(phdrs.data(), phdrs.size() * sizeof(phdrs[0]));
+ Flush();
}
// The running program does not have access to section headers
@@ -509,6 +517,13 @@ class ElfBuilder FINAL {
return new_offset;
}
+ bool Flush() {
+ if (output_good_) {
+ output_good_ = output_->Flush();
+ }
+ return output_good_;
+ }
+
static Elf_Ehdr MakeElfHeader(InstructionSet isa) {
Elf_Ehdr elf_header = Elf_Ehdr();
switch (isa) {
diff --git a/compiler/elf_writer.h b/compiler/elf_writer.h
index 03f8ceb306..357d5f624e 100644
--- a/compiler/elf_writer.h
+++ b/compiler/elf_writer.h
@@ -25,13 +25,16 @@
#include "base/macros.h"
#include "base/mutex.h"
#include "os.h"
+#include "utils/array_ref.h"
namespace art {
-class CompilerDriver;
-class DexFile;
class ElfFile;
-class OatWriter;
+class OutputStream;
+
+namespace dwarf {
+struct MethodDebugInfo;
+} // namespace dwarf
class ElfWriter {
public:
@@ -46,21 +49,21 @@ class ElfWriter {
static bool Fixup(File* file, uintptr_t oat_data_begin);
- protected:
- ElfWriter(const CompilerDriver& driver, File* elf_file)
- : compiler_driver_(&driver), elf_file_(elf_file) {
- }
-
virtual ~ElfWriter() {}
- virtual bool Write(OatWriter* oat_writer,
- const std::vector<const DexFile*>& dex_files,
- const std::string& android_root,
- bool is_host)
- SHARED_REQUIRES(Locks::mutator_lock_) = 0;
+ virtual void Start() = 0;
+ virtual OutputStream* StartRoData() = 0;
+ virtual void EndRoData(OutputStream* rodata) = 0;
+ virtual OutputStream* StartText() = 0;
+ virtual void EndText(OutputStream* text) = 0;
+ virtual void SetBssSize(size_t bss_size) = 0;
+ virtual void WriteDynamicSection() = 0;
+ virtual void WriteDebugInfo(const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) = 0;
+ virtual void WritePatchLocations(const ArrayRef<const uintptr_t>& patch_locations) = 0;
+ virtual bool End() = 0;
- const CompilerDriver* const compiler_driver_;
- File* const elf_file_;
+ protected:
+ ElfWriter() = default;
};
} // namespace art
diff --git a/compiler/elf_writer_debug.cc b/compiler/elf_writer_debug.cc
index ee557fc8c3..5738779609 100644
--- a/compiler/elf_writer_debug.cc
+++ b/compiler/elf_writer_debug.cc
@@ -17,6 +17,7 @@
#include "elf_writer_debug.h"
#include <unordered_set>
+#include <vector>
#include "base/casts.h"
#include "base/stl_util.h"
@@ -25,6 +26,7 @@
#include "dex_file-inl.h"
#include "dwarf/dedup_vector.h"
#include "dwarf/headers.h"
+#include "dwarf/method_debug_info.h"
#include "dwarf/register.h"
#include "elf_builder.h"
#include "oat_writer.h"
@@ -203,7 +205,7 @@ static void WriteCIE(InstructionSet isa,
template<typename ElfTypes>
void WriteCFISection(ElfBuilder<ElfTypes>* builder,
- const std::vector<OatWriter::DebugInfo>& method_infos,
+ const ArrayRef<const MethodDebugInfo>& method_infos,
CFIFormat format) {
CHECK(format == dwarf::DW_DEBUG_FRAME_FORMAT ||
format == dwarf::DW_EH_FRAME_FORMAT);
@@ -233,7 +235,7 @@ void WriteCFISection(ElfBuilder<ElfTypes>* builder,
cfi_section->WriteFully(buffer.data(), buffer.size());
buffer_address += buffer.size();
buffer.clear();
- for (const OatWriter::DebugInfo& mi : method_infos) {
+ for (const MethodDebugInfo& mi : method_infos) {
if (!mi.deduped_) { // Only one FDE per unique address.
ArrayRef<const uint8_t> opcodes = mi.compiled_method_->GetCFIInfo();
if (!opcodes.empty()) {
@@ -286,12 +288,13 @@ void WriteCFISection(ElfBuilder<ElfTypes>* builder,
header_section->WriteFully(binary_search_table.data(), binary_search_table.size());
header_section->End();
} else {
- builder->WritePatches(".debug_frame.oat_patches", &patch_locations);
+ builder->WritePatches(".debug_frame.oat_patches",
+ ArrayRef<const uintptr_t>(patch_locations));
}
}
struct CompilationUnit {
- std::vector<const OatWriter::DebugInfo*> methods_;
+ std::vector<const MethodDebugInfo*> methods_;
size_t debug_line_offset_ = 0;
uint32_t low_pc_ = 0xFFFFFFFFU;
uint32_t high_pc_ = 0;
@@ -417,7 +420,7 @@ class DebugInfoWriter {
// Write table into .debug_loc which describes location of dex register.
// The dex register might be valid only at some points and it might
// move between machine registers and stack.
- void WriteRegLocation(const OatWriter::DebugInfo* method_info, uint16_t vreg,
+ void WriteRegLocation(const MethodDebugInfo* method_info, uint16_t vreg,
bool is64bitValue, uint32_t compilation_unit_low_pc) {
using Kind = DexRegisterLocation::Kind;
bool is_optimizing = method_info->compiled_method_->GetQuickCode().size() > 0 &&
@@ -736,7 +739,8 @@ class DebugInfoWriter {
void End() {
builder_->GetDebugInfo()->End();
- builder_->WritePatches(".debug_info.oat_patches", &debug_info_patches_);
+ builder_->WritePatches(".debug_info.oat_patches",
+ ArrayRef<const uintptr_t>(debug_info_patches_));
builder_->WriteSection(".debug_abbrev", &debug_abbrev_.Data());
builder_->WriteSection(".debug_str", &debug_str_.Data());
builder_->WriteSection(".debug_loc", &debug_loc_);
@@ -803,7 +807,7 @@ class DebugLineWriter {
if (dwarf_isa != -1) {
opcodes.SetISA(dwarf_isa);
}
- for (const OatWriter::DebugInfo* mi : compilation_unit.methods_) {
+ for (const MethodDebugInfo* mi : compilation_unit.methods_) {
// Ignore function if we have already generated line table for the same address.
// It would confuse the debugger and the DWARF specification forbids it.
if (mi->deduped_) {
@@ -920,7 +924,8 @@ class DebugLineWriter {
void End() {
builder_->GetDebugLine()->End();
- builder_->WritePatches(".debug_line.oat_patches", &debug_line_patches);
+ builder_->WritePatches(".debug_line.oat_patches",
+ ArrayRef<const uintptr_t>(debug_line_patches));
}
private:
@@ -930,11 +935,11 @@ class DebugLineWriter {
template<typename ElfTypes>
void WriteDebugSections(ElfBuilder<ElfTypes>* builder,
- const std::vector<OatWriter::DebugInfo>& method_infos) {
+ const ArrayRef<const MethodDebugInfo>& method_infos) {
// Group the methods into compilation units based on source file.
std::vector<CompilationUnit> compilation_units;
const char* last_source_file = nullptr;
- for (const OatWriter::DebugInfo& mi : method_infos) {
+ for (const MethodDebugInfo& mi : method_infos) {
auto& dex_class_def = mi.dex_file_->GetClassDef(mi.class_def_index_);
const char* source_file = mi.dex_file_->GetSourceFile(dex_class_def);
if (compilation_units.empty() || source_file != last_source_file) {
@@ -971,18 +976,18 @@ void WriteDebugSections(ElfBuilder<ElfTypes>* builder,
// Explicit instantiations
template void WriteCFISection<ElfTypes32>(
ElfBuilder<ElfTypes32>* builder,
- const std::vector<OatWriter::DebugInfo>& method_infos,
+ const ArrayRef<const MethodDebugInfo>& method_infos,
CFIFormat format);
template void WriteCFISection<ElfTypes64>(
ElfBuilder<ElfTypes64>* builder,
- const std::vector<OatWriter::DebugInfo>& method_infos,
+ const ArrayRef<const MethodDebugInfo>& method_infos,
CFIFormat format);
template void WriteDebugSections<ElfTypes32>(
ElfBuilder<ElfTypes32>* builder,
- const std::vector<OatWriter::DebugInfo>& method_infos);
+ const ArrayRef<const MethodDebugInfo>& method_infos);
template void WriteDebugSections<ElfTypes64>(
ElfBuilder<ElfTypes64>* builder,
- const std::vector<OatWriter::DebugInfo>& method_infos);
+ const ArrayRef<const MethodDebugInfo>& method_infos);
} // namespace dwarf
} // namespace art
diff --git a/compiler/elf_writer_debug.h b/compiler/elf_writer_debug.h
index e58fd0a390..9ed102f91b 100644
--- a/compiler/elf_writer_debug.h
+++ b/compiler/elf_writer_debug.h
@@ -17,23 +17,22 @@
#ifndef ART_COMPILER_ELF_WRITER_DEBUG_H_
#define ART_COMPILER_ELF_WRITER_DEBUG_H_
-#include <vector>
-
#include "elf_builder.h"
#include "dwarf/dwarf_constants.h"
#include "oat_writer.h"
+#include "utils/array_ref.h"
namespace art {
namespace dwarf {
template<typename ElfTypes>
void WriteCFISection(ElfBuilder<ElfTypes>* builder,
- const std::vector<OatWriter::DebugInfo>& method_infos,
+ const ArrayRef<const MethodDebugInfo>& method_infos,
CFIFormat format);
template<typename ElfTypes>
void WriteDebugSections(ElfBuilder<ElfTypes>* builder,
- const std::vector<OatWriter::DebugInfo>& method_infos);
+ const ArrayRef<const MethodDebugInfo>& method_infos);
} // namespace dwarf
} // namespace art
diff --git a/compiler/elf_writer_quick.cc b/compiler/elf_writer_quick.cc
index 5c059e1e82..9da2af8d3e 100644
--- a/compiler/elf_writer_quick.cc
+++ b/compiler/elf_writer_quick.cc
@@ -21,19 +21,16 @@
#include "base/casts.h"
#include "base/logging.h"
-#include "base/unix_file/fd_file.h"
+#include "base/stl_util.h"
#include "compiled_method.h"
-#include "dex_file-inl.h"
-#include "driver/compiler_driver.h"
#include "driver/compiler_options.h"
+#include "dwarf/method_debug_info.h"
+#include "elf.h"
#include "elf_builder.h"
-#include "elf_file.h"
#include "elf_utils.h"
#include "elf_writer_debug.h"
#include "globals.h"
#include "leb128.h"
-#include "oat.h"
-#include "oat_writer.h"
#include "utils.h"
namespace art {
@@ -57,125 +54,186 @@ constexpr dwarf::CFIFormat kCFIFormat = dwarf::DW_DEBUG_FRAME_FORMAT;
constexpr bool kGenerateSingleArmMappingSymbol = true;
template <typename ElfTypes>
-bool ElfWriterQuick<ElfTypes>::Create(File* elf_file,
- OatWriter* oat_writer,
- const std::vector<const DexFile*>& dex_files,
- const std::string& android_root,
- bool is_host,
- const CompilerDriver& driver) {
- ElfWriterQuick elf_writer(driver, elf_file);
- return elf_writer.Write(oat_writer, dex_files, android_root, is_host);
+class ElfWriterQuick FINAL : public ElfWriter {
+ public:
+ ElfWriterQuick(InstructionSet instruction_set,
+ const CompilerOptions* compiler_options,
+ File* elf_file);
+ ~ElfWriterQuick();
+
+ void Start() OVERRIDE;
+ OutputStream* StartRoData() OVERRIDE;
+ void EndRoData(OutputStream* rodata) OVERRIDE;
+ OutputStream* StartText() OVERRIDE;
+ void EndText(OutputStream* text) OVERRIDE;
+ void SetBssSize(size_t bss_size) OVERRIDE;
+ void WriteDynamicSection() OVERRIDE;
+ void WriteDebugInfo(const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) OVERRIDE;
+ void WritePatchLocations(const ArrayRef<const uintptr_t>& patch_locations) OVERRIDE;
+ bool End() OVERRIDE;
+
+ static void EncodeOatPatches(const std::vector<uintptr_t>& locations,
+ std::vector<uint8_t>* buffer);
+
+ private:
+ const CompilerOptions* const compiler_options_;
+ File* const elf_file_;
+ std::unique_ptr<BufferedOutputStream> output_stream_;
+ std::unique_ptr<ElfBuilder<ElfTypes>> builder_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ElfWriterQuick);
+};
+
+std::unique_ptr<ElfWriter> CreateElfWriterQuick(InstructionSet instruction_set,
+ const CompilerOptions* compiler_options,
+ File* elf_file) {
+ if (Is64BitInstructionSet(instruction_set)) {
+ return MakeUnique<ElfWriterQuick<ElfTypes64>>(instruction_set, compiler_options, elf_file);
+ } else {
+ return MakeUnique<ElfWriterQuick<ElfTypes32>>(instruction_set, compiler_options, elf_file);
+ }
}
template <typename ElfTypes>
-static void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder, OatWriter* oat_writer);
+static void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder,
+ const ArrayRef<const dwarf::MethodDebugInfo>& method_infos);
+
+template <typename ElfTypes>
+ElfWriterQuick<ElfTypes>::ElfWriterQuick(InstructionSet instruction_set,
+ const CompilerOptions* compiler_options,
+ File* elf_file)
+ : ElfWriter(),
+ compiler_options_(compiler_options),
+ elf_file_(elf_file),
+ output_stream_(MakeUnique<BufferedOutputStream>(MakeUnique<FileOutputStream>(elf_file))),
+ builder_(new ElfBuilder<ElfTypes>(instruction_set, output_stream_.get())) {}
template <typename ElfTypes>
-bool ElfWriterQuick<ElfTypes>::Write(
- OatWriter* oat_writer,
- const std::vector<const DexFile*>& dex_files_unused ATTRIBUTE_UNUSED,
- const std::string& android_root_unused ATTRIBUTE_UNUSED,
- bool is_host_unused ATTRIBUTE_UNUSED) {
- const InstructionSet isa = compiler_driver_->GetInstructionSet();
- std::unique_ptr<BufferedOutputStream> output_stream(
- new BufferedOutputStream(new FileOutputStream(elf_file_)));
- std::unique_ptr<ElfBuilder<ElfTypes>> builder(
- new ElfBuilder<ElfTypes>(isa, output_stream.get()));
-
- builder->Start();
-
- auto* rodata = builder->GetRoData();
- auto* text = builder->GetText();
- auto* bss = builder->GetBss();
+ElfWriterQuick<ElfTypes>::~ElfWriterQuick() {}
+template <typename ElfTypes>
+void ElfWriterQuick<ElfTypes>::Start() {
+ builder_->Start();
+}
+
+template <typename ElfTypes>
+OutputStream* ElfWriterQuick<ElfTypes>::StartRoData() {
+ auto* rodata = builder_->GetRoData();
rodata->Start();
- if (!oat_writer->WriteRodata(rodata)) {
- return false;
- }
- rodata->End();
+ return rodata;
+}
+template <typename ElfTypes>
+void ElfWriterQuick<ElfTypes>::EndRoData(OutputStream* rodata) {
+ CHECK_EQ(builder_->GetRoData(), rodata);
+ builder_->GetRoData()->End();
+}
+
+template <typename ElfTypes>
+OutputStream* ElfWriterQuick<ElfTypes>::StartText() {
+ auto* text = builder_->GetText();
text->Start();
- if (!oat_writer->WriteCode(text)) {
- return false;
- }
- text->End();
+ return text;
+}
+
+template <typename ElfTypes>
+void ElfWriterQuick<ElfTypes>::EndText(OutputStream* text) {
+ CHECK_EQ(builder_->GetText(), text);
+ builder_->GetText()->End();
+}
- if (oat_writer->GetBssSize() != 0) {
+template <typename ElfTypes>
+void ElfWriterQuick<ElfTypes>::SetBssSize(size_t bss_size) {
+ auto* bss = builder_->GetBss();
+ if (bss_size != 0u) {
bss->Start();
- bss->SetSize(oat_writer->GetBssSize());
+ bss->SetSize(bss_size);
bss->End();
}
+}
- builder->WriteDynamicSection(elf_file_->GetPath());
+template <typename ElfTypes>
+void ElfWriterQuick<ElfTypes>::WriteDynamicSection() {
+ builder_->WriteDynamicSection(elf_file_->GetPath());
+}
- if (compiler_driver_->GetCompilerOptions().GetGenerateDebugInfo()) {
- const auto& method_infos = oat_writer->GetMethodDebugInfo();
+template <typename ElfTypes>
+void ElfWriterQuick<ElfTypes>::WriteDebugInfo(
+ const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) {
+ if (compiler_options_->GetGenerateDebugInfo()) {
if (!method_infos.empty()) {
// Add methods to .symtab.
- WriteDebugSymbols(builder.get(), oat_writer);
+ WriteDebugSymbols(builder_.get(), method_infos);
// Generate CFI (stack unwinding information).
- dwarf::WriteCFISection(builder.get(), method_infos, kCFIFormat);
+ dwarf::WriteCFISection(builder_.get(), method_infos, kCFIFormat);
// Write DWARF .debug_* sections.
- dwarf::WriteDebugSections(builder.get(), method_infos);
+ dwarf::WriteDebugSections(builder_.get(), method_infos);
}
}
+}
+template <typename ElfTypes>
+void ElfWriterQuick<ElfTypes>::WritePatchLocations(
+ const ArrayRef<const uintptr_t>& patch_locations) {
// Add relocation section for .text.
- if (compiler_driver_->GetCompilerOptions().GetIncludePatchInformation()) {
+ if (compiler_options_->GetIncludePatchInformation()) {
// Note that ElfWriter::Fixup will be called regardless and therefore
// we need to include oat_patches for debug sections unconditionally.
- builder->WritePatches(".text.oat_patches", &oat_writer->GetAbsolutePatchLocations());
+ builder_->WritePatches(".text.oat_patches", patch_locations);
}
+}
- builder->End();
+template <typename ElfTypes>
+bool ElfWriterQuick<ElfTypes>::End() {
+ builder_->End();
- return builder->Good() && output_stream->Flush();
+ return builder_->Good();
}
template <typename ElfTypes>
-static void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder, OatWriter* oat_writer) {
- const std::vector<OatWriter::DebugInfo>& method_info = oat_writer->GetMethodDebugInfo();
+static void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder,
+ const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) {
bool generated_mapping_symbol = false;
auto* strtab = builder->GetStrTab();
auto* symtab = builder->GetSymTab();
- if (method_info.empty()) {
+ if (method_infos.empty()) {
return;
}
// Find all addresses (low_pc) which contain deduped methods.
// The first instance of method is not marked deduped_, but the rest is.
std::unordered_set<uint32_t> deduped_addresses;
- for (auto it = method_info.begin(); it != method_info.end(); ++it) {
- if (it->deduped_) {
- deduped_addresses.insert(it->low_pc_);
+ for (const dwarf::MethodDebugInfo& info : method_infos) {
+ if (info.deduped_) {
+ deduped_addresses.insert(info.low_pc_);
}
}
strtab->Start();
strtab->Write(""); // strtab should start with empty string.
- for (auto it = method_info.begin(); it != method_info.end(); ++it) {
- if (it->deduped_) {
+ for (const dwarf::MethodDebugInfo& info : method_infos) {
+ if (info.deduped_) {
continue; // Add symbol only for the first instance.
}
- std::string name = PrettyMethod(it->dex_method_index_, *it->dex_file_, true);
- if (deduped_addresses.find(it->low_pc_) != deduped_addresses.end()) {
+ std::string name = PrettyMethod(info.dex_method_index_, *info.dex_file_, true);
+ if (deduped_addresses.find(info.low_pc_) != deduped_addresses.end()) {
name += " [DEDUPED]";
}
- uint32_t low_pc = it->low_pc_;
+ uint32_t low_pc = info.low_pc_;
// Add in code delta, e.g., thumb bit 0 for Thumb2 code.
- low_pc += it->compiled_method_->CodeDelta();
+ low_pc += info.compiled_method_->CodeDelta();
symtab->Add(strtab->Write(name), builder->GetText(), low_pc,
- true, it->high_pc_ - it->low_pc_, STB_GLOBAL, STT_FUNC);
+ true, info.high_pc_ - info.low_pc_, STB_GLOBAL, STT_FUNC);
// Conforming to aaelf, add $t mapping symbol to indicate start of a sequence of thumb2
// instructions, so that disassembler tools can correctly disassemble.
// Note that even if we generate just a single mapping symbol, ARM's Streamline
// requires it to match function symbol. Just address 0 does not work.
- if (it->compiled_method_->GetInstructionSet() == kThumb2) {
+ if (info.compiled_method_->GetInstructionSet() == kThumb2) {
if (!generated_mapping_symbol || !kGenerateSingleArmMappingSymbol) {
- symtab->Add(strtab->Write("$t"), builder->GetText(), it->low_pc_ & ~1,
+ symtab->Add(strtab->Write("$t"), builder->GetText(), info.low_pc_ & ~1,
true, 0, STB_LOCAL, STT_NOTYPE);
generated_mapping_symbol = true;
}
diff --git a/compiler/elf_writer_quick.h b/compiler/elf_writer_quick.h
index 83781abeff..347d372fe2 100644
--- a/compiler/elf_writer_quick.h
+++ b/compiler/elf_writer_quick.h
@@ -17,46 +17,19 @@
#ifndef ART_COMPILER_ELF_WRITER_QUICK_H_
#define ART_COMPILER_ELF_WRITER_QUICK_H_
-#include "elf_utils.h"
+#include <memory>
+
+#include "arch/instruction_set.h"
#include "elf_writer.h"
-#include "oat_writer.h"
+#include "os.h"
namespace art {
-template <typename ElfTypes>
-class ElfWriterQuick FINAL : public ElfWriter {
- public:
- // Write an ELF file. Returns true on success, false on failure.
- static bool Create(File* file,
- OatWriter* oat_writer,
- const std::vector<const DexFile*>& dex_files,
- const std::string& android_root,
- bool is_host,
- const CompilerDriver& driver)
- SHARED_REQUIRES(Locks::mutator_lock_);
-
- static void EncodeOatPatches(const std::vector<uintptr_t>& locations,
- std::vector<uint8_t>* buffer);
-
- protected:
- bool Write(OatWriter* oat_writer,
- const std::vector<const DexFile*>& dex_files,
- const std::string& android_root,
- bool is_host)
- OVERRIDE
- SHARED_REQUIRES(Locks::mutator_lock_);
-
- private:
- ElfWriterQuick(const CompilerDriver& driver, File* elf_file)
- : ElfWriter(driver, elf_file) {}
- ~ElfWriterQuick() {}
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(ElfWriterQuick);
-};
-
-// Explicitly instantiated in elf_writer_quick.cc
-typedef ElfWriterQuick<ElfTypes32> ElfWriterQuick32;
-typedef ElfWriterQuick<ElfTypes64> ElfWriterQuick64;
+class CompilerOptions;
+
+std::unique_ptr<ElfWriter> CreateElfWriterQuick(InstructionSet instruction_set,
+ const CompilerOptions* compiler_options,
+ File* elf_file);
} // namespace art
diff --git a/compiler/elf_writer_test.cc b/compiler/elf_writer_test.cc
index b413a9eb7b..7cf774e95f 100644
--- a/compiler/elf_writer_test.cc
+++ b/compiler/elf_writer_test.cc
@@ -101,7 +101,8 @@ TEST_F(ElfWriterTest, EncodeDecodeOatPatches) {
// Encode patch locations.
std::vector<uint8_t> oat_patches;
- ElfBuilder<ElfTypes32>::EncodeOatPatches(patch_locations, &oat_patches);
+ ElfBuilder<ElfTypes32>::EncodeOatPatches(ArrayRef<const uintptr_t>(patch_locations),
+ &oat_patches);
// Create buffer to be patched.
std::vector<uint8_t> initial_data(256);
diff --git a/compiler/file_output_stream.cc b/compiler/file_output_stream.cc
index 3ee16f53e8..bbfbdfdca8 100644
--- a/compiler/file_output_stream.cc
+++ b/compiler/file_output_stream.cc
@@ -33,4 +33,8 @@ 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 art
diff --git a/compiler/file_output_stream.h b/compiler/file_output_stream.h
index 9dfbd7fcef..6917d83f29 100644
--- a/compiler/file_output_stream.h
+++ b/compiler/file_output_stream.h
@@ -27,11 +27,13 @@ class FileOutputStream FINAL : public OutputStream {
public:
explicit FileOutputStream(File* file);
- virtual ~FileOutputStream() {}
+ ~FileOutputStream() OVERRIDE {}
- virtual bool WriteFully(const void* buffer, size_t byte_count);
+ bool WriteFully(const void* buffer, size_t byte_count) OVERRIDE;
- virtual off_t Seek(off_t offset, Whence whence);
+ off_t Seek(off_t offset, Whence whence) OVERRIDE;
+
+ bool Flush() OVERRIDE;
private:
File* const file_;
diff --git a/compiler/image_test.cc b/compiler/image_test.cc
index 6df15279a0..5f4a92299b 100644
--- a/compiler/image_test.cc
+++ b/compiler/image_test.cc
@@ -23,7 +23,9 @@
#include "base/unix_file/fd_file.h"
#include "class_linker-inl.h"
#include "common_compiler_test.h"
+#include "dwarf/method_debug_info.h"
#include "elf_writer.h"
+#include "elf_writer_quick.h"
#include "gc/space/image_space.h"
#include "image_writer.h"
#include "lock_word.h"
@@ -92,12 +94,37 @@ TEST_F(ImageTest, WriteRead) {
/*compiling_boot_image*/true,
&timings,
&key_value_store);
- bool success = writer->PrepareImageAddressSpace() &&
- compiler_driver_->WriteElf(GetTestAndroidRoot(),
- !kIsTargetBuild,
- class_linker->GetBootClassPath(),
- &oat_writer,
- oat_file.GetFile());
+ std::unique_ptr<ElfWriter> elf_writer = CreateElfWriterQuick(
+ compiler_driver_->GetInstructionSet(),
+ &compiler_driver_->GetCompilerOptions(),
+ oat_file.GetFile());
+ bool success = writer->PrepareImageAddressSpace();
+ ASSERT_TRUE(success);
+
+ elf_writer->Start();
+
+ OutputStream* rodata = elf_writer->StartRoData();
+ bool rodata_ok = oat_writer.WriteRodata(rodata);
+ ASSERT_TRUE(rodata_ok);
+ elf_writer->EndRoData(rodata);
+
+ OutputStream* text = elf_writer->StartText();
+ bool text_ok = oat_writer.WriteCode(text);
+ ASSERT_TRUE(text_ok);
+ elf_writer->EndText(text);
+
+ elf_writer->SetBssSize(oat_writer.GetBssSize());
+
+ elf_writer->WriteDynamicSection();
+
+ ArrayRef<const dwarf::MethodDebugInfo> method_infos(oat_writer.GetMethodDebugInfo());
+ elf_writer->WriteDebugInfo(method_infos);
+
+ ArrayRef<const uintptr_t> patch_locations(oat_writer.GetAbsolutePatchLocations());
+ elf_writer->WritePatchLocations(patch_locations);
+
+ success = elf_writer->End();
+
ASSERT_TRUE(success);
}
}
diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc
index 030451c1cb..c305b120cb 100644
--- a/compiler/oat_test.cc
+++ b/compiler/oat_test.cc
@@ -27,6 +27,9 @@
#include "dex/verification_results.h"
#include "driver/compiler_driver.h"
#include "driver/compiler_options.h"
+#include "dwarf/method_debug_info.h"
+#include "elf_writer.h"
+#include "elf_writer_quick.h"
#include "entrypoints/quick/quick_entrypoints.h"
#include "mirror/class-inl.h"
#include "mirror/object_array-inl.h"
@@ -134,11 +137,36 @@ class OatTest : public CommonCompilerTest {
/*compiling_boot_image*/false,
&timings,
&key_value_store);
- return compiler_driver_->WriteElf(GetTestAndroidRoot(),
- !kIsTargetBuild,
- dex_files,
- &oat_writer,
- file);
+ std::unique_ptr<ElfWriter> elf_writer = CreateElfWriterQuick(
+ compiler_driver_->GetInstructionSet(),
+ &compiler_driver_->GetCompilerOptions(),
+ file);
+
+ elf_writer->Start();
+
+ OutputStream* rodata = elf_writer->StartRoData();
+ if (!oat_writer.WriteRodata(rodata)) {
+ return false;
+ }
+ elf_writer->EndRoData(rodata);
+
+ OutputStream* text = elf_writer->StartText();
+ if (!oat_writer.WriteCode(text)) {
+ return false;
+ }
+ elf_writer->EndText(text);
+
+ elf_writer->SetBssSize(oat_writer.GetBssSize());
+
+ elf_writer->WriteDynamicSection();
+
+ ArrayRef<const dwarf::MethodDebugInfo> method_infos(oat_writer.GetMethodDebugInfo());
+ elf_writer->WriteDebugInfo(method_infos);
+
+ ArrayRef<const uintptr_t> patch_locations(oat_writer.GetAbsolutePatchLocations());
+ elf_writer->WritePatchLocations(patch_locations);
+
+ return elf_writer->End();
}
std::unique_ptr<const InstructionSetFeatures> insn_features_;
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index 40a3f14f93..a6a49f901a 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -31,6 +31,7 @@
#include "dex/verification_results.h"
#include "driver/compiler_driver.h"
#include "driver/compiler_options.h"
+#include "dwarf/method_debug_info.h"
#include "gc/space/image_space.h"
#include "gc/space/space.h"
#include "handle_scope-inl.h"
@@ -485,7 +486,7 @@ class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor {
// Record debug information for this function if we are doing that.
const uint32_t quick_code_start = quick_code_offset -
writer_->oat_header_->GetExecutableOffset() - thumb_offset;
- writer_->method_info_.push_back(DebugInfo {
+ writer_->method_info_.push_back(dwarf::MethodDebugInfo {
dex_file_,
class_def_index_,
it.GetMemberIndex(),
diff --git a/compiler/oat_writer.h b/compiler/oat_writer.h
index 7027434cca..6c46ebc4ec 100644
--- a/compiler/oat_writer.h
+++ b/compiler/oat_writer.h
@@ -38,6 +38,10 @@ class OutputStream;
class TimingLogger;
class TypeLookupTable;
+namespace dwarf {
+struct MethodDebugInfo;
+} // namespace dwarf
+
// OatHeader variable length with count of D OatDexFiles
//
// OatDexFile[0] one variable sized OatDexFile with offsets to Dex and OatClasses
@@ -129,19 +133,7 @@ class OatWriter {
~OatWriter();
- struct DebugInfo {
- const DexFile* dex_file_;
- size_t class_def_index_;
- uint32_t dex_method_index_;
- uint32_t access_flags_;
- const DexFile::CodeItem *code_item_;
- bool deduped_;
- uint32_t low_pc_;
- uint32_t high_pc_;
- CompiledMethod* compiled_method_;
- };
-
- const std::vector<DebugInfo>& GetMethodDebugInfo() const {
+ const std::vector<dwarf::MethodDebugInfo>& GetMethodDebugInfo() const {
return method_info_;
}
@@ -280,7 +272,7 @@ class OatWriter {
DISALLOW_COPY_AND_ASSIGN(OatClass);
};
- std::vector<DebugInfo> method_info_;
+ std::vector<dwarf::MethodDebugInfo> method_info_;
const CompilerDriver* const compiler_driver_;
ImageWriter* const image_writer_;
diff --git a/compiler/output_stream.h b/compiler/output_stream.h
index 4d30b83234..8f6b6d8235 100644
--- a/compiler/output_stream.h
+++ b/compiler/output_stream.h
@@ -45,6 +45,14 @@ class OutputStream {
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_;
diff --git a/compiler/output_stream_test.cc b/compiler/output_stream_test.cc
index 6104ccd758..84c76f2c6c 100644
--- a/compiler/output_stream_test.cc
+++ b/compiler/output_stream_test.cc
@@ -19,6 +19,7 @@
#include "base/unix_file/fd_file.h"
#include "base/logging.h"
+#include "base/stl_util.h"
#include "buffered_output_stream.h"
#include "common_runtime_test.h"
@@ -48,6 +49,7 @@ class OutputStreamTest : public CommonRuntimeTest {
EXPECT_TRUE(output_stream_->WriteFully(buf, 4));
CheckOffset(10);
EXPECT_TRUE(output_stream_->WriteFully(buf, 6));
+ EXPECT_TRUE(output_stream_->Flush());
}
void CheckTestOutput(const std::vector<uint8_t>& actual) {
@@ -77,9 +79,7 @@ TEST_F(OutputStreamTest, File) {
TEST_F(OutputStreamTest, Buffered) {
ScratchFile tmp;
{
- std::unique_ptr<FileOutputStream> file_output_stream(new FileOutputStream(tmp.GetFile()));
- CHECK(file_output_stream.get() != nullptr);
- BufferedOutputStream buffered_output_stream(file_output_stream.release());
+ BufferedOutputStream buffered_output_stream(MakeUnique<FileOutputStream>(tmp.GetFile()));
SetOutputStream(buffered_output_stream);
GenerateTestOutput();
}
@@ -99,4 +99,39 @@ TEST_F(OutputStreamTest, Vector) {
CheckTestOutput(output);
}
+TEST_F(OutputStreamTest, BufferedFlush) {
+ struct CheckingOutputStream : OutputStream {
+ CheckingOutputStream()
+ : OutputStream("dummy"),
+ flush_called(false) { }
+ ~CheckingOutputStream() OVERRIDE {}
+
+ bool WriteFully(const void* buffer ATTRIBUTE_UNUSED,
+ size_t byte_count ATTRIBUTE_UNUSED) OVERRIDE {
+ LOG(FATAL) << "UNREACHABLE";
+ UNREACHABLE();
+ }
+
+ off_t Seek(off_t offset ATTRIBUTE_UNUSED, Whence whence ATTRIBUTE_UNUSED) OVERRIDE {
+ LOG(FATAL) << "UNREACHABLE";
+ UNREACHABLE();
+ }
+
+ bool Flush() OVERRIDE {
+ flush_called = true;
+ return true;
+ }
+
+ bool flush_called;
+ };
+
+ std::unique_ptr<CheckingOutputStream> cos = MakeUnique<CheckingOutputStream>();
+ CheckingOutputStream* checking_output_stream = cos.get();
+ BufferedOutputStream buffered(std::move(cos));
+ ASSERT_FALSE(checking_output_stream->flush_called);
+ bool flush_result = buffered.Flush();
+ ASSERT_TRUE(flush_result);
+ ASSERT_TRUE(checking_output_stream->flush_called);
+}
+
} // namespace art
diff --git a/compiler/vector_output_stream.h b/compiler/vector_output_stream.h
index 3c5877c0bd..a3c58d0800 100644
--- a/compiler/vector_output_stream.h
+++ b/compiler/vector_output_stream.h
@@ -29,9 +29,9 @@ class VectorOutputStream FINAL : public OutputStream {
public:
VectorOutputStream(const std::string& location, std::vector<uint8_t>* vector);
- virtual ~VectorOutputStream() {}
+ ~VectorOutputStream() OVERRIDE {}
- bool WriteFully(const void* buffer, size_t byte_count) {
+ 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]);
@@ -45,7 +45,11 @@ class VectorOutputStream FINAL : public OutputStream {
return true;
}
- off_t Seek(off_t offset, Whence whence);
+ off_t Seek(off_t offset, Whence whence) OVERRIDE;
+
+ bool Flush() OVERRIDE {
+ return true;
+ }
private:
void EnsureCapacity(off_t new_offset) {
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 89c2a7cbdf..77211ce059 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -55,8 +55,10 @@
#include "dex/quick/dex_file_to_method_inliner_map.h"
#include "driver/compiler_driver.h"
#include "driver/compiler_options.h"
+#include "dwarf/method_debug_info.h"
#include "elf_file.h"
#include "elf_writer.h"
+#include "elf_writer_quick.h"
#include "gc/space/image_space.h"
#include "gc/space/space-inl.h"
#include "image_writer.h"
@@ -494,6 +496,7 @@ class Dex2Oat FINAL {
app_image_(false),
boot_image_(false),
is_host_(false),
+ image_writer_(nullptr),
driver_(nullptr),
dump_stats_(false),
dump_passes_(false),
@@ -1408,8 +1411,36 @@ class Dex2Oat FINAL {
{
TimingLogger::ScopedTiming t2("dex2oat Write ELF", timings_);
- if (!driver_->WriteElf(android_root_, is_host_, dex_files_, oat_writer.get(),
- oat_file_.get())) {
+ std::unique_ptr<ElfWriter> elf_writer =
+ CreateElfWriterQuick(instruction_set_, compiler_options_.get(), oat_file_.get());
+
+ elf_writer->Start();
+
+ OutputStream* rodata = elf_writer->StartRoData();
+ if (!oat_writer->WriteRodata(rodata)) {
+ LOG(ERROR) << "Failed to write .rodata section to the ELF file " << oat_file_->GetPath();
+ return false;
+ }
+ elf_writer->EndRoData(rodata);
+
+ OutputStream* text = elf_writer->StartText();
+ if (!oat_writer->WriteCode(text)) {
+ LOG(ERROR) << "Failed to write .text section to the ELF file " << oat_file_->GetPath();
+ return false;
+ }
+ elf_writer->EndText(text);
+
+ elf_writer->SetBssSize(oat_writer->GetBssSize());
+
+ elf_writer->WriteDynamicSection();
+
+ ArrayRef<const dwarf::MethodDebugInfo> method_infos(oat_writer->GetMethodDebugInfo());
+ elf_writer->WriteDebugInfo(method_infos);
+
+ ArrayRef<const uintptr_t> patch_locations(oat_writer->GetAbsolutePatchLocations());
+ elf_writer->WritePatchLocations(patch_locations);
+
+ if (!elf_writer->End()) {
LOG(ERROR) << "Failed to write ELF file " << oat_file_->GetPath();
return false;
}
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 94eb82b054..d20f7d53de 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -28,6 +28,7 @@
#include "arch/instruction_set_features.h"
#include "art_field-inl.h"
#include "art_method-inl.h"
+#include "base/stl_util.h"
#include "base/unix_file/fd_file.h"
#include "class_linker.h"
#include "class_linker-inl.h"
@@ -116,7 +117,7 @@ class OatSymbolizer FINAL {
File* elf_file = OS::CreateEmptyFile(output_name_.c_str());
std::unique_ptr<BufferedOutputStream> output_stream(
- new BufferedOutputStream(new FileOutputStream(elf_file)));
+ MakeUnique<BufferedOutputStream>(MakeUnique<FileOutputStream>(elf_file)));
builder_.reset(new ElfBuilder<ElfTypes32>(isa, output_stream.get()));
builder_->Start();
@@ -162,7 +163,7 @@ class OatSymbolizer FINAL {
builder_->End();
- return builder_->Good() && output_stream->Flush();
+ return builder_->Good();
}
void Walk(Callback callback) {