summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Hsieh <andrewhsieh@google.com>2011-11-22 00:04:41 -0800
committerAndrew Hsieh <andrewhsieh@google.com>2011-11-22 00:08:09 -0800
commit72dca268900fa25946bade332f0fbdc2c2ff9487 (patch)
tree628c73b47de36dd50bfe0b6ed00cd425991fc079
parentf1f0810dd01271b1769ca69526a606fa320820e9 (diff)
downloadlinkloader-72dca268900fa25946bade332f0fbdc2c2ff9487.tar.gz
Enhance to relocate cross-compiled binary
Change-Id: I070a3a8a2d1d5f5b18e4062a299ecc9cb5e92a51
-rw-r--r--include/ELFSectionProgBits.h28
-rw-r--r--include/StubLayout.h23
-rw-r--r--include/impl/ELFObject.hxx13
-rw-r--r--include/impl/ELFSectionProgBits.hxx49
-rw-r--r--include/impl/ELFSymbol.hxx4
-rw-r--r--lib/StubLayout.cpp40
6 files changed, 91 insertions, 66 deletions
diff --git a/include/ELFSectionProgBits.h b/include/ELFSectionProgBits.h
index 54388bc..e0da71e 100644
--- a/include/ELFSectionProgBits.h
+++ b/include/ELFSectionProgBits.h
@@ -29,9 +29,7 @@ public:
ELF_TYPE_INTRO_TO_TEMPLATE_SCOPE(Bitwidth);
private:
-#ifdef __arm__
- StubLayout stubs;
-#endif
+ StubLayout *stubs;
public:
template <typename Archiver>
@@ -39,11 +37,29 @@ public:
ELFObjectTy *owner,
ELFSectionHeaderTy const *sh);
-#ifdef __arm__
StubLayout *getStubLayout() {
- return &stubs;
+ return stubs;
+ }
+
+ ELFSectionProgBits(int machine) {
+ switch(machine) {
+ case EM_ARM:
+ stubs = new StubLayoutARM();
+ break;
+
+ case EM_MIPS:
+ stubs = new StubLayoutMIPS();
+ break;
+
+ default:
+ stubs = NULL;
+ }
+ }
+
+ ~ELFSectionProgBits() {
+ if (stubs)
+ delete stubs;
}
-#endif
private:
template <typename Archiver>
diff --git a/include/StubLayout.h b/include/StubLayout.h
index c6f5f20..9705743 100644
--- a/include/StubLayout.h
+++ b/include/StubLayout.h
@@ -29,15 +29,36 @@ private:
public:
StubLayout();
+ virtual ~StubLayout() { }
void initStubTable(unsigned char *table, size_t count);
void *allocateStub(void *addr = 0);
size_t calcStubTableSize(size_t count) const;
+ virtual size_t getUnitStubSize() const = 0;
private:
- void setStubAddress(void *stub, void *addr);
+ virtual void setStubAddress(void *stub, void *addr) = 0;
};
+class StubLayoutARM : public StubLayout {
+public:
+ StubLayoutARM() { }
+ size_t getUnitStubSize() const;
+
+private:
+ virtual void setStubAddress(void *stub, void *addr);
+};
+
+class StubLayoutMIPS : public StubLayout {
+public:
+ StubLayoutMIPS() { }
+ size_t getUnitStubSize() const;
+
+private:
+ virtual void setStubAddress(void *stub, void *addr);
+};
+
+
#endif // STUB_LAYOUT_H
diff --git a/include/impl/ELFObject.hxx b/include/impl/ELFObject.hxx
index f47db79..83a1bc6 100644
--- a/include/impl/ELFObject.hxx
+++ b/include/impl/ELFObject.hxx
@@ -192,9 +192,15 @@ relocateARM(void *(*find_sym)(void *context, char const *name),
break;
}
-#if __arm__
// Get the stub for this function
- void *stub = text->getStubLayout()->allocateStub(callee_addr);
+ StubLayout *stub_layout = text->getStubLayout();
+
+ if (!stub_layout) {
+ llvm::errs() << "unable to get stub layout." << "\n";
+ abort();
+ }
+
+ void *stub = stub_layout->allocateStub(callee_addr);
if (!stub) {
llvm::errs() << "unable to allocate stub." << "\n";
@@ -203,9 +209,6 @@ relocateARM(void *(*find_sym)(void *context, char const *name),
//LOGI("Function %s: using stub %p\n", sym->getName(), stub);
S = (uint32_t)(uintptr_t)stub;
-#else
- S = (uint32_t)(uintptr_t)callee_addr;
-#endif
// Relocate the R_ARM_CALL relocation type
uint32_t result = (S >> 2) - (P >> 2) + A;
diff --git a/include/impl/ELFSectionProgBits.hxx b/include/impl/ELFSectionProgBits.hxx
index 61ec76c..ac83f61 100644
--- a/include/impl/ELFSectionProgBits.hxx
+++ b/include/impl/ELFSectionProgBits.hxx
@@ -33,42 +33,41 @@ ELFSectionProgBits<Bitwidth> *
ELFSectionProgBits<Bitwidth>::read(Archiver &AR,
ELFObjectTy *owner,
ELFSectionHeaderTy const *sh) {
+ int machine = owner->getHeader()->getMachine();
+ ELFSectionProgBits *secp = new ELFSectionProgBits(machine);
+ llvm::OwningPtr<ELFSectionProgBits> result(secp);
+ size_t max_num_stubs = 0;
+ size_t alloc_size = (sh->getSize() + 3) / 4 * 4;
+ StubLayout *stubs = result->getStubLayout();
+ if (stubs) {
+ // Compute the maximal possible numbers of stubs
+ std::string reltab_name(".rel" + std::string(sh->getName()));
- llvm::OwningPtr<ELFSectionProgBits> result(new ELFSectionProgBits());
+ ELFSectionRelTableTy const *reltab =
+ static_cast<ELFSectionRelTableTy *>(
+ owner->getSectionByName(reltab_name.c_str()));
-#ifdef __arm__
- // Compute the maximal possible numbers of stubs
- std::string reltab_name(".rel" + std::string(sh->getName()));
+ if (reltab) {
+ // If we have relocation table, then get the approximation of
+ // maximum numbers of stubs.
+ max_num_stubs = reltab->getMaxNumStubs(owner);
+ }
- ELFSectionRelTableTy const *reltab =
- static_cast<ELFSectionRelTableTy *>(
- owner->getSectionByName(reltab_name.c_str()));
+ // Compute the stub table size
+ size_t stub_table_size = stubs->calcStubTableSize(max_num_stubs);
- size_t max_num_stubs = 0;
-
- if (reltab) {
- // If we have relocation table, then get the approximation of maximum
- // numbers of stubs.
- max_num_stubs = reltab->getMaxNumStubs(owner);
+ // Allocate PROGBITS section with stubs table
+ alloc_size += stub_table_size;
}
- // Compute the stub table size
- StubLayout *stubs = result->getStubLayout();
- size_t stub_table_size = stubs->calcStubTableSize(max_num_stubs);
-
- // Allocate PROGBITS section with stubs table
- size_t alloc_size = ((sh->getSize() + 3) / 4 * 4) + stub_table_size;
+ // Allocate text section
if (!result->chunk.allocate(alloc_size)) {
return NULL;
}
- stubs->initStubTable(result->chunk.getBuffer()+sh->getSize(), max_num_stubs);
-#else
- // Allocate text section
- if (!result->chunk.allocate(sh->getSize())) {
- return NULL;
+ if (stubs) {
+ stubs->initStubTable(result->chunk.getBuffer()+sh->getSize(), max_num_stubs);
}
-#endif
result->sh = sh;
diff --git a/include/impl/ELFSymbol.hxx b/include/impl/ELFSymbol.hxx
index 04166f7..e52a43e 100644
--- a/include/impl/ELFSymbol.hxx
+++ b/include/impl/ELFSymbol.hxx
@@ -29,10 +29,8 @@
#include "utils/rsl_assert.h"
#include "ELF.h"
-#ifdef __arm__
#define LOG_TAG "bcc"
#include "cutils/log.h"
-#endif
template <unsigned Bitwidth>
inline char const *ELFSymbol_CRTP<Bitwidth>::getName() const {
@@ -170,7 +168,6 @@ void *ELFSymbol_CRTP<Bitwidth>::getAddress(bool autoAlloc) const {
}
#if 0
-#ifdef __arm__
LOGD("Symbol %s\n", getName());
if (strcmp(getName(), "camera") == 0) {
uint32_t *p = (uint32_t *)(&st[0] + (size_t)getValue());
@@ -180,7 +177,6 @@ void *ELFSymbol_CRTP<Bitwidth>::getAddress(bool autoAlloc) const {
LOGD(" | %08x %08x %08x %08x\n", p[12], p[13], p[14], p[15]);
}
#endif
-#endif
}
break;
diff --git a/lib/StubLayout.cpp b/lib/StubLayout.cpp
index bb1772d..977fb63 100644
--- a/lib/StubLayout.cpp
+++ b/lib/StubLayout.cpp
@@ -24,12 +24,6 @@
#include <stdlib.h>
#include <sys/mman.h>
-#if defined(__arm__)
-#define STUB_SIZE 8
-#elif defined(__mips__)
-#define STUB_SIZE 16
-#endif
-
StubLayout::StubLayout() : table(NULL), count(0) {
}
@@ -39,7 +33,6 @@ void StubLayout::initStubTable(unsigned char *table_, size_t count_) {
}
void *StubLayout::allocateStub(void *addr) {
-#if defined(__arm__) || defined(__mips__)
// Check if we have created this stub or not.
std::map<void *, void *>::iterator index_iter = stub_index.find(addr);
@@ -59,18 +52,21 @@ void *StubLayout::allocateStub(void *addr) {
stub_index.insert(std::make_pair(addr, stub));
// Increase the free stub slot pointer
- table += STUB_SIZE;
+ table += getUnitStubSize();
count--;
return stub;
+}
+
+size_t StubLayout::calcStubTableSize(size_t count) const {
+ return count * getUnitStubSize();
+}
-#else
- return NULL;
-#endif
+size_t StubLayoutARM::getUnitStubSize() const {
+ return 8;
}
-void StubLayout::setStubAddress(void *stub_, void *addr) {
-#if defined(__arm__)
+void StubLayoutARM::setStubAddress(void *stub_, void *addr) {
uint8_t *stub = (uint8_t *)stub_;
stub[0] = 0x04; // ldr pc, [pc, #-4]
stub[1] = 0xf0; // ldr pc, [pc, #-4]
@@ -79,8 +75,13 @@ void StubLayout::setStubAddress(void *stub_, void *addr) {
void **target = (void **)(stub + 4);
*target = addr;
+}
-#elif defined(__mips__)
+size_t StubLayoutMIPS::getUnitStubSize() const {
+ return 16;
+}
+
+void StubLayoutMIPS::setStubAddress(void *stub_, void *addr) {
uint32_t addr32 = (uint32_t)(uintptr_t)addr;
uint16_t addr_hi16 = (addr32 >> 16) & 0xffff;
uint16_t addr_lo16 = addr32 & 0xffff;
@@ -90,16 +91,5 @@ void StubLayout::setStubAddress(void *stub_, void *addr) {
stub[1] = 0x37390000ul | addr_lo16; // ori
stub[2] = 0x03200008ul; // jr (jump register)
stub[3] = 0x00000000ul; // nop
-
-#else
- rsl_assert(0 && "Stub is not supported on this platform");
-#endif
}
-size_t StubLayout::calcStubTableSize(size_t count) const {
-#if defined(__arm__) || defined(__mips__)
- return count * STUB_SIZE;
-#else
- return 0;
-#endif
-}