Make GetSortedDexFileSections a utility
Make this method a utility in preparation for other users outside
dexlayout.
Bug: 35800981
Test: make -j 40 test-art-host
Change-Id: I054c1e1c82834a0c94be6b9ee63d1992fa9f52df
diff --git a/dexlayout/dex_ir.cc b/dexlayout/dex_ir.cc
index 4228503..4502626 100644
--- a/dexlayout/dex_ir.cc
+++ b/dexlayout/dex_ir.cc
@@ -763,5 +763,138 @@
return class_data;
}
+static uint32_t HeaderOffset(const dex_ir::Collections& collections ATTRIBUTE_UNUSED) {
+ return 0;
+}
+
+static uint32_t HeaderSize(const dex_ir::Collections& collections ATTRIBUTE_UNUSED) {
+ // Size is in elements, so there is only one header.
+ return 1;
+}
+
+// The description of each dex file section type.
+struct FileSectionDescriptor {
+ public:
+ std::string name;
+ uint16_t type;
+ // A function that when applied to a collection object, gives the size of the section.
+ std::function<uint32_t(const dex_ir::Collections&)> size_fn;
+ // A function that when applied to a collection object, gives the offset of the section.
+ std::function<uint32_t(const dex_ir::Collections&)> offset_fn;
+};
+
+static const std::vector<FileSectionDescriptor> kFileSectionDescriptors = {
+ {
+ "Header",
+ DexFile::kDexTypeHeaderItem,
+ &HeaderSize,
+ &HeaderOffset,
+ }, {
+ "StringId",
+ DexFile::kDexTypeStringIdItem,
+ &dex_ir::Collections::StringIdsSize,
+ &dex_ir::Collections::StringIdsOffset
+ }, {
+ "TypeId",
+ DexFile::kDexTypeTypeIdItem,
+ &dex_ir::Collections::TypeIdsSize,
+ &dex_ir::Collections::TypeIdsOffset
+ }, {
+ "ProtoId",
+ DexFile::kDexTypeProtoIdItem,
+ &dex_ir::Collections::ProtoIdsSize,
+ &dex_ir::Collections::ProtoIdsOffset
+ }, {
+ "FieldId",
+ DexFile::kDexTypeFieldIdItem,
+ &dex_ir::Collections::FieldIdsSize,
+ &dex_ir::Collections::FieldIdsOffset
+ }, {
+ "MethodId",
+ DexFile::kDexTypeMethodIdItem,
+ &dex_ir::Collections::MethodIdsSize,
+ &dex_ir::Collections::MethodIdsOffset
+ }, {
+ "ClassDef",
+ DexFile::kDexTypeClassDefItem,
+ &dex_ir::Collections::ClassDefsSize,
+ &dex_ir::Collections::ClassDefsOffset
+ }, {
+ "StringData",
+ DexFile::kDexTypeStringDataItem,
+ &dex_ir::Collections::StringDatasSize,
+ &dex_ir::Collections::StringDatasOffset
+ }, {
+ "TypeList",
+ DexFile::kDexTypeTypeList,
+ &dex_ir::Collections::TypeListsSize,
+ &dex_ir::Collections::TypeListsOffset
+ }, {
+ "EncArr",
+ DexFile::kDexTypeEncodedArrayItem,
+ &dex_ir::Collections::EncodedArrayItemsSize,
+ &dex_ir::Collections::EncodedArrayItemsOffset
+ }, {
+ "Annotation",
+ DexFile::kDexTypeAnnotationItem,
+ &dex_ir::Collections::AnnotationItemsSize,
+ &dex_ir::Collections::AnnotationItemsOffset
+ }, {
+ "AnnoSet",
+ DexFile::kDexTypeAnnotationSetItem,
+ &dex_ir::Collections::AnnotationSetItemsSize,
+ &dex_ir::Collections::AnnotationSetItemsOffset
+ }, {
+ "AnnoSetRL",
+ DexFile::kDexTypeAnnotationSetRefList,
+ &dex_ir::Collections::AnnotationSetRefListsSize,
+ &dex_ir::Collections::AnnotationSetRefListsOffset
+ }, {
+ "AnnoDir",
+ DexFile::kDexTypeAnnotationsDirectoryItem,
+ &dex_ir::Collections::AnnotationsDirectoryItemsSize,
+ &dex_ir::Collections::AnnotationsDirectoryItemsOffset
+ }, {
+ "DebugInfo",
+ DexFile::kDexTypeDebugInfoItem,
+ &dex_ir::Collections::DebugInfoItemsSize,
+ &dex_ir::Collections::DebugInfoItemsOffset
+ }, {
+ "CodeItem",
+ DexFile::kDexTypeCodeItem,
+ &dex_ir::Collections::CodeItemsSize,
+ &dex_ir::Collections::CodeItemsOffset
+ }, {
+ "ClassData",
+ DexFile::kDexTypeClassDataItem,
+ &dex_ir::Collections::ClassDatasSize,
+ &dex_ir::Collections::ClassDatasOffset
+ }
+};
+
+std::vector<dex_ir::DexFileSection> GetSortedDexFileSections(dex_ir::Header* header,
+ dex_ir::SortDirection direction) {
+ const dex_ir::Collections& collections = header->GetCollections();
+ std::vector<dex_ir::DexFileSection> sorted_sections;
+ // Build the table that will map from offset to color
+ for (const FileSectionDescriptor& s : kFileSectionDescriptors) {
+ sorted_sections.push_back(dex_ir::DexFileSection(s.name,
+ s.type,
+ s.size_fn(collections),
+ s.offset_fn(collections)));
+ }
+ // Sort by offset.
+ std::sort(sorted_sections.begin(),
+ sorted_sections.end(),
+ [=](dex_ir::DexFileSection& a, dex_ir::DexFileSection& b) {
+ if (direction == SortDirection::kSortDescending) {
+ return a.offset > b.offset;
+ } else {
+ return a.offset < b.offset;
+ }
+ });
+ return sorted_sections;
+}
+
} // namespace dex_ir
} // namespace art
diff --git a/dexlayout/dex_ir.h b/dexlayout/dex_ir.h
index 78ddde8..cad0395 100644
--- a/dexlayout/dex_ir.h
+++ b/dexlayout/dex_ir.h
@@ -1104,6 +1104,28 @@
DISALLOW_COPY_AND_ASSIGN(MapItem);
};
+// Interface for building a vector of file sections for use by other clients.
+struct DexFileSection {
+ public:
+ DexFileSection(const std::string& name, uint16_t type, uint32_t size, uint32_t offset)
+ : name(name), type(type), size(size), offset(offset) { }
+ std::string name;
+ // The type (DexFile::MapItemType).
+ uint16_t type;
+ // The size (in elements, not bytes).
+ uint32_t size;
+ // The byte offset from the start of the file.
+ uint32_t offset;
+};
+
+enum class SortDirection {
+ kSortAscending,
+ kSortDescending
+};
+
+std::vector<DexFileSection> GetSortedDexFileSections(dex_ir::Header* header,
+ SortDirection direction);
+
} // namespace dex_ir
} // namespace art
diff --git a/dexlayout/dex_visualize.cc b/dexlayout/dex_visualize.cc
index 452f51b..829e9fe 100644
--- a/dexlayout/dex_visualize.cc
+++ b/dexlayout/dex_visualize.cc
@@ -41,142 +41,13 @@
return prefix + ((dex_file_index > 0) ? std::to_string(dex_file_index + 1) : "") + suffix;
}
-struct FileSection {
- public:
- std::string name_;
- uint16_t type_;
- std::function<uint32_t(const dex_ir::Collections&)> size_fn_;
- std::function<uint32_t(const dex_ir::Collections&)> offset_fn_;
-};
-
-static uint32_t HeaderOffset(const dex_ir::Collections& collections ATTRIBUTE_UNUSED) {
- return 0;
-}
-
-static uint32_t HeaderSize(const dex_ir::Collections& collections ATTRIBUTE_UNUSED) {
- // Size is in elements, so there is only one header.
- return 1;
-}
-
-static const std::vector<FileSection> kFileSections = {
- {
- "Header",
- DexFile::kDexTypeHeaderItem,
- &HeaderSize,
- &HeaderOffset,
- }, {
- "StringId",
- DexFile::kDexTypeStringIdItem,
- &dex_ir::Collections::StringIdsSize,
- &dex_ir::Collections::StringIdsOffset
- }, {
- "TypeId",
- DexFile::kDexTypeTypeIdItem,
- &dex_ir::Collections::TypeIdsSize,
- &dex_ir::Collections::TypeIdsOffset
- }, {
- "ProtoId",
- DexFile::kDexTypeProtoIdItem,
- &dex_ir::Collections::ProtoIdsSize,
- &dex_ir::Collections::ProtoIdsOffset
- }, {
- "FieldId",
- DexFile::kDexTypeFieldIdItem,
- &dex_ir::Collections::FieldIdsSize,
- &dex_ir::Collections::FieldIdsOffset
- }, {
- "MethodId",
- DexFile::kDexTypeMethodIdItem,
- &dex_ir::Collections::MethodIdsSize,
- &dex_ir::Collections::MethodIdsOffset
- }, {
- "ClassDef",
- DexFile::kDexTypeClassDefItem,
- &dex_ir::Collections::ClassDefsSize,
- &dex_ir::Collections::ClassDefsOffset
- }, {
- "StringData",
- DexFile::kDexTypeStringDataItem,
- &dex_ir::Collections::StringDatasSize,
- &dex_ir::Collections::StringDatasOffset
- }, {
- "TypeList",
- DexFile::kDexTypeTypeList,
- &dex_ir::Collections::TypeListsSize,
- &dex_ir::Collections::TypeListsOffset
- }, {
- "EncArr",
- DexFile::kDexTypeEncodedArrayItem,
- &dex_ir::Collections::EncodedArrayItemsSize,
- &dex_ir::Collections::EncodedArrayItemsOffset
- }, {
- "Annotation",
- DexFile::kDexTypeAnnotationItem,
- &dex_ir::Collections::AnnotationItemsSize,
- &dex_ir::Collections::AnnotationItemsOffset
- }, {
- "AnnoSet",
- DexFile::kDexTypeAnnotationSetItem,
- &dex_ir::Collections::AnnotationSetItemsSize,
- &dex_ir::Collections::AnnotationSetItemsOffset
- }, {
- "AnnoSetRL",
- DexFile::kDexTypeAnnotationSetRefList,
- &dex_ir::Collections::AnnotationSetRefListsSize,
- &dex_ir::Collections::AnnotationSetRefListsOffset
- }, {
- "AnnoDir",
- DexFile::kDexTypeAnnotationsDirectoryItem,
- &dex_ir::Collections::AnnotationsDirectoryItemsSize,
- &dex_ir::Collections::AnnotationsDirectoryItemsOffset
- }, {
- "DebugInfo",
- DexFile::kDexTypeDebugInfoItem,
- &dex_ir::Collections::DebugInfoItemsSize,
- &dex_ir::Collections::DebugInfoItemsOffset
- }, {
- "CodeItem",
- DexFile::kDexTypeCodeItem,
- &dex_ir::Collections::CodeItemsSize,
- &dex_ir::Collections::CodeItemsOffset
- }, {
- "ClassData",
- DexFile::kDexTypeClassDataItem,
- &dex_ir::Collections::ClassDatasSize,
- &dex_ir::Collections::ClassDatasOffset
- }
-};
-
-static constexpr bool kSortAscending = false;
-static constexpr bool kSortDescending = true;
-
-static std::vector<const FileSection*> GetSortedSections(
- const dex_ir::Collections& collections,
- bool sort_descending) {
- std::vector<const FileSection*> sorted_sections;
- // Build the table that will map from offset to color
- for (const FileSection& s : kFileSections) {
- sorted_sections.push_back(&s);
- }
- // Sort by offset.
- std::sort(sorted_sections.begin(),
- sorted_sections.end(),
- [&](const FileSection* a, const FileSection* b) {
- if (sort_descending) {
- return a->offset_fn_(collections) > b->offset_fn_(collections);
- } else {
- return a->offset_fn_(collections) < b->offset_fn_(collections);
- }
- });
- return sorted_sections;
-}
-
class Dumper {
public:
// Colors are based on the type of the section in MapList.
- explicit Dumper(const dex_ir::Collections& collections)
- : collections_(collections), out_file_(nullptr),
- sorted_sections_(GetSortedSections(collections, kSortDescending)) { }
+ explicit Dumper(dex_ir::Header* header)
+ : out_file_(nullptr),
+ sorted_sections_(
+ dex_ir::GetSortedDexFileSections(header, dex_ir::SortDirection::kSortDescending)) { }
bool OpenAndPrintHeader(size_t dex_index) {
// Open the file and emit the gnuplot prologue.
@@ -191,12 +62,13 @@
fprintf(out_file_, "set ylabel \"ClassDef index\"\n");
fprintf(out_file_, "set xtics rotate out (");
bool printed_one = false;
- for (const FileSection& s : kFileSections) {
- if (s.size_fn_(collections_) > 0) {
+
+ for (const dex_ir::DexFileSection& s : sorted_sections_) {
+ if (s.size > 0) {
if (printed_one) {
fprintf(out_file_, ", ");
}
- fprintf(out_file_, "\"%s\" %d", s.name_.c_str(), s.offset_fn_(collections_) / kPageSize);
+ fprintf(out_file_, "\"%s\" %d", s.name.c_str(), s.offset / kPageSize);
printed_one = true;
}
}
@@ -209,9 +81,9 @@
int GetColor(uint32_t offset) const {
// The dread linear search to find the right section for the reference.
uint16_t section = 0;
- for (const FileSection* file_section : sorted_sections_) {
- if (file_section->offset_fn_(collections_) < offset) {
- section = file_section->type_;
+ for (const dex_ir::DexFileSection& file_section : sorted_sections_) {
+ if (file_section.offset < offset) {
+ section = file_section.type;
break;
}
}
@@ -362,9 +234,8 @@
{ DexFile::kDexTypeAnnotationsDirectoryItem, 16 }
};
- const dex_ir::Collections& collections_;
FILE* out_file_;
- std::vector<const FileSection*> sorted_sections_;
+ std::vector<dex_ir::DexFileSection> sorted_sections_;
DISALLOW_COPY_AND_ASSIGN(Dumper);
};
@@ -377,7 +248,7 @@
const DexFile* dex_file,
size_t dex_file_index,
ProfileCompilationInfo* profile_info) {
- std::unique_ptr<Dumper> dumper(new Dumper(header->GetCollections()));
+ std::unique_ptr<Dumper> dumper(new Dumper(header));
if (!dumper->OpenAndPrintHeader(dex_file_index)) {
fprintf(stderr, "Could not open output file.\n");
return;
@@ -433,13 +304,12 @@
}
static uint32_t FindNextByteAfterSection(dex_ir::Header* header,
- const dex_ir::Collections& collections,
- std::vector<const FileSection*>& sorted_sections,
+ const std::vector<dex_ir::DexFileSection>& sorted_sections,
size_t section_index) {
for (size_t i = section_index + 1; i < sorted_sections.size(); ++i) {
- const FileSection* section = sorted_sections[i];
- if (section->size_fn_(collections) != 0) {
- return section->offset_fn_(collections);
+ const dex_ir::DexFileSection& section = sorted_sections.at(i);
+ if (section.size != 0) {
+ return section.offset;
}
}
return header->FileSize();
@@ -454,19 +324,22 @@
MultidexName("classes", dex_file_index, ".dex").c_str(),
header->FileSize());
fprintf(stdout, "section offset items bytes pages pct\n");
- const dex_ir::Collections& collections = header->GetCollections();
- std::vector<const FileSection*> sorted_sections(GetSortedSections(collections, kSortAscending));
+ std::vector<dex_ir::DexFileSection> sorted_sections =
+ GetSortedDexFileSections(header, dex_ir::SortDirection::kSortAscending);
for (size_t i = 0; i < sorted_sections.size(); ++i) {
- const FileSection* file_section = sorted_sections[i];
- const char* name = file_section->name_.c_str();
- uint32_t offset = file_section->offset_fn_(collections);
- uint32_t items = file_section->size_fn_(collections);
+ const dex_ir::DexFileSection& file_section = sorted_sections[i];
uint32_t bytes = 0;
- if (items > 0) {
- bytes = FindNextByteAfterSection(header, collections, sorted_sections, i) - offset;
+ if (file_section.size > 0) {
+ bytes = FindNextByteAfterSection(header, sorted_sections, i) - file_section.offset;
}
- fprintf(stdout, "%-10s %8d %8d %8d %8d %%%02d\n", name, offset, items, bytes,
- (bytes + kPageSize - 1) / kPageSize, 100 * bytes / header->FileSize());
+ fprintf(stdout,
+ "%-10s %8d %8d %8d %8d %%%02d\n",
+ file_section.name.c_str(),
+ file_section.offset,
+ file_section.size,
+ bytes,
+ RoundUp(bytes, kPageSize) / kPageSize,
+ 100 * bytes / header->FileSize());
}
fprintf(stdout, "\n");
}