/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "DEX/json_internal.hpp"
#include "LIEF/DEX.hpp"
namespace LIEF::DEX {
json to_json_obj(const Object& v) {
JsonVisitor visitor;
visitor(v);
return visitor.get();
}
void JsonVisitor::visit(const File& file) {
JsonVisitor header_visitor;
header_visitor(file.header());
JsonVisitor map_item_visitor;
map_item_visitor(file.map());
// Classes
std::vector<json> classes;
for (const Class& cls : file.classes()) {
JsonVisitor clsvisitor;
clsvisitor(cls);
classes.emplace_back(clsvisitor.get());
}
node_["header"] = header_visitor.get();
node_["classes"] = classes;
node_["map"] = map_item_visitor.get();
}
void JsonVisitor::visit(const Header& header) {
node_["magic"] = header.magic();
node_["checksum"] = header.checksum();
node_["signature"] = header.signature();
node_["file_size"] = header.file_size();
node_["header_size"] = header.header_size();
node_["endian_tag"] = header.endian_tag();
node_["map"] = header.map();
node_["strings"] = header.strings();
node_["link"] = header.link();
node_["types"] = header.types();
node_["prototypes"] = header.prototypes();
node_["fields"] = header.fields();
node_["methods"] = header.methods();
node_["classes"] = header.classes();
node_["data"] = header.data();
}
void JsonVisitor::visit(const CodeInfo& /*code_info*/) {}
void JsonVisitor::visit(const Class& cls) {
std::vector<json> flags;
for (ACCESS_FLAGS f : cls.access_flags()) {
flags.emplace_back(to_string(f));
}
std::vector<json> fields;
for (const Field& f : cls.fields()) {
JsonVisitor fv;
fv(f);
fields.emplace_back(fv.get());
}
std::vector<json> methods;
for (const Method& m : cls.methods()) {
JsonVisitor mv;
mv(m);
methods.emplace_back(mv.get());
}
node_["fullname"] = cls.fullname();
node_["source_filename"] = cls.source_filename();
node_["access_flags"] = flags;
node_["index"] = cls.index();
node_["fields"] = fields;
node_["methods"] = methods;
if (const auto* parent = cls.parent()) {
node_["parent"] = parent->fullname();
}
}
void JsonVisitor::visit(const Field& field) {
std::vector<json> flags;
for (ACCESS_FLAGS f : field.access_flags()) {
flags.emplace_back(to_string(f));
}
JsonVisitor type_visitor;
type_visitor(*field.type());
node_["name"] = field.name();
node_["index"] = field.index();
node_["is_static"] = field.is_static();
node_["type"] = type_visitor.get();
node_["access_flags"] = flags;
}
void JsonVisitor::visit(const Method& method) {
std::vector<json> flags;
for (ACCESS_FLAGS f : method.access_flags()) {
flags.emplace_back(to_string(f));
}
JsonVisitor proto_visitor;
if (const Prototype* p = method.prototype()) {
proto_visitor(*p);
}
node_["name"] = method.name();
node_["code_offset"] = method.code_offset();
node_["index"] = method.index();
node_["is_virtual"] = method.is_virtual();
node_["prototype"] = proto_visitor.get();
node_["access_flags"] = flags;
}
void JsonVisitor::visit(const Type& type) {
node_["type"] = to_string(type.type());
switch (type.type()) {
case Type::TYPES::CLASS:
{
node_["value"] = type.cls().fullname();
break;
}
case Type::TYPES::PRIMITIVE:
{
node_["value"] = Type::pretty_name(type.primitive());
break;
}
case Type::TYPES::ARRAY:
{
const Type& uderlying_t = type.underlying_array_type();
node_["dim"] = type.dim();
if (uderlying_t.type() == Type::TYPES::CLASS) {
node_["value"] = uderlying_t.cls().fullname();
break;
}
if (uderlying_t.type() == Type::TYPES::PRIMITIVE) {
node_["value"] = Type::pretty_name(type.primitive());
break;
}
break;
}
default:
{
}
}
}
void JsonVisitor::visit(const Prototype& type) {
JsonVisitor rtype_visitor;
if (const Type* rty = type.return_type()) {
rtype_visitor(*rty);
}
std::vector<json> params;
for (const Type& t : type.parameters_type()) {
JsonVisitor pvisitor;
pvisitor(t);
params.emplace_back(pvisitor.get());
}
node_["return_type"] = rtype_visitor.get();
node_["parameters"] = params;
}
void JsonVisitor::visit(const MapItem& item) {
node_["offset"] = item.offset();
node_["size"] = item.size();
node_["type"] = to_string(item.type());
}
void JsonVisitor::visit(const MapList& list) {
std::vector<json> items;
for (const MapItem& i : list.items()) {
JsonVisitor itemvisitor;
itemvisitor(i);
items.emplace_back(itemvisitor.get());
}
node_["map_items"] = items;
}
} // namespace LIEF::DEX