Compare commits
No commits in common. "4420fee251c0869c0988cde41ded66b01f1f7534" and "5aa115e8fad2ae7ea661f2964bc90015f3e36117" have entirely different histories.
4420fee251
...
5aa115e8fa
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,2 @@
|
|||||||
.idea/
|
.idea/
|
||||||
cmake-build-debug/
|
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,6 @@ project(unflutter)
|
|||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
|
||||||
add_executable(unflutter main.cpp dart/Reader.cpp dart/Reader.h dart/Snapshot.cpp dart/Snapshot.h dart/Leb128Int.cpp dart/Leb128Int.h dart/ClassId.h)
|
add_executable(unflutter main.cpp dart/dart.h)
|
||||||
|
|
||||||
target_include_directories(unflutter PRIVATE ${CMAKE_SOURCE_DIR}/ThirdParty)
|
target_include_directories(unflutter PRIVATE ${CMAKE_SOURCE_DIR}/ThirdParty)
|
||||||
170
dart/ClassId.h
170
dart/ClassId.h
@ -1,170 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by Selim Mustafaev on 29.11.2022.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef UNFLUTTER_CLASSID_H
|
|
||||||
#define UNFLUTTER_CLASSID_H
|
|
||||||
|
|
||||||
namespace Dart {
|
|
||||||
|
|
||||||
enum class ClassId: uint64_t {
|
|
||||||
Illegal = 0,
|
|
||||||
NativePointer = 1,
|
|
||||||
FreeListElement = 2,
|
|
||||||
ForwardingCorpse = 3,
|
|
||||||
Object = 4,
|
|
||||||
Class = 5,
|
|
||||||
PatchClass = 6,
|
|
||||||
Function = 7,
|
|
||||||
TypeParameters = 8,
|
|
||||||
ClosureData = 9,
|
|
||||||
FfiTrampolineData = 10,
|
|
||||||
Field = 11,
|
|
||||||
Script = 12,
|
|
||||||
Library = 13,
|
|
||||||
Namespace = 14,
|
|
||||||
KernelProgramInfo = 15,
|
|
||||||
WeakSerializationReference = 16,
|
|
||||||
Code = 17,
|
|
||||||
Instructions = 18,
|
|
||||||
InstructionsSection = 19,
|
|
||||||
InstructionsTable = 20,
|
|
||||||
ObjectPool = 21,
|
|
||||||
PcDescriptors = 22,
|
|
||||||
CodeSourceMap = 23,
|
|
||||||
CompressedStackMaps = 24,
|
|
||||||
LocalVarDescriptors = 25,
|
|
||||||
ExceptionHandlers = 26,
|
|
||||||
Context = 27,
|
|
||||||
ContextScope = 28,
|
|
||||||
Sentinel = 29,
|
|
||||||
SingleTargetCache = 30,
|
|
||||||
UnlinkedCall = 31,
|
|
||||||
MonomorphicSmiableCall = 32,
|
|
||||||
CallSiteData = 33,
|
|
||||||
ICData = 34,
|
|
||||||
MegamorphicCache = 35,
|
|
||||||
SubtypeTestCache = 36,
|
|
||||||
LoadingUnit = 37,
|
|
||||||
Error = 38,
|
|
||||||
ApiError = 39,
|
|
||||||
LanguageError = 40,
|
|
||||||
UnhandledException = 41,
|
|
||||||
UnwindError = 42,
|
|
||||||
Instance = 43,
|
|
||||||
LibraryPrefix = 44,
|
|
||||||
TypeArguments = 45,
|
|
||||||
AbstractType = 46,
|
|
||||||
Type = 47,
|
|
||||||
FunctionType = 48,
|
|
||||||
TypeRef = 49,
|
|
||||||
TypeParameter = 50,
|
|
||||||
Closure = 51,
|
|
||||||
Number = 52,
|
|
||||||
Integer = 53,
|
|
||||||
Smi = 54,
|
|
||||||
Mint = 55,
|
|
||||||
Double = 56,
|
|
||||||
Bool = 57,
|
|
||||||
Float32x4 = 58,
|
|
||||||
Int32x4 = 59,
|
|
||||||
Float64x2 = 60,
|
|
||||||
TypedDataBase = 61,
|
|
||||||
TypedData = 62,
|
|
||||||
ExternalTypedData = 63,
|
|
||||||
TypedDataView = 64,
|
|
||||||
Pointer = 65,
|
|
||||||
DynamicLibrary = 66,
|
|
||||||
Capability = 67,
|
|
||||||
ReceivePort = 68,
|
|
||||||
SendPort = 69,
|
|
||||||
StackTrace = 70,
|
|
||||||
RegExp = 71,
|
|
||||||
WeakProperty = 72,
|
|
||||||
MirrorReference = 73,
|
|
||||||
FutureOr = 74,
|
|
||||||
UserTag = 75,
|
|
||||||
TransferableTypedData = 76,
|
|
||||||
LinkedHashMap = 77,
|
|
||||||
ImmutableLinkedHashMap = 78,
|
|
||||||
LinkedHashSet = 79,
|
|
||||||
ImmutableLinkedHashSet = 80,
|
|
||||||
Array = 81,
|
|
||||||
ImmutableArray = 82,
|
|
||||||
GrowableObjectArray = 83,
|
|
||||||
String = 84,
|
|
||||||
OneByteString = 85,
|
|
||||||
TwoByteString = 86,
|
|
||||||
ExternalOneByteString = 87,
|
|
||||||
ExternalTwoByteString = 88,
|
|
||||||
kFfiNativeFunctionCid = 89,
|
|
||||||
FfiInt8 = 90,
|
|
||||||
FfiInt16 = 91,
|
|
||||||
FfiInt32 = 92,
|
|
||||||
FfiInt64 = 93,
|
|
||||||
FfiUint8 = 94,
|
|
||||||
FfiUint16 = 95,
|
|
||||||
FfiUint32 = 96,
|
|
||||||
FfiUint64 = 97,
|
|
||||||
FfiIntPtr = 98,
|
|
||||||
FfiFloat = 99,
|
|
||||||
FfiDouble = 100,
|
|
||||||
FfiVoid = 101,
|
|
||||||
FfiHandle = 102,
|
|
||||||
FfiBool = 103,
|
|
||||||
FfiNativeType = 104,
|
|
||||||
FfiStruct = 105,
|
|
||||||
TypedDataInt8Array = 106,
|
|
||||||
TypedDataInt8ArrayView = 107,
|
|
||||||
ExternalTypedDataInt8Array = 108,
|
|
||||||
TypedDataUint8Array = 109,
|
|
||||||
TypedDataUint8ArrayView = 110,
|
|
||||||
ExternalTypedDataUint8Array = 111,
|
|
||||||
TypedDataUint8ClampedArray = 112,
|
|
||||||
TypedDataUint8ClampedArrayView = 113,
|
|
||||||
ExternalTypedDataUint8ClampedArray = 114,
|
|
||||||
TypedDataInt16Array = 115,
|
|
||||||
TypedDataInt16ArrayView = 116,
|
|
||||||
ExternalTypedDataInt16Array = 117,
|
|
||||||
TypedDataUint16Array = 118,
|
|
||||||
TypedDataUint16ArrayView = 119,
|
|
||||||
ExternalTypedDataUint16Array = 120,
|
|
||||||
TypedDataInt32Array = 121,
|
|
||||||
TypedDataInt32ArrayView = 122,
|
|
||||||
ExternalTypedDataInt32Array = 123,
|
|
||||||
TypedDataUint32Array = 124,
|
|
||||||
TypedDataUint32ArrayView = 125,
|
|
||||||
ExternalTypedDataUint32Array = 126,
|
|
||||||
TypedDataInt64Array = 127,
|
|
||||||
TypedDataInt64ArrayView = 128,
|
|
||||||
ExternalTypedDataInt64Array = 129,
|
|
||||||
TypedDataUint64Array = 130,
|
|
||||||
TypedDataUint64ArrayView = 131,
|
|
||||||
ExternalTypedDataUint64Array = 132,
|
|
||||||
TypedDataFloat32Array = 133,
|
|
||||||
TypedDataFloat32ArrayView = 134,
|
|
||||||
ExternalTypedDataFloat32Array = 135,
|
|
||||||
TypedDataFloat64Array = 136,
|
|
||||||
TypedDataFloat64ArrayView = 137,
|
|
||||||
ExternalTypedDataFloat64Array = 138,
|
|
||||||
TypedDataFloat32x4Array = 139,
|
|
||||||
TypedDataFloat32x4ArrayView = 140,
|
|
||||||
ExternalTypedDataFloat32x4Array = 141,
|
|
||||||
TypedDataInt32x4Array = 142,
|
|
||||||
TypedDataInt32x4ArrayView = 143,
|
|
||||||
ExternalTypedDataInt32x4Array = 144,
|
|
||||||
TypedDataFloat64x2Array = 145,
|
|
||||||
TypedDataFloat64x2ArrayView = 146,
|
|
||||||
ExternalTypedDataFloat64x2Array = 147,
|
|
||||||
ByteDataView = 148,
|
|
||||||
ByteBuffer = 149,
|
|
||||||
Null = 150,
|
|
||||||
Dynamic = 151,
|
|
||||||
Void = 152,
|
|
||||||
Never = 153,
|
|
||||||
NumPredefined = 154
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //UNFLUTTER_CLASSID_H
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
//
|
|
||||||
// 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<const uint8_t*>(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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by Selim Mustafaev on 28.11.2022.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef UNFLUTTER_LEB128INT_H
|
|
||||||
#define UNFLUTTER_LEB128INT_H
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cstddef>
|
|
||||||
|
|
||||||
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
|
|
||||||
@ -1,84 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by selim on 27.11.22.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "Reader.h"
|
|
||||||
#include "elfio/elfio_dump.hpp"
|
|
||||||
#include "elfio/elf_types.hpp"
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
namespace Dart {
|
|
||||||
|
|
||||||
Reader::Reader(const fs::path& path) {
|
|
||||||
if(!fs::exists(path)) {
|
|
||||||
throw std::runtime_error("File does not exists");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!_elfio.load(path)) {
|
|
||||||
throw std::runtime_error("Failed to load ELF file");
|
|
||||||
}
|
|
||||||
|
|
||||||
auto size = fs::file_size(path);
|
|
||||||
_file = std::make_unique<std::byte[]>(size);
|
|
||||||
|
|
||||||
std::ifstream stream(path, std::ios::binary);
|
|
||||||
stream.read(reinterpret_cast<char*>(_file.get()), static_cast<std::streamsize>(size));
|
|
||||||
|
|
||||||
if(stream.bad()) {
|
|
||||||
throw std::runtime_error("Error reading ELF file");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Reader::dumpInfo() const {
|
|
||||||
ELFIO::dump::header( std::cout, _elfio );
|
|
||||||
ELFIO::dump::section_headers( std::cout, _elfio );
|
|
||||||
ELFIO::dump::segment_headers( std::cout, _elfio );
|
|
||||||
ELFIO::dump::symbol_tables( std::cout, _elfio );
|
|
||||||
ELFIO::dump::notes( std::cout, _elfio );
|
|
||||||
ELFIO::dump::modinfo( std::cout, _elfio );
|
|
||||||
ELFIO::dump::dynamic_tags( std::cout, _elfio );
|
|
||||||
ELFIO::dump::section_datas( std::cout, _elfio );
|
|
||||||
ELFIO::dump::segment_datas( std::cout, _elfio );
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::byte *Reader::getSnapshotPtr(DartSnapshot snapshot) const {
|
|
||||||
auto snapshotName = getSnapshotName(snapshot);
|
|
||||||
|
|
||||||
for(const auto& section: _elfio.sections) {
|
|
||||||
const ELFIO::symbol_section_accessor symbols(_elfio, section.get());
|
|
||||||
for(size_t i = 0; i < symbols.get_symbols_num(); ++i) {
|
|
||||||
std::string name;
|
|
||||||
ELFIO::Elf64_Addr address;
|
|
||||||
ELFIO::Elf_Xword size;
|
|
||||||
ELFIO::Elf_Half section_index;
|
|
||||||
unsigned char bind, type, other;
|
|
||||||
symbols.get_symbol(i, name, address, size, bind, type, section_index, other );
|
|
||||||
|
|
||||||
if(name == snapshotName) {
|
|
||||||
return _file.get() + address;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Reader::getSnapshotName(DartSnapshot snapshot) {
|
|
||||||
switch (snapshot) {
|
|
||||||
case DartSnapshot::VM_INSTRUCTIONS: return "_kDartVmSnapshotInstructions";
|
|
||||||
case DartSnapshot::VM_DATA: return "_kDartVmSnapshotData";
|
|
||||||
case DartSnapshot::ISOLATE_INSTRUCTIONS: return "_kDartIsolateSnapshotInstructions";
|
|
||||||
case DartSnapshot::ISOLATE_DATA: return "_kDartIsolateSnapshotData";
|
|
||||||
case DartSnapshot::BUILD_ID: return "_kDartSnapshotBuildId";
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
Snapshot Reader::getSnapshot(DartSnapshot snapshot) const {
|
|
||||||
auto ptr = getSnapshotPtr(snapshot);
|
|
||||||
return Snapshot(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by selim on 27.11.22.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef UNFLUTTER_READER_H
|
|
||||||
#define UNFLUTTER_READER_H
|
|
||||||
|
|
||||||
#include "elfio/elfio.hpp"
|
|
||||||
#include "Snapshot.h"
|
|
||||||
#include <filesystem>
|
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
|
||||||
|
|
||||||
namespace Dart {
|
|
||||||
|
|
||||||
enum class DartSnapshot {
|
|
||||||
VM_INSTRUCTIONS,
|
|
||||||
VM_DATA,
|
|
||||||
ISOLATE_INSTRUCTIONS,
|
|
||||||
ISOLATE_DATA,
|
|
||||||
BUILD_ID
|
|
||||||
};
|
|
||||||
|
|
||||||
class Reader {
|
|
||||||
private:
|
|
||||||
ELFIO::elfio _elfio;
|
|
||||||
std::unique_ptr<std::byte[]> _file;
|
|
||||||
|
|
||||||
private:
|
|
||||||
static std::string getSnapshotName(DartSnapshot snapshot) ;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit Reader(const fs::path& path);
|
|
||||||
void dumpInfo() const;
|
|
||||||
[[nodiscard]] const std::byte* getSnapshotPtr(DartSnapshot snapshot) const;
|
|
||||||
[[nodiscard]] Snapshot getSnapshot(DartSnapshot snapshot) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //UNFLUTTER_READER_H
|
|
||||||
@ -1,129 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by selim on 27.11.22.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "Snapshot.h"
|
|
||||||
#include "ClassId.h"
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <ranges>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
namespace Dart {
|
|
||||||
|
|
||||||
Snapshot::Snapshot(const std::byte *data) {
|
|
||||||
_magic = *(uint32_t*)data;
|
|
||||||
data += sizeof(_magic);
|
|
||||||
|
|
||||||
if(_magic != MAGIC) {
|
|
||||||
throw std::runtime_error("Snapshot magic mismatch");
|
|
||||||
}
|
|
||||||
|
|
||||||
_size = *(uint64_t*)data;
|
|
||||||
data += sizeof(_size);
|
|
||||||
|
|
||||||
_kind = *(Kind*)data;
|
|
||||||
data += sizeof(Kind);
|
|
||||||
|
|
||||||
_versionHash.assign((char*)data, 32);
|
|
||||||
data += _versionHash.size();
|
|
||||||
|
|
||||||
auto features = std::string((char*)data);
|
|
||||||
data += features.size() + 1;
|
|
||||||
_features = split(features);
|
|
||||||
|
|
||||||
_baseObjectsCount = Leb128Int(data);
|
|
||||||
data += _baseObjectsCount.size();
|
|
||||||
|
|
||||||
_allObjectsCount = Leb128Int(data);
|
|
||||||
data += _allObjectsCount.size();
|
|
||||||
|
|
||||||
_clustersCount = Leb128Int(data);
|
|
||||||
data += _clustersCount.size();
|
|
||||||
|
|
||||||
_fieldTableLength = Leb128Int(data);
|
|
||||||
data += _fieldTableLength.size();
|
|
||||||
|
|
||||||
_instructionsTableLength = Leb128Int(data);
|
|
||||||
data += _instructionsTableLength.size();
|
|
||||||
|
|
||||||
uint64_t cidAndCanonical = *(uint64_t*)data;
|
|
||||||
uint64_t cid = (cidAndCanonical >> 1) & 0xFFFFFFFF;
|
|
||||||
bool canonical = cidAndCanonical & 1;
|
|
||||||
|
|
||||||
// If non-predefined (instance) cid
|
|
||||||
if (cid >= (uint64_t)ClassId::NumPredefined || cid == (uint64_t)ClassId::Instance) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
auto nextInt = Leb128Int(data);
|
|
||||||
auto val = nextInt.value();
|
|
||||||
auto size = nextInt.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t Snapshot::size() const {
|
|
||||||
return _size;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Snapshot::kindString() const {
|
|
||||||
switch (_kind) {
|
|
||||||
case Kind::FULL: return "Full";
|
|
||||||
case Kind::FULL_JIT: return "Full JIT";
|
|
||||||
case Kind::FULL_AOT: return "Full AOT";
|
|
||||||
case Kind::FULL_CORE: return "Full core";
|
|
||||||
case Kind::NONE: return "None";
|
|
||||||
case Kind::INVALID: return "Invalid";
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Snapshot::versionHash() const {
|
|
||||||
return _versionHash;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Snapshot::featuresString() const {
|
|
||||||
std::stringstream ss;
|
|
||||||
size_t size = _features.size();
|
|
||||||
for(size_t i = 0; i < size; ++i) {
|
|
||||||
ss << _features[i];
|
|
||||||
if(i < size - 1) {
|
|
||||||
ss << ", ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> Snapshot::split(const std::string &str) {
|
|
||||||
std::vector<std::string> 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t Snapshot::instructionsTableLength() const {
|
|
||||||
return _instructionsTableLength.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,55 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by selim on 27.11.22.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef UNFLUTTER_SNAPSHOT_H
|
|
||||||
#define UNFLUTTER_SNAPSHOT_H
|
|
||||||
|
|
||||||
#include "Leb128Int.h"
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace Dart {
|
|
||||||
|
|
||||||
class Snapshot {
|
|
||||||
public:
|
|
||||||
enum class Kind: uint64_t {
|
|
||||||
FULL, FULL_CORE, FULL_JIT, FULL_AOT, NONE, INVALID
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint32_t MAGIC = 0xDCDCF5F5;
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint32_t _magic;
|
|
||||||
uint64_t _size;
|
|
||||||
Kind _kind;
|
|
||||||
std::string _versionHash;
|
|
||||||
std::vector<std::string> _features;
|
|
||||||
Leb128Int _baseObjectsCount;
|
|
||||||
Leb128Int _allObjectsCount;
|
|
||||||
Leb128Int _clustersCount;
|
|
||||||
Leb128Int _fieldTableLength;
|
|
||||||
Leb128Int _instructionsTableLength;
|
|
||||||
|
|
||||||
private:
|
|
||||||
static std::vector<std::string> split(const std::string &str);
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit Snapshot(const std::byte* data);
|
|
||||||
[[nodiscard]] uint64_t size() const;
|
|
||||||
[[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;
|
|
||||||
[[nodiscard]] uint64_t instructionsTableLength() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //UNFLUTTER_SNAPSHOT_H
|
|
||||||
30
dart/dart.h
Normal file
30
dart/dart.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 21.11.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef UNFLUTTER_DART_H
|
||||||
|
#define UNFLUTTER_DART_H
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
const int32_t DART_MAGIC = 0xdcdcf5f5;
|
||||||
|
|
||||||
|
enum class SnaphotKind: uint64_t {
|
||||||
|
FULL,
|
||||||
|
FULL_JIT,
|
||||||
|
FULL_AOT,
|
||||||
|
MESSAGE,
|
||||||
|
NONE,
|
||||||
|
INVALID
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SnapshotHeader {
|
||||||
|
uint32_t magic;
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t size2;
|
||||||
|
SnaphotKind kind;
|
||||||
|
std::array<char8_t, 32> versionHash;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //UNFLUTTER_DART_H
|
||||||
51
main.cpp
51
main.cpp
@ -1,19 +1,46 @@
|
|||||||
#include "dart/Reader.h"
|
#include "ThirdParty/elfio/elfio.hpp"
|
||||||
|
#include "dart/dart.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
Dart::Reader reader(argv[1]);
|
std::string elfPath = "/home/selim/Downloads/libapp.so"; //argv[1];
|
||||||
auto snapshot = reader.getSnapshot(Dart::DartSnapshot::ISOLATE_DATA);
|
std::cout << "Analyzing file: " << elfPath << std::endl;
|
||||||
|
|
||||||
std::cout << "Snapshot kind: " << snapshot.kindString() << std::endl;
|
ELFIO::elfio reader;
|
||||||
std::cout << "Size: " << snapshot.size() << std::endl;
|
if(!reader.load(elfPath)) {
|
||||||
std::cout << "Version hash: " << snapshot.versionHash() << std::endl;
|
std::cout << "error loading elf: " << elfPath << std::endl;
|
||||||
std::cout << "Features: " << snapshot.featuresString() << std::endl;
|
return 0;
|
||||||
std::cout << "Base objects: " << snapshot.baseObjectsCount() << std::endl;
|
}
|
||||||
std::cout << "All objects: " << snapshot.allObjectsCount() << std::endl;
|
|
||||||
std::cout << "Clusters: " << snapshot.clustersCount() << std::endl;
|
const void* data = nullptr;
|
||||||
std::cout << "Field table length: " << snapshot.fieldTableLength() << std::endl;
|
const void* text = nullptr;
|
||||||
std::cout << "Instructions table length: " << snapshot.instructionsTableLength() << std::endl;
|
|
||||||
|
ELFIO::Elf_Half sec_num = reader.sections.size();
|
||||||
|
std::cout << "Number of sections: " << sec_num << std::endl;
|
||||||
|
for ( int i = 0; i < sec_num; ++i ) {
|
||||||
|
const ELFIO::section* psec = reader.sections[i];
|
||||||
|
std::cout << " [" << i << "] "
|
||||||
|
<< psec->get_name()
|
||||||
|
<< "\t"
|
||||||
|
<< psec->get_size()
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
if(psec->get_name() == ".rodata") {
|
||||||
|
data = psec->get_data();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(psec->get_name() == ".text") {
|
||||||
|
text = psec->get_data();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto header = reinterpret_cast<const SnapshotHeader*>(data);
|
||||||
|
if(header->magic != DART_MAGIC) {
|
||||||
|
std::cout << "Wrong magic!!!!" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sizer = __builtin_bswap32(header->size);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user