VirtualBox

vbox的更動 64380 路徑 trunk/src/VBox/Debugger


忽略:
時間撮記:
2016-10-24 下午12:39:30 (8 年 以前)
作者:
vboxsync
訊息:

Debugger/Digger/FreeBSD: Update, loads the symbols now and supports getting at the kernel log buffer

檔案:
修改 1 筆資料

圖例:

未更動
新增
刪除
  • trunk/src/VBox/Debugger/DBGPlugInFreeBsd.cpp

    r64372 r64380  
    2525#include <VBox/vmm/dbgf.h>
    2626#include <iprt/asm.h>
     27#include <iprt/ctype.h>
    2728#include <iprt/mem.h>
    2829#include <iprt/stream.h>
     
    4243
    4344/**
     45 * ELF headers union.
     46 */
     47typedef union ELFEHDRS
     48{
     49    /** 32bit version of the ELF header. */
     50    Elf32_Ehdr    Hdr32;
     51    /** 64bit version of the ELF header. */
     52    Elf64_Ehdr    Hdr64;
     53} ELFEHDRS;
     54/** Pointer to a ELF header union. */
     55typedef ELFEHDRS *PELFEHDRS;
     56/** Pointer to const ELF header union. */
     57typedef ELFEHDRS const *PCELFEHDRS;
     58
     59/**
     60 * ELF symbol entry union.
     61 */
     62typedef union ELFSYMS
     63{
     64    /** 32bit version of the ELF section header. */
     65    Elf32_Sym     Hdr32;
     66    /** 64bit version of the ELF section header. */
     67    Elf64_Sym     Hdr64;
     68} ELFSYMS;
     69/** Pointer to a ELF symbol entry union. */
     70typedef ELFSYMS *PELFSYMS;
     71/** Pointer to const ELF symbol entry union. */
     72typedef ELFSYMS const *PCELFSYMS;
     73
     74/**
     75 * Message buffer structure.
     76 */
     77typedef union FBSDMSGBUF
     78{
     79    /** 32bit version. */
     80    struct
     81    {
     82        /** Message buffer pointer. */
     83        uint32_t        msg_ptr;
     84        /** Magic value to identify the structure. */
     85        uint32_t        msg_magic;
     86        /** Size of the buffer area. */
     87        uint32_t        msg_size;
     88        /** Write sequence number. */
     89        uint32_t        msg_wseq;
     90        /** Read sequence number. */
     91        uint32_t        msg_rseq;
     92        /** @todo: More fields which are not required atm. */
     93    } Hdr32;
     94    /** 64bit version. */
     95    struct
     96    {
     97        /** Message buffer pointer. */
     98        uint64_t        msg_ptr;
     99        /** Magic value to identify the structure. */
     100        uint32_t        msg_magic;
     101        /** Size of the buffer area. */
     102        uint32_t        msg_size;
     103        /** Write sequence number. */
     104        uint32_t        msg_wseq;
     105        /** Read sequence number. */
     106        uint32_t        msg_rseq;
     107        /** @todo: More fields which are not required atm. */
     108    } Hdr64;
     109} FBSDMSGBUF;
     110/** Pointer to a message buffer structure. */
     111typedef FBSDMSGBUF *PFBSDMSGBUF;
     112/** Pointer to a const message buffer structure. */
     113typedef FBSDMSGBUF const *PCFBSDMSGBUF;
     114
     115/** Magic value to identify the message buffer structure. */
     116#define FBSD_MSGBUF_MAGIC UINT32_C(0x063062)
     117
     118/**
    44119 * FreeBSD guest OS digger instance data.
    45120 */
     
    48123    /** Whether the information is valid or not.
    49124     * (For fending off illegal interface method calls.) */
    50     bool        fValid;
     125    bool            fValid;
    51126    /** 64-bit/32-bit indicator. */
    52     bool        f64Bit;
     127    bool            f64Bit;
    53128
    54129    /** Address of the start of the kernel ELF image,
    55130     * set during probing. */
    56     DBGFADDRESS AddrKernelElfStart;
     131    DBGFADDRESS     AddrKernelElfStart;
     132    /** Address of the the interpreter content aka "/red/herring". */
     133    DBGFADDRESS     AddrKernelInterp;
     134    /** Address of the start of the text section. */
     135    DBGFADDRESS     AddrKernelText;
     136
     137    /** The kernel message log interface. */
     138    DBGFOSIDMESG    IDmesg;
    57139
    58140} DBGDIGGERFBSD;
     
    70152
    71153/** Min kernel address (64bit). */
    72 #define FBSD64_MIN_KRNL_ADDR             UINT64_C(0xFFFFFE0000000000)
     154#define FBSD64_MIN_KRNL_ADDR             UINT64_C(0xFFFFF80000000000)
    73155/** Max kernel address (64bit). */
    74156#define FBSD64_MAX_KRNL_ADDR             UINT64_C(0xFFFFFFFFFFF00000)
     
    82164                                          && (Addr) < FBSD64_MAX_KRNL_ADDR)
    83165
     166/** Validates a FreeBSD kernel address. */
     167#define FBSD_VALID_ADDRESS(a_pThis, a_Addr) ((a_pThis)->f64Bit ? FBSD64_VALID_ADDRESS(a_Addr) : FBSD32_VALID_ADDRESS(a_Addr))
     168
    84169/** Maximum offset from the start of the ELF image we look for the /red/herring .interp section content. */
    85170#define FBSD_MAX_INTERP_OFFSET           _16K
     
    87172#define FBSD_MAX_KERNEL_SIZE             UINT32_C(0x0f000000)
    88173
     174/** Versioned and bitness wrapper. */
     175#define FBSD_UNION(a_pThis, a_pUnion, a_Member)  ((a_pThis)->f64Bit ? (a_pUnion)->Hdr64. a_Member : (a_pUnion)->Hdr32. a_Member )
    89176
    90177/*********************************************************************************************************************************
     
    102189    UINT64_C(0xffffffff80100000)
    103190};
     191/** Magic string which resides in the .interp section of the image. */
     192static const uint8_t g_abNeedleInterp[] = "/red/herring";
     193
     194
     195/**
     196 * Load the symbols from the .dynsym and .dynstr sections given
     197 * by their address in guest memory.
     198 *
     199 * @returns VBox status code.
     200 * @param   pThis           The instance data.
     201 * @param   pUVM            The user mode VM handle.
     202 * @param   pszName         The image name.
     203 * @param   uKernelStart    The kernel start address.
     204 * @param   cbKernel        Size of the kernel image.
     205 * @param   pAddrDynsym     Start address of the .dynsym section.
     206 * @param   cSymbols        Number of symbols in the .dynsym section.
     207 * @param   pAddrDynstr     Start address of the .dynstr section containing the symbol names.
     208 * @param   cbDynstr        Size of the .dynstr section.
     209 */
     210static int dbgDiggerFreeBsdLoadSymbols(PDBGDIGGERFBSD pThis, PUVM pUVM, const char *pszName, RTGCUINTPTR uKernelStart,
     211                                       size_t cbKernel, PDBGFADDRESS pAddrDynsym, uint32_t cSymbols, PDBGFADDRESS pAddrDynstr,
     212                                       size_t cbDynstr)
     213{
     214    LogFlowFunc(("pThis=%#p pszName=%s uKernelStart=%RGv cbKernel=%zu pAddrDynsym=%#p{%RGv} cSymbols=%u pAddrDynstr=%#p{%RGv} cbDynstr=%zu\n",
     215                 pThis, pszName, uKernelStart, cbKernel, pAddrDynsym, pAddrDynsym->FlatPtr, cSymbols, pAddrDynstr, pAddrDynstr->FlatPtr, cbDynstr));
     216
     217    char *pbDynstr = (char *)RTMemAllocZ(cbDynstr);
     218    int rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, pAddrDynstr, pbDynstr, cbDynstr);
     219    if (RT_SUCCESS(rc))
     220    {
     221        uint32_t cbDynsymEnt = pThis->f64Bit ? sizeof(Elf64_Sym) : sizeof(Elf32_Sym);
     222        uint8_t *pbDynsym = (uint8_t *)RTMemAllocZ(cSymbols * cbDynsymEnt);
     223        rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, pAddrDynsym, pbDynsym, cSymbols * cbDynsymEnt);
     224        if (RT_SUCCESS(rc))
     225        {
     226            /*
     227             * Create a module for the kernel.
     228             */
     229            RTDBGMOD hMod;
     230            rc = RTDbgModCreate(&hMod, pszName, cbKernel, 0 /*fFlags*/);
     231            if (RT_SUCCESS(rc))
     232            {
     233                rc = RTDbgModSetTag(hMod, DIG_FBSD_MOD_TAG); AssertRC(rc);
     234                rc = VINF_SUCCESS;
     235
     236                /*
     237                 * Enumerate the symbols.
     238                 */
     239                uint32_t cLeft = cSymbols;
     240                while (cLeft-- > 0 && RT_SUCCESS(rc))
     241                {
     242                    PCELFSYMS   pSym      = (PCELFSYMS)&pbDynsym[cLeft * cbDynsymEnt];
     243                    uint32_t    idxSymStr = FBSD_UNION(pThis, pSym, st_name);
     244                    uint8_t     uType     = FBSD_UNION(pThis, pSym, st_info);
     245                    RTGCUINTPTR AddrVal   = FBSD_UNION(pThis, pSym, st_value);
     246                    size_t      cbSymVal  = FBSD_UNION(pThis, pSym, st_size);
     247
     248                    /* Add it without the type char. */
     249                    RT_NOREF(uType);
     250                    if (AddrVal <= uKernelStart + cbKernel)
     251                    {
     252                        rc = RTDbgModSymbolAdd(hMod, &pbDynstr[idxSymStr], RTDBGSEGIDX_RVA, AddrVal - uKernelStart,
     253                                               cbSymVal, 0 /*fFlags*/, NULL);
     254                        if (RT_FAILURE(rc))
     255                        {
     256                            if (   rc == VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE
     257                                || rc == VERR_DBG_INVALID_RVA
     258                                || rc == VERR_DBG_ADDRESS_CONFLICT
     259                                || rc == VERR_DBG_DUPLICATE_SYMBOL)
     260                            {
     261                                Log2(("dbgDiggerFreeBsdLoadSymbols: RTDbgModSymbolAdd(,%s,) failed %Rrc (ignored)\n",
     262                                      &pbDynstr[idxSymStr], rc));
     263                                rc = VINF_SUCCESS;
     264                            }
     265                            else
     266                                Log(("dbgDiggerFreeBsdLoadSymbols: RTDbgModSymbolAdd(,%s,) failed %Rrc\n",
     267                                     &pbDynstr[idxSymStr], rc));
     268                        }
     269                    }
     270                }
     271
     272                /*
     273                 * Link the module into the address space.
     274                 */
     275                if (RT_SUCCESS(rc))
     276                {
     277                    RTDBGAS hAs = DBGFR3AsResolveAndRetain(pUVM, DBGF_AS_KERNEL);
     278                    if (hAs != NIL_RTDBGAS)
     279                        rc = RTDbgAsModuleLink(hAs, hMod, uKernelStart, RTDBGASLINK_FLAGS_REPLACE);
     280                    else
     281                        rc = VERR_INTERNAL_ERROR;
     282                    RTDbgAsRelease(hAs);
     283                }
     284                else
     285                    Log(("dbgDiggerFreeBsdLoadSymbols: Failed: %Rrc\n", rc));
     286                RTDbgModRelease(hMod);
     287            }
     288            else
     289                Log(("dbgDiggerFreeBsdLoadSymbols: RTDbgModCreate failed: %Rrc\n", rc));
     290        }
     291        else
     292            Log(("dbgDiggerFreeBsdLoadSymbols: Reading symbol table at %RGv failed: %Rrc\n",
     293                 pAddrDynsym->FlatPtr, rc));
     294        RTMemFree(pbDynsym);
     295    }
     296    else
     297        Log(("dbgDiggerFreeBsdLoadSymbols: Reading symbol string table at %RGv failed: %Rrc\n",
     298             pAddrDynstr->FlatPtr, rc));
     299    RTMemFree(pbDynstr);
     300
     301    LogFlowFunc(("returns %Rrc\n", rc));
     302    return rc;
     303}
     304
     305/**
     306 * Process the kernel image.
     307 *
     308 * @param   pThis           The instance data.
     309 * @param   pUVM            The user mode VM handle.
     310 * @param   pszName         The image name.
     311 */
     312static void dbgDiggerFreeBsdProcessKernelImage(PDBGDIGGERFBSD pThis, PUVM pUVM, const char *pszName)
     313{
     314    /*
     315     * FreeBSD has parts of the kernel ELF image in guest memory, starting with the
     316     * ELF header and the content of the sections which are indicated to be loaded
     317     * into memory (text, rodata, etc.) of course. Whats missing are the section headers
     318     * which is understandable but unfortunate because it would make our life easier.
     319     *
     320     * All checked FreeBSD kernels so far have the following layout in the kernel:
     321     *     [.interp] - contiains the /red/herring string we used for probing earlier
     322     *     [.hash]   - contains the hashes of the symbol names, 8 byte alignent
     323     *     [.dynsym] - contains the ELF symbol descriptors, 8 byte alignment
     324     *     [.dynstr] - contains the symbol names as a string table, 1 byte alignmnt
     325     *     [.text]   - contains the executable code, 16 byte alignment.
     326     * The sections are always adjacent (sans alignment) so we just parse the .hash section right after
     327     * .interp, ELF states that it can contain 32bit or 64bit words but all observed kernels
     328     * always use 32bit words. It contains two counters at the beginning which we can use to
     329     * deduct the .hash section size and the beginning of .dynsym.
     330     * .dynsym contains an array of symbol descriptors which have a fixed size depending on the
     331     * guest bitness.
     332     * Finding the end of .dynsym is not easily doable as there is no counter available (it lives
     333     * in the section headers) at this point so we just have to check whether the record is valid
     334     * and if not check if it contains an ASCII string which marks the start of the .dynstr section.
     335     */
     336
     337    /* Calculate the start of the .hash section. */
     338    DBGFADDRESS AddrHashStart = pThis->AddrKernelInterp;
     339    DBGFR3AddrAdd(&AddrHashStart, sizeof(g_abNeedleInterp));
     340    AddrHashStart.FlatPtr = RT_ALIGN_GCPT(AddrHashStart.FlatPtr, 8, RTGCUINTPTR);
     341    uint32_t au32Counters[2];
     342    int rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &AddrHashStart, &au32Counters[0], sizeof(au32Counters));
     343    if (RT_SUCCESS(rc))
     344    {
     345        size_t cbHash = (au32Counters[0] + au32Counters[1] + 2) * sizeof(uint32_t);
     346        if (AddrHashStart.FlatPtr + cbHash < pThis->AddrKernelText.FlatPtr) /* Should be much smaller */
     347        {
     348            DBGFADDRESS AddrDynsymStart = AddrHashStart;
     349            uint32_t cSymbols = 0;
     350            size_t cbKernel = 0;
     351            RTGCUINTPTR uKernelStart = pThis->AddrKernelElfStart.FlatPtr;
     352
     353            DBGFR3AddrAdd(&AddrDynsymStart, cbHash);
     354            AddrDynsymStart.FlatPtr = RT_ALIGN_GCPT(AddrDynsymStart.FlatPtr, 8, RTGCUINTPTR);
     355
     356            DBGFADDRESS AddrDynstrStart = AddrDynsymStart;
     357            while (AddrDynstrStart.FlatPtr < pThis->AddrKernelText.FlatPtr)
     358            {
     359                size_t cbDynSymEnt = pThis->f64Bit ? sizeof(Elf64_Sym) : sizeof(Elf32_Sym);
     360                uint8_t abBuf[_16K];
     361                size_t cbToRead = RT_MIN(sizeof(abBuf), pThis->AddrKernelText.FlatPtr - AddrDynstrStart.FlatPtr);
     362
     363                rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &AddrDynstrStart, &abBuf[0], cbToRead);
     364                if (RT_FAILURE(rc))
     365                    break;
     366
     367                for (unsigned i = 0; i < cbToRead / cbDynSymEnt; i++)
     368                {
     369                    PCELFSYMS   pSym      = (PCELFSYMS)&abBuf[i * cbDynSymEnt];
     370                    uint32_t    idxSymStr = FBSD_UNION(pThis, pSym, st_name);
     371                    uint8_t     uType     = FBSD_UNION(pThis, pSym, st_info);
     372                    RTGCUINTPTR AddrVal   = FBSD_UNION(pThis, pSym, st_value);
     373                    size_t      cbSymVal  = FBSD_UNION(pThis, pSym, st_size);
     374
     375                    /*
     376                     * If the entry doesn't look valid check whether it contains an ASCII string,
     377                     * we then found the start of the .dynstr section.
     378                     */
     379                    RT_NOREF(uType);
     380                    if (   ELF32_ST_TYPE(uType) != STT_NOTYPE
     381                        && (   !FBSD_VALID_ADDRESS(pThis, AddrVal)
     382                            || cbSymVal > FBSD_MAX_KERNEL_SIZE
     383                            || idxSymStr > pThis->AddrKernelText.FlatPtr - AddrDynstrStart.FlatPtr))
     384                    {
     385                        LogFlowFunc(("Invalid symbol table entry found at %RGv\n",
     386                                     AddrDynstrStart.FlatPtr + i * cbDynSymEnt));
     387
     388                        uint8_t *pbBuf = &abBuf[i * cbDynSymEnt];
     389                        size_t cbLeft = cbToRead - i * cbDynSymEnt;
     390                        /*
     391                         * Check to the end of the buffer whether it contains only a certain set of
     392                         * ASCII characters and 0 terminators.
     393                         */
     394                        while (   cbLeft > 0
     395                               && (   RT_C_IS_ALNUM(*pbBuf)
     396                                   || *pbBuf == '_'
     397                                   || *pbBuf == '\0'
     398                                   || *pbBuf == '.'))
     399                        {
     400                            cbLeft--;
     401                            pbBuf++;
     402                        }
     403
     404                        if (!cbLeft)
     405                        {
     406                            DBGFR3AddrAdd(&AddrDynstrStart, i * cbDynSymEnt);
     407                            LogFlowFunc(("Found all required section start addresses (.dynsym=%RGv cSymbols=%u, .dynstr=%RGv cb=%u)\n",
     408                                         AddrDynsymStart.FlatPtr, cSymbols, AddrDynstrStart.FlatPtr,
     409                                         pThis->AddrKernelText.FlatPtr - AddrDynstrStart.FlatPtr));
     410                            dbgDiggerFreeBsdLoadSymbols(pThis, pUVM, pszName, uKernelStart, cbKernel, &AddrDynsymStart, cSymbols, &AddrDynstrStart,
     411                                                        pThis->AddrKernelText.FlatPtr - AddrDynstrStart.FlatPtr);
     412                            return;
     413                        }
     414                        else
     415                            LogFlowFunc(("Found invalid ASCII character in .dynstr section candidate: %#x\n", *pbBuf));
     416                    }
     417                    else
     418                    {
     419                        cSymbols++;
     420                        if (   ELF32_ST_TYPE(uType) != STT_NOTYPE
     421                            && FBSD_VALID_ADDRESS(pThis, AddrVal))
     422                        {
     423                            uKernelStart = RT_MIN(uKernelStart, AddrVal);
     424                            cbKernel = RT_MAX(cbKernel, AddrVal + cbSymVal - uKernelStart);
     425                        }
     426                    }
     427                }
     428
     429                /* Don't account incomplete entries. */
     430                DBGFR3AddrAdd(&AddrDynstrStart, (cbToRead / cbDynSymEnt) * cbDynSymEnt);
     431            }
     432        }
     433        else
     434            LogFlowFunc((".hash section overlaps with .text section: %zu (expected much less than %u)\n", cbHash,
     435                         pThis->AddrKernelText.FlatPtr - AddrHashStart.FlatPtr));
     436    }
     437}
     438
     439
     440/**
     441 * @interface_method_impl{DBGFOSIDMESG,pfnQueryKernelLog}
     442 */
     443static DECLCALLBACK(int) dbgDiggerFreeBsdIDmsg_QueryKernelLog(PDBGFOSIDMESG pThis, PUVM pUVM, uint32_t fFlags, uint32_t cMessages,
     444                                                              char *pszBuf, size_t cbBuf, size_t *pcbActual)
     445{
     446    RT_NOREF1(fFlags);
     447    PDBGDIGGERFBSD pData = RT_FROM_MEMBER(pThis, DBGDIGGERFBSD, IDmesg);
     448
     449    if (cMessages < 1)
     450        return VERR_INVALID_PARAMETER;
     451
     452    /* Resolve the message buffer address from the msgbufp symbol. */
     453    RTDBGSYMBOL SymInfo;
     454    int rc = DBGFR3AsSymbolByName(pUVM, DBGF_AS_KERNEL, "kernel!msgbufp", &SymInfo, NULL);
     455    if (RT_SUCCESS(rc))
     456    {
     457        DBGFADDRESS AddrMsgBuf;
     458
     459        /* Read the message buffer pointer. */
     460        RTGCPTR     GCPtrMsgBufP = 0;
     461        rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, DBGFR3AddrFromFlat(pUVM, &AddrMsgBuf, SymInfo.Value),
     462                           &GCPtrMsgBufP, pData->f64Bit ? sizeof(uint64_t) : sizeof(uint32_t));
     463        if (RT_FAILURE(rc))
     464        {
     465            Log(("dbgDiggerFreeBsdIDmsg_QueryKernelLog: failed to read msgbufp at %RGv: %Rrc\n", AddrMsgBuf.FlatPtr, rc));
     466            return VERR_NOT_FOUND;
     467        }
     468        if (!FBSD_VALID_ADDRESS(pData, GCPtrMsgBufP))
     469        {
     470            Log(("dbgDiggerFreeBsdIDmsg_QueryKernelLog: Invalid address for msgbufp: %RGv\n", GCPtrMsgBufP));
     471            return VERR_NOT_FOUND;
     472        }
     473
     474        /* Read the structure. */
     475        FBSDMSGBUF MsgBuf;
     476        rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, DBGFR3AddrFromFlat(pUVM, &AddrMsgBuf, GCPtrMsgBufP),
     477                           &MsgBuf, sizeof(MsgBuf));
     478        if (RT_SUCCESS(rc))
     479        {
     480            RTGCUINTPTR AddrBuf = FBSD_UNION(pData, &MsgBuf, msg_ptr);
     481            uint32_t cbMsgBuf = FBSD_UNION(pData, &MsgBuf, msg_size);
     482            uint32_t uMsgBufSeqR = FBSD_UNION(pData, &MsgBuf, msg_rseq);
     483            uint32_t uMsgBufSeqW = FBSD_UNION(pData, &MsgBuf, msg_wseq);
     484
     485            /*
     486             * Validate the structure.
     487             */
     488            if (   FBSD_UNION(pData, &MsgBuf, msg_magic) != FBSD_MSGBUF_MAGIC
     489                || cbMsgBuf < UINT32_C(4096)
     490                || cbMsgBuf > 16*_1M
     491                || FBSD_UNION(pData, &MsgBuf, msg_rseq) > cbMsgBuf
     492                || FBSD_UNION(pData, &MsgBuf, msg_wseq) > cbMsgBuf
     493                || !FBSD_VALID_ADDRESS(pData, AddrBuf) )
     494            {
     495                Log(("dbgDiggerFreeBsdIDmsg_QueryKernelLog: Invalid MsgBuf data: msg_magic=%#x msg_size=%#x msg_rseq=%#x msg_wseq=%#x msg_ptr=%RGv\n",
     496                     FBSD_UNION(pData, &MsgBuf, msg_magic), cbMsgBuf, uMsgBufSeqR, uMsgBufSeqW, AddrBuf));
     497                return VERR_INVALID_STATE;
     498            }
     499
     500            /*
     501             * Read the buffer.
     502             */
     503            char *pchMsgBuf = (char *)RTMemAlloc(cbMsgBuf);
     504            if (!pchMsgBuf)
     505            {
     506                Log(("dbgDiggerFreeBsdIDmsg_QueryKernelLog: Failed to allocate %#x bytes of memory for the log buffer\n",
     507                     cbMsgBuf));
     508                return VERR_INVALID_STATE;
     509            }
     510            rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, DBGFR3AddrFromFlat(pUVM, &AddrMsgBuf, AddrBuf), pchMsgBuf, cbMsgBuf);
     511            if (RT_SUCCESS(rc))
     512            {
     513                /*
     514                 * Copy it out raw.
     515                 */
     516                uint32_t offDst = 0;
     517                if (uMsgBufSeqR < uMsgBufSeqW)
     518                {
     519                    /* Single chunk between the read and write offsets. */
     520                    uint32_t cbToCopy = uMsgBufSeqW - uMsgBufSeqR;
     521                    if (cbToCopy < cbBuf)
     522                    {
     523                        memcpy(pszBuf, &pchMsgBuf[uMsgBufSeqR], cbToCopy);
     524                        pszBuf[cbToCopy] = '\0';
     525                        rc = VINF_SUCCESS;
     526                    }
     527                    else
     528                    {
     529                        if (cbBuf)
     530                        {
     531                            memcpy(pszBuf, &pchMsgBuf[uMsgBufSeqR], cbBuf - 1);
     532                            pszBuf[cbBuf - 1] = '\0';
     533                        }
     534                        rc = VERR_BUFFER_OVERFLOW;
     535                    }
     536                    offDst = cbToCopy + 1;
     537                }
     538                else
     539                {
     540                    /* Two chunks, read offset to end, start to write offset. */
     541                    uint32_t cbFirst  = cbMsgBuf - uMsgBufSeqR;
     542                    uint32_t cbSecond = uMsgBufSeqW;
     543                    if (cbFirst + cbSecond < cbBuf)
     544                    {
     545                        memcpy(pszBuf, &pchMsgBuf[uMsgBufSeqR], cbFirst);
     546                        memcpy(&pszBuf[cbFirst], pchMsgBuf, cbSecond);
     547                        offDst = cbFirst + cbSecond;
     548                        pszBuf[offDst++] = '\0';
     549                        rc = VINF_SUCCESS;
     550                    }
     551                    else
     552                    {
     553                        offDst = cbFirst + cbSecond + 1;
     554                        if (cbFirst < cbBuf)
     555                        {
     556                            memcpy(pszBuf, &pchMsgBuf[uMsgBufSeqR], cbFirst);
     557                            memcpy(&pszBuf[cbFirst], pchMsgBuf, cbBuf - cbFirst);
     558                            pszBuf[cbBuf - 1] = '\0';
     559                        }
     560                        else if (cbBuf)
     561                        {
     562                            memcpy(pszBuf, &pchMsgBuf[uMsgBufSeqR], cbBuf - 1);
     563                            pszBuf[cbBuf - 1] = '\0';
     564                        }
     565                        rc = VERR_BUFFER_OVERFLOW;
     566                    }
     567                }
     568
     569                if (pcbActual)
     570                    *pcbActual = offDst;
     571            }
     572            else
     573                Log(("dbgDiggerFreeBsdIDmsg_QueryKernelLog: Error reading %#x bytes at %RGv: %Rrc\n", cbBuf, AddrBuf, rc));
     574            RTMemFree(pchMsgBuf);
     575        }
     576        else
     577            LogFlowFunc(("Failed to read message buffer header: %Rrc\n", rc));
     578    }
     579
     580    return rc;
     581}
     582
    104583
    105584/**
     
    108587static DECLCALLBACK(void *) dbgDiggerFreeBsdQueryInterface(PUVM pUVM, void *pvData, DBGFOSINTERFACE enmIf)
    109588{
    110     RT_NOREF3(pUVM, pvData, enmIf);
    111     return NULL;
     589    RT_NOREF1(pUVM);
     590    PDBGDIGGERFBSD pThis = (PDBGDIGGERFBSD)pvData;
     591    switch (enmIf)
     592    {
     593        case DBGFOSINTERFACE_DMESG:
     594            return &pThis->IDmesg;
     595
     596        default:
     597            return NULL;
     598    }
    112599}
    113600
     
    121608    Assert(pThis->fValid);
    122609
    123     RT_NOREF4(pUVM, pThis, pszVersion, cchVersion);
    124 
    125     return VERR_NOT_IMPLEMENTED;
     610    RTDBGSYMBOL SymInfo;
     611    int rc = DBGFR3AsSymbolByName(pUVM, DBGF_AS_KERNEL, "kernel!version", &SymInfo, NULL);
     612    if (RT_SUCCESS(rc))
     613    {
     614        DBGFADDRESS AddrVersion;
     615        DBGFR3AddrFromFlat(pUVM, &AddrVersion, SymInfo.Value);
     616
     617        rc = DBGFR3MemReadString(pUVM, 0, &AddrVersion, pszVersion, cchVersion);
     618        if (RT_SUCCESS(rc))
     619        {
     620            char *pszEnd = RTStrEnd(pszVersion, cchVersion);
     621            AssertReturn(pszEnd, VERR_BUFFER_OVERFLOW);
     622            while (     pszEnd > pszVersion
     623                   &&   RT_C_IS_SPACE(pszEnd[-1]))
     624                pszEnd--;
     625            *pszEnd = '\0';
     626        }
     627        else
     628            RTStrPrintf(pszVersion, cchVersion, "DBGFR3MemReadString -> %Rrc", rc);
     629    }
     630
     631    return rc;
    126632}
    127633
     
    167673    RT_NOREF1(pUVM);
    168674
     675    dbgDiggerFreeBsdProcessKernelImage(pThis, pUVM, "kernel");
    169676    pThis->fValid = true;
    170677    return VINF_SUCCESS;
     
    204711             * ELF header.
    205712             */
    206             static const uint8_t s_abNeedleInterp[] = "/red/herring";
    207713            DBGFADDRESS HitAddrInterp;
    208714            rc = DBGFR3MemScan(pUVM, 0 /*idCpu*/, &HitAddr, FBSD_MAX_INTERP_OFFSET, 1,
    209                                s_abNeedleInterp, sizeof(s_abNeedleInterp), &HitAddrInterp);
     715                               g_abNeedleInterp, sizeof(g_abNeedleInterp), &HitAddrInterp);
    210716            if (RT_SUCCESS(rc))
    211717            {
     
    237743                        pThis->f64Bit = ElfHdr.Hdr32.e_ident[EI_CLASS] == ELFCLASS64;
    238744                        pThis->AddrKernelElfStart = HitAddr;
     745                        pThis->AddrKernelInterp = HitAddrInterp;
     746                        pThis->AddrKernelText.FlatPtr = FBSD_UNION(pThis, &ElfHdr, e_entry);
     747                        LogFunc(("Found %s FreeBSD kernel at %RGv (.interp section at %RGv, .text section at %RGv)\n",
     748                                 pThis->f64Bit ? "amd64" : "i386", pThis->AddrKernelElfStart.FlatPtr,
     749                                 pThis->AddrKernelInterp.FlatPtr, pThis->AddrKernelText.FlatPtr));
    239750                        return true;
    240751                    }
     
    271782static DECLCALLBACK(int)  dbgDiggerFreeBsdConstruct(PUVM pUVM, void *pvData)
    272783{
    273     RT_NOREF2(pUVM, pvData);
     784    RT_NOREF1(pUVM);
     785    PDBGDIGGERFBSD pThis = (PDBGDIGGERFBSD)pvData;
     786
     787    pThis->fValid = false;
     788    pThis->f64Bit = false;
     789    pThis->IDmesg.u32Magic = DBGFOSIDMESG_MAGIC;
     790    pThis->IDmesg.pfnQueryKernelLog = dbgDiggerFreeBsdIDmsg_QueryKernelLog;
     791    pThis->IDmesg.u32EndMagic = DBGFOSIDMESG_MAGIC;
     792
    274793    return VINF_SUCCESS;
    275794}
注意: 瀏覽 TracChangeset 來幫助您使用更動檢視器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette