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"
36 jcf_unexpected_eof (JCF
*jcf
, int count ATTRIBUTE_UNUSED
)
39 fprintf (stderr
, "Premature end of .class file %s.\n", jcf
->filename
);
41 fprintf (stderr
, "Premature end of .class file <stdin>.\n");
46 jcf_trim_old_input (JCF
*jcf
)
48 int count
= jcf
->read_ptr
- jcf
->buffer
;
51 memmove (jcf
->buffer
, jcf
->read_ptr
, jcf
->read_end
- jcf
->read_ptr
);
52 jcf
->read_ptr
-= count
;
53 jcf
->read_end
-= count
;
58 jcf_filbuf_from_stdio (JCF
*jcf
, int count
)
60 FILE *file
= (FILE*) (jcf
->read_state
);
61 if (count
> jcf
->buffer_end
- jcf
->read_ptr
)
63 JCF_u4 old_read_ptr
= jcf
->read_ptr
- jcf
->buffer
;
64 JCF_u4 old_read_end
= jcf
->read_end
- jcf
->buffer
;
65 JCF_u4 old_size
= jcf
->buffer_end
- jcf
->buffer
;
66 JCF_u4 new_size
= (old_size
== 0 ? 2000 : 2 * old_size
) + count
;
67 unsigned char *new_buffer
68 = jcf
->buffer
== NULL
? XNEWVAR (unsigned char, new_size
)
69 : XRESIZEVAR (unsigned char, jcf
->buffer
, new_size
);
70 jcf
->buffer
= new_buffer
;
71 jcf
->buffer_end
= new_buffer
+ new_size
;
72 jcf
->read_ptr
= new_buffer
+ old_read_ptr
;
73 jcf
->read_end
= new_buffer
+ old_read_end
;
75 count
-= jcf
->read_end
- jcf
->read_ptr
;
78 if ((int) fread (jcf
->read_end
, 1, count
, file
) != count
)
79 jcf_unexpected_eof (jcf
, count
);
80 jcf
->read_end
+= count
;
86 struct ZipFile
*SeenZipFiles
= NULL
;
88 /* Open a zip file with the given name, and cache directory and file
89 descriptor. If the file is missing, treat it as an empty archive.
90 Return NULL if the .zip file is malformed.
94 opendir_in_zip (const char *zipfile
, int is_system
)
99 for (zipf
= SeenZipFiles
; zipf
!= NULL
; zipf
= zipf
->next
)
101 if (strcmp (zipf
->name
, zipfile
) == 0)
105 zipf
= XNEWVAR (struct ZipFile
, sizeof (struct ZipFile
) + strlen (zipfile
) + 1);
106 zipf
->next
= SeenZipFiles
;
107 zipf
->name
= (char*)(zipf
+1);
108 strcpy (zipf
->name
, zipfile
);
109 fd
= open (zipfile
, O_RDONLY
| O_BINARY
);
113 /* A missing zip file is not considered an error.
114 We may want to re-consider that. FIXME. */
117 zipf
->central_directory
= NULL
;
121 jcf_dependency_add_file (zipfile
, is_system
);
122 if (read (fd
, magic
, 4) != 4 || GET_u4 (magic
) != (JCF_u4
)ZIPMAGIC
)
128 lseek (fd
, 0L, SEEK_SET
);
129 if (read_zip_archive (zipf
) != 0)
142 0: OK - zipmember found.
144 -2: Malformed archive.
148 open_in_zip (JCF
*jcf
, const char *zipfile
, const char *zipmember
,
153 ZipFile
*zipf
= opendir_in_zip (zipfile
, is_system
);
161 len
= strlen (zipmember
);
163 zipd
= (struct ZipDirectory
*) zipf
->central_directory
;
164 for (i
= 0; i
< zipf
->count
; i
++, zipd
= ZIPDIR_NEXT (zipd
))
166 if (len
== zipd
->filename_length
&&
167 strncmp (ZIPDIR_FILENAME (zipd
), zipmember
, len
) == 0)
171 jcf
->filename
= xstrdup (zipfile
);
172 jcf
->classname
= xstrdup (zipmember
);
173 return read_zip_member(jcf
, zipd
, zipf
);
179 /* Read data from zip archive member. */
182 read_zip_member (JCF
*jcf
, ZipDirectory
*zipd
, ZipFile
*zipf
)
184 jcf
->filbuf
= jcf_unexpected_eof
;
187 if (zipd
->compression_method
== Z_NO_COMPRESSION
)
189 jcf
->buffer
= XNEWVEC (unsigned char, zipd
->size
);
190 jcf
->buffer_end
= jcf
->buffer
+ zipd
->size
;
191 jcf
->read_ptr
= jcf
->buffer
;
192 jcf
->read_end
= jcf
->buffer_end
;
193 if (lseek (zipf
->fd
, zipd
->filestart
, 0) < 0
194 || read (zipf
->fd
, jcf
->buffer
, zipd
->size
) != (long) zipd
->size
)
200 z_stream d_stream
; /* decompression stream */
201 memset (&d_stream
, 0, sizeof (d_stream
));
203 jcf
->buffer
= XNEWVEC (unsigned char, zipd
->uncompressed_size
);
204 d_stream
.next_out
= jcf
->buffer
;
205 d_stream
.avail_out
= zipd
->uncompressed_size
;
206 jcf
->buffer_end
= jcf
->buffer
+ zipd
->uncompressed_size
;
207 jcf
->read_ptr
= jcf
->buffer
;
208 jcf
->read_end
= jcf
->buffer_end
;
209 buffer
= XNEWVEC (char, zipd
->size
);
210 d_stream
.next_in
= (unsigned char *) buffer
;
211 d_stream
.avail_in
= zipd
->size
;
212 if (lseek (zipf
->fd
, zipd
->filestart
, 0) < 0
213 || read (zipf
->fd
, buffer
, zipd
->size
) != (long) zipd
->size
)
215 /* Handle NO_HEADER using undocumented zlib feature.
216 This is a very common hack. */
217 inflateInit2 (&d_stream
, -MAX_WBITS
);
218 inflate (&d_stream
, Z_NO_FLUSH
);
219 inflateEnd (&d_stream
);
227 open_class (const char *filename
, JCF
*jcf
, int fd
, const char *dep_name
)
231 struct stat stat_buf
;
232 if (fstat (fd
, &stat_buf
) != 0
233 || ! S_ISREG (stat_buf
.st_mode
))
235 perror ("Could not figure length of .class file");
238 if (dep_name
!= NULL
)
239 jcf_dependency_add_file (dep_name
, 0);
241 jcf
->buffer
= XNEWVEC (unsigned char, stat_buf
.st_size
);
242 jcf
->buffer_end
= jcf
->buffer
+ stat_buf
.st_size
;
243 jcf
->read_ptr
= jcf
->buffer
;
244 jcf
->read_end
= jcf
->buffer_end
;
245 jcf
->read_state
= NULL
;
246 jcf
->filename
= xstrdup (filename
);
247 if (read (fd
, jcf
->buffer
, stat_buf
.st_size
) != stat_buf
.st_size
)
249 perror ("Failed to read .class file");
253 jcf
->filbuf
= jcf_unexpected_eof
;
262 find_classfile (char *filename
, JCF
*jcf
, const char *dep_name
)
264 int fd
= open (filename
, O_RDONLY
| O_BINARY
);
267 return open_class (filename
, jcf
, fd
, dep_name
);
270 /* A hash table keeping track of class names that were not found
271 during class lookup. (There is no need to cache the values
272 associated with names that were found; they are saved in
273 IDENTIFIER_CLASS_VALUE.) */
274 static hash_table
<nofree_string_hash
> *memoized_class_lookups
;
276 /* Returns a freshly malloc'd string with the fully qualified pathname
277 of the .class file for the class CLASSNAME. CLASSNAME must be
278 allocated in permanent storage; this function may retain a pointer
279 to it. Returns NULL on failure. If JCF != NULL, it is suitably
280 initialized. SOURCE_OK is true if we should also look for .java
284 find_class (const char *classname
, int classname_length
, JCF
*jcf
)
287 int i
, k
, klass
= -1;
288 struct stat class_buf
;
295 /* Create the hash table, if it does not already exist. */
296 if (!memoized_class_lookups
)
297 memoized_class_lookups
= new hash_table
<nofree_string_hash
> (37);
299 /* Loop for this class in the hashtable. If it is present, we've
300 already looked for this class and failed to find it. */
301 hash
= nofree_string_hash::hash (classname
);
302 if (memoized_class_lookups
->find_with_hash (classname
, hash
))
305 /* Allocate and zero out the buffer, since we don't explicitly put a
306 null pointer when we're copying it below. */
307 buflen
= jcf_path_max_len () + classname_length
+ 10;
308 buffer
= XNEWVAR (char, buflen
);
309 memset (buffer
, 0, buflen
);
311 for (entry
= jcf_path_start (); entry
!= NULL
; entry
= jcf_path_next (entry
))
313 const char *path_name
= jcf_path_name (entry
);
318 strcpy (buffer
, path_name
);
321 /* This is right because we know that `.zip' entries will have a
322 trailing slash. See jcf-path.c. */
325 for (k
= 0; k
< classname_length
; k
++, i
++)
327 char ch
= classname
[k
];
328 buffer
[i
] = ch
== '.' ? '/' : ch
;
330 strcpy (buffer
+i
, ".class");
332 if (jcf_path_is_zipfile (entry
))
336 buffer
[dir_len
] = '\0';
337 SOURCE_FRONTEND_DEBUG
338 (("Trying [...%s]:%s",
339 &buffer
[dir_len
-(dir_len
> 15 ? 15 : dir_len
)],
343 err_code
= open_in_zip (jcf
, buffer
, buffer
+dir_len
+1,
344 jcf_path_is_system (entry
));
347 /* Should we check if .zip is out-of-date wrt .java? */
348 buffer
[dir_len
] = '(';
349 strcpy (buffer
+i
, ".class)");
357 klass
= stat (buffer
, &class_buf
);
364 SOURCE_FRONTEND_DEBUG ((stderr
, "[Class selected: %s]\n",
365 classname
+classname_length
-
366 (classname_length
<= 30 ?
367 classname_length
: 30)));
368 fd
= JCF_OPEN_EXACT_CASE (buffer
, O_RDONLY
| O_BINARY
);
375 /* Remember that this class could not be found so that we do not
376 have to look again. */
377 *memoized_class_lookups
->find_slot_with_hash (classname
, hash
, INSERT
)
383 const char *const tmp
= open_class (buffer
, jcf
, fd
, dep_file
);
384 jcf
->classname
= xstrdup (classname
);
390 jcf_print_char (FILE *stream
, int ch
)
397 fprintf (stream
, "\\%c", ch
);
400 fprintf (stream
, "\\n");
403 fprintf (stream
, "\\t");
406 fprintf (stream
, "\\r");
409 if (ch
>= ' ' && ch
< 127)
412 fprintf (stream
, "\\%03x", ch
);
414 fprintf (stream
, "\\u%04x", ch
);
418 /* Print UTF8 string at STR of length LENGTH bytes to STREAM. */
421 jcf_print_utf8 (FILE *stream
, const unsigned char *str
, int length
)
423 const unsigned char * limit
= str
+ length
;
426 int ch
= UTF8_GET (str
, limit
);
429 fprintf (stream
, "\\<invalid>");
432 jcf_print_char (stream
, ch
);
436 /* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */
439 jcf_print_utf8_replace (FILE *stream
, const unsigned char *str
, int length
,
440 int in_char
, int out_char
)
442 const unsigned char *limit
= str
+ length
;
445 int ch
= UTF8_GET (str
, limit
);
448 fprintf (stream
, "\\<invalid>");
451 jcf_print_char (stream
, ch
== in_char
? out_char
: ch
);
455 /* Check that all the cross-references in the constant pool are
456 valid. Returns 0 on success.
457 Otherwise, returns the index of the (first) invalid entry.
458 Only checks internal consistency, but does not check that
459 any classes, fields, or methods are valid.*/
462 verify_constant_pool (JCF
*jcf
)
465 for (i
= 1; i
< JPOOL_SIZE (jcf
); i
++)
467 switch (JPOOL_TAG (jcf
, i
))
469 case CONSTANT_NameAndType
:
470 n
= JPOOL_USHORT2 (jcf
, i
);
471 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
472 || JPOOL_TAG (jcf
, n
) != CONSTANT_Utf8
)
474 /* ... fall through ... */
476 case CONSTANT_String
:
477 n
= JPOOL_USHORT1 (jcf
, i
);
478 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
479 || JPOOL_TAG (jcf
, n
) != CONSTANT_Utf8
)
482 case CONSTANT_Fieldref
:
483 case CONSTANT_Methodref
:
484 case CONSTANT_InterfaceMethodref
:
485 n
= JPOOL_USHORT1 (jcf
, i
);
486 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
487 || JPOOL_TAG (jcf
, n
) != CONSTANT_Class
)
489 n
= JPOOL_USHORT2 (jcf
, i
);
490 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
491 || JPOOL_TAG (jcf
, n
) != CONSTANT_NameAndType
)
495 case CONSTANT_Double
:
499 case CONSTANT_Integer
:
501 case CONSTANT_Unicode
:
503 case CONSTANT_MethodHandle
:
504 n
= JPOOL_USHORT1 (jcf
, i
);
507 n
= JPOOL_USHORT2 (jcf
, i
);
508 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
))
511 case CONSTANT_MethodType
:
512 n
= JPOOL_USHORT1 (jcf
, i
);
513 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
514 || JPOOL_TAG (jcf
, n
) != CONSTANT_Utf8
)
517 case CONSTANT_InvokeDynamic
:
518 n
= JPOOL_USHORT2 (jcf
, i
);
519 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
520 || JPOOL_TAG (jcf
, n
) != CONSTANT_NameAndType
)
531 format_uint (char *buffer
, uint64 value
, int base
)
533 #define WRITE_BUF_SIZE (4 + sizeof(uint64) * 8)
534 char buf
[WRITE_BUF_SIZE
];
535 char *buf_ptr
= buf
+WRITE_BUF_SIZE
; /* End of buf. */
539 /* Now do the actual conversion, placing the result at the *end* of buf. */
540 /* Note this code does not pretend to be optimized. */
542 int digit
= value
% base
;
543 static const char digit_chars
[] = "0123456789abcdefghijklmnopqrstuvwxyz";
544 *--buf_ptr
= digit_chars
[digit
];
546 } while (value
!= 0);
548 chars_written
= buf
+WRITE_BUF_SIZE
- buf_ptr
;
549 for (i
= 0; i
< chars_written
; i
++)
550 buffer
[i
] = *buf_ptr
++;
555 format_int (char *buffer
, jlong value
, int base
)
560 abs_value
= -(uint64
)value
;
564 abs_value
= (uint64
) value
;
565 format_uint (buffer
, abs_value
, base
);