/** Returns the number of COFF Symbol Table slots occupied by the symbol table. The number of slots can be larger than the
 *  number of symbols since some symbols might have auxiliary entries. */
size_t
SgAsmCoffSymbolTable::get_nslots() const
{
    size_t nsyms = p_symbols->get_symbols().size();
    size_t nslots = nsyms;
    for (size_t i=0; i<nsyms; i++) {
        SgAsmCoffSymbol *symbol = p_symbols->get_symbols()[i];
        nslots += symbol->get_st_num_aux_entries();
    }
    return nslots;
}
/* Write symbol table back to disk */
void
SgAsmCoffSymbolTable::unparse(std::ostream &f) const
{
    rose_addr_t spos = 0; /*section offset*/
    
    for (size_t i=0; i < p_symbols->get_symbols().size(); i++) {
        SgAsmCoffSymbol *symbol = p_symbols->get_symbols()[i];
        SgAsmCoffSymbol::COFFSymbol_disk disk;
        symbol->encode(&disk);
        spos = write(f, spos, SgAsmCoffSymbol::COFFSymbol_disk_size, &disk);
        spos = write(f, (rose_addr_t) spos, symbol->get_aux_data());
    }
    if (get_strtab())
        get_strtab()->unparse(f);
}
SgAsmCoffSymbolTable*
SgAsmCoffSymbolTable::parse()
{
    /* Set the section size according to the number of entries indicated in the header. */
    SgAsmPEFileHeader *fhdr = dynamic_cast<SgAsmPEFileHeader*>(get_header());
    ROSE_ASSERT(fhdr!=NULL);
    set_offset(fhdr->get_e_coff_symtab());
    set_size(fhdr->get_e_coff_nsyms()*SgAsmCoffSymbol::COFFSymbol_disk_size);

    SgAsmGenericSection::parse();

    /* The string table immediately follows the symbols. The first four bytes of the string table are the size of the
     * string table in little endian. */
    rose_addr_t strtab_offset = get_offset() + fhdr->get_e_coff_nsyms() * SgAsmCoffSymbol::COFFSymbol_disk_size;
    p_strtab = new SgAsmGenericSection(fhdr->get_file(), fhdr);
    p_strtab->set_offset(strtab_offset);
    p_strtab->set_size(sizeof(uint32_t));
    p_strtab->set_synthesized(true);
    p_strtab->set_name(new SgAsmBasicString("COFF Symbol Strtab"));
    p_strtab->set_purpose(SP_HEADER);
    p_strtab->parse();

    uint32_t word;
    p_strtab->read_content(0, &word, sizeof word);
    rose_addr_t strtab_size = ByteOrder::le_to_host(word);
    if (strtab_size < sizeof(uint32_t))
        throw FormatError("COFF symbol table string table size is less than four bytes");
    p_strtab->extend(strtab_size - sizeof(uint32_t));

    /* Parse symbols until we've parsed the required number or we run off the end of the section. */
    for (size_t i = 0; i < fhdr->get_e_coff_nsyms(); i++) {
        try {
            SgAsmCoffSymbol *symbol = new SgAsmCoffSymbol(fhdr, this, p_strtab, i);
            i += symbol->get_st_num_aux_entries();
            p_symbols->get_symbols().push_back(symbol);
        } catch (const ShortRead &e) {
            fprintf(stderr, "SgAsmCoffSymbolTable::parse: warning: read past end of section \"%s\" [%d]\n"
                    "    symbol #%zu at file offset 0x%08"PRIx64"\n"
                    "    skipping %zu symbols (including this one)\n",
                    get_name()->get_string(true).c_str(), get_id(),
                    i, e.offset,
                    fhdr->get_e_coff_nsyms()-i);
            break;
        }
    }

    return this;
}
void
Visitor::visit(SgNode* n)
   {
     SgAsmGenericSymbol *symbol = isSgAsmGenericSymbol(n);
     if (symbol != NULL)
        {
          printf("Found a SgAsmGenericSymbol, Here: offset = %zu, %p = %s = %s \n",
                 (size_t)0, symbol, escapeString(symbol->class_name()).c_str(),
                 symbol->get_name()->get_string(true).c_str());
          printf ("symbol->get_name()      = %s \n",symbol->get_name()->get_string(true).c_str());
          printf ("symbol->get_bound()     = %p \n",symbol->get_bound());
          printf ("symbol->get_size()      = %" PRIu64 " \n",symbol->get_size());
          printf ("symbol->get_value()     = %" PRIu64 " \n",symbol->get_value());

          printf ("symbol->get_type()      = %u = %s \n",symbol->get_type(),symbol->stringifyType().c_str());
          printf ("symbol->get_binding()   = %u = %s \n",symbol->get_binding(),symbol->stringifyBinding().c_str());
          printf ("symbol->get_def_state() = %u = %s \n",symbol->get_def_state(),symbol->stringifyDefState().c_str());

          /* All the ELF-specific stuff and most of the COFF-specific stuff is also represented in the base class, displayed
           * above.  The general rule is that notions that are present in at least two file formats are represented in a
           * common base class and there's no need to access the copies that might be stored in the derived classes. However,
           * they are duplicated in the derived classes because those classes tend to represent data structures described
           * directly in the format specifications. The only reason they're publicly visible in the derived classes is because
           * ROSETTA doesn't support marking certain things as being for internal use only. I'm working on documenting these
           * things better.
           * 
           * For instance, the p_st_name member of an SgAsmElfSymbol is a byte offset into an ELF String Table. The actual
           * string is stored in the p_name member of SgAsmGenericSymbol. Modifying the string will cause all the correct
           * memory management actions to occur (ultimately adjusting p_st_name), while modifying p_st_name bypasses string
           * table management (and your new value would be overwritten if/when memory management does occur).
           * 
           * [RPM 2008-12-15] */

          /* The Coff-specific stuff may eventually disappear as the base class evolves to handle more of this. In fact, some
           * of these are already duplicates of the same info above. */
          SgAsmCoffSymbol* coffSymbol = isSgAsmCoffSymbol(symbol);
          if (coffSymbol != NULL)
             {
               printf ("   coffSymbol->get_st_name()            = %s \n",coffSymbol->get_st_name().c_str());
               printf ("   coffSymbol->get_st_name_offset()     = %" PRIu64 " \n",coffSymbol->get_st_name_offset());
               printf ("   coffSymbol->get_st_section_num()     = %d  \n",coffSymbol->get_st_section_num());
               printf ("   coffSymbol->get_st_type()            = %u  \n",coffSymbol->get_st_type());
               printf ("   coffSymbol->get_st_storage_class()   = %u  \n",coffSymbol->get_st_storage_class());
               printf ("   coffSymbol->get_st_num_aux_entries() = %u \n",coffSymbol->get_st_num_aux_entries());
               printf ("   coffSymbol->get_aux_data():  size    = %zu \n",coffSymbol->get_aux_data().size());
               for (SgUnsignedCharList::iterator i = coffSymbol->get_aux_data().begin(); i != coffSymbol->get_aux_data().end(); i++)
                  {
                    printf ("      coffSymbol->get_aux_data() = %u \n",*i);
                  }
             }
        }
   }