* 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:
parent
6863eb4b74
commit
3c37f9ca0c
|
@ -1,5 +1,9 @@
|
||||||
Sun Feb 13 14:30:00 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
|
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>.
|
* som.h: Include <lst.h> and <ar.h>.
|
||||||
|
|
||||||
Sat Feb 12 22:34:14 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
|
Sat Feb 12 22:34:14 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
|
||||||
|
|
382
bfd/som.c
382
bfd/som.c
|
@ -191,7 +191,14 @@ static const reloc_howto_type * som_bfd_reloc_type_lookup
|
||||||
PARAMS ((bfd_arch_info_type *, bfd_reloc_code_real_type));
|
PARAMS ((bfd_arch_info_type *, bfd_reloc_code_real_type));
|
||||||
static char som_section_type PARAMS ((const char *));
|
static char som_section_type PARAMS ((const char *));
|
||||||
static int som_decode_symclass PARAMS ((asymbol *));
|
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.
|
/* 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;
|
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. */
|
/* End of miscellaneous support functions. */
|
||||||
|
|
||||||
#define som_bfd_debug_info_start bfd_void
|
#define som_bfd_debug_info_start bfd_void
|
||||||
#define som_bfd_debug_info_end 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_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_openr_next_archived_file bfd_generic_openr_next_archived_file
|
||||||
#define som_generic_stat_arch_elt bfd_generic_stat_arch_elt
|
#define som_generic_stat_arch_elt bfd_generic_stat_arch_elt
|
||||||
#define som_slurp_armap bfd_false
|
#define som_truncate_arname bfd_bsd_truncate_arname
|
||||||
#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_get_lineno (struct lineno_cache_entry *(*)())bfd_nullvoidptr
|
#define som_get_lineno (struct lineno_cache_entry *(*)())bfd_nullvoidptr
|
||||||
#define som_close_and_cleanup bfd_generic_close_and_cleanup
|
#define som_close_and_cleanup bfd_generic_close_and_cleanup
|
||||||
|
|
Loading…
Reference in New Issue