COFFI
1.2
               
coffi_symbols.hpp
Go to the documentation of this file.
1 /*
2 Copyright (C) 2014-2014 by Serge Lamikhov-Center
3 
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10 
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13 
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
21 */
22 
23 /*! @file coffi_symbols.hpp
24  * @brief COFFI library classes for the COFF symbols and symbol table.
25  *
26  * Do not include this file directly. This file is included by coffi.hpp.
27  */
28 
29 #ifndef COFFI_SYMBOLS_HPP
30 #define COFFI_SYMBOLS_HPP
31 
32 #include <vector>
33 
34 #include <coffi/coffi_utils.hpp>
35 #include <coffi/coffi_headers.hpp>
36 
37 #if defined(__has_include) && __has_include(<gsl/narrow>)
38 #include <gsl/narrow>
39 using gsl::narrow_cast;
40 #else
41 #ifndef narrow_cast
42 #define narrow_cast static_cast
43 #endif
44 #endif
45 
46 namespace COFFI {
47 
48 //-------------------------------------------------------------------------
49 //! Class for accessing a COFF symbol.
50 class symbol
51 {
52  public:
53  //---------------------------------------------------------------------
54  symbol(string_to_name_provider* stn) : index_(0), stn_{stn}
55  {
56  std::fill_n(reinterpret_cast<char*>(&header), sizeof(header), '\0');
57  }
58 
59  //---------------------------------------------------------------------
60  //! @accessors{symbol}
61  COFFI_GET_SET_ACCESS(uint32_t, value);
62  COFFI_GET_SET_ACCESS(uint16_t, section_number);
63  COFFI_GET_SET_ACCESS(uint16_t, type);
64  COFFI_GET_SET_ACCESS(uint8_t, storage_class);
65  COFFI_GET_SET_ACCESS(uint8_t, aux_symbols_number);
66  //! @endaccessors
67 
68  //---------------------------------------------------------------------
69  uint32_t get_index() const { return index_; }
70 
71  //---------------------------------------------------------------------
72  void set_index(uint32_t index) { index_ = index; }
73 
74  //------------------------------------------------------------------------------
75  const std::string get_name() const
76  {
77  return stn_->string_to_name(header.name);
78  }
79 
80  //---------------------------------------------------------------------
81  void set_name(const std::string& value)
82  {
83  stn_->name_to_string(value, header.name);
84  }
85 
86  //---------------------------------------------------------------------
87  const std::vector<auxiliary_symbol_record>& get_auxiliary_symbols() const
88  {
89  return auxs;
90  }
91 
92  //---------------------------------------------------------------------
93  std::vector<auxiliary_symbol_record>& get_auxiliary_symbols()
94  {
95  return auxs;
96  }
97 
98  //---------------------------------------------------------------------
99  bool load(std::istream& stream)
100  {
101  stream.read(reinterpret_cast<char*>(&header), sizeof(header));
102  if (stream.gcount() != sizeof(header)) {
103  return false;
104  }
105 
106  for (uint8_t i = 0; i < get_aux_symbols_number(); ++i) {
108  stream.read(reinterpret_cast<char*>(&a), sizeof(symbol_record));
109  if (stream.gcount() != sizeof(symbol_record)) {
110  return false;
111  }
112  auxs.push_back(a);
113  }
114  return true;
115  }
116 
117  //---------------------------------------------------------------------
118  void save(std::ostream& stream)
119  {
120  set_aux_symbols_number(narrow_cast<uint8_t>(auxs.size()));
121  stream.write(reinterpret_cast<char*>(&header), sizeof(header));
122  for (auto const& aux : auxs) {
123  stream.write(reinterpret_cast<char const*>(&aux),
124  sizeof(symbol_record));
125  }
126  }
127 
128  //---------------------------------------------------------------------
129  protected:
130  symbol_record header;
131  std::vector<auxiliary_symbol_record> auxs;
132  uint32_t index_;
134 };
135 
136 //-------------------------------------------------------------------------
137 //! Class for accessing the symbol table.
138 class coffi_symbols : public virtual symbol_provider,
139  public virtual string_to_name_provider
140 {
141  public:
142  //---------------------------------------------------------------------
143  coffi_symbols() {}
144 
145  //---------------------------------------------------------------------
146  ~coffi_symbols() { clean_symbols(); }
147 
148  //---------------------------------------------------------------------
149  //! @copydoc symbol_provider::get_symbol(uint32_t)
150  virtual symbol* get_symbol(uint32_t index)
151  {
152  return (symbol*)((const coffi_symbols*)this)->get_symbol(index);
153  }
154 
155  //---------------------------------------------------------------------
156  //! @copydoc symbol_provider::get_symbol(uint32_t)
157  virtual const symbol* get_symbol(uint32_t index) const
158  {
159  uint32_t L = 0;
160  uint32_t R = narrow_cast<uint32_t>(symbols_.size()) - 1;
161  while (L <= R) {
162  uint32_t m = (L + R) / 2;
163  if (symbols_[m].get_index() < index) {
164  L = m + 1;
165  }
166  else if (symbols_[m].get_index() > index) {
167  R = m - 1;
168  }
169  else {
170  return &(symbols_[m]);
171  }
172  }
173  return nullptr;
174  }
175 
176  //---------------------------------------------------------------------
177  //! @copydoc symbol_provider::get_symbol(const std::string &)
178  virtual symbol* get_symbol(const std::string& name)
179  {
180  return (symbol*)((const coffi_symbols*)this)->get_symbol(name);
181  }
182 
183  //---------------------------------------------------------------------
184  //! @copydoc symbol_provider::get_symbol(const std::string &)
185  virtual const symbol* get_symbol(const std::string& name) const
186  {
187  for (auto s = symbols_.begin(); s != symbols_.end(); s++) {
188  if (s->get_name() == name) {
189  return &(*s);
190  }
191  }
192  return nullptr;
193  }
194 
195  //---------------------------------------------------------------------
196  std::vector<symbol>* get_symbols() { return &symbols_; }
197 
198  //---------------------------------------------------------------------
199  const std::vector<symbol>* get_symbols() const { return &symbols_; }
200 
201  //---------------------------------------------------------------------
202  //! @copydoc symbol_provider::add_symbol()
203  symbol* add_symbol(const std::string& name)
204  {
205  uint32_t index = 0;
206  if (symbols_.size() > 0) {
207  index = (symbols_.end() - 1)->get_index() + 1 +
208  narrow_cast<uint32_t>(
209  (symbols_.end() - 1)->get_auxiliary_symbols().size());
210  }
211  symbol s{this};
212  s.set_index(index);
213  s.set_name(name);
214  symbols_.push_back(s);
215  return &*(symbols_.end() - 1);
216  }
217 
218  //---------------------------------------------------------------------
219  protected:
220  //---------------------------------------------------------------------
221  void clean_symbols() { symbols_.clear(); }
222 
223  //---------------------------------------------------------------------
224  bool load_symbols(std::istream& stream, const coff_header* header)
225  {
226  if (header->get_symbol_table_offset() == 0) {
227  return true;
228  }
229 
230  stream.seekg(header->get_symbol_table_offset());
231  for (uint32_t i = 0; i < header->get_symbols_count(); ++i) {
232  symbol s{this};
233  if (!s.load(stream)) {
234  return false;
235  }
236  s.set_index(i);
237  i += narrow_cast<uint32_t>(s.get_auxiliary_symbols().size());
238  symbols_.push_back(s);
239  }
240 
241  return true;
242  }
243 
244  //---------------------------------------------------------------------
245  void save_symbols(std::ostream& stream)
246  {
247  for (auto s : symbols_) {
248  s.save(stream);
249  }
250  }
251 
252  //---------------------------------------------------------------------
253  uint32_t get_symbols_filesize()
254  {
255  uint32_t filesize = 0;
256  for (auto s : symbols_) {
257  filesize +=
258  sizeof(symbol_record) *
259  (1 + narrow_cast<uint32_t>(s.get_auxiliary_symbols().size()));
260  }
261  return filesize;
262  }
263 
264  //---------------------------------------------------------------------
265  std::vector<symbol> symbols_;
266 };
267 
268 } // namespace COFFI
269 
270 #endif //COFFI_SYMBOLS_HPP
Class for accessing the symbol table.
virtual symbol * get_symbol(uint32_t index)
Gets a symbol from its index.
virtual const symbol * get_symbol(const std::string &name) const
Gets a symbol from its name.
virtual symbol * get_symbol(const std::string &name)
Gets a symbol from its name.
symbol * add_symbol(const std::string &name)
Adds a symbol in the table.
virtual const symbol * get_symbol(uint32_t index) const
Gets a symbol from its index.
Interface for accessing to the string table.
virtual std::string string_to_name(const char *str) const =0
Converts an 8-bytes symbol short name into a full name, eventually by looking into the strings table.
virtual void name_to_string(const std::string &name, char *str)=0
Converts symbol full name into an 8-bytes short name, eventually creating an entry in the strings tab...
Interface for accessing to the symbol table.
Class for accessing a COFF symbol.
COFFI library classes for the COFF file headers.
COFFI library utilities.
COFFI library namespace.
Definition: coffi.hpp:66
Generic auxiliary symbol record, covers any type of auxiliary symbol.
Symbol record.