1 /* Utility routines for finding and reading Java(TM) .class files.
2 Copyright (C) 1996-2015 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 GCC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>.
20 Java and all Java-based marks are trademarks or registered trademarks
21 of Sun Microsystems, Inc. in the United States and other countries.
22 The Free Software Foundation is independent of Sun Microsystems, Inc. */
24 /* Written by Per Bothner <bothner@cygnus.com>, February 1996. */
28 #include "coretypes.h"
35 #include "java-tree.h"
41 jcf_unexpected_eof (JCF
*jcf
, int count ATTRIBUTE_UNUSED
)
44 fprintf (stderr
, "Premature end of .class file %s.\n", jcf
->filename
);
46 fprintf (stderr
, "Premature end of .class file <stdin>.\n");
51 jcf_trim_old_input (JCF
*jcf
)
53 int count
= jcf
->read_ptr
- jcf
->buffer
;
56 memmove (jcf
->buffer
, jcf
->read_ptr
, jcf
->read_end
- jcf
->read_ptr
);
57 jcf
->read_ptr
-= count
;
58 jcf
->read_end
-= count
;
63 jcf_filbuf_from_stdio (JCF
*jcf
, int count
)
65 FILE *file
= (FILE*) (jcf
->read_state
);
66 if (count
> jcf
->buffer_end
- jcf
->read_ptr
)
68 JCF_u4 old_read_ptr
= jcf
->read_ptr
- jcf
->buffer
;
69 JCF_u4 old_read_end
= jcf
->read_end
- jcf
->buffer
;
70 JCF_u4 old_size
= jcf
->buffer_end
- jcf
->buffer
;
71 JCF_u4 new_size
= (old_size
== 0 ? 2000 : 2 * old_size
) + count
;
72 unsigned char *new_buffer
73 = jcf
->buffer
== NULL
? XNEWVAR (unsigned char, new_size
)
74 : XRESIZEVAR (unsigned char, jcf
->buffer
, new_size
);
75 jcf
->buffer
= new_buffer
;
76 jcf
->buffer_end
= new_buffer
+ new_size
;
77 jcf
->read_ptr
= new_buffer
+ old_read_ptr
;
78 jcf
->read_end
= new_buffer
+ old_read_end
;
80 count
-= jcf
->read_end
- jcf
->read_ptr
;
83 if ((int) fread (jcf
->read_end
, 1, count
, file
) != count
)
84 jcf_unexpected_eof (jcf
, count
);
85 jcf
->read_end
+= count
;
91 struct ZipFile
*SeenZipFiles
= NULL
;
93 /* Open a zip file with the given name, and cache directory and file
94 descriptor. If the file is missing, treat it as an empty archive.
95 Return NULL if the .zip file is malformed.
99 opendir_in_zip (const char *zipfile
, int is_system
)
101 struct ZipFile
* zipf
;
104 for (zipf
= SeenZipFiles
; zipf
!= NULL
; zipf
= zipf
->next
)
106 if (strcmp (zipf
->name
, zipfile
) == 0)
110 zipf
= XNEWVAR (struct ZipFile
, sizeof (struct ZipFile
) + strlen (zipfile
) + 1);
111 zipf
->next
= SeenZipFiles
;
112 zipf
->name
= (char*)(zipf
+1);
113 strcpy (zipf
->name
, zipfile
);
114 fd
= open (zipfile
, O_RDONLY
| O_BINARY
);
118 /* A missing zip file is not considered an error.
119 We may want to re-consider that. FIXME. */
122 zipf
->central_directory
= NULL
;
126 jcf_dependency_add_file (zipfile
, is_system
);
127 if (read (fd
, magic
, 4) != 4 || GET_u4 (magic
) != (JCF_u4
)ZIPMAGIC
)
133 lseek (fd
, 0L, SEEK_SET
);
134 if (read_zip_archive (zipf
) != 0)
147 0: OK - zipmember found.
149 -2: Malformed archive.
153 open_in_zip (JCF
*jcf
, const char *zipfile
, const char *zipmember
,
158 ZipFile
*zipf
= opendir_in_zip (zipfile
, is_system
);
166 len
= strlen (zipmember
);
168 zipd
= (struct ZipDirectory
*) zipf
->central_directory
;
169 for (i
= 0; i
< zipf
->count
; i
++, zipd
= ZIPDIR_NEXT (zipd
))
171 if (len
== zipd
->filename_length
&&
172 strncmp (ZIPDIR_FILENAME (zipd
), zipmember
, len
) == 0)
176 jcf
->filename
= xstrdup (zipfile
);
177 jcf
->classname
= xstrdup (zipmember
);
178 return read_zip_member(jcf
, zipd
, zipf
);
184 /* Read data from zip archive member. */
187 read_zip_member (JCF
*jcf
, ZipDirectory
*zipd
, ZipFile
*zipf
)
189 jcf
->filbuf
= jcf_unexpected_eof
;
192 if (zipd
->compression_method
== Z_NO_COMPRESSION
)
194 jcf
->buffer
= XNEWVEC (unsigned char, zipd
->size
);
195 jcf
->buffer_end
= jcf
->buffer
+ zipd
->size
;
196 jcf
->read_ptr
= jcf
->buffer
;
197 jcf
->read_end
= jcf
->buffer_end
;
198 if (lseek (zipf
->fd
, zipd
->filestart
, 0) < 0
199 || read (zipf
->fd
, jcf
->buffer
, zipd
->size
) != (long) zipd
->size
)
205 z_stream d_stream
; /* decompression stream */
206 memset (&d_stream
, 0, sizeof (d_stream
));
208 jcf
->buffer
= XNEWVEC (unsigned char, zipd
->uncompressed_size
);
209 d_stream
.next_out
= jcf
->buffer
;
210 d_stream
.avail_out
= zipd
->uncompressed_size
;
211 jcf
->buffer_end
= jcf
->buffer
+ zipd
->uncompressed_size
;
212 jcf
->read_ptr
= jcf
->buffer
;
213 jcf
->read_end
= jcf
->buffer_end
;
214 buffer
= XNEWVEC (char, zipd
->size
);
215 d_stream
.next_in
= (unsigned char *) buffer
;
216 d_stream
.avail_in
= zipd
->size
;
217 if (lseek (zipf
->fd
, zipd
->filestart
, 0) < 0
218 || read (zipf
->fd
, buffer
, zipd
->size
) != (long) zipd
->size
)
220 /* Handle NO_HEADER using undocumented zlib feature.
221 This is a very common hack. */
222 inflateInit2 (&d_stream
, -MAX_WBITS
);
223 inflate (&d_stream
, Z_NO_FLUSH
);
224 inflateEnd (&d_stream
);
232 open_class (const char *filename
, JCF
*jcf
, int fd
, const char *dep_name
)
236 struct stat stat_buf
;
237 if (fstat (fd
, &stat_buf
) != 0
238 || ! S_ISREG (stat_buf
.st_mode
))
240 perror ("Could not figure length of .class file");
243 if (dep_name
!= NULL
)
244 jcf_dependency_add_file (dep_name
, 0);
246 jcf
->buffer
= XNEWVEC (unsigned char, stat_buf
.st_size
);
247 jcf
->buffer_end
= jcf
->buffer
+ stat_buf
.st_size
;
248 jcf
->read_ptr
= jcf
->buffer
;
249 jcf
->read_end
= jcf
->buffer_end
;
250 jcf
->read_state
= NULL
;
251 jcf
->filename
= xstrdup (filename
);
252 if (read (fd
, jcf
->buffer
, stat_buf
.st_size
) != stat_buf
.st_size
)
254 perror ("Failed to read .class file");
258 jcf
->filbuf
= jcf_unexpected_eof
;
267 find_classfile (char *filename
, JCF
*jcf
, const char *dep_name
)
269 int fd
= open (filename
, O_RDONLY
| O_BINARY
);
272 return open_class (filename
, jcf
, fd
, dep_name
);
275 /* A hash table keeping track of class names that were not found
276 during class lookup. (There is no need to cache the values
277 associated with names that were found; they are saved in
278 IDENTIFIER_CLASS_VALUE.) */
279 static hash_table
<nofree_string_hash
> *memoized_class_lookups
;
281 /* Returns a freshly malloc'd string with the fully qualified pathname
282 of the .class file for the class CLASSNAME. CLASSNAME must be
283 allocated in permanent storage; this function may retain a pointer
284 to it. Returns NULL on failure. If JCF != NULL, it is suitably
285 initialized. SOURCE_OK is true if we should also look for .java
289 find_class (const char *classname
, int classname_length
, JCF
*jcf
)
292 int i
, k
, klass
= -1;
293 struct stat class_buf
;
300 /* Create the hash table, if it does not already exist. */
301 if (!memoized_class_lookups
)
302 memoized_class_lookups
= new hash_table
<nofree_string_hash
> (37);
304 /* Loop for this class in the hashtable. If it is present, we've
305 already looked for this class and failed to find it. */
306 hash
= nofree_string_hash::hash (classname
);
307 if (memoized_class_lookups
->find_with_hash (classname
, hash
))
310 /* Allocate and zero out the buffer, since we don't explicitly put a
311 null pointer when we're copying it below. */
312 buflen
= jcf_path_max_len () + classname_length
+ 10;
313 buffer
= XNEWVAR (char, buflen
);
314 memset (buffer
, 0, buflen
);
316 for (entry
= jcf_path_start (); entry
!= NULL
; entry
= jcf_path_next (entry
))
318 const char *path_name
= jcf_path_name (entry
);
323 strcpy (buffer
, path_name
);
326 /* This is right because we know that `.zip' entries will have a
327 trailing slash. See jcf-path.c. */
330 for (k
= 0; k
< classname_length
; k
++, i
++)
332 char ch
= classname
[k
];
333 buffer
[i
] = ch
== '.' ? '/' : ch
;
335 strcpy (buffer
+i
, ".class");
337 if (jcf_path_is_zipfile (entry
))
341 buffer
[dir_len
] = '\0';
342 SOURCE_FRONTEND_DEBUG
343 (("Trying [...%s]:%s",
344 &buffer
[dir_len
-(dir_len
> 15 ? 15 : dir_len
)],
348 err_code
= open_in_zip (jcf
, buffer
, buffer
+dir_len
+1,
349 jcf_path_is_system (entry
));
352 /* Should we check if .zip is out-of-date wrt .java? */
353 buffer
[dir_len
] = '(';
354 strcpy (buffer
+i
, ".class)");
362 klass
= stat (buffer
, &class_buf
);
369 SOURCE_FRONTEND_DEBUG ((stderr
, "[Class selected: %s]\n",
370 classname
+classname_length
-
371 (classname_length
<= 30 ?
372 classname_length
: 30)));
373 fd
= JCF_OPEN_EXACT_CASE (buffer
, O_RDONLY
| O_BINARY
);
380 /* Remember that this class could not be found so that we do not
381 have to look again. */
382 *memoized_class_lookups
->find_slot_with_hash (classname
, hash
, INSERT
)
388 const char *const tmp
= open_class (buffer
, jcf
, fd
, dep_file
);
389 jcf
->classname
= xstrdup (classname
);
395 jcf_print_char (FILE *stream
, int ch
)
402 fprintf (stream
, "\\%c", ch
);
405 fprintf (stream
, "\\n");
408 fprintf (stream
, "\\t");
411 fprintf (stream
, "\\r");
414 if (ch
>= ' ' && ch
< 127)
417 fprintf (stream
, "\\%03x", ch
);
419 fprintf (stream
, "\\u%04x", ch
);
423 /* Print UTF8 string at STR of length LENGTH bytes to STREAM. */
426 jcf_print_utf8 (FILE *stream
, const unsigned char *str
, int length
)
428 const unsigned char * limit
= str
+ length
;
431 int ch
= UTF8_GET (str
, limit
);
434 fprintf (stream
, "\\<invalid>");
437 jcf_print_char (stream
, ch
);
441 /* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */
444 jcf_print_utf8_replace (FILE *stream
, const unsigned char *str
, int length
,
445 int in_char
, int out_char
)
447 const unsigned char *limit
= str
+ length
;
450 int ch
= UTF8_GET (str
, limit
);
453 fprintf (stream
, "\\<invalid>");
456 jcf_print_char (stream
, ch
== in_char
? out_char
: ch
);
460 /* Check that all the cross-references in the constant pool are
461 valid. Returns 0 on success.
462 Otherwise, returns the index of the (first) invalid entry.
463 Only checks internal consistency, but does not check that
464 any classes, fields, or methods are valid.*/
467 verify_constant_pool (JCF
*jcf
)
470 for (i
= 1; i
< JPOOL_SIZE (jcf
); i
++)
472 switch (JPOOL_TAG (jcf
, i
))
474 case CONSTANT_NameAndType
:
475 n
= JPOOL_USHORT2 (jcf
, i
);
476 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
477 || JPOOL_TAG (jcf
, n
) != CONSTANT_Utf8
)
479 /* ... fall through ... */
481 case CONSTANT_String
:
482 n
= JPOOL_USHORT1 (jcf
, i
);
483 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
484 || JPOOL_TAG (jcf
, n
) != CONSTANT_Utf8
)
487 case CONSTANT_Fieldref
:
488 case CONSTANT_Methodref
:
489 case CONSTANT_InterfaceMethodref
:
490 n
= JPOOL_USHORT1 (jcf
, i
);
491 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
492 || JPOOL_TAG (jcf
, n
) != CONSTANT_Class
)
494 n
= JPOOL_USHORT2 (jcf
, i
);
495 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
496 || JPOOL_TAG (jcf
, n
) != CONSTANT_NameAndType
)
500 case CONSTANT_Double
:
504 case CONSTANT_Integer
:
506 case CONSTANT_Unicode
:
508 case CONSTANT_MethodHandle
:
509 n
= JPOOL_USHORT1 (jcf
, i
);
512 n
= JPOOL_USHORT2 (jcf
, i
);
513 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
))
516 case CONSTANT_MethodType
:
517 n
= JPOOL_USHORT1 (jcf
, i
);
518 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
519 || JPOOL_TAG (jcf
, n
) != CONSTANT_Utf8
)
522 case CONSTANT_InvokeDynamic
:
523 n
= JPOOL_USHORT2 (jcf
, i
);
524 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
525 || JPOOL_TAG (jcf
, n
) != CONSTANT_NameAndType
)
536 format_uint (char *buffer
, uint64 value
, int base
)
538 #define WRITE_BUF_SIZE (4 + sizeof(uint64) * 8)
539 char buf
[WRITE_BUF_SIZE
];
540 char *buf_ptr
= buf
+WRITE_BUF_SIZE
; /* End of buf. */
544 /* Now do the actual conversion, placing the result at the *end* of buf. */
545 /* Note this code does not pretend to be optimized. */
547 int digit
= value
% base
;
548 static const char digit_chars
[] = "0123456789abcdefghijklmnopqrstuvwxyz";
549 *--buf_ptr
= digit_chars
[digit
];
551 } while (value
!= 0);
553 chars_written
= buf
+WRITE_BUF_SIZE
- buf_ptr
;
554 for (i
= 0; i
< chars_written
; i
++)
555 buffer
[i
] = *buf_ptr
++;
560 format_int (char *buffer
, jlong value
, int base
)
565 abs_value
= -(uint64
)value
;
569 abs_value
= (uint64
) value
;
570 format_uint (buffer
, abs_value
, base
);