2015-05-05 Yvan Roux <yvan.roux@linaro.org>
[official-gcc.git] / gcc / java / jcf-io.c
blob36ceb074cf305e402b6fc8119c300d236f6af8af
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 char *candidate);
291 static inline bool equal (const char *existing, const char *candidate);
294 inline hashval_t
295 charstar_hash::hash (const char *candidate)
297 return htab_hash_string (candidate);
300 inline bool
301 charstar_hash::equal (const char *existing, const char *candidate)
303 return strcmp (existing, candidate) == 0;
307 /* A hash table keeping track of class names that were not found
308 during class lookup. (There is no need to cache the values
309 associated with names that were found; they are saved in
310 IDENTIFIER_CLASS_VALUE.) */
311 static hash_table<charstar_hash> *memoized_class_lookups;
313 /* Returns a freshly malloc'd string with the fully qualified pathname
314 of the .class file for the class CLASSNAME. CLASSNAME must be
315 allocated in permanent storage; this function may retain a pointer
316 to it. Returns NULL on failure. If JCF != NULL, it is suitably
317 initialized. SOURCE_OK is true if we should also look for .java
318 file. */
320 const char *
321 find_class (const char *classname, int classname_length, JCF *jcf)
323 int fd;
324 int i, k, klass = -1;
325 struct stat class_buf;
326 char *dep_file;
327 void *entry;
328 int buflen;
329 char *buffer;
330 hashval_t hash;
332 /* Create the hash table, if it does not already exist. */
333 if (!memoized_class_lookups)
334 memoized_class_lookups = new hash_table<charstar_hash> (37);
336 /* Loop for this class in the hashtable. If it is present, we've
337 already looked for this class and failed to find it. */
338 hash = charstar_hash::hash (classname);
339 if (memoized_class_lookups->find_with_hash (classname, hash))
340 return NULL;
342 /* Allocate and zero out the buffer, since we don't explicitly put a
343 null pointer when we're copying it below. */
344 buflen = jcf_path_max_len () + classname_length + 10;
345 buffer = XNEWVAR (char, buflen);
346 memset (buffer, 0, buflen);
348 for (entry = jcf_path_start (); entry != NULL; entry = jcf_path_next (entry))
350 const char *path_name = jcf_path_name (entry);
351 if (klass != 0)
353 int dir_len;
355 strcpy (buffer, path_name);
356 i = strlen (buffer);
358 /* This is right because we know that `.zip' entries will have a
359 trailing slash. See jcf-path.c. */
360 dir_len = i - 1;
362 for (k = 0; k < classname_length; k++, i++)
364 char ch = classname[k];
365 buffer[i] = ch == '.' ? '/' : ch;
367 strcpy (buffer+i, ".class");
369 if (jcf_path_is_zipfile (entry))
371 int err_code;
372 JCF _jcf;
373 buffer[dir_len] = '\0';
374 SOURCE_FRONTEND_DEBUG
375 (("Trying [...%s]:%s",
376 &buffer[dir_len-(dir_len > 15 ? 15 : dir_len)],
377 buffer+dir_len+1));
378 if (jcf == NULL)
379 jcf = &_jcf;
380 err_code = open_in_zip (jcf, buffer, buffer+dir_len+1,
381 jcf_path_is_system (entry));
382 if (err_code == 0)
384 /* Should we check if .zip is out-of-date wrt .java? */
385 buffer[dir_len] = '(';
386 strcpy (buffer+i, ".class)");
387 if (jcf == &_jcf)
388 JCF_FINISH (jcf);
389 return buffer;
391 else
392 continue;
394 klass = stat (buffer, &class_buf);
398 dep_file = buffer;
399 if (!klass)
401 SOURCE_FRONTEND_DEBUG ((stderr, "[Class selected: %s]\n",
402 classname+classname_length-
403 (classname_length <= 30 ?
404 classname_length : 30)));
405 fd = JCF_OPEN_EXACT_CASE (buffer, O_RDONLY | O_BINARY);
406 if (fd >= 0)
407 goto found;
410 free (buffer);
412 /* Remember that this class could not be found so that we do not
413 have to look again. */
414 *memoized_class_lookups->find_slot_with_hash (classname, hash, INSERT)
415 = classname;
417 return NULL;
418 found:
420 const char *const tmp = open_class (buffer, jcf, fd, dep_file);
421 jcf->classname = xstrdup (classname);
422 return tmp;
426 void
427 jcf_print_char (FILE *stream, int ch)
429 switch (ch)
431 case '\'':
432 case '\\':
433 case '\"':
434 fprintf (stream, "\\%c", ch);
435 break;
436 case '\n':
437 fprintf (stream, "\\n");
438 break;
439 case '\t':
440 fprintf (stream, "\\t");
441 break;
442 case '\r':
443 fprintf (stream, "\\r");
444 break;
445 default:
446 if (ch >= ' ' && ch < 127)
447 putc (ch, stream);
448 else if (ch < 256)
449 fprintf (stream, "\\%03x", ch);
450 else
451 fprintf (stream, "\\u%04x", ch);
455 /* Print UTF8 string at STR of length LENGTH bytes to STREAM. */
457 void
458 jcf_print_utf8 (FILE *stream, const unsigned char *str, int length)
460 const unsigned char * limit = str + length;
461 while (str < limit)
463 int ch = UTF8_GET (str, limit);
464 if (ch < 0)
466 fprintf (stream, "\\<invalid>");
467 return;
469 jcf_print_char (stream, ch);
473 /* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */
475 void
476 jcf_print_utf8_replace (FILE *stream, const unsigned char *str, int length,
477 int in_char, int out_char)
479 const unsigned char *limit = str + length;
480 while (str < limit)
482 int ch = UTF8_GET (str, limit);
483 if (ch < 0)
485 fprintf (stream, "\\<invalid>");
486 return;
488 jcf_print_char (stream, ch == in_char ? out_char : ch);
492 /* Check that all the cross-references in the constant pool are
493 valid. Returns 0 on success.
494 Otherwise, returns the index of the (first) invalid entry.
495 Only checks internal consistency, but does not check that
496 any classes, fields, or methods are valid.*/
499 verify_constant_pool (JCF *jcf)
501 int i, n;
502 for (i = 1; i < JPOOL_SIZE (jcf); i++)
504 switch (JPOOL_TAG (jcf, i))
506 case CONSTANT_NameAndType:
507 n = JPOOL_USHORT2 (jcf, i);
508 if (n <= 0 || n >= JPOOL_SIZE(jcf)
509 || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
510 return i;
511 /* ... fall through ... */
512 case CONSTANT_Class:
513 case CONSTANT_String:
514 n = JPOOL_USHORT1 (jcf, i);
515 if (n <= 0 || n >= JPOOL_SIZE(jcf)
516 || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
517 return i;
518 break;
519 case CONSTANT_Fieldref:
520 case CONSTANT_Methodref:
521 case CONSTANT_InterfaceMethodref:
522 n = JPOOL_USHORT1 (jcf, i);
523 if (n <= 0 || n >= JPOOL_SIZE(jcf)
524 || JPOOL_TAG (jcf, n) != CONSTANT_Class)
525 return i;
526 n = JPOOL_USHORT2 (jcf, i);
527 if (n <= 0 || n >= JPOOL_SIZE(jcf)
528 || JPOOL_TAG (jcf, n) != CONSTANT_NameAndType)
529 return i;
530 break;
531 case CONSTANT_Long:
532 case CONSTANT_Double:
533 i++;
534 break;
535 case CONSTANT_Float:
536 case CONSTANT_Integer:
537 case CONSTANT_Utf8:
538 case CONSTANT_Unicode:
539 break;
540 case CONSTANT_MethodHandle:
541 n = JPOOL_USHORT1 (jcf, i);
542 if (n < 1 || n > 9)
543 return i;
544 n = JPOOL_USHORT2 (jcf, i);
545 if (n <= 0 || n >= JPOOL_SIZE(jcf))
546 return i;
547 break;
548 case CONSTANT_MethodType:
549 n = JPOOL_USHORT1 (jcf, i);
550 if (n <= 0 || n >= JPOOL_SIZE(jcf)
551 || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
552 return i;
553 break;
554 case CONSTANT_InvokeDynamic:
555 n = JPOOL_USHORT2 (jcf, i);
556 if (n <= 0 || n >= JPOOL_SIZE(jcf)
557 || JPOOL_TAG (jcf, n) != CONSTANT_NameAndType)
558 return i;
559 break;
560 default:
561 return i;
564 return 0;
567 void
568 format_uint (char *buffer, uint64 value, int base)
570 #define WRITE_BUF_SIZE (4 + sizeof(uint64) * 8)
571 char buf[WRITE_BUF_SIZE];
572 char *buf_ptr = buf+WRITE_BUF_SIZE; /* End of buf. */
573 int chars_written;
574 int i;
576 /* Now do the actual conversion, placing the result at the *end* of buf. */
577 /* Note this code does not pretend to be optimized. */
578 do {
579 int digit = value % base;
580 static const char digit_chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
581 *--buf_ptr = digit_chars[digit];
582 value /= base;
583 } while (value != 0);
585 chars_written = buf+WRITE_BUF_SIZE - buf_ptr;
586 for (i = 0; i < chars_written; i++)
587 buffer[i] = *buf_ptr++;
588 buffer[i] = 0;
591 void
592 format_int (char *buffer, jlong value, int base)
594 uint64 abs_value;
595 if (value < 0)
597 abs_value = -(uint64)value;
598 *buffer++ = '-';
600 else
601 abs_value = (uint64) value;
602 format_uint (buffer, abs_value, base);