diff options
author | Andrew Hsieh <andrewhsieh@google.com> | 2011-11-22 00:04:41 -0800 |
---|---|---|
committer | Andrew Hsieh <andrewhsieh@google.com> | 2011-11-22 00:08:09 -0800 |
commit | 72dca268900fa25946bade332f0fbdc2c2ff9487 (patch) | |
tree | 628c73b47de36dd50bfe0b6ed00cd425991fc079 | |
parent | f1f0810dd01271b1769ca69526a606fa320820e9 (diff) | |
download | linkloader-72dca268900fa25946bade332f0fbdc2c2ff9487.tar.gz |
Enhance to relocate cross-compiled binary
Change-Id: I070a3a8a2d1d5f5b18e4062a299ecc9cb5e92a51
-rw-r--r-- | include/ELFSectionProgBits.h | 28 | ||||
-rw-r--r-- | include/StubLayout.h | 23 | ||||
-rw-r--r-- | include/impl/ELFObject.hxx | 13 | ||||
-rw-r--r-- | include/impl/ELFSectionProgBits.hxx | 49 | ||||
-rw-r--r-- | include/impl/ELFSymbol.hxx | 4 | ||||
-rw-r--r-- | lib/StubLayout.cpp | 40 |
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 -} |