1 /* Utility routines for finding and reading Java(TM) .class files.
2 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005,
3 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>.
21 Java and all Java-based marks are trademarks or registered trademarks
22 of Sun Microsystems, Inc. in the United States and other countries.
23 The Free Software Foundation is independent of Sun Microsystems, Inc. */
25 /* Written by Per Bothner <bothner@cygnus.com>, February 1996. */
29 #include "coretypes.h"
33 #include "java-tree.h"
39 /* DOS brain-damage */
41 #define O_BINARY 0 /* MS-DOS brain-damage */
45 jcf_unexpected_eof (JCF
*jcf
, int count ATTRIBUTE_UNUSED
)
48 fprintf (stderr
, "Premature end of .class file %s.\n", jcf
->filename
);
50 fprintf (stderr
, "Premature end of .class file <stdin>.\n");
55 jcf_trim_old_input (JCF
*jcf
)
57 int count
= jcf
->read_ptr
- jcf
->buffer
;
60 memmove (jcf
->buffer
, jcf
->read_ptr
, jcf
->read_end
- jcf
->read_ptr
);
61 jcf
->read_ptr
-= count
;
62 jcf
->read_end
-= count
;
67 jcf_filbuf_from_stdio (JCF
*jcf
, int count
)
69 FILE *file
= (FILE*) (jcf
->read_state
);
70 if (count
> jcf
->buffer_end
- jcf
->read_ptr
)
72 JCF_u4 old_read_ptr
= jcf
->read_ptr
- jcf
->buffer
;
73 JCF_u4 old_read_end
= jcf
->read_end
- jcf
->buffer
;
74 JCF_u4 old_size
= jcf
->buffer_end
- jcf
->buffer
;
75 JCF_u4 new_size
= (old_size
== 0 ? 2000 : 2 * old_size
) + count
;
76 unsigned char *new_buffer
77 = jcf
->buffer
== NULL
? XNEWVAR (unsigned char, new_size
)
78 : XRESIZEVAR (unsigned char, jcf
->buffer
, new_size
);
79 jcf
->buffer
= new_buffer
;
80 jcf
->buffer_end
= new_buffer
+ new_size
;
81 jcf
->read_ptr
= new_buffer
+ old_read_ptr
;
82 jcf
->read_end
= new_buffer
+ old_read_end
;
84 count
-= jcf
->read_end
- jcf
->read_ptr
;
87 if ((int) fread (jcf
->read_end
, 1, count
, file
) != count
)
88 jcf_unexpected_eof (jcf
, count
);
89 jcf
->read_end
+= count
;
95 struct ZipFile
*SeenZipFiles
= NULL
;
97 /* Open a zip file with the given name, and cache directory and file
98 descriptor. If the file is missing, treat it as an empty archive.
99 Return NULL if the .zip file is malformed.
103 opendir_in_zip (const char *zipfile
, int is_system
)
105 struct ZipFile
* zipf
;
108 for (zipf
= SeenZipFiles
; zipf
!= NULL
; zipf
= zipf
->next
)
110 if (strcmp (zipf
->name
, zipfile
) == 0)
114 zipf
= XNEWVAR (struct ZipFile
, sizeof (struct ZipFile
) + strlen (zipfile
) + 1);
115 zipf
->next
= SeenZipFiles
;
116 zipf
->name
= (char*)(zipf
+1);
117 strcpy (zipf
->name
, zipfile
);
118 fd
= open (zipfile
, O_RDONLY
| O_BINARY
);
122 /* A missing zip file is not considered an error.
123 We may want to re-consider that. FIXME. */
126 zipf
->central_directory
= NULL
;
130 jcf_dependency_add_file (zipfile
, is_system
);
131 if (read (fd
, magic
, 4) != 4 || GET_u4 (magic
) != (JCF_u4
)ZIPMAGIC
)
137 lseek (fd
, 0L, SEEK_SET
);
138 if (read_zip_archive (zipf
) != 0)
151 0: OK - zipmember found.
153 -2: Malformed archive.
157 open_in_zip (JCF
*jcf
, const char *zipfile
, const char *zipmember
,
162 ZipFile
*zipf
= opendir_in_zip (zipfile
, is_system
);
170 len
= strlen (zipmember
);
172 zipd
= (struct ZipDirectory
*) zipf
->central_directory
;
173 for (i
= 0; i
< zipf
->count
; i
++, zipd
= ZIPDIR_NEXT (zipd
))
175 if (len
== zipd
->filename_length
&&
176 strncmp (ZIPDIR_FILENAME (zipd
), zipmember
, len
) == 0)
180 jcf
->filename
= xstrdup (zipfile
);
181 jcf
->classname
= xstrdup (zipmember
);
182 return read_zip_member(jcf
, zipd
, zipf
);
188 /* Read data from zip archive member. */
191 read_zip_member (JCF
*jcf
, ZipDirectory
*zipd
, ZipFile
*zipf
)
193 jcf
->filbuf
= jcf_unexpected_eof
;
196 if (zipd
->compression_method
== Z_NO_COMPRESSION
)
198 jcf
->buffer
= XNEWVEC (unsigned char, zipd
->size
);
199 jcf
->buffer_end
= jcf
->buffer
+ zipd
->size
;
200 jcf
->read_ptr
= jcf
->buffer
;
201 jcf
->read_end
= jcf
->buffer_end
;
202 if (lseek (zipf
->fd
, zipd
->filestart
, 0) < 0
203 || read (zipf
->fd
, jcf
->buffer
, zipd
->size
) != (long) zipd
->size
)
209 z_stream d_stream
; /* decompression stream */
210 d_stream
.zalloc
= (alloc_func
) 0;
211 d_stream
.zfree
= (free_func
) 0;
212 d_stream
.opaque
= (voidpf
) 0;
214 jcf
->buffer
= XNEWVEC (unsigned char, zipd
->uncompressed_size
);
215 d_stream
.next_out
= jcf
->buffer
;
216 d_stream
.avail_out
= zipd
->uncompressed_size
;
217 jcf
->buffer_end
= jcf
->buffer
+ zipd
->uncompressed_size
;
218 jcf
->read_ptr
= jcf
->buffer
;
219 jcf
->read_end
= jcf
->buffer_end
;
220 buffer
= XNEWVEC (char, zipd
->size
);
221 d_stream
.next_in
= (unsigned char *) buffer
;
222 d_stream
.avail_in
= zipd
->size
;
223 if (lseek (zipf
->fd
, zipd
->filestart
, 0) < 0
224 || read (zipf
->fd
, buffer
, zipd
->size
) != (long) zipd
->size
)
226 /* Handle NO_HEADER using undocumented zlib feature.
227 This is a very common hack. */
228 inflateInit2 (&d_stream
, -MAX_WBITS
);
229 inflate (&d_stream
, Z_NO_FLUSH
);
230 inflateEnd (&d_stream
);
238 open_class (const char *filename
, JCF
*jcf
, int fd
, const char *dep_name
)
242 struct stat stat_buf
;
243 if (fstat (fd
, &stat_buf
) != 0
244 || ! S_ISREG (stat_buf
.st_mode
))
246 perror ("Could not figure length of .class file");
249 if (dep_name
!= NULL
)
250 jcf_dependency_add_file (dep_name
, 0);
252 jcf
->buffer
= XNEWVEC (unsigned char, stat_buf
.st_size
);
253 jcf
->buffer_end
= jcf
->buffer
+ stat_buf
.st_size
;
254 jcf
->read_ptr
= jcf
->buffer
;
255 jcf
->read_end
= jcf
->buffer_end
;
256 jcf
->read_state
= NULL
;
257 jcf
->filename
= xstrdup (filename
);
258 if (read (fd
, jcf
->buffer
, stat_buf
.st_size
) != stat_buf
.st_size
)
260 perror ("Failed to read .class file");
264 jcf
->filbuf
= jcf_unexpected_eof
;
273 find_classfile (char *filename
, JCF
*jcf
, const char *dep_name
)
275 int fd
= open (filename
, O_RDONLY
| O_BINARY
);
278 return open_class (filename
, jcf
, fd
, dep_name
);
281 /* Returns 1 if the CLASSNAME (really a char *) matches the name
282 stored in TABLE_ENTRY (also a char *). */
285 memoized_class_lookup_eq (const void *table_entry
, const void *classname
)
287 return strcmp ((const char *)classname
, (const char *)table_entry
) == 0;
290 /* A hash table keeping track of class names that were not found
291 during class lookup. (There is no need to cache the values
292 associated with names that were found; they are saved in
293 IDENTIFIER_CLASS_VALUE.) */
294 static htab_t memoized_class_lookups
;
296 /* Returns a freshly malloc'd string with the fully qualified pathname
297 of the .class file for the class CLASSNAME. CLASSNAME must be
298 allocated in permanent storage; this function may retain a pointer
299 to it. Returns NULL on failure. If JCF != NULL, it is suitably
300 initialized. SOURCE_OK is true if we should also look for .java
304 find_class (const char *classname
, int classname_length
, JCF
*jcf
)
307 int i
, k
, klass
= -1;
308 struct stat class_buf
;
315 /* Create the hash table, if it does not already exist. */
316 if (!memoized_class_lookups
)
317 memoized_class_lookups
= htab_create (37,
319 memoized_class_lookup_eq
,
322 /* Loop for this class in the hashtable. If it is present, we've
323 already looked for this class and failed to find it. */
324 hash
= htab_hash_string (classname
);
325 if (htab_find_with_hash (memoized_class_lookups
, classname
, hash
))
328 /* Allocate and zero out the buffer, since we don't explicitly put a
329 null pointer when we're copying it below. */
330 buflen
= jcf_path_max_len () + classname_length
+ 10;
331 buffer
= XNEWVAR (char, buflen
);
332 memset (buffer
, 0, buflen
);
334 for (entry
= jcf_path_start (); entry
!= NULL
; entry
= jcf_path_next (entry
))
336 const char *path_name
= jcf_path_name (entry
);
341 strcpy (buffer
, path_name
);
344 /* This is right because we know that `.zip' entries will have a
345 trailing slash. See jcf-path.c. */
348 for (k
= 0; k
< classname_length
; k
++, i
++)
350 char ch
= classname
[k
];
351 buffer
[i
] = ch
== '.' ? '/' : ch
;
353 strcpy (buffer
+i
, ".class");
355 if (jcf_path_is_zipfile (entry
))
359 buffer
[dir_len
] = '\0';
360 SOURCE_FRONTEND_DEBUG
361 (("Trying [...%s]:%s",
362 &buffer
[dir_len
-(dir_len
> 15 ? 15 : dir_len
)],
366 err_code
= open_in_zip (jcf
, buffer
, buffer
+dir_len
+1,
367 jcf_path_is_system (entry
));
370 /* Should we check if .zip is out-of-date wrt .java? */
371 buffer
[dir_len
] = '(';
372 strcpy (buffer
+i
, ".class)");
380 klass
= stat (buffer
, &class_buf
);
387 SOURCE_FRONTEND_DEBUG ((stderr
, "[Class selected: %s]\n",
388 classname
+classname_length
-
389 (classname_length
<= 30 ?
390 classname_length
: 30)));
391 fd
= JCF_OPEN_EXACT_CASE (buffer
, O_RDONLY
| O_BINARY
);
398 /* Remember that this class could not be found so that we do not
399 have to look again. */
400 *htab_find_slot_with_hash (memoized_class_lookups
, classname
, hash
, INSERT
)
401 = (void *) CONST_CAST (char *, classname
);
406 const char *const tmp
= open_class (buffer
, jcf
, fd
, dep_file
);
407 jcf
->classname
= xstrdup (classname
);
413 jcf_print_char (FILE *stream
, int ch
)
420 fprintf (stream
, "\\%c", ch
);
423 fprintf (stream
, "\\n");
426 fprintf (stream
, "\\t");
429 fprintf (stream
, "\\r");
432 if (ch
>= ' ' && ch
< 127)
435 fprintf (stream
, "\\%03x", ch
);
437 fprintf (stream
, "\\u%04x", ch
);
441 /* Print UTF8 string at STR of length LENGTH bytes to STREAM. */
444 jcf_print_utf8 (FILE *stream
, const unsigned char *str
, int length
)
446 const unsigned char * limit
= str
+ length
;
449 int ch
= UTF8_GET (str
, limit
);
452 fprintf (stream
, "\\<invalid>");
455 jcf_print_char (stream
, ch
);
459 /* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */
462 jcf_print_utf8_replace (FILE *stream
, const unsigned char *str
, int length
,
463 int in_char
, int out_char
)
465 const unsigned char *limit
= str
+ length
;
468 int ch
= UTF8_GET (str
, limit
);
471 fprintf (stream
, "\\<invalid>");
474 jcf_print_char (stream
, ch
== in_char
? out_char
: ch
);
478 /* Check that all the cross-references in the constant pool are
479 valid. Returns 0 on success.
480 Otherwise, returns the index of the (first) invalid entry.
481 Only checks internal consistency, but does not check that
482 any classes, fields, or methods are valid.*/
485 verify_constant_pool (JCF
*jcf
)
488 for (i
= 1; i
< JPOOL_SIZE (jcf
); i
++)
490 switch (JPOOL_TAG (jcf
, i
))
492 case CONSTANT_NameAndType
:
493 n
= JPOOL_USHORT2 (jcf
, i
);
494 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
495 || JPOOL_TAG (jcf
, n
) != CONSTANT_Utf8
)
497 /* ... fall through ... */
499 case CONSTANT_String
:
500 n
= JPOOL_USHORT1 (jcf
, i
);
501 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
502 || JPOOL_TAG (jcf
, n
) != CONSTANT_Utf8
)
505 case CONSTANT_Fieldref
:
506 case CONSTANT_Methodref
:
507 case CONSTANT_InterfaceMethodref
:
508 n
= JPOOL_USHORT1 (jcf
, i
);
509 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
510 || JPOOL_TAG (jcf
, n
) != CONSTANT_Class
)
512 n
= JPOOL_USHORT2 (jcf
, i
);
513 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
514 || JPOOL_TAG (jcf
, n
) != CONSTANT_NameAndType
)
518 case CONSTANT_Double
:
522 case CONSTANT_Integer
:
524 case CONSTANT_Unicode
:
534 format_uint (char *buffer
, uint64 value
, int base
)
536 #define WRITE_BUF_SIZE (4 + sizeof(uint64) * 8)
537 char buf
[WRITE_BUF_SIZE
];
538 char *buf_ptr
= buf
+WRITE_BUF_SIZE
; /* End of buf. */
542 /* Now do the actual conversion, placing the result at the *end* of buf. */
543 /* Note this code does not pretend to be optimized. */
545 int digit
= value
% base
;
546 static const char digit_chars
[] = "0123456789abcdefghijklmnopqrstuvwxyz";
547 *--buf_ptr
= digit_chars
[digit
];
549 } while (value
!= 0);
551 chars_written
= buf
+WRITE_BUF_SIZE
- buf_ptr
;
552 for (i
= 0; i
< chars_written
; i
++)
553 buffer
[i
] = *buf_ptr
++;
558 format_int (char *buffer
, jlong value
, int base
)
563 abs_value
= -(uint64
)value
;
567 abs_value
= (uint64
) value
;
568 format_uint (buffer
, abs_value
, base
);