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, 2009, 2010 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"
33 #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 /* Returns 1 if the CLASSNAME (really a char *) matches the name
275 stored in TABLE_ENTRY (also a char *). */
278 memoized_class_lookup_eq (const void *table_entry
, const void *classname
)
280 return strcmp ((const char *)classname
, (const char *)table_entry
) == 0;
283 /* A hash table keeping track of class names that were not found
284 during class lookup. (There is no need to cache the values
285 associated with names that were found; they are saved in
286 IDENTIFIER_CLASS_VALUE.) */
287 static htab_t memoized_class_lookups
;
289 /* Returns a freshly malloc'd string with the fully qualified pathname
290 of the .class file for the class CLASSNAME. CLASSNAME must be
291 allocated in permanent storage; this function may retain a pointer
292 to it. Returns NULL on failure. If JCF != NULL, it is suitably
293 initialized. SOURCE_OK is true if we should also look for .java
297 find_class (const char *classname
, int classname_length
, JCF
*jcf
)
300 int i
, k
, klass
= -1;
301 struct stat class_buf
;
308 /* Create the hash table, if it does not already exist. */
309 if (!memoized_class_lookups
)
310 memoized_class_lookups
= htab_create (37,
312 memoized_class_lookup_eq
,
315 /* Loop for this class in the hashtable. If it is present, we've
316 already looked for this class and failed to find it. */
317 hash
= htab_hash_string (classname
);
318 if (htab_find_with_hash (memoized_class_lookups
, classname
, hash
))
321 /* Allocate and zero out the buffer, since we don't explicitly put a
322 null pointer when we're copying it below. */
323 buflen
= jcf_path_max_len () + classname_length
+ 10;
324 buffer
= XNEWVAR (char, buflen
);
325 memset (buffer
, 0, buflen
);
327 for (entry
= jcf_path_start (); entry
!= NULL
; entry
= jcf_path_next (entry
))
329 const char *path_name
= jcf_path_name (entry
);
334 strcpy (buffer
, path_name
);
337 /* This is right because we know that `.zip' entries will have a
338 trailing slash. See jcf-path.c. */
341 for (k
= 0; k
< classname_length
; k
++, i
++)
343 char ch
= classname
[k
];
344 buffer
[i
] = ch
== '.' ? '/' : ch
;
346 strcpy (buffer
+i
, ".class");
348 if (jcf_path_is_zipfile (entry
))
352 buffer
[dir_len
] = '\0';
353 SOURCE_FRONTEND_DEBUG
354 (("Trying [...%s]:%s",
355 &buffer
[dir_len
-(dir_len
> 15 ? 15 : dir_len
)],
359 err_code
= open_in_zip (jcf
, buffer
, buffer
+dir_len
+1,
360 jcf_path_is_system (entry
));
363 /* Should we check if .zip is out-of-date wrt .java? */
364 buffer
[dir_len
] = '(';
365 strcpy (buffer
+i
, ".class)");
373 klass
= stat (buffer
, &class_buf
);
380 SOURCE_FRONTEND_DEBUG ((stderr
, "[Class selected: %s]\n",
381 classname
+classname_length
-
382 (classname_length
<= 30 ?
383 classname_length
: 30)));
384 fd
= JCF_OPEN_EXACT_CASE (buffer
, O_RDONLY
| O_BINARY
);
391 /* Remember that this class could not be found so that we do not
392 have to look again. */
393 *htab_find_slot_with_hash (memoized_class_lookups
, classname
, hash
, INSERT
)
394 = (void *) CONST_CAST (char *, classname
);
399 const char *const tmp
= open_class (buffer
, jcf
, fd
, dep_file
);
400 jcf
->classname
= xstrdup (classname
);
406 jcf_print_char (FILE *stream
, int ch
)
413 fprintf (stream
, "\\%c", ch
);
416 fprintf (stream
, "\\n");
419 fprintf (stream
, "\\t");
422 fprintf (stream
, "\\r");
425 if (ch
>= ' ' && ch
< 127)
428 fprintf (stream
, "\\%03x", ch
);
430 fprintf (stream
, "\\u%04x", ch
);
434 /* Print UTF8 string at STR of length LENGTH bytes to STREAM. */
437 jcf_print_utf8 (FILE *stream
, const unsigned char *str
, int length
)
439 const unsigned char * limit
= str
+ length
;
442 int ch
= UTF8_GET (str
, limit
);
445 fprintf (stream
, "\\<invalid>");
448 jcf_print_char (stream
, ch
);
452 /* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */
455 jcf_print_utf8_replace (FILE *stream
, const unsigned char *str
, int length
,
456 int in_char
, int out_char
)
458 const unsigned char *limit
= str
+ length
;
461 int ch
= UTF8_GET (str
, limit
);
464 fprintf (stream
, "\\<invalid>");
467 jcf_print_char (stream
, ch
== in_char
? out_char
: ch
);
471 /* Check that all the cross-references in the constant pool are
472 valid. Returns 0 on success.
473 Otherwise, returns the index of the (first) invalid entry.
474 Only checks internal consistency, but does not check that
475 any classes, fields, or methods are valid.*/
478 verify_constant_pool (JCF
*jcf
)
481 for (i
= 1; i
< JPOOL_SIZE (jcf
); i
++)
483 switch (JPOOL_TAG (jcf
, i
))
485 case CONSTANT_NameAndType
:
486 n
= JPOOL_USHORT2 (jcf
, i
);
487 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
488 || JPOOL_TAG (jcf
, n
) != CONSTANT_Utf8
)
490 /* ... fall through ... */
492 case CONSTANT_String
:
493 n
= JPOOL_USHORT1 (jcf
, i
);
494 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
495 || JPOOL_TAG (jcf
, n
) != CONSTANT_Utf8
)
498 case CONSTANT_Fieldref
:
499 case CONSTANT_Methodref
:
500 case CONSTANT_InterfaceMethodref
:
501 n
= JPOOL_USHORT1 (jcf
, i
);
502 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
503 || JPOOL_TAG (jcf
, n
) != CONSTANT_Class
)
505 n
= JPOOL_USHORT2 (jcf
, i
);
506 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
507 || JPOOL_TAG (jcf
, n
) != CONSTANT_NameAndType
)
511 case CONSTANT_Double
:
515 case CONSTANT_Integer
:
517 case CONSTANT_Unicode
:
519 case CONSTANT_MethodHandle
:
520 n
= JPOOL_USHORT1 (jcf
, i
);
523 n
= JPOOL_USHORT2 (jcf
, i
);
524 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
))
527 case CONSTANT_MethodType
:
528 n
= JPOOL_USHORT1 (jcf
, i
);
529 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
530 || JPOOL_TAG (jcf
, n
) != CONSTANT_Utf8
)
533 case CONSTANT_InvokeDynamic
:
534 n
= JPOOL_USHORT2 (jcf
, i
);
535 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
536 || JPOOL_TAG (jcf
, n
) != CONSTANT_NameAndType
)
547 format_uint (char *buffer
, uint64 value
, int base
)
549 #define WRITE_BUF_SIZE (4 + sizeof(uint64) * 8)
550 char buf
[WRITE_BUF_SIZE
];
551 char *buf_ptr
= buf
+WRITE_BUF_SIZE
; /* End of buf. */
555 /* Now do the actual conversion, placing the result at the *end* of buf. */
556 /* Note this code does not pretend to be optimized. */
558 int digit
= value
% base
;
559 static const char digit_chars
[] = "0123456789abcdefghijklmnopqrstuvwxyz";
560 *--buf_ptr
= digit_chars
[digit
];
562 } while (value
!= 0);
564 chars_written
= buf
+WRITE_BUF_SIZE
- buf_ptr
;
565 for (i
= 0; i
< chars_written
; i
++)
566 buffer
[i
] = *buf_ptr
++;
571 format_int (char *buffer
, jlong value
, int base
)
576 abs_value
= -(uint64
)value
;
580 abs_value
= (uint64
) value
;
581 format_uint (buffer
, abs_value
, base
);