source: soft/giet_vm/memo/src/libelfpp/elfpp_object.cc

Last change on this file was 238, checked in by alain, 11 years ago

Major evolution to support physical addresses larger than 32 bits.
The map.xml format has been modified: the vsegs associated to schedulers
are now explicitely defined and mapped in the page tables.

File size: 8.6 KB
Line 
1/*
2    This file is part of Libelfpp.
3
4    Libelfpp is free software: you can redistribute it and/or modify
5    it under the terms of the GNU Lesser General Public License as
6    published by the Free Software Foundation, either version 3 of the
7    License, or (at your option) any later version.
8
9    Libelfpp is distributed in the hope that it will be useful, but
10    WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    General Public License for more details.
13
14    You should have received a copy of the GNU Lesser General Public
15    License along with Libelfpp.  If not, see
16    <http://www.gnu.org/licenses/>.
17
18   Copyright (c) Alexandre Becoulet <alexandre.becoulet@free.fr>
19*/
20
21
22#include <stdexcept>
23#include <cstring>
24
25#include <dpp/foreach>
26#include <dpp/interval_set>
27
28#include <elfpp/object>
29#include <elfpp/access>
30#include <elfpp/section>
31#include <elfpp/segment>
32#include <elfpp/symbol>
33#include <elfpp/reloc>
34
35namespace elfpp
36{
37
38  ei_class_e object::get_word_width(e_machine_e machine)
39  {
40    switch (machine)
41      {
42      case EM_386:
43        return ELFCLASS32;
44
45      case EM_X86_64:
46        return ELFCLASS64;
47
48      default:
49        throw std::runtime_error("unable to guess machine word width");
50      }
51  }
52
53  ei_data_e object::get_byte_order(e_machine_e machine)
54  {
55    switch (machine)
56      {
57      case EM_SPARC:
58        return ELFDATA2MSB;
59
60      case EM_X86_64:
61      case EM_386:
62        return ELFDATA2LSB;
63
64      default:
65        throw std::runtime_error("unable to guess machine byte order");
66      }
67  }
68
69  object::object(e_machine_e machine,
70                 ei_class_e word_width,
71                 ei_data_e byte_order)
72    : section_tab_(),
73      os_abi_(ELFOSABI_SYSV),
74      type_(ET_REL),
75      machine_(machine),
76      generate_symtab_(true),
77      entry_(0),
78      flags_(0)
79  {
80    switch (machine)
81      {
82      case EM_X86_64:
83      case EM_386:
84        rel_with_addend_ = false;
85        break;
86
87      default:
88        rel_with_addend_ = true;
89        break;
90      }
91
92    if (byte_order == ELFDATANONE)
93      byte_order = get_byte_order(machine);
94
95    if (word_width == ELFCLASSNONE)
96      word_width = get_word_width(machine);
97
98    switch (word_width)
99    {
100        case ELFCLASS32: {
101          static elf32_access a;
102          access_ = static_cast<elf_access*>(&a);
103          break;
104        }
105
106        case ELFCLASS64: {
107          static elf64_access a;
108          access_ = static_cast<elf_access*>(&a);
109          break;
110        }
111
112        default:
113          throw std::runtime_error("bad elf class");
114        }
115
116
117  }
118
119  object::object()
120    : section_tab_(),
121      os_abi_(ELFOSABI_SYSV),
122      type_(ET_REL),
123      machine_(EM_NONE),
124      generate_symtab_(true),
125      entry_(0),
126      flags_(0)
127  {}
128
129   
130
131  void object::copy_info(object& obj, size_t word_width)
132  {
133
134        if(word_width == 32)
135                this->word_width_  = ELFCLASS32;
136        else if(word_width == 64)
137            this->word_width_  =  ELFCLASS64;
138        else
139            this->word_width_  = obj.word_width_ ;
140
141    this->byteorder_  = obj.byteorder_ ;
142    this->machine_  = obj.machine_ ;
143    this->os_abi_   = obj.os_abi_ ;
144    this->abi_ver_  = obj.abi_ver_ ;
145    this->type_     = obj.type_ ;
146    this->flags_    = obj.flags_ ;
147
148    switch (this->word_width_)
149    {
150        case ELFCLASS32: {
151          static elf32_access a;
152          access_ = static_cast<elf_access*>(&a);
153          break;
154        }
155
156        case ELFCLASS64: {
157          static elf64_access a;
158          access_ = static_cast<elf_access*>(&a);
159          break;
160        }
161
162        default:
163          throw std::runtime_error("bad elf class");
164        }
165
166  }
167
168  object::object(const std::string &filename)
169    : generate_symtab_(false)
170  {
171    FILE *file = fopen(filename.c_str(), "rb");
172
173    if (!file)
174      throw std::runtime_error("unable to open file");
175
176    unsigned char       e_ident[EI_NIDENT];     /* Magic number and other info */
177
178    if (fread(e_ident, EI_NIDENT, 1, file) != 1)
179      throw std::runtime_error("unable to read file");
180
181    try {
182
183      if (std::memcmp(e_ident, ELFMAG, 4))
184        throw std::runtime_error("bad elf file header");
185
186      switch (e_ident[EI_CLASS])
187        {
188        case ELFCLASS32: {
189          static elf32_access a;
190          access_ = static_cast<elf_access*>(&a);
191          break;
192        }
193
194        case ELFCLASS64: {
195          static elf64_access a;
196          access_ = static_cast<elf_access*>(&a);
197          break;
198        }
199
200        default:
201          throw std::runtime_error("bad elf class");
202        }
203
204      access_->read(*this, file);
205
206    } catch (...) {
207      fclose(file);
208      throw;
209    }
210
211    fclose(file);
212  }
213
214  object::~object()
215  {
216    FOREACH2(s, section_tab_)
217      delete &*s;
218
219    FOREACH(s, sym_tab_)
220      delete s->second;
221  }
222
223    e_machine_e object::get_machine()
224    {
225        return machine_;
226    }
227    ei_class_e object::get_word_width()
228    {
229        return  word_width_;
230    }
231    ei_data_e object::get_byteorder()
232    {
233        return byteorder_;
234    }
235
236  section & object::get_section(const std::string &name)
237  {
238    FOREACH(s, section_tab_)
239      if (s->get_name() == name)
240        return *s;
241
242    throw std::runtime_error("no such section");
243  }
244
245  void object::parse_symbol_table()
246  {
247    access_->load_symtab(*this);
248    access_->load_reltab(*this);
249  }
250
251  void object::set_relative_relocs(symbol *sym)
252  {
253    // find mangled symbol for each relocation and set offset relative
254    // to symbol value.
255    FOREACH2(k, sym->get_reloc_table())
256      {
257        if (k->get_mangled_symbol())
258          continue;
259
260        if (sym->get_type() == STT_SECTION)
261          {
262            section *sS = sym->get_section();
263            int64_t addend = k->get_addend();
264            try {
265              symbol &ss = sS->get_symbol(addend);
266              k->set_symbol(&ss);
267              k->set_addend(addend - ss.get_value());
268            } catch (std::runtime_error &e) {
269#if 0
270              std::cerr << e.what() << " at " << sS->get_name() << ":" << std::hex << addend
271                        << " while resolving section symbol addend at "
272                        << k->get_section()->get_name() << ":" << k->get_offset() << " type " << k->get_type() << std::endl;
273#endif
274            }
275          }
276
277        try {
278          symbol &msym = k->get_section()->get_symbol(k->get_offset());
279          // std::cerr << *i->second << " " << msym << std::endl;
280          k->set_mangled_symbol(&msym);
281          k->set_offset(k->get_offset() - msym.get_value());
282
283        } catch (std::runtime_error &e) {
284#if 0
285          if (strncmp(k->get_section()->get_name().c_str(), ".debug", 6))
286            std::cerr << e.what() << " at " << k->get_section()->get_name() << ":" << std::hex << k->get_offset() << std::endl;
287#endif
288        }
289
290      }
291  }
292
293  void object::create_orphan_symbols()
294  {
295    FOREACH(s, get_section_table())
296      {
297        if (!(s->get_flags() & SHF_ALLOC))
298          continue;
299
300        typedef dpp::interval_set<uint32_t> is_t;
301        is_t is;
302
303        is |= is_t::interval_type(s->get_size(), (uint32_t)-1);
304
305        FOREACH(i, s->get_symbol_table())
306          {
307            uint32_t val = i->second->get_value();
308            size_t size = i->second->get_size();
309
310            if (size)
311              is |= is_t::interval_type(val, val + size);
312          }
313
314        is = ~is;
315
316        // create symbols for all orphan section areas in this object
317        FOREACH(i, is)
318          {
319            static int nosym_id = 0;
320            char name[32];
321            sprintf(name, "nosym_%i", nosym_id++);
322            symbol *sym = new symbol(name);
323
324            sym->set_value(i->low_bound());
325            sym->set_size(i->high_bound() - i->low_bound());
326            sym->set_section(*s);
327            s->add_symbol(*sym);
328          }
329      }
330  }
331
332  void object::load_symbol_data()
333  {
334    FOREACH(s, get_section_table())
335      {
336        if (s->get_type() == SHT_NOBITS)
337          continue;
338
339        FOREACH(i, s->get_symbol_table())
340          {
341            symbol *j = i->second;
342
343            // copy section data in each symbol content buffer
344            size_t size = j->get_size();
345
346            if (size != 0 && j->get_value() + size <= s->get_size())
347              j->set_content(s->get_content() + j->get_value());
348          }
349      }
350  }
351
352  void object::set_relative_relocs()
353  {
354    FOREACH(s, get_section_table())
355      {
356        FOREACH(i, s->get_symbol_table())
357          set_relative_relocs(i->second);
358      }
359
360    FOREACH(i, get_symbol_table())
361      set_relative_relocs(i->second);
362  }
363
364  void object::write(const std::string &filename)
365  {
366    FILE *file = fopen(filename.c_str(), "wb");
367
368    if (!file)
369      throw std::runtime_error("unable to open file");
370
371    try {
372      access_->write(*this, file);
373    } catch (...) {
374      fclose(file);
375      throw;
376    }
377
378    fclose(file);
379  }
380
381  void object::add_section(section &sec)
382  {
383    section_tab_.push_back(sec);
384  }
385
386  void object::add_segment(segment &seg)
387  {
388    segment_tab_.push_back(seg);
389  }
390
391  void object::remove_section(section &sec)
392  {
393    sec.remove();
394  }
395
396  void object::add_symbol(symbol &sym)
397  {
398#if 0
399    if (sym.get_section())
400      sym.get_section()->add_symbol(sym);
401    else
402#endif
403      sym_tab_.insert(sym_tab_map_t::value_type(sym.get_name(), &sym));
404  }
405
406  void object::remove_symbol(symbol &sym)
407  {
408    sym_tab_.erase(sym.get_name());
409  }
410
411}
412
Note: See TracBrowser for help on using the repository browser.