Implement MemChunk::registerAllocFreeCallbacks().
This function allows a driver implementation to register its own handler for
allocating/freeing MemChunk objects. MemChunk is primarily used by the ELF
loader for various code/data segments.
Change-Id: If497f07a538c714933fcaa1b0c04ed5a6febeeba
diff --git a/Android.mk b/Android.mk
index eaed350..4675d65 100644
--- a/Android.mk
+++ b/Android.mk
@@ -40,6 +40,7 @@
LOCAL_SHARED_LIBRARIES += libbcc libbcinfo libLLVM libui libgui libsync
LOCAL_C_INCLUDES += frameworks/compile/libbcc/include
+LOCAL_C_INCLUDES += frameworks/rs/driver/linkloader/include
LOCAL_CFLAGS += $(rs_base_CFLAGS)
diff --git a/driver/linkloader/include/MemChunk.h b/driver/linkloader/include/MemChunk.h
index fb853e9..c4d78c9 100644
--- a/driver/linkloader/include/MemChunk.h
+++ b/driver/linkloader/include/MemChunk.h
@@ -18,12 +18,22 @@
#define MEM_CHUNK_H
#include <stddef.h>
+#include <stdint.h>
#include <stdlib.h>
+typedef void *(*AllocFunc) (size_t, uint32_t);
+typedef void (*FreeFunc) (void *);
+
class MemChunk {
private:
unsigned char *buf;
size_t buf_size;
+ bool bVendorBuf;
+
+ static AllocFunc VendorAlloc;
+ static FreeFunc VendorFree;
+
+ bool invalidBuf() const;
public:
MemChunk();
@@ -56,6 +66,12 @@
return buf_size;
}
+ // The allocation function must return page-aligned memory or we will be
+ // unable to mprotect the region appropriately.
+ static void registerAllocFreeCallbacks(AllocFunc a, FreeFunc f) {
+ VendorAlloc = a;
+ VendorFree = f;
+ }
};
#endif // MEM_CHUNK_H
diff --git a/driver/linkloader/lib/MemChunk.cpp b/driver/linkloader/lib/MemChunk.cpp
index 24dcf8e..c01305a 100644
--- a/driver/linkloader/lib/MemChunk.cpp
+++ b/driver/linkloader/lib/MemChunk.cpp
@@ -37,32 +37,49 @@
static uintptr_t StartAddr = 0x7e000000UL;
#endif
-MemChunk::MemChunk() : buf((unsigned char *)MAP_FAILED), buf_size(0) {
+AllocFunc MemChunk::VendorAlloc = NULL;
+FreeFunc MemChunk::VendorFree = NULL;
+
+MemChunk::MemChunk() : buf(NULL), buf_size(0), bVendorBuf(true) {
}
MemChunk::~MemChunk() {
- if (buf != MAP_FAILED) {
+ if (!invalidBuf() && bVendorBuf && VendorFree) {
+ (*VendorFree)(buf);
+ return;
+ }
+ if (!invalidBuf()) {
munmap(buf, buf_size);
}
}
+bool MemChunk::invalidBuf() const {
+ return (buf == 0 || buf == (unsigned char *)MAP_FAILED);
+}
+
bool MemChunk::allocate(size_t size) {
if (size == 0) {
return true;
}
+ if (VendorAlloc) {
+ buf = (unsigned char*)(*VendorAlloc)(size, 0);
+ }
+ if (invalidBuf()) {
+ bVendorBuf = false;
#if USE_FIXED_ADDR_MEM_CHUNK
- buf = (unsigned char *)mmap((void *)StartAddr, size,
- PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANON | MAP_32BIT,
- -1, 0);
+ buf = (unsigned char *)mmap((void *)StartAddr, size,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON | MAP_32BIT,
+ -1, 0);
#else
- buf = (unsigned char *)mmap(0, size,
- PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANON | MAP_32BIT,
- -1, 0);
+ buf = (unsigned char *)mmap(0, size,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON | MAP_32BIT,
+ -1, 0);
#endif
+ }
- if (buf == MAP_FAILED) {
+ if (invalidBuf()) {
return false;
}
@@ -75,7 +92,7 @@
}
void MemChunk::print() const {
- if (buf != MAP_FAILED) {
+ if (!invalidBuf()) {
dump_hex(buf, buf_size, 0, buf_size);
}
}
diff --git a/driver/rsdCore.cpp b/driver/rsdCore.cpp
index 3357969..4aad52a 100644
--- a/driver/rsdCore.cpp
+++ b/driver/rsdCore.cpp
@@ -20,6 +20,7 @@
#include "rsdAllocation.h"
#include "rsdBcc.h"
#ifndef RS_COMPATIBILITY_LIB
+ #include "MemChunk.h"
#include "rsdGL.h"
#include "rsdPath.h"
#include "rsdProgramStore.h"
@@ -189,7 +190,7 @@
}
rsc->mHal.drv = dc;
- dc->mCpuRef = RsdCpuReference::create((Context *)c, version_major, version_minor,
+ dc->mCpuRef = RsdCpuReference::create(rsc, version_major, version_minor,
&rsdLookupRuntimeStub, &LookupScript);
if (!dc->mCpuRef) {
ALOGE("RsdCpuReference::create for driver hal failed.");
@@ -202,6 +203,16 @@
if (false) {
dc->mCpuRef->setSetupCompilerCallback(NULL);
}
+
+ // Set a callback for switching MemChunk's allocator here.
+ // Note that the allocation function must return page-aligned memory, so
+ // that it can be mprotected properly (i.e. code should be written and
+ // later switched to read+execute only).
+ if (false) {
+ MemChunk::registerAllocFreeCallbacks(
+ rsc->mHal.funcs.allocRuntimeMem,
+ rsc->mHal.funcs.freeRuntimeMem);
+ }
#endif
return true;