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/
|
||||
cmake-build-debug/
|
||||
|
||||
|
||||
@ -3,6 +3,6 @@ project(unflutter)
|
||||
|
||||
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)
|
||||
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/dart.h"
|
||||
|
||||
#include "dart/Reader.h"
|
||||
#include <iostream>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
std::string elfPath = "/home/selim/Downloads/libapp.so"; //argv[1];
|
||||
std::cout << "Analyzing file: " << elfPath << std::endl;
|
||||
Dart::Reader reader(argv[1]);
|
||||
auto snapshot = reader.getSnapshot(Dart::DartSnapshot::ISOLATE_DATA);
|
||||
|
||||
ELFIO::elfio reader;
|
||||
if(!reader.load(elfPath)) {
|
||||
std::cout << "error loading elf: " << elfPath << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const void* data = nullptr;
|
||||
const void* text = nullptr;
|
||||
|
||||
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);
|
||||
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;
|
||||
std::cout << "Instructions table length: " << snapshot.instructionsTableLength() << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user