[svn:parrot] r37140 - in trunk: . examples/tools

NotFound at svn.parrot.org NotFound at svn.parrot.org
Thu Mar 5 22:34:41 UTC 2009


Author: NotFound
Date: Thu Mar  5 22:34:41 2009
New Revision: 37140
URL: https://trac.parrot.org/parrot/changeset/37140

Log:
[examples] add pbc_checker tool

Added:
   trunk/examples/tools/
   trunk/examples/tools/Makefile   (contents, props changed)
   trunk/examples/tools/pbc_checker.cpp   (contents, props changed)
Modified:
   trunk/MANIFEST

Modified: trunk/MANIFEST
==============================================================================
--- trunk/MANIFEST	Thu Mar  5 21:14:50 2009	(r37139)
+++ trunk/MANIFEST	Thu Mar  5 22:34:41 2009	(r37140)
@@ -1,7 +1,7 @@
 # ex: set ro:
 # $Id$
 #
-# generated by tools/dev/mk_manifest_and_skip.pl Thu Mar  5 03:46:49 2009 UT
+# generated by tools/dev/mk_manifest_and_skip.pl Thu Mar  5 22:29:07 2009 UT
 #
 # See tools/dev/install_files.pl for documentation on the
 # format of this file.
@@ -821,6 +821,8 @@
 examples/tge/branch/lib/Branch.pir                          [examples]
 examples/tge/branch/lib/Leaf.pir                            [examples]
 examples/tge/branch/transform.pir                           [examples]
+examples/tools/Makefile                                     [examples]
+examples/tools/pbc_checker.cpp                              [examples]
 examples/tutorial/00_README.pod                             []doc
 examples/tutorial/01_temp_var.pir                           [examples]
 examples/tutorial/02_local_var.pir                          [examples]

Added: trunk/examples/tools/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ trunk/examples/tools/Makefile	Thu Mar  5 22:34:41 2009	(r37140)
@@ -0,0 +1,21 @@
+#
+# Copyright (C) 2009, Parrot Foundation.
+# * $Id$
+#
+# Makefile for pbc_checker
+
+CXX= g++
+CXXFLAGS = -Wall -Wextra
+LD = g++
+
+pbc_checker: pbc_checker.o
+	$(LD) -o pbc_checker pbc_checker.o
+
+pbc_checker.o: pbc_checker.cpp
+	$(CXX) $(CXXFLAGS) -c pbc_checker.cpp
+
+clean:
+	rm -f pbc_checker
+	rm -f *.o
+
+# End

Added: trunk/examples/tools/pbc_checker.cpp
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ trunk/examples/tools/pbc_checker.cpp	Thu Mar  5 22:34:41 2009	(r37140)
@@ -0,0 +1,672 @@
+/*
+ * Copyright (C) 2009, Parrot Foundation.
+ * $Id$
+*/
+
+// pbc_checker.cpp
+// A multiplatform checker for pbc files
+
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+#include <string>
+#include <vector>
+#include <algorithm>
+#include <functional>
+#include <stdexcept>
+
+using std::cout;
+using std::cerr;
+using std::ifstream;
+using std::string;
+using std::hex;
+using std::dec;
+using std::setw;
+using std::setfill;
+
+//**********************************************************************
+
+const char unknown[] = "Unknown";
+
+const char * desc_byte_order(unsigned char c)
+{
+    switch(c) {
+        case 0:  return "Little endian";
+        case 1:  return "Big endian";
+        default: return unknown;
+    }
+}
+
+const unsigned char
+   FpEncodingIEEE_754_8 = 0,
+   FpEncodingIEEE_i386_12 = 1,
+   FpEncodingIEEE_754_16 = 2;
+
+const char * desc_fp_encoding(unsigned char c)
+{
+    switch(c) {
+        case FpEncodingIEEE_754_8:  return "IEEE 754 8 byte double";
+        case FpEncodingIEEE_i386_12:  return "i386 little endian 12 byte long double";
+        case FpEncodingIEEE_754_16:  return "IEEE 754 16 byte lobg double";
+        default: return unknown;
+    }
+}
+
+const char * desc_uuid_type(unsigned char c)
+{
+    switch(c) {
+        case 0:  return "none";
+        case 1:  return "MD5";
+        default: return unknown;
+    }
+}
+
+const unsigned long
+    SegmentTypeDirectory     = 0x00,
+    SegmentTypeDefault       = 0x01,
+    SegmentTypeFixup         = 0x02,
+    SegmentTypeConstantTable = 0x03,
+    SegmentTypeBytecode      = 0x04,
+    SegmentTypePIRDebug      = 0x05,
+    SegmentTypeAnnotations   = 0x06,
+    SegmentTypePICData       = 0x07,
+    SegmentTypeDependencies  = 0x08;
+
+const char * desc_segment_type(unsigned long t)
+{
+    switch(t) {
+        case SegmentTypeDirectory:     return "Directory";
+        case SegmentTypeDefault:       return "Default";
+        case SegmentTypeFixup:         return "Fixup";
+        case SegmentTypeConstantTable: return "Constant table";
+        case SegmentTypeBytecode:      return "Bytecode";
+        case SegmentTypePIRDebug:      return "PIR Debug";
+        case SegmentTypeAnnotations:   return "Annotations";
+        case SegmentTypePICData:       return "PIC Data";
+        case SegmentTypeDependencies:  return "Dependencies";
+        default:                       return unknown;
+    }
+}
+
+const unsigned long
+    ConstantTypeNone =   0x00,
+    ConstantTypeNumber = 0x6E,
+    ConstantTypeString = 0x73,
+    ConstantTypePMC    = 0x70,
+    ConstantTypeKey    = 0x6B;
+
+const char * desc_constant_type(unsigned long t)
+{
+    switch(t) {
+        case ConstantTypeNone:   return "None";
+        case ConstantTypeNumber: return "Number";
+        case ConstantTypeString: return "String";
+        case ConstantTypePMC:    return "PMC";
+        case ConstantTypeKey:    return "Key";
+        default:                 return unknown;
+    }
+}
+
+const unsigned long
+    KeyIntegerRegister = 0x00,
+    KeyStringRegister  = 0x01,
+    KeyPMCRegister     = 0x02,
+    KeyNumberRegister  = 0x03,
+    KeyIntegerConstant = 0x10,
+    KeyStringConstant  = 0x11,
+    KeyPMCConstant     = 0x12,
+    KeyNumberConstant  = 0x13;
+
+const char * desc_key_type(unsigned long t)
+{
+    switch (t) {
+        case KeyIntegerRegister: return "Integer register";
+        case KeyStringRegister:  return "String register";
+        case KeyPMCRegister:     return "PMC register";
+        case KeyNumberRegister:  return "Number register";
+        case KeyIntegerConstant: return "Integer constant";
+        case KeyStringConstant:  return "String constant";
+        case KeyPMCConstant:     return "PMC constant";
+        case KeyNumberConstant:  return "Number constant";
+        default:                 return unknown;
+    }
+}
+
+//**********************************************************************
+
+class ReadError : public std::runtime_error
+{
+public:
+    ReadError(const std::string &msg);
+};
+
+ReadError::ReadError(const std::string &msg) :
+    std::runtime_error("Error reading " + msg)
+{
+}
+
+//**********************************************************************
+
+void signature(ifstream &pbcfile)
+{
+    static const char pbc_signature [] = {
+        0xFE, 0x50, 0x42, 0x43, 0x0D, 0x0A, 0x1A, 0x0A
+    };
+    char signature [sizeof (pbc_signature)];
+    pbcfile.read(signature, sizeof (signature));
+    if (pbcfile.gcount() != sizeof (signature))
+        throw ReadError("pbc signature");
+    if (! std::equal(pbc_signature, pbc_signature + sizeof(pbc_signature),
+            signature))
+        throw std::runtime_error("Invalid pbc signature");
+}
+
+//**********************************************************************
+
+class DirEntry
+{
+public:
+    DirEntry(string name_n, unsigned long type_n,
+        unsigned long offset_n, unsigned long length_n);
+    string getName() const;
+    unsigned long getType() const;
+    unsigned long getOffset() const;
+    unsigned long getLength() const;
+private:
+    string name;
+    unsigned long type;
+    unsigned long offset;
+    unsigned long length;
+};
+
+DirEntry::DirEntry(string name_n, unsigned long type_n,
+        unsigned long offset_n, unsigned long length_n) :
+    name(name_n),
+    type(type_n),
+    offset(offset_n),
+    length(length_n)
+{
+}
+
+string DirEntry::getName() const
+{
+    return name;
+}
+
+unsigned long DirEntry::getType() const
+{
+    return type;
+}
+
+unsigned long DirEntry::getOffset() const
+{
+    return offset;
+}
+
+unsigned long DirEntry::getLength() const
+{
+    return length;
+}
+
+bool operator < (const DirEntry & de1, const DirEntry & de2)
+{
+    return de1.getOffset() < de2.getOffset();
+}
+
+//**********************************************************************
+
+void check_overlap(const std::vector<DirEntry> & directory)
+{
+    unsigned int entries = directory.size();
+    for (unsigned int i= 0; i < entries; ++i)
+    {
+        unsigned long offset = directory[i].getOffset();
+        unsigned long length = directory[i].getLength();
+        unsigned long after = offset + length;
+        for (unsigned int j= i + 1; j < entries; ++j) {
+            unsigned long offset2 = directory[j].getOffset();
+            if (offset2 >= offset && offset2 < after)
+                throw std::runtime_error("overlap");
+            unsigned long after2 = offset2 + directory[j].getLength();
+            if (offset >= offset2 && offset < after2)
+                throw std::runtime_error("overlap");
+        }
+    }
+}
+
+//**********************************************************************
+
+class PbcFile
+{
+public:
+    PbcFile();
+    void check_directory_format(ifstream &pbcfile);
+    void read(const char *filename);
+    void read_directory(ifstream &pbcfile);
+    void dump_constant_string(ifstream &pbcfile);
+    void dump_constant_number(ifstream &pbcfile);
+    void dump_constant_key(ifstream &pbcfile);
+    void dump_segment_constant(ifstream &pbcfile);
+    void dump_segment_bytecode(ifstream &pbcfile);
+    void dump_segment_fixup(ifstream &pbcfile);
+    void dump_segment_pir_debug(ifstream &pbcfile);
+    void dump_segment(const DirEntry & entry, ifstream &pbcfile);
+    string read_cstring(ifstream &pbcfile);
+    unsigned long read_opcode(ifstream &pbcfile);
+private:
+    unsigned int opcode_size;
+    unsigned int pbc_version;
+
+    unsigned char byte_order;
+    static const unsigned char bo_little = 0;
+    static const unsigned char bo_big = 1;
+    unsigned char fp_encoding;
+
+    std::vector<DirEntry> directory;
+};
+
+PbcFile::PbcFile()
+{
+    opcode_size = 0;
+}
+
+void PbcFile::check_directory_format(ifstream &pbcfile)
+{
+    unsigned char dir_format = pbcfile.get();
+    cout << "Directory format: " << (int) dir_format << '\n';
+    pbcfile.ignore(3);
+
+    pbcfile.ignore(12);
+    if (pbc_version <= 0x0325 && opcode_size == 8)
+        pbcfile.ignore(16);
+}
+
+void PbcFile::read(const char *filename)
+{
+    ifstream pbcfile(filename);
+    if (! pbcfile.is_open())
+        throw std::runtime_error("Can't open file");
+
+    signature(pbcfile);
+    unsigned char opcode_size = pbcfile.get();
+    unsigned char byte_order = pbcfile.get();
+    unsigned char fp_encoding = pbcfile.get();
+    unsigned char major = pbcfile.get();
+    unsigned char minor = pbcfile.get();
+    unsigned char patch = pbcfile.get();
+    unsigned char pbc_major = pbcfile.get();
+    unsigned char pbc_minor = pbcfile.get();
+
+    if (!pbcfile)
+        throw ReadError("pbc header data");
+
+    cout <<
+        "Opcode size            : " << (int) opcode_size << '\n' <<
+        "Byte order             : " << desc_byte_order(byte_order) << '\n' <<
+        "Floating point encoding: " << desc_fp_encoding(fp_encoding) << '\n' <<
+        "Parrot version         : " <<
+        (int) major << '.' << (int) minor << '.' << (int) patch << '\n' <<
+        "PBC version            : " <<
+        (int) pbc_major << '.' << (int) pbc_minor << '\n'
+        ;
+
+    this->opcode_size = opcode_size;
+    this->pbc_version = ((unsigned int) pbc_major) * 8 + pbc_minor;
+    this->byte_order = byte_order;
+    this->fp_encoding = fp_encoding;
+
+    unsigned char uuid_type = pbcfile.get();
+    cout <<
+        "UUID type              : " << desc_uuid_type(uuid_type) << '\n'
+        ;
+    unsigned char uuid_length = pbcfile.get();
+    cout <<
+        "UUID length            : " << (int) uuid_length << '\n'
+        ;
+    unsigned int curpos = 18 + uuid_length;
+    unsigned int endheader = ((curpos + 15) / 16) * 16;
+    pbcfile.ignore(endheader - 18);
+
+    check_directory_format(pbcfile);
+    read_directory(pbcfile);
+    check_overlap(directory);
+
+    std::sort(directory.begin(), directory.end());
+
+    for (size_t i= 0; i < directory.size(); ++i)
+        dump_segment(directory[i], pbcfile);
+}
+
+void PbcFile::dump_constant_string(ifstream &pbcfile)
+{
+    unsigned long flags = read_opcode(pbcfile);
+    cout << "Flags: 0x" << hex << flags << dec << '\n';
+    unsigned long charset = read_opcode(pbcfile);
+    cout << "Charset: " << charset << '\n';
+
+    //unsigned long encoding = read_opcode(pbcfile);
+    //cout << "Encoding: "<< encoding << '\n';
+
+    unsigned long length = read_opcode(pbcfile);
+    cout << "Length: "<< length << '\n';
+    cout << '\'';
+    for (unsigned long i= 0; i < length; ++i) {
+        unsigned char c = pbcfile.get();
+        if (c >= 32 && c < 128)
+            cout << c;
+        else
+            cout << "\\x" << hex << setw(2) << setfill('0') <<
+                (unsigned int) c << dec;
+    }
+    cout << "'\n";
+    for (unsigned int i= length; i % opcode_size; ++i) {
+        pbcfile.ignore(1);
+    }
+}
+
+void PbcFile::dump_constant_number(ifstream &pbcfile)
+{
+    cout << "Number constant (not shown)\n";
+    switch(fp_encoding) {
+        case FpEncodingIEEE_754_8:
+            pbcfile.ignore(8);
+            break;
+        case FpEncodingIEEE_i386_12:
+            pbcfile.ignore(12);
+            break;
+        case FpEncodingIEEE_754_16:
+            pbcfile.ignore(16);
+            break;
+    }
+}
+
+void PbcFile::dump_constant_key(ifstream &pbcfile)
+{
+    unsigned long components = read_opcode(pbcfile);
+    cout << "Key components: " << components << '\n';
+    for (unsigned long i= 0; i < components; ++i) {
+        cout << "  " << i << ' ';
+        unsigned long type = read_opcode(pbcfile);
+        cout << "Type: " << desc_key_type (type) <<
+            " (0x" << hex << type << dec << ") ";
+        unsigned long value = read_opcode(pbcfile);
+        cout << "Value: " << value << '\n';
+    }
+}
+
+void PbcFile::dump_segment_constant(ifstream &pbcfile)
+{
+    cout << "<SegmentConstantTable>\n";
+
+    unsigned long segsize = read_opcode(pbcfile);
+    cout << "Segment size: " << segsize << '\n';
+    pbcfile.ignore(16 - opcode_size);
+    if (pbc_version <= 0x0325 && opcode_size == 8)
+        pbcfile.ignore(16);
+
+    unsigned long tablelength = read_opcode(pbcfile);
+    cout << "Number of constants: " << tablelength << '\n';
+
+    for (unsigned long n= 0; n < tablelength; ++n) {
+        cout << "Constant " << n;
+        unsigned long type = read_opcode(pbcfile);
+        cout << " Type: " << desc_constant_type(type) <<
+             " (0x" << hex << type << dec << ")\n";
+        switch(type) {
+            case ConstantTypeString:
+            case ConstantTypePMC:
+                dump_constant_string(pbcfile);
+                break;
+            case ConstantTypeNumber:
+                dump_constant_number(pbcfile);
+                break;
+            case ConstantTypeKey:
+                dump_constant_key(pbcfile);
+                break;
+            default:
+                throw std::runtime_error("Unimplemented");
+        }
+    }
+
+    cout << "</SegmentConstantTable>\n";
+}
+
+void PbcFile::dump_segment_bytecode(ifstream &pbcfile)
+{
+    cout << "<SegmentBytecode>\n";
+
+    unsigned long segsize = read_opcode(pbcfile);
+    cout << "Segment size: " << segsize << '\n';
+    pbcfile.ignore(16 - opcode_size);
+    if (pbc_version <= 0x0325 && opcode_size == 8)
+        pbcfile.ignore(16);
+
+    for (unsigned long n= 0; n < segsize; ++n) {
+        unsigned long code = read_opcode(pbcfile);
+        cout << ' ' << hex << setfill('0') << setw(opcode_size * 2) << code << dec;
+    }
+    cout << '\n';
+
+    cout << "</SegmentBytecode>\n";
+}
+
+void PbcFile::dump_segment_fixup(ifstream &pbcfile)
+{
+    cout << "<SegmentFixup>\n";
+
+    unsigned long segsize = read_opcode(pbcfile);
+    cout << "Segment size: " << segsize << '\n';
+    pbcfile.ignore(16 - opcode_size);
+    if (pbc_version <= 0x0325 && opcode_size == 8)
+        pbcfile.ignore(16);
+
+    unsigned long tablelength = read_opcode(pbcfile);
+    cout << "Number of fixups: " << tablelength << '\n';
+
+    for (unsigned long n= 0; n < tablelength; ++n) {
+        cout << "Fixup " << n;
+        unsigned long type = read_opcode(pbcfile);
+        cout << " Type: " <<
+             " (0x" << hex << type << dec << ')';
+        switch (type) {
+            case 0x01:
+                {
+                unsigned long label = read_opcode(pbcfile);
+                cout << " Label: " << label;
+                unsigned long sub = read_opcode(pbcfile);
+                cout << " Sub: " << sub;
+                }
+                break;
+            case 0x02:
+                {
+                string label = read_cstring(pbcfile);
+                cout << " Label: '" << label << '\'';
+                unsigned long sub = read_opcode(pbcfile);
+                cout << " Sub: " << sub;
+                }
+                break;
+            default:
+                throw std::runtime_error("Invalid fixup");
+        }
+        cout << '\n';
+    }
+
+    cout << "</SegmentFixup>\n";
+}
+
+void PbcFile::dump_segment_pir_debug(ifstream &pbcfile)
+{
+    cout << "<SegmentPIRDebug>\n";
+
+    unsigned long segsize = read_opcode(pbcfile);
+    cout << "Segment size: " << segsize << '\n';
+
+    pbcfile.ignore(8);
+/*
+    pbcfile.ignore(16 - opcode_size);
+*/
+    if (pbc_version <= 0x0325 && opcode_size == 8)
+        pbcfile.ignore(16);
+
+    unsigned long tablelength = read_opcode(pbcfile);
+    cout << "Number of mappings: " << tablelength << '\n';
+
+    for (unsigned long n= 0; n < tablelength; ++n) {
+        unsigned long linenum = read_opcode(pbcfile);
+        cout << " Line: " << linenum;
+    }
+    cout << '\n';
+
+    unsigned long mappings = read_opcode(pbcfile);
+    cout << "Mappings: " << mappings << '\n';
+    for (unsigned long n= 0; n < mappings; ++n) {
+        cout << "  " << n;
+        unsigned long offset = read_opcode(pbcfile);
+        cout << " Offset: " << offset;
+        unsigned long filename = read_opcode(pbcfile);
+        cout << " File: " << filename;
+        cout << '\n';
+    }
+
+    cout << "</SegmentPIRDebug>\n";
+}
+
+void PbcFile::dump_segment(const DirEntry &entry, ifstream &pbcfile)
+{
+    cout << "Segment '" << entry.getName() << "'\n";
+    unsigned long const type = entry.getType();
+    cout << "Type: " << desc_segment_type(type) <<
+        " (0x" << hex << type << dec << ")\n";
+    pbcfile.seekg(entry.getOffset() * opcode_size);
+    switch(type)
+    {
+    case SegmentTypeFixup:
+        dump_segment_fixup(pbcfile);
+        break;
+    case SegmentTypeConstantTable:
+        dump_segment_constant(pbcfile);
+        break;
+    case SegmentTypeBytecode:
+        dump_segment_bytecode(pbcfile);
+        break;
+    case SegmentTypePIRDebug:
+        dump_segment_pir_debug(pbcfile);
+        break;
+    default:
+        cout << "(unimplemented)\n";
+    }
+}
+
+void PbcFile::read_directory(ifstream &pbcfile)
+{
+    unsigned long size = read_opcode(pbcfile);
+    cout << "Directory segment size: " << size << '\n';
+
+    pbcfile.ignore(16 - opcode_size);
+    if (pbc_version <= 0x0325 && opcode_size == 8)
+        pbcfile.ignore(16);
+
+    unsigned long entries = read_opcode(pbcfile);
+    cout << "Directory entries: " << entries << '\n';
+
+    for (unsigned int n= 0; n < entries; ++n)
+    {
+        unsigned long type = read_opcode(pbcfile);
+        cout << n << ": Type: '" << desc_segment_type(type) << "' Name: '";
+        string name;
+        char c;
+        unsigned int namelen= 0;
+        while ((c = pbcfile.get()))
+        {
+            cout << c;
+            name+= c;
+            ++namelen;
+        }
+        ++namelen;
+        while(namelen % opcode_size)
+        {
+            c= pbcfile.get();
+            ++namelen;
+        }
+        unsigned long offset = read_opcode(pbcfile);
+        unsigned long length = read_opcode(pbcfile);
+        cout << "'\n   Offset: " << offset << " Length: " << length << '\n';
+        DirEntry entry(name, type, offset, length);
+        directory.push_back(entry);
+    }
+}
+
+string PbcFile::read_cstring(ifstream &pbcfile)
+{
+    string r;
+    char c;
+    while ((c= pbcfile.get())) {
+        r+= c;
+    }
+    for (unsigned long l = r.size() + 1; l % opcode_size; ++l)
+        pbcfile.ignore(1);
+    return r;
+}
+
+unsigned long PbcFile::read_opcode(ifstream &pbcfile)
+{
+    unsigned char buffer [32]; // Allow 256 bits opcode size
+    pbcfile.read((char *)buffer, opcode_size);
+    if (static_cast<unsigned int>(pbcfile.gcount()) != opcode_size)
+        throw ReadError("opcode");
+
+    unsigned long result = 0;
+    switch(byte_order)
+    {
+    case bo_little:
+        for (unsigned int i= 0; i < opcode_size; ++i) {
+            result <<= 8;
+            result += buffer [opcode_size - 1 - i];
+        }
+        break;
+    case bo_big:
+        for (unsigned int i= 0; i < opcode_size; ++i) {
+            result <<= 8;
+            result += buffer [i];
+        }
+        break;
+    default:
+        throw std::logic_error("Bad byte order");
+    }
+    return result;
+}
+
+//**********************************************************************
+
+void pbc_checker_main(int argc, char **argv)
+{
+    if (argc < 2)
+        throw std::runtime_error("Bad args");
+
+    PbcFile pbcfile;
+    pbcfile.read(argv[1]);
+}
+
+//**********************************************************************
+
+int main(int argc, char **argv)
+{
+    try
+    {
+        pbc_checker_main(argc, argv);
+        return 0;
+    }
+    catch(std::exception &e)
+    {
+        cerr << "FAILED: " << e.what() << '\n';
+    }
+    return 1;
+}
+
+// End of pbc_checker.cpp
+/*
+ * Local variables:
+ *   c-file-style: "parrot"
+ * End:
+ * vim: expandtab shiftwidth=4:
+ */


More information about the parrot-commits mailing list