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

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

Merge "Fix which maps to search for globals."

parents f2eaefe3 56d0e07d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ cc_library {
        "Elf.cpp",
        "ElfInterface.cpp",
        "ElfInterfaceArm.cpp",
        "Global.cpp",
        "JitDebug.cpp",
        "Log.cpp",
        "MapInfo.cpp",
+8 −32
Original line number Diff line number Diff line
@@ -43,10 +43,10 @@ struct DEXFileEntry64 {
  uint64_t dex_file;
};

DexFiles::DexFiles(std::shared_ptr<Memory>& memory) : memory_(memory) {}
DexFiles::DexFiles(std::shared_ptr<Memory>& memory) : Global(memory) {}

DexFiles::DexFiles(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs)
    : memory_(memory), search_libs_(search_libs) {}
    : Global(memory, search_libs) {}

DexFiles::~DexFiles() {
  for (auto& entry : files_) {
@@ -117,6 +117,11 @@ bool DexFiles::ReadEntry64() {
  return true;
}

bool DexFiles::ReadVariableData(uint64_t ptr_offset) {
  entry_addr_ = (this->*read_entry_ptr_func_)(ptr_offset);
  return entry_addr_ != 0;
}

void DexFiles::Init(Maps* maps) {
  if (initialized_) {
    return;
@@ -124,36 +129,7 @@ void DexFiles::Init(Maps* maps) {
  initialized_ = true;
  entry_addr_ = 0;

  const std::string dex_debug_name("__dex_debug_descriptor");
  for (MapInfo* info : *maps) {
    if (!(info->flags & PROT_READ) || info->offset != 0) {
      continue;
    }

    if (!search_libs_.empty()) {
      bool found = false;
      const char* lib = basename(info->name.c_str());
      for (const std::string& name : search_libs_) {
        if (name == lib) {
          found = true;
          break;
        }
      }
      if (!found) {
        continue;
      }
    }

    Elf* elf = info->GetElf(memory_, true);
    uint64_t ptr;
    // Find first non-empty list (libart might be loaded multiple times).
    if (elf->GetGlobalVariable(dex_debug_name, &ptr) && ptr != 0) {
      entry_addr_ = (this->*read_entry_ptr_func_)(ptr + info->start);
      if (entry_addr_ != 0) {
        break;
      }
    }
  }
  FindAndReadVariable(maps, "__dex_debug_descriptor");
}

DexFile* DexFiles::GetDexFile(uint64_t dex_file_offset, MapInfo* info) {
+96 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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 <stdint.h>
#include <sys/mman.h>

#include <string>
#include <vector>

#include <unwindstack/Global.h>
#include <unwindstack/MapInfo.h>
#include <unwindstack/Maps.h>
#include <unwindstack/Memory.h>

namespace unwindstack {

Global::Global(std::shared_ptr<Memory>& memory) : memory_(memory) {}
Global::Global(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs)
    : memory_(memory), search_libs_(search_libs) {}

uint64_t Global::GetVariableOffset(MapInfo* info, const std::string& variable) {
  if (!search_libs_.empty()) {
    bool found = false;
    const char* lib = basename(info->name.c_str());
    for (const std::string& name : search_libs_) {
      if (name == lib) {
        found = true;
        break;
      }
    }
    if (!found) {
      return 0;
    }
  }

  Elf* elf = info->GetElf(memory_, true);
  uint64_t ptr;
  // Find first non-empty list (libraries might be loaded multiple times).
  if (elf->GetGlobalVariable(variable, &ptr) && ptr != 0) {
    return ptr + info->start;
  }
  return 0;
}

void Global::FindAndReadVariable(Maps* maps, const char* var_str) {
  std::string variable(var_str);
  // When looking for global variables, do not arbitrarily search every
  // readable map. Instead look for a specific pattern that must exist.
  // The pattern should be a readable map, followed by a read-write
  // map with a non-zero offset.
  // For example:
  //   f0000-f1000 0 r-- /system/lib/libc.so
  //   f1000-f2000 1000 r-x /system/lib/libc.so
  //   f2000-f3000 2000 rw- /system/lib/libc.so
  // This also works:
  //   f0000-f2000 0 r-- /system/lib/libc.so
  //   f2000-f3000 2000 rw- /system/lib/libc.so
  MapInfo* map_start = nullptr;
  for (MapInfo* info : *maps) {
    if (map_start != nullptr) {
      if (map_start->name == info->name) {
        if (info->offset != 0 &&
            (info->flags & (PROT_READ | PROT_WRITE)) == (PROT_READ | PROT_WRITE)) {
          uint64_t ptr = GetVariableOffset(map_start, variable);
          if (ptr != 0 && ReadVariableData(ptr)) {
            break;
          } else {
            // Failed to find the global variable, do not bother trying again.
            map_start = nullptr;
          }
        }
      } else {
        map_start = nullptr;
      }
    }
    if (map_start == nullptr && (info->flags & PROT_READ) && info->offset == 0 &&
        !info->name.empty()) {
      map_start = info;
    }
  }
}

}  // namespace unwindstack
+8 −32
Original line number Diff line number Diff line
@@ -69,10 +69,10 @@ struct JITDescriptor64 {
  uint64_t first_entry;
};

JitDebug::JitDebug(std::shared_ptr<Memory>& memory) : memory_(memory) {}
JitDebug::JitDebug(std::shared_ptr<Memory>& memory) : Global(memory) {}

JitDebug::JitDebug(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs)
    : memory_(memory), search_libs_(search_libs) {}
    : Global(memory, search_libs) {}

JitDebug::~JitDebug() {
  for (auto* elf : elf_list_) {
@@ -165,6 +165,11 @@ void JitDebug::SetArch(ArchEnum arch) {
  }
}

bool JitDebug::ReadVariableData(uint64_t ptr) {
  entry_addr_ = (this->*read_descriptor_func_)(ptr);
  return entry_addr_ != 0;
}

void JitDebug::Init(Maps* maps) {
  if (initialized_) {
    return;
@@ -172,36 +177,7 @@ void JitDebug::Init(Maps* maps) {
  // Regardless of what happens below, consider the init finished.
  initialized_ = true;

  const std::string descriptor_name("__jit_debug_descriptor");
  for (MapInfo* info : *maps) {
    if (!(info->flags & PROT_READ) || info->offset != 0) {
      continue;
    }

    if (!search_libs_.empty()) {
      bool found = false;
      const char* lib = basename(info->name.c_str());
      for (std::string& name : search_libs_) {
        if (strcmp(name.c_str(), lib) == 0) {
          found = true;
          break;
        }
      }
      if (!found) {
        continue;
      }
    }

    Elf* elf = info->GetElf(memory_, true);
    uint64_t descriptor_addr;
    // Find first non-empty entry (libart might be loaded multiple times).
    if (elf->GetGlobalVariable(descriptor_name, &descriptor_addr) && descriptor_addr != 0) {
      entry_addr_ = (this->*read_descriptor_func_)(descriptor_addr + info->start);
      if (entry_addr_ != 0) {
        break;
      }
    }
  }
  FindAndReadVariable(maps, "__jit_debug_descriptor");
}

Elf* JitDebug::GetElf(Maps* maps, uint64_t pc) {
+5 −4
Original line number Diff line number Diff line
@@ -25,16 +25,18 @@
#include <unordered_map>
#include <vector>

#include <unwindstack/Global.h>
#include <unwindstack/Memory.h>

namespace unwindstack {

// Forward declarations.
class DexFile;
class Maps;
struct MapInfo;
class Memory;
enum ArchEnum : uint8_t;

class DexFiles {
class DexFiles : public Global {
 public:
  explicit DexFiles(std::shared_ptr<Memory>& memory);
  DexFiles(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs);
@@ -60,8 +62,7 @@ class DexFiles {

  bool ReadEntry64();

  std::shared_ptr<Memory> memory_;
  std::vector<std::string> search_libs_;
  bool ReadVariableData(uint64_t ptr_offset) override;

  std::mutex lock_;
  bool initialized_ = false;
Loading