示例#1
0
// the result doesn't have to be free()d but is only valid until the next call to this function
static const char *GetObjFileName(IDiaSectionContrib *item)
{
    static str::Str<char> strTmp;
    BSTR            name = 0;

    IDiaSymbol *    compiland = 0;
    item->get_compiland(&compiland);
    if (compiland) {
        compiland->get_name(&name);
        compiland->Release();
    }
    BStrToString(strTmp, name, "<noobjfile>");
    SysFreeStringSafe(name);
    return strTmp.Get();
}
示例#2
0
AddrInfo GetAddr(wstring req)
{
  uint32_t module;
  uint64_t addr;
  int charsRead = swscanf_s(req.c_str(), L"%d %llu", &module, &addr);

  AddrInfo ret;
  ZeroMemory(&ret, sizeof(ret));

  if(module > 0 && module < modules.size())
  {
    SymTagEnum tag = SymTagFunction;
    IDiaSymbol *pFunc = NULL;
    HRESULT hr = modules[module].pSession->findSymbolByVA(addr, tag, &pFunc);

    if(hr != S_OK)
    {
      if(pFunc)
        pFunc->Release();

      // try again looking for public symbols
      tag = SymTagPublicSymbol;
      hr = modules[module].pSession->findSymbolByVA(addr, tag, &pFunc);

      if(hr != S_OK)
      {
        if(pFunc)
          pFunc->Release();
        return ret;
      }
    }

    DWORD opts = 0;
    opts |= UNDNAME_NO_LEADING_UNDERSCORES;
    opts |= UNDNAME_NO_MS_KEYWORDS;
    opts |= UNDNAME_NO_FUNCTION_RETURNS;
    opts |= UNDNAME_NO_ALLOCATION_MODEL;
    opts |= UNDNAME_NO_ALLOCATION_LANGUAGE;
    opts |= UNDNAME_NO_THISTYPE;
    opts |= UNDNAME_NO_ACCESS_SPECIFIERS;
    opts |= UNDNAME_NO_THROW_SIGNATURES;
    opts |= UNDNAME_NO_MEMBER_TYPE;
    opts |= UNDNAME_NO_RETURN_UDT_MODEL;
    opts |= UNDNAME_32_BIT_DECODE;
    opts |= UNDNAME_NO_LEADING_UNDERSCORES;

    // first try undecorated name
    BSTR file;
    hr = pFunc->get_undecoratedNameEx(opts, &file);

    // if not, just try name
    if(hr != S_OK)
    {
      hr = pFunc->get_name(&file);

      if(hr != S_OK)
      {
        pFunc->Release();
        SysFreeString(file);
        return ret;
      }

      wcsncpy_s(ret.funcName, file, 126);
    }
    else
    {
      wcsncpy_s(ret.funcName, file, 126);

      wchar_t *voidparam = wcsstr(ret.funcName, L"(void)");

      // remove stupid (void) for empty parameters
      if(voidparam != NULL)
      {
        *(voidparam + 1) = L')';
        *(voidparam + 2) = 0;
      }
    }

    pFunc->Release();
    pFunc = NULL;

    SysFreeString(file);

    // find the line numbers touched by this address.
    IDiaEnumLineNumbers *lines = NULL;
    hr = modules[module].pSession->findLinesByVA(addr, DWORD(4), &lines);
    if(FAILED(hr))
    {
      if(lines)
        lines->Release();
      return ret;
    }

    IDiaLineNumber *line = NULL;
    ULONG count = 0;

    // just take the first one
    if(SUCCEEDED(lines->Next(1, &line, &count)) && count == 1)
    {
      IDiaSourceFile *dia_source = NULL;
      hr = line->get_sourceFile(&dia_source);
      if(FAILED(hr))
      {
        line->Release();
        lines->Release();
        if(dia_source)
          dia_source->Release();
        return ret;
      }

      hr = dia_source->get_fileName(&file);
      if(FAILED(hr))
      {
        line->Release();
        lines->Release();
        dia_source->Release();
        return ret;
      }

      wcsncpy_s(ret.fileName, file, 126);

      SysFreeString(file);

      dia_source->Release();
      dia_source = NULL;

      DWORD line_num = 0;
      hr = line->get_lineNumber(&line_num);
      if(FAILED(hr))
      {
        line->Release();
        lines->Release();
        return ret;
      }

      ret.lineNum = line_num;

      line->Release();
    }

    lines->Release();
  }

  return ret;
}
示例#3
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);
}
示例#4
0
//-----------------------------------------------------------------------------
// Name: ParseModules
// Object: parse all compilands
// Parameters :
//     in  : 
//     out : 
//     return : TRUE on success
//-----------------------------------------------------------------------------
BOOL CDebugInfos::ParseModules()
{
    HRESULT hr;
    IDiaEnumSymbols* pEnumSymbols;
    IDiaEnumSymbols* pEnumChildren;
    IDiaSymbol* pCompiland;
    IDiaSymbol* pSymbol;
    ULONG celt = 0;
    CModuleInfos* pModuleInfo;
    BSTR Name;

    // Retrieve the compilands first
    if(FAILED(this->pDiaGlobalSymbol->findChildren(SymTagCompiland, NULL, nsNone, &pEnumSymbols)))
        return FALSE;

    // for each compiland
    while(pEnumSymbols->Next(1, &pCompiland, &celt) == S_OK && celt == 1) 
    {
        // Retrieve the name of the module
        Name=NULL;
        pCompiland->get_name(&Name);

#if (REMOVE_LINKER_COMPILAND==1)
        // avoid to display "* Linker *" infos
        if (Name)
        {
            if (wcsicmp(Name,LINKER_COMPILAND_NAME)==0)
            {
                SysFreeString(Name);
                pCompiland->Release();
                continue;
            }
        }
#endif

        // create module info
        pModuleInfo=new CModuleInfos();
        // add it to modules list
        this->pLinkListModules->AddItem(pModuleInfo);
        // assume module name is set
        if (Name)
        {
#if (defined(UNICODE)||defined(_UNICODE))
            pModuleInfo->Name=_tcsdup(Name);
#else
            CAnsiUnicodeConvert::UnicodeToAnsi(Name,&pModuleInfo->Name);
#endif
            SysFreeString(Name);
        }
        else
            pModuleInfo->Name=_tcsdup(_T(""));

        // Find all the symbols defined in this compiland and get their info
        if(SUCCEEDED(pCompiland->findChildren(SymTagNull, NULL, nsNone, &pEnumChildren)))
        {
            ULONG celt_ = 0;
            while (pEnumChildren->Next(1, &pSymbol, &celt_) == S_OK && celt_ == 1) 
            {
                hr=pModuleInfo->Parse(pSymbol);
                if (FAILED(hr))
                    this->ReportError(_T("Error parsing module information"),hr);
                pSymbol->Release();
            }
            pEnumChildren->Release();
        }
        pCompiland->Release();
    }
    pEnumSymbols->Release();
    return TRUE;
}
示例#5
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;
}
示例#6
0
bool LoadDIASymbols(const wxString &strPDBFile, 
					wxInt32 modulenum,
					std::list<CFunctionDescription> & llFuncs,
					stdext::hash_map<BasedAddress,int> & addressmap
					)
{
	// Create DIA80 Data Source Object
	IDiaDataSource *pDataSource;
	HRESULT hr = NoRegCoCreate( L"msdia80.dll", _uuidof( DiaSource ), _uuidof( IDiaDataSource ), (void **) &(pDataSource));
	if(!SUCCEEDED(hr)) 
	{
		return false;
	}
	/*
	HMODULE mod=LoadLibrary(L"msdia80.dll");
	if(!mod)
	{
		return false;
	}

	TYPEOF_DllGetClassObject *pGetClassObject=(TYPEOF_DllGetClassObject *)GetProcAddress(mod,"DllGetClassObject");
	if(!pGetClassObject)
	{
		FreeLibrary(mod);
		return false;
	}

	IClassFactory *pcf;
	HRESULT hr=(*pGetClassObject)(CLSID_DiaSource,IID_IClassFactory,(void **)&pcf);
	if(!SUCCEEDED(hr))
	{
		FreeLibrary(mod);
		return false;
	}

	IDiaDataSource *pDataSource;
	hr=pcf->CreateInstance(NULL,_uuidof(IDiaDataSource),(void **)&pDataSource);
	if(!SUCCEEDED(hr))
	{
		pcf->Release();
		FreeLibrary(mod);
		return false;
	}
	pcf->Release();
*/
		
	// Load the executable's debug symbols
	hr=pDataSource->loadDataFromPdb(strPDBFile);
	if(!SUCCEEDED(hr))
	{
		pDataSource->Release();
		return false;	
	}
	
	// Open a symbol session
	IDiaSession *pDIASession;
	hr=pDataSource->openSession(&pDIASession);
	if(!SUCCEEDED(hr)) 
	{
		pDataSource->Release();
		return false;
	}

	// Set the UNBASED address on the session, for resolving BasedAddress addrs
	hr=pDIASession->put_loadAddress(0);
	if(!SUCCEEDED(hr)) 
	{
		pDIASession->Release();
		pDataSource->Release();
		return false;
	}

	// Get addresses for this module
	std::list<BasedAddress> addresses;
	for(stdext::hash_map<BasedAddress,int>::iterator iter=addressmap.begin();iter!=addressmap.end();iter++)
	{
		if(iter->first.nModule==modulenum)
		{
			addresses.push_back(iter->first);
		}
	}
	stdext::hash_map<DWORD,wxInt32> functions;

	int curidx=(int)llFuncs.size();

	for(std::list<BasedAddress>::iterator itera=addresses.begin();itera!=addresses.end();itera++)
	{
		// Get the symbol for this thing
		IDiaSymbol* pFunc;
		if(FAILED(pDIASession->findSymbolByVA(itera->nAddr, SymTagFunction, &pFunc)) || pFunc==NULL)
		{
			continue;
		}

		// Get the unique symbol index id
		DWORD indexId;
		if(FAILED(pFunc->get_symIndexId(&indexId)))
		{
			pFunc->Release();
			continue;
		}

		// See if we have this function already
		stdext::hash_map<DWORD,int>::iterator iterf=functions.find(indexId);
		if(iterf!=functions.end())
		{
			addressmap[*itera]=iterf->second;
		}
		else
		{
			CFunctionDescription func;
	
			//////
			ULONGLONG addr;
			if(FAILED(pFunc->get_virtualAddress(&addr)))
			{
				pFunc->Release();
				continue;
			}

			//////
			ULONGLONG length;
			if(FAILED(pFunc->get_length(&length)))
			{
				pFunc->Release();
				continue;
			}

			/////////
			BSTR pName;
			if(FAILED(pFunc->get_name(&pName)))
			{
				pFunc->Release();
				continue;
			}
			func.strMangledName=(const LPWSTR)pName;
			LocalFree(pName);
				
			char mangled[512];
			WideCharToMultiByte(CP_UTF8,0,func.strMangledName,-1,mangled,512,NULL,NULL);
			
			/////////
			char outbase[512];
			__unDName(outbase,mangled,512,&malloc,&free,0x1000);
			wchar_t outbasew[512];
			MultiByteToWideChar(CP_UTF8,0,outbase,-1,outbasew,512);
			
			func.strBaseName=(const wchar_t *)(outbasew);

			/////////
			char outfull[512];
			__unDName(outfull,mangled,512,&malloc,&free,0);
			wchar_t outfullw[512];
			MultiByteToWideChar(CP_UTF8,0,outfull,-1,outfullw,512);
			
			func.strFullName=(const wchar_t *)(outfullw);


			//////////
			func.nAddress=BasedAddress(addr,modulenum);
			func.nByteLength=length;
			
			/////////

			IDiaEnumLineNumbers *pdeln;
			func.strSourceFile=wxT("<unknown>");
			func.nFirstSourceLine=0;
			func.nLastSourceLine=0;
			bool bGotFile=false;
			if(SUCCEEDED(pDIASession->findLinesByVA(addr,length,&pdeln)))
			{
				IDiaLineNumber *pdln;
				int nLineItem=0;
				while(SUCCEEDED(pdeln->Item(nLineItem,&pdln)))
				{
					DWORD dwLineNumber;
					IDiaSourceFile *pdsf;
					if(SUCCEEDED(pdln->get_lineNumber(&dwLineNumber)) &&
						SUCCEEDED(pdln->get_sourceFile(&pdsf)))
					{
						BSTR filename;
						if(SUCCEEDED(pdsf->get_fileName(&filename)))
						{
							if(bGotFile)
							{
								if(filename==func.strSourceFile)
								{
									if(dwLineNumber<func.nFirstSourceLine)
									{
										func.nFirstSourceLine=dwLineNumber;
									}
									if(dwLineNumber>func.nLastSourceLine)
									{
										func.nLastSourceLine=dwLineNumber;
									}
								}
							}
							else
							{
								bGotFile=true;
								func.strSourceFile=filename;
								func.nFirstSourceLine=dwLineNumber;
								func.nLastSourceLine=dwLineNumber;
							}
							LocalFree(filename);
						}
						pdsf->Release();
					}
					pdln->Release();
					nLineItem++;
				}
				pdeln->Release();
			}
           
			llFuncs.push_back(func);

			functions[indexId]=curidx;

			addressmap[*itera]=curidx;

			curidx++;
		}
	}
	
	pDIASession->Release();
	pDataSource->Release();
		
//	FreeLibrary(mod);

	return true;
}