Home | History | Annotate | Download | only in impl
      1 /*
      2  * Copyright 2011, The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef ELF_SYMBOL_HXX
     18 #define ELF_SYMBOL_HXX
     19 
     20 #include "ELFSectionHeaderTable.h"
     21 #include "ELFSection.h"
     22 #include "ELFSectionStrTab.h"
     23 
     24 #include "ELFObject.h"
     25 #include "ELFSectionHeaderTable.h"
     26 #include "ELFSectionProgBits.h"
     27 #include "ELFSectionNoBits.h"
     28 
     29 #include "utils/rsl_assert.h"
     30 #include "ELF.h"
     31 
     32 template <unsigned Bitwidth>
     33 inline char const *ELFSymbol_CRTP<Bitwidth>::getName() const {
     34   ELFSectionHeaderTableTy const &shtab = *owner->getSectionHeaderTable();
     35   size_t const index = shtab.getByName(std::string(".strtab"))->getIndex();
     36   ELFSectionTy const *section = owner->getSectionByIndex(index);
     37   ELFSectionStrTabTy const &strtab =
     38     *static_cast<ELFSectionStrTabTy const *>(section);
     39   return strtab[getNameIndex()];
     40 }
     41 
     42 template <unsigned Bitwidth>
     43 template <typename Archiver>
     44 inline ELFSymbol<Bitwidth> *
     45 ELFSymbol_CRTP<Bitwidth>::read(Archiver &AR,
     46                                ELFObjectTy const *owner,
     47                                size_t index) {
     48   if (!AR) {
     49     // Archiver is in bad state before calling read function.
     50     // Return NULL and do nothing.
     51     return 0;
     52   }
     53 
     54   llvm::OwningPtr<ELFSymbolTy> sh(new ELFSymbolTy());
     55 
     56   if (!sh->serialize(AR)) {
     57     // Unable to read the structure.  Return NULL.
     58     return 0;
     59   }
     60 
     61   if (!sh->isValid()) {
     62     // SymTabEntry read from archiver is not valid.  Return NULL.
     63     return 0;
     64   }
     65 
     66   // Set the section header index
     67   sh->index = index;
     68 
     69   // Set the owner elf object
     70   sh->owner = owner;
     71 
     72   return sh.take();
     73 }
     74 
     75 template <unsigned Bitwidth>
     76 inline void ELFSymbol_CRTP<Bitwidth>::print(bool shouldPrintHeader) const {
     77   using namespace llvm;
     78 
     79   if (shouldPrintHeader) {
     80     out() << '\n' << fillformat('=', 79) << '\n';
     81     out().changeColor(raw_ostream::WHITE, true);
     82     out() << "ELF Symbol Table Entry "
     83           << this->getIndex() << '\n';
     84     out().resetColor();
     85     out() << fillformat('-', 79) << '\n';
     86   } else {
     87     out() << fillformat('-', 79) << '\n';
     88     out().changeColor(raw_ostream::YELLOW, true);
     89     out() << "ELF Symbol Table Entry "
     90           << this->getIndex() << " : " << '\n';
     91     out().resetColor();
     92   }
     93 
     94 #define PRINT_LINT(title, value) \
     95   out() << format("  %-11s : ", (char const *)(title)) << (value) << '\n'
     96   PRINT_LINT("Name",        getName()                                    );
     97   PRINT_LINT("Type",        getTypeStr(getType())                        );
     98   PRINT_LINT("Bind",        getBindingAttributeStr(getBindingAttribute()));
     99   PRINT_LINT("Visibility",  getVisibilityStr(getVisibility())            );
    100   PRINT_LINT("Shtab Index", getSectionIndex()                            );
    101   PRINT_LINT("Value",       getValue()                                   );
    102   PRINT_LINT("Size",        getSize()                                    );
    103 #undef PRINT_LINT
    104 
    105 // TODO: Horizontal type or vertical type can use option to decide.
    106 #if 0
    107   using namespace term::color;
    108   using namespace std;
    109 
    110   cout << setw(20) << getName() <<
    111           setw(10) << getTypeStr(getType()) <<
    112           setw(10) << getBindingAttributeStr(getBindingAttribute()) <<
    113           setw(15) << getVisibilityStr(getVisibility()) <<
    114           setw(10) << getSectionIndex() <<
    115           setw(7) << getValue() <<
    116           setw(7) << getSize() <<
    117           endl;
    118 #endif
    119 }
    120 
    121 template <unsigned Bitwidth>
    122 void *ELFSymbol_CRTP<Bitwidth>::getAddress(int machine, bool autoAlloc) const {
    123   if (my_addr != 0) {
    124     return my_addr;
    125   }
    126   size_t idx = (size_t)getSectionIndex();
    127   switch (getType()) {
    128     default:
    129       break;
    130 
    131     case STT_OBJECT:
    132       switch (idx) {
    133         default:
    134           {
    135             ELFSectionHeaderTableTy const *header =
    136               owner->getSectionHeaderTable();
    137 
    138             unsigned section_type = (*header)[idx]->getType();
    139 
    140             rsl_assert((section_type == SHT_PROGBITS ||
    141                         section_type == SHT_NOBITS) &&
    142                        "STT_OBJECT with not BITS section.");
    143 
    144             if (section_type == SHT_NOBITS) {
    145               // FIXME(logan): This is a workaround for .lcomm directives
    146               // bug of LLVM ARM MC code generator.  Remove this when the
    147               // LLVM bug is fixed.
    148 
    149               size_t align = 16;
    150 
    151               my_addr = const_cast<ELFObjectTy *>(owner)->
    152                 allocateSHNCommonData((size_t)getSize(), align);
    153 
    154               if (!my_addr) {
    155                 rsl_assert(0 && "Unable to allocate memory for SHN_COMMON.");
    156                 abort();
    157               }
    158             } else {
    159               ELFSectionTy const *sec = owner->getSectionByIndex(idx);
    160               rsl_assert(sec != 0 && "STT_OBJECT with null section.");
    161 
    162               ELFSectionBitsTy const &st =
    163                 static_cast<ELFSectionBitsTy const &>(*sec);
    164               my_addr =const_cast<unsigned char *>(&st[0] + (off_t)getValue());
    165             }
    166           }
    167           break;
    168 
    169         case SHN_COMMON:
    170           {
    171             if (!autoAlloc) {
    172               return NULL;
    173             }
    174 #if 0
    175 #if _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600
    176             if (posix_memalign(&my_addr,
    177                                std::max((size_t)getValue(), sizeof(void*)),
    178                                (size_t)getSize()) != 0) {
    179               rsl_assert(0 && "posix_memalign failed.");
    180             }
    181 #else
    182             my_addr = memalign(std::max((size_t)getValue(), sizeof(void *)),
    183                                (size_t)getSize());
    184 
    185             rsl_assert(my_addr != NULL && "memalign failed.");
    186 #endif
    187             if (my_addr) {
    188               memset(my_addr, '\0', getSize());
    189             }
    190 #else
    191             size_t align = (size_t)getValue();
    192             my_addr = const_cast<ELFObjectTy *>(owner)->
    193                           allocateSHNCommonData((size_t)getSize(), align);
    194             if (!my_addr) {
    195               rsl_assert(0 && "Unable to allocate memory for SHN_COMMON.");
    196               abort();
    197             }
    198 #endif
    199           }
    200           break;
    201 
    202         case SHN_UNDEF:
    203           if (machine == EM_MIPS && strcmp(getName(), "_gp_disp") == 0) // OK for MIPS
    204             break;
    205 
    206         case SHN_ABS:
    207         case SHN_XINDEX:
    208           rsl_assert(0 && "STT_OBJECT with special st_shndx.");
    209           break;
    210       }
    211       break;
    212 
    213 
    214     case STT_FUNC:
    215       switch (idx) {
    216         default:
    217           {
    218 #ifndef NDEBUG
    219             ELFSectionHeaderTableTy const *header =
    220               owner->getSectionHeaderTable();
    221             rsl_assert((*header)[idx]->getType() == SHT_PROGBITS &&
    222                    "STT_FUNC with not PROGBITS section.");
    223 #endif
    224             ELFSectionTy const *sec = owner->getSectionByIndex(idx);
    225             rsl_assert(sec != 0 && "STT_FUNC with null section.");
    226 
    227             ELFSectionProgBitsTy const &st =
    228               static_cast<ELFSectionProgBitsTy const &>(*sec);
    229             my_addr = const_cast<unsigned char *>(&st[0] + (off_t)getValue());
    230           }
    231           break;
    232 
    233         case SHN_ABS:
    234         case SHN_COMMON:
    235         case SHN_UNDEF:
    236         case SHN_XINDEX:
    237           rsl_assert(0 && "STT_FUNC with special st_shndx.");
    238           break;
    239       }
    240       break;
    241 
    242 
    243     case STT_SECTION:
    244       switch (idx) {
    245         default:
    246           {
    247 #ifndef NDEBUG
    248             ELFSectionHeaderTableTy const *header =
    249               owner->getSectionHeaderTable();
    250             rsl_assert(((*header)[idx]->getType() == SHT_PROGBITS ||
    251                     (*header)[idx]->getType() == SHT_NOBITS) &&
    252                    "STT_SECTION with not BITS section.");
    253 #endif
    254             ELFSectionTy const *sec = owner->getSectionByIndex(idx);
    255             rsl_assert(sec != 0 && "STT_SECTION with null section.");
    256 
    257             ELFSectionBitsTy const &st =
    258               static_cast<ELFSectionBitsTy const &>(*sec);
    259             my_addr = const_cast<unsigned char *>(&st[0] + (off_t)getValue());
    260           }
    261           break;
    262 
    263         case SHN_ABS:
    264         case SHN_COMMON:
    265         case SHN_UNDEF:
    266         case SHN_XINDEX:
    267           rsl_assert(0 && "STT_SECTION with special st_shndx.");
    268           break;
    269       }
    270       break;
    271 
    272     case STT_NOTYPE:
    273       switch (idx) {
    274         default:
    275           {
    276 #ifndef NDEBUG
    277             ELFSectionHeaderTableTy const *header =
    278               owner->getSectionHeaderTable();
    279             rsl_assert(((*header)[idx]->getType() == SHT_PROGBITS ||
    280                     (*header)[idx]->getType() == SHT_NOBITS) &&
    281                    "STT_SECTION with not BITS section.");
    282 #endif
    283             ELFSectionTy const *sec = owner->getSectionByIndex(idx);
    284             rsl_assert(sec != 0 && "STT_SECTION with null section.");
    285 
    286             ELFSectionBitsTy const &st =
    287               static_cast<ELFSectionBitsTy const &>(*sec);
    288             my_addr = const_cast<unsigned char *>(&st[0] + (off_t)getValue());
    289           }
    290           break;
    291 
    292         case SHN_ABS:
    293         case SHN_COMMON:
    294         case SHN_XINDEX:
    295           rsl_assert(0 && "STT_SECTION with special st_shndx.");
    296           break;
    297         case SHN_UNDEF:
    298           return 0;
    299       }
    300       break;
    301       return 0;
    302 
    303     case STT_COMMON:
    304     case STT_FILE:
    305     case STT_TLS:
    306     case STT_LOOS:
    307     case STT_HIOS:
    308     case STT_LOPROC:
    309     case STT_HIPROC:
    310       rsl_assert(0 && "Not implement.");
    311       return 0;
    312   }
    313   return my_addr;
    314 }
    315 
    316 #endif // ELF_SYMBOL_HXX
    317