xref: /netbsd-src/external/gpl3/binutils.old/dist/gold/common.cc (revision e992f068c547fd6e84b3f104dc2340adcc955732)
175fd0b74Schristos // common.cc -- handle common symbols for gold
275fd0b74Schristos 
3*e992f068Schristos // Copyright (C) 2006-2022 Free Software Foundation, Inc.
475fd0b74Schristos // Written by Ian Lance Taylor <iant@google.com>.
575fd0b74Schristos 
675fd0b74Schristos // This file is part of gold.
775fd0b74Schristos 
875fd0b74Schristos // This program is free software; you can redistribute it and/or modify
975fd0b74Schristos // it under the terms of the GNU General Public License as published by
1075fd0b74Schristos // the Free Software Foundation; either version 3 of the License, or
1175fd0b74Schristos // (at your option) any later version.
1275fd0b74Schristos 
1375fd0b74Schristos // This program is distributed in the hope that it will be useful,
1475fd0b74Schristos // but WITHOUT ANY WARRANTY; without even the implied warranty of
1575fd0b74Schristos // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1675fd0b74Schristos // GNU General Public License for more details.
1775fd0b74Schristos 
1875fd0b74Schristos // You should have received a copy of the GNU General Public License
1975fd0b74Schristos // along with this program; if not, write to the Free Software
2075fd0b74Schristos // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
2175fd0b74Schristos // MA 02110-1301, USA.
2275fd0b74Schristos 
2375fd0b74Schristos #include "gold.h"
2475fd0b74Schristos 
2575fd0b74Schristos #include <algorithm>
2675fd0b74Schristos 
2775fd0b74Schristos #include "workqueue.h"
2875fd0b74Schristos #include "mapfile.h"
2975fd0b74Schristos #include "layout.h"
3075fd0b74Schristos #include "output.h"
3175fd0b74Schristos #include "symtab.h"
3275fd0b74Schristos #include "common.h"
3375fd0b74Schristos 
3475fd0b74Schristos namespace gold
3575fd0b74Schristos {
3675fd0b74Schristos 
3775fd0b74Schristos // Allocate_commons_task methods.
3875fd0b74Schristos 
3975fd0b74Schristos // This task allocates the common symbols.  We arrange to run it
4075fd0b74Schristos // before anything else which needs to access the symbol table.
4175fd0b74Schristos 
4275fd0b74Schristos Task_token*
is_runnable()4375fd0b74Schristos Allocate_commons_task::is_runnable()
4475fd0b74Schristos {
4575fd0b74Schristos   return NULL;
4675fd0b74Schristos }
4775fd0b74Schristos 
4875fd0b74Schristos // Release a blocker.
4975fd0b74Schristos 
5075fd0b74Schristos void
locks(Task_locker * tl)5175fd0b74Schristos Allocate_commons_task::locks(Task_locker* tl)
5275fd0b74Schristos {
5375fd0b74Schristos   tl->add(this, this->blocker_);
5475fd0b74Schristos }
5575fd0b74Schristos 
5675fd0b74Schristos // Allocate the common symbols.
5775fd0b74Schristos 
5875fd0b74Schristos void
run(Workqueue *)5975fd0b74Schristos Allocate_commons_task::run(Workqueue*)
6075fd0b74Schristos {
6175fd0b74Schristos   this->symtab_->allocate_commons(this->layout_, this->mapfile_);
6275fd0b74Schristos }
6375fd0b74Schristos 
6475fd0b74Schristos // This class is used to sort the common symbol.  We normally put the
6575fd0b74Schristos // larger common symbols first.  This can be changed by using
6675fd0b74Schristos // --sort-commons, which tells the linker to sort by alignment.
6775fd0b74Schristos 
6875fd0b74Schristos template<int size>
6975fd0b74Schristos class Sort_commons
7075fd0b74Schristos {
7175fd0b74Schristos  public:
Sort_commons(const Symbol_table * symtab,Symbol_table::Sort_commons_order sort_order)7275fd0b74Schristos   Sort_commons(const Symbol_table* symtab,
7375fd0b74Schristos 	       Symbol_table::Sort_commons_order sort_order)
7475fd0b74Schristos     : symtab_(symtab), sort_order_(sort_order)
7575fd0b74Schristos   { }
7675fd0b74Schristos 
7775fd0b74Schristos   bool operator()(const Symbol* a, const Symbol* b) const;
7875fd0b74Schristos 
7975fd0b74Schristos  private:
8075fd0b74Schristos   // The symbol table.
8175fd0b74Schristos   const Symbol_table* symtab_;
8275fd0b74Schristos   // How to sort.
8375fd0b74Schristos   Symbol_table::Sort_commons_order sort_order_;
8475fd0b74Schristos };
8575fd0b74Schristos 
8675fd0b74Schristos template<int size>
8775fd0b74Schristos bool
operator ()(const Symbol * pa,const Symbol * pb) const8875fd0b74Schristos Sort_commons<size>::operator()(const Symbol* pa, const Symbol* pb) const
8975fd0b74Schristos {
9075fd0b74Schristos   if (pa == NULL)
9175fd0b74Schristos     return false;
9275fd0b74Schristos   if (pb == NULL)
9375fd0b74Schristos     return true;
9475fd0b74Schristos 
9575fd0b74Schristos   const Symbol_table* symtab = this->symtab_;
9675fd0b74Schristos   const Sized_symbol<size>* psa = symtab->get_sized_symbol<size>(pa);
9775fd0b74Schristos   const Sized_symbol<size>* psb = symtab->get_sized_symbol<size>(pb);
9875fd0b74Schristos 
9975fd0b74Schristos   // The size.
10075fd0b74Schristos   typename Sized_symbol<size>::Size_type sa = psa->symsize();
10175fd0b74Schristos   typename Sized_symbol<size>::Size_type sb = psb->symsize();
10275fd0b74Schristos 
10375fd0b74Schristos   // The alignment.
10475fd0b74Schristos   typename Sized_symbol<size>::Value_type aa = psa->value();
10575fd0b74Schristos   typename Sized_symbol<size>::Value_type ab = psb->value();
10675fd0b74Schristos 
10775fd0b74Schristos   if (this->sort_order_ == Symbol_table::SORT_COMMONS_BY_ALIGNMENT_DESCENDING)
10875fd0b74Schristos     {
10975fd0b74Schristos       if (aa < ab)
11075fd0b74Schristos 	return false;
11175fd0b74Schristos       else if (ab < aa)
11275fd0b74Schristos 	return true;
11375fd0b74Schristos     }
11475fd0b74Schristos   else if (this->sort_order_
11575fd0b74Schristos 	   == Symbol_table::SORT_COMMONS_BY_ALIGNMENT_ASCENDING)
11675fd0b74Schristos     {
11775fd0b74Schristos       if (aa < ab)
11875fd0b74Schristos 	return true;
11975fd0b74Schristos       else if (ab < aa)
12075fd0b74Schristos 	return false;
12175fd0b74Schristos     }
12275fd0b74Schristos   else
12375fd0b74Schristos     gold_assert(this->sort_order_
12475fd0b74Schristos 		== Symbol_table::SORT_COMMONS_BY_SIZE_DESCENDING);
12575fd0b74Schristos 
12675fd0b74Schristos   // Sort by descending size.
12775fd0b74Schristos   if (sa < sb)
12875fd0b74Schristos     return false;
12975fd0b74Schristos   else if (sb < sa)
13075fd0b74Schristos     return true;
13175fd0b74Schristos 
13275fd0b74Schristos   if (this->sort_order_ == Symbol_table::SORT_COMMONS_BY_SIZE_DESCENDING)
13375fd0b74Schristos     {
13475fd0b74Schristos       // When the symbols are the same size, we sort them by
13575fd0b74Schristos       // alignment, largest alignment first.
13675fd0b74Schristos       if (aa < ab)
13775fd0b74Schristos 	return false;
13875fd0b74Schristos       else if (ab < aa)
13975fd0b74Schristos 	return true;
14075fd0b74Schristos     }
14175fd0b74Schristos 
14275fd0b74Schristos   // Otherwise we stabilize the sort by sorting by name.
14375fd0b74Schristos   return strcmp(psa->name(), psb->name()) < 0;
14475fd0b74Schristos }
14575fd0b74Schristos 
14675fd0b74Schristos // Allocate the common symbols.
14775fd0b74Schristos 
14875fd0b74Schristos void
allocate_commons(Layout * layout,Mapfile * mapfile)14975fd0b74Schristos Symbol_table::allocate_commons(Layout* layout, Mapfile* mapfile)
15075fd0b74Schristos {
15175fd0b74Schristos   Sort_commons_order sort_order;
15275fd0b74Schristos   if (!parameters->options().user_set_sort_common())
15375fd0b74Schristos     sort_order = SORT_COMMONS_BY_SIZE_DESCENDING;
15475fd0b74Schristos   else
15575fd0b74Schristos     {
15675fd0b74Schristos       const char* order = parameters->options().sort_common();
15775fd0b74Schristos       if (*order == '\0' || strcmp(order, "descending") == 0)
15875fd0b74Schristos 	sort_order = SORT_COMMONS_BY_ALIGNMENT_DESCENDING;
15975fd0b74Schristos       else if (strcmp(order, "ascending") == 0)
16075fd0b74Schristos 	sort_order = SORT_COMMONS_BY_ALIGNMENT_ASCENDING;
16175fd0b74Schristos       else
16275fd0b74Schristos 	{
16375fd0b74Schristos 	  gold_error("invalid --sort-common argument: %s", order);
16475fd0b74Schristos 	  sort_order = SORT_COMMONS_BY_SIZE_DESCENDING;
16575fd0b74Schristos 	}
16675fd0b74Schristos     }
16775fd0b74Schristos 
16875fd0b74Schristos   if (parameters->target().get_size() == 32)
16975fd0b74Schristos     {
17075fd0b74Schristos #if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
17175fd0b74Schristos       this->do_allocate_commons<32>(layout, mapfile, sort_order);
17275fd0b74Schristos #else
17375fd0b74Schristos       gold_unreachable();
17475fd0b74Schristos #endif
17575fd0b74Schristos     }
17675fd0b74Schristos   else if (parameters->target().get_size() == 64)
17775fd0b74Schristos     {
17875fd0b74Schristos #if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
17975fd0b74Schristos       this->do_allocate_commons<64>(layout, mapfile, sort_order);
18075fd0b74Schristos #else
18175fd0b74Schristos       gold_unreachable();
18275fd0b74Schristos #endif
18375fd0b74Schristos     }
18475fd0b74Schristos   else
18575fd0b74Schristos     gold_unreachable();
18675fd0b74Schristos }
18775fd0b74Schristos 
18875fd0b74Schristos // Allocated the common symbols, sized version.
18975fd0b74Schristos 
19075fd0b74Schristos template<int size>
19175fd0b74Schristos void
do_allocate_commons(Layout * layout,Mapfile * mapfile,Sort_commons_order sort_order)19275fd0b74Schristos Symbol_table::do_allocate_commons(Layout* layout, Mapfile* mapfile,
19375fd0b74Schristos 				  Sort_commons_order sort_order)
19475fd0b74Schristos {
19575fd0b74Schristos   if (!this->commons_.empty())
19675fd0b74Schristos     this->do_allocate_commons_list<size>(layout, COMMONS_NORMAL,
19775fd0b74Schristos 					 &this->commons_, mapfile,
19875fd0b74Schristos 					 sort_order);
19975fd0b74Schristos   if (!this->tls_commons_.empty())
20075fd0b74Schristos     this->do_allocate_commons_list<size>(layout, COMMONS_TLS,
20175fd0b74Schristos 					 &this->tls_commons_, mapfile,
20275fd0b74Schristos 					 sort_order);
20375fd0b74Schristos   if (!this->small_commons_.empty())
20475fd0b74Schristos     this->do_allocate_commons_list<size>(layout, COMMONS_SMALL,
20575fd0b74Schristos 					 &this->small_commons_, mapfile,
20675fd0b74Schristos 					 sort_order);
20775fd0b74Schristos   if (!this->large_commons_.empty())
20875fd0b74Schristos     this->do_allocate_commons_list<size>(layout, COMMONS_LARGE,
20975fd0b74Schristos 					 &this->large_commons_, mapfile,
21075fd0b74Schristos 					 sort_order);
21175fd0b74Schristos }
21275fd0b74Schristos 
21375fd0b74Schristos // Allocate the common symbols in a list.  IS_TLS indicates whether
21475fd0b74Schristos // these are TLS common symbols.
21575fd0b74Schristos 
21675fd0b74Schristos template<int size>
21775fd0b74Schristos void
do_allocate_commons_list(Layout * layout,Commons_section_type commons_section_type,Commons_type * commons,Mapfile * mapfile,Sort_commons_order sort_order)21875fd0b74Schristos Symbol_table::do_allocate_commons_list(
21975fd0b74Schristos     Layout* layout,
22075fd0b74Schristos     Commons_section_type commons_section_type,
22175fd0b74Schristos     Commons_type* commons,
22275fd0b74Schristos     Mapfile* mapfile,
22375fd0b74Schristos     Sort_commons_order sort_order)
22475fd0b74Schristos {
22575fd0b74Schristos   // We've kept a list of all the common symbols.  But the symbol may
22675fd0b74Schristos   // have been resolved to a defined symbol by now.  And it may be a
22775fd0b74Schristos   // forwarder.  First remove all non-common symbols.
22875fd0b74Schristos   bool any = false;
22975fd0b74Schristos   uint64_t addralign = 0;
23075fd0b74Schristos   for (Commons_type::iterator p = commons->begin();
23175fd0b74Schristos        p != commons->end();
23275fd0b74Schristos        ++p)
23375fd0b74Schristos     {
23475fd0b74Schristos       Symbol* sym = *p;
23575fd0b74Schristos       if (sym->is_forwarder())
23675fd0b74Schristos 	{
23775fd0b74Schristos 	  sym = this->resolve_forwards(sym);
23875fd0b74Schristos 	  *p = sym;
23975fd0b74Schristos 	}
24075fd0b74Schristos       if (!sym->is_common())
24175fd0b74Schristos 	*p = NULL;
24275fd0b74Schristos       else
24375fd0b74Schristos 	{
24475fd0b74Schristos 	  any = true;
24575fd0b74Schristos 	  Sized_symbol<size>* ssym = this->get_sized_symbol<size>(sym);
24675fd0b74Schristos 	  if (ssym->value() > addralign)
24775fd0b74Schristos 	    addralign = ssym->value();
24875fd0b74Schristos 	}
24975fd0b74Schristos     }
25075fd0b74Schristos   if (!any)
25175fd0b74Schristos     return;
25275fd0b74Schristos 
25375fd0b74Schristos   // Sort the common symbols.
25475fd0b74Schristos   std::sort(commons->begin(), commons->end(),
25575fd0b74Schristos 	    Sort_commons<size>(this, sort_order));
25675fd0b74Schristos 
25775fd0b74Schristos   // Place them in a newly allocated BSS section.
25875fd0b74Schristos   elfcpp::Elf_Xword flags = elfcpp::SHF_WRITE | elfcpp::SHF_ALLOC;
25975fd0b74Schristos   const char* name;
26075fd0b74Schristos   const char* ds_name;
26175fd0b74Schristos   switch (commons_section_type)
26275fd0b74Schristos     {
26375fd0b74Schristos     case COMMONS_NORMAL:
26475fd0b74Schristos       name = ".bss";
26575fd0b74Schristos       ds_name = "** common";
26675fd0b74Schristos       break;
26775fd0b74Schristos     case COMMONS_TLS:
26875fd0b74Schristos       flags |= elfcpp::SHF_TLS;
26975fd0b74Schristos       name = ".tbss";
27075fd0b74Schristos       ds_name = "** tls common";
27175fd0b74Schristos       break;
27275fd0b74Schristos     case COMMONS_SMALL:
27375fd0b74Schristos       flags |= parameters->target().small_common_section_flags();
27475fd0b74Schristos       name = ".sbss";
27575fd0b74Schristos       ds_name = "** small common";
27675fd0b74Schristos       break;
27775fd0b74Schristos     case COMMONS_LARGE:
27875fd0b74Schristos       flags |= parameters->target().large_common_section_flags();
27975fd0b74Schristos       name = ".lbss";
28075fd0b74Schristos       ds_name = "** large common";
28175fd0b74Schristos       break;
28275fd0b74Schristos     default:
28375fd0b74Schristos       gold_unreachable();
28475fd0b74Schristos     }
28575fd0b74Schristos 
28675fd0b74Schristos   Output_data_space* poc;
28775fd0b74Schristos   Output_section* os;
28875fd0b74Schristos 
28975fd0b74Schristos   if (!parameters->incremental_update())
29075fd0b74Schristos     {
29175fd0b74Schristos       poc = new Output_data_space(addralign, ds_name);
29275fd0b74Schristos       os = layout->add_output_section_data(name, elfcpp::SHT_NOBITS, flags,
29375fd0b74Schristos 					   poc, ORDER_INVALID, false);
29475fd0b74Schristos     }
29575fd0b74Schristos   else
29675fd0b74Schristos     {
29775fd0b74Schristos       // When doing an incremental update, we need to allocate each common
29875fd0b74Schristos       // directly from the output section's free list.
29975fd0b74Schristos       poc = NULL;
30075fd0b74Schristos       os = layout->find_output_section(name);
30175fd0b74Schristos     }
30275fd0b74Schristos 
30375fd0b74Schristos   if (os != NULL)
30475fd0b74Schristos     {
30575fd0b74Schristos       if (commons_section_type == COMMONS_SMALL)
30675fd0b74Schristos 	os->set_is_small_section();
30775fd0b74Schristos       else if (commons_section_type == COMMONS_LARGE)
30875fd0b74Schristos 	os->set_is_large_section();
30975fd0b74Schristos     }
31075fd0b74Schristos 
31175fd0b74Schristos   // Allocate them all.
31275fd0b74Schristos 
31375fd0b74Schristos   off_t off = 0;
31475fd0b74Schristos   for (Commons_type::iterator p = commons->begin();
31575fd0b74Schristos        p != commons->end();
31675fd0b74Schristos        ++p)
31775fd0b74Schristos     {
31875fd0b74Schristos       Symbol* sym = *p;
31975fd0b74Schristos       if (sym == NULL)
32075fd0b74Schristos 	break;
32175fd0b74Schristos 
32275fd0b74Schristos       // Because we followed forwarding symbols above, but we didn't
32375fd0b74Schristos       // do it reliably before adding symbols to the list, it is
32475fd0b74Schristos       // possible for us to have the same symbol on the list twice.
32575fd0b74Schristos       // This can happen in the horrible case where a program defines
32675fd0b74Schristos       // a common symbol with the same name as a versioned libc
32775fd0b74Schristos       // symbol.  That will show up here as a symbol which has already
32875fd0b74Schristos       // been allocated and is therefore no longer a common symbol.
32975fd0b74Schristos       if (!sym->is_common())
33075fd0b74Schristos 	continue;
33175fd0b74Schristos 
33275fd0b74Schristos       Sized_symbol<size>* ssym = this->get_sized_symbol<size>(sym);
33375fd0b74Schristos 
33475fd0b74Schristos       // Record the symbol in the map file now, before we change its
33575fd0b74Schristos       // value.  Pass the size in separately so that we don't have to
33675fd0b74Schristos       // templatize the map code, which is not performance sensitive.
33775fd0b74Schristos       if (mapfile != NULL)
33875fd0b74Schristos 	mapfile->report_allocate_common(sym, ssym->symsize());
33975fd0b74Schristos 
34075fd0b74Schristos       if (poc != NULL)
34175fd0b74Schristos 	{
34275fd0b74Schristos 	  off = align_address(off, ssym->value());
34375fd0b74Schristos 	  ssym->allocate_common(poc, off);
34475fd0b74Schristos 	  off += ssym->symsize();
34575fd0b74Schristos 	}
34675fd0b74Schristos       else
34775fd0b74Schristos 	{
34875fd0b74Schristos 	  // For an incremental update, allocate from the free list.
34975fd0b74Schristos 	  off = os->allocate(ssym->symsize(), ssym->value());
35075fd0b74Schristos 	  if (off == -1)
35175fd0b74Schristos 	    gold_fallback(_("out of patch space in section %s; "
35275fd0b74Schristos 			    "relink with --incremental-full"),
35375fd0b74Schristos 			  os->name());
35475fd0b74Schristos 	  ssym->allocate_common(os, off);
35575fd0b74Schristos 	}
35675fd0b74Schristos     }
35775fd0b74Schristos 
35875fd0b74Schristos   if (poc != NULL)
35975fd0b74Schristos     poc->set_current_data_size(off);
36075fd0b74Schristos 
36175fd0b74Schristos   commons->clear();
36275fd0b74Schristos }
36375fd0b74Schristos 
36475fd0b74Schristos } // End namespace gold.
365