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

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

Merge "Fix which maps to search for globals." am: 7cffd151 am: 00a95a93

am: e4272f17

Change-Id: I760d74bdd125911bec6c7f1a4cfecca41e3de1c9
parents d3584831 e4272f17
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -58,6 +58,7 @@ cc_library {
        "Elf.cpp",
        "Elf.cpp",
        "ElfInterface.cpp",
        "ElfInterface.cpp",
        "ElfInterfaceArm.cpp",
        "ElfInterfaceArm.cpp",
        "Global.cpp",
        "JitDebug.cpp",
        "JitDebug.cpp",
        "Log.cpp",
        "Log.cpp",
        "MapInfo.cpp",
        "MapInfo.cpp",
+8 −32
Original line number Original line Diff line number Diff line
@@ -43,10 +43,10 @@ struct DEXFileEntry64 {
  uint64_t dex_file;
  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)
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() {
DexFiles::~DexFiles() {
  for (auto& entry : files_) {
  for (auto& entry : files_) {
@@ -117,6 +117,11 @@ bool DexFiles::ReadEntry64() {
  return true;
  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) {
void DexFiles::Init(Maps* maps) {
  if (initialized_) {
  if (initialized_) {
    return;
    return;
@@ -124,36 +129,7 @@ void DexFiles::Init(Maps* maps) {
  initialized_ = true;
  initialized_ = true;
  entry_addr_ = 0;
  entry_addr_ = 0;


  const std::string dex_debug_name("__dex_debug_descriptor");
  FindAndReadVariable(maps, "__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;
      }
    }
  }
}
}


DexFile* DexFiles::GetDexFile(uint64_t dex_file_offset, MapInfo* info) {
DexFile* DexFiles::GetDexFile(uint64_t dex_file_offset, MapInfo* info) {
+96 −0
Original line number Original line 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 Original line Diff line number Diff line
@@ -69,10 +69,10 @@ struct JITDescriptor64 {
  uint64_t first_entry;
  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)
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() {
JitDebug::~JitDebug() {
  for (auto* elf : elf_list_) {
  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) {
void JitDebug::Init(Maps* maps) {
  if (initialized_) {
  if (initialized_) {
    return;
    return;
@@ -172,36 +177,7 @@ void JitDebug::Init(Maps* maps) {
  // Regardless of what happens below, consider the init finished.
  // Regardless of what happens below, consider the init finished.
  initialized_ = true;
  initialized_ = true;


  const std::string descriptor_name("__jit_debug_descriptor");
  FindAndReadVariable(maps, "__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;
      }
    }
  }
}
}


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


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

namespace unwindstack {
namespace unwindstack {


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


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


  bool ReadEntry64();
  bool ReadEntry64();


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


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