diff options
author | Christopher Ferris <cferris@google.com> | 2017-03-17 17:01:45 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2017-03-17 17:01:46 +0000 |
commit | cc404b51fc424cbb786abce8b8f36b1dce1c0ab9 (patch) | |
tree | 62ebb9ce531a818efa51e551179dccad32ea949e /libunwindstack/Elf.cpp | |
parent | 0add3ca7c47b287bc01b5e738cb9b682d43f6f97 (diff) | |
parent | 3958f8060ac0adccd977c0fab7a53d45f3fce58d (diff) |
Merge "Elf interface for new unwinder."
Diffstat (limited to 'libunwindstack/Elf.cpp')
-rw-r--r-- | libunwindstack/Elf.cpp | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/libunwindstack/Elf.cpp b/libunwindstack/Elf.cpp new file mode 100644 index 000000000..272b5f029 --- /dev/null +++ b/libunwindstack/Elf.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <elf.h> +#include <string.h> + +#include <memory> +#include <string> + +#define LOG_TAG "unwind" +#include <log/log.h> + +#include "Elf.h" +#include "ElfInterface.h" +#include "ElfInterfaceArm.h" +#include "Machine.h" +#include "Memory.h" +#include "Regs.h" + +bool Elf::Init() { + if (!memory_) { + return false; + } + + interface_.reset(CreateInterfaceFromMemory(memory_.get())); + if (!interface_) { + return false; + } + + valid_ = interface_->Init(); + if (valid_) { + interface_->InitHeaders(); + } else { + interface_.reset(nullptr); + } + return valid_; +} + +bool Elf::IsValidElf(Memory* memory) { + if (memory == nullptr) { + return false; + } + + // Verify that this is a valid elf file. + uint8_t e_ident[SELFMAG + 1]; + if (!memory->Read(0, e_ident, SELFMAG)) { + return false; + } + + if (memcmp(e_ident, ELFMAG, SELFMAG) != 0) { + return false; + } + return true; +} + +ElfInterface* Elf::CreateInterfaceFromMemory(Memory* memory) { + if (!IsValidElf(memory)) { + return nullptr; + } + + std::unique_ptr<ElfInterface> interface; + if (!memory->Read(EI_CLASS, &class_type_, 1)) { + return nullptr; + } + if (class_type_ == ELFCLASS32) { + Elf32_Half e_machine; + if (!memory->Read(EI_NIDENT + sizeof(Elf32_Half), &e_machine, sizeof(e_machine))) { + return nullptr; + } + + if (e_machine != EM_ARM && e_machine != EM_386) { + // Unsupported. + ALOGI("32 bit elf that is neither arm nor x86: e_machine = %d\n", e_machine); + return nullptr; + } + + machine_type_ = e_machine; + if (e_machine == EM_ARM) { + interface.reset(new ElfInterfaceArm(memory)); + } else { + interface.reset(new ElfInterface32(memory)); + } + } else if (class_type_ == ELFCLASS64) { + Elf64_Half e_machine; + if (!memory->Read(EI_NIDENT + sizeof(Elf64_Half), &e_machine, sizeof(e_machine))) { + return nullptr; + } + + if (e_machine != EM_AARCH64 && e_machine != EM_X86_64) { + // Unsupported. + ALOGI("64 bit elf that is neither aarch64 nor x86_64: e_machine = %d\n", e_machine); + return nullptr; + } + + machine_type_ = e_machine; + interface.reset(new ElfInterface64(memory)); + } + + return interface.release(); +} |