Compare commits
10 Commits
5aa115e8fa
...
4420fee251
| Author | SHA1 | Date | |
|---|---|---|---|
| 4420fee251 | |||
| 24917a40ab | |||
| 59e8789455 | |||
| fdaf533bca | |||
|
|
cfd527fb54 | ||
|
|
5ec1117337 | ||
| 2a6e45b05d | |||
| 9cc38354d7 | |||
| 328703ac5f | |||
| cabd4abe7f |
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
.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/dart.h)
|
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)
|
||||||
|
|
||||||
target_include_directories(unflutter PRIVATE ${CMAKE_SOURCE_DIR}/ThirdParty)
|
target_include_directories(unflutter PRIVATE ${CMAKE_SOURCE_DIR}/ThirdParty)
|
||||||
170
dart/ClassId.h
Normal file
170
dart/ClassId.h
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
36
dart/Leb128Int.cpp
Normal file
36
dart/Leb128Int.cpp
Normal file
@ -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<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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
28
dart/Leb128Int.h
Normal file
28
dart/Leb128Int.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
84
dart/Reader.cpp
Normal file
84
dart/Reader.cpp
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
//
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
41
dart/Reader.h
Normal file
41
dart/Reader.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
129
dart/Snapshot.cpp
Normal file
129
dart/Snapshot.cpp
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
//
|
||||||
|
// 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
55
dart/Snapshot.h
Normal file
55
dart/Snapshot.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
//
|
||||||
|
// 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
30
dart/dart.h
@ -1,30 +0,0 @@
|
|||||||
//
|
|
||||||
// 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,46 +1,19 @@
|
|||||||
#include "ThirdParty/elfio/elfio.hpp"
|
#include "dart/Reader.h"
|
||||||
#include "dart/dart.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
std::string elfPath = "/home/selim/Downloads/libapp.so"; //argv[1];
|
Dart::Reader reader(argv[1]);
|
||||||
std::cout << "Analyzing file: " << elfPath << std::endl;
|
auto snapshot = reader.getSnapshot(Dart::DartSnapshot::ISOLATE_DATA);
|
||||||
|
|
||||||
ELFIO::elfio reader;
|
std::cout << "Snapshot kind: " << snapshot.kindString() << std::endl;
|
||||||
if(!reader.load(elfPath)) {
|
std::cout << "Size: " << snapshot.size() << std::endl;
|
||||||
std::cout << "error loading elf: " << elfPath << std::endl;
|
std::cout << "Version hash: " << snapshot.versionHash() << std::endl;
|
||||||
return 0;
|
std::cout << "Features: " << snapshot.featuresString() << std::endl;
|
||||||
}
|
std::cout << "Base objects: " << snapshot.baseObjectsCount() << std::endl;
|
||||||
|
std::cout << "All objects: " << snapshot.allObjectsCount() << std::endl;
|
||||||
const void* data = nullptr;
|
std::cout << "Clusters: " << snapshot.clustersCount() << std::endl;
|
||||||
const void* text = nullptr;
|
std::cout << "Field table length: " << snapshot.fieldTableLength() << std::endl;
|
||||||
|
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