<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">Dmitry, The classification of the for the thread local data is good, though we should just have a bool attribute on the section that specifies that the section is thread local. Any addresses that fall within these thread local sections will need to be resolved per thread. Eventually we will need to have each "lldb_private::Thread" subclass be able to resolve a section load address when we try to resolve a section that is thread specific. For now they just won't resolve, but they shouldn't get in the way.<div><br></div><div><div>I have checked in a different fix that should work for you:</div><div><br></div><div><div>Index: include/lldb/Target/Target.h</div><div>===================================================================</div><div>--- include/lldb/Target/Target.h<span class="Apple-tab-span" style="white-space:pre">     </span>(revision 153535)</div><div>+++ include/lldb/Target/Target.h<span class="Apple-tab-span" style="white-space:pre">    </span>(working copy)</div><div>@@ -844,33 +844,6 @@</div><div>         return m_section_load_list;</div><div>     }</div><div> </div><div>-</div><div>-    //------------------------------------------------------------------</div><div>-    /// Load a module in this target by at the section file addresses</div><div>-    /// with an optional constant slide applied to each section.</div><div>-    ///</div><div>-    /// This function will load all top level sections at their file</div><div>-    /// addresses and apply an optional constant slide amount to each </div><div>-    /// section. This can be used to easily load a module at the same </div><div>-    /// addresses that are contained in the object file (trust that</div><div>-    /// the addresses in an object file are the correct load addresses).</div><div>-    ///</div><div>-    /// @param[in] module</div><div>-    ///     The module to load.</div><div>-    ///</div><div>-    /// @param[in] slide</div><div>-    ///     A constant slide to add to each file address as each section</div><div>-    ///     is being loaded.</div><div>-    ///</div><div>-    /// @return</div><div>-    ///     \b true if loading the module at the specified address </div><div>-    ///     causes a section to be loaded when it previously wasn't, or</div><div>-    ///     if a section changes load address. Returns \b false if</div><div>-    ///     the sections were all already loaded at these addresses.</div><div>-    //------------------------------------------------------------------</div><div>-    bool</div><div>-    LoadModuleWithSlide (Module *module, lldb::addr_t slide);</div><div>-</div><div>     static Target *</div><div>     GetTargetFromContexts (const ExecutionContext *exe_ctx_ptr, </div><div>                            const SymbolContext *sc_ptr);</div><div>Index: include/lldb/Core/Section.h</div><div>===================================================================</div><div>--- include/lldb/Core/Section.h<span class="Apple-tab-span" style="white-space:pre">      </span>(revision 153535)</div><div>+++ include/lldb/Core/Section.h<span class="Apple-tab-span" style="white-space:pre">     </span>(working copy)</div><div>@@ -261,7 +261,19 @@</div><div>     {</div><div>         return m_parent_wp.lock();</div><div>     }</div><div>+    </div><div>+    bool</div><div>+    IsThreadSpecific () const</div><div>+    {</div><div>+        return m_thread_specific;</div><div>+    }</div><div> </div><div>+    void</div><div>+    SetIsThreadSpecific (bool b)</div><div>+    {</div><div>+        m_thread_specific = b;</div><div>+    }</div><div>+</div><div> protected:</div><div> </div><div>     lldb::SectionWP m_parent_wp;        // Weak pointer to parent section</div><div>@@ -277,7 +289,8 @@</div><div>                                         // children contains an address. This allows for gaps between the children</div><div>                                         // that are contained in the address range for this section, but do not produce</div><div>                                         // hits unless the children contain the address.</div><div>-                    m_encrypted:1;      // Set to true if the contents are encrypted</div><div>+                    m_encrypted:1,      // Set to true if the contents are encrypted</div><div>+                    m_thread_specific:1;// This section is thread specific</div><div>     lldb::SectionWP m_linked_section_wp;</div><div>     uint64_t        m_linked_offset;</div><div> private:</div><div>Index: source/Commands/CommandObjectTarget.cpp</div><div>===================================================================</div><div>--- source/Commands/CommandObjectTarget.cpp<span class="Apple-tab-span" style="white-space:pre">     </span>(revision 153535)</div><div>+++ source/Commands/CommandObjectTarget.cpp<span class="Apple-tab-span" style="white-space:pre"> </span>(working copy)</div><div>@@ -2517,30 +2517,13 @@</div><div>                             SectionList *section_list = objfile->GetSectionList();</div><div>                             if (section_list)</div><div>                             {</div><div>+                                bool changed = false;</div><div>                                 if (argc == 0)</div><div>                                 {</div><div>                                     if (m_slide_option.GetOptionValue().OptionWasSet())</div><div>                                     {</div><div>-                                        Module *module = matching_modules.GetModulePointerAtIndex(0);</div><div>-                                        if (module)</div><div>-                                        {</div><div>-                                            ObjectFile *objfile = module->GetObjectFile();</div><div>-                                            if (objfile)</div><div>-                                            {</div><div>-                                                SectionList *section_list = objfile->GetSectionList();</div><div>-                                                if (section_list)</div><div>-                                                {</div><div>-                                                    const size_t num_sections = section_list->GetSize();</div><div>-                                                    const addr_t slide = m_slide_option.GetOptionValue().GetCurrentValue();</div><div>-                                                    for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx)</div><div>-                                                    {</div><div>-                                                        SectionSP section_sp (section_list->GetSectionAtIndex(sect_idx));</div><div>-                                                        if (section_sp)</div><div>-                                                            target->GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), section_sp->GetFileAddress() + slide);</div><div>-                                                    }</div><div>-                                                }</div><div>-                                            }</div><div>-                                        }</div><div>+                                        const addr_t slide = m_slide_option.GetOptionValue().GetCurrentValue();</div><div>+                                        module->SetLoadAddress (*target, slide, changed);</div><div>                                     }</div><div>                                     else</div><div>                                     {</div><div>@@ -2572,8 +2555,18 @@</div><div>                                                 SectionSP section_sp (section_list->FindSectionByName(const_sect_name));</div><div>                                                 if (section_sp)</div><div>                                                 {</div><div>-                                                    target->GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), load_addr);</div><div>-                                                    result.AppendMessageWithFormat("section '%s' loaded at 0x%llx\n", sect_name, load_addr);</div><div>+                                                    if (section_sp->IsThreadSpecific())</div><div>+                                                    {</div><div>+                                                        result.AppendErrorWithFormat ("thread specific sections are not yet supported (section '%s')\n", sect_name);</div><div>+                                                        result.SetStatus (eReturnStatusFailed);</div><div>+                                                        break;</div><div>+                                                    }</div><div>+                                                    else</div><div>+                                                    {</div><div>+                                                        if (target->GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), load_addr))</div><div>+                                                            changed = true;</div><div>+                                                        result.AppendMessageWithFormat("section '%s' loaded at 0x%llx\n", sect_name, load_addr);</div><div>+                                                    }</div><div>                                                 }</div><div>                                                 else</div><div>                                                 {</div><div>@@ -2600,6 +2593,9 @@</div><div>                                         }</div><div>                                     }</div><div>                                 }</div><div>+                                </div><div>+                                if (changed)</div><div>+                                    target->ModulesDidLoad (matching_modules);</div><div>                             }</div><div>                             else</div><div>                             {</div><div>Index: source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp</div><div>===================================================================</div><div>--- source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp<span class="Apple-tab-span" style="white-space:pre">      </span>(revision 153535)</div><div>+++ source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp<span class="Apple-tab-span" style="white-space:pre"> </span>(working copy)</div><div>@@ -621,6 +621,8 @@</div><div>             static ConstString g_sect_name_text (".text");</div><div>             static ConstString g_sect_name_data (".data");</div><div>             static ConstString g_sect_name_bss (".bss");</div><div>+            static ConstString g_sect_name_tdata (".tdata");</div><div>+            static ConstString g_sect_name_tbss (".tbss");</div><div>             static ConstString g_sect_name_dwarf_debug_abbrev (".debug_abbrev");</div><div>             static ConstString g_sect_name_dwarf_debug_aranges (".debug_aranges");</div><div>             static ConstString g_sect_name_dwarf_debug_frame (".debug_frame");</div><div>@@ -636,9 +638,21 @@</div><div> </div><div>             SectionType sect_type = eSectionTypeOther;</div><div> </div><div>+            bool is_thread_specific = false;</div><div>+            </div><div>             if      (name == g_sect_name_text)                  sect_type = eSectionTypeCode;</div><div>             else if (name == g_sect_name_data)                  sect_type = eSectionTypeData;</div><div>             else if (name == g_sect_name_bss)                   sect_type = eSectionTypeZeroFill;</div><div>+            else if (name == g_sect_name_tdata)</div><div>+            {</div><div>+                sect_type = eSectionTypeData;</div><div>+                is_thread_specific = true;   </div><div>+            }</div><div>+            else if (name == g_sect_name_tbss)</div><div>+            {</div><div>+                sect_type = eSectionTypeZeroFill;   </div><div>+                is_thread_specific = true;   </div><div>+            }</div><div>             else if (name == g_sect_name_dwarf_debug_abbrev)    sect_type = eSectionTypeDWARFDebugAbbrev;</div><div>             else if (name == g_sect_name_dwarf_debug_aranges)   sect_type = eSectionTypeDWARFDebugAranges;</div><div>             else if (name == g_sect_name_dwarf_debug_frame)     sect_type = eSectionTypeDWARFDebugFrame;</div><div>@@ -653,7 +667,7 @@</div><div>             else if (name == g_sect_name_eh_frame)              sect_type = eSectionTypeEHFrame;</div><div>             </div><div>             </div><div>-            SectionSP section(new Section(</div><div>+            SectionSP section_sp(new Section(</div><div>                 GetModule(),        // Module to which this section belongs.</div><div>                 SectionIndex(I),    // Section ID.</div><div>                 name,               // Section name.</div><div>@@ -664,7 +678,9 @@</div><div>                 file_size,          // Size of the section as found in the file.</div><div>                 header.sh_flags));  // Flags for this section.</div><div> </div><div>-            m_sections_ap->AddSection(section);</div><div>+            if (is_thread_specific)</div><div>+                section_sp->SetIsThreadSpecific (is_thread_specific);</div><div>+            m_sections_ap->AddSection(section_sp);</div><div>         }</div><div>     }</div><div> </div><div>Index: source/Target/Target.cpp</div><div>===================================================================</div><div>--- source/Target/Target.cpp<span class="Apple-tab-span" style="white-space:pre">   </span>(revision 153535)</div><div>+++ source/Target/Target.cpp<span class="Apple-tab-span" style="white-space:pre">        </span>(working copy)</div><div>@@ -1957,46 +1957,7 @@</div><div>     result.GetImmediateErrorStream()->Flush();</div><div> }</div><div> </div><div>-bool </div><div>-Target::LoadModuleWithSlide (Module *module, lldb::addr_t slide)</div><div>-{</div><div>-    bool changed = false;</div><div>-    if (module)</div><div>-    {</div><div>-        ObjectFile *object_file = module->GetObjectFile();</div><div>-        if (object_file)</div><div>-        {</div><div>-            SectionList *section_list = object_file->GetSectionList ();</div><div>-            if (section_list)</div><div>-            {</div><div>-                // All sections listed in the dyld image info structure will all</div><div>-                // either be fixed up already, or they will all be off by a single</div><div>-                // slide amount that is determined by finding the first segment</div><div>-                // that is at file offset zero which also has bytes (a file size</div><div>-                // that is greater than zero) in the object file.</div><div>-                </div><div>-                // Determine the slide amount (if any)</div><div>-                const size_t num_sections = section_list->GetSize();</div><div>-                size_t sect_idx = 0;</div><div>-                for (sect_idx = 0; sect_idx < num_sections; ++sect_idx)</div><div>-                {</div><div>-                    // Iterate through the object file sections to find the</div><div>-                    // first section that starts of file offset zero and that</div><div>-                    // has bytes in the file...</div><div>-                    Section *section = section_list->GetSectionAtIndex (sect_idx).get();</div><div>-                    if (section)</div><div>-                    {</div><div>-                        if (m_section_load_list.SetSectionLoadAddress (section, section->GetFileAddress() + slide))</div><div>-                            changed = true;</div><div>-                    }</div><div>-                }</div><div>-            }</div><div>-        }</div><div>-    }</div><div>-    return changed;</div><div>-}</div><div> </div><div>-</div><div> //--------------------------------------------------------------</div><div> // class Target::StopHook</div><div> //--------------------------------------------------------------</div><div>Index: source/Core/Module.cpp</div><div>===================================================================</div><div>--- source/Core/Module.cpp<span class="Apple-tab-span" style="white-space:pre">   </span>(revision 153535)</div><div>+++ source/Core/Module.cpp<span class="Apple-tab-span" style="white-space:pre">  </span>(working copy)</div><div>@@ -1104,11 +1104,11 @@</div><div> bool </div><div> Module::SetLoadAddress (Target &target, lldb::addr_t offset, bool &changed)</div><div> {</div><div>-    changed = false;</div><div>-    ObjectFile *image_object_file = GetObjectFile();</div><div>-    if (image_object_file)</div><div>+    size_t num_loaded_sections = 0;</div><div>+    ObjectFile *objfile = GetObjectFile();</div><div>+    if (objfile)</div><div>     {</div><div>-        SectionList *section_list = image_object_file->GetSectionList ();</div><div>+        SectionList *section_list = objfile->GetSectionList ();</div><div>         if (section_list)</div><div>         {</div><div>             const size_t num_sections = section_list->GetSize();</div><div>@@ -1119,16 +1119,17 @@</div><div>                 // first section that starts of file offset zero and that</div><div>                 // has bytes in the file...</div><div>                 Section *section = section_list->GetSectionAtIndex (sect_idx).get();</div><div>-                if (section)</div><div>+                // Only load non-thread specific sections when given a slide</div><div>+                if (section && !section->IsThreadSpecific())</div><div>                 {</div><div>                     if (target.GetSectionLoadList().SetSectionLoadAddress (section, section->GetFileAddress() + offset))</div><div>-                        changed = true;</div><div>+                        ++num_loaded_sections;</div><div>                 }</div><div>             }</div><div>-            return sect_idx > 0;</div><div>         }</div><div>     }</div><div>-    return false;</div><div>+    changed = num_loaded_sections > 0;</div><div>+    return num_loaded_sections > 0;</div><div> }</div><div> </div><div> </div><div>Index: source/Core/Section.cpp</div><div>===================================================================</div><div>--- source/Core/Section.cpp<span class="Apple-tab-span" style="white-space:pre">    </span>(revision 153535)</div><div>+++ source/Core/Section.cpp<span class="Apple-tab-span" style="white-space:pre"> </span>(working copy)</div><div>@@ -36,6 +36,8 @@</div><div>     m_file_size     (file_size),</div><div>     m_children      (),</div><div>     m_fake          (false),</div><div>+    m_encrypted     (false),</div><div>+    m_thread_specific (false),</div><div>     m_linked_section_wp(),</div><div>     m_linked_offset (0)</div><div> {</div><div>@@ -65,6 +67,8 @@</div><div>     m_file_size     (file_size),</div><div>     m_children      (),</div><div>     m_fake          (false),</div><div>+    m_encrypted     (false),</div><div>+    m_thread_specific (false),</div><div>     m_linked_section_wp(),</div><div>     m_linked_offset (0)</div><div> {</div><div>Index: source/API/SBTarget.cpp</div><div>===================================================================</div><div>--- source/API/SBTarget.cpp<span class="Apple-tab-span" style="white-space:pre">       </span>(revision 153535)</div><div>+++ source/API/SBTarget.cpp<span class="Apple-tab-span" style="white-space:pre"> </span>(working copy)</div><div>@@ -2086,12 +2086,23 @@</div><div>         }</div><div>         else</div><div>         {</div><div>-            target_sp->GetSectionLoadList().SetSectionLoadAddress (section.GetSP().get(), section_base_addr);</div><div>+            SectionSP section_sp (section.GetSP());</div><div>+            if (section_sp)</div><div>+            {</div><div>+                if (section_sp->IsThreadSpecific())</div><div>+                {</div><div>+                    sb_error.SetErrorString ("thread specific sections are not yet supported");</div><div>+                }</div><div>+                else</div><div>+                {</div><div>+                    target_sp->GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), section_base_addr);</div><div>+                }</div><div>+            }</div><div>         }</div><div>     }</div><div>     else</div><div>     {</div><div>-        sb_error.SetErrorStringWithFormat ("invalid target");</div><div>+        sb_error.SetErrorString ("invalid target");</div><div>     }</div><div>     return sb_error;</div><div> }</div><div>@@ -2132,31 +2143,18 @@</div><div>         ModuleSP module_sp (module.GetSP());</div><div>         if (module_sp)</div><div>         {</div><div>-            ObjectFile *objfile = module_sp->GetObjectFile();</div><div>-            if (objfile)</div><div>+            bool changed = false;</div><div>+            if (module_sp->SetLoadAddress (*target_sp, slide_offset, changed))</div><div>             {</div><div>-                SectionList *section_list = objfile->GetSectionList();</div><div>-                if (section_list)</div><div>+                // The load was successful, make sure that at least some sections</div><div>+                // changed before we notify that our module was loaded.</div><div>+                if (changed)</div><div>                 {</div><div>-                    const size_t num_sections = section_list->GetSize();</div><div>-                    for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx)</div><div>-                    {</div><div>-                        SectionSP section_sp (section_list->GetSectionAtIndex(sect_idx));</div><div>-                        if (section_sp)</div><div>-                            target_sp->GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), section_sp->GetFileAddress() + slide_offset);</div><div>-                    }</div><div>+                    ModuleList module_list;</div><div>+                    module_list.Append(module_sp);</div><div>+                    target_sp->ModulesDidLoad (module_list);</div><div>                 }</div><div>-                else</div><div>-                {</div><div>-                    module_sp->GetFileSpec().GetPath (path, sizeof(path));</div><div>-                    sb_error.SetErrorStringWithFormat ("no sections in object file '%s'", path);</div><div>-                }</div><div>             }</div><div>-            else</div><div>-            {</div><div>-                module_sp->GetFileSpec().GetPath (path, sizeof(path));</div><div>-                sb_error.SetErrorStringWithFormat ("no object file for module '%s'", path);</div><div>-            }</div><div>         }</div><div>         else</div><div>         {</div></div><div><br></div><div><br><div><div>On Mar 26, 2012, at 2:21 AM, Dmitry Vyukov wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite">ping<br><br><div class="gmail_quote">On Tue, Feb 28, 2012 at 1:57 PM, Dmitry Vyukov <span dir="ltr"><<a href="mailto:dvyukov@google.com">dvyukov@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex; position: static; z-index: auto; ">
Hi,<div><br></div><div>I would like to ask you to review and land the following patch.</div><div>It improves SBTarget::SetModuleLoadAddress() (at least for Linux) by skipping sections that are not actually mapped. I had to hack around .tbss section, because it has weird elf representation on Linux (from everything you see in the elf itself it is mapped, but it is actually not).</div>

<div><br><div><br></div><div><div>Index: include/lldb/lldb-enumerations.h</div><div>===================================================================</div><div>--- include/lldb/lldb-enumerations.h<span style="white-space:pre-wrap">     </span>(revision 151625)</div>

<div>+++ include/lldb/lldb-enumerations.h<span style="white-space:pre-wrap">      </span>(working copy)</div><div>@@ -467,6 +467,7 @@</div><div>         eSectionTypeCode,</div><div>         eSectionTypeContainer,              // The section contains child sections</div>

<div>         eSectionTypeData,</div><div>+        eSectionTypeThreadData,             // Thread-local data</div><div>         eSectionTypeDataCString,            // Inlined C string data</div><div>         eSectionTypeDataCStringPointers,    // Pointers to C string data</div>

<div>         eSectionTypeDataSymbolAddress,      // Address of a symbol in the symbol table</div><div>@@ -476,6 +477,7 @@</div><div>         eSectionTypeDataPointers,</div><div>         eSectionTypeDebug,</div><div>         eSectionTypeZeroFill,</div>

<div>+        eSectionTypeThreadZeroFill,         // Thread-local zero data</div><div>         eSectionTypeDataObjCMessageRefs,    // Pointer to function pointer + selector</div><div>         eSectionTypeDataObjCCFStrings,      // Objective C const CFString/NSString objects</div>

<div>         eSectionTypeDWARFDebugAbbrev,</div><div>Index: source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp</div><div>===================================================================</div><div>--- source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp<span style="white-space:pre-wrap">  </span>(revision 151625)</div>

<div>+++ source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp<span style="white-space:pre-wrap">       </span>(working copy)</div><div>@@ -620,6 +620,8 @@</div><div>             static ConstString g_sect_name_text (".text");</div>

<div>             static ConstString g_sect_name_data (".data");</div><div>             static ConstString g_sect_name_bss (".bss");</div><div>+            static ConstString g_sect_name_tdata (".tdata");</div>

<div>+            static ConstString g_sect_name_tbss (".tbss");</div><div>             static ConstString g_sect_name_dwarf_debug_abbrev (".debug_abbrev");</div><div>             static ConstString g_sect_name_dwarf_debug_aranges (".debug_aranges");</div>

<div>             static ConstString g_sect_name_dwarf_debug_frame (".debug_frame");</div><div>@@ -638,6 +640,8 @@</div><div>             if      (name == g_sect_name_text)                  sect_type = eSectionTypeCode;</div>

<div>             else if (name == g_sect_name_data)                  sect_type = eSectionTypeData;</div><div>             else if (name == g_sect_name_bss)                   sect_type = eSectionTypeZeroFill;</div><div>+            else if (name == g_sect_name_tdata)                 sect_type = eSectionTypeThreadData;</div>

<div>+            else if (name == g_sect_name_tbss)                  sect_type = eSectionTypeThreadZeroFill;</div><div>             else if (name == g_sect_name_dwarf_debug_abbrev)    sect_type = eSectionTypeDWARFDebugAbbrev;</div>

<div>             else if (name == g_sect_name_dwarf_debug_aranges)   sect_type = eSectionTypeDWARFDebugAranges;</div><div>             else if (name == g_sect_name_dwarf_debug_frame)     sect_type = eSectionTypeDWARFDebugFrame;</div>

<div>Index: source/API/SBTarget.cpp</div><div>===================================================================</div><div>--- source/API/SBTarget.cpp<span style="white-space:pre-wrap">        </span>(revision 151625)</div>
<div>+++ source/API/SBTarget.cpp<span style="white-space:pre-wrap">       </span>(working copy)</div><div>@@ -2010,7 +2010,19 @@</div><div>                     {</div><div>                         SectionSP section_sp (section_list->GetSectionAtIndex(sect_idx));</div>

<div>                         if (section_sp)</div><div>+                        {</div><div>+                            // These are not actually mapped.</div><div>+                            if (section_sp->GetFileAddress() == 0)</div>

<div>+                                continue;</div><div>+                            // Skip .tbss</div><div>+                            // On Linux I observe that .tbss has some real virtual address</div><div>+                            // and ALLOC flag, but the next section starts at the same address.</div>

<div>+                            // It suggests that .tbss is not actually mapped</div><div>+                            // (even if it is mapped, it should be uninteresting for us).</div><div>+                            if (section_sp->GetType() == eSectionTypeThreadZeroFill)</div>

<div>+                                continue;</div><div>                             target_sp->GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), section_sp->GetFileAddress() + slide_offset);</div><div>

+                        }</div><div>                     }</div><div>                 }</div><div>                 else</div></div><div><br></div></div>
</blockquote></div><br>
</blockquote></div><br></div></div></body></html>