Skip to content

Conversation

Jinjie-Huang
Copy link
Contributor

@Jinjie-Huang Jinjie-Huang commented Aug 21, 2025

Perhaps we can skip mapping the RangeListsWriters for those DWOs with a DWOId of 0, since currently "0" is considered invalid?

Btw, multiple DWOIds of 0 may lead to an assertion failure inside createRangeLocListAddressWriters("RangeLists writer for DWO unit already exists"). I hit this case when using the compiler built prior to this commit with -fsplit-dwarf-inlining enabled, which generates a large number of Compile Units with a DWO ID == 0. I'm not sure if there are other cases could also trigger this issue.

@llvmbot
Copy link
Member

llvmbot commented Aug 21, 2025

@llvm/pr-subscribers-bolt

Author: Jinjie Huang (Jinjie-Huang)

Changes

DWOs with a DWOId of 0 are considered invalid. Currently, createRangeLocListAddressWriters() is called before these invalid DWOs are skipped, which seems unnecessary. Perhaps we can check the DWOId beforehand?

BTW, this may lead to an assertion failure inside createRangeLocListAddressWriters("RangeLists writer for DWO unit already exists.), when a duplicate DWO ID of 0 is encountered. I hit this case when using the compiler built prior to this commit with -fsplit-dwarf-inlining enabled, which generates a large number of Compile Units with a DWO ID == 0. I'm not sure if other scenarios could also trigger this issue.


Full diff: https://github.com/llvm/llvm-project/pull/154749.diff

1 Files Affected:

  • (modified) bolt/lib/Rewrite/DWARFRewriter.cpp (+1-1)
diff --git a/bolt/lib/Rewrite/DWARFRewriter.cpp b/bolt/lib/Rewrite/DWARFRewriter.cpp
index 0c1a1bac6c72e..e8f6189eb5a69 100644
--- a/bolt/lib/Rewrite/DWARFRewriter.cpp
+++ b/bolt/lib/Rewrite/DWARFRewriter.cpp
@@ -729,13 +729,13 @@ void DWARFRewriter::updateDebugInfo() {
     ThreadPoolInterface &ThreadPool =
         ParallelUtilities::getThreadPool(ThreadCount);
     for (DWARFUnit *CU : DIEBlder.getProcessedCUs()) {
-      createRangeLocListAddressWriters(*CU);
       std::optional<DWARFUnit *> SplitCU;
       std::optional<uint64_t> DWOId = CU->getDWOId();
       if (DWOId)
         SplitCU = BC.getDWOCU(*DWOId);
       if (!SplitCU)
         continue;
+      createRangeLocListAddressWriters(*CU);
       DebugAddrWriter &AddressWriter =
           *AddressWritersByCU[CU->getOffset()].get();
       DebugRangesSectionWriter &TempRangesSectionWriter =

@Jinjie-Huang Jinjie-Huang force-pushed the users/huangjinjie/bolt_dwoid_zero branch 2 times, most recently from 7e2e637 to b6c3f3c Compare August 21, 2025 13:29
@Jinjie-Huang Jinjie-Huang changed the title [BOLT][DWARF] Avoid unnecessary work if DWO id is zero [BOLT][DWARF] Avoid work if DWO id is zero Aug 21, 2025
@Jinjie-Huang Jinjie-Huang changed the title [BOLT][DWARF] Avoid work if DWO id is zero [BOLT][DWARF] Avoid invalid work if DWO id is zero Aug 27, 2025
@ayermolo ayermolo self-assigned this Aug 27, 2025
@ayermolo
Copy link
Contributor

That sounds like a broken DWARF. Maybe better approach is to detect it and not to update debug information at all.

@Jinjie-Huang Jinjie-Huang force-pushed the users/huangjinjie/bolt_dwoid_zero branch from bb17368 to 8851f2e Compare September 2, 2025 09:18
@Jinjie-Huang Jinjie-Huang changed the title [BOLT][DWARF] Avoid invalid work if DWO id is zero [BOLT][DWARF] Skip processing DWO files with ID 0 Sep 2, 2025
@Jinjie-Huang Jinjie-Huang force-pushed the users/huangjinjie/bolt_dwoid_zero branch from 39145c2 to 1acbf66 Compare September 2, 2025 10:09
Copy link

github-actions bot commented Sep 2, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@Jinjie-Huang Jinjie-Huang force-pushed the users/huangjinjie/bolt_dwoid_zero branch from 1acbf66 to 5a9460a Compare September 2, 2025 10:18
@Jinjie-Huang
Copy link
Contributor Author

Jinjie-Huang commented Sep 2, 2025

@ayermolo Thanks for the review.

This kind of dwarf can reproduced via thinlto + split-dwarf + "-fsplit-dwarf-inlining" with clang prior to this commit.
And we can get dwarf like this(btw, a test has also been added):

0x000000d7: Compile Unit: length = 0x00000025, format = DWARF32, version = 0x0005, unit_type = DW_UT_skeleton, abbr_offset = 0x005b, addr_size = 0x08, DWO_id = 0x0000000000000000 (next unit at 0x00000100)

0x000000eb: DW_TAG_skeleton_unit
              DW_AT_stmt_list [DW_FORM_sec_offset]	(0x000001f3)
              DW_AT_str_offsets_base [DW_FORM_sec_offset]	(0x00000008)
              DW_AT_comp_dir [DW_FORM_strx1]	(".")
              DW_AT_GNU_pubnames [DW_FORM_flag_present]	(true)
              DW_AT_producer [DW_FORM_strx1]	("clang version 16.0.6)")
              DW_AT_language [DW_FORM_data2]	(DW_LANG_C_plus_plus_14)
              DW_AT_name [DW_FORM_strx1]	("callee.cpp")
              DW_AT_addr_base [DW_FORM_sec_offset]	(0x00000008)

0x000000fd:   DW_TAG_subprogram
                DW_AT_name [DW_FORM_strx1]	("hotFunction")
                DW_AT_inline [DW_FORM_implicit_const]	(DW_INL_inlined)

The compiler generates DWARF for the cross-CU callee source file, and there can be multiple CUs with a dwoid of 0. This DWARF seems structurally normal, except that the dwoid is left at its initial value of '0'. I’m not sure whether this counts as a 'broken DWARF', or whether it can be effectively detected.

The current implementation of this patch skips processing duplicates with a dwoid of 0, is this reasonable?

@ayermolo
Copy link
Contributor

ayermolo commented Sep 2, 2025

Before BOLT it has multiple DWO IDs that are the same, zero. Which should make llvm-dwp abort.
Although if there are still .o/.dwo files it should be debuggable I believe. Not sure how lldb uses DWO ID internally.

After BOLT it will definitely will be broken because those dwo cus will be referring to the structure of the binary before BOLT.

If we do want to support partial update maybe a better way is not to include those CUs in final output?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants