current commit
260929.11 · deps: update lief to 1.0.0
/* 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