From 5ec11173378992121e03c1dfc52e05443cd0a747 Mon Sep 17 00:00:00 2001 From: Selim Mustafaev Date: Mon, 28 Nov 2022 20:46:19 +0300 Subject: [PATCH] Fix building on macOS. Adding LEB128 reader class. --- CMakeLists.txt | 2 +- dart/Leb128Int.cpp | 36 +++++++++++++++++++++++++++++++++++ dart/Leb128Int.h | 28 +++++++++++++++++++++++++++ dart/Reader.cpp | 4 ++-- dart/Snapshot.cpp | 47 +++++++++++++++++++++++++++++++++++++++------- dart/Snapshot.h | 13 +++++++++++++ main.cpp | 6 +++++- 7 files changed, 125 insertions(+), 11 deletions(-) create mode 100644 dart/Leb128Int.cpp create mode 100644 dart/Leb128Int.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b02c113..e9c5163 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,6 @@ project(unflutter) set(CMAKE_CXX_STANDARD 20) -add_executable(unflutter main.cpp dart/Reader.cpp dart/Reader.h dart/Snapshot.cpp dart/Snapshot.h) +add_executable(unflutter main.cpp dart/Reader.cpp dart/Reader.h dart/Snapshot.cpp dart/Snapshot.h dart/Leb128Int.cpp dart/Leb128Int.h) target_include_directories(unflutter PRIVATE ${CMAKE_SOURCE_DIR}/ThirdParty) \ No newline at end of file diff --git a/dart/Leb128Int.cpp b/dart/Leb128Int.cpp new file mode 100644 index 0000000..8414132 --- /dev/null +++ b/dart/Leb128Int.cpp @@ -0,0 +1,36 @@ +// +// Created by Selim Mustafaev on 28.11.2022. +// + +#include "Leb128Int.h" + +namespace Dart { + + Leb128Int::Leb128Int(): _value(0), _size(0) { + + } + + Dart::Leb128Int::Leb128Int(const std::byte* ptr): _value(0), _size(0) { + size_t bitShift = 0; + auto data = reinterpret_cast(ptr); + + while (*data < 0x80) { + _value |= (*data << bitShift); + bitShift += 7; + data++; + _size++; + } + + _value |= ((*data & 0x7f) << bitShift); + _size++; + } + + uint64_t Leb128Int::value() const { + return _value; + } + + size_t Leb128Int::size() const { + return _size; + } + +} diff --git a/dart/Leb128Int.h b/dart/Leb128Int.h new file mode 100644 index 0000000..02bf4bf --- /dev/null +++ b/dart/Leb128Int.h @@ -0,0 +1,28 @@ +// +// Created by Selim Mustafaev on 28.11.2022. +// + +#ifndef UNFLUTTER_LEB128INT_H +#define UNFLUTTER_LEB128INT_H + +#include +#include +#include + +namespace Dart { + + class Leb128Int { + private: + uint64_t _value; + size_t _size; + + public: + Leb128Int(); + explicit Leb128Int(const std::byte* ptr); + [[nodiscard]] uint64_t value() const; + [[nodiscard]] size_t size() const; + }; + +} + +#endif //UNFLUTTER_LEB128INT_H diff --git a/dart/Reader.cpp b/dart/Reader.cpp index df9a7ca..85907b9 100644 --- a/dart/Reader.cpp +++ b/dart/Reader.cpp @@ -4,9 +4,9 @@ #include "Reader.h" #include "elfio/elfio_dump.hpp" +#include "elfio/elf_types.hpp" #include -#include namespace Dart { @@ -49,7 +49,7 @@ namespace Dart { const ELFIO::symbol_section_accessor symbols(_elfio, section.get()); for(size_t i = 0; i < symbols.get_symbols_num(); ++i) { std::string name; - Elf64_Addr address; + ELFIO::Elf64_Addr address; ELFIO::Elf_Xword size; ELFIO::Elf_Half section_index; unsigned char bind, type, other; diff --git a/dart/Snapshot.cpp b/dart/Snapshot.cpp index c54d3b7..d42ffb1 100644 --- a/dart/Snapshot.cpp +++ b/dart/Snapshot.cpp @@ -27,15 +27,20 @@ namespace Dart { data += _versionHash.size(); auto features = std::string((char*)data); - data += features.size(); + data += features.size() + 1; + _features = split(features); - auto view = features - | std::ranges::views::split(' ') - | std::ranges::views::transform([](auto &&rng) { - return std::string(&*rng.begin(), std::ranges::distance(rng)); - }); + _baseObjectsCount = Leb128Int(data); + data += _baseObjectsCount.size(); - _features.assign(view.begin(), view.end()); + _allObjectsCount = Leb128Int(data); + data += _allObjectsCount.size(); + + _clustersCount = Leb128Int(data); + data += _clustersCount.size(); + + _fieldTableLength = Leb128Int(data); + data += _fieldTableLength.size(); } uint64_t Snapshot::size() const { @@ -72,4 +77,32 @@ namespace Dart { return ss.str(); } + std::vector Snapshot::split(const std::string &str) { + std::vector result; + std::stringstream ss(str); + std::string item; + + while (std::getline (ss, item, ' ')) { + result.push_back (item); + } + + return result; + } + + uint64_t Snapshot::baseObjectsCount() const { + return _baseObjectsCount.value(); + } + + uint64_t Snapshot::allObjectsCount() const { + return _allObjectsCount.value(); + } + + uint64_t Snapshot::clustersCount() const { + return _clustersCount.value(); + } + + uint64_t Snapshot::fieldTableLength() const { + return _fieldTableLength.value(); + } + } diff --git a/dart/Snapshot.h b/dart/Snapshot.h index 4aa1183..0843fe9 100644 --- a/dart/Snapshot.h +++ b/dart/Snapshot.h @@ -5,6 +5,8 @@ #ifndef UNFLUTTER_SNAPSHOT_H #define UNFLUTTER_SNAPSHOT_H +#include "Leb128Int.h" + #include #include #include @@ -26,6 +28,13 @@ namespace Dart { Kind _kind; std::string _versionHash; std::vector _features; + Leb128Int _baseObjectsCount; + Leb128Int _allObjectsCount; + Leb128Int _clustersCount; + Leb128Int _fieldTableLength; + + private: + static std::vector split(const std::string &str); public: explicit Snapshot(const std::byte* data); @@ -33,6 +42,10 @@ namespace Dart { [[nodiscard]] std::string kindString() const; [[nodiscard]] std::string versionHash() const; [[nodiscard]] std::string featuresString() const; + [[nodiscard]] uint64_t baseObjectsCount() const; + [[nodiscard]] uint64_t allObjectsCount() const; + [[nodiscard]] uint64_t clustersCount() const; + [[nodiscard]] uint64_t fieldTableLength() const; }; } diff --git a/main.cpp b/main.cpp index f2d6457..195bc35 100644 --- a/main.cpp +++ b/main.cpp @@ -2,13 +2,17 @@ #include int main(int argc, char** argv) { - Dart::Reader reader("/home/selim/Downloads/libapp.so"); + Dart::Reader reader("/Users/selim/Documents/libapp.so"); auto snapshot = reader.getSnapshot(Dart::DartSnapshot::VM_DATA); std::cout << "Snapshot kind: " << snapshot.kindString() << std::endl; std::cout << "Size: " << snapshot.size() << std::endl; std::cout << "Version hash: " << snapshot.versionHash() << std::endl; std::cout << "Features: " << snapshot.featuresString() << std::endl; + std::cout << "Base objects: " << snapshot.baseObjectsCount() << std::endl; + std::cout << "All objects: " << snapshot.allObjectsCount() << std::endl; + std::cout << "Clusters: " << snapshot.clustersCount() << std::endl; + std::cout << "Field table length: " << snapshot.fieldTableLength() << std::endl; return 0; }