PR go/64999
[official-gcc.git] / gcc / java / jcf-io.c
blob2c48f143c2a90199e8adc97d012e8380256bc8a9
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)
9 any later version.
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. */
26 #include "config.h"
27 #include "system.h"
28 #include "coretypes.h"
30 #include "jcf.h"
31 #include "hash-set.h"
32 #include "machmode.h"
33 #include "vec.h"
34 #include "double-int.h"
35 #include "input.h"
36 #include "alias.h"
37 #include "symtab.h"
38 #include "options.h"
39 #include "wide-int.h"
40 #include "inchash.h"
41 #include "tree.h"
42 #include "java-tree.h"
43 #include "hash-table.h"
44 #include <dirent.h>
46 #include "zlib.h"
48 int
49 jcf_unexpected_eof (JCF *jcf, int count ATTRIBUTE_UNUSED)
51 if (jcf->filename)
52 fprintf (stderr, "Premature end of .class file %s.\n", jcf->filename);
53 else
54 fprintf (stderr, "Premature end of .class file <stdin>.\n");
55 exit (-1);
58 void
59 jcf_trim_old_input (JCF *jcf)
61 int count = jcf->read_ptr - jcf->buffer;
62 if (count > 0)
64 memmove (jcf->buffer, jcf->read_ptr, jcf->read_end - jcf->read_ptr);
65 jcf->read_ptr -= count;
66 jcf->read_end -= count;
70 int
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;
89 if (count <= 0)
90 return 0;
91 if ((int) fread (jcf->read_end, 1, count, file) != count)
92 jcf_unexpected_eof (jcf, count);
93 jcf->read_end += count;
94 return 0;
97 #include "zipfile.h"
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.
106 ZipFile *
107 opendir_in_zip (const char *zipfile, int is_system)
109 struct ZipFile* zipf;
110 char magic [4];
111 int fd;
112 for (zipf = SeenZipFiles; zipf != NULL; zipf = zipf->next)
114 if (strcmp (zipf->name, zipfile) == 0)
115 return zipf;
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);
123 zipf->fd = fd;
124 if (fd < 0)
126 /* A missing zip file is not considered an error.
127 We may want to re-consider that. FIXME. */
128 zipf->count = 0;
129 zipf->dir_size = 0;
130 zipf->central_directory = NULL;
132 else
134 jcf_dependency_add_file (zipfile, is_system);
135 if (read (fd, magic, 4) != 4 || GET_u4 (magic) != (JCF_u4)ZIPMAGIC)
137 free (zipf);
138 close (fd);
139 return NULL;
141 lseek (fd, 0L, SEEK_SET);
142 if (read_zip_archive (zipf) != 0)
144 free (zipf);
145 close (fd);
146 return NULL;
150 SeenZipFiles = zipf;
151 return zipf;
154 /* Returns:
155 0: OK - zipmember found.
156 -1: Not found.
157 -2: Malformed archive.
161 open_in_zip (JCF *jcf, const char *zipfile, const char *zipmember,
162 int is_system)
164 ZipDirectory *zipd;
165 int i, len;
166 ZipFile *zipf = opendir_in_zip (zipfile, is_system);
168 if (zipf == NULL)
169 return -2;
171 if (!zipmember)
172 return 0;
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)
182 JCF_ZERO (jcf);
184 jcf->filename = xstrdup (zipfile);
185 jcf->classname = xstrdup (zipmember);
186 return read_zip_member(jcf, zipd, zipf);
189 return -1;
192 /* Read data from zip archive member. */
195 read_zip_member (JCF *jcf, ZipDirectory *zipd, ZipFile *zipf)
197 jcf->filbuf = jcf_unexpected_eof;
198 jcf->zipd = zipd;
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)
208 return -2;
210 else
212 char *buffer;
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)
227 return -2;
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);
233 free (buffer);
236 return 0;
239 const char *
240 open_class (const char *filename, JCF *jcf, int fd, const char *dep_name)
242 if (jcf)
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");
249 return NULL;
251 if (dep_name != NULL)
252 jcf_dependency_add_file (dep_name, 0);
253 JCF_ZERO (jcf);
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");
263 return NULL;
265 close (fd);
266 jcf->filbuf = jcf_unexpected_eof;
268 else
269 close (fd);
270 return filename;
274 const char *
275 find_classfile (char *filename, JCF *jcf, const char *dep_name)
277 int fd = open (filename, O_RDONLY | O_BINARY);
278 if (fd < 0)
279 return NULL;
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);
295 inline hashval_t
296 charstar_hash::hash (const value_type *candidate)
298 return htab_hash_string (candidate);
301 inline bool
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
319 file. */
321 const char *
322 find_class (const char *classname, int classname_length, JCF *jcf)
324 int fd;
325 int i, k, klass = -1;
326 struct stat class_buf;
327 char *dep_file;
328 void *entry;
329 int buflen;
330 char *buffer;
331 hashval_t hash;
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))
341 return NULL;
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);
352 if (klass != 0)
354 int dir_len;
356 strcpy (buffer, path_name);
357 i = strlen (buffer);
359 /* This is right because we know that `.zip' entries will have a
360 trailing slash. See jcf-path.c. */
361 dir_len = i - 1;
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))
372 int err_code;
373 JCF _jcf;
374 buffer[dir_len] = '\0';
375 SOURCE_FRONTEND_DEBUG
376 (("Trying [...%s]:%s",
377 &buffer[dir_len-(dir_len > 15 ? 15 : dir_len)],
378 buffer+dir_len+1));
379 if (jcf == NULL)
380 jcf = &_jcf;
381 err_code = open_in_zip (jcf, buffer, buffer+dir_len+1,
382 jcf_path_is_system (entry));
383 if (err_code == 0)
385 /* Should we check if .zip is out-of-date wrt .java? */
386 buffer[dir_len] = '(';
387 strcpy (buffer+i, ".class)");
388 if (jcf == &_jcf)
389 JCF_FINISH (jcf);
390 return buffer;
392 else
393 continue;
395 klass = stat (buffer, &class_buf);
399 dep_file = buffer;
400 if (!klass)
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);
407 if (fd >= 0)
408 goto found;
411 free (buffer);
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)
416 = classname;
418 return NULL;
419 found:
421 const char *const tmp = open_class (buffer, jcf, fd, dep_file);
422 jcf->classname = xstrdup (classname);
423 return tmp;
427 void
428 jcf_print_char (FILE *stream, int ch)
430 switch (ch)
432 case '\'':
433 case '\\':
434 case '\"':
435 fprintf (stream, "\\%c", ch);
436 break;
437 case '\n':
438 fprintf (stream, "\\n");
439 break;
440 case '\t':
441 fprintf (stream, "\\t");
442 break;
443 case '\r':
444 fprintf (stream, "\\r");
445 break;
446 default:
447 if (ch >= ' ' && ch < 127)
448 putc (ch, stream);
449 else if (ch < 256)
450 fprintf (stream, "\\%03x", ch);
451 else
452 fprintf (stream, "\\u%04x", ch);
456 /* Print UTF8 string at STR of length LENGTH bytes to STREAM. */
458 void
459 jcf_print_utf8 (FILE *stream, const unsigned char *str, int length)
461 const unsigned char * limit = str + length;
462 while (str < limit)
464 int ch = UTF8_GET (str, limit);
465 if (ch < 0)
467 fprintf (stream, "\\<invalid>");
468 return;
470 jcf_print_char (stream, ch);
474 /* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */
476 void
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;
481 while (str < limit)
483 int ch = UTF8_GET (str, limit);
484 if (ch < 0)
486 fprintf (stream, "\\<invalid>");
487 return;
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)
502 int i, n;
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)
511 return i;
512 /* ... fall through ... */
513 case CONSTANT_Class:
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)
518 return i;
519 break;
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)
526 return i;
527 n = JPOOL_USHORT2 (jcf, i);
528 if (n <= 0 || n >= JPOOL_SIZE(jcf)
529 || JPOOL_TAG (jcf, n) != CONSTANT_NameAndType)
530 return i;
531 break;
532 case CONSTANT_Long:
533 case CONSTANT_Double:
534 i++;
535 break;
536 case CONSTANT_Float:
537 case CONSTANT_Integer:
538 case CONSTANT_Utf8:
539 case CONSTANT_Unicode:
540 break;
541 case CONSTANT_MethodHandle:
542 n = JPOOL_USHORT1 (jcf, i);
543 if (n < 1 || n > 9)
544 return i;
545 n = JPOOL_USHORT2 (jcf, i);
546 if (n <= 0 || n >= JPOOL_SIZE(jcf))
547 return i;
548 break;
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)
553 return i;
554 break;
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)
559 return i;
560 break;
561 default:
562 return i;
565 return 0;
568 void
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. */
574 int chars_written;
575 int i;
577 /* Now do the actual conversion, placing the result at the *end* of buf. */
578 /* Note this code does not pretend to be optimized. */
579 do {
580 int digit = value % base;
581 static const char digit_chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
582 *--buf_ptr = digit_chars[digit];
583 value /= base;
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++;
589 buffer[i] = 0;
592 void
593 format_int (char *buffer, jlong value, int base)
595 uint64 abs_value;
596 if (value < 0)
598 abs_value = -(uint64)value;
599 *buffer++ = '-';
601 else
602 abs_value = (uint64) value;
603 format_uint (buffer, abs_value, base);