123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387 |
- /* javaclfl.c: Copyright (C) Codemist Ltd., 1996. */
-
- #include <stdio.h>
- #include <string.h>
- #include "machine.h"
- #include "tags.h"
- #include "cslerror.h"
- #include "externs.h"
- #include "read.h"
- #include "stream.h"
- #include "arith.h"
- #include "entries.h"
- #include "javahost.h"
- #include "javaglb.h"
- /* #include "javatype.h" */
- #define D_CLASSFILE 1
- #define D_CLASSFILEIO 2
- #define D_CLASSFILECODE 4
- static int depth;
- static unsigned32 rd1(FILE *f)
- { unsigned32 x = getc(f);
- if (debugging & D_CLASSFILEIO) jdebug("rd1 %d", x);
- return x;
- }
- static unsigned32 rd2(FILE *f)
- { unsigned32 x = getc(f);
- x = x<<8 | getc(f);
- if (debugging & D_CLASSFILEIO) jdebug("rd2 0x%.4x", x);
- return x;
- }
- static unsigned32 rd4(FILE *f)
- { unsigned32 x = getc(f);
- x = x<<8 | getc(f);
- x = x<<8 | getc(f);
- x = x<<8 | getc(f);
- if (debugging & D_CLASSFILEIO) jdebug("rd4 0x%.8x", x);
- return x;
- }
- static char *rd1string(FILE *f, unsigned32 n)
- { int i;
- unsigned8 *p = (unsigned8 *)jmalloc((n+1) * sizeof(*p));
- for (i=0; i<n; i++) p[i] = rd1(f);
- p[n] = 0; /* @@@ ease C access for debugging (temp?) */
- return (char *)p;
- }
- static char *rd2string(FILE *f, unsigned32 n)
- { int i;
- unsigned16 *p = (unsigned16 *)jmalloc(n * sizeof(*p));
- for (i=0; i<n; i++) p[i] = rd2(f);
- return (char *)p;
- }
- static char *cpname(unsigned32 cpx, ClassFile *cf)
- { if (cpx < cf->constant_pool_count)
- { Cp_Info *cpitem = &cf->constant_pool[cpx];
- if (cpitem->tag == CONSTANT_Utf8) return cpitem->u.utf8;
- return "<non-utf8 const pool index>";
- }
- return "<bad const pool index>";
- }
- static Attribute_Sort lookup_attribute_sort(char *utf8, unsigned32 len)
- { /* Should use 'len' not rely on rd1string() zero padding. */
- if (strcmp(utf8,"SourceFile") == 0) return ATT_SourceFile;
- if (strcmp(utf8,"ConstantValue") == 0) return ATT_ConstantValue;
- if (strcmp(utf8,"Code") == 0) return ATT_Code;
- if (strcmp(utf8,"Exceptions") == 0) return ATT_Exceptions;
- if (strcmp(utf8,"LineNumberTable") == 0) return ATT_LineNumberTable;
- if (strcmp(utf8,"LocalVariableTable") == 0) return ATT_LocalVariableTable;
- return ATT_unknown;
- }
- static int rdAttribute_Info(FILE *f, ClassFile *cf, unsigned32 n, Attribute_Info **res);
- static int rdSourceFile_Attribute(FILE *f, ClassFile *cf,
- SourceFile_Attribute **res)
- { SourceFile_Attribute *p = (SourceFile_Attribute *)jmalloc(sizeof(*p));
- depth++;
- p->sourcefile_index = rd2(f);
- if (debugging & D_CLASSFILE)
- jdebug("%*sAttribute Sourcefile '%s'",
- depth*2, "", cpname(p->sourcefile_index, cf));
- *res = p;
- return (depth--, 0);
- }
- static int rdConstantValue_Attribute(FILE *f, ClassFile *cf,
- ConstantValue_Attribute **res)
- { ConstantValue_Attribute *p = (ConstantValue_Attribute *)jmalloc(sizeof(*p));
- depth++;
- p->constantvalue_index = rd2(f);
- if (debugging & D_CLASSFILE)
- jdebug("%*sAttribute ConstantValue [%d]",
- depth*2, "", p->constantvalue_index);
- *res = p;
- return (depth--, 0);
- }
- static int rdCode_Attribute(FILE *f, ClassFile *cf, Code_Attribute **res)
- { Code_Attribute *p = (Code_Attribute *)jmalloc(sizeof(*p));
- unsigned32 i,n;
- depth++;
- p->max_stack = rd2(f);
- p->max_locals = rd2(f);
- p->code_length = n = rd4(f);
- p->code = (unsigned8 *)jmalloc(n * sizeof(*p->code));
- for (i=0; i<n; i++) p->code[i] = rd1(f);
- p->exception_table_length = n = rd2(f);
- p->exception_table = (Exception_Info *)jmalloc(n * sizeof(*p->exception_table));
- for (i=0; i<n; i++)
- { Exception_Info *q = &p->exception_table[i];
- q->start_pc = rd2(f);
- q->end_pc = rd2(f);
- q->handler_pc = rd2(f);
- q->catch_type = rd2(f);
- }
- p->attributes_count = n = rd2(f);
- if (debugging & D_CLASSFILE)
- jdebug("%*sAttribute Code \
- (stack %d, locals %d, bytes %d, exceptions %d)",
- depth*2, "",
- p->max_stack, p->max_locals,
- p->code_length, p->exception_table_length);
- if (debugging & D_CLASSFILECODE)
- javadecode(p->code, p->code_length,
- cf->constant_pool, cf->constant_pool_count);
- if (rdAttribute_Info(f, cf, n, &p[i].attributes)) return 5;
- *res = p;
- return (depth--, 0);
- }
- static int rdExceptions_Attribute(FILE *f, ClassFile *cf,
- Exceptions_Attribute **res)
- { Exceptions_Attribute *p = (Exceptions_Attribute *)jmalloc(sizeof(*p));
- unsigned32 i,n;
- depth++;
- p->number_of_exceptions = n = rd2(f);
- p->exception_index_table = (unsigned16 *)jmalloc(n * sizeof(*p->exception_index_table));
- for (i=0; i<n; i++)
- p->exception_index_table[i] = rd2(f);
- if (debugging & D_CLASSFILE)
- jdebug("%*sAttribute Exceptions (entries %d)",
- depth*2, "", p->number_of_exceptions);
- *res = p;
- return (depth--, 0);
- }
- static int rdLineNumberTable_Attribute(FILE *f, ClassFile *cf,
- LineNumberTable_Attribute **res)
- { LineNumberTable_Attribute *p = (LineNumberTable_Attribute *)jmalloc(sizeof(*p));
- unsigned32 i,n;
- depth++;
- p->line_number_table_length = n = rd2(f);
- p->line_number_table = (LineNumber_Info *)jmalloc(n * sizeof(*p->line_number_table));
- for (i=0; i<n; i++)
- { LineNumber_Info *q = &p->line_number_table[i];
- q->start_pc = rd2(f);
- q->line_number = rd2(f);
- }
- if (debugging & D_CLASSFILE)
- jdebug("%*sAttribute LineNumberTable (entries %d)",
- depth*2, "", p->line_number_table_length);
- *res = p;
- return (depth--, 0);
- }
- static int rdLocalVariableTable_Attribute(FILE *f, ClassFile *cf,
- LocalVariableTable_Attribute **res)
- { LocalVariableTable_Attribute *p = (LocalVariableTable_Attribute *)jmalloc(sizeof(*p));
- unsigned32 i,n;
- depth++;
- p->local_variable_table_length = n = rd2(f);
- p->local_variable_table = (LocalVariable_Info *)jmalloc(n * sizeof(*p->local_variable_table));
- for (i=0; i<n; i++)
- { LocalVariable_Info *q = &p->local_variable_table[i];
- q->start_pc = rd2(f);
- q->length = rd2(f);
- q->name_index = rd2(f);
- q->signature_index = rd2(f);
- q->slot = rd2(f);
- }
- if (debugging & D_CLASSFILE)
- jdebug("%*sAttribute LocalVariableTable (entries %d)",
- depth*2, "", p->local_variable_table_length);
- *res = p;
- return (depth--, 0);
- }
- /* 'Attributes' occur more than once in a Classfile, hence they are */
- /* stored in *res (OK/NOK is return value), but reading Attributes */
- /* also requires cf to access the previously read Cp_Info. */
- static int rdAttribute_Info(FILE *f, ClassFile *cf, unsigned32 n, Attribute_Info **res)
- { Attribute_Info *p;
- unsigned32 i;
- if (n > 0xffff) return 1;
- p = (Attribute_Info *)jmalloc(n * sizeof(*p));
- if (debugging & D_CLASSFILE)
- jdebug("%*sAttributes_Info %d", depth*2, "", n);
- for (i=0; i<n; i++)
- { unsigned32 cpx = rd2(f);
- unsigned32 len = rd4(f);
- Cp_Info *cpitem = &cf->constant_pool[cpx];
- if (cpitem->tag != CONSTANT_Utf8) return 3;
- switch (p[i].sort = lookup_attribute_sort(cpitem->u.utf8, cpitem->len))
- {
- case ATT_Code:
- if (rdCode_Attribute(f, cf, &p[i].uattr.code)) return 6;
- break;
- case ATT_SourceFile:
- if (rdSourceFile_Attribute(f, cf, &p[i].uattr.sourcefile)) return 6;
- break;
- case ATT_ConstantValue:
- if (rdConstantValue_Attribute(f, cf, &p[i].uattr.constantvalue))
- return 6;
- break;
- case ATT_Exceptions:
- if (rdExceptions_Attribute(f, cf, &p[i].uattr.exceptions))
- return 6;
- break;
- case ATT_LineNumberTable:
- if (rdLineNumberTable_Attribute(f, cf, &p[i].uattr.linenumbertable))
- return 6;
- break;
- case ATT_LocalVariableTable:
- if (rdLocalVariableTable_Attribute(f, cf, &p[i].uattr.localvariabletable))
- return 6;
- break;
- default: /* currently ignore other attributes */
- if (debugging & D_CLASSFILE)
- jdebug("%*sAttribute '%s' unknown", (depth+1)*2, "",
- cpitem->u.utf8);
- while (len) rd1(f), len--;
- }
- }
- *res = p;
- return 0;
- }
- static int rdCp_Info(FILE *f, ClassFile *cf, unsigned32 n)
- { Cp_Info *p;
- unsigned32 i, nn;
- depth++;
- if (n > 0xffff) return 1;
- if (debugging & D_CLASSFILE) jdebug("Cp_Info %d", n);
- p = (Cp_Info *)jmalloc(n * sizeof(*p));
- /* Yes, the next line really is '1'! */
- for (i=1; i<n; i++) switch (p[i].tag = rd1(f))
- {
- default: jsyserr("tag %d", p[i].tag); return 2;
- case CONSTANT_Class:
- p[i].u.val = rd2(f); break;
- case CONSTANT_FieldRef:
- case CONSTANT_MethodRef:
- case CONSTANT_InterfaceMethodRef:
- /* stuff name_and_type_index into len */
- p[i].u.val = rd2(f); p[i].len = rd2(f); break;
- case CONSTANT_String:
- p[i].u.val = rd2(f); break;
- case CONSTANT_Integer:
- case CONSTANT_Float: p[i].u.val = rd4(f);
- break;
- case CONSTANT_Long:
- case CONSTANT_Double: p[i].u.val = rd4(f);
- i++; p[i].tag = CONSTANT_Xhalf; p[i].u.val = rd4(f);
- break;
- case CONSTANT_Utf8: if ((nn = rd2(f)) > 0xffff) nn = 0; /* EOF */
- p[i].len = nn; p[i].u.utf8 = rd1string(f, nn);
- break;
- case CONSTANT_Unicode: if ((nn = rd2(f)) > 0xffff) nn = 0; /* EOF */
- p[i].len = nn; p[i].u.utf8 = rd2string(f, nn);
- break;
- case CONSTANT_NameAndType:
- /* stuff signature_index into len */
- p[i].u.val = rd2(f); p[i].len = rd2(f); break;
- }
- cf->constant_pool = p;
- return (depth--, 0);
- }
- static int rdInterface_Info(FILE *f, ClassFile *cf, unsigned32 n)
- { unsigned16 *p;
- unsigned32 i;
- depth++;
- if (n > 0xffff) return 1;
- if (debugging & D_CLASSFILE) jdebug("Interface_Info %d", n);
- p = (unsigned16 *)jmalloc(n * sizeof(*p));
- for (i=0; i<n; i++) p[i] = rd2(f);
- cf->interfaces = p;
- return (depth--, 0);
- }
- static int rdField_Info(FILE *f, ClassFile *cf, unsigned32 n)
- { Field_Info *p;
- unsigned32 i;
- depth++;
- if (n > 0xffff) return 1;
- if (debugging & D_CLASSFILE) jdebug("Field_Info %d", n);
- p = (Field_Info *)jmalloc(n * sizeof(*p));
- for (i=0; i<n; i++)
- { unsigned32 nn;
- p[i].access_flags = rd2(f);
- p[i].name_index = rd2(f);
- p[i].signature_index = rd2(f);
- p[i].attributes_count = nn = rd2(f);
- if (debugging & D_CLASSFILE)
- jdebug(" Field '%s' signature '%s' flags 0x%x",
- cpname(p[i].name_index, cf),
- cpname(p[i].signature_index, cf),
- p[i].access_flags);
- if (rdAttribute_Info(f, cf, nn, &p[i].attributes)) return 4;
- }
- cf->fields = p;
- return (depth--, 0);
- }
- static int rdMethod_Info(FILE *f, ClassFile *cf, unsigned32 n)
- { Method_Info *p;
- unsigned32 i;
- depth++;
- if (n > 0xffff) return 1;
- if (debugging & D_CLASSFILE) jdebug("Method_Info %d", n);
- p = (Method_Info *)jmalloc(n * sizeof(*p));
- for (i=0; i<n; i++)
- { unsigned32 nn;
- p[i].access_flags = rd2(f);
- p[i].name_index = rd2(f);
- p[i].signature_index = rd2(f);
- p[i].attributes_count = nn = rd2(f);
- if (debugging & D_CLASSFILE)
- jdebug(" Method '%s' signature '%s' flags 0x%x",
- cpname(p[i].name_index, cf),
- cpname(p[i].signature_index, cf),
- p[i].access_flags);
- if (rdAttribute_Info(f, cf, nn, &p[i].attributes)) return 4;
- }
- cf->methods = p;
- return (depth--, 0);
- }
- ClassFile *rdClassFile(char *name)
- { FILE *f = fopen(name, "rb");
- ClassFile *cf = rdClassFILE1(f, name);
- fclose(f);
- return cf;
- }
- ClassFile *rdClassFILE1(FILE *f, char *name)
- {
- ClassFile *cf;
- unsigned32 n;
- depth = 0;
- if (f == 0)
- { jsyserr("cannot read '%s'", name); return 0; }
- if (rd4(f) != JAVA_MAGIC)
- { jsyserr("not class file '%s'", name); return 0; }
- if ((n = rd2(f)) > JAVA_THIS_MIN)
- jdebug("ClassFile '%s' wrong minor vsn %d", name, n);
- if ((n = rd2(f)) != JAVA_THIS_MAJ)
- jdebug("ClassFile '%s' wrong major vsn %d", name, n);
- cf = (ClassFile *)jmalloc(sizeof(ClassFile));
- cf->constant_pool_count = n = rd2(f);
- if (rdCp_Info(f, cf, n)) goto corrupt;
- cf->access_flags = rd2(f);
- cf->this_class = rd2(f);
- cf->super_class = rd2(f);
- cf->interfaces_count = n = rd2(f);
- if (rdInterface_Info(f, cf, n)) goto corrupt;
- cf->fields_count = n = rd2(f);
- if (rdField_Info(f, cf, n)) goto corrupt;
- cf->methods_count = n = rd2(f);
- if (rdMethod_Info(f, cf, n)) goto corrupt;
- cf->attributes_count = n = rd2(f);
- if (rdAttribute_Info(f, cf, n, &cf->attributes)) goto corrupt;
- if (rd1(f) != EOF) jdebug("junk at end of ClassFile '%s'", name);
- return cf;
- corrupt:
- jsyserr("ClassFile '%s' corrupted", name);
- return 0;
- }
|