Home | History | Annotate | Download | only in libunwindstack
      1 /*
      2  * Copyright (C) 2016 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 #include <elf.h>
     18 #include <string.h>
     19 
     20 #include <memory>
     21 #include <string>
     22 
     23 #define LOG_TAG "unwind"
     24 #include <log/log.h>
     25 
     26 #include "Elf.h"
     27 #include "ElfInterface.h"
     28 #include "ElfInterfaceArm.h"
     29 #include "Machine.h"
     30 #include "Memory.h"
     31 #include "Regs.h"
     32 
     33 bool Elf::Init() {
     34   if (!memory_) {
     35     return false;
     36   }
     37 
     38   interface_.reset(CreateInterfaceFromMemory(memory_.get()));
     39   if (!interface_) {
     40     return false;
     41   }
     42 
     43   valid_ = interface_->Init();
     44   if (valid_) {
     45     interface_->InitHeaders();
     46   } else {
     47     interface_.reset(nullptr);
     48   }
     49   return valid_;
     50 }
     51 
     52 bool Elf::IsValidElf(Memory* memory) {
     53   if (memory == nullptr) {
     54     return false;
     55   }
     56 
     57   // Verify that this is a valid elf file.
     58   uint8_t e_ident[SELFMAG + 1];
     59   if (!memory->Read(0, e_ident, SELFMAG)) {
     60     return false;
     61   }
     62 
     63   if (memcmp(e_ident, ELFMAG, SELFMAG) != 0) {
     64     return false;
     65   }
     66   return true;
     67 }
     68 
     69 ElfInterface* Elf::CreateInterfaceFromMemory(Memory* memory) {
     70   if (!IsValidElf(memory)) {
     71     return nullptr;
     72   }
     73 
     74   std::unique_ptr<ElfInterface> interface;
     75   if (!memory->Read(EI_CLASS, &class_type_, 1)) {
     76     return nullptr;
     77   }
     78   if (class_type_ == ELFCLASS32) {
     79     Elf32_Half e_machine;
     80     if (!memory->Read(EI_NIDENT + sizeof(Elf32_Half), &e_machine, sizeof(e_machine))) {
     81       return nullptr;
     82     }
     83 
     84     if (e_machine != EM_ARM && e_machine != EM_386) {
     85       // Unsupported.
     86       ALOGI("32 bit elf that is neither arm nor x86: e_machine = %d\n", e_machine);
     87       return nullptr;
     88     }
     89 
     90     machine_type_ = e_machine;
     91     if (e_machine == EM_ARM) {
     92       interface.reset(new ElfInterfaceArm(memory));
     93     } else {
     94       interface.reset(new ElfInterface32(memory));
     95     }
     96   } else if (class_type_ == ELFCLASS64) {
     97     Elf64_Half e_machine;
     98     if (!memory->Read(EI_NIDENT + sizeof(Elf64_Half), &e_machine, sizeof(e_machine))) {
     99       return nullptr;
    100     }
    101 
    102     if (e_machine != EM_AARCH64 && e_machine != EM_X86_64) {
    103       // Unsupported.
    104       ALOGI("64 bit elf that is neither aarch64 nor x86_64: e_machine = %d\n", e_machine);
    105       return nullptr;
    106     }
    107 
    108     machine_type_ = e_machine;
    109     interface.reset(new ElfInterface64(memory));
    110   }
    111 
    112   return interface.release();
    113 }
    114