-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathlayout.h
1487 lines (1231 loc) · 43.5 KB
/
layout.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// layout.h -- lay out output file sections for gold -*- C++ -*-
// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <[email protected]>.
// This file is part of gold.
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
// MA 02110-1301, USA.
#ifndef GOLD_LAYOUT_H
#define GOLD_LAYOUT_H
#include <cstring>
#include <list>
#include <map>
#include <string>
#include <utility>
#include <vector>
#include "script.h"
#include "workqueue.h"
#include "object.h"
#include "dynobj.h"
#include "stringpool.h"
namespace gold
{
class General_options;
class Incremental_inputs;
class Incremental_binary;
class Input_objects;
class Mapfile;
class Symbol_table;
class Output_section_data;
class Output_section;
class Output_section_headers;
class Output_segment_headers;
class Output_file_header;
class Output_segment;
class Output_data;
class Output_data_reloc_generic;
class Output_data_dynamic;
class Output_symtab_xindex;
class Output_reduced_debug_abbrev_section;
class Output_reduced_debug_info_section;
class Eh_frame;
class Target;
struct Timespec;
// Return TRUE if SECNAME is the name of a compressed debug section.
extern bool
is_compressed_debug_section(const char* secname);
// Maintain a list of free space within a section, segment, or file.
// Used for incremental update links.
class Free_list
{
public:
Free_list()
: list_(), last_remove_(list_.begin()), extend_(false), length_(0)
{ }
void
init(off_t len, bool extend);
void
remove(off_t start, off_t end);
off_t
allocate(off_t len, uint64_t align, off_t minoff);
void
dump();
static void
print_stats();
private:
struct Free_list_node
{
Free_list_node(off_t start, off_t end)
: start_(start), end_(end)
{ }
off_t start_;
off_t end_;
};
typedef std::list<Free_list_node>::iterator Iterator;
// The free list.
std::list<Free_list_node> list_;
// The last node visited during a remove operation.
Iterator last_remove_;
// Whether we can extend past the original length.
bool extend_;
// The total length of the section, segment, or file.
off_t length_;
// Statistics:
// The total number of free lists used.
static unsigned int num_lists;
// The total number of free list nodes used.
static unsigned int num_nodes;
// The total number of calls to Free_list::remove.
static unsigned int num_removes;
// The total number of nodes visited during calls to Free_list::remove.
static unsigned int num_remove_visits;
// The total number of calls to Free_list::allocate.
static unsigned int num_allocates;
// The total number of nodes visited during calls to Free_list::allocate.
static unsigned int num_allocate_visits;
};
// This task function handles mapping the input sections to output
// sections and laying them out in memory.
class Layout_task_runner : public Task_function_runner
{
public:
// OPTIONS is the command line options, INPUT_OBJECTS is the list of
// input objects, SYMTAB is the symbol table, LAYOUT is the layout
// object.
Layout_task_runner(const General_options& options,
const Input_objects* input_objects,
Symbol_table* symtab,
Target* target,
Layout* layout,
Mapfile* mapfile)
: options_(options), input_objects_(input_objects), symtab_(symtab),
target_(target), layout_(layout), mapfile_(mapfile)
{ }
// Run the operation.
void
run(Workqueue*, const Task*);
private:
Layout_task_runner(const Layout_task_runner&);
Layout_task_runner& operator=(const Layout_task_runner&);
const General_options& options_;
const Input_objects* input_objects_;
Symbol_table* symtab_;
Target* target_;
Layout* layout_;
Mapfile* mapfile_;
};
// This class holds information about the comdat group or
// .gnu.linkonce section that will be kept for a given signature.
class Kept_section
{
private:
// For a comdat group, we build a mapping from the name of each
// section in the group to the section index and the size in object.
// When we discard a group in some other object file, we use this
// map to figure out which kept section the discarded section is
// associated with. We then use that mapping when processing relocs
// against discarded sections.
struct Comdat_section_info
{
// The section index.
unsigned int shndx;
// The section size.
uint64_t size;
Comdat_section_info(unsigned int a_shndx, uint64_t a_size)
: shndx(a_shndx), size(a_size)
{ }
};
// Most comdat groups have only one or two sections, so we use a
// std::map rather than an Unordered_map to optimize for that case
// without paying too heavily for groups with more sections.
typedef std::map<std::string, Comdat_section_info> Comdat_group;
public:
Kept_section()
: object_(NULL), shndx_(0), is_comdat_(false), is_group_name_(false)
{ this->u_.linkonce_size = 0; }
// We need to support copies for the signature map in the Layout
// object, but we should never copy an object after it has been
// marked as a comdat section.
Kept_section(const Kept_section& k)
: object_(k.object_), shndx_(k.shndx_), is_comdat_(false),
is_group_name_(k.is_group_name_)
{
gold_assert(!k.is_comdat_);
this->u_.linkonce_size = 0;
}
~Kept_section()
{
if (this->is_comdat_)
delete this->u_.group_sections;
}
// The object where this section lives.
Relobj*
object() const
{ return this->object_; }
// Set the object.
void
set_object(Relobj* object)
{
gold_assert(this->object_ == NULL);
this->object_ = object;
}
// The section index.
unsigned int
shndx() const
{ return this->shndx_; }
// Set the section index.
void
set_shndx(unsigned int shndx)
{
gold_assert(this->shndx_ == 0);
this->shndx_ = shndx;
}
// Whether this is a comdat group.
bool
is_comdat() const
{ return this->is_comdat_; }
// Set that this is a comdat group.
void
set_is_comdat()
{
gold_assert(!this->is_comdat_);
this->is_comdat_ = true;
this->u_.group_sections = new Comdat_group();
}
// Whether this is associated with the name of a group or section
// rather than the symbol name derived from a linkonce section.
bool
is_group_name() const
{ return this->is_group_name_; }
// Note that this represents a comdat group rather than a single
// linkonce section.
void
set_is_group_name()
{ this->is_group_name_ = true; }
// Add a section to the group list.
void
add_comdat_section(const std::string& name, unsigned int shndx,
uint64_t size)
{
gold_assert(this->is_comdat_);
Comdat_section_info sinfo(shndx, size);
this->u_.group_sections->insert(std::make_pair(name, sinfo));
}
// Look for a section name in the group list, and return whether it
// was found. If found, returns the section index and size.
bool
find_comdat_section(const std::string& name, unsigned int* pshndx,
uint64_t* psize) const
{
gold_assert(this->is_comdat_);
Comdat_group::const_iterator p = this->u_.group_sections->find(name);
if (p == this->u_.group_sections->end())
return false;
*pshndx = p->second.shndx;
*psize = p->second.size;
return true;
}
// If there is only one section in the group list, return true, and
// return the section index and size.
bool
find_single_comdat_section(unsigned int* pshndx, uint64_t* psize) const
{
gold_assert(this->is_comdat_);
if (this->u_.group_sections->size() != 1)
return false;
Comdat_group::const_iterator p = this->u_.group_sections->begin();
*pshndx = p->second.shndx;
*psize = p->second.size;
return true;
}
// Return the size of a linkonce section.
uint64_t
linkonce_size() const
{
gold_assert(!this->is_comdat_);
return this->u_.linkonce_size;
}
// Set the size of a linkonce section.
void
set_linkonce_size(uint64_t size)
{
gold_assert(!this->is_comdat_);
this->u_.linkonce_size = size;
}
private:
// No assignment.
Kept_section& operator=(const Kept_section&);
// The object containing the comdat group or .gnu.linkonce section.
Relobj* object_;
// Index of the group section for comdats and the section itself for
// .gnu.linkonce.
unsigned int shndx_;
// True if this is for a comdat group rather than a .gnu.linkonce
// section.
bool is_comdat_;
// The Kept_sections are values of a mapping, that maps names to
// them. This field is true if this struct is associated with the
// name of a comdat or .gnu.linkonce, false if it is associated with
// the name of a symbol obtained from the .gnu.linkonce.* name
// through some heuristics.
bool is_group_name_;
union
{
// If the is_comdat_ field is true, this holds a map from names of
// the sections in the group to section indexes in object_ and to
// section sizes.
Comdat_group* group_sections;
// If the is_comdat_ field is false, this holds the size of the
// single section.
uint64_t linkonce_size;
} u_;
};
// The ordering for output sections. This controls how output
// sections are ordered within a PT_LOAD output segment.
enum Output_section_order
{
// Unspecified. Used for non-load segments. Also used for the file
// and segment headers.
ORDER_INVALID,
// The PT_INTERP section should come first, so that the dynamic
// linker can pick it up quickly.
ORDER_INTERP,
// Loadable read-only note sections come next so that the PT_NOTE
// segment is on the first page of the executable.
ORDER_RO_NOTE,
// Put read-only sections used by the dynamic linker early in the
// executable to minimize paging.
ORDER_DYNAMIC_LINKER,
// Put reloc sections used by the dynamic linker after other
// sections used by the dynamic linker; otherwise, objcopy and strip
// get confused.
ORDER_DYNAMIC_RELOCS,
// Put the PLT reloc section after the other dynamic relocs;
// otherwise, prelink gets confused.
ORDER_DYNAMIC_PLT_RELOCS,
// The .init section.
ORDER_INIT,
// The PLT.
ORDER_PLT,
// The regular text sections.
ORDER_TEXT,
// The .fini section.
ORDER_FINI,
// The read-only sections.
ORDER_READONLY,
// The exception frame sections.
ORDER_EHFRAME,
// The TLS sections come first in the data section.
ORDER_TLS_DATA,
ORDER_TLS_BSS,
// Local RELRO (read-only after relocation) sections come before
// non-local RELRO sections. This data will be fully resolved by
// the prelinker.
ORDER_RELRO_LOCAL,
// Non-local RELRO sections are grouped together after local RELRO
// sections. All RELRO sections must be adjacent so that they can
// all be put into a PT_GNU_RELRO segment.
ORDER_RELRO,
// We permit marking exactly one output section as the last RELRO
// section. We do this so that the read-only GOT can be adjacent to
// the writable GOT.
ORDER_RELRO_LAST,
// Similarly, we permit marking exactly one output section as the
// first non-RELRO section.
ORDER_NON_RELRO_FIRST,
// The regular data sections come after the RELRO sections.
ORDER_DATA,
// Large data sections normally go in large data segments.
ORDER_LARGE_DATA,
// Group writable notes so that we can have a single PT_NOTE
// segment.
ORDER_RW_NOTE,
// The small data sections must be at the end of the data sections,
// so that they can be adjacent to the small BSS sections.
ORDER_SMALL_DATA,
// The BSS sections start here.
// The small BSS sections must be at the start of the BSS sections,
// so that they can be adjacent to the small data sections.
ORDER_SMALL_BSS,
// The regular BSS sections.
ORDER_BSS,
// The large BSS sections come after the other BSS sections.
ORDER_LARGE_BSS,
// Maximum value.
ORDER_MAX
};
// This class handles the details of laying out input sections.
class Layout
{
public:
Layout(int number_of_input_files, Script_options*);
~Layout()
{
delete this->relaxation_debug_check_;
delete this->segment_states_;
}
// For incremental links, record the base file to be modified.
void
set_incremental_base(Incremental_binary* base);
Incremental_binary*
incremental_base()
{ return this->incremental_base_; }
// For incremental links, record the initial fixed layout of a section
// from the base file, and return a pointer to the Output_section.
template<int size, bool big_endian>
Output_section*
init_fixed_output_section(const char*, elfcpp::Shdr<size, big_endian>&);
// Given an input section SHNDX, named NAME, with data in SHDR, from
// the object file OBJECT, return the output section where this
// input section should go. RELOC_SHNDX is the index of a
// relocation section which applies to this section, or 0 if none,
// or -1U if more than one. RELOC_TYPE is the type of the
// relocation section if there is one. Set *OFFSET to the offset
// within the output section.
template<int size, bool big_endian>
Output_section*
layout(Sized_relobj_file<size, big_endian> *object, unsigned int shndx,
const char* name, const elfcpp::Shdr<size, big_endian>& shdr,
unsigned int reloc_shndx, unsigned int reloc_type, off_t* offset);
bool
is_section_ordering_specified()
{ return this->section_ordering_specified_; }
void
set_section_ordering_specified()
{ this->section_ordering_specified_ = true; }
// For incremental updates, allocate a block of memory from the
// free list. Find a block starting at or after MINOFF.
off_t
allocate(off_t len, uint64_t align, off_t minoff)
{ return this->free_list_.allocate(len, align, minoff); }
unsigned int
find_section_order_index(const std::string&);
// Read the sequence of input sections from the file specified with
// linker option --section-ordering-file.
void
read_layout_from_file();
// Layout an input reloc section when doing a relocatable link. The
// section is RELOC_SHNDX in OBJECT, with data in SHDR.
// DATA_SECTION is the reloc section to which it refers. RR is the
// relocatable information.
template<int size, bool big_endian>
Output_section*
layout_reloc(Sized_relobj_file<size, big_endian>* object,
unsigned int reloc_shndx,
const elfcpp::Shdr<size, big_endian>& shdr,
Output_section* data_section,
Relocatable_relocs* rr);
// Layout a group section when doing a relocatable link.
template<int size, bool big_endian>
void
layout_group(Symbol_table* symtab,
Sized_relobj_file<size, big_endian>* object,
unsigned int group_shndx,
const char* group_section_name,
const char* signature,
const elfcpp::Shdr<size, big_endian>& shdr,
elfcpp::Elf_Word flags,
std::vector<unsigned int>* shndxes);
// Like layout, only for exception frame sections. OBJECT is an
// object file. SYMBOLS is the contents of the symbol table
// section, with size SYMBOLS_SIZE. SYMBOL_NAMES is the contents of
// the symbol name section, with size SYMBOL_NAMES_SIZE. SHNDX is a
// .eh_frame section in OBJECT. SHDR is the section header.
// RELOC_SHNDX is the index of a relocation section which applies to
// this section, or 0 if none, or -1U if more than one. RELOC_TYPE
// is the type of the relocation section if there is one. This
// returns the output section, and sets *OFFSET to the offset.
template<int size, bool big_endian>
Output_section*
layout_eh_frame(Sized_relobj_file<size, big_endian>* object,
const unsigned char* symbols,
off_t symbols_size,
const unsigned char* symbol_names,
off_t symbol_names_size,
unsigned int shndx,
const elfcpp::Shdr<size, big_endian>& shdr,
unsigned int reloc_shndx, unsigned int reloc_type,
off_t* offset);
// Add .eh_frame information for a PLT. The FDE must start with a
// 4-byte PC-relative reference to the start of the PLT, followed by
// a 4-byte size of PLT.
void
add_eh_frame_for_plt(Output_data* plt, const unsigned char* cie_data,
size_t cie_length, const unsigned char* fde_data,
size_t fde_length);
// Handle a GNU stack note. This is called once per input object
// file. SEEN_GNU_STACK is true if the object file has a
// .note.GNU-stack section. GNU_STACK_FLAGS is the section flags
// from that section if there was one.
void
layout_gnu_stack(bool seen_gnu_stack, uint64_t gnu_stack_flags,
const Object*);
// Add an Output_section_data to the layout. This is used for
// special sections like the GOT section. ORDER is where the
// section should wind up in the output segment. IS_RELRO is true
// for relro sections.
Output_section*
add_output_section_data(const char* name, elfcpp::Elf_Word type,
elfcpp::Elf_Xword flags,
Output_section_data*, Output_section_order order,
bool is_relro);
// Increase the size of the relro segment by this much.
void
increase_relro(unsigned int s)
{ this->increase_relro_ += s; }
// Create dynamic sections if necessary.
void
create_initial_dynamic_sections(Symbol_table*);
// Define __start and __stop symbols for output sections.
void
define_section_symbols(Symbol_table*);
// Create automatic note sections.
void
create_notes();
// Create sections for linker scripts.
void
create_script_sections()
{ this->script_options_->create_script_sections(this); }
// Define symbols from any linker script.
void
define_script_symbols(Symbol_table* symtab)
{ this->script_options_->add_symbols_to_table(symtab); }
// Define symbols for group signatures.
void
define_group_signatures(Symbol_table*);
// Return the Stringpool used for symbol names.
const Stringpool*
sympool() const
{ return &this->sympool_; }
// Return the Stringpool used for dynamic symbol names and dynamic
// tags.
const Stringpool*
dynpool() const
{ return &this->dynpool_; }
// Return the .dynamic output section. This is only valid after the
// layout has been finalized.
Output_section*
dynamic_section() const
{ return this->dynamic_section_; }
// Return the symtab_xindex section used to hold large section
// indexes for the normal symbol table.
Output_symtab_xindex*
symtab_xindex() const
{ return this->symtab_xindex_; }
// Return the dynsym_xindex section used to hold large section
// indexes for the dynamic symbol table.
Output_symtab_xindex*
dynsym_xindex() const
{ return this->dynsym_xindex_; }
// Return whether a section is a .gnu.linkonce section, given the
// section name.
static inline bool
is_linkonce(const char* name)
{ return strncmp(name, ".gnu.linkonce", sizeof(".gnu.linkonce") - 1) == 0; }
// Whether we have added an input section.
bool
have_added_input_section() const
{ return this->have_added_input_section_; }
// Return true if a section is a debugging section.
static inline bool
is_debug_info_section(const char* name)
{
// Debugging sections can only be recognized by name.
return (strncmp(name, ".debug", sizeof(".debug") - 1) == 0
|| strncmp(name, ".zdebug", sizeof(".zdebug") - 1) == 0
|| strncmp(name, ".gnu.linkonce.wi.",
sizeof(".gnu.linkonce.wi.") - 1) == 0
|| strncmp(name, ".line", sizeof(".line") - 1) == 0
|| strncmp(name, ".stab", sizeof(".stab") - 1) == 0);
}
// Return true if RELOBJ is an input file whose base name matches
// FILE_NAME. The base name must have an extension of ".o", and
// must be exactly FILE_NAME.o or FILE_NAME, one character, ".o".
static bool
match_file_name(const Relobj* relobj, const char* file_name);
// Return whether section SHNDX in RELOBJ is a .ctors/.dtors section
// with more than one word being mapped to a .init_array/.fini_array
// section.
bool
is_ctors_in_init_array(Relobj* relobj, unsigned int shndx) const;
// Check if a comdat group or .gnu.linkonce section with the given
// NAME is selected for the link. If there is already a section,
// *KEPT_SECTION is set to point to the signature and the function
// returns false. Otherwise, OBJECT, SHNDX,IS_COMDAT, and
// IS_GROUP_NAME are recorded for this NAME in the layout object,
// *KEPT_SECTION is set to the internal copy and the function return
// false.
bool
find_or_add_kept_section(const std::string& name, Relobj* object,
unsigned int shndx, bool is_comdat,
bool is_group_name, Kept_section** kept_section);
// Finalize the layout after all the input sections have been added.
off_t
finalize(const Input_objects*, Symbol_table*, Target*, const Task*);
// Return whether any sections require postprocessing.
bool
any_postprocessing_sections() const
{ return this->any_postprocessing_sections_; }
// Return the size of the output file.
off_t
output_file_size() const
{ return this->output_file_size_; }
// Return the TLS segment. This will return NULL if there isn't
// one.
Output_segment*
tls_segment() const
{ return this->tls_segment_; }
// Return the normal symbol table.
Output_section*
symtab_section() const
{
gold_assert(this->symtab_section_ != NULL);
return this->symtab_section_;
}
// Return the file offset of the normal symbol table.
off_t
symtab_section_offset() const;
// Return the section index of the normal symbol tabl.e
unsigned int
symtab_section_shndx() const;
// Return the dynamic symbol table.
Output_section*
dynsym_section() const
{
gold_assert(this->dynsym_section_ != NULL);
return this->dynsym_section_;
}
// Return the dynamic tags.
Output_data_dynamic*
dynamic_data() const
{ return this->dynamic_data_; }
// Write out the output sections.
void
write_output_sections(Output_file* of) const;
// Write out data not associated with an input file or the symbol
// table.
void
write_data(const Symbol_table*, Output_file*) const;
// Write out output sections which can not be written until all the
// input sections are complete.
void
write_sections_after_input_sections(Output_file* of);
// Return an output section named NAME, or NULL if there is none.
Output_section*
find_output_section(const char* name) const;
// Return an output segment of type TYPE, with segment flags SET set
// and segment flags CLEAR clear. Return NULL if there is none.
Output_segment*
find_output_segment(elfcpp::PT type, elfcpp::Elf_Word set,
elfcpp::Elf_Word clear) const;
// Return the number of segments we expect to produce.
size_t
expected_segment_count() const;
// Set a flag to indicate that an object file uses the static TLS model.
void
set_has_static_tls()
{ this->has_static_tls_ = true; }
// Return true if any object file uses the static TLS model.
bool
has_static_tls() const
{ return this->has_static_tls_; }
// Return the options which may be set by a linker script.
Script_options*
script_options()
{ return this->script_options_; }
const Script_options*
script_options() const
{ return this->script_options_; }
// Return the object managing inputs in incremental build. NULL in
// non-incremental builds.
Incremental_inputs*
incremental_inputs() const
{ return this->incremental_inputs_; }
// For the target-specific code to add dynamic tags which are common
// to most targets.
void
add_target_dynamic_tags(bool use_rel, const Output_data* plt_got,
const Output_data* plt_rel,
const Output_data_reloc_generic* dyn_rel,
bool add_debug, bool dynrel_includes_plt);
// Compute and write out the build ID if needed.
void
write_build_id(Output_file*) const;
// Rewrite output file in binary format.
void
write_binary(Output_file* in) const;
// Print output sections to the map file.
void
print_to_mapfile(Mapfile*) const;
// Dump statistical information to stderr.
void
print_stats() const;
// A list of segments.
typedef std::vector<Output_segment*> Segment_list;
// A list of sections.
typedef std::vector<Output_section*> Section_list;
// The list of information to write out which is not attached to
// either a section or a segment.
typedef std::vector<Output_data*> Data_list;
// Store the allocated sections into the section list. This is used
// by the linker script code.
void
get_allocated_sections(Section_list*) const;
// Make a section for a linker script to hold data.
Output_section*
make_output_section_for_script(const char* name,
Script_sections::Section_type section_type);
// Make a segment. This is used by the linker script code.
Output_segment*
make_output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags);
// Return the number of segments.
size_t
segment_count() const
{ return this->segment_list_.size(); }
// Map from section flags to segment flags.
static elfcpp::Elf_Word
section_flags_to_segment(elfcpp::Elf_Xword flags);
// Attach sections to segments.
void
attach_sections_to_segments();
// For relaxation clean up, we need to know output section data created
// from a linker script.
void
new_output_section_data_from_script(Output_section_data* posd)
{
if (this->record_output_section_data_from_script_)
this->script_output_section_data_list_.push_back(posd);
}
// Return section list.
const Section_list&
section_list() const
{ return this->section_list_; }
private:
Layout(const Layout&);
Layout& operator=(const Layout&);
// Mapping from input section names to output section names.
struct Section_name_mapping
{
const char* from;
int fromlen;
const char* to;
int tolen;
};
static const Section_name_mapping section_name_mapping[];
static const int section_name_mapping_count;
// During a relocatable link, a list of group sections and
// signatures.
struct Group_signature
{
// The group section.
Output_section* section;
// The signature.
const char* signature;
Group_signature()
: section(NULL), signature(NULL)
{ }
Group_signature(Output_section* sectiona, const char* signaturea)
: section(sectiona), signature(signaturea)
{ }
};
typedef std::vector<Group_signature> Group_signatures;
// Create a note section, filling in the header.
Output_section*
create_note(const char* name, int note_type, const char* section_name,
size_t descsz, bool allocate, size_t* trailing_padding);
// Create a note section for gold version.
void
create_gold_note();
// Record whether the stack must be executable.
void
create_executable_stack_info();
// Create a build ID note if needed.
void
create_build_id();
// Link .stab and .stabstr sections.
void
link_stabs_sections();
// Create .gnu_incremental_inputs and .gnu_incremental_strtab sections needed
// for the next run of incremental linking to check what has changed.
void
create_incremental_info_sections(Symbol_table*);
// Find the first read-only PT_LOAD segment, creating one if
// necessary.
Output_segment*
find_first_load_seg();
// Count the local symbols in the regular symbol table and the dynamic
// symbol table, and build the respective string pools.
void
count_local_symbols(const Task*, const Input_objects*);
// Create the output sections for the symbol table.
void
create_symtab_sections(const Input_objects*, Symbol_table*,
unsigned int, off_t*);
// Create the .shstrtab section.
Output_section*
create_shstrtab();
// Create the section header table.
void
create_shdrs(const Output_section* shstrtab_section, off_t*);
// Create the dynamic symbol table.
void
create_dynamic_symtab(const Input_objects*, Symbol_table*,
Output_section** pdynstr,
unsigned int* plocal_dynamic_count,
std::vector<Symbol*>* pdynamic_symbols,
Versions* versions);
// Assign offsets to each local portion of the dynamic symbol table.
void
assign_local_dynsym_offsets(const Input_objects*);
// Finish the .dynamic section and PT_DYNAMIC segment.
void
finish_dynamic_section(const Input_objects*, const Symbol_table*);
// Set the size of the _DYNAMIC symbol.
void
set_dynamic_symbol_size(const Symbol_table*);
// Create the .interp section and PT_INTERP segment.
void
create_interp(const Target* target);
// Create the version sections.
void
create_version_sections(const Versions*,
const Symbol_table*,
unsigned int local_symcount,
const std::vector<Symbol*>& dynamic_symbols,
const Output_section* dynstr);
template<int size, bool big_endian>
void
sized_create_version_sections(const Versions* versions,
const Symbol_table*,
unsigned int local_symcount,
const std::vector<Symbol*>& dynamic_symbols,
const Output_section* dynstr);
// Return whether to include this section in the link.
template<int size, bool big_endian>
bool