[llvm] [BOLT][DWARF] Add support for .debug_names (PR #81062)
Davide Italiano via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 14 12:47:54 PST 2024
================
@@ -0,0 +1,644 @@
+//===- bolt/Rewrite/DebugNames.cpp -------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "bolt/Core/DebugNames.h"
+#include "bolt/Core/BinaryContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
+#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
+#include "llvm/Support/EndianStream.h"
+#include "llvm/Support/LEB128.h"
+
+namespace llvm {
+namespace bolt {
+DWARF5AcceleratorTable::DWARF5AcceleratorTable(
+ const bool CreateDebugNames, BinaryContext &BC,
+ DebugStrWriter &MainBinaryStrWriter)
+ : MainBinaryStrWriter(MainBinaryStrWriter) {
+ NeedToCreate = CreateDebugNames || BC.getDebugNamesSection();
+ if (!NeedToCreate)
+ return;
+ FullTableBuffer = std::make_unique<DebugStrBufferVector>();
+ FullTableStream = std::make_unique<raw_svector_ostream>(*FullTableBuffer);
+ StrBuffer = std::make_unique<DebugStrBufferVector>();
+ StrStream = std::make_unique<raw_svector_ostream>(*StrBuffer);
+ EntriesBuffer = std::make_unique<DebugStrBufferVector>();
+ Entriestream = std::make_unique<raw_svector_ostream>(*EntriesBuffer);
+ AugStringBuffer = std::make_unique<DebugStrBufferVector>();
+ AugStringtream = std::make_unique<raw_svector_ostream>(*AugStringBuffer);
+
+ // Binary has split-dwarf CUs.
+ // Even thought for non-skeleton-cu all names are in .debug_str.dwo section,
+ // for the .debug_names contributions they are in .debug_str section.
+ if (BC.getNumDWOCUs()) {
+ DataExtractor StrData(BC.DwCtx->getDWARFObj().getStrSection(),
+ BC.DwCtx->isLittleEndian(), 0);
+ uint64_t Offset = 0;
+ uint64_t StrOffset = 0;
+ while (StrData.isValidOffset(Offset)) {
+ Error Err = Error::success();
+ const char *CStr = StrData.getCStr(&Offset, &Err);
+ if (Err) {
+ NeedToCreate = false;
+ errs() << "BOLT-WARNING: [internal-dwarf-error]: Could not extract "
+ "string from .debug_str section at offset: "
+ << Twine::utohexstr(StrOffset) << ".\n";
+ return;
+ }
+ auto R = StrCacheToOffsetMap.try_emplace(
+ llvm::hash_value(llvm::StringRef(CStr)), StrOffset);
+ if (!R.second)
+ errs() << "BOLT-WARNING: [internal-dwarf-error]: collision occured on "
+ << CStr << " at offset : 0x" << Twine::utohexstr(StrOffset)
+ << ". Previous string offset is: 0x"
+ << Twine::utohexstr(R.first->second) << ".\n";
+ StrOffset = Offset;
+ }
+ }
+}
+
+void DWARF5AcceleratorTable::setCurrentUnit(DWARFUnit &Unit,
+ const uint64_t UnitStartOffset) {
+ CurrentUnit = nullptr;
+ CurrentUnitOffset = UnitStartOffset;
+ std::optional<uint64_t> DWOID = Unit.getDWOId();
+ // We process Skelton CUs after DWO Units for it.
+ // Patching offset in CU list to correct one.
+ if (!Unit.isDWOUnit() && DWOID) {
+ auto Iter = CUOffsetsToPatch.find(*DWOID);
+ // Check in case no entries were added from non skeleton DWO section.
+ if (Iter != CUOffsetsToPatch.end())
+ CUList[Iter->second] = UnitStartOffset;
+ }
+}
+
+void DWARF5AcceleratorTable::addUnit(DWARFUnit &Unit,
+ const std::optional<uint64_t> &DWOID) {
+ StrOffsetsWriter.clear();
+ StrOffsetsWriter.initialize(Unit);
+ StrSection = Unit.getStringSection();
+ if (Unit.isTypeUnit()) {
+ if (DWOID) {
+ // We adding an entry for a DWO TU. The DWO CU might not have any entries,
+ // so need to add it to the list pre-emptively.
+ auto Iter = CUOffsetsToPatch.insert({*DWOID, CUList.size()});
+ if (Iter.second)
+ CUList.push_back(0xBADBAD);
+ ForeignTUList.push_back(
+ cast_or_null<DWARFTypeUnit>(&Unit)->getTypeHash());
+ } else {
+ LocalTUList.push_back(CurrentUnitOffset);
+ }
+ } else {
+ if (DWOID) {
+ // This is a path for split dwarf without type units.
+ // We process DWO Units before Skeleton CU. So at this point we don't know
+ // the offset of Skeleton CU. Adding CULit index to a map to patch later
+ // with the correct offset.
+ auto Iter = CUOffsetsToPatch.insert({*DWOID, CUList.size()});
+ if (Iter.second)
+ CUList.push_back(0xBADBAD);
+ } else {
+ CUList.push_back(CurrentUnitOffset);
+ }
+ }
+}
+
+// Returns true if DW_TAG_variable should be included in .debug-names based on
+// section 6.1.1.1 for DWARF5 spec.
+static bool shouldIncludeVariable(const DWARFUnit &Unit, const DIE &Die) {
+ if (Die.findAttribute(dwarf::Attribute::DW_AT_declaration))
+ return false;
+ const DIEValue LocAttrInfo =
+ Die.findAttribute(dwarf::Attribute::DW_AT_location);
+ if (!LocAttrInfo)
+ return false;
+ if (!(doesFormBelongToClass(LocAttrInfo.getForm(), DWARFFormValue::FC_Exprloc,
+ Unit.getVersion()) ||
+ doesFormBelongToClass(LocAttrInfo.getForm(), DWARFFormValue::FC_Block,
+ Unit.getVersion())))
+ return false;
+ std::vector<uint8_t> Sblock;
+ auto constructVect =
+ [&](const DIEValueList::const_value_range &Iter) -> void {
+ for (const DIEValue &Val : Iter)
+ Sblock.push_back(Val.getDIEInteger().getValue());
+ };
+ if (doesFormBelongToClass(LocAttrInfo.getForm(), DWARFFormValue::FC_Exprloc,
+ Unit.getVersion()))
+ constructVect(LocAttrInfo.getDIELoc().values());
+ else
+ constructVect(LocAttrInfo.getDIEBlock().values());
+ ArrayRef<uint8_t> Expr = ArrayRef<uint8_t>(Sblock);
+ DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()),
+ Unit.getContext().isLittleEndian(), 0);
+ DWARFExpression LocExpr(Data, Unit.getAddressByteSize(),
+ Unit.getFormParams().Format);
+ for (const DWARFExpression::Operation &Expr : LocExpr)
----------------
dcci wrote:
trying to confirm -- is this correct? i.e. as long as you have at least (not all) the locexpr being `addrx` or `form_tls_address`, do they qualify to be included in `.debug_names` ?
https://github.com/llvm/llvm-project/pull/81062
More information about the llvm-commits
mailing list