Index: trunk/src/VBox/Runtime/common/dbg/dbgmoddwarf.cpp
===================================================================
--- trunk/src/VBox/Runtime/common/dbg/dbgmoddwarf.cpp	(revision 47057)
+++ trunk/src/VBox/Runtime/common/dbg/dbgmoddwarf.cpp	(revision 47290)
@@ -388,6 +388,4 @@
 typedef struct RTDWARFABBREV
 {
-    /** Whether this entry is filled in or not. */
-    bool                fFilled;
     /** Whether there are children or not. */
     bool                fChildren;
@@ -396,4 +394,7 @@
     /** Offset into the abbrev section of the specification pairs. */
     uint32_t            offSpec;
+    /** The abbreviation table offset this is entry is valid for.
+     * UINT32_MAX if not valid. */
+    uint32_t            offAbbrev;
 } RTDWARFABBREV;
 /** Pointer to an abbreviation cache entry. */
@@ -453,6 +454,4 @@
     /** The number of cached abbreviations we've allocated space for. */
     uint32_t                cCachedAbbrevsAlloced;
-    /** Used for range checking cache lookups. */
-    uint32_t                cCachedAbbrevs;
     /** Array of cached abbreviations, indexed by code. */
     PRTDWARFABBREV          paCachedAbbrevs;
@@ -2838,5 +2837,5 @@
     if (pThis->cCachedAbbrevsAlloced < uCode)
     {
-        if (uCode > _64K)
+        if (uCode >= _64K)
             fFillCache = false;
         else
@@ -2848,6 +2847,9 @@
             else
             {
+                Log(("rtDwarfAbbrev_LookupMiss: Growing from %u to %u...\n", pThis->cCachedAbbrevsAlloced, cNew));
+                pThis->paCachedAbbrevs       = (PRTDWARFABBREV)pv;
+                for (uint32_t i = pThis->cCachedAbbrevsAlloced; i < cNew; i++)
+                    pThis->paCachedAbbrevs[i].offAbbrev = UINT32_MAX;
                 pThis->cCachedAbbrevsAlloced = cNew;
-                pThis->paCachedAbbrevs       = (PRTDWARFABBREV)pv;
             }
         }
@@ -2867,9 +2869,14 @@
         /*
          * Search for the entry and fill the cache while doing so.
+         * We assume that abbreviation codes for a unit will stop when we see
+         * zero code or when the code value drops.
          */
+        uint32_t uPrevCode = 0;
         for (;;)
         {
             /* Read the 'header'. Skipping zero code bytes. */
-            uint32_t const uCurCode  = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
+            uint32_t const uCurCode = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
+            if (pRet && (uCurCode == 0 || uCurCode < uPrevCode))
+                break; /* probably end of unit. */
             if (uCurCode != 0)
             {
@@ -2889,21 +2896,22 @@
                 {
                     PRTDWARFABBREV pEntry = &pThis->paCachedAbbrevs[uCurCode - 1];
-                    while (pThis->cCachedAbbrevs < uCurCode)
+                    if (pEntry->offAbbrev != pThis->offCachedAbbrev)
                     {
-                        pThis->paCachedAbbrevs[pThis->cCachedAbbrevs].fFilled = false;
-                        pThis->cCachedAbbrevs++;
+                        pEntry->offAbbrev = pThis->offCachedAbbrev;
+                        pEntry->fChildren = RT_BOOL(uChildren);
+                        pEntry->uTag      = uCurTag;
+                        pEntry->offSpec   = rtDwarfCursor_CalcSectOffsetU32(&Cursor);
+
+                        if (uCurCode == uCode)
+                        {
+                            Assert(!pRet);
+                            pRet = pEntry;
+                            if (uCurCode == pThis->cCachedAbbrevsAlloced)
+                                break;
+                        }
                     }
-
-                    pEntry->fFilled   = true;
-                    pEntry->fChildren = RT_BOOL(uChildren);
-                    pEntry->uTag      = uCurTag;
-                    pEntry->offSpec   = rtDwarfCursor_CalcSectOffsetU32(&Cursor);
-
-                    if (uCurCode == uCode)
-                    {
-                        pRet = pEntry;
-                        if (uCurCode == pThis->cCachedAbbrevsAlloced)
-                            break;
-                    }
+                    else if (pRet)
+                        break; /* Next unit, don't cache more. */
+                    /* else: We're growing the cache and re-reading old data. */
                 }
 
@@ -2949,8 +2957,8 @@
             {
                 pRet = &pThis->LookupAbbrev;
-                pRet->fFilled   = true;
                 pRet->fChildren = RT_BOOL(uChildren);
                 pRet->uTag      = uCurTag;
                 pRet->offSpec   = rtDwarfCursor_CalcSectOffsetU32(&Cursor);
+                pRet->offAbbrev = pThis->offCachedAbbrev;
                 break;
             }
@@ -2983,6 +2991,6 @@
 static PCRTDWARFABBREV rtDwarfAbbrev_Lookup(PRTDBGMODDWARF pThis, uint32_t uCode)
 {
-    if (   uCode - 1 >= pThis->cCachedAbbrevs
-        || !pThis->paCachedAbbrevs[uCode - 1].fFilled)
+    if (   uCode - 1 >= pThis->cCachedAbbrevsAlloced
+        || pThis->paCachedAbbrevs[uCode - 1].offAbbrev != pThis->offCachedAbbrev)
         return rtDwarfAbbrev_LookupMiss(pThis, uCode);
     return &pThis->paCachedAbbrevs[uCode - 1];
@@ -2993,7 +3001,4 @@
  * Sets the abbreviation offset of the current unit.
  *
- * This will flush the cached abbreviation entries if the offset differs from
- * the previous unit.
- *
  * @param   pThis               The DWARF instance.
  * @param   offAbbrev           The offset into the abbreviation section.
@@ -3001,9 +3006,5 @@
 static void rtDwarfAbbrev_SetUnitOffset(PRTDBGMODDWARF pThis, uint32_t offAbbrev)
 {
-    if (pThis->offCachedAbbrev != offAbbrev)
-    {
-        pThis->offCachedAbbrev = offAbbrev;
-        pThis->cCachedAbbrevs  = 0;
-    }
+    pThis->offCachedAbbrev = offAbbrev;
 }
 
@@ -4284,23 +4285,11 @@
         {
             /* End of siblings, up one level. (Is this correct?) */
-            pParentDie = pParentDie->pParent;
-            if (!pParentDie)
+            if (pParentDie->pParent)
             {
-                /* Padding. */
-                while (!rtDwarfCursor_IsAtEndOfUnit(pCursor))
-                {
-                    uAbbrCode = rtDwarfCursor_GetULeb128AsU32(pCursor, UINT32_MAX);
-                    if (uAbbrCode)
-                    {
-                        Log(("%08x: End of DIE stack, but still more info to parse: uAbbrCode=%#x (+%u bytes).\n",
-                             offLog, uAbbrCode, pCursor->cbUnitLeft));
-                        return VERR_DWARF_BAD_INFO;
-                    }
-                }
-                break;
+                pParentDie = pParentDie->pParent;
+                cDepth--;
+                if (!fKeepDies && pParentDie->pParent)
+                    rtDwarfInfo_FreeChildren(pThis, pParentDie);
             }
-            cDepth--;
-            if (!fKeepDies && pParentDie->pParent)
-                rtDwarfInfo_FreeChildren(pThis, pParentDie);
         }
         else
@@ -4326,6 +4315,6 @@
                 pDieDesc = g_aTagDescs[0].pDesc;
             }
-            Log4(("%08x: %*stag=%s (%#x)%s\n", offLog, cDepth * 2, "", pszName,
-                  pAbbrev->uTag, pAbbrev->fChildren ? " has children" : ""));
+            Log4(("%08x: %*stag=%s (%#x, abbrev %u)%s\n", offLog, cDepth * 2, "", pszName,
+                  pAbbrev->uTag, uAbbrCode, pAbbrev->fChildren ? " has children" : ""));
 
             /*
@@ -4756,6 +4745,7 @@
                      * Free the cached abbreviations and unload all sections.
                      */
-                    pThis->cCachedAbbrevs = pThis->cCachedAbbrevsAlloced = 0;
+                    pThis->cCachedAbbrevsAlloced = 0;
                     RTMemFree(pThis->paCachedAbbrevs);
+                    pThis->paCachedAbbrevs = NULL;
 
                     for (unsigned iSect = 0; iSect < RT_ELEMENTS(pThis->aSections); iSect++)
Index: trunk/src/VBox/Runtime/common/dbg/dbgmodexports.cpp
===================================================================
--- trunk/src/VBox/Runtime/common/dbg/dbgmodexports.cpp	(revision 47057)
+++ trunk/src/VBox/Runtime/common/dbg/dbgmodexports.cpp	(revision 47290)
@@ -48,4 +48,6 @@
     PRTDBGMODINT    pDbgMod;
     RTLDRADDR       uImageBase;
+    RTLDRADDR       uRvaNext;
+    uint32_t        cSegs;
 } RTDBGMODEXPORTARGS;
 /** Pointer to an argument package. */
@@ -82,9 +84,5 @@
     NOREF(hLdrMod);
 
-    /* Find the best base address for the module. */
-    if (    pSeg->LinkAddress != NIL_RTLDRADDR
-        &&  (   !pArgs->uImageBase
-             || pArgs->uImageBase > pSeg->LinkAddress))
-        pArgs->uImageBase = pSeg->LinkAddress;
+    pArgs->cSegs++;
 
     /* Add dummy segments for segments that doesn't get mapped. */
@@ -92,6 +90,21 @@
         return RTDbgModSegmentAdd(pArgs->pDbgMod, 0, 0, pSeg->pszName, 0 /*fFlags*/, NULL);
 
+    RTLDRADDR uRva = pSeg->RVA;
+#if 0 /* Kluge for the .data..percpu segment in 64-bit linux kernels and similar. (Moved to ELF.) */
+    if (uRva < pArgs->uRvaNext)
+        uRva = RT_ALIGN_T(pArgs->uRvaNext, pSeg->Alignment, RTLDRADDR);
+#endif
+
+    /* Find the best base address for the module. */
+    if (   (  !pArgs->uImageBase
+            || pArgs->uImageBase > pSeg->LinkAddress)
+        && (   pSeg->LinkAddress != 0 /* .data..percpu again. */
+            || pArgs->cSegs == 1))
+        pArgs->uImageBase = pSeg->LinkAddress;
+
+    /* Add it. */
     RTLDRADDR cb = RT_MAX(pSeg->cb, pSeg->cbMapped);
-    return RTDbgModSegmentAdd(pArgs->pDbgMod, pSeg->RVA, cb, pSeg->pszName, 0 /*fFlags*/, NULL);
+    pArgs->uRvaNext = uRva + cb;
+    return RTDbgModSegmentAdd(pArgs->pDbgMod, uRva, cb, pSeg->pszName, 0 /*fFlags*/, NULL);
 }
 
@@ -128,4 +141,6 @@
     Args.pDbgMod    = pDbgMod;
     Args.uImageBase = 0;
+    Args.uRvaNext   = 0;
+    Args.cSegs      = 0;
     rc = pDbgMod->pImgVt->pfnEnumSegments(pDbgMod, rtDbgModExportsAddSegmentsCallback, &Args);
     if (RT_SUCCESS(rc))
