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 33bool 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 52bool 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 69ElfInterface* 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