| /* |
| * Copyright 2011, 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 ELF_SYMBOL_HXX |
| #define ELF_SYMBOL_HXX |
| |
| #include "ELFSectionHeaderTable.h" |
| #include "ELFSection.h" |
| #include "ELFSectionStrTab.h" |
| |
| #include "ELFObject.h" |
| #include "ELFSectionHeaderTable.h" |
| #include "ELFSectionProgBits.h" |
| #include "ELFSectionNoBits.h" |
| |
| #include "utils/rsl_assert.h" |
| #include "ELF.h" |
| |
| template <unsigned Bitwidth> |
| inline char const *ELFSymbol_CRTP<Bitwidth>::getName() const { |
| ELFSectionHeaderTableTy const &shtab = *owner->getSectionHeaderTable(); |
| size_t const index = shtab.getByName(std::string(".strtab"))->getIndex(); |
| ELFSectionTy const *section = owner->getSectionByIndex(index); |
| ELFSectionStrTabTy const &strtab = |
| *static_cast<ELFSectionStrTabTy const *>(section); |
| return strtab[getNameIndex()]; |
| } |
| |
| template <unsigned Bitwidth> |
| template <typename Archiver> |
| inline ELFSymbol<Bitwidth> * |
| ELFSymbol_CRTP<Bitwidth>::read(Archiver &AR, |
| ELFObjectTy const *owner, |
| size_t index) { |
| if (!AR) { |
| // Archiver is in bad state before calling read function. |
| // Return NULL and do nothing. |
| return 0; |
| } |
| |
| llvm::OwningPtr<ELFSymbolTy> sh(new ELFSymbolTy()); |
| |
| if (!sh->serialize(AR)) { |
| // Unable to read the structure. Return NULL. |
| return 0; |
| } |
| |
| if (!sh->isValid()) { |
| // SymTabEntry read from archiver is not valid. Return NULL. |
| return 0; |
| } |
| |
| // Set the section header index |
| sh->index = index; |
| |
| // Set the owner elf object |
| sh->owner = owner; |
| |
| return sh.take(); |
| } |
| |
| template <unsigned Bitwidth> |
| inline void ELFSymbol_CRTP<Bitwidth>::print(bool shouldPrintHeader) const { |
| using namespace llvm; |
| |
| if (shouldPrintHeader) { |
| out() << '\n' << fillformat('=', 79) << '\n'; |
| out().changeColor(raw_ostream::WHITE, true); |
| out() << "ELF Symbol Table Entry " |
| << this->getIndex() << '\n'; |
| out().resetColor(); |
| out() << fillformat('-', 79) << '\n'; |
| } else { |
| out() << fillformat('-', 79) << '\n'; |
| out().changeColor(raw_ostream::YELLOW, true); |
| out() << "ELF Symbol Table Entry " |
| << this->getIndex() << " : " << '\n'; |
| out().resetColor(); |
| } |
| |
| #define PRINT_LINT(title, value) \ |
| out() << format(" %-11s : ", (char const *)(title)) << (value) << '\n' |
| PRINT_LINT("Name", getName() ); |
| PRINT_LINT("Type", getTypeStr(getType()) ); |
| PRINT_LINT("Bind", getBindingAttributeStr(getBindingAttribute())); |
| PRINT_LINT("Visibility", getVisibilityStr(getVisibility()) ); |
| PRINT_LINT("Shtab Index", getSectionIndex() ); |
| PRINT_LINT("Value", getValue() ); |
| PRINT_LINT("Size", getSize() ); |
| #undef PRINT_LINT |
| |
| // TODO: Horizontal type or vertical type can use option to decide. |
| #if 0 |
| using namespace term::color; |
| using namespace std; |
| |
| cout << setw(20) << getName() << |
| setw(10) << getTypeStr(getType()) << |
| setw(10) << getBindingAttributeStr(getBindingAttribute()) << |
| setw(15) << getVisibilityStr(getVisibility()) << |
| setw(10) << getSectionIndex() << |
| setw(7) << getValue() << |
| setw(7) << getSize() << |
| endl; |
| #endif |
| } |
| |
| template <unsigned Bitwidth> |
| void *ELFSymbol_CRTP<Bitwidth>::getAddress(int machine, bool autoAlloc) const { |
| if (my_addr != 0) { |
| return my_addr; |
| } |
| size_t idx = (size_t)getSectionIndex(); |
| switch (getType()) { |
| default: |
| break; |
| |
| case STT_OBJECT: |
| switch (idx) { |
| default: |
| { |
| ELFSectionHeaderTableTy const *header = |
| owner->getSectionHeaderTable(); |
| |
| unsigned section_type = (*header)[idx]->getType(); |
| |
| rsl_assert((section_type == SHT_PROGBITS || |
| section_type == SHT_NOBITS) && |
| "STT_OBJECT with not BITS section."); |
| |
| if (section_type == 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; |
| |
| my_addr = const_cast<ELFObjectTy *>(owner)-> |
| allocateSHNCommonData((size_t)getSize(), align); |
| |
| if (!my_addr) { |
| rsl_assert(0 && "Unable to allocate memory for SHN_COMMON."); |
| abort(); |
| } |
| } else { |
| ELFSectionTy const *sec = owner->getSectionByIndex(idx); |
| rsl_assert(sec != 0 && "STT_OBJECT with null section."); |
| |
| ELFSectionBitsTy const &st = |
| static_cast<ELFSectionBitsTy const &>(*sec); |
| my_addr =const_cast<unsigned char *>(&st[0] + (off_t)getValue()); |
| } |
| } |
| break; |
| |
| case SHN_COMMON: |
| { |
| if (!autoAlloc) { |
| return NULL; |
| } |
| #if 0 |
| #if _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 |
| if (posix_memalign(&my_addr, |
| std::max((size_t)getValue(), sizeof(void*)), |
| (size_t)getSize()) != 0) { |
| rsl_assert(0 && "posix_memalign failed."); |
| } |
| #else |
| my_addr = memalign(std::max((size_t)getValue(), sizeof(void *)), |
| (size_t)getSize()); |
| |
| rsl_assert(my_addr != NULL && "memalign failed."); |
| #endif |
| if (my_addr) { |
| memset(my_addr, '\0', getSize()); |
| } |
| #else |
| size_t align = (size_t)getValue(); |
| my_addr = const_cast<ELFObjectTy *>(owner)-> |
| allocateSHNCommonData((size_t)getSize(), align); |
| if (!my_addr) { |
| rsl_assert(0 && "Unable to allocate memory for SHN_COMMON."); |
| abort(); |
| } |
| #endif |
| } |
| break; |
| |
| case SHN_UNDEF: |
| if (machine == EM_MIPS && strcmp(getName(), "_gp_disp") == 0) // OK for MIPS |
| break; |
| |
| case SHN_ABS: |
| case SHN_XINDEX: |
| rsl_assert(0 && "STT_OBJECT with special st_shndx."); |
| break; |
| } |
| break; |
| |
| |
| case STT_FUNC: |
| switch (idx) { |
| default: |
| { |
| #ifndef NDEBUG |
| ELFSectionHeaderTableTy const *header = |
| owner->getSectionHeaderTable(); |
| rsl_assert((*header)[idx]->getType() == SHT_PROGBITS && |
| "STT_FUNC with not PROGBITS section."); |
| #endif |
| ELFSectionTy const *sec = owner->getSectionByIndex(idx); |
| rsl_assert(sec != 0 && "STT_FUNC with null section."); |
| |
| ELFSectionProgBitsTy const &st = |
| static_cast<ELFSectionProgBitsTy const &>(*sec); |
| my_addr = const_cast<unsigned char *>(&st[0] + (off_t)getValue()); |
| } |
| break; |
| |
| case SHN_ABS: |
| case SHN_COMMON: |
| case SHN_UNDEF: |
| case SHN_XINDEX: |
| rsl_assert(0 && "STT_FUNC with special st_shndx."); |
| break; |
| } |
| break; |
| |
| |
| case STT_SECTION: |
| switch (idx) { |
| default: |
| { |
| #ifndef NDEBUG |
| ELFSectionHeaderTableTy const *header = |
| owner->getSectionHeaderTable(); |
| rsl_assert(((*header)[idx]->getType() == SHT_PROGBITS || |
| (*header)[idx]->getType() == SHT_NOBITS) && |
| "STT_SECTION with not BITS section."); |
| #endif |
| ELFSectionTy const *sec = owner->getSectionByIndex(idx); |
| rsl_assert(sec != 0 && "STT_SECTION with null section."); |
| |
| ELFSectionBitsTy const &st = |
| static_cast<ELFSectionBitsTy const &>(*sec); |
| my_addr = const_cast<unsigned char *>(&st[0] + (off_t)getValue()); |
| } |
| break; |
| |
| case SHN_ABS: |
| case SHN_COMMON: |
| case SHN_UNDEF: |
| case SHN_XINDEX: |
| rsl_assert(0 && "STT_SECTION with special st_shndx."); |
| break; |
| } |
| break; |
| |
| case STT_NOTYPE: |
| switch (idx) { |
| default: |
| { |
| #ifndef NDEBUG |
| ELFSectionHeaderTableTy const *header = |
| owner->getSectionHeaderTable(); |
| rsl_assert(((*header)[idx]->getType() == SHT_PROGBITS || |
| (*header)[idx]->getType() == SHT_NOBITS) && |
| "STT_SECTION with not BITS section."); |
| #endif |
| ELFSectionTy const *sec = owner->getSectionByIndex(idx); |
| rsl_assert(sec != 0 && "STT_SECTION with null section."); |
| |
| ELFSectionBitsTy const &st = |
| static_cast<ELFSectionBitsTy const &>(*sec); |
| my_addr = const_cast<unsigned char *>(&st[0] + (off_t)getValue()); |
| } |
| break; |
| |
| case SHN_ABS: |
| case SHN_COMMON: |
| case SHN_XINDEX: |
| rsl_assert(0 && "STT_SECTION with special st_shndx."); |
| break; |
| case SHN_UNDEF: |
| return 0; |
| } |
| break; |
| return 0; |
| |
| case STT_COMMON: |
| case STT_FILE: |
| case STT_TLS: |
| case STT_LOOS: |
| case STT_HIOS: |
| case STT_LOPROC: |
| case STT_HIPROC: |
| rsl_assert(0 && "Not implement."); |
| return 0; |
| } |
| return my_addr; |
| } |
| |
| #endif // ELF_SYMBOL_HXX |