Ejemplo n.º 1
0
static int set_pe_context(Context * ctx, int frame, ContextAddress ip, HANDLE process, IMAGEHLP_STACK_FRAME * stack_frame) {
    if (get_stack_frame(ctx, frame, ip, stack_frame) < 0) return -1;

    if (!SymSetContext(process, stack_frame, NULL)) {
        DWORD err = GetLastError();
        if (err == ERROR_SUCCESS) {
            /* Don't know why Windows do that */
        }
        else if (err == ERROR_MOD_NOT_FOUND && frame != STACK_NO_FRAME) {
            /* No local symbols data, search global scope */
            if (get_stack_frame(ctx, STACK_NO_FRAME, 0, stack_frame) < 0) return -1;
            if (!SymSetContext(process, stack_frame, NULL)) {
                err = GetLastError();
                if (err != ERROR_SUCCESS) {
                    set_win32_errno(err);
                    return -1;
                }
            }
        }
        else if (err == ERROR_NOT_SUPPORTED) {
            /* Compiled without debug info */
            errno = ERR_SYM_NOT_FOUND;
            return -1;
        }
        else {
            set_win32_errno(err);
            return -1;
        }
    }
    return 0;
}
Ejemplo n.º 2
0
    void FunctionResolver::resolveParameters(const ULONG64& functionAddress, const ULONG64& modBase, const ULONG& typeIndex, std::vector<FunctionParameter>& resolvedParameters)
    {
        IMAGEHLP_STACK_FRAME sf;

        sf.InstructionOffset = functionAddress;

        if (!SymSetContext(this->m_hProcess, &sf, 0))
        {
            throw;
        }

        // Retrieve all parameters of this function.
        SymEnumSymbols(this->m_hProcess, NULL, NULL, EnumParamsCallback, &resolvedParameters);
    }
Ejemplo n.º 3
0
static BOOL stack_set_frame_internal(int newframe)
{
    if (newframe >= dbg_curr_thread->num_frames)
        newframe = dbg_curr_thread->num_frames - 1;
    if (newframe < 0)
        newframe = 0;

    if (dbg_curr_thread->curr_frame != newframe)
    {
        IMAGEHLP_STACK_FRAME    ihsf;

        dbg_curr_thread->curr_frame = newframe;
        stack_get_current_frame(&ihsf);
        SymSetContext(dbg_curr_process->handle, &ihsf, NULL);
    }
    return TRUE;
}
Ejemplo n.º 4
0
static void stack_print_addr_and_args(int nf)
{
    char                        buffer[sizeof(SYMBOL_INFO) + 256];
    SYMBOL_INFO*                si = (SYMBOL_INFO*)buffer;
    IMAGEHLP_STACK_FRAME        ihsf;
    IMAGEHLP_LINE64             il;
    IMAGEHLP_MODULE             im;
    DWORD64                     disp64;

    print_bare_address(&dbg_curr_thread->frames[nf].addr_pc);

    stack_get_frame(nf, &ihsf);

    /* grab module where symbol is. If we don't have a module, we cannot print more */
    im.SizeOfStruct = sizeof(im);
    if (!SymGetModuleInfo(dbg_curr_process->handle, ihsf.InstructionOffset, &im))
        return;

    si->SizeOfStruct = sizeof(*si);
    si->MaxNameLen   = 256;
    if (SymFromAddr(dbg_curr_process->handle, ihsf.InstructionOffset, &disp64, si))
    {
        struct sym_enum se;
        DWORD           disp;

        dbg_printf(" %s", si->Name);
        if (disp64) dbg_printf("+0x%lx", (DWORD_PTR)disp64);

        SymSetContext(dbg_curr_process->handle, &ihsf, NULL);
        se.first = TRUE;
        se.frame = ihsf.FrameOffset;
        dbg_printf("(");
        SymEnumSymbols(dbg_curr_process->handle, 0, NULL, sym_enum_cb, &se);
        dbg_printf(")");

        il.SizeOfStruct = sizeof(il);
        if (SymGetLineFromAddr64(dbg_curr_process->handle,
                                 ihsf.InstructionOffset, &disp, &il))
            dbg_printf(" [%s:%u]", il.FileName, il.LineNumber);
        dbg_printf(" in %s", im.ModuleName);
    }
    else dbg_printf(" in %s (+0x%lx)",
                        im.ModuleName, (DWORD_PTR)(ihsf.InstructionOffset - im.BaseOfImage));
}
Ejemplo n.º 5
0
int enumerate_symbols(Context * ctx, int frame, EnumerateSymbolsCallBack * call_back, void * args) {
    ULONG64 buffer[(sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)];
    SYMBOL_INFO * symbol = (SYMBOL_INFO *)buffer;
    IMAGEHLP_STACK_FRAME stack_frame;
    EnumerateSymbolsContext enum_context;
    HANDLE process = get_context_handle(ctx->parent == NULL ? ctx : ctx->parent);

    symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
    symbol->MaxNameLen = MAX_SYM_NAME;

    if (frame == STACK_TOP_FRAME) frame = get_top_frame(ctx);
    if (frame == STACK_TOP_FRAME) return -1;
    if (get_stack_frame(ctx, frame, 0, &stack_frame) < 0) return -1;

    if (!SymSetContext(process, &stack_frame, NULL)) {
        DWORD err = GetLastError();
        if (err == ERROR_SUCCESS) {
            /* Don't know why Windows does that */
        }
        else {
            set_win32_errno(err);
            return -1;
        }
    }

    enum_context.ctx = ctx;
    enum_context.frame = frame;
    enum_context.call_back = call_back;
    enum_context.args = args;

    if (!SymEnumSymbols(process, 0, NULL, enumerate_symbols_proc, &enum_context)) {
        set_win32_errno(GetLastError());
        return -1;
    }

    return 0;
}
Ejemplo n.º 6
0
/******************************************************************
 *		backtrace
 *
 * Do a backtrace on the current thread
 */
static void backtrace(void)
{
    unsigned                    cf = dbg_curr_thread->curr_frame;
    IMAGEHLP_STACK_FRAME        ihsf;

    dbg_printf("Backtrace:\n");
    for (dbg_curr_thread->curr_frame = 0;
            dbg_curr_thread->curr_frame < dbg_curr_thread->num_frames;
            dbg_curr_thread->curr_frame++)
    {
        dbg_printf("%s%d ",
                   (cf == dbg_curr_thread->curr_frame ? "=>" : "  "),
                   dbg_curr_thread->curr_frame);
        stack_print_addr_and_args(dbg_curr_thread->curr_frame);
        dbg_printf(" (");
        print_bare_address(&dbg_curr_thread->frames[dbg_curr_thread->curr_frame].addr_frame);
        dbg_printf(")\n");
    }
    /* reset context to current stack frame */
    dbg_curr_thread->curr_frame = cf;
    if (!dbg_curr_thread->frames) return;
    stack_get_frame(dbg_curr_thread->curr_frame, &ihsf);
    SymSetContext(dbg_curr_process->handle, &ihsf, NULL);
}
Ejemplo n.º 7
0
HRESULT
ParseImageSymbols(
    _In_ HMODULE hmod,
    _Inout_ PEXPORT_DATA pExportData)
{
    DWORD64 dwModuleBase;
    ULONG i;
    IMAGEHLP_STACK_FRAME StackFrame;
    SYMINFO_EX sym;

    dwModuleBase = (DWORD_PTR)hmod;

    /* Loop through all exports */
    for (i = 0; i < pExportData->cNumberOfExports; i++)
    {
        PEXPORT pExport = &pExportData->aExports[i];
        ULONG64 ullFunction = dwModuleBase + pExportData->aExports[i].ulRva;
        ULONG64 ullDisplacement;

        /* Check if this is a forwarder */
        if (pExport->pszForwarder != NULL)
        {
            /* Load the module and get the function address */
            ullFunction = GetFunctionFromForwarder(pExport->pszForwarder);
            if (ullFunction == 0)
            {
                printf("Failed to get function for forwarder '%s'. Skipping.\n", pExport->pszForwarder);
                continue;
            }
        }

        RtlZeroMemory(&sym, sizeof(sym));
        sym.si.SizeOfStruct = sizeof(SYMBOL_INFO);
        sym.si.MaxNameLen = MAX_SYMBOL_NAME;

        /* Try to find the symbol */
        if (!SymFromAddr(ghProcess, ullFunction, &ullDisplacement, &sym.si))
        {
            error("Error: SymFromAddr() failed.");
            continue;
        }

        /* Get the symbol name */
        pExport->pszSymbol = _strdup(sym.si.Name);

        /* Check if it is a function */
        if (sym.si.Tag == SymTagFunction)
        {
            /* Get the calling convention */
            if (!SymGetTypeInfo(ghProcess,
                                dwModuleBase,
                                sym.si.TypeIndex,
                                TI_GET_CALLING_CONVENTION,
                                &pExport->dwCallingConvention))
            {
                /* Fall back to __stdcall */
                pExport->dwCallingConvention = CV_CALL_NEAR_STD;
            }

            /* Set the context to the function address */
            RtlZeroMemory(&StackFrame, sizeof(StackFrame));
            StackFrame.InstructionOffset = ullFunction;
            if (!SymSetContext(ghProcess, &StackFrame, NULL))
            {
                error("SymSetContext failed for i = %u.", i);
                continue;
            }

            /* Enumerate all symbols for this function */
            if (!SymEnumSymbols(ghProcess,
                                0, // use SymSetContext
                                NULL,
                                EnumParametersCallback,
                                pExport))
            {
                error("SymEnumSymbols failed for i = %u.", i);
                continue;
            }
        }
        else if (sym.si.Tag == SymTagPublicSymbol)
        {
            pExport->dwCallingConvention = CV_CALL_NEAR_STD;
        }
        else if (sym.si.Tag == SymTagData)
        {
            pExport->fData = TRUE;
        }
    }

    return S_OK;
}
Ejemplo n.º 8
0
void write_stack_trace(PCONTEXT pContext, TextOutputStream& outputStream)
{
  HANDLE m_hProcess = GetCurrentProcess();
  DWORD dwMachineType = 0;

  CONTEXT context = *pContext;

  // Could use SymSetOptions here to add the SYMOPT_DEFERRED_LOADS flag
  if ( !SymInitialize( m_hProcess, (PSTR)environment_get_app_path(), TRUE ) )
  {
    return;
  }

  STACKFRAME sf;
  memset( &sf, 0, sizeof(sf) );

#ifdef _M_IX86
  // Initialize the STACKFRAME structure for the first call.  This is only
  // necessary for Intel CPUs, and isn't mentioned in the documentation.
  sf.AddrPC.Offset       = context.Eip;
  sf.AddrPC.Mode         = AddrModeFlat;
  sf.AddrStack.Offset    = context.Esp;
  sf.AddrStack.Mode      = AddrModeFlat;
  sf.AddrFrame.Offset    = context.Ebp;
  sf.AddrFrame.Mode      = AddrModeFlat;

  dwMachineType = IMAGE_FILE_MACHINE_I386;
#endif

  while ( 1 )
  {
    // Get the next stack frame
    if ( ! StackWalk(  dwMachineType,
                        m_hProcess,
                        GetCurrentThread(),
                        &sf,
                        &context,
                        0,
                        SymFunctionTableAccess,
                        SymGetModuleBase,
                        0 ) )
        break;

    if ( 0 == sf.AddrFrame.Offset ) // Basic sanity check to make sure
      break;                      // the frame is OK.  Bail if not.

    // Get the name of the function for this stack frame entry
    BYTE symbolBuffer[ sizeof(SYMBOL_INFO) + MAX_SYM_NAME ];
    PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)symbolBuffer;
    pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
    pSymbol->MaxNameLen = MAX_SYM_NAME;
                    
    DWORD64 symDisplacement = 0;    // Displacement of the input address,
                                    // relative to the start of the symbol

    IMAGEHLP_MODULE module = { sizeof(IMAGEHLP_MODULE) };
    if(SymGetModuleInfo(m_hProcess, sf.AddrPC.Offset, &module))
    {
      outputStream << module.ModuleName << "!";

      if ( SymFromAddr(m_hProcess, sf.AddrPC.Offset, &symDisplacement, pSymbol))
      {
        char undecoratedName[MAX_SYM_NAME];
        UnDecorateSymbolName(pSymbol->Name, undecoratedName, MAX_SYM_NAME, UNDNAME_COMPLETE);

        outputStream << undecoratedName;

        outputStream << "(";
        // Use SymSetContext to get just the locals/params for this frame
        IMAGEHLP_STACK_FRAME imagehlpStackFrame;
        imagehlpStackFrame.InstructionOffset = sf.AddrPC.Offset;
        SymSetContext( m_hProcess, &imagehlpStackFrame, 0 );

        // Enumerate the locals/parameters
        EnumerateSymbolsContext context(sf, outputStream);
        SymEnumSymbols( m_hProcess, 0, 0, EnumerateSymbolsCallback, &context );
        outputStream << ")";

        outputStream << " + " << Offset(reinterpret_cast<void*>(symDisplacement));

        // Get the source line for this stack frame entry
        IMAGEHLP_LINE lineInfo = { sizeof(IMAGEHLP_LINE) };
        DWORD dwLineDisplacement;
        if ( SymGetLineFromAddr( m_hProcess, sf.AddrPC.Offset,
                                &dwLineDisplacement, &lineInfo ) )
        {
          outputStream << " " << lineInfo.FileName << " line " << Unsigned(lineInfo.LineNumber); 
        }
      }
      else
      {
        outputStream << Address(reinterpret_cast<void*>(sf.AddrPC.Offset));
      }
    }

    outputStream << "\n";
  }

  SymCleanup(m_hProcess);

  return;
}