ROSE  0.11.2.0
PeSymbolTable.C
1 /* Windows PE COFF Symbol Tables (SgAsmCoffSymbolTable and related objects) */
2 #include <rosePublicConfig.h>
3 #ifdef ROSE_BUILD_BINARY_ANALYSIS_SUPPORT
4 #include "sage3basic.h"
5 
6 #include "Diagnostics.h"
7 
8 // In order to efficiently (in terms of amount of code) parse a file format that's defined for a different architecture, we
9 // need to occassionally take addresses of structs that don't follow alignment rules for this architecture.
10 #pragma GCC diagnostic ignored "-Waddress-of-packed-member"
11 
12 using namespace Rose;
13 using namespace Rose::Diagnostics;
14 
15 /* Constructor reads symbol table entries beginning at entry 'i'. We can't pass an array of COFFSymbolEntry_disk structs
16  * because the disk size is 18 bytes, which is not properly aligned according to the C standard. Therefore we pass the actual
17  * section and table index. The symbol occupies the specified table slot and st_num_aux_entries additional slots.
18  *
19  * See http://www.skyfree.org/linux/references/coff.pdf */
20 void
21 SgAsmCoffSymbol::ctor(SgAsmPEFileHeader *fhdr, SgAsmGenericSection *symtab, SgAsmGenericSection *strtab, size_t idx)
22 {
23  ASSERT_not_null(fhdr);
24  ASSERT_not_null(symtab);
25  ASSERT_not_null(strtab);
26 
27  Sawyer::Message::Stream debug(mlog[DEBUG]);
28 
29  static uint8_t zeroRecord[COFFSymbol_disk_size];
30  memset(zeroRecord, 0, sizeof zeroRecord);
31  COFFSymbol_disk disk;
32  symtab->read_content_local(idx * COFFSymbol_disk_size, &disk, COFFSymbol_disk_size);
33  if (0 == memcmp(&disk, zeroRecord, COFFSymbol_disk_size))
34  throw FormatError("zero symbol record");
35 
36  if (disk.st_zero == 0) {
37  p_st_name_offset = ByteOrder::le_to_host(disk.st_offset);
38  if (p_st_name_offset < 4)
39  throw FormatError("name collides with size field");
40  std::string s = strtab->read_content_local_str(p_st_name_offset);
41  set_name(new SgAsmBasicString(s));
42  } else {
43  char temp[9];
44  memcpy(temp, disk.st_name, 8);
45  temp[8] = '\0';
46  set_name(new SgAsmBasicString(temp));
47  p_st_name_offset = 0;
48  }
49 
50  p_st_name = get_name()->get_string();
51  p_st_section_num = ByteOrder::le_to_host(disk.st_section_num);
52  p_st_type = ByteOrder::le_to_host(disk.st_type);
53  p_st_storage_class = ByteOrder::le_to_host(disk.st_storage_class);
54  p_st_num_aux_entries = ByteOrder::le_to_host(disk.st_num_aux_entries);
55 
56  /* Bind to section number. We can do this now because we've already parsed the PE Section Table */
57  ASSERT_not_null(fhdr->get_section_table());
58  if (p_st_section_num > 0) {
59  p_bound = fhdr->get_file()->get_section_by_id(p_st_section_num);
60  if (NULL==p_bound) {
61  mlog[WARN] <<"PE symbol \"" <<StringUtility::cEscape(p_st_name) <<"\" (index " <<idx <<")"
62  <<" is not bound to any section (section " <<p_st_section_num <<")\n";
63  }
64  }
65 
66  /* Make initial guesses for storage class, type, and definition state. We'll adjust them after reading aux entries. */
67  p_value = ByteOrder::le_to_host(disk.st_value);
68  p_def_state = SYM_DEFINED;
69  switch (p_st_storage_class) {
70  case 0: p_binding = SYM_NO_BINDING; break; /*none*/
71  case 1: p_binding = SYM_LOCAL; break; /*stack*/
72  case 2: p_binding = SYM_GLOBAL; break; /*extern*/
73  case 3: p_binding = SYM_GLOBAL; break; /*static*/
74  case 4: p_binding = SYM_LOCAL; break; /*register*/
75  case 5: p_binding = SYM_GLOBAL; break; /*extern def*/
76  case 6: p_binding = SYM_LOCAL; break; /*label*/
77  case 7: p_binding = SYM_LOCAL; break; /*label(undef)*/
78  case 8: p_binding = SYM_LOCAL; break; /*struct member*/
79  case 9: p_binding = SYM_LOCAL; break; /*formal arg*/
80  case 10: p_binding = SYM_LOCAL; break; /*struct tag*/
81  case 11: p_binding = SYM_LOCAL; break; /*union member*/
82  case 12: p_binding = SYM_GLOBAL; break; /*union tag*/
83  case 13: p_binding = SYM_GLOBAL; break; /*typedef*/
84  case 14: p_binding = SYM_GLOBAL; break; /*static(undef)*/
85  case 15: p_binding = SYM_GLOBAL; break; /*enum tag*/
86  case 16: p_binding = SYM_LOCAL; break; /*enum member*/
87  case 17: p_binding = SYM_GLOBAL; break; /*register param*/
88  case 18: p_binding = SYM_LOCAL; break; /*bit field*/
89  case 100: p_binding = SYM_GLOBAL; break; /*block(bb or eb)*/
90  case 101: p_binding = SYM_GLOBAL; break; /*function*/
91  case 102: p_binding = SYM_LOCAL; break; /*struct end*/
92  case 103: p_binding = SYM_GLOBAL; break; /*file*/
93  case 104: p_binding = SYM_GLOBAL; break; /*section*/
94  case 105: p_binding = SYM_WEAK; break; /*weak extern*/
95  case 107: p_binding = SYM_LOCAL; break; /*CLR token*/
96  case 0xff: p_binding = SYM_GLOBAL; break; /*end of function*/
97  }
98  switch (p_st_type & 0xf0) {
99  case 0x00: p_type = SYM_NO_TYPE; break; /*none*/
100  case 0x10: p_type = SYM_DATA; break; /*ptr*/
101  case 0x20: p_type = SYM_FUNC; break; /*function*/
102  case 0x30: p_type = SYM_ARRAY; break; /*array*/
103  }
104 
105  if (debug) {
106  debug <<"COFF symbol entry #" <<idx <<" before AUX parsing"
107  <<": p_st_name_offset=" <<p_st_name_offset
108  <<", p_st_name=\"" <<StringUtility::cEscape(p_st_name) <<"\""
109  <<", p_st_section_num=" <<p_st_section_num
110  <<", p_st_type=" <<p_st_type
111  <<", p_st_storage_class=" <<p_st_storage_class
112  <<", p_st_num_aux_entries=" <<p_st_num_aux_entries
113  <<", p_value=" <<p_value
114  <<", p_def_state=" <<p_def_state
115  <<", p_binding=" <<p_binding
116  <<", p_type=" <<p_type <<"\n";
117  }
118 
119  /* Read additional aux entries. We keep this as 'char' to avoid alignment problems. */
120  if (p_st_num_aux_entries > 0) {
121  p_aux_data = symtab->read_content_local_ucl((idx+1)*COFFSymbol_disk_size, p_st_num_aux_entries * COFFSymbol_disk_size);
122 
123  if (2 /*external*/ == p_st_storage_class && get_type() == SYM_FUNC && p_st_section_num > 0) {
124  // Auxiliary record format 1: Function definitions
125  unsigned bf_idx = ByteOrder::le_to_host(*(uint32_t*)&(p_aux_data[0]));
126  unsigned size = ByteOrder::le_to_host(*(uint32_t*)&(p_aux_data[4]));
127  unsigned lnum_ptr = ByteOrder::le_to_host(*(uint32_t*)&(p_aux_data[8]));
128  unsigned next_fn_idx = ByteOrder::le_to_host(*(uint32_t*)&(p_aux_data[12]));
129  unsigned res1 = ByteOrder::le_to_host(*(uint16_t*)&(p_aux_data[16]));
130  set_size(size);
131  SAWYER_MESG(debug) <<"COFF aux func " <<escapeString(p_st_name) <<": bf_idx=" <<bf_idx
132  <<", size=" <<size <<", lnum_ptr=" <<StringUtility::addrToString(lnum_ptr)
133  <<", next_fn_idx=" <<next_fn_idx <<", res1=" <<res1 <<"\n";
134 
135  } else if (p_st_storage_class == 101 /*function*/ && (p_st_name == ".bf" || p_st_name == ".ef")) {
136  // Auxiliary record format 2: .bf and .ef symbols
137  unsigned res1 = ByteOrder::le_to_host(*(uint32_t*)&(p_aux_data[0]));
138  unsigned lnum = ByteOrder::le_to_host(*(uint16_t*)&(p_aux_data[4])); /*line num within source file*/
139  unsigned res2 = ByteOrder::le_to_host(*(uint16_t*)&(p_aux_data[6]));
140  unsigned res3 = ByteOrder::le_to_host(*(uint32_t*)&(p_aux_data[8]));
141  unsigned next_bf = ByteOrder::le_to_host(*(uint32_t*)&(p_aux_data[12])); /*only for .bf; reserved in .ef*/
142  unsigned res4 = ByteOrder::le_to_host(*(uint16_t*)&(p_aux_data[16]));
143  SAWYER_MESG(debug) <<"COFF aux " <<escapeString(p_st_name) <<": res1=" <<res1 <<", lnum=" <<lnum
144  <<", res2=" <<res2 <<", res3=" <<res3 <<", next_bf=" <<next_bf <<", res4=" <<res4 <<"\n";
145 
146  } else if (p_st_storage_class == 2/*external*/ && p_st_section_num == 0/*undef*/ && get_value()==0) {
147  // Auxiliary record format 3: weak externals
148  unsigned sym2_idx = ByteOrder::le_to_host(*(uint32_t*)&(p_aux_data[0]));
149  unsigned flags = ByteOrder::le_to_host(*(uint32_t*)&(p_aux_data[4]));
150  unsigned res1 = ByteOrder::le_to_host(*(uint32_t*)&(p_aux_data[8]));
151  unsigned res2 = ByteOrder::le_to_host(*(uint32_t*)&(p_aux_data[12]));
152  unsigned res3 = ByteOrder::le_to_host(*(uint16_t*)&(p_aux_data[16]));
153  SAWYER_MESG(debug) <<"COFF aux weak " <<escapeString(p_st_name) <<": sym2_idx=" <<sym2_idx
154  <<", flags=" <<flags <<", res1=" <<res1 <<", res2=" <<res2 <<", res3=" <<res3 <<"\n";
155 
156  } else if (p_st_storage_class == 103/*file*/ && 0 == p_st_name.compare(".file")) {
157  // Auxiliary record format 4: files. The file name is stored in the aux data as either the name itself or an offset
158  // into the string table. Replace the fake ".file" with the real file name.
159  const COFFSymbol_disk *d = (const COFFSymbol_disk*) &(p_aux_data[0]);
160  if (0 == d->st_zero) {
161  rose_addr_t fname_offset = ByteOrder::le_to_host(d->st_offset);
162  if (fname_offset < 4)
163  throw FormatError("name collides with size field");
164  set_name(new SgAsmBasicString(strtab->read_content_local_str(fname_offset)));
165  SAWYER_MESG(debug) <<"COFF aux file: offset=" <<fname_offset
166  <<", name=\"" <<get_name()->get_string(true) <<"\"\n";
167 
168  } else {
169  /* Aux data contains a NUL-padded name; the NULs (if any) are not part of the name. */
170  ASSERT_require(p_st_num_aux_entries == 1);
171  char fname[COFFSymbol_disk_size+1];
172  memcpy(fname, &(p_aux_data[0]), COFFSymbol_disk_size);
173  fname[COFFSymbol_disk_size] = '\0';
174  set_name(new SgAsmBasicString(fname));
175  SAWYER_MESG(debug) <<"COFF aux file: inline-name=\"" <<get_name()->get_string(true) <<"\"\n";
176  }
177  set_type(SYM_FILE);
178 
179  } else if (p_st_storage_class == 3/*static*/ && NULL != fhdr->get_file()->get_section_by_name(p_st_name, '$')) {
180  // Auxiliary record format 5: Section definition.
181  unsigned size = ByteOrder::le_to_host(*(uint32_t*)&(p_aux_data[0])); /*same as section header SizeOfRawData */
182  unsigned nrel = ByteOrder::le_to_host(*(uint16_t*)&(p_aux_data[4])); /*number of relocations*/
183  unsigned nln_ents = ByteOrder::le_to_host(*(uint16_t*)&(p_aux_data[6])); /*number of line number entries */
184  unsigned cksum = ByteOrder::le_to_host(*(uint32_t*)&(p_aux_data[8]));
185  unsigned sect_id = ByteOrder::le_to_host(*(uint16_t*)&(p_aux_data[12])); /*1-base index into section table*/
186  unsigned comdat = p_aux_data[14]; /*comdat selection number if section is a COMDAT section*/
187  unsigned res1 = p_aux_data[15];
188  unsigned res2 = ByteOrder::le_to_host(*(uint16_t*)&(p_aux_data[16]));
189  set_size(size);
190  set_type(SYM_SECTION);
191  SAWYER_MESG(debug) <<"COFF aux section: size=" <<size <<", nrel=" <<nrel <<", nln_ents=" <<nln_ents
192  <<", cksum=" <<cksum <<", sect_id=" <<sect_id <<", comdat=" <<comdat
193  <<", res1=" <<res1 <<", res2=" <<res2 <<"\n";
194 
195  } else if (p_st_storage_class==3/*static*/ && (p_st_type & 0xf)==0/*null*/ &&
196  get_value()==0 && NULL!=fhdr->get_file()->get_section_by_name(p_st_name)) {
197  // Auxiliary record for common data (COMDAT) sections
198  // FIXME[Robb P Matzke 2017-05-17]: The record format isn't documented in the reference listed above.
199  if (debug) {
200  debug <<"COFF aux comdat " <<escapeString(p_st_name) <<": aux record ignored\n";
201  hexdump(debug, (rose_addr_t) symtab->get_offset()+(idx+1)*COFFSymbol_disk_size, " ", p_aux_data);
202  }
203 
204  } else {
205  if (mlog[WARN]) {
206  mlog[WARN] <<"COFF aux unknown " <<escapeString(p_st_name)
207  <<": st_storage_class=" <<p_st_storage_class
208  <<", st_type=" <<p_st_type <<", st_section_num=" <<p_st_section_num <<"\n";
209  hexdump(mlog[WARN], symtab->get_offset()+(idx+1)*COFFSymbol_disk_size, " ", p_aux_data);
210  }
211  }
212  }
213 }
214 
215 /* Encode a symbol back into disk format */
216 void *
217 SgAsmCoffSymbol::encode(COFFSymbol_disk *disk) const
218 {
219  if (0 == p_st_name_offset) {
220  /* Name is stored in entry */
221  memset(disk->st_name, 0, sizeof(disk->st_name));
222  ROSE_ASSERT(p_st_name.size() <= sizeof(disk->st_name));
223  memcpy(disk->st_name, p_st_name.c_str(), p_st_name.size());
224  } else {
225  /* Name is an offset into the string table */
226  disk->st_zero = 0;
227  ByteOrder::host_to_le(p_st_name_offset, &(disk->st_offset));
228  }
229 
230  // ByteOrder::host_to_le(get_value(), &(disk->st_value));
231  ByteOrder::host_to_le(p_value, &(disk->st_value));
232  ByteOrder::host_to_le(p_st_section_num, &(disk->st_section_num));
233  ByteOrder::host_to_le(p_st_type, &(disk->st_type));
234  ByteOrder::host_to_le(p_st_storage_class, &(disk->st_storage_class));
235  ByteOrder::host_to_le(p_st_num_aux_entries, &(disk->st_num_aux_entries));
236  return disk;
237 }
238 
239 /* Print some debugging info */
240 void
241 SgAsmCoffSymbol::dump(FILE *f, const char *prefix, ssize_t idx) const
242 {
243  char p[4096], ss[128], tt[128];
244  const char *s=NULL, *t=NULL;
245  if (idx>=0) {
246  sprintf(p, "%sCOFFSymbol[%zd].", prefix, idx);
247  } else {
248  sprintf(p, "%sCOFFSymbol.", prefix);
249  }
250 
251  const int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
252 
253 
254  SgAsmGenericSymbol::dump(f, p, -1);
255 
256  switch (p_st_section_num) {
257  case 0: s = "external, not assigned"; break;
258  case -1: s = "absolute value"; break;
259  case -2: s = "general debug, no section"; break;
260  default: sprintf(ss, "%d", p_st_section_num); s = ss; break;
261  }
262  fprintf(f, "%s%-*s = %s\n", p, w, "st_section_num", s);
263 
264  switch (p_st_type & 0xf0) {
265  case 0x00: s = "none"; break;
266  case 0x10: s = "pointer"; break;
267  case 0x20: s = "function"; break;
268  case 0x30: s = "array"; break;
269  default:
270  sprintf(ss, "%u", p_st_type >> 8);
271  s = ss;
272  break;
273  }
274  switch (p_st_type & 0xf) {
275  case 0x00: t = "none"; break;
276  case 0x01: t = "void"; break;
277  case 0x02: t = "char"; break;
278  case 0x03: t = "short"; break;
279  case 0x04: t = "int"; break;
280  case 0x05: t = "long"; break;
281  case 0x06: t = "float"; break;
282  case 0x07: t = "double"; break;
283  case 0x08: t = "struct"; break;
284  case 0x09: t = "union"; break;
285  case 0x0a: t = "enum"; break;
286  case 0x0b: t = "enum member"; break;
287  case 0x0c: t = "byte"; break;
288  case 0x0d: t = "2-byte word"; break;
289  case 0x0e: t = "unsigned int"; break;
290  case 0x0f: t = "4-byte unsigned"; break;
291  default:
292  sprintf(tt, "%u", p_st_type & 0xf);
293  t = tt;
294  break;
295  }
296  fprintf(f, "%s%-*s = %s / %s\n", p, w, "st_type", s, t);
297 
298  switch (p_st_storage_class) {
299  case 0: s = "none"; t = ""; break;
300  case 1: s = "auto variable"; t = "stack frame offset"; break;
301  case 2: s = "external"; t = "size or section offset"; break;
302  case 3: s = "static"; t = "offset in section or section name"; break;
303  case 4: s = "register"; t = "register number"; break;
304  case 5: s = "extern_def"; t = ""; break;
305  case 6: s = "label"; t = "offset in section"; break;
306  case 7: s = "label(undef)"; t = ""; break;
307  case 8: s = "struct member"; t = "member number"; break;
308  case 9: s = "formal arg"; t = "argument number"; break;
309  case 10: s = "struct tag"; t = "tag name"; break;
310  case 11: s = "union member"; t = "member number"; break;
311  case 12: s = "union tag"; t = "tag name"; break;
312  case 13: s = "typedef"; t = ""; break;
313  case 14: s = "static(undef)"; t = ""; break;
314  case 15: s = "enum tag"; t = ""; break;
315  case 16: s = "enum member"; t = "member number"; break;
316  case 17: s = "register param"; t = ""; break;
317  case 18: s = "bit field"; t = "bit number"; break;
318  case 19: s = "auto arg"; t = ""; break;
319  case 20: s = "dummy entry (EOB)"; t=""; break;
320  case 100: s = "block(bb,eb)"; t = "relocatable address"; break;
321  case 101: s = "function"; t = "nlines or size"; break;
322  case 102: s = "struct end"; t = ""; break;
323  case 103: s = "file"; t = ""; break;
324  case 104: s = "section/line#"; t = ""; break;
325  case 105: s = "weak extern"; t = ""; break;
326  case 106: s = "ext in dmert pub lib";t=""; break;
327  case 107: s = "CLR token"; t = ""; break;
328  case 0xff: s = "end of function"; t = ""; break;
329  default:
330  sprintf(ss, "%u", p_st_storage_class);
331  s = ss;
332  t = "";
333  break;
334  }
335  fprintf(f, "%s%-*s = %s\n", p, w, "st_storage_class", s);
336  fprintf(f, "%s%-*s = \"%s\"\n", p, w, "st_name", escapeString(p_st_name).c_str());
337  fprintf(f, "%s%-*s = %u\n", p, w, "st_num_aux_entries", p_st_num_aux_entries);
338  fprintf(f, "%s%-*s = %" PRIuPTR " bytes\n", p, w, "aux_data", p_aux_data.size());
339  hexdump(f, 0, std::string(p)+"aux_data at ", p_aux_data);
340 }
341 
342 /* Constructor */
343 void
344 SgAsmCoffSymbolTable::ctor()
345 {
346  set_synthesized(true);
347  set_name(new SgAsmBasicString("COFF Symbols"));
348  set_purpose(SP_SYMTAB);
349 
350  p_symbols = new SgAsmCoffSymbolList;
351  p_symbols->set_parent(this);
352 }
353 
355 SgAsmCoffSymbolTable::parse()
356 {
357  /* Set the section size according to the number of entries indicated in the header. */
358  SgAsmPEFileHeader *fhdr = dynamic_cast<SgAsmPEFileHeader*>(get_header());
359  ROSE_ASSERT(fhdr!=NULL);
360  set_offset(fhdr->get_e_coff_symtab());
361  set_size(fhdr->get_e_coff_nsyms()*SgAsmCoffSymbol::COFFSymbol_disk_size);
362 
363  SgAsmGenericSection::parse();
364 
365  /* The string table immediately follows the symbols. The first four bytes of the string table are the size of the
366  * string table in little endian. */
367  rose_addr_t strtab_offset = get_offset() + fhdr->get_e_coff_nsyms() * SgAsmCoffSymbol::COFFSymbol_disk_size;
368  p_strtab = new SgAsmGenericSection(fhdr->get_file(), fhdr);
369  p_strtab->set_offset(strtab_offset);
370  p_strtab->set_size(sizeof(uint32_t));
371  p_strtab->set_synthesized(true);
372  p_strtab->set_name(new SgAsmBasicString("COFF Symbol Strtab"));
373  p_strtab->set_purpose(SP_HEADER);
374  p_strtab->parse();
375 
376  uint32_t word;
377  p_strtab->read_content(0, &word, sizeof word);
378  rose_addr_t strtab_size = ByteOrder::le_to_host(word);
379  if (strtab_size < sizeof(uint32_t))
380  throw FormatError("COFF symbol table string table size is less than four bytes");
381  p_strtab->extend(strtab_size - sizeof(uint32_t));
382 
383  /* Parse symbols until we've parsed the required number or we run off the end of the section. */
384  for (size_t i = 0; i < fhdr->get_e_coff_nsyms(); i++) {
385  try {
386  SgAsmCoffSymbol *symbol = new SgAsmCoffSymbol(fhdr, this, p_strtab, i);
387  i += symbol->get_st_num_aux_entries();
388  p_symbols->get_symbols().push_back(symbol);
389  } catch (const FormatError &e) {
390  mlog[WARN] <<"SgAsmCoffSymbolTable::parse: invalid symbol: " <<e.what() <<"\n"
391  <<" in section \"" <<get_name()->get_string(true) <<"\"[" <<get_id() <<"]\n"
392  <<" symbol #" <<i <<" at file offset "
393  <<StringUtility::addrToString(get_offset() + i*SgAsmCoffSymbol::COFFSymbol_disk_size) <<"\n"
394  <<" discarding this symbol\n";
395  } catch (const ShortRead &e) {
396  mlog[WARN] <<"SgAsmCoffSymbolTable::parse: read past end of section \"" <<get_name()->get_string(true) <<"\""
397  <<"[" <<get_id() <<"]\n"
398  <<" symbol #" <<i <<" at file offset " <<StringUtility::addrToString(e.offset) <<"\n"
399  <<" skipping " <<StringUtility::plural(fhdr->get_e_coff_nsyms()-i, "symbols")
400  <<" (including this one)\n";
401  break;
402  }
403  }
404 
405  return this;
406 }
407 
410 size_t
412 {
413  size_t nsyms = p_symbols->get_symbols().size();
414  size_t nslots = nsyms;
415  for (size_t i=0; i<nsyms; i++) {
416  SgAsmCoffSymbol *symbol = p_symbols->get_symbols()[i];
417  nslots += symbol->get_st_num_aux_entries();
418  }
419  return nslots;
420 }
421 
422 /* Write symbol table back to disk */
423 void
424 SgAsmCoffSymbolTable::unparse(std::ostream &f) const
425 {
426  rose_addr_t spos = 0; /*section offset*/
427 
428  for (size_t i=0; i < p_symbols->get_symbols().size(); i++) {
429  SgAsmCoffSymbol *symbol = p_symbols->get_symbols()[i];
431  symbol->encode(&disk);
432  spos = write(f, spos, SgAsmCoffSymbol::COFFSymbol_disk_size, &disk);
433  spos = write(f, (rose_addr_t) spos, symbol->get_aux_data());
434  }
435  if (get_strtab())
436  get_strtab()->unparse(f);
437 }
438 
439 /* Print some debugging info */
440 void
441 SgAsmCoffSymbolTable::dump(FILE *f, const char *prefix, ssize_t idx) const
442 {
443  char p[4096];
444  if (idx>=0) {
445  sprintf(p, "%sCOFFSymtab[%zd].", prefix, idx);
446  } else {
447  sprintf(p, "%sCOFFSymtab.", prefix);
448  }
449 
450 
451  const int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
452 
453  SgAsmGenericSection::dump(f, p, -1);
454  fprintf(f, "%s%-*s = %" PRIuPTR " symbols\n", p, w, "size", p_symbols->get_symbols().size());
455  for (size_t i = 0; i < p_symbols->get_symbols().size(); i++) {
456  p_symbols->get_symbols()[i]->dump(f, p, i);
457  }
458 
459  if (variantT() == V_SgAsmCoffSymbolTable) //unless a base class
460  hexdump(f, 0, std::string(p)+"data at ", p_data);
461 }
462 
463 #endif
std::string read_content_local_str(rose_addr_t rel_offset, bool strict=true)
Reads a string from the file.
SgAsmGenericFile * get_file() const
Property: File to which this section belongs.
String associated with a binary file.
Contiguous region of a file.
std::string plural(T n, const std::string &plural_phrase, const std::string &singular_phrase="")
Helpful way to print singular or plural words.
SgUnsignedCharList read_content_local_ucl(rose_addr_t rel_offset, rose_addr_t size)
Reads content of a section and returns it as a container.
SgAsmPESectionTable * get_section_table() const
Property: Section table.
virtual void unparse(std::ostream &) const
Write a section back to the file.
ROSE_DLL_API Sawyer::Message::Facility mlog
Diagnostic facility for the ROSE library as a whole.
size_t read_content_local(rose_addr_t rel_offset, void *dst_buf, rose_addr_t size, bool strict=true)
Reads data from a file.
void set_parent(SgNode *parent)
All nodes in the AST contain a reference to a parent node.
SgAsmGenericSection * get_section_by_name(const std::string &, char sep=0, size_t *nfound=0) const
Find section by name.
rose_addr_t get_offset() const
Property: Offset to start of section in file.
std::string get_name(const SgNode *node)
Generate a useful name to describe the SgNode.
Main namespace for the ROSE library.
ROSE_UTIL_API std::string cEscape(const std::string &, char context= '"')
Escapes characters that are special to C/C++.
ROSE_DLL_API int set_name(SgInitializedName *initializedNameNode, SgName new_name)
set_name of symbol in symbol table.
virtual void set_offset(rose_addr_t)
Property: Offset to start of section in file.
virtual void dump(FILE *, const char *prefix, ssize_t idx) const
Print some debugging info.
rose_addr_t get_e_coff_symtab() const
Property: COFF symbol table.
virtual void dump(FILE *f, const char *prefix, ssize_t idx) const $ROSE_OVERRIDE
Print some debugging info.
unsigned get_e_coff_nsyms() const
Property: Number of COFF symbols.
size_t get_nslots() const
Returns the number of COFF Symbol Table slots occupied by the symbol table.
ROSE_UTIL_API std::string addrToString(uint64_t value, size_t nbits=0)
Convert a virtual address to a string.
List of COFF symbols.
Windows PE file header.
Warning messages that indicate an unusual situation from which the program was able to fully recover...
Definition: Message.h:328
Converts text to messages.
Definition: Message.h:1396
Controls diagnostic messages from ROSE.
Definition: Diagnostics.h:290
virtual void dump(FILE *, const char *prefix, ssize_t idx) const
Print some debugging info.
SgAsmGenericSection * get_section_by_id(int id, size_t *nfound=0) const
Find section with specified ID.
COFF symbol table.