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