예제 #1
0
void PDBFileReader::ProcessSymbol(IDiaSymbol *symbol,DebugInfo &to)
{
    DWORD section,offset,rva;
    enum SymTagEnum tag;
    ULONGLONG length = 0;
    sU32 compilandId;
    IDiaSymbol *compiland = 0;
    BSTR name = 0, sourceName = 0;
    sBool codeFlag;

    symbol->get_symTag((DWORD *) &tag);
    symbol->get_relativeVirtualAddress(&rva);
    symbol->get_length(&length);
    symbol->get_addressSection(&section);
    symbol->get_addressOffset(&offset);

    // is the previous symbol desperately looking for a length? we can help!
    if(DanglingLengthStart)
    {
        to.Symbols[to.Symbols.Count - 1].Size = rva - DanglingLengthStart;
        DanglingLengthStart = 0;
    }

    // get length from type for data
    if(tag == SymTagData)
    {
        IDiaSymbol *type;
        if(symbol->get_type(&type) == S_OK)
        {
            type->get_length(&length);
            type->Release();
        }

        // if length still zero, just guess and take number of bytes between
        // this symbol and the next one.
        if(!length)
            DanglingLengthStart = rva;
    }

    compilandId = CompilandFromSectionOffset(section,offset,codeFlag);
    Session->symbolById(compilandId,&compiland);

    if(compiland)
        compiland->get_name(&sourceName);

    symbol->get_name(&name);

    // fill out structure
    sChar *nameStr = BStrToString(name,"<no name>");
    sChar *sourceStr = BStrToString(sourceName,"<no source>");

    if(tag == SymTagPublicSymbol)
    {
        length = 0;
        DanglingLengthStart = rva;
    }

    DISymbol *outSym = to.Symbols.Add();
    outSym->Name.Index = outSym->MangledName.Index = to.MakeString(nameStr);
    outSym->FileNum = to.GetFileByName(sourceStr);
    outSym->VA = rva;
    outSym->Size = (sU32) length;
    outSym->Class = codeFlag ? DIC_CODE : DIC_DATA;
    outSym->NameSpNum = to.GetNameSpaceByName(nameStr);

    // clean up
    delete[] nameStr;
    delete[] sourceStr;

    if(compiland)   compiland->Release();
    if(sourceName)  SysFreeString(sourceName);
    if(name)        SysFreeString(name);
}
예제 #2
0
void PDBFileReader::ReadEverything(DebugInfo &to)
{
  ULONG celt;
  
  Contribs = 0;
  nContribs = 0;
  
  // read section table
  IDiaEnumTables *enumTables;
  if(Session->getEnumTables(&enumTables) == S_OK)
  {
    VARIANT vIndex;
    vIndex.vt = VT_BSTR;
    vIndex.bstrVal = SysAllocString(L"Sections");

    IDiaTable *secTable;
    if(enumTables->Item(vIndex,&secTable) == S_OK)
    {
      LONG count;

      secTable->get_Count(&count);
      Contribs = new SectionContrib[count];
      nContribs = 0;

      IDiaSectionContrib *item;
      while(SUCCEEDED(secTable->Next(1,(IUnknown **)&item,&celt)) && celt == 1)
      {
        SectionContrib &contrib = Contribs[nContribs++];

        item->get_addressOffset(&contrib.Offset);
        item->get_addressSection(&contrib.Section);
        item->get_length(&contrib.Length);
        item->get_compilandId(&contrib.Compiland);

				BOOL code=FALSE,initData=FALSE,uninitData=FALSE;
				item->get_code(&code);
				item->get_initializedData(&initData);
				item->get_uninitializedData(&uninitData);

				if(code && !initData && !uninitData)
					contrib.Type = DIC_CODE;
				else if(!code && initData && !uninitData)
					contrib.Type = DIC_DATA;
				else if(!code && !initData && uninitData)
					contrib.Type = DIC_BSS;
				else
					contrib.Type = DIC_UNKNOWN;

				BSTR objFileName = 0;
				
				IDiaSymbol *compiland = 0;
				item->get_compiland(&compiland);
				if(compiland)
				{
					compiland->get_name(&objFileName);
					compiland->Release();
				}

				sChar *objFileStr = BStrToString(objFileName,"<noobjfile>");
				contrib.ObjFile = to.GetFileByName(objFileStr);

				delete[] objFileStr;
				if(objFileName)
					SysFreeString(objFileName);

        item->Release();
      }

      secTable->Release();
    }

    SysFreeString(vIndex.bstrVal);
    enumTables->Release();
  }

  // enumerate symbols by (virtual) address
  IDiaEnumSymbolsByAddr *enumByAddr;
  if(SUCCEEDED(Session->getSymbolsByAddr(&enumByAddr)))
  {
    IDiaSymbol *symbol;
    // get first symbol to get first RVA (argh)
    if(SUCCEEDED(enumByAddr->symbolByAddr(1,0,&symbol)))
    {
      DWORD rva;
      if(symbol->get_relativeVirtualAddress(&rva) == S_OK)
      {
        symbol->Release();

        // now, enumerate by rva.
        if(SUCCEEDED(enumByAddr->symbolByRVA(rva,&symbol)))
        {
          do
          {
            ProcessSymbol(symbol,to);
            symbol->Release();

            if(FAILED(enumByAddr->Next(1,&symbol,&celt)))
              break;
          }
          while(celt == 1);
        }
      }
      else
        symbol->Release();
    }

    enumByAddr->Release();
  }

  // clean up
  delete[] Contribs;
}