157 lines
5.2 KiB
C++
157 lines
5.2 KiB
C++
#include "FieldInfo.h"
|
|
#include "Methods.h"
|
|
#include <ConstantPoolTags/Tags.h>
|
|
#include <SpecTypes.h>
|
|
#include <cassert>
|
|
#include <cstdint>
|
|
#include <cstdlib>
|
|
#include <fstream>
|
|
#include <ClassFormat.h>
|
|
#include <Utils/Utils.h>
|
|
#include <iostream>
|
|
#include <Globals.h>
|
|
|
|
#define JVM_STACK_SIZE 4096
|
|
|
|
int stack[JVM_STACK_SIZE];
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
if (argc < 2)
|
|
{
|
|
std::cerr << "Usage " << argv[0] << " <jar file to run>" << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
for (int i = 0; i < JVM_STACK_SIZE; i++)
|
|
{
|
|
stack[i] = 0;
|
|
}
|
|
std::ifstream f;
|
|
JavaClassFormat jc;
|
|
f.open(argv[1], std::ios::binary);
|
|
|
|
ConstantPoolTags::ConstantPool cp;
|
|
|
|
if (!f.is_open())
|
|
{
|
|
std::cerr << "Failed to open " << argv[1] << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
// std::vector<uint8_t> Globals::buffer(std::istreambuf_iterator<char>(f), {});
|
|
Globals::buffer() = std::vector<uint8_t>(std::istreambuf_iterator<char>(f), {});
|
|
f.close();
|
|
|
|
int size = Globals::buffer().size();
|
|
|
|
jc.magic = Utils::ReadFromStartIntoVal<uint32_t>(Globals::buffer(), 4);
|
|
|
|
assert(jc.magic.ToHostFormat() == 0xcafebabe);
|
|
|
|
jc.minor = Utils::ReadFromStartIntoVal<uint16_t>(Globals::buffer(), 2);
|
|
|
|
jc.major = Utils::ReadFromStartIntoVal<uint16_t>(Globals::buffer(), 2);
|
|
|
|
jc.constant_pool_count = Utils::ReadFromStartIntoVal<uint16_t>(Globals::buffer(), 2);
|
|
|
|
std::cout << "Magic: 0x" << std::hex << jc.magic.ToHostFormat() << std::endl;
|
|
std::cout << "Minor: " << Utils::Hex2Int(jc.minor.ToHostFormat()) << std::endl;
|
|
std::cout << "Major: " << Utils::Hex2Int(jc.major.ToHostFormat()) << std::endl;
|
|
std::cout << "Constant Pool Count: "
|
|
<< Utils::Hex2Int(jc.constant_pool_count.ToHostFormat()) << std::endl;
|
|
|
|
for (int i = 0; i < jc.constant_pool_count.ToHostFormat() - 1; i++)
|
|
{
|
|
ConstantPoolTags::ConstantPool cp;
|
|
cp.tag = (ConstantPoolTags::Tags)Utils::ReadFromStartIntoVal<int>(Globals::buffer(), 1);
|
|
|
|
ConstantPoolTags::ConstantPoolParser(cp, jc);
|
|
}
|
|
jc.access_flags = Utils::ReadFromStartIntoVal<uint16_t>(Globals::buffer(), 2);
|
|
jc.this_class = Utils::ReadFromStartIntoVal<uint16_t>(Globals::buffer(), 2);
|
|
jc.super_class = Utils::ReadFromStartIntoVal<uint16_t>(Globals::buffer(), 2);
|
|
jc.interfaces_count = Utils::ReadFromStartIntoVal<uint16_t>(Globals::buffer(), 2);
|
|
|
|
assert(jc.this_class.ToHostFormat() >= 0);
|
|
assert(jc.super_class.ToHostFormat() >= 0);
|
|
|
|
assert(jc.constant_pool.size() > jc.this_class.ToHostFormat());
|
|
assert(jc.constant_pool[jc.this_class.ToHostFormat() - 1].tag == ConstantPoolTags::Tags::Class);
|
|
|
|
if (jc.super_class.ToHostFormat() != 0)
|
|
{
|
|
// For a class, the value of the super_class item either must be zero or
|
|
// must be a valid index into the constant_pool table. If the value of
|
|
// the super_class item is nonzero, the constant_pool entry at that index
|
|
// must be a CONSTANT_Class_info structure representing the direct superclass
|
|
// of the class defined by this class file. Neither the direct superclass nor
|
|
// any of its superclasses may have the ACC_FINAL flag set in the access_flags
|
|
// item of its ClassFile structure.
|
|
|
|
// FIXME: Finish implementing the above comment.
|
|
assert(jc.constant_pool.size() > jc.super_class.ToHostFormat());
|
|
assert(jc.constant_pool[jc.super_class.ToHostFormat() - 1].tag == ConstantPoolTags::Tags::Class);
|
|
}
|
|
else
|
|
{
|
|
// FIXME: Implement zero super_class checks
|
|
}
|
|
|
|
std::cout << "Access Flags: " << jc.access_flags.ToHostFormat() << std::endl;
|
|
std::cout << "This Class: " << std::dec << jc.this_class.ToHostFormat() << std::endl;
|
|
std::cout << "Super Class: " << jc.super_class.ToHostFormat() << std::endl;
|
|
std::cout << "Interfaces Count: " << std::dec << jc.interfaces_count.ToHostFormat() << std::endl;
|
|
|
|
if (jc.access_flags.ToHostFormat() >= (int)JavaClass::ACCESS_FLAGS::ACC_MODULE)
|
|
{
|
|
assert(jc.access_flags.ToHostFormat() == (int)JavaClass::ACCESS_FLAGS::ACC_MODULE);
|
|
// Conditions for when jc.access_flags == JavaClass::ACCESS_FLAGS::ACC_MODULE
|
|
// major_version, minor_version: ≥ 53.0 (i.e., Java SE 9 and above)
|
|
assert(jc.major.ToHostFormat() >= 53);
|
|
assert(jc.minor.ToHostFormat() >= 0);
|
|
|
|
}
|
|
// std::cout << std::dec << (int)(jc.constant_pool[jc.this_class.ToHostFormat()].info.tag) << std::endl;
|
|
|
|
// std::cout << "" << std::hex << size - Globals::buffer().size() << std::endl;
|
|
|
|
for (int i = 0; i < jc.interfaces_count.ToHostFormat(); i++)
|
|
{
|
|
uint16_t data = Utils::ReadFromStartIntoVal<uint16_t>(Globals::buffer(), 2);
|
|
|
|
jc.interfaces.push_back(data);
|
|
}
|
|
|
|
jc.fields_count = Utils::ReadFromStartIntoVal<uint16_t>(Globals::buffer(), 2);
|
|
|
|
std::cout << "Fields Count: " << jc.fields_count.ToHostFormat() << std::endl;
|
|
|
|
for (int i = 0; i < jc.fields_count.ToHostFormat(); i++)
|
|
{
|
|
field_info f;
|
|
FieldInfo::FieldInfoParser(f, jc);
|
|
}
|
|
|
|
jc.methods_count = Utils::ReadFromStartIntoVal<uint16_t>(Globals::buffer());
|
|
|
|
for (int i = 0; i < jc.methods_count.ToHostFormat(); i++)
|
|
{
|
|
method_info m;
|
|
Methods::MethodParser(m, jc);
|
|
|
|
// std::cout << std::hex << size - Globals::buffer().size() << std::endl;
|
|
}
|
|
|
|
for (int i = 0; i < jc.constant_pool_count.ToHostFormat() - 1; i++)
|
|
{
|
|
std::cout << "(" << i << ") " << (int)jc.constant_pool[i].tag << std::endl;
|
|
}
|
|
|
|
std::cout << &jc.constant_pool[30].info << std::endl;
|
|
// delete[] ((ConstantPoolTags::ConstantUtf8Info*)(&jc.constant_pool[30].info))->bytes;
|
|
|
|
// std::cout << jc.methods_count.ToHostFormat() << std::endl;
|
|
|
|
return 0;
|
|
} |