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 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"
35 #include "java-tree.h"
44 /* DOS brain-damage */
46 #define O_BINARY 0 /* MS-DOS brain-damage */
50 jcf_unexpected_eof (JCF
*jcf
, int count ATTRIBUTE_UNUSED
)
53 fprintf (stderr
, "Premature end of .class file %s.\n", jcf
->filename
);
55 fprintf (stderr
, "Premature end of .class file <stdin>.\n");
60 jcf_trim_old_input (JCF
*jcf
)
62 int count
= jcf
->read_ptr
- jcf
->buffer
;
65 memmove (jcf
->buffer
, jcf
->read_ptr
, jcf
->read_end
- jcf
->read_ptr
);
66 jcf
->read_ptr
-= count
;
67 jcf
->read_end
-= count
;
72 jcf_filbuf_from_stdio (JCF
*jcf
, int count
)
74 FILE *file
= (FILE*) (jcf
->read_state
);
75 if (count
> jcf
->buffer_end
- jcf
->read_ptr
)
77 JCF_u4 old_read_ptr
= jcf
->read_ptr
- jcf
->buffer
;
78 JCF_u4 old_read_end
= jcf
->read_end
- jcf
->buffer
;
79 JCF_u4 old_size
= jcf
->buffer_end
- jcf
->buffer
;
80 JCF_u4 new_size
= (old_size
== 0 ? 2000 : 2 * old_size
) + count
;
81 unsigned char *new_buffer
82 = jcf
->buffer
== NULL
? XNEWVAR (unsigned char, new_size
)
83 : XRESIZEVAR (unsigned char, jcf
->buffer
, new_size
);
84 jcf
->buffer
= new_buffer
;
85 jcf
->buffer_end
= new_buffer
+ new_size
;
86 jcf
->read_ptr
= new_buffer
+ old_read_ptr
;
87 jcf
->read_end
= new_buffer
+ old_read_end
;
89 count
-= jcf
->read_end
- jcf
->read_ptr
;
92 if ((int) fread (jcf
->read_end
, 1, count
, file
) != count
)
93 jcf_unexpected_eof (jcf
, count
);
94 jcf
->read_end
+= count
;
100 struct ZipFile
*SeenZipFiles
= NULL
;
102 /* Open a zip file with the given name, and cache directory and file
103 descriptor. If the file is missing, treat it as an empty archive.
104 Return NULL if the .zip file is malformed.
108 opendir_in_zip (const char *zipfile
, int is_system
)
110 struct ZipFile
* zipf
;
113 for (zipf
= SeenZipFiles
; zipf
!= NULL
; zipf
= zipf
->next
)
115 if (strcmp (zipf
->name
, zipfile
) == 0)
119 zipf
= XNEWVAR (struct ZipFile
, sizeof (struct ZipFile
) + strlen (zipfile
) + 1);
120 zipf
->next
= SeenZipFiles
;
121 zipf
->name
= (char*)(zipf
+1);
122 strcpy (zipf
->name
, zipfile
);
123 fd
= open (zipfile
, O_RDONLY
| O_BINARY
);
127 /* A missing zip file is not considered an error.
128 We may want to re-consider that. FIXME. */
131 zipf
->central_directory
= NULL
;
135 jcf_dependency_add_file (zipfile
, is_system
);
136 if (read (fd
, magic
, 4) != 4 || GET_u4 (magic
) != (JCF_u4
)ZIPMAGIC
)
142 lseek (fd
, 0L, SEEK_SET
);
143 if (read_zip_archive (zipf
) != 0)
156 0: OK - zipmember found.
158 -2: Malformed archive.
162 open_in_zip (JCF
*jcf
, const char *zipfile
, const char *zipmember
,
167 ZipFile
*zipf
= opendir_in_zip (zipfile
, is_system
);
175 len
= strlen (zipmember
);
177 zipd
= (struct ZipDirectory
*) zipf
->central_directory
;
178 for (i
= 0; i
< zipf
->count
; i
++, zipd
= ZIPDIR_NEXT (zipd
))
180 if (len
== zipd
->filename_length
&&
181 strncmp (ZIPDIR_FILENAME (zipd
), zipmember
, len
) == 0)
185 jcf
->filename
= xstrdup (zipfile
);
186 jcf
->classname
= xstrdup (zipmember
);
187 return read_zip_member(jcf
, zipd
, zipf
);
193 /* Read data from zip archive member. */
196 read_zip_member (JCF
*jcf
, ZipDirectory
*zipd
, ZipFile
*zipf
)
198 jcf
->filbuf
= jcf_unexpected_eof
;
201 if (zipd
->compression_method
== Z_NO_COMPRESSION
)
203 jcf
->buffer
= XNEWVEC (unsigned char, zipd
->size
);
204 jcf
->buffer_end
= jcf
->buffer
+ zipd
->size
;
205 jcf
->read_ptr
= jcf
->buffer
;
206 jcf
->read_end
= jcf
->buffer_end
;
207 if (lseek (zipf
->fd
, zipd
->filestart
, 0) < 0
208 || read (zipf
->fd
, jcf
->buffer
, zipd
->size
) != (long) zipd
->size
)
214 z_stream d_stream
; /* decompression stream */
215 d_stream
.zalloc
= (alloc_func
) 0;
216 d_stream
.zfree
= (free_func
) 0;
217 d_stream
.opaque
= (voidpf
) 0;
219 jcf
->buffer
= XNEWVEC (unsigned char, zipd
->uncompressed_size
);
220 d_stream
.next_out
= jcf
->buffer
;
221 d_stream
.avail_out
= zipd
->uncompressed_size
;
222 jcf
->buffer_end
= jcf
->buffer
+ zipd
->uncompressed_size
;
223 jcf
->read_ptr
= jcf
->buffer
;
224 jcf
->read_end
= jcf
->buffer_end
;
225 buffer
= XNEWVEC (char, zipd
->size
);
226 d_stream
.next_in
= (unsigned char *) buffer
;
227 d_stream
.avail_in
= zipd
->size
;
228 if (lseek (zipf
->fd
, zipd
->filestart
, 0) < 0
229 || read (zipf
->fd
, buffer
, zipd
->size
) != (long) zipd
->size
)
231 /* Handle NO_HEADER using undocumented zlib feature.
232 This is a very common hack. */
233 inflateInit2 (&d_stream
, -MAX_WBITS
);
234 inflate (&d_stream
, Z_NO_FLUSH
);
235 inflateEnd (&d_stream
);
243 open_class (const char *filename
, JCF
*jcf
, int fd
, const char *dep_name
)
247 struct stat stat_buf
;
248 if (fstat (fd
, &stat_buf
) != 0
249 || ! S_ISREG (stat_buf
.st_mode
))
251 perror ("Could not figure length of .class file");
254 if (dep_name
!= NULL
)
255 jcf_dependency_add_file (dep_name
, 0);
257 jcf
->buffer
= XNEWVEC (unsigned char, stat_buf
.st_size
);
258 jcf
->buffer_end
= jcf
->buffer
+ stat_buf
.st_size
;
259 jcf
->read_ptr
= jcf
->buffer
;
260 jcf
->read_end
= jcf
->buffer_end
;
261 jcf
->read_state
= NULL
;
262 jcf
->filename
= xstrdup (filename
);
263 if (read (fd
, jcf
->buffer
, stat_buf
.st_size
) != stat_buf
.st_size
)
265 perror ("Failed to read .class file");
269 jcf
->filbuf
= jcf_unexpected_eof
;
278 find_classfile (char *filename
, JCF
*jcf
, const char *dep_name
)
280 int fd
= open (filename
, O_RDONLY
| O_BINARY
);
283 return open_class (filename
, jcf
, fd
, dep_name
);
288 /* A comparison function (as for qsort) that compares KEY (a char *
289 giving the basename of a file) with the name stored in ENTRY (a
293 compare_path (const void *key
, const void *entry
)
295 return strcmp ((const char *) key
,
296 (*((const struct dirent
*const*) entry
))->d_name
);
299 /* Returns nonzero if ENTRY names a .java or .class file. */
302 java_or_class_file (const struct dirent
*entry
)
304 const char *base
= lbasename (entry
->d_name
);
305 return (fnmatch ("*.java", base
, 0) == 0 ||
306 fnmatch ("*.class", base
, 0) == 0);
309 /* Information about the files present in a particular directory. */
310 typedef struct memoized_dirlist_entry
312 /* The name of the directory. */
314 /* The number of .java and .class files present, or -1 if we could
315 not, for some reason, obtain the list. */
317 /* The .java and .class files in the directory, in alphabetical
319 struct dirent
**files
;
320 } memoized_dirlist_entry
;
322 /* A hash function for a memoized_dirlist_entry. */
324 memoized_dirlist_hash (const void *entry
)
326 const memoized_dirlist_entry
*mde
= (const memoized_dirlist_entry
*) entry
;
327 return htab_hash_string (mde
->dir
);
330 /* Returns true if ENTRY (a memoized_dirlist_entry *) corresponds to
331 the directory given by KEY (a char *) giving the directory
335 memoized_dirlist_lookup_eq (const void *entry
, const void *key
)
337 return strcmp ((const char *) key
,
338 ((const memoized_dirlist_entry
*) entry
)->dir
) == 0;
341 /* A hash table mapping directory names to the lists of .java and
342 .class files in that directory. */
344 static htab_t memoized_dirlists
;
348 /* Like stat, but avoids actually making the stat system call if we
349 know that it cannot succeed. FILENAME and BUF are as for stat. */
352 caching_stat (char *filename
, struct stat
*buf
)
358 memoized_dirlist_entry
*dent
;
360 struct memoized_dirlist_entry temp
;
362 /* If the hashtable has not already been created, create it now. */
363 if (!memoized_dirlists
)
364 memoized_dirlists
= htab_create (37,
365 memoized_dirlist_hash
,
366 memoized_dirlist_lookup_eq
,
369 /* Get the name of the directory. */
370 sep
= strrchr (filename
, DIR_SEPARATOR
);
371 #ifdef DIR_SEPARATOR_2
373 sep
= strrchr (filename
, DIR_SEPARATOR_2
);
384 /* Obtain the entry for this directory from the hash table. This
385 approach is ok since we know that the hash function only looks at
386 the directory name. */
390 slot
= htab_find_slot (memoized_dirlists
, &temp
, INSERT
);
393 /* We have not already scanned this directory; scan it now. */
394 dent
= XNEW (memoized_dirlist_entry
);
395 dent
->dir
= xstrdup (filename
);
396 /* Unfortunately, scandir is not fully standardized. In
397 particular, the type of the function pointer passed as the
398 third argument sometimes takes a "const struct dirent *"
399 parameter, and sometimes just a "struct dirent *". We cast
400 to (void *) and use __extension__ so that either way it is
401 quietly accepted. FIXME: scandir is not in POSIX. */
402 dent
->num_files
= __extension__
scandir (filename
, &dent
->files
,
403 (void *) java_or_class_file
,
408 dent
= *((memoized_dirlist_entry
**) slot
);
410 /* Put the separator back. */
414 /* If the file is not in the list, there is no need to stat it; it
416 if (dent
->num_files
!= -1
417 && !bsearch (base
, dent
->files
, dent
->num_files
,
418 sizeof (struct dirent
*), compare_path
))
422 return stat (filename
, buf
);
425 /* Returns 1 if the CLASSNAME (really a char *) matches the name
426 stored in TABLE_ENTRY (also a char *). */
429 memoized_class_lookup_eq (const void *table_entry
, const void *classname
)
431 return strcmp ((const char *)classname
, (const char *)table_entry
) == 0;
434 /* A hash table keeping track of class names that were not found
435 during class lookup. (There is no need to cache the values
436 associated with names that were found; they are saved in
437 IDENTIFIER_CLASS_VALUE.) */
438 static htab_t memoized_class_lookups
;
440 /* Returns a freshly malloc'd string with the fully qualified pathname
441 of the .class file for the class CLASSNAME. CLASSNAME must be
442 allocated in permanent storage; this function may retain a pointer
443 to it. Returns NULL on failure. If JCF != NULL, it is suitably
444 initialized. SOURCE_OK is true if we should also look for .java
448 find_class (const char *classname
, int classname_length
, JCF
*jcf
)
451 int i
, k
, klass
= -1;
452 struct stat class_buf
;
459 /* Create the hash table, if it does not already exist. */
460 if (!memoized_class_lookups
)
461 memoized_class_lookups
= htab_create (37,
463 memoized_class_lookup_eq
,
466 /* Loop for this class in the hashtable. If it is present, we've
467 already looked for this class and failed to find it. */
468 hash
= htab_hash_string (classname
);
469 if (htab_find_with_hash (memoized_class_lookups
, classname
, hash
))
472 /* Allocate and zero out the buffer, since we don't explicitly put a
473 null pointer when we're copying it below. */
474 buflen
= jcf_path_max_len () + classname_length
+ 10;
475 buffer
= XNEWVAR (char, buflen
);
476 memset (buffer
, 0, buflen
);
478 for (entry
= jcf_path_start (); entry
!= NULL
; entry
= jcf_path_next (entry
))
480 const char *path_name
= jcf_path_name (entry
);
485 strcpy (buffer
, path_name
);
488 /* This is right because we know that `.zip' entries will have a
489 trailing slash. See jcf-path.c. */
492 for (k
= 0; k
< classname_length
; k
++, i
++)
494 char ch
= classname
[k
];
495 buffer
[i
] = ch
== '.' ? '/' : ch
;
497 strcpy (buffer
+i
, ".class");
499 if (jcf_path_is_zipfile (entry
))
503 buffer
[dir_len
] = '\0';
504 SOURCE_FRONTEND_DEBUG
505 (("Trying [...%s]:%s",
506 &buffer
[dir_len
-(dir_len
> 15 ? 15 : dir_len
)],
510 err_code
= open_in_zip (jcf
, buffer
, buffer
+dir_len
+1,
511 jcf_path_is_system (entry
));
514 /* Should we check if .zip is out-of-date wrt .java? */
515 buffer
[dir_len
] = '(';
516 strcpy (buffer
+i
, ".class)");
524 klass
= caching_stat(buffer
, &class_buf
);
531 SOURCE_FRONTEND_DEBUG ((stderr
, "[Class selected: %s]\n",
532 classname
+classname_length
-
533 (classname_length
<= 30 ?
534 classname_length
: 30)));
535 fd
= JCF_OPEN_EXACT_CASE (buffer
, O_RDONLY
| O_BINARY
);
542 /* Remember that this class could not be found so that we do not
543 have to look again. */
544 *(const void **)htab_find_slot_with_hash (memoized_class_lookups
,
545 classname
, hash
, INSERT
)
551 const char *const tmp
= open_class (buffer
, jcf
, fd
, dep_file
);
552 jcf
->classname
= xstrdup (classname
);
558 jcf_print_char (FILE *stream
, int ch
)
565 fprintf (stream
, "\\%c", ch
);
568 fprintf (stream
, "\\n");
571 fprintf (stream
, "\\t");
574 fprintf (stream
, "\\r");
577 if (ch
>= ' ' && ch
< 127)
580 fprintf (stream
, "\\%03x", ch
);
582 fprintf (stream
, "\\u%04x", ch
);
586 /* Print UTF8 string at STR of length LENGTH bytes to STREAM. */
589 jcf_print_utf8 (FILE *stream
, const unsigned char *str
, int length
)
591 const unsigned char * limit
= str
+ length
;
594 int ch
= UTF8_GET (str
, limit
);
597 fprintf (stream
, "\\<invalid>");
600 jcf_print_char (stream
, ch
);
604 /* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */
607 jcf_print_utf8_replace (FILE *stream
, const unsigned char *str
, int length
,
608 int in_char
, int out_char
)
610 const unsigned char *limit
= str
+ length
;
613 int ch
= UTF8_GET (str
, limit
);
616 fprintf (stream
, "\\<invalid>");
619 jcf_print_char (stream
, ch
== in_char
? out_char
: ch
);
623 /* Check that all the cross-references in the constant pool are
624 valid. Returns 0 on success.
625 Otherwise, returns the index of the (first) invalid entry.
626 Only checks internal consistency, but does not check that
627 any classes, fields, or methods are valid.*/
630 verify_constant_pool (JCF
*jcf
)
633 for (i
= 1; i
< JPOOL_SIZE (jcf
); i
++)
635 switch (JPOOL_TAG (jcf
, i
))
637 case CONSTANT_NameAndType
:
638 n
= JPOOL_USHORT2 (jcf
, i
);
639 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
640 || JPOOL_TAG (jcf
, n
) != CONSTANT_Utf8
)
642 /* ... fall through ... */
644 case CONSTANT_String
:
645 n
= JPOOL_USHORT1 (jcf
, i
);
646 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
647 || JPOOL_TAG (jcf
, n
) != CONSTANT_Utf8
)
650 case CONSTANT_Fieldref
:
651 case CONSTANT_Methodref
:
652 case CONSTANT_InterfaceMethodref
:
653 n
= JPOOL_USHORT1 (jcf
, i
);
654 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
655 || JPOOL_TAG (jcf
, n
) != CONSTANT_Class
)
657 n
= JPOOL_USHORT2 (jcf
, i
);
658 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
659 || JPOOL_TAG (jcf
, n
) != CONSTANT_NameAndType
)
663 case CONSTANT_Double
:
667 case CONSTANT_Integer
:
669 case CONSTANT_Unicode
:
679 format_uint (char *buffer
, uint64 value
, int base
)
681 #define WRITE_BUF_SIZE (4 + sizeof(uint64) * 8)
682 char buf
[WRITE_BUF_SIZE
];
683 char *buf_ptr
= buf
+WRITE_BUF_SIZE
; /* End of buf. */
687 /* Now do the actual conversion, placing the result at the *end* of buf. */
688 /* Note this code does not pretend to be optimized. */
690 int digit
= value
% base
;
691 static const char digit_chars
[] = "0123456789abcdefghijklmnopqrstuvwxyz";
692 *--buf_ptr
= digit_chars
[digit
];
694 } while (value
!= 0);
696 chars_written
= buf
+WRITE_BUF_SIZE
- buf_ptr
;
697 for (i
= 0; i
< chars_written
; i
++)
698 buffer
[i
] = *buf_ptr
++;
703 format_int (char *buffer
, jlong value
, int base
)
708 abs_value
= -(uint64
)value
;
712 abs_value
= (uint64
) value
;
713 format_uint (buffer
, abs_value
, base
);