OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [gold/] [common.cc] - Blame information for rev 298

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 khays
// common.cc -- handle common symbols for gold
2
 
3
// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
4
// Written by Ian Lance Taylor <iant@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
  typedef typename Sized_symbol<size>::Value_type Value_type;
226
  typedef typename Sized_symbol<size>::Size_type Size_type;
227
 
228
  // We've kept a list of all the common symbols.  But the symbol may
229
  // have been resolved to a defined symbol by now.  And it may be a
230
  // forwarder.  First remove all non-common symbols.
231
  bool any = false;
232
  uint64_t addralign = 0;
233
  for (Commons_type::iterator p = commons->begin();
234
       p != commons->end();
235
       ++p)
236
    {
237
      Symbol* sym = *p;
238
      if (sym->is_forwarder())
239
        {
240
          sym = this->resolve_forwards(sym);
241
          *p = sym;
242
        }
243
      if (!sym->is_common())
244
        *p = NULL;
245
      else
246
        {
247
          any = true;
248
          Sized_symbol<size>* ssym = this->get_sized_symbol<size>(sym);
249
          if (ssym->value() > addralign)
250
            addralign = ssym->value();
251
        }
252
    }
253
  if (!any)
254
    return;
255
 
256
  // Sort the common symbols.
257
  std::sort(commons->begin(), commons->end(),
258
            Sort_commons<size>(this, sort_order));
259
 
260
  // Place them in a newly allocated BSS section.
261
  elfcpp::Elf_Xword flags = elfcpp::SHF_WRITE | elfcpp::SHF_ALLOC;
262
  const char* name;
263
  const char* ds_name;
264
  switch (commons_section_type)
265
    {
266
    case COMMONS_NORMAL:
267
      name = ".bss";
268
      ds_name = "** common";
269
      break;
270
    case COMMONS_TLS:
271
      flags |= elfcpp::SHF_TLS;
272
      name = ".tbss";
273
      ds_name = "** tls common";
274
      break;
275
    case COMMONS_SMALL:
276
      flags |= parameters->target().small_common_section_flags();
277
      name = ".sbss";
278
      ds_name = "** small common";
279
      break;
280
    case COMMONS_LARGE:
281
      flags |= parameters->target().large_common_section_flags();
282
      name = ".lbss";
283
      ds_name = "** large common";
284
      break;
285
    default:
286
      gold_unreachable();
287
    }
288
 
289 148 khays
  Output_data_space* poc;
290
  Output_section* os;
291
 
292
  if (!parameters->incremental_update())
293
    {
294
      poc = new Output_data_space(addralign, ds_name);
295
      os = layout->add_output_section_data(name, elfcpp::SHT_NOBITS, flags,
296
                                           poc, ORDER_INVALID, false);
297
    }
298
  else
299
    {
300
      // When doing an incremental update, we need to allocate each common
301
      // directly from the output section's free list.
302
      poc = NULL;
303
      os = layout->find_output_section(name);
304
    }
305
 
306 27 khays
  if (os != NULL)
307
    {
308
      if (commons_section_type == COMMONS_SMALL)
309
        os->set_is_small_section();
310
      else if (commons_section_type == COMMONS_LARGE)
311
        os->set_is_large_section();
312
    }
313
 
314
  // Allocate them all.
315
 
316
  off_t off = 0;
317
  for (Commons_type::iterator p = commons->begin();
318
       p != commons->end();
319
       ++p)
320
    {
321
      Symbol* sym = *p;
322
      if (sym == NULL)
323
        break;
324
 
325
      // Because we followed forwarding symbols above, but we didn't
326
      // do it reliably before adding symbols to the list, it is
327
      // possible for us to have the same symbol on the list twice.
328
      // This can happen in the horrible case where a program defines
329
      // a common symbol with the same name as a versioned libc
330
      // symbol.  That will show up here as a symbol which has already
331
      // been allocated and is therefore no longer a common symbol.
332
      if (!sym->is_common())
333
        continue;
334
 
335
      Sized_symbol<size>* ssym = this->get_sized_symbol<size>(sym);
336
 
337
      // Record the symbol in the map file now, before we change its
338
      // value.  Pass the size in separately so that we don't have to
339
      // templatize the map code, which is not performance sensitive.
340
      if (mapfile != NULL)
341
        mapfile->report_allocate_common(sym, ssym->symsize());
342
 
343 148 khays
      if (poc != NULL)
344
        {
345
          off = align_address(off, ssym->value());
346
          ssym->allocate_common(poc, off);
347
          off += ssym->symsize();
348
        }
349
      else
350
        {
351
          // For an incremental update, allocate from the free list.
352
          off = os->allocate(ssym->symsize(), ssym->value());
353
          if (off == -1)
354
            gold_fallback(_("out of patch space in section %s; "
355
                            "relink with --incremental-full"),
356
                          os->name());
357
          ssym->allocate_common(os, off);
358
        }
359 27 khays
    }
360
 
361 148 khays
  if (poc != NULL)
362
    poc->set_current_data_size(off);
363 27 khays
 
364
  commons->clear();
365
}
366
 
367
} // End namespace gold.

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.