From: Jeff Law Date: Sat, 13 Nov 1993 23:28:34 +0000 (+0000) Subject: * som.c (som_prep_for_fixups): New function. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=aff977904874706286cb13dcc02439db6ac6f02b;p=binutils-gdb.git * som.c (som_prep_for_fixups): New function. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index e13c92b79eb..85327496ca9 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,7 @@ +Sat Nov 13 15:27:15 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * som.c (som_prep_for_fixups): New function. + Fri Nov 12 15:29:36 1993 Jeffrey A. Law (law@snake.cs.utah.edu) * som.c (som_write_object_contents): Do not abort. Flesh out. diff --git a/bfd/som.c b/bfd/som.c index 9139fab4713..e63d7d52003 100644 --- a/bfd/som.c +++ b/bfd/som.c @@ -161,6 +161,7 @@ static boolean som_prep_headers PARAMS ((bfd *)); static int som_sizeof_headers PARAMS ((bfd *, boolean)); static boolean som_write_headers PARAMS ((bfd *)); static boolean som_build_and_write_symbol_table PARAMS ((bfd *)); +static void som_prep_for_fixups PARAMS ((bfd *, asymbol **, unsigned long)); static reloc_howto_type som_hppa_howto_table[] = @@ -1443,6 +1444,102 @@ compare_syms (sym1, sym2) return 0; } +/* Perform various work in preparation for emitting the fixup stream. */ + +static void +som_prep_for_fixups (abfd, syms, num_syms) + bfd *abfd; + asymbol **syms; + unsigned long num_syms; +{ + int i; + asection *section; + + /* Most SOM relocations involving a symbol have a length which is + dependent on the index of the symbol. So symbols which are + used often in relocations should have a small index. */ + + /* First initialize the counters for each symbol. */ + for (i = 0; i < num_syms; i++) + { + /* Handle a section symbol; these have no pointers back to the + SOM symbol info. So we just use the pointer field (udata) + to hold the relocation count. + + FIXME. While we're here set the name of any section symbol + to something which will not screw GDB. How do other formats + deal with this?!? */ + if (som_symbol_data (syms[i]) == NULL) + { + syms[i]->flags |= BSF_SECTION_SYM; + syms[i]->name = "L$0\002"; + syms[i]->udata = (PTR) 0; + } + else + (*som_symbol_data (syms[i]))->reloc_count = 0; + } + + /* Now that the counters are initialized, make a weighted count + of how often a given symbol is used in a relocation. */ + for (section = abfd->sections; section != NULL; section = section->next) + { + int i; + + /* Does this section have any relocations? */ + if (section->reloc_count <= 0) + continue; + + /* Walk through each relocation for this section. */ + for (i = 1; i < section->reloc_count; i++) + { + arelent *reloc = section->orelocation[i]; + int scale; + + /* If no symbol, then there is no counter to increase. */ + if (reloc->sym_ptr_ptr == NULL) + continue; + + /* Scaling to encourage symbols involved in R_DP_RELATIVE + and R_CODE_ONE_SYMBOL relocations to come first. These + two relocations have single byte versions if the symbol + index is very small. */ + if (reloc->howto->type == R_DP_RELATIVE + || reloc->howto->type == R_CODE_ONE_SYMBOL) + scale = 2; + else + scale = 1; + + /* Handle section symbols by ramming the count in the udata + field. It will not be used and the count is very important + for these symbols. */ + if ((*reloc->sym_ptr_ptr)->flags & BSF_SECTION_SYM) + { + (*reloc->sym_ptr_ptr)->udata = + (PTR) ((int) (*reloc->sym_ptr_ptr)->udata + scale); + continue; + } + + /* A normal symbol. Increment the count. */ + (*som_symbol_data ((*reloc->sym_ptr_ptr)))->reloc_count += scale; + } + } + + /* Now sort the symbols. */ + qsort (syms, num_syms, sizeof (asymbol *), compare_syms); + + /* Compute the symbol indexes, they will be needed by the relocation + code. */ + for (i = 0; i < num_syms; i++) + { + /* A section symbol. Again, there is no pointer to backend symbol + information, so we reuse (abuse) the udata field again. */ + if (syms[i]->flags & BSF_SECTION_SYM) + syms[i]->udata = (PTR) i; + else + (*som_symbol_data (syms[i]))->index = i; + } +} + /* Finally, scribble out the various headers to the disk. */ static boolean