/*++ Copyright (c) 1998-2001 Klaus P. Gerlicher Module ModuleName: symbols.c Abstract: Environment: Kernel mode only Author: Klaus P. Gerlicher Reactos Port by Eugene Ingerman Revision History: 19-Aug-1998: created 15-Nov-2000: general cleanup of source files Copyright notice: This file may be distributed under the terms of the GNU Public License. --*/ //////////////////////////////////////////////////// // INCLUDES //// #include "remods.h" #include "precomp.h" #include "stab_gnu.h" #include #include #include #include #include #define NDEBUG #include PVOID pExports=0; ULONG ulExportLen=0; LOCAL_VARIABLE local_vars[512]; PICE_SYMBOLFILE_HEADER* apSymbols[32]={NULL,}; ULONG ulNumSymbolsLoaded=0; ULONG kernel_end=0; char tempSym[1024]; // temp buffer for output PULONG LocalRegs[]= { &CurrentEAX, &CurrentECX, &CurrentEDX, &CurrentEBX, &CurrentESP, &CurrentEBP, &CurrentESI, &CurrentEDI, &CurrentEIP, &CurrentEFL }; typedef struct _VRET { ULONG value; ULONG type; ULONG father_type; ULONG error; ULONG file; ULONG size; ULONG address; char name[256]; char type_name[256]; BOOLEAN bPtrType; BOOLEAN bStructType; BOOLEAN bArrayType; PICE_SYMBOLFILE_HEADER* pSymbols; }VRET,*PVRET; ULONG ulIndex; LPSTR pExpression; VRET vr; VRET vrStructMembers[1024]; ULONG ulNumStructMembers; BOOLEAN Expression(PVRET pvr); LIST_ENTRY *pModuleListHead = NULL; extern PDIRECTORY_OBJECT *pNameSpaceRoot; extern PDEBUG_MODULE pdebug_module_tail; extern PDEBUG_MODULE pdebug_module_head; PVOID HEADER_TO_BODY(POBJECT_HEADER obj) { return(((void *)obj)+sizeof(OBJECT_HEADER)-sizeof(COMMON_BODY_HEADER)); } POBJECT_HEADER BODY_TO_HEADER(PVOID body) { PCOMMON_BODY_HEADER chdr = (PCOMMON_BODY_HEADER)body; return(CONTAINING_RECORD((&(chdr->Type)),OBJECT_HEADER,Type)); } /*-----------------12/26/2001 7:59PM---------------- * FreeModuleList - free list allocated with InitModuleList. Must * be called at passive irql. * --------------------------------------------------*/ VOID FreeModuleList( PDEBUG_MODULE pm ) { PDEBUG_MODULE pNext = pm; ENTER_FUNC(); while( pNext ){ pNext = pm->next; ExFreePool( pm ); } LEAVE_FUNC(); } /*-----------------12/26/2001 7:58PM---------------- * InitModuleList - creates linked list of length len for debugger. Can't be * called at elevated IRQL * --------------------------------------------------*/ BOOLEAN InitModuleList( PDEBUG_MODULE *ppmodule, ULONG len ) { ULONG i; PDEBUG_MODULE pNext = NULL, pm = *ppmodule; ENTER_FUNC(); ASSERT(pm==NULL); for(i=1;i<=len;i++){ pm = (PDEBUG_MODULE)ExAllocatePool( NonPagedPool, sizeof( DEBUG_MODULE ) ); if( !pm ){ FreeModuleList(pNext); return FALSE; } pm->next = pNext; pm->size = 0; pm->BaseAddress = NULL; //DbgPrint("len1: %d\n", pm->name.Length); pNext = pm; } *ppmodule = pm; LEAVE_FUNC(); return TRUE; } BOOLEAN ListUserModules( PPEB peb ) { PLIST_ENTRY UserModuleListHead; PLIST_ENTRY Entry; PLDR_DATA_TABLE_ENTRY Module; PPEB_LDR_DATA Ldr; ENTER_FUNC(); Ldr = peb->Ldr; if( Ldr && IsAddressValid((ULONG)Ldr)){ UserModuleListHead = &Ldr->InLoadOrderModuleList; ASSERT(IsAddressValid((ULONG)UserModuleListHead)); Entry = UserModuleListHead->Flink; while (Entry != UserModuleListHead) { Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList); //DbgPrint("Module: %x, BaseAddress: %x\n", Module, Module->BaseAddress); DPRINT((0,"FullName: %S, BaseName: %S, Length: %ld, EntryPoint: %x, BaseAddress: %x\n", Module->FullDllName.Buffer, Module->BaseDllName.Buffer, Module->SizeOfImage, Module->EntryPoint, Module->BaseAddress )); pdebug_module_tail->size = Module->SizeOfImage; pdebug_module_tail->BaseAddress = Module->BaseAddress; pdebug_module_tail->EntryPoint = (PVOID)(Module->EntryPoint); ASSERT(Module->BaseDllName.Lengthname, Module->BaseDllName.Buffer ); pdebug_module_tail = pdebug_module_tail->next; Entry = Entry->Flink; } } LEAVE_FUNC(); return TRUE; } POBJECT FindDriverObjectDirectory( void ) { PLIST_ENTRY current; POBJECT_HEADER current_obj; PDIRECTORY_OBJECT pd; ENTER_FUNC(); if( pNameSpaceRoot && *pNameSpaceRoot ){ current = (*pNameSpaceRoot)->head.Flink; while (current!=(&((*pNameSpaceRoot)->head))) { current_obj = CONTAINING_RECORD(current,OBJECT_HEADER,Entry); DPRINT((0,"Scanning %S\n",current_obj->Name.Buffer)); if (_wcsicmp(current_obj->Name.Buffer, L"Modules")==0) { pd=HEADER_TO_BODY(current_obj); DPRINT((0,"Found it %x\n",pd)); return pd; } current = current->Flink; } } LEAVE_FUNC(); return NULL; } BOOLEAN ListDriverModules( void ) { PLIST_ENTRY current_entry; PMODULE_OBJECT current; POBJECT_HEADER current_obj; ENTER_FUNC(); ASSERT( pModuleListHead ); current_entry = pModuleListHead->Flink; while (current_entry != (pModuleListHead)){ current = CONTAINING_RECORD(current_entry,MODULE_OBJECT,ListEntry); DPRINT((0,"FullName: %S, BaseName: %S, Length: %ld, EntryPoint: %x\n", current->FullName.Buffer, current->BaseName.Buffer, current->Length, current->EntryPoint )); pdebug_module_tail->BaseAddress = current->Base; pdebug_module_tail->size = current->Length; PICE_wcscpy( pdebug_module_tail->name, current->BaseName.Buffer); pdebug_module_tail->EntryPoint = current->EntryPoint; pdebug_module_tail = pdebug_module_tail->next; if (current && _wcsicmp(current->BaseName.Buffer, L"ntoskrnl")==0) { kernel_end = (ULONG)current->Base + current->Length; } current_entry = current_entry->Flink; } LEAVE_FUNC(); return TRUE; } BOOLEAN BuildModuleList( void ) { PPEB peb; PEPROCESS tsk; ENTER_FUNC(); pdebug_module_tail = pdebug_module_head; tsk = IoGetCurrentProcess(); ASSERT(IsAddressValid((ULONG)tsk)); if( tsk ){ peb = tsk->Peb; if( peb ){ if( !ListUserModules( peb ) ){ LEAVE_FUNC(); return FALSE; } } } if( !ListDriverModules() ){ LEAVE_FUNC(); return FALSE; } LEAVE_FUNC(); return TRUE; } //************************************************************************* // IsModuleLoaded() // //************************************************************************* PDEBUG_MODULE IsModuleLoaded(LPSTR p) { PDEBUG_MODULE pd; ENTER_FUNC(); DPRINT((0,"IsModuleLoaded(%s)\n",p)); if(BuildModuleList()) { pd = pdebug_module_head; do { char temp[DEBUG_MODULE_NAME_LEN]; DPRINT((0,"module (%x) %S\n",pd->size,pd->name)); CopyWideToAnsi(temp,pd->name); if(pd->size && PICE_strcmpi(p,temp) == 0) { DPRINT((0,"module %S is loaded!\n",pd->name)); LEAVE_FUNC(); return pd; } }while((pd = pd->next)!=pdebug_module_tail); } LEAVE_FUNC(); return NULL; } //************************************************************************* // ScanExports() // //************************************************************************* BOOLEAN ScanExports(const char *pFind,PULONG pValue) { char temp[256]; LPSTR pStr=NULL; LPSTR pExp = pExports; BOOLEAN bResult = FALSE; ENTER_FUNC(); DPRINT((0,"ScanExports pValue: %x\n", pValue)); nomatch: if(pExports) pStr = strstr(pExp,pFind); if(pStr) { LPSTR p; ULONG state; LPSTR pOldStr = pStr; for(;(*pStr!=0x0a && *pStr!=0x0d) && (ULONG)pStr>=(ULONG)pExports;pStr--); pStr++; p = temp; for(;(*pStr!=0x0a && *pStr!=0x0d);)*p++=*pStr++; *p=0; p = (LPSTR) PICE_strtok(temp," "); state=0; while(p) { switch(state) { case 0: ConvertTokenToHex(p,pValue); break; case 1: break; case 2: if(strcmp(p,pFind)!=0) { DPRINT((0,"Not: %s\n", p)); pExp = pOldStr+1; goto nomatch; } state = -1; bResult = TRUE; DPRINT((0,"%s @ %x\n",pFind,*pValue)); goto exit; break; } state++; p = (char*) PICE_strtok(NULL," "); } } exit: DPRINT((0,"%s %x @ %x\n",pFind,pValue,*pValue)); LEAVE_FUNC(); return bResult; } //************************************************************************* // ReadHex() // //************************************************************************* BOOLEAN ReadHex(LPSTR p,PULONG pValue) { ULONG result=0,i; for(i=0;i<8 && p[i]!=0 && p[i]!=' ';i++) { if(p[i]>='0' && p[i]<='9') { result<<=4; result|=(ULONG)(UCHAR)(p[i]-'0'); } else if(p[i]>='A' && p[i]<='F') { result<<=4; result|=(ULONG)(UCHAR)(p[i]-'A'+10); } else if(p[i]>='a' && p[i]<='f') { result<<=4; result|=(ULONG)(UCHAR)(p[i]-'a'+10); } else return FALSE; } *pValue = result; return TRUE; } //************************************************************************* // ScanExportLine() // //************************************************************************* BOOLEAN ScanExportLine(LPSTR p,PULONG ulValue,LPSTR* ppPtrToSymbol) { BOOLEAN bResult = FALSE; if(ReadHex(p,ulValue)) { p += 11; *ppPtrToSymbol += 11; bResult = TRUE; } return bResult; } //************************************************************************* // ValidityCheckSymbols() // //************************************************************************* BOOLEAN ValidityCheckSymbols(PICE_SYMBOLFILE_HEADER* pSymbols) { BOOLEAN bRet; DPRINT((0,"ValidityCheckSymbols()\n")); bRet = (IsRangeValid((ULONG)pSymbols + pSymbols->ulOffsetToHeaders,pSymbols->ulSizeOfHeader) && IsRangeValid((ULONG)pSymbols + pSymbols->ulOffsetToGlobals,pSymbols->ulSizeOfGlobals) && IsRangeValid((ULONG)pSymbols + pSymbols->ulOffsetToGlobalsStrings,pSymbols->ulSizeOfGlobalsStrings) && IsRangeValid((ULONG)pSymbols + pSymbols->ulOffsetToStabs,pSymbols->ulSizeOfStabs) && IsRangeValid((ULONG)pSymbols + pSymbols->ulOffsetToStabsStrings,pSymbols->ulSizeOfStabsStrings)); DPRINT((0,"ValidityCheckSymbols(): symbols are %s\n",bRet?"VALID":"NOT VALID")); return bRet; } //************************************************************************* // FindModuleSymbols() // //************************************************************************* PICE_SYMBOLFILE_HEADER* FindModuleSymbols(ULONG addr) { ULONG start,end,i; PDEBUG_MODULE pd = pdebug_module_head; DPRINT((0,"FindModuleSymbols(%x)\n",addr)); if(BuildModuleList()) { i=0; pd = pdebug_module_head; do { DPRINT((0,"pd: %x\n", pd)); if(pd->size) { start = (ULONG)pd->BaseAddress; end = start + pd->size; DPRINT((0,"FindModuleSymbols(): %S %x-%x\n",pd->name,start,end)); if(addr>=start && addrname,start,end)); for(i=0;iname )); if(PICE_wcsicmp(pd->name,apSymbols[i]->name) == 0) { if(ValidityCheckSymbols(apSymbols[i])) return apSymbols[i]; else return NULL; } } } } }while((pd = pd->next) != pdebug_module_tail); } return NULL; } //************************************************************************* // FindModuleFromAddress() // //************************************************************************* PDEBUG_MODULE FindModuleFromAddress(ULONG addr) { PDEBUG_MODULE pd; ULONG start,end; DPRINT((0,"FindModuleFromAddress()\n")); if(BuildModuleList()) { pd = pdebug_module_head; do { if(pd->size) { start = (ULONG)pd->BaseAddress; end = start + pd->size; DPRINT((0,"FindModuleFromAddress(): %S %x-%x\n",pd->name,start,end)); if(addr>=start && addrname)); return pd; } } }while((pd = pd->next)!=pdebug_module_tail); } return NULL; } //************************************************************************* // FindModuleByName() // //************************************************************************* PDEBUG_MODULE FindModuleByName(LPSTR modname) { PDEBUG_MODULE pd; WCHAR tempstr[DEBUG_MODULE_NAME_LEN]; DPRINT((0,"FindModuleFromAddress()\n")); if( !PICE_MultiByteToWideChar(CP_ACP, NULL, modname, -1, tempstr, DEBUG_MODULE_NAME_LEN ) ) { DPRINT((0,"Can't convert module name.\n")); return NULL; } if(BuildModuleList()) { pd = pdebug_module_head; do { if(pd->size) { if(PICE_wcsicmp(tempstr,pd->name) == 0) { DPRINT((0,"FindModuleByName(): found %S\n",pd->name)); return pd; } } }while((pd = pd->next) != pdebug_module_tail); } return NULL; } //************************************************************************* // FindModuleSymbolsByModuleName() // //************************************************************************* PICE_SYMBOLFILE_HEADER* FindModuleSymbolsByModuleName(LPSTR modname) { ULONG i; WCHAR tempstr[DEBUG_MODULE_NAME_LEN]; DPRINT((0,"FindModuleSymbols()\n")); if( !PICE_MultiByteToWideChar(CP_ACP, NULL, modname, -1, tempstr, DEBUG_MODULE_NAME_LEN ) ) { DPRINT((0,"Can't convert module name in FindModuleSymbols.\n")); return NULL; } for(i=0;iname) == 0) return apSymbols[i]; } return NULL; } //************************************************************************* // ScanExportsByAddress() // //************************************************************************* BOOLEAN ScanExportsByAddress(LPSTR *pFind,ULONG ulValue) { char temp[256]; static char temp3[256]; LPSTR p,pStartOfLine,pSymbolName=NULL; ULONG ulCurrentValue=0; BOOLEAN bResult = FALSE; PDEBUG_MODULE pd; ULONG ulMinValue = -1; PIMAGE_SYMBOL pSym,pSymEnd; //running pointer to symbols and end of sym talbe PIMAGE_SYMBOL pFoundSym = NULL; //current best symbol match ULONG ulAddr = 0x0; //address of the best match LPSTR pStr; PIMAGE_SECTION_HEADER pShdr; PICE_SYMBOLFILE_HEADER* pSymbols; ULONG ulSectionSize; LPSTR pName; ENTER_FUNC(); DPRINT((0,"In ScanExportsByAddress:\n")); pSymbols = FindModuleSymbols(ulValue); DPRINT((0,"pSymbols: %x\n", pSymbols)); if(BuildModuleList()){ if(pSymbols && pdebug_module_head) { PDEBUG_MODULE pdTemp; DPRINT((0,"looking up symbols\n")); pd = pdebug_module_head; do { if(pd->size){ pdTemp = pd; if(ulValue>=((ULONG)pdTemp->BaseAddress) && ulValue<((ULONG)pdTemp+pdTemp->size)) { if(PICE_wcsicmp(pdTemp->name,pSymbols->name) == 0) { DPRINT((0,"ScanExportsByAddress(): found symbols for module %S @ %x \n",pdTemp->name,(ULONG)pSymbols)); pSym = (PIMAGE_SYMBOL)((ULONG)pSymbols+pSymbols->ulOffsetToGlobals); pSymEnd = (PIMAGE_SYMBOL)((ULONG)pSym+pSymbols->ulSizeOfGlobals); pStr = (LPSTR)((ULONG)pSymbols+pSymbols->ulOffsetToGlobalsStrings); pShdr = (PIMAGE_SECTION_HEADER)((ULONG)pSymbols+pSymbols->ulOffsetToHeaders); if(!IsRangeValid((ULONG)pSym,sizeof(IMAGE_SYMBOL) ) ) //should we actually check all the symbols here? { DPRINT((0,"ScanExportsByAddress(): pSym = %x is not a valid pointer\n",(ULONG)pSym)); return FALSE; } DPRINT((0,"ScanExportsByAddress(): pSym = %x\n",pSym)); DPRINT((0,"ScanExportsByAddress(): pStr = %x\n",pStr)); DPRINT((0,"ScanExportsByAddress(): pShdr = %x\n",pShdr)); DPRINT((0,"ScanExportsByAddress(): %S has %u symbols\n",pSymbols->name,pSymbols->ulSizeOfGlobals/sizeof(IMAGE_SYMBOL))); /* go through all the global symbols and find the one with the largest address which is less than ulValue */ while(pSym < pSymEnd) { //it seems only 0x0 and 0x20 are used for type and External or Static storage classes if(((pSym->Type == 0x0) || (pSym->Type == 0x20) ) && ((pSym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) || (pSym->StorageClass==IMAGE_SYM_CLASS_STATIC)) && (pSym->SectionNumber > 0 )) { ULONG ulCurrAddr; PIMAGE_SECTION_HEADER pShdrThis = (PIMAGE_SECTION_HEADER)pShdr + (pSym->SectionNumber-1); DPRINT((0,"ScanExportsByAddress(): pShdr[%x] = %x\n",pSym->SectionNumber,(ULONG)pShdrThis)); if(!IsRangeValid((ULONG)pShdrThis,sizeof(IMAGE_SECTION_HEADER)) ) { DPRINT((0,"ScanExportsByAddress(): pElfShdr[%x] = %x is not a valid pointer\n",pSym->SectionNumber,(ULONG)pShdrThis)); return FALSE; } //to get address in the memory we base address of the module and //add offset of the section and then add offset of the symbol from //the begining of the section ulCurrAddr = ((ULONG)pdTemp->BaseAddress+pShdrThis->VirtualAddress+pSym->Value); DPRINT((0,"ScanExportsByAddress(): CurrAddr [1] = %x\n",ulCurrAddr)); if(ulCurrAddr<=ulValue && ulCurrAddr>ulAddr) { ulAddr = ulCurrAddr; pFoundSym = pSym; } } //skip the auxiliary symbols and get the next symbol pSym += pSym->NumberOfAuxSymbols + 1; } *pFind = temp3; if( pFoundSym->N.Name.Short ){ pName = pFoundSym->N.ShortName; //name is in the header PICE_sprintf(temp3,"%S!%.8s",pdTemp->name,pName); //if name is in the header it may be nonzero terminated } else{ ASSERT(pFoundSym->N.Name.Long<=pSymbols->ulSizeOfGlobalsStrings); //sanity check pName = pStr+pFoundSym->N.Name.Long; if(!IsAddressValid((ULONG)pName)) { DPRINT((0,"ScanExportsByAddress(): pName = %x is not a valid pointer\n",pName)); return FALSE; } PICE_sprintf(temp3,"%S!%s",pdTemp->name,pName); } DPRINT((0,"ScanExportsByAddress(): pName = %x\n",(ULONG)pName)); return TRUE; } } } }while((pd = pd->next)); } } // if haven't found in the symbols try ntoskrnl exports. (note: check that this is needed since we // already checked ntoskrnl coff symbol table) if(pExports && ulValue >= KERNEL_START && ulValue < kernel_end) { p = pExports; // while we bound in System.map while(p<((LPSTR)pExports+ulExportLen)) { // make a temp ptr to the line we can change pStartOfLine = p; // will read the hex value and return a pointer to the symbol name if(ScanExportLine(p,&ulCurrentValue,&pStartOfLine)) { if(ulValue>=ulCurrentValue && (ulValue-ulCurrentValue)name,(ULONG)pSymbols)); if(pSymbols && pdebug_module_head) { DPRINT((0,"looking up symbol\n")); pd = pdebug_module_head; do { ASSERT(pd->size); pdTemp = pd; //initial values for start and end. start = (ULONG)pdTemp->BaseAddress; end = start+pdTemp->size; DPRINT((0,"FindFunctionByAddress(): ulValue %x\n",ulValue)); if(ulValue>=start && ulValuename)); if(PICE_wcsicmp(pdTemp->name,pSymbols->name) == 0) { DPRINT((0,"found symbols for module %S\n",pdTemp->name)); pSym = (PIMAGE_SYMBOL)((ULONG)pSymbols+pSymbols->ulOffsetToGlobals); pSymEnd = (PIMAGE_SYMBOL)((ULONG)pSym+pSymbols->ulSizeOfGlobals); pStr = (LPSTR)((ULONG)pSymbols+pSymbols->ulOffsetToGlobalsStrings); pShdr = (PIMAGE_SECTION_HEADER)((ULONG)pSymbols+pSymbols->ulOffsetToHeaders); if(!IsRangeValid((ULONG)pSym,sizeof(IMAGE_SYMBOL) ) ) //should we actually check all the symbols here? { DPRINT((0,"FindFunctionByAddress(): pSym = %x is not a valid pointer\n",(ULONG)pSym)); return FALSE; } DPRINT((0,"pSym = %x\n",pSym)); DPRINT((0,"pStr = %x\n",pStr)); DPRINT((0,"pShdr = %x\n",pShdr)); while( pSym < pSymEnd ) { //symbol is a function is it's type is 0x20, and section>0 if(( (pSym->Type == 0x20) && (pSym->SectionNumber > 0 ))) { ULONG ulCurrAddr; PIMAGE_SECTION_HEADER pShdrThis = (PIMAGE_SECTION_HEADER)pShdr + (pSym->SectionNumber-1); DPRINT((0,"FindFunctionByAddress(): pShdr[%x] = %x\n",pSym->SectionNumber,(ULONG)pShdrThis)); if(!IsRangeValid((ULONG)pShdrThis,sizeof(IMAGE_SECTION_HEADER)) ) { DPRINT((0,"ScanExportsByAddress(): pElfShdr[%x] = %x is not a valid pointer\n",pSym->SectionNumber,(ULONG)pShdrThis)); return FALSE; } //to get address in the memory we base address of the module and //add offset of the section and then add offset of the symbol from //the begining of the section ulCurrAddr = ((ULONG)pdTemp->BaseAddress+pShdrThis->VirtualAddress+pSym->Value); DPRINT((0,"FindFunctionByAddress(): CurrAddr [1] = %x\n",ulCurrAddr)); DPRINT((0,"%x ", ulCurrAddr)); if(ulCurrAddr<=ulValue && ulCurrAddr>start) { start = ulCurrAddr; pFoundSym = pSym; //DPRINT((0,"FindFunctionByAddress(): CANDIDATE for start %x\n",start)); } else if(ulCurrAddr>=ulValue && ulCurrAddrNumberOfAuxSymbols + 1; } //we went through all the symbols for this module //now start should point to the start of the function and //end to the start of the next (or end of section) if(pulstart) *pulstart = start; if(pulend){ //just in case there is more than one code section PIMAGE_SECTION_HEADER pShdrThis = (PIMAGE_SECTION_HEADER)pShdr + (pFoundSym->SectionNumber-1); if( end > (ULONG)pdTemp->BaseAddress+pShdrThis->SizeOfRawData ){ DPRINT((0,"Hmm: end=%d, end of section: %d\n", end, (ULONG)pdTemp->BaseAddress+pShdrThis->SizeOfRawData)); end = (ULONG)pdTemp->BaseAddress+pShdrThis->SizeOfRawData; } *pulend = end; } if(pFoundSym->N.Name.Short){ //name is in the header. it's not zero terminated. have to copy. PICE_sprintf(temp4,"%.8s", pFoundSym->N.ShortName); pName = temp4; DPRINT((0,"Function name: %S!%.8s",pdTemp->name,pName)); } else{ ASSERT(pFoundSym->N.Name.Long<=pSymbols->ulSizeOfGlobalsStrings); //sanity check pName = pStr+pFoundSym->N.Name.Long; if(!IsAddressValid((ULONG)pName)) { DPRINT((0,"FindFunctionByAddress(): pName = %x is not a valid pointer\n",pName)); return NULL; } DPRINT((0,"Function name: %S!%s",pdTemp->name,pName)); } return pName; } } }while((pd = pd->next) != pdebug_module_tail); } return NULL; } //************************************************************************* // FindDataSectionOffset() // //************************************************************************* /* ei: never used ULONG FindDataSectionOffset(Elf32_Shdr* pSHdr) { DPRINT((0,"FindDataSectionOffset()\n")); while(1) { DPRINT((0,"FindDataSectionOffset(): sh_offset %.8X sh_addr = %.8X\n",pSHdr->sh_offset,pSHdr->sh_addr)); if((pSHdr->sh_flags & (SHF_WRITE|SHF_ALLOC) ) == (SHF_WRITE|SHF_ALLOC)) { return pSHdr->sh_offset; } pSHdr++; } return 0; } */ //************************************************************************* // FindFunctionInModuleByNameViaKsyms() // //************************************************************************* /* ei: not needed. no Ksyms! ULONG FindFunctionInModuleByNameViaKsyms(struct module* pMod,LPSTR szFunctionname) { ULONG i; ENTER_FUNC(); if(pMod->nsyms) { DPRINT((0,"FindFunctionInModuleByNameViaKsyms(): %u symbols for module %s\n",pMod->nsyms,pMod->name)); for(i=0;insyms;i++) { DPRINT((0,"FindFunctionInModuleByNameViaKsyms(): %s\n",pMod->syms[i].name)); if(PICE_strcmpi((LPSTR)pMod->syms[i].name,szFunctionname) == 0) { DPRINT((0,"FindFunctionInModuleByName(): symbol was in exports\n")); LEAVE_FUNC(); return pMod->syms[i].value; } } } DPRINT((0,"FindFunctionInModuleByName(): symbol wasn't in exports\n")); LEAVE_FUNC(); return 0; } */ //************************************************************************* // FindFunctionInModuleByName() // //************************************************************************* ULONG FindFunctionInModuleByName(LPSTR szFunctionname, PDEBUG_MODULE pd) { ULONG i,addr; PICE_SYMBOLFILE_HEADER* pSymbols=NULL; PIMAGE_SYMBOL pSym, pSymEnd; LPSTR pStr; PIMAGE_SECTION_HEADER pShdr; ENTER_FUNC(); DPRINT((0,"FindFunctionInModuleByName(%s)\n",szFunctionname)); DPRINT((0,"FindFunctionInModuleByName(): mod size = %x\n",pd->size)); DPRINT((0,"FindFunctionInModuleByName(): module is %S\n",pd->name)); addr = (ULONG)pd->BaseAddress; pSymbols = FindModuleSymbols(addr); if(pSymbols) { DPRINT((0,"FindFunctionInModuleByName(): found symbol table for %S\n",pSymbols->name)); pSym = (PIMAGE_SYMBOL)((ULONG)pSymbols+pSymbols->ulOffsetToGlobals); pSymEnd = (PIMAGE_SYMBOL)((ULONG)pSym+pSymbols->ulSizeOfGlobals); pStr = (LPSTR)((ULONG)pSymbols+pSymbols->ulOffsetToGlobalsStrings); pShdr = (PIMAGE_SECTION_HEADER)((ULONG)pSymbols+pSymbols->ulOffsetToHeaders); while( pSym < pSymEnd ) { //symbol is a function is it's type is 0x20, storage class is external and section>0 //if(( (pSym->Type == 0x20) && (pSym->StorageClass==IMAGE_SYM_CLASS_EXTERNAL) && // (pSym->SectionNumber > 0 ))) if(((pSym->Type == 0x0) || (pSym->Type == 0x20) ) && ((pSym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) || (pSym->StorageClass==IMAGE_SYM_CLASS_STATIC)) && (pSym->SectionNumber > 0 )) { ULONG start; LPSTR pName; PIMAGE_SECTION_HEADER pShdrThis = (PIMAGE_SECTION_HEADER)pShdr + (pSym->SectionNumber-1); start = ((ULONG)pd->BaseAddress+pShdrThis->VirtualAddress+pSym->Value); DPRINT((0,"FindFunctionInModuleByName(): %s @ %x\n",szFunctionname,start)); if(pSym->N.Name.Short){ //if name is stored in the structure //name may be not zero terminated but 8 characters max DPRINT((0,"FindFunctionInModuleByName: %.8s\n", pSym->N.ShortName)); pName = pSym->N.ShortName; //name is in the header if((PICE_fnncmp(pName,szFunctionname, 8) == 0) && start) { DPRINT((0,"FindFunctionInModuleByName(): symbol was in symbol table, start: %x\n", start)); LEAVE_FUNC(); return start; } }else{ pName = pStr+pSym->N.Name.Long; DPRINT((0,"FindFunctionInModuleByName: %s\n", pName)); if((PICE_fncmp(pName,szFunctionname) == 0) && start) { DPRINT((0,"FindFunctionInModuleByName(): symbol was in string table, start: %x\n", start)); LEAVE_FUNC(); return start; } } } //skip the auxiliary symbols and get the next symbol pSym += pSym->NumberOfAuxSymbols + 1; } } LEAVE_FUNC(); return 0; } //************************************************************************* // ExtractTypeNumber() // //************************************************************************* ULONG ExtractTypeNumber(LPSTR p) { LPSTR pTypeNumber; ULONG ulTypeNumber = 0; DPRINT((0,"ExtractTypeNumber(%s)\n",p)); pTypeNumber = PICE_strchr(p,'('); if(pTypeNumber) { pTypeNumber++; ulTypeNumber = ExtractNumber(pTypeNumber); ulTypeNumber <<= 16; pTypeNumber = PICE_strchr(p,','); if(pTypeNumber) { pTypeNumber++; ulTypeNumber += ExtractNumber(pTypeNumber); } else { ulTypeNumber = 0; } } return ulTypeNumber; } //************************************************************************* // FindTypeDefinitionForCombinedTypes() // //************************************************************************* LPSTR FindTypeDefinitionForCombinedTypes(PICE_SYMBOLFILE_HEADER* pSymbols,ULONG ulTypeNumber,ULONG ulFileNumber) { ULONG i; PSTAB_ENTRY pStab; LPSTR pStr,pName,pTypeNumber,pTypeDefIncluded,pNameTemp; int nStabLen; int nOffset=0,nNextOffset=0,nLen; static char szAccumulatedName[2048]; ULONG ulCurrentTypeNumber,ulCurrentFileNumber=0; static char szCurrentPath[256]; ENTER_FUNC(); *szAccumulatedName = 0; pStab = (PSTAB_ENTRY )((ULONG)pSymbols + pSymbols->ulOffsetToStabs); nStabLen = pSymbols->ulSizeOfStabs; pStr = (LPSTR)((ULONG)pSymbols + pSymbols->ulOffsetToStabsStrings); DPRINT((0,"FindTypeDefinitionForCombinedTypes()\n")); for(i=0;i<(nStabLen/sizeof(STAB_ENTRY));i++) { pName = &pStr[pStab->n_strx + nOffset]; switch(pStab->n_type) { case N_UNDF: nOffset += nNextOffset; nNextOffset = pStab->n_value; break; case N_SO: if((nLen = PICE_strlen(pName))) { if(pName[nLen-1]!='/') { ulCurrentFileNumber++; if(PICE_strlen(szCurrentPath)) { PICE_strcat(szCurrentPath,pName); DPRINT((0,"FindTypeDefinitionForCombinedTypes(): changing source file %s\n",szCurrentPath)); } else { DPRINT((0,"FindTypeDefinitionForCombinedTypes(): changing source file %s\n",pName)); } } else PICE_strcpy(szCurrentPath,pName); } else { szCurrentPath[0]=0; } break; case N_GSYM: //ei File number count is not reliable if( 1 /*ulCurrentFileNumber == ulFileNumber*/) { DPRINT((0,"FindTypeDefinitionForCombinedTypes(): %s\n",pName)); // handle multi-line symbols if(PICE_strchr(pName,'\\')) { if(PICE_strlen(szAccumulatedName)) { PICE_strcat(szAccumulatedName,pName); } else { PICE_strcpy(szAccumulatedName,pName); } szAccumulatedName[PICE_strlen(szAccumulatedName)-1]=0; //DPRINT((0,"accum. %s\n",szAccumulatedName)); } else { if(PICE_strlen(szAccumulatedName)==0) { PICE_strcpy(szAccumulatedName,pName); } else { PICE_strcat(szAccumulatedName,pName); } pNameTemp = szAccumulatedName; // symbol-name:type-identifier type-number = nLen = StrLenUpToWhiteChar(pNameTemp,":"); if((pTypeDefIncluded = PICE_strchr(pNameTemp,'=')) && pNameTemp[nLen+1]=='G') { DPRINT((0,"FindTypeDefinitionForCombinedTypes(): symbol includes type definition (%s)\n",pNameTemp)); pTypeNumber = pNameTemp+nLen+1; if((ulCurrentTypeNumber = ExtractTypeNumber(pTypeNumber)) ) { DPRINT((0,"FindTypeDefinitionForCombinedTypes(): type-number %x\n",ulCurrentTypeNumber)); if(ulCurrentTypeNumber == ulTypeNumber) { DPRINT((0,"FindTypeDefinitionForCombinedTypes(): typenumber %x matches!\n",ulCurrentTypeNumber)); return pNameTemp; } } } *szAccumulatedName = 0; } } break; } pStab++; } return NULL; } //************************************************************************* // FindTypeDefinition() // //************************************************************************* LPSTR FindTypeDefinition(PICE_SYMBOLFILE_HEADER* pSymbols,ULONG ulTypeNumber,ULONG ulFileNumber) { ULONG i; PSTAB_ENTRY pStab; LPSTR pStr,pName,pTypeString; int nStabLen; int nOffset=0,nNextOffset=0,strLen; static char szAccumulatedName[2048]; ULONG ulCurrentTypeNumber,ulCurrentFileNumber=0; LPSTR pTypeSymbol; static char szCurrentPath[256]; ENTER_FUNC(); DPRINT((0,"FindTypeDefinition(%u,%u)\n",ulTypeNumber,ulFileNumber)); *szAccumulatedName = 0; pStab = (PSTAB_ENTRY )((ULONG)pSymbols + pSymbols->ulOffsetToStabs); nStabLen = pSymbols->ulSizeOfStabs; pStr = (LPSTR)((ULONG)pSymbols + pSymbols->ulOffsetToStabsStrings); for(i=0;i<(nStabLen/sizeof(STAB_ENTRY));i++) { pName = &pStr[pStab->n_strx + nOffset]; switch(pStab->n_type) { case N_UNDF: nOffset += nNextOffset; nNextOffset = pStab->n_value; break; case N_SO: if((strLen = PICE_strlen(pName))) { if(pName[strLen-1]!='/') { ulCurrentFileNumber++; if(PICE_strlen(szCurrentPath)) { PICE_strcat(szCurrentPath,pName); DPRINT((0,"FindTypeDefinition()1: cha %s, %u\n",szCurrentPath, ulCurrentFileNumber)); } else { DPRINT((0,"FindTypeDefinition(): cha %s, %u\n",pName, ulCurrentFileNumber)); } } else PICE_strcpy(szCurrentPath,pName); } else { szCurrentPath[0]=0; } break; case N_LSYM: // stab has no value -> must be type definition //ei File number count is not reliable if(pStab->n_value == 0 /*&& ulCurrentFileNumber==ulFileNumber*/) { DPRINT((0,"FindTypeDefinition(): pre type definition %s\n",pName)); // handle multi-line symbols if(strrchr(pName,'\\')) { if(PICE_strlen(szAccumulatedName)) { PICE_strcat(szAccumulatedName,pName); DPRINT((0,"FindTypeDefinition(): [1] accum. %s\n",szAccumulatedName)); } else { PICE_strcpy(szAccumulatedName,pName); DPRINT((0,"FindTypeDefinition(): [2] accum. %s\n",szAccumulatedName)); } szAccumulatedName[PICE_strlen(szAccumulatedName)-1]=0; } else { DPRINT((0,"FindTypeDefinition(): [3] accum. %s, pname: %s\n",szAccumulatedName, pName)); if(PICE_strlen(szAccumulatedName)==0) { PICE_strcpy(szAccumulatedName,pName); } else { PICE_strcat(szAccumulatedName,pName); } pTypeString = szAccumulatedName; pTypeSymbol = PICE_strchr(pTypeString,':'); if(pTypeSymbol && (*(pTypeSymbol+1)=='t' || *(pTypeSymbol+1)=='T')) { // parse it ulCurrentTypeNumber = ExtractTypeNumber(pTypeString); DPRINT((0,"FindTypeDefinition(): ulCurrType: %u, LSYM is type %s\n",ulCurrentTypeNumber,pName)); if(ulCurrentTypeNumber == ulTypeNumber) { DPRINT((0,"FindTypeDefinition(): type definition %s\n",pTypeString)); return pTypeString; } } *szAccumulatedName=0; } } break; } pStab++; } return FindTypeDefinitionForCombinedTypes(pSymbols,ulTypeNumber,ulFileNumber); } //************************************************************************* // TruncateString() // //************************************************************************* LPSTR TruncateString(LPSTR p,char c) { static char temp[1024]; LPSTR pTemp; pTemp = temp; while(*p!=0 && *p!=c) *pTemp++ = *p++; *pTemp = 0; return temp; } //************************************************************************* // FindLocalsByAddress() // // find all locals for a given address by first looking up the function // and then it's locals //************************************************************************* PLOCAL_VARIABLE FindLocalsByAddress(ULONG addr) { ULONG i; PSTAB_ENTRY pStab; LPSTR pStr,pName; int nStabLen; int nOffset=0,nNextOffset=0; PICE_SYMBOLFILE_HEADER* pSymbols; static char szCurrentFunction[256]; static char szCurrentPath[256]; LPSTR pFunctionName; ULONG start,end,strLen; ULONG ulTypeNumber,ulCurrentFileNumber=0; LPSTR pTypedef; ULONG ulNumLocalVars=0; DPRINT((0,"FindLocalsByAddress()\n")); pFunctionName = FindFunctionByAddress(addr,&start,&end); DPRINT((0,"FindLocalsByAddress(): pFunctionName = %s\n",pFunctionName)); if(pFunctionName) { pSymbols = FindModuleSymbols(addr); if(pSymbols) { pStab = (PSTAB_ENTRY )((ULONG)pSymbols + pSymbols->ulOffsetToStabs); nStabLen = pSymbols->ulSizeOfStabs; pStr = (LPSTR)((ULONG)pSymbols + pSymbols->ulOffsetToStabsStrings); for(i=0;i<(nStabLen/sizeof(STAB_ENTRY));i++) { pName = &pStr[pStab->n_strx + nOffset]; DPRINT((0,"FindLocalsByAddress(): %x %x %x %x %x\n", pStab->n_strx, pStab->n_type, pStab->n_other, pStab->n_desc, pStab->n_value)); switch(pStab->n_type) { case N_UNDF: nOffset += nNextOffset; nNextOffset = pStab->n_value; break; case N_SO: if((strLen = PICE_strlen(pName))) { if(pName[strLen-1]!='/') { ulCurrentFileNumber++; if(PICE_strlen(szCurrentPath)) { PICE_strcat(szCurrentPath,pName); DPRINT((0,"changing source file1 %s, %u\n",szCurrentPath,ulCurrentFileNumber)); } else { DPRINT((0,"changing source file %s, %u\n",pName,ulCurrentFileNumber)); } } else PICE_strcpy(szCurrentPath,pName); } else { szCurrentPath[0]=0; } break; case N_LSYM: // if we're in the function we're looking for if(szCurrentFunction[0] && PICE_fncmp(szCurrentFunction,pFunctionName)==0) { DPRINT((0,"local variable1 %.8X %.8X %.8X %.8X %.8X %s\n",pStab->n_strx,pStab->n_type,pStab->n_other,pStab->n_desc,pStab->n_value,pName)); ulTypeNumber = ExtractTypeNumber(pName); DPRINT((0,"type number = %u\n",ulTypeNumber)); if((pTypedef = FindTypeDefinition(pSymbols,ulTypeNumber,ulCurrentFileNumber))) { DPRINT((0,"pTypedef: %x\n", pTypedef)); PICE_strcpy(local_vars[ulNumLocalVars].type_name,TruncateString(pTypedef,':')); PICE_strcpy(local_vars[ulNumLocalVars].name,TruncateString(pName,':')); local_vars[ulNumLocalVars].value = (CurrentEBP+pStab->n_value); local_vars[ulNumLocalVars].offset = pStab->n_value; local_vars[ulNumLocalVars].line = pStab->n_desc; local_vars[ulNumLocalVars].bRegister = FALSE; ulNumLocalVars++; } } break; case N_PSYM: // if we're in the function we're looking for if(szCurrentFunction[0] && PICE_fncmp(szCurrentFunction,pFunctionName)==0) { DPRINT((0,"parameter variable %.8X %.8X %.8X %.8X %.8X %s\n",pStab->n_strx,pStab->n_type,pStab->n_other,pStab->n_desc,pStab->n_value,pName)); ulTypeNumber = ExtractTypeNumber(pName); DPRINT((0,"type number = %x\n",ulTypeNumber)); if((pTypedef = FindTypeDefinition(pSymbols,ulTypeNumber,ulCurrentFileNumber))) { PICE_strcpy(local_vars[ulNumLocalVars].type_name,TruncateString(pTypedef,':')); PICE_strcpy(local_vars[ulNumLocalVars].name,TruncateString(pName,':')); local_vars[ulNumLocalVars].value = (CurrentEBP+pStab->n_value); local_vars[ulNumLocalVars].offset = pStab->n_value; ulNumLocalVars++; } } break; case N_RSYM: // if we're in the function we're looking for if(szCurrentFunction[0] && PICE_fncmp(szCurrentFunction,pFunctionName)==0) { DPRINT((0,"local variable2 %.8X %.8X %.8X %.8X %.8X %s\n",pStab->n_strx,pStab->n_type,pStab->n_other,pStab->n_desc,pStab->n_value,pName)); ulTypeNumber = ExtractTypeNumber(pName); DPRINT((0,"type number = %x\n",ulTypeNumber)); if((pTypedef = FindTypeDefinition(pSymbols,ulTypeNumber,ulCurrentFileNumber))) { PICE_strcpy(local_vars[ulNumLocalVars].type_name,TruncateString(pTypedef,':')); PICE_strcpy(local_vars[ulNumLocalVars].name,TruncateString(pName,':')); local_vars[ulNumLocalVars].value = (LocalRegs[pStab->n_value]); local_vars[ulNumLocalVars].offset = pStab->n_value; local_vars[ulNumLocalVars].line = pStab->n_desc; local_vars[ulNumLocalVars].bRegister = TRUE; ulNumLocalVars++; } } break; case N_FUN: if(PICE_strlen(pName)) { ULONG len; len=StrLenUpToWhiteChar(pName,":"); PICE_strncpy(szCurrentFunction,pName,len); szCurrentFunction[len]=0; DPRINT((0,"function %s\n",szCurrentFunction)); } else { DPRINT((0,"END of function %s\n",szCurrentFunction)); szCurrentFunction[0]=0; if(ulNumLocalVars) { *local_vars[ulNumLocalVars].name = 0; return local_vars; } } break; } pStab++; } } } return NULL; } //************************************************************************* // FindSourceLineForAddress() // //************************************************************************* LPSTR FindSourceLineForAddress(ULONG addr,PULONG pulLineNumber,LPSTR* ppSrcStart,LPSTR* ppSrcEnd,LPSTR* ppFilename) { ULONG i; // index for walking through STABS PSTAB_ENTRY pStab; // pointer to STABS LPSTR pStr,pName; // pointer to STAB strings and current STAB string int nStabLen; // length of STAB section in bytes int nOffset=0,nNextOffset=0; // offset and next offset in string table PICE_SYMBOLFILE_HEADER* pSymbols; // pointer to module's STAB symbol table static char szCurrentFunction[256]; static char szCurrentPath[256]; static char szWantedPath[256]; LPSTR pFunctionName; // name of function that brackets the current address ULONG start,end,strLen,ulMinValue=0xFFFFFFFF; LPSTR pSrcLine=NULL; BOOLEAN bFirstOccurence = TRUE; // lookup the functions name and start-end (external symbols) pFunctionName = FindFunctionByAddress(addr,&start,&end); DPRINT((0,"FindSourceLineForAddress: for function: %s\n", pFunctionName)); if(pFunctionName) { // lookup the modules symbol table (STABS) pSymbols = FindModuleSymbols(addr); DPRINT((0,"FindSourceLineForAddress: pSymbols %x\n", pSymbols)); if(pSymbols) { DPRINT((0,"FindSourceLineForAddress: pSymbols->ulNumberOfSrcFiles %x\n", pSymbols->ulNumberOfSrcFiles)); // no source files so we don't need to lookup anything if(!pSymbols->ulNumberOfSrcFiles) return NULL; // prepare STABS access pStab = (PSTAB_ENTRY )((ULONG)pSymbols + pSymbols->ulOffsetToStabs); nStabLen = pSymbols->ulSizeOfStabs; pStr = (LPSTR)((ULONG)pSymbols + pSymbols->ulOffsetToStabsStrings); // walk over all STABS for(i=0;i<(nStabLen/sizeof(STAB_ENTRY));i++) { // the name string corresponding to the STAB pName = &pStr[pStab->n_strx + nOffset]; // switch STAB type switch(pStab->n_type) { // change offset of name strings case N_UNDF: nOffset += nNextOffset; nNextOffset = pStab->n_value; break; // source file change case N_SO: DPRINT((0,"changing source file %s\n",pName)); // if filename has a length record it if((strLen = PICE_strlen(pName))) { PICE_strcpy(szCurrentPath,pName); } // else empty filename else { szCurrentPath[0]=0; } break; // sub-source file change case N_SOL: DPRINT((0,"changing sub source file %s\n",pName)); // if filename has a length record it if((strLen = PICE_strlen(pName))) { PICE_strcpy(szCurrentPath,pName); } // else empty filename else { szCurrentPath[0]=0; } break; // a function symbol case N_FUN: if(!PICE_strlen(pName)) {// it's the end of a function DPRINT((0,"END of function %s\n",szCurrentFunction)); szCurrentFunction[0]=0; // in case we haven't had a zero delta match we return from here if(pSrcLine) return pSrcLine; break; } else {// if it has a length it's the start of a function ULONG len; // extract the name only, the type string is of no use here len=StrLenUpToWhiteChar(pName,":"); PICE_strncpy(szCurrentFunction,pName,len); szCurrentFunction[len]=0; DPRINT((0,"function %s\n",szCurrentFunction)); } //intentional fall through // line number case N_SLINE: // if we're in the function we're looking for if(szCurrentFunction[0] && PICE_fncmp(szCurrentFunction,pFunctionName)==0) { DPRINT((0,"cslnum#%u for addr.%x (fn @ %x) ulMinVal=%x ulDelta=%x\n",pStab->n_desc,start+pStab->n_value,start,ulMinValue,(addr-(start+pStab->n_value)))); if(bFirstOccurence) { PICE_strcpy(szWantedPath,szCurrentPath); DPRINT((0,"source file must be %s\n",szWantedPath)); bFirstOccurence = FALSE; } DPRINT((0,"wanted %s, current: %s\n",szWantedPath, szCurrentPath)); // we might have a match if our address is greater than the one in the STAB // and we're lower or equal than minimum value if(addr>=start+pStab->n_value && (addr-(start+pStab->n_value))<=ulMinValue && PICE_strcmpi(szWantedPath,szCurrentPath)==0 ) { ULONG j; PICE_SYMBOLFILE_SOURCE* pSrc = (PICE_SYMBOLFILE_SOURCE*)((ULONG)pSymbols+pSymbols->ulOffsetToSrcFiles); DPRINT((0,"code source line number #%u for addr. %x found!\n",pStab->n_desc,start+pStab->n_value)); // compute new minimum ulMinValue = addr-(start+pStab->n_value); // if we have a pointer for storage of line number, store it if(pulLineNumber) *pulLineNumber = pStab->n_desc; // NB: should put this somewhere else so that it's not done all the time // if we have source files at all DPRINT((0,"%u source files @ %x\n",pSymbols->ulNumberOfSrcFiles,pSrc)); // for all source files in this module for(j=0;julNumberOfSrcFiles;j++) { LPSTR pSlash; ULONG currlen, fnamelen; currlen = PICE_strlen( szCurrentPath ); fnamelen = PICE_strlen( pSrc->filename ); pSlash = pSrc->filename + fnamelen - currlen; //DPRINT((0,"pSlash: %s, szCurrentPath: %s\n", pSlash, szCurrentPath)); // if base name matches current path we have found the correct source file if(PICE_strcmpi(pSlash,szCurrentPath)==0) { // the linenumber ULONG k = pStab->n_desc; DPRINT((0,"found src file %s @ %x\n",pSrc->filename,pSrc)); // store the pointer to the filename if(ppFilename) *ppFilename = pSrc->filename; if(pSrc->ulOffsetToNext > sizeof(PICE_SYMBOLFILE_SOURCE)) { // get a pointer to the source file (right after the file header) pSrcLine = (LPSTR)((ULONG)pSrc+sizeof(PICE_SYMBOLFILE_SOURCE)); // store the source start and end address if(ppSrcStart) *ppSrcStart = pSrcLine; if(ppSrcEnd) *ppSrcEnd = pSrcLine+pSrc->ulOffsetToNext-sizeof(PICE_SYMBOLFILE_SOURCE); // goto to the right line while(--k) { while(*pSrcLine!=0 && *pSrcLine!=0x0a && *pSrcLine!=0x0d) pSrcLine++; if(!IsAddressValid((ULONG)pSrcLine)) return NULL; pSrcLine++; } if(ulMinValue == 0) return pSrcLine; } else { DPRINT((0,"src file descriptor found, but contains no source\n")); } break; } (ULONG)pSrc += pSrc->ulOffsetToNext; } } } break; } pStab++; } } } DPRINT((0,"FindSourceLineForAddress: exit 1\n")); return NULL; } //************************************************************************* // FindAddressForSourceLine() // //************************************************************************* BOOLEAN FindAddressForSourceLine(ULONG ulLineNumber,LPSTR pFilename,PDEBUG_MODULE pMod,PULONG pValue) { ULONG i; PSTAB_ENTRY pStab; LPSTR pStr,pName; int nStabLen; int nOffset=0,nNextOffset=0; PICE_SYMBOLFILE_HEADER* pSymbols; static char szCurrentFunction[256]; static char szCurrentPath[256]; ULONG strLen,addr,ulMinValue=0xFFFFFFFF; BOOLEAN bFound = FALSE; DPRINT((0,"FindAddressForSourceLine(%u,%s,%x)\n",ulLineNumber,pFilename,(ULONG)pMod)); addr = (ULONG)pMod->BaseAddress; pSymbols = FindModuleSymbols(addr); if(pSymbols) { pStab = (PSTAB_ENTRY )((ULONG)pSymbols + pSymbols->ulOffsetToStabs); nStabLen = pSymbols->ulSizeOfStabs; pStr = (LPSTR)((ULONG)pSymbols + pSymbols->ulOffsetToStabsStrings); for(i=0;i<(nStabLen/sizeof(STAB_ENTRY));i++) { pName = &pStr[pStab->n_strx + nOffset]; switch(pStab->n_type) { case N_UNDF: nOffset += nNextOffset; nNextOffset = pStab->n_value; break; case N_SO: if((strLen = PICE_strlen(pName))) { if(pName[strLen-1]!='/') { if(PICE_strlen(szCurrentPath)) { PICE_strcat(szCurrentPath,pName); DPRINT((0,"changing source file %s\n",szCurrentPath)); } else { DPRINT((0,"changing source file %s\n",pName)); PICE_strcpy(szCurrentPath,pName); } } else PICE_strcpy(szCurrentPath,pName); } else { szCurrentPath[0]=0; } break; case N_SLINE: // if we're in the function we're looking for if(PICE_strcmpi(pFilename,szCurrentPath)==0) { if(pStab->n_desc>=ulLineNumber && (pStab->n_desc-ulLineNumber)<=ulMinValue) { ulMinValue = pStab->n_desc-ulLineNumber; DPRINT((0,"code source line number #%u for offset %x in function @ %s)\n",pStab->n_desc,pStab->n_value,szCurrentFunction)); addr = FindFunctionInModuleByName(szCurrentFunction,pMod); if(addr) { *pValue = addr + pStab->n_value; bFound = TRUE; } } } break; case N_FUN: if(PICE_strlen(pName)) { ULONG len; len=StrLenUpToWhiteChar(pName,":"); PICE_strncpy(szCurrentFunction,pName,len); szCurrentFunction[len]=0; DPRINT((0,"function %s\n",szCurrentFunction)); } else { DPRINT((0,"END of function %s\n",szCurrentFunction)); szCurrentFunction[0]=0; } break; } pStab++; } } return bFound; } //************************************************************************* // ListSymbolStartingAt() // iterate through the list of module symbols (both functions and variables) //************************************************************************* ULONG ListSymbolStartingAt(PDEBUG_MODULE pMod,PICE_SYMBOLFILE_HEADER* pSymbols,ULONG index,LPSTR pOutput) { PIMAGE_SYMBOL pSym, pSymEnd; LPSTR pStr; PIMAGE_SECTION_HEADER pShdr; DPRINT((0,"ListSymbolStartingAt(%x,%u)\n",(ULONG)pSymbols,index)); DPRINT((0,"ListSymbolStartingAt(): ulOffsetToGlobals = %x ulSizeofGlobals = %x\n",pSymbols->ulOffsetToGlobals,pSymbols->ulSizeOfGlobals)); pSym = (PIMAGE_SYMBOL)((ULONG)pSymbols+pSymbols->ulOffsetToGlobals); pSymEnd = (PIMAGE_SYMBOL)((ULONG)pSym+pSymbols->ulSizeOfGlobals); pStr = (LPSTR)((ULONG)pSymbols+pSymbols->ulOffsetToGlobalsStrings); pShdr = (PIMAGE_SECTION_HEADER)((ULONG)pSymbols+pSymbols->ulOffsetToHeaders); pSym += index; while( pSym < pSymEnd ) { LPSTR pName; if(((pSym->Type == 0x0) || (pSym->Type == 0x20) ) && ((pSym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) /*|| (pSym->StorageClass==IMAGE_SYM_CLASS_STATIC)*/) && (pSym->SectionNumber > 0 )) { PIMAGE_SECTION_HEADER pShdrThis = (PIMAGE_SECTION_HEADER)pShdr + (pSym->SectionNumber-1); ULONG section_flags; ULONG start; DPRINT((0,"ListSymbolStartingAt(): pShdr[%x] = %x\n",pSym->SectionNumber,(ULONG)pShdrThis)); if(!IsRangeValid((ULONG)pShdrThis,sizeof(IMAGE_SECTION_HEADER)) ) { DPRINT((0,"ListSymbolStartingAt(): pShdr[%x] = %x is not a valid pointer\n",pSym->SectionNumber,(ULONG)pShdrThis)); return FALSE; } section_flags = pShdrThis->Characteristics; //to get address in the memory we base address of the module and //add offset of the section and then add offset of the symbol from //the begining of the section start = ((ULONG)pMod->BaseAddress+pShdrThis->VirtualAddress+pSym->Value); if(pSym->N.Name.Short){ //name is in the header. it's not zero terminated. have to copy. PICE_sprintf(pOutput,"%.8X (%s) %.8s\n",start,(section_flags&IMAGE_SCN_CNT_CODE)?"TEXT":"DATA",pSym->N.ShortName); } else{ ASSERT(pSym->N.Name.Long<=pSymbols->ulSizeOfGlobalsStrings); //sanity check pName = pStr+pSym->N.Name.Long; if(!IsAddressValid((ULONG)pName)) { DPRINT((0,"ListSymbolStartingAt(): pName = %x is not a valid pointer\n",pName)); return 0; } PICE_sprintf(pOutput,"%.8X (%s) %s\n",start,(section_flags&IMAGE_SCN_CNT_CODE)?"TEXT":"DATA",pName); } if((pSym+pSym->NumberOfAuxSymbols+1)<(pSymEnd)) return (index+pSym->NumberOfAuxSymbols+1); } index += pSym->NumberOfAuxSymbols + 1; pSym += pSym->NumberOfAuxSymbols + 1; } return 0; } //************************************************************************* // SanityCheckExports() // //************************************************************************* BOOLEAN SanityCheckExports(void) { BOOLEAN bResult = FALSE; ULONG i,ulValue,incr; Print(OUTPUT_WINDOW,"pICE: sanity-checking exports...\n"); return TRUE; /* fix later!!! do we really need to cross reference two kinds of symbolic info? if(fake_kernel_module.nsyms && fake_kernel_module.syms) { incr = (fake_kernel_module.nsyms/4); if(!incr)incr = 1; for(i=0;imagic = %X\n",pSymbols->magic)); } //set_fs(oldfs); if(pSymbols->magic == PICE_MAGIC) { DPRINT((0,"magic = %X\n",pSymbols->magic)); DPRINT((0,"name = %S\n",pSymbols->name)); DPRINT((0,"ulOffsetToHeaders,ulSizeOfHeader = %X,%X\n",pSymbols->ulOffsetToHeaders,pSymbols->ulSizeOfHeader)); DPRINT((0,"ulOffsetToGlobals,ulSizeOfGlobals = %X,%X\n",pSymbols->ulOffsetToGlobals,pSymbols->ulSizeOfGlobals)); DPRINT((0,"ulOffsetToGlobalsStrings,ulSizeOfGlobalsStrings = %X,%X\n",pSymbols->ulOffsetToGlobalsStrings,pSymbols->ulSizeOfGlobalsStrings)); DPRINT((0,"ulOffsetToStabs,ulSizeOfStabs = %X,%X\n",pSymbols->ulOffsetToStabs,pSymbols->ulSizeOfStabs)); DPRINT((0,"ulOffsetToStabsStrings,ulSizeOfStabsStrings = %X,%X\n",pSymbols->ulOffsetToStabsStrings,pSymbols->ulSizeOfStabsStrings)); DPRINT((0,"ulOffsetToSrcFiles,ulNumberOfSrcFiles = %X,%X\n",pSymbols->ulOffsetToSrcFiles,pSymbols->ulNumberOfSrcFiles)); DPRINT((0,"pICE: symbols loaded for module \"%S\" @ %x\n",pSymbols->name,pSymbols)); apSymbols[ulNumSymbolsLoaded++]=pSymbols; } else { DPRINT((0,"LoadSymbols(): freeing %x\n",pSymbols)); DPRINT((0,"pICE: symbols file \"%s\" corrupt\n",filename)); PICE_free(pSymbols); } } } PICE_close(hf); } else { DPRINT((0,"pICE: could not load symbols for %s...\n",filename)); } } LEAVE_FUNC(); return pSymbols; } //************************************************************************* // ReloadSymbols() // //************************************************************************* BOOLEAN ReloadSymbols(void) { BOOLEAN bResult; ENTER_FUNC(); UnloadSymbols(); bResult = LoadSymbolsFromConfig(TRUE); LEAVE_FUNC(); return bResult; } //************************************************************************* // UnloadSymbols() // //************************************************************************* void UnloadSymbols() { ULONG i; ENTER_FUNC(); if(ulNumSymbolsLoaded) { for(i=0;i1) { if(PICE_strcmpi(temp,"+vga")==0) { eTerminalMode = TERMINAL_MODE_VGA_TEXT; DPRINT((0,"pICE: eTerminalMode = TERMINAL_MODE_VGA_TEXT\n")); } else if(PICE_strcmpi(temp,"+hercules")==0) { eTerminalMode = TERMINAL_MODE_HERCULES_GRAPHICS; DPRINT((0,"pICE: eTerminalMode = TERMINAL_MODE_HERCULES_GRAPHICS\n")); } else if(PICE_strcmpi(temp,"+serial")==0) { eTerminalMode = TERMINAL_MODE_SERIAL; DPRINT((0,"pICE: eTerminalMode = TERMINAL_MODE_SERIAL\n")); } } else { DPRINT((0,"pICE: found option, but no value\n")); } } // comment else if(*temp == '#') { DPRINT((0,"comment out\n")); } // symbol file name/path else { DPRINT((0,"Load symbols from file %s\n", temp)); pSymbols = LoadSymbols(temp); DPRINT((0,"Load symbols from file %s, pSymbols: %x\n", temp, pSymbols)); if(pSymbols) { PICE_SYMBOLFILE_SOURCE* pSrc; LPSTR p; pSrc = (PICE_SYMBOLFILE_SOURCE*)((ULONG)pSymbols + pSymbols->ulOffsetToSrcFiles); pCurrentSymbols = pSymbols; p = strrchr(pSrc->filename,'\\'); if(p) { PICE_strcpy(szCurrentFile,p+1); } else { PICE_strcpy(szCurrentFile,pSrc->filename); } } } } else { DPRINT((0,"invalid line [%u] in config!\n",line)); } line++; } } else { //set_fs(oldfs); } } PICE_close(hf); bResult = TRUE; } else { DPRINT((0,"pICE: config file not found! No symbols loaded.\n")); DPRINT((0,"pICE: Please make sure to create a file \\systemroot\\symbols\\pice.conf\n")); DPRINT((0,"pICE: if you want to have symbols for any module loaded.\n")); } LEAVE_FUNC(); return bResult; } //************************************************************************* // EVALUATION OF EXPRESSIONS //************************************************************************* //************************************************************************* // SkipSpaces() // //************************************************************************* void SkipSpaces(void) { while(pExpression[ulIndex]==' ') ulIndex++; }; //************************************************************************* // FindGlobalStabSymbol() // //************************************************************************* BOOLEAN FindGlobalStabSymbol(LPSTR pExpression,PULONG pValue,PULONG pulTypeNumber,PULONG pulFileNumber) { ULONG i; PSTAB_ENTRY pStab; LPSTR pStr,pName; int nStabLen; int nOffset=0,nNextOffset=0,nLen,strLen; PICE_SYMBOLFILE_HEADER* pSymbols; ULONG ulTypeNumber; static char SymbolName[1024]; static char szCurrentPath[256]; ULONG ulCurrentFileNumber=0; LPSTR pTypeDefIncluded; ULONG addr; // must have a current module if(pCurrentMod) { // in case we query for the kernel we need to use the fake kernel module addr = (ULONG)pCurrentMod->BaseAddress; // find the symbols for the module pSymbols = FindModuleSymbols(addr); if(pSymbols) { // prepare table access pStab = (PSTAB_ENTRY )((ULONG)pSymbols + pSymbols->ulOffsetToStabs); nStabLen = pSymbols->ulSizeOfStabs; pStr = (LPSTR)((ULONG)pSymbols + pSymbols->ulOffsetToStabsStrings); // starting at file 0 *pulFileNumber = 0; // go through stabs for(i=0;i<(nStabLen/sizeof(STAB_ENTRY));i++) { pName = &pStr[pStab->n_strx + nOffset]; switch(pStab->n_type) { // an N_UNDF symbol marks a change of string table offset case N_UNDF: nOffset += nNextOffset; nNextOffset = pStab->n_value; break; // a source file symbol case N_SO: if((strLen = PICE_strlen(pName))) { if(pName[strLen-1]!='/') { ulCurrentFileNumber++; if(PICE_strlen(szCurrentPath)) { PICE_strcat(szCurrentPath,pName); DPRINT((0,"changing source file %s\n",szCurrentPath)); } else { DPRINT((0,"changing source file %s\n",pName)); } } else PICE_strcpy(szCurrentPath,pName); } else { szCurrentPath[0]=0; } break; case N_GSYM: case N_LSYM: case N_PSYM: // symbol-name:type-identifier type-number = nLen = StrLenUpToWhiteChar(pName,":"); PICE_strncpy(SymbolName,pName,nLen); SymbolName[nLen] = 0; if(PICE_strcmpi(SymbolName,pExpression)==0) { DPRINT((0,"global symbol %s\n",pName)); // extract type-number from stab ulTypeNumber = ExtractTypeNumber(pName); DPRINT((0,"type number = %x, from %s\n",ulTypeNumber, pName)); *pulTypeNumber = ulTypeNumber; // look for symbols address in external symbols if( pStab->n_type == N_LSYM || pStab->n_type == N_PSYM ) *pValue = CurrentEBP + pStab->n_value; else *pValue = FindFunctionInModuleByName(SymbolName,pCurrentMod); DPRINT((0,"value = %x\n",*pValue)); *pulFileNumber = ulCurrentFileNumber; DPRINT((0,"file = %x\n",ulCurrentFileNumber)); if((pTypeDefIncluded = PICE_strchr(pName,'=')) ) { DPRINT((0,"symbol includes type definition (%s)\n",pTypeDefIncluded)); } return TRUE; } break; } pStab++; } } } return FALSE; } //************************************************************************* // ExtractToken() // //************************************************************************* void ExtractToken(LPSTR pStringToken) { while(PICE_isalpha(pExpression[ulIndex]) || PICE_isdigit(pExpression[ulIndex]) || pExpression[ulIndex]=='_') { *pStringToken++=pExpression[ulIndex++]; *pStringToken=0; } } //************************************************************************* // ExtractTypeName() // //************************************************************************* LPSTR ExtractTypeName(LPSTR p) { static char temp[1024]; ULONG i; DPRINT((1,"ExtractTypeName(%s)\n",p)); for(i=0;IsAddressValid((ULONG)p) && *p!=0 && *p!=':';i++,p++) temp[i] = *p; if(!IsAddressValid((ULONG)p) ) { DPRINT((1,"hit invalid page %x!\n",(ULONG)p)); } temp[i]=0; return temp; } //************************************************************************* // ExtractNumber() // //************************************************************************* LONG ExtractNumber(LPSTR p) { LONG lMinus = 1,lBase; ULONG lNumber = 0; DPRINT((0,"ExtractNumber(): %s\n",p)); if(!IsAddressValid((ULONG)p) ) { DPRINT((1,"ExtractNumber(): [1] invalid page %x hit!\n",p)); return 0; } if(*p == '-') { lMinus = -1; p++; } if(!IsAddressValid((ULONG)p) ) { DPRINT((1,"ExtractNumber(): [2] invalid page %x hit!\n",p)); return 0; } if(*p != '0') // non-octal -> decimal number lBase = 10; else lBase = 8; if(!IsAddressValid((ULONG)p) ) { DPRINT((1,"ExtractNumber(): [3] invalid page %x hit!\n",p)); return 0; } while(PICE_isdigit(*p)) { lNumber *= lBase; lNumber += *p-'0'; p++; if(!IsAddressValid((ULONG)p) ) { DPRINT((1,"ExtractNumber(): [4] invalid page %x hit!\n",p)); return 0; } } return (lNumber*lMinus); } //************************************************************************* // ExtractArray() // //************************************************************************* BOOLEAN ExtractArray(PVRET pvr,LPSTR p) { ULONG index_typenumber,type_number; ULONG lower_bound,upper_bound; LPSTR pTypeDef; DPRINT((1,"ExtractArray(%s)\n",p)); // index-type index-type-number;lower;upper;element-type-number pvr->bArrayType = TRUE; p++; index_typenumber = ExtractTypeNumber(p); p = PICE_strchr(p,';'); if(p) { p++; lower_bound = ExtractNumber(p); p = PICE_strchr(p,';'); if(p) { p++; upper_bound = ExtractNumber(p); p = PICE_strchr(p,';'); if(p) { p++; type_number = ExtractTypeNumber(p); DPRINT((1,"ExtractArray(): %x %x %x %x\n",index_typenumber,lower_bound,upper_bound,type_number)); pTypeDef = FindTypeDefinition(pvr->pSymbols,type_number,pvr->file); if(pTypeDef) { PICE_strcpy(pvr->type_name,ExtractTypeName(pTypeDef)); pvr->type = type_number; return TRUE; } } } } return FALSE; } //************************************************************************* // ExtractStructMembers() // //************************************************************************* PVRET ExtractStructMembers(PVRET pvr,LPSTR p) { ULONG len; static char member_name[128]; LONG bit_offset,bit_size,type_number,byte_size; static VRET vr; LPSTR pTypeDef,pEqual; DPRINT((1,"ExtractStructMembers(): %s\n",p)); PICE_memset(&vr,0,sizeof(vr)); // name:type-number,bit-offset,bit-size len=StrLenUpToWhiteChar(p,":"); if(len) { // extract member name PICE_strncpy(member_name,p,len); member_name[len]=0; DPRINT((1,"ExtractStructMembers(): member_name = %s\n",member_name)); // go to char following ':' p += (len+1); if(IsAddressValid((ULONG)p) ) { type_number = ExtractTypeNumber(p); DPRINT((1,"ExtractStructMembers(): type_number = %x\n",type_number)); vr.type = type_number; pEqual = PICE_strchr(p,')'); // see if it includes type def if(pEqual) { p = pEqual+1; if(*p == '=') { p++; if(*p == 'a') { DPRINT((1,"ExtractStructMembers(): member is array\n")); vr.bArrayType = TRUE; p = PICE_strchr(p,';'); p = PICE_strchr(p,';'); p = PICE_strchr(p,';'); if(p) p++; type_number = ExtractTypeNumber(p); vr.father_type = type_number; } else if(*p == '*') { DPRINT((1,"ExtractStructMembers(): member is ptr\n")); vr.bPtrType = TRUE; type_number = ExtractTypeNumber(p); DPRINT((1,"ExtractStructMembers(): type_number = %x\n",type_number)); vr.father_type = type_number; } else if(*p == 'u') { DPRINT((1,"ExtractStructMembers(): member is union\n")); while(*p!=';' && *(p+1)!=';' && *p!=0)p++; } } } p = PICE_strchr(p,','); if(p) { p++; bit_offset = ExtractNumber(p); DPRINT((1,"ExtractStructMembers(): bit_offset = %x\n",bit_offset)); p = PICE_strchr(p,','); if(p) { p++; bit_size = ExtractNumber(p); DPRINT((1,"ExtractStructMembers(): bit_size = %x\n",bit_size)); vr.address = pvr->value + bit_offset/8; vr.file = pvr->file; vr.size = bit_size; PICE_strcpy(vr.name,member_name); byte_size = (bit_size+1)/8; if(!byte_size) byte_size = 4; pvr->address = pvr->value; if(IsRangeValid(vr.address,byte_size)) { switch(byte_size) { case 1: vr.value = *(PUCHAR)vr.address; break; case 2: vr.value = *(PUSHORT)vr.address; break; case 4: vr.value = *(PULONG)vr.address; break; } } DPRINT((1,"ExtractStructMembers(): member %s type %x bit_offset %x bit_size%x\n",member_name,type_number,bit_offset,bit_size)); pTypeDef = FindTypeDefinition(pvr->pSymbols,type_number,pvr->file); if(pTypeDef) { DPRINT((1,"ExtractStructMembers(): pTypedef= %s\n",pTypeDef)); PICE_strcpy(vr.type_name,ExtractTypeName(pTypeDef)); pTypeDef = PICE_strchr(pTypeDef,':'); if(pTypeDef) { pTypeDef++; type_number = ExtractTypeNumber(pTypeDef); DPRINT((1,"ExtractStructMembers(): type_number = %x\n",type_number)); vr.father_type = type_number; } } } } } } return &vr; } //************************************************************************* // EvaluateSymbol() // //************************************************************************* BOOLEAN EvaluateSymbol(PVRET pvr,LPSTR pToken) { LPSTR pTypeDef,pTypeName,pTypeBase,pSemiColon,pStructMembers; BOOLEAN bDone = FALSE; ULONG ulType,ulBits,ulBytes; LONG lLowerRange,lUpperRange,lDelta; static char type_def[2048]; DPRINT((1,"EvaluateSymbol(%s)\n",pToken)); if(FindGlobalStabSymbol(pToken,&pvr->value,&pvr->type,&pvr->file)) { DPRINT((1,"EvaluateSymbol(%s) pvr->value = %x pvr->type = %x\n",pToken,pvr->value,pvr->type)); while(!bDone) { if(!(pTypeDef = FindTypeDefinition(pvr->pSymbols,pvr->type,pvr->file))) break; PICE_strcpy(type_def,pTypeDef); pTypeDef = type_def; pTypeName = ExtractTypeName(pTypeDef); DPRINT((1,"%s %s\n",pTypeName,pToken)); PICE_strcpy(pvr->type_name,pTypeName); pTypeBase = PICE_strchr(pTypeDef,'='); if(!pTypeBase) return FALSE; pTypeBase++; switch(*pTypeBase) { case '(': // type reference ulType = ExtractTypeNumber(pTypeBase); DPRINT((1,"%x is a type reference to %x\n",pvr->type,ulType)); pvr->type = ulType; break; case 'r': // subrange pTypeBase++; ulType = ExtractTypeNumber(pTypeBase); DPRINT((1,"%x is sub range of %x\n",pvr->type,ulType)); if(pvr->type == ulType) { DPRINT((1,"%x is a self reference\n",pvr->type)); pSemiColon = PICE_strchr(pTypeBase,';'); pSemiColon++; lLowerRange = ExtractNumber(pSemiColon); pSemiColon = PICE_strchr(pSemiColon,';'); pSemiColon++; lUpperRange = ExtractNumber(pSemiColon); lDelta = lUpperRange-lLowerRange; DPRINT((1,"bounds %x-%x range %x\n",lLowerRange,lUpperRange,lDelta)); ulBits=0; do { ulBits++; lDelta /= 2; }while(lDelta); ulBytes = (ulBits+1)/8; if(!ulBytes) ulBytes = 4; DPRINT((1,"# of bytes = %x\n",ulBytes)); pvr->address = pvr->value; if(IsRangeValid(pvr->value,ulBytes)) { switch(ulBytes) { case 1: pvr->value = *(PUCHAR)pvr->value; break; case 2: pvr->value = *(PUSHORT)pvr->value; break; case 4: pvr->value = *(PULONG)pvr->value; break; } } bDone=TRUE; } else pvr->type = ulType; break; case 'a': // array type DPRINT((1,"%x array\n",pvr->type)); pTypeBase++; if(!ExtractArray(pvr,pTypeBase)) { bDone = TRUE; pvr->error = 1; } break; case '*': // ptr type DPRINT((1,"%x is ptr to\n",pvr->type)); bDone = TRUE; // meanwhile break; case 's': // struct type [name:T(#,#)=s#membername1:(#,#),#,#;membername1:(#,#),#,#;;] // go past 's' pTypeBase++; // extract the the struct size lLowerRange = ExtractNumber(pTypeBase); DPRINT((1,"%x struct size = %x\n",pvr->type,lLowerRange)); // skip over the digits while(PICE_isdigit(*pTypeBase)) pTypeBase++; // the structs address is is value pvr->address = pvr->value; pvr->bStructType = TRUE; // decode the struct members. pStructMembers now points to first member name pStructMembers = pTypeBase; while(pStructMembers && *pStructMembers && *pStructMembers!=';' && ulNumStructMemberstype == vrStructMembers[i].type) { PICE_strcpy(pvrThis->type_name,vrStructMembers[i].type_name); pvrThis->bArrayType = vrStructMembers[i].bArrayType; pvrThis->bPtrType = vrStructMembers[i].bPtrType; pvrThis->bStructType = vrStructMembers[i].bStructType; break; } } } DPRINT((1,"EvaluateSymbol(): vr.type_name = %s\n",vrStructMembers[ulNumStructMembers].type_name)); DPRINT((1,"EvaluateSymbol(): vr.name = %s\n",vrStructMembers[ulNumStructMembers].name)); DPRINT((1,"EvaluateSymbol(): vr.address = %.8X\n",vrStructMembers[ulNumStructMembers].address)); DPRINT((1,"EvaluateSymbol(): vr.value = %.8X\n",vrStructMembers[ulNumStructMembers].value)); DPRINT((1,"EvaluateSymbol(): vr.size = %.8X\n",vrStructMembers[ulNumStructMembers].size)); DPRINT((1,"EvaluateSymbol(): vr.type = %.8X\n",vrStructMembers[ulNumStructMembers].type)); ulNumStructMembers++; // skip to next ':' pStructMembers = PICE_strchr(pStructMembers,';'); pStructMembers = PICE_strchr(pStructMembers,':'); if(pStructMembers) { DPRINT((1,"EvaluateSymbol(): ptr is now %s\n",pStructMembers)); // go back to where member name starts while(*pStructMembers!=';') pStructMembers--; // if ';' present, go to next char if(pStructMembers) pStructMembers++; } } bDone = TRUE; // meanwhile break; case 'u': // union type DPRINT((1,"%x union\n",pvr->type)); bDone = TRUE; // meanwhile break; case 'e': // enum type DPRINT((1,"%x enum\n",pvr->type)); bDone = TRUE; // meanwhile break; default: DPRINT((1,"DEFAULT %x, base: %c\n",pvr->type, *pTypeBase)); pvr->address = pvr->value; if(IsRangeValid(pvr->value,ulBytes)) { switch(ulBytes) { case 1: pvr->value = *(PUCHAR)pvr->value; break; case 2: pvr->value = *(PUSHORT)pvr->value; break; case 4: pvr->value = *(PULONG)pvr->value; break; } } bDone = TRUE; break; } } return TRUE; } return FALSE; } //************************************************************************* // Symbol() // // Symbol := v //************************************************************************* BOOLEAN Symbol(PVRET pvr) { char SymbolToken[128]; ExtractToken(SymbolToken); DPRINT((1,"SymbolToken = %s\n",SymbolToken)); return EvaluateSymbol(pvr,SymbolToken); } //************************************************************************* // Expression() // // Expression := Symbol | Symbol->Symbol //************************************************************************* BOOLEAN Expression(PVRET pvr) { if(!Symbol(pvr)) return FALSE; return TRUE; } //************************************************************************* // Evaluate() // //************************************************************************* void Evaluate(PICE_SYMBOLFILE_HEADER* pSymbols,LPSTR p) { ULONG i; PICE_memset(&vr,0,sizeof(vr)); vr.pSymbols = pSymbols; pExpression = p; ulIndex=0; ulNumStructMembers=0; if(Expression(&vr)) { DPRINT((1,"\nOK!\n")); DPRINT((1,"value = %x type = %x\n",vr.value,vr.type)); if(vr.bStructType) { PICE_sprintf(tempSym,"struct %s %s @ %x\n",vr.type_name,p,vr.address); Print(OUTPUT_WINDOW,tempSym); for(i=0;i %x (%u)\n", vrStructMembers[i].address, vrStructMembers[i].size/8, vrStructMembers[i].type_name, vrStructMembers[i].name, vrStructMembers[i].value, vrStructMembers[i].value); } else { PICE_sprintf(tempSym,"[%.8X %.8X] %s %s = %x (%u)\n", vrStructMembers[i].address, vrStructMembers[i].size/8, vrStructMembers[i].type_name, vrStructMembers[i].name, vrStructMembers[i].value, vrStructMembers[i].value); } Print(OUTPUT_WINDOW,tempSym); } } else if(vr.bArrayType) { Print(OUTPUT_WINDOW,"array\n"); } else { PICE_sprintf(tempSym,"%s %s @ %x = %x (%u)\n",vr.type_name,p,vr.address,vr.value,vr.value); Print(OUTPUT_WINDOW,tempSym); } } else { DPRINT((1,"\nERROR: code %x\n",vr.error)); } }