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 d_stream
.zalloc
= (alloc_func
) 0;
206 d_stream
.zfree
= (free_func
) 0;
207 d_stream
.opaque
= (voidpf
) 0;
209 jcf
->buffer
= XNEWVEC (unsigned char, zipd
->uncompressed_size
);
210 d_stream
.next_out
= jcf
->buffer
;
211 d_stream
.avail_out
= zipd
->uncompressed_size
;
212 jcf
->buffer_end
= jcf
->buffer
+ zipd
->uncompressed_size
;
213 jcf
->read_ptr
= jcf
->buffer
;
214 jcf
->read_end
= jcf
->buffer_end
;
215 buffer
= XNEWVEC (char, zipd
->size
);
216 d_stream
.next_in
= (unsigned char *) buffer
;
217 d_stream
.avail_in
= zipd
->size
;
218 if (lseek (zipf
->fd
, zipd
->filestart
, 0) < 0
219 || read (zipf
->fd
, buffer
, zipd
->size
) != (long) zipd
->size
)
221 /* Handle NO_HEADER using undocumented zlib feature.
222 This is a very common hack. */
223 inflateInit2 (&d_stream
, -MAX_WBITS
);
224 inflate (&d_stream
, Z_NO_FLUSH
);
225 inflateEnd (&d_stream
);
233 open_class (const char *filename
, JCF
*jcf
, int fd
, const char *dep_name
)
237 struct stat stat_buf
;
238 if (fstat (fd
, &stat_buf
) != 0
239 || ! S_ISREG (stat_buf
.st_mode
))
241 perror ("Could not figure length of .class file");
244 if (dep_name
!= NULL
)
245 jcf_dependency_add_file (dep_name
, 0);
247 jcf
->buffer
= XNEWVEC (unsigned char, stat_buf
.st_size
);
248 jcf
->buffer_end
= jcf
->buffer
+ stat_buf
.st_size
;
249 jcf
->read_ptr
= jcf
->buffer
;
250 jcf
->read_end
= jcf
->buffer_end
;
251 jcf
->read_state
= NULL
;
252 jcf
->filename
= xstrdup (filename
);
253 if (read (fd
, jcf
->buffer
, stat_buf
.st_size
) != stat_buf
.st_size
)
255 perror ("Failed to read .class file");
259 jcf
->filbuf
= jcf_unexpected_eof
;
268 find_classfile (char *filename
, JCF
*jcf
, const char *dep_name
)
270 int fd
= open (filename
, O_RDONLY
| O_BINARY
);
273 return open_class (filename
, jcf
, fd
, dep_name
);
276 /* Returns 1 if the CLASSNAME (really a char *) matches the name
277 stored in TABLE_ENTRY (also a char *). */
280 memoized_class_lookup_eq (const void *table_entry
, const void *classname
)
282 return strcmp ((const char *)classname
, (const char *)table_entry
) == 0;
285 /* A hash table keeping track of class names that were not found
286 during class lookup. (There is no need to cache the values
287 associated with names that were found; they are saved in
288 IDENTIFIER_CLASS_VALUE.) */
289 static htab_t memoized_class_lookups
;
291 /* Returns a freshly malloc'd string with the fully qualified pathname
292 of the .class file for the class CLASSNAME. CLASSNAME must be
293 allocated in permanent storage; this function may retain a pointer
294 to it. Returns NULL on failure. If JCF != NULL, it is suitably
295 initialized. SOURCE_OK is true if we should also look for .java
299 find_class (const char *classname
, int classname_length
, JCF
*jcf
)
302 int i
, k
, klass
= -1;
303 struct stat class_buf
;
310 /* Create the hash table, if it does not already exist. */
311 if (!memoized_class_lookups
)
312 memoized_class_lookups
= htab_create (37,
314 memoized_class_lookup_eq
,
317 /* Loop for this class in the hashtable. If it is present, we've
318 already looked for this class and failed to find it. */
319 hash
= htab_hash_string (classname
);
320 if (htab_find_with_hash (memoized_class_lookups
, classname
, hash
))
323 /* Allocate and zero out the buffer, since we don't explicitly put a
324 null pointer when we're copying it below. */
325 buflen
= jcf_path_max_len () + classname_length
+ 10;
326 buffer
= XNEWVAR (char, buflen
);
327 memset (buffer
, 0, buflen
);
329 for (entry
= jcf_path_start (); entry
!= NULL
; entry
= jcf_path_next (entry
))
331 const char *path_name
= jcf_path_name (entry
);
336 strcpy (buffer
, path_name
);
339 /* This is right because we know that `.zip' entries will have a
340 trailing slash. See jcf-path.c. */
343 for (k
= 0; k
< classname_length
; k
++, i
++)
345 char ch
= classname
[k
];
346 buffer
[i
] = ch
== '.' ? '/' : ch
;
348 strcpy (buffer
+i
, ".class");
350 if (jcf_path_is_zipfile (entry
))
354 buffer
[dir_len
] = '\0';
355 SOURCE_FRONTEND_DEBUG
356 (("Trying [...%s]:%s",
357 &buffer
[dir_len
-(dir_len
> 15 ? 15 : dir_len
)],
361 err_code
= open_in_zip (jcf
, buffer
, buffer
+dir_len
+1,
362 jcf_path_is_system (entry
));
365 /* Should we check if .zip is out-of-date wrt .java? */
366 buffer
[dir_len
] = '(';
367 strcpy (buffer
+i
, ".class)");
375 klass
= stat (buffer
, &class_buf
);
382 SOURCE_FRONTEND_DEBUG ((stderr
, "[Class selected: %s]\n",
383 classname
+classname_length
-
384 (classname_length
<= 30 ?
385 classname_length
: 30)));
386 fd
= JCF_OPEN_EXACT_CASE (buffer
, O_RDONLY
| O_BINARY
);
393 /* Remember that this class could not be found so that we do not
394 have to look again. */
395 *htab_find_slot_with_hash (memoized_class_lookups
, classname
, hash
, INSERT
)
396 = (void *) CONST_CAST (char *, classname
);
401 const char *const tmp
= open_class (buffer
, jcf
, fd
, dep_file
);
402 jcf
->classname
= xstrdup (classname
);
408 jcf_print_char (FILE *stream
, int ch
)
415 fprintf (stream
, "\\%c", ch
);
418 fprintf (stream
, "\\n");
421 fprintf (stream
, "\\t");
424 fprintf (stream
, "\\r");
427 if (ch
>= ' ' && ch
< 127)
430 fprintf (stream
, "\\%03x", ch
);
432 fprintf (stream
, "\\u%04x", ch
);
436 /* Print UTF8 string at STR of length LENGTH bytes to STREAM. */
439 jcf_print_utf8 (FILE *stream
, const unsigned char *str
, int length
)
441 const unsigned char * limit
= str
+ length
;
444 int ch
= UTF8_GET (str
, limit
);
447 fprintf (stream
, "\\<invalid>");
450 jcf_print_char (stream
, ch
);
454 /* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */
457 jcf_print_utf8_replace (FILE *stream
, const unsigned char *str
, int length
,
458 int in_char
, int out_char
)
460 const unsigned char *limit
= str
+ length
;
463 int ch
= UTF8_GET (str
, limit
);
466 fprintf (stream
, "\\<invalid>");
469 jcf_print_char (stream
, ch
== in_char
? out_char
: ch
);
473 /* Check that all the cross-references in the constant pool are
474 valid. Returns 0 on success.
475 Otherwise, returns the index of the (first) invalid entry.
476 Only checks internal consistency, but does not check that
477 any classes, fields, or methods are valid.*/
480 verify_constant_pool (JCF
*jcf
)
483 for (i
= 1; i
< JPOOL_SIZE (jcf
); i
++)
485 switch (JPOOL_TAG (jcf
, i
))
487 case CONSTANT_NameAndType
:
488 n
= JPOOL_USHORT2 (jcf
, i
);
489 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
490 || JPOOL_TAG (jcf
, n
) != CONSTANT_Utf8
)
492 /* ... fall through ... */
494 case CONSTANT_String
:
495 n
= JPOOL_USHORT1 (jcf
, i
);
496 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
497 || JPOOL_TAG (jcf
, n
) != CONSTANT_Utf8
)
500 case CONSTANT_Fieldref
:
501 case CONSTANT_Methodref
:
502 case CONSTANT_InterfaceMethodref
:
503 n
= JPOOL_USHORT1 (jcf
, i
);
504 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
505 || JPOOL_TAG (jcf
, n
) != CONSTANT_Class
)
507 n
= JPOOL_USHORT2 (jcf
, i
);
508 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
509 || JPOOL_TAG (jcf
, n
) != CONSTANT_NameAndType
)
513 case CONSTANT_Double
:
517 case CONSTANT_Integer
:
519 case CONSTANT_Unicode
:
529 format_uint (char *buffer
, uint64 value
, int base
)
531 #define WRITE_BUF_SIZE (4 + sizeof(uint64) * 8)
532 char buf
[WRITE_BUF_SIZE
];
533 char *buf_ptr
= buf
+WRITE_BUF_SIZE
; /* End of buf. */
537 /* Now do the actual conversion, placing the result at the *end* of buf. */
538 /* Note this code does not pretend to be optimized. */
540 int digit
= value
% base
;
541 static const char digit_chars
[] = "0123456789abcdefghijklmnopqrstuvwxyz";
542 *--buf_ptr
= digit_chars
[digit
];
544 } while (value
!= 0);
546 chars_written
= buf
+WRITE_BUF_SIZE
- buf_ptr
;
547 for (i
= 0; i
< chars_written
; i
++)
548 buffer
[i
] = *buf_ptr
++;
553 format_int (char *buffer
, jlong value
, int base
)
558 abs_value
= -(uint64
)value
;
562 abs_value
= (uint64
) value
;
563 format_uint (buffer
, abs_value
, base
);