+/* Read in the external symbols. */
+
+boolean
+_bfd_coff_get_external_symbols (abfd)
+ bfd *abfd;
+{
+ bfd_size_type symesz;
+ size_t size;
+ PTR syms;
+
+ if (obj_coff_external_syms (abfd) != NULL)
+ return true;
+
+ symesz = bfd_coff_symesz (abfd);
+
+ size = obj_raw_syment_count (abfd) * symesz;
+
+ syms = (PTR) bfd_malloc (size);
+ if (syms == NULL && size != 0)
+ return false;
+
+ if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0
+ || bfd_read (syms, size, 1, abfd) != size)
+ {
+ if (syms != NULL)
+ free (syms);
+ return false;
+ }
+
+ obj_coff_external_syms (abfd) = syms;
+
+ return true;
+}
+
+/* Read in the external strings. The strings are not loaded until
+ they are needed. This is because we have no simple way of
+ detecting a missing string table in an archive. */
+
+const char *
+_bfd_coff_read_string_table (abfd)
+ bfd *abfd;
+{
+ char extstrsize[STRING_SIZE_SIZE];
+ size_t strsize;
+ char *strings;
+
+ if (obj_coff_strings (abfd) != NULL)
+ return obj_coff_strings (abfd);
+
+ if (obj_sym_filepos (abfd) == 0)
+ {
+ bfd_set_error (bfd_error_no_symbols);
+ return NULL;
+ }
+
+ if (bfd_seek (abfd,
+ (obj_sym_filepos (abfd)
+ + obj_raw_syment_count (abfd) * bfd_coff_symesz (abfd)),
+ SEEK_SET) != 0)
+ return NULL;
+
+ if (bfd_read (extstrsize, sizeof extstrsize, 1, abfd) != sizeof extstrsize)
+ {
+ if (bfd_get_error () != bfd_error_file_truncated)
+ return NULL;
+
+ /* There is no string table. */
+ strsize = STRING_SIZE_SIZE;
+ }
+ else
+ {
+#if STRING_SIZE_SIZE == 4
+ strsize = bfd_h_get_32 (abfd, (bfd_byte *) extstrsize);
+#else
+ #error Change bfd_h_get_32
+#endif
+ }
+
+ if (strsize < STRING_SIZE_SIZE)
+ {
+ (*_bfd_error_handler)
+ ("%s: bad string table size %lu", bfd_get_filename (abfd),
+ (unsigned long) strsize);
+ bfd_set_error (bfd_error_bad_value);
+ return NULL;
+ }
+
+ strings = (char *) bfd_malloc (strsize);
+ if (strings == NULL)
+ return NULL;
+
+ if (bfd_read (strings + STRING_SIZE_SIZE,
+ strsize - STRING_SIZE_SIZE, 1, abfd)
+ != strsize - STRING_SIZE_SIZE)
+ {
+ free (strings);
+ return NULL;
+ }
+
+ obj_coff_strings (abfd) = strings;
+
+ return strings;
+}
+
+/* Free up the external symbols and strings read from a COFF file. */
+
+boolean
+_bfd_coff_free_symbols (abfd)
+ bfd *abfd;
+{
+ if (obj_coff_external_syms (abfd) != NULL
+ && ! obj_coff_keep_syms (abfd))
+ {
+ free (obj_coff_external_syms (abfd));
+ obj_coff_external_syms (abfd) = NULL;
+ }
+ if (obj_coff_strings (abfd) != NULL
+ && ! obj_coff_keep_strings (abfd))
+ {
+ free (obj_coff_strings (abfd));
+ obj_coff_strings (abfd) = NULL;
+ }
+ return true;
+}
+