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