diff options
author | Shih-wei Liao <sliao@google.com> | 2011-08-08 06:03:12 -0700 |
---|---|---|
committer | Shih-wei Liao <sliao@google.com> | 2011-08-09 06:18:35 -0700 |
commit | 768a6e8961ae16a5bcf6cab2b21405306b259a0b (patch) | |
tree | 880344c0d7a0baece062caccd2ad3d391783e522 | |
parent | fa06e91015017e8d0627d26a88e2a575643bec11 (diff) | |
download | linkloader-768a6e8961ae16a5bcf6cab2b21405306b259a0b.tar.gz |
Count size for common variable before relocate.
BUG=5057160.
Tested on x86, crespo and stingray.
TODO: I did a workaround for .lcomm directives bug of LLVM ARM MC code
generator. Remove this when the LLVM bug is fixed.
TODO: Need to refactor initSHNCommonDataSize.
Change-Id: I060c5306586224ddb92e79744c80f2a5925b3dff
-rw-r--r-- | include/ELFObject.h | 24 | ||||
-rw-r--r-- | include/impl/ELFObject.hxx | 45 |
2 files changed, 58 insertions, 11 deletions
diff --git a/include/ELFObject.h b/include/ELFObject.h index db3150e..a1a25b9 100644 --- a/include/ELFObject.h +++ b/include/ELFObject.h @@ -41,6 +41,18 @@ private: unsigned char *SHNCommonDataPtr; size_t SHNCommonDataFreeSize; + // TODO: Need refactor! + bool initSHNCommonDataSize(size_t SHNCommonDataSize) { + rsl_assert(!SHNCommonDataPtr && "Can't init twice."); + if (!SHNCommonData.allocate(SHNCommonDataSize)) { + return false; + } + + SHNCommonDataPtr = SHNCommonData.getBuffer(); + SHNCommonDataFreeSize = SHNCommonDataSize; + return true; + } + private: ELFObject() : SHNCommonDataPtr(NULL) { } @@ -65,17 +77,7 @@ public: void *allocateSHNCommonData(size_t size, size_t align = 1) { rsl_assert(size > 0 && align != 0); - enum { SHN_COMMON_DATA_SIZE = 0x40000 }; - - if (!SHNCommonDataPtr) { - // FIXME: We should not hard code these number! - if (!SHNCommonData.allocate(SHN_COMMON_DATA_SIZE)) { - return NULL; - } - - SHNCommonDataPtr = SHNCommonData.getBuffer(); - SHNCommonDataFreeSize = SHN_COMMON_DATA_SIZE; - } + rsl_assert(SHNCommonDataPtr && "Must init common data size before use!"); // Ensure alignment size_t rem = ((uintptr_t)SHNCommonDataPtr) % align; diff --git a/include/impl/ELFObject.hxx b/include/impl/ELFObject.hxx index 279a850..680cc4d 100644 --- a/include/impl/ELFObject.hxx +++ b/include/impl/ELFObject.hxx @@ -335,9 +335,54 @@ relocateX86_32(void *(*find_sym)(void *context, char const *name), } } +// TODO: Refactor all relocations. template <unsigned Bitwidth> inline void ELFObject<Bitwidth>:: relocate(void *(*find_sym)(void *context, char const *name), void *context) { + // Init SHNCommonDataSize. + // Need refactoring + size_t SHNCommonDataSize = 0; + + ELFSectionSymTabTy *symtab = + static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab")); + rsl_assert(symtab && "Symtab is required."); + + for (size_t i = 0; i < symtab->size(); ++i) { + ELFSymbolTy *sym = (*symtab)[i]; + + if (sym->getType() != STT_OBJECT) { + continue; + } + + size_t idx = (size_t)sym->getSectionIndex(); + switch (idx) { + default: + if ((*shtab)[idx]->getType() == SHT_NOBITS) { + // FIXME(logan): This is a workaround for .lcomm directives + // bug of LLVM ARM MC code generator. Remove this when the + // LLVM bug is fixed. + + size_t align = 16; + SHNCommonDataSize += (size_t)sym->getSize() + align; + } + break; + + case SHN_COMMON: + { + size_t align = 16; + SHNCommonDataSize += (size_t)sym->getSize() + align; + } + break; + + case SHN_ABS: + case SHN_UNDEF: + case SHN_XINDEX: + break; + } + } + if (!initSHNCommonDataSize(SHNCommonDataSize)) { + rsl_assert("Allocate memory for common variable fail!"); + } for (size_t i = 0; i < stab.size(); ++i) { ELFSectionHeaderTy *sh = (*shtab)[i]; |