Question

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();
    }
}
Était-ce utile?

La solution

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top