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"
34 #include "java-tree.h"
40 jcf_unexpected_eof (JCF
*jcf
, int count ATTRIBUTE_UNUSED
)
43 fprintf (stderr
, "Premature end of .class file %s.\n", jcf
->filename
);
45 fprintf (stderr
, "Premature end of .class file <stdin>.\n");
50 jcf_trim_old_input (JCF
*jcf
)
52 int count
= jcf
->read_ptr
- jcf
->buffer
;
55 memmove (jcf
->buffer
, jcf
->read_ptr
, jcf
->read_end
- jcf
->read_ptr
);
56 jcf
->read_ptr
-= count
;
57 jcf
->read_end
-= count
;
62 jcf_filbuf_from_stdio (JCF
*jcf
, int count
)
64 FILE *file
= (FILE*) (jcf
->read_state
);
65 if (count
> jcf
->buffer_end
- jcf
->read_ptr
)
67 JCF_u4 old_read_ptr
= jcf
->read_ptr
- jcf
->buffer
;
68 JCF_u4 old_read_end
= jcf
->read_end
- jcf
->buffer
;
69 JCF_u4 old_size
= jcf
->buffer_end
- jcf
->buffer
;
70 JCF_u4 new_size
= (old_size
== 0 ? 2000 : 2 * old_size
) + count
;
71 unsigned char *new_buffer
72 = jcf
->buffer
== NULL
? XNEWVAR (unsigned char, new_size
)
73 : XRESIZEVAR (unsigned char, jcf
->buffer
, new_size
);
74 jcf
->buffer
= new_buffer
;
75 jcf
->buffer_end
= new_buffer
+ new_size
;
76 jcf
->read_ptr
= new_buffer
+ old_read_ptr
;
77 jcf
->read_end
= new_buffer
+ old_read_end
;
79 count
-= jcf
->read_end
- jcf
->read_ptr
;
82 if ((int) fread (jcf
->read_end
, 1, count
, file
) != count
)
83 jcf_unexpected_eof (jcf
, count
);
84 jcf
->read_end
+= count
;
90 struct ZipFile
*SeenZipFiles
= NULL
;
92 /* Open a zip file with the given name, and cache directory and file
93 descriptor. If the file is missing, treat it as an empty archive.
94 Return NULL if the .zip file is malformed.
98 opendir_in_zip (const char *zipfile
, int is_system
)
100 struct ZipFile
* zipf
;
103 for (zipf
= SeenZipFiles
; zipf
!= NULL
; zipf
= zipf
->next
)
105 if (strcmp (zipf
->name
, zipfile
) == 0)
109 zipf
= XNEWVAR (struct ZipFile
, sizeof (struct ZipFile
) + strlen (zipfile
) + 1);
110 zipf
->next
= SeenZipFiles
;
111 zipf
->name
= (char*)(zipf
+1);
112 strcpy (zipf
->name
, zipfile
);
113 fd
= open (zipfile
, O_RDONLY
| O_BINARY
);
117 /* A missing zip file is not considered an error.
118 We may want to re-consider that. FIXME. */
121 zipf
->central_directory
= NULL
;
125 jcf_dependency_add_file (zipfile
, is_system
);
126 if (read (fd
, magic
, 4) != 4 || GET_u4 (magic
) != (JCF_u4
)ZIPMAGIC
)
132 lseek (fd
, 0L, SEEK_SET
);
133 if (read_zip_archive (zipf
) != 0)
146 0: OK - zipmember found.
148 -2: Malformed archive.
152 open_in_zip (JCF
*jcf
, const char *zipfile
, const char *zipmember
,
157 ZipFile
*zipf
= opendir_in_zip (zipfile
, is_system
);
165 len
= strlen (zipmember
);
167 zipd
= (struct ZipDirectory
*) zipf
->central_directory
;
168 for (i
= 0; i
< zipf
->count
; i
++, zipd
= ZIPDIR_NEXT (zipd
))
170 if (len
== zipd
->filename_length
&&
171 strncmp (ZIPDIR_FILENAME (zipd
), zipmember
, len
) == 0)
175 jcf
->filename
= xstrdup (zipfile
);
176 jcf
->classname
= xstrdup (zipmember
);
177 return read_zip_member(jcf
, zipd
, zipf
);
183 /* Read data from zip archive member. */
186 read_zip_member (JCF
*jcf
, ZipDirectory
*zipd
, ZipFile
*zipf
)
188 jcf
->filbuf
= jcf_unexpected_eof
;
191 if (zipd
->compression_method
== Z_NO_COMPRESSION
)
193 jcf
->buffer
= XNEWVEC (unsigned char, zipd
->size
);
194 jcf
->buffer_end
= jcf
->buffer
+ zipd
->size
;
195 jcf
->read_ptr
= jcf
->buffer
;
196 jcf
->read_end
= jcf
->buffer_end
;
197 if (lseek (zipf
->fd
, zipd
->filestart
, 0) < 0
198 || read (zipf
->fd
, jcf
->buffer
, zipd
->size
) != (long) zipd
->size
)
204 z_stream d_stream
; /* decompression stream */
205 memset (&d_stream
, 0, sizeof (d_stream
));
207 jcf
->buffer
= XNEWVEC (unsigned char, zipd
->uncompressed_size
);
208 d_stream
.next_out
= jcf
->buffer
;
209 d_stream
.avail_out
= zipd
->uncompressed_size
;
210 jcf
->buffer_end
= jcf
->buffer
+ zipd
->uncompressed_size
;
211 jcf
->read_ptr
= jcf
->buffer
;
212 jcf
->read_end
= jcf
->buffer_end
;
213 buffer
= XNEWVEC (char, zipd
->size
);
214 d_stream
.next_in
= (unsigned char *) buffer
;
215 d_stream
.avail_in
= zipd
->size
;
216 if (lseek (zipf
->fd
, zipd
->filestart
, 0) < 0
217 || read (zipf
->fd
, buffer
, zipd
->size
) != (long) zipd
->size
)
219 /* Handle NO_HEADER using undocumented zlib feature.
220 This is a very common hack. */
221 inflateInit2 (&d_stream
, -MAX_WBITS
);
222 inflate (&d_stream
, Z_NO_FLUSH
);
223 inflateEnd (&d_stream
);
231 open_class (const char *filename
, JCF
*jcf
, int fd
, const char *dep_name
)
235 struct stat stat_buf
;
236 if (fstat (fd
, &stat_buf
) != 0
237 || ! S_ISREG (stat_buf
.st_mode
))
239 perror ("Could not figure length of .class file");
242 if (dep_name
!= NULL
)
243 jcf_dependency_add_file (dep_name
, 0);
245 jcf
->buffer
= XNEWVEC (unsigned char, stat_buf
.st_size
);
246 jcf
->buffer_end
= jcf
->buffer
+ stat_buf
.st_size
;
247 jcf
->read_ptr
= jcf
->buffer
;
248 jcf
->read_end
= jcf
->buffer_end
;
249 jcf
->read_state
= NULL
;
250 jcf
->filename
= xstrdup (filename
);
251 if (read (fd
, jcf
->buffer
, stat_buf
.st_size
) != stat_buf
.st_size
)
253 perror ("Failed to read .class file");
257 jcf
->filbuf
= jcf_unexpected_eof
;
266 find_classfile (char *filename
, JCF
*jcf
, const char *dep_name
)
268 int fd
= open (filename
, O_RDONLY
| O_BINARY
);
271 return open_class (filename
, jcf
, fd
, dep_name
);
274 /* A hash table keeping track of class names that were not found
275 during class lookup. (There is no need to cache the values
276 associated with names that were found; they are saved in
277 IDENTIFIER_CLASS_VALUE.) */
278 static hash_table
<nofree_string_hash
> *memoized_class_lookups
;
280 /* Returns a freshly malloc'd string with the fully qualified pathname
281 of the .class file for the class CLASSNAME. CLASSNAME must be
282 allocated in permanent storage; this function may retain a pointer
283 to it. Returns NULL on failure. If JCF != NULL, it is suitably
284 initialized. SOURCE_OK is true if we should also look for .java
288 find_class (const char *classname
, int classname_length
, JCF
*jcf
)
291 int i
, k
, klass
= -1;
292 struct stat class_buf
;
299 /* Create the hash table, if it does not already exist. */
300 if (!memoized_class_lookups
)
301 memoized_class_lookups
= new hash_table
<nofree_string_hash
> (37);
303 /* Loop for this class in the hashtable. If it is present, we've
304 already looked for this class and failed to find it. */
305 hash
= nofree_string_hash::hash (classname
);
306 if (memoized_class_lookups
->find_with_hash (classname
, hash
))
309 /* Allocate and zero out the buffer, since we don't explicitly put a
310 null pointer when we're copying it below. */
311 buflen
= jcf_path_max_len () + classname_length
+ 10;
312 buffer
= XNEWVAR (char, buflen
);
313 memset (buffer
, 0, buflen
);
315 for (entry
= jcf_path_start (); entry
!= NULL
; entry
= jcf_path_next (entry
))
317 const char *path_name
= jcf_path_name (entry
);
322 strcpy (buffer
, path_name
);
325 /* This is right because we know that `.zip' entries will have a
326 trailing slash. See jcf-path.c. */
329 for (k
= 0; k
< classname_length
; k
++, i
++)
331 char ch
= classname
[k
];
332 buffer
[i
] = ch
== '.' ? '/' : ch
;
334 strcpy (buffer
+i
, ".class");
336 if (jcf_path_is_zipfile (entry
))
340 buffer
[dir_len
] = '\0';
341 SOURCE_FRONTEND_DEBUG
342 (("Trying [...%s]:%s",
343 &buffer
[dir_len
-(dir_len
> 15 ? 15 : dir_len
)],
347 err_code
= open_in_zip (jcf
, buffer
, buffer
+dir_len
+1,
348 jcf_path_is_system (entry
));
351 /* Should we check if .zip is out-of-date wrt .java? */
352 buffer
[dir_len
] = '(';
353 strcpy (buffer
+i
, ".class)");
361 klass
= stat (buffer
, &class_buf
);
368 SOURCE_FRONTEND_DEBUG ((stderr
, "[Class selected: %s]\n",
369 classname
+classname_length
-
370 (classname_length
<= 30 ?
371 classname_length
: 30)));
372 fd
= JCF_OPEN_EXACT_CASE (buffer
, O_RDONLY
| O_BINARY
);
379 /* Remember that this class could not be found so that we do not
380 have to look again. */
381 *memoized_class_lookups
->find_slot_with_hash (classname
, hash
, INSERT
)
387 const char *const tmp
= open_class (buffer
, jcf
, fd
, dep_file
);
388 jcf
->classname
= xstrdup (classname
);
394 jcf_print_char (FILE *stream
, int ch
)
401 fprintf (stream
, "\\%c", ch
);
404 fprintf (stream
, "\\n");
407 fprintf (stream
, "\\t");
410 fprintf (stream
, "\\r");
413 if (ch
>= ' ' && ch
< 127)
416 fprintf (stream
, "\\%03x", ch
);
418 fprintf (stream
, "\\u%04x", ch
);
422 /* Print UTF8 string at STR of length LENGTH bytes to STREAM. */
425 jcf_print_utf8 (FILE *stream
, const unsigned char *str
, int length
)
427 const unsigned char * limit
= str
+ length
;
430 int ch
= UTF8_GET (str
, limit
);
433 fprintf (stream
, "\\<invalid>");
436 jcf_print_char (stream
, ch
);
440 /* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */
443 jcf_print_utf8_replace (FILE *stream
, const unsigned char *str
, int length
,
444 int in_char
, int out_char
)
446 const unsigned char *limit
= str
+ length
;
449 int ch
= UTF8_GET (str
, limit
);
452 fprintf (stream
, "\\<invalid>");
455 jcf_print_char (stream
, ch
== in_char
? out_char
: ch
);
459 /* Check that all the cross-references in the constant pool are
460 valid. Returns 0 on success.
461 Otherwise, returns the index of the (first) invalid entry.
462 Only checks internal consistency, but does not check that
463 any classes, fields, or methods are valid.*/
466 verify_constant_pool (JCF
*jcf
)
469 for (i
= 1; i
< JPOOL_SIZE (jcf
); i
++)
471 switch (JPOOL_TAG (jcf
, i
))
473 case CONSTANT_NameAndType
:
474 n
= JPOOL_USHORT2 (jcf
, i
);
475 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
476 || JPOOL_TAG (jcf
, n
) != CONSTANT_Utf8
)
478 /* ... fall through ... */
480 case CONSTANT_String
:
481 n
= JPOOL_USHORT1 (jcf
, i
);
482 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
483 || JPOOL_TAG (jcf
, n
) != CONSTANT_Utf8
)
486 case CONSTANT_Fieldref
:
487 case CONSTANT_Methodref
:
488 case CONSTANT_InterfaceMethodref
:
489 n
= JPOOL_USHORT1 (jcf
, i
);
490 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
491 || JPOOL_TAG (jcf
, n
) != CONSTANT_Class
)
493 n
= JPOOL_USHORT2 (jcf
, i
);
494 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
495 || JPOOL_TAG (jcf
, n
) != CONSTANT_NameAndType
)
499 case CONSTANT_Double
:
503 case CONSTANT_Integer
:
505 case CONSTANT_Unicode
:
507 case CONSTANT_MethodHandle
:
508 n
= JPOOL_USHORT1 (jcf
, i
);
511 n
= JPOOL_USHORT2 (jcf
, i
);
512 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
))
515 case CONSTANT_MethodType
:
516 n
= JPOOL_USHORT1 (jcf
, i
);
517 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
518 || JPOOL_TAG (jcf
, n
) != CONSTANT_Utf8
)
521 case CONSTANT_InvokeDynamic
:
522 n
= JPOOL_USHORT2 (jcf
, i
);
523 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
524 || JPOOL_TAG (jcf
, n
) != CONSTANT_NameAndType
)
535 format_uint (char *buffer
, uint64 value
, int base
)
537 #define WRITE_BUF_SIZE (4 + sizeof(uint64) * 8)
538 char buf
[WRITE_BUF_SIZE
];
539 char *buf_ptr
= buf
+WRITE_BUF_SIZE
; /* End of buf. */
543 /* Now do the actual conversion, placing the result at the *end* of buf. */
544 /* Note this code does not pretend to be optimized. */
546 int digit
= value
% base
;
547 static const char digit_chars
[] = "0123456789abcdefghijklmnopqrstuvwxyz";
548 *--buf_ptr
= digit_chars
[digit
];
550 } while (value
!= 0);
552 chars_written
= buf
+WRITE_BUF_SIZE
- buf_ptr
;
553 for (i
= 0; i
< chars_written
; i
++)
554 buffer
[i
] = *buf_ptr
++;
559 format_int (char *buffer
, jlong value
, int base
)
564 abs_value
= -(uint64
)value
;
568 abs_value
= (uint64
) value
;
569 format_uint (buffer
, abs_value
, base
);