Home | History | Annotate | Download | only in gold
      1 // common.cc -- handle common symbols for gold
      2 
      3 // Copyright (C) 2006-2014 Free Software Foundation, Inc.
      4 // Written by Ian Lance Taylor <iant (at) google.com>.
      5 
      6 // This file is part of gold.
      7 
      8 // This program is free software; you can redistribute it and/or modify
      9 // it under the terms of the GNU General Public License as published by
     10 // the Free Software Foundation; either version 3 of the License, or
     11 // (at your option) any later version.
     12 
     13 // This program is distributed in the hope that it will be useful,
     14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16 // GNU General Public License for more details.
     17 
     18 // You should have received a copy of the GNU General Public License
     19 // along with this program; if not, write to the Free Software
     20 // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     21 // MA 02110-1301, USA.
     22 
     23 #include "gold.h"
     24 
     25 #include <algorithm>
     26 
     27 #include "workqueue.h"
     28 #include "mapfile.h"
     29 #include "layout.h"
     30 #include "output.h"
     31 #include "symtab.h"
     32 #include "common.h"
     33 
     34 namespace gold
     35 {
     36 
     37 // Allocate_commons_task methods.
     38 
     39 // This task allocates the common symbols.  We arrange to run it
     40 // before anything else which needs to access the symbol table.
     41 
     42 Task_token*
     43 Allocate_commons_task::is_runnable()
     44 {
     45   return NULL;
     46 }
     47 
     48 // Release a blocker.
     49 
     50 void
     51 Allocate_commons_task::locks(Task_locker* tl)
     52 {
     53   tl->add(this, this->blocker_);
     54 }
     55 
     56 // Allocate the common symbols.
     57 
     58 void
     59 Allocate_commons_task::run(Workqueue*)
     60 {
     61   this->symtab_->allocate_commons(this->layout_, this->mapfile_);
     62 }
     63 
     64 // This class is used to sort the common symbol.  We normally put the
     65 // larger common symbols first.  This can be changed by using
     66 // --sort-commons, which tells the linker to sort by alignment.
     67 
     68 template<int size>
     69 class Sort_commons
     70 {
     71  public:
     72   Sort_commons(const Symbol_table* symtab,
     73 	       Symbol_table::Sort_commons_order sort_order)
     74     : symtab_(symtab), sort_order_(sort_order)
     75   { }
     76 
     77   bool operator()(const Symbol* a, const Symbol* b) const;
     78 
     79  private:
     80   // The symbol table.
     81   const Symbol_table* symtab_;
     82   // How to sort.
     83   Symbol_table::Sort_commons_order sort_order_;
     84 };
     85 
     86 template<int size>
     87 bool
     88 Sort_commons<size>::operator()(const Symbol* pa, const Symbol* pb) const
     89 {
     90   if (pa == NULL)
     91     return false;
     92   if (pb == NULL)
     93     return true;
     94 
     95   const Symbol_table* symtab = this->symtab_;
     96   const Sized_symbol<size>* psa = symtab->get_sized_symbol<size>(pa);
     97   const Sized_symbol<size>* psb = symtab->get_sized_symbol<size>(pb);
     98 
     99   // The size.
    100   typename Sized_symbol<size>::Size_type sa = psa->symsize();
    101   typename Sized_symbol<size>::Size_type sb = psb->symsize();
    102 
    103   // The alignment.
    104   typename Sized_symbol<size>::Value_type aa = psa->value();
    105   typename Sized_symbol<size>::Value_type ab = psb->value();
    106 
    107   if (this->sort_order_ == Symbol_table::SORT_COMMONS_BY_ALIGNMENT_DESCENDING)
    108     {
    109       if (aa < ab)
    110 	return false;
    111       else if (ab < aa)
    112 	return true;
    113     }
    114   else if (this->sort_order_
    115 	   == Symbol_table::SORT_COMMONS_BY_ALIGNMENT_ASCENDING)
    116     {
    117       if (aa < ab)
    118 	return true;
    119       else if (ab < aa)
    120 	return false;
    121     }
    122   else
    123     gold_assert(this->sort_order_
    124 		== Symbol_table::SORT_COMMONS_BY_SIZE_DESCENDING);
    125 
    126   // Sort by descending size.
    127   if (sa < sb)
    128     return false;
    129   else if (sb < sa)
    130     return true;
    131 
    132   if (this->sort_order_ == Symbol_table::SORT_COMMONS_BY_SIZE_DESCENDING)
    133     {
    134       // When the symbols are the same size, we sort them by
    135       // alignment, largest alignment first.
    136       if (aa < ab)
    137 	return false;
    138       else if (ab < aa)
    139 	return true;
    140     }
    141 
    142   // Otherwise we stabilize the sort by sorting by name.
    143   return strcmp(psa->name(), psb->name()) < 0;
    144 }
    145 
    146 // Allocate the common symbols.
    147 
    148 void
    149 Symbol_table::allocate_commons(Layout* layout, Mapfile* mapfile)
    150 {
    151   Sort_commons_order sort_order;
    152   if (!parameters->options().user_set_sort_common())
    153     sort_order = SORT_COMMONS_BY_SIZE_DESCENDING;
    154   else
    155     {
    156       const char* order = parameters->options().sort_common();
    157       if (*order == '\0' || strcmp(order, "descending") == 0)
    158 	sort_order = SORT_COMMONS_BY_ALIGNMENT_DESCENDING;
    159       else if (strcmp(order, "ascending") == 0)
    160 	sort_order = SORT_COMMONS_BY_ALIGNMENT_ASCENDING;
    161       else
    162 	{
    163 	  gold_error("invalid --sort-common argument: %s", order);
    164 	  sort_order = SORT_COMMONS_BY_SIZE_DESCENDING;
    165 	}
    166     }
    167 
    168   if (parameters->target().get_size() == 32)
    169     {
    170 #if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
    171       this->do_allocate_commons<32>(layout, mapfile, sort_order);
    172 #else
    173       gold_unreachable();
    174 #endif
    175     }
    176   else if (parameters->target().get_size() == 64)
    177     {
    178 #if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
    179       this->do_allocate_commons<64>(layout, mapfile, sort_order);
    180 #else
    181       gold_unreachable();
    182 #endif
    183     }
    184   else
    185     gold_unreachable();
    186 }
    187 
    188 // Allocated the common symbols, sized version.
    189 
    190 template<int size>
    191 void
    192 Symbol_table::do_allocate_commons(Layout* layout, Mapfile* mapfile,
    193 				  Sort_commons_order sort_order)
    194 {
    195   if (!this->commons_.empty())
    196     this->do_allocate_commons_list<size>(layout, COMMONS_NORMAL,
    197 					 &this->commons_, mapfile,
    198 					 sort_order);
    199   if (!this->tls_commons_.empty())
    200     this->do_allocate_commons_list<size>(layout, COMMONS_TLS,
    201 					 &this->tls_commons_, mapfile,
    202 					 sort_order);
    203   if (!this->small_commons_.empty())
    204     this->do_allocate_commons_list<size>(layout, COMMONS_SMALL,
    205 					 &this->small_commons_, mapfile,
    206 					 sort_order);
    207   if (!this->large_commons_.empty())
    208     this->do_allocate_commons_list<size>(layout, COMMONS_LARGE,
    209 					 &this->large_commons_, mapfile,
    210 					 sort_order);
    211 }
    212 
    213 // Allocate the common symbols in a list.  IS_TLS indicates whether
    214 // these are TLS common symbols.
    215 
    216 template<int size>
    217 void
    218 Symbol_table::do_allocate_commons_list(
    219     Layout* layout,
    220     Commons_section_type commons_section_type,
    221     Commons_type* commons,
    222     Mapfile* mapfile,
    223     Sort_commons_order sort_order)
    224 {
    225   // We've kept a list of all the common symbols.  But the symbol may
    226   // have been resolved to a defined symbol by now.  And it may be a
    227   // forwarder.  First remove all non-common symbols.
    228   bool any = false;
    229   uint64_t addralign = 0;
    230   for (Commons_type::iterator p = commons->begin();
    231        p != commons->end();
    232        ++p)
    233     {
    234       Symbol* sym = *p;
    235       if (sym->is_forwarder())
    236 	{
    237 	  sym = this->resolve_forwards(sym);
    238 	  *p = sym;
    239 	}
    240       if (!sym->is_common())
    241 	*p = NULL;
    242       else
    243 	{
    244 	  any = true;
    245 	  Sized_symbol<size>* ssym = this->get_sized_symbol<size>(sym);
    246 	  if (ssym->value() > addralign)
    247 	    addralign = ssym->value();
    248 	}
    249     }
    250   if (!any)
    251     return;
    252 
    253   // Sort the common symbols.
    254   std::sort(commons->begin(), commons->end(),
    255 	    Sort_commons<size>(this, sort_order));
    256 
    257   // Place them in a newly allocated BSS section.
    258   elfcpp::Elf_Xword flags = elfcpp::SHF_WRITE | elfcpp::SHF_ALLOC;
    259   const char* name;
    260   const char* ds_name;
    261   switch (commons_section_type)
    262     {
    263     case COMMONS_NORMAL:
    264       name = ".bss";
    265       ds_name = "** common";
    266       break;
    267     case COMMONS_TLS:
    268       flags |= elfcpp::SHF_TLS;
    269       name = ".tbss";
    270       ds_name = "** tls common";
    271       break;
    272     case COMMONS_SMALL:
    273       flags |= parameters->target().small_common_section_flags();
    274       name = ".sbss";
    275       ds_name = "** small common";
    276       break;
    277     case COMMONS_LARGE:
    278       flags |= parameters->target().large_common_section_flags();
    279       name = ".lbss";
    280       ds_name = "** large common";
    281       break;
    282     default:
    283       gold_unreachable();
    284     }
    285 
    286   Output_data_space* poc;
    287   Output_section* os;
    288 
    289   if (!parameters->incremental_update())
    290     {
    291       poc = new Output_data_space(addralign, ds_name);
    292       os = layout->add_output_section_data(name, elfcpp::SHT_NOBITS, flags,
    293 					   poc, ORDER_INVALID, false);
    294     }
    295   else
    296     {
    297       // When doing an incremental update, we need to allocate each common
    298       // directly from the output section's free list.
    299       poc = NULL;
    300       os = layout->find_output_section(name);
    301     }
    302 
    303   if (os != NULL)
    304     {
    305       if (commons_section_type == COMMONS_SMALL)
    306 	os->set_is_small_section();
    307       else if (commons_section_type == COMMONS_LARGE)
    308 	os->set_is_large_section();
    309     }
    310 
    311   // Allocate them all.
    312 
    313   off_t off = 0;
    314   for (Commons_type::iterator p = commons->begin();
    315        p != commons->end();
    316        ++p)
    317     {
    318       Symbol* sym = *p;
    319       if (sym == NULL)
    320 	break;
    321 
    322       // Because we followed forwarding symbols above, but we didn't
    323       // do it reliably before adding symbols to the list, it is
    324       // possible for us to have the same symbol on the list twice.
    325       // This can happen in the horrible case where a program defines
    326       // a common symbol with the same name as a versioned libc
    327       // symbol.  That will show up here as a symbol which has already
    328       // been allocated and is therefore no longer a common symbol.
    329       if (!sym->is_common())
    330 	continue;
    331 
    332       Sized_symbol<size>* ssym = this->get_sized_symbol<size>(sym);
    333 
    334       // Record the symbol in the map file now, before we change its
    335       // value.  Pass the size in separately so that we don't have to
    336       // templatize the map code, which is not performance sensitive.
    337       if (mapfile != NULL)
    338 	mapfile->report_allocate_common(sym, ssym->symsize());
    339 
    340       if (poc != NULL)
    341 	{
    342 	  off = align_address(off, ssym->value());
    343 	  ssym->allocate_common(poc, off);
    344 	  off += ssym->symsize();
    345 	}
    346       else
    347 	{
    348 	  // For an incremental update, allocate from the free list.
    349 	  off = os->allocate(ssym->symsize(), ssym->value());
    350 	  if (off == -1)
    351 	    gold_fallback(_("out of patch space in section %s; "
    352 			    "relink with --incremental-full"),
    353 			  os->name());
    354 	  ssym->allocate_common(os, off);
    355 	}
    356     }
    357 
    358   if (poc != NULL)
    359     poc->set_current_data_size(off);
    360 
    361   commons->clear();
    362 }
    363 
    364 } // End namespace gold.
    365