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 "double-int.h"
42 #include "java-tree.h"
43 #include "hash-table.h"
49 jcf_unexpected_eof (JCF
*jcf
, int count ATTRIBUTE_UNUSED
)
52 fprintf (stderr
, "Premature end of .class file %s.\n", jcf
->filename
);
54 fprintf (stderr
, "Premature end of .class file <stdin>.\n");
59 jcf_trim_old_input (JCF
*jcf
)
61 int count
= jcf
->read_ptr
- jcf
->buffer
;
64 memmove (jcf
->buffer
, jcf
->read_ptr
, jcf
->read_end
- jcf
->read_ptr
);
65 jcf
->read_ptr
-= count
;
66 jcf
->read_end
-= count
;
71 jcf_filbuf_from_stdio (JCF
*jcf
, int count
)
73 FILE *file
= (FILE*) (jcf
->read_state
);
74 if (count
> jcf
->buffer_end
- jcf
->read_ptr
)
76 JCF_u4 old_read_ptr
= jcf
->read_ptr
- jcf
->buffer
;
77 JCF_u4 old_read_end
= jcf
->read_end
- jcf
->buffer
;
78 JCF_u4 old_size
= jcf
->buffer_end
- jcf
->buffer
;
79 JCF_u4 new_size
= (old_size
== 0 ? 2000 : 2 * old_size
) + count
;
80 unsigned char *new_buffer
81 = jcf
->buffer
== NULL
? XNEWVAR (unsigned char, new_size
)
82 : XRESIZEVAR (unsigned char, jcf
->buffer
, new_size
);
83 jcf
->buffer
= new_buffer
;
84 jcf
->buffer_end
= new_buffer
+ new_size
;
85 jcf
->read_ptr
= new_buffer
+ old_read_ptr
;
86 jcf
->read_end
= new_buffer
+ old_read_end
;
88 count
-= jcf
->read_end
- jcf
->read_ptr
;
91 if ((int) fread (jcf
->read_end
, 1, count
, file
) != count
)
92 jcf_unexpected_eof (jcf
, count
);
93 jcf
->read_end
+= count
;
99 struct ZipFile
*SeenZipFiles
= NULL
;
101 /* Open a zip file with the given name, and cache directory and file
102 descriptor. If the file is missing, treat it as an empty archive.
103 Return NULL if the .zip file is malformed.
107 opendir_in_zip (const char *zipfile
, int is_system
)
109 struct ZipFile
* zipf
;
112 for (zipf
= SeenZipFiles
; zipf
!= NULL
; zipf
= zipf
->next
)
114 if (strcmp (zipf
->name
, zipfile
) == 0)
118 zipf
= XNEWVAR (struct ZipFile
, sizeof (struct ZipFile
) + strlen (zipfile
) + 1);
119 zipf
->next
= SeenZipFiles
;
120 zipf
->name
= (char*)(zipf
+1);
121 strcpy (zipf
->name
, zipfile
);
122 fd
= open (zipfile
, O_RDONLY
| O_BINARY
);
126 /* A missing zip file is not considered an error.
127 We may want to re-consider that. FIXME. */
130 zipf
->central_directory
= NULL
;
134 jcf_dependency_add_file (zipfile
, is_system
);
135 if (read (fd
, magic
, 4) != 4 || GET_u4 (magic
) != (JCF_u4
)ZIPMAGIC
)
141 lseek (fd
, 0L, SEEK_SET
);
142 if (read_zip_archive (zipf
) != 0)
155 0: OK - zipmember found.
157 -2: Malformed archive.
161 open_in_zip (JCF
*jcf
, const char *zipfile
, const char *zipmember
,
166 ZipFile
*zipf
= opendir_in_zip (zipfile
, is_system
);
174 len
= strlen (zipmember
);
176 zipd
= (struct ZipDirectory
*) zipf
->central_directory
;
177 for (i
= 0; i
< zipf
->count
; i
++, zipd
= ZIPDIR_NEXT (zipd
))
179 if (len
== zipd
->filename_length
&&
180 strncmp (ZIPDIR_FILENAME (zipd
), zipmember
, len
) == 0)
184 jcf
->filename
= xstrdup (zipfile
);
185 jcf
->classname
= xstrdup (zipmember
);
186 return read_zip_member(jcf
, zipd
, zipf
);
192 /* Read data from zip archive member. */
195 read_zip_member (JCF
*jcf
, ZipDirectory
*zipd
, ZipFile
*zipf
)
197 jcf
->filbuf
= jcf_unexpected_eof
;
200 if (zipd
->compression_method
== Z_NO_COMPRESSION
)
202 jcf
->buffer
= XNEWVEC (unsigned char, zipd
->size
);
203 jcf
->buffer_end
= jcf
->buffer
+ zipd
->size
;
204 jcf
->read_ptr
= jcf
->buffer
;
205 jcf
->read_end
= jcf
->buffer_end
;
206 if (lseek (zipf
->fd
, zipd
->filestart
, 0) < 0
207 || read (zipf
->fd
, jcf
->buffer
, zipd
->size
) != (long) zipd
->size
)
213 z_stream d_stream
; /* decompression stream */
214 memset (&d_stream
, 0, sizeof (d_stream
));
216 jcf
->buffer
= XNEWVEC (unsigned char, zipd
->uncompressed_size
);
217 d_stream
.next_out
= jcf
->buffer
;
218 d_stream
.avail_out
= zipd
->uncompressed_size
;
219 jcf
->buffer_end
= jcf
->buffer
+ zipd
->uncompressed_size
;
220 jcf
->read_ptr
= jcf
->buffer
;
221 jcf
->read_end
= jcf
->buffer_end
;
222 buffer
= XNEWVEC (char, zipd
->size
);
223 d_stream
.next_in
= (unsigned char *) buffer
;
224 d_stream
.avail_in
= zipd
->size
;
225 if (lseek (zipf
->fd
, zipd
->filestart
, 0) < 0
226 || read (zipf
->fd
, buffer
, zipd
->size
) != (long) zipd
->size
)
228 /* Handle NO_HEADER using undocumented zlib feature.
229 This is a very common hack. */
230 inflateInit2 (&d_stream
, -MAX_WBITS
);
231 inflate (&d_stream
, Z_NO_FLUSH
);
232 inflateEnd (&d_stream
);
240 open_class (const char *filename
, JCF
*jcf
, int fd
, const char *dep_name
)
244 struct stat stat_buf
;
245 if (fstat (fd
, &stat_buf
) != 0
246 || ! S_ISREG (stat_buf
.st_mode
))
248 perror ("Could not figure length of .class file");
251 if (dep_name
!= NULL
)
252 jcf_dependency_add_file (dep_name
, 0);
254 jcf
->buffer
= XNEWVEC (unsigned char, stat_buf
.st_size
);
255 jcf
->buffer_end
= jcf
->buffer
+ stat_buf
.st_size
;
256 jcf
->read_ptr
= jcf
->buffer
;
257 jcf
->read_end
= jcf
->buffer_end
;
258 jcf
->read_state
= NULL
;
259 jcf
->filename
= xstrdup (filename
);
260 if (read (fd
, jcf
->buffer
, stat_buf
.st_size
) != stat_buf
.st_size
)
262 perror ("Failed to read .class file");
266 jcf
->filbuf
= jcf_unexpected_eof
;
275 find_classfile (char *filename
, JCF
*jcf
, const char *dep_name
)
277 int fd
= open (filename
, O_RDONLY
| O_BINARY
);
280 return open_class (filename
, jcf
, fd
, dep_name
);
284 /* Hash table helper. */
286 struct charstar_hash
: typed_noop_remove
<char>
288 typedef const char value_type
;
289 typedef const char compare_type
;
290 static inline hashval_t
hash (const value_type
*candidate
);
291 static inline bool equal (const value_type
*existing
,
292 const compare_type
*candidate
);
296 charstar_hash::hash (const value_type
*candidate
)
298 return htab_hash_string (candidate
);
302 charstar_hash::equal (const value_type
*existing
, const compare_type
*candidate
)
304 return strcmp (existing
, candidate
) == 0;
308 /* A hash table keeping track of class names that were not found
309 during class lookup. (There is no need to cache the values
310 associated with names that were found; they are saved in
311 IDENTIFIER_CLASS_VALUE.) */
312 static hash_table
<charstar_hash
> *memoized_class_lookups
;
314 /* Returns a freshly malloc'd string with the fully qualified pathname
315 of the .class file for the class CLASSNAME. CLASSNAME must be
316 allocated in permanent storage; this function may retain a pointer
317 to it. Returns NULL on failure. If JCF != NULL, it is suitably
318 initialized. SOURCE_OK is true if we should also look for .java
322 find_class (const char *classname
, int classname_length
, JCF
*jcf
)
325 int i
, k
, klass
= -1;
326 struct stat class_buf
;
333 /* Create the hash table, if it does not already exist. */
334 if (!memoized_class_lookups
)
335 memoized_class_lookups
= new hash_table
<charstar_hash
> (37);
337 /* Loop for this class in the hashtable. If it is present, we've
338 already looked for this class and failed to find it. */
339 hash
= charstar_hash::hash (classname
);
340 if (memoized_class_lookups
->find_with_hash (classname
, hash
))
343 /* Allocate and zero out the buffer, since we don't explicitly put a
344 null pointer when we're copying it below. */
345 buflen
= jcf_path_max_len () + classname_length
+ 10;
346 buffer
= XNEWVAR (char, buflen
);
347 memset (buffer
, 0, buflen
);
349 for (entry
= jcf_path_start (); entry
!= NULL
; entry
= jcf_path_next (entry
))
351 const char *path_name
= jcf_path_name (entry
);
356 strcpy (buffer
, path_name
);
359 /* This is right because we know that `.zip' entries will have a
360 trailing slash. See jcf-path.c. */
363 for (k
= 0; k
< classname_length
; k
++, i
++)
365 char ch
= classname
[k
];
366 buffer
[i
] = ch
== '.' ? '/' : ch
;
368 strcpy (buffer
+i
, ".class");
370 if (jcf_path_is_zipfile (entry
))
374 buffer
[dir_len
] = '\0';
375 SOURCE_FRONTEND_DEBUG
376 (("Trying [...%s]:%s",
377 &buffer
[dir_len
-(dir_len
> 15 ? 15 : dir_len
)],
381 err_code
= open_in_zip (jcf
, buffer
, buffer
+dir_len
+1,
382 jcf_path_is_system (entry
));
385 /* Should we check if .zip is out-of-date wrt .java? */
386 buffer
[dir_len
] = '(';
387 strcpy (buffer
+i
, ".class)");
395 klass
= stat (buffer
, &class_buf
);
402 SOURCE_FRONTEND_DEBUG ((stderr
, "[Class selected: %s]\n",
403 classname
+classname_length
-
404 (classname_length
<= 30 ?
405 classname_length
: 30)));
406 fd
= JCF_OPEN_EXACT_CASE (buffer
, O_RDONLY
| O_BINARY
);
413 /* Remember that this class could not be found so that we do not
414 have to look again. */
415 *memoized_class_lookups
->find_slot_with_hash (classname
, hash
, INSERT
)
421 const char *const tmp
= open_class (buffer
, jcf
, fd
, dep_file
);
422 jcf
->classname
= xstrdup (classname
);
428 jcf_print_char (FILE *stream
, int ch
)
435 fprintf (stream
, "\\%c", ch
);
438 fprintf (stream
, "\\n");
441 fprintf (stream
, "\\t");
444 fprintf (stream
, "\\r");
447 if (ch
>= ' ' && ch
< 127)
450 fprintf (stream
, "\\%03x", ch
);
452 fprintf (stream
, "\\u%04x", ch
);
456 /* Print UTF8 string at STR of length LENGTH bytes to STREAM. */
459 jcf_print_utf8 (FILE *stream
, const unsigned char *str
, int length
)
461 const unsigned char * limit
= str
+ length
;
464 int ch
= UTF8_GET (str
, limit
);
467 fprintf (stream
, "\\<invalid>");
470 jcf_print_char (stream
, ch
);
474 /* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */
477 jcf_print_utf8_replace (FILE *stream
, const unsigned char *str
, int length
,
478 int in_char
, int out_char
)
480 const unsigned char *limit
= str
+ length
;
483 int ch
= UTF8_GET (str
, limit
);
486 fprintf (stream
, "\\<invalid>");
489 jcf_print_char (stream
, ch
== in_char
? out_char
: ch
);
493 /* Check that all the cross-references in the constant pool are
494 valid. Returns 0 on success.
495 Otherwise, returns the index of the (first) invalid entry.
496 Only checks internal consistency, but does not check that
497 any classes, fields, or methods are valid.*/
500 verify_constant_pool (JCF
*jcf
)
503 for (i
= 1; i
< JPOOL_SIZE (jcf
); i
++)
505 switch (JPOOL_TAG (jcf
, i
))
507 case CONSTANT_NameAndType
:
508 n
= JPOOL_USHORT2 (jcf
, i
);
509 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
510 || JPOOL_TAG (jcf
, n
) != CONSTANT_Utf8
)
512 /* ... fall through ... */
514 case CONSTANT_String
:
515 n
= JPOOL_USHORT1 (jcf
, i
);
516 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
517 || JPOOL_TAG (jcf
, n
) != CONSTANT_Utf8
)
520 case CONSTANT_Fieldref
:
521 case CONSTANT_Methodref
:
522 case CONSTANT_InterfaceMethodref
:
523 n
= JPOOL_USHORT1 (jcf
, i
);
524 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
525 || JPOOL_TAG (jcf
, n
) != CONSTANT_Class
)
527 n
= JPOOL_USHORT2 (jcf
, i
);
528 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
529 || JPOOL_TAG (jcf
, n
) != CONSTANT_NameAndType
)
533 case CONSTANT_Double
:
537 case CONSTANT_Integer
:
539 case CONSTANT_Unicode
:
541 case CONSTANT_MethodHandle
:
542 n
= JPOOL_USHORT1 (jcf
, i
);
545 n
= JPOOL_USHORT2 (jcf
, i
);
546 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
))
549 case CONSTANT_MethodType
:
550 n
= JPOOL_USHORT1 (jcf
, i
);
551 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
552 || JPOOL_TAG (jcf
, n
) != CONSTANT_Utf8
)
555 case CONSTANT_InvokeDynamic
:
556 n
= JPOOL_USHORT2 (jcf
, i
);
557 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
558 || JPOOL_TAG (jcf
, n
) != CONSTANT_NameAndType
)
569 format_uint (char *buffer
, uint64 value
, int base
)
571 #define WRITE_BUF_SIZE (4 + sizeof(uint64) * 8)
572 char buf
[WRITE_BUF_SIZE
];
573 char *buf_ptr
= buf
+WRITE_BUF_SIZE
; /* End of buf. */
577 /* Now do the actual conversion, placing the result at the *end* of buf. */
578 /* Note this code does not pretend to be optimized. */
580 int digit
= value
% base
;
581 static const char digit_chars
[] = "0123456789abcdefghijklmnopqrstuvwxyz";
582 *--buf_ptr
= digit_chars
[digit
];
584 } while (value
!= 0);
586 chars_written
= buf
+WRITE_BUF_SIZE
- buf_ptr
;
587 for (i
= 0; i
< chars_written
; i
++)
588 buffer
[i
] = *buf_ptr
++;
593 format_int (char *buffer
, jlong value
, int base
)
598 abs_value
= -(uint64
)value
;
602 abs_value
= (uint64
) value
;
603 format_uint (buffer
, abs_value
, base
);