Add a --whitelist and --only-report-sdk-uses to veridex.
In order to list SDK uses.
bug: 112978171
Test: manual
Change-Id: Ic2b36d6e8a3e07d3ec7001ed24888bd390219a85
diff --git a/Android.mk b/Android.mk
index 7852be5..0c20973 100644
--- a/Android.mk
+++ b/Android.mk
@@ -427,7 +427,7 @@
define build-art-hiddenapi
$(shell if [ ! -d frameworks/base ]; then \
mkdir -p ${TARGET_OUT_COMMON_INTERMEDIATES}/PACKAGING; \
- touch ${TARGET_OUT_COMMON_INTERMEDIATES}/PACKAGING/hiddenapi-{blacklist,dark-greylist,light-greylist}.txt; \
+ touch ${TARGET_OUT_COMMON_INTERMEDIATES}/PACKAGING/hiddenapi-{whitelist,blacklist,dark-greylist,light-greylist}.txt; \
fi;)
endef
diff --git a/libdexfile/dex/hidden_api_access_flags.h b/libdexfile/dex/hidden_api_access_flags.h
index 1aaeabd..369615d 100644
--- a/libdexfile/dex/hidden_api_access_flags.h
+++ b/libdexfile/dex/hidden_api_access_flags.h
@@ -62,6 +62,7 @@
kLightGreylist,
kDarkGreylist,
kBlacklist,
+ kNoList,
};
static ALWAYS_INLINE ApiList DecodeFromDex(uint32_t dex_access_flags) {
@@ -159,6 +160,9 @@
case HiddenApiAccessFlags::kBlacklist:
os << "blacklist";
break;
+ case HiddenApiAccessFlags::kNoList:
+ os << "no list";
+ break;
}
return os;
}
diff --git a/tools/veridex/Android.mk b/tools/veridex/Android.mk
index 2faa577..99ced7b 100644
--- a/tools/veridex/Android.mk
+++ b/tools/veridex/Android.mk
@@ -31,6 +31,7 @@
$(transform-classes.jar-to-dex)
app_compat_lists := \
+ $(INTERNAL_PLATFORM_HIDDENAPI_WHITELIST) \
$(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST) \
$(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST) \
$(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST)
diff --git a/tools/veridex/appcompat.sh b/tools/veridex/appcompat.sh
index e7b735d..9a24d82 100755
--- a/tools/veridex/appcompat.sh
+++ b/tools/veridex/appcompat.sh
@@ -22,6 +22,7 @@
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
if [[ -e ${SCRIPT_DIR}/veridex && \
+ -e ${SCRIPT_DIR}/hiddenapi-whitelist.txt && \
-e ${SCRIPT_DIR}/hiddenapi-blacklist.txt && \
-e ${SCRIPT_DIR}/hiddenapi-light-greylist.txt && \
-e ${SCRIPT_DIR}/hiddenapi-dark-greylist.txt && \
@@ -29,6 +30,7 @@
-e ${SCRIPT_DIR}/system-stubs.zip ]]; then
exec ${SCRIPT_DIR}/veridex \
--core-stubs=${SCRIPT_DIR}/system-stubs.zip:${SCRIPT_DIR}/org.apache.http.legacy-stubs.zip \
+ --whitelist=${SCRIPT_DIR}/hiddenapi-whitelist.txt \
--blacklist=${SCRIPT_DIR}/hiddenapi-blacklist.txt \
--light-greylist=${SCRIPT_DIR}/hiddenapi-light-greylist.txt \
--dark-greylist=${SCRIPT_DIR}/hiddenapi-dark-greylist.txt \
@@ -62,6 +64,7 @@
${ANDROID_HOST_OUT}/bin/veridex \
--core-stubs=${PACKAGING}/core_dex_intermediates/classes.dex:${PACKAGING}/oahl_dex_intermediates/classes.dex \
+ --whitelist=${PACKAGING}/hiddenapi-whitelist.txt \
--blacklist=${PACKAGING}/hiddenapi-blacklist.txt \
--light-greylist=${PACKAGING}/hiddenapi-light-greylist.txt \
--dark-greylist=${PACKAGING}/hiddenapi-dark-greylist.txt \
diff --git a/tools/veridex/hidden_api.h b/tools/veridex/hidden_api.h
index b1c8559..68485bd 100644
--- a/tools/veridex/hidden_api.h
+++ b/tools/veridex/hidden_api.h
@@ -33,10 +33,14 @@
*/
class HiddenApi {
public:
- HiddenApi(const char* blacklist, const char* dark_greylist, const char* light_greylist) {
+ HiddenApi(const char* whitelist,
+ const char* blacklist,
+ const char* dark_greylist,
+ const char* light_greylist) {
FillList(light_greylist, light_greylist_);
FillList(dark_greylist, dark_greylist_);
FillList(blacklist, blacklist_);
+ FillList(whitelist, whitelist_);
}
HiddenApiAccessFlags::ApiList GetApiList(const std::string& name) const {
@@ -46,13 +50,15 @@
return HiddenApiAccessFlags::kDarkGreylist;
} else if (IsInList(name, light_greylist_)) {
return HiddenApiAccessFlags::kLightGreylist;
- } else {
+ } else if (IsInList(name, whitelist_)) {
return HiddenApiAccessFlags::kWhitelist;
+ } else {
+ return HiddenApiAccessFlags::kNoList;
}
}
- bool IsInRestrictionList(const std::string& name) const {
- return GetApiList(name) != HiddenApiAccessFlags::kWhitelist;
+ bool IsInAnyList(const std::string& name) const {
+ return GetApiList(name) != HiddenApiAccessFlags::kNoList;
}
static std::string GetApiMethodName(const DexFile& dex_file, uint32_t method_index);
@@ -76,6 +82,7 @@
static void FillList(const char* filename, std::set<std::string>& entries);
+ std::set<std::string> whitelist_;
std::set<std::string> blacklist_;
std::set<std::string> light_greylist_;
std::set<std::string> dark_greylist_;
@@ -85,7 +92,7 @@
uint32_t count = 0;
uint32_t reflection_count = 0;
uint32_t linking_count = 0;
- uint32_t api_counts[4] = { 0, 0, 0, 0 };
+ uint32_t api_counts[5] = { 0, 0, 0, 0, 0 };
};
} // namespace art
diff --git a/tools/veridex/hidden_api_finder.cc b/tools/veridex/hidden_api_finder.cc
index d81f133..9e2f936 100644
--- a/tools/veridex/hidden_api_finder.cc
+++ b/tools/veridex/hidden_api_finder.cc
@@ -35,7 +35,7 @@
// Note: we always query whether a method is in a list, as the app
// might define blacklisted APIs (which won't be used at runtime).
std::string name = HiddenApi::GetApiMethodName(resolver->GetDexFile(), method_id);
- if (hidden_api_.IsInRestrictionList(name)) {
+ if (hidden_api_.IsInAnyList(name)) {
method_locations_[name].push_back(ref);
}
}
@@ -46,7 +46,7 @@
// Note: we always query whether a field is in a list, as the app
// might define blacklisted APIs (which won't be used at runtime).
std::string name = HiddenApi::GetApiFieldName(resolver->GetDexFile(), field_id);
- if (hidden_api_.IsInRestrictionList(name)) {
+ if (hidden_api_.IsInAnyList(name)) {
field_locations_[name].push_back(ref);
}
}
@@ -57,7 +57,7 @@
// types can lead to being used through reflection.
for (uint32_t i = 0; i < dex_file.NumTypeIds(); ++i) {
std::string name(dex_file.StringByTypeIdx(dex::TypeIndex(i)));
- if (hidden_api_.IsInRestrictionList(name)) {
+ if (hidden_api_.IsInAnyList(name)) {
classes_.insert(name);
}
}
@@ -81,9 +81,9 @@
// private methods and fields in them.
// We don't add class names to the `strings_` set as we know method/field names
// don't have '.' or '/'. All hidden API class names have a '/'.
- if (hidden_api_.IsInRestrictionList(str)) {
+ if (hidden_api_.IsInAnyList(str)) {
classes_.insert(str);
- } else if (hidden_api_.IsInRestrictionList(name)) {
+ } else if (hidden_api_.IsInAnyList(name)) {
// Could be something passed to JNI.
classes_.insert(name);
} else {
@@ -210,7 +210,7 @@
std::string full_name = cls + "->" + name;
HiddenApiAccessFlags::ApiList api_list = hidden_api_.GetApiList(full_name);
stats->api_counts[api_list]++;
- if (api_list != HiddenApiAccessFlags::kWhitelist) {
+ if (api_list != HiddenApiAccessFlags::kNoList) {
stats->reflection_count++;
os << "#" << ++stats->count << ": Reflection " << api_list << " " << full_name
<< " potential use(s):";
diff --git a/tools/veridex/precise_hidden_api_finder.cc b/tools/veridex/precise_hidden_api_finder.cc
index 445221e..08ac6d7 100644
--- a/tools/veridex/precise_hidden_api_finder.cc
+++ b/tools/veridex/precise_hidden_api_finder.cc
@@ -92,7 +92,7 @@
std::string name(info.name.ToString());
std::string full_name = cls + "->" + name;
HiddenApiAccessFlags::ApiList api_list = hidden_api_.GetApiList(full_name);
- if (api_list != HiddenApiAccessFlags::kWhitelist) {
+ if (api_list != HiddenApiAccessFlags::kNoList) {
named_uses[full_name].push_back(ref);
}
}
diff --git a/tools/veridex/veridex.cc b/tools/veridex/veridex.cc
index 1d3a4fb..cf1167f 100644
--- a/tools/veridex/veridex.cc
+++ b/tools/veridex/veridex.cc
@@ -68,11 +68,13 @@
struct VeridexOptions {
const char* dex_file = nullptr;
const char* core_stubs = nullptr;
+ const char* whitelist = nullptr;
const char* blacklist = nullptr;
const char* light_greylist = nullptr;
const char* dark_greylist = nullptr;
bool precise = true;
int target_sdk_version = 28; /* P */
+ bool only_report_sdk_uses = false;
};
static const char* Substr(const char* str, int index) {
@@ -90,17 +92,21 @@
static const char* kDexFileOption = "--dex-file=";
static const char* kStubsOption = "--core-stubs=";
+ static const char* kWhitelistOption = "--whitelist=";
static const char* kBlacklistOption = "--blacklist=";
static const char* kDarkGreylistOption = "--dark-greylist=";
static const char* kLightGreylistOption = "--light-greylist=";
static const char* kImprecise = "--imprecise";
static const char* kTargetSdkVersion = "--target-sdk-version=";
+ static const char* kOnlyReportSdkUses = "--only-report-sdk-uses";
for (int i = 0; i < argc; ++i) {
if (StartsWith(argv[i], kDexFileOption)) {
options->dex_file = Substr(argv[i], strlen(kDexFileOption));
} else if (StartsWith(argv[i], kStubsOption)) {
options->core_stubs = Substr(argv[i], strlen(kStubsOption));
+ } else if (StartsWith(argv[i], kWhitelistOption)) {
+ options->whitelist = Substr(argv[i], strlen(kWhitelistOption));
} else if (StartsWith(argv[i], kBlacklistOption)) {
options->blacklist = Substr(argv[i], strlen(kBlacklistOption));
} else if (StartsWith(argv[i], kDarkGreylistOption)) {
@@ -111,6 +117,8 @@
options->precise = false;
} else if (StartsWith(argv[i], kTargetSdkVersion)) {
options->target_sdk_version = atoi(Substr(argv[i], strlen(kTargetSdkVersion)));
+ } else if (strcmp(argv[i], kOnlyReportSdkUses) == 0) {
+ options->only_report_sdk_uses = true;
}
}
}
@@ -215,8 +223,17 @@
std::vector<std::unique_ptr<VeridexResolver>> app_resolvers;
Resolve(app_dex_files, resolver_map, type_map, &app_resolvers);
+ if (options.only_report_sdk_uses) {
+ // If we only need to report SDK uses, clear out any of the other lists so that
+ // the analysis don't report them.
+ options.blacklist = nullptr;
+ options.dark_greylist = nullptr;
+ options.light_greylist = nullptr;
+ }
+
// Find and log uses of hidden APIs.
- HiddenApi hidden_api(options.blacklist, options.dark_greylist, options.light_greylist);
+ HiddenApi hidden_api(
+ options.whitelist, options.blacklist, options.dark_greylist, options.light_greylist);
HiddenApiStats stats;
HiddenApiFinder api_finder(hidden_api);
@@ -229,7 +246,7 @@
precise_api_finder.Dump(std::cout, &stats);
}
- DumpSummaryStats(std::cout, stats);
+ DumpSummaryStats(std::cout, stats, options);
if (options.precise) {
std::cout << "To run an analysis that can give more reflection accesses, " << std::endl
@@ -240,17 +257,23 @@
}
private:
- static void DumpSummaryStats(std::ostream& os, const HiddenApiStats& stats) {
+ static void DumpSummaryStats(std::ostream& os,
+ const HiddenApiStats& stats,
+ const VeridexOptions& options) {
static const char* kPrefix = " ";
- os << stats.count << " hidden API(s) used: "
- << stats.linking_count << " linked against, "
- << stats.reflection_count << " through reflection" << std::endl;
- os << kPrefix << stats.api_counts[HiddenApiAccessFlags::kBlacklist]
- << " in blacklist" << std::endl;
- os << kPrefix << stats.api_counts[HiddenApiAccessFlags::kDarkGreylist]
- << " in dark greylist" << std::endl;
- os << kPrefix << stats.api_counts[HiddenApiAccessFlags::kLightGreylist]
- << " in light greylist" << std::endl;
+ if (options.only_report_sdk_uses) {
+ os << stats.api_counts[HiddenApiAccessFlags::kWhitelist] << " SDK API uses." << std::endl;
+ } else {
+ os << stats.count << " hidden API(s) used: "
+ << stats.linking_count << " linked against, "
+ << stats.reflection_count << " through reflection" << std::endl;
+ os << kPrefix << stats.api_counts[HiddenApiAccessFlags::kBlacklist]
+ << " in blacklist" << std::endl;
+ os << kPrefix << stats.api_counts[HiddenApiAccessFlags::kDarkGreylist]
+ << " in dark greylist" << std::endl;
+ os << kPrefix << stats.api_counts[HiddenApiAccessFlags::kLightGreylist]
+ << " in light greylist" << std::endl;
+ }
}
static bool Load(const std::string& filename,