summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dex2oat/linker/oat_writer.cc64
-rw-r--r--dex2oat/linker/oat_writer.h7
-rw-r--r--dexlayout/compact_dex_writer.cc54
-rw-r--r--dexlayout/dex_container.h7
-rw-r--r--dexlayout/dex_ir.cc9
-rw-r--r--dexlayout/dex_ir_builder.cc7
-rw-r--r--dexlayout/dex_writer.cc2
-rw-r--r--dexlayout/dexlayout.cc39
-rw-r--r--oatdump/oatdump.cc7
-rw-r--r--openjdkjvmti/fixed_up_dex_file.cc18
-rw-r--r--runtime/dex/art_dex_file_loader.cc8
-rw-r--r--runtime/dex/code_item_accessors-no_art-inl.h2
-rw-r--r--runtime/dex/code_item_accessors_test.cc8
-rw-r--r--runtime/dex/compact_dex_file.cc33
-rw-r--r--runtime/dex/compact_dex_file.h20
-rw-r--r--runtime/dex/dex_file-inl.h4
-rw-r--r--runtime/dex/dex_file.cc19
-rw-r--r--runtime/dex/dex_file.h103
-rw-r--r--runtime/dex/dex_file_loader.cc60
-rw-r--r--runtime/dex/dex_file_loader.h16
-rw-r--r--runtime/dex/standard_dex_file.cc5
-rw-r--r--runtime/dex/standard_dex_file.h2
-rw-r--r--runtime/oat_file.cc23
-rw-r--r--runtime/type_lookup_table.cc4
-rw-r--r--runtime/type_lookup_table.h8
-rw-r--r--runtime/vdex_file.cc21
-rw-r--r--runtime/vdex_file.h11
27 files changed, 418 insertions, 143 deletions
diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc
index b3a92e59ac..c7e9cdaae0 100644
--- a/dex2oat/linker/oat_writer.cc
+++ b/dex2oat/linker/oat_writer.cc
@@ -372,6 +372,7 @@ OatWriter::OatWriter(bool compiling_boot_image,
dex_files_(nullptr),
vdex_size_(0u),
vdex_dex_files_offset_(0u),
+ vdex_dex_shared_data_offset_(0u),
vdex_verifier_deps_offset_(0u),
vdex_quickening_info_offset_(0u),
oat_size_(0u),
@@ -3363,6 +3364,54 @@ bool OatWriter::WriteDexFiles(OutputStream* out, File* file, bool update_input_v
return false;
}
}
+
+ // Write shared dex file data section and fix up the dex file headers.
+ vdex_dex_shared_data_offset_ = vdex_size_;
+ if (dex_container_ != nullptr) {
+ DexContainer::Section* const section = dex_container_->GetDataSection();
+ if (section->Size() > 0) {
+ const uint32_t shared_data_offset = vdex_size_;
+ const off_t existing_offset = out->Seek(0, kSeekCurrent);
+ if (static_cast<uint32_t>(existing_offset) != shared_data_offset) {
+ LOG(ERROR) << "Expected offset " << shared_data_offset << " but got " << existing_offset;
+ return false;
+ }
+ const uint32_t shared_data_size = section->Size();
+ if (!out->WriteFully(section->Begin(), shared_data_size)) {
+ LOG(ERROR) << "Failed to write shared data!";
+ return false;
+ }
+ // Fix up the dex headers to have correct offsets to the data section.
+ for (OatDexFile& oat_dex_file : oat_dex_files_) {
+ // Overwrite the header by reading it, updating the offset, and writing it back out.
+ DexFile::Header header;
+ if (!file->PreadFully(&header, sizeof(header), oat_dex_file.dex_file_offset_)) {
+ LOG(ERROR) << "Failed to read dex header for updating";
+ return false;
+ }
+ CHECK(CompactDexFile::IsMagicValid(header.magic_)) << "Must be compact dex";
+ CHECK_GT(shared_data_offset, oat_dex_file.dex_file_offset_);
+ // Offset is from the dex file base.
+ header.data_off_ = shared_data_offset - oat_dex_file.dex_file_offset_;
+ // The size should already be what part of the data buffer may be used by the dex.
+ CHECK_LE(header.data_size_, shared_data_size);
+ if (!file->PwriteFully(&header, sizeof(header), oat_dex_file.dex_file_offset_)) {
+ LOG(ERROR) << "Failed to write dex header for updating";
+ return false;
+ }
+ }
+ vdex_size_ += shared_data_size;
+ size_dex_file_ += shared_data_size;
+ section->Clear();
+ if (!out->Flush()) {
+ PLOG(ERROR) << "Failed to flush after writing shared dex section.";
+ return false;
+ }
+ }
+ dex_container_.reset();
+ }
+ } else {
+ vdex_dex_shared_data_offset_ = vdex_size_;
}
return true;
@@ -3521,20 +3570,23 @@ bool OatWriter::LayoutAndWriteDexFile(OutputStream* out, OatDexFile* oat_dex_fil
options.compact_dex_level_ = compact_dex_level_;
options.update_checksum_ = true;
DexLayout dex_layout(options, profile_compilation_info_, /*file*/ nullptr, /*header*/ nullptr);
- std::unique_ptr<DexContainer> out_data;
- dex_layout.ProcessDexFile(location.c_str(), dex_file.get(), 0, &out_data);
+ dex_layout.ProcessDexFile(location.c_str(), dex_file.get(), 0, &dex_container_);
oat_dex_file->dex_sections_layout_ = dex_layout.GetSections();
// Dex layout can affect the size of the dex file, so we update here what we have set
// when adding the dex file as a source.
const UnalignedDexFileHeader* header =
- AsUnalignedDexFileHeader(out_data->GetMainSection()->Begin());
+ AsUnalignedDexFileHeader(dex_container_->GetMainSection()->Begin());
oat_dex_file->dex_file_size_ = header->file_size_;
if (!WriteDexFile(out,
oat_dex_file,
- out_data->GetMainSection()->Begin(),
+ dex_container_->GetMainSection()->Begin(),
/* update_input_vdex */ false)) {
return false;
}
+ if (dex_container_ != nullptr) {
+ // Clear the main section in case we write more data into the container.
+ dex_container_->GetMainSection()->Clear();
+ }
CHECK_EQ(oat_dex_file->dex_file_location_checksum_, dex_file->GetLocationChecksum());
return true;
}
@@ -3996,12 +4048,14 @@ bool OatWriter::WriteChecksumsAndVdexHeader(OutputStream* vdex_out) {
DCHECK_NE(vdex_verifier_deps_offset_, 0u);
DCHECK_NE(vdex_quickening_info_offset_, 0u);
- size_t dex_section_size = vdex_verifier_deps_offset_ - vdex_dex_files_offset_;
+ size_t dex_section_size = vdex_dex_shared_data_offset_ - vdex_dex_files_offset_;
+ size_t dex_shared_data_size = vdex_verifier_deps_offset_ - vdex_dex_shared_data_offset_;
size_t verifier_deps_section_size = vdex_quickening_info_offset_ - vdex_verifier_deps_offset_;
size_t quickening_info_section_size = vdex_size_ - vdex_quickening_info_offset_;
VdexFile::Header vdex_header(oat_dex_files_.size(),
dex_section_size,
+ dex_shared_data_size,
verifier_deps_section_size,
quickening_info_section_size);
if (!vdex_out->WriteFully(&vdex_header, sizeof(VdexFile::Header))) {
diff --git a/dex2oat/linker/oat_writer.h b/dex2oat/linker/oat_writer.h
index c08c05a93b..dfcaafc336 100644
--- a/dex2oat/linker/oat_writer.h
+++ b/dex2oat/linker/oat_writer.h
@@ -41,6 +41,7 @@ namespace art {
class BitVector;
class CompiledMethod;
class CompilerDriver;
+class DexContainer;
class ProfileCompilationInfo;
class TimingLogger;
class TypeLookupTable;
@@ -382,6 +383,9 @@ class OatWriter {
// Offset of section holding Dex files inside Vdex.
size_t vdex_dex_files_offset_;
+ // Offset of section holding shared dex data section in the Vdex.
+ size_t vdex_dex_shared_data_offset_;
+
// Offset of section holding VerifierDeps inside Vdex.
size_t vdex_verifier_deps_offset_;
@@ -518,6 +522,9 @@ class OatWriter {
// This pointer is only non-null after InitOatCodeDexFiles succeeds.
std::unique_ptr<OrderedMethodList> ordered_methods_;
+ // Container of shared dex data.
+ std::unique_ptr<DexContainer> dex_container_;
+
DISALLOW_COPY_AND_ASSIGN(OatWriter);
};
diff --git a/dexlayout/compact_dex_writer.cc b/dexlayout/compact_dex_writer.cc
index 2f601b6b1a..ef31c3f212 100644
--- a/dexlayout/compact_dex_writer.cc
+++ b/dexlayout/compact_dex_writer.cc
@@ -167,6 +167,7 @@ uint32_t CompactDexWriter::WriteCodeItem(Stream* stream,
code_item->GetOffset());
if (deduped_offset != Deduper::kDidNotDedupe) {
code_item->SetOffset(deduped_offset);
+ stream->Clear(start_offset, stream->Tell() - start_offset);
// Undo the offset for all that we wrote since we deduped.
stream->Seek(start_offset);
}
@@ -287,9 +288,16 @@ void CompactDexWriter::Write(DexContainer* output) {
CHECK(output->IsCompactDexContainer());
Container* const container = down_cast<Container*>(output);
// For now, use the same stream for both data and metadata.
- Stream stream(output->GetMainSection());
- Stream* main_stream = &stream;
- Stream* data_stream = &stream;
+ Stream temp_main_stream(output->GetMainSection());
+ Stream temp_data_stream(output->GetDataSection());
+ Stream* main_stream = &temp_main_stream;
+ Stream* data_stream = &temp_data_stream;
+
+ // We want offset 0 to be reserved for null, seek to the data section alignment or the end of the
+ // section.
+ data_stream->Seek(std::max(
+ static_cast<uint32_t>(output->GetDataSection()->Size()),
+ kDataSectionAlignment));
code_item_dedupe_ = &container->code_item_dedupe_;
// Starting offset is right after the header.
@@ -312,11 +320,9 @@ void CompactDexWriter::Write(DexContainer* output) {
WriteCallSiteIds(main_stream, /*reserve_only*/ true);
WriteMethodHandles(main_stream);
- uint32_t data_offset_ = 0u;
if (compute_offsets_) {
// Data section.
data_stream->AlignTo(kDataSectionAlignment);
- data_offset_ = data_stream->Tell();
}
// Write code item first to minimize the space required for encoded methods.
@@ -362,19 +368,9 @@ void CompactDexWriter::Write(DexContainer* output) {
} else {
data_stream->Seek(collection.MapListOffset());
}
- GenerateAndWriteMapItems(data_stream);
- data_stream->AlignTo(kDataSectionAlignment);
// Map items are included in the data section.
- if (compute_offsets_) {
- header_->SetDataSize(data_stream->Tell() - data_offset_);
- if (header_->DataSize() != 0) {
- // Offset must be zero when the size is zero.
- header_->SetDataOffset(data_offset_);
- } else {
- header_->SetDataOffset(0u);
- }
- }
+ GenerateAndWriteMapItems(data_stream);
// Write link data if it exists.
const std::vector<uint8_t>& link_data = collection.LinkData();
@@ -391,19 +387,39 @@ void CompactDexWriter::Write(DexContainer* output) {
// Write debug info offset table last to make dex file verifier happy.
WriteDebugInfoOffsetTable(data_stream);
+ data_stream->AlignTo(kDataSectionAlignment);
+ if (compute_offsets_) {
+ header_->SetDataSize(data_stream->Tell());
+ if (header_->DataSize() != 0) {
+ // Offset must be zero when the size is zero.
+ main_stream->AlignTo(kDataSectionAlignment);
+ // For now, default to saying the data is right after the main stream.
+ header_->SetDataOffset(main_stream->Tell());
+ header_->SetDataOffset(0u);
+ } else {
+ header_->SetDataOffset(0u);
+ }
+ }
+
// Write header last.
if (compute_offsets_) {
header_->SetFileSize(main_stream->Tell());
}
WriteHeader(main_stream);
+ // Trim sections to make sure they are sized properly.
+ output->GetMainSection()->Resize(header_->FileSize());
+ output->GetDataSection()->Resize(data_stream->Tell());
+
if (dex_layout_->GetOptions().update_checksum_) {
- header_->SetChecksum(DexFile::CalculateChecksum(main_stream->Begin(), header_->FileSize()));
+ // Compute the cdex section (also covers the used part of the data section).
+ header_->SetChecksum(CompactDexFile::CalculateChecksum(output->GetMainSection()->Begin(),
+ output->GetMainSection()->Size(),
+ output->GetDataSection()->Begin(),
+ output->GetDataSection()->Size()));
// Rewrite the header with the calculated checksum.
WriteHeader(main_stream);
}
- // Trim the map to make it sized as large as the dex file.
- output->GetMainSection()->Resize(header_->FileSize());
}
std::unique_ptr<DexContainer> CompactDexWriter::CreateDexContainer() const {
diff --git a/dexlayout/dex_container.h b/dexlayout/dex_container.h
index 7c426cbc53..2b9a5f9959 100644
--- a/dexlayout/dex_container.h
+++ b/dexlayout/dex_container.h
@@ -43,6 +43,9 @@ class DexContainer {
// Resize the backing storage.
virtual void Resize(size_t size) = 0;
+ // Clear the container.
+ virtual void Clear() = 0;
+
// Returns the end of the memory region.
uint8_t* End() {
return Begin() + Size();
@@ -66,6 +69,10 @@ class DexContainer {
data_.resize(size, 0u);
}
+ void Clear() OVERRIDE {
+ data_.clear();
+ }
+
private:
std::vector<uint8_t> data_;
};
diff --git a/dexlayout/dex_ir.cc b/dexlayout/dex_ir.cc
index fb7dff63b7..1525d537b7 100644
--- a/dexlayout/dex_ir.cc
+++ b/dexlayout/dex_ir.cc
@@ -280,7 +280,7 @@ void Collections::ReadEncodedValue(const DexFile& dex_file,
}
case DexFile::kDexAnnotationArray: {
EncodedValueVector* values = new EncodedValueVector();
- const uint32_t offset = *data - dex_file.Begin();
+ const uint32_t offset = *data - dex_file.DataBegin();
const uint32_t size = DecodeUnsignedLeb128(data);
// Decode all elements.
for (uint32_t i = 0; i < size; i++) {
@@ -440,7 +440,7 @@ void Collections::AddAnnotationsFromMapListSection(const DexFile& dex_file,
AnnotationItem* Collections::CreateAnnotationItem(const DexFile& dex_file,
const DexFile::AnnotationItem* annotation) {
const uint8_t* const start_data = reinterpret_cast<const uint8_t*>(annotation);
- const uint32_t offset = start_data - dex_file.Begin();
+ const uint32_t offset = start_data - dex_file.DataBegin();
AnnotationItem* annotation_item = annotation_items_map_.GetExistingObject(offset);
if (annotation_item == nullptr) {
uint8_t visibility = annotation->visibility_;
@@ -772,8 +772,7 @@ ClassData* Collections::CreateClassData(
void Collections::CreateCallSitesAndMethodHandles(const DexFile& dex_file) {
// Iterate through the map list and set the offset of the CallSiteIds and MethodHandleItems.
- const DexFile::MapList* map =
- reinterpret_cast<const DexFile::MapList*>(dex_file.Begin() + MapListOffset());
+ const DexFile::MapList* map = dex_file.GetMapList();
for (uint32_t i = 0; i < map->size_; ++i) {
const DexFile::MapItem* item = map->list_ + i;
switch (item->type_) {
@@ -799,7 +798,7 @@ void Collections::CreateCallSitesAndMethodHandles(const DexFile& dex_file) {
void Collections::CreateCallSiteId(const DexFile& dex_file, uint32_t i) {
const DexFile::CallSiteIdItem& disk_call_site_id = dex_file.GetCallSiteId(i);
- const uint8_t* disk_call_item_ptr = dex_file.Begin() + disk_call_site_id.data_off_;
+ const uint8_t* disk_call_item_ptr = dex_file.DataBegin() + disk_call_site_id.data_off_;
EncodedArrayItem* call_site_item =
CreateEncodedArrayItem(dex_file, disk_call_item_ptr, disk_call_site_id.data_off_);
diff --git a/dexlayout/dex_ir_builder.cc b/dexlayout/dex_ir_builder.cc
index 231826b7a8..3ec163cea1 100644
--- a/dexlayout/dex_ir_builder.cc
+++ b/dexlayout/dex_ir_builder.cc
@@ -83,8 +83,8 @@ Header* DexIrBuilder(const DexFile& dex_file, bool eagerly_assign_offsets) {
// Load the link data if it exists.
collections.SetLinkData(std::vector<uint8_t>(
- dex_file.Begin() + dex_file.GetHeader().link_off_,
- dex_file.Begin() + dex_file.GetHeader().link_off_ + dex_file.GetHeader().link_size_));
+ dex_file.DataBegin() + dex_file.GetHeader().link_off_,
+ dex_file.DataBegin() + dex_file.GetHeader().link_off_ + dex_file.GetHeader().link_size_));
return header;
}
@@ -92,8 +92,7 @@ Header* DexIrBuilder(const DexFile& dex_file, bool eagerly_assign_offsets) {
static void CheckAndSetRemainingOffsets(const DexFile& dex_file, Collections* collections) {
const DexFile::Header& disk_header = dex_file.GetHeader();
// Read MapItems and validate/set remaining offsets.
- const DexFile::MapList* map =
- reinterpret_cast<const DexFile::MapList*>(dex_file.Begin() + disk_header.map_off_);
+ const DexFile::MapList* map = dex_file.GetMapList();
const uint32_t count = map->size_;
for (uint32_t i = 0; i < count; ++i) {
const DexFile::MapItem* item = map->list_ + i;
diff --git a/dexlayout/dex_writer.cc b/dexlayout/dex_writer.cc
index eb038a008b..67d0f9ac68 100644
--- a/dexlayout/dex_writer.cc
+++ b/dexlayout/dex_writer.cc
@@ -30,6 +30,8 @@
namespace art {
+constexpr uint32_t DexWriter::kDataSectionAlignment;
+
static size_t EncodeIntValue(int32_t value, uint8_t* buffer) {
size_t length = 0;
if (value >= 0) {
diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc
index d33a0bde03..1b32f7b0d9 100644
--- a/dexlayout/dexlayout.cc
+++ b/dexlayout/dexlayout.cc
@@ -1838,13 +1838,17 @@ void DexLayout::OutputDexFile(const DexFile* input_dex_file,
}
}
DexWriter::Output(this, dex_container, compute_offsets);
- DexContainer* const container = dex_container->get();
- DexContainer::Section* const main_section = container->GetMainSection();
- DexContainer::Section* const data_section = container->GetDataSection();
- CHECK_EQ(data_section->Size(), 0u) << "Unsupported";
if (new_file != nullptr) {
+ DexContainer* const container = dex_container->get();
+ DexContainer::Section* const main_section = container->GetMainSection();
if (!new_file->WriteFully(main_section->Begin(), main_section->Size())) {
- LOG(ERROR) << "Failed tow write dex file to " << dex_file_location;
+ LOG(ERROR) << "Failed to write main section for dex file " << dex_file_location;
+ new_file->Erase();
+ return;
+ }
+ DexContainer::Section* const data_section = container->GetDataSection();
+ if (!new_file->WriteFully(data_section->Begin(), data_section->Size())) {
+ LOG(ERROR) << "Failed to write data section for dex file " << dex_file_location;
new_file->Erase();
return;
}
@@ -1919,17 +1923,22 @@ void DexLayout::ProcessDexFile(const char* file_name,
// Dex file verifier cannot handle compact dex.
bool verify = options_.compact_dex_level_ == CompactDexLevel::kCompactDexLevelNone;
const ArtDexFileLoader dex_file_loader;
- DexContainer::Section* section = (*dex_container)->GetMainSection();
- DCHECK_EQ(file_size, section->Size());
+ DexContainer::Section* const main_section = (*dex_container)->GetMainSection();
+ DexContainer::Section* const data_section = (*dex_container)->GetDataSection();
+ DCHECK_EQ(file_size, main_section->Size())
+ << main_section->Size() << " " << data_section->Size();
std::unique_ptr<const DexFile> output_dex_file(
- dex_file_loader.Open(section->Begin(),
- file_size,
- location,
- /* checksum */ 0,
- /*oat_dex_file*/ nullptr,
- verify,
- /*verify_checksum*/ false,
- &error_msg));
+ dex_file_loader.OpenWithDataSection(
+ main_section->Begin(),
+ main_section->Size(),
+ data_section->Begin(),
+ data_section->Size(),
+ location,
+ /* checksum */ 0,
+ /*oat_dex_file*/ nullptr,
+ verify,
+ /*verify_checksum*/ false,
+ &error_msg));
CHECK(output_dex_file != nullptr) << "Failed to re-open output file:" << error_msg;
// Do IR-level comparison between input and output. This check ignores potential differences
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index f2a69f3bb3..f7151b350d 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -1156,6 +1156,7 @@ class OatDumper {
// Vdex unquicken output should match original input bytecode
uint32_t orig_checksum =
reinterpret_cast<DexFile::Header*>(const_cast<uint8_t*>(dex_file->Begin()))->checksum_;
+ CHECK_EQ(orig_checksum, dex_file->CalculateChecksum());
if (orig_checksum != dex_file->CalculateChecksum()) {
os << "Unexpected checksum from unquicken dex file '" << dex_file_location << "'\n";
return false;
@@ -1208,7 +1209,11 @@ class OatDumper {
return false;
}
- if (!file->WriteFully(dex_file->Begin(), fsize)) {
+ bool success = false;
+ success = file->WriteFully(dex_file->Begin(), fsize);
+ // }
+
+ if (!success) {
os << "Failed to write dex file";
file->Erase();
return false;
diff --git a/openjdkjvmti/fixed_up_dex_file.cc b/openjdkjvmti/fixed_up_dex_file.cc
index 323137aa5b..cc56a7b714 100644
--- a/openjdkjvmti/fixed_up_dex_file.cc
+++ b/openjdkjvmti/fixed_up_dex_file.cc
@@ -70,8 +70,21 @@ static void DoDexUnquicken(const art::DexFile& new_dex_file, const art::DexFile&
std::unique_ptr<FixedUpDexFile> FixedUpDexFile::Create(const art::DexFile& original) {
// Copy the data into mutable memory.
std::vector<unsigned char> data;
- data.resize(original.Size());
- memcpy(data.data(), original.Begin(), original.Size());
+ if (original.IsCompactDexFile()) {
+ // Compact dex has a separate data section that is relative from the original dex.
+ // We need to copy the shared data section so that dequickening doesn't change anything.
+ data.resize(original.Size() + original.DataSize());
+ memcpy(data.data(), original.Begin(), original.Size());
+ memcpy(data.data() + original.Size(), original.DataBegin(), original.DataSize());
+ // Go patch up the header to point to the copied data section.
+ art::CompactDexFile::Header* const header =
+ const_cast<art::CompactDexFile::Header*>(art::CompactDexFile::Header::At(data.data()));
+ header->data_off_ = original.Size();
+ header->data_size_ = original.DataSize();
+ } else {
+ data.resize(original.Size());
+ memcpy(data.data(), original.Begin(), original.Size());
+ }
std::string error;
const art::ArtDexFileLoader dex_file_loader;
std::unique_ptr<const art::DexFile> new_dex_file(dex_file_loader.Open(
@@ -105,6 +118,7 @@ std::unique_ptr<FixedUpDexFile> FixedUpDexFile::Create(const art::DexFile& origi
0,
&dex_container);
art::DexContainer::Section* main_section = dex_container->GetMainSection();
+ CHECK_EQ(dex_container->GetDataSection()->Size(), 0u);
// Overwrite the dex file stored in data with the new result.
data.clear();
data.insert(data.end(), main_section->Begin(), main_section->End());
diff --git a/runtime/dex/art_dex_file_loader.cc b/runtime/dex/art_dex_file_loader.cc
index dee736ecff..08cf30d5bf 100644
--- a/runtime/dex/art_dex_file_loader.cc
+++ b/runtime/dex/art_dex_file_loader.cc
@@ -154,6 +154,8 @@ std::unique_ptr<const DexFile> ArtDexFileLoader::Open(const uint8_t* base,
ScopedTrace trace(std::string("Open dex file from RAM ") + location);
return OpenCommon(base,
size,
+ /*data_base*/ nullptr,
+ /*data_size*/ 0u,
location,
location_checksum,
oat_dex_file,
@@ -182,6 +184,8 @@ std::unique_ptr<const DexFile> ArtDexFileLoader::Open(const std::string& locatio
std::unique_ptr<DexFile> dex_file = OpenCommon(map->Begin(),
map->Size(),
+ /*data_base*/ nullptr,
+ /*data_size*/ 0u,
location,
location_checksum,
kNoOatDexFile,
@@ -303,6 +307,8 @@ std::unique_ptr<const DexFile> ArtDexFileLoader::OpenFile(int fd,
std::unique_ptr<DexFile> dex_file = OpenCommon(map->Begin(),
map->Size(),
+ /*data_base*/ nullptr,
+ /*data_size*/ 0u,
location,
dex_header->checksum_,
kNoOatDexFile,
@@ -370,6 +376,8 @@ std::unique_ptr<const DexFile> ArtDexFileLoader::OpenOneDexFileFromZip(
VerifyResult verify_result;
std::unique_ptr<DexFile> dex_file = OpenCommon(map->Begin(),
map->Size(),
+ /*data_base*/ nullptr,
+ /*data_size*/ 0u,
location,
zip_entry->GetCrc32(),
kNoOatDexFile,
diff --git a/runtime/dex/code_item_accessors-no_art-inl.h b/runtime/dex/code_item_accessors-no_art-inl.h
index 6a99009b00..a243a4a6f4 100644
--- a/runtime/dex/code_item_accessors-no_art-inl.h
+++ b/runtime/dex/code_item_accessors-no_art-inl.h
@@ -50,7 +50,7 @@ inline void CodeItemInstructionAccessor::Init(const StandardDexFile::CodeItem& c
inline void CodeItemInstructionAccessor::Init(const DexFile& dex_file,
const DexFile::CodeItem* code_item) {
if (code_item != nullptr) {
- DCHECK(dex_file.HasAddress(code_item));
+ DCHECK(dex_file.IsInDataSection(code_item));
if (dex_file.IsCompactDexFile()) {
Init(down_cast<const CompactDexFile::CodeItem&>(*code_item));
} else {
diff --git a/runtime/dex/code_item_accessors_test.cc b/runtime/dex/code_item_accessors_test.cc
index 3380be8acf..8e2548bf3d 100644
--- a/runtime/dex/code_item_accessors_test.cc
+++ b/runtime/dex/code_item_accessors_test.cc
@@ -39,8 +39,12 @@ std::unique_ptr<const DexFile> CreateFakeDex(bool compact_dex) {
&error_msg));
CHECK(map != nullptr) << error_msg;
if (compact_dex) {
- CompactDexFile::WriteMagic(map->Begin());
- CompactDexFile::WriteCurrentVersion(map->Begin());
+ CompactDexFile::Header* header =
+ const_cast<CompactDexFile::Header*>(CompactDexFile::Header::At(map->Begin()));
+ CompactDexFile::WriteMagic(header->magic_);
+ CompactDexFile::WriteCurrentVersion(header->magic_);
+ header->data_off_ = 0;
+ header->data_size_ = map->Size();
} else {
StandardDexFile::WriteMagic(map->Begin());
StandardDexFile::WriteCurrentVersion(map->Begin());
diff --git a/runtime/dex/compact_dex_file.cc b/runtime/dex/compact_dex_file.cc
index ff193ffb07..37f5d0074c 100644
--- a/runtime/dex/compact_dex_file.cc
+++ b/runtime/dex/compact_dex_file.cc
@@ -56,27 +56,52 @@ bool CompactDexFile::SupportsDefaultMethods() const {
}
uint32_t CompactDexFile::GetCodeItemSize(const DexFile::CodeItem& item) const {
- // TODO: Clean up this temporary code duplication with StandardDexFile. Eventually the
- // implementations will differ.
- DCHECK(HasAddress(&item));
+ DCHECK(IsInDataSection(&item));
return reinterpret_cast<uintptr_t>(CodeItemDataAccessor(*this, &item).CodeItemDataEnd()) -
reinterpret_cast<uintptr_t>(&item);
}
+
+uint32_t CompactDexFile::CalculateChecksum(const uint8_t* base_begin,
+ size_t base_size,
+ const uint8_t* data_begin,
+ size_t data_size) {
+ Header temp_header(*Header::At(base_begin));
+ // Zero out fields that are not included in the sum.
+ temp_header.checksum_ = 0u;
+ temp_header.data_off_ = 0u;
+ temp_header.data_size_ = 0u;
+ uint32_t checksum = ChecksumMemoryRange(reinterpret_cast<const uint8_t*>(&temp_header),
+ sizeof(temp_header));
+ // Exclude the header since we already computed it's checksum.
+ checksum = (checksum * 31) ^ ChecksumMemoryRange(base_begin + sizeof(temp_header),
+ base_size - sizeof(temp_header));
+ checksum = (checksum * 31) ^ ChecksumMemoryRange(data_begin, data_size);
+ return checksum;
+}
+
+uint32_t CompactDexFile::CalculateChecksum() const {
+ return CalculateChecksum(Begin(), Size(), DataBegin(), DataSize());
+}
+
CompactDexFile::CompactDexFile(const uint8_t* base,
size_t size,
+ const uint8_t* data_begin,
+ size_t data_size,
const std::string& location,
uint32_t location_checksum,
const OatDexFile* oat_dex_file,
DexFileContainer* container)
: DexFile(base,
size,
+ data_begin,
+ data_size,
location,
location_checksum,
oat_dex_file,
container,
/*is_compact_dex*/ true),
- debug_info_offsets_(Begin() + GetHeader().debug_info_offsets_pos_,
+ debug_info_offsets_(DataBegin() + GetHeader().debug_info_offsets_pos_,
GetHeader().debug_info_base_,
GetHeader().debug_info_offsets_table_offset_) {}
diff --git a/runtime/dex/compact_dex_file.h b/runtime/dex/compact_dex_file.h
index 8dad84d5cd..1ecff04cba 100644
--- a/runtime/dex/compact_dex_file.h
+++ b/runtime/dex/compact_dex_file.h
@@ -35,10 +35,22 @@ class CompactDexFile : public DexFile {
class Header : public DexFile::Header {
public:
+ static const Header* At(const void* at) {
+ return reinterpret_cast<const Header*>(at);
+ }
+
uint32_t GetFeatureFlags() const {
return feature_flags_;
}
+ uint32_t GetDataOffset() const {
+ return data_off_;
+ }
+
+ uint32_t GetDataSize() const {
+ return data_size_;
+ }
+
private:
uint32_t feature_flags_ = 0u;
@@ -245,9 +257,17 @@ class CompactDexFile : public DexFile {
return debug_info_offsets_.GetDebugInfoOffset(dex_method_index);
}
+ static uint32_t CalculateChecksum(const uint8_t* base_begin,
+ size_t base_size,
+ const uint8_t* data_begin,
+ size_t data_size);
+ virtual uint32_t CalculateChecksum() const OVERRIDE;
+
private:
CompactDexFile(const uint8_t* base,
size_t size,
+ const uint8_t* data_begin,
+ size_t data_size,
const std::string& location,
uint32_t location_checksum,
const OatDexFile* oat_dex_file,
diff --git a/runtime/dex/dex_file-inl.h b/runtime/dex/dex_file-inl.h
index 9b14514cf4..aa53daac35 100644
--- a/runtime/dex/dex_file-inl.h
+++ b/runtime/dex/dex_file-inl.h
@@ -29,14 +29,14 @@
namespace art {
inline int32_t DexFile::GetStringLength(const StringId& string_id) const {
- const uint8_t* ptr = begin_ + string_id.string_data_off_;
+ const uint8_t* ptr = DataBegin() + string_id.string_data_off_;
return DecodeUnsignedLeb128(&ptr);
}
inline const char* DexFile::GetStringDataAndUtf16Length(const StringId& string_id,
uint32_t* utf16_length) const {
DCHECK(utf16_length != nullptr) << GetLocation();
- const uint8_t* ptr = begin_ + string_id.string_data_off_;
+ const uint8_t* ptr = DataBegin() + string_id.string_data_off_;
*utf16_length = DecodeUnsignedLeb128(&ptr);
return reinterpret_cast<const char*>(ptr);
}
diff --git a/runtime/dex/dex_file.cc b/runtime/dex/dex_file.cc
index 16325b83f6..6ec997c93f 100644
--- a/runtime/dex/dex_file.cc
+++ b/runtime/dex/dex_file.cc
@@ -50,9 +50,12 @@ uint32_t DexFile::CalculateChecksum() const {
}
uint32_t DexFile::CalculateChecksum(const uint8_t* begin, size_t size) {
- const uint32_t non_sum = OFFSETOF_MEMBER(DexFile::Header, signature_);
- const uint8_t* non_sum_ptr = begin + non_sum;
- return adler32(adler32(0L, Z_NULL, 0), non_sum_ptr, size - non_sum);
+ const uint32_t non_sum_bytes = OFFSETOF_MEMBER(DexFile::Header, signature_);
+ return ChecksumMemoryRange(begin + non_sum_bytes, size - non_sum_bytes);
+}
+
+uint32_t DexFile::ChecksumMemoryRange(const uint8_t* begin, size_t size) {
+ return adler32(adler32(0L, Z_NULL, 0), begin, size);
}
int DexFile::GetPermissions() const {
@@ -77,6 +80,8 @@ bool DexFile::DisableWrite() const {
DexFile::DexFile(const uint8_t* base,
size_t size,
+ const uint8_t* data_begin,
+ size_t data_size,
const std::string& location,
uint32_t location_checksum,
const OatDexFile* oat_dex_file,
@@ -84,6 +89,8 @@ DexFile::DexFile(const uint8_t* base,
bool is_compact_dex)
: begin_(base),
size_(size),
+ data_begin_(data_begin),
+ data_size_(data_size),
location_(location),
location_checksum_(location_checksum),
header_(reinterpret_cast<const Header*>(base)),
@@ -149,7 +156,7 @@ bool DexFile::CheckMagicAndVersion(std::string* error_msg) const {
}
void DexFile::InitializeSectionsFromMapList() {
- const MapList* map_list = reinterpret_cast<const MapList*>(begin_ + header_->map_off_);
+ const MapList* map_list = reinterpret_cast<const MapList*>(DataBegin() + header_->map_off_);
if (header_->map_off_ == 0 || header_->map_off_ > size_) {
// Bad offset. The dex file verifier runs after this method and will reject the file.
return;
@@ -166,10 +173,10 @@ void DexFile::InitializeSectionsFromMapList() {
for (size_t i = 0; i < count; ++i) {
const MapItem& map_item = map_list->list_[i];
if (map_item.type_ == kDexTypeMethodHandleItem) {
- method_handles_ = reinterpret_cast<const MethodHandleItem*>(begin_ + map_item.offset_);
+ method_handles_ = reinterpret_cast<const MethodHandleItem*>(DataBegin() + map_item.offset_);
num_method_handles_ = map_item.size_;
} else if (map_item.type_ == kDexTypeCallSiteIdItem) {
- call_site_ids_ = reinterpret_cast<const CallSiteIdItem*>(begin_ + map_item.offset_);
+ call_site_ids_ = reinterpret_cast<const CallSiteIdItem*>(DataBegin() + map_item.offset_);
num_call_site_ids_ = map_item.size_;
}
}
diff --git a/runtime/dex/dex_file.h b/runtime/dex/dex_file.h
index 511ce312cd..ef25797274 100644
--- a/runtime/dex/dex_file.h
+++ b/runtime/dex/dex_file.h
@@ -646,11 +646,7 @@ class DexFile {
const ClassDef* FindClassDef(dex::TypeIndex type_idx) const;
const TypeList* GetInterfacesList(const ClassDef& class_def) const {
- if (class_def.interfaces_off_ == 0) {
- return nullptr;
- }
- const uint8_t* addr = begin_ + class_def.interfaces_off_;
- return reinterpret_cast<const TypeList*>(addr);
+ return DataPointer<TypeList>(class_def.interfaces_off_);
}
uint32_t NumMethodHandles() const {
@@ -673,17 +669,13 @@ class DexFile {
// Returns a pointer to the raw memory mapped class_data_item
const uint8_t* GetClassData(const ClassDef& class_def) const {
- return (class_def.class_data_off_ == 0) ? nullptr : begin_ + class_def.class_data_off_;
+ return DataPointer<uint8_t>(class_def.class_data_off_);
}
- //
+ // Return the code item for a provided offset.
const CodeItem* GetCodeItem(const uint32_t code_off) const {
- DCHECK_LT(code_off, size_) << "Code item offset larger then maximum allowed offset";
- if (code_off == 0) {
- return nullptr; // native or abstract method
- }
- const uint8_t* addr = begin_ + code_off;
- return reinterpret_cast<const CodeItem*>(addr);
+ // May be null for native or abstract methods.
+ return DataPointer<CodeItem>(code_off);
}
const char* GetReturnTypeDescriptor(const ProtoId& proto_id) const;
@@ -728,17 +720,15 @@ class DexFile {
const char* GetShorty(uint32_t proto_idx) const;
const TypeList* GetProtoParameters(const ProtoId& proto_id) const {
- return (proto_id.parameters_off_ == 0)
- ? nullptr
- : reinterpret_cast<const TypeList*>(begin_ + proto_id.parameters_off_);
+ return DataPointer<TypeList>(proto_id.parameters_off_);
}
const uint8_t* GetEncodedStaticFieldValuesArray(const ClassDef& class_def) const {
- return (class_def.static_values_off_ == 0) ? 0 : begin_ + class_def.static_values_off_;
+ return DataPointer<uint8_t>(class_def.static_values_off_);
}
const uint8_t* GetCallSiteEncodedValuesArray(const CallSiteIdItem& call_site_id) const {
- return begin_ + call_site_id.data_off_;
+ return DataBegin() + call_site_id.data_off_;
}
static const TryItem* GetTryItems(const DexInstructionIterator& code_item_end, uint32_t offset);
@@ -756,7 +746,9 @@ class DexFile {
// Check that the offset is in bounds.
// Note that although the specification says that 0 should be used if there
// is no debug information, some applications incorrectly use 0xFFFFFFFF.
- return (debug_info_off == 0 || debug_info_off >= size_) ? nullptr : begin_ + debug_info_off;
+ return (debug_info_off == 0 || debug_info_off >= data_size_)
+ ? nullptr
+ : DataBegin() + debug_info_off;
}
struct PositionInfo {
@@ -787,21 +779,17 @@ class DexFile {
static bool LineNumForPcCb(void* context, const PositionInfo& entry);
const AnnotationsDirectoryItem* GetAnnotationsDirectory(const ClassDef& class_def) const {
- return (class_def.annotations_off_ == 0)
- ? nullptr
- : reinterpret_cast<const AnnotationsDirectoryItem*>(begin_ + class_def.annotations_off_);
+ return DataPointer<AnnotationsDirectoryItem>(class_def.annotations_off_);
}
const AnnotationSetItem* GetClassAnnotationSet(const AnnotationsDirectoryItem* anno_dir) const {
- return (anno_dir->class_annotations_off_ == 0)
- ? nullptr
- : reinterpret_cast<const AnnotationSetItem*>(begin_ + anno_dir->class_annotations_off_);
+ return DataPointer<AnnotationSetItem>(anno_dir->class_annotations_off_);
}
const FieldAnnotationsItem* GetFieldAnnotations(const AnnotationsDirectoryItem* anno_dir) const {
return (anno_dir->fields_size_ == 0)
- ? nullptr
- : reinterpret_cast<const FieldAnnotationsItem*>(&anno_dir[1]);
+ ? nullptr
+ : reinterpret_cast<const FieldAnnotationsItem*>(&anno_dir[1]);
}
const MethodAnnotationsItem* GetMethodAnnotations(const AnnotationsDirectoryItem* anno_dir)
@@ -828,33 +816,21 @@ class DexFile {
}
const AnnotationSetItem* GetFieldAnnotationSetItem(const FieldAnnotationsItem& anno_item) const {
- uint32_t offset = anno_item.annotations_off_;
- return (offset == 0)
- ? nullptr
- : reinterpret_cast<const AnnotationSetItem*>(begin_ + offset);
+ return DataPointer<AnnotationSetItem>(anno_item.annotations_off_);
}
const AnnotationSetItem* GetMethodAnnotationSetItem(const MethodAnnotationsItem& anno_item)
const {
- uint32_t offset = anno_item.annotations_off_;
- return (offset == 0)
- ? nullptr
- : reinterpret_cast<const AnnotationSetItem*>(begin_ + offset);
+ return DataPointer<AnnotationSetItem>(anno_item.annotations_off_);
}
const AnnotationSetRefList* GetParameterAnnotationSetRefList(
const ParameterAnnotationsItem* anno_item) const {
- uint32_t offset = anno_item->annotations_off_;
- return (offset == 0)
- ? nullptr
- : reinterpret_cast<const AnnotationSetRefList*>(begin_ + offset);
+ return DataPointer<AnnotationSetRefList>(anno_item->annotations_off_);
}
ALWAYS_INLINE const AnnotationItem* GetAnnotationItemAtOffset(uint32_t offset) const {
- DCHECK_LE(offset, Size());
- return (offset == 0)
- ? nullptr
- : reinterpret_cast<const AnnotationItem*>(begin_ + offset);
+ return DataPointer<AnnotationItem>(offset);
}
const AnnotationItem* GetAnnotationItem(const AnnotationSetItem* set_item, uint32_t index) const {
@@ -863,10 +839,7 @@ class DexFile {
}
const AnnotationSetItem* GetSetRefItemItem(const AnnotationSetRefItem* anno_item) const {
- uint32_t offset = anno_item->annotations_off_;
- return (offset == 0)
- ? nullptr
- : reinterpret_cast<const AnnotationSetItem*>(begin_ + offset);
+ return DataPointer<AnnotationSetItem>(anno_item->annotations_off_);
}
// Debug info opcodes and constants
@@ -955,6 +928,20 @@ class DexFile {
return size_;
}
+ const uint8_t* DataBegin() const {
+ return data_begin_;
+ }
+
+ size_t DataSize() const {
+ return data_size_;
+ }
+
+ template <typename T>
+ const T* DataPointer(size_t offset) const {
+ DCHECK_LT(offset, DataSize()) << "Offset past end of data section";
+ return (offset != 0u) ? reinterpret_cast<const T*>(DataBegin() + offset) : nullptr;
+ }
+
const OatDexFile* GetOatDexFile() const {
return oat_dex_file_;
}
@@ -964,6 +951,11 @@ class DexFile {
oat_dex_file_ = oat_dex_file;
}
+ // Read MapItems and validate/set remaining offsets.
+ const DexFile::MapList* GetMapList() const {
+ return reinterpret_cast<const DexFile::MapList*>(DataBegin() + header_->map_off_);
+ }
+
// Utility methods for reading integral values from a buffer.
static int32_t ReadSignedInt(const uint8_t* ptr, int zwidth);
static uint32_t ReadUnsignedInt(const uint8_t* ptr, int zwidth, bool fill_on_right);
@@ -971,8 +963,9 @@ class DexFile {
static uint64_t ReadUnsignedLong(const uint8_t* ptr, int zwidth, bool fill_on_right);
// Recalculates the checksum of the dex file. Does not use the current value in the header.
- uint32_t CalculateChecksum() const;
+ virtual uint32_t CalculateChecksum() const;
static uint32_t CalculateChecksum(const uint8_t* begin, size_t size);
+ static uint32_t ChecksumMemoryRange(const uint8_t* begin, size_t size);
// Returns a human-readable form of the method at an index.
std::string PrettyMethod(uint32_t method_idx, bool with_signature = true) const;
@@ -991,10 +984,14 @@ class DexFile {
ALWAYS_INLINE const StandardDexFile* AsStandardDexFile() const;
ALWAYS_INLINE const CompactDexFile* AsCompactDexFile() const;
- bool HasAddress(const void* addr) const {
+ bool IsInMainSection(const void* addr) const {
return Begin() <= addr && addr < Begin() + Size();
}
+ bool IsInDataSection(const void* addr) const {
+ return DataBegin() <= addr && addr < DataBegin() + DataSize();
+ }
+
DexFileContainer* GetContainer() const {
return container_.get();
}
@@ -1005,6 +1002,8 @@ class DexFile {
DexFile(const uint8_t* base,
size_t size,
+ const uint8_t* data_begin,
+ size_t data_size,
const std::string& location,
uint32_t location_checksum,
const OatDexFile* oat_dex_file,
@@ -1026,6 +1025,12 @@ class DexFile {
// The size of the underlying memory allocation in bytes.
const size_t size_;
+ // The base address of the data section (same as Begin() for standard dex).
+ const uint8_t* const data_begin_;
+
+ // The size of the data section.
+ const size_t data_size_;
+
// Typically the dex file name when available, alternatively some identifying string.
//
// The ClassLinker will use this to match DexFiles the boot class
diff --git a/runtime/dex/dex_file_loader.cc b/runtime/dex/dex_file_loader.cc
index ccad19f22e..7dde0a42fd 100644
--- a/runtime/dex/dex_file_loader.cc
+++ b/runtime/dex/dex_file_loader.cc
@@ -222,6 +222,33 @@ std::unique_ptr<const DexFile> DexFileLoader::Open(const uint8_t* base,
std::string* error_msg) const {
return OpenCommon(base,
size,
+ /*data_base*/ base,
+ /*data_size*/ size,
+ location,
+ location_checksum,
+ oat_dex_file,
+ verify,
+ verify_checksum,
+ error_msg,
+ /*container*/ nullptr,
+ /*verify_result*/ nullptr);
+}
+
+std::unique_ptr<const DexFile> DexFileLoader::OpenWithDataSection(
+ const uint8_t* base,
+ size_t size,
+ const uint8_t* data_base,
+ size_t data_size,
+ const std::string& location,
+ uint32_t location_checksum,
+ const OatDexFile* oat_dex_file,
+ bool verify,
+ bool verify_checksum,
+ std::string* error_msg) const {
+ return OpenCommon(base,
+ size,
+ data_base,
+ data_size,
location,
location_checksum,
oat_dex_file,
@@ -278,6 +305,8 @@ bool DexFileLoader::OpenAll(
std::unique_ptr<DexFile> DexFileLoader::OpenCommon(const uint8_t* base,
size_t size,
+ const uint8_t* data_base,
+ size_t data_size,
const std::string& location,
uint32_t location_checksum,
const OatDexFile* oat_dex_file,
@@ -291,11 +320,32 @@ std::unique_ptr<DexFile> DexFileLoader::OpenCommon(const uint8_t* base,
}
std::unique_ptr<DexFile> dex_file;
if (StandardDexFile::IsMagicValid(base)) {
- dex_file.reset(
- new StandardDexFile(base, size, location, location_checksum, oat_dex_file, container));
+ if (data_size != 0) {
+ CHECK_EQ(base, data_base) << "Unsupported for standard dex";
+ }
+ dex_file.reset(new StandardDexFile(base,
+ size,
+ location,
+ location_checksum,
+ oat_dex_file,
+ container));
} else if (CompactDexFile::IsMagicValid(base)) {
- dex_file.reset(
- new CompactDexFile(base, size, location, location_checksum, oat_dex_file, container));
+ if (data_base == nullptr) {
+ // TODO: Is there a clean way to support both an explicit data section and reading the one
+ // from the header.
+ CHECK_EQ(data_size, 0u);
+ const CompactDexFile::Header* const header = CompactDexFile::Header::At(base);
+ data_base = base + header->data_off_;
+ data_size = header->data_size_;
+ }
+ dex_file.reset(new CompactDexFile(base,
+ size,
+ data_base,
+ data_size,
+ location,
+ location_checksum,
+ oat_dex_file,
+ container));
}
if (dex_file == nullptr) {
*error_msg = StringPrintf("Failed to open dex file '%s' from memory: %s", location.c_str(),
@@ -353,6 +403,8 @@ std::unique_ptr<const DexFile> DexFileLoader::OpenOneDexFileFromZip(
VerifyResult verify_result;
std::unique_ptr<const DexFile> dex_file = OpenCommon(map.data(),
map.size(),
+ /*data_base*/ nullptr,
+ /*data_size*/ 0u,
location,
zip_entry->GetCrc32(),
/*oat_dex_file*/ nullptr,
diff --git a/runtime/dex/dex_file_loader.h b/runtime/dex/dex_file_loader.h
index 05a51d09b3..508397cb00 100644
--- a/runtime/dex/dex_file_loader.h
+++ b/runtime/dex/dex_file_loader.h
@@ -120,6 +120,20 @@ class DexFileLoader {
bool verify_checksum,
std::string* error_msg) const;
+ // Open a dex file with a separate data section.
+ virtual std::unique_ptr<const DexFile> OpenWithDataSection(
+ const uint8_t* base,
+ size_t size,
+ const uint8_t* data_base,
+ size_t data_size,
+ const std::string& location,
+ uint32_t location_checksum,
+ const OatDexFile* oat_dex_file,
+ bool verify,
+ bool verify_checksum,
+ std::string* error_msg) const;
+
+
// Opens all .dex files found in the memory map, guessing the container format based on file
// extension.
virtual bool OpenAll(const uint8_t* base,
@@ -148,6 +162,8 @@ class DexFileLoader {
static std::unique_ptr<DexFile> OpenCommon(const uint8_t* base,
size_t size,
+ const uint8_t* data_base,
+ size_t data_size,
const std::string& location,
uint32_t location_checksum,
const OatDexFile* oat_dex_file,
diff --git a/runtime/dex/standard_dex_file.cc b/runtime/dex/standard_dex_file.cc
index 52fdff303b..024f73b4e5 100644
--- a/runtime/dex/standard_dex_file.cc
+++ b/runtime/dex/standard_dex_file.cc
@@ -73,10 +73,7 @@ bool StandardDexFile::SupportsDefaultMethods() const {
}
uint32_t StandardDexFile::GetCodeItemSize(const DexFile::CodeItem& item) const {
- DCHECK(HasAddress(&item));
- // TODO: Clean up this temporary code duplication with StandardDexFile. Eventually the
- // implementations will differ.
- DCHECK(HasAddress(&item));
+ DCHECK(IsInDataSection(&item));
return reinterpret_cast<uintptr_t>(CodeItemDataAccessor(*this, &item).CodeItemDataEnd()) -
reinterpret_cast<uintptr_t>(&item);
}
diff --git a/runtime/dex/standard_dex_file.h b/runtime/dex/standard_dex_file.h
index 6437def4f5..94ef1f2a8e 100644
--- a/runtime/dex/standard_dex_file.h
+++ b/runtime/dex/standard_dex_file.h
@@ -92,6 +92,8 @@ class StandardDexFile : public DexFile {
DexFileContainer* container)
: DexFile(base,
size,
+ /*data_begin*/ base,
+ /*data_size*/ size,
location,
location_checksum,
oat_dex_file,
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index 9fd99057a1..307f7b96ed 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -1653,7 +1653,12 @@ OatFile::OatDexFile::OatDexFile(const OatFile* oat_file,
if (lookup_table_data_ + TypeLookupTable::RawDataLength(num_class_defs) > GetOatFile()->End()) {
LOG(WARNING) << "found truncated lookup table in " << dex_file_location_;
} else {
- lookup_table_ = TypeLookupTable::Open(dex_file_pointer_, lookup_table_data_, num_class_defs);
+ const uint8_t* dex_data = dex_file_pointer_;
+ // TODO: Clean this up to create the type lookup table after the dex file has been created?
+ if (CompactDexFile::IsMagicValid(dex_header->magic_)) {
+ dex_data += dex_header->data_off_;
+ }
+ lookup_table_ = TypeLookupTable::Open(dex_data, lookup_table_data_, num_class_defs);
}
}
}
@@ -1733,9 +1738,17 @@ const DexFile::ClassDef* OatFile::OatDexFile::FindClassDef(const DexFile& dex_fi
size_t hash) {
const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
DCHECK_EQ(ComputeModifiedUtf8Hash(descriptor), hash);
+ bool used_lookup_table = false;
+ const DexFile::ClassDef* lookup_table_classdef = nullptr;
if (LIKELY((oat_dex_file != nullptr) && (oat_dex_file->GetTypeLookupTable() != nullptr))) {
+ used_lookup_table = true;
const uint32_t class_def_idx = oat_dex_file->GetTypeLookupTable()->Lookup(descriptor, hash);
- return (class_def_idx != dex::kDexNoIndex) ? &dex_file.GetClassDef(class_def_idx) : nullptr;
+ lookup_table_classdef = (class_def_idx != dex::kDexNoIndex)
+ ? &dex_file.GetClassDef(class_def_idx)
+ : nullptr;
+ if (!kIsDebugBuild) {
+ return lookup_table_classdef;
+ }
}
// Fast path for rare no class defs case.
const uint32_t num_class_defs = dex_file.NumClassDefs();
@@ -1745,7 +1758,11 @@ const DexFile::ClassDef* OatFile::OatDexFile::FindClassDef(const DexFile& dex_fi
const DexFile::TypeId* type_id = dex_file.FindTypeId(descriptor);
if (type_id != nullptr) {
dex::TypeIndex type_idx = dex_file.GetIndexForTypeId(*type_id);
- return dex_file.FindClassDef(type_idx);
+ const DexFile::ClassDef* found_class_def = dex_file.FindClassDef(type_idx);
+ if (kIsDebugBuild && used_lookup_table) {
+ DCHECK_EQ(found_class_def, lookup_table_classdef);
+ }
+ return found_class_def;
}
return nullptr;
}
diff --git a/runtime/type_lookup_table.cc b/runtime/type_lookup_table.cc
index 6eb3d83631..649a4f9547 100644
--- a/runtime/type_lookup_table.cc
+++ b/runtime/type_lookup_table.cc
@@ -66,7 +66,7 @@ std::unique_ptr<TypeLookupTable> TypeLookupTable::Open(const uint8_t* dex_file_p
}
TypeLookupTable::TypeLookupTable(const DexFile& dex_file, uint8_t* storage)
- : dex_file_begin_(dex_file.Begin()),
+ : dex_data_begin_(dex_file.DataBegin()),
raw_data_length_(RawDataLength(dex_file.NumClassDefs())),
mask_(CalculateMask(dex_file.NumClassDefs())),
entries_(storage != nullptr ? reinterpret_cast<Entry*>(storage) : new Entry[mask_ + 1]),
@@ -106,7 +106,7 @@ TypeLookupTable::TypeLookupTable(const DexFile& dex_file, uint8_t* storage)
TypeLookupTable::TypeLookupTable(const uint8_t* dex_file_pointer,
const uint8_t* raw_data,
uint32_t num_class_defs)
- : dex_file_begin_(dex_file_pointer),
+ : dex_data_begin_(dex_file_pointer),
raw_data_length_(RawDataLength(num_class_defs)),
mask_(CalculateMask(num_class_defs)),
entries_(reinterpret_cast<Entry*>(const_cast<uint8_t*>(raw_data))),
diff --git a/runtime/type_lookup_table.h b/runtime/type_lookup_table.h
index 6a6f47fba2..50c93ad9f0 100644
--- a/runtime/type_lookup_table.h
+++ b/runtime/type_lookup_table.h
@@ -43,7 +43,7 @@ class TypeLookupTable {
// Method search class_def_idx by class descriptor and it's hash.
// If no data found then the method returns dex::kDexNoIndex.
- ALWAYS_INLINE uint32_t Lookup(const char* str, uint32_t hash) const {
+ uint32_t Lookup(const char* str, uint32_t hash) const {
uint32_t pos = hash & GetSizeMask();
// Thanks to special insertion algorithm, the element at position pos can be empty or start of
// bucket.
@@ -127,8 +127,8 @@ class TypeLookupTable {
uint32_t num_class_defs);
bool IsStringsEquals(const char* str, uint32_t str_offset) const {
- const uint8_t* ptr = dex_file_begin_ + str_offset;
- CHECK(dex_file_begin_ != nullptr);
+ const uint8_t* ptr = dex_data_begin_ + str_offset;
+ CHECK(dex_data_begin_ != nullptr);
// Skip string length.
DecodeUnsignedLeb128(&ptr);
return CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(
@@ -160,7 +160,7 @@ class TypeLookupTable {
// Find the last entry in a chain.
uint32_t FindLastEntryInBucket(uint32_t cur_pos) const;
- const uint8_t* dex_file_begin_;
+ const uint8_t* dex_data_begin_;
const uint32_t raw_data_length_;
const uint32_t mask_;
std::unique_ptr<Entry[]> entries_;
diff --git a/runtime/vdex_file.cc b/runtime/vdex_file.cc
index cab91dfe76..36ebb17f4f 100644
--- a/runtime/vdex_file.cc
+++ b/runtime/vdex_file.cc
@@ -48,10 +48,12 @@ bool VdexFile::Header::IsVersionValid() const {
VdexFile::Header::Header(uint32_t number_of_dex_files,
uint32_t dex_size,
+ uint32_t dex_shared_data_size,
uint32_t verifier_deps_size,
uint32_t quickening_info_size)
: number_of_dex_files_(number_of_dex_files),
dex_size_(dex_size),
+ dex_shared_data_size_(dex_shared_data_size),
verifier_deps_size_(verifier_deps_size),
quickening_info_size_(quickening_info_size) {
memcpy(magic_, kVdexMagic, sizeof(kVdexMagic));
@@ -183,14 +185,17 @@ bool VdexFile::OpenAllDexFiles(std::vector<std::unique_ptr<const DexFile>>* dex_
// TODO: Supply the location information for a vdex file.
static constexpr char kVdexLocation[] = "";
std::string location = DexFileLoader::GetMultiDexLocation(i, kVdexLocation);
- std::unique_ptr<const DexFile> dex(dex_file_loader.Open(dex_file_start,
- size,
- location,
- GetLocationChecksum(i),
- nullptr /*oat_dex_file*/,
- false /*verify*/,
- false /*verify_checksum*/,
- error_msg));
+ std::unique_ptr<const DexFile> dex(dex_file_loader.OpenWithDataSection(
+ dex_file_start,
+ size,
+ /*data_base*/ nullptr,
+ /*data_size*/ 0u,
+ location,
+ GetLocationChecksum(i),
+ nullptr /*oat_dex_file*/,
+ false /*verify*/,
+ false /*verify_checksum*/,
+ error_msg));
if (dex == nullptr) {
return false;
}
diff --git a/runtime/vdex_file.h b/runtime/vdex_file.h
index 4e45128420..e8d66ace8e 100644
--- a/runtime/vdex_file.h
+++ b/runtime/vdex_file.h
@@ -54,6 +54,7 @@ class VdexFile {
public:
Header(uint32_t number_of_dex_files_,
uint32_t dex_size,
+ uint32_t dex_shared_data_size,
uint32_t verifier_deps_size,
uint32_t quickening_info_size);
@@ -64,6 +65,7 @@ class VdexFile {
bool IsValid() const { return IsMagicValid() && IsVersionValid(); }
uint32_t GetDexSize() const { return dex_size_; }
+ uint32_t GetDexSharedDataSize() const { return dex_shared_data_size_; }
uint32_t GetVerifierDepsSize() const { return verifier_deps_size_; }
uint32_t GetQuickeningInfoSize() const { return quickening_info_size_; }
uint32_t GetNumberOfDexFiles() const { return number_of_dex_files_; }
@@ -72,6 +74,7 @@ class VdexFile {
return sizeof(Header) +
GetSizeOfChecksumsSection() +
GetDexSize() +
+ GetDexSharedDataSize() +
GetVerifierDepsSize() +
GetQuickeningInfoSize();
}
@@ -84,13 +87,14 @@ class VdexFile {
private:
static constexpr uint8_t kVdexMagic[] = { 'v', 'd', 'e', 'x' };
- // Last update: Use efficient encoding for compact dex code item fields
- static constexpr uint8_t kVdexVersion[] = { '0', '1', '5', '\0' };
+ // Last update: Separate section for compact dex data.
+ static constexpr uint8_t kVdexVersion[] = { '0', '1', '6', '\0' };
uint8_t magic_[4];
uint8_t version_[4];
uint32_t number_of_dex_files_;
uint32_t dex_size_;
+ uint32_t dex_shared_data_size_;
uint32_t verifier_deps_size_;
uint32_t quickening_info_size_;
@@ -172,7 +176,8 @@ class VdexFile {
ArrayRef<const uint8_t> GetVerifierDepsData() const {
return ArrayRef<const uint8_t>(
- DexBegin() + GetHeader().GetDexSize(), GetHeader().GetVerifierDepsSize());
+ DexBegin() + GetHeader().GetDexSize() + GetHeader().GetDexSharedDataSize(),
+ GetHeader().GetVerifierDepsSize());
}
ArrayRef<const uint8_t> GetQuickeningInfo() const {