Separate libdexfile external C ABI from the C++ header file.
Also add a test to compile it with C.
Test: m
Test: m test-art-{host,target}-gtest-dex_file_ext_c_test
Test: art/test/testrunner/run_build_test_target.py -j80 art-test
Bug: 120978655
Change-Id: I6e9944a2051bef9a2775bc2072df4e0ed81dc833
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index a926d9a..d95777f 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -383,6 +383,7 @@
art_hiddenapi_tests \
art_imgdiag_tests \
art_libartbase_tests \
+ art_libdexfile_external_tests \
art_libdexfile_tests \
art_libprofile_tests \
art_oatdump_tests \
diff --git a/libdexfile/Android.bp b/libdexfile/Android.bp
index 9c48aa2..bc7a20b 100644
--- a/libdexfile/Android.bp
+++ b/libdexfile/Android.bp
@@ -176,6 +176,36 @@
},
}
+art_cc_test {
+ name: "art_libdexfile_tests",
+ defaults: [
+ "art_gtest_defaults",
+ ],
+ srcs: [
+ "dex/art_dex_file_loader_test.cc",
+ "dex/class_accessor_test.cc",
+ "dex/code_item_accessors_test.cc",
+ "dex/compact_dex_file_test.cc",
+ "dex/compact_offset_table_test.cc",
+ "dex/descriptors_names_test.cc",
+ "dex/test_dex_file_builder_test.cc",
+ "dex/dex_file_loader_test.cc",
+ "dex/dex_file_verifier_test.cc",
+ "dex/dex_instruction_test.cc",
+ "dex/primitive_test.cc",
+ "dex/string_reference_test.cc",
+ "dex/type_lookup_table_test.cc",
+ "dex/utf_test.cc",
+ ],
+ shared_libs: [
+ "libbacktrace",
+ "libziparchive",
+ ],
+ include_dirs: [
+ "external/zlib",
+ ],
+}
+
cc_library_headers {
name: "libdexfile_external_headers",
host_supported: true,
@@ -227,6 +257,16 @@
},
}
+art_cc_test {
+ name: "art_libdexfile_external_tests",
+ host_supported: true,
+ test_per_src: true, // For consistency with other ART gtests.
+ srcs: [
+ "external/dex_file_ext_c_test.c",
+ ],
+ header_libs: ["libdexfile_external_headers"],
+}
+
// Support library with a C++ API for accessing the libdexfile API for external
// (non-ART) users. They should link to their own instance of this (either
// statically or through linker namespaces).
@@ -240,33 +280,3 @@
shared_libs: ["libdexfile_external"],
export_header_lib_headers: ["libdexfile_external_headers"],
}
-
-art_cc_test {
- name: "art_libdexfile_tests",
- defaults: [
- "art_gtest_defaults",
- ],
- srcs: [
- "dex/art_dex_file_loader_test.cc",
- "dex/class_accessor_test.cc",
- "dex/code_item_accessors_test.cc",
- "dex/compact_dex_file_test.cc",
- "dex/compact_offset_table_test.cc",
- "dex/descriptors_names_test.cc",
- "dex/test_dex_file_builder_test.cc",
- "dex/dex_file_loader_test.cc",
- "dex/dex_file_verifier_test.cc",
- "dex/dex_instruction_test.cc",
- "dex/primitive_test.cc",
- "dex/string_reference_test.cc",
- "dex/type_lookup_table_test.cc",
- "dex/utf_test.cc",
- ],
- shared_libs: [
- "libbacktrace",
- "libziparchive",
- ],
- include_dirs: [
- "external/zlib",
- ],
-}
diff --git a/libdexfile/external/dex_file_ext.cc b/libdexfile/external/dex_file_ext.cc
index 7bf01a8..348ed60 100644
--- a/libdexfile/external/dex_file_ext.cc
+++ b/libdexfile/external/dex_file_ext.cc
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "art_api/dex_file_external.h"
+
#include <inttypes.h>
#include <stdint.h>
#include <sys/mman.h>
@@ -39,18 +41,9 @@
#include <dex/dex_file-inl.h>
#include <dex/dex_file_loader.h>
-#include "art_api/dex_file_support.h"
-
-extern "C" class ExtDexFileString {
- public:
- const std::string str_;
-};
-
namespace art {
namespace {
-const ExtDexFileString empty_string{""};
-
struct MethodCacheEntry {
int32_t offset; // Offset relative to the start of the dex file header.
int32_t len;
@@ -77,9 +70,15 @@
extern "C" {
+struct ExtDexFileString {
+ const std::string str_;
+};
+
+static const ExtDexFileString empty_string{""};
+
const ExtDexFileString* ExtDexFileMakeString(const char* str) {
if (str[0] == '\0') {
- return &art::empty_string;
+ return &empty_string;
}
return new ExtDexFileString{str};
}
@@ -92,14 +91,15 @@
void ExtDexFileFreeString(const ExtDexFileString* ext_string) {
DCHECK(ext_string != nullptr);
- if (ext_string != &art::empty_string) {
+ if (ext_string != &empty_string) {
delete (ext_string);
}
}
// Wraps DexFile to add the caching needed by the external interface. This is
// what gets passed over as ExtDexFile*.
-class ExtDexFile {
+struct ExtDexFile {
+ private:
// Method cache for GetMethodInfoForOffset. This is populated as we iterate
// sequentially through the class defs. MethodCacheEntry.name is only set for
// methods returned by GetMethodInfoForOffset.
diff --git a/libdexfile/external/dex_file_ext_c_test.c b/libdexfile/external/dex_file_ext_c_test.c
new file mode 100644
index 0000000..ad0737a
--- /dev/null
+++ b/libdexfile/external/dex_file_ext_c_test.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2019 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 <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+/* The main purpose of this test is to ensure this C header compiles in C, so
+ * that no C++ features inadvertently leak into the C ABI. */
+#include "art_api/dex_file_external.h"
+
+static const char gtest_output_arg[] = "--gtest_output=xml:";
+static const char gtest_output_xml[] = "\
+<?xml version=\"1.0\"?>\n\
+<testsuites tests=\"0\" failures=\"0\" disabled=\"0\" errors=\"0\" name=\"AllTests\">";
+
+/* Writes a dummy gtest xml report to the given path. */
+static int write_gtest_output_xml(char* gtest_output_path) {
+ FILE* output_fd = fopen(gtest_output_path, "w");
+ if (output_fd == NULL) {
+ fprintf(stderr, "Failed to open %s: %s\n", gtest_output_path, strerror(errno));
+ return 1;
+ }
+ if (fprintf(output_fd, gtest_output_xml) != sizeof(gtest_output_xml) - 1) {
+ fprintf(stderr, "Failed to write %s: %s\n", gtest_output_path, strerror(errno));
+ return 1;
+ }
+ if (fclose(output_fd) != 0) {
+ fprintf(stderr, "Failed to close %s: %s\n", gtest_output_path, strerror(errno));
+ return 1;
+ }
+ return 0;
+}
+
+int main(int argc, char** argv) {
+ if (argc >= 1 && strncmp(argv[1], gtest_output_arg, sizeof(gtest_output_arg) - 1) == 0) {
+ /* The ART gtest framework expects all tests to understand --gtest_output. */
+ return write_gtest_output_xml(argv[1] + sizeof(gtest_output_arg) - 1);
+ }
+ return 0;
+}
diff --git a/libdexfile/external/include/art_api/dex_file_external.h b/libdexfile/external/include/art_api/dex_file_external.h
new file mode 100644
index 0000000..b29235f
--- /dev/null
+++ b/libdexfile/external/include/art_api/dex_file_external.h
@@ -0,0 +1,89 @@
+/*
+ * 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_LIBDEXFILE_EXTERNAL_INCLUDE_ART_API_DEX_FILE_EXTERNAL_H_
+#define ART_LIBDEXFILE_EXTERNAL_INCLUDE_ART_API_DEX_FILE_EXTERNAL_H_
+
+// Dex file external API
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// This is the stable C ABI that backs art_api::dex below. Structs and functions
+// may only be added here. C++ users should use dex_file_support.h instead.
+
+// Opaque wrapper for an std::string allocated in libdexfile which must be freed
+// using ExtDexFileFreeString.
+struct ExtDexFileString;
+
+// Returns an ExtDexFileString initialized to the given string.
+const struct ExtDexFileString* ExtDexFileMakeString(const char* str);
+
+// Returns a pointer to the underlying null-terminated character array and its
+// size for the given ExtDexFileString.
+const char* ExtDexFileGetString(const struct ExtDexFileString* ext_string, /*out*/ size_t* size);
+
+// Frees an ExtDexFileString.
+void ExtDexFileFreeString(const struct ExtDexFileString* ext_string);
+
+struct ExtDexFileMethodInfo {
+ int32_t offset;
+ int32_t len;
+ const struct ExtDexFileString* name;
+};
+
+struct ExtDexFile;
+
+// See art_api::dex::DexFile::OpenFromMemory. Returns true on success.
+int ExtDexFileOpenFromMemory(const void* addr,
+ /*inout*/ size_t* size,
+ const char* location,
+ /*out*/ const struct ExtDexFileString** error_msg,
+ /*out*/ struct ExtDexFile** ext_dex_file);
+
+// See art_api::dex::DexFile::OpenFromFd. Returns true on success.
+int ExtDexFileOpenFromFd(int fd,
+ off_t offset,
+ const char* location,
+ /*out*/ const struct ExtDexFileString** error_msg,
+ /*out*/ struct ExtDexFile** ext_dex_file);
+
+// See art_api::dex::DexFile::GetMethodInfoForOffset. Returns true on success.
+int ExtDexFileGetMethodInfoForOffset(struct ExtDexFile* ext_dex_file,
+ int64_t dex_offset,
+ int with_signature,
+ /*out*/ struct ExtDexFileMethodInfo* method_info);
+
+typedef void ExtDexFileMethodInfoCallback(const struct ExtDexFileMethodInfo* ext_method_info,
+ void* user_data);
+
+// See art_api::dex::DexFile::GetAllMethodInfos.
+void ExtDexFileGetAllMethodInfos(struct ExtDexFile* ext_dex_file,
+ int with_signature,
+ ExtDexFileMethodInfoCallback* method_info_cb,
+ void* user_data);
+
+// Frees an ExtDexFile.
+void ExtDexFileFree(struct ExtDexFile* ext_dex_file);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // ART_LIBDEXFILE_EXTERNAL_INCLUDE_ART_API_DEX_FILE_EXTERNAL_H_
diff --git a/libdexfile/external/include/art_api/dex_file_support.h b/libdexfile/external/include/art_api/dex_file_support.h
index 99d60d1..9a20a30 100644
--- a/libdexfile/external/include/art_api/dex_file_support.h
+++ b/libdexfile/external/include/art_api/dex_file_support.h
@@ -17,9 +17,7 @@
#ifndef ART_LIBDEXFILE_EXTERNAL_INCLUDE_ART_API_DEX_FILE_SUPPORT_H_
#define ART_LIBDEXFILE_EXTERNAL_INCLUDE_ART_API_DEX_FILE_SUPPORT_H_
-// Dex file external API
-
-#include <sys/types.h>
+// C++ wrapper for the dex file external API.
#include <cstring>
#include <memory>
@@ -29,69 +27,7 @@
#include <android-base/macros.h>
-extern "C" {
-
-// This is the stable C ABI that backs art_api::dex below. Structs and functions
-// may only be added here.
-// TODO(b/120978655): Move this to a separate pure C header.
-//
-// Clients should use the C++ wrappers in art_api::dex instead.
-
-// Opaque wrapper for an std::string allocated in libdexfile which must be freed
-// using ExtDexFileFreeString.
-class ExtDexFileString;
-
-// Returns an ExtDexFileString initialized to the given string.
-const ExtDexFileString* ExtDexFileMakeString(const char* str);
-
-// Returns a pointer to the underlying null-terminated character array and its
-// size for the given ExtDexFileString.
-const char* ExtDexFileGetString(const ExtDexFileString* ext_string, /*out*/ size_t* size);
-
-// Frees an ExtDexFileString.
-void ExtDexFileFreeString(const ExtDexFileString* ext_string);
-
-struct ExtDexFileMethodInfo {
- int32_t offset;
- int32_t len;
- const ExtDexFileString* name;
-};
-
-class ExtDexFile;
-
-// See art_api::dex::DexFile::OpenFromMemory. Returns true on success.
-int ExtDexFileOpenFromMemory(const void* addr,
- /*inout*/ size_t* size,
- const char* location,
- /*out*/ const ExtDexFileString** error_msg,
- /*out*/ ExtDexFile** ext_dex_file);
-
-// See art_api::dex::DexFile::OpenFromFd. Returns true on success.
-int ExtDexFileOpenFromFd(int fd,
- off_t offset,
- const char* location,
- /*out*/ const ExtDexFileString** error_msg,
- /*out*/ ExtDexFile** ext_dex_file);
-
-// See art_api::dex::DexFile::GetMethodInfoForOffset. Returns true on success.
-int ExtDexFileGetMethodInfoForOffset(ExtDexFile* ext_dex_file,
- int64_t dex_offset,
- int with_signature,
- /*out*/ ExtDexFileMethodInfo* method_info);
-
-typedef void ExtDexFileMethodInfoCallback(const ExtDexFileMethodInfo* ext_method_info,
- void* user_data);
-
-// See art_api::dex::DexFile::GetAllMethodInfos.
-void ExtDexFileGetAllMethodInfos(ExtDexFile* ext_dex_file,
- int with_signature,
- ExtDexFileMethodInfoCallback* method_info_cb,
- void* user_data);
-
-// Frees an ExtDexFile.
-void ExtDexFileFree(ExtDexFile* ext_dex_file);
-
-} // extern "C"
+#include "art_api/dex_file_external.h"
namespace art_api {
namespace dex {