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 
Init()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 
IsValidElf(Memory * memory)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 
CreateInterfaceFromMemory(Memory * memory)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