[GDBJIT] Make gdbjit thread-safe & bug fix (#14390)
authorKonstantin Baladurin <k.baladurin@partner.samsung.com>
Mon, 9 Oct 2017 17:21:22 +0000 (20:21 +0300)
committerJan Vorlicek <janvorli@microsoft.com>
Mon, 9 Oct 2017 17:21:22 +0000 (19:21 +0200)
* [GDBJIT] Fix DW_AT_comp_dir setting

We should use cuPath to set dirPath in NotifyGdb::EmitDebugInfo instead of
DebugString[1].

* [GDBJIT] Make gdbjit thread-safe

NotifyGdb::MethodPrepared method can be called from multiple threads
simultaneously in this case gdbjit will work incorrectly as it uses
global variable without synchronization.

src/inc/CrstTypes.def
src/inc/crsttypes.h
src/vm/ceemain.cpp
src/vm/gdbjit.cpp
src/vm/gdbjit.h

index 5bf4ec6..8dc0d26 100644 (file)
@@ -783,3 +783,6 @@ End
 Crst EventPipe
     AcquiredBefore ThreadIdDispenser ThreadStore DomainLocalBlock InstMethodHashTable
 End
+
+Crst NotifyGdb
+End
index 55dc5bd..1d6b349 100644 (file)
@@ -1,6 +1,8 @@
+//
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
+//
 
 #ifndef __CRST_TYPES_INCLUDED
 #define __CRST_TYPES_INCLUDED
@@ -121,70 +123,71 @@ enum CrstType
     CrstNativeBinderInit = 104,
     CrstNativeImageCache = 105,
     CrstNls = 106,
-    CrstObjectList = 107,
-    CrstOnEventManager = 108,
-    CrstPatchEntryPoint = 109,
-    CrstPEFileSecurityManager = 110,
-    CrstPEImage = 111,
-    CrstPEImagePDBStream = 112,
-    CrstPendingTypeLoadEntry = 113,
-    CrstPinHandle = 114,
-    CrstPinnedByrefValidation = 115,
-    CrstProfilerGCRefDataFreeList = 116,
-    CrstProfilingAPIStatus = 117,
-    CrstPublisherCertificate = 118,
-    CrstRCWCache = 119,
-    CrstRCWCleanupList = 120,
-    CrstRCWRefCache = 121,
-    CrstReDacl = 122,
-    CrstReflection = 123,
-    CrstReJITDomainTable = 124,
-    CrstReJITGlobalRequest = 125,
-    CrstReJITSharedDomainTable = 126,
-    CrstRemoting = 127,
-    CrstRetThunkCache = 128,
-    CrstRWLock = 129,
-    CrstSavedExceptionInfo = 130,
-    CrstSaveModuleProfileData = 131,
-    CrstSecurityPolicyCache = 132,
-    CrstSecurityPolicyInit = 133,
-    CrstSecurityStackwalkCache = 134,
-    CrstSharedAssemblyCreate = 135,
-    CrstSharedBaseDomain = 136,
-    CrstSigConvert = 137,
-    CrstSingleUseLock = 138,
-    CrstSpecialStatics = 139,
-    CrstSqmManager = 140,
-    CrstStackSampler = 141,
-    CrstStressLog = 142,
-    CrstStrongName = 143,
-    CrstStubCache = 144,
-    CrstStubDispatchCache = 145,
-    CrstStubUnwindInfoHeapSegments = 146,
-    CrstSyncBlockCache = 147,
-    CrstSyncHashLock = 148,
-    CrstSystemBaseDomain = 149,
-    CrstSystemDomain = 150,
-    CrstSystemDomainDelayedUnloadList = 151,
-    CrstThreadIdDispenser = 152,
-    CrstThreadpoolEventCache = 153,
-    CrstThreadpoolTimerQueue = 154,
-    CrstThreadpoolWaitThreads = 155,
-    CrstThreadpoolWorker = 156,
-    CrstThreadStaticDataHashTable = 157,
-    CrstThreadStore = 158,
-    CrstTPMethodTable = 159,
-    CrstTypeEquivalenceMap = 160,
-    CrstTypeIDMap = 161,
-    CrstUMEntryThunkCache = 162,
-    CrstUMThunkHash = 163,
-    CrstUniqueStack = 164,
-    CrstUnresolvedClassLock = 165,
-    CrstUnwindInfoTableLock = 166,
-    CrstVSDIndirectionCellLock = 167,
-    CrstWinRTFactoryCache = 168,
-    CrstWrapperTemplate = 169,
-    kNumberOfCrstTypes = 170
+    CrstNotifyGdb = 107,
+    CrstObjectList = 108,
+    CrstOnEventManager = 109,
+    CrstPatchEntryPoint = 110,
+    CrstPEFileSecurityManager = 111,
+    CrstPEImage = 112,
+    CrstPEImagePDBStream = 113,
+    CrstPendingTypeLoadEntry = 114,
+    CrstPinHandle = 115,
+    CrstPinnedByrefValidation = 116,
+    CrstProfilerGCRefDataFreeList = 117,
+    CrstProfilingAPIStatus = 118,
+    CrstPublisherCertificate = 119,
+    CrstRCWCache = 120,
+    CrstRCWCleanupList = 121,
+    CrstRCWRefCache = 122,
+    CrstReDacl = 123,
+    CrstReflection = 124,
+    CrstReJITDomainTable = 125,
+    CrstReJITGlobalRequest = 126,
+    CrstReJITSharedDomainTable = 127,
+    CrstRemoting = 128,
+    CrstRetThunkCache = 129,
+    CrstRWLock = 130,
+    CrstSavedExceptionInfo = 131,
+    CrstSaveModuleProfileData = 132,
+    CrstSecurityPolicyCache = 133,
+    CrstSecurityPolicyInit = 134,
+    CrstSecurityStackwalkCache = 135,
+    CrstSharedAssemblyCreate = 136,
+    CrstSharedBaseDomain = 137,
+    CrstSigConvert = 138,
+    CrstSingleUseLock = 139,
+    CrstSpecialStatics = 140,
+    CrstSqmManager = 141,
+    CrstStackSampler = 142,
+    CrstStressLog = 143,
+    CrstStrongName = 144,
+    CrstStubCache = 145,
+    CrstStubDispatchCache = 146,
+    CrstStubUnwindInfoHeapSegments = 147,
+    CrstSyncBlockCache = 148,
+    CrstSyncHashLock = 149,
+    CrstSystemBaseDomain = 150,
+    CrstSystemDomain = 151,
+    CrstSystemDomainDelayedUnloadList = 152,
+    CrstThreadIdDispenser = 153,
+    CrstThreadpoolEventCache = 154,
+    CrstThreadpoolTimerQueue = 155,
+    CrstThreadpoolWaitThreads = 156,
+    CrstThreadpoolWorker = 157,
+    CrstThreadStaticDataHashTable = 158,
+    CrstThreadStore = 159,
+    CrstTPMethodTable = 160,
+    CrstTypeEquivalenceMap = 161,
+    CrstTypeIDMap = 162,
+    CrstUMEntryThunkCache = 163,
+    CrstUMThunkHash = 164,
+    CrstUniqueStack = 165,
+    CrstUnresolvedClassLock = 166,
+    CrstUnwindInfoTableLock = 167,
+    CrstVSDIndirectionCellLock = 168,
+    CrstWinRTFactoryCache = 169,
+    CrstWrapperTemplate = 170,
+    kNumberOfCrstTypes = 171
 };
 
 #endif // __CRST_TYPES_INCLUDED
@@ -302,6 +305,7 @@ int g_rgCrstLevelMap[] =
     -1,                        // CrstNativeBinderInit
     -1,                        // CrstNativeImageCache
     0,                 // CrstNls
+    0,                 // CrstNotifyGdb
     2,                 // CrstObjectList
     0,                 // CrstOnEventManager
     0,                 // CrstPatchEntryPoint
@@ -477,6 +481,7 @@ LPCSTR g_rgCrstNameMap[] =
     "CrstNativeBinderInit",
     "CrstNativeImageCache",
     "CrstNls",
+    "CrstNotifyGdb",
     "CrstObjectList",
     "CrstOnEventManager",
     "CrstPatchEntryPoint",
index 011caf0..44f5d8e 100644 (file)
 #include "process.h"
 #endif // !FEATURE_PAL
 
+#ifdef FEATURE_GDBJIT
+#include "gdbjit.h"
+#endif // FEATURE_GDBJIT
+
 #ifdef FEATURE_IPCMAN
 static HRESULT InitializeIPCManager(void);
 static void PublishIPCManager(void);
@@ -685,6 +689,11 @@ void EEStartupHelper(COINITIEE fFlags)
         EventPipe::Initialize();
 #endif // FEATURE_PERFTRACING
 
+#ifdef FEATURE_GDBJIT
+        // Initialize gdbjit
+        NotifyGdb::Initialize();
+#endif // FEATURE_GDBJIT
+
 #ifdef FEATURE_EVENT_TRACE        
         // Initialize event tracing early so we can trace CLR startup time events.
         InitializeEventTracing();
index 9dbf9df..22bf30a 100644 (file)
@@ -661,15 +661,57 @@ void __attribute__((noinline)) __jit_debug_register_code() { __asm__(""); };
 /* Make sure to specify the version statically, because the
    debugger may check the version before we can set it.  */
 struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
+static CrstStatic g_jitDescriptorCrst;
 
 // END of GDB JIT interface
 
-/* Static data for .debug_str section */
-const char* DebugStrings[] = {
-  "CoreCLR", "" /* module name */, "" /* module path */
-};
+class DebugStringsCU
+{
+public:
+    DebugStringsCU(const char *module, const char *path)
+        : m_producerName("CoreCLR"),
+          m_moduleName(module),
+          m_moduleDir(path),
+          m_producerOffset(0),
+          m_moduleNameOffset(0),
+          m_moduleDirOffset(0)
+    {
+    }
 
-const int DebugStringCount = sizeof(DebugStrings) / sizeof(DebugStrings[0]);
+    int GetProducerOffset() const   { return m_producerOffset; }
+    int GetModuleNameOffset() const { return m_moduleNameOffset; }
+    int GetModuleDirOffset() const  { return m_moduleDirOffset; }
+
+    void DumpStrings(char *ptr, int &offset)
+    {
+        m_producerOffset = offset;
+        DumpString(m_producerName, ptr, offset);
+
+        m_moduleNameOffset = offset;
+        DumpString(m_moduleName, ptr, offset);
+
+        m_moduleDirOffset = offset;
+        DumpString(m_moduleDir, ptr, offset);
+    }
+
+private:
+    const char* m_producerName;
+    const char* m_moduleName;
+    const char* m_moduleDir;
+
+    int m_producerOffset;
+    int m_moduleNameOffset;
+    int m_moduleDirOffset;
+
+    static void DumpString(const char *str, char *ptr, int &offset)
+    {
+        if (ptr != nullptr)
+        {
+            strcpy(ptr + offset, str);
+        }
+        offset += strlen(str) + 1;
+    }
+};
 
 /* Static data for .debug_abbrev */
 const unsigned char AbbrevTable[] = {
@@ -1785,48 +1827,23 @@ static int getNextPrologueIndex(int from, T &arr, int n)
     return -1;
 }
 
+static NewArrayHolder<WCHAR> g_wszModuleNames;
+static DWORD g_cBytesNeeded;
+
 static inline bool isListedModule(const WCHAR *wszModuleFile)
 {
-    static NewArrayHolder<WCHAR> wszModuleNames = nullptr;
-    static DWORD cBytesNeeded = 0;
-
-    // Get names of interesting modules from environment
-    if (wszModuleNames == nullptr && cBytesNeeded == 0)
-    {
-        DWORD cCharsNeeded = GetEnvironmentVariableW(W("CORECLR_GDBJIT"), NULL, 0);
-
-        if (cCharsNeeded == 0)
-        {
-            cBytesNeeded = 0xffffffff;
-            return false;
-        }
-
-        WCHAR *wszModuleNamesBuf = new WCHAR[cCharsNeeded+1];
-
-        cCharsNeeded = GetEnvironmentVariableW(W("CORECLR_GDBJIT"), wszModuleNamesBuf, cCharsNeeded);
-
-        if (cCharsNeeded == 0)
-        {
-            delete[] wszModuleNamesBuf;
-            cBytesNeeded = 0xffffffff;
-            return false;
-        }
-
-        wszModuleNames = wszModuleNamesBuf;
-        cBytesNeeded = cCharsNeeded + 1;
-    }
-    else if (wszModuleNames == nullptr)
+    if (g_wszModuleNames == nullptr)
     {
         return false;
     }
 
-    _ASSERTE(wszModuleNames != nullptr && cBytesNeeded > 0);
+    _ASSERTE(g_cBytesNeeded > 0);
 
     BOOL isUserDebug = FALSE;
 
-    NewArrayHolder<WCHAR> wszModuleName = new WCHAR[cBytesNeeded];
-    LPWSTR pComma = wcsstr(wszModuleNames, W(","));
-    LPWSTR tmp = wszModuleNames;
+    NewArrayHolder<WCHAR> wszModuleName = new WCHAR[g_cBytesNeeded];
+    LPWSTR pComma = wcsstr(g_wszModuleNames, W(","));
+    LPWSTR tmp = g_wszModuleNames;
 
     while (pComma != NULL)
     {
@@ -1854,7 +1871,8 @@ static inline bool isListedModule(const WCHAR *wszModuleFile)
     return isUserDebug;
 }
 
-static NotifyGdb::AddrSet codeAddrs;
+static NotifyGdb::AddrSet g_codeAddrs;
+static CrstStatic g_codeAddrsCrst;
 
 class Elf_SectionTracker
 {
@@ -2440,6 +2458,38 @@ static void BuildDebugFrame(Elf_Builder &elfBuilder, PCODE pCode, TADDR codeSize
 }
 #endif // FEATURE_GDBJIT_FRAME
 
+void NotifyGdb::Initialize()
+{
+    g_jitDescriptorCrst.Init(CrstNotifyGdb);
+    g_codeAddrsCrst.Init(CrstNotifyGdb);
+
+    // Get names of interesting modules from environment
+    if (g_wszModuleNames == nullptr && g_cBytesNeeded == 0)
+    {
+        DWORD cCharsNeeded = GetEnvironmentVariableW(W("CORECLR_GDBJIT"), NULL, 0);
+
+        if (cCharsNeeded == 0)
+        {
+            g_cBytesNeeded = 0xffffffff;
+            return;
+        }
+
+        WCHAR *wszModuleNamesBuf = new WCHAR[cCharsNeeded+1];
+
+        cCharsNeeded = GetEnvironmentVariableW(W("CORECLR_GDBJIT"), wszModuleNamesBuf, cCharsNeeded);
+
+        if (cCharsNeeded == 0)
+        {
+            delete[] wszModuleNamesBuf;
+            g_cBytesNeeded = 0xffffffff;
+            return;
+        }
+
+        g_wszModuleNames = wszModuleNamesBuf;
+        g_cBytesNeeded = cCharsNeeded + 1;
+    }
+}
+
 /* Create ELF/DWARF debug info for jitted method */
 void NotifyGdb::MethodPrepared(MethodDesc* methodDescPtr)
 {
@@ -2547,21 +2597,25 @@ void NotifyGdb::OnMethodPrepared(MethodDesc* methodDescPtr)
     jit_symbols->symfile_addr = symfile_addr;
     jit_symbols->symfile_size = symfile_size;
 
-    /* Link into list */
-    jit_code_entry *head = __jit_debug_descriptor.first_entry;
-    __jit_debug_descriptor.first_entry = jit_symbols;
-    if (head != 0)
     {
-        jit_symbols->next_entry = head;
-        head->prev_entry = jit_symbols;
-    }
+        CrstHolder crst(&g_jitDescriptorCrst);
 
-    jit_symbols.SuppressRelease();
+        /* Link into list */
+        jit_code_entry *head = __jit_debug_descriptor.first_entry;
+        __jit_debug_descriptor.first_entry = jit_symbols;
+        if (head != 0)
+        {
+            jit_symbols->next_entry = head;
+            head->prev_entry = jit_symbols;
+        }
 
-    /* Notify the debugger */
-    __jit_debug_descriptor.relevant_entry = jit_symbols;
-    __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
-    __jit_debug_register_code();
+        jit_symbols.SuppressRelease();
+
+        /* Notify the debugger */
+        __jit_debug_descriptor.relevant_entry = jit_symbols;
+        __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
+        __jit_debug_register_code();
+    }
 }
 
 #ifdef FEATURE_GDBJIT_FRAME
@@ -2764,27 +2818,24 @@ bool NotifyGdb::EmitDebugInfo(Elf_Builder &elfBuilder, MethodDesc* methodDescPtr
     if (dirLen != 0)
     {
         dirPath = new char[dirLen];
-        memcpy(dirPath, DebugStrings[1], dirLen - 1);
+        memcpy(dirPath, cuPath, dirLen - 1);
         dirPath[dirLen - 1] = '\0';
     }
-    DebugStrings[1] = fileName;
-    DebugStrings[2] = dirPath ? (const char *)dirPath : "";
+
+    DebugStringsCU debugStringsCU(fileName, dirPath ? (const char *)dirPath : "");
 
     /* Build .debug_str section */
-    if (!BuildDebugStrings(dbgStr, pTypeMap, method))
+    if (!BuildDebugStrings(dbgStr, pTypeMap, method, debugStringsCU))
     {
         return false;
     }
 
     /* Build .debug_info section */
-    if (!BuildDebugInfo(dbgInfo, pTypeMap, method))
+    if (!BuildDebugInfo(dbgInfo, pTypeMap, method, debugStringsCU))
     {
         return false;
     }
 
-    DebugStrings[1] = "";
-    DebugStrings[2] = "";
-
     for (int i = 0; i < method.GetCount(); ++i)
     {
         method[i]->lines = nullptr;
@@ -2877,6 +2928,8 @@ void NotifyGdb::MethodPitched(MethodDesc* methodDescPtr)
     if (pCode == NULL)
         return;
 
+    CrstHolder crst(&g_jitDescriptorCrst);
+
     /* Find relevant entry */
     for (jit_code_entry* jit_symbols = __jit_debug_descriptor.first_entry; jit_symbols != 0; jit_symbols = jit_symbols->next_entry)
     {
@@ -3197,7 +3250,7 @@ static void fixLineMapping(SymbolsInfo* lines, unsigned nlines)
 /* Build program for DWARF source line section */
 bool NotifyGdb::BuildLineProg(MemBuf& buf, PCODE startAddr, TADDR codeSize, SymbolsInfo* lines, unsigned nlines)
 {
-    static char cnv_buf[16];
+    char cnv_buf[16];
 
     /* reserve memory assuming worst case: set address, advance line command, set proglogue/epilogue and copy for each line */
     buf.MemSize =
@@ -3266,15 +3319,15 @@ bool NotifyGdb::BuildLineProg(MemBuf& buf, PCODE startAddr, TADDR codeSize, Symb
 }
 
 /* Build the DWARF .debug_str section */
-bool NotifyGdb::BuildDebugStrings(MemBuf& buf, PTK_TypeInfoMap pTypeMap, FunctionMemberPtrArrayHolder &method)
+bool NotifyGdb::BuildDebugStrings(MemBuf& buf,
+                                  PTK_TypeInfoMap pTypeMap,
+                                  FunctionMemberPtrArrayHolder &method,
+                                  DebugStringsCU &debugStringsCU)
 {
     int totalLength = 0;
 
     /* calculate total section size */
-    for (int i = 0; i < DebugStringCount; ++i)
-    {
-        totalLength += strlen(DebugStrings[i]) + 1;
-    }
+    debugStringsCU.DumpStrings(nullptr, totalLength);
 
     for (int i = 0; i < method.GetCount(); ++i)
     {
@@ -3297,11 +3350,8 @@ bool NotifyGdb::BuildDebugStrings(MemBuf& buf, PTK_TypeInfoMap pTypeMap, Functio
     /* copy strings */
     char* bufPtr = buf.MemPtr;
     int offset = 0;
-    for (int i = 0; i < DebugStringCount; ++i)
-    {
-        strcpy(bufPtr + offset, DebugStrings[i]);
-        offset += strlen(DebugStrings[i]) + 1;
-    }
+
+    debugStringsCU.DumpStrings(bufPtr, offset);
 
     for (int i = 0; i < method.GetCount(); ++i)
     {
@@ -3332,7 +3382,10 @@ bool NotifyGdb::BuildDebugAbbrev(MemBuf& buf)
 }
 
 /* Build tge DWARF .debug_info section */
-bool NotifyGdb::BuildDebugInfo(MemBuf& buf, PTK_TypeInfoMap pTypeMap, FunctionMemberPtrArrayHolder &method)
+bool NotifyGdb::BuildDebugInfo(MemBuf& buf,
+                               PTK_TypeInfoMap pTypeMap,
+                               FunctionMemberPtrArrayHolder &method,
+                               DebugStringsCU &debugStringsCU)
 {
     int totalTypeVarSubSize = 0;
     {
@@ -3366,9 +3419,9 @@ bool NotifyGdb::BuildDebugInfo(MemBuf& buf, PTK_TypeInfoMap pTypeMap, FunctionMe
        reinterpret_cast<DebugInfoCU*>(buf.MemPtr + offset);
     memcpy(buf.MemPtr + offset, &debugInfoCU, sizeof(DebugInfoCU));
     offset += sizeof(DebugInfoCU);
-    diCU->m_prod_off = 0;
-    diCU->m_cu_name = strlen(DebugStrings[0]) + 1;
-    diCU->m_cu_dir = diCU->m_cu_name + strlen(DebugStrings[1]) + 1;
+    diCU->m_prod_off = debugStringsCU.GetProducerOffset();
+    diCU->m_cu_name  = debugStringsCU.GetModuleNameOffset();
+    diCU->m_cu_dir   = debugStringsCU.GetModuleDirOffset();
     {
         auto iter = pTypeMap->Begin();
         while (iter != pTypeMap->End())
@@ -3422,8 +3475,10 @@ bool NotifyGdb::CollectCalledMethods(CalledMethod* pCalledMethods,
 {
     AddrSet tmpCodeAddrs;
 
-    if (!codeAddrs.Contains(nativeCode))
-        codeAddrs.Add(nativeCode);
+    CrstHolder crst(&g_codeAddrsCrst);
+
+    if (!g_codeAddrs.Contains(nativeCode))
+        g_codeAddrs.Add(nativeCode);
 
     CalledMethod* pList = pCalledMethods;
 
@@ -3431,7 +3486,7 @@ bool NotifyGdb::CollectCalledMethods(CalledMethod* pCalledMethods,
     while (pList != NULL)
     {
         TADDR callAddr = (TADDR)pList->GetCallAddr();
-        if (!tmpCodeAddrs.Contains(callAddr) && !codeAddrs.Contains(callAddr)) {
+        if (!tmpCodeAddrs.Contains(callAddr) && !g_codeAddrs.Contains(callAddr)) {
             tmpCodeAddrs.Add(callAddr);
         }
         pList = pList->GetNext();
@@ -3445,7 +3500,7 @@ bool NotifyGdb::CollectCalledMethods(CalledMethod* pCalledMethods,
     while (i < symbolCount && pList != NULL)
     {
         TADDR callAddr = (TADDR)pList->GetCallAddr();
-        if (!codeAddrs.Contains(callAddr))
+        if (!g_codeAddrs.Contains(callAddr))
         {
             MethodDesc* pMD = pList->GetMethodDesc();
             LPCUTF8 methodName = pMD->GetName();
@@ -3455,7 +3510,7 @@ bool NotifyGdb::CollectCalledMethods(CalledMethod* pCalledMethods,
             sprintf_s((char*)symbolNames[i].m_name, symbolNameLength, "__thunk_%s", methodName);
             symbolNames[i].m_value = callAddr;
             ++i;
-            codeAddrs.Add(callAddr);
+            g_codeAddrs.Add(callAddr);
         }
         pList = pList->GetNext();
     }
index 6cfe52c..abb8480 100644 (file)
@@ -336,11 +336,13 @@ public:
 
 struct Elf_Symbol;
 class Elf_Builder;
+class DebugStringsCU;
 
 class NotifyGdb
 {
 public:
     class FileTableBuilder;
+    static void Initialize();
     static void MethodPrepared(MethodDesc* methodDescPtr);
     static void MethodPitched(MethodDesc* methodDescPtr);
     template <typename PARENT_TRAITS>
@@ -429,9 +431,11 @@ private:
                                         NewArrayHolder<Elf_Symbol> &symbolNames, int symbolCount,
                                         unsigned int thunkIndexBase);
     static bool BuildStringTableSection(MemBuf& strTab, NewArrayHolder<Elf_Symbol> &symbolNames, int symbolCount);
-    static bool BuildDebugStrings(MemBuf& buf, PTK_TypeInfoMap pTypeMap, FunctionMemberPtrArrayHolder &method);
+    static bool BuildDebugStrings(MemBuf& buf, PTK_TypeInfoMap pTypeMap, FunctionMemberPtrArrayHolder &method,
+                                  DebugStringsCU &debugStringsCU);
     static bool BuildDebugAbbrev(MemBuf& buf);
-    static bool BuildDebugInfo(MemBuf& buf, PTK_TypeInfoMap pTypeMap, FunctionMemberPtrArrayHolder &method);
+    static bool BuildDebugInfo(MemBuf& buf, PTK_TypeInfoMap pTypeMap, FunctionMemberPtrArrayHolder &method,
+                               DebugStringsCU &debugStringsCU);
     static bool BuildDebugPub(MemBuf& buf, const char* name, uint32_t size, uint32_t dieOffset);
     static bool BuildLineTable(MemBuf& buf, PCODE startAddr, TADDR codeSize, SymbolsInfo* lines, unsigned nlines,
                                const char * &cuPath);