Main Page | Namespace List | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

classfile.c

Go to the documentation of this file.
00001 /*!
00002  * @file classfile.c
00003  *
00004  * @brief Implementation of <em>The Java Virtual Machine Specification,
00005  * version 2 Chapter 4, The Class File Format</em>.
00006  *
00007  * Manipulation of attributes is performed in
00008  * @link jvm/src/cfattrib.c cfattrib.c@endlink.
00009  * All other work is done here.
00010  *
00011  * The JVM specification is available from Sun Microsystems' web site
00012  * at http://java.sun.com/docs/books/vmspec/index.html and
00013  * may be read online at
00014 http://java.sun.com/docs/books/vmspec/2nd-edition/html/VMSpecTOC.doc.html
00015  *
00016  * The Java 5 class file format is available as a PDF file separately at
00017 http://java.sun.com/docs/books/vmspec/2nd-edition/ClassFileFormat-final-draft.pdf
00018  * and was the basis for the ClassFile structure of this implementation.
00019  *
00020  *
00021  * @todo  Per spec section 5.4.1, need to verify the contents of
00022  *        the file read in before initializing the class, else
00023  *        throw @b VerifyError.
00024  *
00025  * @todo Need to verify which web document for the
00026  *       Java 5 class file definition is either "official",
00027  *       actually correct, or is the <em>de facto</em> standard.
00028  *
00029  *
00030  * @section Control
00031  *
00032  * \$URL: https://svn.apache.org/path/name/classfile.c $ \$Id: classfile.c 0 09/28/2005 dlydick $
00033  *
00034  * Copyright 2005 The Apache Software Foundation
00035  * or its licensors, as applicable.
00036  *
00037  * Licensed under the Apache License, Version 2.0 ("the License");
00038  * you may not use this file except in compliance with the License.
00039  * You may obtain a copy of the License at
00040  *
00041  *     http://www.apache.org/licenses/LICENSE-2.0
00042  *
00043  * Unless required by applicable law or agreed to in writing,
00044  * software distributed under the License is distributed on an
00045  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
00046  * either express or implied.
00047  *
00048  * See the License for the specific language governing permissions
00049  * and limitations under the License.
00050  *
00051  * @version \$LastChangedRevision: 0 $
00052  *
00053  * @date \$LastChangedDate: 09/28/2005 $
00054  *
00055  * @author \$LastChangedBy: dlydick $
00056  *         Original code contributed by Daniel Lydick on 09/28/2005.
00057  *
00058  * @section Reference
00059  *
00060  */
00061 
00062 #include "arch.h"
00063 ARCH_COPYRIGHT_APACHE(classfile, c, "$URL: https://svn.apache.org/path/name/classfile.c $ $Id: classfile.c 0 09/28/2005 dlydick $");
00064 
00065 
00066 #include <fcntl.h>
00067 #include <stdlib.h>
00068 #include <string.h>
00069 #include <unistd.h>
00070 #include <sys/stat.h>
00071 
00072 #include "jvmcfg.h"
00073 #include "cfmacros.h"
00074 #include "classfile.h"
00075 #include "classpath.h"
00076 #include "exit.h"
00077 #include "jvm.h"
00078 #include "native.h"
00079 #include "util.h"
00080 
00081 
00082 /*!
00083  * @brief Build up empty JVM class file structure for use
00084  * by Java primative data types.
00085  *
00086  * Each primative data type needs a minimal class definition
00087  * to avoid having special cases for class processing logic.
00088  * Also, treating primatives like classes can provide convenient
00089  * information on data size types, like @b (jlong) versus @b (jint).
00090  * This can be provided by the base type information, which is
00091  * passed in here when creating these minimal classes.
00092  *
00093  * The constant pool for such a minima class looks like this:
00094  *
00095  * <ul>
00096  * <li><b>CP[0]</b>:  Not represented, per spec.  Implies
00097  *                    @c @b java.lang.Object .
00098  * </li>
00099  * <li><b>CP[1]</b>:  CONSTANT_Utf8_info string of one character, the
00100  *                    @link #BASETYPE_CHAR_B basetype@endlink letter.
00101  * </li>
00102  * <li><b>CP[2]</b>:  CONSTANT_Class_info class definition of this
00103  *                    primative, with @link
00104                       CONSTANT_Class_info#name_index name_index@endlink
00105  *                    pointing to UTF8 string at index 1.
00106  * </li>
00107  * </ul>
00108  *
00109  * @todo  Need to take a hard look at the requirements
00110  *        for @c @b java.lang.Class and see if this is sufficient
00111  *        or even accurately implemented.
00112  *
00113  *
00114  * @param  basetype   One of the primative base types BASETYPE_CHAR_x
00115  *
00116  *
00117  * @returns (ClassFile *) to heap-allocated area, used throughtout life
00118  *          of JVM, then released.
00119  *
00120  */
00121 ClassFile *classfile_allocate_primative(jvm_basetype basetype)
00122 {
00123     /*!
00124      * @internal INITIALIZE TO ZEROES all fields so there are
00125      * automatic @link #rnull rnull@endlink pointers in case of
00126      * failure along the way.
00127      */
00128     ClassFile *pcfs = HEAP_GET_DATA(sizeof(ClassFile), rtrue);
00129 
00130 
00131     pcfs->magic = CLASSFILE_MAGIC;      /* "This is a Java class" */
00132                                         /* Look like -r1.2 source file*/
00133     pcfs->major_version = VERSION_MAJOR_JDK2;
00134     pcfs->minor_version = VERSION_MINOR_DEFAULT;
00135 
00136     pcfs->constant_pool_count = 3; /* 1 class, 1 string, + j/l/Object */
00137     pcfs->constant_pool = HEAP_GET_DATA(pcfs->constant_pool_count *
00138                                         sizeof(cp_info_dup *), rfalse);
00139 
00140 
00141     /*!
00142      * @internal Since @c @b java.lang.Object is implied,
00143      * don't need this slot.
00144      */
00145     pcfs->constant_pool[0] = (cp_info_dup *) rnull;
00146 
00147 
00148     /* Allocate CONSTANT_Utf8_info member.  Default of u1[1] okay */
00149     pcfs->constant_pool[1] = HEAP_GET_DATA(sizeof(cp_info_dup) +
00150                                            sizeof(CONSTANT_Utf8_info) -
00151                                            sizeof(cp_info), rtrue);
00152     CONSTANT_Utf8_info *putf =PTR_THIS_CP_Utf8(pcfs->constant_pool[1]);
00153     putf->tag = CONSTANT_Utf8;
00154     putf->length = sizeof(u1); /* Primatives have a single char name */
00155     putf->bytes[0] = basetype; /* single (u1) character */
00156 
00157     /* Allocate CONSTANT_Class_info member */
00158     pcfs->constant_pool[2] = HEAP_GET_DATA(sizeof(cp_info_dup) +
00159                                            sizeof(CONSTANT_Class_info) -
00160                                            sizeof(cp_info), rfalse);
00161     CONSTANT_Class_info *pci =PTR_THIS_CP_Class(pcfs->constant_pool[2]);
00162     pci->tag = CONSTANT_Class;
00163     pci->name_index = 1; /* Index of Utf8 string of primative desc. */
00164 
00165 
00166     pcfs->access_flags = ACC_SYNTHETIC; /*! @todo  Needs more thought */
00167     pcfs->this_class = 2;   /* Index to class entry */
00168 
00169                             /*! @todo  Is this assumption
00170                                        valid/meaningful? */
00171     pcfs->super_class = 0;  /* No superclass, imply java.lang.Object */
00172 
00173     pcfs->interfaces_count = 0;
00174     pcfs->interfaces = (u2 *) rnull;
00175 
00176     pcfs->fields_count = 0;
00177     pcfs->fields = (field_info **) rnull;
00178 
00179     pcfs->methods_count = 0;
00180     pcfs->methods = (method_info **) rnull;
00181 
00182     pcfs->attributes_count = 0;
00183     pcfs->attributes = (attribute_info_dup **) rnull;
00184 
00185     return(pcfs);
00186 
00187 } /* END of classfile_allocate_primative() */
00188 
00189 
00190 /*!
00191  * @def ALLOC_CP_INFO()
00192  *
00193  * @brief Allocate a cp_info_dup structure containing any generic
00194  * type of constant_pool entry.
00195  *
00196  * Allocate space from heap, populate from class file data,
00197  * and fill in initial pad bytes.
00198  *
00199  *
00200  * @param spec_typedef   Structure @link #CONSTANT_Class_info
00201                          CONSTANT_xxx_info@endlink type definition
00202  *                       of one of the constant_pool types.
00203  *
00204  *
00205  * @param binding_struct Name of local binding structure @link
00206                          #CONSTANT_Class_info.LOCAL_Class_binding
00207                          LOCAL_xxx_binding@endlink associated with
00208  *                       @b spec_typedef
00209  *
00210  *
00211  * @returns @link #rvoid rvoid@endlink
00212  *
00213  */
00214 
00215 #define ALLOC_CP_INFO(spec_typedef, binding_struct)                    \
00216     misc_adj = sizeof(u1) * CP_INFO_NUM_EMPTIES;                       \
00217                                                                        \
00218     cf_item_size = sizeof(spec_typedef)-sizeof(struct binding_struct); \
00219     pcpd = HEAP_GET_METHOD(misc_adj + sizeof(spec_typedef), rfalse);   \
00220     memcpy(((rbyte *) pcpd) + misc_adj,pcpbytes,cf_item_size);         \
00221                                                                        \
00222     pcpd->empty[0] = FILL_INFO_DUP0;                                   \
00223     pcpd->empty[1] = FILL_INFO_DUP1;                                   \
00224     pcpd->empty[2] = FILL_INFO_DUP2; /* Extra ; */
00225 
00226 
00227 /*!
00228  * @def ALLOC_CF_ITEM()
00229  *
00230  * @brief Allocate either a field_info or method_info structure.
00231  *
00232  * Allocate space from heap and  populate from class file data,
00233  *
00234  *
00235  * @param spec_typedef   Structure field_info or method_info type
00236  *                       definition.
00237  *
00238  * @param pbytes         Name <b><code>(jbyte *)</code></b> pointer into
00239  *                       class file data being parsed pointing to
00240  *                       where this structure is found.
00241 
00242  * @param pcfsi          <b><code>(spec_typedef *)</code></b> array[]
00243  *                       pointer to the field_info or method_info table
00244  *                       slot where the parsed data will be stored.
00245  *
00246  * @param binding_struct Structure LOCAL_field_binding or
00247  *                       LOCAL_method_binding for appropriate
00248  *                       @b spec_typedef type definition.
00249  */
00250 
00251 #define ALLOC_CF_ITEM(spec_typedef, pbytes, pcfsi, binding_struct) \
00252     cf_item_size = sizeof(spec_typedef) -                          \
00253                    sizeof(struct binding_struct) -                 \
00254                    sizeof(attribute_info_dup **);                  \
00255     pcfsi = HEAP_GET_METHOD(sizeof(spec_typedef), rfalse);  \
00256     memcpy(((rbyte *) pcfsi),pbytes,cf_item_size);/*Extra ;*/
00257 
00258 /*!
00259  * @name Range check of constant_pool indices.
00260  *
00261  * @brief Range check constant_pool @b cpidx against max index,
00262  * with/without typed pointer.
00263  *
00264  * (Testing <b><code>cpidx < 0</code></b> is not checked,
00265  * since @p @b cpidx is an unsigned integer.)
00266  * 
00267  *
00268  * @param type  @link #CONSTANT_Class_info CONSTANT_xxx_info@endlink
00269  *              pointer of data type to be checked
00270  *
00271  * @param pcfs  ClassFile area to be checked
00272  *
00273  * @param cpidx constant_pool index to be checked
00274  *
00275  * @param msg   Error message to display at failure
00276  *
00277  *
00278  * @returns @link #rvoid rvoid@endlink
00279  *
00280  */
00281 
00282 /*@{ */ /* Begin grouped definitions */
00283 
00284 /*!
00285  * @brief Range check a typed pointer against the
00286  * @link #ClassFile.constant_pool_count constant_pool_count@endlink
00287  * value
00288  */
00289 #define CPTYPEIDX_RANGE_CHECK(type, pcfs, cpidx, msg)                  \
00290     LOAD_SYSCALL_FAILURE(( /* ((((type *) &pcpd->cp)->cpidx) < 0) || */\
00291                           ((((type *) &pcpd->cp)->cpidx) >=            \
00292                                           pcfs->constant_pool_count)), \
00293                          msg,                                          \
00294                          rnull,                                        \
00295                          rnull); /* Extra ; */   
00296 
00297 /*!
00298  * @brief Range check a simple index against the
00299  * @link #ClassFile.constant_pool_count constant_pool_count@endlink
00300  * value
00301  */
00302 #define CPIDX_RANGE_CHECK(pcfs, cpidx, msg)                         \
00303     LOAD_SYSCALL_FAILURE((/* (cpidx < 0) || */                      \
00304                              (cpidx >= pcfs->constant_pool_count)), \
00305                          msg,                                       \
00306                          rnull,                                     \
00307                          rnull); /* Extra ; */
00308 
00309 /*@} */ /* End of grouped definitions */
00310 
00311 /*!
00312  * @brief Parse an in-memory JVM class file, create structures to point
00313  * to various parts of it, per JVM spec pseuco-code structures.
00314  *
00315  * Interpret the class file data and load up the data structures
00316  * which access it, such as the fully qualified class names,
00317  * the code area, etc.
00318  *
00319  * @todo Need a @e much better way to free partially built class
00320  *       structure when an error occurs.  The current scheme is
00321  *       only piecemeal and @e will leave orphaned memory blocks
00322  *       lying around when something is freed that has @e the
00323  *       pointer to it, case in point, the constant_pool[] table
00324  *       when freeing the main ClassFile structure block on error.
00325  *       The partial solutions of adding heap pointer parameters to
00326  *       LOAD_SYSCALL_FAILURE() and GENERIC_FAILURExxx() macros
00327  *       is not useful here since so @e many allocations are done
00328  *       in this function.
00329  *
00330  * @param  pclassfile_image  Null-terminated ASCII string,
00331  *                           pathname of file.
00332  *
00333  *
00334  * @returns Complete class file structure, fully loaded with the
00335  *          real instantiation of the JVM spec pseudo-code structures.
00336  *          If error detected, @link #rnull rnull@endlink is returned
00337  *          and perror("msg") may be called to report the system call
00338  *          problem that caused the particular failure more.  Status
00339  *          of heap areas will be undefined since a failure like this
00340  *          should be fatal to program execution.
00341  *
00342  */
00343 
00344 ClassFile *classfile_loadclassdata(u1       *pclassfile_image)
00345 {
00346     rint misc_adj; /* For ALLOC_xxx macros */
00347 
00348 
00349     u2 tmplenutf;
00350 
00351     /* Needed for CP_ITEM_SWAP_Ux() macros */
00352 #ifdef CONFIG_LITTLE_ENDIAN
00353     u2    *pcpu2;
00354     u4    *pcpu4;
00355 #endif
00356 
00357     /* Generic data pointers, loaded via MAKE_Ux() macros above */
00358     u2    *pu2;
00359     u4    *pu4;
00360 
00361     /*
00362      * First things first:  Need to sequentially access class file data
00363      * (Data SOURCE into which *pcfs structure pointers will point)
00364      */
00365     u1 *pcfd = (u1 *) pclassfile_image;
00366 
00367     /*
00368      * Also need to access class file structures
00369      * (Data INDEX area that holds pointers to class file data in *pcfd)
00370      */
00371     ClassFile *pcfs = (ClassFile *) HEAP_GET_METHOD(sizeof(ClassFile),
00372                                                     rtrue);
00373 
00374     /*
00375      * Need default value until field is loaded.  Set default
00376      * to "no class".  Spec also says that this constant_pool
00377      * index implies <code>java.lang.Object<code>.
00378      */
00379     pcfs->this_class = jvm_class_index_null;
00380 
00381     /*****************************************************************/
00382     /* Get magic number-- an easy exercise in using generic pointers */
00383     /*****************************************************************/
00384     MAKE_PU4(pu4, pcfd);     /* Allocate next class file data pointer */
00385                              /* Byte swap 2 & 4 byte areas */
00386 
00387     /*
00388      * Copy into class file structure area.
00389      *
00390      * ALWAYS use GETRxx() macros for multi-byte accesses
00391      * in *pclassfile_image since they are NEVER guaranteed
00392      * to be 2-byte aligned! (See getrs2() in
00393      * @link jvm/src/bytegames.c bytegames.c@endlink
00394      * and ARCH_ODD_ADDRESS_SIGSEGV in
00395      * @link jvm/src/arch.h arch.h@endlink
00396      * for details.)
00397      */
00398     pcfs->magic = GETRI4(pu4);
00399 
00400     /*
00401      * Perform little-endian byte swapping,
00402      * where appropriate (NOP otherwise)
00403      */
00404     MACHINE_JINT_SWAP(pcfs->magic);
00405 
00406     sysDbgMsg(DMLNORM,
00407               "classfile_loadclassdata",
00408               "magic=%08x",
00409               pcfs->magic);
00410 
00411     /*
00412      * Perform integrity checking as needed for each data type.
00413      */
00414     LOAD_SYSCALL_FAILURE((CLASSFILE_MAGIC != pcfs->magic),
00415                          "magic",
00416                          rnull,
00417                          rnull);
00418 
00419     /* calculate offset to next field in file data */
00420     pu4++;
00421 
00422 
00423     /*****************************************************************/
00424     /* Get minor class file version                                  */
00425     /*****************************************************************/
00426     MAKE_PU2(pu2, pu4);
00427 
00428     pcfs->minor_version = GETRS2(pu2);
00429 
00430     MACHINE_JSHORT_SWAP(pcfs->minor_version);
00431 
00432     /* LOAD_SYSCALL_FAILURE( what needs checking here?, "minor"); */
00433 
00434     sysDbgMsg(DMLNORM,
00435               "classfile_loadclassdata",
00436               "minor=%d",
00437               pcfs->minor_version);
00438 
00439     pu2++;                   /* calc offset to next field in file data*/
00440 
00441 
00442     /*****************************************************************/
00443     /* Get major class file version                                  */
00444     /*****************************************************************/
00445 
00446     /* Can optimize along the way-- pu2 already points here */
00447     /* MAKE_PU2(pu2, pu2); */
00448 
00449     pcfs->major_version = GETRS2(pu2++);
00450 
00451     MACHINE_JSHORT_SWAP(pcfs->major_version);
00452 
00453     sysDbgMsg(DMLNORM,
00454               "classfile_loadclassdata",
00455               "major=%d",
00456               pcfs->major_version);
00457 
00458     /* Range check against spec (footnote to field definition in spec)*/
00459     LOAD_SYSCALL_FAILURE(((pcfs->major_version < VERSION_MAJOR_LOW) ||
00460                           (pcfs->major_version > VERSION_MAJOR_HIGH)),
00461                          "major",
00462                          rnull,
00463                          rnull);
00464 
00465     LOAD_SYSCALL_FAILURE(((pcfs->major_version == VERSION_MAJOR_LOW)
00466                           /* &&
00467                           (pcfs->minor_version <  VERSION_MINOR_LOW) */
00468                          ),
00469                          "low minor",
00470                          rnull,
00471                          rnull);
00472 
00473     LOAD_SYSCALL_FAILURE(((pcfs->major_version == VERSION_MAJOR_HIGH) &&
00474                           (pcfs->minor_version >  VERSION_MINOR_HIGH)),
00475                          "high minor",
00476                          rnull,
00477                          rnull);
00478 
00479 
00480     /*! @todo  Throw @b UnsupportedClassVersionError for bad versions */
00481 
00482     /*****************************************************************/
00483     /* Get constant_pool_count                                       */
00484     /*****************************************************************/
00485     pcfs->constant_pool_count = GETRS2(pu2++);
00486 
00487     MACHINE_JSHORT_SWAP(pcfs->constant_pool_count);
00488 
00489     sysDbgMsg(DMLNORM,
00490               "classfile_loadclassdata",
00491               "cp count=%d",
00492               pcfs->constant_pool_count);
00493 
00494     /* In reality a NOP, but theoretically possible for empty file */
00495  /* LOAD_SYSCALL_FAILURE((0 > pcfs->constant_pool_count), "CP index");*/
00496 
00497 
00498     /*****************************************************************/
00499     /* Create constant pool index, then load up constant pool        */
00500     /*****************************************************************/
00501 
00502     jvm_constant_pool_index cpidx;
00503     rint    cf_item_size;
00504     jbyte  *pcpbytes = (jbyte *) pu2;
00505 
00506     /*
00507      * Map the indices in the class file to point to actual
00508      * constant pool enties via a pointer lookup table.
00509      *
00510      * Make constant_pool[] large enough for 0th element as well
00511      * as defined element (the @c @b java.lang.Object per spec).
00512      * This is simply a convenience for future access without doing
00513      * an <b><code>x - 1</code></b> calculation.  Therefore, fill
00514      * in 0th element with @link #rnull rnull@endlink info as it
00515      * should never be used.  Any access SHOULD produce @b SIGSEGV
00516      * because the proper class info should be accessed instead.
00517      */
00518      pcfs->constant_pool = HEAP_GET_METHOD(pcfs->constant_pool_count *
00519                                                sizeof(cp_info_dup *),
00520                                            rfalse);
00521 
00522     /*
00523      * Dummy entry for @c @b java.lang.Object constant pool
00524      * references (0th element)
00525      */
00526     pcfs->constant_pool[CONSTANT_CP_DEFAULT_INDEX] =
00527         (cp_info_dup *) rnull;
00528 
00529     /*
00530      * Iterate through class file's constant_pool and fill in
00531      * the constant_pool[] pointer array for normal use.
00532      */
00533     for (cpidx = CONSTANT_CP_START_INDEX;
00534          cpidx < pcfs->constant_pool_count + CONSTANT_CP_START_INDEX -1;
00535          cpidx++)
00536     {
00537         cp_info_dup *pcpd;
00538 
00539         pu2 = (u2 *) pcpbytes;
00540 
00541         /*
00542          * Look up structure size, perform in-place byte swap
00543          * for little-endian architectures.
00544          */
00545         switch (((cp_info *) pcpbytes)->tag)
00546         {
00547             case CONSTANT_Class:
00548                 ALLOC_CP_INFO(CONSTANT_Class_info,
00549                               LOCAL_Class_binding);
00550 
00551                 CP_ITEM_SWAP_U2(CONSTANT_Class_info, name_index);
00552 
00553                 CPTYPEIDX_RANGE_CHECK(CONSTANT_Class_info,
00554                                       pcfs,
00555                                       name_index,
00556                                       "CP name index");
00557 
00558                 /* Initialize late binding extension */
00559                 PTR_THIS_CP_Class(pcpd)->LOCAL_Class_binding.clsidxJVM =
00560                                                    jvm_class_index_null;
00561 
00562                 break;
00563 
00564             case CONSTANT_Fieldref:
00565                 ALLOC_CP_INFO(CONSTANT_Fieldref_info,
00566                               LOCAL_Fieldref_binding);
00567 
00568                 CP_ITEM_SWAP_U2(CONSTANT_Fieldref_info,class_index);
00569 
00570                 CP_ITEM_SWAP_U2(CONSTANT_Fieldref_info,
00571                                 name_and_type_index);
00572 
00573                 CPTYPEIDX_RANGE_CHECK(CONSTANT_Fieldref_info,
00574                                       pcfs,
00575                                       class_index,
00576                                       "CP class index");
00577 
00578                 /* Initialize late binding extension */
00579                 PTR_THIS_CP_Fieldref(pcpd)
00580                     ->LOCAL_Fieldref_binding.clsidxJVM =
00581                                                    jvm_class_index_null;
00582 
00583                 PTR_THIS_CP_Fieldref(pcpd)
00584                     ->LOCAL_Fieldref_binding.fluidxJVM =
00585                                                     jvm_field_index_bad;
00586 
00587                 PTR_THIS_CP_Fieldref(pcpd)
00588                     ->LOCAL_Fieldref_binding.oiflagJVM =
00589                                                 rneither_true_nor_false;
00590 
00591                 PTR_THIS_CP_Fieldref(pcpd)
00592                     ->LOCAL_Fieldref_binding.jvaluetypeJVM =
00593                                                    LOCAL_BASETYPE_ERROR;
00594 
00595                 break;
00596 
00597             case CONSTANT_Methodref:
00598                 ALLOC_CP_INFO(CONSTANT_Methodref_info,
00599                               LOCAL_Methodref_binding);
00600 
00601                 CP_ITEM_SWAP_U2(CONSTANT_Methodref_info, class_index);
00602 
00603                 CP_ITEM_SWAP_U2(CONSTANT_Methodref_info,
00604                                 name_and_type_index);
00605 
00606                 CPTYPEIDX_RANGE_CHECK(CONSTANT_Methodref_info,
00607                                       pcfs,
00608                                       class_index,
00609                                       "CP method class index");
00610 
00611                 CPTYPEIDX_RANGE_CHECK(CONSTANT_Methodref_info,
00612                                       pcfs,
00613                                       name_and_type_index,
00614                                       "CP method name and type index");
00615 
00616                 /* Initialize late binding extension */
00617                 PTR_THIS_CP_Methodref(pcpd)
00618                     ->LOCAL_Methodref_binding.clsidxJVM =
00619                                                    jvm_class_index_null;
00620 
00621                 PTR_THIS_CP_Methodref(pcpd)
00622                     ->LOCAL_Methodref_binding.mthidxJVM =
00623                                                    jvm_method_index_bad;
00624 
00625                 PTR_THIS_CP_Methodref(pcpd)
00626                     ->LOCAL_Methodref_binding.codeatridxJVM =
00627                                                 jvm_attribute_index_bad;
00628 
00629                 PTR_THIS_CP_Methodref(pcpd)
00630                     ->LOCAL_Methodref_binding.excpatridxJVM =
00631                                                 jvm_attribute_index_bad;
00632 
00633                 PTR_THIS_CP_Methodref(pcpd)
00634                     ->LOCAL_Methodref_binding.nmordJVM =
00635                                          jvm_native_method_ordinal_null;
00636 
00637                 break;
00638 
00639             case CONSTANT_InterfaceMethodref:
00640                 ALLOC_CP_INFO(CONSTANT_InterfaceMethodref_info,
00641                               LOCAL_InterfaceMethodref_binding);
00642 
00643                 CP_ITEM_SWAP_U2(CONSTANT_InterfaceMethodref_info,
00644                                 class_index);
00645 
00646                 CP_ITEM_SWAP_U2(CONSTANT_InterfaceMethodref_info,
00647                                 name_and_type_index);
00648 
00649                 CPTYPEIDX_RANGE_CHECK(CONSTANT_InterfaceMethodref_info,
00650                                       pcfs,
00651                                       class_index,
00652                                      "CP interface method class index");
00653 
00654                 CPTYPEIDX_RANGE_CHECK(CONSTANT_InterfaceMethodref_info,
00655                                       pcfs,
00656                                       name_and_type_index,
00657                              "CP interface method name and type index");
00658 
00659                 /* Initialize late binding extension */
00660                 PTR_THIS_CP_InterfaceMethodref(pcpd)
00661                     ->LOCAL_InterfaceMethodref_binding.clsidxJVM =
00662                                                    jvm_class_index_null;
00663 
00664                 PTR_THIS_CP_InterfaceMethodref(pcpd)
00665                     ->LOCAL_InterfaceMethodref_binding.mthidxJVM =
00666                                                    jvm_method_index_bad;
00667 
00668                 PTR_THIS_CP_InterfaceMethodref(pcpd)
00669                     ->LOCAL_InterfaceMethodref_binding.codeatridxJVM =
00670                                                 jvm_attribute_index_bad;
00671 
00672                 PTR_THIS_CP_InterfaceMethodref(pcpd)
00673                     ->LOCAL_InterfaceMethodref_binding.excpatridxJVM =
00674                                                 jvm_attribute_index_bad;
00675 
00676                 PTR_THIS_CP_InterfaceMethodref(pcpd)
00677                     ->LOCAL_InterfaceMethodref_binding.nmordJVM =
00678                                          jvm_native_method_ordinal_null;
00679 
00680                 break;
00681 
00682             case CONSTANT_String:
00683                 ALLOC_CP_INFO(CONSTANT_String_info,
00684                               LOCAL_String_binding);
00685 
00686                 CP_ITEM_SWAP_U2(CONSTANT_String_info, string_index);
00687 
00688                 CPTYPEIDX_RANGE_CHECK(CONSTANT_String_info,
00689                                       pcfs,
00690                                       string_index,
00691                                       "CP string index");
00692                 break;
00693 
00694             case CONSTANT_Integer:
00695                 ALLOC_CP_INFO(CONSTANT_Integer_info,
00696                               LOCAL_Integer_binding);
00697 
00698                 CP_ITEM_SWAP_U4(CONSTANT_Integer_info, bytes);
00699 
00700                 break;
00701 
00702             case CONSTANT_Float:
00703                 ALLOC_CP_INFO(CONSTANT_Float_info,
00704                               LOCAL_Float_binding);
00705 
00706                 CP_ITEM_SWAP_U4(CONSTANT_Float_info, bytes);
00707 
00708                 break;
00709 
00710             case CONSTANT_Long:
00711                 ALLOC_CP_INFO(CONSTANT_Long_info,
00712                               LOCAL_Long_binding);
00713 
00714                 CP_ITEM_SWAP_U4(CONSTANT_Long_info, high_bytes);
00715 
00716                 CP_ITEM_SWAP_U4(CONSTANT_Long_info, low_bytes);
00717 
00718                 /*
00719                  * Make both slots point to the same place-- see
00720                  * assignment below for value at [cpidx].  This is
00721                  * a simple way to have something meaningful in
00722                  * the unused slot.  Ignore this second slot, but
00723                  * make sure it does not contain garbage.
00724                  */
00725                 pcfs->constant_pool[cpidx] = pcpd;
00726                 cpidx++;
00727 
00728                 break;
00729 
00730             case CONSTANT_Double:
00731                 ALLOC_CP_INFO(CONSTANT_Double_info,
00732                               LOCAL_Double_binding);
00733 
00734                 CP_ITEM_SWAP_U4(CONSTANT_Double_info, high_bytes);
00735 
00736                 CP_ITEM_SWAP_U4(CONSTANT_Double_info, low_bytes);
00737 
00738                 /*
00739                  * Make both slots point to the same place-- see
00740                  * assignment below for value at [cpidx].  This is
00741                  * a simple way to have something meaningful in
00742                  * the unused slot.  Ignore this second slot, but
00743                  * make sure it does not contain garbage.
00744                  */
00745                 pcfs->constant_pool[cpidx] = pcpd;
00746                 cpidx++;
00747 
00748                 break;
00749 
00750             case CONSTANT_NameAndType:
00751                 ALLOC_CP_INFO(CONSTANT_NameAndType_info,
00752                               LOCAL_NameAndType_binding);
00753                 CP_ITEM_SWAP_U2(CONSTANT_NameAndType_info, name_index);
00754                 CP_ITEM_SWAP_U2(CONSTANT_NameAndType_info,
00755                                 descriptor_index);
00756                 CPTYPEIDX_RANGE_CHECK(CONSTANT_NameAndType_info,
00757                                       pcfs,
00758                                       name_index,
00759                                       "CP name and type name index");
00760                 CPTYPEIDX_RANGE_CHECK(CONSTANT_NameAndType_info,
00761                                       pcfs,
00762                                       descriptor_index,
00763                                    "CP name and type descriptor index");
00764 
00765                 /* Initialize late binding extension */
00766 
00767                 /* (There is no late binding associated with this tag)*/
00768                 break;
00769 
00770             case CONSTANT_Utf8:
00771 
00772                 tmplenutf = ((CONSTANT_Utf8_info *) pcpbytes)->length;
00773                 MACHINE_JSHORT_SWAP(tmplenutf);
00774 
00775                 /*
00776                  * Explicitly unroll the ALLOC_CP_INFO() macro
00777                  * due to the variable length string area.  Adjust
00778                  * also for the dummy item
00779                  * @link CONSTANT_Utf8_info#bytes bytes@endlink,
00780                  * namely @c @b sizeof(info[1]), or 1 byte.
00781                  *
00782                  * The segment below copies each piece of the buffer
00783                  * from @c @b *pcpbytes to @c @b *pcpd .
00784                  */
00785 
00786                 /* Size of structure to copy */
00787                 cf_item_size = sizeof(CONSTANT_Utf8_info) -
00788                                sizeof(struct LOCAL_Utf8_binding) -
00789                                sizeof(u1);
00790 
00791                 /* Allocate heap for structure */
00792                 pcpd = HEAP_GET_METHOD(sizeof(u1) * CP_INFO_NUM_EMPTIES+
00793                                            tmplenutf + cf_item_size,
00794                                        rfalse);
00795 
00796                 /* Copy structure, including @b empty bytes */
00797                 memcpy(((rbyte *)pcpd) +
00798                            sizeof(u1) * CP_INFO_NUM_EMPTIES,
00799                        pcpbytes,
00800                        cf_item_size);
00801                 pcpd->empty[0] = FILL_INFO_DUP0;
00802                 pcpd->empty[1] = FILL_INFO_DUP1;
00803                 pcpd->empty[2] = FILL_INFO_DUP2;
00804 
00805                 /*
00806                  * Byte swap contents of
00807                  * @link CONSTANT_Utf8_info#length length@endlink
00808                  * field (only multi-byte field in structure)
00809                  */
00810                 CP_ITEM_SWAP_U2(CONSTANT_Utf8_info, length);
00811 
00812                 /* Copy UTF string itself (No byte reversal needed.) */
00813                 memcpy(PTR_THIS_CP_Utf8(pcpd)->bytes,
00814                        ((CONSTANT_Utf8_info *) pcpbytes)->bytes,
00815                        tmplenutf);
00816 
00817                 /*
00818                  * Adjust for variable length UTF8 string in source bfr
00819                  */
00820                 cf_item_size += tmplenutf;
00821 
00822                 /* Initialize late binding extension */
00823 
00824                 /* (There is no late binding associated with this tag)*/
00825 
00826                 break;
00827 
00828             default:
00829                 /*!
00830                  * @todo  Need better and more complete heap free here
00831                  */
00832 
00833                 /* This pointer came from HEAP_GET_METHOD() */
00834                 HEAP_FREE_METHOD(pcfs);
00835 
00836                 GENERIC_FAILURE1_PTR(rtrue,
00837                                      DMLNORM,
00838                                      "classfile_loadclassdata", 
00839                                      "Invalid CP tag %d",
00840                                      (((cp_info *) pcpbytes)->tag),
00841                                      ClassFile,
00842                                      rnull,
00843                                      rnull);
00844 
00845         } /* switch ... */
00846 
00847         /* Point to storage area for this constant_pool[] item */
00848         pcfs->constant_pool[cpidx] = pcpd;
00849 
00850         /* Now point past this CONSTANT_Xxxxxx_info area */
00851         pcpbytes += cf_item_size;
00852 
00853     } /* for (cpidx) */
00854 
00855 
00856     /*****************************************************************/
00857     /* Get access_flags                                              */
00858     /*****************************************************************/
00859 
00860     /* Point past the constant_pool[] area */
00861     MAKE_PU2(pu2, pcpbytes);
00862 
00863     pcfs->access_flags = GETRS2(pu2++);
00864     /*
00865      * Strip out all other @link #ACC_PUBLIC ACC_xxx@endlink bits, per
00866      * spec
00867      */
00868     pcfs->access_flags &= (ACC_PUBLIC | ACC_FINAL | ACC_SUPER |
00869         ACC_INTERFACE | ACC_ABSTRACT | ACC_SYNTHETIC | ACC_ANNOTATION |
00870         ACC_ENUM);
00871 
00872     MACHINE_JSHORT_SWAP(pcfs->access_flags);
00873 
00874     /* LOAD_SYSCALL_FAILURE(what needs checking here?,"access flags");*/
00875 
00876     sysDbgMsg(DMLNORM,
00877               "classfile_loadclassdata",
00878               "access %04x",
00879               pcfs->access_flags);
00880 
00881 
00882     /*****************************************************************/
00883     /* Get this_class                                                */
00884     /*****************************************************************/
00885     pcfs->this_class = GETRS2(pu2++);
00886 
00887     MACHINE_JSHORT_SWAP(pcfs->this_class);
00888 
00889     /*!
00890      * @todo Need to free constant_pool[0..n] also if failure
00891      */
00892     CPIDX_RANGE_CHECK(pcfs, pcfs->this_class, "this class");
00893 
00894     cfmsgs_typemsg("this", pcfs, pcfs->this_class);
00895 
00896     cfmsgs_show_constant_pool(pcfs);
00897 
00898 
00899     /*****************************************************************/
00900     /* Get super_class                                               */
00901     /*****************************************************************/
00902     pcfs->super_class = GETRS2(pu2++);
00903 
00904     MACHINE_JSHORT_SWAP(pcfs->super_class);
00905 
00906     /* LOAD_SYSCALL_FAILURE(what needs checking here?,"access flags");*/
00907 
00908     cfmsgs_typemsg("super", pcfs, pcfs->super_class);
00909 
00910     /*****************************************************************/
00911     /* Create interfaces index, then load up interfaces array        */
00912     /*****************************************************************/
00913     pcfs->interfaces_count = GETRS2(pu2++);
00914 
00915     MACHINE_JSHORT_SWAP(pcfs->interfaces_count);
00916 
00917     sysDbgMsg(DMLNORM,
00918               "classfile_loadclassdata",
00919               "intfc count=%d",
00920               pcfs->interfaces_count);
00921 
00922     /*
00923      LOAD_SYSCALL_FAILURE(what needs checking here?,"interfaces_count");
00924      */
00925 
00926     if (0 == pcfs->interfaces_count)
00927     {
00928         /* Quite possible, and theoretically okay */
00929         pcfs->interfaces = (u2 *) rnull;
00930     }
00931     else
00932     {
00933         /*
00934          * Map the indices in the class file to point to actual
00935          * constant pool enties via a pointer lookup table.
00936          */
00937         pcfs->interfaces = HEAP_GET_METHOD(pcfs->interfaces_count *
00938                                                sizeof(u2 *),
00939                                            rfalse);
00940 
00941         /*
00942          * Iterate through class file's interfaces[] array and
00943          * fill in the constant_pool[] references for normal use.
00944          */
00945         jvm_interface_index ifidx;
00946         for (ifidx = 0; ifidx < pcfs->interfaces_count; ifidx++)
00947         {
00948             /* Retrieve next interface index from class file area */
00949             jvm_interface_index cfifidx = GETRS2(pu2++);
00950 
00951             /* Range check the index value */
00952             CPIDX_RANGE_CHECK(pcfs,
00953                               cfifidx,
00954                               "interface index");
00955 
00956             /*
00957              * Can't free in GENERIC_FAILURE1_PTR() because
00958              * these pointer came from HEAP_GET_METHOD(),
00959              * not from HEAP_GET_DATA()
00960              */
00961             if (CONSTANT_Class != CP_TAG(pcfs, cfifidx))
00962             {
00963                 HEAP_FREE_METHOD(pcfs->interfaces);
00964                 /*!
00965                  * @todo HEAP_FREE_METHOD(pcfs->constan_pool[0..n]);
00966                  */
00967                 HEAP_FREE_METHOD(pcfs);
00968             }
00969 
00970             GENERIC_FAILURE1_PTR((CONSTANT_Class !=
00971                                                   CP_TAG(pcfs,cfifidx)),
00972                                  DMLNORM,
00973                                  "classfile_loadclassdata",
00974                                  "Invalid interface tag %d",
00975                                  CP_TAG(pcfs, cfifidx),
00976                                  ClassFile,
00977                                  rnull,
00978                                  rnull);
00979 
00980             /* Finally store valid constant pool entry index */
00981             pcfs->interfaces[ifidx] = cfifidx;
00982 
00983             cfmsgs_typemsg("intfc", pcfs, cfifidx);
00984 
00985         } /* for (ifidx) */
00986 
00987         /*
00988          * Point past the interfaces[] area
00989          * (done above by autoincrement)
00990          */
00991 
00992         /* pu2 += pcfs->interfaces_count; */
00993 
00994     }
00995 
00996 
00997     /*****************************************************************/
00998     /* Get field_count                                               */
00999     /*****************************************************************/
01000     pcfs->fields_count = GETRS2(pu2++);
01001 
01002     MACHINE_JSHORT_SWAP(pcfs->fields_count);
01003 
01004     /* LOAD_SYSCALL_FAILURE(what needs checking here?,"fields_count");*/
01005 
01006     sysDbgMsg(DMLNORM,
01007               "classfile_loadclassdata",
01008               "flds count=%d",
01009               pcfs->fields_count);
01010 
01011 
01012     /*****************************************************************/
01013     /* Create constant pool index, then load up fields[] array       */
01014     /*****************************************************************/
01015     jbyte *pfbytes = (jbyte *) pu2;
01016 
01017     if (0 == pcfs->fields_count)
01018     {
01019         /* Quite possible, and theoretically okay */
01020         pcfs->fields = (field_info **) rnull;
01021     }
01022     else
01023     {
01024         jvm_field_index fldidx;
01025 
01026         /*
01027          * Map the indices in the class file to point to actual
01028          * constant pool enties via a pointer lookup table.
01029          */
01030         pcfs->fields = HEAP_GET_METHOD(pcfs->fields_count *
01031                                            sizeof(field_info *),
01032                                        rtrue);
01033 
01034 
01035         /*
01036          * Iterate through class file's fields and fill in
01037          * the attributes[] pointer array for normal use.
01038          */
01039         for (fldidx = 0; fldidx < pcfs->fields_count; fldidx++)
01040         {
01041             /* Allocate a heap area for each fields[] entry */
01042             ALLOC_CF_ITEM(field_info,
01043                           pfbytes,
01044                           pcfs->fields[fldidx],
01045                           LOCAL_field_binding);
01046 
01047             MACHINE_JSHORT_SWAP(pcfs->fields[fldidx]->access_flags);
01048             MACHINE_JSHORT_SWAP(pcfs->fields[fldidx]->name_index);
01049             MACHINE_JSHORT_SWAP(pcfs->fields[fldidx]->descriptor_index);
01050             MACHINE_JSHORT_SWAP(pcfs->fields[fldidx]->attributes_count);
01051 
01052             /* Strip out unused access flags, per spec */
01053             pcfs->fields[fldidx]->access_flags &=
01054                 (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
01055                  ACC_STATIC | ACC_FINAL | ACC_VOLATILE | ACC_TRANSIENT |
01056                  ACC_SYNTHETIC | ACC_ENUM);
01057 
01058             /* Range check the indices */
01059             CPIDX_RANGE_CHECK(pcfs,
01060                               pcfs->fields[fldidx]->name_index,
01061                               "field name index");
01062             CPIDX_RANGE_CHECK(pcfs,
01063                               pcfs->fields[fldidx]->descriptor_index,
01064                               "field descriptor index");
01065 
01066             cfmsgs_typemsg("fld name",
01067                            pcfs,
01068                            pcfs->fields[fldidx]->name_index);
01069             cfmsgs_typemsg("fld desc",
01070                            pcfs,
01071                            pcfs->fields[fldidx]->descriptor_index);
01072 
01073             /* Skip past above items to attributes area */
01074             pfbytes = (jbyte *) &((method_info *) pfbytes)->attributes;
01075 
01076 
01077             /*
01078              * Map the indices in the class file to point to actual
01079              * constant pool enties via a pointer lookup table.
01080              */
01081             if (0 ==  pcfs->fields[fldidx]->attributes_count)
01082             {
01083                 /* Quite possible for small objects */
01084                 pcfs->fields[fldidx]->attributes =
01085                                           (attribute_info_dup **) rnull;
01086             }
01087             else
01088             {
01089                 pcfs->fields[fldidx]->attributes =
01090                     HEAP_GET_METHOD(
01091                         pcfs->fields[fldidx]->attributes_count *
01092                             sizeof(attribute_info *),
01093                         rtrue);
01094 
01095                 /*
01096                  * Load up each attribute in this attribute area
01097                  */
01098                 jvm_attribute_index atridx;
01099                 for (atridx = 0;
01100                      atridx < pcfs->fields[fldidx]->attributes_count;
01101                      atridx++)
01102                 {
01103                     /*
01104                      * Load an attribute and verify that it is either
01105                      * a valid (or an ignored) attribute, then point to
01106                      * next attribute in class file image.
01107                      */
01108 
01109                     pfbytes =
01110                         cfattrib_loadattribute(
01111                             pcfs,
01112                             &pcfs->fields[fldidx]->attributes[atridx],
01113                             (attribute_info *) pfbytes);
01114 
01115                     LOAD_SYSCALL_FAILURE((rnull == pfbytes),
01116                                          "load field attribute",
01117                                          rnull,
01118                                          rnull);
01119 
01120                 } /* for (atridx) */
01121 
01122             } /* if attributes_count else */
01123 
01124             /* Finally, Initialize the late binding extension */
01125             pcfs->fields[fldidx]->LOCAL_field_binding.fluidxJVM =
01126                                                     jvm_field_index_bad;
01127 
01128         } /* for (fldidx) */
01129 
01130     } /* if pcfs->fields */
01131 
01132 
01133     /*****************************************************************/
01134     /* Get method_count                                              */
01135     /*****************************************************************/
01136 
01137     /* Point past end of fields area */
01138     MAKE_PU2(pu2, pfbytes);
01139 
01140     /*LOAD_SYSCALL_FAILURE(what needs checking here?,"methods count");*/
01141     MACHINE_JSHORT_SWAP(pu2);
01142     pcfs->methods_count =  GETRS2(pu2++);
01143 
01144     sysDbgMsg(DMLNORM,
01145               "classfile_loadclassdata",
01146               "meth count=%d",
01147               pcfs->methods_count);
01148 
01149     /*****************************************************************/
01150     /* Create constant pool index, then load up methods[] array      */
01151     /*****************************************************************/
01152     jbyte *pmbytes = (jbyte *) pu2;
01153 
01154     if (0 == pcfs->methods_count)
01155     {
01156         /* Quite possible, and theoretically okay */
01157         pcfs->methods = (method_info **) rnull;
01158     }
01159     else
01160     {
01161         jvm_method_index mthidx;
01162 
01163         /*
01164          * Map the indices in the class file to point to actual
01165          * constant pool enties via a pointer lookup table.
01166          */
01167         pcfs->methods = HEAP_GET_METHOD(pcfs->methods_count *
01168                                             sizeof(method_info *),
01169                                         rtrue);
01170 
01171         /*
01172          * Iterate through class file's methods and fill in
01173          * the attributes[] pointer array for normal use.
01174          */
01175         for (mthidx = 0; mthidx < pcfs->methods_count; mthidx++)
01176         {
01177             /* Allocate a heap area for each methods[] entry */
01178             ALLOC_CF_ITEM(method_info,
01179                           pmbytes,
01180                           pcfs->methods[mthidx],
01181                           LOCAL_method_binding);
01182 
01183             MACHINE_JSHORT_SWAP(pcfs->methods[mthidx]->access_flags);
01184             MACHINE_JSHORT_SWAP(pcfs->methods[mthidx]->name_index);
01185            MACHINE_JSHORT_SWAP(pcfs->methods[mthidx]->descriptor_index);
01186            MACHINE_JSHORT_SWAP(pcfs->methods[mthidx]->attributes_count);
01187 
01188             /* Strip out unused access flags, per spec */
01189             pcfs->methods[mthidx]->access_flags &=
01190                 (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
01191                  ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED | 
01192                  ACC_BRIDGE | ACC_VARARGS | ACC_NATIVE| ACC_ABSTRACT |
01193                  ACC_STRICT | ACC_SYNTHETIC);
01194 
01195             /* Range check the indices */
01196             CPIDX_RANGE_CHECK(pcfs,
01197                               pcfs->methods[mthidx]->name_index,
01198                               "method name index");
01199             CPIDX_RANGE_CHECK(pcfs,
01200                               pcfs->methods[mthidx]->descriptor_index,
01201                               "method descriptor index");
01202 
01203             cfmsgs_typemsg("meth name",
01204                            pcfs,
01205                            pcfs->methods[mthidx]->name_index);
01206             cfmsgs_typemsg("meth desc",
01207                           pcfs,
01208                           pcfs->methods[mthidx]->descriptor_index);
01209 
01210 
01211             /* Skip past above items to attributes area */
01212             pmbytes = (jbyte *) &((method_info *) pmbytes)->attributes;
01213 
01214             /*
01215              * Initialize the late binding extension.
01216              * These values will get overwritten when a
01217              * code attribute is found and when an optional
01218              * exception attribute is found.
01219              */
01220             pcfs->methods[mthidx]
01221                     ->LOCAL_method_binding.codeatridxJVM =
01222                                             jvm_attribute_index_bad;
01223 
01224             pcfs->methods[mthidx]
01225                     ->LOCAL_method_binding.excpatridxJVM =
01226                                             jvm_attribute_index_bad;
01227 
01228             pcfs->methods[mthidx]
01229                     ->LOCAL_method_binding.nmordJVM =
01230                                      jvm_native_method_ordinal_null;
01231 
01232 
01233             /*
01234              * Map the indices in the class file to point to actual
01235              * constant pool enties via a pointer lookup table.
01236              */
01237             if (0 ==  pcfs->methods[mthidx]->attributes_count)
01238             {
01239                 /* Quite possible for small objects */
01240                 pcfs->methods[mthidx]->attributes =
01241                                           (attribute_info_dup **) rnull;
01242             }
01243             else
01244             {
01245                 /*
01246                  * Allocate the attribute area for this method
01247                  */
01248                 pcfs->methods[mthidx]->attributes =
01249                     HEAP_GET_METHOD(
01250                         pcfs->methods[mthidx]->attributes_count *
01251                             sizeof(attribute_info_dup *),
01252                         rtrue);
01253 
01254                 /*
01255                  * Load up each attribute in this attribute area
01256                  */
01257                 jvm_attribute_index atridx;
01258                 for (atridx = 0;
01259                      atridx < pcfs->methods[mthidx]->attributes_count;
01260                      atridx++)
01261                 {
01262                     /*
01263                      * Load an attribute and verify that it is either
01264                      * a valid (or an ignored) attribute, then point to
01265                      * next attribute in class file image.
01266                      */
01267 
01268                     pmbytes =
01269                         cfattrib_loadattribute(
01270                             pcfs,
01271                             &pcfs->methods[mthidx]->attributes[atridx],
01272                             (attribute_info *) pmbytes);
01273 
01274                     LOAD_SYSCALL_FAILURE((rnull == pmbytes),
01275                                          "verify member attribute",
01276                                          rnull,
01277                                          rnull);
01278 
01279                     /*
01280                      * Load Code_attribute and Exceptions_attribute
01281                      * atridx
01282                      */
01283                     switch (cfattrib_atr2enum(pcfs,
01284                             pcfs->methods[mthidx]->attributes[atridx]
01285                                       ->ai.attribute_name_index))
01286                     {
01287                         case LOCAL_CODE_ATTRIBUTE:
01288                             pcfs
01289                               ->methods[mthidx]
01290                                 ->LOCAL_method_binding.codeatridxJVM =
01291                                                                  atridx;
01292                             break;
01293 
01294                         case LOCAL_EXCEPTIONS_ATTRIBUTE:
01295 
01296                             pcfs
01297                               ->methods[mthidx]
01298                                 ->LOCAL_method_binding.excpatridxJVM =
01299                                                                  atridx;
01300                             break;
01301 
01302                         /* Satisfy compiler that all cases are handled*/
01303                         case LOCAL_UNKNOWN_ATTRIBUTE:
01304                         case LOCAL_CONSTANTVALUE_ATTRIBUTE:
01305                         case LOCAL_INNERCLASSES_ATTRIBUTE:
01306                         case LOCAL_ENCLOSINGMETHOD_ATTRIBUTE:
01307                         case LOCAL_SYNTHETIC_ATTRIBUTE:
01308                         case LOCAL_SIGNATURE_ATTRIBUTE:
01309                         case LOCAL_SOURCEFILE_ATTRIBUTE:
01310                         case LOCAL_LINENUMBERTABLE_ATTRIBUTE:
01311                         case LOCAL_LOCALVARIABLETABLE_ATTRIBUTE:
01312                         case LOCAL_LOCALVARIABLETYPETABLE_ATTRIBUTE:
01313                         case LOCAL_DEPRECATED_ATTRIBUTE:
01314                         case LOCAL_RUNTIMEVISIBLEANNOTATIONS_ATTRIBUTE:
01315                         case
01316                             LOCAL_RUNTIMEINVISIBLEANNOTATIONS_ATTRIBUTE:
01317                         case
01318                      LOCAL_RUNTIMEVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE:
01319                         case
01320                    LOCAL_RUNTIMEINVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE:
01321                         case LOCAL_ANNOTATIONDEFAULT_ATTRIBUTE:
01322                             break;
01323                     } /* switch cfattrib_atr2enum() */
01324 
01325                 } /* for (atridx) */
01326 
01327             } /* if attributes_count else */
01328 
01329         } /* for (mthidx) */
01330 
01331     } /* if pcfs->methods */
01332 
01333     /*****************************************************************/
01334     /* Get attributes_count                                          */
01335     /*****************************************************************/
01336 
01337     /* Point past end of methods area */
01338     MAKE_PU2(pu2, pmbytes);
01339 
01340     /*LOAD_SYSCALL_FAILURE(what needs checking here?,"methods count");*/
01341     MACHINE_JSHORT_SWAP(pu2);
01342     pcfs->attributes_count = GETRS2(pu2++);
01343 
01344     sysDbgMsg(DMLNORM,
01345               "classfile_loadclassdata",
01346               "att cnt=%d",
01347               pcfs->attributes_count);
01348 
01349     /*****************************************************************/
01350     /* Create constant pool index, then load up attributes[] array   */
01351     /*****************************************************************/
01352 
01353     if (0 == pcfs->attributes_count)
01354     {
01355         /* Not really possible, and theoretically faulty */
01356         pcfs->attributes = (attribute_info_dup **) rnull;
01357     }
01358     else
01359     {
01360         /*
01361          * Map the indices in the class file to point to actual
01362          * constant pool enties via a pointer lookup table.
01363          */
01364         pcfs->attributes = HEAP_GET_METHOD(pcfs->attributes_count *
01365                                                sizeof(attribute_info *),
01366                                            rtrue);
01367 
01368         /*
01369          * Load up each attribute in the class file attribute area
01370          */
01371         jvm_attribute_index atridx;
01372         jbyte *pcbytes = (jbyte *) pu2;
01373 
01374         for (atridx = 0; atridx < pcfs->attributes_count; atridx++)
01375         {
01376             /*
01377              * Load an attribute and verify that it is either
01378              * a valid (or an ignored) attribute, then point to
01379              * next attribute in class file image.
01380              */
01381 
01382             pcbytes =
01383                 cfattrib_loadattribute(
01384                     pcfs,
01385                     &pcfs->attributes[atridx],
01386                     (attribute_info *) pcbytes);
01387 
01388             LOAD_SYSCALL_FAILURE((rnull == pcbytes),
01389                                  "verify file attribute",
01390                                  rnull,
01391                                  rnull);
01392 
01393         } /* for (atridx) */
01394 
01395     } /* if pcfs->methods_count else */
01396 
01397 
01398    /*! @todo Throw @b VerifyError for classes w/ questionable contents*/
01399 
01400     /* Class file structures are now fully loaded from class file data*/
01401 
01402     return(pcfs);
01403 
01404 } /* END of classfile_loadclassdata() */
01405 
01406 
01407 /*!
01408  * @brief Release all heap allocated to a fully loaded
01409  * ClassFile structure
01410  *
01411  * @param  pcfs   Pointer to a ClassFile structure with all its pieces
01412  *
01413  * @returns @link #rvoid rvoid@endlink Whether it succeeds or fails,
01414  *          returning anything does not make much sense.  This is
01415  *          similar to @c @b free(3) not returning anything even
01416  *          when a bad pointer was passed in.
01417  */ 
01418 rvoid classfile_unloadclassdata(ClassFile *pcfs)
01419 {
01420     if (rnull == pcfs)
01421     { 
01422         return; /* Nothing to do if @link #rnull rnull@endlink pointer*/
01423     }
01424 
01425     jvm_constant_pool_index cpidx;
01426     jvm_field_index         fldidx;
01427     jvm_method_index        mthidx;
01428     jvm_attribute_index     atridx;
01429 
01430     /*
01431      * Deallocate in the reverse order of allocation to eliminate
01432      * @e any chance for @link #rnull rnull@endlink pointer.  Do
01433      * file attributes first (last entry to first), then method
01434      * attributes, methods, field attributes, fields, and constant_pool.
01435      */
01436 
01437     if ((0 < pcfs->attributes_count) && (rnull != pcfs->attributes))
01438     {
01439         for (atridx = pcfs->attributes_count - 1;
01440              atridx != JVMCFG_BAD_ATTRIBUTE; /* wrap-around when done */
01441              atridx--)
01442         {
01443             /*
01444              * Skip any @link #rnull rnull@endlink entries
01445              * (should NEVER happen)
01446              */
01447             if (rnull == pcfs->attributes[atridx])
01448             {
01449                 continue;
01450             }
01451 
01452            cfattrib_unloadattribute(pcfs, pcfs->attributes[atridx]);
01453         }
01454     }
01455 
01456 
01457     if ((0 < pcfs->methods_count) && (rnull != pcfs->methods))
01458     {
01459         for (mthidx = pcfs->methods_count - 1;
01460              mthidx != JVMCFG_BAD_METHOD; /* wrap-around when done */
01461              mthidx--)
01462         {
01463             /*
01464              * Skip any @link #rnull rnull@endlink entries
01465              * (should NEVER happen)
01466              */
01467             if (rnull == pcfs->methods[mthidx])
01468             {
01469                 continue;
01470             }
01471 
01472             if (0 < pcfs->methods[mthidx]->attributes_count)
01473             {
01474                 for (atridx = pcfs->methods[mthidx]->attributes_count-1;
01475                                              /* wrap-around when done */
01476                      atridx != JVMCFG_BAD_ATTRIBUTE;
01477                      atridx--)
01478                 {
01479                     /*
01480                      * Skip any @link #rnull rnull@endlink entries
01481                      * (should NEVER happen)
01482                      */
01483                     if (rnull ==
01484                         pcfs->methods[mthidx]->attributes[atridx])
01485                     {
01486                         continue;
01487                     }
01488 
01489                     cfattrib_unloadattribute(pcfs,
01490                              pcfs->methods[mthidx]->attributes[atridx]);
01491                 }
01492             }
01493 
01494             HEAP_FREE_METHOD(pcfs->methods[mthidx]->attributes);
01495             HEAP_FREE_METHOD(pcfs->methods[mthidx]);
01496         }
01497     }
01498 
01499 
01500     if ((0 < pcfs->fields_count) && (rnull != pcfs->fields))
01501     {
01502         for (fldidx = pcfs->fields_count - 1;
01503              fldidx != JVMCFG_BAD_FIELD; /* wrap-around when done */
01504              fldidx--)
01505         {
01506             /*
01507              * Skip any @link #rnull rnull@endlink entries
01508              * (should NEVER happen)
01509              */
01510             if (rnull == pcfs->fields[fldidx])
01511             {
01512                 continue;
01513             }
01514 
01515             if (0 < pcfs->fields[fldidx]->attributes_count)
01516             {
01517                 for (atridx = pcfs->fields[fldidx]->attributes_count -1;
01518                                              /* wrap-around when done */
01519                      atridx != JVMCFG_BAD_ATTRIBUTE;
01520                      atridx--)
01521                 {
01522                     /*
01523                      * Skip any @link #rnull rnull@endlink entries
01524                      * (should NEVER happen)
01525                      */
01526                     if (rnull ==
01527                         pcfs->fields[fldidx]->attributes[atridx])
01528                     {
01529                         continue;
01530                     }
01531 
01532                     cfattrib_unloadattribute(pcfs,
01533                               pcfs->fields[fldidx]->attributes[atridx]);
01534                 }
01535             }
01536 
01537             HEAP_FREE_METHOD(pcfs->fields[fldidx]->attributes);
01538             HEAP_FREE_METHOD(pcfs->fields[fldidx]);
01539         }
01540     }
01541 
01542 
01543     if ((0 < pcfs->constant_pool_count)&&(rnull != pcfs->constant_pool))
01544     {
01545         for (cpidx = pcfs->constant_pool_count - 1;
01546              cpidx > CONSTANT_CP_DEFAULT_INDEX;
01547              cpidx--)
01548         {
01549             /*
01550              * Skip any @link #rnull rnull@endlink entries
01551              * (should NEVER happen)
01552              */
01553             if (rnull == pcfs->constant_pool[cpidx])
01554             {
01555                 continue;
01556             }
01557 
01558             HEAP_FREE_METHOD(pcfs->constant_pool[cpidx]);
01559         }
01560     }
01561 
01562     HEAP_FREE_METHOD(pcfs->constant_pool);
01563     HEAP_FREE_METHOD(pcfs);
01564 
01565     return;
01566 
01567 } /* end of classfile_unloadclassdata() */
01568 
01569 
01570 /*******************************************************************/
01571 /*!
01572  *
01573  * @brief Report an error @link #rnull rnull@endlink pointer if
01574  * a system call fails
01575  *
01576  *
01577  * @param  expr   Any logical expression that returns
01578  *                @link #rtrue rtrue@endlink or
01579  *                @link #rfalse rfalse@endlink.
01580  *
01581  * @param  msg    Text to display to sysDbgMsg() upon failure
01582  *
01583  *
01584  * @returns If @b expr is @link #rtrue rtrue@endlink, return a
01585  *          @link #rnull rnull@endlink pointer to the
01586  *          calling function, cast as <b><code>(rvoid *)</code></b>,
01587  *          else continue with inline code.
01588  *
01589  */
01590 #define READ_SYSCALL_FAILURE(expr, msg)            \
01591     GENERIC_FAILURE_PTR((expr),                    \
01592                         DMLMIN,                    \
01593                         "classfile_readclassfile", \
01594                         msg,                       \
01595                         rvoid,                     \
01596                         rnull,                     \
01597                         rnull)
01598 
01599 /*!
01600  * @name Read Java object code (class data) from disk files.
01601  *
01602  *
01603  * @param  filename    Null-terminated ASCII string, pathname
01604  *                     of JAR file or class file.
01605  *
01606  *
01607  * @returns Pointer to memory area containing class file data.
01608  *          If error detected, @link #rnull rnull@endlink is
01609  *          returned and perror("msg") may be called to report
01610  *          the system call problem that caused the
01611  *          particular failure more.
01612  *
01613  */
01614 
01615 /*@{ */ /* Begin grouped definitions */
01616 
01617 /*!
01618  * @brief Read a JVM class file.
01619  *
01620  * If a valid class file is read, return pointer to memory area
01621  * containing its Java class image.
01622  *
01623  */
01624 u1 *classfile_readclassfile(rchar *filename)
01625 {
01626     off_t filesize = 0;
01627 
01628     struct stat statbfr;
01629 
01630     rvoid *pclassfile_image;
01631 
01632     int fd;
01633 
01634     /*
01635      * Chk if file is available and read its stat info, esp file size
01636      */
01637     int rc = stat(filename, &statbfr);
01638     READ_SYSCALL_FAILURE(0 > rc, "statbfr");
01639 
01640     /*
01641      * Allocate enough space for entire class file to be
01642      * Read into memory at once.
01643      */
01644 
01645     pclassfile_image = (rvoid *) HEAP_GET_DATA(statbfr.st_size, rfalse);
01646 
01647     /* Now go open the file and read it */
01648     fd = open(filename, O_RDONLY);
01649     READ_SYSCALL_FAILURE(0 > fd, "file open");
01650 
01651     /* Read the whole file in at once and close it. */
01652     filesize = read(fd, pclassfile_image, statbfr.st_size);
01653     READ_SYSCALL_FAILURE(0 > filesize, "file read");
01654 
01655     close(fd);
01656 
01657     /* Make sure stat() and read() have the same size */
01658     GENERIC_FAILURE_PTR((filesize != statbfr.st_size),
01659                         DMLNORM,
01660                         "classfile_readclassfile", 
01661                         "Incomplete file read",
01662                         rvoid,
01663                         pclassfile_image,
01664                         rnull);
01665 
01666     /* Proper completion when entire file is read in */
01667     return(pclassfile_image);
01668 
01669 } /* END of classfile_readclassfile() */
01670 
01671 
01672 /*!
01673  * @brief Read an entire JAR file into temporary disk area and
01674  * load up one class file from it.
01675  *
01676  * If a valid JAR file is read, return pointer to memory area containing
01677  * the JAva class image of the startup class that was specified in Jar
01678  * Manifest file.  In the future, all classes in the JAR file will
01679  * be available for loading  from the temporary disk area via
01680  * @b CLASSPATH.
01681  *
01682  */
01683 u1 *classfile_readjarfile(rchar *filename)
01684 {
01685     struct stat statbfr;
01686 
01687     rchar *jarparm = HEAP_GET_DATA(JVMCFG_SCRIPT_MAX, rfalse);
01688 
01689     rchar *pwd = HEAP_GET_DATA(JVMCFG_SCRIPT_MAX, rfalse);
01690 
01691     rchar *jarscript = HEAP_GET_DATA(JVMCFG_SCRIPT_MAX, rfalse);
01692 
01693     /*! @todo  Need a version of this that works on MS Windows */
01694 
01695     /*
01696      * Make sure to have an @e absolute path name to @b filename
01697      * since it may be relative and the @c @b jar command
01698      * used @c @b chdir
01699      */
01700     if (JVMCFG_PATHNAME_DELIMITER_CHAR == filename[0])
01701     {
01702         strcpy(jarparm, filename);
01703     }
01704     else
01705     {
01706         /*!
01707          * @todo  Check `pwd` overflow and @link #rnull rnull@endlink
01708          *        returned
01709          */
01710         getwd(pwd);
01711 
01712         sprintfLocal(jarparm,
01713                      "%s%c%s",
01714                      pwd,
01715                      JVMCFG_PATHNAME_DELIMITER_CHAR,
01716                      filename);
01717     }
01718 
01719     /* Convert input parm to internal form, append suffix */
01720 
01721     /*
01722      * Build up JAR command using internal class name w/suffix.  Make
01723      * @e sure all files are writeable for final <code>rm -rf<code>.
01724      */
01725     sprintfLocal(jarscript,
01726                  JVMCFG_JARFILE_MANIFEST_EXTRACT_SCRIPT,
01727                  tmparea_get(),
01728                  pjvm->java_home,
01729                  jarparm);
01730 
01731     int rc = system(jarscript);
01732 
01733     if (0 != rc)
01734     {
01735         sysErrMsg("classfile_readjarfile",
01736                   "Cannot extract data from JAR file %s",
01737                   jarparm);
01738         exit_jvm(EXIT_CLASSPATH_JAR);
01739 /*NOTREACHED*/
01740     }
01741 
01742     /* Verify extraction of manifest file */
01743     sprintfLocal(jarscript, /* Reuse unneeded buffer */
01744                  "%s%c%s",
01745                  tmparea_get(),
01746                  JVMCFG_PATHNAME_DELIMITER_CHAR,
01747                  JVMCFG_JARFILE_MANIFEST_FILENAME);
01748 
01749     rc = stat(jarscript, &statbfr);
01750 
01751 
01752     /* Read manifest file and locate starting class name */
01753     rchar *mnfstartclass = manifest_get_main(jarscript);
01754 
01755     if (rnull == mnfstartclass)
01756     {
01757         sysErrMsg("classfile_readjarfile",
01758                   "Cannot locate start class in JAR file %s",
01759                   jarparm);
01760         exit_jvm(EXIT_CLASSPATH_JAR);
01761 /*NOTREACHED*/
01762     }
01763 
01764     /* Reuse unneeded bfr w/ descriptive name */
01765     rchar *start_class_tmpfile = pwd;
01766     
01767     /* Verify existence of start class in JAR file */
01768     sprintfLocal(start_class_tmpfile,
01769                  "%s%c",
01770                  tmparea_get(),
01771                  JVMCFG_PATHNAME_DELIMITER_CHAR);
01772 
01773     int dirlen = strlen(start_class_tmpfile);
01774     strcat(pwd, mnfstartclass);
01775 
01776     (rvoid) classpath_external2internal_classname_inplace(&pwd[dirlen]);
01777 
01778     int alllen = strlen(start_class_tmpfile);
01779     start_class_tmpfile[alllen] = JVMCFG_EXTENSION_DELIMITER_CHAR;
01780     start_class_tmpfile[alllen + 1] = '\0';
01781     strcat(pwd, CLASSFILE_EXTENSION_DEFAULT);
01782 
01783     rc = stat(start_class_tmpfile, &statbfr);
01784 
01785     /* Complain if class in manifest was not found in JAR file */
01786     if (0 != rc)
01787     {
01788         sysErrMsg("classfile_readjarfile",
01789            "Cannot locate start class '%s' in manifest for JAR file %s",
01790                   mnfstartclass,
01791                   jarparm);
01792 
01793         HEAP_FREE_DATA(mnfstartclass);
01794         HEAP_FREE_DATA(jarparm);
01795         HEAP_FREE_DATA(start_class_tmpfile);
01796         HEAP_FREE_DATA(jarscript);
01797 
01798         exit_jvm(EXIT_CLASSPATH_JAR);
01799     }
01800 
01801     /* Clean up for return */
01802     HEAP_FREE_DATA(jarparm);
01803     HEAP_FREE_DATA(mnfstartclass);
01804     HEAP_FREE_DATA(jarscript);
01805 
01806     /*
01807      * If starting class file was extracted, report result
01808      * in heap-allocated bfr
01809      */
01810 
01811     rvoid *pvrc = classfile_readclassfile(start_class_tmpfile);
01812 
01813     HEAP_FREE_DATA(start_class_tmpfile);
01814 
01815     return(pvrc);
01816 
01817 } /* END of classfile_readjarfile() */
01818 
01819 /*@} */ /* End of grouped definitions */
01820 
01821 
01822 /* EOF */
01823 

Generated on Fri Sep 30 18:49:00 2005 by  doxygen 1.4.4