VirtualBox

Changeset 38557 in vbox for trunk/src


Ignore:
Timestamp:
Aug 29, 2011 1:13:27 PM (13 years ago)
Author:
vboxsync
Message:

dbgmoddwarf.cpp: line number virtual machine coding.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/dbg/dbgmoddwarf.cpp

    r38554 r38557  
    3636#include <iprt/ctype.h>
    3737#include <iprt/mem.h>
     38#include <iprt/path.h>
    3839#include <iprt/stream.h>
    3940#include <iprt/string.h>
    4041#include "internal/dbgmod.h"
     42
     43
     44/*******************************************************************************
     45*   Defined Constants And Macros                                               *
     46*******************************************************************************/
     47/** @name Standard DWARF Line Number Opcodes
     48 * @{ */
     49#define DW_LNS_extended             UINT8_C(0)
     50#define DW_LNS_copy                 UINT8_C(1)
     51#define DW_LNS_advance_pc           UINT8_C(2)
     52#define DW_LNS_advance_line         UINT8_C(3)
     53#define DW_LNS_set_file             UINT8_C(4)
     54#define DW_LNS_set_column           UINT8_C(5)
     55#define DW_LNS_negate_stmt          UINT8_C(6)
     56#define DW_LNS_set_basic_block      UINT8_C(7)
     57#define DW_LNS_const_add_pc         UINT8_C(8)
     58#define DW_LNS_fixed_advance_pc     UINT8_C(9)
     59#define DW_LNS_set_prologue_end     UINT8_C(10)
     60#define DW_LNS_set_epilogue_begin   UINT8_C(11)
     61#define DW_LNS_set_isa              UINT8_C(12)
     62/** @} */
     63
     64
     65/** @name Extended DWARF Line Number Opcodes
     66 * @{ */
     67#define DW_LNE_end_sequence         UINT8_C(1)
     68#define DW_LNE_set_address          UINT8_C(2)
     69#define DW_LNE_define_file          UINT8_C(3)
     70#define DW_LNE_set_descriminator    UINT8_C(4)
     71/** @} */
    4172
    4273
     
    97128typedef struct RTDWARFSECTRDR
    98129{
    99     /** The DWARF debug info reader instance. */
    100     PRTDBGMODDWARF          pDwarfMod;
    101     /** The section we're reading.  */
    102     krtDbgModDwarfSect      enmSect;
    103130    /** The current position. */
    104131    uint8_t const          *pb;
    105132    /** The number of bytes left to read. */
    106133    size_t                  cbLeft;
     134    /** The number of bytes left to read in the current unit. */
     135    size_t                  cbUnitLeft;
     136    /** The DWARF debug info reader instance. */
     137    PRTDBGMODDWARF          pDwarfMod;
    107138    /** Set if this is 64-bit DWARF, clear if 32-bit. */
    108     bool                    f64bit;
     139    bool                    f64bitDwarf;
    109140    /** Set if the format endian is native, clear if endian needs to be
    110141     * inverted. */
    111142    bool                    fNativEndian;
    112 } RTDWARFSECTRDR;
     143    /** The size of a native address. */
     144    uint8_t                 cbNativeAddr;
     145    /** The cursor status code.  This is VINF_SUCCESS until some error
     146     *  occurs. */
     147    int                     rc;
     148} RTDWARFCURSOR;
    113149/** Pointer to a DWARF section reader. */
    114 typedef RTDWARFSECTRDR *PRTDWARFSECTRDR;
    115 
     150typedef RTDWARFCURSOR *PRTDWARFCURSOR;
     151
     152
     153#define VERR_DWARF_BAD_LINE_NUMBER_HEADER   -55555
     154#define VERR_DWARF_UNEXPECTED_END           -55554
     155#define VERR_DWARF_LEB_OVERFLOW             -55553
     156#define VERR_DWARF_BAD_LNE                  -55552
    116157
    117158
     
    176217
    177218/**
    178  * Corrects the endianness of a 32-bit unsigned value.
    179  *
    180  * @returns The corrected value.
    181  *
    182  * @param   pThis       The DWARF instance.
    183  * @param   pu32        The variable to correct.
    184  */
    185 DECLINLINE(uint32_t) rtDbgModDwarfEndianU32(PRTDBGMODDWARF pThis, uint32_t *pu32)
    186 {
    187     return *pu32;
    188 }
    189 
    190 
    191 /**
    192  * Corrects the endianness of a 64-bit unsigned value.
    193  *
    194  * @returns The corrected value.
    195  *
    196  * @param   pThis       The DWARF instance.
    197  * @param   pu64        The variable to correct.
    198  */
    199 DECLINLINE(uint64_t) rtDbgModDwarfEndianU64(PRTDBGMODDWARF pThis, uint64_t *pu64)
    200 {
    201     return *pu64;
    202 }
    203 
    204 
    205 static uint8_t rtDwarfSectRdrGetU8(PRTDWARFSECTRDR pSectRdr, uint8_t uErrValue)
    206 {
    207     if (pSectRdr->cbLeft < 1)
    208     {
    209         pSectRdr->pb    += pSectRdr->cbLeft;
    210         pSectRdr->cbLeft = 0;
     219 * Converts to UTF-8 or otherwise makes sure it's valid UTF-8.
     220 *
     221 * @returns IPRT status code.
     222 * @param   pThis               The DWARF instance.
     223 * @param   ppsz                Pointer to the string pointer.  May be
     224 *                              reallocated (RTStr*).
     225 */
     226static int rtDbgModDwarfStringToUtf8(PRTDBGMODDWARF pThis, char **ppsz)
     227{
     228    RTStrPurgeEncoding(*ppsz);
     229    return VINF_SUCCESS;
     230}
     231
     232
     233/**
     234 * Convers a link address into a segment+offset or RVA.
     235 *
     236 * @returns IPRT status code.
     237 * @param   pThis           The DWARF instance.
     238 * @param   LinkAddress     The address to convert..
     239 * @param   piSeg           The segment index.
     240 * @param   poffSeg         Where to return the segment offset.
     241 */
     242static int rtDbgModDwarfLinkAddressToSegOffset(PRTDBGMODDWARF pThis, uint64_t LinkAddress,
     243                                               PRTDBGSEGIDX piSeg, PRTUINTPTR poffSeg)
     244{
     245    /** @todo The image should be doing this conversion, not we. */
     246    *piSeg   = RTDBGSEGIDX_RVA;
     247    *poffSeg = LinkAddress;
     248    return VINF_SUCCESS;
     249}
     250
     251
     252static uint8_t rtDwarfCursor_GetU8(PRTDWARFCURSOR pCursor, uint8_t uErrValue)
     253{
     254    if (pCursor->cbUnitLeft < 1)
     255    {
     256        pCursor->rc = VERR_DWARF_UNEXPECTED_END;
    211257        return uErrValue;
    212258    }
    213259
    214     uint8_t u8 = pSectRdr->pb[0];
    215     pSectRdr->pb      += 1;
    216     pSectRdr->cbLeft  -= 1;
     260    uint8_t u8 = pCursor->pb[0];
     261    pCursor->pb         += 1;
     262    pCursor->cbUnitLeft -= 1;
     263    pCursor->cbLeft     -= 1;
    217264    return u8;
    218265}
    219266
    220267
    221 static uint16_t rtDwarfSectRdrGetU16(PRTDWARFSECTRDR pSectRdr, uint16_t uErrValue)
    222 {
    223     if (pSectRdr->cbLeft < 2)
    224     {
    225         pSectRdr->pb    += pSectRdr->cbLeft;
    226         pSectRdr->cbLeft = 0;
     268static uint16_t rtDwarfCursor_GetU16(PRTDWARFCURSOR pCursor, uint16_t uErrValue)
     269{
     270    if (pCursor->cbUnitLeft < 2)
     271    {
     272        pCursor->pb         += pCursor->cbUnitLeft;
     273        pCursor->cbLeft     -= pCursor->cbUnitLeft;
     274        pCursor->cbUnitLeft  = 0;
     275        pCursor->rc          = VERR_DWARF_UNEXPECTED_END;
    227276        return uErrValue;
    228277    }
    229278
    230     uint16_t u16 = RT_MAKE_U16(pSectRdr->pb[0], pSectRdr->pb[1]);
    231     pSectRdr->pb      += 2;
    232     pSectRdr->cbLeft  -= 2;
    233     if (!pSectRdr->fNativEndian)
     279    uint16_t u16 = RT_MAKE_U16(pCursor->pb[0], pCursor->pb[1]);
     280    pCursor->pb         += 2;
     281    pCursor->cbUnitLeft -= 2;
     282    pCursor->cbLeft     -= 2;
     283    if (!pCursor->fNativEndian)
    234284        u16 = RT_BSWAP_U16(u16);
    235285    return u16;
     
    237287
    238288
    239 static uint32_t rtDwarfSectRdrGetU32(PRTDWARFSECTRDR pSectRdr, uint32_t uErrValue)
    240 {
    241     if (pSectRdr->cbLeft < 4)
    242     {
    243         pSectRdr->pb    += pSectRdr->cbLeft;
    244         pSectRdr->cbLeft = 0;
     289static uint32_t rtDwarfCursor_GetU32(PRTDWARFCURSOR pCursor, uint32_t uErrValue)
     290{
     291    if (pCursor->cbUnitLeft < 4)
     292    {
     293        pCursor->pb         += pCursor->cbUnitLeft;
     294        pCursor->cbLeft     -= pCursor->cbUnitLeft;
     295        pCursor->cbUnitLeft  = 0;
     296        pCursor->rc          = VERR_DWARF_UNEXPECTED_END;
    245297        return uErrValue;
    246298    }
    247299
    248     uint32_t u32 = RT_MAKE_U32_FROM_U8(pSectRdr->pb[0], pSectRdr->pb[1], pSectRdr->pb[2], pSectRdr->pb[3]);
    249     pSectRdr->pb      += 4;
    250     pSectRdr->cbLeft  -= 4;
    251     if (!pSectRdr->fNativEndian)
     300    uint32_t u32 = RT_MAKE_U32_FROM_U8(pCursor->pb[0], pCursor->pb[1], pCursor->pb[2], pCursor->pb[3]);
     301    pCursor->pb         += 4;
     302    pCursor->cbUnitLeft -= 4;
     303    pCursor->cbLeft     -= 4;
     304    if (!pCursor->fNativEndian)
    252305        u32 = RT_BSWAP_U32(u32);
    253306    return u32;
     
    255308
    256309
    257 static uint64_t rtDwarfSectRdrGetU64(PRTDWARFSECTRDR pSectRdr, uint64_t uErrValue)
    258 {
    259     if (pSectRdr->cbLeft < 8)
    260     {
    261         pSectRdr->pb    += pSectRdr->cbLeft;
    262         pSectRdr->cbLeft = uErrValue;
    263         return 0;
    264     }
    265 
    266     uint64_t u64 = RT_MAKE_U64_FROM_U8(pSectRdr->pb[0], pSectRdr->pb[1], pSectRdr->pb[2], pSectRdr->pb[3],
    267                                        pSectRdr->pb[4], pSectRdr->pb[5], pSectRdr->pb[6], pSectRdr->pb[7]);
    268     pSectRdr->pb      += 8;
    269     pSectRdr->cbLeft  -= 8;
    270     if (!pSectRdr->fNativEndian)
     310static uint64_t rtDwarfCursor_GetU64(PRTDWARFCURSOR pCursor, uint64_t uErrValue)
     311{
     312    if (pCursor->cbUnitLeft < 8)
     313    {
     314        pCursor->pb         += pCursor->cbUnitLeft;
     315        pCursor->cbLeft     -= pCursor->cbUnitLeft;
     316        pCursor->cbUnitLeft  = 0;
     317        pCursor->rc          = VERR_DWARF_UNEXPECTED_END;
     318        return uErrValue;
     319    }
     320
     321    uint64_t u64 = RT_MAKE_U64_FROM_U8(pCursor->pb[0], pCursor->pb[1], pCursor->pb[2], pCursor->pb[3],
     322                                       pCursor->pb[4], pCursor->pb[5], pCursor->pb[6], pCursor->pb[7]);
     323    pCursor->pb         += 8;
     324    pCursor->cbUnitLeft -= 8;
     325    pCursor->cbLeft     -= 8;
     326    if (!pCursor->fNativEndian)
    271327        u64 = RT_BSWAP_U64(u64);
    272328    return u64;
     
    274330
    275331
    276 static uint16_t rtDwarfSectRdrGetUHalf(PRTDWARFSECTRDR pSectRdr, uint16_t uErrValue)
    277 {
    278     return rtDwarfSectRdrGetU16(pSectRdr, uErrValue);
    279 }
    280 
    281 
    282 static uint8_t rtDwarfSectRdrGetUByte(PRTDWARFSECTRDR pSectRdr, uint8_t uErrValue)
    283 {
    284     return rtDwarfSectRdrGetU8(pSectRdr, uErrValue);
    285 }
    286 
    287 
    288 static int8_t rtDwarfSectRdrGetSByte(PRTDWARFSECTRDR pSectRdr, int8_t iErrValue)
    289 {
    290     return (int8_t)rtDwarfSectRdrGetU8(pSectRdr, (uint8_t)iErrValue);
    291 }
    292 
    293 
    294 static uint64_t rtDwarfSectRdrGetUOff(PRTDWARFSECTRDR pSectRdr, uint64_t uErrValue)
    295 {
    296     if (pSectRdr->f64bit)
    297         return rtDwarfSectRdrGetU64(pSectRdr, uErrValue);
    298     return rtDwarfSectRdrGetU32(pSectRdr, (uint32_t)uErrValue);
     332/**
     333 * Gets a unsigned LEB128 encoded number.
     334 *
     335 * @returns unsigned number.
     336 * @param   pCursor             The cursor.
     337 * @param   uErrValue           The value to return on error.
     338 */
     339static uint64_t rtDwarfCursor_GetULeb128(PRTDWARFCURSOR pCursor, uint64_t uErrValue)
     340{
     341    if (pCursor->cbUnitLeft < 1)
     342    {
     343        pCursor->rc = VERR_DWARF_UNEXPECTED_END;
     344        return uErrValue;
     345    }
     346
     347    /*
     348     * Special case - single byte.
     349     */
     350    uint8_t b = pCursor->pb[0];
     351    if (!(b & 0x80))
     352    {
     353        pCursor->pb         += 1;
     354        pCursor->cbUnitLeft -= 1;
     355        pCursor->cbLeft     -= 1;
     356        return b;
     357    }
     358
     359    /*
     360     * Generic case.
     361     */
     362    /* Decode. */
     363    uint32_t off    = 1;
     364    uint64_t u64Ret = b & 0x7f;
     365    do
     366    {
     367        if (off == pCursor->cbUnitLeft)
     368        {
     369            pCursor->rc = VERR_DWARF_UNEXPECTED_END;
     370            u64Ret = uErrValue;
     371            break;
     372        }
     373        b = pCursor->pb[off];
     374        u64Ret |= (b & 0x7f) << off * 7;
     375        off++;
     376    } while (b & 0x80);
     377
     378    /* Update the cursor. */
     379    pCursor->pb         += off;
     380    pCursor->cbUnitLeft -= off;
     381    pCursor->cbLeft     -= off;
     382
     383    /* Check the range. */
     384    uint32_t cBits = off * 7;
     385    if (cBits > 64)
     386    {
     387        pCursor->rc = VERR_DWARF_LEB_OVERFLOW;
     388        u64Ret = uErrValue;
     389    }
     390
     391    return u64Ret;
     392}
     393
     394
     395/**
     396 * Gets a signed LEB128 encoded number.
     397 *
     398 * @returns signed number.
     399 * @param   pCursor             The cursor.
     400 * @param   sErrValue           The value to return on error.
     401 */
     402static int64_t rtDwarfCursor_GetSLeb128(PRTDWARFCURSOR pCursor, int64_t sErrValue)
     403{
     404    if (pCursor->cbUnitLeft < 1)
     405    {
     406        pCursor->rc = VERR_DWARF_UNEXPECTED_END;
     407        return sErrValue;
     408    }
     409
     410    /*
     411     * Special case - single byte.
     412     */
     413    uint8_t b = pCursor->pb[0];
     414    if (!(b & 0x80))
     415    {
     416        pCursor->pb         += 1;
     417        pCursor->cbUnitLeft -= 1;
     418        pCursor->cbLeft     -= 1;
     419        if (b & 0x40)
     420            b |= 0x80;
     421        return (int8_t)b;
     422    }
     423
     424    /*
     425     * Generic case.
     426     */
     427    /* Decode it. */
     428    uint32_t off    = 1;
     429    uint64_t u64Ret = b & 0x7f;
     430    do
     431    {
     432        if (off == pCursor->cbUnitLeft)
     433        {
     434            pCursor->rc = VERR_DWARF_UNEXPECTED_END;
     435            u64Ret = (uint64_t)sErrValue;
     436            break;
     437        }
     438        b = pCursor->pb[off];
     439        u64Ret |= (b & 0x7f) << off * 7;
     440        off++;
     441    } while (b & 0x80);
     442
     443    /* Update cursor. */
     444    pCursor->pb         += off;
     445    pCursor->cbUnitLeft -= off;
     446    pCursor->cbLeft     -= off;
     447
     448    /* Check the range. */
     449    uint32_t cBits = off * 7;
     450    if (cBits > 64)
     451    {
     452        pCursor->rc = VERR_DWARF_LEB_OVERFLOW;
     453        u64Ret = (uint64_t)sErrValue;
     454    }
     455    /* Sign extend the value. */
     456    else if (u64Ret & RT_BIT_64(cBits - 1))
     457        u64Ret |= ~RT_BIT_64(cBits - 1);
     458
     459    return (int64_t)u64Ret;
     460}
     461
     462
     463/**
     464 * Gets a unsigned LEB128 encoded number, max 32-bit width.
     465 *
     466 * @returns unsigned number.
     467 * @param   pCursor             The cursor.
     468 * @param   uErrValue           The value to return on error.
     469 */
     470static uint32_t rtDwarfCursor_GetULeb128AsU32(PRTDWARFCURSOR pCursor, uint32_t uErrValue)
     471{
     472    uint64_t u64 = rtDwarfCursor_GetULeb128(pCursor, uErrValue);
     473    if (u64 > UINT32_MAX)
     474    {
     475        pCursor->rc = VERR_DWARF_LEB_OVERFLOW;
     476        return uErrValue;
     477    }
     478    return (uint32_t)u64;
     479}
     480
     481
     482/**
     483 * Gets a signed LEB128 encoded number, max 32-bit width.
     484 *
     485 * @returns unsigned number.
     486 * @param   pCursor             The cursor.
     487 * @param   sErrValue           The value to return on error.
     488 */
     489static int32_t rtDwarfCursor_GetSLeb128AsS32(PRTDWARFCURSOR pCursor, int32_t sErrValue)
     490{
     491    int64_t s64 = rtDwarfCursor_GetSLeb128(pCursor, sErrValue);
     492    if (s64 > INT32_MAX || s64 < INT32_MIN)
     493    {
     494        pCursor->rc = VERR_DWARF_LEB_OVERFLOW;
     495        return sErrValue;
     496    }
     497    return (int32_t)s64;
     498}
     499
     500
     501static int rtDwarfCursor_SkipLeb128(PRTDWARFCURSOR pCursor)
     502{
     503    if (pCursor->cbUnitLeft < 1)
     504        return pCursor->rc = VERR_DWARF_UNEXPECTED_END;
     505
     506    uint32_t offSkip = 1;
     507    if (pCursor->pb[0] & 0x80)
     508        do
     509        {
     510            if (offSkip == pCursor->cbUnitLeft)
     511            {
     512                pCursor->rc = VERR_DWARF_UNEXPECTED_END;
     513                break;
     514            }
     515        } while (pCursor->pb[offSkip++] & 0x80);
     516
     517    pCursor->pb         += offSkip;
     518    pCursor->cbUnitLeft -= offSkip;
     519    pCursor->cbLeft     -= offSkip;
     520    return pCursor->rc;
     521}
     522
     523
     524
     525/**
     526 * Reads a zero terminated string, advancing the cursor beyond the terminator.
     527 *
     528 * @returns Pointer to the string.
     529 * @param   pCursor             The cursor.
     530 * @param   pszErrValue         What to return if the string isn't terminated
     531 *                              before the end of the unit.
     532 */
     533static const char *rtDwarfCursor_GetSZ(PRTDWARFCURSOR pCursor, const char *pszErrValue)
     534{
     535    const char *pszRet = (const char *)pCursor->pb;
     536    for (;;)
     537    {
     538        if (!pCursor->cbUnitLeft)
     539            return pszErrValue;
     540        pCursor->cbUnitLeft--;
     541        pCursor->cbLeft--;
     542        if (!*pCursor->pb++)
     543            break;
     544    }
     545    return pszRet;
     546}
     547
     548
     549
     550static uint16_t rtDwarfCursor_GetUHalf(PRTDWARFCURSOR pCursor, uint16_t uErrValue)
     551{
     552    return rtDwarfCursor_GetU16(pCursor, uErrValue);
     553}
     554
     555
     556static uint8_t rtDwarfCursor_GetUByte(PRTDWARFCURSOR pCursor, uint8_t uErrValue)
     557{
     558    return rtDwarfCursor_GetU8(pCursor, uErrValue);
     559}
     560
     561
     562static int8_t rtDwarfCursor_GetSByte(PRTDWARFCURSOR pCursor, int8_t iErrValue)
     563{
     564    return (int8_t)rtDwarfCursor_GetU8(pCursor, (uint8_t)iErrValue);
     565}
     566
     567
     568static uint64_t rtDwarfCursor_GetUOff(PRTDWARFCURSOR pCursor, uint64_t uErrValue)
     569{
     570    if (pCursor->f64bitDwarf)
     571        return rtDwarfCursor_GetU64(pCursor, uErrValue);
     572    return rtDwarfCursor_GetU32(pCursor, (uint32_t)uErrValue);
     573}
     574
     575
     576/**
     577 * Gets the unit length, updating the unit length member and DWARF bitness
     578 * members of the cursor.
     579 *
     580 * @returns The unit length.
     581 * @param   pCursor             The cursor.
     582 */
     583static uint64_t rtDwarfCursor_GetInitalLength(PRTDWARFCURSOR pCursor)
     584{
     585    /*
     586     * Read the initial length.
     587     */
     588    pCursor->cbUnitLeft = pCursor->cbLeft;
     589    uint64_t cbUnit = rtDwarfCursor_GetU32(pCursor, 0);
     590    if (cbUnit != UINT32_C(0xffffffff))
     591        pCursor->f64bitDwarf = false;
     592    else
     593    {
     594        pCursor->f64bitDwarf = true;
     595        cbUnit = rtDwarfCursor_GetU64(pCursor, 0);
     596    }
     597
     598
     599    /*
     600     * Set the unit length, quitely fixing bad lengths.
     601     */
     602    pCursor->cbUnitLeft = (size_t)cbUnit;
     603    if (   pCursor->cbUnitLeft > pCursor->cbLeft
     604        || pCursor->cbUnitLeft != cbUnit)
     605        pCursor->cbUnitLeft = pCursor->cbLeft;
     606
     607    return cbUnit;
     608}
     609
     610
     611static bool rtDwarfCursor_IsAtEndOfUnit(PRTDWARFCURSOR pCursor)
     612{
     613    return pCursor->cbUnitLeft > 0;
     614}
     615
     616
     617static int rtDwarfCursor_SkipUnit(PRTDWARFCURSOR pCursor)
     618{
     619    pCursor->pb        += pCursor->cbUnitLeft;
     620    pCursor->cbLeft    -= pCursor->cbUnitLeft;
     621    pCursor->cbUnitLeft = 0;
     622    return VINF_SUCCESS;
     623}
     624
     625
     626static bool rtDwarfCursor_IsAtEnd(PRTDWARFCURSOR pCursor)
     627{
     628    return pCursor->cbLeft > 0;
    299629}
    300630
     
    304634 *
    305635 * @returns IPRT status code.
    306  * @param   pSectRdr            The section reader.
     636 * @param   pCursor            The section reader.
    307637 * @param   pThis               The dwarf module.
    308638 * @param   enmSect             .
    309639 */
    310 static int rtDwarfSectRdrInit(PRTDWARFSECTRDR pSectRdr, PRTDBGMODDWARF pThis, krtDbgModDwarfSect enmSect)
     640static int rtDwarfCursor_Init(PRTDWARFCURSOR pCursor, PRTDBGMODDWARF pThis, krtDbgModDwarfSect enmSect)
    311641{
    312642    int rc = rtDbgModDwarfLoadSection(pThis, enmSect);
     
    314644        return rc;
    315645
    316     pSectRdr->pDwarfMod    = pThis;
    317     pSectRdr->enmSect      = enmSect;
    318     pSectRdr->pb           = (uint8_t const *)pThis->aSections[krtDbgModDwarfSect_line].pv;
    319     pSectRdr->cbLeft       = pThis->aSections[krtDbgModDwarfSect_line].cb;
    320     pSectRdr->fNativEndian = true; /** @todo endian */
    321     pSectRdr->f64bit       = false;
    322 
    323     /*
    324      * Read the initial length.
    325      */
    326     uint64_t cbUnit = rtDwarfSectRdrGetU32(pSectRdr, 0);
    327     if (cbUnit == UINT32_C(0xffffffff))
    328     {
    329         pSectRdr->f64bit = true;
    330         cbUnit = rtDwarfSectRdrGetU64(pSectRdr, 0);
    331     }
    332     if (cbUnit < pSectRdr->cbLeft)
    333         pSectRdr->cbLeft = (size_t)cbUnit;
     646    pCursor->pb           = (uint8_t const *)pThis->aSections[enmSect].pv;
     647    pCursor->cbLeft       = pThis->aSections[enmSect].cb;
     648    pCursor->cbUnitLeft   = pCursor->cbLeft;
     649    pCursor->pDwarfMod    = pThis;
     650    pCursor->fNativEndian = true; /** @todo endian */
     651    pCursor->f64bitDwarf  = false;
     652    pCursor->cbNativeAddr = 4;
     653    pCursor->rc           = VINF_SUCCESS;
     654
     655    /** @todo ask the image about the endian used as well as the address
     656     *        width. */
    334657
    335658    return VINF_SUCCESS;
     
    338661
    339662/**
    340  * Deletes a section reader initialized by rtDwarfSectRdrInit.
    341  *
    342  * @param   pSectRdr            The section reader.
    343  */
    344 static void rtDwarfSectRdrDelete(PRTDWARFSECTRDR pSectRdr)
    345 {
    346     rtDbgModDwarfUnloadSection(pSectRdr->pDwarfMod, pSectRdr->enmSect);
    347 
     663 * Deletes a section reader initialized by rtDwarfCursor_Init.
     664 *
     665 * @param   pCursor            The section reader.
     666 */
     667static void rtDwarfCursor_Delete(PRTDWARFCURSOR pCursor)
     668{
    348669    /* ... and a drop of poison. */
    349     pSectRdr->pb = NULL;
    350     pSectRdr->cbLeft = ~(size_t)0;
    351     pSectRdr->enmSect = krtDbgModDwarfSect_End;
     670    pCursor->pb         = NULL;
     671    pCursor->cbLeft     = ~(size_t)0;
     672    pCursor->cbUnitLeft = ~(size_t)0;
     673    pCursor->pDwarfMod  = NULL;
     674    pCursor->rc         = VERR_INTERNAL_ERROR_4;
    352675}
    353676
     
    492815
    493816/**
     817 * DWARF line number program state.
     818 */
     819typedef struct RTDWARFLINESTATE
     820{
     821    /** Registers */
     822    struct
     823    {
     824        uint64_t        uAddress;
     825        uint32_t        idxOp;
     826        uint32_t        iFile;
     827        uint32_t        uLine;
     828        uint32_t        uColumn;
     829        bool            fIsStatement;
     830        bool            fBasicBlock;
     831        bool            fEndSequence;
     832        bool            fPrologueEnd;
     833        bool            fEpilogueBegin;
     834        uint32_t        uIsa;
     835        uint32_t        uDiscriminator;
     836    } Regs;
     837    /** @} */
     838
     839    /** @name Header
     840     * @{ */
     841    uint32_t        uVer;
     842    uint64_t        cbSkipAfterHdr;
     843    uint8_t         cbMinInstr;
     844    uint8_t         cMaxOpsPerInstr;
     845    uint8_t         u8DefIsStmt;
     846    int8_t          s8LineBase;
     847    uint8_t         u8LineRange;
     848    uint8_t         u8OpcodeBase;
     849    uint8_t const  *pacStdOperands;
     850    /** @} */
     851
     852    /** @name Include Path Table (0-based)
     853     * @{ */
     854    const char    **papszIncPaths;
     855    uint32_t        cIncPaths;
     856    /** @} */
     857
     858    /** @name File Name Table (1-based)
     859     * @{ */
     860    char          **papszFileNames;
     861    uint32_t        cFileNames;
     862    /** @} */
     863
     864    /** The DWARF debug info reader instance. */
     865    PRTDBGMODDWARF  pDwarfMod;
     866} RTDWARFLINESTATE;
     867/** Pointer to a DWARF line number program state. */
     868typedef RTDWARFLINESTATE *PRTDWARFLINESTATE;
     869
     870
     871static int rtDwarfLine_DefineFileName(PRTDWARFLINESTATE pLnState, const char *pszFilename, uint64_t idxInc)
     872{
     873    /*
     874     * Resize the array if necessary.
     875     */
     876    size_t iFileName = pLnState->cFileNames;
     877    if ((iFileName % 2) == 0)
     878    {
     879        void *pv = RTMemRealloc(pLnState->papszFileNames, sizeof(pLnState->papszFileNames[0]) * (iFileName + 2));
     880        if (!pv)
     881            return VERR_NO_MEMORY;
     882        pLnState->papszFileNames = (char **)pv;
     883    }
     884
     885    /*
     886     * Add the file name.
     887     */
     888    if (   pszFilename[0] == '/'
     889        || pszFilename[0] == '\\'
     890        || (RT_C_IS_ALPHA(pszFilename[0]) && pszFilename[1] == ':') )
     891        pLnState->papszFileNames[iFileName] = RTStrDup(pszFilename);
     892    else if (idxInc < pLnState->cIncPaths)
     893        pLnState->papszFileNames[iFileName] = RTPathJoinA(pLnState->papszIncPaths[idxInc], pszFilename);
     894    else
     895        return VERR_DWARF_BAD_LINE_NUMBER_HEADER;
     896    if (!pLnState->papszFileNames[iFileName])
     897        return VERR_NO_STR_MEMORY;
     898    pLnState->cFileNames = iFileName + 1;
     899
     900    /*
     901     * Sanitize the name.
     902     */
     903    return rtDbgModDwarfStringToUtf8(pLnState->pDwarfMod, &pLnState->papszFileNames[iFileName]);
     904}
     905
     906
     907static int rtDwarfLine_StdOp_Copy(PRTDWARFLINESTATE pLnState)
     908{
     909    const char *pszFile = pLnState->Regs.iFile < pLnState->cFileNames
     910                        ? pLnState->papszFileNames[pLnState->Regs.iFile]
     911                        : "<bad file name index>";
     912    RTDBGSEGIDX iSeg;
     913    RTUINTPTR   offSeg;
     914    int rc = rtDbgModDwarfLinkAddressToSegOffset(pLnState->pDwarfMod, pLnState->Regs.uAddress, &iSeg, &offSeg);
     915    if (RT_SUCCESS(rc))
     916        rc = RTDbgModLineAdd(pLnState->pDwarfMod->hCnt, pszFile, pLnState->Regs.uLine, iSeg, offSeg, NULL);
     917
     918    pLnState->Regs.fBasicBlock    = false;
     919    pLnState->Regs.fPrologueEnd   = false;
     920    pLnState->Regs.fEpilogueBegin = false;
     921    pLnState->Regs.uDiscriminator = 0;
     922    return rc;
     923}
     924
     925
     926/**
     927 * Reset the program to the start-of-sequence state.
     928 *
     929 * @param   pLnState            The line number program state.
     930 */
     931static void rtDwarfLine_ResetState(PRTDWARFLINESTATE pLnState)
     932{
     933    pLnState->Regs.uAddress         = 0;
     934    pLnState->Regs.idxOp            = 0;
     935    pLnState->Regs.iFile            = 1;
     936    pLnState->Regs.uLine            = 1;
     937    pLnState->Regs.uColumn          = 0;
     938    pLnState->Regs.fIsStatement     = RT_BOOL(pLnState->u8DefIsStmt);
     939    pLnState->Regs.fBasicBlock      = false;
     940    pLnState->Regs.fEndSequence     = false;
     941    pLnState->Regs.fPrologueEnd     = false;
     942    pLnState->Regs.fEpilogueBegin   = false;
     943    pLnState->Regs.uIsa             = 0;
     944    pLnState->Regs.uDiscriminator   = 0;
     945}
     946
     947
     948/**
     949 * Runs the line number program.
     950 *
     951 * @returns IPRT status code.
     952 * @param   pLnState            The line number program state.
     953 * @param   pCursor             The cursor.
     954 */
     955static int rtDwarfLine_RunProgram(PRTDWARFLINESTATE pLnState, PRTDWARFCURSOR pCursor)
     956{
     957    int rc = VINF_SUCCESS;
     958    rtDwarfLine_ResetState(pLnState);
     959    do
     960    {
     961        uint8_t bOpCode = rtDwarfCursor_GetUByte(pCursor, 0);
     962        if (bOpCode > pLnState->u8OpcodeBase)
     963        {
     964            /*
     965             * Special opcode.
     966             */
     967            bOpCode -= pLnState->u8OpcodeBase;
     968            pLnState->Regs.uLine    += bOpCode % pLnState->u8LineRange + (int32_t)pLnState->s8LineBase;
     969            bOpCode /= pLnState->u8LineRange;
     970            pLnState->Regs.uAddress += (pLnState->Regs.idxOp + bOpCode) / pLnState->cMaxOpsPerInstr
     971                                     * pLnState->cbMinInstr;
     972            pLnState->Regs.idxOp    += (pLnState->Regs.idxOp + bOpCode) % pLnState->cMaxOpsPerInstr;
     973
     974            rc = rtDwarfLine_StdOp_Copy(pLnState);
     975        }
     976        else
     977        {
     978            switch (bOpCode)
     979            {
     980                /*
     981                 * Standard opcode.
     982                 */
     983                case DW_LNS_copy:
     984                    rtDwarfLine_StdOp_Copy(pLnState);
     985                    break;
     986
     987                case DW_LNS_advance_pc:
     988                {
     989                    uint64_t u64Adv = rtDwarfCursor_GetULeb128(pCursor, 0);
     990                    pLnState->Regs.uAddress += (pLnState->Regs.idxOp + u64Adv) / pLnState->cMaxOpsPerInstr
     991                                             * pLnState->cbMinInstr;
     992                    pLnState->Regs.idxOp    += (pLnState->Regs.idxOp + u64Adv) % pLnState->cMaxOpsPerInstr;
     993                    break;
     994                }
     995
     996                case DW_LNS_advance_line:
     997                    pLnState->Regs.uLine += rtDwarfCursor_GetSLeb128AsS32(pCursor, 0);
     998                    break;
     999
     1000                case DW_LNS_set_file:
     1001                    pLnState->Regs.iFile = rtDwarfCursor_GetULeb128AsU32(pCursor, 0);
     1002                    break;
     1003
     1004                case DW_LNS_set_column:
     1005                    pLnState->Regs.uColumn = rtDwarfCursor_GetULeb128AsU32(pCursor, 0);
     1006                    break;
     1007
     1008                case DW_LNS_negate_stmt:
     1009                    pLnState->Regs.fIsStatement = !pLnState->Regs.fIsStatement;
     1010                    break;
     1011
     1012                case DW_LNS_set_basic_block:
     1013                    pLnState->Regs.fBasicBlock = true;
     1014                    break;
     1015
     1016                case DW_LNS_const_add_pc:
     1017                    pLnState->Regs.uAddress += (pLnState->Regs.idxOp + 255) / pLnState->cMaxOpsPerInstr
     1018                                             * pLnState->cbMinInstr;
     1019                    pLnState->Regs.idxOp    += (pLnState->Regs.idxOp + 255) % pLnState->cMaxOpsPerInstr;
     1020                    break;
     1021
     1022                case DW_LNS_fixed_advance_pc:
     1023                    pLnState->Regs.uAddress += rtDwarfCursor_GetUHalf(pCursor, 0);
     1024                    pLnState->Regs.idxOp     = 0;
     1025                    break;
     1026
     1027                case DW_LNS_set_prologue_end:
     1028                    pLnState->Regs.fPrologueEnd = true;
     1029                    break;
     1030
     1031                case DW_LNS_set_epilogue_begin:
     1032                    pLnState->Regs.fEpilogueBegin = true;
     1033                    break;
     1034
     1035                case DW_LNS_set_isa:
     1036                    pLnState->Regs.uIsa = rtDwarfCursor_GetULeb128AsU32(pCursor, 0);
     1037                    break;
     1038
     1039                default:
     1040                {
     1041                    unsigned cOpsToSkip = pLnState->pacStdOperands[bOpCode - 1];
     1042                    while (cOpsToSkip-- > 0)
     1043                        rc = rtDwarfCursor_SkipLeb128(pCursor);
     1044                    break;
     1045                }
     1046
     1047                /*
     1048                 * Extended opcode.
     1049                 */
     1050                case DW_LNS_extended:
     1051                {
     1052                    uint64_t cbInstr = rtDwarfCursor_GetULeb128(pCursor, UINT64_MAX);
     1053                    if (cbInstr > pCursor->cbUnitLeft)
     1054                        return VERR_DWARF_BAD_LNE;
     1055                    /** @todo continue here. */
     1056                    bOpCode = rtDwarfCursor_GetUByte(pCursor, 0);
     1057                    switch (bOpCode)
     1058                    {
     1059                        case DW_LNE_end_sequence:
     1060                        case DW_LNE_set_address:
     1061                        case DW_LNE_define_file:
     1062                        case DW_LNE_set_descriminator:
     1063                            break;
     1064                    }
     1065                    break;
     1066                }
     1067            }
     1068        }
     1069    } while (RT_SUCCESS(rc));
     1070    return rc;
     1071}
     1072
     1073
     1074/**
     1075 * Reads the include directories for a line number unit.
     1076 *
     1077 * @returns IPRT status code
     1078 * @param   pLnState            The line number program state.
     1079 * @param   pCursor             The cursor.
     1080 */
     1081static int rtDwarfLine_ReadFileNames(PRTDWARFLINESTATE pLnState, PRTDWARFCURSOR pCursor)
     1082{
     1083    for (;;)
     1084    {
     1085        const char *psz = rtDwarfCursor_GetSZ(pCursor, NULL);
     1086        if (!*psz)
     1087            break;
     1088
     1089        uint64_t idxInc = rtDwarfCursor_GetULeb128(pCursor, UINT64_MAX);
     1090        rtDwarfCursor_SkipLeb128(pCursor); /* st_mtime */
     1091        rtDwarfCursor_SkipLeb128(pCursor); /* st_size */
     1092
     1093        int rc = rtDwarfLine_DefineFileName(pLnState, psz, idxInc);
     1094        if (RT_FAILURE(rc))
     1095            return rc;
     1096    }
     1097    return VINF_SUCCESS;
     1098}
     1099
     1100
     1101/**
     1102 * Reads the include directories for a line number unit.
     1103 *
     1104 * @returns IPRT status code
     1105 * @param   pLnState            The line number program state.
     1106 * @param   pCursor             The cursor.
     1107 */
     1108static int rtDwarfLine_ReadIncludePaths(PRTDWARFLINESTATE pLnState, PRTDWARFCURSOR pCursor)
     1109{
     1110    const char *psz = "";   /* The zeroth is the unit dir. */
     1111    for (;;)
     1112    {
     1113        if ((pLnState->cIncPaths % 2) == 0)
     1114        {
     1115            void *pv = RTMemRealloc(pLnState->papszIncPaths, sizeof(pLnState->papszIncPaths[0]) * (pLnState->cIncPaths + 2));
     1116            if (!pv)
     1117                return VERR_NO_MEMORY;
     1118            pLnState->papszIncPaths = (const char **)pv;
     1119        }
     1120        pLnState->papszIncPaths[pLnState->cIncPaths] = psz;
     1121        pLnState->cIncPaths++;
     1122
     1123        psz = rtDwarfCursor_GetSZ(pCursor, NULL);
     1124        if (!*psz)
     1125            break;
     1126    }
     1127
     1128    return VINF_SUCCESS;
     1129}
     1130
     1131
     1132static int rtDbgModDwarfExplodeLineNumbersForUnit(PRTDBGMODDWARF pThis, PRTDWARFCURSOR pCursor)
     1133{
     1134    RTDWARFLINESTATE LnState;
     1135    RT_ZERO(LnState);
     1136    LnState.pDwarfMod = pThis;
     1137
     1138    /*
     1139     * Parse the header.
     1140     */
     1141    LnState.uVer           = rtDwarfCursor_GetUHalf(pCursor, 0);
     1142    if (LnState.uVer >= 2 && LnState.uVer <= 4)
     1143        return rtDwarfCursor_SkipUnit(pCursor);
     1144    LnState.cbSkipAfterHdr = rtDwarfCursor_GetUOff(pCursor, 0);
     1145    LnState.cbMinInstr     = rtDwarfCursor_GetUByte(pCursor, 0);
     1146    LnState.cMaxOpsPerInstr= rtDwarfCursor_GetUByte(pCursor, 0);
     1147    LnState.u8DefIsStmt    = rtDwarfCursor_GetUByte(pCursor, 0);
     1148    LnState.s8LineBase     = rtDwarfCursor_GetSByte(pCursor, 0);
     1149    LnState.u8LineRange    = rtDwarfCursor_GetUByte(pCursor, 0);
     1150    LnState.u8OpcodeBase   = rtDwarfCursor_GetUByte(pCursor, 0);
     1151    if (!LnState.u8OpcodeBase)
     1152        return VERR_DWARF_BAD_LINE_NUMBER_HEADER;
     1153
     1154    LnState.pacStdOperands = pCursor->pb;
     1155    for (uint8_t iStdOpcode = 1; iStdOpcode < LnState.u8OpcodeBase; iStdOpcode++)
     1156        rtDwarfCursor_GetUByte(pCursor, 0);
     1157
     1158    int rc = rtDwarfLine_ReadIncludePaths(&LnState, pCursor);
     1159    if (RT_SUCCESS(rc))
     1160        rc = rtDwarfLine_ReadFileNames(&LnState, pCursor);
     1161
     1162    /*
     1163     * Run the program....
     1164     */
     1165    if (RT_SUCCESS(rc))
     1166        rc = rtDwarfLine_RunProgram(&LnState, pCursor);
     1167
     1168    /*
     1169     * Clean up.
     1170     */
     1171    size_t i = LnState.cFileNames;
     1172    while (i-- > 0)
     1173        RTStrFree(LnState.papszFileNames[i]);
     1174    RTMemFree(LnState.papszFileNames);
     1175    RTMemFree(LnState.papszIncPaths);
     1176
     1177    Assert(rtDwarfCursor_IsAtEndOfUnit(pCursor) || RT_FAILURE(rc));
     1178    return rc;
     1179}
     1180
     1181
     1182/**
    4941183 * Explodes the line number table.
    4951184 *
     
    5041193        return VINF_SUCCESS;
    5051194
    506     RTDWARFSECTRDR SectRdr;
    507     int rc = rtDwarfSectRdrInit(&SectRdr, pThis, krtDbgModDwarfSect_line);
     1195    RTDWARFCURSOR Cursor;
     1196    int rc = rtDwarfCursor_Init(&Cursor, pThis, krtDbgModDwarfSect_line);
    5081197    if (RT_FAILURE(rc))
    5091198        return rc;
    5101199
    511     /*
    512      * Parse the header.
    513      */
    514     uint32_t const uVer           = rtDwarfSectRdrGetUHalf(&SectRdr, 0);
    515     uint64_t const cbSkipAfterHdr = rtDwarfSectRdrGetUOff(&SectRdr, 0);
    516     uint8_t  const cbMinInstr     = rtDwarfSectRdrGetUByte(&SectRdr, 0);
    517     uint8_t  const cbMaxInstr     = rtDwarfSectRdrGetUByte(&SectRdr, 0);
    518     uint8_t  const fDefIsStmt     = rtDwarfSectRdrGetUByte(&SectRdr, 0);
    519     int8_t   const i8LineBase     = rtDwarfSectRdrGetSByte(&SectRdr, 0);
    520     uint8_t  const u8LineRange    = rtDwarfSectRdrGetUByte(&SectRdr, 0);
    521     uint8_t  const u8OpcodeBase   = rtDwarfSectRdrGetUByte(&SectRdr, 0);
    522     /*...*/
    523 
    524     if (uVer >= 2 && uVer <= 4)
    525     {
    526         /*
    527          * Run the program....
    528          */
    529 
    530     }
    531 
    532     rtDwarfSectRdrDelete(&SectRdr);
     1200    while (   rtDwarfCursor_IsAtEnd(&Cursor)
     1201           && RT_SUCCESS(rc))
     1202        rc = rtDbgModDwarfExplodeLineNumbersForUnit(pThis, &Cursor);
     1203
     1204
     1205    rtDwarfCursor_Delete(&Cursor);
    5331206    return rc;
    5341207}
Note: See TracChangeset for help on using the changeset viewer.

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