📄 file.c
字号:
/* * @(#)file.c 1.40 02/09/27 * * Copyright 1995-1998 by Sun Microsystems, Inc., * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A. * All rights reserved. * * This software is the confidential and proprietary information * of Sun Microsystems, Inc. ("Confidential Information"). You * shall not disclose such Confidential Information and shall use * it only in accordance with the terms of the license agreement * you entered into with Sun. * Use is subject to license terms. *//*========================================================================= * SYSTEM: Verifier * SUBSYSTEM: Operations on class files. * FILE: file.c * OVERVIEW: Routines for outputing the internal class file. * * AUTHOR(s): Original implementation, * Sheng Liang, Sun Microsystems, Inc. * * Modifications for JAR support, debug support, CLDC compliance, * Tasneem Sayeed, Sun Microsystems * * Added support for inner classes, fixes for stack maps, etc. * Frank Yellin, Sun Microsystems *=======================================================================*//*========================================================================= * Include files *=======================================================================*/#include <sys/types.h>#include <fcntl.h>#include <sys/stat.h>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <stddef.h>#ifdef UNIX#include <unistd.h>#endif#include <oobj.h>#include <jar.h>#include <tree.h>#include <sys_api.h>#include <convert_md.h>#ifdef WIN32#include <direct.h>#endif/* initialize opnames[256]; */#include <opcodes.init>/*========================================================================= * Globals and extern declarations *=======================================================================*/extern char *progname;extern bool_t JARfile;extern bool_t tmpDirExists;char *current_class_name = NULL;bool_t stack_map_on = TRUE;static char *PrintableClassname(char *classname);extern char tmp_dir[32];char *output_dir = "output";unsigned char *class_buf;int class_buf_size = 0;int class_index;int last_not_utf8_index;#define INIT_CLASS_BUF_SIZE 256void ensure_capacity(int sz){ if (class_index + sz >= class_buf_size) { while (class_index + sz >= class_buf_size) { class_buf_size *= 2; } } class_buf = (unsigned char *)realloc(class_buf, class_buf_size);}void write_u1(unsigned long u1){ ensure_capacity(1); class_buf[class_index++] = (unsigned char)u1;}void write_u2(unsigned long u2){ ensure_capacity(2); class_buf[class_index++] = (unsigned char)(u2 >> 8); class_buf[class_index++] = (unsigned char)u2;}void write_u4(unsigned long u4){ ensure_capacity(4); class_buf[class_index++] = (unsigned char)(u4 >> 24); class_buf[class_index++] = (unsigned char)(u4 >> 16); class_buf[class_index++] = (unsigned char)(u4 >> 8); class_buf[class_index++] = (unsigned char)u4;}int new_utf8_index(ClassClass *cb, int index){ if (index > last_not_utf8_index) { return index + unhand(cb)->n_new_class_entries; } else { return index; }}unsigned long lookup_utf8(ClassClass *cb, char *utf8){ int i; cp_item_type *constant_pool = cbConstantPool(cb); int cpEntries, newEntries; unsigned char *type_table = constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type; cpEntries = cbConstantPoolCount(cb); newEntries = unhand(cb)->n_new_utf8_entries; for (i = 0; i < cpEntries; i++) { if (type_table[i] == (CONSTANT_Utf8 | CONSTANT_POOL_ENTRY_RESOLVED) && strcmp(utf8, constant_pool[i].cp) == 0) { return new_utf8_index(cb, i); } } for (i = 0; i < newEntries; i++) { if (strcmp(unhand(cb)->new_utf8_entries[i], utf8) == 0) { return i + cpEntries + unhand(cb)->n_new_class_entries; } } unhand(cb)->new_utf8_entries[newEntries] = utf8; unhand(cb)->n_new_utf8_entries = newEntries + 1; return newEntries + cpEntries + unhand(cb)->n_new_class_entries;}unsigned long lookup_class(ClassClass *cb, char *name){ int i; cp_item_type *constant_pool = cbConstantPool(cb); unsigned char *type_table = constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type; for (i = 0; i < cbConstantPoolCount(cb); i++) { if (type_table[i] == (CONSTANT_Class | CONSTANT_POOL_ENTRY_RESOLVED) && strcmp(name, cbName(constant_pool[i].clazz)) == 0) { return i; } if (type_table[i] == CONSTANT_Class && strcmp(name, constant_pool[constant_pool[i].i].cp) == 0) { return i; } } panic("class expected to be in constant pool: %s", name); return 0;}int get_last_not_utf8_index(ClassClass *cb){ int i; int result; cp_item_type *constant_pool = cbConstantPool(cb); unsigned char *type_table = constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type; for (i = 0, result = -1; i < cbConstantPoolCount(cb); i++) { if (type_table[i] != (CONSTANT_Utf8 | CONSTANT_POOL_ENTRY_RESOLVED)) { result = i; } } return result;}void write_constant_pool(ClassClass *cb){ int i, j; cp_item_type *constant_pool = cbConstantPool(cb); unsigned char *type_table = constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type; unsigned int sealedValue; last_not_utf8_index = get_last_not_utf8_index(cb); if (stack_map_on && unhand(cb)->has_stack_maps) { /* The maximum number of new utf8 entries we'll need is one * for "StackMap", plus one for each of the new class entries. * However, we bump the number to 2 in case we need to add another * entry for the SourceFile attribute. */ unhand(cb)->n_new_utf8_entries = 0; unhand(cb)->new_utf8_entries = (char **)malloc((unhand(cb)->n_new_class_entries + 2) * sizeof(char *)); /* Put sure we have all the Utf8 entries that we need, so that * we'll know the final size of the constant pool. */ lookup_utf8(cb, "StackMap"); for (i = 0; i < unhand(cb)->n_new_class_entries; i++) { lookup_utf8(cb, unhand(cb)->new_class_entries[i]); } } else { unhand(cb)->n_new_utf8_entries = 0; unhand(cb)->new_utf8_entries = NULL; unhand(cb)->n_new_class_entries = 0; if (unhand(cb)->new_class_entries != NULL) { free(unhand(cb)->new_class_entries); unhand(cb)->new_class_entries = NULL; } } /* At this, we should not add have to create any more utf8 entries. * We find the value of unhand(cb)->n_new_utf8_entries, and complain * later if this value has changed. */ sealedValue = unhand(cb)->n_new_utf8_entries; write_u2(cbConstantPoolCount(cb) + unhand(cb)->n_new_class_entries + unhand(cb)->n_new_utf8_entries); for (i = 1; i < cbConstantPoolCount(cb); i++) { write_u1(type_table[i] & CONSTANT_POOL_ENTRY_TYPEMASK); switch(type_table[i]) { case CONSTANT_Utf8 | CONSTANT_POOL_ENTRY_RESOLVED: write_u2(strlen(constant_pool[i].cp)); for (j = 0; j < (int)strlen(constant_pool[i].cp); j++) { write_u1(constant_pool[i].cp[j]); } break; case CONSTANT_Class: case CONSTANT_String: write_u2(new_utf8_index(cb, constant_pool[i].i)); break; case CONSTANT_Class | CONSTANT_POOL_ENTRY_RESOLVED: write_u2(lookup_utf8(cb, cbName(constant_pool[i].clazz))); break; case CONSTANT_Fieldref: case CONSTANT_Methodref: case CONSTANT_InterfaceMethodref: write_u2(constant_pool[i].i >> 16); write_u2(constant_pool[i].i & 0xFFFF); break; case CONSTANT_NameAndType: write_u2(new_utf8_index(cb, constant_pool[i].i >> 16)); write_u2(new_utf8_index(cb, constant_pool[i].i & 0xFFFF)); break; case CONSTANT_Integer | CONSTANT_POOL_ENTRY_RESOLVED: case CONSTANT_Float | CONSTANT_POOL_ENTRY_RESOLVED: write_u4(constant_pool[i].i); break; case CONSTANT_Long | CONSTANT_POOL_ENTRY_RESOLVED: case CONSTANT_Double | CONSTANT_POOL_ENTRY_RESOLVED: write_u4(constant_pool[i].i); write_u4(constant_pool[i + 1].i); i++; break; default: panic("bad constant pool entry type: %d", type_table[i]); } if (i == last_not_utf8_index) { /* Write extra CONSTANT_Class entries created by the stackmaps */ for (j = 0; j < unhand(cb)->n_new_class_entries; j++) { char *classname = unhand(cb)->new_class_entries[j]; write_u1(CONSTANT_Class); write_u2(lookup_utf8(cb, classname)); } } } /* Write extra CONSTANT_Utf8 entries created by the stackmaps */ for (i = 0; i < unhand(cb)->n_new_utf8_entries; i++) { char *string = unhand(cb)->new_utf8_entries[i]; int length = strlen(string); write_u1(CONSTANT_Utf8); write_u2(length); for (j = 0; j < length; j++) { write_u1(string[j]); } } if (sealedValue != (unsigned int) unhand(cb)->n_new_utf8_entries) { panic("New utf8 entries have been added???"); }}void write_interfaces(ClassClass *cb){ int i; write_u2(cbImplementsCount(cb)); for (i = 0; i < cbImplementsCount(cb); i++) { write_u2(cbImplements(cb)[i]); }}void write_fields(ClassClass *cb){ int i; write_u2(cbFieldsCount(cb)); for (i = 0; i < cbFieldsCount(cb); i++) { struct fieldblock *fb = &cbFields(cb)[i]; write_u2(fb->access & ACC_WRITTEN_FLAGS); write_u2(lookup_utf8(cb, fb->name)); write_u2(lookup_utf8(cb, fb->signature)); /* Number of attributes we're about to output. * Each item in the following sum is a boolean that returns 1 or 0. */ write_u2( ((fb->access & ACC_VALKNOWN) != 0) + (fb->synthetic != 0) + (fb->deprecated != 0)); if (fb->access & ACC_VALKNOWN) { write_u2(lookup_utf8(cb, "ConstantValue")); /* Attribute name */ write_u4(2); /* Length */ write_u2(fb->u.offset); } if (fb->deprecated) { write_u2(lookup_utf8(cb, "Deprecated")); /* Attribute name */ write_u4(0); /* Length */ } if (fb->synthetic) { write_u2(lookup_utf8(cb, "Synthetic")); /* Attribute name */ write_u4(0); /* Length */ } }}void write_stack_map(int nentries, struct map_entry *entries){ int i; for (i = 0; i < nentries; i++) { struct map_entry *entry = entries + i; write_u1(entry->type); if (entry->type == CF_ITEM_NewObject) { write_u2(entry->info); } if (entry->type == CF_ITEM_Object) { /* This is ugly * Non-negative entries refer to classes * in the original constant pool. * Negative entries, ~(entry->info) is the entry's index * in the list of additional constant pool entries. */ if (entry->info >= 0) { write_u2(entry->info); } else { write_u2(last_not_utf8_index + 1 + ~entry->info); } } }}int stack_map_size(int nentries, struct map_entry *entries){ int i; int result = 0; for (i = 0; i < nentries; i++) { struct map_entry *entry = entries + i; result += 1; if (entry->type == CF_ITEM_Object || entry->type == CF_ITEM_NewObject) { result += 2; } } return result;}void write_methods(ClassClass *cb){ int i; write_u2(cbMethodsCount(cb)); for (i = 0; i < cbMethodsCount(cb); i++) { struct methodblock *mb = &cbMethods(cb)[i]; write_u2(mb->fb.access & ACC_WRITTEN_FLAGS); write_u2(lookup_utf8(cb, mb->fb.name)); write_u2(lookup_utf8(cb, mb->fb.signature));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -