* som.c (som_bfd_count_ar_symbols): New helper function.

(som_bfd_fill_in_ar_symbols): New helper function.
        (som_slurp_armap): New function to read a SOM LST.
This commit is contained in:
Jeff Law 1994-02-13 23:34:52 +00:00
parent 6863eb4b74
commit 3c37f9ca0c
2 changed files with 380 additions and 6 deletions

View File

@ -1,5 +1,9 @@
Sun Feb 13 14:30:00 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
* som.c (som_bfd_count_ar_symbols): New helper function.
(som_bfd_fill_in_ar_symbols): New helper function.
(som_slurp_armap): New function to read a SOM LST.
* som.h: Include <lst.h> and <ar.h>.
Sat Feb 12 22:34:14 1994 Jeffrey A. Law (law@snake.cs.utah.edu)

382
bfd/som.c
View File

@ -191,7 +191,14 @@ static const reloc_howto_type * som_bfd_reloc_type_lookup
PARAMS ((bfd_arch_info_type *, bfd_reloc_code_real_type));
static char som_section_type PARAMS ((const char *));
static int som_decode_symclass PARAMS ((asymbol *));
static boolean som_bfd_count_ar_symbols PARAMS ((bfd *, struct lst_header *,
symindex *));
static boolean som_bfd_fill_in_ar_symbols PARAMS ((bfd *, struct lst_header *,
carsym **syms));
static boolean som_slurp_armap PARAMS ((bfd *));
static boolean som_write_armap PARAMS ((bfd *));
static boolean som_slurp_extended_name_table PARAMS ((bfd *));
/* Map SOM section names to POSIX/BSD single-character symbol types.
@ -4190,18 +4197,381 @@ som_get_symbol_info (ignore_abfd, symbol, ret)
ret->name = symbol->name;
}
/* Count the number of symbols in the archive symbol table. Necessary
so that we can allocate space for all the carsyms at once. */
static boolean
som_bfd_count_ar_symbols (abfd, lst_header, count)
bfd *abfd;
struct lst_header *lst_header;
symindex *count;
{
unsigned int i;
unsigned int hash_table[lst_header->hash_size];
file_ptr lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
/* Don't forget to initialize the counter! */
*count = 0;
/* Read in the hash table. The has table is an array of 32bit file offsets
which point to the hash chains. */
if (bfd_read ((PTR) hash_table, lst_header->hash_size, 4, abfd)
!= lst_header->hash_size * 4)
{
bfd_error = system_call_error;
return false;
}
/* Walk each chain counting the number of symbols found on that particular
chain. */
for (i = 0; i < lst_header->hash_size; i++)
{
struct lst_symbol_record lst_symbol;
/* An empty chain has zero as it's file offset. */
if (hash_table[i] == 0)
continue;
/* Seek to the first symbol in this hash chain. */
if (bfd_seek (abfd, lst_filepos + hash_table[i], SEEK_SET) < 0)
{
bfd_error = system_call_error;
return false;
}
/* Read in this symbol and update the counter. */
if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
!= sizeof (lst_symbol))
{
bfd_error = system_call_error;
return false;
}
(*count)++;
/* Now iterate through the rest of the symbols on this chain. */
while (lst_symbol.next_entry)
{
/* Seek to the next symbol. */
if (bfd_seek (abfd, lst_filepos + lst_symbol.next_entry, SEEK_SET)
< 0)
{
bfd_error = system_call_error;
return false;
}
/* Read the symbol in and update the counter. */
if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
!= sizeof (lst_symbol))
{
bfd_error = system_call_error;
return false;
}
(*count)++;
}
}
return true;
}
/* Fill in the canonical archive symbols (SYMS) from the archive described
by ABFD and LST_HEADER. */
static boolean
som_bfd_fill_in_ar_symbols (abfd, lst_header, syms)
bfd *abfd;
struct lst_header *lst_header;
carsym **syms;
{
unsigned int i, len;
carsym *set = syms[0];
unsigned int hash_table[lst_header->hash_size];
struct som_entry som_dict[lst_header->module_count];
file_ptr lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
/* Read in the hash table. The has table is an array of 32bit file offsets
which point to the hash chains. */
if (bfd_read ((PTR) hash_table, lst_header->hash_size, 4, abfd)
!= lst_header->hash_size * 4)
{
bfd_error = system_call_error;
return false;
}
/* Seek to and read in the SOM dictionary. We will need this to fill
in the carsym's filepos field. */
if (bfd_seek (abfd, lst_filepos + lst_header->dir_loc, SEEK_SET) < 0)
{
bfd_error = system_call_error;
return false;
}
if (bfd_read ((PTR) som_dict, lst_header->module_count,
sizeof (struct som_entry), abfd)
!= lst_header->module_count * sizeof (struct som_entry))
{
bfd_error = system_call_error;
return false;
}
/* Walk each chain filling in the carsyms as we go along. */
for (i = 0; i < lst_header->hash_size; i++)
{
struct lst_symbol_record lst_symbol;
/* An empty chain has zero as it's file offset. */
if (hash_table[i] == 0)
continue;
/* Seek to and read the first symbol on the chain. */
if (bfd_seek (abfd, lst_filepos + hash_table[i], SEEK_SET) < 0)
{
bfd_error = system_call_error;
return false;
}
if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
!= sizeof (lst_symbol))
{
bfd_error = system_call_error;
return false;
}
/* Get the name of the symbol, first get the length which is stored
as a 32bit integer just before the symbol.
One might ask why we don't just read in the entire string table
and index into it. Well, according to the SOM ABI the string
index can point *anywhere* in the archive to save space, so just
using the string table would not be safe. */
if (bfd_seek (abfd, lst_filepos + lst_header->string_loc
+ lst_symbol.name.n_strx - 4, SEEK_SET) < 0)
{
bfd_error = system_call_error;
return false;
}
if (bfd_read (&len, 1, 4, abfd) != 4)
{
bfd_error = system_call_error;
return false;
}
/* Allocate space for the name and null terminate it too. */
set->name = bfd_zalloc (abfd, len + 1);
if (!set->name)
{
bfd_error = no_memory;
return false;
}
if (bfd_read (set->name, 1, len, abfd) != len)
{
bfd_error = system_call_error;
return false;
}
set->name[len] = 0;
/* Fill in the file offset. Note that the "location" field points
to the SOM itself, not the ar_hdr in front of it. */
set->file_offset = som_dict[lst_symbol.som_index].location
- sizeof (struct ar_hdr);
/* Go to the next symbol. */
set++;
/* Iterate through the rest of the chain. */
while (lst_symbol.next_entry)
{
/* Seek to the next symbol and read it in. */
if (bfd_seek (abfd, lst_filepos + lst_symbol.next_entry, SEEK_SET)
< 0)
{
bfd_error = system_call_error;
return false;
}
if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
!= sizeof (lst_symbol))
{
bfd_error = system_call_error;
return false;
}
/* Seek to the name length & string and read them in. */
if (bfd_seek (abfd, lst_filepos + lst_header->string_loc
+ lst_symbol.name.n_strx - 4, SEEK_SET) < 0)
{
bfd_error = system_call_error;
return false;
}
if (bfd_read (&len, 1, 4, abfd) != 4)
{
bfd_error = system_call_error;
return false;
}
/* Allocate space for the name and null terminate it too. */
set->name = bfd_zalloc (abfd, len + 1);
if (!set->name)
{
bfd_error = no_memory;
return false;
}
if (bfd_read (set->name, 1, len, abfd) != len)
{
bfd_error = system_call_error;
return false;
}
set->name[len] = 0;
/* Fill in the file offset. Note that the "location" field points
to the SOM itself, not the ar_hdr in front of it. */
set->file_offset = som_dict[lst_symbol.som_index].location
- sizeof (struct ar_hdr);
/* Go on to the next symbol. */
set++;
}
}
/* If we haven't died by now, then we successfully read the entire
archive symbol table. */
return true;
}
/* Read in the LST from the archive. */
static boolean
som_slurp_armap (abfd)
bfd *abfd;
{
struct lst_header lst_header;
struct ar_hdr ar_header;
unsigned int parsed_size;
struct artdata *ardata = bfd_ardata (abfd);
char nextname[17];
int i = bfd_read ((PTR) nextname, 1, 16, abfd);
/* Special cases. */
if (i == 0)
return true;
if (i != 16)
return false;
if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) < 0)
{
bfd_error = system_call_error;
return false;
}
/* For archives without .o files there is no symbol table. */
if (strncmp (nextname, "/ ", 16))
{
bfd_has_map (abfd) = false;
return true;
}
/* Read in and sanity check the archive header. */
if (bfd_read ((PTR) &ar_header, 1, sizeof (struct ar_hdr), abfd)
!= sizeof (struct ar_hdr))
{
bfd_error = system_call_error;
return false;
}
if (strncmp (ar_header.ar_fmag, ARFMAG, 2))
{
bfd_error = malformed_archive;
return NULL;
}
/* How big is the archive symbol table entry? */
errno = 0;
parsed_size = strtol (ar_header.ar_size, NULL, 10);
if (errno != 0)
{
bfd_error = malformed_archive;
return NULL;
}
/* Save off the file offset of the first real user data. */
ardata->first_file_filepos = bfd_tell (abfd) + parsed_size;
/* Read in the library symbol table. We'll make heavy use of this
in just a minute. */
if (bfd_read ((PTR) & lst_header, 1, sizeof (struct lst_header), abfd)
!= sizeof (struct lst_header))
{
bfd_error = system_call_error;
return false;
}
/* Sanity check. */
if (lst_header.a_magic != LIBMAGIC)
{
bfd_error = malformed_archive;
return NULL;
}
/* Count the number of symbols in the library symbol table. */
if (som_bfd_count_ar_symbols (abfd, &lst_header, &ardata->symdef_count)
== false)
return false;
/* Get back to the start of the library symbol table. */
if (bfd_seek (abfd, ardata->first_file_filepos - parsed_size
+ sizeof (struct lst_header), SEEK_SET) < 0)
{
bfd_error = system_call_error;
return false;
}
/* Initializae the cache and allocate space for the library symbols. */
ardata->cache = 0;
ardata->symdefs = (carsym *) bfd_alloc (abfd,
(ardata->symdef_count
* sizeof (carsym)));
if (!ardata->symdefs)
{
bfd_error = no_memory;
return false;
}
/* Now fill in the canonical archive symbols. */
if (som_bfd_fill_in_ar_symbols (abfd, &lst_header, &ardata->symdefs)
== false)
return false;
/* Notify the generic archive code that we have a symbol map. */
bfd_has_map (abfd) = true;
return true;
}
/* Write out the LST for the archive. Not supported yet. */
static boolean
som_write_armap (abfd)
bfd *abfd;
{
return false;
}
/* Apparently the extened names are never used, even though they appear
in the SOM ABI. Hmmm. */
static boolean
som_slurp_extended_name_table (abfd)
bfd *abfd;
{
bfd_ardata (abfd)->extended_names = NULL;
return true;
}
/* End of miscellaneous support functions. */
#define som_bfd_debug_info_start bfd_void
#define som_bfd_debug_info_end bfd_void
#define som_bfd_debug_info_accumulate (PROTO(void,(*),(bfd*, struct sec *))) bfd_void
#define som_openr_next_archived_file bfd_generic_openr_next_archived_file
#define som_generic_stat_arch_elt bfd_generic_stat_arch_elt
#define som_slurp_armap bfd_false
#define som_slurp_extended_name_table _bfd_slurp_extended_name_table
#define som_truncate_arname (void (*)())bfd_nullvoidptr
#define som_write_armap 0
#define som_openr_next_archived_file bfd_generic_openr_next_archived_file
#define som_generic_stat_arch_elt bfd_generic_stat_arch_elt
#define som_truncate_arname bfd_bsd_truncate_arname
#define som_get_lineno (struct lineno_cache_entry *(*)())bfd_nullvoidptr
#define som_close_and_cleanup bfd_generic_close_and_cleanup