COFFI
1.2
               
coffi_strings.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_strings.hpp
24  * @brief COFFI library classes for the COFF strings and string table.
25  *
26  * Do not include this file directly. This file is included by coffi.hpp.
27  */
28 
29 #ifndef COFFI_STRINGS_HPP
30 #define COFFI_STRINGS_HPP
31 
32 #include <cstring>
33 
34 #include <coffi/coffi_utils.hpp>
35 #include <coffi/coffi_headers.hpp>
36 
37 namespace COFFI {
38 //-------------------------------------------------------------------------
39 //! Class for accessing the strings table.
40 class coffi_strings : public virtual string_to_name_provider
41 {
42  public:
43  //---------------------------------------------------------------------
44  coffi_strings() : strings_{0}, strings_reserved_{0} { clean_strings(); }
45 
46  //---------------------------------------------------------------------
47  //! Discards the copy constructor
48  coffi_strings(const coffi_strings&) = delete;
49 
50  //---------------------------------------------------------------------
51  virtual ~coffi_strings()
52  {
53  clean_strings();
54  delete[] strings_;
55  }
56 
57  //---------------------------------------------------------------------
58  uint32_t get_strings_size() const
59  {
60  if (!strings_) {
61  return 0;
62  }
63  return *reinterpret_cast<uint32_t*>(strings_);
64  }
65 
66  //---------------------------------------------------------------------
67  void set_strings_size(uint32_t value)
68  {
69  if (!strings_) {
70  return;
71  }
72  *reinterpret_cast<uint32_t*>(strings_) = value;
73  }
74 
75  //---------------------------------------------------------------------
76  //! @copydoc string_to_name_provider::string_to_name()
77  virtual std::string string_to_name(const char* str) const
78  {
79  return string_to_name_internal(str, false);
80  }
81 
82  //---------------------------------------------------------------------
83  //! @copydoc string_to_name_provider::section_string_to_name()
84  virtual std::string section_string_to_name(const char* str) const
85  {
86  return string_to_name_internal(str, true);
87  }
88 
89  //---------------------------------------------------------------------
90  //! @copydoc string_to_name_provider::name_to_string()
91  virtual void name_to_string(const std::string& name, char* str)
92  {
93  return name_to_string_internal(name, str, false);
94  }
95 
96  //---------------------------------------------------------------------
97  //! @copydoc string_to_name_provider::name_to_section_string()
98  virtual void name_to_section_string(const std::string& name, char* str)
99  {
100  return name_to_string_internal(name, str, true);
101  }
102 
103  //---------------------------------------------------------------------
104  virtual const char* get_strings() const { return strings_; }
105 
106  //---------------------------------------------------------------------
107  virtual void set_strings(const char* str, uint32_t size)
108  {
109  char* new_strings = new char[size];
110  if (new_strings) {
111  std::copy(str, str + size, new_strings);
112  delete[] strings_;
113  strings_ = new_strings;
114  strings_reserved_ = size;
115  set_strings_size(size);
116  }
117  }
118 
119  //---------------------------------------------------------------------
120  protected:
121  //---------------------------------------------------------------------
122  void clean_strings()
123  {
124  if (strings_) {
125  delete[] strings_;
126  }
127  strings_ = new char[4];
128  strings_reserved_ = 4;
129  set_strings_size(4);
130  }
131 
132  //---------------------------------------------------------------------
133  bool load_strings(std::istream& stream, const coff_header* header)
134  {
135  clean_strings();
136 
137  if (header->get_symbol_table_offset() == 0) {
138  return true;
139  }
140 
141  uint32_t strings_offset =
142  header->get_symbol_table_offset() +
143  header->get_symbols_count() * sizeof(symbol_record);
144  stream.seekg(strings_offset);
145  stream.read(strings_, 4);
146  char* new_strings = new char[get_strings_size()];
147  if (!new_strings) {
148  return false;
149  }
150  strings_reserved_ = get_strings_size();
151  stream.seekg(strings_offset);
152  stream.read(new_strings, get_strings_size());
153  if (stream.gcount() !=
154  static_cast<std::streamsize>(get_strings_size())) {
155  return false;
156  }
157  delete[] strings_;
158  strings_ = new_strings;
159  return true;
160  }
161 
162  //---------------------------------------------------------------------
163  void save_strings(std::ostream& stream) const
164  {
165  if (strings_ && get_strings_size() > 4) {
166  stream.write(strings_, get_strings_size());
167  }
168  }
169 
170  //---------------------------------------------------------------------
171  virtual std::string string_to_name_internal(const char* str,
172  bool is_section) const
173  {
174  std::string ret;
175 
176  if (*(uint32_t*)str == 0 && strings_) {
177  uint32_t off = *(uint32_t*)(str + sizeof(uint32_t));
178  ret = strings_ + off;
179  }
180  else if (is_section && str[0] == '/') {
181  int32_t off = std::atol(str + 1);
182  ret = strings_ + off;
183  }
184  else {
185  char dst[COFFI_NAME_SIZE + 1];
186  dst[COFFI_NAME_SIZE] = 0;
187  std::strncpy(dst, str, COFFI_NAME_SIZE);
188  ret = std::string(dst);
189  }
190 
191  return ret;
192  }
193 
194  //---------------------------------------------------------------------
195  virtual void
196  name_to_string_internal(const std::string& name, char* str, bool is_section)
197  {
198  size_t size = name.size();
199  if (size > COFFI_NAME_SIZE) {
200  size++;
201  uint32_t offset = get_strings_size();
202  if (get_strings_size() + size > strings_reserved_) {
203  uint32_t new_strings_reserved =
204  2 * (strings_reserved_ + narrow_cast<uint32_t>(size));
205  char* new_strings = new char[new_strings_reserved];
206  if (!new_strings) {
207  offset = 0;
208  size = 0;
209  }
210  else {
211  strings_reserved_ = new_strings_reserved;
212  std::copy(strings_, strings_ + get_strings_size(),
213  new_strings);
214  delete[] strings_;
215  strings_ = new_strings;
216  }
217  }
218  std::copy(name.c_str(), name.c_str() + size,
219  strings_ + get_strings_size());
220  set_strings_size(get_strings_size() + narrow_cast<uint32_t>(size));
221  if (is_section) {
222  str[0] = '/';
223  std::string s = std::to_string(offset);
224  std::strncpy(str + 1, s.c_str(), COFFI_NAME_SIZE - 1);
225  }
226  else {
227  *(uint32_t*)str = 0;
228  *((uint32_t*)str + 1) = offset;
229  }
230  }
231  else {
232  std::fill_n(str, COFFI_NAME_SIZE, '\0');
233  std::copy(name.begin(), name.end(), str);
234  }
235  }
236 
237  //---------------------------------------------------------------------
238  char* strings_;
239  uint32_t strings_reserved_;
240 };
241 
242 } // namespace COFFI
243 
244 #endif //COFFI_STRINGS_HPP
Class for accessing the strings table.
virtual std::string string_to_name(const char *str) const
Converts an 8-bytes symbol short name into a full name, eventually by looking into the strings table.
coffi_strings(const coffi_strings &)=delete
Discards the copy constructor.
virtual void name_to_string(const std::string &name, char *str)
Converts symbol full name into an 8-bytes short name, eventually creating an entry in the strings tab...
virtual void name_to_section_string(const std::string &name, char *str)
Converts section full name into an 8-bytes short name, eventually creating an entry in the strings ta...
virtual std::string section_string_to_name(const char *str) const
Converts an 8-bytes section short name into a full name, eventually by looking into the strings table...
Interface for accessing to the string table.
COFFI library classes for the COFF file headers.
#define COFFI_NAME_SIZE
COFF symbol names size.
Definition: coffi_types.hpp:62
COFFI library utilities.
COFFI library namespace.
Definition: coffi.hpp:66