ROSE  0.9.6a
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GenericHeader.C
Go to the documentation of this file.
1 /* Generic File Headers (SgAsmGenericHeader and related classes). Describes a binary file header. Most binary files have at
2  * least one header that serves as sort of a superblock for describing the rest of the file. Many formats have more than one
3  * header (e.g., Microsoft Windows files have both a DOS header and a PE header). */
4 
5 #include "sage3basic.h"
6 #include "stringify.h"
7 
8 using namespace rose;
9 
15 void
17 {
18  set_synthesized(true);
19  set_purpose(SP_HEADER);
20 
21  /* The bidirectional link between file and header */
22  get_file()->add_header(this);
23 
24  /* Create child IR nodes and set their parent (initialized to null in real constructor) */
25  ROSE_ASSERT(p_dlls == NULL);
26  p_dlls = new SgAsmGenericDLLList;
27  p_dlls->set_parent(this);
28 
29  ROSE_ASSERT(p_exec_format == NULL);
30  p_exec_format = new SgAsmGenericFormat;
31  p_exec_format->set_parent(this);
32 
33  ROSE_ASSERT(p_sections == NULL);
34  p_sections = new SgAsmGenericSectionList;
35  p_sections->set_parent(this);
36 }
37 
38 /* Destructor must remove header/file link. Children in the AST have already been deleted when called from
39  * SageInterface::deleteAST() */
41 {
42  /* Deletion of section children should have emptied the list of header-to-section links */
43  ROSE_ASSERT(p_sections->get_sections().empty() == true);
44 
45  /* Destroy the header/file bidirectional link. See comment in constructor. */
46  ROSE_ASSERT(get_file()!=NULL);
47  get_file()->remove_header(this);
48 }
49 
51 bool
53 {
54  bool reallocated = false;
55  for (SgAsmGenericSectionPtrList::iterator i=p_sections->get_sections().begin(); i!=p_sections->get_sections().end(); ++i) {
56  if ((*i)->reallocate())
57  reallocated = true;
58  }
59  return reallocated;
60 }
61 
63 void
64 SgAsmGenericHeader::unparse(std::ostream &f) const
65 {
67 
68  /* Unparse each section */
69  for (SgAsmGenericSectionPtrList::iterator i=p_sections->get_sections().begin(); i!=p_sections->get_sections().end(); ++i)
70  (*i)->unparse(f);
71 }
72 
77 {
78  if (p_entry_rvas.size()==0)
79  return rose_addr_t();
80  return p_entry_rvas[0].get_rva();
81 }
82 
84 void
86 {
87  ROSE_ASSERT(section != NULL);
88  ROSE_ASSERT(p_sections != NULL);
89  p_sections->set_isModified(true);
90 
91 #ifndef NDEBUG
92  /* New section must not already be present. */
93  for (size_t i = 0; i < p_sections->get_sections().size(); i++) {
94  ROSE_ASSERT(p_sections->get_sections()[i] != section);
95  }
96 #endif
97  section->set_header(this);
98  section->set_parent(p_sections);
99  p_sections->get_sections().push_back(section);
100 }
101 
103 void
105 {
106  if (section!=NULL) {
107  ROSE_ASSERT(p_sections != NULL);
108  SgAsmGenericSectionPtrList::iterator i = find(p_sections->get_sections().begin(),
109  p_sections->get_sections().end(),
110  section);
111  if (i != p_sections->get_sections().end()) {
112  p_sections->get_sections().erase(i);
113  p_sections->set_isModified(true);
114  }
115  }
116 }
117 
119 void
121 {
122  ROSE_ASSERT(p_dlls != NULL);
123  p_dlls->set_isModified(true);
124 
125 #ifndef NDEBUG
126  // for (size_t i = 0; i < p_dlls.size(); i++) {
127  for (size_t i = 0; i < p_dlls->get_dlls().size(); i++) {
128  ROSE_ASSERT(p_dlls->get_dlls()[i] != dll); /*duplicate*/
129  }
130 #endif
131  p_dlls->get_dlls().push_back(dll);
132 
133  dll->set_parent(p_dlls);
134 }
135 
139 {
141  for (SgAsmGenericSectionPtrList::iterator i=p_sections->get_sections().begin(); i!=p_sections->get_sections().end(); ++i) {
142  if ((*i)->is_mapped()) {
143  retval.push_back(*i);
144  }
145  }
146  return retval;
147 }
148 
152 {
154  for (SgAsmGenericSectionPtrList::iterator i=p_sections->get_sections().begin(); i!=p_sections->get_sections().end(); ++i) {
155  if ((*i)->get_id() == id) {
156  retval.push_back(*i);
157  }
158  }
159  return retval;
160 }
161 
164 SgAsmGenericHeader::get_section_by_id(int id, size_t *nfound/*optional*/) const
165 {
166  SgAsmGenericSectionPtrList possible = get_sections_by_id(id);
167  if (nfound) *nfound = possible.size();
168  return possible.size()==1 ? possible[0] : NULL;
169 }
170 
174 SgAsmGenericHeader::get_sections_by_name(std::string name, char sep/*or NUL*/) const
175 {
176  if (sep) {
177  size_t pos = name.find(sep);
178  if (pos!=name.npos)
179  name.erase(pos);
180  }
181 
183  for (SgAsmGenericSectionPtrList::iterator i=p_sections->get_sections().begin(); i!=p_sections->get_sections().end(); ++i) {
184  std::string secname = (*i)->get_name()->get_string();
185  if (sep) {
186  size_t pos = secname.find(sep);
187  if (pos!=secname.npos)
188  secname.erase(pos);
189  }
190  if (0==secname.compare(name))
191  retval.push_back(*i);
192  }
193  return retval;
194 }
195 
198 SgAsmGenericHeader::get_section_by_name(const std::string &name, char sep/*or NUL*/, size_t *nfound/*optional*/) const
199 {
200  SgAsmGenericSectionPtrList possible = get_sections_by_name(name, sep);
201  if (nfound) *nfound = possible.size();
202  return possible.size()==1 ? possible[0] : NULL;
203 }
204 
208 {
210  for (SgAsmGenericSectionPtrList::iterator i=p_sections->get_sections().begin(); i!=p_sections->get_sections().end(); ++i) {
211  SgAsmGenericSection *section = *i;
212  if (offset >= section->get_offset() &&
213  offset < section->get_offset()+section->get_size() &&
214  offset-section->get_offset() + size <= section->get_size())
215  retval.push_back(section);
216  }
217  return retval;
218 }
219 
223 {
224  SgAsmGenericSectionPtrList possible = get_sections_by_offset(offset, size);
225  if (nfound) *nfound = possible.size();
226  return possible.size()==1 ? possible[0] : NULL;
227 }
228 
232 {
234  for (SgAsmGenericSectionPtrList::iterator i = p_sections->get_sections().begin(); i!=p_sections->get_sections().end(); ++i) {
235  SgAsmGenericSection *section = *i;
236  if (section->is_mapped() &&
237  rva >= section->get_mapped_preferred_rva() && rva < section->get_mapped_preferred_rva() + section->get_mapped_size()) {
238  retval.push_back(section);
239  }
240  }
241  return retval;
242 }
243 
247 SgAsmGenericHeader::get_section_by_rva(rose_addr_t rva, size_t *nfound/*optional*/) const
248 {
249  SgAsmGenericSectionPtrList possible = get_sections_by_rva(rva);
250  if (nfound) *nfound = possible.size();
251  return possible.size()==1 ? possible[0] : NULL;
252 }
253 
260 {
261  if (use_preferred) {
262  if (va < get_base_va())
264  rose_addr_t rva = va - get_base_va();
265  return get_sections_by_rva(rva);
266  }
267 
269  for (size_t i=0; i<p_sections->get_sections().size(); i++) {
270  SgAsmGenericSection *section = p_sections->get_sections()[i];
271  if (section->is_mapped() &&
272  va>=section->get_mapped_actual_va() && va<section->get_mapped_actual_va()+section->get_mapped_size())
273  retval.push_back(section);
274  }
275  return retval;
276 }
277 
284 SgAsmGenericHeader::get_section_by_va(rose_addr_t va, bool use_preferred, size_t *nfound/*optional*/) const
285 {
286  SgAsmGenericSectionPtrList possible = get_sections_by_va(va, use_preferred);
287  if (nfound) *nfound = possible.size();
288  return possible.size()==1 ? possible[0] : NULL;
289 }
290 
293 SgAsmGenericHeader::get_best_section_by_va(rose_addr_t va, bool use_preferred, size_t *nfound) const
294 {
295  const SgAsmGenericSectionPtrList &candidates = get_sections_by_va(va, use_preferred);
296  if (nfound) *nfound = candidates.size();
297  return SgAsmGenericFile::best_section_by_va(candidates, va);
298 }
299 
300 /* Print some debugging info */
301 void
302 SgAsmGenericHeader::dump(FILE *f, const char *prefix, ssize_t idx) const
303 {
304  char p[4096];
305  if (idx>=0) {
306  sprintf(p, "%sHeader[%zd].", prefix, idx);
307  } else {
308  sprintf(p, "%sHeader.", prefix);
309  }
310  const int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
311 
312  SgAsmGenericSection::dump(f, p, -1);
313 
314  ROSE_ASSERT(p_exec_format != NULL);
315  p_exec_format->dump(f, p, -1);
316 
317  fprintf(f, "%s%-*s = 0x%x (%s)\n", p, w, "ins_arch",
319 
320  fprintf(f, "%s%-*s = \"", p, w, "magic");
321  for (size_t i = 0; i < p_magic.size(); i++) {
322  switch (p_magic[i]) {
323  case '\\': fputs("\\\\", f); break;
324  case '\n': fputs("\\n", f); break;
325  case '\r': fputs("\\r", f); break;
326  case '\t': fputs("\\t", f); break;
327  default:
328  if (isprint(p_magic[i])) {
329  fputc(p_magic[i], f);
330  } else {
331  fprintf(f, "\\%03o", (unsigned)p_magic[i]);
332  }
333  break;
334  }
335  }
336  fputs("\"\n", f);
337 
338  /* Base virtual address and entry addresses */
339  fprintf(f, "%s%-*s = 0x%08"PRIx64" (%"PRIu64")\n", p, w, "base_va", get_base_va(), get_base_va());
340  fprintf(f, "%s%-*s = %zu entry points\n", p, w, "entry_rva.size", p_entry_rvas.size());
341  for (size_t i = 0; i < p_entry_rvas.size(); i++) {
342  char label[64];
343  sprintf(label, "entry_rva[%zu]", i);
344  rose_addr_t entry_rva = p_entry_rvas[i].get_rva();
345  fprintf(f, "%s%-*s = 0x%08"PRIx64" (%"PRIu64")\n", p, w, label, entry_rva, entry_rva);
346  SgAsmGenericSectionPtrList sections = get_file()->get_sections();
347  dump_containing_sections(f, std::string(p)+label, entry_rva, sections);
348  }
349 
350  fprintf(f, "%s%-*s = %zu sections\n", p, w, "section", p_sections->get_sections().size());
351  for (size_t i=0; i<p_sections->get_sections().size(); i++) {
352  SgAsmGenericSection *section = p_sections->get_sections()[i];
353  char label[1024];
354  sprintf(label, "section[%zu]", i);
355  fprintf(f, "%s%-*s = [%d] \"%s\"\n", p, w, label, section->get_id(), section->get_name()->get_string(true).c_str());
356  }
357 
358  fprintf(f, "%s%-*s = %zu entries\n", p, w, "DLL.size", p_dlls->get_dlls().size());
359  for (size_t i = 0; i < p_dlls->get_dlls().size(); i++)
360  p_dlls->get_dlls()[i]->dump(f, p, i);
361 }
362