More section layout code.
[platform/upstream/binutils.git] / gold / output.cc
1 // output.cc -- manage the output file for gold
2
3 #include "gold.h"
4
5 #include <cstdlib>
6
7 #include "object.h"
8 #include "output.h"
9
10 namespace gold
11 {
12
13 // Output_data methods.
14
15 Output_data::~Output_data()
16 {
17 }
18
19 // Output_data_const methods.
20
21 void
22 Output_data_const::write(Output_file* output, off_t off)
23 {
24   output->write(off, data_.data(), data_.size());
25 }
26
27 // Output_segment_header methods.
28
29 void
30 Output_segment_headers::write(Output_file*, off_t)
31 {
32   // FIXME: Unimplemented.
33   abort();
34 }
35
36 // Output_section methods.
37
38 // Construct an Output_section.  NAME will point into a Stringpool.
39
40 Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
41                                elfcpp::Elf_Xword flags)
42   : name_(name),
43     addr_(0),
44     addralign_(0),
45     entsize_(0),
46     offset_(0),
47     link_(0),
48     info_(0),
49     type_(type),
50     flags_(flags)
51 {
52 }
53
54 Output_section::~Output_section()
55 {
56 }
57
58 // Add an input section to an Output_section.  We don't keep track of
59 // input sections for an Output_section.  Instead, each Object keeps
60 // track of the Output_section for each of its input sections.
61
62 template<int size, bool big_endian>
63 off_t
64 Output_section::add_input_section(Object* object, const char* secname,
65                                   const elfcpp::Shdr<size, big_endian>& shdr)
66 {
67   elfcpp::Elf_Xword addralign = shdr.get_sh_addralign();
68   if ((addralign & (addralign - 1)) != 0)
69     {
70       fprintf(stderr, _("%s: %s: invalid alignment %lu for section \"%s\"\n"),
71               program_name, object->name().c_str(),
72               static_cast<unsigned long>(addralign), secname);
73       gold_exit(false);
74     }
75
76   if (addralign > this->addralign_)
77     this->addralign_ = addralign;
78
79   off_t ssize = this->get_size();
80   ssize = (ssize + addralign - 1) &~ (addralign - 1);
81
82   this->set_size(ssize + shdr.get_sh_size());
83
84   return size;
85 }
86
87 // Output segment methods.
88
89 Output_segment::Output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags)
90   : output_data_(),
91     vaddr_(0),
92     paddr_(0),
93     memsz_(0),
94     align_(0),
95     offset_(0),
96     filesz_(0),
97     type_(type),
98     flags_(flags)
99 {
100 }
101
102 // Add an Output_section to an Output_segment.
103
104 void
105 Output_segment::add_output_section(Output_section* os)
106 {
107   // Update the segment flags.
108   this->flags_ |= os->flags() & (elfcpp::PF_R | elfcpp::PF_W | elfcpp::PF_X);
109
110   // So that PT_NOTE segments will work correctly, we need to ensure
111   // that all SHT_NOTE sections are adjacent.  This will normally
112   // happen automatically, because all the SHT_NOTE input sections
113   // will wind up in the same output section.  However, it is possible
114   // for multiple SHT_NOTE input sections to have different section
115   // flags, and thus be in different output sections, but for the
116   // different section flags to map into the same segment flags and
117   // thus the same output segment.
118
119   // Note that while there may be many input sections in an output
120   // section, there are normally only a few output sections in an
121   // output segment.  This loop is expected to be fast.
122
123   if (os->type() == elfcpp::SHT_NOTE)
124     {
125       for (Layout::Data_list::iterator p = this->output_data_.begin();
126            p != this->output_data_.end();
127            ++p)
128         {
129           if ((*p)->is_section_type(elfcpp::SHT_NOTE))
130             {
131               ++p;
132               this->output_data_.insert(p, os);
133               return;
134             }
135         }
136     }
137
138   // Similarly, so that PT_TLS segments will work, we need to group
139   // SHF_TLS sections.
140   if ((os->flags() & elfcpp::SHF_TLS) != 0)
141     {
142       for (Layout::Data_list::iterator p = this->output_data_.begin();
143            p != this->output_data_.end();
144            ++p)
145         {
146           if ((*p)->is_section_flag_set(elfcpp::SHF_TLS))
147             {
148               ++p;
149               this->output_data_.insert(p, os);
150               return;
151             }
152         }
153     }
154
155   this->output_data_.push_back(os);
156 }
157
158 // Output_file methods.
159
160 void
161 Output_file::write(off_t, const void*, off_t)
162 {
163   abort();
164 }
165
166 // Instantiate the templates we need.  We could use the configure
167 // script to restrict this to only the ones for implemented targets.
168
169 template
170 off_t
171 Output_section::add_input_section<32, false>(
172     Object* object,
173     const char* secname,
174     const elfcpp::Shdr<32, false>& shdr);
175
176 template
177 off_t
178 Output_section::add_input_section<32, true>(
179     Object* object,
180     const char* secname,
181     const elfcpp::Shdr<32, true>& shdr);
182
183 template
184 off_t
185 Output_section::add_input_section<64, false>(
186     Object* object,
187     const char* secname,
188     const elfcpp::Shdr<64, false>& shdr);
189
190 template
191 off_t
192 Output_section::add_input_section<64, true>(
193     Object* object,
194     const char* secname,
195     const elfcpp::Shdr<64, true>& shdr);
196
197 } // End namespace gold.