Introduce ObjectLoader and RSExecutable.
ObjectLoader loads an object file into memory.
ObjectLoaderImpl defines a set of format-independent interfaces
that a object file format loader has to provide.
ELFObjectLoaderImpl is a subclass of ObjectLoaderImpl and can be used
to load an ELF relocatable object built based on librsloader. It
directly uses the C++ APIs provided by librsloader instead of using
wrapped C APIs defined in librsloader.h
RSExecutable holds the build results of a RSScript.
Change-Id: Ib73d3f567fce3dcfea8c9f2c9bc19fbc47ec78bc
diff --git a/lib/ExecutionEngine/Android.mk b/lib/ExecutionEngine/Android.mk
index 430f872..02088cb 100644
--- a/lib/ExecutionEngine/Android.mk
+++ b/lib/ExecutionEngine/Android.mk
@@ -27,13 +27,16 @@
BCCContextImpl.cpp \
BCCRuntimeSymbolResolver.cpp \
Compiler.cpp \
+ ELFObjectLoaderImpl.cpp \
FileBase.cpp \
GDBJIT.cpp \
GDBJITRegistrar.cpp \
InputFile.cpp \
MCCacheWriter.cpp \
MCCacheReader.cpp \
+ ObjectLoader.cpp \
OutputFile.cpp \
+ RSExecutable.cpp \
RSInfo.cpp \
RSInfoExtractor.cpp \
RSInfoReader.cpp \
@@ -62,7 +65,10 @@
LOCAL_CFLAGS += $(libbcc_CFLAGS)
LOCAL_CFLAGS += -DTARGET_BUILD
-LOCAL_C_INCLUDES := $(libbcc_C_INCLUDES)
+LOCAL_C_INCLUDES := \
+ $(libbcc_C_INCLUDES) \
+ $(RSLOADER_ROOT_PATH) \
+ $(RSLOADER_ROOT_PATH)/include
LOCAL_SRC_FILES := $(libbcc_executionengine_SRC_FILES)
LOCAL_SHARED_LIBRARIES := libbcinfo
@@ -85,7 +91,10 @@
LOCAL_CFLAGS += $(libbcc_CFLAGS)
LOCAL_CFLAGS += -D__HOST__
-LOCAL_C_INCLUDES := $(libbcc_C_INCLUDES)
+LOCAL_C_INCLUDES := \
+ $(libbcc_C_INCLUDES) \
+ $(RSLOADER_ROOT_PATH) \
+ $(RSLOADER_ROOT_PATH)/include
LOCAL_SRC_FILES := $(libbcc_executionengine_SRC_FILES)
LOCAL_SHARED_LIBRARIES := libbcinfo
diff --git a/lib/ExecutionEngine/ELFObjectLoaderImpl.cpp b/lib/ExecutionEngine/ELFObjectLoaderImpl.cpp
new file mode 100644
index 0000000..01f613e
--- /dev/null
+++ b/lib/ExecutionEngine/ELFObjectLoaderImpl.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2012, 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 "ELFObjectLoaderImpl.h"
+
+#include <llvm/Support/ELF.h>
+
+// The following files are included from librsloader.
+#include "ELFObject.h"
+#include "ELFSectionSymTab.h"
+#include "ELFSymbol.h"
+#include "utils/serialize.h"
+
+#include "DebugHelper.h"
+#include "SymbolResolverInterface.h"
+
+using namespace bcc;
+
+bool ELFObjectLoaderImpl::load(const void *pMem, size_t pMemSize) {
+ ArchiveReaderLE reader(reinterpret_cast<const unsigned char *>(pMem),
+ pMemSize);
+
+ mObject = ELFObject<32>::read(reader);
+ if (mObject == NULL) {
+ ALOGE("Unable to load the ELF object!");
+ return false;
+ }
+
+ // Retrive the pointer to the symbol table.
+ mSymTab = static_cast<ELFSectionSymTab<32> *>(
+ mObject->getSectionByName(".symtab"));
+ if (mSymTab == NULL) {
+ ALOGW("Object doesn't contain any symbol table.");
+ }
+
+ return true;
+}
+
+bool ELFObjectLoaderImpl::relocate(SymbolResolverInterface &pResolver) {
+ mObject->relocate(SymbolResolverInterface::LookupFunction, &pResolver);
+
+ if (mObject->getMissingSymbols()) {
+ ALOGE("Some symbols are found to be undefined during relocation!");
+ return false;
+ }
+
+ return true;
+}
+
+bool ELFObjectLoaderImpl::prepareDebugImage(void *pDebugImg,
+ size_t pDebugImgSize) {
+ // Update the value of sh_addr in pDebugImg to its corresponding section in
+ // the mObject.
+ llvm::ELF::Elf32_Ehdr *elf_header =
+ reinterpret_cast<llvm::ELF::Elf32_Ehdr *>(pDebugImg);
+
+ if (elf_header->e_shoff > pDebugImgSize) {
+ ALOGE("Invalid section header table offset found! (e_shoff = %d)",
+ elf_header->e_shoff);
+ return false;
+ }
+
+ if ((elf_header->e_shoff +
+ sizeof(llvm::ELF::Elf32_Shdr) * elf_header->e_shnum) > pDebugImgSize) {
+ ALOGE("Invalid image supplied (debug image doesn't contain all the section"
+ "header or corrupted image)! (e_shoff = %d, e_shnum = %d)",
+ elf_header->e_shoff, elf_header->e_shnum);
+ return false;
+ }
+
+ llvm::ELF::Elf32_Shdr *section_header_table =
+ reinterpret_cast<llvm::ELF::Elf32_Shdr *>(
+ reinterpret_cast<uint8_t*>(pDebugImg) + elf_header->e_shoff);
+
+ for (unsigned i = 0; i < elf_header->e_shnum; i++) {
+ if (section_header_table[i].sh_flags & llvm::ELF::SHF_ALLOC) {
+ ELFSectionBits<32> *section =
+ static_cast<ELFSectionBits<32> *>(mObject->getSectionByIndex(i));
+ if (section != NULL) {
+ section_header_table[i].sh_addr =
+ reinterpret_cast<llvm::ELF::Elf32_Addr>(section->getBuffer());
+ }
+ }
+ }
+
+ return true;
+}
+
+void *ELFObjectLoaderImpl::getSymbolAddress(const char *pName) const {
+ if (mSymTab == NULL) {
+ return NULL;
+ }
+
+ ELFSymbol<32> *symbol = mSymTab->getByName(pName);
+ if (symbol == NULL) {
+ ALOGV("Request symbol '%s' is not found in the object!", pName);
+ return NULL;
+ }
+
+ return symbol->getAddress(mObject->getHeader()->getMachine(),
+ /* autoAlloc */false);
+}
+
+ELFObjectLoaderImpl::~ELFObjectLoaderImpl() {
+ delete mObject;
+ return;
+}
diff --git a/lib/ExecutionEngine/ELFObjectLoaderImpl.h b/lib/ExecutionEngine/ELFObjectLoaderImpl.h
new file mode 100644
index 0000000..37766fb
--- /dev/null
+++ b/lib/ExecutionEngine/ELFObjectLoaderImpl.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2012, 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 BCC_EXECUTION_ENGINE_ELF_OBJECT_LOADER_IMPL_H
+#define BCC_EXECUTION_ENGINE_ELF_OBJECT_LOADER_IMPL_H
+
+#include "ObjectLoaderImpl.h"
+
+// ELFObject and ELFSectionSymTab comes from librsloader. They're both
+// defined under global scope without a namespace enclosed.
+template <unsigned Bitwidth>
+class ELFObject;
+
+template <unsigned Bitwidth>
+class ELFSectionSymTab;
+
+namespace bcc {
+
+class ELFObjectLoaderImpl : public ObjectLoaderImpl {
+private:
+ ELFObject<32> *mObject;
+ ELFSectionSymTab<32> *mSymTab;
+
+public:
+ ELFObjectLoaderImpl() : ObjectLoaderImpl(), mObject(NULL), mSymTab(NULL) { }
+
+ virtual bool load(const void *pMem, size_t pMemSize);
+
+ virtual bool relocate(SymbolResolverInterface &pResolver);
+
+ virtual bool prepareDebugImage(void *pDebugImg, size_t pDebugImgSize);
+
+ virtual void *getSymbolAddress(const char *pName) const;
+
+ ~ELFObjectLoaderImpl();
+};
+
+} // end namespace bcc
+
+#endif // BCC_EXECUTION_ENGINE_ELF_OBJECT_LOADER_IMPL_H
diff --git a/lib/ExecutionEngine/ObjectLoader.cpp b/lib/ExecutionEngine/ObjectLoader.cpp
new file mode 100644
index 0000000..708ded3
--- /dev/null
+++ b/lib/ExecutionEngine/ObjectLoader.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2012, 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 "ObjectLoader.h"
+
+#include <utils/FileMap.h>
+
+#include "DebugHelper.h"
+#include "ELFObjectLoaderImpl.h"
+#include "FileBase.h"
+#include "GDBJITRegistrar.h"
+
+using namespace bcc;
+
+ObjectLoader *ObjectLoader::Load(void *pMemStart, size_t pMemSize,
+ const char *pName,
+ SymbolResolverInterface &pResolver,
+ bool pEnableGDBDebug) {
+ ObjectLoader *result = NULL;
+
+ // Check parameters.
+ if ((pMemStart == NULL) || (pMemSize <= 0)) {
+ ALOGE("Invalid memory '%s' was given to load (memory addr: %p, size: %u)",
+ pName, pMemStart, static_cast<unsigned>(pMemSize));
+ goto bail;
+ }
+
+ // Create result object
+ result = new (std::nothrow) ObjectLoader();
+ if (result == NULL) {
+ ALOGE("Out of memory when create object loader for %s!", pName);
+ goto bail;
+ }
+
+ // Currently, only ELF object loader is supported. Therefore, there's no codes
+ // to detect the object file type and to select the one appropriated. Directly
+ // try out the ELF object loader.
+ result->mImpl = new (std::nothrow) ELFObjectLoaderImpl();
+ if (result->mImpl == NULL) {
+ ALOGE("Out of memory when create ELF object loader for %s", pName);
+ goto bail;
+ }
+
+ // Load the object file.
+ if (!result->mImpl->load(pMemStart, pMemSize)) {
+ ALOGE("Failed to load %s!", pName);
+ goto bail;
+ }
+
+ // Perform relocation.
+ if (!result->mImpl->relocate(pResolver)) {
+ ALOGE("Error occurred when performs relocation on %s!", pName);
+ goto bail;
+ }
+
+ // GDB debugging is enabled. Note that error occurrs during the setup of
+ // debugging won't failed the object load. Only a warning is issued to notify
+ // that the debugging is disabled due to the failure.
+ if (pEnableGDBDebug) {
+ // GDB's JIT debugging requires the source object file corresponded to the
+ // process image desired to debug with. And some fields in the object file
+ // must be updated to record the runtime information after it's loaded into
+ // memory. For example, GDB's JIT debugging requires an ELF file with the
+ // value of sh_addr in the section header to be the memory address that the
+ // section lives in the process image. Therefore, a writable memory with its
+ // contents initialized to the contents of pFile is created.
+ result->mDebugImage = new (std::nothrow) uint8_t [ pMemSize ];
+ if (result->mDebugImage != NULL) {
+ ::memcpy(result->mDebugImage, pMemStart, pMemSize);
+ if (!result->mImpl->prepareDebugImage(result->mDebugImage, pMemSize)) {
+ ALOGW("GDB debug for %s is enabled by the user but won't work due to "
+ "failure debug image preparation!", pName);
+ } else {
+ registerObjectWithGDB(
+ reinterpret_cast<const ObjectBuffer *>(result->mDebugImage),
+ pMemSize);
+ }
+ }
+ }
+
+ return result;
+
+bail:
+ delete result;
+ return NULL;
+}
+
+ObjectLoader *ObjectLoader::Load(FileBase &pFile,
+ SymbolResolverInterface &pResolver,
+ bool pEnableGDBDebug) {
+ size_t file_size;
+ android::FileMap *file_map = NULL;
+ const char *input_filename = pFile.getName().c_str();
+ ObjectLoader *result = NULL;
+
+ // Check the inputs.
+ if (pFile.hasError()) {
+ ALOGE("Input file %s to the object loader is in the invalid state! (%s)",
+ input_filename, pFile.getErrorMessage().c_str());
+ return NULL;
+ }
+
+ // Get the file size.
+ file_size = pFile.getSize();
+ if (pFile.hasError()) {
+ ALOGE("Failed to get size of file %s! (%s)", input_filename,
+ pFile.getErrorMessage().c_str());
+ return NULL;
+ }
+
+ // Abort on empty file.
+ if (file_size <= 0) {
+ ALOGE("Empty file %s to the object loader.", input_filename);
+ return NULL;
+ }
+
+ // Create memory map for the input file.
+ file_map = pFile.createMap(0, file_size, /* pIsReadOnly */true);
+ if ((file_map == NULL) || pFile.hasError()) {
+ ALOGE("Failed to map the file %s to the memory! (%s)", input_filename,
+ pFile.getErrorMessage().c_str());
+ return NULL;
+ }
+
+ // Delegate the load request.
+ result = Load(file_map->getDataPtr(), file_size, input_filename, pResolver,
+ pEnableGDBDebug);
+
+ // No whether the load is successful or not, file_map is no longer needed. On
+ // success, there's a copy of the object corresponded to the pFile in the
+ // memory. Therefore, file_map can be safely released.
+ file_map->release();
+
+ return result;
+}
+
+void *ObjectLoader::getSymbolAddress(const char *pName) const {
+ return mImpl->getSymbolAddress(pName);
+}
+
+ObjectLoader::~ObjectLoader() {
+ delete mImpl;
+ delete [] reinterpret_cast<uint8_t *>(mDebugImage);
+}
diff --git a/lib/ExecutionEngine/ObjectLoader.h b/lib/ExecutionEngine/ObjectLoader.h
new file mode 100644
index 0000000..6c2bc8c
--- /dev/null
+++ b/lib/ExecutionEngine/ObjectLoader.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2012, 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 BCC_EXECUTION_ENGINE_OBJECT_LOADER_H
+#define BCC_EXECUTION_ENGINE_OBJECT_LOADER_H
+
+#include <cstddef>
+
+namespace bcc {
+
+class FileBase;
+class ObjectLoaderImpl;
+class SymbolResolverInterface;
+
+class ObjectLoader {
+private:
+ ObjectLoaderImpl *mImpl;
+
+ void *mDebugImage;
+
+ ObjectLoader() : mImpl(NULL), mDebugImage(0) { }
+
+public:
+ // Load from a in-memory object. pName is a descriptive name of this memory.
+ static ObjectLoader *Load(void *pMemStart, size_t pMemSize, const char *pName,
+ SymbolResolverInterface &pResolver,
+ bool pEnableGDBDebug);
+
+ // Load from a file.
+ static ObjectLoader *Load(FileBase &pFile,
+ SymbolResolverInterface &pResolver,
+ bool pEnableGDBDebug);
+
+ void *getSymbolAddress(const char *pName) const;
+
+ ~ObjectLoader();
+};
+
+} // namespace bcc
+
+#endif // BCC_EXECUTION_ENGINE_OBJECT_LOADER_H
diff --git a/lib/ExecutionEngine/ObjectLoaderImpl.h b/lib/ExecutionEngine/ObjectLoaderImpl.h
new file mode 100644
index 0000000..81756f8
--- /dev/null
+++ b/lib/ExecutionEngine/ObjectLoaderImpl.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2012, 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 BCC_EXECUTION_ENGINE_OBJECT_LOADER_IMPL_H
+#define BCC_EXECUTION_ENGINE_OBJECT_LOADER_IMPL_H
+
+#include <cstring>
+
+namespace bcc {
+
+class SymbolResolverInterface;
+
+class ObjectLoaderImpl {
+public:
+ ObjectLoaderImpl() { }
+
+ virtual bool load(const void *pMem, size_t pMemSize) = 0;
+
+ virtual bool relocate(SymbolResolverInterface &pResolver) = 0;
+
+ virtual bool prepareDebugImage(void *pDebugImg, size_t pDebugImgSize) = 0;
+
+ virtual void *getSymbolAddress(const char *pName) const = 0;
+
+ virtual ~ObjectLoaderImpl() { }
+};
+
+} // namespace bcc
+
+#endif // BCC_EXECUTION_ENGINE_OBJECT_LOADER_IMPL_H
diff --git a/lib/ExecutionEngine/RSExecutable.cpp b/lib/ExecutionEngine/RSExecutable.cpp
new file mode 100644
index 0000000..46ec726
--- /dev/null
+++ b/lib/ExecutionEngine/RSExecutable.cpp
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2012, 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 "RSExecutable.h"
+
+#include "DebugHelper.h"
+#include "FileBase.h"
+#include "OutputFile.h"
+#include "SymbolResolverProxy.h"
+
+#include <utils/String8.h>
+
+using namespace bcc;
+
+const char *RSExecutable::SpecialFunctionNames[] = {
+ "root",
+ "init",
+ ".rs.dtor",
+ // Must be NULL-terminated.
+ NULL
+};
+
+RSExecutable *RSExecutable::Create(RSInfo &pInfo,
+ FileBase &pObjFile,
+ SymbolResolverProxy &pResolver) {
+ // Load the object file. Enable the GDB's JIT debugging if the script contains
+ // debug information.
+ ObjectLoader *loader = ObjectLoader::Load(pObjFile,
+ pResolver,
+ pInfo.hasDebugInformation());
+ if (loader == NULL) {
+ return NULL;
+ }
+
+ // Now, all things required to build a RSExecutable object are ready.
+ RSExecutable *result = new (std::nothrow) RSExecutable(pInfo,
+ pObjFile,
+ *loader);
+ if (result == NULL) {
+ ALOGE("Out of memory when create object to hold RS result file for %s!",
+ pObjFile.getName().c_str());
+ return NULL;
+ }
+
+ unsigned idx;
+ // Resolve addresses of RS export vars.
+ idx = 0;
+ const RSInfo::ExportVarNameListTy &export_var_names =
+ pInfo.getExportVarNames();
+ for (RSInfo::ExportVarNameListTy::const_iterator
+ var_iter = export_var_names.begin(),
+ var_end = export_var_names.end(); var_iter != var_end;
+ var_iter++, idx++) {
+ const char *name = *var_iter;
+ void *addr = result->getSymbolAddress(name);
+ if (addr == NULL) {
+ ALOGW("RS export var at entry #%u named %s cannot be found in the result "
+ "object!", idx, name);
+ }
+ result->mExportVarAddrs.push_back(addr);
+ }
+
+ // Resolve addresses of RS export functions.
+ idx = 0;
+ const RSInfo::ExportFuncNameListTy &export_func_names =
+ pInfo.getExportFuncNames();
+ for (RSInfo::ExportFuncNameListTy::const_iterator
+ func_iter = export_func_names.begin(),
+ func_end = export_func_names.end(); func_iter != func_end;
+ func_iter++, idx++) {
+ const char *name = *func_iter;
+ void *addr = result->getSymbolAddress(name);
+ if (addr == NULL) {
+ ALOGW("RS export func at entry #%u named %s cannot be found in the result"
+ " object!", idx, name);
+ }
+ result->mExportFuncAddrs.push_back(addr);
+ }
+
+ // Resolve addresses of expanded RS foreach function.
+ idx = 0;
+ const RSInfo::ExportForeachFuncListTy &export_foreach_funcs =
+ pInfo.getExportForeachFuncs();
+ for (RSInfo::ExportForeachFuncListTy::const_iterator
+ foreach_iter = export_foreach_funcs.begin(),
+ foreach_end = export_foreach_funcs.end();
+ foreach_iter != foreach_end; foreach_iter++, idx++) {
+ const char *func_name = foreach_iter->first;
+ android::String8 expanded_func_name(func_name);
+ expanded_func_name.append(".expand");
+ void *addr = result->getSymbolAddress(expanded_func_name.string());
+ if (addr == NULL) {
+ ALOGW("Expanded RS foreach at entry #%u named %s cannot be found in the "
+ "result object!", idx, expanded_func_name.string());
+ }
+ result->mExportForeachFuncAddrs.push_back(addr);
+ }
+
+ // Copy pragma key/value pairs from RSInfo::getPragmas() into mPragmaKeys and
+ // mPragmaValues, respectively.
+ const RSInfo::PragmaListTy &pragmas = pInfo.getPragmas();
+ for (RSInfo::PragmaListTy::const_iterator pragma_iter = pragmas.begin(),
+ pragma_end = pragmas.end(); pragma_iter != pragma_end;
+ pragma_iter++){
+ result->mPragmaKeys.push_back(pragma_iter->first);
+ result->mPragmaValues.push_back(pragma_iter->second);
+ }
+
+ return result;
+}
+
+bool RSExecutable::syncInfo(bool pForce) {
+ if (!pForce && !mIsInfoDirty) {
+ return true;
+ }
+
+ android::String8 info_path = RSInfo::GetPath(*mObjFile);
+ OutputFile info_file(info_path.string());
+
+ if (info_file.hasError()) {
+ ALOGE("Failed to open the info file %s for write! (%s)", info_path.string(),
+ info_file.getErrorMessage().c_str());
+ return false;
+ }
+
+ // Operation to the RS info file need to acquire the lock on the output file
+ // first.
+ if (!mObjFile->lock(FileBase::kWriteLock)) {
+ ALOGE("Write to RS info file %s required the acquisition of the write lock "
+ "on %s but got failure! (%s)", info_path.string(),
+ mObjFile->getName().c_str(), info_file.getErrorMessage().c_str());
+ return false;
+ }
+
+ // Perform the write.
+ if (!mInfo->write(info_file)) {
+ ALOGE("Failed to sync the RS info file %s!", info_path.string());
+ mObjFile->unlock();
+ return false;
+ }
+
+ mObjFile->unlock();
+ mIsInfoDirty = false;
+ return true;
+}
+
+RSExecutable::~RSExecutable() {
+ syncInfo();
+ delete mInfo;
+ delete mObjFile;
+ delete mLoader;
+}
diff --git a/lib/ExecutionEngine/RSExecutable.h b/lib/ExecutionEngine/RSExecutable.h
new file mode 100644
index 0000000..12e0f0a
--- /dev/null
+++ b/lib/ExecutionEngine/RSExecutable.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2012, 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 BCC_EXECUTION_ENGINE_RS_EXECUTABLE_H
+#define BCC_EXECUTION_ENGINE_RS_EXECUTABLE_H
+
+#include <cstddef>
+
+#include "DebugHelper.h"
+#include "ObjectLoader.h"
+#include "RSInfo.h"
+
+#include <utils/Vector.h>
+
+namespace bcc {
+
+class FileBase;
+class SymbolResolverProxy;
+
+/*
+ * RSExecutable holds the build results of a RSScript.
+ */
+class RSExecutable {
+private:
+ RSInfo *mInfo;
+ bool mIsInfoDirty;
+
+ FileBase *mObjFile;
+
+ ObjectLoader *mLoader;
+
+ // Memory address of rs export stuffs
+ android::Vector<void *> mExportVarAddrs;
+ android::Vector<void *> mExportFuncAddrs;
+ android::Vector<void *> mExportForeachFuncAddrs;
+
+ // FIXME: These are designed for RenderScript HAL and is initialized in
+ // RSExecutable::Create(). Both of them come from RSInfo::getPragmas().
+ // If possible, read the pragma key/value pairs directly from RSInfo.
+ android::Vector<const char *> mPragmaKeys;
+ android::Vector<const char *> mPragmaValues;
+
+ RSExecutable(RSInfo &pInfo, FileBase &pObjFile, ObjectLoader &pLoader)
+ : mInfo(&pInfo), mIsInfoDirty(false), mObjFile(&pObjFile), mLoader(&pLoader)
+ { }
+
+public:
+ // This is a NULL-terminated string array which specifies "Special" functions
+ // in RenderScript (e.g., root().)
+ static const char *SpecialFunctionNames[];
+
+ // Return NULL on error. If the return object is non-NULL, it claims the
+ // ownership of pInfo and pObjFile.
+ static RSExecutable *Create(RSInfo &pInfo,
+ FileBase &pObjFile,
+ SymbolResolverProxy &pResolver);
+
+ inline const RSInfo &getInfo() const
+ { return *mInfo; }
+
+ // Interfaces to RSInfo
+ inline bool isThreadable() const
+ { return mInfo->isThreadable(); }
+
+ inline void setThreadable(bool pThreadable = true) {
+ if (mInfo->isThreadable() != pThreadable) {
+ mInfo->setThreadable(pThreadable);
+ mIsInfoDirty = true;
+ }
+ return;
+ }
+
+ // Interfaces to ObjectLoader
+ inline void *getSymbolAddress(const char *pName) const
+ { return mLoader->getSymbolAddress(pName); }
+
+ bool syncInfo(bool pForce = false);
+
+ inline const android::Vector<void *> &getExportVarAddrs() const
+ { return mExportVarAddrs; }
+ inline const android::Vector<void *> &getExportFuncAddrs() const
+ { return mExportFuncAddrs; }
+ inline const android::Vector<void *> &getExportForeachFuncAddrs() const
+ { return mExportForeachFuncAddrs; }
+
+ inline const android::Vector<const char *> &getPragmaKeys() const
+ { return mPragmaKeys; }
+ inline const android::Vector<const char *> &getPragmaValues() const
+ { return mPragmaValues; }
+
+ ~RSExecutable();
+};
+
+} // end namespace bcc
+
+#endif // BCC_EXECUTION_ENGINE_RS_EXECUTABLE_H