Reputation: 23495
I'm trying to learn how to read a Java class file using C++. Can anyone help me figure out why AccessFlag prints 0? The lowest value it can print is 0x00001. So I think I'm reading the constant pool table wrong but I'm not sure what is wrong with it. Any ideas? I was following: http://www.murrayc.com/learning/java/java_classfileformat.shtml
So far I got:
#include <iostream>
#include <fstream>
#include <vector>
template <typename T>
T ReadPointer(char*& Pointer)
{
T Result = *(reinterpret_cast<T*>(Pointer));
Pointer += sizeof(T);
return Result;
}
struct ConstantPool
{
int type;
std::string name;
ConstantPool* arg1;
ConstantPool* arg2;
short index1, index2;
std::string strValue;
int intValue;
std::int64_t longValue;
float floatValue;
double doubleValue;
ConstantPool() {}
ConstantPool(char* &Pointer) {this->Read(Pointer);}
void Read(char* &Pointer);
};
void ConstantPool::Read(char* &Pointer)
{
switch(type = static_cast<int>(ReadPointer<std::uint8_t>(Pointer)))
{
case 1:
{
name = "Ascii";
int Length = ReadPointer<short>(Pointer);
while (Length > 0)
{
char C = ReadPointer<char>(Pointer);
strValue += C;
Length--;
}
}
break;
case 2:
{
name = "Unicode";
int Length = ReadPointer<short>(Pointer);
while (Length > 0)
{
char C = ReadPointer<char>(Pointer);
strValue += C;
Length--;
}
}
break;
case 3:
name = "Int";
intValue = ReadPointer<double>(Pointer);
break;
case 4:
name = "Float";
floatValue = ReadPointer<float>(Pointer);
break;
case 5:
name = "Long";
longValue = ReadPointer<long>(Pointer);
break;
case 6:
name = "Double";
doubleValue = ReadPointer<double>(Pointer);
break;
case 7:
name = "Class";
index1 = ReadPointer<short>(Pointer);
index2 = -1;
break;
case 8:
name = "String";
index1 = ReadPointer<short>(Pointer);
index2 = -1;
break;
case 9:
name = "Field Reference";
index1 = ReadPointer<short>(Pointer);
index2 = ReadPointer<short>(Pointer);
break;
case 10:
name = "Method Reference";
index1 = ReadPointer<short>(Pointer);
index2 = ReadPointer<short>(Pointer);
break;
case 11:
name = "Interface Reference";
index1 = ReadPointer<short>(Pointer);
index2 = ReadPointer<short>(Pointer);
break;
case 12:
name = "Name And Type";
index1 = ReadPointer<short>(Pointer);
index2 = ReadPointer<short>(Pointer);
break;
}
}
typedef struct
{
int MagicNumber;
short MinorVersion;
short MajorVersion;
short ConstantPoolCount;
} ClassFile;
int main()
{
std::fstream File("Animal.class", std::ios::in | std::ios::binary);
if (File.is_open())
{
File.seekg(0, std::ios::end);
std::vector<std::uint8_t> Data(File.tellg());
char* Ptr = reinterpret_cast<char*>(&Data[0]);
File.seekg(0, std::ios::beg);
File.read(Ptr, Data.size());
/**Check Magic Number.**/
ClassFile BaseInfo = ReadPointer<ClassFile>(Ptr);
if (BaseInfo.MagicNumber == 0xBEBAFECA)
{
std::cout << "Magic Number: " << BaseInfo.MagicNumber << "\n";
std::cout << "Minor Number: " << BaseInfo.MinorVersion << "\n";
std::cout << "Major Number: " << BaseInfo.MajorVersion << "\n";
std::cout << "Const Pool Size: " << BaseInfo.ConstantPoolCount << "\n";
std::vector<ConstantPool> ConstPool;
for (int I = 0; I < BaseInfo.ConstantPoolCount - 1; ++I)
{
ConstPool.push_back(ConstantPool(Ptr));
if (ConstPool.back().type == 5 || ConstPool.back().type == 6)
++I;
}
std::cout << "Access Flags: " << ReadPointer<short>(Ptr);
}
File.close();
}
}
Upvotes: 1
Views: 357
Reputation: 39461
One mistake is
intValue = ReadPointer<double>(Pointer);
You're reading a double instead of an int, which will throw everything else off.
Of course your code has plenty of other issues too. For example, you're completely ignoring alignment and struct padding issues.
Upvotes: 1