Merge "ART: Add class-alloc-inl.h"
diff --git a/adbconnection/Android.bp b/adbconnection/Android.bp
index 95fc274..5f78278 100644
--- a/adbconnection/Android.bp
+++ b/adbconnection/Android.bp
@@ -30,11 +30,6 @@
"libbase",
],
target: {
- android: {
- shared_libs: [
- "libcutils",
- ],
- },
host: {
},
darwin: {
diff --git a/adbconnection/adbconnection.cc b/adbconnection/adbconnection.cc
index ba25393..cf35914 100644
--- a/adbconnection/adbconnection.cc
+++ b/adbconnection/adbconnection.cc
@@ -24,6 +24,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/mutex.h"
+#include "base/socket_peer_is_trusted.h"
#include "jni/java_vm_ext.h"
#include "jni/jni_env_ext.h"
#include "mirror/throwable.h"
@@ -39,10 +40,6 @@
#include "poll.h"
-#ifdef ART_TARGET_ANDROID
-#include "cutils/sockets.h"
-#endif
-
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/un.h>
@@ -517,11 +514,7 @@
// the debuggable flag set.
int ret = connect(sock, &control_addr_.controlAddrPlain, control_addr_len_);
if (ret == 0) {
- bool trusted = sock >= 0;
-#ifdef ART_TARGET_ANDROID
- // Needed for socket_peer_is_trusted.
- trusted = trusted && socket_peer_is_trusted(sock);
-#endif
+ bool trusted = sock >= 0 && art::SocketPeerIsTrusted(sock);
if (!trusted) {
LOG(ERROR) << "adb socket is not trusted. Aborting connection.";
if (sock >= 0 && shutdown(sock, SHUT_RDWR)) {
diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc
index 01c24fc..23c486d 100644
--- a/dex2oat/linker/oat_writer.cc
+++ b/dex2oat/linker/oat_writer.cc
@@ -3401,6 +3401,11 @@
}
bool OatWriter::LayoutAndWriteDexFile(OutputStream* out, OatDexFile* oat_dex_file) {
+ // Open dex files and write them into `out`.
+ // Note that we only verify dex files which do not belong to the boot class path.
+ // This is because those have been processed by `hiddenapi` and would not pass
+ // some of the checks. No guarantees are lost, however, as `hiddenapi` verifies
+ // the dex files prior to processing.
TimingLogger::ScopedTiming split("Dex Layout", timings_);
std::string error_msg;
std::string location(oat_dex_file->GetLocation());
@@ -3421,7 +3426,7 @@
dex_file = dex_file_loader.Open(location,
zip_entry->GetCrc32(),
std::move(mem_map),
- /* verify */ true,
+ /* verify */ !GetCompilerOptions().IsBootImage(),
/* verify_checksum */ true,
&error_msg);
} else if (oat_dex_file->source_.IsRawFile()) {
@@ -3433,7 +3438,7 @@
}
TimingLogger::ScopedTiming extract("Open", timings_);
dex_file = dex_file_loader.OpenDex(dup_fd, location,
- /* verify */ true,
+ /* verify */ !GetCompilerOptions().IsBootImage(),
/* verify_checksum */ true,
/* mmap_shared */ false,
&error_msg);
diff --git a/dexdump/dexdump.cc b/dexdump/dexdump.cc
index 2b59342..6b2a1b9 100644
--- a/dexdump/dexdump.cc
+++ b/dexdump/dexdump.cc
@@ -1208,7 +1208,7 @@
*/
static void dumpMethod(const ClassAccessor::Method& method, int i) {
// Bail for anything private if export only requested.
- const uint32_t flags = method.GetAccessFlags();
+ const uint32_t flags = method.GetRawAccessFlags();
if (gOptions.exportsOnly && (flags & (kAccPublic | kAccProtected)) == 0) {
return;
}
@@ -1319,7 +1319,7 @@
*/
static void dumpField(const ClassAccessor::Field& field, int i, const u1** data = nullptr) {
// Bail for anything private if export only requested.
- const uint32_t flags = field.GetAccessFlags();
+ const uint32_t flags = field.GetRawAccessFlags();
if (gOptions.exportsOnly && (flags & (kAccPublic | kAccProtected)) == 0) {
return;
}
diff --git a/dexlayout/compact_dex_writer.cc b/dexlayout/compact_dex_writer.cc
index a7dad07..a04cfb6 100644
--- a/dexlayout/compact_dex_writer.cc
+++ b/dexlayout/compact_dex_writer.cc
@@ -441,7 +441,6 @@
WriteTypeLists(data_stream);
WriteClassDatas(data_stream);
WriteStringDatas(data_stream);
- WriteHiddenapiClassData(data_stream);
// Write delayed id sections that depend on data sections.
{
diff --git a/dexlayout/dex_ir.h b/dexlayout/dex_ir.h
index 20ebc17..598f7df 100644
--- a/dexlayout/dex_ir.h
+++ b/dexlayout/dex_ir.h
@@ -21,11 +21,11 @@
#include <stdint.h>
+#include <map>
#include <vector>
#include "base/iteration_range.h"
#include "base/leb128.h"
-#include "base/safe_map.h"
#include "base/stl_util.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_types.h"
@@ -50,7 +50,6 @@
class FieldId;
class FieldItem;
class Header;
-class HiddenapiClassData;
class MapList;
class MapItem;
class MethodHandleItem;
@@ -102,7 +101,6 @@
virtual void Dispatch(AnnotationSetItem* annotation_set_item) = 0;
virtual void Dispatch(AnnotationSetRefList* annotation_set_ref_list) = 0;
virtual void Dispatch(AnnotationsDirectoryItem* annotations_directory_item) = 0;
- virtual void Dispatch(HiddenapiClassData* hiddenapi_class_data) = 0;
virtual void Dispatch(MapList* map_list) = 0;
virtual void Dispatch(MapItem* map_item) = 0;
@@ -218,7 +216,6 @@
uint32_t GetOffset() const { return offset_; }
void SetOffset(uint32_t new_offset) { offset_ = new_offset; }
virtual uint32_t Size() const = 0;
- bool Empty() const { return Size() == 0u; }
private:
// Start out unassigned.
@@ -479,12 +476,6 @@
const CollectionVector<AnnotationsDirectoryItem>& AnnotationsDirectoryItems() const {
return annotations_directory_items_;
}
- IndexedCollectionVector<HiddenapiClassData>& HiddenapiClassDatas() {
- return hiddenapi_class_datas_;
- }
- const IndexedCollectionVector<HiddenapiClassData>& HiddenapiClassDatas() const {
- return hiddenapi_class_datas_;
- }
CollectionVector<DebugInfoItem>& DebugInfoItems() { return debug_info_items_; }
const CollectionVector<DebugInfoItem>& DebugInfoItems() const { return debug_info_items_; }
CollectionVector<CodeItem>& CodeItems() { return code_items_; }
@@ -562,7 +553,6 @@
IndexedCollectionVector<AnnotationSetItem> annotation_set_items_;
IndexedCollectionVector<AnnotationSetRefList> annotation_set_ref_lists_;
IndexedCollectionVector<AnnotationsDirectoryItem> annotations_directory_items_;
- IndexedCollectionVector<HiddenapiClassData> hiddenapi_class_datas_;
// The order of the vectors controls the layout of the output file by index order, to change the
// layout just sort the vector. Note that you may only change the order of the non indexed vectors
// below. Indexed vectors are accessed by indices in other places, changing the sorting order will
@@ -1274,49 +1264,6 @@
DISALLOW_COPY_AND_ASSIGN(MethodHandleItem);
};
-using HiddenapiFlagsMap = SafeMap<const Item*, uint32_t>;
-
-class HiddenapiClassData : public IndexedItem {
- public:
- HiddenapiClassData(const ClassDef* class_def, std::unique_ptr<HiddenapiFlagsMap> flags)
- : class_def_(class_def), flags_(std::move(flags)) { }
- ~HiddenapiClassData() override { }
-
- const ClassDef* GetClassDef() const { return class_def_; }
-
- uint32_t GetFlags(const Item* field_or_method_item) const {
- return (flags_ == nullptr) ? 0u : flags_->Get(field_or_method_item);
- }
-
- static uint32_t GetFlags(Header* header, ClassDef* class_def, const Item* field_or_method_item) {
- DCHECK(header != nullptr);
- DCHECK(class_def != nullptr);
- return (header->HiddenapiClassDatas().Empty())
- ? 0u
- : header->HiddenapiClassDatas()[class_def->GetIndex()]->GetFlags(field_or_method_item);
- }
-
- uint32_t ItemSize() const {
- uint32_t size = 0u;
- bool has_non_zero_entries = false;
- if (flags_ != nullptr) {
- for (const auto& entry : *flags_) {
- size += UnsignedLeb128Size(entry.second);
- has_non_zero_entries |= (entry.second != 0u);
- }
- }
- return has_non_zero_entries ? size : 0u;
- }
-
- void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }
-
- private:
- const ClassDef* class_def_;
- std::unique_ptr<HiddenapiFlagsMap> flags_;
-
- DISALLOW_COPY_AND_ASSIGN(HiddenapiClassData);
-};
-
// TODO(sehr): implement MapList.
class MapList : public Item {
public:
diff --git a/dexlayout/dex_ir_builder.cc b/dexlayout/dex_ir_builder.cc
index c38e563..947d3d5 100644
--- a/dexlayout/dex_ir_builder.cc
+++ b/dexlayout/dex_ir_builder.cc
@@ -170,7 +170,6 @@
void AddAnnotationsFromMapListSection(const DexFile& dex_file,
uint32_t start_offset,
uint32_t count);
- void AddHiddenapiClassDataFromMapListSection(const DexFile& dex_file, uint32_t offset);
void CheckAndSetRemainingOffsets(const DexFile& dex_file, const Options& options);
@@ -409,10 +408,6 @@
case DexFile::kDexTypeAnnotationsDirectoryItem:
header_->AnnotationsDirectoryItems().SetOffset(item->offset_);
break;
- case DexFile::kDexTypeHiddenapiClassData:
- header_->HiddenapiClassDatas().SetOffset(item->offset_);
- AddHiddenapiClassDataFromMapListSection(dex_file, item->offset_);
- break;
default:
LOG(ERROR) << "Unknown map list item type.";
}
@@ -629,44 +624,6 @@
}
}
-void BuilderMaps::AddHiddenapiClassDataFromMapListSection(const DexFile& dex_file,
- uint32_t offset) {
- const DexFile::HiddenapiClassData* hiddenapi_class_data =
- dex_file.GetHiddenapiClassDataAtOffset(offset);
- DCHECK(hiddenapi_class_data == dex_file.GetHiddenapiClassData());
-
- for (size_t i = 0; i < dex_file.NumClassDefs(); ++i) {
- ClassDef* class_def = header_->ClassDefs()[i];
- ClassData* class_data = class_def->GetClassData();
- const uint8_t* ptr = hiddenapi_class_data->GetFlagsPointer(i);
-
- std::unique_ptr<HiddenapiFlagsMap> flags = nullptr;
- if (ptr != nullptr) {
- DCHECK(class_data != nullptr);
- flags = std::make_unique<HiddenapiFlagsMap>();
- for (const dex_ir::FieldItem& field : *class_data->StaticFields()) {
- flags->emplace(&field, DecodeUnsignedLeb128(&ptr));
- }
- for (const dex_ir::FieldItem& field : *class_data->InstanceFields()) {
- flags->emplace(&field, DecodeUnsignedLeb128(&ptr));
- }
- for (const dex_ir::MethodItem& method : *class_data->DirectMethods()) {
- flags->emplace(&method, DecodeUnsignedLeb128(&ptr));
- }
- for (const dex_ir::MethodItem& method : *class_data->VirtualMethods()) {
- flags->emplace(&method, DecodeUnsignedLeb128(&ptr));
- }
- }
-
- CreateAndAddIndexedItem(header_->HiddenapiClassDatas(),
- header_->HiddenapiClassDatas().GetOffset() +
- hiddenapi_class_data->flags_offset_[i],
- i,
- class_def,
- std::move(flags));
- }
-}
-
AnnotationItem* BuilderMaps::CreateAnnotationItem(const DexFile& dex_file,
const DexFile::AnnotationItem* annotation) {
const uint8_t* const start_data = reinterpret_cast<const uint8_t*>(annotation);
@@ -951,13 +908,13 @@
FieldItemVector* static_fields = new FieldItemVector();
for (const ClassAccessor::Field& field : accessor.GetStaticFields()) {
FieldId* field_item = header_->FieldIds()[field.GetIndex()];
- uint32_t access_flags = field.GetAccessFlags();
+ uint32_t access_flags = field.GetRawAccessFlags();
static_fields->emplace_back(access_flags, field_item);
}
FieldItemVector* instance_fields = new FieldItemVector();
for (const ClassAccessor::Field& field : accessor.GetInstanceFields()) {
FieldId* field_item = header_->FieldIds()[field.GetIndex()];
- uint32_t access_flags = field.GetAccessFlags();
+ uint32_t access_flags = field.GetRawAccessFlags();
instance_fields->emplace_back(access_flags, field_item);
}
// Direct methods.
@@ -1223,7 +1180,7 @@
MethodItem BuilderMaps::GenerateMethodItem(const DexFile& dex_file,
const ClassAccessor::Method& method) {
MethodId* method_id = header_->MethodIds()[method.GetIndex()];
- uint32_t access_flags = method.GetAccessFlags();
+ uint32_t access_flags = method.GetRawAccessFlags();
const DexFile::CodeItem* disk_code_item = method.GetCodeItem();
// Temporary hack to prevent incorrectly deduping code items if they have the same offset since
// they may have different debug info streams.
diff --git a/dexlayout/dex_writer.cc b/dexlayout/dex_writer.cc
index 929ed40..365171b 100644
--- a/dexlayout/dex_writer.cc
+++ b/dexlayout/dex_writer.cc
@@ -462,58 +462,6 @@
}
}
-void DexWriter::WriteHiddenapiClassData(Stream* stream) {
- if (header_->HiddenapiClassDatas().Empty()) {
- return;
- }
- DCHECK_EQ(header_->HiddenapiClassDatas().Size(), header_->ClassDefs().Size());
-
- const uint32_t start = stream->Tell();
-
- // Compute offsets for each class def and write the header.
- // data_header[0]: total size of the section
- // data_header[i + 1]: offset of class def[i] from the beginning of the section,
- // or zero if no data
- std::vector<uint32_t> data_header(header_->ClassDefs().Size() + 1, 0);
- data_header[0] = sizeof(uint32_t) * (header_->ClassDefs().Size() + 1);
- for (uint32_t i = 0; i < header_->ClassDefs().Size(); ++i) {
- uint32_t item_size = header_->HiddenapiClassDatas()[i]->ItemSize();
- data_header[i + 1] = item_size == 0u ? 0 : data_header[0];
- data_header[0] += item_size;
- }
- stream->Write(data_header.data(), sizeof(uint32_t) * data_header.size());
-
- // Write class data streams.
- for (uint32_t i = 0; i < header_->ClassDefs().Size(); ++i) {
- dex_ir::ClassDef* class_def = header_->ClassDefs()[i];
- const auto& item = header_->HiddenapiClassDatas()[i];
- DCHECK(item->GetClassDef() == class_def);
-
- if (data_header[i + 1] != 0u) {
- dex_ir::ClassData* class_data = class_def->GetClassData();
- DCHECK(class_data != nullptr);
- DCHECK_EQ(data_header[i + 1], stream->Tell() - start);
- for (const dex_ir::FieldItem& field : *class_data->StaticFields()) {
- stream->WriteUleb128(item->GetFlags(&field));
- }
- for (const dex_ir::FieldItem& field : *class_data->InstanceFields()) {
- stream->WriteUleb128(item->GetFlags(&field));
- }
- for (const dex_ir::MethodItem& method : *class_data->DirectMethods()) {
- stream->WriteUleb128(item->GetFlags(&method));
- }
- for (const dex_ir::MethodItem& method : *class_data->VirtualMethods()) {
- stream->WriteUleb128(item->GetFlags(&method));
- }
- }
- }
- DCHECK_EQ(stream->Tell() - start, data_header[0]);
-
- if (compute_offsets_ && start != stream->Tell()) {
- header_->HiddenapiClassDatas().SetOffset(start);
- }
-}
-
void DexWriter::WriteDebugInfoItem(Stream* stream, dex_ir::DebugInfoItem* debug_info) {
stream->AlignTo(SectionAlignment(DexFile::kDexTypeDebugInfoItem));
ProcessOffset(stream, debug_info);
@@ -782,9 +730,6 @@
queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationsDirectoryItem,
header_->AnnotationsDirectoryItems().Size(),
header_->AnnotationsDirectoryItems().GetOffset()));
- queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeHiddenapiClassData,
- header_->HiddenapiClassDatas().Empty() ? 0u : 1u,
- header_->HiddenapiClassDatas().GetOffset()));
WriteMapItems(stream, &queue);
}
@@ -884,7 +829,6 @@
WriteTypeLists(stream);
WriteClassDatas(stream);
WriteStringDatas(stream);
- WriteHiddenapiClassData(stream);
// Write delayed id sections that depend on data sections.
{
diff --git a/dexlayout/dex_writer.h b/dexlayout/dex_writer.h
index 98041d3..dd2ebad 100644
--- a/dexlayout/dex_writer.h
+++ b/dexlayout/dex_writer.h
@@ -257,7 +257,6 @@
void WriteStringDatas(Stream* stream);
void WriteClassDatas(Stream* stream);
void WriteMethodHandles(Stream* stream);
- void WriteHiddenapiClassData(Stream* stream);
void WriteMapItems(Stream* stream, MapItemQueue* queue);
void GenerateAndWriteMapItems(Stream* stream);
diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc
index 09f0b20..8905aa3 100644
--- a/dexlayout/dexlayout.cc
+++ b/dexlayout/dexlayout.cc
@@ -222,17 +222,6 @@
return str;
}
-static const char* GetHiddenapiFlagStr(uint32_t hiddenapi_flags) {
- static const char* const kValue[] = {
- "WHITELIST", /* 0x0 */
- "LIGHT_GREYLIST", /* 0x1 */
- "DARK_GREYLIST", /* 0x2 */
- "BLACKLIST", /* 0x3 */
- };
- DCHECK_LT(hiddenapi_flags, arraysize(kValue));
- return kValue[hiddenapi_flags];
-}
-
static std::string GetSignatureForProtoId(const dex_ir::ProtoId* proto) {
if (proto == nullptr) {
return "<no signature>";
@@ -1158,11 +1147,7 @@
/*
* Dumps a method.
*/
-void DexLayout::DumpMethod(uint32_t idx,
- uint32_t flags,
- uint32_t hiddenapi_flags,
- const dex_ir::CodeItem* code,
- int i) {
+void DexLayout::DumpMethod(uint32_t idx, uint32_t flags, const dex_ir::CodeItem* code, int i) {
// Bail for anything private if export only requested.
if (options_.exports_only_ && (flags & (kAccPublic | kAccProtected)) == 0) {
return;
@@ -1173,16 +1158,12 @@
char* type_descriptor = strdup(GetSignatureForProtoId(method_id->Proto()).c_str());
const char* back_descriptor = method_id->Class()->GetStringId()->Data();
char* access_str = CreateAccessFlagStr(flags, kAccessForMethod);
- const char* hiddenapi_str = GetHiddenapiFlagStr(hiddenapi_flags);
if (options_.output_format_ == kOutputPlain) {
fprintf(out_file_, " #%d : (in %s)\n", i, back_descriptor);
fprintf(out_file_, " name : '%s'\n", name);
fprintf(out_file_, " type : '%s'\n", type_descriptor);
fprintf(out_file_, " access : 0x%04x (%s)\n", flags, access_str);
- if (hiddenapi_flags != 0u) {
- fprintf(out_file_, " hiddenapi : 0x%04x (%s)\n", hiddenapi_flags, hiddenapi_str);
- }
if (code == nullptr) {
fprintf(out_file_, " code : (none)\n");
} else {
@@ -1276,11 +1257,7 @@
/*
* Dumps a static (class) field.
*/
-void DexLayout::DumpSField(uint32_t idx,
- uint32_t flags,
- uint32_t hiddenapi_flags,
- int i,
- dex_ir::EncodedValue* init) {
+void DexLayout::DumpSField(uint32_t idx, uint32_t flags, int i, dex_ir::EncodedValue* init) {
// Bail for anything private if export only requested.
if (options_.exports_only_ && (flags & (kAccPublic | kAccProtected)) == 0) {
return;
@@ -1291,16 +1268,12 @@
const char* type_descriptor = field_id->Type()->GetStringId()->Data();
const char* back_descriptor = field_id->Class()->GetStringId()->Data();
char* access_str = CreateAccessFlagStr(flags, kAccessForField);
- const char* hiddenapi_str = GetHiddenapiFlagStr(hiddenapi_flags);
if (options_.output_format_ == kOutputPlain) {
fprintf(out_file_, " #%d : (in %s)\n", i, back_descriptor);
fprintf(out_file_, " name : '%s'\n", name);
fprintf(out_file_, " type : '%s'\n", type_descriptor);
fprintf(out_file_, " access : 0x%04x (%s)\n", flags, access_str);
- if (hiddenapi_flags != 0u) {
- fprintf(out_file_, " hiddenapi : 0x%04x (%s)\n", hiddenapi_flags, hiddenapi_str);
- }
if (init != nullptr) {
fputs(" value : ", out_file_);
DumpEncodedValue(init);
@@ -1331,11 +1304,8 @@
/*
* Dumps an instance field.
*/
-void DexLayout::DumpIField(uint32_t idx,
- uint32_t flags,
- uint32_t hiddenapi_flags,
- int i) {
- DumpSField(idx, flags, hiddenapi_flags, i, nullptr);
+void DexLayout::DumpIField(uint32_t idx, uint32_t flags, int i) {
+ DumpSField(idx, flags, i, nullptr);
}
/*
@@ -1461,7 +1431,6 @@
for (uint32_t i = 0; i < static_fields->size(); i++) {
DumpSField((*static_fields)[i].GetFieldId()->GetIndex(),
(*static_fields)[i].GetAccessFlags(),
- dex_ir::HiddenapiClassData::GetFlags(header_, class_def, &(*static_fields)[i]),
i,
i < encoded_values_size ? (*encoded_values)[i].get() : nullptr);
} // for
@@ -1478,7 +1447,6 @@
for (uint32_t i = 0; i < instance_fields->size(); i++) {
DumpIField((*instance_fields)[i].GetFieldId()->GetIndex(),
(*instance_fields)[i].GetAccessFlags(),
- dex_ir::HiddenapiClassData::GetFlags(header_, class_def, &(*instance_fields)[i]),
i);
} // for
}
@@ -1494,9 +1462,8 @@
for (uint32_t i = 0; i < direct_methods->size(); i++) {
DumpMethod((*direct_methods)[i].GetMethodId()->GetIndex(),
(*direct_methods)[i].GetAccessFlags(),
- dex_ir::HiddenapiClassData::GetFlags(header_, class_def, &(*direct_methods)[i]),
(*direct_methods)[i].GetCodeItem(),
- i);
+ i);
} // for
}
}
@@ -1511,7 +1478,6 @@
for (uint32_t i = 0; i < virtual_methods->size(); i++) {
DumpMethod((*virtual_methods)[i].GetMethodId()->GetIndex(),
(*virtual_methods)[i].GetAccessFlags(),
- dex_ir::HiddenapiClassData::GetFlags(header_, class_def, &(*virtual_methods)[i]),
(*virtual_methods)[i].GetCodeItem(),
i);
} // for
diff --git a/dexlayout/dexlayout.h b/dexlayout/dexlayout.h
index 6e006b7..2bca10d 100644
--- a/dexlayout/dexlayout.h
+++ b/dexlayout/dexlayout.h
@@ -148,7 +148,7 @@
void DumpEncodedAnnotation(dex_ir::EncodedAnnotation* annotation);
void DumpEncodedValue(const dex_ir::EncodedValue* data);
void DumpFileHeader();
- void DumpIField(uint32_t idx, uint32_t flags, uint32_t hiddenapi_flags, int i);
+ void DumpIField(uint32_t idx, uint32_t flags, int i);
void DumpInstruction(const dex_ir::CodeItem* code,
uint32_t code_offset,
uint32_t insn_idx,
@@ -156,17 +156,9 @@
const Instruction* dec_insn);
void DumpInterface(const dex_ir::TypeId* type_item, int i);
void DumpLocalInfo(const dex_ir::CodeItem* code);
- void DumpMethod(uint32_t idx,
- uint32_t flags,
- uint32_t hiddenapi_flags,
- const dex_ir::CodeItem* code,
- int i);
+ void DumpMethod(uint32_t idx, uint32_t flags, const dex_ir::CodeItem* code, int i);
void DumpPositionInfo(const dex_ir::CodeItem* code);
- void DumpSField(uint32_t idx,
- uint32_t flags,
- uint32_t hiddenapi_flags,
- int i,
- dex_ir::EncodedValue* init);
+ void DumpSField(uint32_t idx, uint32_t flags, int i, dex_ir::EncodedValue* init);
void DumpDexFile();
void LayoutClassDefsAndClassData(const DexFile* dex_file);
diff --git a/dexlist/dexlist.cc b/dexlist/dexlist.cc
index bdf3ca6..7d3ae71 100644
--- a/dexlist/dexlist.cc
+++ b/dexlist/dexlist.cc
@@ -146,7 +146,7 @@
dumpMethod(pDexFile,
fileName,
method.GetIndex(),
- method.GetAccessFlags(),
+ method.GetRawAccessFlags(),
method.GetCodeItem(),
method.GetCodeItemOffset());
}
diff --git a/libartbase/Android.bp b/libartbase/Android.bp
index 19f1532..0c6b1a2 100644
--- a/libartbase/Android.bp
+++ b/libartbase/Android.bp
@@ -40,6 +40,7 @@
"base/safe_copy.cc",
"base/scoped_arena_allocator.cc",
"base/scoped_flock.cc",
+ "base/socket_peer_is_trusted.cc",
"base/time_utils.cc",
"base/unix_file/fd_file.cc",
"base/unix_file/random_access_file_utils.cc",
diff --git a/libartbase/base/socket_peer_is_trusted.cc b/libartbase/base/socket_peer_is_trusted.cc
new file mode 100644
index 0000000..440054e
--- /dev/null
+++ b/libartbase/base/socket_peer_is_trusted.cc
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "socket_peer_is_trusted.h"
+
+#include <pwd.h>
+#include <sys/socket.h>
+
+#include <android-base/logging.h>
+
+namespace art {
+
+// Returns true if the user on the other end of the socket is root or shell.
+#ifdef ART_TARGET_ANDROID
+bool SocketPeerIsTrusted(int fd) {
+ ucred cr;
+ socklen_t cr_length = sizeof(cr);
+ if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_length) != 0) {
+ PLOG(ERROR) << "couldn't get socket credentials";
+ return false;
+ }
+
+ passwd* shell = getpwnam("shell");
+ if (cr.uid != 0 && cr.uid != shell->pw_uid) {
+ LOG(ERROR) << "untrusted uid " << cr.uid << " on other end of socket";
+ return false;
+ }
+
+ return true;
+}
+#else
+bool SocketPeerIsTrusted(int /* fd */) {
+ return true;
+}
+#endif
+
+} // namespace art
diff --git a/libartbase/base/socket_peer_is_trusted.h b/libartbase/base/socket_peer_is_trusted.h
new file mode 100644
index 0000000..4bbadd4
--- /dev/null
+++ b/libartbase/base/socket_peer_is_trusted.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_LIBARTBASE_BASE_SOCKET_PEER_IS_TRUSTED_H_
+#define ART_LIBARTBASE_BASE_SOCKET_PEER_IS_TRUSTED_H_
+
+namespace art {
+
+// Returns true if the user on the other end of the socket is root or shell.
+bool SocketPeerIsTrusted(int fd);
+
+} // namespace art
+
+#endif // ART_LIBARTBASE_BASE_SOCKET_PEER_IS_TRUSTED_H_
diff --git a/libdexfile/dex/class_accessor-inl.h b/libdexfile/dex/class_accessor-inl.h
index 40bca56..21db2cf 100644
--- a/libdexfile/dex/class_accessor-inl.h
+++ b/libdexfile/dex/class_accessor-inl.h
@@ -28,54 +28,34 @@
inline ClassAccessor::ClassAccessor(const ClassIteratorData& data)
: ClassAccessor(data.dex_file_, data.class_def_idx_) {}
-inline ClassAccessor::ClassAccessor(const DexFile& dex_file,
- const DexFile::ClassDef& class_def,
- bool parse_hiddenapi_class_data)
- : ClassAccessor(dex_file,
- dex_file.GetClassData(class_def),
- dex_file.GetIndexForClassDef(class_def),
- parse_hiddenapi_class_data) {}
+inline ClassAccessor::ClassAccessor(const DexFile& dex_file, const DexFile::ClassDef& class_def)
+ : ClassAccessor(dex_file, dex_file.GetIndexForClassDef(class_def)) {}
inline ClassAccessor::ClassAccessor(const DexFile& dex_file, uint32_t class_def_index)
- : ClassAccessor(dex_file, dex_file.GetClassDef(class_def_index)) {}
+ : ClassAccessor(dex_file,
+ dex_file.GetClassData(dex_file.GetClassDef(class_def_index)),
+ class_def_index) {}
inline ClassAccessor::ClassAccessor(const DexFile& dex_file,
const uint8_t* class_data,
- uint32_t class_def_index,
- bool parse_hiddenapi_class_data)
+ uint32_t class_def_index)
: dex_file_(dex_file),
class_def_index_(class_def_index),
ptr_pos_(class_data),
- hiddenapi_ptr_pos_(nullptr),
num_static_fields_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u),
num_instance_fields_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u),
num_direct_methods_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u),
- num_virtual_methods_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u) {
- if (parse_hiddenapi_class_data && class_def_index != DexFile::kDexNoIndex32) {
- const DexFile::HiddenapiClassData* hiddenapi_class_data = dex_file.GetHiddenapiClassData();
- if (hiddenapi_class_data != nullptr) {
- hiddenapi_ptr_pos_ = hiddenapi_class_data->GetFlagsPointer(class_def_index);
- }
- }
-}
+ num_virtual_methods_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u) {}
inline void ClassAccessor::Method::Read() {
index_ += DecodeUnsignedLeb128(&ptr_pos_);
access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
code_off_ = DecodeUnsignedLeb128(&ptr_pos_);
- if (hiddenapi_ptr_pos_ != nullptr) {
- hiddenapi_flags_ = DecodeUnsignedLeb128(&hiddenapi_ptr_pos_);
- DCHECK(HiddenApiAccessFlags::AreValidFlags(hiddenapi_flags_));
- }
}
inline void ClassAccessor::Field::Read() {
index_ += DecodeUnsignedLeb128(&ptr_pos_);
access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
- if (hiddenapi_ptr_pos_ != nullptr) {
- hiddenapi_flags_ = DecodeUnsignedLeb128(&hiddenapi_ptr_pos_);
- DCHECK(HiddenApiAccessFlags::AreValidFlags(hiddenapi_flags_));
- }
}
template <typename DataType, typename Visitor>
@@ -98,12 +78,12 @@
const InstanceFieldVisitor& instance_field_visitor,
const DirectMethodVisitor& direct_method_visitor,
const VirtualMethodVisitor& virtual_method_visitor) const {
- Field field(dex_file_, ptr_pos_, hiddenapi_ptr_pos_);
+ Field field(dex_file_, ptr_pos_);
VisitMembers(num_static_fields_, static_field_visitor, &field);
field.NextSection();
VisitMembers(num_instance_fields_, instance_field_visitor, &field);
- Method method(dex_file_, field.ptr_pos_, field.hiddenapi_ptr_pos_, /*is_static_or_direct*/ true);
+ Method method(dex_file_, field.ptr_pos_, /*is_static_or_direct*/ true);
VisitMembers(num_direct_methods_, direct_method_visitor, &method);
method.NextSection();
VisitMembers(num_virtual_methods_, virtual_method_visitor, &method);
@@ -151,43 +131,19 @@
inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>>
ClassAccessor::GetFieldsInternal(size_t count) const {
- return {
- DataIterator<Field>(dex_file_,
- 0u,
- num_static_fields_,
- count,
- ptr_pos_,
- hiddenapi_ptr_pos_),
- DataIterator<Field>(dex_file_,
- count,
- num_static_fields_,
- count,
- // The following pointers are bogus but unused in the `end` iterator.
- ptr_pos_,
- hiddenapi_ptr_pos_) };
+ return { DataIterator<Field>(dex_file_, 0u, num_static_fields_, count, ptr_pos_),
+ DataIterator<Field>(dex_file_, count, num_static_fields_, count, ptr_pos_) };
}
// Return an iteration range for the first <count> methods.
inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>>
ClassAccessor::GetMethodsInternal(size_t count) const {
// Skip over the fields.
- Field field(dex_file_, ptr_pos_, hiddenapi_ptr_pos_);
+ Field field(dex_file_, ptr_pos_);
VisitMembers(NumFields(), VoidFunctor(), &field);
// Return the iterator pair.
- return {
- DataIterator<Method>(dex_file_,
- 0u,
- num_direct_methods_,
- count,
- field.ptr_pos_,
- field.hiddenapi_ptr_pos_),
- DataIterator<Method>(dex_file_,
- count,
- num_direct_methods_,
- count,
- // The following pointers are bogus but unused in the `end` iterator.
- field.ptr_pos_,
- field.hiddenapi_ptr_pos_) };
+ return { DataIterator<Method>(dex_file_, 0u, num_direct_methods_, count, field.ptr_pos_),
+ DataIterator<Method>(dex_file_, count, num_direct_methods_, count, field.ptr_pos_) };
}
inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>> ClassAccessor::GetFields()
@@ -225,6 +181,14 @@
return { std::next(methods.begin(), NumDirectMethods()), methods.end() };
}
+inline void ClassAccessor::Field::UnHideAccessFlags() const {
+ DexFile::UnHideAccessFlags(const_cast<uint8_t*>(ptr_pos_), GetAccessFlags(), /*is_method*/ false);
+}
+
+inline void ClassAccessor::Method::UnHideAccessFlags() const {
+ DexFile::UnHideAccessFlags(const_cast<uint8_t*>(ptr_pos_), GetAccessFlags(), /*is_method*/ true);
+}
+
inline dex::TypeIndex ClassAccessor::GetClassIdx() const {
return dex_file_.GetClassDef(class_def_index_).class_idx_;
}
diff --git a/libdexfile/dex/class_accessor.h b/libdexfile/dex/class_accessor.h
index e9c1a82..d40577f 100644
--- a/libdexfile/dex/class_accessor.h
+++ b/libdexfile/dex/class_accessor.h
@@ -20,6 +20,7 @@
#include "base/utils.h"
#include "code_item_accessors.h"
#include "dex_file.h"
+#include "hidden_api_access_flags.h"
#include "invoke_type.h"
#include "method_reference.h"
#include "modifiers.h"
@@ -34,20 +35,22 @@
class BaseItem {
public:
explicit BaseItem(const DexFile& dex_file,
- const uint8_t* ptr_pos,
- const uint8_t* hiddenapi_ptr_pos)
- : dex_file_(dex_file), ptr_pos_(ptr_pos), hiddenapi_ptr_pos_(hiddenapi_ptr_pos) {}
+ const uint8_t* ptr_pos) : dex_file_(dex_file), ptr_pos_(ptr_pos) {}
uint32_t GetIndex() const {
return index_;
}
- uint32_t GetAccessFlags() const {
+ uint32_t GetRawAccessFlags() const {
return access_flags_;
}
- uint32_t GetHiddenapiFlags() const {
- return hiddenapi_flags_;
+ uint32_t GetAccessFlags() const {
+ return HiddenApiAccessFlags::RemoveFromDex(access_flags_);
+ }
+
+ HiddenApiAccessFlags::ApiList DecodeHiddenAccessFlags() const {
+ return HiddenApiAccessFlags::DecodeFromDex(access_flags_);
}
bool IsFinal() const {
@@ -63,21 +66,19 @@
}
bool MemberIsNative() const {
- return GetAccessFlags() & kAccNative;
+ return GetRawAccessFlags() & kAccNative;
}
bool MemberIsFinal() const {
- return GetAccessFlags() & kAccFinal;
+ return GetRawAccessFlags() & kAccFinal;
}
protected:
// Internal data pointer for reading.
const DexFile& dex_file_;
const uint8_t* ptr_pos_ = nullptr;
- const uint8_t* hiddenapi_ptr_pos_ = nullptr;
uint32_t index_ = 0u;
uint32_t access_flags_ = 0u;
- uint32_t hiddenapi_flags_ = 0u;
};
// A decoded version of the method of a class_data_item.
@@ -106,13 +107,14 @@
return is_static_or_direct_;
}
+ // Unhide the hidden API access flags at the iterator position. TODO: Deprecate.
+ void UnHideAccessFlags() const;
+
private:
- Method(const DexFile& dex_file,
- const uint8_t* ptr_pos,
- const uint8_t* hiddenapi_ptr_pos = nullptr,
- bool is_static_or_direct = true)
- : BaseItem(dex_file, ptr_pos, hiddenapi_ptr_pos),
- is_static_or_direct_(is_static_or_direct) {}
+ explicit Method(const DexFile& dex_file,
+ const uint8_t* ptr_pos,
+ bool is_static_or_direct = true)
+ : BaseItem(dex_file, ptr_pos), is_static_or_direct_(is_static_or_direct) {}
void Read();
@@ -148,15 +150,16 @@
// A decoded version of the field of a class_data_item.
class Field : public BaseItem {
public:
- Field(const DexFile& dex_file,
- const uint8_t* ptr_pos,
- const uint8_t* hiddenapi_ptr_pos = nullptr)
- : BaseItem(dex_file, ptr_pos, hiddenapi_ptr_pos) {}
+ explicit Field(const DexFile& dex_file,
+ const uint8_t* ptr_pos) : BaseItem(dex_file, ptr_pos) {}
bool IsStatic() const {
return is_static_;
}
+ // Unhide the hidden API access flags at the iterator position. TODO: Deprecate.
+ void UnHideAccessFlags() const;
+
private:
void Read();
@@ -182,9 +185,8 @@
uint32_t position,
uint32_t partition_pos,
uint32_t iterator_end,
- const uint8_t* ptr_pos,
- const uint8_t* hiddenapi_ptr_pos)
- : data_(dex_file, ptr_pos, hiddenapi_ptr_pos),
+ const uint8_t* ptr_pos)
+ : data_(dex_file, ptr_pos),
position_(position),
partition_pos_(partition_pos),
iterator_end_(iterator_end) {
@@ -266,16 +268,13 @@
// Not explicit specifically for range-based loops.
ALWAYS_INLINE ClassAccessor(const ClassIteratorData& data);
- ALWAYS_INLINE ClassAccessor(const DexFile& dex_file,
- const DexFile::ClassDef& class_def,
- bool parse_hiddenapi_class_data = false);
+ ALWAYS_INLINE ClassAccessor(const DexFile& dex_file, const DexFile::ClassDef& class_def);
ALWAYS_INLINE ClassAccessor(const DexFile& dex_file, uint32_t class_def_index);
ClassAccessor(const DexFile& dex_file,
const uint8_t* class_data,
- uint32_t class_def_index = DexFile::kDexNoIndex32,
- bool parse_hiddenapi_class_data = false);
+ uint32_t class_def_index = DexFile::kDexNoIndex32);
// Return the code item for a method.
const DexFile::CodeItem* GetCodeItem(const Method& method) const;
@@ -354,10 +353,6 @@
return ptr_pos_ != nullptr;
}
- bool HasHiddenapiClassData() const {
- return hiddenapi_ptr_pos_ != nullptr;
- }
-
uint32_t GetClassDefIndex() const {
return class_def_index_;
}
@@ -382,7 +377,6 @@
const DexFile& dex_file_;
const uint32_t class_def_index_;
const uint8_t* ptr_pos_ = nullptr; // Pointer into stream of class_data_item.
- const uint8_t* hiddenapi_ptr_pos_ = nullptr; // Pointer into stream of hiddenapi_metadata.
const uint32_t num_static_fields_ = 0u;
const uint32_t num_instance_fields_ = 0u;
const uint32_t num_direct_methods_ = 0u;
diff --git a/libdexfile/dex/dex_file.cc b/libdexfile/dex/dex_file.cc
index 7ccb9c0..48f38ca 100644
--- a/libdexfile/dex/dex_file.cc
+++ b/libdexfile/dex/dex_file.cc
@@ -46,6 +46,31 @@
static_assert(sizeof(dex::TypeIndex) == sizeof(uint16_t), "TypeIndex size is wrong");
static_assert(std::is_trivially_copyable<dex::TypeIndex>::value, "TypeIndex not trivial");
+void DexFile::UnHideAccessFlags(uint8_t* data_ptr,
+ uint32_t new_access_flags,
+ bool is_method) {
+ // Go back 1 uleb to start.
+ data_ptr = ReverseSearchUnsignedLeb128(data_ptr);
+ if (is_method) {
+ // Methods have another uleb field before the access flags
+ data_ptr = ReverseSearchUnsignedLeb128(data_ptr);
+ }
+ DCHECK_EQ(HiddenApiAccessFlags::RemoveFromDex(DecodeUnsignedLeb128WithoutMovingCursor(data_ptr)),
+ new_access_flags);
+ UpdateUnsignedLeb128(data_ptr, new_access_flags);
+}
+
+void DexFile::UnhideApis() const {
+ for (ClassAccessor accessor : GetClasses()) {
+ for (const ClassAccessor::Field& field : accessor.GetFields()) {
+ field.UnHideAccessFlags();
+ }
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
+ method.UnHideAccessFlags();
+ }
+ }
+}
+
uint32_t DexFile::CalculateChecksum() const {
return CalculateChecksum(Begin(), Size());
}
@@ -105,7 +130,6 @@
num_method_handles_(0),
call_site_ids_(nullptr),
num_call_site_ids_(0),
- hiddenapi_class_data_(nullptr),
oat_dex_file_(oat_dex_file),
container_(std::move(container)),
is_compact_dex_(is_compact_dex),
@@ -181,11 +205,6 @@
} else if (map_item.type_ == kDexTypeCallSiteIdItem) {
call_site_ids_ = reinterpret_cast<const CallSiteIdItem*>(Begin() + map_item.offset_);
num_call_site_ids_ = map_item.size_;
- } else if (map_item.type_ == kDexTypeHiddenapiClassData) {
- hiddenapi_class_data_ = GetHiddenapiClassDataAtOffset(map_item.offset_);
- } else {
- // Pointers to other sections are not necessary to retain in the DexFile struct.
- // Other items have pointers directly into their data.
}
}
}
diff --git a/libdexfile/dex/dex_file.h b/libdexfile/dex/dex_file.h
index 6a52f67..30d8b6d 100644
--- a/libdexfile/dex/dex_file.h
+++ b/libdexfile/dex/dex_file.h
@@ -92,7 +92,7 @@
uint32_t endian_tag_ = 0;
uint32_t link_size_ = 0; // unused
uint32_t link_off_ = 0; // unused
- uint32_t map_off_ = 0; // map list offset from data_off_
+ uint32_t map_off_ = 0; // unused
uint32_t string_ids_size_ = 0; // number of StringIds
uint32_t string_ids_off_ = 0; // file offset of StringIds array
uint32_t type_ids_size_ = 0; // number of TypeIds, we don't support more than 65535
@@ -134,7 +134,6 @@
kDexTypeAnnotationItem = 0x2004,
kDexTypeEncodedArrayItem = 0x2005,
kDexTypeAnnotationsDirectoryItem = 0x2006,
- kDexTypeHiddenapiClassData = 0xF000,
};
struct MapItem {
@@ -148,8 +147,6 @@
uint32_t size_;
MapItem list_[1];
- size_t Size() const { return sizeof(uint32_t) + (size_ * sizeof(MapItem)); }
-
private:
DISALLOW_COPY_AND_ASSIGN(MapList);
};
@@ -422,27 +419,6 @@
DISALLOW_COPY_AND_ASSIGN(AnnotationItem);
};
- struct HiddenapiClassData {
- uint32_t size_; // total size of the item
- uint32_t flags_offset_[1]; // array of offsets from the beginning of this item,
- // indexed by class def index
-
- // Returns a pointer to the beginning of a uleb128-stream of hiddenapi
- // flags for a class def of given index. Values are in the same order
- // as fields/methods in the class data. Returns null if the class does
- // not have class data.
- const uint8_t* GetFlagsPointer(uint32_t class_def_idx) const {
- if (flags_offset_[class_def_idx] == 0) {
- return nullptr;
- } else {
- return reinterpret_cast<const uint8_t*>(this) + flags_offset_[class_def_idx];
- }
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(HiddenapiClassData);
- };
-
enum AnnotationResultStyle { // private
kAllObjects,
kPrimitivesOrObjects,
@@ -861,14 +837,6 @@
return DataPointer<AnnotationItem>(offset);
}
- ALWAYS_INLINE const HiddenapiClassData* GetHiddenapiClassDataAtOffset(uint32_t offset) const {
- return DataPointer<HiddenapiClassData>(offset);
- }
-
- ALWAYS_INLINE const HiddenapiClassData* GetHiddenapiClassData() const {
- return hiddenapi_class_data_;
- }
-
const AnnotationItem* GetAnnotationItem(const AnnotationSetItem* set_item, uint32_t index) const {
DCHECK_LE(index, set_item->size_);
return GetAnnotationItemAtOffset(set_item->entries_[index]);
@@ -1024,6 +992,12 @@
return container_.get();
}
+ // Changes the dex class data pointed to by data_ptr it to not have any hiddenapi flags.
+ static void UnHideAccessFlags(uint8_t* data_ptr, uint32_t new_access_flags, bool is_method);
+
+ // Iterate dex classes and remove hiddenapi flags in fields and methods.
+ void UnhideApis() const;
+
IterationRange<ClassIterator> GetClasses() const;
template <typename Visitor>
@@ -1106,10 +1080,6 @@
// Number of elements in the call sites list.
size_t num_call_site_ids_;
- // Points to the base of the hiddenapi class data item_, or nullptr if the dex
- // file does not have one.
- const HiddenapiClassData* hiddenapi_class_data_;
-
// If this dex file was loaded from an oat file, oat_dex_file_ contains a
// pointer to the OatDexFile it was loaded from. Otherwise oat_dex_file_ is
// null.
diff --git a/libdexfile/dex/dex_file_verifier.cc b/libdexfile/dex/dex_file_verifier.cc
index 43471c3..499a89b 100644
--- a/libdexfile/dex/dex_file_verifier.cc
+++ b/libdexfile/dex/dex_file_verifier.cc
@@ -67,7 +67,6 @@
case DexFile::kDexTypeAnnotationItem: return 1 << 17;
case DexFile::kDexTypeEncodedArrayItem: return 1 << 18;
case DexFile::kDexTypeAnnotationsDirectoryItem: return 1 << 19;
- case DexFile::kDexTypeHiddenapiClassData: return 1 << 20;
}
return 0;
}
@@ -95,7 +94,6 @@
case DexFile::kDexTypeAnnotationItem:
case DexFile::kDexTypeEncodedArrayItem:
case DexFile::kDexTypeAnnotationsDirectoryItem:
- case DexFile::kDexTypeHiddenapiClassData:
return true;
}
return true;
@@ -1098,7 +1096,7 @@
return false;
}
if (!CheckClassDataItemField(curr_index,
- field->GetAccessFlags(),
+ field->GetRawAccessFlags(),
(*class_def)->access_flags_,
*class_type_index,
kStatic)) {
@@ -1149,7 +1147,7 @@
return false;
}
if (!CheckClassDataItemMethod(curr_index,
- method->GetAccessFlags(),
+ method->GetRawAccessFlags(),
(*class_def)->access_flags_,
*class_type_index,
method->GetCodeItemOffset(),
@@ -1557,107 +1555,6 @@
return true;
}
-bool DexFileVerifier::CheckIntraHiddenapiClassData() {
- const DexFile::HiddenapiClassData* item =
- reinterpret_cast<const DexFile::HiddenapiClassData*>(ptr_);
-
- // Check expected header size.
- uint32_t num_header_elems = dex_file_->NumClassDefs() + 1;
- uint32_t elem_size = sizeof(uint32_t);
- uint32_t header_size = num_header_elems * elem_size;
- if (!CheckListSize(item, num_header_elems, elem_size, "hiddenapi class data section header")) {
- return false;
- }
-
- // Check total size.
- if (!CheckListSize(item, item->size_, 1u, "hiddenapi class data section")) {
- return false;
- }
-
- // Check that total size can fit header.
- if (item->size_ < header_size) {
- ErrorStringPrintf(
- "Hiddenapi class data too short to store header (%u < %u)", item->size_, header_size);
- return false;
- }
-
- const uint8_t* data_end = ptr_ + item->size_;
- ptr_ += header_size;
-
- // Check offsets for each class def.
- for (uint32_t i = 0; i < dex_file_->NumClassDefs(); ++i) {
- const DexFile::ClassDef& class_def = dex_file_->GetClassDef(i);
- const uint8_t* class_data = dex_file_->GetClassData(class_def);
- uint32_t offset = item->flags_offset_[i];
-
- if (offset == 0) {
- continue;
- }
-
- // Check that class defs with no class data do not have any hiddenapi class data.
- if (class_data == nullptr) {
- ErrorStringPrintf(
- "Hiddenapi class data offset not zero for class def %u with no class data", i);
- return false;
- }
-
- // Check that the offset is within the section.
- if (offset > item->size_) {
- ErrorStringPrintf(
- "Hiddenapi class data offset out of section bounds (%u > %u) for class def %u",
- offset, item->size_, i);
- return false;
- }
-
- // Check that the offset matches current pointer position. We do not allow
- // offsets into already parsed data, or gaps between class def data.
- uint32_t ptr_offset = ptr_ - reinterpret_cast<const uint8_t*>(item);
- if (offset != ptr_offset) {
- ErrorStringPrintf(
- "Hiddenapi class data unexpected offset (%u != %u) for class def %u",
- offset, ptr_offset, i);
- return false;
- }
-
- // Parse a uleb128 value for each field and method of this class.
- bool failure = false;
- auto fn_member = [&](const ClassAccessor::BaseItem& member, const char* member_type) {
- if (failure) {
- return;
- }
- uint32_t decoded_flags;
- if (!DecodeUnsignedLeb128Checked(&ptr_, data_end, &decoded_flags)) {
- ErrorStringPrintf("Hiddenapi class data value out of bounds (%p > %p) for %s %i",
- ptr_, data_end, member_type, member.GetIndex());
- failure = true;
- return;
- }
- if (!HiddenApiAccessFlags::AreValidFlags(decoded_flags)) {
- ErrorStringPrintf("Hiddenapi class data flags invalid (%u) for %s %i",
- decoded_flags, member_type, member.GetIndex());
- failure = true;
- return;
- }
- };
- auto fn_field = [&](const ClassAccessor::Field& field) { fn_member(field, "field"); };
- auto fn_method = [&](const ClassAccessor::Method& method) { fn_member(method, "method"); };
- ClassAccessor accessor(*dex_file_, class_data);
- accessor.VisitFieldsAndMethods(fn_field, fn_field, fn_method, fn_method);
- if (failure) {
- return false;
- }
- }
-
- if (ptr_ != data_end) {
- ErrorStringPrintf("Hiddenapi class data wrong reported size (%u != %u)",
- static_cast<uint32_t>(ptr_ - reinterpret_cast<const uint8_t*>(item)),
- item->size_);
- return false;
- }
-
- return true;
-}
-
bool DexFileVerifier::CheckIntraAnnotationsDirectoryItem() {
const DexFile::AnnotationsDirectoryItem* item =
reinterpret_cast<const DexFile::AnnotationsDirectoryItem*>(ptr_);
@@ -1872,12 +1769,6 @@
}
break;
}
- case DexFile::kDexTypeHiddenapiClassData: {
- if (!CheckIntraHiddenapiClassData()) {
- return false;
- }
- break;
- }
case DexFile::kDexTypeHeaderItem:
case DexFile::kDexTypeMapList:
break;
@@ -2082,7 +1973,6 @@
CHECK_INTRA_DATA_SECTION_CASE(DexFile::kDexTypeAnnotationItem)
CHECK_INTRA_DATA_SECTION_CASE(DexFile::kDexTypeEncodedArrayItem)
CHECK_INTRA_DATA_SECTION_CASE(DexFile::kDexTypeAnnotationsDirectoryItem)
- CHECK_INTRA_DATA_SECTION_CASE(DexFile::kDexTypeHiddenapiClassData)
#undef CHECK_INTRA_DATA_SECTION_CASE
}
@@ -2846,7 +2736,6 @@
case DexFile::kDexTypeDebugInfoItem:
case DexFile::kDexTypeAnnotationItem:
case DexFile::kDexTypeEncodedArrayItem:
- case DexFile::kDexTypeHiddenapiClassData:
break;
case DexFile::kDexTypeStringIdItem: {
if (!CheckInterStringIdItem()) {
@@ -2979,8 +2868,7 @@
case DexFile::kDexTypeAnnotationSetRefList:
case DexFile::kDexTypeAnnotationSetItem:
case DexFile::kDexTypeClassDataItem:
- case DexFile::kDexTypeAnnotationsDirectoryItem:
- case DexFile::kDexTypeHiddenapiClassData: {
+ case DexFile::kDexTypeAnnotationsDirectoryItem: {
if (!CheckInterSectionIterate(section_offset, section_count, type)) {
return false;
}
diff --git a/libdexfile/dex/dex_file_verifier.h b/libdexfile/dex/dex_file_verifier.h
index a81df48..79ddea4 100644
--- a/libdexfile/dex/dex_file_verifier.h
+++ b/libdexfile/dex/dex_file_verifier.h
@@ -126,7 +126,6 @@
bool CheckIntraDebugInfoItem();
bool CheckIntraAnnotationItem();
bool CheckIntraAnnotationsDirectoryItem();
- bool CheckIntraHiddenapiClassData();
template <DexFile::MapItemType kType>
bool CheckIntraSectionIterate(size_t offset, uint32_t count);
diff --git a/libdexfile/dex/hidden_api_access_flags.h b/libdexfile/dex/hidden_api_access_flags.h
index 837056b..369615d 100644
--- a/libdexfile/dex/hidden_api_access_flags.h
+++ b/libdexfile/dex/hidden_api_access_flags.h
@@ -28,14 +28,31 @@
* of information on whether the given class member should be hidden from apps
* and under what circumstances.
*
- * Two bits are encoded for each class member in the HiddenapiClassData item,
- * stored in a stream of uleb128-encoded values for each ClassDef item.
- * The two bits correspond to values in the ApiList enum below.
+ * The encoding is different inside DexFile, where we are concerned with size,
+ * and at runtime where we want to optimize for speed of access. The class
+ * provides helper functions to decode/encode both of them.
*
- * At runtime, two bits are set aside in the uint32_t access flags in the
- * intrinsics ordinal space (thus intrinsics need to be special-cased). These are
- * two consecutive bits and they are directly used to store the integer value of
- * the ApiList enum values.
+ * Encoding in DexFile
+ * ===================
+ *
+ * First bit is encoded as inversion of visibility flags (public/private/protected).
+ * At most one can be set for any given class member. If two or three are set,
+ * this is interpreted as the first bit being set and actual visibility flags
+ * being the complement of the encoded flags.
+ *
+ * Second bit is either encoded as bit 5 for fields and non-native methods, where
+ * it carries no other meaning. If a method is native (bit 8 set), bit 9 is used.
+ *
+ * Bits were selected so that they never increase the length of unsigned LEB-128
+ * encoding of the access flags.
+ *
+ * Encoding at runtime
+ * ===================
+ *
+ * Two bits are set aside in the uint32_t access flags in the intrinsics ordinal
+ * space (thus intrinsics need to be special-cased). These are two consecutive
+ * bits and they are directly used to store the integer value of the ApiList
+ * enum values.
*
*/
class HiddenApiAccessFlags {
@@ -48,6 +65,27 @@
kNoList,
};
+ static ALWAYS_INLINE ApiList DecodeFromDex(uint32_t dex_access_flags) {
+ DexHiddenAccessFlags flags(dex_access_flags);
+ uint32_t int_value = (flags.IsFirstBitSet() ? 1 : 0) + (flags.IsSecondBitSet() ? 2 : 0);
+ return static_cast<ApiList>(int_value);
+ }
+
+ static ALWAYS_INLINE uint32_t RemoveFromDex(uint32_t dex_access_flags) {
+ DexHiddenAccessFlags flags(dex_access_flags);
+ flags.SetFirstBit(false);
+ flags.SetSecondBit(false);
+ return flags.GetEncoding();
+ }
+
+ static ALWAYS_INLINE uint32_t EncodeForDex(uint32_t dex_access_flags, ApiList value) {
+ DexHiddenAccessFlags flags(RemoveFromDex(dex_access_flags));
+ uint32_t int_value = static_cast<uint32_t>(value);
+ flags.SetFirstBit((int_value & 1) != 0);
+ flags.SetSecondBit((int_value & 2) != 0);
+ return flags.GetEncoding();
+ }
+
static ALWAYS_INLINE ApiList DecodeFromRuntime(uint32_t runtime_access_flags) {
// This is used in the fast path, only DCHECK here.
DCHECK_EQ(runtime_access_flags & kAccIntrinsic, 0u);
@@ -65,14 +103,47 @@
return runtime_access_flags | hidden_api_flags;
}
- static ALWAYS_INLINE bool AreValidFlags(uint32_t flags) {
- return flags <= static_cast<uint32_t>(kBlacklist);
- }
-
private:
static const int kAccFlagsShift = CTZ(kAccHiddenApiBits);
static_assert(IsPowerOfTwo((kAccHiddenApiBits >> kAccFlagsShift) + 1),
"kAccHiddenApiBits are not continuous");
+
+ struct DexHiddenAccessFlags {
+ explicit DexHiddenAccessFlags(uint32_t access_flags) : access_flags_(access_flags) {}
+
+ ALWAYS_INLINE uint32_t GetSecondFlag() {
+ return ((access_flags_ & kAccNative) != 0) ? kAccDexHiddenBitNative : kAccDexHiddenBit;
+ }
+
+ ALWAYS_INLINE bool IsFirstBitSet() {
+ static_assert(IsPowerOfTwo(0u), "Following statement checks if *at most* one bit is set");
+ return !IsPowerOfTwo(access_flags_ & kAccVisibilityFlags);
+ }
+
+ ALWAYS_INLINE void SetFirstBit(bool value) {
+ if (IsFirstBitSet() != value) {
+ access_flags_ ^= kAccVisibilityFlags;
+ }
+ }
+
+ ALWAYS_INLINE bool IsSecondBitSet() {
+ return (access_flags_ & GetSecondFlag()) != 0;
+ }
+
+ ALWAYS_INLINE void SetSecondBit(bool value) {
+ if (value) {
+ access_flags_ |= GetSecondFlag();
+ } else {
+ access_flags_ &= ~GetSecondFlag();
+ }
+ }
+
+ ALWAYS_INLINE uint32_t GetEncoding() const {
+ return access_flags_;
+ }
+
+ uint32_t access_flags_;
+ };
};
inline std::ostream& operator<<(std::ostream& os, HiddenApiAccessFlags::ApiList value) {
diff --git a/libdexfile/dex/modifiers.h b/libdexfile/dex/modifiers.h
index 018b141..38f8455 100644
--- a/libdexfile/dex/modifiers.h
+++ b/libdexfile/dex/modifiers.h
@@ -42,6 +42,11 @@
static constexpr uint32_t kAccJavaFlagsMask = 0xffff; // bits set from Java sources (low 16)
+// The following flags are used to insert hidden API access flags into boot class path dex files.
+// They are decoded by ClassAccessor and removed from the access flags before used by the runtime.
+static constexpr uint32_t kAccDexHiddenBit = 0x00000020; // field, method (not native)
+static constexpr uint32_t kAccDexHiddenBitNative = 0x00000200; // method (native)
+
static constexpr uint32_t kAccConstructor = 0x00010000; // method (dex only) <(cl)init>
static constexpr uint32_t kAccDeclaredSynchronized = 0x00020000; // method (dex only)
static constexpr uint32_t kAccClassIsProxy = 0x00040000; // class (dex only)
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 358b7ba..86a36f2 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -628,6 +628,9 @@
CHECK(oat_dex_file != nullptr);
CHECK(vdex_dex_file != nullptr);
+ // Remove hiddenapis
+ vdex_dex_file->UnhideApis();
+
// If a CompactDex file is detected within a Vdex container, DexLayout is used to convert
// back to a StandardDex file. Since the converted DexFile will most likely not reproduce
// the original input Dex file, the `update_checksum_` option is used to recompute the
@@ -1075,7 +1078,7 @@
dex_file,
method.GetIndex(),
method.GetCodeItem(),
- method.GetAccessFlags(),
+ method.GetRawAccessFlags(),
&addr_found)) {
success = false;
}
diff --git a/openjdkjvmti/fixed_up_dex_file.cc b/openjdkjvmti/fixed_up_dex_file.cc
index eb93fc9..6745d91 100644
--- a/openjdkjvmti/fixed_up_dex_file.cc
+++ b/openjdkjvmti/fixed_up_dex_file.cc
@@ -71,6 +71,7 @@
original_dex_file,
/* decompile_return_instruction= */ true);
}
+ new_dex_file.UnhideApis();
}
static void DCheckVerifyDexFile(const art::DexFile& dex) {
diff --git a/runtime/Android.bp b/runtime/Android.bp
index 5d99187..86ee952 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -392,7 +392,7 @@
"libbacktrace",
"liblz4",
"liblog",
- // For atrace, properties, ashmem, set_sched_policy and socket_peer_is_trusted.
+ // For atrace, properties, ashmem, set_sched_policy.
"libcutils",
// For common macros.
"libbase",
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 0247e4e..e240167 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -3277,9 +3277,7 @@
const DexFile& dex_file,
const DexFile::ClassDef& dex_class_def,
Handle<mirror::Class> klass) {
- ClassAccessor accessor(dex_file,
- dex_class_def,
- /* parse_hiddenapi_class_data= */ klass->IsBootStrapClassLoaded());
+ ClassAccessor accessor(dex_file, dex_class_def);
if (!accessor.HasClassData()) {
return;
}
@@ -3395,8 +3393,8 @@
// also set its runtime hidden API access flags.
uint32_t access_flags = field.GetAccessFlags();
if (klass->IsBootStrapClassLoaded()) {
- access_flags = HiddenApiAccessFlags::EncodeForRuntime(
- access_flags, static_cast<HiddenApiAccessFlags::ApiList>(field.GetHiddenapiFlags()));
+ access_flags =
+ HiddenApiAccessFlags::EncodeForRuntime(access_flags, field.DecodeHiddenAccessFlags());
}
dst->SetAccessFlags(access_flags);
}
@@ -3417,9 +3415,10 @@
// Get access flags from the DexFile. If this is a boot class path class,
// also set its runtime hidden API access flags.
uint32_t access_flags = method.GetAccessFlags();
+
if (klass->IsBootStrapClassLoaded()) {
- access_flags = HiddenApiAccessFlags::EncodeForRuntime(
- access_flags, static_cast<HiddenApiAccessFlags::ApiList>(method.GetHiddenapiFlags()));
+ access_flags =
+ HiddenApiAccessFlags::EncodeForRuntime(access_flags, method.DecodeHiddenAccessFlags());
}
if (UNLIKELY(strcmp("finalize", method_name) == 0)) {
diff --git a/runtime/gc/allocation_record.cc b/runtime/gc/allocation_record.cc
index b9c1dc6..e11fa5c 100644
--- a/runtime/gc/allocation_record.cc
+++ b/runtime/gc/allocation_record.cc
@@ -24,9 +24,7 @@
#include "object_callbacks.h"
#include "stack.h"
-#ifdef ART_TARGET_ANDROID
-#include "cutils/properties.h"
-#endif
+#include <android-base/properties.h>
namespace art {
namespace gc {
@@ -45,10 +43,10 @@
#ifdef ART_TARGET_ANDROID
// Check whether there's a system property overriding the max number of records.
const char* propertyName = "dalvik.vm.allocTrackerMax";
- char allocMaxString[PROPERTY_VALUE_MAX];
- if (property_get(propertyName, allocMaxString, "") > 0) {
+ std::string allocMaxString = android::base::GetProperty(propertyName, "");
+ if (!allocMaxString.empty()) {
char* end;
- size_t value = strtoul(allocMaxString, &end, 10);
+ size_t value = strtoul(allocMaxString.c_str(), &end, 10);
if (*end != '\0') {
LOG(ERROR) << "Ignoring " << propertyName << " '" << allocMaxString
<< "' --- invalid";
@@ -61,10 +59,10 @@
}
// Check whether there's a system property overriding the number of recent records.
propertyName = "dalvik.vm.recentAllocMax";
- char recentAllocMaxString[PROPERTY_VALUE_MAX];
- if (property_get(propertyName, recentAllocMaxString, "") > 0) {
+ std::string recentAllocMaxString = android::base::GetProperty(propertyName, "");
+ if (!recentAllocMaxString.empty()) {
char* end;
- size_t value = strtoul(recentAllocMaxString, &end, 10);
+ size_t value = strtoul(recentAllocMaxString.c_str(), &end, 10);
if (*end != '\0') {
LOG(ERROR) << "Ignoring " << propertyName << " '" << recentAllocMaxString
<< "' --- invalid";
@@ -77,10 +75,10 @@
}
// Check whether there's a system property overriding the max depth of stack trace.
propertyName = "debug.allocTracker.stackDepth";
- char stackDepthString[PROPERTY_VALUE_MAX];
- if (property_get(propertyName, stackDepthString, "") > 0) {
+ std::string stackDepthString = android::base::GetProperty(propertyName, "");
+ if (!stackDepthString.empty()) {
char* end;
- size_t value = strtoul(stackDepthString, &end, 10);
+ size_t value = strtoul(stackDepthString.c_str(), &end, 10);
if (*end != '\0') {
LOG(ERROR) << "Ignoring " << propertyName << " '" << stackDepthString
<< "' --- invalid";
diff --git a/runtime/jdwp/jdwp_adb.cc b/runtime/jdwp/jdwp_adb.cc
index 9245f1e..d64f11f 100644
--- a/runtime/jdwp/jdwp_adb.cc
+++ b/runtime/jdwp/jdwp_adb.cc
@@ -23,13 +23,10 @@
#include "android-base/stringprintf.h"
#include "base/logging.h" // For VLOG.
+#include "base/socket_peer_is_trusted.h"
#include "jdwp/jdwp_priv.h"
#include "thread-current-inl.h"
-#ifdef ART_TARGET_ANDROID
-#include "cutils/sockets.h"
-#endif
-
/*
* The JDWP <-> ADB transport protocol is explained in detail
* in system/core/adb/jdwp_service.c. Here's a summary.
@@ -265,7 +262,7 @@
if (!ret) {
int control_sock = ControlSock();
#ifdef ART_TARGET_ANDROID
- if (control_sock < 0 || !socket_peer_is_trusted(control_sock)) {
+ if (control_sock < 0 || !art::SocketPeerIsTrusted(control_sock)) {
if (control_sock >= 0 && shutdown(control_sock, SHUT_RDWR)) {
PLOG(ERROR) << "trouble shutting down socket";
}
diff --git a/test/etc/default-build b/test/etc/default-build
index 3e6699a..8542ad0 100755
--- a/test/etc/default-build
+++ b/test/etc/default-build
@@ -323,8 +323,7 @@
function make_hiddenapi() {
local args=( "encode" )
while [[ $# -gt 0 ]]; do
- args+=("--input-dex=$1")
- args+=("--output-dex=$1")
+ args+=("--dex=$1")
shift
done
if [ -f api-light-greylist.txt ]; then
diff --git a/tools/hiddenapi/hiddenapi.cc b/tools/hiddenapi/hiddenapi.cc
index 06bea1a..68211a1 100644
--- a/tools/hiddenapi/hiddenapi.cc
+++ b/tools/hiddenapi/hiddenapi.cc
@@ -22,8 +22,6 @@
#include "android-base/stringprintf.h"
#include "android-base/strings.h"
-#include "base/bit_utils.h"
-#include "base/stl_util.h"
#include "base/mem_map.h"
#include "base/os.h"
#include "base/unix_file/fd_file.h"
@@ -68,9 +66,8 @@
UsageError("Usage: hiddenapi [command_name] [options]...");
UsageError("");
UsageError(" Command \"encode\": encode API list membership in boot dex files");
- UsageError(" --input-dex=<filename>: dex file which belongs to boot class path");
- UsageError(" --output-dex=<filename>: file to write encoded dex into");
- UsageError(" input and output dex files are paired in order of appearance");
+ UsageError(" --dex=<filename>: dex file which belongs to boot class path,");
+ UsageError(" the file will be overwritten");
UsageError("");
UsageError(" --light-greylist=<filename>:");
UsageError(" --dark-greylist=<filename>:");
@@ -150,6 +147,30 @@
inline const DexClass& GetDeclaringClass() const { return klass_; }
+ // Sets hidden bits in access flags and writes them back into the DEX in memory.
+ // Note that this will not update the cached data of the class accessor
+ // until it iterates over this item again and therefore will fail a CHECK if
+ // it is called multiple times on the same DexMember.
+ void SetHidden(HiddenApiAccessFlags::ApiList value) const {
+ const uint32_t old_flags = item_.GetRawAccessFlags();
+ const uint32_t new_flags = HiddenApiAccessFlags::EncodeForDex(old_flags, value);
+ CHECK_EQ(UnsignedLeb128Size(new_flags), UnsignedLeb128Size(old_flags));
+
+ // Locate the LEB128-encoded access flags in class data.
+ // `ptr` initially points to the next ClassData item. We iterate backwards
+ // until we hit the terminating byte of the previous Leb128 value.
+ const uint8_t* ptr = item_.GetDataPointer();
+ if (IsMethod()) {
+ ptr = ReverseSearchUnsignedLeb128(ptr);
+ DCHECK_EQ(DecodeUnsignedLeb128WithoutMovingCursor(ptr), GetMethod().GetCodeItemOffset());
+ }
+ ptr = ReverseSearchUnsignedLeb128(ptr);
+ DCHECK_EQ(DecodeUnsignedLeb128WithoutMovingCursor(ptr), old_flags);
+
+ // Overwrite the access flags.
+ UpdateUnsignedLeb128(const_cast<uint8_t*>(ptr), new_flags);
+ }
+
inline bool IsMethod() const { return is_method_; }
inline bool IsVirtualMethod() const { return IsMethod() && !GetMethod().IsStaticOrDirect(); }
inline bool IsConstructor() const { return IsMethod() && HasAccessFlags(kAccConstructor); }
@@ -241,10 +262,6 @@
});
}
- std::vector<const DexFile*> GetDexFiles() const {
- return MakeNonOwningPointerVector(dex_files_);
- }
-
void UpdateDexChecksums() {
for (auto& dex_file : dex_files_) {
// Obtain a writeable pointer to the dex header.
@@ -542,316 +559,6 @@
std::map<std::string, HierarchyClass> classes_;
};
-// Builder of dex section containing hiddenapi flags.
-class HiddenapiClassDataBuilder final {
- public:
- explicit HiddenapiClassDataBuilder(const DexFile& dex_file)
- : num_classdefs_(dex_file.NumClassDefs()),
- next_class_def_idx_(0u),
- class_def_has_non_zero_flags_(false),
- dex_file_has_non_zero_flags_(false),
- data_(sizeof(uint32_t) * (num_classdefs_ + 1), 0u) {
- *GetSizeField() = GetCurrentDataSize();
- }
-
- // Notify the builder that new flags for the next class def
- // will be written now. The builder records the current offset
- // into the header.
- void BeginClassDef(uint32_t idx) {
- CHECK_EQ(next_class_def_idx_, idx);
- CHECK_LT(idx, num_classdefs_);
- GetOffsetArray()[idx] = GetCurrentDataSize();
- class_def_has_non_zero_flags_ = false;
- }
-
- // Notify the builder that all flags for this class def have been
- // written. The builder updates the total size of the data struct
- // and may set offset for class def in header to zero if no data
- // has been written.
- void EndClassDef(uint32_t idx) {
- CHECK_EQ(next_class_def_idx_, idx);
- CHECK_LT(idx, num_classdefs_);
-
- ++next_class_def_idx_;
-
- if (!class_def_has_non_zero_flags_) {
- // No need to store flags for this class. Remove the written flags
- // and set offset in header to zero.
- data_.resize(GetOffsetArray()[idx]);
- GetOffsetArray()[idx] = 0u;
- }
-
- dex_file_has_non_zero_flags_ |= class_def_has_non_zero_flags_;
-
- if (idx == num_classdefs_ - 1) {
- if (dex_file_has_non_zero_flags_) {
- // This was the last class def and we have generated non-zero hiddenapi
- // flags. Update total size in the header.
- *GetSizeField() = GetCurrentDataSize();
- } else {
- // This was the last class def and we have not generated any non-zero
- // hiddenapi flags. Clear all the data.
- data_.clear();
- }
- }
- }
-
- // Append flags at the end of the data struct. This should be called
- // between BeginClassDef and EndClassDef in the order of appearance of
- // fields/methods in the class data stream.
- void WriteFlags(uint32_t flags) {
- EncodeUnsignedLeb128(&data_, flags);
- class_def_has_non_zero_flags_ |= (flags != 0u);
- }
-
- // Return backing data, assuming that all flags have been written.
- const std::vector<uint8_t>& GetData() const {
- CHECK_EQ(next_class_def_idx_, num_classdefs_) << "Incomplete data";
- return data_;
- }
-
- private:
- // Returns pointer to the size field in the header of this dex section.
- uint32_t* GetSizeField() {
- // Assume malloc() aligns allocated memory to at least uint32_t.
- CHECK(IsAligned<sizeof(uint32_t)>(data_.data()));
- return reinterpret_cast<uint32_t*>(data_.data());
- }
-
- // Returns pointer to array of offsets (indexed by class def indices) in the
- // header of this dex section.
- uint32_t* GetOffsetArray() { return &GetSizeField()[1]; }
- uint32_t GetCurrentDataSize() const { return data_.size(); }
-
- // Number of class defs in this dex file.
- const uint32_t num_classdefs_;
-
- // Next expected class def index.
- uint32_t next_class_def_idx_;
-
- // Whether non-zero flags have been encountered for this class def.
- bool class_def_has_non_zero_flags_;
-
- // Whether any non-zero flags have been encountered for this dex file.
- bool dex_file_has_non_zero_flags_;
-
- // Vector containing the data of the built data structure.
- std::vector<uint8_t> data_;
-};
-
-// Edits a dex file, inserting a new HiddenapiClassData section.
-class DexFileEditor final {
- public:
- DexFileEditor(const DexFile& old_dex, const std::vector<uint8_t>& hiddenapi_class_data)
- : old_dex_(old_dex),
- hiddenapi_class_data_(hiddenapi_class_data),
- loaded_dex_header_(nullptr),
- loaded_dex_maplist_(nullptr) {}
-
- // Copies dex file into a backing data vector, appends the given HiddenapiClassData
- // and updates the MapList.
- void Encode() {
- // We do not support non-standard dex encodings, e.g. compact dex.
- CHECK(old_dex_.IsStandardDexFile());
-
- // If there are no data to append, copy the old dex file and return.
- if (hiddenapi_class_data_.empty()) {
- AllocateMemory(old_dex_.Size());
- Append(old_dex_.Begin(), old_dex_.Size(), /* update_header= */ false);
- return;
- }
-
- // Find the old MapList, find its size.
- const DexFile::MapList* old_map = old_dex_.GetMapList();
- CHECK_LT(old_map->size_, std::numeric_limits<uint32_t>::max());
-
- // Compute the size of the new dex file. We append the HiddenapiClassData,
- // one MapItem and possibly some padding to align the new MapList.
- CHECK(IsAligned<kMapListAlignment>(old_dex_.Size()))
- << "End of input dex file is not 4-byte aligned, possibly because its MapList is not "
- << "at the end of the file.";
- size_t size_delta =
- RoundUp(hiddenapi_class_data_.size(), kMapListAlignment) + sizeof(DexFile::MapItem);
- size_t new_size = old_dex_.Size() + size_delta;
- AllocateMemory(new_size);
-
- // Copy the old dex file into the backing data vector. Load the copied
- // dex file to obtain pointers to its header and MapList.
- Append(old_dex_.Begin(), old_dex_.Size(), /* update_header= */ false);
- ReloadDex(/* verify= */ false);
-
- // Truncate the new dex file before the old MapList. This assumes that
- // the MapList is the last entry in the dex file. This is currently true
- // for our tooling.
- // TODO: Implement the general case by zero-ing the old MapList (turning
- // it into padding.
- RemoveOldMapList();
-
- // Append HiddenapiClassData.
- size_t payload_offset = AppendHiddenapiClassData();
-
- // Wrute new MapList with an entry for HiddenapiClassData.
- CreateMapListWithNewItem(payload_offset);
-
- // Check that the pre-computed size matches the actual size.
- CHECK_EQ(offset_, new_size);
-
- // Reload to all data structures.
- ReloadDex(/* verify= */ false);
-
- // Update the dex checksum.
- UpdateChecksum();
-
- // Run DexFileVerifier on the new dex file as a CHECK.
- ReloadDex(/* verify= */ true);
- }
-
- // Writes the edited dex file into a file.
- void WriteTo(const std::string& path) {
- CHECK(!data_.empty());
- std::ofstream ofs(path.c_str(), std::ofstream::out | std::ofstream::binary);
- ofs.write(reinterpret_cast<const char*>(data_.data()), data_.size());
- ofs.flush();
- CHECK(ofs.good());
- ofs.close();
- }
-
- private:
- static constexpr size_t kMapListAlignment = 4u;
- static constexpr size_t kHiddenapiClassDataAlignment = 4u;
-
- void ReloadDex(bool verify) {
- std::string error_msg;
- DexFileLoader loader;
- loaded_dex_ = loader.Open(
- data_.data(),
- data_.size(),
- "test_location",
- old_dex_.GetLocationChecksum(),
- /* oat_dex_file= */ nullptr,
- /* verify= */ verify,
- /* verify_checksum= */ verify,
- &error_msg);
- if (loaded_dex_.get() == nullptr) {
- LOG(FATAL) << "Failed to load edited dex file: " << error_msg;
- UNREACHABLE();
- }
-
- // Load the location of header and map list before we start editing the file.
- loaded_dex_header_ = const_cast<DexFile::Header*>(&loaded_dex_->GetHeader());
- loaded_dex_maplist_ = const_cast<DexFile::MapList*>(loaded_dex_->GetMapList());
- }
-
- DexFile::Header& GetHeader() const {
- CHECK(loaded_dex_header_ != nullptr);
- return *loaded_dex_header_;
- }
-
- DexFile::MapList& GetMapList() const {
- CHECK(loaded_dex_maplist_ != nullptr);
- return *loaded_dex_maplist_;
- }
-
- void AllocateMemory(size_t total_size) {
- data_.clear();
- data_.resize(total_size);
- CHECK(IsAligned<kMapListAlignment>(data_.data()));
- CHECK(IsAligned<kHiddenapiClassDataAlignment>(data_.data()));
- offset_ = 0;
- }
-
- uint8_t* GetCurrentDataPtr() {
- return data_.data() + offset_;
- }
-
- void UpdateDataSize(off_t delta, bool update_header) {
- offset_ += delta;
- if (update_header) {
- DexFile::Header& header = GetHeader();
- header.file_size_ += delta;
- header.data_size_ += delta;
- }
- }
-
- template<typename T>
- T* Append(const T* src, size_t len, bool update_header = true) {
- CHECK_LE(offset_ + len, data_.size());
- uint8_t* dst = GetCurrentDataPtr();
- memcpy(dst, src, len);
- UpdateDataSize(len, update_header);
- return reinterpret_cast<T*>(dst);
- }
-
- void InsertPadding(size_t alignment) {
- size_t len = RoundUp(offset_, alignment) - offset_;
- std::vector<uint8_t> padding(len, 0);
- Append(padding.data(), padding.size());
- }
-
- void RemoveOldMapList() {
- size_t map_size = GetMapList().Size();
- uint8_t* map_start = reinterpret_cast<uint8_t*>(&GetMapList());
- CHECK_EQ(map_start + map_size, GetCurrentDataPtr()) << "MapList not at the end of dex file";
- UpdateDataSize(-static_cast<off_t>(map_size), /* update_header= */ true);
- CHECK_EQ(map_start, GetCurrentDataPtr());
- loaded_dex_maplist_ = nullptr; // do not use this map list any more
- }
-
- void CreateMapListWithNewItem(size_t payload_offset) {
- InsertPadding(/* alignment= */ kMapListAlignment);
-
- size_t new_map_offset = offset_;
- DexFile::MapList* map = Append(old_dex_.GetMapList(), old_dex_.GetMapList()->Size());
-
- // Check last map entry is a pointer to itself.
- DexFile::MapItem& old_item = map->list_[map->size_ - 1];
- CHECK(old_item.type_ == DexFile::kDexTypeMapList);
- CHECK_EQ(old_item.size_, 1u);
- CHECK_EQ(old_item.offset_, GetHeader().map_off_);
-
- // Create a new MapItem entry with new MapList details.
- DexFile::MapItem new_item;
- new_item.type_ = old_item.type_;
- new_item.size_ = old_item.size_;
- new_item.offset_ = new_map_offset;
-
- // Update pointer in the header.
- GetHeader().map_off_ = new_map_offset;
-
- // Append a new MapItem and return its pointer.
- map->size_++;
- Append(&new_item, sizeof(DexFile::MapItem));
-
- // Change penultimate entry to point to metadata.
- old_item.type_ = DexFile::kDexTypeHiddenapiClassData;
- old_item.size_ = 1u; // there is only one section
- old_item.offset_ = payload_offset;
- }
-
- size_t AppendHiddenapiClassData() {
- size_t payload_offset = offset_;
- CHECK_EQ(kMapListAlignment, kHiddenapiClassDataAlignment);
- CHECK(IsAligned<kHiddenapiClassDataAlignment>(payload_offset))
- << "Should not need to align the section, previous data was already aligned";
- Append(hiddenapi_class_data_.data(), hiddenapi_class_data_.size());
- return payload_offset;
- }
-
- void UpdateChecksum() {
- GetHeader().checksum_ = loaded_dex_->CalculateChecksum();
- }
-
- const DexFile& old_dex_;
- const std::vector<uint8_t>& hiddenapi_class_data_;
-
- std::vector<uint8_t> data_;
- size_t offset_;
-
- std::unique_ptr<const DexFile> loaded_dex_;
- DexFile::Header* loaded_dex_header_;
- DexFile::MapList* loaded_dex_maplist_;
-};
-
class HiddenApi final {
public:
HiddenApi() {}
@@ -883,10 +590,8 @@
if (command == "encode") {
for (int i = 1; i < argc; ++i) {
const StringPiece option(argv[i]);
- if (option.starts_with("--input-dex=")) {
- boot_dex_paths_.push_back(option.substr(strlen("--input-dex=")).ToString());
- } else if (option.starts_with("--output-dex=")) {
- output_dex_paths_.push_back(option.substr(strlen("--output-dex=")).ToString());
+ if (option.starts_with("--dex=")) {
+ boot_dex_paths_.push_back(option.substr(strlen("--dex=")).ToString());
} else if (option.starts_with("--light-greylist=")) {
light_greylist_path_ = option.substr(strlen("--light-greylist=")).ToString();
} else if (option.starts_with("--dark-greylist=")) {
@@ -925,9 +630,7 @@
void EncodeAccessFlags() {
if (boot_dex_paths_.empty()) {
- Usage("No input DEX files specified");
- } else if (output_dex_paths_.size() != boot_dex_paths_.size()) {
- Usage("Number of input DEX files does not match number of output DEX files");
+ Usage("No boot DEX files specified");
}
// Load dex signatures.
@@ -936,41 +639,16 @@
OpenApiFile(dark_greylist_path_, api_list, HiddenApiAccessFlags::kDarkGreylist);
OpenApiFile(blacklist_path_, api_list, HiddenApiAccessFlags::kBlacklist);
- // Iterate over input dex files and insert HiddenapiClassData sections.
- for (size_t i = 0; i < boot_dex_paths_.size(); ++i) {
- const std::string& input_path = boot_dex_paths_[i];
- const std::string& output_path = output_dex_paths_[i];
+ // Open all dex files.
+ ClassPath boot_classpath(boot_dex_paths_, /* open_writable= */ true);
- ClassPath boot_classpath({ input_path }, /* open_writable= */ false);
- std::vector<const DexFile*> input_dex_files = boot_classpath.GetDexFiles();
- CHECK_EQ(input_dex_files.size(), 1u);
- const DexFile& input_dex = *input_dex_files[0];
+ // Set access flags of all members.
+ boot_classpath.ForEachDexMember([&api_list](const DexMember& boot_member) {
+ auto it = api_list.find(boot_member.GetApiEntry());
+ boot_member.SetHidden(it == api_list.end() ? HiddenApiAccessFlags::kWhitelist : it->second);
+ });
- HiddenapiClassDataBuilder builder(input_dex);
- boot_classpath.ForEachDexClass([&api_list, &builder](const DexClass& boot_class) {
- builder.BeginClassDef(boot_class.GetClassDefIndex());
- if (boot_class.GetData() != nullptr) {
- auto fn_shared = [&](const DexMember& boot_member) {
- // TODO: Load whitelist and CHECK that entry was found.
- auto it = api_list.find(boot_member.GetApiEntry());
- builder.WriteFlags(
- (it == api_list.end()) ? HiddenApiAccessFlags::kWhitelist : it->second);
- };
- auto fn_field = [&](const ClassAccessor::Field& boot_field) {
- fn_shared(DexMember(boot_class, boot_field));
- };
- auto fn_method = [&](const ClassAccessor::Method& boot_method) {
- fn_shared(DexMember(boot_class, boot_method));
- };
- boot_class.VisitFieldsAndMethods(fn_field, fn_field, fn_method, fn_method);
- }
- builder.EndClassDef(boot_class.GetClassDefIndex());
- });
-
- DexFileEditor dex_editor(input_dex, builder.GetData());
- dex_editor.Encode();
- dex_editor.WriteTo(output_path);
- }
+ boot_classpath.UpdateDexChecksums();
}
void OpenApiFile(const std::string& path,
@@ -1070,9 +748,6 @@
// Paths to DEX files which should be processed.
std::vector<std::string> boot_dex_paths_;
- // Output paths where modified DEX files should be written.
- std::vector<std::string> output_dex_paths_;
-
// Set of public API stub classpaths. Each classpath is formed by a list
// of DEX/APK files in the order they appear on the classpath.
std::vector<std::vector<std::string>> stub_classpaths_;
@@ -1090,8 +765,6 @@
} // namespace art
int main(int argc, char** argv) {
- art::original_argc = argc;
- art::original_argv = argv;
android::base::InitLogging(argv);
art::MemMap::Init();
art::HiddenApi().Run(argc, argv);
diff --git a/tools/hiddenapi/hiddenapi_test.cc b/tools/hiddenapi/hiddenapi_test.cc
index cdf797e..799546e 100644
--- a/tools/hiddenapi/hiddenapi_test.cc
+++ b/tools/hiddenapi/hiddenapi_test.cc
@@ -47,7 +47,6 @@
const std::vector<std::string>& extra_args,
ScratchFile* out_dex) {
std::string error;
- ScratchFile in_dex;
std::unique_ptr<ZipArchive> jar(
ZipArchive::Open(GetTestDexFileName("HiddenApi").c_str(), &error));
if (jar == nullptr) {
@@ -59,7 +58,7 @@
LOG(FATAL) << "Could not find classes.dex in test file " << GetTestDexFileName("HiddenApi")
<< ": " << error;
UNREACHABLE();
- } else if (!jar_classes_dex->ExtractToFile(*in_dex.GetFile(), &error)) {
+ } else if (!jar_classes_dex->ExtractToFile(*out_dex->GetFile(), &error)) {
LOG(FATAL) << "Could not extract classes.dex from test file "
<< GetTestDexFileName("HiddenApi") << ": " << error;
UNREACHABLE();
@@ -69,8 +68,7 @@
argv_str.push_back(GetHiddenApiCmd());
argv_str.insert(argv_str.end(), extra_args.begin(), extra_args.end());
argv_str.push_back("encode");
- argv_str.push_back("--input-dex=" + in_dex.GetFilename());
- argv_str.push_back("--output-dex=" + out_dex->GetFilename());
+ argv_str.push_back("--dex=" + out_dex->GetFilename());
argv_str.push_back("--light-greylist=" + light_greylist.GetFilename());
argv_str.push_back("--dark-greylist=" + dark_greylist.GetFilename());
argv_str.push_back("--blacklist=" + blacklist.GetFilename());
@@ -94,7 +92,7 @@
}
std::unique_ptr<const DexFile> dex_file(dex_loader.OpenDex(
- fd.Release(), /* location= */ file.GetFilename(), /* verify= */ true,
+ fd.Release(), /* location= */ file.GetFilename(), /* verify= */ false,
/* verify_checksum= */ true, /* mmap_shared= */ false, &error_msg));
if (dex_file.get() == nullptr) {
LOG(FATAL) << "Open failed for '" << file.GetFilename() << "' " << error_msg;
@@ -128,20 +126,16 @@
uint32_t expected_visibility,
const DexFile::ClassDef& class_def,
const DexFile& dex_file) {
- ClassAccessor accessor(dex_file, class_def, /* parse hiddenapi flags */ true);
+ ClassAccessor accessor(dex_file, class_def);
CHECK(accessor.HasClassData()) << "Class " << accessor.GetDescriptor() << " has no data";
- if (!accessor.HasHiddenapiClassData()) {
- return HiddenApiAccessFlags::kWhitelist;
- }
-
for (const ClassAccessor::Field& field : accessor.GetFields()) {
const DexFile::FieldId& fid = dex_file.GetFieldId(field.GetIndex());
if (strcmp(name, dex_file.GetFieldName(fid)) == 0) {
const uint32_t actual_visibility = field.GetAccessFlags() & kAccVisibilityFlags;
CHECK_EQ(actual_visibility, expected_visibility)
<< "Field " << name << " in class " << accessor.GetDescriptor();
- return static_cast<HiddenApiAccessFlags::ApiList>(field.GetHiddenapiFlags());
+ return field.DecodeHiddenAccessFlags();
}
}
@@ -155,13 +149,9 @@
bool expected_native,
const DexFile::ClassDef& class_def,
const DexFile& dex_file) {
- ClassAccessor accessor(dex_file, class_def, /* parse hiddenapi flags */ true);
+ ClassAccessor accessor(dex_file, class_def);
CHECK(accessor.HasClassData()) << "Class " << accessor.GetDescriptor() << " has no data";
- if (!accessor.HasHiddenapiClassData()) {
- return HiddenApiAccessFlags::kWhitelist;
- }
-
for (const ClassAccessor::Method& method : accessor.GetMethods()) {
const DexFile::MethodId& mid = dex_file.GetMethodId(method.GetIndex());
if (strcmp(name, dex_file.GetMethodName(mid)) == 0) {
@@ -170,7 +160,7 @@
const uint32_t actual_visibility = method.GetAccessFlags() & kAccVisibilityFlags;
CHECK_EQ(actual_visibility, expected_visibility)
<< "Method " << name << " in class " << accessor.GetDescriptor();
- return static_cast<HiddenApiAccessFlags::ApiList>(method.GetHiddenapiFlags());
+ return method.DecodeHiddenAccessFlags();
}
}