Initial CVS checkin of gold
[platform/upstream/binutils.git] / gold / object.cc
1 // object.cc -- support for an object file for linking in gold
2
3 #include "gold.h"
4
5 #include <cerrno>
6 #include <cstring>
7 #include <cassert>
8
9 #include "object.h"
10
11 namespace gold
12 {
13
14 // Class Object.
15
16 const unsigned char*
17 Object::get_view(off_t start, off_t size)
18 {
19   return this->input_file_->file().get_view(start + this->offset_, size);
20 }
21
22 void
23 Object::read(off_t start, off_t size, void* p)
24 {
25   this->input_file_->file().read(start + this->offset_, size, p);
26 }
27
28 File_view*
29 Object::get_lasting_view(off_t start, off_t size)
30 {
31   return this->input_file_->file().get_lasting_view(start + this->offset_,
32                                                     size);
33 }
34
35 // Class Sized_object.
36
37 template<int size, bool big_endian>
38 Sized_object<size, big_endian>::Sized_object(
39     const std::string& name,
40     Input_file* input_file,
41     off_t offset,
42     const elfcpp::Ehdr<size, big_endian>& ehdr)
43   : Object(name, input_file, offset),
44     osabi_(ehdr.get_e_ident()[elfcpp::EI_OSABI]),
45     abiversion_(ehdr.get_e_ident()[elfcpp::EI_ABIVERSION]),
46     machine_(ehdr.get_e_machine()),
47     flags_(ehdr.get_e_flags()),
48     target_(NULL),
49     shoff_(ehdr.get_e_shoff()),
50     shnum_(0),
51     shstrndx_(0),
52     symtab_shnum_(0)
53 {
54   if (ehdr.get_e_ehsize() != elfcpp::Elf_sizes<size>::ehdr_size)
55     {
56       fprintf(stderr, _("%s: %s: bad e_ehsize field (%d != %d)\n"),
57               program_name, this->name().c_str(), ehdr.get_e_ehsize(),
58               elfcpp::Elf_sizes<size>::ehdr_size);
59       gold_exit(false);
60     }
61   if (ehdr.get_e_shentsize() != elfcpp::Elf_sizes<size>::shdr_size)
62     {
63       fprintf(stderr, _("%s: %s: bad e_shentsize field (%d != %d)\n"),
64               program_name, this->name().c_str(), ehdr.get_e_shentsize(),
65               elfcpp::Elf_sizes<size>::shdr_size);
66       gold_exit(false);
67     }
68 }
69
70 template<int size, bool big_endian>
71 Sized_object<size, big_endian>::~Sized_object()
72 {
73 }
74
75 // Set up an object file bsaed on the file header.  This sets up the
76 // target and reads the section information.
77
78 template<int size, bool big_endian>
79 void
80 Sized_object<size, big_endian>::setup(
81     const elfcpp::Ehdr<size, big_endian>& ehdr)
82 {
83   //  this->target_ = select_target(this->machine_, size, big_endian,
84   //                            this->osabi_, this->abiversion_);
85   unsigned int shnum = ehdr.get_e_shnum();
86   unsigned int shstrndx = ehdr.get_e_shstrndx();
87   if ((shnum == 0 || shstrndx == elfcpp::SHN_XINDEX)
88       && this->shoff_ != 0)
89     {
90       const unsigned char* p = this->get_view
91         (this->shoff_, elfcpp::Elf_sizes<size>::shdr_size);
92       elfcpp::Shdr<size, big_endian> shdr(p);
93       if (shnum == 0)
94         shnum = shdr.get_sh_size();
95       if (shstrndx == elfcpp::SHN_XINDEX)
96         shstrndx = shdr.get_sh_link();
97     }
98   this->shnum_ = shnum;
99   this->shstrndx_ = shstrndx;
100
101   if (shnum == 0)
102     return;
103
104   // Find the SHT_SYMTAB section.
105   const unsigned char* p = this->get_view
106     (this->shoff_, shnum * elfcpp::Elf_sizes<size>::shdr_size);
107   // Skip the first section, which is always empty.
108   p += elfcpp::Elf_sizes<size>::shdr_size;
109   for (unsigned int i = 1; i < shnum; ++i)
110     {
111       elfcpp::Shdr<size, big_endian> shdr(p);
112       if (shdr.get_sh_type() == elfcpp::SHT_SYMTAB)
113         {
114           this->symtab_shnum_ = i;
115           break;
116         }
117       p += elfcpp::Elf_sizes<size>::shdr_size;
118     }
119 }
120
121 // Read the symbols and relocations from an object file.
122
123 template<int size, bool big_endian>
124 Read_symbols_data
125 Sized_object<size, big_endian>::do_read_symbols()
126 {
127   if (this->symtab_shnum_ == 0)
128     {
129       // No symbol table.  Weird but legal.
130       Read_symbols_data ret;
131       ret.symbols = NULL;
132       ret.symbols_size = 0;
133       ret.symbol_names = NULL;
134       ret.symbol_names_size = 0;
135       return ret;
136     }
137
138   int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
139
140   // Read the symbol table section header.
141   off_t symtabshdroff = this->shoff_ + (this->symtab_shnum_ * shdr_size);
142   const unsigned char* psymtabshdr = this->get_view(symtabshdroff, shdr_size);
143   elfcpp::Shdr<size, big_endian> symtabshdr(psymtabshdr);
144   assert(symtabshdr.get_sh_type() == elfcpp::SHT_SYMTAB);
145
146   // Read the symbol table.
147   File_view* fvsymtab = this->get_lasting_view(symtabshdr.get_sh_offset(),
148                                                symtabshdr.get_sh_size());
149
150   // Read the section header for the symbol names.
151   unsigned int strtab_shnum = symtabshdr.get_sh_link();
152   if (strtab_shnum == 0 || strtab_shnum >= this->shnum_)
153     {
154       fprintf(stderr, _("%s: %s: invalid symbol table name index: %u\n"),
155               program_name, this->name().c_str(), strtab_shnum);
156       gold_exit(false);
157     }
158   off_t strtabshdroff = this->shoff_ + (strtab_shnum * shdr_size);
159   const unsigned char *pstrtabshdr = this->get_view(strtabshdroff, shdr_size);
160   elfcpp::Shdr<size, big_endian> strtabshdr(pstrtabshdr);
161   if (strtabshdr.get_sh_type() != elfcpp::SHT_STRTAB)
162     {
163       fprintf(stderr,
164               _("%s: %s: symbol table name section has wrong type: %u\n"),
165               program_name, this->name().c_str(),
166               static_cast<unsigned int>(strtabshdr.get_sh_type()));
167       gold_exit(false);
168     }
169
170   // Read the symbol names.
171   File_view* fvstrtab = this->get_lasting_view(strtabshdr.get_sh_offset(),
172                                                strtabshdr.get_sh_size());
173
174   Read_symbols_data ret;
175   ret.symbols = fvsymtab;
176   ret.symbols_size = symtabshdr.get_sh_size();
177   ret.symbol_names = fvstrtab;
178   ret.symbol_names_size = strtabshdr.get_sh_size();
179
180   return ret;
181 }
182
183 // Add the symbols to the symbol table.
184
185 template<int size, bool big_endian>
186 void
187 Sized_object<size, big_endian>::do_add_symbols(Read_symbols_data sd)
188 {
189   if (sd.symbols == NULL)
190     {
191       assert(sd.symbol_names == NULL);
192       return;
193     }
194
195   int sym_size = elfcpp::Elf_sizes<size>::sym_size;
196   const unsigned char* symstart = sd.symbols->data();
197   const unsigned char* symend = symstart + sd.symbols_size;
198   for (const unsigned char* p = symstart; p < symend; p += sym_size)
199     {
200       elfcpp::Sym<size, big_endian> sym(p);
201
202       unsigned int nameoff = sym.get_st_name();
203       if (nameoff >= sd.symbol_names_size)
204         {
205           fprintf(stderr,
206                   _("%s: %s: invalid symbol name offset %u for symbol %d\n"),
207                   program_name, this->name().c_str(), nameoff,
208                   (p - symstart) / sym_size);
209           gold_exit(false);
210         }
211       const unsigned char* name = sd.symbol_names->data() + nameoff;
212       printf("%s\n", name);
213     }
214 }
215
216 } // End namespace gold.
217
218 namespace
219 {
220
221 using namespace gold;
222
223 // Read an ELF file with the header and return the appropriate
224 // instance of Object.
225
226 template<int size, bool big_endian>
227 Object*
228 make_elf_sized_object(const std::string& name, Input_file* input_file,
229                       off_t offset, const elfcpp::Ehdr<size, big_endian>& ehdr)
230 {
231   int et = ehdr.get_e_type();
232   if (et != elfcpp::ET_REL && et != elfcpp::ET_DYN)
233     {
234       fprintf(stderr, "%s: %s: unsupported ELF type %d\n",
235               program_name, name.c_str(), static_cast<int>(et));
236       gold_exit(false);
237     }
238
239   if (et == elfcpp::ET_REL)
240     {
241       Sized_object<size, big_endian>* obj =
242         new Sized_object<size, big_endian>(name, input_file, offset, ehdr);
243       obj->setup(ehdr);
244       return obj;
245     }
246   else
247     {
248       // elfcpp::ET_DYN
249       fprintf(stderr, _("%s: %s: dynamic objects are not yet supported\n"),
250               program_name, name.c_str());
251       gold_exit(false);
252 //       Sized_dynobj<size, big_endian>* obj =
253 //      new Sized_dynobj<size, big_endian>(this->input_.name(), input_file,
254 //                                         offset, ehdr);
255 //       obj->setup(ehdr);
256 //       return obj;
257     }
258 }
259
260 } // End anonymous namespace.
261
262 namespace gold
263 {
264
265 // Read an ELF file and return the appropriate instance of Object.
266
267 Object*
268 make_elf_object(const std::string& name, Input_file* input_file, off_t offset,
269                 const unsigned char* p, off_t bytes)
270 {
271   if (bytes < elfcpp::EI_NIDENT)
272     {
273       fprintf(stderr, _("%s: %s: ELF file too short\n"),
274               program_name, name.c_str());
275       gold_exit(false);
276     }
277
278   int v = p[elfcpp::EI_VERSION];
279   if (v != elfcpp::EV_CURRENT)
280     {
281       if (v == elfcpp::EV_NONE)
282         fprintf(stderr, _("%s: %s: invalid ELF version 0\n"),
283                 program_name, name.c_str());
284       else
285         fprintf(stderr, _("%s: %s: unsupported ELF version %d\n"),
286                 program_name, name.c_str(), v);
287       gold_exit(false);
288     }
289
290   int c = p[elfcpp::EI_CLASS];
291   if (c == elfcpp::ELFCLASSNONE)
292     {
293       fprintf(stderr, _("%s: %s: invalid ELF class 0\n"),
294               program_name, name.c_str());
295       gold_exit(false);
296     }
297   else if (c != elfcpp::ELFCLASS32
298            && c != elfcpp::ELFCLASS64)
299     {
300       fprintf(stderr, _("%s: %s: unsupported ELF class %d\n"),
301               program_name, name.c_str(), c);
302       gold_exit(false);
303     }
304
305   int d = p[elfcpp::EI_DATA];
306   if (d == elfcpp::ELFDATANONE)
307     {
308       fprintf(stderr, _("%s: %s: invalid ELF data encoding\n"),
309               program_name, name.c_str());
310       gold_exit(false);
311     }
312   else if (d != elfcpp::ELFDATA2LSB
313            && d != elfcpp::ELFDATA2MSB)
314     {
315       fprintf(stderr, _("%s: %s: unsupported ELF data encoding %d\n"),
316               program_name, name.c_str(), d);
317       gold_exit(false);
318     }
319
320   bool big_endian = d == elfcpp::ELFDATA2MSB;
321
322   if (c == elfcpp::ELFCLASS32)
323     {
324       if (bytes < elfcpp::Elf_sizes<32>::ehdr_size)
325         {
326           fprintf(stderr, _("%s: %s: ELF file too short\n"),
327                   program_name, name.c_str());
328           gold_exit(false);
329         }
330       if (big_endian)
331         {
332           elfcpp::Ehdr<32, true> ehdr(p);
333           return make_elf_sized_object<32, true>(name, input_file,
334                                                  offset, ehdr);
335         }
336       else
337         {
338           elfcpp::Ehdr<32, false> ehdr(p);
339           return make_elf_sized_object<32, false>(name, input_file,
340                                                   offset, ehdr);
341         }
342     }
343   else
344     {
345       if (bytes < elfcpp::Elf_sizes<32>::ehdr_size)
346         {
347           fprintf(stderr, _("%s: %s: ELF file too short\n"),
348                   program_name, name.c_str());
349           gold_exit(false);
350         }
351       if (big_endian)
352         {
353           elfcpp::Ehdr<64, true> ehdr(p);
354           return make_elf_sized_object<64, true>(name, input_file,
355                                                  offset, ehdr);
356         }
357       else
358         {
359           elfcpp::Ehdr<64, false> ehdr(p);
360           return make_elf_sized_object<64, false>(name, input_file,
361                                                   offset, ehdr);
362         }
363     }
364 }
365
366 // Instantiate the templates we need.  We could use the configure
367 // script to restrict this to only the ones for implemented targets.
368
369 template
370 class Sized_object<32, false>;
371
372 template
373 class Sized_object<32, true>;
374
375 template
376 class Sized_object<64, false>;
377
378 template
379 class Sized_object<64, true>;
380
381 } // End namespace gold.