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