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 <unwindstack/Elf.h>
     27 #include <unwindstack/ElfInterface.h>
     28 #include <unwindstack/MapInfo.h>
     29 #include <unwindstack/Memory.h>
     30 #include <unwindstack/Regs.h>
     31 
     32 #include "ElfInterfaceArm.h"
     33 #include "Machine.h"
     34 #include "Symbols.h"
     35 
     36 namespace unwindstack {
     37 
     38 bool Elf::Init() {
     39   if (!memory_) {
     40     return false;
     41   }
     42 
     43   interface_.reset(CreateInterfaceFromMemory(memory_.get()));
     44   if (!interface_) {
     45     return false;
     46   }
     47 
     48   valid_ = interface_->Init();
     49   if (valid_) {
     50     interface_->InitHeaders();
     51   } else {
     52     interface_.reset(nullptr);
     53   }
     54   return valid_;
     55 }
     56 
     57 // It is expensive to initialize the .gnu_debugdata section. Provide a method
     58 // to initialize this data separately.
     59 void Elf::InitGnuDebugdata() {
     60   if (!valid_ || interface_->gnu_debugdata_offset() == 0) {
     61     return;
     62   }
     63 
     64   gnu_debugdata_memory_.reset(interface_->CreateGnuDebugdataMemory());
     65   gnu_debugdata_interface_.reset(CreateInterfaceFromMemory(gnu_debugdata_memory_.get()));
     66   ElfInterface* gnu = gnu_debugdata_interface_.get();
     67   if (gnu == nullptr) {
     68     return;
     69   }
     70   if (gnu->Init()) {
     71     gnu->InitHeaders();
     72   } else {
     73     // Free all of the memory associated with the gnu_debugdata section.
     74     gnu_debugdata_memory_.reset(nullptr);
     75     gnu_debugdata_interface_.reset(nullptr);
     76   }
     77 }
     78 
     79 bool Elf::GetSoname(std::string* name) {
     80   return valid_ && interface_->GetSoname(name);
     81 }
     82 
     83 uint64_t Elf::GetRelPc(uint64_t pc, const MapInfo* map_info) {
     84   uint64_t load_bias = 0;
     85   if (valid()) {
     86     load_bias = interface_->load_bias();
     87   }
     88 
     89   return pc - map_info->start + load_bias + map_info->elf_offset;
     90 }
     91 
     92 bool Elf::GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) {
     93   return valid_ && (interface_->GetFunctionName(addr, name, func_offset) ||
     94                     (gnu_debugdata_interface_ &&
     95                      gnu_debugdata_interface_->GetFunctionName(addr, name, func_offset)));
     96 }
     97 
     98 bool Elf::Step(uint64_t rel_pc, Regs* regs, Memory* process_memory) {
     99   return valid_ && (regs->StepIfSignalHandler(rel_pc, this, process_memory) ||
    100                     interface_->Step(rel_pc, regs, process_memory) ||
    101                     (gnu_debugdata_interface_ &&
    102                      gnu_debugdata_interface_->Step(rel_pc, regs, process_memory)));
    103 }
    104 
    105 uint64_t Elf::GetLoadBias() {
    106   if (!valid_) return 0;
    107   return interface_->load_bias();
    108 }
    109 
    110 bool Elf::IsValidElf(Memory* memory) {
    111   if (memory == nullptr) {
    112     return false;
    113   }
    114 
    115   // Verify that this is a valid elf file.
    116   uint8_t e_ident[SELFMAG + 1];
    117   if (!memory->Read(0, e_ident, SELFMAG)) {
    118     return false;
    119   }
    120 
    121   if (memcmp(e_ident, ELFMAG, SELFMAG) != 0) {
    122     return false;
    123   }
    124   return true;
    125 }
    126 
    127 ElfInterface* Elf::CreateInterfaceFromMemory(Memory* memory) {
    128   if (!IsValidElf(memory)) {
    129     return nullptr;
    130   }
    131 
    132   std::unique_ptr<ElfInterface> interface;
    133   if (!memory->Read(EI_CLASS, &class_type_, 1)) {
    134     return nullptr;
    135   }
    136   if (class_type_ == ELFCLASS32) {
    137     Elf32_Half e_machine;
    138     if (!memory->Read(EI_NIDENT + sizeof(Elf32_Half), &e_machine, sizeof(e_machine))) {
    139       return nullptr;
    140     }
    141 
    142     if (e_machine != EM_ARM && e_machine != EM_386) {
    143       // Unsupported.
    144       ALOGI("32 bit elf that is neither arm nor x86: e_machine = %d\n", e_machine);
    145       return nullptr;
    146     }
    147 
    148     machine_type_ = e_machine;
    149     if (e_machine == EM_ARM) {
    150       interface.reset(new ElfInterfaceArm(memory));
    151     } else if (e_machine == EM_386) {
    152       interface.reset(new ElfInterface32(memory));
    153     } else {
    154       ALOGI("32 bit elf that is neither arm nor x86: e_machine = %d\n", e_machine);
    155       return nullptr;
    156     }
    157   } else if (class_type_ == ELFCLASS64) {
    158     Elf64_Half e_machine;
    159     if (!memory->Read(EI_NIDENT + sizeof(Elf64_Half), &e_machine, sizeof(e_machine))) {
    160       return nullptr;
    161     }
    162     if (e_machine != EM_AARCH64 && e_machine != EM_X86_64) {
    163       // Unsupported.
    164       ALOGI("64 bit elf that is neither aarch64 nor x86_64: e_machine = %d\n", e_machine);
    165       return nullptr;
    166     }
    167     machine_type_ = e_machine;
    168     interface.reset(new ElfInterface64(memory));
    169   }
    170 
    171   return interface.release();
    172 }
    173 
    174 }  // namespace unwindstack
    175