Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 639bab97 authored by Christopher Ferris's avatar Christopher Ferris Committed by android-build-merger
Browse files

Merge "Elf interface for new unwinder."

am: cc404b51

Change-Id: Ie5e8c6814989db86e8888dc59fe7aff2f1fc15d0
parents ecacca30 cc404b51
Loading
Loading
Loading
Loading
+45 −10
Original line number Diff line number Diff line
@@ -30,6 +30,15 @@ cc_defaults {
            enabled: false,
        },
    },

    multilib: {
        lib32: {
            suffix: "32",
        },
        lib64: {
            suffix: "64",
        },
    },
}

cc_defaults {
@@ -38,8 +47,12 @@ cc_defaults {

    srcs: [
        "ArmExidx.cpp",
        "Memory.cpp",
        "Elf.cpp",
        "ElfInterface.cpp",
        "ElfInterfaceArm.cpp",
        "Log.cpp",
        "Regs.cpp",
        "Memory.cpp",
    ],

    shared_libs: [
@@ -74,6 +87,9 @@ cc_defaults {
    srcs: [
        "tests/ArmExidxDecodeTest.cpp",
        "tests/ArmExidxExtractTest.cpp",
        "tests/ElfInterfaceArmTest.cpp",
        "tests/ElfInterfaceTest.cpp",
        "tests/ElfTest.cpp",
        "tests/LogFake.cpp",
        "tests/MemoryFake.cpp",
        "tests/MemoryFileTest.cpp",
@@ -93,15 +109,6 @@ cc_defaults {
        "liblog",
    ],

    multilib: {
        lib32: {
            suffix: "32",
        },
        lib64: {
            suffix: "64",
        },
    },

    target: {
        linux: {
            host_ldlibs: [
@@ -130,3 +137,31 @@ cc_test {
        "libunwindstack_debug",
    ],
}

//-------------------------------------------------------------------------
// Utility Executables
//-------------------------------------------------------------------------
cc_defaults {
    name: "libunwindstack_executables",
    defaults: ["libunwindstack_flags"],

    shared_libs: [
        "libunwindstack",
        "libbase",
    ],

    static_libs: [
        "liblog",
    ],

    compile_multilib: "both",
}

cc_binary {
    name: "unwind_info",
    defaults: ["libunwindstack_executables"],

    srcs: [
        "unwind_info.cpp",
    ],
}
+9 −3
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@
#include "ArmExidx.h"
#include "Log.h"
#include "Machine.h"
#include "Memory.h"
#include "Regs.h"

void ArmExidx::LogRawData() {
  std::string log_str("Raw Data:");
@@ -216,10 +218,16 @@ inline bool ArmExidx::DecodePrefix_10_00(uint8_t byte) {
      cfa_ += 4;
    }
  }

  // If the sp register is modified, change the cfa value.
  if (registers & (1 << ARM_REG_SP)) {
    cfa_ = (*regs_)[ARM_REG_SP];
  }

  // Indicate if the pc register was set.
  if (registers & (1 << ARM_REG_PC)) {
    pc_set_ = true;
  }
  return true;
}

@@ -296,9 +304,6 @@ inline bool ArmExidx::DecodePrefix_10_11_0000() {
      return false;
    }
  }
  if (!(*regs_)[ARM_REG_PC]) {
    (*regs_)[ARM_REG_PC] = (*regs_)[ARM_REG_LR];
  }
  status_ = ARM_STATUS_FINISH;
  return false;
}
@@ -675,6 +680,7 @@ bool ArmExidx::Decode() {
}

bool ArmExidx::Eval() {
  pc_set_ = false;
  while (Decode());
  return status_ == ARM_STATUS_FINISH;
}
+10 −5
Original line number Diff line number Diff line
@@ -21,8 +21,9 @@

#include <deque>

#include "Memory.h"
#include "Regs.h"
// Forward declarations.
class Memory;
class RegsArm;

enum ArmStatus : size_t {
  ARM_STATUS_NONE = 0,
@@ -43,7 +44,7 @@ enum ArmOp : uint8_t {

class ArmExidx {
 public:
  ArmExidx(Regs32* regs, Memory* elf_memory, Memory* process_memory)
  ArmExidx(RegsArm* regs, Memory* elf_memory, Memory* process_memory)
      : regs_(regs), elf_memory_(elf_memory), process_memory_(process_memory) {}
  virtual ~ArmExidx() {}

@@ -59,11 +60,14 @@ class ArmExidx {

  ArmStatus status() { return status_; }

  Regs32* regs() { return regs_; }
  RegsArm* regs() { return regs_; }

  uint32_t cfa() { return cfa_; }
  void set_cfa(uint32_t cfa) { cfa_ = cfa; }

  bool pc_set() { return pc_set_; }
  void set_pc_set(bool pc_set) { pc_set_ = pc_set; }

  void set_log(bool log) { log_ = log; }
  void set_log_skip_execution(bool skip_execution) { log_skip_execution_ = skip_execution; }
  void set_log_indent(uint8_t indent) { log_indent_ = indent; }
@@ -87,7 +91,7 @@ class ArmExidx {
  bool DecodePrefix_11_010(uint8_t byte);
  bool DecodePrefix_11(uint8_t byte);

  Regs32* regs_ = nullptr;
  RegsArm* regs_ = nullptr;
  uint32_t cfa_ = 0;
  std::deque<uint8_t> data_;
  ArmStatus status_ = ARM_STATUS_NONE;
@@ -98,6 +102,7 @@ class ArmExidx {
  bool log_ = false;
  uint8_t log_indent_ = 0;
  bool log_skip_execution_ = false;
  bool pc_set_ = false;
};

#endif  // _LIBUNWINDSTACK_ARM_EXIDX_H

libunwindstack/Elf.cpp

0 → 100644
+113 −0
Original line number Diff line number Diff line
/*
 * 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();
}

libunwindstack/Elf.h

0 → 100644
+78 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

#ifndef _LIBUNWINDSTACK_ELF_H
#define _LIBUNWINDSTACK_ELF_H

#include <stddef.h>

#include <memory>
#include <string>

#include "ElfInterface.h"
#include "Memory.h"

#if !defined(EM_AARCH64)
#define EM_AARCH64 183
#endif

// Forward declaration.
class Regs;

class Elf {
 public:
  Elf(Memory* memory) : memory_(memory) {}
  virtual ~Elf() = default;

  bool Init();

  void InitGnuDebugdata();

  bool GetSoname(std::string* name) {
    return valid_ && interface_->GetSoname(name);
  }

  bool GetFunctionName(uint64_t, std::string*, uint64_t*) {
    return false;
  }

  bool Step(uint64_t rel_pc, Regs* regs, Memory* process_memory) {
    return valid_ && interface_->Step(rel_pc, regs, process_memory);
  }

  ElfInterface* CreateInterfaceFromMemory(Memory* memory);

  bool valid() { return valid_; }

  uint32_t machine_type() { return machine_type_; }

  uint8_t class_type() { return class_type_; }

  Memory* memory() { return memory_.get(); }

  ElfInterface* interface() { return interface_.get(); }

  static bool IsValidElf(Memory* memory);

 protected:
  bool valid_ = false;
  std::unique_ptr<ElfInterface> interface_;
  std::unique_ptr<Memory> memory_;
  uint32_t machine_type_;
  uint8_t class_type_;
};

#endif  // _LIBUNWINDSTACK_ELF_H
Loading