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

Last change on this file since 173 was 163, checked in by karaoui, 12 years ago

changing mover to memo
changing soft.bin to soft.elf
...

File size: 8.4 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)
132  {
133    this->word_width_  = obj.word_width_ ;
134    this->byteorder_  = obj.byteorder_ ;
135    this->machine_  = obj.machine_ ;
136    this->os_abi_   = obj.os_abi_ ;
137    this->abi_ver_  = obj.abi_ver_ ;
138    this->type_     = obj.type_ ;
139    this->flags_    = obj.flags_ ;
140
141    switch (this->word_width_)
142    {
143        case ELFCLASS32: {
144          static elf32_access a;
145          access_ = static_cast<elf_access*>(&a);
146          break;
147        }
148
149        case ELFCLASS64: {
150          static elf64_access a;
151          access_ = static_cast<elf_access*>(&a);
152          break;
153        }
154
155        default:
156          throw std::runtime_error("bad elf class");
157        }
158
159  }
160
161  object::object(const std::string &filename)
162    : generate_symtab_(false)
163  {
164    FILE *file = fopen(filename.c_str(), "rb");
165
166    if (!file)
167      throw std::runtime_error("unable to open file");
168
169    unsigned char       e_ident[EI_NIDENT];     /* Magic number and other info */
170
171    if (fread(e_ident, EI_NIDENT, 1, file) != 1)
172      throw std::runtime_error("unable to read file");
173
174    try {
175
176      if (std::memcmp(e_ident, ELFMAG, 4))
177        throw std::runtime_error("bad elf file header");
178
179      switch (e_ident[EI_CLASS])
180        {
181        case ELFCLASS32: {
182          static elf32_access a;
183          access_ = static_cast<elf_access*>(&a);
184          break;
185        }
186
187        case ELFCLASS64: {
188          static elf64_access a;
189          access_ = static_cast<elf_access*>(&a);
190          break;
191        }
192
193        default:
194          throw std::runtime_error("bad elf class");
195        }
196
197      access_->read(*this, file);
198
199    } catch (...) {
200      fclose(file);
201      throw;
202    }
203
204    fclose(file);
205  }
206
207  object::~object()
208  {
209    FOREACH2(s, section_tab_)
210      delete &*s;
211
212    FOREACH(s, sym_tab_)
213      delete s->second;
214  }
215
216    e_machine_e object::get_machine()
217    {
218        return machine_;
219    }
220    ei_class_e object::get_word_width()
221    {
222        return  word_width_;
223    }
224    ei_data_e object::get_byteorder()
225    {
226        return byteorder_;
227    }
228
229  section & object::get_section(const std::string &name)
230  {
231    FOREACH(s, section_tab_)
232      if (s->get_name() == name)
233        return *s;
234
235    throw std::runtime_error("no such section");
236  }
237
238  void object::parse_symbol_table()
239  {
240    access_->load_symtab(*this);
241    access_->load_reltab(*this);
242  }
243
244  void object::set_relative_relocs(symbol *sym)
245  {
246    // find mangled symbol for each relocation and set offset relative
247    // to symbol value.
248    FOREACH2(k, sym->get_reloc_table())
249      {
250        if (k->get_mangled_symbol())
251          continue;
252
253        if (sym->get_type() == STT_SECTION)
254          {
255            section *sS = sym->get_section();
256            int64_t addend = k->get_addend();
257            try {
258              symbol &ss = sS->get_symbol(addend);
259              k->set_symbol(&ss);
260              k->set_addend(addend - ss.get_value());
261            } catch (std::runtime_error &e) {
262#if 0
263              std::cerr << e.what() << " at " << sS->get_name() << ":" << std::hex << addend
264                        << " while resolving section symbol addend at "
265                        << k->get_section()->get_name() << ":" << k->get_offset() << " type " << k->get_type() << std::endl;
266#endif
267            }
268          }
269
270        try {
271          symbol &msym = k->get_section()->get_symbol(k->get_offset());
272          // std::cerr << *i->second << " " << msym << std::endl;
273          k->set_mangled_symbol(&msym);
274          k->set_offset(k->get_offset() - msym.get_value());
275
276        } catch (std::runtime_error &e) {
277#if 0
278          if (strncmp(k->get_section()->get_name().c_str(), ".debug", 6))
279            std::cerr << e.what() << " at " << k->get_section()->get_name() << ":" << std::hex << k->get_offset() << std::endl;
280#endif
281        }
282
283      }
284  }
285
286  void object::create_orphan_symbols()
287  {
288    FOREACH(s, get_section_table())
289      {
290        if (!(s->get_flags() & SHF_ALLOC))
291          continue;
292
293        typedef dpp::interval_set<uint32_t> is_t;
294        is_t is;
295
296        is |= is_t::interval_type(s->get_size(), (uint32_t)-1);
297
298        FOREACH(i, s->get_symbol_table())
299          {
300            uint32_t val = i->second->get_value();
301            size_t size = i->second->get_size();
302
303            if (size)
304              is |= is_t::interval_type(val, val + size);
305          }
306
307        is = ~is;
308
309        // create symbols for all orphan section areas in this object
310        FOREACH(i, is)
311          {
312            static int nosym_id = 0;
313            char name[32];
314            sprintf(name, "nosym_%i", nosym_id++);
315            symbol *sym = new symbol(name);
316
317            sym->set_value(i->low_bound());
318            sym->set_size(i->high_bound() - i->low_bound());
319            sym->set_section(*s);
320            s->add_symbol(*sym);
321          }
322      }
323  }
324
325  void object::load_symbol_data()
326  {
327    FOREACH(s, get_section_table())
328      {
329        if (s->get_type() == SHT_NOBITS)
330          continue;
331
332        FOREACH(i, s->get_symbol_table())
333          {
334            symbol *j = i->second;
335
336            // copy section data in each symbol content buffer
337            size_t size = j->get_size();
338
339            if (size != 0 && j->get_value() + size <= s->get_size())
340              j->set_content(s->get_content() + j->get_value());
341          }
342      }
343  }
344
345  void object::set_relative_relocs()
346  {
347    FOREACH(s, get_section_table())
348      {
349        FOREACH(i, s->get_symbol_table())
350          set_relative_relocs(i->second);
351      }
352
353    FOREACH(i, get_symbol_table())
354      set_relative_relocs(i->second);
355  }
356
357  void object::write(const std::string &filename)
358  {
359    FILE *file = fopen(filename.c_str(), "wb");
360
361    if (!file)
362      throw std::runtime_error("unable to open file");
363
364    try {
365      access_->write(*this, file);
366    } catch (...) {
367      fclose(file);
368      throw;
369    }
370
371    fclose(file);
372  }
373
374  void object::add_section(section &sec)
375  {
376    section_tab_.push_back(sec);
377  }
378
379  void object::add_segment(segment &seg)
380  {
381    segment_tab_.push_back(seg);
382  }
383
384  void object::remove_section(section &sec)
385  {
386    sec.remove();
387  }
388
389  void object::add_symbol(symbol &sym)
390  {
391#if 0
392    if (sym.get_section())
393      sym.get_section()->add_symbol(sym);
394    else
395#endif
396      sym_tab_.insert(sym_tab_map_t::value_type(sym.get_name(), &sym));
397  }
398
399  void object::remove_symbol(symbol &sym)
400  {
401    sym_tab_.erase(sym.get_name());
402  }
403
404}
405
Note: See TracBrowser for help on using the repository browser.