Initial Commit

This commit is contained in:
ComputerKing12 2024-08-13 08:12:22 -04:00 committed by calcium
parent 0da888414c
commit 3429da6282
36 changed files with 924 additions and 0 deletions

21
CMakeLists.txt Normal file
View File

@ -0,0 +1,21 @@
cmake_minimum_required(VERSION 3.25)
project(JavaBytecodeParser)
include_directories(include)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CXX_STANDARD 23)
add_subdirectory(src)
set(CONSTANT_POOL_TAG_SRC ${CONSTANT_POOL_TAG_SRC})
message("src " ${CONSTANT_POOL_TAG_SRC})
add_executable(parser
src/Main.cpp
${CONSTANT_POOL_TAG_SRC}
)
set(CMAKE_CXX_FLAGS "-std=c++${CXX_STANDARD} -O0 -g -Wpedantic")

58
include/BigEndian.h Normal file
View File

@ -0,0 +1,58 @@
#ifndef __JAVA_PARSER_BIG_ENDIAN_H
#define __JAVA_PARSER_BIG_ENDIAN_H
#include <Types.h>
#include <cstddef>
template <typename T>
class BigEndian
{
public:
ALWAYS_INLINE BigEndian(T val)
{
_val = val;
}
ALWAYS_INLINE BigEndian()
{
}
ALWAYS_INLINE T ToHostFormat()
{
return ToHostFormat(_val);
}
ALWAYS_INLINE T ToHostFormat(T val)
{
switch (sizeof(T))
{
case 1:
return val;
case 2:
return __builtin_bswap16(val);
case 4:
return __builtin_bswap32(val);
case 8:
return __builtin_bswap64(val);
// Clang doesn't support __builtin_bswap128, so we fall back to a generic byte-order swap implementation
#ifndef __clang__
case 16:
return __builtin_bswap128(val);
#endif
default:
char *p = reinterpret_cast<char*>(val);
size_t lo, hi;
for(lo = 0, hi = sizeof(T) - 1; hi > lo; lo++, hi--)
{
char tmp = p[lo];
p[lo] = p[hi];
p[hi] = tmp;
}
return (T)(*p);
}
}
private:
T _val;
};
#endif

105
include/ClassFormat.h Normal file
View File

@ -0,0 +1,105 @@
#ifndef __JAVA_PARSER_CLASS_FORMAT_H
#define __JAVA_PARSER_CLASS_FORMAT_H
#include <SpecTypes.h>
#include <cstdlib>
#include <vector>
#include <ConstantPoolTags/Tags.h>
namespace FieldInfo
{
enum class ACCESS_FLAGS
{
ACC_PUBLIC = 0x0001,
ACC_PRIVATE,
ACC_PROTECTED = 0x0004,
ACC_STATIC = 0x0008,
ACC_FINAL = 0x0010,
ACC_VOLATILE = 0x0040,
ACC_TRANSIENT = 0x0080,
ACC_SYNTHETIC = 0x1000,
ACC_ENUM = 0x4000
};
} // namespace FieldInfo
namespace JavaClass
{
enum class ACCESS_FLAGS
{
ACC_PUBLIC = 0x0001,
ACC_FINAL = 0x0010,
ACC_SUPER = 0x0020,
ACC_INTERFACE = 0x0200,
ACC_ABSTRACT = 0x0400,
ACC_SYNTHETIC = 0x1000,
ACC_ANNOTATION = 0x2000,
ACC_ENUM = 0x4000,
ACC_MODULE = 0x8000
};
} // namespace JavaClass
namespace Method
{
enum class ACCESS_FLAGS
{
ACC_PUBLIC = 0x0001, // Declared public; may be accessed from outside its package.
ACC_PRIVATE = 0x0002, // Declared private; accessible only within the defining class and other classes belonging to the same nest (§5.4.4).
ACC_PROTECTED = 0x0004, // Declared protected; may be accessed within subclasses.
ACC_STATIC = 0x0008, // Declared static.
ACC_FINAL = 0x0010, // Declared final; must not be overridden (§5.4.5).
ACC_SYNCHRONIZED = 0x0020, // Declared synchronized; invocation is wrapped by a monitor use.
ACC_BRIDGE = 0x0040, // A bridge method, generated by the compiler.
ACC_VARARGS = 0x0080, // Declared with variable number of arguments.
ACC_NATIVE = 0x0100, // Declared native; implemented in a language other than the Java programming language.
ACC_ABSTRACT = 0x0400, // Declared abstract; no implementation is provided.
ACC_STRICT = 0x0800, // In a class file whose major version number is at least 46 and at most 60: Declared strictfp.
ACC_SYNTHETIC = 0x1000 // Declared synthetic; not present in the source code.
};
} // namespace Method
typedef struct
{
u2 attribute_name_index;
u4 attribute_length;
std::vector<u1> info;
} attribute_info;
typedef struct
{
u2 access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
std::vector<attribute_info> attributes;
} method_info;
typedef struct
{
u2 access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
std::vector<attribute_info> attributes;
} field_info;
struct JavaClassFormat
{
u4 magic;
u2 minor;
u2 major;
u2 constant_pool_count;
std::vector<ConstantPoolTags::ConstantPool> constant_pool;
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
std::vector<u2> interfaces;
u2 fields_count;
std::vector<field_info> fields;
u2 methods_count;
std::vector<method_info> methods;
u2 attributes_count;
std::vector<attribute_info> attributes;
};
#endif

View File

@ -0,0 +1,90 @@
#ifndef __JAVA_PARSER_CONSTANT_POOL_TAGS_TAGS_H
#define __JAVA_PARSER_CONSTANT_POOL_TAGS_TAGS_H
#include <SpecTypes.h>
#include <cstdint>
#include <cstdlib>
struct JavaClassFormat;
namespace ConstantPoolTags
{
enum class Tags : uint8_t
{
Utf8 = 1,
Integer = 3,
Float,
Long,
Double,
Class,
String,
Fieldref,
Methodref,
InterfaceMethodref,
NameAndType,
MethodHandle = 15,
MethodType,
Dynamic,
InvokeDynamic,
Module,
Package
};
struct ConstantPoolInfo
{
ConstantPoolTags::Tags tag;
};
struct ConstantPool
{
ConstantPoolTags::Tags tag;
ConstantPoolInfo info;
};
struct ConstantUtf8Info : ConstantPoolInfo
{
ConstantPoolTags::Tags tag;
u2 length;
unsigned char* bytes;
// std::vector<unsigned char> bytes;
};
struct ConstantClassInfo : ConstantPoolInfo
{
ConstantPoolTags::Tags tag;
u2 name_index;
};
struct ConstantStringInfo : ConstantPoolInfo
{
ConstantPoolTags::Tags tag;
u2 string_index;
};
struct ConstantFieldrefInfo : ConstantPoolInfo
{
ConstantPoolTags::Tags tag;
u2 class_index;
u2 name_and_type_index;
};
struct ConstantMethodrefInfo : ConstantPoolInfo
{
ConstantPoolTags::Tags tag;
u2 class_index;
u2 name_and_type_index;
};
struct ConstantNameAndTypeInfo : ConstantPoolInfo
{
ConstantPoolTags::Tags tag;
u2 name_index;
u2 descriptor_index;
};
void ConstantPoolParser(ConstantPool &p, JavaClassFormat &jc);
}
#endif

12
include/FieldInfo.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef __JAVA_PARSER_FIELD_INFO_H
#define __JAVA_PARSER_FIELD_INFO_H
#include <ClassFormat.h>
namespace FieldInfo
{
void FieldInfoParser(field_info &p, JavaClassFormat &jc);
}
#endif

17
include/Globals.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef __JAVA_PARSER_GLOBALS_H
#define __JAVA_PARSER_GLOBALS_H
#include <vector>
#include <cstdint>
namespace Globals
{
inline std::vector<uint8_t> &buffer()
{
static std::vector<uint8_t> BUFFER;
return BUFFER;
}
}
#endif

11
include/Methods.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef __JAVA_PARSER_METHOD_INFO_H
#define __JAVA_PARSER_METHOD_INFO_H
#include <ClassFormat.h>
namespace Methods
{
void MethodParser(method_info &p, JavaClassFormat &jc);
}
#endif

11
include/SpecTypes.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef __JAVA_PARSER_SPEC_TYPES_H
#define __JAVA_PARSER_SPEC_TYPES_H
#include <cstdint>
#include <BigEndian.h>
typedef BigEndian<uint32_t> u4;
typedef BigEndian<uint16_t> u2;
typedef BigEndian<uint8_t> u1;
#endif

6
include/Types.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef __JAVA_PARSER_TYPES_H
#define __JAVA_PARSER_TYPES_H
#define ALWAYS_INLINE __attribute__((always_inline)) inline
#endif

138
include/Utils/Utils.h Normal file
View File

@ -0,0 +1,138 @@
#ifndef __JAVA_PARSER_UTILS_UTILS_H
#define __JAVA_PARSER_UTILS_UTILS_H
#include <vector>
#include <cstdint>
#include <stdexcept>
#include <SpecTypes.h>
namespace Utils
{
template <typename T, typename X>
ALWAYS_INLINE T M_POW(T x, X power)
{
T ret = 1;
if (power == 0)
return 1;
for (int i = 0; i < power; i++)
{
ret *= x;
}
if (power < 0)
{
for (int i = (int)power; i > 0; i++)
{
ret *= 1 / x;
}
}
return ret;
}
template<typename T = unsigned int>
ALWAYS_INLINE T Hex2Int(T x)
{
T ret = 0;
int digits = 0;
while (x != 0)
{
T a = x % 10;
ret += a * M_POW(16, digits);
x = (int)(x / 10);
digits += 1;
}
return ret;
}
template <typename T>
ALWAYS_INLINE const char* Int2Hex(T x)
{
constexpr const char *digits[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"};
std::vector<char> ret;
while (x != 0)
{
T rem = x % 16;
x = (int)(x / 16);
ret.push_back(digits[rem]);
}
for (int i = 0; i < ret.size() / 2; i++)
{
char tmp = ret[i];
ret[i] = ret[ret.size() - i];
ret[ret.size() - i] = tmp;
}
const char *data = ret.data();
return data;
}
template <typename T>
ALWAYS_INLINE std::vector<T> Read(std::vector<T> &vec, int start, int end)
{
std::vector<T> ret;
for (int i = start; i < end; i++)
{
ret.push_back(vec.at(i));
}
return ret;
}
template <typename T>
ALWAYS_INLINE std::vector<T> ReadFromStart(std::vector<T> &vec, int end)
{
std::vector<T> ret = Read(vec, 0, end);
for (int i = 0; i < end; i++)
vec.erase(vec.begin());
return ret;
}
template <typename T, typename vec_type=uint8_t>
ALWAYS_INLINE T vecToVal(std::vector<vec_type> &vec)
{
if (vec.size() > sizeof(T))
{
throw std::out_of_range("Provided vector larger than type to convert to.");
}
T ret = 0;
for (int i = vec.size() - 1; i >= 0; i--)
{
ret |= vec.at(i) << (i * 8);
}
return ret;
}
template <typename T, typename vec_type>
ALWAYS_INLINE T ReadFromStartIntoVal(std::vector<vec_type> &vec, int end)
{
std::vector<uint8_t> val = ReadFromStart<vec_type>(vec, end);
return vecToVal<T>(val);
}
template <typename T, typename vec_type>
ALWAYS_INLINE T ReadFromStartIntoVal(std::vector<vec_type> &vec)
{
std::vector<uint8_t> val = ReadFromStart<vec_type>(vec, sizeof(T));
return vecToVal<T>(val);
}
}
#endif

13
samples/Hello.java Normal file
View File

@ -0,0 +1,13 @@
public class Hello
{
public static void main(String[] args)
{
final int i = 0;
final double j = 1.0;
final String k = "Hello World1";
System.out.println("Hello World");
System.out.println(i);
System.out.println(j);
System.out.println(k);
}
}

9
src/CMakeLists.txt Normal file
View File

@ -0,0 +1,9 @@
add_subdirectory(ConstantPoolTags)
add_subdirectory(FieldInfo)
add_subdirectory(Method)
set(CONSTANT_POOL_TAG_SRC
${CONSTANT_POOL_TAG_SRC}
PARENT_SCOPE
)

View File

@ -0,0 +1,24 @@
set(CWD ${CMAKE_CURRENT_LIST_DIR})
set(CONSTANT_POOL_TAG_SRC
${CWD}/Class.cpp
${CWD}/Double.cpp
${CWD}/Dynamic.cpp
${CWD}/Fieldref.cpp
${CWD}/Float.cpp
${CWD}/Integer.cpp
${CWD}/InterfaceMethodref.cpp
${CWD}/InvokeDynamic.cpp
${CWD}/Long.cpp
${CWD}/MethodHandle.cpp
${CWD}/MethodType.cpp
${CWD}/Methodref.cpp
${CWD}/Module.cpp
${CWD}/NameAndType.cpp
${CWD}/Package.cpp
${CWD}/String.cpp
${CWD}/Utf8.cpp
${CWD}/PoolParser.cpp
PARENT_SCOPE
)

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

@ -0,0 +1,170 @@
#include <Globals.h>
#include <ConstantPoolTags/Tags.h>
#include <Utils/Utils.h>
#include <cstdint>
#include <cstdlib>
#include <iostream>
#include <ClassFormat.h>
#include <ostream>
void ConstantPoolTags::ConstantPoolParser(ConstantPool &p, JavaClassFormat &jc)
{
switch (p.tag)
{
case Tags::Utf8: {
// std::cout << "FIXME: Implement Utf8 Constant Pool Tag" << std::endl;
ConstantUtf8Info ref = static_cast<ConstantUtf8Info>(p.info);
std::vector<uint8_t> length = Utils::ReadFromStart(Globals::buffer(), 2);
ref.tag = p.tag;
ref.length = Utils::vecToVal<uint16_t>(length);
unsigned char x = Utils::ReadFromStartIntoVal<unsigned char>(Globals::buffer(), 1);
bool valid = true;
ref.bytes = new unsigned char[ref.length.ToHostFormat()];
for (int i = 0; i < ref.length.ToHostFormat(); i++)
{
if ((x & 0x80) == 0)
{
ref.bytes[i] = x;
}
else if ((x & 0x800) == 0)
{
unsigned char y = Utils::ReadFromStartIntoVal<unsigned char>(Globals::buffer(), 1);
ref.bytes[i] = ((x & 0x1f) << 6) + (y & 0x3f);
}
else if ((x & 0x10000) == 0)
{
unsigned char y = Utils::ReadFromStartIntoVal<unsigned char>(Globals::buffer(), 1);
unsigned char z = Utils::ReadFromStartIntoVal<unsigned char>(Globals::buffer(), 1);
ref.bytes[i] = ((x & 0xf) << 12) + ((y & 0x3f) << 6) + (z & 0x3f);
}
else
{
std::cerr << "Invalid character: " << x << std::endl;
exit(1);
}
if (i != ref.length.ToHostFormat() - 1)
x = Utils::ReadFromStartIntoVal<unsigned char>(Globals::buffer(), 1);
}
p.info = static_cast<ConstantPoolInfo>(ref);
jc.constant_pool.push_back(p);
break;
}
case Tags::Integer:
std::cout << "FIXME: Implement Integer Constant Pool Tag" << std::endl;
exit(EXIT_SUCCESS);
case Tags::Float:
std::cout << "FIXME: Implement Float Constant Pool Tag" << std::endl;
exit(EXIT_SUCCESS);
case Tags::Long:
std::cout << "FIXME: Implement Long Constant Pool Tag" << std::endl;
exit(EXIT_SUCCESS);
case Tags::Double:
std::cout << "FIXME: Implement Double Constant Pool Tag" << std::endl;
exit(EXIT_SUCCESS);
case Tags::Class: {
// std::cout << "FIXME: Implement Class Constant Pool Tag" << std::endl;
ConstantClassInfo ref = static_cast<ConstantClassInfo>(p.info);
// std::vector<uint8_t> name_index = Utils::ReadFromStart(Globals::buffer(), 2);
ref.tag = p.tag;
ref.name_index = Utils::ReadFromStartIntoVal<uint16_t>(Globals::buffer(), 2);
p.info = static_cast<ConstantPoolInfo>(ref);
jc.constant_pool.push_back(p);
// exit(EXIT_SUCCESS);
break;
}
case Tags::String: {
// std::cout << "FIXME: Implement String Constant Pool Tag" << std::endl;
ConstantStringInfo ref = static_cast<ConstantStringInfo>(p.info);
ref.tag = p.tag;
// std::cout << std::dec << Globals::buffer().size() << std::endl;
ref.string_index = Utils::ReadFromStartIntoVal<uint16_t>(Globals::buffer(), 2);
// std::cout << std::dec << ref.string_index.ToHostFormat() << std::endl;
p.info = static_cast<ConstantPoolInfo>(ref);
// std::cout << Globals::buffer().size() << std::endl;
jc.constant_pool.push_back(p);
// exit(EXIT_SUCCESS);
break;
}
case Tags::Fieldref: {
// std::cout << "FIXME: Implement Fieldref Constant Pool Tag" << std::endl;
ConstantFieldrefInfo ref = static_cast<ConstantFieldrefInfo>(p.info);
ref.tag = p.tag;
ref.class_index = Utils::ReadFromStartIntoVal<uint16_t>(Globals::buffer(), 2);
ref.name_and_type_index = Utils::ReadFromStartIntoVal<uint16_t>(Globals::buffer(), 2);
p.info = static_cast<ConstantPoolInfo>(ref);
jc.constant_pool.push_back(p);
// exit(EXIT_SUCCESS);
break;
}
case Tags::Methodref:
{
// std::cout << "FIXME: Implement Methodref Constant Pool Tag" << std::endl;
// ConstantMethodrefInfo ref = *reinterpret_cast<ConstantMethodrefInfo*>(p->info);
ConstantMethodrefInfo ref = static_cast<ConstantMethodrefInfo>(p.info);
ref.tag = p.tag;
ref.class_index = Utils::ReadFromStartIntoVal<uint16_t>(Globals::buffer(), 2);
ref.name_and_type_index = Utils::ReadFromStartIntoVal<uint16_t>(Globals::buffer(), 2);
p.info = static_cast<ConstantPoolInfo>(ref);
jc.constant_pool.push_back(p);
// exit(EXIT_SUCCESS);
break;
}
case Tags::InterfaceMethodref:
std::cout << "FIXME: Implement InterfaceMethodref Constant Pool Tag" << std::endl;
exit(EXIT_SUCCESS);
case Tags::NameAndType: {
// std::cout << "FIXME: Implement NameAndType Constant Pool Tag" << std::endl;
ConstantNameAndTypeInfo ref = static_cast<ConstantNameAndTypeInfo>(p.info);
ref.tag = p.tag;
ref.name_index = Utils::ReadFromStartIntoVal<uint16_t>(Globals::buffer(), 2);
ref.descriptor_index = Utils::ReadFromStartIntoVal<uint16_t>(Globals::buffer(), 2);
p.info = static_cast<ConstantPoolInfo>(ref);
jc.constant_pool.push_back(p);
// exit(EXIT_SUCCESS);
break;
}
case Tags::MethodHandle:
std::cout << "FIXME: Implement MethodHandle Constant Pool Tag" << std::endl;
exit(EXIT_SUCCESS);
case Tags::MethodType:
std::cout << "FIXME: Implement MethodType Constant Pool Tag" << std::endl;
exit(EXIT_SUCCESS);
case Tags::Dynamic:
std::cout << "FIXME: Implement Dynamic Constant Pool Tag" << std::endl;
exit(EXIT_SUCCESS);
case Tags::InvokeDynamic:
std::cout << "FIXME: Implement InvokeDynamic Constant Pool Tag" << std::endl;
exit(EXIT_SUCCESS);
case Tags::Module:
std::cout << "FIXME: Implement Module Constant Pool Tag" << std::endl;
exit(EXIT_SUCCESS);
case Tags::Package:
std::cout << "FIXME: Implement Package Constant Pool Tag" << std::endl;
exit(EXIT_SUCCESS);
default:
std::cerr << "Unknown tag: " << std::hex << (int)p.tag << " @ byte " << std::dec << Globals::buffer().size() << " from end of class file" << std::endl;
exit(EXIT_FAILURE);
}
}

View File

View File

View File

@ -0,0 +1,9 @@
set(CWD ${CMAKE_CURRENT_LIST_DIR})
set(CONSTANT_POOL_TAG_SRC
${CONSTANT_POOL_TAG_SRC}
${CWD}/FieldInfoParser.cpp
PARENT_SCOPE
)

View File

@ -0,0 +1,19 @@
#include <SpecTypes.h>
#include <Utils/Utils.h>
#include <Globals.h>
#include <FieldInfo.h>
#include <cassert>
#include <cstdint>
void FieldInfo::FieldInfoParser(field_info &p, JavaClassFormat &jc)
{
p.access_flags = Utils::ReadFromStartIntoVal<uint16_t>(Globals::buffer());
p.name_index = Utils::ReadFromStartIntoVal<uint16_t>(Globals::buffer());
p.descriptor_index = Utils::ReadFromStartIntoVal<uint16_t>(Globals::buffer());
p.attributes_count = Utils::ReadFromStartIntoVal<uint16_t>(Globals::buffer());
// FIXME: Implement attributes[]
jc.fields.push_back(p);
}

157
src/Main.cpp Normal file
View File

@ -0,0 +1,157 @@
#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;
}

View File

@ -0,0 +1,9 @@
set(CWD ${CMAKE_CURRENT_LIST_DIR})
set(CONSTANT_POOL_TAG_SRC
${CONSTANT_POOL_TAG_SRC}
${CWD}/MethodParser.cpp
PARENT_SCOPE
)

View File

@ -0,0 +1,45 @@
#include "ConstantPoolTags/Tags.h"
#include <Globals.h>
#include <Utils/Utils.h>
#include <ClassFormat.h>
#include <SpecTypes.h>
#include <Methods.h>
#include <cassert>
#include <cstdint>
#include <string>
#include <iostream>
void Methods::MethodParser(method_info &p, JavaClassFormat &jc)
{
p.access_flags = Utils::ReadFromStartIntoVal<uint16_t>(Globals::buffer());
p.name_index = Utils::ReadFromStartIntoVal<uint16_t>(Globals::buffer());
p.descriptor_index = Utils::ReadFromStartIntoVal<uint16_t>(Globals::buffer());
p.attributes_count = Utils::ReadFromStartIntoVal<uint16_t>(Globals::buffer());
// std::cout << p.attributes_count.ToHostFormat() << std::endl;
// FIXME: Implement attributes[]
for (int i = 0; i < p.attributes_count.ToHostFormat(); i++)
{
attribute_info a;
a.attribute_name_index = Utils::ReadFromStartIntoVal<uint16_t>(Globals::buffer());
a.attribute_length = Utils::ReadFromStartIntoVal<uint32_t>(Globals::buffer());
for (int j = 0; j < a.attribute_length.ToHostFormat(); j++)
{
a.info.push_back(Utils::ReadFromStartIntoVal<uint8_t>(Globals::buffer()));
}
std::cout << a.attribute_name_index.ToHostFormat() << std::endl;
// std::cout << a.info.size() << std::endl;
}
// if ((p.access_flags.ToHostFormat() & (int)Method::ACCESS_FLAGS::ACC_NATIVE) == 0 &&
// (p.access_flags.ToHostFormat() & (int)Method::ACCESS_FLAGS::ACC_ABSTRACT) == 0)
// {
// std::cout << "Not Set" << std::endl;
// }
jc.methods.push_back(p);
}