Add reader and snapshot classes
This commit is contained in:
parent
9cc38354d7
commit
2a6e45b05d
@ -3,6 +3,6 @@ project(unflutter)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
add_executable(unflutter main.cpp dart/dart.h dart/dart.cpp)
|
||||
add_executable(unflutter main.cpp dart/Reader.cpp dart/Reader.h dart/Snapshot.cpp dart/Snapshot.h)
|
||||
|
||||
target_include_directories(unflutter PRIVATE ${CMAKE_SOURCE_DIR}/ThirdParty)
|
||||
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 <fstream>
|
||||
#include <elf.h>
|
||||
|
||||
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;
|
||||
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
|
||||
75
dart/Snapshot.cpp
Normal file
75
dart/Snapshot.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
//
|
||||
// Created by selim on 27.11.22.
|
||||
//
|
||||
|
||||
#include "Snapshot.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();
|
||||
|
||||
auto view = features
|
||||
| std::ranges::views::split(' ')
|
||||
| std::ranges::views::transform([](auto &&rng) {
|
||||
return std::string(&*rng.begin(), std::ranges::distance(rng));
|
||||
});
|
||||
|
||||
_features.assign(view.begin(), view.end());
|
||||
}
|
||||
|
||||
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::MESSAGE: return "Message";
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
40
dart/Snapshot.h
Normal file
40
dart/Snapshot.h
Normal file
@ -0,0 +1,40 @@
|
||||
//
|
||||
// Created by selim on 27.11.22.
|
||||
//
|
||||
|
||||
#ifndef UNFLUTTER_SNAPSHOT_H
|
||||
#define UNFLUTTER_SNAPSHOT_H
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Dart {
|
||||
|
||||
class Snapshot {
|
||||
public:
|
||||
enum class Kind: uint64_t {
|
||||
FULL, FULL_JIT, FULL_AOT, MESSAGE, 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;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //UNFLUTTER_SNAPSHOT_H
|
||||
@ -1,16 +0,0 @@
|
||||
//
|
||||
// Created by selim on 26.11.22.
|
||||
//
|
||||
|
||||
#include "dart.h"
|
||||
|
||||
std::string snapshotKindString(SnapshotKind kind) {
|
||||
switch (kind) {
|
||||
case FULL: return "Full";
|
||||
case FULL_JIT: return "Full JIT";
|
||||
case FULL_AOT: return "Full AOT";
|
||||
case MESSAGE: return "Message";
|
||||
case NONE: return "None";
|
||||
case INVALID: return "Invalid";
|
||||
}
|
||||
}
|
||||
40
dart/dart.h
40
dart/dart.h
@ -1,40 +0,0 @@
|
||||
//
|
||||
// Created by selim on 21.11.22.
|
||||
//
|
||||
|
||||
#ifndef UNFLUTTER_DART_H
|
||||
#define UNFLUTTER_DART_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <array>
|
||||
#include <string>
|
||||
|
||||
const uint32_t DART_MAGIC = 0xDCDCF5F5;
|
||||
|
||||
const char* vmInstructions = "_kDartVmSnapshotInstructions";
|
||||
const char* vmData = "_kDartVmSnapshotData";
|
||||
const char* isolateInstructions = "_kDartIsolateSnapshotInstructions";
|
||||
const char* isolateData = "_kDartIsolateSnapshotData";
|
||||
const char* buildId = "_kDartSnapshotBuildId";
|
||||
|
||||
enum SnapshotKind: uint64_t {
|
||||
FULL,
|
||||
FULL_JIT,
|
||||
FULL_AOT,
|
||||
MESSAGE,
|
||||
NONE,
|
||||
INVALID
|
||||
};
|
||||
|
||||
#pragma pack (1)
|
||||
struct SnapshotHeader {
|
||||
uint32_t magic;
|
||||
int64_t size;
|
||||
SnapshotKind kind;
|
||||
std::array<char8_t, 32> versionHash;
|
||||
};
|
||||
#pragma pack ()
|
||||
|
||||
std::string snapshotKindString(SnapshotKind kind);
|
||||
|
||||
#endif //UNFLUTTER_DART_H
|
||||
86
main.cpp
86
main.cpp
@ -1,86 +1,14 @@
|
||||
#include "ThirdParty/elfio/elfio.hpp"
|
||||
#include "dart/dart.h"
|
||||
#include "elfio/elfio_dump.hpp"
|
||||
|
||||
#include "dart/Reader.h"
|
||||
#include <iostream>
|
||||
#include <cstddef>
|
||||
#include <elf.h>
|
||||
|
||||
void dumpElf(const ELFIO::elfio& reader) {
|
||||
ELFIO::dump::header( std::cout, reader );
|
||||
ELFIO::dump::section_headers( std::cout, reader );
|
||||
ELFIO::dump::segment_headers( std::cout, reader );
|
||||
ELFIO::dump::symbol_tables( std::cout, reader );
|
||||
ELFIO::dump::notes( std::cout, reader );
|
||||
ELFIO::dump::modinfo( std::cout, reader );
|
||||
ELFIO::dump::dynamic_tags( std::cout, reader );
|
||||
ELFIO::dump::section_datas( std::cout, reader );
|
||||
ELFIO::dump::segment_datas( std::cout, reader );
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
std::string elfPath = "/home/selim/Загрузки/libapp.so"; //argv[1];
|
||||
std::cout << "Analyzing file: " << elfPath << std::endl;
|
||||
Dart::Reader reader("/home/selim/Downloads/libapp.so");
|
||||
auto snapshot = reader.getSnapshot(Dart::DartSnapshot::VM_DATA);
|
||||
|
||||
ELFIO::elfio reader;
|
||||
if(!reader.load(elfPath)) {
|
||||
std::cout << "error loading elf: " << elfPath << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
dumpElf(reader);
|
||||
|
||||
const std::byte* data = nullptr;
|
||||
const std::byte* text = nullptr;
|
||||
|
||||
for(auto section: reader.sections) {
|
||||
|
||||
}
|
||||
|
||||
ELFIO::Elf_Half sec_num = reader.sections.size();
|
||||
for ( int i = 0; i < sec_num; ++i ) {
|
||||
ELFIO::section* psec = reader.sections[i];
|
||||
|
||||
if(psec->get_name() == ".rodata") {
|
||||
data = reinterpret_cast<const std::byte*>(psec->get_data());
|
||||
}
|
||||
|
||||
if(psec->get_name() == ".text") {
|
||||
text = reinterpret_cast<const std::byte*>(psec->get_data());
|
||||
}
|
||||
|
||||
auto sectionType = psec->get_type();
|
||||
if(sectionType == SHT_SYMTAB || sectionType == SHT_DYNSYM) {
|
||||
const ELFIO::symbol_section_accessor symbols( reader, psec );
|
||||
for ( unsigned int j = 0; j < symbols.get_symbols_num(); ++j ) {
|
||||
std::string name;
|
||||
Elf64_Addr value;
|
||||
ELFIO::Elf_Xword size;
|
||||
unsigned char bind;
|
||||
unsigned char type;
|
||||
ELFIO::Elf_Half section_index;
|
||||
unsigned char other;
|
||||
symbols.get_symbol( j, name, value, size, bind,
|
||||
type, section_index, other );
|
||||
std::cout << j << " " << name << " " << value << " (section " << section_index << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "====================================================" << std::endl;
|
||||
std::cout << "===== .rodata ======================================" << std::endl;
|
||||
std::cout << std::endl;
|
||||
|
||||
auto header = reinterpret_cast<const SnapshotHeader*>(data);
|
||||
if(header->magic != DART_MAGIC) {
|
||||
std::cout << "Wrong magic!!!!" << std::endl;
|
||||
}
|
||||
|
||||
std::cout << "Snapshot kind: " << snapshotKindString(header->kind) << std::endl;
|
||||
std::cout << "Size: " << header->size << std::endl;
|
||||
std::cout << std::endl;
|
||||
|
||||
auto ptr = data + header->size + 4;
|
||||
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;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user