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

Commit cc404b51 authored by Christopher Ferris's avatar Christopher Ferris Committed by Gerrit Code Review
Browse files

Merge "Elf interface for new unwinder."

parents 0add3ca7 3958f806
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