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