.arcconfig→/dev/null
@@ -1,8 +0,0 @@
-{
- "phabricator.uri" : "https://reviews.llvm.org/",
- "repository.callsign" : "G",
- "conduit_uri" : "https://reviews.llvm.org/",
- "base": "git:HEAD^",
- "arc.land.onto.default": "main",
- "arc.land.onto": ["main"]
-}
.arclint→/dev/null
@@ -1,15 +0,0 @@
-{
- "linters": {
- "clang-format": {
- "type": "script-and-regex",
- "script-and-regex.script": "bash utils/arcanist/clang-format.sh",
- "script-and-regex.regex": "/^(?P<severity>[[:alpha:]]+)\n(?P<message>[^\n]+)\n(====|(?P<line>\\d),(?P<char>\\d)\n(?P<original>.*)>>>>\n(?P<replacement>.*)<<<<\n)$/s",
- "include": [
- "(\\.(cc|cpp|h)$)"
- ],
- "exclude": [
- "(^clang/test/)"
- ]
- }
- }
-}
.ci/generate-buildkite-pipeline-premerge
@@ -68,7 +68,7 @@ function compute-projects-to-test() {
done done
;; ;;
clang) clang)
- for p in clang-tools-extra compiler-rt flang libc lldb openmp cross-project-tests; do+ for p in clang-tools-extra compiler-rt flang lldb cross-project-tests; do
echo $p echo $p
done done
;; ;;
@@ -224,7 +224,7 @@ fi
# needs while letting them run on the infrastructure provided by LLVM. # needs while letting them run on the infrastructure provided by LLVM.
# Figure out which projects need to be built on each platform # Figure out which projects need to be built on each platform
-all_projects="bolt clang-tools-extra compiler-rt cross-project-tests flang libc libclc lld lldb llvm mlir openmp polly pstl"+all_projects="bolt clang clang-tools-extra compiler-rt cross-project-tests flang libc libclc lld lldb llvm mlir openmp polly pstl"
modified_projects="$(keep-modified-projects ${all_projects})" modified_projects="$(keep-modified-projects ${all_projects})"
linux_projects_to_test=$(exclude-linux $(compute-projects-to-test ${modified_projects})) linux_projects_to_test=$(exclude-linux $(compute-projects-to-test ${modified_projects}))
.ci/monolithic-linux.sh
@@ -54,4 +54,4 @@ cmake -S ${MONOREPO_ROOT}/llvm -B ${BUILD_DIR} \
echo "--- ninja" echo "--- ninja"
# Targets are not escaped as they are passed as separate arguments. # Targets are not escaped as they are passed as separate arguments.
-ninja -C "${BUILD_DIR}" ${targets}+ninja -C "${BUILD_DIR}" -k 0 ${targets}
.ci/monolithic-windows.sh
@@ -62,4 +62,4 @@ cmake -S ${MONOREPO_ROOT}/llvm -B ${BUILD_DIR} \
echo "--- ninja" echo "--- ninja"
# Targets are not escaped as they are passed as separate arguments. # Targets are not escaped as they are passed as separate arguments.
-ninja -C "${BUILD_DIR}" ${targets}+ninja -C "${BUILD_DIR}" -k 0 ${targets}
.clang-tidy
@@ -1,4 +1,4 @@
-Checks: '-*,clang-diagnostic-*,llvm-*,misc-*,-misc-const-correctness,-misc-unused-parameters,-misc-non-private-member-variables-in-classes,-misc-no-recursion,-misc-use-anonymous-namespace,readability-identifier-naming'+Checks: '-*,clang-diagnostic-*,llvm-*,misc-*,-misc-const-correctness,-misc-unused-parameters,-misc-non-private-member-variables-in-classes,-misc-no-recursion,-misc-use-anonymous-namespace,readability-identifier-naming,-misc-include-cleaner'
CheckOptions: CheckOptions:
- key: readability-identifier-naming.ClassCase - key: readability-identifier-naming.ClassCase
value: CamelCase value: CamelCase
.github/CODEOWNERS
@@ -27,10 +27,14 @@
/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp @nikic /llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp @nikic
/llvm/lib/Transforms/InstCombine/ @nikic /llvm/lib/Transforms/InstCombine/ @nikic
+/clang/include/clang/Sema/Sema.h @Endilll
/clang/test/CXX/drs/ @Endilll /clang/test/CXX/drs/ @Endilll
/clang/www/cxx_dr_status.html @Endilll /clang/www/cxx_dr_status.html @Endilll
/clang/www/make_cxx_dr_status @Endilll /clang/www/make_cxx_dr_status @Endilll
+clang/lib/AST/Interp/ @tbaederr
+clang/test/AST/Interp/ @tbaederr
+
/lldb/ @JDevlieghere /lldb/ @JDevlieghere
# MLIR Interfaces. # MLIR Interfaces.
.github/new-prs-labeler.yml
@@ -869,6 +869,9 @@ backend:SystemZ:
third-party:unittests: third-party:unittests:
- third-party/unittests/** - third-party/unittests/**
+third-party:benchmark:
+ - third-party/benchmark/**
+
llvm:binary-utilities: llvm:binary-utilities:
- llvm/docs/CommandGuide/llvm-* - llvm/docs/CommandGuide/llvm-*
- llvm/include/llvm/BinaryFormat/** - llvm/include/llvm/BinaryFormat/**
.github/workflows/build-ci-container.yml
@@ -77,14 +77,18 @@ jobs:
cp ./.github/workflows/containers/github-action-ci/storage.conf ~/.config/containers/storage.conf cp ./.github/workflows/containers/github-action-ci/storage.conf ~/.config/containers/storage.conf
podman info podman info
+ # Download the container image into /mnt/podman rather than
+ # $GITHUB_WORKSPACE to avoid space limitations on the default drive
+ # and use the permissions setup for /mnt/podman.
- name: Download stage1-toolchain - name: Download stage1-toolchain
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
with: with:
name: stage1-toolchain name: stage1-toolchain
+ path: /mnt/podman
- name: Load stage1-toolchain - name: Load stage1-toolchain
run: | run: |
- podman load -i stage1-toolchain.tar+ podman load -i /mnt/podman/stage1-toolchain.tar
- name: Build Container - name: Build Container
working-directory: ./.github/workflows/containers/github-action-ci/ working-directory: ./.github/workflows/containers/github-action-ci/
.github/workflows/containers/github-action-ci/stage2.Dockerfile
@@ -12,11 +12,13 @@ COPY --from=stage2-toolchain $LLVM_SYSROOT $LLVM_SYSROOT
# Need to install curl for hendrikmuhs/ccache-action # Need to install curl for hendrikmuhs/ccache-action
# Need nodejs for some of the GitHub actions. # Need nodejs for some of the GitHub actions.
# Need perl-modules for clang analyzer tests. # Need perl-modules for clang analyzer tests.
+# Need git for SPIRV-Tools tests.
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y \ apt-get install -y \
binutils \ binutils \
cmake \ cmake \
curl \ curl \
+ git \
libstdc++-11-dev \ libstdc++-11-dev \
ninja-build \ ninja-build \
nodejs \ nodejs \
.github/workflows/issue-release-workflow.yml
@@ -65,5 +65,5 @@ jobs:
release-workflow \ release-workflow \
--branch-repo-token ${{ secrets.RELEASE_WORKFLOW_PUSH_SECRET }} \ --branch-repo-token ${{ secrets.RELEASE_WORKFLOW_PUSH_SECRET }} \
--issue-number ${{ github.event.issue.number }} \ --issue-number ${{ github.event.issue.number }} \
- --requested-by ${{ github.event.issue.user.login }} \+ --requested-by ${{ (github.event.action == 'opened' && github.event.issue.user.login) || github.event.comment.user.login }} \
auto auto
.github/workflows/llvm-project-tests.yml
@@ -118,6 +118,11 @@ jobs:
else else
builddir="$(pwd)"/build builddir="$(pwd)"/build
fi fi
+ if [ "${{ runner.os }}" == "macOS" ]; then
+ # Workaround test failure on some lld tests on MacOS
+ # https://github.com/llvm/llvm-project/issues/81967
+ extra_cmake_args="-DLLVM_DISABLE_ASSEMBLY_FILES=ON"
+ fi
echo "llvm-builddir=$builddir" >> "$GITHUB_OUTPUT" echo "llvm-builddir=$builddir" >> "$GITHUB_OUTPUT"
cmake -G Ninja \ cmake -G Ninja \
-B "$builddir" \ -B "$builddir" \
.github/workflows/release-binaries.yml
@@ -35,6 +35,7 @@ jobs:
prepare: prepare:
name: Prepare to build binaries name: Prepare to build binaries
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
+ if: github.repository == 'llvm/llvm-project'
outputs: outputs:
release-version: ${{ steps.vars.outputs.release-version }} release-version: ${{ steps.vars.outputs.release-version }}
flags: ${{ steps.vars.outputs.flags }} flags: ${{ steps.vars.outputs.flags }}
@@ -47,11 +48,16 @@ jobs:
- name: Checkout LLVM - name: Checkout LLVM
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - name: Install Dependencies
+ run: |
+ pip install -r ./llvm/utils/git/requirements.txt
+
- name: Check Permissions - name: Check Permissions
env: env:
GITHUB_TOKEN: ${{ github.token }} GITHUB_TOKEN: ${{ github.token }}
+ USER_TOKEN: ${{ secrets.RELEASE_TASKS_USER_TOKEN }}
run: | run: |
- ./llvm/utils/release/./github-upload-release.py --token "$GITHUB_TOKEN" --user ${{ github.actor }} check-permissions+ ./llvm/utils/release/./github-upload-release.py --token "$GITHUB_TOKEN" --user ${{ github.actor }} --user-token "$USER_TOKEN" check-permissions
- name: Collect Variables - name: Collect Variables
id: vars id: vars
@@ -65,8 +71,8 @@ jobs:
# | X.Y.Z | -final # | X.Y.Z | -final
run: | run: |
tag="${{ github.ref_name }}" tag="${{ github.ref_name }}"
- trimmed=$(echo ${{ inputs.tag }} | xargs)+ trimmed=$(echo ${{ inputs.release-version }} | xargs)
- [[ "$trimmed" != "" ]] && tag="$trimmed"+ [[ "$trimmed" != "" ]] && tag="llvmorg-$trimmed"
if [ "$tag" = "main" ]; then if [ "$tag" = "main" ]; then
# If tag is main, then we've been triggered by a scheduled so pass so # If tag is main, then we've been triggered by a scheduled so pass so
# use the head commit as the tag. # use the head commit as the tag.
@@ -85,6 +91,7 @@ jobs:
name: "Fill Cache ${{ matrix.os }}" name: "Fill Cache ${{ matrix.os }}"
needs: prepare needs: prepare
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
+ if: github.repository == 'llvm/llvm-project'
strategy: strategy:
matrix: matrix:
os: os:
@@ -119,6 +126,7 @@ jobs:
- prepare - prepare
- fill-cache - fill-cache
runs-on: ${{ matrix.target.runs-on }} runs-on: ${{ matrix.target.runs-on }}
+ if: github.repository == 'llvm/llvm-project'
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
bolt/include/bolt/Core/BinaryContext.h
@@ -997,6 +997,10 @@ public:
return getUniqueSectionByName(".gdb_index"); return getUniqueSectionByName(".gdb_index");
} }
+ ErrorOr<BinarySection &> getDebugNamesSection() const {
+ return getUniqueSectionByName(".debug_names");
+ }
+
/// @} /// @}
/// Register \p TargetFunction as a fragment of \p Function if checks pass: /// Register \p TargetFunction as a fragment of \p Function if checks pass:
bolt/include/bolt/Core/BinaryFunction.h
@@ -2056,6 +2056,14 @@ public:
/// Returns false if disassembly failed. /// Returns false if disassembly failed.
Error disassemble(); Error disassemble();
+ /// An external interface to register a branch while the function is in
+ /// disassembled state. Allows to make custom modifications to the
+ /// disassembler. E.g., a pre-CFG pass can add an instruction and register
+ /// a branch that will later be used during the CFG construction.
+ ///
+ /// Return a label at the branch destination.
+ MCSymbol *registerBranch(uint64_t Src, uint64_t Dst);
+
Error handlePCRelOperand(MCInst &Instruction, uint64_t Address, Error handlePCRelOperand(MCInst &Instruction, uint64_t Address,
uint64_t Size); uint64_t Size);
bolt/include/bolt/Core/DIEBuilder.h
@@ -16,6 +16,7 @@
#define BOLT_CORE_DIE_BUILDER_H #define BOLT_CORE_DIE_BUILDER_H
#include "bolt/Core/BinaryContext.h" #include "bolt/Core/BinaryContext.h"
+#include "bolt/Core/DebugNames.h"
#include "llvm/CodeGen/DIE.h" #include "llvm/CodeGen/DIE.h"
#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
#include "llvm/DebugInfo/DWARF/DWARFDie.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h"
@@ -127,6 +128,7 @@ private:
DWARFUnit *SkeletonCU{nullptr}; DWARFUnit *SkeletonCU{nullptr};
uint64_t UnitSize{0}; uint64_t UnitSize{0};
llvm::DenseSet<uint64_t> AllProcessed; llvm::DenseSet<uint64_t> AllProcessed;
+ DWARF5AcceleratorTable &DebugNamesTable;
/// Returns current state of the DIEBuilder /// Returns current state of the DIEBuilder
State &getState() { return *BuilderState.get(); } State &getState() { return *BuilderState.get(); }
@@ -206,8 +208,8 @@ private:
/// Update references once the layout is finalized. /// Update references once the layout is finalized.
void updateReferences(); void updateReferences();
- /// Update the Offset and Size of DIE.+ /// Update the Offset and Size of DIE, populate DebugNames table.
- uint32_t computeDIEOffset(const DWARFUnit &CU, DIE &Die, uint32_t &CurOffset);+ uint32_t finalizeDIEs(DWARFUnit &CU, DIE &Die, uint32_t &CurOffset);
void registerUnit(DWARFUnit &DU, bool NeedSort); void registerUnit(DWARFUnit &DU, bool NeedSort);
@@ -269,6 +271,7 @@ private:
public: public:
DIEBuilder(BinaryContext &BC, DWARFContext *DwarfContext, DIEBuilder(BinaryContext &BC, DWARFContext *DwarfContext,
+ DWARF5AcceleratorTable &DebugNamesTable,
DWARFUnit *SkeletonCU = nullptr); DWARFUnit *SkeletonCU = nullptr);
/// Returns enum to what we are currently processing. /// Returns enum to what we are currently processing.
bolt/include/bolt/Core/DebugData.h
@@ -439,6 +439,8 @@ public:
/// Update Str offset in .debug_str in .debug_str_offsets. /// Update Str offset in .debug_str in .debug_str_offsets.
void updateAddressMap(uint32_t Index, uint32_t Address); void updateAddressMap(uint32_t Index, uint32_t Address);
+ /// Get offset for given index in original .debug_str_offsets section.
+ uint64_t getOffset(uint32_t Index) const { return StrOffsets[Index]; }
/// Writes out current sections entry into .debug_str_offsets. /// Writes out current sections entry into .debug_str_offsets.
void finalizeSection(DWARFUnit &Unit, DIEBuilder &DIEBldr); void finalizeSection(DWARFUnit &Unit, DIEBuilder &DIEBldr);
@@ -463,7 +465,7 @@ private:
std::unique_ptr<DebugStrOffsetsBufferVector> StrOffsetsBuffer; std::unique_ptr<DebugStrOffsetsBufferVector> StrOffsetsBuffer;
std::unique_ptr<raw_svector_ostream> StrOffsetsStream; std::unique_ptr<raw_svector_ostream> StrOffsetsStream;
std::map<uint32_t, uint32_t> IndexToAddressMap; std::map<uint32_t, uint32_t> IndexToAddressMap;
- std::vector<uint32_t> StrOffsets;+ SmallVector<uint32_t, 5> StrOffsets;
std::unordered_map<uint64_t, uint64_t> ProcessedBaseOffsets; std::unordered_map<uint64_t, uint64_t> ProcessedBaseOffsets;
bool StrOffsetSectionWasModified = false; bool StrOffsetSectionWasModified = false;
}; };
@@ -484,11 +486,12 @@ public:
/// Returns False if no strings were added to .debug_str. /// Returns False if no strings were added to .debug_str.
bool isInitialized() const { return !StrBuffer->empty(); } bool isInitialized() const { return !StrBuffer->empty(); }
+ /// Initializes Buffer and Stream.
+ void initialize();
+
private: private:
/// Mutex used for parallel processing of debug info. /// Mutex used for parallel processing of debug info.
std::mutex WriterMutex; std::mutex WriterMutex;
- /// Initializes Buffer and Stream.
- void initialize();
/// Creates internal data structures. /// Creates internal data structures.
void create(); void create();
std::unique_ptr<DebugStrBufferVector> StrBuffer; std::unique_ptr<DebugStrBufferVector> StrBuffer;
bolt/include/bolt/Core/DebugNames.h
@@ -0,0 +1,172 @@
+//===- bolt/Core/DebugNames.h - Debug names support ---*- C++
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains declaration of classes required for generation of
+// .debug_names section.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef BOLT_CORE_DEBUG_NAMES_H
+#define BOLT_CORE_DEBUG_NAMES_H
+
+#include "DebugData.h"
+#include "llvm/CodeGen/AccelTable.h"
+
+namespace llvm {
+namespace bolt {
+class BOLTDWARF5AccelTableData : public DWARF5AccelTableData {
+public:
+ BOLTDWARF5AccelTableData(const uint64_t DieOffset,
+ const std::optional<uint64_t> DefiningParentOffset,
+ const unsigned DieTag, const unsigned UnitID,
+ const bool IsTU,
+ const std::optional<unsigned> SecondUnitID)
+ : DWARF5AccelTableData(DieOffset, DefiningParentOffset, DieTag, UnitID,
+ IsTU),
+ SecondUnitID(SecondUnitID) {}
+
+ uint64_t getDieOffset() const { return DWARF5AccelTableData::getDieOffset(); }
+ unsigned getDieTag() const { return DWARF5AccelTableData::getDieTag(); }
+ unsigned getUnitID() const { return DWARF5AccelTableData::getUnitID(); }
+ bool isTU() const { return DWARF5AccelTableData::isTU(); }
+ std::optional<unsigned> getSecondUnitID() const { return SecondUnitID; }
+
+private:
+ std::optional<unsigned> SecondUnitID;
+};
+
+class DWARF5AcceleratorTable {
+public:
+ DWARF5AcceleratorTable(const bool CreateDebugNames, BinaryContext &BC,
+ DebugStrWriter &MainBinaryStrWriter);
+ ~DWARF5AcceleratorTable() {
+ for (DebugNamesAbbrev *Abbrev : AbbreviationsVector)
+ Abbrev->~DebugNamesAbbrev();
+ }
+ /// Add DWARF5 Accelerator table entry.
+ /// Input is DWARFUnit being processed, DIE that belongs to it, and potential
+ /// SkeletonCU if the Unit comes from a DWO section.
+ void addAccelTableEntry(DWARFUnit &Unit, const DIE &Die,
+ const std::optional<uint64_t> &DWOID);
+ /// Set current unit being processed.
+ void setCurrentUnit(DWARFUnit &Unit, const uint64_t UnitStartOffset);
+ /// Emit Accelerator table.
+ void emitAccelTable();
+ /// Returns true if the table was crated.
+ bool isCreated() const { return NeedToCreate; }
+ /// Returns buffer containing the accelerator table.
+ std::unique_ptr<DebugBufferVector> releaseBuffer() {
+ return std::move(FullTableBuffer);
+ }
+
+private:
+ BinaryContext &BC;
+ bool NeedToCreate = false;
+ BumpPtrAllocator Allocator;
+ DebugStrWriter &MainBinaryStrWriter;
+ StringRef StrSection;
+ uint64_t CurrentUnitOffset = 0;
+ const DWARFUnit *CurrentUnit = nullptr;
+ std::unordered_map<uint32_t, uint32_t> AbbrevTagToIndexMap;
+
+ /// Represents a group of entries with identical name (and hence, hash value).
+ struct HashData {
+ uint64_t StrOffset;
+ uint32_t HashValue;
+ uint32_t EntryOffset;
+ std::vector<BOLTDWARF5AccelTableData *> Values;
+ };
+ using HashList = std::vector<HashData *>;
+ using BucketList = std::vector<HashList>;
+ /// Contains all the offsets of CUs.
+ SmallVector<uint32_t, 1> CUList;
+ /// Contains all the offsets of local TUs.
+ SmallVector<uint32_t, 1> LocalTUList;
+ /// Contains all the type hashes for split dwarf TUs.
+ SmallVector<uint64_t, 1> ForeignTUList;
+ using StringEntries =
+ MapVector<std::string, HashData, llvm::StringMap<unsigned>>;
+ StringEntries Entries;
+ /// FoldingSet that uniques the abbreviations.
+ FoldingSet<DebugNamesAbbrev> AbbreviationsSet;
+ /// Vector containing DebugNames abbreviations for iteration in order.
+ SmallVector<DebugNamesAbbrev *, 5> AbbreviationsVector;
+ /// The bump allocator to use when creating DIEAbbrev objects in the uniqued
+ /// storage container.
+ BumpPtrAllocator Alloc;
+ uint32_t BucketCount = 0;
+ uint32_t UniqueHashCount = 0;
+ uint32_t AbbrevTableSize = 0;
+ uint32_t CUIndexEncodingSize = 4;
+ uint32_t TUIndexEncodingSize = 4;
+ uint32_t AugmentationStringSize = 0;
+ dwarf::Form CUIndexForm = dwarf::DW_FORM_data4;
+ dwarf::Form TUIndexForm = dwarf::DW_FORM_data4;
+
+ BucketList Buckets;
+
+ std::unique_ptr<DebugBufferVector> FullTableBuffer;
+ std::unique_ptr<raw_svector_ostream> FullTableStream;
+ std::unique_ptr<DebugBufferVector> StrBuffer;
+ std::unique_ptr<raw_svector_ostream> StrStream;
+ std::unique_ptr<DebugBufferVector> EntriesBuffer;
+ std::unique_ptr<raw_svector_ostream> Entriestream;
+ std::unique_ptr<DebugBufferVector> AugStringBuffer;
+ std::unique_ptr<raw_svector_ostream> AugStringtream;
+ llvm::DenseMap<llvm::hash_code, uint64_t> StrCacheToOffsetMap;
+ // Contains DWO ID to CUList Index.
+ llvm::DenseMap<uint64_t, uint32_t> CUOffsetsToPatch;
+ /// Adds Unit to either CUList, LocalTUList or ForeignTUList.
+ /// Input Unit being processed, and DWO ID if Unit is being processed comes
+ /// from a DWO section.
+ void addUnit(DWARFUnit &Unit, const std::optional<uint64_t> &DWOID);
+ /// Returns number of buckets in .debug_name table.
+ ArrayRef<HashList> getBuckets() const { return Buckets; }
+ /// Get encoding for a given attribute.
+ std::optional<DWARF5AccelTable::UnitIndexAndEncoding>
+ getIndexForEntry(const BOLTDWARF5AccelTableData &Value) const;
+ /// Get encoding for a given attribute for second index.
+ /// Returns nullopt if there is no second index.
+ std::optional<DWARF5AccelTable::UnitIndexAndEncoding>
+ getSecondIndexForEntry(const BOLTDWARF5AccelTableData &Value) const;
+ /// Uniquify Entries.
+ void finalize();
+ /// Computes bucket count.
+ void computeBucketCount();
+ /// Populate Abbreviations Map.
+ void populateAbbrevsMap();
+ /// Write Entries.
+ void writeEntries();
+ /// Write an Entry.
+ void writeEntry(const BOLTDWARF5AccelTableData &Entry);
+ /// Write augmentation_string for BOLT.
+ void writeAugmentationString();
+ /// Emit out Header for DWARF5 Accelerator table.
+ void emitHeader() const;
+ /// Emit out CU list.
+ void emitCUList() const;
+ /// Emit out TU List. Combination of LocalTUList and ForeignTUList.
+ void emitTUList() const;
+ /// Emit buckets.
+ void emitBuckets() const;
+ /// Emit hashes for hash table.
+ void emitHashes() const;
+ /// Emit string offsets for hash table.
+ void emitStringOffsets() const;
+ /// Emit Entry Offsets for hash table.
+ void emitOffsets() const;
+ /// Emit abbreviation table.
+ void emitAbbrevs();
+ /// Emit entries.
+ void emitData();
+ /// Emit augmentation string.
+ void emitAugmentationString() const;
+};
+} // namespace bolt
+} // namespace llvm
+#endif
bolt/include/bolt/Core/MCPlusBuilder.h
@@ -487,10 +487,9 @@ public:
llvm_unreachable("not implemented"); llvm_unreachable("not implemented");
} }
- virtual bool createDirectCall(MCInst &Inst, const MCSymbol *Target,+ virtual void createDirectCall(MCInst &Inst, const MCSymbol *Target,
MCContext *Ctx, bool IsTailCall) { MCContext *Ctx, bool IsTailCall) {
llvm_unreachable("not implemented"); llvm_unreachable("not implemented");
- return false;
} }
virtual MCPhysReg getX86R11() const { llvm_unreachable("not implemented"); } virtual MCPhysReg getX86R11() const { llvm_unreachable("not implemented"); }
@@ -620,7 +619,17 @@ public:
return Info->get(Inst.getOpcode()).mayStore(); return Info->get(Inst.getOpcode()).mayStore();
} }
- virtual bool isAArch64Exclusive(const MCInst &Inst) const {+ virtual bool isAArch64ExclusiveLoad(const MCInst &Inst) const {
+ llvm_unreachable("not implemented");
+ return false;
+ }
+
+ virtual bool isAArch64ExclusiveStore(const MCInst &Inst) const {
+ llvm_unreachable("not implemented");
+ return false;
+ }
+
+ virtual bool isAArch64ExclusiveClear(const MCInst &Inst) const {
llvm_unreachable("not implemented"); llvm_unreachable("not implemented");
return false; return false;
} }
@@ -1173,11 +1182,16 @@ public:
bool clearOffset(MCInst &Inst) const; bool clearOffset(MCInst &Inst) const;
/// Return the label of \p Inst, if available. /// Return the label of \p Inst, if available.
- MCSymbol *getLabel(const MCInst &Inst) const;+ MCSymbol *getInstLabel(const MCInst &Inst) const;
+
+ /// Set the label of \p Inst or return the existing label for the instruction.
+ /// This label will be emitted right before \p Inst is emitted to MCStreamer.
+ MCSymbol *getOrCreateInstLabel(MCInst &Inst, const Twine &Name,
+ MCContext *Ctx) const;
/// Set the label of \p Inst. This label will be emitted right before \p Inst /// Set the label of \p Inst. This label will be emitted right before \p Inst
/// is emitted to MCStreamer. /// is emitted to MCStreamer.
- bool setLabel(MCInst &Inst, MCSymbol *Label) const;+ void setInstLabel(MCInst &Inst, MCSymbol *Label) const;
/// Get instruction size specified via annotation. /// Get instruction size specified via annotation.
std::optional<uint32_t> getSize(const MCInst &Inst) const; std::optional<uint32_t> getSize(const MCInst &Inst) const;
@@ -1519,15 +1533,13 @@ public:
} }
/// Create a no-op instruction. /// Create a no-op instruction.
- virtual bool createNoop(MCInst &Inst) const {+ virtual void createNoop(MCInst &Inst) const {
llvm_unreachable("not implemented"); llvm_unreachable("not implemented");
- return false;
} }
/// Create a return instruction. /// Create a return instruction.
- virtual bool createReturn(MCInst &Inst) const {+ virtual void createReturn(MCInst &Inst) const {
llvm_unreachable("not implemented"); llvm_unreachable("not implemented");
- return false;
} }
/// Store \p Target absolute address to \p RegName /// Store \p Target absolute address to \p RegName
@@ -1541,32 +1553,30 @@ public:
/// Creates a new unconditional branch instruction in Inst and set its operand /// Creates a new unconditional branch instruction in Inst and set its operand
/// to TBB. /// to TBB.
- ///+ virtual void createUncondBranch(MCInst &Inst, const MCSymbol *TBB,
- /// Returns true on success.
- virtual bool createUncondBranch(MCInst &Inst, const MCSymbol *TBB,
MCContext *Ctx) const { MCContext *Ctx) const {
llvm_unreachable("not implemented"); llvm_unreachable("not implemented");
- return false;+ }
+
+ /// Create a version of unconditional jump that has the largest span for a
+ /// single instruction with direct target.
+ virtual void createLongUncondBranch(MCInst &Inst, const MCSymbol *Target,
+ MCContext *Ctx) const {
+ llvm_unreachable("not implemented");
} }
/// Creates a new call instruction in Inst and sets its operand to /// Creates a new call instruction in Inst and sets its operand to
/// Target. /// Target.
- ///+ virtual void createCall(MCInst &Inst, const MCSymbol *Target,
- /// Returns true on success.
- virtual bool createCall(MCInst &Inst, const MCSymbol *Target,
MCContext *Ctx) { MCContext *Ctx) {
llvm_unreachable("not implemented"); llvm_unreachable("not implemented");
- return false;
} }
/// Creates a new tail call instruction in Inst and sets its operand to /// Creates a new tail call instruction in Inst and sets its operand to
/// Target. /// Target.
- ///+ virtual void createTailCall(MCInst &Inst, const MCSymbol *Target,
- /// Returns true on success.
- virtual bool createTailCall(MCInst &Inst, const MCSymbol *Target,
MCContext *Ctx) { MCContext *Ctx) {
llvm_unreachable("not implemented"); llvm_unreachable("not implemented");
- return false;
} }
virtual void createLongTailCall(InstructionListType &Seq, virtual void createLongTailCall(InstructionListType &Seq,
@@ -1575,43 +1585,36 @@ public:
} }
/// Creates a trap instruction in Inst. /// Creates a trap instruction in Inst.
- ///+ virtual void createTrap(MCInst &Inst) const {
- /// Returns true on success.
- virtual bool createTrap(MCInst &Inst) const {
llvm_unreachable("not implemented"); llvm_unreachable("not implemented");
- return false;
} }
/// Creates an instruction to bump the stack pointer just like a call. /// Creates an instruction to bump the stack pointer just like a call.
- virtual bool createStackPointerIncrement(MCInst &Inst, int Size = 8,+ virtual void createStackPointerIncrement(MCInst &Inst, int Size = 8,
bool NoFlagsClobber = false) const { bool NoFlagsClobber = false) const {
llvm_unreachable("not implemented"); llvm_unreachable("not implemented");
- return false;
} }
/// Creates an instruction to move the stack pointer just like a ret. /// Creates an instruction to move the stack pointer just like a ret.
- virtual bool createStackPointerDecrement(MCInst &Inst, int Size = 8,+ virtual void createStackPointerDecrement(MCInst &Inst, int Size = 8,
bool NoFlagsClobber = false) const { bool NoFlagsClobber = false) const {
llvm_unreachable("not implemented"); llvm_unreachable("not implemented");
- return false;
} }
/// Create a store instruction using \p StackReg as the base register /// Create a store instruction using \p StackReg as the base register
/// and \p Offset as the displacement. /// and \p Offset as the displacement.
- virtual bool createSaveToStack(MCInst &Inst, const MCPhysReg &StackReg,+ virtual void createSaveToStack(MCInst &Inst, const MCPhysReg &StackReg,
int Offset, const MCPhysReg &SrcReg, int Offset, const MCPhysReg &SrcReg,
int Size) const { int Size) const {
llvm_unreachable("not implemented"); llvm_unreachable("not implemented");
- return false;
} }
- virtual bool createLoad(MCInst &Inst, const MCPhysReg &BaseReg, int64_t Scale,+ virtual void createLoad(MCInst &Inst, const MCPhysReg &BaseReg, int64_t Scale,
const MCPhysReg &IndexReg, int64_t Offset, const MCPhysReg &IndexReg, int64_t Offset,
const MCExpr *OffsetExpr, const MCExpr *OffsetExpr,
const MCPhysReg &AddrSegmentReg, const MCPhysReg &AddrSegmentReg,
const MCPhysReg &DstReg, int Size) const { const MCPhysReg &DstReg, int Size) const {
llvm_unreachable("not implemented"); llvm_unreachable("not implemented");
- return false;
} }
virtual InstructionListType createLoadImmediate(const MCPhysReg Dest, virtual InstructionListType createLoadImmediate(const MCPhysReg Dest,
@@ -1621,32 +1624,27 @@ public:
/// Create a fragment of code (sequence of instructions) that load a 32-bit /// Create a fragment of code (sequence of instructions) that load a 32-bit
/// address from memory, zero-extends it to 64 and jump to it (indirect jump). /// address from memory, zero-extends it to 64 and jump to it (indirect jump).
- virtual bool+ virtual void
createIJmp32Frag(SmallVectorImpl<MCInst> &Insts, const MCOperand &BaseReg, createIJmp32Frag(SmallVectorImpl<MCInst> &Insts, const MCOperand &BaseReg,
const MCOperand &Scale, const MCOperand &IndexReg, const MCOperand &Scale, const MCOperand &IndexReg,
const MCOperand &Offset, const MCOperand &TmpReg) const { const MCOperand &Offset, const MCOperand &TmpReg) const {
llvm_unreachable("not implemented"); llvm_unreachable("not implemented");
- return false;
} }
/// Create a load instruction using \p StackReg as the base register /// Create a load instruction using \p StackReg as the base register
/// and \p Offset as the displacement. /// and \p Offset as the displacement.
- virtual bool createRestoreFromStack(MCInst &Inst, const MCPhysReg &StackReg,+ virtual void createRestoreFromStack(MCInst &Inst, const MCPhysReg &StackReg,
int Offset, const MCPhysReg &DstReg, int Offset, const MCPhysReg &DstReg,
int Size) const { int Size) const {
llvm_unreachable("not implemented"); llvm_unreachable("not implemented");
- return false;
} }
/// Creates a call frame pseudo instruction. A single operand identifies which /// Creates a call frame pseudo instruction. A single operand identifies which
/// MCCFIInstruction this MCInst is referring to. /// MCCFIInstruction this MCInst is referring to.
- ///+ virtual void createCFI(MCInst &Inst, int64_t Offset) const {
- /// Returns true on success.
- virtual bool createCFI(MCInst &Inst, int64_t Offset) const {
Inst.clear(); Inst.clear();
Inst.setOpcode(TargetOpcode::CFI_INSTRUCTION); Inst.setOpcode(TargetOpcode::CFI_INSTRUCTION);
Inst.addOperand(MCOperand::createImm(Offset)); Inst.addOperand(MCOperand::createImm(Offset));
- return true;
} }
/// Create an inline version of memcpy(dest, src, 1). /// Create an inline version of memcpy(dest, src, 1).
@@ -1684,6 +1682,12 @@ public:
return Inst.getOpcode() == TargetOpcode::CFI_INSTRUCTION; return Inst.getOpcode() == TargetOpcode::CFI_INSTRUCTION;
} }
+ /// Create a conditional branch with a target-specific conditional code \p CC.
+ virtual void createCondBranch(MCInst &Inst, const MCSymbol *Target,
+ unsigned CC, MCContext *Ctx) const {
+ llvm_unreachable("not implemented");
+ }
+
/// Reverses the branch condition in Inst and update its taken target to TBB. /// Reverses the branch condition in Inst and update its taken target to TBB.
/// ///
/// Returns true on success. /// Returns true on success.
bolt/include/bolt/Core/ParallelUtilities.h
@@ -18,6 +18,7 @@
#include "bolt/Core/MCPlusBuilder.h" #include "bolt/Core/MCPlusBuilder.h"
#include "llvm/Support/CommandLine.h" #include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ThreadPool.h"
using namespace llvm; using namespace llvm;
@@ -28,8 +29,6 @@ extern cl::opt<unsigned> TaskCount;
} // namespace opts } // namespace opts
namespace llvm { namespace llvm {
-class ThreadPool;
-
namespace bolt { namespace bolt {
class BinaryContext; class BinaryContext;
class BinaryFunction; class BinaryFunction;
@@ -50,8 +49,8 @@ enum SchedulingPolicy {
SP_BB_QUADRATIC, /// cost is estimated by the square of the BB count SP_BB_QUADRATIC, /// cost is estimated by the square of the BB count
}; };
-/// Return the managed thread pool and initialize it if not initiliazed.+/// Return the managed thread pool and initialize it if not initialized.
-ThreadPool &getThreadPool();+ThreadPoolInterface &getThreadPool();
/// Perform the work on each BinaryFunction except those that are accepted /// Perform the work on each BinaryFunction except those that are accepted
/// by SkipPredicate, scheduling heuristic is based on SchedPolicy. /// by SkipPredicate, scheduling heuristic is based on SchedPolicy.
bolt/include/bolt/Rewrite/DWARFRewriter.h
@@ -11,6 +11,7 @@
#include "bolt/Core/DIEBuilder.h" #include "bolt/Core/DIEBuilder.h"
#include "bolt/Core/DebugData.h" #include "bolt/Core/DebugData.h"
+#include "bolt/Core/DebugNames.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/DIE.h" #include "llvm/CodeGen/DIE.h"
#include "llvm/DWP/DWP.h" #include "llvm/DWP/DWP.h"
@@ -140,8 +141,10 @@ private:
const std::list<DWARFUnit *> &CUs); const std::list<DWARFUnit *> &CUs);
/// Finalize debug sections in the main binary. /// Finalize debug sections in the main binary.
- void finalizeDebugSections(DIEBuilder &DIEBlder, DIEStreamer &Streamer,+ void finalizeDebugSections(DIEBuilder &DIEBlder,
- raw_svector_ostream &ObjOS, CUOffsetMap &CUMap);+ DWARF5AcceleratorTable &DebugNamesTable,
+ DIEStreamer &Streamer, raw_svector_ostream &ObjOS,
+ CUOffsetMap &CUMap);
/// Patches the binary for DWARF address ranges (e.g. in functions and lexical /// Patches the binary for DWARF address ranges (e.g. in functions and lexical
/// blocks) to be updated. /// blocks) to be updated.
bolt/lib/Core/BinaryContext.cpp
@@ -1967,7 +1967,7 @@ void BinaryContext::printInstruction(raw_ostream &OS, const MCInst &Instruction,
OS << " # Offset: " << *Offset; OS << " # Offset: " << *Offset;
if (std::optional<uint32_t> Size = MIB->getSize(Instruction)) if (std::optional<uint32_t> Size = MIB->getSize(Instruction))
OS << " # Size: " << *Size; OS << " # Size: " << *Size;
- if (MCSymbol *Label = MIB->getLabel(Instruction))+ if (MCSymbol *Label = MIB->getInstLabel(Instruction))
OS << " # Label: " << *Label; OS << " # Label: " << *Label;
MIB->printAnnotations(Instruction, OS); MIB->printAnnotations(Instruction, OS);
bolt/lib/Core/BinaryEmitter.cpp
@@ -489,7 +489,7 @@ void BinaryEmitter::emitFunctionBody(BinaryFunction &BF, FunctionFragment &FF,
if (!EmitCodeOnly) { if (!EmitCodeOnly) {
// A symbol to be emitted before the instruction to mark its location. // A symbol to be emitted before the instruction to mark its location.
- MCSymbol *InstrLabel = BC.MIB->getLabel(Instr);+ MCSymbol *InstrLabel = BC.MIB->getInstLabel(Instr);
if (opts::UpdateDebugSections && BF.getDWARFUnit()) { if (opts::UpdateDebugSections && BF.getDWARFUnit()) {
LastLocSeen = emitLineInfo(BF, Instr.getLoc(), LastLocSeen, LastLocSeen = emitLineInfo(BF, Instr.getLoc(), LastLocSeen,
bolt/lib/Core/BinaryFunction.cpp
@@ -1424,7 +1424,7 @@ add_instruction:
InstrMapType::iterator II = Instructions.find(Offset); InstrMapType::iterator II = Instructions.find(Offset);
assert(II != Instructions.end() && "reference to non-existing instruction"); assert(II != Instructions.end() && "reference to non-existing instruction");
- BC.MIB->setLabel(II->second, Label);+ BC.MIB->setInstLabel(II->second, Label);
} }
// Reset symbolizer for the disassembler. // Reset symbolizer for the disassembler.
@@ -1445,6 +1445,16 @@ add_instruction:
return Error::success(); return Error::success();
} }
+MCSymbol *BinaryFunction::registerBranch(uint64_t Src, uint64_t Dst) {
+ assert(CurrentState == State::Disassembled &&
+ "Cannot register branch unless function is in disassembled state.");
+ assert(containsAddress(Src) && containsAddress(Dst) &&
+ "Cannot register external branch.");
+ MCSymbol *Target = getOrCreateLocalLabel(Dst);
+ TakenBranches.emplace_back(Src - getAddress(), Dst - getAddress());
+ return Target;
+}
+
bool BinaryFunction::scanExternalRefs() { bool BinaryFunction::scanExternalRefs() {
bool Success = true; bool Success = true;
bool DisassemblyFailed = false; bool DisassemblyFailed = false;
@@ -1759,13 +1769,6 @@ void BinaryFunction::postProcessJumpTables() {
} }
} }
} }
-
- // Remove duplicates branches. We can get a bunch of them from jump tables.
- // Without doing jump table value profiling we don't have use for extra
- // (duplicate) branches.
- llvm::sort(TakenBranches);
- auto NewEnd = std::unique(TakenBranches.begin(), TakenBranches.end());
- TakenBranches.erase(NewEnd, TakenBranches.end());
} }
bool BinaryFunction::validateExternallyReferencedOffsets() { bool BinaryFunction::validateExternallyReferencedOffsets() {
@@ -2128,6 +2131,13 @@ Error BinaryFunction::buildCFG(MCPlusBuilder::AllocatorIdTy AllocatorId) {
// e.g. exit(3), etc. Otherwise we'll see a false fall-through // e.g. exit(3), etc. Otherwise we'll see a false fall-through
// blocks. // blocks.
+ // Remove duplicates branches. We can get a bunch of them from jump tables.
+ // Without doing jump table value profiling we don't have a use for extra
+ // (duplicate) branches.
+ llvm::sort(TakenBranches);
+ auto NewEnd = std::unique(TakenBranches.begin(), TakenBranches.end());
+ TakenBranches.erase(NewEnd, TakenBranches.end());
+
for (std::pair<uint32_t, uint32_t> &Branch : TakenBranches) { for (std::pair<uint32_t, uint32_t> &Branch : TakenBranches) {
LLVM_DEBUG(dbgs() << "registering branch [0x" LLVM_DEBUG(dbgs() << "registering branch [0x"
<< Twine::utohexstr(Branch.first) << "] -> [0x" << Twine::utohexstr(Branch.first) << "] -> [0x"
bolt/lib/Core/CMakeLists.txt
@@ -20,6 +20,7 @@ add_llvm_library(LLVMBOLTCore
BinaryFunctionProfile.cpp BinaryFunctionProfile.cpp
BinarySection.cpp BinarySection.cpp
DebugData.cpp DebugData.cpp
+ DebugNames.cpp
DIEBuilder.cpp DIEBuilder.cpp
DynoStats.cpp DynoStats.cpp
Exceptions.cpp Exceptions.cpp
bolt/lib/Core/DIEBuilder.cpp
@@ -19,20 +19,17 @@
#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFUnit.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
-#include "llvm/ObjectYAML/DWARFYAML.h"
#include "llvm/Support/Casting.h" #include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h" #include "llvm/Support/Format.h"
#include "llvm/Support/LEB128.h" #include "llvm/Support/LEB128.h"
-#include "llvm/Support/ThreadPool.h"
-#include "llvm/Support/YAMLTraits.h"
#include <algorithm> #include <algorithm>
#include <cstdint> #include <cstdint>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
-#include <string>+#include <optional>
#include <unordered_map> #include <unordered_map>
#include <utility> #include <utility>
#include <vector> #include <vector>
@@ -179,8 +176,10 @@ void DIEBuilder::constructFromUnit(DWARFUnit &DU) {
} }
DIEBuilder::DIEBuilder(BinaryContext &BC, DWARFContext *DwarfContext, DIEBuilder::DIEBuilder(BinaryContext &BC, DWARFContext *DwarfContext,
+ DWARF5AcceleratorTable &DebugNamesTable,
DWARFUnit *SkeletonCU) DWARFUnit *SkeletonCU)
- : BC(BC), DwarfContext(DwarfContext), SkeletonCU(SkeletonCU) {}+ : BC(BC), DwarfContext(DwarfContext), SkeletonCU(SkeletonCU),
+ DebugNamesTable(DebugNamesTable) {}
static unsigned int getCUNum(DWARFContext *DwarfContext, bool IsDWO) { static unsigned int getCUNum(DWARFContext *DwarfContext, bool IsDWO) {
unsigned int CUNum = IsDWO ? DwarfContext->getNumDWOCompileUnits() unsigned int CUNum = IsDWO ? DwarfContext->getNumDWOCompileUnits()
@@ -378,18 +377,20 @@ getUnitForOffset(DIEBuilder &Builder, DWARFContext &DWCtx,
return nullptr; return nullptr;
} }
-uint32_t DIEBuilder::computeDIEOffset(const DWARFUnit &CU, DIE &Die,+uint32_t DIEBuilder::finalizeDIEs(DWARFUnit &CU, DIE &Die,
- uint32_t &CurOffset) {+ uint32_t &CurOffset) {
getState().DWARFDieAddressesParsed.erase(Die.getOffset()); getState().DWARFDieAddressesParsed.erase(Die.getOffset());
uint32_t CurSize = 0; uint32_t CurSize = 0;
Die.setOffset(CurOffset); Die.setOffset(CurOffset);
+ DebugNamesTable.addAccelTableEntry(
+ CU, Die, SkeletonCU ? SkeletonCU->getDWOId() : std::nullopt);
for (DIEValue &Val : Die.values()) for (DIEValue &Val : Die.values())
CurSize += Val.sizeOf(CU.getFormParams()); CurSize += Val.sizeOf(CU.getFormParams());
CurSize += getULEB128Size(Die.getAbbrevNumber()); CurSize += getULEB128Size(Die.getAbbrevNumber());
CurOffset += CurSize; CurOffset += CurSize;
for (DIE &Child : Die.children()) { for (DIE &Child : Die.children()) {
- uint32_t ChildSize = computeDIEOffset(CU, Child, CurOffset);+ uint32_t ChildSize = finalizeDIEs(CU, Child, CurOffset);
CurSize += ChildSize; CurSize += ChildSize;
} }
// for children end mark. // for children end mark.
@@ -404,12 +405,12 @@ uint32_t DIEBuilder::computeDIEOffset(const DWARFUnit &CU, DIE &Die,
} }
void DIEBuilder::finish() { void DIEBuilder::finish() {
- auto computeOffset = [&](const DWARFUnit &CU,+ auto finalizeCU = [&](DWARFUnit &CU, uint64_t &UnitStartOffset) -> void {
- uint64_t &UnitStartOffset) -> void {
DIE *UnitDIE = getUnitDIEbyUnit(CU); DIE *UnitDIE = getUnitDIEbyUnit(CU);
uint32_t HeaderSize = CU.getHeaderSize(); uint32_t HeaderSize = CU.getHeaderSize();
uint32_t CurOffset = HeaderSize; uint32_t CurOffset = HeaderSize;
- computeDIEOffset(CU, *UnitDIE, CurOffset);+ DebugNamesTable.setCurrentUnit(CU, UnitStartOffset);
+ finalizeDIEs(CU, *UnitDIE, CurOffset);
DWARFUnitInfo &CurUnitInfo = getUnitInfoByDwarfUnit(CU); DWARFUnitInfo &CurUnitInfo = getUnitInfoByDwarfUnit(CU);
CurUnitInfo.UnitOffset = UnitStartOffset; CurUnitInfo.UnitOffset = UnitStartOffset;
@@ -420,18 +421,18 @@ void DIEBuilder::finish() {
// It's processed first when CU is registered so will be at the begginnig of // It's processed first when CU is registered so will be at the begginnig of
// the vector. // the vector.
uint64_t TypeUnitStartOffset = 0; uint64_t TypeUnitStartOffset = 0;
- for (const DWARFUnit *CU : getState().DUList) {+ for (DWARFUnit *CU : getState().DUList) {
// We process DWARF$ types first. // We process DWARF$ types first.
if (!(CU->getVersion() < 5 && CU->isTypeUnit())) if (!(CU->getVersion() < 5 && CU->isTypeUnit()))
break; break;
- computeOffset(*CU, TypeUnitStartOffset);+ finalizeCU(*CU, TypeUnitStartOffset);
} }
- for (const DWARFUnit *CU : getState().DUList) {+ for (DWARFUnit *CU : getState().DUList) {
// Skipping DWARF4 types. // Skipping DWARF4 types.
if (CU->getVersion() < 5 && CU->isTypeUnit()) if (CU->getVersion() < 5 && CU->isTypeUnit())
continue; continue;
- computeOffset(*CU, UnitSize);+ finalizeCU(*CU, UnitSize);
} }
if (opts::Verbosity >= 1) { if (opts::Verbosity >= 1) {
if (!getState().DWARFDieAddressesParsed.empty()) if (!getState().DWARFDieAddressesParsed.empty())
bolt/lib/Core/DebugNames.cpp
@@ -0,0 +1,623 @@
+//===- 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"
+#include <cstdint>
+
+namespace llvm {
+namespace bolt {
+DWARF5AcceleratorTable::DWARF5AcceleratorTable(
+ const bool CreateDebugNames, BinaryContext &BC,
+ DebugStrWriter &MainBinaryStrWriter)
+ : BC(BC), 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;
+ BC.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)
+ BC.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 skeleton 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) {
+ constexpr uint32_t BADCUOFFSET = 0xBADBAD;
+ 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(BADCUOFFSET);
+ ForeignTUList.push_back(cast<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(BADCUOFFSET);
+ } 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)
+ if (Expr.getCode() == dwarf::DW_OP_addrx ||
+ Expr.getCode() == dwarf::DW_OP_form_tls_address)
+ return true;
+ return false;
+}
+
+/// Returns name offset in String Offset section.
+static uint64_t getNameOffset(BinaryContext &BC, DWARFUnit &Unit,
+ const uint64_t Index) {
+ const DWARFSection &StrOffsetsSection = Unit.getStringOffsetSection();
+ const std::optional<StrOffsetsContributionDescriptor> &Contr =
+ Unit.getStringOffsetsTableContribution();
+ if (!Contr) {
+ BC.errs() << "BOLT-WARNING: [internal-dwarf-warning]: Could not get "
+ "StringOffsetsTableContribution for unit at offset: "
+ << Twine::utohexstr(Unit.getOffset()) << ".\n";
+ return 0;
+ }
+
+ const uint8_t DwarfOffsetByteSize = Contr->getDwarfOffsetByteSize();
+ return support::endian::read32le(StrOffsetsSection.Data.data() + Contr->Base +
+ Index * DwarfOffsetByteSize);
+}
+
+void DWARF5AcceleratorTable::addAccelTableEntry(
+ DWARFUnit &Unit, const DIE &Die, const std::optional<uint64_t> &DWOID) {
+ if (Unit.getVersion() < 5 || !NeedToCreate)
+ return;
+ std::string NameToUse = "";
+ auto canProcess = [&](const DIE &Die) -> bool {
+ switch (Die.getTag()) {
+ case dwarf::DW_TAG_base_type:
+ case dwarf::DW_TAG_class_type:
+ case dwarf::DW_TAG_enumeration_type:
+ case dwarf::DW_TAG_imported_declaration:
+ case dwarf::DW_TAG_pointer_type:
+ case dwarf::DW_TAG_structure_type:
+ case dwarf::DW_TAG_typedef:
+ case dwarf::DW_TAG_unspecified_type:
+ if (Die.findAttribute(dwarf::Attribute::DW_AT_name))
+ return true;
+ return false;
+ case dwarf::DW_TAG_namespace:
+ // According to DWARF5 spec namespaces without DW_AT_name needs to have
+ // "(anonymous namespace)"
+ if (!Die.findAttribute(dwarf::Attribute::DW_AT_name))
+ NameToUse = "(anonymous namespace)";
+ return true;
+ case dwarf::DW_TAG_inlined_subroutine:
+ case dwarf::DW_TAG_label:
+ case dwarf::DW_TAG_subprogram:
+ if (Die.findAttribute(dwarf::Attribute::DW_AT_low_pc) ||
+ Die.findAttribute(dwarf::Attribute::DW_AT_high_pc) ||
+ Die.findAttribute(dwarf::Attribute::DW_AT_ranges) ||
+ Die.findAttribute(dwarf::Attribute::DW_AT_entry_pc))
+ return true;
+ return false;
+ case dwarf::DW_TAG_variable:
+ return shouldIncludeVariable(Unit, Die);
+ default:
+ break;
+ }
+ return false;
+ };
+
+ auto getUnitID = [&](const DWARFUnit &Unit, bool &IsTU,
+ uint32_t &DieTag) -> uint32_t {
+ IsTU = Unit.isTypeUnit();
+ DieTag = Die.getTag();
+ if (IsTU) {
+ if (DWOID)
+ return ForeignTUList.size() - 1;
+ return LocalTUList.size() - 1;
+ }
+ return CUList.size() - 1;
+ };
+
+ if (!canProcess(Die))
+ return;
+
+ // Addes a Unit to either CU, LocalTU or ForeignTU list the first time we
+ // encounter it.
+ // Invoking it here so that we don't add Units that don't have any entries.
+ if (&Unit != CurrentUnit) {
+ CurrentUnit = &Unit;
+ addUnit(Unit, DWOID);
+ }
+
+ auto addEntry = [&](DIEValue ValName) -> void {
+ if ((!ValName || ValName.getForm() == dwarf::DW_FORM_string) &&
+ NameToUse.empty())
+ return;
+ std::string Name = "";
+ uint64_t NameIndexOffset = 0;
+ if (NameToUse.empty()) {
+ NameIndexOffset = ValName.getDIEInteger().getValue();
+ if (ValName.getForm() != dwarf::DW_FORM_strp)
+ NameIndexOffset = getNameOffset(BC, Unit, NameIndexOffset);
+ // Counts on strings end with '\0'.
+ Name = std::string(&StrSection.data()[NameIndexOffset]);
+ } else {
+ Name = NameToUse;
+ }
+ auto &It = Entries[Name];
+ if (It.Values.empty()) {
+ if (DWOID && NameToUse.empty()) {
+ // For DWO Unit the offset is in the .debug_str.dwo section.
+ // Need to find offset for the name in the .debug_str section.
+ llvm::hash_code Hash = llvm::hash_value(llvm::StringRef(Name));
+ auto ItCache = StrCacheToOffsetMap.find(Hash);
+ if (ItCache == StrCacheToOffsetMap.end())
+ NameIndexOffset = MainBinaryStrWriter.addString(Name);
+ else
+ NameIndexOffset = ItCache->second;
+ }
+ if (!NameToUse.empty())
+ NameIndexOffset = MainBinaryStrWriter.addString(Name);
+ It.StrOffset = NameIndexOffset;
+ // This the same hash function used in DWARF5AccelTableData.
+ It.HashValue = caseFoldingDjbHash(Name);
+ }
+
+ bool IsTU = false;
+ uint32_t DieTag = 0;
+ uint32_t UnitID = getUnitID(Unit, IsTU, DieTag);
+ std::optional<unsigned> SecondIndex = std::nullopt;
+ if (IsTU && DWOID) {
+ auto Iter = CUOffsetsToPatch.find(*DWOID);
+ if (Iter == CUOffsetsToPatch.end())
+ BC.errs() << "BOLT-WARNING: [internal-dwarf-warning]: Could not find "
+ "DWO ID in CU offsets for second Unit Index "
+ << Name << ". For DIE at offset: "
+ << Twine::utohexstr(CurrentUnitOffset + Die.getOffset())
+ << ".\n";
+ SecondIndex = Iter->second;
+ }
+ It.Values.push_back(new (Allocator) BOLTDWARF5AccelTableData(
+ Die.getOffset(), std::nullopt, DieTag, UnitID, IsTU, SecondIndex));
+ };
+
+ addEntry(Die.findAttribute(dwarf::Attribute::DW_AT_name));
+ addEntry(Die.findAttribute(dwarf::Attribute::DW_AT_linkage_name));
+ return;
+}
+
+/// Algorithm from llvm implementation.
+void DWARF5AcceleratorTable::computeBucketCount() {
+ // First get the number of unique hashes.
+ std::vector<uint32_t> Uniques;
+ Uniques.reserve(Entries.size());
+ for (const auto &E : Entries)
+ Uniques.push_back(E.second.HashValue);
+ array_pod_sort(Uniques.begin(), Uniques.end());
+ std::vector<uint32_t>::iterator P =
+ std::unique(Uniques.begin(), Uniques.end());
+
+ UniqueHashCount = std::distance(Uniques.begin(), P);
+
+ if (UniqueHashCount > 1024)
+ BucketCount = UniqueHashCount / 4;
+ else if (UniqueHashCount > 16)
+ BucketCount = UniqueHashCount / 2;
+ else
+ BucketCount = std::max<uint32_t>(UniqueHashCount, 1);
+}
+
+/// Bucket code as in: AccelTableBase::finalize()
+void DWARF5AcceleratorTable::finalize() {
+ if (!NeedToCreate)
+ return;
+ // Figure out how many buckets we need, then compute the bucket contents and
+ // the final ordering. The hashes and offsets can be emitted by walking these
+ // data structures.
+ computeBucketCount();
+
+ // Compute bucket contents and final ordering.
+ Buckets.resize(BucketCount);
+ for (auto &E : Entries) {
+ uint32_t Bucket = E.second.HashValue % BucketCount;
+ Buckets[Bucket].push_back(&E.second);
+ }
+
+ // Sort the contents of the buckets by hash value so that hash collisions end
+ // up together. Stable sort makes testing easier and doesn't cost much more.
+ for (HashList &Bucket : Buckets) {
+ llvm::stable_sort(Bucket, [](const HashData *LHS, const HashData *RHS) {
+ return LHS->HashValue < RHS->HashValue;
+ });
+ for (HashData *H : Bucket)
+ llvm::stable_sort(H->Values, [](const BOLTDWARF5AccelTableData *LHS,
+ const BOLTDWARF5AccelTableData *RHS) {
+ return LHS->getDieOffset() < RHS->getDieOffset();
+ });
+ }
+
+ CUIndexForm = DIEInteger::BestForm(/*IsSigned*/ false, CUList.size() - 1);
+ TUIndexForm = DIEInteger::BestForm(
+ /*IsSigned*/ false, LocalTUList.size() + ForeignTUList.size() - 1);
+ const dwarf::FormParams FormParams{5, 4, dwarf::DwarfFormat::DWARF32, false};
+ CUIndexEncodingSize = *dwarf::getFixedFormByteSize(CUIndexForm, FormParams);
+ TUIndexEncodingSize = *dwarf::getFixedFormByteSize(TUIndexForm, FormParams);
+}
+
+std::optional<DWARF5AccelTable::UnitIndexAndEncoding>
+DWARF5AcceleratorTable::getIndexForEntry(
+ const BOLTDWARF5AccelTableData &Value) const {
+ // The foreign TU list immediately follows the local TU list and they both
+ // use the same index, so that if there are N local TU entries, the index for
+ // the first foreign TU is N.
+ if (Value.isTU())
+ return {{(Value.getSecondUnitID() ? (unsigned)LocalTUList.size() : 0) +
+ Value.getUnitID(),
+ {dwarf::DW_IDX_type_unit, TUIndexForm}}};
+ if (CUList.size() > 1)
+ return {{Value.getUnitID(), {dwarf::DW_IDX_compile_unit, CUIndexForm}}};
+ return std::nullopt;
+}
+
+std::optional<DWARF5AccelTable::UnitIndexAndEncoding>
+DWARF5AcceleratorTable::getSecondIndexForEntry(
+ const BOLTDWARF5AccelTableData &Value) const {
+ if (Value.isTU() && CUList.size() > 1 && Value.getSecondUnitID())
+ return {
+ {*Value.getSecondUnitID(), {dwarf::DW_IDX_compile_unit, CUIndexForm}}};
+ return std::nullopt;
+}
+
+void DWARF5AcceleratorTable::populateAbbrevsMap() {
+ for (auto &Bucket : getBuckets()) {
+ for (DWARF5AcceleratorTable::HashData *Hash : Bucket) {
+ for (BOLTDWARF5AccelTableData *Value : Hash->Values) {
+ const std::optional<DWARF5AccelTable::UnitIndexAndEncoding> EntryRet =
+ getIndexForEntry(*Value);
+ // For entries that need to refer to the foreign type units and to
+ // the CU.
+ const std::optional<DWARF5AccelTable::UnitIndexAndEncoding>
+ SecondEntryRet = getSecondIndexForEntry(*Value);
+ DebugNamesAbbrev Abbrev(Value->getDieTag());
+ if (EntryRet)
+ Abbrev.addAttribute(EntryRet->Encoding);
+ if (SecondEntryRet)
+ Abbrev.addAttribute(SecondEntryRet->Encoding);
+ Abbrev.addAttribute({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4});
+ FoldingSetNodeID ID;
+ Abbrev.Profile(ID);
+ void *InsertPos;
+ if (DebugNamesAbbrev *Existing =
+ AbbreviationsSet.FindNodeOrInsertPos(ID, InsertPos)) {
+ Value->setAbbrevNumber(Existing->getNumber());
+ continue;
+ }
+ DebugNamesAbbrev *NewAbbrev =
+ new (Alloc) DebugNamesAbbrev(std::move(Abbrev));
+ AbbreviationsVector.push_back(NewAbbrev);
+ NewAbbrev->setNumber(AbbreviationsVector.size());
+ AbbreviationsSet.InsertNode(NewAbbrev, InsertPos);
+ Value->setAbbrevNumber(NewAbbrev->getNumber());
+ }
+ }
+ }
+}
+
+void DWARF5AcceleratorTable::writeEntry(const BOLTDWARF5AccelTableData &Entry) {
+ const std::optional<DWARF5AccelTable::UnitIndexAndEncoding> EntryRet =
+ getIndexForEntry(Entry);
+ // For forgeign type (FTU) units that need to refer to the FTU and to the CU.
+ const std::optional<DWARF5AccelTable::UnitIndexAndEncoding> SecondEntryRet =
+ getSecondIndexForEntry(Entry);
+ const unsigned AbbrevIndex = Entry.getAbbrevNumber() - 1;
+ assert(AbbrevIndex < AbbreviationsVector.size() &&
+ "Entry abbrev index is outside of abbreviations vector range.");
+ const DebugNamesAbbrev *Abbrev = AbbreviationsVector[AbbrevIndex];
+ encodeULEB128(Entry.getAbbrevNumber(), *Entriestream);
+ auto writeIndex = [&](uint32_t Index, uint32_t IndexSize) -> void {
+ switch (IndexSize) {
+ default:
+ llvm_unreachable("Unsupported Index Size!");
+ break;
+ case 1:
+ support::endian::write(*Entriestream, static_cast<uint8_t>(Index),
+ llvm::endianness::little);
+ break;
+ case 2:
+ support::endian::write(*Entriestream, static_cast<uint16_t>(Index),
+ llvm::endianness::little);
+ break;
+ case 4:
+ support::endian::write(*Entriestream, static_cast<uint32_t>(Index),
+ llvm::endianness::little);
+ break;
+ };
+ };
+
+ for (const DebugNamesAbbrev::AttributeEncoding &AttrEnc :
+ Abbrev->getAttributes()) {
+ switch (AttrEnc.Index) {
+ default: {
+ llvm_unreachable("Unexpected index attribute!");
+ break;
+ }
+ case dwarf::DW_IDX_compile_unit: {
+ const unsigned CUIndex =
+ SecondEntryRet ? SecondEntryRet->Index : EntryRet->Index;
+ writeIndex(CUIndex, CUIndexEncodingSize);
+ break;
+ }
+ case dwarf::DW_IDX_type_unit: {
+ writeIndex(EntryRet->Index, TUIndexEncodingSize);
+ break;
+ }
+ case dwarf::DW_IDX_die_offset: {
+ assert(AttrEnc.Form == dwarf::DW_FORM_ref4);
+ support::endian::write(*Entriestream,
+ static_cast<uint32_t>(Entry.getDieOffset()),
+ llvm::endianness::little);
+ break;
+ }
+ }
+ }
+}
+
+void DWARF5AcceleratorTable::writeEntries() {
+ for (auto &Bucket : getBuckets()) {
+ for (DWARF5AcceleratorTable::HashData *Hash : Bucket) {
+ Hash->EntryOffset = EntriesBuffer->size();
+ for (const BOLTDWARF5AccelTableData *Value : Hash->Values) {
+ writeEntry(*Value);
+ }
+ support::endian::write(*Entriestream, static_cast<uint8_t>(0),
+ llvm::endianness::little);
+ }
+ }
+}
+
+void DWARF5AcceleratorTable::writeAugmentationString() {
+ // String needs to be multiple of 4 bytes.
+ *AugStringtream << "BOLT";
+ AugmentationStringSize = AugStringBuffer->size();
+}
+
+/// Calculates size of .debug_names header without Length field.
+static constexpr uint32_t getDebugNamesHeaderSize() {
+ constexpr uint16_t VersionLength = sizeof(uint16_t);
+ constexpr uint16_t PaddingLength = sizeof(uint16_t);
+ constexpr uint32_t CompUnitCountLength = sizeof(uint32_t);
+ constexpr uint32_t LocalTypeUnitCountLength = sizeof(uint32_t);
+ constexpr uint32_t ForeignTypeUnitCountLength = sizeof(uint32_t);
+ constexpr uint32_t BucketCountLength = sizeof(uint32_t);
+ constexpr uint32_t NameCountLength = sizeof(uint32_t);
+ constexpr uint32_t AbbrevTableSizeLength = sizeof(uint32_t);
+ constexpr uint32_t AugmentationStringSizeLenght = sizeof(uint32_t);
+ return VersionLength + PaddingLength + CompUnitCountLength +
+ LocalTypeUnitCountLength + ForeignTypeUnitCountLength +
+ BucketCountLength + NameCountLength + AbbrevTableSizeLength +
+ AugmentationStringSizeLenght;
+}
+
+void DWARF5AcceleratorTable::emitHeader() const {
+ constexpr uint32_t HeaderSize = getDebugNamesHeaderSize();
+ // Header Length
+ support::endian::write(*FullTableStream,
+ static_cast<uint32_t>(HeaderSize + StrBuffer->size() +
+ AugmentationStringSize),
+ llvm::endianness::little);
+ // Version
+ support::endian::write(*FullTableStream, static_cast<uint16_t>(5),
+ llvm::endianness::little);
+ // Padding
+ support::endian::write(*FullTableStream, static_cast<uint16_t>(0),
+ llvm::endianness::little);
+ // Compilation Unit Count
+ support::endian::write(*FullTableStream, static_cast<uint32_t>(CUList.size()),
+ llvm::endianness::little);
+ // Local Type Unit Count
+ support::endian::write(*FullTableStream,
+ static_cast<uint32_t>(LocalTUList.size()),
+ llvm::endianness::little);
+ // Foreign Type Unit Count
+ support::endian::write(*FullTableStream,
+ static_cast<uint32_t>(ForeignTUList.size()),
+ llvm::endianness::little);
+ // Bucket Count
+ support::endian::write(*FullTableStream, static_cast<uint32_t>(BucketCount),
+ llvm::endianness::little);
+ // Name Count
+ support::endian::write(*FullTableStream,
+ static_cast<uint32_t>(Entries.size()),
+ llvm::endianness::little);
+ // Abbrev Table Size
+ support::endian::write(*FullTableStream,
+ static_cast<uint32_t>(AbbrevTableSize),
+ llvm::endianness::little);
+ // Augmentation String Size
+ support::endian::write(*FullTableStream,
+ static_cast<uint32_t>(AugmentationStringSize),
+ llvm::endianness::little);
+
+ emitAugmentationString();
+ FullTableStream->write(StrBuffer->data(), StrBuffer->size());
+}
+
+void DWARF5AcceleratorTable::emitCUList() const {
+ for (const uint32_t CUID : CUList)
+ support::endian::write(*StrStream, CUID, llvm::endianness::little);
+}
+void DWARF5AcceleratorTable::emitTUList() const {
+ for (const uint32_t TUID : LocalTUList)
+ support::endian::write(*StrStream, TUID, llvm::endianness::little);
+
+ for (const uint64_t TUID : ForeignTUList)
+ support::endian::write(*StrStream, TUID, llvm::endianness::little);
+}
+void DWARF5AcceleratorTable::emitBuckets() const {
+ uint32_t Index = 1;
+ for (const auto &Bucket : enumerate(getBuckets())) {
+ const uint32_t TempIndex = Bucket.value().empty() ? 0 : Index;
+ support::endian::write(*StrStream, TempIndex, llvm::endianness::little);
+ Index += Bucket.value().size();
+ }
+}
+void DWARF5AcceleratorTable::emitHashes() const {
+ for (const auto &Bucket : getBuckets()) {
+ for (const DWARF5AcceleratorTable::HashData *Hash : Bucket)
+ support::endian::write(*StrStream, Hash->HashValue,
+ llvm::endianness::little);
+ }
+}
+void DWARF5AcceleratorTable::emitStringOffsets() const {
+ for (const auto &Bucket : getBuckets()) {
+ for (const DWARF5AcceleratorTable::HashData *Hash : Bucket)
+ support::endian::write(*StrStream, static_cast<uint32_t>(Hash->StrOffset),
+ llvm::endianness::little);
+ }
+}
+void DWARF5AcceleratorTable::emitOffsets() const {
+ for (const auto &Bucket : getBuckets()) {
+ for (const DWARF5AcceleratorTable::HashData *Hash : Bucket)
+ support::endian::write(*StrStream,
+ static_cast<uint32_t>(Hash->EntryOffset),
+ llvm::endianness::little);
+ }
+}
+void DWARF5AcceleratorTable::emitAbbrevs() {
+ const uint32_t AbbrevTableStart = StrBuffer->size();
+ for (const auto *Abbrev : AbbreviationsVector) {
+ encodeULEB128(Abbrev->getNumber(), *StrStream);
+ encodeULEB128(Abbrev->getDieTag(), *StrStream);
+ for (const auto &AttrEnc : Abbrev->getAttributes()) {
+ encodeULEB128(AttrEnc.Index, *StrStream);
+ encodeULEB128(AttrEnc.Form, *StrStream);
+ }
+ encodeULEB128(0, *StrStream);
+ encodeULEB128(0, *StrStream);
+ }
+ encodeULEB128(0, *StrStream);
+ AbbrevTableSize = StrBuffer->size() - AbbrevTableStart;
+}
+void DWARF5AcceleratorTable::emitData() {
+ StrStream->write(EntriesBuffer->data(), EntriesBuffer->size());
+}
+void DWARF5AcceleratorTable::emitAugmentationString() const {
+ FullTableStream->write(AugStringBuffer->data(), AugStringBuffer->size());
+}
+void DWARF5AcceleratorTable::emitAccelTable() {
+ if (!NeedToCreate)
+ return;
+ finalize();
+ populateAbbrevsMap();
+ writeEntries();
+ writeAugmentationString();
+ emitCUList();
+ emitTUList();
+ emitBuckets();
+ emitHashes();
+ emitStringOffsets();
+ emitOffsets();
+ emitAbbrevs();
+ emitData();
+ emitHeader();
+}
+} // namespace bolt
+} // namespace llvm
bolt/lib/Core/Exceptions.cpp
@@ -408,12 +408,11 @@ void BinaryFunction::updateEHRanges() {
// Same symbol is used for the beginning and the end of the range. // Same symbol is used for the beginning and the end of the range.
MCSymbol *EHSymbol; MCSymbol *EHSymbol;
- if (MCSymbol *InstrLabel = BC.MIB->getLabel(Instr)) {+ if (MCSymbol *InstrLabel = BC.MIB->getInstLabel(Instr)) {
EHSymbol = InstrLabel; EHSymbol = InstrLabel;
} else { } else {
std::unique_lock<llvm::sys::RWMutex> Lock(BC.CtxMutex); std::unique_lock<llvm::sys::RWMutex> Lock(BC.CtxMutex);
- EHSymbol = BC.Ctx->createNamedTempSymbol("EH");+ EHSymbol = BC.MIB->getOrCreateInstLabel(Instr, "EH", BC.Ctx.get());
- BC.MIB->setLabel(Instr, EHSymbol);
} }
// At this point we could be in one of the following states: // At this point we could be in one of the following states:
bolt/lib/Core/MCPlusBuilder.cpp
@@ -12,6 +12,7 @@
#include "bolt/Core/MCPlusBuilder.h" #include "bolt/Core/MCPlusBuilder.h"
#include "bolt/Core/MCPlus.h" #include "bolt/Core/MCPlus.h"
+#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInst.h" #include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrAnalysis.h" #include "llvm/MC/MCInstrAnalysis.h"
#include "llvm/MC/MCInstrDesc.h" #include "llvm/MC/MCInstrDesc.h"
@@ -266,17 +267,29 @@ bool MCPlusBuilder::clearOffset(MCInst &Inst) const {
return true; return true;
} }
-MCSymbol *MCPlusBuilder::getLabel(const MCInst &Inst) const {+MCSymbol *MCPlusBuilder::getInstLabel(const MCInst &Inst) const {
if (std::optional<int64_t> Label = if (std::optional<int64_t> Label =
getAnnotationOpValue(Inst, MCAnnotation::kLabel)) getAnnotationOpValue(Inst, MCAnnotation::kLabel))
return reinterpret_cast<MCSymbol *>(*Label); return reinterpret_cast<MCSymbol *>(*Label);
return nullptr; return nullptr;
} }
-bool MCPlusBuilder::setLabel(MCInst &Inst, MCSymbol *Label) const {+MCSymbol *MCPlusBuilder::getOrCreateInstLabel(MCInst &Inst, const Twine &Name,
+ MCContext *Ctx) const {
+ MCSymbol *Label = getInstLabel(Inst);
+ if (Label)
+ return Label;
+
+ Label = Ctx->createNamedTempSymbol(Name);
+ setAnnotationOpValue(Inst, MCAnnotation::kLabel,
+ reinterpret_cast<int64_t>(Label));
+ return Label;
+}
+
+void MCPlusBuilder::setInstLabel(MCInst &Inst, MCSymbol *Label) const {
+ assert(!getInstLabel(Inst) && "Instruction already has assigned label.");
setAnnotationOpValue(Inst, MCAnnotation::kLabel, setAnnotationOpValue(Inst, MCAnnotation::kLabel,
reinterpret_cast<int64_t>(Label)); reinterpret_cast<int64_t>(Label));
- return true;
} }
std::optional<uint32_t> MCPlusBuilder::getSize(const MCInst &Inst) const { std::optional<uint32_t> MCPlusBuilder::getSize(const MCInst &Inst) const {
bolt/lib/Core/ParallelUtilities.cpp
@@ -49,7 +49,7 @@ namespace ParallelUtilities {
namespace { namespace {
/// A single thread pool that is used to run parallel tasks /// A single thread pool that is used to run parallel tasks
-std::unique_ptr<ThreadPool> ThreadPoolPtr;+std::unique_ptr<DefaultThreadPool> ThreadPoolPtr;
unsigned computeCostFor(const BinaryFunction &BF, unsigned computeCostFor(const BinaryFunction &BF,
const PredicateTy &SkipPredicate, const PredicateTy &SkipPredicate,
@@ -102,11 +102,11 @@ inline unsigned estimateTotalCost(const BinaryContext &BC,
} // namespace } // namespace
-ThreadPool &getThreadPool() {+ThreadPoolInterface &getThreadPool() {
if (ThreadPoolPtr.get()) if (ThreadPoolPtr.get())
return *ThreadPoolPtr; return *ThreadPoolPtr;
- ThreadPoolPtr = std::make_unique<ThreadPool>(+ ThreadPoolPtr = std::make_unique<DefaultThreadPool>(
llvm::hardware_concurrency(opts::ThreadCount)); llvm::hardware_concurrency(opts::ThreadCount));
return *ThreadPoolPtr; return *ThreadPoolPtr;
} }
@@ -145,7 +145,7 @@ void runOnEachFunction(BinaryContext &BC, SchedulingPolicy SchedPolicy,
TotalCost > BlocksCount ? TotalCost / BlocksCount : 1; TotalCost > BlocksCount ? TotalCost / BlocksCount : 1;
// Divide work into blocks of equal cost // Divide work into blocks of equal cost
- ThreadPool &Pool = getThreadPool();+ ThreadPoolInterface &Pool = getThreadPool();
auto BlockBegin = BC.getBinaryFunctions().begin(); auto BlockBegin = BC.getBinaryFunctions().begin();
unsigned CurrentCost = 0; unsigned CurrentCost = 0;
@@ -202,7 +202,7 @@ void runOnEachFunctionWithUniqueAllocId(
TotalCost > BlocksCount ? TotalCost / BlocksCount : 1; TotalCost > BlocksCount ? TotalCost / BlocksCount : 1;
// Divide work into blocks of equal cost // Divide work into blocks of equal cost
- ThreadPool &Pool = getThreadPool();+ ThreadPoolInterface &Pool = getThreadPool();
auto BlockBegin = BC.getBinaryFunctions().begin(); auto BlockBegin = BC.getBinaryFunctions().begin();
unsigned CurrentCost = 0; unsigned CurrentCost = 0;
unsigned AllocId = 1; unsigned AllocId = 1;
bolt/lib/Core/Relocation.cpp
@@ -381,6 +381,14 @@ static uint64_t encodeValueAArch64(uint64_t Type, uint64_t Value, uint64_t PC) {
// OP 1001_01 goes in bits 31:26 of BL. // OP 1001_01 goes in bits 31:26 of BL.
Value = ((Value >> 2) & 0x3ffffff) | 0x94000000ULL; Value = ((Value >> 2) & 0x3ffffff) | 0x94000000ULL;
break; break;
+ case ELF::R_AARCH64_JUMP26:
+ Value -= PC;
+ assert(isInt<28>(Value) &&
+ "only PC +/- 128MB is allowed for direct branch");
+ // Immediate goes in bits 25:0 of B.
+ // OP 0001_01 goes in bits 31:26 of B.
+ Value = ((Value >> 2) & 0x3ffffff) | 0x14000000ULL;
+ break;
} }
return Value; return Value;
} }
bolt/lib/Passes/BinaryPasses.cpp
@@ -1056,10 +1056,9 @@ void Peepholes::addTailcallTraps(BinaryFunction &Function) {
MCInst *Inst = BB.getLastNonPseudoInstr(); MCInst *Inst = BB.getLastNonPseudoInstr();
if (Inst && MIB->isTailCall(*Inst) && MIB->isIndirectBranch(*Inst)) { if (Inst && MIB->isTailCall(*Inst) && MIB->isIndirectBranch(*Inst)) {
MCInst Trap; MCInst Trap;
- if (MIB->createTrap(Trap)) {+ MIB->createTrap(Trap);
- BB.addInstruction(Trap);+ BB.addInstruction(Trap);
- ++TailCallTraps;+ ++TailCallTraps;
- }
} }
} }
} }
bolt/lib/Passes/IdenticalCodeFolding.cpp
@@ -397,7 +397,7 @@ Error IdenticalCodeFolding::runOnFunctions(BinaryContext &BC) {
Timer SinglePass("single fold pass", "single fold pass"); Timer SinglePass("single fold pass", "single fold pass");
LLVM_DEBUG(SinglePass.startTimer()); LLVM_DEBUG(SinglePass.startTimer());
- ThreadPool *ThPool;+ ThreadPoolInterface *ThPool;
if (!opts::NoThreads) if (!opts::NoThreads)
ThPool = &ParallelUtilities::getThreadPool(); ThPool = &ParallelUtilities::getThreadPool();
bolt/lib/Passes/Instrumentation.cpp
@@ -17,7 +17,9 @@
#include "bolt/Utils/Utils.h" #include "bolt/Utils/Utils.h"
#include "llvm/Support/CommandLine.h" #include "llvm/Support/CommandLine.h"
#include "llvm/Support/RWMutex.h" #include "llvm/Support/RWMutex.h"
+#include <queue>
#include <stack> #include <stack>
+#include <unordered_set>
#define DEBUG_TYPE "bolt-instrumentation" #define DEBUG_TYPE "bolt-instrumentation"
@@ -86,21 +88,89 @@ cl::opt<bool> InstrumentCalls("instrument-calls",
namespace llvm { namespace llvm {
namespace bolt { namespace bolt {
-static bool hasAArch64ExclusiveMemop(BinaryFunction &Function) {+static bool hasAArch64ExclusiveMemop(
+ BinaryFunction &Function,
+ std::unordered_set<const BinaryBasicBlock *> &BBToSkip) {
// FIXME ARMv8-a architecture reference manual says that software must avoid // FIXME ARMv8-a architecture reference manual says that software must avoid
// having any explicit memory accesses between exclusive load and associated // having any explicit memory accesses between exclusive load and associated
- // store instruction. So for now skip instrumentation for functions that have+ // store instruction. So for now skip instrumentation for basic blocks that
- // these instructions, since it might lead to runtime deadlock.+ // have these instructions, since it might lead to runtime deadlock.
BinaryContext &BC = Function.getBinaryContext(); BinaryContext &BC = Function.getBinaryContext();
- for (const BinaryBasicBlock &BB : Function)+ std::queue<std::pair<BinaryBasicBlock *, bool>> BBQueue; // {BB, isLoad}
- for (const MCInst &Inst : BB)+ std::unordered_set<BinaryBasicBlock *> Visited;
- if (BC.MIB->isAArch64Exclusive(Inst)) {+
- if (opts::Verbosity >= 1)+ if (Function.getLayout().block_begin() == Function.getLayout().block_end())
- BC.outs() << "BOLT-INSTRUMENTER: Function " << Function+ return 0;
- << " has exclusive instructions, skip instrumentation\n";+
+ BinaryBasicBlock *BBfirst = *Function.getLayout().block_begin();
+ BBQueue.push({BBfirst, false});
+
+ while (!BBQueue.empty()) {
+ BinaryBasicBlock *BB = BBQueue.front().first;
+ bool IsLoad = BBQueue.front().second;
+ BBQueue.pop();
+ if (Visited.find(BB) != Visited.end())
+ continue;
+ Visited.insert(BB);
+
+ for (const MCInst &Inst : *BB) {
+ // Two loads one after another - skip whole function
+ if (BC.MIB->isAArch64ExclusiveLoad(Inst) && IsLoad) {
+ if (opts::Verbosity >= 2) {
+ outs() << "BOLT-INSTRUMENTER: function " << Function.getPrintName()
+ << " has two exclusive loads. Ignoring the function.\n";
+ }
return true; return true;
} }
+ if (BC.MIB->isAArch64ExclusiveLoad(Inst))
+ IsLoad = true;
+
+ if (IsLoad && BBToSkip.find(BB) == BBToSkip.end()) {
+ BBToSkip.insert(BB);
+ if (opts::Verbosity >= 2) {
+ outs() << "BOLT-INSTRUMENTER: skip BB " << BB->getName()
+ << " due to exclusive instruction in function "
+ << Function.getPrintName() << "\n";
+ }
+ }
+
+ if (!IsLoad && BC.MIB->isAArch64ExclusiveStore(Inst)) {
+ if (opts::Verbosity >= 2) {
+ outs() << "BOLT-INSTRUMENTER: function " << Function.getPrintName()
+ << " has exclusive store without corresponding load. Ignoring "
+ "the function.\n";
+ }
+ return true;
+ }
+
+ if (IsLoad && (BC.MIB->isAArch64ExclusiveStore(Inst) ||
+ BC.MIB->isAArch64ExclusiveClear(Inst)))
+ IsLoad = false;
+ }
+
+ if (IsLoad && BB->succ_size() == 0) {
+ if (opts::Verbosity >= 2) {
+ outs()
+ << "BOLT-INSTRUMENTER: function " << Function.getPrintName()
+ << " has exclusive load in trailing BB. Ignoring the function.\n";
+ }
+ return true;
+ }
+
+ for (BinaryBasicBlock *BBS : BB->successors())
+ BBQueue.push({BBS, IsLoad});
+ }
+
+ if (BBToSkip.size() == Visited.size()) {
+ if (opts::Verbosity >= 2) {
+ outs() << "BOLT-INSTRUMENTER: all BBs are marked with true. Ignoring the "
+ "function "
+ << Function.getPrintName() << "\n";
+ }
+ return true;
+ }
+
return false; return false;
} }
@@ -307,7 +377,8 @@ void Instrumentation::instrumentFunction(BinaryFunction &Function,
if (BC.isMachO() && Function.hasName("___GLOBAL_init_65535/1")) if (BC.isMachO() && Function.hasName("___GLOBAL_init_65535/1"))
return; return;
- if (BC.isAArch64() && hasAArch64ExclusiveMemop(Function))+ std::unordered_set<const BinaryBasicBlock *> BBToSkip;
+ if (BC.isAArch64() && hasAArch64ExclusiveMemop(Function, BBToSkip))
return; return;
SplitWorklistTy SplitWorklist; SplitWorklistTy SplitWorklist;
@@ -389,6 +460,11 @@ void Instrumentation::instrumentFunction(BinaryFunction &Function,
for (auto BBI = Function.begin(), BBE = Function.end(); BBI != BBE; ++BBI) { for (auto BBI = Function.begin(), BBE = Function.end(); BBI != BBE; ++BBI) {
BinaryBasicBlock &BB = *BBI; BinaryBasicBlock &BB = *BBI;
+
+ // Skip BBs with exclusive load/stores
+ if (BBToSkip.find(&BB) != BBToSkip.end())
+ continue;
+
bool HasUnconditionalBranch = false; bool HasUnconditionalBranch = false;
bool HasJumpTable = false; bool HasJumpTable = false;
bool IsInvokeBlock = InvokeBlocks.count(&BB) > 0; bool IsInvokeBlock = InvokeBlocks.count(&BB) > 0;
bolt/lib/Passes/ShrinkWrapping.cpp
@@ -680,16 +680,15 @@ void StackLayoutModifier::performChanges() {
if (StackPtrReg != BC.MIB->getFramePointer()) if (StackPtrReg != BC.MIB->getFramePointer())
Adjustment = -Adjustment; Adjustment = -Adjustment;
if (IsLoad) if (IsLoad)
- Success = BC.MIB->createRestoreFromStack(+ BC.MIB->createRestoreFromStack(Inst, StackPtrReg,
- Inst, StackPtrReg, StackOffset + Adjustment, Reg, Size);+ StackOffset + Adjustment, Reg, Size);
else if (IsStore) else if (IsStore)
- Success = BC.MIB->createSaveToStack(+ BC.MIB->createSaveToStack(Inst, StackPtrReg, StackOffset + Adjustment,
- Inst, StackPtrReg, StackOffset + Adjustment, Reg, Size);+ Reg, Size);
LLVM_DEBUG({ LLVM_DEBUG({
dbgs() << "Adjusted instruction: "; dbgs() << "Adjusted instruction: ";
Inst.dump(); Inst.dump();
}); });
- assert(Success);
} }
} }
} }
@@ -1653,19 +1652,13 @@ Expected<MCInst> ShrinkWrapping::createStackAccess(int SPVal, int FPVal,
if (SPVal != StackPointerTracking::SUPERPOSITION && if (SPVal != StackPointerTracking::SUPERPOSITION &&
SPVal != StackPointerTracking::EMPTY) { SPVal != StackPointerTracking::EMPTY) {
if (FIE.IsLoad) { if (FIE.IsLoad) {
- if (!BC.MIB->createRestoreFromStack(NewInst, BC.MIB->getStackPointer(),+ BC.MIB->createRestoreFromStack(NewInst, BC.MIB->getStackPointer(),
- FIE.StackOffset - SPVal, FIE.RegOrImm,
- FIE.Size)) {
- return createFatalBOLTError(
- "createRestoreFromStack: not supported on this platform\n");
- }
- } else {
- if (!BC.MIB->createSaveToStack(NewInst, BC.MIB->getStackPointer(),
FIE.StackOffset - SPVal, FIE.RegOrImm, FIE.StackOffset - SPVal, FIE.RegOrImm,
- FIE.Size)) {+ FIE.Size);
- return createFatalBOLTError(+ } else {
- "createSaveToStack: not supported on this platform\n");+ BC.MIB->createSaveToStack(NewInst, BC.MIB->getStackPointer(),
- }+ FIE.StackOffset - SPVal, FIE.RegOrImm,
+ FIE.Size);
} }
if (CreatePushOrPop) if (CreatePushOrPop)
BC.MIB->changeToPushOrPop(NewInst); BC.MIB->changeToPushOrPop(NewInst);
@@ -1675,19 +1668,12 @@ Expected<MCInst> ShrinkWrapping::createStackAccess(int SPVal, int FPVal,
FPVal != StackPointerTracking::EMPTY); FPVal != StackPointerTracking::EMPTY);
if (FIE.IsLoad) { if (FIE.IsLoad) {
- if (!BC.MIB->createRestoreFromStack(NewInst, BC.MIB->getFramePointer(),+ BC.MIB->createRestoreFromStack(NewInst, BC.MIB->getFramePointer(),
- FIE.StackOffset - FPVal, FIE.RegOrImm,
- FIE.Size)) {
- return createFatalBOLTError(
- "createRestoreFromStack: not supported on this platform\n");
- }
- } else {
- if (!BC.MIB->createSaveToStack(NewInst, BC.MIB->getFramePointer(),
FIE.StackOffset - FPVal, FIE.RegOrImm, FIE.StackOffset - FPVal, FIE.RegOrImm,
- FIE.Size)) {+ FIE.Size);
- return createFatalBOLTError(+ } else {
- "createSaveToStack: not supported on this platform\n");+ BC.MIB->createSaveToStack(NewInst, BC.MIB->getFramePointer(),
- }+ FIE.StackOffset - FPVal, FIE.RegOrImm, FIE.Size);
} }
return NewInst; return NewInst;
} }
bolt/lib/Rewrite/DWARFRewriter.cpp
@@ -347,6 +347,12 @@ static cl::opt<bool>
"multiple non-relocatable dwarf object files (dwo)."), "multiple non-relocatable dwarf object files (dwo)."),
cl::init(false), cl::cat(BoltCategory)); cl::init(false), cl::cat(BoltCategory));
+static cl::opt<bool> CreateDebugNames(
+ "create-debug-names-section",
+ cl::desc("Creates .debug_names section, if the input binary doesn't have "
+ "it already, for DWARF5 CU/TUs."),
+ cl::init(false), cl::cat(BoltCategory));
+
static cl::opt<bool> static cl::opt<bool>
DebugSkeletonCu("debug-skeleton-cu", DebugSkeletonCu("debug-skeleton-cu",
cl::desc("prints out offsetrs for abbrev and debu_info of " cl::desc("prints out offsetrs for abbrev and debu_info of "
@@ -692,6 +698,8 @@ void DWARFRewriter::updateDebugInfo() {
return ObjectName; return ObjectName;
}; };
+ DWARF5AcceleratorTable DebugNamesTable(opts::CreateDebugNames, BC,
+ *StrWriter);
DWPState State; DWPState State;
if (opts::WriteDWP) if (opts::WriteDWP)
initDWPState(State); initDWPState(State);
@@ -709,7 +717,8 @@ void DWARFRewriter::updateDebugInfo() {
: LegacyRangesSectionWriter.get(); : LegacyRangesSectionWriter.get();
// Skipping CUs that failed to load. // Skipping CUs that failed to load.
if (SplitCU) { if (SplitCU) {
- DIEBuilder DWODIEBuilder(BC, &(*SplitCU)->getContext(), Unit);+ DIEBuilder DWODIEBuilder(BC, &(*SplitCU)->getContext(), DebugNamesTable,
+ Unit);
DWODIEBuilder.buildDWOUnit(**SplitCU); DWODIEBuilder.buildDWOUnit(**SplitCU);
std::string DWOName = updateDWONameCompDir( std::string DWOName = updateDWONameCompDir(
*Unit, *DIEBlder, *DIEBlder->getUnitDIEbyUnit(*Unit)); *Unit, *DIEBlder, *DIEBlder->getUnitDIEbyUnit(*Unit));
@@ -749,7 +758,7 @@ void DWARFRewriter::updateDebugInfo() {
AddrWriter->update(*DIEBlder, *Unit); AddrWriter->update(*DIEBlder, *Unit);
}; };
- DIEBuilder DIEBlder(BC, BC.DwCtx.get());+ DIEBuilder DIEBlder(BC, BC.DwCtx.get(), DebugNamesTable);
DIEBlder.buildTypeUnits(StrOffstsWriter.get()); DIEBlder.buildTypeUnits(StrOffstsWriter.get());
SmallVector<char, 20> OutBuffer; SmallVector<char, 20> OutBuffer;
std::unique_ptr<raw_svector_ostream> ObjOS = std::unique_ptr<raw_svector_ostream> ObjOS =
@@ -775,16 +784,19 @@ void DWARFRewriter::updateDebugInfo() {
} }
} else { } else {
// Update unit debug info in parallel // Update unit debug info in parallel
- ThreadPool &ThreadPool = ParallelUtilities::getThreadPool();+ ThreadPoolInterface &ThreadPool = ParallelUtilities::getThreadPool();
for (std::unique_ptr<DWARFUnit> &CU : BC.DwCtx->compile_units()) for (std::unique_ptr<DWARFUnit> &CU : BC.DwCtx->compile_units())
ThreadPool.async(processUnitDIE, CU.get(), &DIEBlder); ThreadPool.async(processUnitDIE, CU.get(), &DIEBlder);
ThreadPool.wait(); ThreadPool.wait();
} }
+ DebugNamesTable.emitAccelTable();
+
if (opts::WriteDWP) if (opts::WriteDWP)
finalizeDWP(State); finalizeDWP(State);
- finalizeDebugSections(DIEBlder, *Streamer, *ObjOS, OffsetMap);+ finalizeDebugSections(DIEBlder, DebugNamesTable, *Streamer, *ObjOS,
+ OffsetMap);
updateGdbIndexSection(OffsetMap, CUIndex); updateGdbIndexSection(OffsetMap, CUIndex);
} }
@@ -1515,10 +1527,9 @@ CUOffsetMap DWARFRewriter::finalizeTypeSections(DIEBuilder &DIEBlder,
return CUMap; return CUMap;
} }
-void DWARFRewriter::finalizeDebugSections(DIEBuilder &DIEBlder,+void DWARFRewriter::finalizeDebugSections(
- DIEStreamer &Streamer,+ DIEBuilder &DIEBlder, DWARF5AcceleratorTable &DebugNamesTable,
- raw_svector_ostream &ObjOS,+ DIEStreamer &Streamer, raw_svector_ostream &ObjOS, CUOffsetMap &CUMap) {
- CUOffsetMap &CUMap) {
if (StrWriter->isInitialized()) { if (StrWriter->isInitialized()) {
RewriteInstance::addToDebugSectionsToOverwrite(".debug_str"); RewriteInstance::addToDebugSectionsToOverwrite(".debug_str");
std::unique_ptr<DebugStrBufferVector> DebugStrSectionContents = std::unique_ptr<DebugStrBufferVector> DebugStrSectionContents =
@@ -1616,6 +1627,15 @@ void DWARFRewriter::finalizeDebugSections(DIEBuilder &DIEBlder,
copyByteArray(ARangesContents), copyByteArray(ARangesContents),
ARangesContents.size()); ARangesContents.size());
} }
+
+ if (DebugNamesTable.isCreated()) {
+ RewriteInstance::addToDebugSectionsToOverwrite(".debug_names");
+ std::unique_ptr<DebugBufferVector> DebugNamesSectionContents =
+ DebugNamesTable.releaseBuffer();
+ BC.registerOrUpdateNoteSection(".debug_names",
+ copyByteArray(*DebugNamesSectionContents),
+ DebugNamesSectionContents->size());
+ }
} }
void DWARFRewriter::finalizeCompileUnits(DIEBuilder &DIEBlder, void DWARFRewriter::finalizeCompileUnits(DIEBuilder &DIEBlder,
bolt/lib/Rewrite/LinuxKernelRewriter.cpp
@@ -14,6 +14,7 @@
#include "bolt/Rewrite/MetadataRewriter.h" #include "bolt/Rewrite/MetadataRewriter.h"
#include "bolt/Rewrite/MetadataRewriters.h" #include "bolt/Rewrite/MetadataRewriters.h"
#include "bolt/Utils/CommandLineOpts.h" #include "bolt/Utils/CommandLineOpts.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/Support/BinaryStreamWriter.h" #include "llvm/Support/BinaryStreamWriter.h"
#include "llvm/Support/CommandLine.h" #include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
@@ -27,19 +28,48 @@ using namespace bolt;
namespace opts { namespace opts {
static cl::opt<bool> static cl::opt<bool>
- PrintORC("print-orc",+ AltInstHasPadLen("alt-inst-has-padlen",
- cl::desc("print ORC unwind information for instructions"),+ cl::desc("specify that .altinstructions has padlen field"),
- cl::init(true), cl::Hidden, cl::cat(BoltCategory));+ cl::init(false), cl::Hidden, cl::cat(BoltCategory));
+
+static cl::opt<uint32_t>
+ AltInstFeatureSize("alt-inst-feature-size",
+ cl::desc("size of feature field in .altinstructions"),
+ cl::init(2), cl::Hidden, cl::cat(BoltCategory));
+
+static cl::opt<bool>
+ DumpAltInstructions("dump-alt-instructions",
+ cl::desc("dump Linux alternative instructions info"),
+ cl::init(false), cl::Hidden, cl::cat(BoltCategory));
+
+static cl::opt<bool>
+ DumpExceptions("dump-linux-exceptions",
+ cl::desc("dump Linux kernel exception table"),
+ cl::init(false), cl::Hidden, cl::cat(BoltCategory));
static cl::opt<bool> static cl::opt<bool>
DumpORC("dump-orc", cl::desc("dump raw ORC unwind information (sorted)"), DumpORC("dump-orc", cl::desc("dump raw ORC unwind information (sorted)"),
cl::init(false), cl::Hidden, cl::cat(BoltCategory)); cl::init(false), cl::Hidden, cl::cat(BoltCategory));
+static cl::opt<bool> DumpParavirtualPatchSites(
+ "dump-para-sites", cl::desc("dump Linux kernel paravitual patch sites"),
+ cl::init(false), cl::Hidden, cl::cat(BoltCategory));
+
+static cl::opt<bool>
+ DumpPCIFixups("dump-pci-fixups",
+ cl::desc("dump Linux kernel PCI fixup table"),
+ cl::init(false), cl::Hidden, cl::cat(BoltCategory));
+
static cl::opt<bool> DumpStaticCalls("dump-static-calls", static cl::opt<bool> DumpStaticCalls("dump-static-calls",
cl::desc("dump Linux kernel static calls"), cl::desc("dump Linux kernel static calls"),
cl::init(false), cl::Hidden, cl::init(false), cl::Hidden,
cl::cat(BoltCategory)); cl::cat(BoltCategory));
+static cl::opt<bool>
+ PrintORC("print-orc",
+ cl::desc("print ORC unwind information for instructions"),
+ cl::init(true), cl::Hidden, cl::cat(BoltCategory));
+
} // namespace opts } // namespace opts
/// Linux Kernel supports stack unwinding using ORC (oops rewind capability). /// Linux Kernel supports stack unwinding using ORC (oops rewind capability).
@@ -134,6 +164,32 @@ class LinuxKernelRewriter final : public MetadataRewriter {
using StaticCallListType = std::vector<StaticCallInfo>; using StaticCallListType = std::vector<StaticCallInfo>;
StaticCallListType StaticCallEntries; StaticCallListType StaticCallEntries;
+ /// Section containing the Linux exception table.
+ ErrorOr<BinarySection &> ExceptionsSection = std::errc::bad_address;
+ static constexpr size_t EXCEPTION_TABLE_ENTRY_SIZE = 12;
+
+ /// Functions with exception handling code.
+ DenseSet<BinaryFunction *> FunctionsWithExceptions;
+
+ /// Section with paravirtual patch sites.
+ ErrorOr<BinarySection &> ParavirtualPatchSection = std::errc::bad_address;
+
+ /// Alignment of paravirtual patch structures.
+ static constexpr size_t PARA_PATCH_ALIGN = 8;
+
+ /// .altinstructions section.
+ ErrorOr<BinarySection &> AltInstrSection = std::errc::bad_address;
+
+ /// Section containing Linux bug table.
+ ErrorOr<BinarySection &> BugTableSection = std::errc::bad_address;
+
+ /// Size of bug_entry struct.
+ static constexpr size_t BUG_TABLE_ENTRY_SIZE = 12;
+
+ /// .pci_fixup section.
+ ErrorOr<BinarySection &> PCIFixupSection = std::errc::bad_address;
+ static constexpr size_t PCI_FIXUP_ENTRY_SIZE = 16;
+
/// Insert an LKMarker for a given code pointer \p PC from a non-code section /// Insert an LKMarker for a given code pointer \p PC from a non-code section
/// \p SectionName. /// \p SectionName.
void insertLKMarker(uint64_t PC, uint64_t SectionOffset, void insertLKMarker(uint64_t PC, uint64_t SectionOffset,
@@ -143,18 +199,9 @@ class LinuxKernelRewriter final : public MetadataRewriter {
/// Process linux kernel special sections and their relocations. /// Process linux kernel special sections and their relocations.
void processLKSections(); void processLKSections();
- /// Process special linux kernel section, __ex_table.
- void processLKExTable();
-
- /// Process special linux kernel section, .pci_fixup.
- void processLKPCIFixup();
-
/// Process __ksymtab and __ksymtab_gpl. /// Process __ksymtab and __ksymtab_gpl.
void processLKKSymtab(bool IsGPL = false); void processLKKSymtab(bool IsGPL = false);
- /// Process special linux kernel section, __bug_table.
- void processLKBugTable();
-
/// Process special linux kernel section, .smp_locks. /// Process special linux kernel section, .smp_locks.
void processLKSMPLocks(); void processLKSMPLocks();
@@ -174,6 +221,20 @@ class LinuxKernelRewriter final : public MetadataRewriter {
Error readStaticCalls(); Error readStaticCalls();
Error rewriteStaticCalls(); Error rewriteStaticCalls();
+ Error readExceptionTable();
+ Error rewriteExceptionTable();
+
+ /// Paravirtual instruction patch sites.
+ Error readParaInstructions();
+
+ Error readBugTable();
+
+ /// Read alternative instruction info from .altinstructions.
+ Error readAltInstructions();
+
+ /// Read .pci_fixup
+ Error readPCIFixupTable();
+
/// Mark instructions referenced by kernel metadata. /// Mark instructions referenced by kernel metadata.
Error markInstructions(); Error markInstructions();
@@ -192,6 +253,21 @@ public:
if (Error E = readStaticCalls()) if (Error E = readStaticCalls())
return E; return E;
+ if (Error E = readExceptionTable())
+ return E;
+
+ if (Error E = readParaInstructions())
+ return E;
+
+ if (Error E = readBugTable())
+ return E;
+
+ if (Error E = readAltInstructions())
+ return E;
+
+ if (Error E = readPCIFixupTable())
+ return E;
+
return Error::success(); return Error::success();
} }
@@ -203,6 +279,11 @@ public:
} }
Error preEmitFinalizer() override { Error preEmitFinalizer() override {
+ // Since rewriteExceptionTable() can mark functions as non-simple, run it
+ // before other rewriters that depend on simple/emit status.
+ if (Error E = rewriteExceptionTable())
+ return E;
+
if (Error E = rewriteORCTables()) if (Error E = rewriteORCTables())
return E; return E;
@@ -249,106 +330,11 @@ void LinuxKernelRewriter::insertLKMarker(uint64_t PC, uint64_t SectionOffset,
} }
void LinuxKernelRewriter::processLKSections() { void LinuxKernelRewriter::processLKSections() {
- processLKExTable();
- processLKPCIFixup();
processLKKSymtab(); processLKKSymtab();
processLKKSymtab(true); processLKKSymtab(true);
- processLKBugTable();
processLKSMPLocks(); processLKSMPLocks();
} }
-/// Process __ex_table section of Linux Kernel.
-/// This section contains information regarding kernel level exception
-/// handling (https://www.kernel.org/doc/html/latest/x86/exception-tables.html).
-/// More documentation is in arch/x86/include/asm/extable.h.
-///
-/// The section is the list of the following structures:
-///
-/// struct exception_table_entry {
-/// int insn;
-/// int fixup;
-/// int handler;
-/// };
-///
-void LinuxKernelRewriter::processLKExTable() {
- ErrorOr<BinarySection &> SectionOrError =
- BC.getUniqueSectionByName("__ex_table");
- if (!SectionOrError)
- return;
-
- const uint64_t SectionSize = SectionOrError->getSize();
- const uint64_t SectionAddress = SectionOrError->getAddress();
- assert((SectionSize % 12) == 0 &&
- "The size of the __ex_table section should be a multiple of 12");
- for (uint64_t I = 0; I < SectionSize; I += 4) {
- const uint64_t EntryAddress = SectionAddress + I;
- ErrorOr<uint64_t> Offset = BC.getSignedValueAtAddress(EntryAddress, 4);
- assert(Offset && "failed reading PC-relative offset for __ex_table");
- int32_t SignedOffset = *Offset;
- const uint64_t RefAddress = EntryAddress + SignedOffset;
-
- BinaryFunction *ContainingBF =
- BC.getBinaryFunctionContainingAddress(RefAddress);
- if (!ContainingBF)
- continue;
-
- MCSymbol *ReferencedSymbol = ContainingBF->getSymbol();
- const uint64_t FunctionOffset = RefAddress - ContainingBF->getAddress();
- switch (I % 12) {
- default:
- llvm_unreachable("bad alignment of __ex_table");
- break;
- case 0:
- // insn
- insertLKMarker(RefAddress, I, SignedOffset, true, "__ex_table");
- break;
- case 4:
- // fixup
- if (FunctionOffset)
- ReferencedSymbol = ContainingBF->addEntryPointAtOffset(FunctionOffset);
- BC.addRelocation(EntryAddress, ReferencedSymbol, Relocation::getPC32(), 0,
- *Offset);
- break;
- case 8:
- // handler
- assert(!FunctionOffset &&
- "__ex_table handler entry should point to function start");
- BC.addRelocation(EntryAddress, ReferencedSymbol, Relocation::getPC32(), 0,
- *Offset);
- break;
- }
- }
-}
-
-/// Process .pci_fixup section of Linux Kernel.
-/// This section contains a list of entries for different PCI devices and their
-/// corresponding hook handler (code pointer where the fixup
-/// code resides, usually on x86_64 it is an entry PC relative 32 bit offset).
-/// Documentation is in include/linux/pci.h.
-void LinuxKernelRewriter::processLKPCIFixup() {
- ErrorOr<BinarySection &> SectionOrError =
- BC.getUniqueSectionByName(".pci_fixup");
- if (!SectionOrError)
- return;
-
- const uint64_t SectionSize = SectionOrError->getSize();
- const uint64_t SectionAddress = SectionOrError->getAddress();
- assert((SectionSize % 16) == 0 && ".pci_fixup size is not a multiple of 16");
-
- for (uint64_t I = 12; I + 4 <= SectionSize; I += 16) {
- const uint64_t PC = SectionAddress + I;
- ErrorOr<uint64_t> Offset = BC.getSignedValueAtAddress(PC, 4);
- assert(Offset && "cannot read value from .pci_fixup");
- const int32_t SignedOffset = *Offset;
- const uint64_t HookupAddress = PC + SignedOffset;
- BinaryFunction *HookupFunction =
- BC.getBinaryFunctionAtAddress(HookupAddress);
- assert(HookupFunction && "expected function for entry in .pci_fixup");
- BC.addRelocation(PC, HookupFunction->getSymbol(), Relocation::getPC32(), 0,
- *Offset);
- }
-}
-
/// Process __ksymtab[_gpl] sections of Linux Kernel. /// Process __ksymtab[_gpl] sections of Linux Kernel.
/// This section lists all the vmlinux symbols that kernel modules can access. /// This section lists all the vmlinux symbols that kernel modules can access.
/// ///
@@ -383,37 +369,6 @@ void LinuxKernelRewriter::processLKKSymtab(bool IsGPL) {
} }
} }
-/// Process __bug_table section.
-/// This section contains information useful for kernel debugging.
-/// Each entry in the section is a struct bug_entry that contains a pointer to
-/// the ud2 instruction corresponding to the bug, corresponding file name (both
-/// pointers use PC relative offset addressing), line number, and flags.
-/// The definition of the struct bug_entry can be found in
-/// `include/asm-generic/bug.h`
-void LinuxKernelRewriter::processLKBugTable() {
- ErrorOr<BinarySection &> SectionOrError =
- BC.getUniqueSectionByName("__bug_table");
- if (!SectionOrError)
- return;
-
- const uint64_t SectionSize = SectionOrError->getSize();
- const uint64_t SectionAddress = SectionOrError->getAddress();
- assert((SectionSize % 12) == 0 &&
- "The size of the __bug_table section should be a multiple of 12");
- for (uint64_t I = 0; I < SectionSize; I += 12) {
- const uint64_t EntryAddress = SectionAddress + I;
- ErrorOr<uint64_t> Offset = BC.getSignedValueAtAddress(EntryAddress, 4);
- assert(Offset &&
- "Reading valid PC-relative offset for a __bug_table entry");
- const int32_t SignedOffset = *Offset;
- const uint64_t RefAddress = EntryAddress + SignedOffset;
- assert(BC.getBinaryFunctionContainingAddress(RefAddress) &&
- "__bug_table entries should point to a function");
-
- insertLKMarker(RefAddress, I, SignedOffset, true, "__bug_table");
- }
-}
-
/// .smp_locks section contains PC-relative references to instructions with LOCK /// .smp_locks section contains PC-relative references to instructions with LOCK
/// prefix. The prefix can be converted to NOP at boot time on non-SMP systems. /// prefix. The prefix can be converted to NOP at boot time on non-SMP systems.
void LinuxKernelRewriter::processLKSMPLocks() { void LinuxKernelRewriter::processLKSMPLocks() {
@@ -527,7 +482,8 @@ Error LinuxKernelRewriter::readORCTables() {
// Consume the status of the cursor. // Consume the status of the cursor.
if (!IPCursor) if (!IPCursor)
return createStringError(errc::executable_format_error, return createStringError(errc::executable_format_error,
- "out of bounds while reading ORC IP table");+ "out of bounds while reading ORC IP table: %s",
+ toString(IPCursor.takeError()).c_str());
if (IP < PrevIP && opts::Verbosity) if (IP < PrevIP && opts::Verbosity)
BC.errs() << "BOLT-WARNING: out of order IP 0x" << Twine::utohexstr(IP) BC.errs() << "BOLT-WARNING: out of order IP 0x" << Twine::utohexstr(IP)
@@ -549,7 +505,8 @@ Error LinuxKernelRewriter::readORCTables() {
// Consume the status of the cursor. // Consume the status of the cursor.
if (!ORCCursor) if (!ORCCursor)
return createStringError(errc::executable_format_error, return createStringError(errc::executable_format_error,
- "out of bounds while reading ORC");+ "out of bounds while reading ORC: %s",
+ toString(ORCCursor.takeError()).c_str());
if (Entry.ORC == NullORC) if (Entry.ORC == NullORC)
continue; continue;
@@ -770,11 +727,8 @@ Error LinuxKernelRewriter::rewriteORCTables() {
continue; continue;
// Issue label for the instruction. // Issue label for the instruction.
- MCSymbol *Label = BC.MIB->getLabel(Inst);+ MCSymbol *Label =
- if (!Label) {+ BC.MIB->getOrCreateInstLabel(Inst, "__ORC_", BC.Ctx.get());
- Label = BC.Ctx->createTempSymbol("__ORC_");
- BC.MIB->setLabel(Inst, Label);
- }
if (Error E = emitORCEntry(0, *ErrorOrState, Label)) if (Error E = emitORCEntry(0, *ErrorOrState, Label))
return E; return E;
@@ -873,7 +827,8 @@ Error LinuxKernelRewriter::readStaticCalls() {
// Consume the status of the cursor. // Consume the status of the cursor.
if (!Cursor) if (!Cursor)
return createStringError(errc::executable_format_error, return createStringError(errc::executable_format_error,
- "out of bounds while reading static calls");+ "out of bounds while reading static calls: %s",
+ toString(Cursor.takeError()).c_str());
++EntryID; ++EntryID;
@@ -908,11 +863,8 @@ Error LinuxKernelRewriter::readStaticCalls() {
BC.MIB->addAnnotation(*Inst, "StaticCall", EntryID); BC.MIB->addAnnotation(*Inst, "StaticCall", EntryID);
- MCSymbol *Label = BC.MIB->getLabel(*Inst);+ MCSymbol *Label =
- if (!Label) {+ BC.MIB->getOrCreateInstLabel(*Inst, "__SC_", BC.Ctx.get());
- Label = BC.Ctx->createTempSymbol("__SC_");
- BC.MIB->setLabel(*Inst, Label);
- }
StaticCallEntries.push_back({EntryID, BF, Label}); StaticCallEntries.push_back({EntryID, BF, Label});
} }
@@ -949,6 +901,448 @@ Error LinuxKernelRewriter::rewriteStaticCalls() {
return Error::success(); return Error::success();
} }
+/// Instructions that access user-space memory can cause page faults. These
+/// faults will be handled by the kernel and execution will resume at the fixup
+/// code location if the address was invalid. The kernel uses the exception
+/// table to match the faulting instruction to its fixup. The table consists of
+/// the following entries:
+///
+/// struct exception_table_entry {
+/// int insn;
+/// int fixup;
+/// int data;
+/// };
+///
+/// More info at:
+/// https://www.kernel.org/doc/Documentation/x86/exception-tables.txt
+Error LinuxKernelRewriter::readExceptionTable() {
+ ExceptionsSection = BC.getUniqueSectionByName("__ex_table");
+ if (!ExceptionsSection)
+ return Error::success();
+
+ if (ExceptionsSection->getSize() % EXCEPTION_TABLE_ENTRY_SIZE)
+ return createStringError(errc::executable_format_error,
+ "exception table size error");
+
+ const uint64_t SectionAddress = ExceptionsSection->getAddress();
+ DataExtractor DE(ExceptionsSection->getContents(),
+ BC.AsmInfo->isLittleEndian(),
+ BC.AsmInfo->getCodePointerSize());
+ DataExtractor::Cursor Cursor(0);
+ uint32_t EntryID = 0;
+ while (Cursor && Cursor.tell() < ExceptionsSection->getSize()) {
+ const uint64_t InstAddress =
+ SectionAddress + Cursor.tell() + (int32_t)DE.getU32(Cursor);
+ const uint64_t FixupAddress =
+ SectionAddress + Cursor.tell() + (int32_t)DE.getU32(Cursor);
+ const uint64_t Data = DE.getU32(Cursor);
+
+ // Consume the status of the cursor.
+ if (!Cursor)
+ return createStringError(
+ errc::executable_format_error,
+ "out of bounds while reading exception table: %s",
+ toString(Cursor.takeError()).c_str());
+
+ ++EntryID;
+
+ if (opts::DumpExceptions) {
+ BC.outs() << "Exception Entry: " << EntryID << '\n';
+ BC.outs() << "\tInsn: 0x" << Twine::utohexstr(InstAddress) << '\n'
+ << "\tFixup: 0x" << Twine::utohexstr(FixupAddress) << '\n'
+ << "\tData: 0x" << Twine::utohexstr(Data) << '\n';
+ }
+
+ MCInst *Inst = nullptr;
+ MCSymbol *FixupLabel = nullptr;
+
+ BinaryFunction *InstBF = BC.getBinaryFunctionContainingAddress(InstAddress);
+ if (InstBF && BC.shouldEmit(*InstBF)) {
+ Inst = InstBF->getInstructionAtOffset(InstAddress - InstBF->getAddress());
+ if (!Inst)
+ return createStringError(errc::executable_format_error,
+ "no instruction at address 0x%" PRIx64
+ " in exception table",
+ InstAddress);
+ BC.MIB->addAnnotation(*Inst, "ExceptionEntry", EntryID);
+ FunctionsWithExceptions.insert(InstBF);
+ }
+
+ if (!InstBF && opts::Verbosity) {
+ BC.outs() << "BOLT-INFO: no function matches instruction at 0x"
+ << Twine::utohexstr(InstAddress)
+ << " referenced by Linux exception table\n";
+ }
+
+ BinaryFunction *FixupBF =
+ BC.getBinaryFunctionContainingAddress(FixupAddress);
+ if (FixupBF && BC.shouldEmit(*FixupBF)) {
+ const uint64_t Offset = FixupAddress - FixupBF->getAddress();
+ if (!FixupBF->getInstructionAtOffset(Offset))
+ return createStringError(errc::executable_format_error,
+ "no instruction at fixup address 0x%" PRIx64
+ " in exception table",
+ FixupAddress);
+ FixupLabel = Offset ? FixupBF->addEntryPointAtOffset(Offset)
+ : FixupBF->getSymbol();
+ if (Inst)
+ BC.MIB->addAnnotation(*Inst, "Fixup", FixupLabel->getName());
+ FunctionsWithExceptions.insert(FixupBF);
+ }
+
+ if (!FixupBF && opts::Verbosity) {
+ BC.outs() << "BOLT-INFO: no function matches fixup code at 0x"
+ << Twine::utohexstr(FixupAddress)
+ << " referenced by Linux exception table\n";
+ }
+ }
+
+ BC.outs() << "BOLT-INFO: parsed "
+ << ExceptionsSection->getSize() / EXCEPTION_TABLE_ENTRY_SIZE
+ << " exception table entries\n";
+
+ return Error::success();
+}
+
+/// Depending on the value of CONFIG_BUILDTIME_TABLE_SORT, the kernel expects
+/// the exception table to be sorted. Hence we have to sort it after code
+/// reordering.
+Error LinuxKernelRewriter::rewriteExceptionTable() {
+ // Disable output of functions with exceptions before rewrite support is
+ // added.
+ for (BinaryFunction *BF : FunctionsWithExceptions)
+ BF->setSimple(false);
+
+ return Error::success();
+}
+
+/// .parainsrtuctions section contains information for patching parvirtual call
+/// instructions during runtime. The entries in the section are in the form:
+///
+/// struct paravirt_patch_site {
+/// u8 *instr; /* original instructions */
+/// u8 type; /* type of this instruction */
+/// u8 len; /* length of original instruction */
+/// };
+///
+/// Note that the structures are aligned at 8-byte boundary.
+Error LinuxKernelRewriter::readParaInstructions() {
+ ParavirtualPatchSection = BC.getUniqueSectionByName(".parainstructions");
+ if (!ParavirtualPatchSection)
+ return Error::success();
+
+ DataExtractor DE = DataExtractor(ParavirtualPatchSection->getContents(),
+ BC.AsmInfo->isLittleEndian(),
+ BC.AsmInfo->getCodePointerSize());
+ uint32_t EntryID = 0;
+ DataExtractor::Cursor Cursor(0);
+ while (Cursor && !DE.eof(Cursor)) {
+ const uint64_t NextOffset = alignTo(Cursor.tell(), Align(PARA_PATCH_ALIGN));
+ if (!DE.isValidOffset(NextOffset))
+ break;
+
+ Cursor.seek(NextOffset);
+
+ const uint64_t InstrLocation = DE.getU64(Cursor);
+ const uint8_t Type = DE.getU8(Cursor);
+ const uint8_t Len = DE.getU8(Cursor);
+
+ if (!Cursor)
+ return createStringError(
+ errc::executable_format_error,
+ "out of bounds while reading .parainstructions: %s",
+ toString(Cursor.takeError()).c_str());
+
+ ++EntryID;
+
+ if (opts::DumpParavirtualPatchSites) {
+ BC.outs() << "Paravirtual patch site: " << EntryID << '\n';
+ BC.outs() << "\tInstr: 0x" << Twine::utohexstr(InstrLocation)
+ << "\n\tType: 0x" << Twine::utohexstr(Type) << "\n\tLen: 0x"
+ << Twine::utohexstr(Len) << '\n';
+ }
+
+ BinaryFunction *BF = BC.getBinaryFunctionContainingAddress(InstrLocation);
+ if (!BF && opts::Verbosity) {
+ BC.outs() << "BOLT-INFO: no function matches address 0x"
+ << Twine::utohexstr(InstrLocation)
+ << " referenced by paravirutal patch site\n";
+ }
+
+ if (BF && BC.shouldEmit(*BF)) {
+ MCInst *Inst =
+ BF->getInstructionAtOffset(InstrLocation - BF->getAddress());
+ if (!Inst)
+ return createStringError(errc::executable_format_error,
+ "no instruction at address 0x%" PRIx64
+ " in paravirtual call site %d",
+ InstrLocation, EntryID);
+ BC.MIB->addAnnotation(*Inst, "ParaSite", EntryID);
+ }
+ }
+
+ BC.outs() << "BOLT-INFO: parsed " << EntryID << " paravirtual patch sites\n";
+
+ return Error::success();
+}
+
+/// Process __bug_table section.
+/// This section contains information useful for kernel debugging.
+/// Each entry in the section is a struct bug_entry that contains a pointer to
+/// the ud2 instruction corresponding to the bug, corresponding file name (both
+/// pointers use PC relative offset addressing), line number, and flags.
+/// The definition of the struct bug_entry can be found in
+/// `include/asm-generic/bug.h`
+///
+/// NB: find_bug() uses linear search to match an address to an entry in the bug
+/// table. Hence there is no need to sort entries when rewriting the table.
+Error LinuxKernelRewriter::readBugTable() {
+ BugTableSection = BC.getUniqueSectionByName("__bug_table");
+ if (!BugTableSection)
+ return Error::success();
+
+ if (BugTableSection->getSize() % BUG_TABLE_ENTRY_SIZE)
+ return createStringError(errc::executable_format_error,
+ "bug table size error");
+
+ const uint64_t SectionAddress = BugTableSection->getAddress();
+ DataExtractor DE(BugTableSection->getContents(), BC.AsmInfo->isLittleEndian(),
+ BC.AsmInfo->getCodePointerSize());
+ DataExtractor::Cursor Cursor(0);
+ uint32_t EntryID = 0;
+ while (Cursor && Cursor.tell() < BugTableSection->getSize()) {
+ const uint64_t Pos = Cursor.tell();
+ const uint64_t InstAddress =
+ SectionAddress + Pos + (int32_t)DE.getU32(Cursor);
+ Cursor.seek(Pos + BUG_TABLE_ENTRY_SIZE);
+
+ if (!Cursor)
+ return createStringError(errc::executable_format_error,
+ "out of bounds while reading __bug_table: %s",
+ toString(Cursor.takeError()).c_str());
+
+ ++EntryID;
+
+ BinaryFunction *BF = BC.getBinaryFunctionContainingAddress(InstAddress);
+ if (!BF && opts::Verbosity) {
+ BC.outs() << "BOLT-INFO: no function matches address 0x"
+ << Twine::utohexstr(InstAddress)
+ << " referenced by bug table\n";
+ }
+
+ if (BF && BC.shouldEmit(*BF)) {
+ MCInst *Inst = BF->getInstructionAtOffset(InstAddress - BF->getAddress());
+ if (!Inst)
+ return createStringError(errc::executable_format_error,
+ "no instruction at address 0x%" PRIx64
+ " referenced by bug table entry %d",
+ InstAddress, EntryID);
+ BC.MIB->addAnnotation(*Inst, "BugEntry", EntryID);
+ }
+ }
+
+ BC.outs() << "BOLT-INFO: parsed " << EntryID << " bug table entries\n";
+
+ return Error::success();
+}
+
+/// The kernel can replace certain instruction sequences depending on hardware
+/// it is running on and features specified during boot time. The information
+/// about alternative instruction sequences is stored in .altinstructions
+/// section. The format of entries in this section is defined in
+/// arch/x86/include/asm/alternative.h:
+///
+/// struct alt_instr {
+/// s32 instr_offset;
+/// s32 repl_offset;
+/// uXX feature;
+/// u8 instrlen;
+/// u8 replacementlen;
+/// u8 padlen; // present in older kernels
+/// } __packed;
+///
+/// Note the structures is packed.
+Error LinuxKernelRewriter::readAltInstructions() {
+ AltInstrSection = BC.getUniqueSectionByName(".altinstructions");
+ if (!AltInstrSection)
+ return Error::success();
+
+ const uint64_t Address = AltInstrSection->getAddress();
+ DataExtractor DE = DataExtractor(AltInstrSection->getContents(),
+ BC.AsmInfo->isLittleEndian(),
+ BC.AsmInfo->getCodePointerSize());
+ uint64_t EntryID = 0;
+ DataExtractor::Cursor Cursor(0);
+ while (Cursor && !DE.eof(Cursor)) {
+ const uint64_t OrgInstAddress =
+ Address + Cursor.tell() + (int32_t)DE.getU32(Cursor);
+ const uint64_t AltInstAddress =
+ Address + Cursor.tell() + (int32_t)DE.getU32(Cursor);
+ const uint64_t Feature = DE.getUnsigned(Cursor, opts::AltInstFeatureSize);
+ const uint8_t OrgSize = DE.getU8(Cursor);
+ const uint8_t AltSize = DE.getU8(Cursor);
+
+ // Older kernels may have the padlen field.
+ const uint8_t PadLen = opts::AltInstHasPadLen ? DE.getU8(Cursor) : 0;
+
+ if (!Cursor)
+ return createStringError(
+ errc::executable_format_error,
+ "out of bounds while reading .altinstructions: %s",
+ toString(Cursor.takeError()).c_str());
+
+ ++EntryID;
+
+ if (opts::DumpAltInstructions) {
+ BC.outs() << "Alternative instruction entry: " << EntryID
+ << "\n\tOrg: 0x" << Twine::utohexstr(OrgInstAddress)
+ << "\n\tAlt: 0x" << Twine::utohexstr(AltInstAddress)
+ << "\n\tFeature: 0x" << Twine::utohexstr(Feature)
+ << "\n\tOrgSize: " << (int)OrgSize
+ << "\n\tAltSize: " << (int)AltSize << '\n';
+ if (opts::AltInstHasPadLen)
+ BC.outs() << "\tPadLen: " << (int)PadLen << '\n';
+ }
+
+ if (AltSize > OrgSize)
+ return createStringError(errc::executable_format_error,
+ "error reading .altinstructions");
+
+ BinaryFunction *BF = BC.getBinaryFunctionContainingAddress(OrgInstAddress);
+ if (!BF && opts::Verbosity) {
+ BC.outs() << "BOLT-INFO: no function matches address 0x"
+ << Twine::utohexstr(OrgInstAddress)
+ << " of instruction from .altinstructions\n";
+ }
+
+ BinaryFunction *AltBF =
+ BC.getBinaryFunctionContainingAddress(AltInstAddress);
+ if (AltBF && BC.shouldEmit(*AltBF)) {
+ BC.errs()
+ << "BOLT-WARNING: alternative instruction sequence found in function "
+ << *AltBF << '\n';
+ AltBF->setIgnored();
+ }
+
+ if (!BF || !BC.shouldEmit(*BF))
+ continue;
+
+ if (OrgInstAddress + OrgSize > BF->getAddress() + BF->getSize())
+ return createStringError(errc::executable_format_error,
+ "error reading .altinstructions");
+
+ MCInst *Inst =
+ BF->getInstructionAtOffset(OrgInstAddress - BF->getAddress());
+ if (!Inst)
+ return createStringError(errc::executable_format_error,
+ "no instruction at address 0x%" PRIx64
+ " referenced by .altinstructions entry %d",
+ OrgInstAddress, EntryID);
+
+ // There could be more than one alternative instruction sequences for the
+ // same original instruction. Annotate each alternative separately.
+ std::string AnnotationName = "AltInst";
+ unsigned N = 2;
+ while (BC.MIB->hasAnnotation(*Inst, AnnotationName))
+ AnnotationName = "AltInst" + std::to_string(N++);
+
+ BC.MIB->addAnnotation(*Inst, AnnotationName, EntryID);
+
+ // Annotate all instructions from the original sequence. Note that it's not
+ // the most efficient way to look for instructions in the address range,
+ // but since alternative instructions are uncommon, it will do for now.
+ for (uint32_t Offset = 1; Offset < OrgSize; ++Offset) {
+ Inst = BF->getInstructionAtOffset(OrgInstAddress + Offset -
+ BF->getAddress());
+ if (Inst)
+ BC.MIB->addAnnotation(*Inst, AnnotationName, EntryID);
+ }
+ }
+
+ BC.outs() << "BOLT-INFO: parsed " << EntryID
+ << " alternative instruction entries\n";
+
+ return Error::success();
+}
+
+/// When the Linux kernel needs to handle an error associated with a given PCI
+/// device, it uses a table stored in .pci_fixup section to locate a fixup code
+/// specific to the vendor and the problematic device. The section contains a
+/// list of the following structures defined in include/linux/pci.h:
+///
+/// struct pci_fixup {
+/// u16 vendor; /* Or PCI_ANY_ID */
+/// u16 device; /* Or PCI_ANY_ID */
+/// u32 class; /* Or PCI_ANY_ID */
+/// unsigned int class_shift; /* should be 0, 8, 16 */
+/// int hook_offset;
+/// };
+///
+/// Normally, the hook will point to a function start and we don't have to
+/// update the pointer if we are not relocating functions. Hence, while reading
+/// the table we validate this assumption. If a function has a fixup code in the
+/// middle of its body, we issue a warning and ignore it.
+Error LinuxKernelRewriter::readPCIFixupTable() {
+ PCIFixupSection = BC.getUniqueSectionByName(".pci_fixup");
+ if (!PCIFixupSection)
+ return Error::success();
+
+ if (PCIFixupSection->getSize() % PCI_FIXUP_ENTRY_SIZE)
+ return createStringError(errc::executable_format_error,
+ "PCI fixup table size error");
+
+ const uint64_t Address = PCIFixupSection->getAddress();
+ DataExtractor DE = DataExtractor(PCIFixupSection->getContents(),
+ BC.AsmInfo->isLittleEndian(),
+ BC.AsmInfo->getCodePointerSize());
+ uint64_t EntryID = 0;
+ DataExtractor::Cursor Cursor(0);
+ while (Cursor && !DE.eof(Cursor)) {
+ const uint16_t Vendor = DE.getU16(Cursor);
+ const uint16_t Device = DE.getU16(Cursor);
+ const uint32_t Class = DE.getU32(Cursor);
+ const uint32_t ClassShift = DE.getU32(Cursor);
+ const uint64_t HookAddress =
+ Address + Cursor.tell() + (int32_t)DE.getU32(Cursor);
+
+ if (!Cursor)
+ return createStringError(errc::executable_format_error,
+ "out of bounds while reading .pci_fixup: %s",
+ toString(Cursor.takeError()).c_str());
+
+ ++EntryID;
+
+ if (opts::DumpPCIFixups) {
+ BC.outs() << "PCI fixup entry: " << EntryID << "\n\tVendor 0x"
+ << Twine::utohexstr(Vendor) << "\n\tDevice: 0x"
+ << Twine::utohexstr(Device) << "\n\tClass: 0x"
+ << Twine::utohexstr(Class) << "\n\tClassShift: 0x"
+ << Twine::utohexstr(ClassShift) << "\n\tHookAddress: 0x"
+ << Twine::utohexstr(HookAddress) << '\n';
+ }
+
+ BinaryFunction *BF = BC.getBinaryFunctionContainingAddress(HookAddress);
+ if (!BF && opts::Verbosity) {
+ BC.outs() << "BOLT-INFO: no function matches address 0x"
+ << Twine::utohexstr(HookAddress)
+ << " of hook from .pci_fixup\n";
+ }
+
+ if (!BF || !BC.shouldEmit(*BF))
+ continue;
+
+ if (const uint64_t Offset = HookAddress - BF->getAddress()) {
+ BC.errs() << "BOLT-WARNING: PCI fixup detected in the middle of function "
+ << *BF << " at offset 0x" << Twine::utohexstr(Offset) << '\n';
+ BF->setSimple(false);
+ }
+ }
+
+ BC.outs() << "BOLT-INFO: parsed " << EntryID << " PCI fixup entries\n";
+
+ return Error::success();
+}
+
} // namespace } // namespace
std::unique_ptr<MetadataRewriter> std::unique_ptr<MetadataRewriter>
bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp
@@ -270,32 +270,38 @@ public:
return isLDRB(Inst) || isLDRH(Inst) || isLDRW(Inst) || isLDRX(Inst); return isLDRB(Inst) || isLDRH(Inst) || isLDRW(Inst) || isLDRX(Inst);
} }
- bool isAArch64Exclusive(const MCInst &Inst) const override {+ bool isAArch64ExclusiveLoad(const MCInst &Inst) const override {
return (Inst.getOpcode() == AArch64::LDXPX || return (Inst.getOpcode() == AArch64::LDXPX ||
Inst.getOpcode() == AArch64::LDXPW || Inst.getOpcode() == AArch64::LDXPW ||
Inst.getOpcode() == AArch64::LDXRX || Inst.getOpcode() == AArch64::LDXRX ||
Inst.getOpcode() == AArch64::LDXRW || Inst.getOpcode() == AArch64::LDXRW ||
Inst.getOpcode() == AArch64::LDXRH || Inst.getOpcode() == AArch64::LDXRH ||
Inst.getOpcode() == AArch64::LDXRB || Inst.getOpcode() == AArch64::LDXRB ||
- Inst.getOpcode() == AArch64::STXPX ||
- Inst.getOpcode() == AArch64::STXPW ||
- Inst.getOpcode() == AArch64::STXRX ||
- Inst.getOpcode() == AArch64::STXRW ||
- Inst.getOpcode() == AArch64::STXRH ||
- Inst.getOpcode() == AArch64::STXRB ||
Inst.getOpcode() == AArch64::LDAXPX || Inst.getOpcode() == AArch64::LDAXPX ||
Inst.getOpcode() == AArch64::LDAXPW || Inst.getOpcode() == AArch64::LDAXPW ||
Inst.getOpcode() == AArch64::LDAXRX || Inst.getOpcode() == AArch64::LDAXRX ||
Inst.getOpcode() == AArch64::LDAXRW || Inst.getOpcode() == AArch64::LDAXRW ||
Inst.getOpcode() == AArch64::LDAXRH || Inst.getOpcode() == AArch64::LDAXRH ||
- Inst.getOpcode() == AArch64::LDAXRB ||+ Inst.getOpcode() == AArch64::LDAXRB);
+ }
+
+ bool isAArch64ExclusiveStore(const MCInst &Inst) const override {
+ return (Inst.getOpcode() == AArch64::STXPX ||
+ Inst.getOpcode() == AArch64::STXPW ||
+ Inst.getOpcode() == AArch64::STXRX ||
+ Inst.getOpcode() == AArch64::STXRW ||
+ Inst.getOpcode() == AArch64::STXRH ||
+ Inst.getOpcode() == AArch64::STXRB ||
Inst.getOpcode() == AArch64::STLXPX || Inst.getOpcode() == AArch64::STLXPX ||
Inst.getOpcode() == AArch64::STLXPW || Inst.getOpcode() == AArch64::STLXPW ||
Inst.getOpcode() == AArch64::STLXRX || Inst.getOpcode() == AArch64::STLXRX ||
Inst.getOpcode() == AArch64::STLXRW || Inst.getOpcode() == AArch64::STLXRW ||
Inst.getOpcode() == AArch64::STLXRH || Inst.getOpcode() == AArch64::STLXRH ||
- Inst.getOpcode() == AArch64::STLXRB ||+ Inst.getOpcode() == AArch64::STLXRB);
- Inst.getOpcode() == AArch64::CLREX);+ }
+
+ bool isAArch64ExclusiveClear(const MCInst &Inst) const override {
+ return (Inst.getOpcode() == AArch64::CLREX);
} }
bool isLoadFromStack(const MCInst &Inst) const { bool isLoadFromStack(const MCInst &Inst) const {
@@ -1020,7 +1026,7 @@ public:
return Code; return Code;
} }
- bool createTailCall(MCInst &Inst, const MCSymbol *Target,+ void createTailCall(MCInst &Inst, const MCSymbol *Target,
MCContext *Ctx) override { MCContext *Ctx) override {
return createDirectCall(Inst, Target, Ctx, /*IsTailCall*/ true); return createDirectCall(Inst, Target, Ctx, /*IsTailCall*/ true);
} }
@@ -1030,11 +1036,10 @@ public:
createShortJmp(Seq, Target, Ctx, /*IsTailCall*/ true); createShortJmp(Seq, Target, Ctx, /*IsTailCall*/ true);
} }
- bool createTrap(MCInst &Inst) const override {+ void createTrap(MCInst &Inst) const override {
Inst.clear(); Inst.clear();
Inst.setOpcode(AArch64::BRK); Inst.setOpcode(AArch64::BRK);
Inst.addOperand(MCOperand::createImm(1)); Inst.addOperand(MCOperand::createImm(1));
- return true;
} }
bool convertJmpToTailCall(MCInst &Inst) override { bool convertJmpToTailCall(MCInst &Inst) override {
@@ -1062,16 +1067,15 @@ public:
Inst.getOperand(0).getImm() == 0; Inst.getOperand(0).getImm() == 0;
} }
- bool createNoop(MCInst &Inst) const override {+ void createNoop(MCInst &Inst) const override {
Inst.setOpcode(AArch64::HINT); Inst.setOpcode(AArch64::HINT);
Inst.clear(); Inst.clear();
Inst.addOperand(MCOperand::createImm(0)); Inst.addOperand(MCOperand::createImm(0));
- return true;
} }
bool mayStore(const MCInst &Inst) const override { return false; } bool mayStore(const MCInst &Inst) const override { return false; }
- bool createDirectCall(MCInst &Inst, const MCSymbol *Target, MCContext *Ctx,+ void createDirectCall(MCInst &Inst, const MCSymbol *Target, MCContext *Ctx,
bool IsTailCall) override { bool IsTailCall) override {
Inst.setOpcode(IsTailCall ? AArch64::B : AArch64::BL); Inst.setOpcode(IsTailCall ? AArch64::B : AArch64::BL);
Inst.clear(); Inst.clear();
@@ -1080,7 +1084,6 @@ public:
*Ctx, 0))); *Ctx, 0)));
if (IsTailCall) if (IsTailCall)
convertJmpToTailCall(Inst); convertJmpToTailCall(Inst);
- return true;
} }
bool analyzeBranch(InstructionIterator Begin, InstructionIterator End, bool analyzeBranch(InstructionIterator Begin, InstructionIterator End,
@@ -1287,14 +1290,13 @@ public:
return true; return true;
} }
- bool createUncondBranch(MCInst &Inst, const MCSymbol *TBB,+ void createUncondBranch(MCInst &Inst, const MCSymbol *TBB,
MCContext *Ctx) const override { MCContext *Ctx) const override {
Inst.setOpcode(AArch64::B); Inst.setOpcode(AArch64::B);
Inst.clear(); Inst.clear();
Inst.addOperand(MCOperand::createExpr(getTargetExprFor( Inst.addOperand(MCOperand::createExpr(getTargetExprFor(
Inst, MCSymbolRefExpr::create(TBB, MCSymbolRefExpr::VK_None, *Ctx), Inst, MCSymbolRefExpr::create(TBB, MCSymbolRefExpr::VK_None, *Ctx),
*Ctx, 0))); *Ctx, 0)));
- return true;
} }
bool shouldRecordCodeRelocation(uint64_t RelType) const override { bool shouldRecordCodeRelocation(uint64_t RelType) const override {
@@ -1347,14 +1349,13 @@ public:
return StringRef("\0\0\0\0", 4); return StringRef("\0\0\0\0", 4);
} }
- bool createReturn(MCInst &Inst) const override {+ void createReturn(MCInst &Inst) const override {
Inst.setOpcode(AArch64::RET); Inst.setOpcode(AArch64::RET);
Inst.clear(); Inst.clear();
Inst.addOperand(MCOperand::createReg(AArch64::LR)); Inst.addOperand(MCOperand::createReg(AArch64::LR));
- return true;
} }
- bool createStackPointerIncrement(+ void createStackPointerIncrement(
MCInst &Inst, int Size, MCInst &Inst, int Size,
bool NoFlagsClobber = false /*unused for AArch64*/) const override { bool NoFlagsClobber = false /*unused for AArch64*/) const override {
Inst.setOpcode(AArch64::SUBXri); Inst.setOpcode(AArch64::SUBXri);
@@ -1363,10 +1364,9 @@ public:
Inst.addOperand(MCOperand::createReg(AArch64::SP)); Inst.addOperand(MCOperand::createReg(AArch64::SP));
Inst.addOperand(MCOperand::createImm(Size)); Inst.addOperand(MCOperand::createImm(Size));
Inst.addOperand(MCOperand::createImm(0)); Inst.addOperand(MCOperand::createImm(0));
- return true;
} }
- bool createStackPointerDecrement(+ void createStackPointerDecrement(
MCInst &Inst, int Size, MCInst &Inst, int Size,
bool NoFlagsClobber = false /*unused for AArch64*/) const override { bool NoFlagsClobber = false /*unused for AArch64*/) const override {
Inst.setOpcode(AArch64::ADDXri); Inst.setOpcode(AArch64::ADDXri);
@@ -1375,12 +1375,12 @@ public:
Inst.addOperand(MCOperand::createReg(AArch64::SP)); Inst.addOperand(MCOperand::createReg(AArch64::SP));
Inst.addOperand(MCOperand::createImm(Size)); Inst.addOperand(MCOperand::createImm(Size));
Inst.addOperand(MCOperand::createImm(0)); Inst.addOperand(MCOperand::createImm(0));
- return true;
} }
void createIndirectBranch(MCInst &Inst, MCPhysReg MemBaseReg, void createIndirectBranch(MCInst &Inst, MCPhysReg MemBaseReg,
int64_t Disp) const { int64_t Disp) const {
Inst.setOpcode(AArch64::BR); Inst.setOpcode(AArch64::BR);
+ Inst.clear();
Inst.addOperand(MCOperand::createReg(MemBaseReg)); Inst.addOperand(MCOperand::createReg(MemBaseReg));
} }
@@ -1623,6 +1623,9 @@ public:
uint64_t RelType; uint64_t RelType;
if (Fixup.getKind() == MCFixupKind(AArch64::fixup_aarch64_pcrel_call26)) if (Fixup.getKind() == MCFixupKind(AArch64::fixup_aarch64_pcrel_call26))
RelType = ELF::R_AARCH64_CALL26; RelType = ELF::R_AARCH64_CALL26;
+ else if (Fixup.getKind() ==
+ MCFixupKind(AArch64::fixup_aarch64_pcrel_branch26))
+ RelType = ELF::R_AARCH64_JUMP26;
else if (FKI.Flags & MCFixupKindInfo::FKF_IsPCRel) { else if (FKI.Flags & MCFixupKindInfo::FKF_IsPCRel) {
switch (FKI.TargetSize) { switch (FKI.TargetSize) {
default: default:
bolt/lib/Target/RISCV/RISCVMCPlusBuilder.cpp
@@ -219,46 +219,43 @@ public:
return true; return true;
} }
- bool createReturn(MCInst &Inst) const override {+ void createReturn(MCInst &Inst) const override {
// TODO "c.jr ra" when RVC is enabled // TODO "c.jr ra" when RVC is enabled
Inst.setOpcode(RISCV::JALR); Inst.setOpcode(RISCV::JALR);
Inst.clear(); Inst.clear();
Inst.addOperand(MCOperand::createReg(RISCV::X0)); Inst.addOperand(MCOperand::createReg(RISCV::X0));
Inst.addOperand(MCOperand::createReg(RISCV::X1)); Inst.addOperand(MCOperand::createReg(RISCV::X1));
Inst.addOperand(MCOperand::createImm(0)); Inst.addOperand(MCOperand::createImm(0));
- return true;
} }
- bool createUncondBranch(MCInst &Inst, const MCSymbol *TBB,+ void createUncondBranch(MCInst &Inst, const MCSymbol *TBB,
MCContext *Ctx) const override { MCContext *Ctx) const override {
Inst.setOpcode(RISCV::JAL); Inst.setOpcode(RISCV::JAL);
Inst.clear(); Inst.clear();
Inst.addOperand(MCOperand::createReg(RISCV::X0)); Inst.addOperand(MCOperand::createReg(RISCV::X0));
Inst.addOperand(MCOperand::createExpr( Inst.addOperand(MCOperand::createExpr(
MCSymbolRefExpr::create(TBB, MCSymbolRefExpr::VK_None, *Ctx))); MCSymbolRefExpr::create(TBB, MCSymbolRefExpr::VK_None, *Ctx)));
- return true;
} }
StringRef getTrapFillValue() const override { StringRef getTrapFillValue() const override {
return StringRef("\0\0\0\0", 4); return StringRef("\0\0\0\0", 4);
} }
- bool createCall(unsigned Opcode, MCInst &Inst, const MCSymbol *Target,+ void createCall(unsigned Opcode, MCInst &Inst, const MCSymbol *Target,
MCContext *Ctx) { MCContext *Ctx) {
Inst.setOpcode(Opcode); Inst.setOpcode(Opcode);
Inst.clear(); Inst.clear();
Inst.addOperand(MCOperand::createExpr(RISCVMCExpr::create( Inst.addOperand(MCOperand::createExpr(RISCVMCExpr::create(
MCSymbolRefExpr::create(Target, MCSymbolRefExpr::VK_None, *Ctx), MCSymbolRefExpr::create(Target, MCSymbolRefExpr::VK_None, *Ctx),
RISCVMCExpr::VK_RISCV_CALL, *Ctx))); RISCVMCExpr::VK_RISCV_CALL, *Ctx)));
- return true;
} }
- bool createCall(MCInst &Inst, const MCSymbol *Target,+ void createCall(MCInst &Inst, const MCSymbol *Target,
MCContext *Ctx) override { MCContext *Ctx) override {
return createCall(RISCV::PseudoCALL, Inst, Target, Ctx); return createCall(RISCV::PseudoCALL, Inst, Target, Ctx);
} }
- bool createTailCall(MCInst &Inst, const MCSymbol *Target,+ void createTailCall(MCInst &Inst, const MCSymbol *Target,
MCContext *Ctx) override { MCContext *Ctx) override {
return createCall(RISCV::PseudoTAIL, Inst, Target, Ctx); return createCall(RISCV::PseudoTAIL, Inst, Target, Ctx);
} }
bolt/lib/Target/X86/X86MCPlusBuilder.cpp
@@ -2230,7 +2230,7 @@ public:
return true; return true;
} }
- bool createStackPointerIncrement(MCInst &Inst, int Size,+ void createStackPointerIncrement(MCInst &Inst, int Size,
bool NoFlagsClobber) const override { bool NoFlagsClobber) const override {
if (NoFlagsClobber) { if (NoFlagsClobber) {
Inst.setOpcode(X86::LEA64r); Inst.setOpcode(X86::LEA64r);
@@ -2241,17 +2241,16 @@ public:
Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // IndexReg Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // IndexReg
Inst.addOperand(MCOperand::createImm(-Size)); // Displacement Inst.addOperand(MCOperand::createImm(-Size)); // Displacement
Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // AddrSegmentReg Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // AddrSegmentReg
- return true;+ return;
} }
Inst.setOpcode(X86::SUB64ri8); Inst.setOpcode(X86::SUB64ri8);
Inst.clear(); Inst.clear();
Inst.addOperand(MCOperand::createReg(X86::RSP)); Inst.addOperand(MCOperand::createReg(X86::RSP));
Inst.addOperand(MCOperand::createReg(X86::RSP)); Inst.addOperand(MCOperand::createReg(X86::RSP));
Inst.addOperand(MCOperand::createImm(Size)); Inst.addOperand(MCOperand::createImm(Size));
- return true;
} }
- bool createStackPointerDecrement(MCInst &Inst, int Size,+ void createStackPointerDecrement(MCInst &Inst, int Size,
bool NoFlagsClobber) const override { bool NoFlagsClobber) const override {
if (NoFlagsClobber) { if (NoFlagsClobber) {
Inst.setOpcode(X86::LEA64r); Inst.setOpcode(X86::LEA64r);
@@ -2262,22 +2261,22 @@ public:
Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // IndexReg Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // IndexReg
Inst.addOperand(MCOperand::createImm(Size)); // Displacement Inst.addOperand(MCOperand::createImm(Size)); // Displacement
Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // AddrSegmentReg Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // AddrSegmentReg
- return true;+ return;
} }
Inst.setOpcode(X86::ADD64ri8); Inst.setOpcode(X86::ADD64ri8);
Inst.clear(); Inst.clear();
Inst.addOperand(MCOperand::createReg(X86::RSP)); Inst.addOperand(MCOperand::createReg(X86::RSP));
Inst.addOperand(MCOperand::createReg(X86::RSP)); Inst.addOperand(MCOperand::createReg(X86::RSP));
Inst.addOperand(MCOperand::createImm(Size)); Inst.addOperand(MCOperand::createImm(Size));
- return true;
} }
- bool createSaveToStack(MCInst &Inst, const MCPhysReg &StackReg, int Offset,+ void createSaveToStack(MCInst &Inst, const MCPhysReg &StackReg, int Offset,
const MCPhysReg &SrcReg, int Size) const override { const MCPhysReg &SrcReg, int Size) const override {
unsigned NewOpcode; unsigned NewOpcode;
switch (Size) { switch (Size) {
default: default:
- return false;+ llvm_unreachable("Invalid operand size");
+ return;
case 2: NewOpcode = X86::MOV16mr; break; case 2: NewOpcode = X86::MOV16mr; break;
case 4: NewOpcode = X86::MOV32mr; break; case 4: NewOpcode = X86::MOV32mr; break;
case 8: NewOpcode = X86::MOV64mr; break; case 8: NewOpcode = X86::MOV64mr; break;
@@ -2290,10 +2289,9 @@ public:
Inst.addOperand(MCOperand::createImm(Offset)); // Displacement Inst.addOperand(MCOperand::createImm(Offset)); // Displacement
Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // AddrSegmentReg Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // AddrSegmentReg
Inst.addOperand(MCOperand::createReg(SrcReg)); Inst.addOperand(MCOperand::createReg(SrcReg));
- return true;
} }
- bool createRestoreFromStack(MCInst &Inst, const MCPhysReg &StackReg,+ void createRestoreFromStack(MCInst &Inst, const MCPhysReg &StackReg,
int Offset, const MCPhysReg &DstReg, int Offset, const MCPhysReg &DstReg,
int Size) const override { int Size) const override {
return createLoad(Inst, StackReg, /*Scale=*/1, /*IndexReg=*/X86::NoRegister, return createLoad(Inst, StackReg, /*Scale=*/1, /*IndexReg=*/X86::NoRegister,
@@ -2301,14 +2299,15 @@ public:
DstReg, Size); DstReg, Size);
} }
- bool createLoad(MCInst &Inst, const MCPhysReg &BaseReg, int64_t Scale,+ void createLoad(MCInst &Inst, const MCPhysReg &BaseReg, int64_t Scale,
const MCPhysReg &IndexReg, int64_t Offset, const MCPhysReg &IndexReg, int64_t Offset,
const MCExpr *OffsetExpr, const MCPhysReg &AddrSegmentReg, const MCExpr *OffsetExpr, const MCPhysReg &AddrSegmentReg,
const MCPhysReg &DstReg, int Size) const override { const MCPhysReg &DstReg, int Size) const override {
unsigned NewOpcode; unsigned NewOpcode;
switch (Size) { switch (Size) {
default: default:
- return false;+ llvm_unreachable("Invalid operand size");
+ return;
case 2: NewOpcode = X86::MOV16rm; break; case 2: NewOpcode = X86::MOV16rm; break;
case 4: NewOpcode = X86::MOV32rm; break; case 4: NewOpcode = X86::MOV32rm; break;
case 8: NewOpcode = X86::MOV64rm; break; case 8: NewOpcode = X86::MOV64rm; break;
@@ -2324,7 +2323,6 @@ public:
else else
Inst.addOperand(MCOperand::createImm(Offset)); // Displacement Inst.addOperand(MCOperand::createImm(Offset)); // Displacement
Inst.addOperand(MCOperand::createReg(AddrSegmentReg)); // AddrSegmentReg Inst.addOperand(MCOperand::createReg(AddrSegmentReg)); // AddrSegmentReg
- return true;
} }
InstructionListType createLoadImmediate(const MCPhysReg Dest, InstructionListType createLoadImmediate(const MCPhysReg Dest,
@@ -2338,7 +2336,7 @@ public:
return Insts; return Insts;
} }
- bool createIJmp32Frag(SmallVectorImpl<MCInst> &Insts,+ void createIJmp32Frag(SmallVectorImpl<MCInst> &Insts,
const MCOperand &BaseReg, const MCOperand &Scale, const MCOperand &BaseReg, const MCOperand &Scale,
const MCOperand &IndexReg, const MCOperand &Offset, const MCOperand &IndexReg, const MCOperand &Offset,
const MCOperand &TmpReg) const override { const MCOperand &TmpReg) const override {
@@ -2362,17 +2360,16 @@ public:
Insts.push_back(Load); Insts.push_back(Load);
Insts.push_back(IJmp); Insts.push_back(IJmp);
- return true;
} }
- bool createNoop(MCInst &Inst) const override {+ void createNoop(MCInst &Inst) const override {
Inst.setOpcode(X86::NOOP); Inst.setOpcode(X86::NOOP);
- return true;+ Inst.clear();
} }
- bool createReturn(MCInst &Inst) const override {+ void createReturn(MCInst &Inst) const override {
Inst.setOpcode(X86::RET64); Inst.setOpcode(X86::RET64);
- return true;+ Inst.clear();
} }
InstructionListType createInlineMemcpy(bool ReturnEnd) const override { InstructionListType createInlineMemcpy(bool ReturnEnd) const override {
@@ -2729,23 +2726,31 @@ public:
return FoundOne; return FoundOne;
} }
- bool createUncondBranch(MCInst &Inst, const MCSymbol *TBB,+ void createUncondBranch(MCInst &Inst, const MCSymbol *TBB,
MCContext *Ctx) const override { MCContext *Ctx) const override {
Inst.setOpcode(X86::JMP_1); Inst.setOpcode(X86::JMP_1);
+ Inst.clear();
Inst.addOperand(MCOperand::createExpr( Inst.addOperand(MCOperand::createExpr(
MCSymbolRefExpr::create(TBB, MCSymbolRefExpr::VK_None, *Ctx))); MCSymbolRefExpr::create(TBB, MCSymbolRefExpr::VK_None, *Ctx)));
- return true;
} }
- bool createCall(MCInst &Inst, const MCSymbol *Target,+ void createLongUncondBranch(MCInst &Inst, const MCSymbol *Target,
+ MCContext *Ctx) const override {
+ Inst.setOpcode(X86::JMP_4);
+ Inst.clear();
+ Inst.addOperand(MCOperand::createExpr(
+ MCSymbolRefExpr::create(Target, MCSymbolRefExpr::VK_None, *Ctx)));
+ }
+
+ void createCall(MCInst &Inst, const MCSymbol *Target,
MCContext *Ctx) override { MCContext *Ctx) override {
Inst.setOpcode(X86::CALL64pcrel32); Inst.setOpcode(X86::CALL64pcrel32);
+ Inst.clear();
Inst.addOperand(MCOperand::createExpr( Inst.addOperand(MCOperand::createExpr(
MCSymbolRefExpr::create(Target, MCSymbolRefExpr::VK_None, *Ctx))); MCSymbolRefExpr::create(Target, MCSymbolRefExpr::VK_None, *Ctx)));
- return true;
} }
- bool createTailCall(MCInst &Inst, const MCSymbol *Target,+ void createTailCall(MCInst &Inst, const MCSymbol *Target,
MCContext *Ctx) override { MCContext *Ctx) override {
return createDirectCall(Inst, Target, Ctx, /*IsTailCall*/ true); return createDirectCall(Inst, Target, Ctx, /*IsTailCall*/ true);
} }
@@ -2757,10 +2762,18 @@ public:
createDirectCall(Seq.back(), Target, Ctx, /*IsTailCall*/ true); createDirectCall(Seq.back(), Target, Ctx, /*IsTailCall*/ true);
} }
- bool createTrap(MCInst &Inst) const override {+ void createTrap(MCInst &Inst) const override {
Inst.clear(); Inst.clear();
Inst.setOpcode(X86::TRAP); Inst.setOpcode(X86::TRAP);
- return true;+ }
+
+ void createCondBranch(MCInst &Inst, const MCSymbol *Target, unsigned CC,
+ MCContext *Ctx) const override {
+ Inst.setOpcode(X86::JCC_1);
+ Inst.clear();
+ Inst.addOperand(MCOperand::createExpr(
+ MCSymbolRefExpr::create(Target, MCSymbolRefExpr::VK_None, *Ctx)));
+ Inst.addOperand(MCOperand::createImm(CC));
} }
bool reverseBranchCondition(MCInst &Inst, const MCSymbol *TBB, bool reverseBranchCondition(MCInst &Inst, const MCSymbol *TBB,
@@ -2862,7 +2875,7 @@ public:
Inst.setOpcode(X86::LFENCE); Inst.setOpcode(X86::LFENCE);
} }
- bool createDirectCall(MCInst &Inst, const MCSymbol *Target, MCContext *Ctx,+ void createDirectCall(MCInst &Inst, const MCSymbol *Target, MCContext *Ctx,
bool IsTailCall) override { bool IsTailCall) override {
Inst.clear(); Inst.clear();
Inst.setOpcode(IsTailCall ? X86::JMP_4 : X86::CALL64pcrel32); Inst.setOpcode(IsTailCall ? X86::JMP_4 : X86::CALL64pcrel32);
@@ -2870,7 +2883,6 @@ public:
MCSymbolRefExpr::create(Target, MCSymbolRefExpr::VK_None, *Ctx))); MCSymbolRefExpr::create(Target, MCSymbolRefExpr::VK_None, *Ctx)));
if (IsTailCall) if (IsTailCall)
setTailCall(Inst); setTailCall(Inst);
- return true;
} }
void createShortJmp(InstructionListType &Seq, const MCSymbol *Target, void createShortJmp(InstructionListType &Seq, const MCSymbol *Target,
@@ -3066,6 +3078,7 @@ public:
void createSwap(MCInst &Inst, MCPhysReg Source, MCPhysReg MemBaseReg, void createSwap(MCInst &Inst, MCPhysReg Source, MCPhysReg MemBaseReg,
int64_t Disp) const { int64_t Disp) const {
Inst.setOpcode(X86::XCHG64rm); Inst.setOpcode(X86::XCHG64rm);
+ Inst.clear();
Inst.addOperand(MCOperand::createReg(Source)); Inst.addOperand(MCOperand::createReg(Source));
Inst.addOperand(MCOperand::createReg(Source)); Inst.addOperand(MCOperand::createReg(Source));
Inst.addOperand(MCOperand::createReg(MemBaseReg)); // BaseReg Inst.addOperand(MCOperand::createReg(MemBaseReg)); // BaseReg
@@ -3078,6 +3091,7 @@ public:
void createIndirectBranch(MCInst &Inst, MCPhysReg MemBaseReg, void createIndirectBranch(MCInst &Inst, MCPhysReg MemBaseReg,
int64_t Disp) const { int64_t Disp) const {
Inst.setOpcode(X86::JMP64m); Inst.setOpcode(X86::JMP64m);
+ Inst.clear();
Inst.addOperand(MCOperand::createReg(MemBaseReg)); // BaseReg Inst.addOperand(MCOperand::createReg(MemBaseReg)); // BaseReg
Inst.addOperand(MCOperand::createImm(1)); // ScaleAmt Inst.addOperand(MCOperand::createImm(1)); // ScaleAmt
Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // IndexReg Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // IndexReg
@@ -3540,9 +3554,10 @@ public:
} }
private: private:
- bool createMove(MCInst &Inst, const MCSymbol *Src, unsigned Reg,+ void createMove(MCInst &Inst, const MCSymbol *Src, unsigned Reg,
MCContext *Ctx) const { MCContext *Ctx) const {
Inst.setOpcode(X86::MOV64rm); Inst.setOpcode(X86::MOV64rm);
+ Inst.clear();
Inst.addOperand(MCOperand::createReg(Reg)); Inst.addOperand(MCOperand::createReg(Reg));
Inst.addOperand(MCOperand::createReg(X86::RIP)); // BaseReg Inst.addOperand(MCOperand::createReg(X86::RIP)); // BaseReg
Inst.addOperand(MCOperand::createImm(1)); // ScaleAmt Inst.addOperand(MCOperand::createImm(1)); // ScaleAmt
@@ -3551,13 +3566,12 @@ private:
MCSymbolRefExpr::create(Src, MCSymbolRefExpr::VK_None, MCSymbolRefExpr::create(Src, MCSymbolRefExpr::VK_None,
*Ctx))); // Displacement *Ctx))); // Displacement
Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // AddrSegmentReg Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // AddrSegmentReg
-
- return true;
} }
- bool createLea(MCInst &Inst, const MCSymbol *Src, unsigned Reg,+ void createLea(MCInst &Inst, const MCSymbol *Src, unsigned Reg,
MCContext *Ctx) const { MCContext *Ctx) const {
Inst.setOpcode(X86::LEA64r); Inst.setOpcode(X86::LEA64r);
+ Inst.clear();
Inst.addOperand(MCOperand::createReg(Reg)); Inst.addOperand(MCOperand::createReg(Reg));
Inst.addOperand(MCOperand::createReg(X86::RIP)); // BaseReg Inst.addOperand(MCOperand::createReg(X86::RIP)); // BaseReg
Inst.addOperand(MCOperand::createImm(1)); // ScaleAmt Inst.addOperand(MCOperand::createImm(1)); // ScaleAmt
@@ -3566,7 +3580,6 @@ private:
MCSymbolRefExpr::create(Src, MCSymbolRefExpr::VK_None, MCSymbolRefExpr::create(Src, MCSymbolRefExpr::VK_None,
*Ctx))); // Displacement *Ctx))); // Displacement
Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // AddrSegmentReg Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // AddrSegmentReg
- return true;
} }
}; };
bolt/test/AArch64/exclusive-instrument.s
@@ -6,32 +6,108 @@
// RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown \ // RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown \
// RUN: %s -o %t.o // RUN: %s -o %t.o
// RUN: %clang %cflags -fPIC -pie %t.o -o %t.exe -nostdlib -Wl,-q -Wl,-fini=dummy // RUN: %clang %cflags -fPIC -pie %t.o -o %t.exe -nostdlib -Wl,-q -Wl,-fini=dummy
-// RUN: llvm-bolt %t.exe -o %t.bolt -instrument -v=1 | FileCheck %s+// RUN: llvm-bolt %t.exe -o %t.bolt -instrument -v=2 | FileCheck %s
-// CHECK: Function foo has exclusive instructions, skip instrumentation+// CHECK: BOLT-INSTRUMENTER: skip BB {{.*}} due to exclusive instruction in function foo
+// CHECK: BOLT-INSTRUMENTER: skip BB {{.*}} due to exclusive instruction in function foo
+// CHECK: BOLT-INSTRUMENTER: skip BB {{.*}} due to exclusive instruction in function foo
+// CHECK: BOLT-INSTRUMENTER: skip BB {{.*}} due to exclusive instruction in function case1
+// CHECK: BOLT-INSTRUMENTER: skip BB {{.*}} due to exclusive instruction in function case2
+// CHECK: BOLT-INSTRUMENTER: skip BB {{.*}} due to exclusive instruction in function case2
+// CHECK: BOLT-INSTRUMENTER: function case3 has exclusive store without corresponding load. Ignoring the function.
+// CHECK: BOLT-INSTRUMENTER: skip BB {{.*}} due to exclusive instruction in function case4
+// CHECK: BOLT-INSTRUMENTER: function case4 has two exclusive loads. Ignoring the function.
+// CHECK: BOLT-INSTRUMENTER: skip BB {{.*}} due to exclusive instruction in function case5
+// CHECK: BOLT-INSTRUMENTER: function case5 has exclusive load in trailing BB. Ignoring the function.
.global foo .global foo
.type foo, %function .type foo, %function
foo: foo:
+ # exclusive load and store in two bbs
ldaxr w9, [x10] ldaxr w9, [x10]
cbnz w9, .Lret cbnz w9, .Lret
stlxr w12, w11, [x9] stlxr w12, w11, [x9]
cbz w12, foo cbz w12, foo
- clrex
.Lret: .Lret:
+ clrex
ret ret
.size foo, .-foo .size foo, .-foo
.global _start .global _start
.type _start, %function .type _start, %function
_start: _start:
- cmp x0, #0+ mov x0, #0
- b.eq .Lexit+ mov x1, #1
- bl foo+ mov x2, #2
-.Lexit:+ mov x3, #3
+
+ bl case1
+ bl case2
+ bl case3
+ bl case4
+ bl case5
+
ret ret
.size _start, .-_start .size _start, .-_start
+# Case 1: exclusive load and store in one basic block
+.global case1
+.type case1, %function
+case1:
+ str x0, [x2]
+ ldxr w0, [x2]
+ add w0, w0, #1
+ stxr w1, w0, [x2]
+ ret
+.size case1, .-case1
+
+# Case 2: exclusive load and store in different blocks
+.global case2
+.type case2, %function
+case2:
+ b case2_load
+
+case2_load:
+ ldxr x0, [x2]
+ b case2_store
+
+case2_store:
+ add x0, x0, #1
+ stxr w1, x0, [x2]
+ ret
+.size case2, .-case2
+
+# Case 3: store without preceding load
+.global case3
+.type case3, %function
+case3:
+ stxr w1, x3, [x2]
+ ret
+.size case3, .-case3
+
+# Case 4: two exclusive load instructions in neighboring blocks
+.global case4
+.type case4, %function
+case4:
+ b case4_load
+
+case4_load:
+ ldxr x0, [x2]
+ b case4_load_next
+
+case4_load_next:
+ ldxr x1, [x2]
+ ret
+.size case4, .-case4
+
+# Case 5: Exclusive load without successor
+.global case5
+.type case5, %function
+case5:
+ ldxr x0, [x2]
+ ret
+.size case5, .-case5
+
.global dummy .global dummy
.type dummy, %function .type dummy, %function
dummy: dummy:
bolt/test/X86/Inputs/dwarf5-debug-names-ftu-ltu-mix-helper.s
@@ -0,0 +1,314 @@
+# struct AMono {
+# int x;
+# };
+#
+# AMono globalMono;
+# # clang++ -g2 -gdwarf-5 -gpubnames -S -fdebug-types-section -o
+
+ .text
+ .file "helper.cpp"
+ .file 0 "/home" "helper.cpp" md5 0x3c0ac73d7b074961c6e8202230a76228
+ .section .debug_info,"G",@progbits,6412503741467814911,comdat
+.Ltu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 2 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .quad 6412503741467814911 # Type Signature
+ .long 35 # Type DIE Offset
+ .byte 1 # Abbrev [1] 0x18:0x20 DW_TAG_type_unit
+ .short 33 # DW_AT_language
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .byte 2 # Abbrev [2] 0x23:0x10 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 6 # DW_AT_name
+ .byte 4 # DW_AT_byte_size
+ .byte 0 # DW_AT_decl_file
+ .byte 1 # DW_AT_decl_line
+ .byte 3 # Abbrev [3] 0x29:0x9 DW_TAG_member
+ .byte 4 # DW_AT_name
+ .long 51 # DW_AT_type
+ .byte 0 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .byte 0 # DW_AT_data_member_location
+ .byte 0 # End Of Children Mark
+ .byte 4 # Abbrev [4] 0x33:0x4 DW_TAG_base_type
+ .byte 5 # DW_AT_name
+ .byte 5 # DW_AT_encoding
+ .byte 4 # DW_AT_byte_size
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end0:
+ .type globalMono,@object # @globalMono
+ .bss
+ .globl globalMono
+ .p2align 2, 0x0
+globalMono:
+ .zero 4
+ .size globalMono, 4
+
+ .section .debug_abbrev,"",@progbits
+ .byte 1 # Abbreviation Code
+ .byte 65 # DW_TAG_type_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 114 # DW_AT_str_offsets_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 2 # Abbreviation Code
+ .byte 19 # DW_TAG_structure_type
+ .byte 1 # DW_CHILDREN_yes
+ .byte 54 # DW_AT_calling_convention
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 3 # Abbreviation Code
+ .byte 13 # DW_TAG_member
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 56 # DW_AT_data_member_location
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 4 # Abbreviation Code
+ .byte 36 # DW_TAG_base_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 62 # DW_AT_encoding
+ .byte 11 # DW_FORM_data1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 5 # Abbreviation Code
+ .byte 17 # DW_TAG_compile_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 37 # DW_AT_producer
+ .byte 37 # DW_FORM_strx1
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 114 # DW_AT_str_offsets_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 27 # DW_AT_comp_dir
+ .byte 37 # DW_FORM_strx1
+ .byte 115 # DW_AT_addr_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 6 # Abbreviation Code
+ .byte 52 # DW_TAG_variable
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 63 # DW_AT_external
+ .byte 25 # DW_FORM_flag_present
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 2 # DW_AT_location
+ .byte 24 # DW_FORM_exprloc
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 7 # Abbreviation Code
+ .byte 19 # DW_TAG_structure_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 60 # DW_AT_declaration
+ .byte 25 # DW_FORM_flag_present
+ .byte 105 # DW_AT_signature
+ .byte 32 # DW_FORM_ref_sig8
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"",@progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end1-.Ldebug_info_start1 # Length of Unit
+.Ldebug_info_start1:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .byte 5 # Abbrev [5] 0xc:0x27 DW_TAG_compile_unit
+ .byte 0 # DW_AT_producer
+ .short 33 # DW_AT_language
+ .byte 1 # DW_AT_name
+ .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .byte 2 # DW_AT_comp_dir
+ .long .Laddr_table_base0 # DW_AT_addr_base
+ .byte 6 # Abbrev [6] 0x1e:0xb DW_TAG_variable
+ .byte 3 # DW_AT_name
+ .long 41 # DW_AT_type
+ # DW_AT_external
+ .byte 0 # DW_AT_decl_file
+ .byte 5 # DW_AT_decl_line
+ .byte 2 # DW_AT_location
+ .byte 161
+ .byte 0
+ .byte 7 # Abbrev [7] 0x29:0x9 DW_TAG_structure_type
+ # DW_AT_declaration
+ .quad 6412503741467814911 # DW_AT_signature
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end1:
+ .section .debug_str_offsets,"",@progbits
+ .long 32 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS",@progbits,1
+.Linfo_string0:
+ .asciz "clang version 19.0.0git (git@github.com:llvm/llvm-project.git ced1fac8a32e35b63733bda27c7f5b9a2b635403)" # string offset=0
+.Linfo_string1:
+ .asciz "helper.cpp" # string offset=104
+.Linfo_string2:
+ .asciz "/home" # string offset=115
+.Linfo_string3:
+ .asciz "globalMono" # string offset=153
+.Linfo_string4:
+ .asciz "AMono" # string offset=164
+.Linfo_string5:
+ .asciz "x" # string offset=170
+.Linfo_string6:
+ .asciz "int" # string offset=172
+ .section .debug_str_offsets,"",@progbits
+ .long .Linfo_string0
+ .long .Linfo_string1
+ .long .Linfo_string2
+ .long .Linfo_string3
+ .long .Linfo_string5
+ .long .Linfo_string6
+ .long .Linfo_string4
+ .section .debug_addr,"",@progbits
+ .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution
+.Ldebug_addr_start0:
+ .short 5 # DWARF version number
+ .byte 8 # Address size
+ .byte 0 # Segment selector size
+.Laddr_table_base0:
+ .quad globalMono
+.Ldebug_addr_end0:
+ .section .debug_names,"",@progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 1 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 3 # Header: bucket count
+ .long 3 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long .Ltu_begin0 # Type unit 0
+ .long 0 # Bucket 0
+ .long 0 # Bucket 1
+ .long 1 # Bucket 2
+ .long 193495088 # Hash in Bucket 2
+ .long 253228319 # Hash in Bucket 2
+ .long -857151761 # Hash in Bucket 2
+ .long .Linfo_string6 # String in Bucket 2: int
+ .long .Linfo_string4 # String in Bucket 2: AMono
+ .long .Linfo_string3 # String in Bucket 2: globalMono
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 2
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 2
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 2
+.Lnames_abbrev_start0:
+ .byte 1 # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 2 # DW_IDX_type_unit
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 2 # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 2 # DW_IDX_type_unit
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 3 # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 4 # Abbrev code
+ .byte 52 # DW_TAG_variable
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames1:
+.L1:
+ .byte 1 # Abbreviation code
+ .byte 0 # DW_IDX_type_unit
+ .long 51 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: int
+.Lnames0:
+.L2:
+ .byte 2 # Abbreviation code
+ .byte 0 # DW_IDX_type_unit
+ .long 35 # DW_IDX_die_offset
+.L3: # DW_IDX_parent
+ .byte 3 # Abbreviation code
+ .long 41 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: AMono
+.Lnames2:
+.L0:
+ .byte 4 # Abbreviation code
+ .long 30 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: globalMono
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 19.0.0git (git@github.com:llvm/llvm-project.git ced1fac8a32e35b63733bda27c7f5b9a2b635403)"
+ .section ".note.GNU-stack","",@progbits
+ .addrsig
+ .section .debug_line,"",@progbits
+.Lline_table_start0:
bolt/test/X86/Inputs/dwarf5-debug-names-ftu-ltu-mix-helper1.s
@@ -0,0 +1,315 @@
+# struct BMono {
+# int x;
+# };
+#
+# BMono globalMono1;
+# clang++ -g2 -gdwarf-5 -gpubnames -S -fdebug-types-section -o
+
+
+ .text
+ .file "helper1.cpp"
+ .file 0 "/home" "helper1.cpp" md5 0x1fdaf911330b73495aed962bc02cfb3a
+ .section .debug_info,"G",@progbits,5884764266900841573,comdat
+.Ltu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 2 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .quad 5884764266900841573 # Type Signature
+ .long 35 # Type DIE Offset
+ .byte 1 # Abbrev [1] 0x18:0x20 DW_TAG_type_unit
+ .short 33 # DW_AT_language
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .byte 2 # Abbrev [2] 0x23:0x10 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 6 # DW_AT_name
+ .byte 4 # DW_AT_byte_size
+ .byte 0 # DW_AT_decl_file
+ .byte 1 # DW_AT_decl_line
+ .byte 3 # Abbrev [3] 0x29:0x9 DW_TAG_member
+ .byte 4 # DW_AT_name
+ .long 51 # DW_AT_type
+ .byte 0 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .byte 0 # DW_AT_data_member_location
+ .byte 0 # End Of Children Mark
+ .byte 4 # Abbrev [4] 0x33:0x4 DW_TAG_base_type
+ .byte 5 # DW_AT_name
+ .byte 5 # DW_AT_encoding
+ .byte 4 # DW_AT_byte_size
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end0:
+ .type globalMono1,@object # @globalMono1
+ .bss
+ .globl globalMono1
+ .p2align 2, 0x0
+globalMono1:
+ .zero 4
+ .size globalMono1, 4
+
+ .section .debug_abbrev,"",@progbits
+ .byte 1 # Abbreviation Code
+ .byte 65 # DW_TAG_type_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 114 # DW_AT_str_offsets_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 2 # Abbreviation Code
+ .byte 19 # DW_TAG_structure_type
+ .byte 1 # DW_CHILDREN_yes
+ .byte 54 # DW_AT_calling_convention
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 3 # Abbreviation Code
+ .byte 13 # DW_TAG_member
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 56 # DW_AT_data_member_location
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 4 # Abbreviation Code
+ .byte 36 # DW_TAG_base_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 62 # DW_AT_encoding
+ .byte 11 # DW_FORM_data1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 5 # Abbreviation Code
+ .byte 17 # DW_TAG_compile_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 37 # DW_AT_producer
+ .byte 37 # DW_FORM_strx1
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 114 # DW_AT_str_offsets_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 27 # DW_AT_comp_dir
+ .byte 37 # DW_FORM_strx1
+ .byte 115 # DW_AT_addr_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 6 # Abbreviation Code
+ .byte 52 # DW_TAG_variable
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 63 # DW_AT_external
+ .byte 25 # DW_FORM_flag_present
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 2 # DW_AT_location
+ .byte 24 # DW_FORM_exprloc
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 7 # Abbreviation Code
+ .byte 19 # DW_TAG_structure_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 60 # DW_AT_declaration
+ .byte 25 # DW_FORM_flag_present
+ .byte 105 # DW_AT_signature
+ .byte 32 # DW_FORM_ref_sig8
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"",@progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end1-.Ldebug_info_start1 # Length of Unit
+.Ldebug_info_start1:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .byte 5 # Abbrev [5] 0xc:0x27 DW_TAG_compile_unit
+ .byte 0 # DW_AT_producer
+ .short 33 # DW_AT_language
+ .byte 1 # DW_AT_name
+ .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .byte 2 # DW_AT_comp_dir
+ .long .Laddr_table_base0 # DW_AT_addr_base
+ .byte 6 # Abbrev [6] 0x1e:0xb DW_TAG_variable
+ .byte 3 # DW_AT_name
+ .long 41 # DW_AT_type
+ # DW_AT_external
+ .byte 0 # DW_AT_decl_file
+ .byte 5 # DW_AT_decl_line
+ .byte 2 # DW_AT_location
+ .byte 161
+ .byte 0
+ .byte 7 # Abbrev [7] 0x29:0x9 DW_TAG_structure_type
+ # DW_AT_declaration
+ .quad 5884764266900841573 # DW_AT_signature
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end1:
+ .section .debug_str_offsets,"",@progbits
+ .long 32 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS",@progbits,1
+.Linfo_string0:
+ .asciz "clang version 19.0.0git (git@github.com:llvm/llvm-project.git ced1fac8a32e35b63733bda27c7f5b9a2b635403)" # string offset=0
+.Linfo_string1:
+ .asciz "helper1.cpp" # string offset=104
+.Linfo_string2:
+ .asciz "/home" # string offset=116
+.Linfo_string3:
+ .asciz "globalMono1" # string offset=154
+.Linfo_string4:
+ .asciz "BMono" # string offset=166
+.Linfo_string5:
+ .asciz "x" # string offset=172
+.Linfo_string6:
+ .asciz "int" # string offset=174
+ .section .debug_str_offsets,"",@progbits
+ .long .Linfo_string0
+ .long .Linfo_string1
+ .long .Linfo_string2
+ .long .Linfo_string3
+ .long .Linfo_string5
+ .long .Linfo_string6
+ .long .Linfo_string4
+ .section .debug_addr,"",@progbits
+ .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution
+.Ldebug_addr_start0:
+ .short 5 # DWARF version number
+ .byte 8 # Address size
+ .byte 0 # Segment selector size
+.Laddr_table_base0:
+ .quad globalMono1
+.Ldebug_addr_end0:
+ .section .debug_names,"",@progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 1 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 3 # Header: bucket count
+ .long 3 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long .Ltu_begin0 # Type unit 0
+ .long 0 # Bucket 0
+ .long 0 # Bucket 1
+ .long 1 # Bucket 2
+ .long 193495088 # Hash in Bucket 2
+ .long 254414240 # Hash in Bucket 2
+ .long 1778763008 # Hash in Bucket 2
+ .long .Linfo_string6 # String in Bucket 2: int
+ .long .Linfo_string4 # String in Bucket 2: BMono
+ .long .Linfo_string3 # String in Bucket 2: globalMono1
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 2
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 2
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 2
+.Lnames_abbrev_start0:
+ .byte 1 # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 2 # DW_IDX_type_unit
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 2 # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 2 # DW_IDX_type_unit
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 3 # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 4 # Abbrev code
+ .byte 52 # DW_TAG_variable
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames1:
+.L1:
+ .byte 1 # Abbreviation code
+ .byte 0 # DW_IDX_type_unit
+ .long 51 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: int
+.Lnames0:
+.L2:
+ .byte 2 # Abbreviation code
+ .byte 0 # DW_IDX_type_unit
+ .long 35 # DW_IDX_die_offset
+.L3: # DW_IDX_parent
+ .byte 3 # Abbreviation code
+ .long 41 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: BMono
+.Lnames2:
+.L0:
+ .byte 4 # Abbreviation code
+ .long 30 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: globalMono1
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 19.0.0git (git@github.com:llvm/llvm-project.git ced1fac8a32e35b63733bda27c7f5b9a2b635403)"
+ .section ".note.GNU-stack","",@progbits
+ .addrsig
+ .section .debug_line,"",@progbits
+.Lline_table_start0:
bolt/test/X86/Inputs/dwarf5-debug-names-helper.s
@@ -0,0 +1,487 @@
+# clang++ -g2 -gdwarf-5 -gpubnames -fdebug-types-section -S
+# header.h
+# struct Foo2a {
+# char *c1;
+# char *c2;
+# char *c3;
+# };
+# helper.cpp
+# #include "header.h"
+# int fooint;
+# struct Foo2Int {
+# int *c1;
+# int *c2;
+# };
+#
+# int foo() {
+# Foo2Int fint;
+# Foo2a f;
+# return 0;
+# }
+
+ .text
+ .file "helper.cpp"
+ .file 0 "/typeDedup" "helper.cpp" md5 0xc33186b2db66a78883b1546aace9855d
+ .globl _Z3foov # -- Begin function _Z3foov
+ .p2align 4, 0x90
+ .type _Z3foov,@function
+_Z3foov: # @_Z3foov
+.Lfunc_begin0:
+ .loc 0 8 0 # helper.cpp:8:0
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+.Ltmp0:
+ .loc 0 11 3 prologue_end # helper.cpp:11:3
+ xorl %eax, %eax
+ .loc 0 11 3 epilogue_begin is_stmt 0 # helper.cpp:11:3
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size _Z3foov, .Lfunc_end0-_Z3foov
+ .cfi_endproc
+ # -- End function
+ .type fooint,@object # @fooint
+ .bss
+ .globl fooint
+ .p2align 2, 0x0
+fooint:
+ .long 0 # 0x0
+ .size fooint, 4
+
+ .file 1 "." "header.h" md5 0xfea7bb1f22c47f129e15695f7137a1e7
+ .section .debug_abbrev,"",@progbits
+ .byte 1 # Abbreviation Code
+ .byte 17 # DW_TAG_compile_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 37 # DW_AT_producer
+ .byte 37 # DW_FORM_strx1
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 114 # DW_AT_str_offsets_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 27 # DW_AT_comp_dir
+ .byte 37 # DW_FORM_strx1
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 115 # DW_AT_addr_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 2 # Abbreviation Code
+ .byte 52 # DW_TAG_variable
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 63 # DW_AT_external
+ .byte 25 # DW_FORM_flag_present
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 2 # DW_AT_location
+ .byte 24 # DW_FORM_exprloc
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 3 # Abbreviation Code
+ .byte 36 # DW_TAG_base_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 62 # DW_AT_encoding
+ .byte 11 # DW_FORM_data1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 4 # Abbreviation Code
+ .byte 46 # DW_TAG_subprogram
+ .byte 1 # DW_CHILDREN_yes
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 64 # DW_AT_frame_base
+ .byte 24 # DW_FORM_exprloc
+ .byte 110 # DW_AT_linkage_name
+ .byte 37 # DW_FORM_strx1
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 63 # DW_AT_external
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 5 # Abbreviation Code
+ .byte 52 # DW_TAG_variable
+ .byte 0 # DW_CHILDREN_no
+ .byte 2 # DW_AT_location
+ .byte 24 # DW_FORM_exprloc
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 6 # Abbreviation Code
+ .byte 19 # DW_TAG_structure_type
+ .byte 1 # DW_CHILDREN_yes
+ .byte 54 # DW_AT_calling_convention
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 7 # Abbreviation Code
+ .byte 13 # DW_TAG_member
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 56 # DW_AT_data_member_location
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 8 # Abbreviation Code
+ .byte 15 # DW_TAG_pointer_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"",@progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .byte 1 # Abbrev [1] 0xc:0x97 DW_TAG_compile_unit
+ .byte 0 # DW_AT_producer
+ .short 33 # DW_AT_language
+ .byte 1 # DW_AT_name
+ .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .byte 2 # DW_AT_comp_dir
+ .byte 1 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .long .Laddr_table_base0 # DW_AT_addr_base
+ .byte 2 # Abbrev [2] 0x23:0xb DW_TAG_variable
+ .byte 3 # DW_AT_name
+ .long 46 # DW_AT_type
+ # DW_AT_external
+ .byte 0 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .byte 2 # DW_AT_location
+ .byte 161
+ .byte 0
+ .byte 3 # Abbrev [3] 0x2e:0x4 DW_TAG_base_type
+ .byte 4 # DW_AT_name
+ .byte 5 # DW_AT_encoding
+ .byte 4 # DW_AT_byte_size
+ .byte 4 # Abbrev [4] 0x32:0x27 DW_TAG_subprogram
+ .byte 1 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .byte 1 # DW_AT_frame_base
+ .byte 86
+ .byte 5 # DW_AT_linkage_name
+ .byte 6 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 8 # DW_AT_decl_line
+ .long 46 # DW_AT_type
+ # DW_AT_external
+ .byte 5 # Abbrev [5] 0x42:0xb DW_TAG_variable
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 112
+ .byte 7 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 9 # DW_AT_decl_line
+ .long 89 # DW_AT_type
+ .byte 5 # Abbrev [5] 0x4d:0xb DW_TAG_variable
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 88
+ .byte 11 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 10 # DW_AT_decl_line
+ .long 119 # DW_AT_type
+ .byte 0 # End Of Children Mark
+ .byte 6 # Abbrev [6] 0x59:0x19 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 10 # DW_AT_name
+ .byte 16 # DW_AT_byte_size
+ .byte 0 # DW_AT_decl_file
+ .byte 3 # DW_AT_decl_line
+ .byte 7 # Abbrev [7] 0x5f:0x9 DW_TAG_member
+ .byte 8 # DW_AT_name
+ .long 114 # DW_AT_type
+ .byte 0 # DW_AT_decl_file
+ .byte 4 # DW_AT_decl_line
+ .byte 0 # DW_AT_data_member_location
+ .byte 7 # Abbrev [7] 0x68:0x9 DW_TAG_member
+ .byte 9 # DW_AT_name
+ .long 114 # DW_AT_type
+ .byte 0 # DW_AT_decl_file
+ .byte 5 # DW_AT_decl_line
+ .byte 8 # DW_AT_data_member_location
+ .byte 0 # End Of Children Mark
+ .byte 8 # Abbrev [8] 0x72:0x5 DW_TAG_pointer_type
+ .long 46 # DW_AT_type
+ .byte 6 # Abbrev [6] 0x77:0x22 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 14 # DW_AT_name
+ .byte 24 # DW_AT_byte_size
+ .byte 1 # DW_AT_decl_file
+ .byte 1 # DW_AT_decl_line
+ .byte 7 # Abbrev [7] 0x7d:0x9 DW_TAG_member
+ .byte 8 # DW_AT_name
+ .long 153 # DW_AT_type
+ .byte 1 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .byte 0 # DW_AT_data_member_location
+ .byte 7 # Abbrev [7] 0x86:0x9 DW_TAG_member
+ .byte 9 # DW_AT_name
+ .long 153 # DW_AT_type
+ .byte 1 # DW_AT_decl_file
+ .byte 3 # DW_AT_decl_line
+ .byte 8 # DW_AT_data_member_location
+ .byte 7 # Abbrev [7] 0x8f:0x9 DW_TAG_member
+ .byte 13 # DW_AT_name
+ .long 153 # DW_AT_type
+ .byte 1 # DW_AT_decl_file
+ .byte 4 # DW_AT_decl_line
+ .byte 16 # DW_AT_data_member_location
+ .byte 0 # End Of Children Mark
+ .byte 8 # Abbrev [8] 0x99:0x5 DW_TAG_pointer_type
+ .long 158 # DW_AT_type
+ .byte 3 # Abbrev [3] 0x9e:0x4 DW_TAG_base_type
+ .byte 12 # DW_AT_name
+ .byte 6 # DW_AT_encoding
+ .byte 1 # DW_AT_byte_size
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"",@progbits
+ .long 64 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS",@progbits,1
+.Linfo_string0:
+ .asciz "clang version 18.0.0git" # string offset=0
+.Linfo_string1:
+ .asciz "helper.cpp" # string offset=24
+.Linfo_string2:
+ .asciz "/home/ayermolo/local/tasks/T138552329/typeDedup" # string offset=35
+.Linfo_string3:
+ .asciz "fooint" # string offset=83
+.Linfo_string4:
+ .asciz "int" # string offset=90
+.Linfo_string5:
+ .asciz "foo" # string offset=94
+.Linfo_string6:
+ .asciz "_Z3foov" # string offset=98
+.Linfo_string7:
+ .asciz "fint" # string offset=106
+.Linfo_string8:
+ .asciz "Foo2Int" # string offset=111
+.Linfo_string9:
+ .asciz "c1" # string offset=119
+.Linfo_string10:
+ .asciz "c2" # string offset=122
+.Linfo_string11:
+ .asciz "f" # string offset=125
+.Linfo_string12:
+ .asciz "Foo2a" # string offset=127
+.Linfo_string13:
+ .asciz "char" # string offset=133
+.Linfo_string14:
+ .asciz "c3" # string offset=138
+ .section .debug_str_offsets,"",@progbits
+ .long .Linfo_string0
+ .long .Linfo_string1
+ .long .Linfo_string2
+ .long .Linfo_string3
+ .long .Linfo_string4
+ .long .Linfo_string6
+ .long .Linfo_string5
+ .long .Linfo_string7
+ .long .Linfo_string9
+ .long .Linfo_string10
+ .long .Linfo_string8
+ .long .Linfo_string11
+ .long .Linfo_string13
+ .long .Linfo_string14
+ .long .Linfo_string12
+ .section .debug_addr,"",@progbits
+ .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution
+.Ldebug_addr_start0:
+ .short 5 # DWARF version number
+ .byte 8 # Address size
+ .byte 0 # Segment selector size
+.Laddr_table_base0:
+ .quad fooint
+ .quad .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"",@progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 7 # Header: bucket count
+ .long 7 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long 1 # Bucket 0
+ .long 0 # Bucket 1
+ .long 2 # Bucket 2
+ .long 3 # Bucket 3
+ .long 0 # Bucket 4
+ .long 5 # Bucket 5
+ .long 7 # Bucket 6
+ .long -1257882357 # Hash in Bucket 0
+ .long -1168750522 # Hash in Bucket 2
+ .long 193495088 # Hash in Bucket 3
+ .long 259227804 # Hash in Bucket 3
+ .long 193491849 # Hash in Bucket 5
+ .long 2090147939 # Hash in Bucket 5
+ .long -35356620 # Hash in Bucket 6
+ .long .Linfo_string6 # String in Bucket 0: _Z3foov
+ .long .Linfo_string8 # String in Bucket 2: Foo2Int
+ .long .Linfo_string4 # String in Bucket 3: int
+ .long .Linfo_string12 # String in Bucket 3: Foo2a
+ .long .Linfo_string5 # String in Bucket 5: foo
+ .long .Linfo_string13 # String in Bucket 5: char
+ .long .Linfo_string3 # String in Bucket 6: fooint
+ .long .Lnames3-.Lnames_entries0 # Offset in Bucket 0
+ .long .Lnames4-.Lnames_entries0 # Offset in Bucket 2
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 3
+ .long .Lnames5-.Lnames_entries0 # Offset in Bucket 3
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 5
+ .long .Lnames6-.Lnames_entries0 # Offset in Bucket 5
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 6
+.Lnames_abbrev_start0:
+ .ascii "\230." # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\230\023" # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\230$" # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\2304" # Abbrev code
+ .byte 52 # DW_TAG_variable
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames3:
+.L0:
+ .ascii "\230." # Abbreviation code
+ .long 50 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: _Z3foov
+.Lnames4:
+.L5:
+ .ascii "\230\023" # Abbreviation code
+ .long 89 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: Foo2Int
+.Lnames0:
+.L2:
+ .ascii "\230$" # Abbreviation code
+ .long 46 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: int
+.Lnames5:
+.L3:
+ .ascii "\230\023" # Abbreviation code
+ .long 119 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: Foo2a
+.Lnames2:
+ .ascii "\230." # Abbreviation code
+ .long 50 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: foo
+.Lnames6:
+.L1:
+ .ascii "\230$" # Abbreviation code
+ .long 158 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: char
+.Lnames1:
+.L4:
+ .ascii "\2304" # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: fooint
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 18.0.0git"
+ .section ".note.GNU-stack","",@progbits
+ .addrsig
+ .section .debug_line,"",@progbits
+.Lline_table_start0:
bolt/test/X86/Inputs/dwarf5-debug-names-main.s
@@ -0,0 +1,712 @@
+# clang++ -g2 -gdwarf-5 -gpubnames -fdebug-types-section
+# header.h
+# struct Foo2a {
+# char *c1;
+# char *c2;
+# char *c3;
+# };
+# main.cpp
+# #include "header.h"
+# extern int fooint;
+# namespace {
+# struct t1 {
+# int i;
+# };
+# }
+# template <int *> struct t2 {
+# t1 v1;
+# };
+# struct t3 {
+# t2<&fooint> v1;
+# };
+# t3 v1;
+#
+# struct Foo {
+# char *c1;
+# char *c2;
+# char *c3;
+# };
+# struct Foo2 {
+# char *c1;
+# char *c2;
+# };
+# int main(int argc, char *argv[]) {
+# Foo f;
+# Foo2 f2;
+# Foo2a f3;
+# return 0;
+# }
+ .text
+ .file "main.cpp"
+ .file 0 "/typeDedup" "main.cpp" md5 0x04e636082b2b8a95a6ca39dde52372ae
+ .globl main # -- Begin function main
+ .p2align 4, 0x90
+ .type main,@function
+main: # @main
+.Lfunc_begin0:
+ .loc 0 25 0 # main.cpp:25:0
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+ movl $0, -4(%rbp)
+ movl %edi, -8(%rbp)
+ movq %rsi, -16(%rbp)
+.Ltmp0:
+ .loc 0 29 2 prologue_end # main.cpp:29:2
+ xorl %eax, %eax
+ .loc 0 29 2 epilogue_begin is_stmt 0 # main.cpp:29:2
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size main, .Lfunc_end0-main
+ .cfi_endproc
+ # -- End function
+ .type v1,@object # @v1
+ .bss
+ .globl v1
+ .p2align 2, 0x0
+v1:
+ .zero 4
+ .size v1, 4
+
+ .file 1 "." "header.h" md5 0xfea7bb1f22c47f129e15695f7137a1e7
+ .section .debug_abbrev,"",@progbits
+ .byte 1 # Abbreviation Code
+ .byte 17 # DW_TAG_compile_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 37 # DW_AT_producer
+ .byte 37 # DW_FORM_strx1
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 114 # DW_AT_str_offsets_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 27 # DW_AT_comp_dir
+ .byte 37 # DW_FORM_strx1
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 115 # DW_AT_addr_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 2 # Abbreviation Code
+ .byte 52 # DW_TAG_variable
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 63 # DW_AT_external
+ .byte 25 # DW_FORM_flag_present
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 2 # DW_AT_location
+ .byte 24 # DW_FORM_exprloc
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 3 # Abbreviation Code
+ .byte 19 # DW_TAG_structure_type
+ .byte 1 # DW_CHILDREN_yes
+ .byte 54 # DW_AT_calling_convention
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 4 # Abbreviation Code
+ .byte 13 # DW_TAG_member
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 56 # DW_AT_data_member_location
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 5 # Abbreviation Code
+ .byte 48 # DW_TAG_template_value_parameter
+ .byte 0 # DW_CHILDREN_no
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 2 # DW_AT_location
+ .byte 24 # DW_FORM_exprloc
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 6 # Abbreviation Code
+ .byte 15 # DW_TAG_pointer_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 7 # Abbreviation Code
+ .byte 36 # DW_TAG_base_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 62 # DW_AT_encoding
+ .byte 11 # DW_FORM_data1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 8 # Abbreviation Code
+ .byte 57 # DW_TAG_namespace
+ .byte 1 # DW_CHILDREN_yes
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 9 # Abbreviation Code
+ .byte 46 # DW_TAG_subprogram
+ .byte 1 # DW_CHILDREN_yes
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 64 # DW_AT_frame_base
+ .byte 24 # DW_FORM_exprloc
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 63 # DW_AT_external
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 10 # Abbreviation Code
+ .byte 5 # DW_TAG_formal_parameter
+ .byte 0 # DW_CHILDREN_no
+ .byte 2 # DW_AT_location
+ .byte 24 # DW_FORM_exprloc
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 11 # Abbreviation Code
+ .byte 52 # DW_TAG_variable
+ .byte 0 # DW_CHILDREN_no
+ .byte 2 # DW_AT_location
+ .byte 24 # DW_FORM_exprloc
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"",@progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .byte 1 # Abbrev [1] 0xc:0x11a DW_TAG_compile_unit
+ .byte 0 # DW_AT_producer
+ .short 33 # DW_AT_language
+ .byte 1 # DW_AT_name
+ .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .byte 2 # DW_AT_comp_dir
+ .byte 2 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .long .Laddr_table_base0 # DW_AT_addr_base
+ .byte 2 # Abbrev [2] 0x23:0xb DW_TAG_variable
+ .byte 3 # DW_AT_name
+ .long 46 # DW_AT_type
+ # DW_AT_external
+ .byte 0 # DW_AT_decl_file
+ .byte 14 # DW_AT_decl_line
+ .byte 2 # DW_AT_location
+ .byte 161
+ .byte 1
+ .byte 3 # Abbrev [3] 0x2e:0x10 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 8 # DW_AT_name
+ .byte 4 # DW_AT_byte_size
+ .byte 0 # DW_AT_decl_file
+ .byte 11 # DW_AT_decl_line
+ .byte 4 # Abbrev [4] 0x34:0x9 DW_TAG_member
+ .byte 3 # DW_AT_name
+ .long 62 # DW_AT_type
+ .byte 0 # DW_AT_decl_file
+ .byte 12 # DW_AT_decl_line
+ .byte 0 # DW_AT_data_member_location
+ .byte 0 # End Of Children Mark
+ .byte 3 # Abbrev [3] 0x3e:0x19 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 7 # DW_AT_name
+ .byte 4 # DW_AT_byte_size
+ .byte 0 # DW_AT_decl_file
+ .byte 8 # DW_AT_decl_line
+ .byte 5 # Abbrev [5] 0x44:0x9 DW_TAG_template_value_parameter
+ .long 87 # DW_AT_type
+ .byte 3 # DW_AT_location
+ .byte 161
+ .byte 0
+ .byte 159
+ .byte 4 # Abbrev [4] 0x4d:0x9 DW_TAG_member
+ .byte 3 # DW_AT_name
+ .long 97 # DW_AT_type
+ .byte 0 # DW_AT_decl_file
+ .byte 9 # DW_AT_decl_line
+ .byte 0 # DW_AT_data_member_location
+ .byte 0 # End Of Children Mark
+ .byte 6 # Abbrev [6] 0x57:0x5 DW_TAG_pointer_type
+ .long 92 # DW_AT_type
+ .byte 7 # Abbrev [7] 0x5c:0x4 DW_TAG_base_type
+ .byte 4 # DW_AT_name
+ .byte 5 # DW_AT_encoding
+ .byte 4 # DW_AT_byte_size
+ .byte 8 # Abbrev [8] 0x60:0x12 DW_TAG_namespace
+ .byte 3 # Abbrev [3] 0x61:0x10 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 6 # DW_AT_name
+ .byte 4 # DW_AT_byte_size
+ .byte 0 # DW_AT_decl_file
+ .byte 4 # DW_AT_decl_line
+ .byte 4 # Abbrev [4] 0x67:0x9 DW_TAG_member
+ .byte 5 # DW_AT_name
+ .long 92 # DW_AT_type
+ .byte 0 # DW_AT_decl_file
+ .byte 5 # DW_AT_decl_line
+ .byte 0 # DW_AT_data_member_location
+ .byte 0 # End Of Children Mark
+ .byte 0 # End Of Children Mark
+ .byte 9 # Abbrev [9] 0x72:0x48 DW_TAG_subprogram
+ .byte 2 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .byte 1 # DW_AT_frame_base
+ .byte 86
+ .byte 9 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 25 # DW_AT_decl_line
+ .long 92 # DW_AT_type
+ # DW_AT_external
+ .byte 10 # Abbrev [10] 0x81:0xb DW_TAG_formal_parameter
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 120
+ .byte 10 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 25 # DW_AT_decl_line
+ .long 92 # DW_AT_type
+ .byte 10 # Abbrev [10] 0x8c:0xb DW_TAG_formal_parameter
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 112
+ .byte 11 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 25 # DW_AT_decl_line
+ .long 186 # DW_AT_type
+ .byte 11 # Abbrev [11] 0x97:0xb DW_TAG_variable
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 88
+ .byte 13 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 26 # DW_AT_decl_line
+ .long 200 # DW_AT_type
+ .byte 11 # Abbrev [11] 0xa2:0xb DW_TAG_variable
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 72
+ .byte 18 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 27 # DW_AT_decl_line
+ .long 234 # DW_AT_type
+ .byte 11 # Abbrev [11] 0xad:0xc DW_TAG_variable
+ .byte 3 # DW_AT_location
+ .byte 145
+ .ascii "\260\177"
+ .byte 20 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 28 # DW_AT_decl_line
+ .long 259 # DW_AT_type
+ .byte 0 # End Of Children Mark
+ .byte 6 # Abbrev [6] 0xba:0x5 DW_TAG_pointer_type
+ .long 191 # DW_AT_type
+ .byte 6 # Abbrev [6] 0xbf:0x5 DW_TAG_pointer_type
+ .long 196 # DW_AT_type
+ .byte 7 # Abbrev [7] 0xc4:0x4 DW_TAG_base_type
+ .byte 12 # DW_AT_name
+ .byte 6 # DW_AT_encoding
+ .byte 1 # DW_AT_byte_size
+ .byte 3 # Abbrev [3] 0xc8:0x22 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 17 # DW_AT_name
+ .byte 24 # DW_AT_byte_size
+ .byte 0 # DW_AT_decl_file
+ .byte 16 # DW_AT_decl_line
+ .byte 4 # Abbrev [4] 0xce:0x9 DW_TAG_member
+ .byte 14 # DW_AT_name
+ .long 191 # DW_AT_type
+ .byte 0 # DW_AT_decl_file
+ .byte 17 # DW_AT_decl_line
+ .byte 0 # DW_AT_data_member_location
+ .byte 4 # Abbrev [4] 0xd7:0x9 DW_TAG_member
+ .byte 15 # DW_AT_name
+ .long 191 # DW_AT_type
+ .byte 0 # DW_AT_decl_file
+ .byte 18 # DW_AT_decl_line
+ .byte 8 # DW_AT_data_member_location
+ .byte 4 # Abbrev [4] 0xe0:0x9 DW_TAG_member
+ .byte 16 # DW_AT_name
+ .long 191 # DW_AT_type
+ .byte 0 # DW_AT_decl_file
+ .byte 19 # DW_AT_decl_line
+ .byte 16 # DW_AT_data_member_location
+ .byte 0 # End Of Children Mark
+ .byte 3 # Abbrev [3] 0xea:0x19 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 19 # DW_AT_name
+ .byte 16 # DW_AT_byte_size
+ .byte 0 # DW_AT_decl_file
+ .byte 21 # DW_AT_decl_line
+ .byte 4 # Abbrev [4] 0xf0:0x9 DW_TAG_member
+ .byte 14 # DW_AT_name
+ .long 191 # DW_AT_type
+ .byte 0 # DW_AT_decl_file
+ .byte 22 # DW_AT_decl_line
+ .byte 0 # DW_AT_data_member_location
+ .byte 4 # Abbrev [4] 0xf9:0x9 DW_TAG_member
+ .byte 15 # DW_AT_name
+ .long 191 # DW_AT_type
+ .byte 0 # DW_AT_decl_file
+ .byte 23 # DW_AT_decl_line
+ .byte 8 # DW_AT_data_member_location
+ .byte 0 # End Of Children Mark
+ .byte 3 # Abbrev [3] 0x103:0x22 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 21 # DW_AT_name
+ .byte 24 # DW_AT_byte_size
+ .byte 1 # DW_AT_decl_file
+ .byte 1 # DW_AT_decl_line
+ .byte 4 # Abbrev [4] 0x109:0x9 DW_TAG_member
+ .byte 14 # DW_AT_name
+ .long 191 # DW_AT_type
+ .byte 1 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .byte 0 # DW_AT_data_member_location
+ .byte 4 # Abbrev [4] 0x112:0x9 DW_TAG_member
+ .byte 15 # DW_AT_name
+ .long 191 # DW_AT_type
+ .byte 1 # DW_AT_decl_file
+ .byte 3 # DW_AT_decl_line
+ .byte 8 # DW_AT_data_member_location
+ .byte 4 # Abbrev [4] 0x11b:0x9 DW_TAG_member
+ .byte 16 # DW_AT_name
+ .long 191 # DW_AT_type
+ .byte 1 # DW_AT_decl_file
+ .byte 4 # DW_AT_decl_line
+ .byte 16 # DW_AT_data_member_location
+ .byte 0 # End Of Children Mark
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"",@progbits
+ .long 92 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS",@progbits,1
+.Linfo_string0:
+ .asciz "clang version 18.0.0git" # string offset=0
+.Linfo_string1:
+ .asciz "main.cpp" # string offset=24
+.Linfo_string2:
+ .asciz "/home/ayermolo/local/tasks/T138552329/typeDedup" # string offset=33
+.Linfo_string3:
+ .asciz "v1" # string offset=81
+.Linfo_string4:
+ .asciz "t3" # string offset=84
+.Linfo_string5:
+ .asciz "t2<&fooint>" # string offset=87
+.Linfo_string6:
+ .asciz "int" # string offset=99
+.Linfo_string7:
+ .asciz "(anonymous namespace)" # string offset=103
+.Linfo_string8:
+ .asciz "t1" # string offset=125
+.Linfo_string9:
+ .asciz "i" # string offset=128
+.Linfo_string10:
+ .asciz "main" # string offset=130
+.Linfo_string11:
+ .asciz "argc" # string offset=135
+.Linfo_string12:
+ .asciz "argv" # string offset=140
+.Linfo_string13:
+ .asciz "char" # string offset=145
+.Linfo_string14:
+ .asciz "f" # string offset=150
+.Linfo_string15:
+ .asciz "Foo" # string offset=152
+.Linfo_string16:
+ .asciz "c1" # string offset=156
+.Linfo_string17:
+ .asciz "c2" # string offset=159
+.Linfo_string18:
+ .asciz "c3" # string offset=162
+.Linfo_string19:
+ .asciz "f2" # string offset=165
+.Linfo_string20:
+ .asciz "Foo2" # string offset=168
+.Linfo_string21:
+ .asciz "f3" # string offset=173
+.Linfo_string22:
+ .asciz "Foo2a" # string offset=176
+ .section .debug_str_offsets,"",@progbits
+ .long .Linfo_string0
+ .long .Linfo_string1
+ .long .Linfo_string2
+ .long .Linfo_string3
+ .long .Linfo_string6
+ .long .Linfo_string9
+ .long .Linfo_string8
+ .long .Linfo_string5
+ .long .Linfo_string4
+ .long .Linfo_string10
+ .long .Linfo_string11
+ .long .Linfo_string12
+ .long .Linfo_string13
+ .long .Linfo_string14
+ .long .Linfo_string16
+ .long .Linfo_string17
+ .long .Linfo_string18
+ .long .Linfo_string15
+ .long .Linfo_string19
+ .long .Linfo_string20
+ .long .Linfo_string21
+ .long .Linfo_string22
+ .section .debug_addr,"",@progbits
+ .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution
+.Ldebug_addr_start0:
+ .short 5 # DWARF version number
+ .byte 8 # Address size
+ .byte 0 # Segment selector size
+.Laddr_table_base0:
+ .quad fooint
+ .quad v1
+ .quad .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"",@progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 11 # Header: bucket count
+ .long 11 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long 1 # Bucket 0
+ .long 3 # Bucket 1
+ .long 5 # Bucket 2
+ .long 0 # Bucket 3
+ .long 0 # Bucket 4
+ .long 6 # Bucket 5
+ .long 8 # Bucket 6
+ .long 9 # Bucket 7
+ .long 11 # Bucket 8
+ .long 0 # Bucket 9
+ .long 0 # Bucket 10
+ .long 259227804 # Hash in Bucket 0
+ .long 2090147939 # Hash in Bucket 0
+ .long 193491849 # Hash in Bucket 1
+ .long 958480634 # Hash in Bucket 1
+ .long 2090263771 # Hash in Bucket 2
+ .long 5863786 # Hash in Bucket 5
+ .long 5863852 # Hash in Bucket 5
+ .long 193495088 # Hash in Bucket 6
+ .long 5863788 # Hash in Bucket 7
+ .long 2090499946 # Hash in Bucket 7
+ .long -1929613044 # Hash in Bucket 8
+ .long .Linfo_string22 # String in Bucket 0: Foo2a
+ .long .Linfo_string13 # String in Bucket 0: char
+ .long .Linfo_string15 # String in Bucket 1: Foo
+ .long .Linfo_string5 # String in Bucket 1: t2<&fooint>
+ .long .Linfo_string20 # String in Bucket 2: Foo2
+ .long .Linfo_string8 # String in Bucket 5: t1
+ .long .Linfo_string3 # String in Bucket 5: v1
+ .long .Linfo_string6 # String in Bucket 6: int
+ .long .Linfo_string4 # String in Bucket 7: t3
+ .long .Linfo_string10 # String in Bucket 7: main
+ .long .Linfo_string7 # String in Bucket 8: (anonymous namespace)
+ .long .Lnames10-.Lnames_entries0 # Offset in Bucket 0
+ .long .Lnames7-.Lnames_entries0 # Offset in Bucket 0
+ .long .Lnames8-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames9-.Lnames_entries0 # Offset in Bucket 2
+ .long .Lnames4-.Lnames_entries0 # Offset in Bucket 5
+ .long .Lnames5-.Lnames_entries0 # Offset in Bucket 5
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 6
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 7
+ .long .Lnames6-.Lnames_entries0 # Offset in Bucket 7
+ .long .Lnames3-.Lnames_entries0 # Offset in Bucket 8
+.Lnames_abbrev_start0:
+ .ascii "\2309" # Abbrev code
+ .byte 57 # DW_TAG_namespace
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\270\023" # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\230\023" # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\230$" # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\2304" # Abbrev code
+ .byte 52 # DW_TAG_variable
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\230." # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames10:
+.L1:
+ .ascii "\230\023" # Abbreviation code
+ .long 259 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: Foo2a
+.Lnames7:
+.L8:
+ .ascii "\230$" # Abbreviation code
+ .long 196 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: char
+.Lnames8:
+.L0:
+ .ascii "\230\023" # Abbreviation code
+ .long 200 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: Foo
+.Lnames1:
+.L2:
+ .ascii "\230\023" # Abbreviation code
+ .long 62 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: t2<&fooint>
+.Lnames9:
+.L9:
+ .ascii "\230\023" # Abbreviation code
+ .long 234 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: Foo2
+.Lnames4:
+.L5:
+ .ascii "\270\023" # Abbreviation code
+ .long 97 # DW_IDX_die_offset
+ .long .L3-.Lnames_entries0 # DW_IDX_parent
+ .byte 0 # End of list: t1
+.Lnames5:
+.L7:
+ .ascii "\2304" # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: v1
+.Lnames2:
+.L10:
+ .ascii "\230$" # Abbreviation code
+ .long 92 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: int
+.Lnames0:
+.L6:
+ .ascii "\230\023" # Abbreviation code
+ .long 46 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: t3
+.Lnames6:
+.L4:
+ .ascii "\230." # Abbreviation code
+ .long 114 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: main
+.Lnames3:
+.L3:
+ .ascii "\2309" # Abbreviation code
+ .long 96 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: (anonymous namespace)
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 18.0.0git"
+ .section ".note.GNU-stack","",@progbits
+ .addrsig
+ .section .debug_line,"",@progbits
+.Lline_table_start0:
bolt/test/X86/Inputs/dwarf5-df-debug-names-ftu-ltu-mix-main.s
@@ -0,0 +1,505 @@
+# struct ASplit {
+# int x;
+# };
+#
+# ASplit globalSplit;
+# int main() {
+# return 0;
+# }
+# clang++ -g2 -gdwarf-5 -gpubnames -S -fdebug-types-section -gsplit-dwarf -fdebug-compilation-dir='.'
+
+ .text
+ .file "main.cpp"
+ .file 0 "." "main.cpp" md5 0xbb74a3c2960dafa324547ebbd87d13ea
+ .section .debug_info.dwo,"e",@progbits
+ .long .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit
+.Ldebug_info_dwo_start0:
+ .short 5 # DWARF version number
+ .byte 6 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long 0 # Offset Into Abbrev. Section
+ .quad -8602855756067469281 # Type Signature
+ .long 33 # Type DIE Offset
+ .byte 1 # Abbrev [1] 0x18:0x1e DW_TAG_type_unit
+ .short 33 # DW_AT_language
+ .byte 1 # DW_AT_comp_dir
+ .byte 2 # DW_AT_dwo_name
+ .long 0 # DW_AT_stmt_list
+ .byte 2 # Abbrev [2] 0x21:0x10 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 5 # DW_AT_name
+ .byte 4 # DW_AT_byte_size
+ .byte 0 # DW_AT_decl_file
+ .byte 1 # DW_AT_decl_line
+ .byte 3 # Abbrev [3] 0x27:0x9 DW_TAG_member
+ .byte 3 # DW_AT_name
+ .long 49 # DW_AT_type
+ .byte 0 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .byte 0 # DW_AT_data_member_location
+ .byte 0 # End Of Children Mark
+ .byte 4 # Abbrev [4] 0x31:0x4 DW_TAG_base_type
+ .byte 4 # DW_AT_name
+ .byte 5 # DW_AT_encoding
+ .byte 4 # DW_AT_byte_size
+ .byte 0 # End Of Children Mark
+.Ldebug_info_dwo_end0:
+ .text
+ .globl main # -- Begin function main
+ .p2align 4, 0x90
+ .type main,@function
+main: # @main
+.Lfunc_begin0:
+ .loc 0 6 0 # main.cpp:6:0
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+ movl $0, -4(%rbp)
+.Ltmp0:
+ .loc 0 7 3 prologue_end # main.cpp:7:3
+ xorl %eax, %eax
+ .loc 0 7 3 epilogue_begin is_stmt 0 # main.cpp:7:3
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size main, .Lfunc_end0-main
+ .cfi_endproc
+ # -- End function
+ .type globalSplit,@object # @globalSplit
+ .bss
+ .globl globalSplit
+ .p2align 2, 0x0
+globalSplit:
+ .zero 4
+ .size globalSplit, 4
+
+ .section .debug_abbrev,"",@progbits
+ .byte 1 # Abbreviation Code
+ .byte 74 # DW_TAG_skeleton_unit
+ .byte 0 # DW_CHILDREN_no
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 114 # DW_AT_str_offsets_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 27 # DW_AT_comp_dir
+ .byte 37 # DW_FORM_strx1
+ .byte 118 # DW_AT_dwo_name
+ .byte 37 # DW_FORM_strx1
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 115 # DW_AT_addr_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"",@progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 4 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .quad 5806847994123082226
+ .byte 1 # Abbrev [1] 0x14:0x14 DW_TAG_skeleton_unit
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .byte 0 # DW_AT_comp_dir
+ .byte 1 # DW_AT_dwo_name
+ .byte 1 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .long .Laddr_table_base0 # DW_AT_addr_base
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"",@progbits
+ .long 12 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS",@progbits,1
+.Lskel_string0:
+ .asciz "." # string offset=0
+.Lskel_string1:
+ .asciz "ASplit" # string offset=2
+.Lskel_string2:
+ .asciz "int" # string offset=9
+.Lskel_string3:
+ .asciz "globalSplit" # string offset=13
+.Lskel_string4:
+ .asciz "main" # string offset=25
+.Lskel_string5:
+ .asciz "main.dwo" # string offset=30
+ .section .debug_str_offsets,"",@progbits
+ .long .Lskel_string0
+ .long .Lskel_string5
+ .section .debug_str_offsets.dwo,"e",@progbits
+ .long 40 # Length of String Offsets Set
+ .short 5
+ .short 0
+ .section .debug_str.dwo,"eMS",@progbits,1
+.Linfo_string0:
+ .asciz "globalSplit" # string offset=0
+.Linfo_string1:
+ .asciz "." # string offset=12
+.Linfo_string2:
+ .asciz "main.dwo" # string offset=14
+.Linfo_string3:
+ .asciz "x" # string offset=23
+.Linfo_string4:
+ .asciz "int" # string offset=25
+.Linfo_string5:
+ .asciz "ASplit" # string offset=29
+.Linfo_string6:
+ .asciz "main" # string offset=36
+.Linfo_string7:
+ .asciz "clang version 19.0.0git (git@github.com:llvm/llvm-project.git ced1fac8a32e35b63733bda27c7f5b9a2b635403)" # string offset=41
+.Linfo_string8:
+ .asciz "main.cpp" # string offset=145
+ .section .debug_str_offsets.dwo,"e",@progbits
+ .long 0
+ .long 12
+ .long 14
+ .long 23
+ .long 25
+ .long 29
+ .long 36
+ .long 41
+ .long 145
+ .section .debug_info.dwo,"e",@progbits
+ .long .Ldebug_info_dwo_end1-.Ldebug_info_dwo_start1 # Length of Unit
+.Ldebug_info_dwo_start1:
+ .short 5 # DWARF version number
+ .byte 5 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long 0 # Offset Into Abbrev. Section
+ .quad 5806847994123082226
+ .byte 5 # Abbrev [5] 0x14:0x2e DW_TAG_compile_unit
+ .byte 7 # DW_AT_producer
+ .short 33 # DW_AT_language
+ .byte 8 # DW_AT_name
+ .byte 2 # DW_AT_dwo_name
+ .byte 6 # Abbrev [6] 0x1a:0xb DW_TAG_variable
+ .byte 0 # DW_AT_name
+ .long 37 # DW_AT_type
+ # DW_AT_external
+ .byte 0 # DW_AT_decl_file
+ .byte 5 # DW_AT_decl_line
+ .byte 2 # DW_AT_location
+ .byte 161
+ .byte 0
+ .byte 7 # Abbrev [7] 0x25:0x9 DW_TAG_structure_type
+ # DW_AT_declaration
+ .quad -8602855756067469281 # DW_AT_signature
+ .byte 8 # Abbrev [8] 0x2e:0xf DW_TAG_subprogram
+ .byte 1 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .byte 1 # DW_AT_frame_base
+ .byte 86
+ .byte 6 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 6 # DW_AT_decl_line
+ .long 61 # DW_AT_type
+ # DW_AT_external
+ .byte 4 # Abbrev [4] 0x3d:0x4 DW_TAG_base_type
+ .byte 4 # DW_AT_name
+ .byte 5 # DW_AT_encoding
+ .byte 4 # DW_AT_byte_size
+ .byte 0 # End Of Children Mark
+.Ldebug_info_dwo_end1:
+ .section .debug_abbrev.dwo,"e",@progbits
+ .byte 1 # Abbreviation Code
+ .byte 65 # DW_TAG_type_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 27 # DW_AT_comp_dir
+ .byte 37 # DW_FORM_strx1
+ .byte 118 # DW_AT_dwo_name
+ .byte 37 # DW_FORM_strx1
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 2 # Abbreviation Code
+ .byte 19 # DW_TAG_structure_type
+ .byte 1 # DW_CHILDREN_yes
+ .byte 54 # DW_AT_calling_convention
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 3 # Abbreviation Code
+ .byte 13 # DW_TAG_member
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 56 # DW_AT_data_member_location
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 4 # Abbreviation Code
+ .byte 36 # DW_TAG_base_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 62 # DW_AT_encoding
+ .byte 11 # DW_FORM_data1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 5 # Abbreviation Code
+ .byte 17 # DW_TAG_compile_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 37 # DW_AT_producer
+ .byte 37 # DW_FORM_strx1
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 118 # DW_AT_dwo_name
+ .byte 37 # DW_FORM_strx1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 6 # Abbreviation Code
+ .byte 52 # DW_TAG_variable
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 63 # DW_AT_external
+ .byte 25 # DW_FORM_flag_present
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 2 # DW_AT_location
+ .byte 24 # DW_FORM_exprloc
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 7 # Abbreviation Code
+ .byte 19 # DW_TAG_structure_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 60 # DW_AT_declaration
+ .byte 25 # DW_FORM_flag_present
+ .byte 105 # DW_AT_signature
+ .byte 32 # DW_FORM_ref_sig8
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 8 # Abbreviation Code
+ .byte 46 # DW_TAG_subprogram
+ .byte 0 # DW_CHILDREN_no
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 64 # DW_AT_frame_base
+ .byte 24 # DW_FORM_exprloc
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 63 # DW_AT_external
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_line.dwo,"e",@progbits
+.Ltmp2:
+ .long .Ldebug_line_end0-.Ldebug_line_start0 # unit length
+.Ldebug_line_start0:
+ .short 5
+ .byte 8
+ .byte 0
+ .long .Lprologue_end0-.Lprologue_start0
+.Lprologue_start0:
+ .byte 1
+ .byte 1
+ .byte 1
+ .byte -5
+ .byte 14
+ .byte 1
+ .byte 1
+ .byte 1
+ .byte 8
+ .byte 1
+ .byte 46
+ .byte 0
+ .byte 3
+ .byte 1
+ .byte 8
+ .byte 2
+ .byte 15
+ .byte 5
+ .byte 30
+ .byte 1
+ .ascii "main.cpp"
+ .byte 0
+ .byte 0
+ .byte 0xbb, 0x74, 0xa3, 0xc2
+ .byte 0x96, 0x0d, 0xaf, 0xa3
+ .byte 0x24, 0x54, 0x7e, 0xbb
+ .byte 0xd8, 0x7d, 0x13, 0xea
+.Lprologue_end0:
+.Ldebug_line_end0:
+ .section .debug_addr,"",@progbits
+ .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution
+.Ldebug_addr_start0:
+ .short 5 # DWARF version number
+ .byte 8 # Address size
+ .byte 0 # Segment selector size
+.Laddr_table_base0:
+ .quad globalSplit
+ .quad .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"",@progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 1 # Header: foreign type unit count
+ .long 4 # Header: bucket count
+ .long 4 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .quad -8602855756067469281 # Type unit 0
+ .long 1 # Bucket 0
+ .long 0 # Bucket 1
+ .long 2 # Bucket 2
+ .long 0 # Bucket 3
+ .long 193495088 # Hash in Bucket 0
+ .long 1785912162 # Hash in Bucket 2
+ .long 2090499946 # Hash in Bucket 2
+ .long -226250862 # Hash in Bucket 2
+ .long .Lskel_string2 # String in Bucket 0: int
+ .long .Lskel_string3 # String in Bucket 2: globalSplit
+ .long .Lskel_string4 # String in Bucket 2: main
+ .long .Lskel_string1 # String in Bucket 2: ASplit
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 0
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 2
+ .long .Lnames3-.Lnames_entries0 # Offset in Bucket 2
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 2
+.Lnames_abbrev_start0:
+ .byte 1 # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 2 # DW_IDX_type_unit
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 2 # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 3 # Abbrev code
+ .byte 52 # DW_TAG_variable
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 4 # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 5 # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 2 # DW_IDX_type_unit
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 6 # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames1:
+.L5:
+ .byte 1 # Abbreviation code
+ .byte 0 # DW_IDX_type_unit
+ .long 49 # DW_IDX_die_offset
+.L1: # DW_IDX_parent
+ .byte 2 # Abbreviation code
+ .long 61 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: int
+.Lnames2:
+.L0:
+ .byte 3 # Abbreviation code
+ .long 26 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: globalSplit
+.Lnames3:
+.L2:
+ .byte 4 # Abbreviation code
+ .long 46 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: main
+.Lnames0:
+.L4:
+ .byte 5 # Abbreviation code
+ .byte 0 # DW_IDX_type_unit
+ .long 33 # DW_IDX_die_offset
+.L3: # DW_IDX_parent
+ .byte 6 # Abbreviation code
+ .long 37 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: ASplit
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 19.0.0git (git@github.com:llvm/llvm-project.git ced1fac8a32e35b63733bda27c7f5b9a2b635403)"
+ .section ".note.GNU-stack","",@progbits
+ .addrsig
+ .section .debug_line,"",@progbits
+.Lline_table_start0:
bolt/test/X86/Inputs/dwarf5-df-debug-names-helper.s
@@ -0,0 +1,326 @@
+# clang++ -gsplit-dwarf -g2 -gdwarf-5 -gpubnames -fdebug-compilation-dir='.'
+# header.h
+# struct Foo2a {
+# char *c1;
+# char *c2;
+# char *c3;
+# };
+# helper.cpp
+# #include "header.h"
+# struct Foo2Int {
+# int *c1;
+# int *c2;
+# };
+# Foo2Int fint;
+# const Foo2a f{nullptr, nullptr};
+
+ .text
+ .file "helper.cpp"
+ .file 0 "." "helper.cpp" md5 0x2804efac708fd4180d403e6d5dbcc54a
+ .type fint,@object # @fint
+ .bss
+ .globl fint
+ .p2align 3, 0x0
+fint:
+ .zero 16
+ .size fint, 16
+
+ .section .debug_abbrev,"",@progbits
+ .byte 1 # Abbreviation Code
+ .byte 74 # DW_TAG_skeleton_unit
+ .byte 0 # DW_CHILDREN_no
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 114 # DW_AT_str_offsets_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 27 # DW_AT_comp_dir
+ .byte 37 # DW_FORM_strx1
+ .byte 118 # DW_AT_dwo_name
+ .byte 37 # DW_FORM_strx1
+ .byte 115 # DW_AT_addr_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"",@progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 4 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .quad 3223434782003797151
+ .byte 1 # Abbrev [1] 0x14:0xf DW_TAG_skeleton_unit
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .byte 0 # DW_AT_comp_dir
+ .byte 1 # DW_AT_dwo_name
+ .long .Laddr_table_base0 # DW_AT_addr_base
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"",@progbits
+ .long 12 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS",@progbits,1
+.Lskel_string0:
+ .asciz "." # string offset=0
+.Lskel_string1:
+ .asciz "Foo2Int" # string offset=2
+.Lskel_string2:
+ .asciz "int" # string offset=10
+.Lskel_string3:
+ .asciz "fint" # string offset=14
+.Lskel_string4:
+ .asciz "helper.dwo" # string offset=19
+ .section .debug_str_offsets,"",@progbits
+ .long .Lskel_string0
+ .long .Lskel_string4
+ .section .debug_str_offsets.dwo,"e",@progbits
+ .long 36 # Length of String Offsets Set
+ .short 5
+ .short 0
+ .section .debug_str.dwo,"eMS",@progbits,1
+.Linfo_string0:
+ .asciz "fint" # string offset=0
+.Linfo_string1:
+ .asciz "c1" # string offset=5
+.Linfo_string2:
+ .asciz "int" # string offset=8
+.Linfo_string3:
+ .asciz "c2" # string offset=12
+.Linfo_string4:
+ .asciz "Foo2Int" # string offset=15
+.Linfo_string5:
+ .asciz "clang version 19.0.0git (git@github.com:ayermolo/llvm-project.git da9e9277be64deca73370a90d22af33e5b37cc52)" # string offset=23
+.Linfo_string6:
+ .asciz "helper.cpp" # string offset=131
+.Linfo_string7:
+ .asciz "helper.dwo" # string offset=142
+ .section .debug_str_offsets.dwo,"e",@progbits
+ .long 0
+ .long 5
+ .long 8
+ .long 12
+ .long 15
+ .long 23
+ .long 131
+ .long 142
+ .section .debug_info.dwo,"e",@progbits
+ .long .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit
+.Ldebug_info_dwo_start0:
+ .short 5 # DWARF version number
+ .byte 5 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long 0 # Offset Into Abbrev. Section
+ .quad 3223434782003797151
+ .byte 1 # Abbrev [1] 0x14:0x34 DW_TAG_compile_unit
+ .byte 5 # DW_AT_producer
+ .short 33 # DW_AT_language
+ .byte 6 # DW_AT_name
+ .byte 7 # DW_AT_dwo_name
+ .byte 2 # Abbrev [2] 0x1a:0xb DW_TAG_variable
+ .byte 0 # DW_AT_name
+ .long 37 # DW_AT_type
+ # DW_AT_external
+ .byte 0 # DW_AT_decl_file
+ .byte 7 # DW_AT_decl_line
+ .byte 2 # DW_AT_location
+ .byte 161
+ .byte 0
+ .byte 3 # Abbrev [3] 0x25:0x19 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 4 # DW_AT_name
+ .byte 16 # DW_AT_byte_size
+ .byte 0 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .byte 4 # Abbrev [4] 0x2b:0x9 DW_TAG_member
+ .byte 1 # DW_AT_name
+ .long 62 # DW_AT_type
+ .byte 0 # DW_AT_decl_file
+ .byte 3 # DW_AT_decl_line
+ .byte 0 # DW_AT_data_member_location
+ .byte 4 # Abbrev [4] 0x34:0x9 DW_TAG_member
+ .byte 3 # DW_AT_name
+ .long 62 # DW_AT_type
+ .byte 0 # DW_AT_decl_file
+ .byte 4 # DW_AT_decl_line
+ .byte 8 # DW_AT_data_member_location
+ .byte 0 # End Of Children Mark
+ .byte 5 # Abbrev [5] 0x3e:0x5 DW_TAG_pointer_type
+ .long 67 # DW_AT_type
+ .byte 6 # Abbrev [6] 0x43:0x4 DW_TAG_base_type
+ .byte 2 # DW_AT_name
+ .byte 5 # DW_AT_encoding
+ .byte 4 # DW_AT_byte_size
+ .byte 0 # End Of Children Mark
+.Ldebug_info_dwo_end0:
+ .section .debug_abbrev.dwo,"e",@progbits
+ .byte 1 # Abbreviation Code
+ .byte 17 # DW_TAG_compile_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 37 # DW_AT_producer
+ .byte 37 # DW_FORM_strx1
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 118 # DW_AT_dwo_name
+ .byte 37 # DW_FORM_strx1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 2 # Abbreviation Code
+ .byte 52 # DW_TAG_variable
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 63 # DW_AT_external
+ .byte 25 # DW_FORM_flag_present
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 2 # DW_AT_location
+ .byte 24 # DW_FORM_exprloc
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 3 # Abbreviation Code
+ .byte 19 # DW_TAG_structure_type
+ .byte 1 # DW_CHILDREN_yes
+ .byte 54 # DW_AT_calling_convention
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 4 # Abbreviation Code
+ .byte 13 # DW_TAG_member
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 56 # DW_AT_data_member_location
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 5 # Abbreviation Code
+ .byte 15 # DW_TAG_pointer_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 6 # Abbreviation Code
+ .byte 36 # DW_TAG_base_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 62 # DW_AT_encoding
+ .byte 11 # DW_FORM_data1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_addr,"",@progbits
+ .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution
+.Ldebug_addr_start0:
+ .short 5 # DWARF version number
+ .byte 8 # Address size
+ .byte 0 # Segment selector size
+.Laddr_table_base0:
+ .quad fint
+.Ldebug_addr_end0:
+ .section .debug_names,"",@progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 3 # Header: bucket count
+ .long 3 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long 1 # Bucket 0
+ .long 2 # Bucket 1
+ .long 3 # Bucket 2
+ .long -1168750522 # Hash in Bucket 0
+ .long 2090257270 # Hash in Bucket 1
+ .long 193495088 # Hash in Bucket 2
+ .long .Lskel_string1 # String in Bucket 0: Foo2Int
+ .long .Lskel_string3 # String in Bucket 1: fint
+ .long .Lskel_string2 # String in Bucket 2: int
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 0
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 2
+.Lnames_abbrev_start0:
+ .ascii "\230\023" # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\2304" # Abbrev code
+ .byte 52 # DW_TAG_variable
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\230$" # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames0:
+.L1:
+ .ascii "\230\023" # Abbreviation code
+ .long 37 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: Foo2Int
+.Lnames2:
+.L0:
+ .ascii "\2304" # Abbreviation code
+ .long 26 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: fint
+.Lnames1:
+.L2:
+ .ascii "\230$" # Abbreviation code
+ .long 67 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: int
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 19.0.0git (git@github.com:ayermolo/llvm-project.git da9e9277be64deca73370a90d22af33e5b37cc52)"
+ .section ".note.GNU-stack","",@progbits
+ .addrsig
+ .section .debug_line,"",@progbits
+.Lline_table_start0:
bolt/test/X86/Inputs/dwarf5-df-debug-names-main.s
@@ -0,0 +1,493 @@
+# clang++ -gsplit-dwarf -g2 -gdwarf-5 -gpubnames -fdebug-compilation-dir='.'
+# header.h
+# struct Foo2a {
+# char *c1;
+# char *c2;
+# char *c3;
+# };
+# main.cpp
+# #include "header.h"
+# struct Foo2 {
+# char *c1;
+# };
+# int main(int argc, char *argv[]) {
+# Foo2 f2;
+# Foo2a f3;
+# return 0;
+# }
+
+ .text
+ .file "main.cpp"
+ .globl main # -- Begin function main
+ .p2align 4, 0x90
+ .type main,@function
+main: # @main
+.Lfunc_begin0:
+ .file 0 "." "main.cpp" md5 0x9c5cea5bb78d3fc265cd175110bfe903
+ .loc 0 5 0 # main.cpp:5:0
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+ movl $0, -4(%rbp)
+ movl %edi, -8(%rbp)
+ movq %rsi, -16(%rbp)
+.Ltmp0:
+ .loc 0 8 2 prologue_end # main.cpp:8:2
+ xorl %eax, %eax
+ .loc 0 8 2 epilogue_begin is_stmt 0 # main.cpp:8:2
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size main, .Lfunc_end0-main
+ .cfi_endproc
+ # -- End function
+ .file 1 "." "header.h" md5 0xfea7bb1f22c47f129e15695f7137a1e7
+ .section .debug_abbrev,"",@progbits
+ .byte 1 # Abbreviation Code
+ .byte 74 # DW_TAG_skeleton_unit
+ .byte 0 # DW_CHILDREN_no
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 114 # DW_AT_str_offsets_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 27 # DW_AT_comp_dir
+ .byte 37 # DW_FORM_strx1
+ .byte 118 # DW_AT_dwo_name
+ .byte 37 # DW_FORM_strx1
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 115 # DW_AT_addr_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"",@progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 4 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .quad -5618023701701543936
+ .byte 1 # Abbrev [1] 0x14:0x14 DW_TAG_skeleton_unit
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .byte 0 # DW_AT_comp_dir
+ .byte 1 # DW_AT_dwo_name
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .long .Laddr_table_base0 # DW_AT_addr_base
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"",@progbits
+ .long 12 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS",@progbits,1
+.Lskel_string0:
+ .asciz "." # string offset=0
+.Lskel_string1:
+ .asciz "main" # string offset=2
+.Lskel_string2:
+ .asciz "int" # string offset=7
+.Lskel_string3:
+ .asciz "char" # string offset=11
+.Lskel_string4:
+ .asciz "Foo2" # string offset=16
+.Lskel_string5:
+ .asciz "Foo2a" # string offset=21
+.Lskel_string6:
+ .asciz "main.dwo" # string offset=27
+ .section .debug_str_offsets,"",@progbits
+ .long .Lskel_string0
+ .long .Lskel_string6
+ .section .debug_str_offsets.dwo,"e",@progbits
+ .long 64 # Length of String Offsets Set
+ .short 5
+ .short 0
+ .section .debug_str.dwo,"eMS",@progbits,1
+.Linfo_string0:
+ .asciz "main" # string offset=0
+.Linfo_string1:
+ .asciz "int" # string offset=5
+.Linfo_string2:
+ .asciz "argc" # string offset=9
+.Linfo_string3:
+ .asciz "argv" # string offset=14
+.Linfo_string4:
+ .asciz "char" # string offset=19
+.Linfo_string5:
+ .asciz "f2" # string offset=24
+.Linfo_string6:
+ .asciz "c1" # string offset=27
+.Linfo_string7:
+ .asciz "Foo2" # string offset=30
+.Linfo_string8:
+ .asciz "f3" # string offset=35
+.Linfo_string9:
+ .asciz "c2" # string offset=38
+.Linfo_string10:
+ .asciz "c3" # string offset=41
+.Linfo_string11:
+ .asciz "Foo2a" # string offset=44
+.Linfo_string12:
+ .asciz "clang version 19.0.0git (git@github.com:ayermolo/llvm-project.git da9e9277be64deca73370a90d22af33e5b37cc52)" # string offset=50
+.Linfo_string13:
+ .asciz "main.cpp" # string offset=158
+.Linfo_string14:
+ .asciz "main.dwo" # string offset=167
+ .section .debug_str_offsets.dwo,"e",@progbits
+ .long 0
+ .long 5
+ .long 9
+ .long 14
+ .long 19
+ .long 24
+ .long 27
+ .long 30
+ .long 35
+ .long 38
+ .long 41
+ .long 44
+ .long 50
+ .long 158
+ .long 167
+ .section .debug_info.dwo,"e",@progbits
+ .long .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit
+.Ldebug_info_dwo_start0:
+ .short 5 # DWARF version number
+ .byte 5 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long 0 # Offset Into Abbrev. Section
+ .quad -5618023701701543936
+ .byte 1 # Abbrev [1] 0x14:0x87 DW_TAG_compile_unit
+ .byte 12 # DW_AT_producer
+ .short 33 # DW_AT_language
+ .byte 13 # DW_AT_name
+ .byte 14 # DW_AT_dwo_name
+ .byte 2 # Abbrev [2] 0x1a:0x3c DW_TAG_subprogram
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .byte 1 # DW_AT_frame_base
+ .byte 86
+ .byte 0 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 5 # DW_AT_decl_line
+ .long 86 # DW_AT_type
+ # DW_AT_external
+ .byte 3 # Abbrev [3] 0x29:0xb DW_TAG_formal_parameter
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 120
+ .byte 2 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 5 # DW_AT_decl_line
+ .long 86 # DW_AT_type
+ .byte 3 # Abbrev [3] 0x34:0xb DW_TAG_formal_parameter
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 112
+ .byte 3 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 5 # DW_AT_decl_line
+ .long 90 # DW_AT_type
+ .byte 4 # Abbrev [4] 0x3f:0xb DW_TAG_variable
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 104
+ .byte 5 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 6 # DW_AT_decl_line
+ .long 104 # DW_AT_type
+ .byte 4 # Abbrev [4] 0x4a:0xb DW_TAG_variable
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 80
+ .byte 8 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 7 # DW_AT_decl_line
+ .long 120 # DW_AT_type
+ .byte 0 # End Of Children Mark
+ .byte 5 # Abbrev [5] 0x56:0x4 DW_TAG_base_type
+ .byte 1 # DW_AT_name
+ .byte 5 # DW_AT_encoding
+ .byte 4 # DW_AT_byte_size
+ .byte 6 # Abbrev [6] 0x5a:0x5 DW_TAG_pointer_type
+ .long 95 # DW_AT_type
+ .byte 6 # Abbrev [6] 0x5f:0x5 DW_TAG_pointer_type
+ .long 100 # DW_AT_type
+ .byte 5 # Abbrev [5] 0x64:0x4 DW_TAG_base_type
+ .byte 4 # DW_AT_name
+ .byte 6 # DW_AT_encoding
+ .byte 1 # DW_AT_byte_size
+ .byte 7 # Abbrev [7] 0x68:0x10 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 7 # DW_AT_name
+ .byte 8 # DW_AT_byte_size
+ .byte 0 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .byte 8 # Abbrev [8] 0x6e:0x9 DW_TAG_member
+ .byte 6 # DW_AT_name
+ .long 95 # DW_AT_type
+ .byte 0 # DW_AT_decl_file
+ .byte 3 # DW_AT_decl_line
+ .byte 0 # DW_AT_data_member_location
+ .byte 0 # End Of Children Mark
+ .byte 7 # Abbrev [7] 0x78:0x22 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 11 # DW_AT_name
+ .byte 24 # DW_AT_byte_size
+ .byte 1 # DW_AT_decl_file
+ .byte 1 # DW_AT_decl_line
+ .byte 8 # Abbrev [8] 0x7e:0x9 DW_TAG_member
+ .byte 6 # DW_AT_name
+ .long 95 # DW_AT_type
+ .byte 1 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .byte 0 # DW_AT_data_member_location
+ .byte 8 # Abbrev [8] 0x87:0x9 DW_TAG_member
+ .byte 9 # DW_AT_name
+ .long 95 # DW_AT_type
+ .byte 1 # DW_AT_decl_file
+ .byte 3 # DW_AT_decl_line
+ .byte 8 # DW_AT_data_member_location
+ .byte 8 # Abbrev [8] 0x90:0x9 DW_TAG_member
+ .byte 10 # DW_AT_name
+ .long 95 # DW_AT_type
+ .byte 1 # DW_AT_decl_file
+ .byte 4 # DW_AT_decl_line
+ .byte 16 # DW_AT_data_member_location
+ .byte 0 # End Of Children Mark
+ .byte 0 # End Of Children Mark
+.Ldebug_info_dwo_end0:
+ .section .debug_abbrev.dwo,"e",@progbits
+ .byte 1 # Abbreviation Code
+ .byte 17 # DW_TAG_compile_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 37 # DW_AT_producer
+ .byte 37 # DW_FORM_strx1
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 118 # DW_AT_dwo_name
+ .byte 37 # DW_FORM_strx1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 2 # Abbreviation Code
+ .byte 46 # DW_TAG_subprogram
+ .byte 1 # DW_CHILDREN_yes
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 64 # DW_AT_frame_base
+ .byte 24 # DW_FORM_exprloc
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 63 # DW_AT_external
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 3 # Abbreviation Code
+ .byte 5 # DW_TAG_formal_parameter
+ .byte 0 # DW_CHILDREN_no
+ .byte 2 # DW_AT_location
+ .byte 24 # DW_FORM_exprloc
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 4 # Abbreviation Code
+ .byte 52 # DW_TAG_variable
+ .byte 0 # DW_CHILDREN_no
+ .byte 2 # DW_AT_location
+ .byte 24 # DW_FORM_exprloc
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 5 # Abbreviation Code
+ .byte 36 # DW_TAG_base_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 62 # DW_AT_encoding
+ .byte 11 # DW_FORM_data1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 6 # Abbreviation Code
+ .byte 15 # DW_TAG_pointer_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 7 # Abbreviation Code
+ .byte 19 # DW_TAG_structure_type
+ .byte 1 # DW_CHILDREN_yes
+ .byte 54 # DW_AT_calling_convention
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 8 # Abbreviation Code
+ .byte 13 # DW_TAG_member
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 56 # DW_AT_data_member_location
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_addr,"",@progbits
+ .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution
+.Ldebug_addr_start0:
+ .short 5 # DWARF version number
+ .byte 8 # Address size
+ .byte 0 # Segment selector size
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"",@progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 5 # Header: bucket count
+ .long 5 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long 0 # Bucket 0
+ .long 1 # Bucket 1
+ .long 0 # Bucket 2
+ .long 3 # Bucket 3
+ .long 4 # Bucket 4
+ .long 2090263771 # Hash in Bucket 1
+ .long 2090499946 # Hash in Bucket 1
+ .long 193495088 # Hash in Bucket 3
+ .long 259227804 # Hash in Bucket 4
+ .long 2090147939 # Hash in Bucket 4
+ .long .Lskel_string4 # String in Bucket 1: Foo2
+ .long .Lskel_string1 # String in Bucket 1: main
+ .long .Lskel_string2 # String in Bucket 3: int
+ .long .Lskel_string5 # String in Bucket 4: Foo2a
+ .long .Lskel_string3 # String in Bucket 4: char
+ .long .Lnames3-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 3
+ .long .Lnames4-.Lnames_entries0 # Offset in Bucket 4
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 4
+.Lnames_abbrev_start0:
+ .ascii "\230\023" # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\230." # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\230$" # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 4 # DW_IDX_parent
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames3:
+.L4:
+ .ascii "\230\023" # Abbreviation code
+ .long 104 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: Foo2
+.Lnames0:
+.L1:
+ .ascii "\230." # Abbreviation code
+ .long 26 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: main
+.Lnames1:
+.L3:
+ .ascii "\230$" # Abbreviation code
+ .long 86 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: int
+.Lnames4:
+.L2:
+ .ascii "\230\023" # Abbreviation code
+ .long 120 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: Foo2a
+.Lnames2:
+.L0:
+ .ascii "\230$" # Abbreviation code
+ .long 100 # DW_IDX_die_offset
+ .byte 0 # DW_IDX_parent
+ # End of list: char
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 19.0.0git (git@github.com:ayermolo/llvm-project.git da9e9277be64deca73370a90d22af33e5b37cc52)"
+ .section ".note.GNU-stack","",@progbits
+ .addrsig
+ .section .debug_line,"",@progbits
+.Lline_table_start0:
bolt/test/X86/Inputs/dwarf5-df-types-debug-names-helper.s
@@ -0,0 +1,650 @@
+# clang++ -gsplit-dwarf -g2 -gdwarf-5 -gpubnames -fdebug-types-section -fdebug-compilation-dir='.' -S
+# header.h
+# struct Foo2a {
+# char *c1;
+# char *c2;
+# char *c3;
+# };
+# #include "header.h"
+# struct Foo2Int {
+# int *c1;
+# int *c2;
+# };
+# Foo2Int fint;
+# const Foo2a f{nullptr, nullptr};
+
+ .text
+ .file "helper.cpp"
+ .file 0 "." "helper.cpp" md5 0xc33186b2db66a78883b1546aace9855d
+ .globl _Z3foov # -- Begin function _Z3foov
+ .p2align 4, 0x90
+ .type _Z3foov,@function
+_Z3foov: # @_Z3foov
+.Lfunc_begin0:
+ .loc 0 8 0 # helper.cpp:8:0
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+.Ltmp0:
+ .loc 0 11 3 prologue_end # helper.cpp:11:3
+ xorl %eax, %eax
+ .loc 0 11 3 epilogue_begin is_stmt 0 # helper.cpp:11:3
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size _Z3foov, .Lfunc_end0-_Z3foov
+ .cfi_endproc
+ # -- End function
+ .type fooint,@object # @fooint
+ .bss
+ .globl fooint
+ .p2align 2, 0x0
+fooint:
+ .long 0 # 0x0
+ .size fooint, 4
+
+ .section .debug_info.dwo,"e",@progbits
+ .long .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit
+.Ldebug_info_dwo_start0:
+ .short 5 # DWARF version number
+ .byte 6 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long 0 # Offset Into Abbrev. Section
+ .quad -3882554063269480080 # Type Signature
+ .long 33 # Type DIE Offset
+ .byte 1 # Abbrev [1] 0x18:0x2c DW_TAG_type_unit
+ .short 33 # DW_AT_language
+ .byte 5 # DW_AT_comp_dir
+ .byte 6 # DW_AT_dwo_name
+ .long 0 # DW_AT_stmt_list
+ .byte 2 # Abbrev [2] 0x21:0x19 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 9 # DW_AT_name
+ .byte 16 # DW_AT_byte_size
+ .byte 0 # DW_AT_decl_file
+ .byte 3 # DW_AT_decl_line
+ .byte 3 # Abbrev [3] 0x27:0x9 DW_TAG_member
+ .byte 7 # DW_AT_name
+ .long 58 # DW_AT_type
+ .byte 0 # DW_AT_decl_file
+ .byte 4 # DW_AT_decl_line
+ .byte 0 # DW_AT_data_member_location
+ .byte 3 # Abbrev [3] 0x30:0x9 DW_TAG_member
+ .byte 8 # DW_AT_name
+ .long 58 # DW_AT_type
+ .byte 0 # DW_AT_decl_file
+ .byte 5 # DW_AT_decl_line
+ .byte 8 # DW_AT_data_member_location
+ .byte 0 # End Of Children Mark
+ .byte 4 # Abbrev [4] 0x3a:0x5 DW_TAG_pointer_type
+ .long 63 # DW_AT_type
+ .byte 5 # Abbrev [5] 0x3f:0x4 DW_TAG_base_type
+ .byte 1 # DW_AT_name
+ .byte 5 # DW_AT_encoding
+ .byte 4 # DW_AT_byte_size
+ .byte 0 # End Of Children Mark
+.Ldebug_info_dwo_end0:
+ .long .Ldebug_info_dwo_end1-.Ldebug_info_dwo_start1 # Length of Unit
+.Ldebug_info_dwo_start1:
+ .short 5 # DWARF version number
+ .byte 6 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long 0 # Offset Into Abbrev. Section
+ .quad 1175092228111723119 # Type Signature
+ .long 33 # Type DIE Offset
+ .byte 1 # Abbrev [1] 0x18:0x35 DW_TAG_type_unit
+ .short 33 # DW_AT_language
+ .byte 5 # DW_AT_comp_dir
+ .byte 6 # DW_AT_dwo_name
+ .long 0 # DW_AT_stmt_list
+ .byte 2 # Abbrev [2] 0x21:0x22 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 13 # DW_AT_name
+ .byte 24 # DW_AT_byte_size
+ .byte 1 # DW_AT_decl_file
+ .byte 1 # DW_AT_decl_line
+ .byte 3 # Abbrev [3] 0x27:0x9 DW_TAG_member
+ .byte 7 # DW_AT_name
+ .long 67 # DW_AT_type
+ .byte 1 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .byte 0 # DW_AT_data_member_location
+ .byte 3 # Abbrev [3] 0x30:0x9 DW_TAG_member
+ .byte 8 # DW_AT_name
+ .long 67 # DW_AT_type
+ .byte 1 # DW_AT_decl_file
+ .byte 3 # DW_AT_decl_line
+ .byte 8 # DW_AT_data_member_location
+ .byte 3 # Abbrev [3] 0x39:0x9 DW_TAG_member
+ .byte 12 # DW_AT_name
+ .long 67 # DW_AT_type
+ .byte 1 # DW_AT_decl_file
+ .byte 4 # DW_AT_decl_line
+ .byte 16 # DW_AT_data_member_location
+ .byte 0 # End Of Children Mark
+ .byte 4 # Abbrev [4] 0x43:0x5 DW_TAG_pointer_type
+ .long 72 # DW_AT_type
+ .byte 5 # Abbrev [5] 0x48:0x4 DW_TAG_base_type
+ .byte 11 # DW_AT_name
+ .byte 6 # DW_AT_encoding
+ .byte 1 # DW_AT_byte_size
+ .byte 0 # End Of Children Mark
+.Ldebug_info_dwo_end1:
+ .section .debug_abbrev,"",@progbits
+ .byte 1 # Abbreviation Code
+ .byte 74 # DW_TAG_skeleton_unit
+ .byte 0 # DW_CHILDREN_no
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 114 # DW_AT_str_offsets_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 27 # DW_AT_comp_dir
+ .byte 37 # DW_FORM_strx1
+ .byte 118 # DW_AT_dwo_name
+ .byte 37 # DW_FORM_strx1
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 115 # DW_AT_addr_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"",@progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 4 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .quad 2142419470755914572
+ .byte 1 # Abbrev [1] 0x14:0x14 DW_TAG_skeleton_unit
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .byte 0 # DW_AT_comp_dir
+ .byte 1 # DW_AT_dwo_name
+ .byte 1 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .long .Laddr_table_base0 # DW_AT_addr_base
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"",@progbits
+ .long 12 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS",@progbits,1
+.Lskel_string0:
+ .asciz "." # string offset=0
+.Lskel_string1:
+ .asciz "int" # string offset=2
+.Lskel_string2:
+ .asciz "fooint" # string offset=6
+.Lskel_string3:
+ .asciz "foo" # string offset=13
+.Lskel_string4:
+ .asciz "_Z3foov" # string offset=17
+.Lskel_string5:
+ .asciz "Foo2Int" # string offset=25
+.Lskel_string6:
+ .asciz "Foo2a" # string offset=33
+.Lskel_string7:
+ .asciz "char" # string offset=39
+.Lskel_string8:
+ .asciz "helper.dwo" # string offset=44
+ .section .debug_str_offsets,"",@progbits
+ .long .Lskel_string0
+ .long .Lskel_string8
+ .section .debug_str_offsets.dwo,"e",@progbits
+ .long 68 # Length of String Offsets Set
+ .short 5
+ .short 0
+ .section .debug_str.dwo,"eMS",@progbits,1
+.Linfo_string0:
+ .asciz "fooint" # string offset=0
+.Linfo_string1:
+ .asciz "int" # string offset=7
+.Linfo_string2:
+ .asciz "_Z3foov" # string offset=11
+.Linfo_string3:
+ .asciz "foo" # string offset=19
+.Linfo_string4:
+ .asciz "fint" # string offset=23
+.Linfo_string5:
+ .asciz "." # string offset=28
+.Linfo_string6:
+ .asciz "helper.dwo" # string offset=30
+.Linfo_string7:
+ .asciz "c1" # string offset=41
+.Linfo_string8:
+ .asciz "c2" # string offset=44
+.Linfo_string9:
+ .asciz "Foo2Int" # string offset=47
+.Linfo_string10:
+ .asciz "f" # string offset=55
+.Linfo_string11:
+ .asciz "char" # string offset=57
+.Linfo_string12:
+ .asciz "c3" # string offset=62
+.Linfo_string13:
+ .asciz "Foo2a" # string offset=65
+.Linfo_string14:
+ .asciz "clang version 18.0.0git (git@github.com:ayermolo/llvm-project.git db35fa8fc524127079662802c4735dbf397f86d0)" # string offset=71
+.Linfo_string15:
+ .asciz "helper.cpp" # string offset=179
+ .section .debug_str_offsets.dwo,"e",@progbits
+ .long 0
+ .long 7
+ .long 11
+ .long 19
+ .long 23
+ .long 28
+ .long 30
+ .long 41
+ .long 44
+ .long 47
+ .long 55
+ .long 57
+ .long 62
+ .long 65
+ .long 71
+ .long 179
+ .section .debug_info.dwo,"e",@progbits
+ .long .Ldebug_info_dwo_end2-.Ldebug_info_dwo_start2 # Length of Unit
+.Ldebug_info_dwo_start2:
+ .short 5 # DWARF version number
+ .byte 5 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long 0 # Offset Into Abbrev. Section
+ .quad 2142419470755914572
+ .byte 6 # Abbrev [6] 0x14:0x4f DW_TAG_compile_unit
+ .byte 14 # DW_AT_producer
+ .short 33 # DW_AT_language
+ .byte 15 # DW_AT_name
+ .byte 6 # DW_AT_dwo_name
+ .byte 7 # Abbrev [7] 0x1a:0xb DW_TAG_variable
+ .byte 0 # DW_AT_name
+ .long 37 # DW_AT_type
+ # DW_AT_external
+ .byte 0 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .byte 2 # DW_AT_location
+ .byte 161
+ .byte 0
+ .byte 5 # Abbrev [5] 0x25:0x4 DW_TAG_base_type
+ .byte 1 # DW_AT_name
+ .byte 5 # DW_AT_encoding
+ .byte 4 # DW_AT_byte_size
+ .byte 8 # Abbrev [8] 0x29:0x27 DW_TAG_subprogram
+ .byte 1 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .byte 1 # DW_AT_frame_base
+ .byte 86
+ .byte 2 # DW_AT_linkage_name
+ .byte 3 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 8 # DW_AT_decl_line
+ .long 37 # DW_AT_type
+ # DW_AT_external
+ .byte 9 # Abbrev [9] 0x39:0xb DW_TAG_variable
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 112
+ .byte 4 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 9 # DW_AT_decl_line
+ .long 80 # DW_AT_type
+ .byte 9 # Abbrev [9] 0x44:0xb DW_TAG_variable
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 88
+ .byte 10 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 10 # DW_AT_decl_line
+ .long 89 # DW_AT_type
+ .byte 0 # End Of Children Mark
+ .byte 10 # Abbrev [10] 0x50:0x9 DW_TAG_structure_type
+ # DW_AT_declaration
+ .quad -3882554063269480080 # DW_AT_signature
+ .byte 10 # Abbrev [10] 0x59:0x9 DW_TAG_structure_type
+ # DW_AT_declaration
+ .quad 1175092228111723119 # DW_AT_signature
+ .byte 0 # End Of Children Mark
+.Ldebug_info_dwo_end2:
+ .section .debug_abbrev.dwo,"e",@progbits
+ .byte 1 # Abbreviation Code
+ .byte 65 # DW_TAG_type_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 27 # DW_AT_comp_dir
+ .byte 37 # DW_FORM_strx1
+ .byte 118 # DW_AT_dwo_name
+ .byte 37 # DW_FORM_strx1
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 2 # Abbreviation Code
+ .byte 19 # DW_TAG_structure_type
+ .byte 1 # DW_CHILDREN_yes
+ .byte 54 # DW_AT_calling_convention
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 3 # Abbreviation Code
+ .byte 13 # DW_TAG_member
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 56 # DW_AT_data_member_location
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 4 # Abbreviation Code
+ .byte 15 # DW_TAG_pointer_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 5 # Abbreviation Code
+ .byte 36 # DW_TAG_base_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 62 # DW_AT_encoding
+ .byte 11 # DW_FORM_data1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 6 # Abbreviation Code
+ .byte 17 # DW_TAG_compile_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 37 # DW_AT_producer
+ .byte 37 # DW_FORM_strx1
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 118 # DW_AT_dwo_name
+ .byte 37 # DW_FORM_strx1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 7 # Abbreviation Code
+ .byte 52 # DW_TAG_variable
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 63 # DW_AT_external
+ .byte 25 # DW_FORM_flag_present
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 2 # DW_AT_location
+ .byte 24 # DW_FORM_exprloc
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 8 # Abbreviation Code
+ .byte 46 # DW_TAG_subprogram
+ .byte 1 # DW_CHILDREN_yes
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 64 # DW_AT_frame_base
+ .byte 24 # DW_FORM_exprloc
+ .byte 110 # DW_AT_linkage_name
+ .byte 37 # DW_FORM_strx1
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 63 # DW_AT_external
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 9 # Abbreviation Code
+ .byte 52 # DW_TAG_variable
+ .byte 0 # DW_CHILDREN_no
+ .byte 2 # DW_AT_location
+ .byte 24 # DW_FORM_exprloc
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 10 # Abbreviation Code
+ .byte 19 # DW_TAG_structure_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 60 # DW_AT_declaration
+ .byte 25 # DW_FORM_flag_present
+ .byte 105 # DW_AT_signature
+ .byte 32 # DW_FORM_ref_sig8
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_line.dwo,"e",@progbits
+.Ltmp2:
+ .long .Ldebug_line_end0-.Ldebug_line_start0 # unit length
+.Ldebug_line_start0:
+ .short 5
+ .byte 8
+ .byte 0
+ .long .Lprologue_end0-.Lprologue_start0
+.Lprologue_start0:
+ .byte 1
+ .byte 1
+ .byte 1
+ .byte -5
+ .byte 14
+ .byte 1
+ .byte 1
+ .byte 1
+ .byte 8
+ .byte 2
+ .byte 46
+ .byte 0
+ .byte 46
+ .byte 0
+ .byte 3
+ .byte 1
+ .byte 8
+ .byte 2
+ .byte 15
+ .byte 5
+ .byte 30
+ .byte 2
+ .ascii "helper.cpp"
+ .byte 0
+ .byte 0
+ .byte 0xc3, 0x31, 0x86, 0xb2
+ .byte 0xdb, 0x66, 0xa7, 0x88
+ .byte 0x83, 0xb1, 0x54, 0x6a
+ .byte 0xac, 0xe9, 0x85, 0x5d
+ .ascii "header.h"
+ .byte 0
+ .byte 1
+ .byte 0xfe, 0xa7, 0xbb, 0x1f
+ .byte 0x22, 0xc4, 0x7f, 0x12
+ .byte 0x9e, 0x15, 0x69, 0x5f
+ .byte 0x71, 0x37, 0xa1, 0xe7
+.Lprologue_end0:
+.Ldebug_line_end0:
+ .section .debug_addr,"",@progbits
+ .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution
+.Ldebug_addr_start0:
+ .short 5 # DWARF version number
+ .byte 8 # Address size
+ .byte 0 # Segment selector size
+.Laddr_table_base0:
+ .quad fooint
+ .quad .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"",@progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 2 # Header: foreign type unit count
+ .long 7 # Header: bucket count
+ .long 7 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .quad -3882554063269480080 # Type unit 0
+ .quad 1175092228111723119 # Type unit 1
+ .long 1 # Bucket 0
+ .long 0 # Bucket 1
+ .long 2 # Bucket 2
+ .long 3 # Bucket 3
+ .long 0 # Bucket 4
+ .long 5 # Bucket 5
+ .long 7 # Bucket 6
+ .long -1257882357 # Hash in Bucket 0
+ .long -1168750522 # Hash in Bucket 2
+ .long 193495088 # Hash in Bucket 3
+ .long 259227804 # Hash in Bucket 3
+ .long 193491849 # Hash in Bucket 5
+ .long 2090147939 # Hash in Bucket 5
+ .long -35356620 # Hash in Bucket 6
+ .long .Lskel_string4 # String in Bucket 0: _Z3foov
+ .long .Lskel_string5 # String in Bucket 2: Foo2Int
+ .long .Lskel_string1 # String in Bucket 3: int
+ .long .Lskel_string6 # String in Bucket 3: Foo2a
+ .long .Lskel_string3 # String in Bucket 5: foo
+ .long .Lskel_string7 # String in Bucket 5: char
+ .long .Lskel_string2 # String in Bucket 6: fooint
+ .long .Lnames3-.Lnames_entries0 # Offset in Bucket 0
+ .long .Lnames4-.Lnames_entries0 # Offset in Bucket 2
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 3
+ .long .Lnames5-.Lnames_entries0 # Offset in Bucket 3
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 5
+ .long .Lnames6-.Lnames_entries0 # Offset in Bucket 5
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 6
+.Lnames_abbrev_start0:
+ .ascii "\350\004" # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\354\004" # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 2 # DW_IDX_type_unit
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\310\013" # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\210\t" # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\210\r" # Abbrev code
+ .byte 52 # DW_TAG_variable
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\214\t" # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 2 # DW_IDX_type_unit
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames3:
+ .ascii "\310\013" # Abbreviation code
+ .long 41 # DW_IDX_die_offset
+ .byte 0 # End of list: _Z3foov
+.Lnames4:
+ .ascii "\354\004" # Abbreviation code
+ .byte 0 # DW_IDX_type_unit
+ .long 33 # DW_IDX_die_offset
+ .ascii "\350\004" # Abbreviation code
+ .long 80 # DW_IDX_die_offset
+ .byte 0 # End of list: Foo2Int
+.Lnames0:
+ .ascii "\210\t" # Abbreviation code
+ .long 37 # DW_IDX_die_offset
+ .ascii "\214\t" # Abbreviation code
+ .byte 0 # DW_IDX_type_unit
+ .long 63 # DW_IDX_die_offset
+ .byte 0 # End of list: int
+.Lnames5:
+ .ascii "\354\004" # Abbreviation code
+ .byte 1 # DW_IDX_type_unit
+ .long 33 # DW_IDX_die_offset
+ .ascii "\350\004" # Abbreviation code
+ .long 89 # DW_IDX_die_offset
+ .byte 0 # End of list: Foo2a
+.Lnames2:
+ .ascii "\310\013" # Abbreviation code
+ .long 41 # DW_IDX_die_offset
+ .byte 0 # End of list: foo
+.Lnames6:
+ .ascii "\214\t" # Abbreviation code
+ .byte 1 # DW_IDX_type_unit
+ .long 72 # DW_IDX_die_offset
+ .byte 0 # End of list: char
+.Lnames1:
+ .ascii "\210\r" # Abbreviation code
+ .long 26 # DW_IDX_die_offset
+ .byte 0 # End of list: fooint
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 18.0.0git (git@github.com:ayermolo/llvm-project.git db35fa8fc524127079662802c4735dbf397f86d0)"
+ .section ".note.GNU-stack","",@progbits
+ .addrsig
+ .section .debug_line,"",@progbits
+.Lline_table_start0:
bolt/test/X86/Inputs/dwarf5-df-types-debug-names-main.s
@@ -0,0 +1,626 @@
+# clang++ -gsplit-dwarf -g2 -gdwarf-5 -gpubnames -fdebug-types-section -fdebug-compilation-dir='.' -S
+# header.h
+# struct Foo2a {
+# char *c1;
+# char *c2;
+# char *c3;
+# };
+# include "header.h"
+# struct Foo2 {
+# char *c1;
+# };
+# int main(int argc, char *argv[]) {
+# Foo2 f2;
+# Foo2a f3;
+# return 0;
+# }
+
+ .text
+ .file "main.cpp"
+ .globl main # -- Begin function main
+ .p2align 4, 0x90
+ .type main,@function
+main: # @main
+.Lfunc_begin0:
+ .file 0 "." "main.cpp" md5 0x9c5cea5bb78d3fc265cd175110bfe903
+ .loc 0 5 0 # main.cpp:5:0
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+ movl $0, -4(%rbp)
+ movl %edi, -8(%rbp)
+ movq %rsi, -16(%rbp)
+.Ltmp0:
+ .loc 0 8 2 prologue_end # main.cpp:8:2
+ xorl %eax, %eax
+ .loc 0 8 2 epilogue_begin is_stmt 0 # main.cpp:8:2
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size main, .Lfunc_end0-main
+ .cfi_endproc
+ # -- End function
+ .section .debug_info.dwo,"e",@progbits
+ .long .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit
+.Ldebug_info_dwo_start0:
+ .short 5 # DWARF version number
+ .byte 6 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long 0 # Offset Into Abbrev. Section
+ .quad 5322170643381124694 # Type Signature
+ .long 33 # Type DIE Offset
+ .byte 1 # Abbrev [1] 0x18:0x23 DW_TAG_type_unit
+ .short 33 # DW_AT_language
+ .byte 6 # DW_AT_comp_dir
+ .byte 7 # DW_AT_dwo_name
+ .long 0 # DW_AT_stmt_list
+ .byte 2 # Abbrev [2] 0x21:0x10 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 9 # DW_AT_name
+ .byte 8 # DW_AT_byte_size
+ .byte 0 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .byte 3 # Abbrev [3] 0x27:0x9 DW_TAG_member
+ .byte 8 # DW_AT_name
+ .long 49 # DW_AT_type
+ .byte 0 # DW_AT_decl_file
+ .byte 3 # DW_AT_decl_line
+ .byte 0 # DW_AT_data_member_location
+ .byte 0 # End Of Children Mark
+ .byte 4 # Abbrev [4] 0x31:0x5 DW_TAG_pointer_type
+ .long 54 # DW_AT_type
+ .byte 5 # Abbrev [5] 0x36:0x4 DW_TAG_base_type
+ .byte 4 # DW_AT_name
+ .byte 6 # DW_AT_encoding
+ .byte 1 # DW_AT_byte_size
+ .byte 0 # End Of Children Mark
+.Ldebug_info_dwo_end0:
+ .long .Ldebug_info_dwo_end1-.Ldebug_info_dwo_start1 # Length of Unit
+.Ldebug_info_dwo_start1:
+ .short 5 # DWARF version number
+ .byte 6 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long 0 # Offset Into Abbrev. Section
+ .quad 1175092228111723119 # Type Signature
+ .long 33 # Type DIE Offset
+ .byte 1 # Abbrev [1] 0x18:0x35 DW_TAG_type_unit
+ .short 33 # DW_AT_language
+ .byte 6 # DW_AT_comp_dir
+ .byte 7 # DW_AT_dwo_name
+ .long 0 # DW_AT_stmt_list
+ .byte 2 # Abbrev [2] 0x21:0x22 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 13 # DW_AT_name
+ .byte 24 # DW_AT_byte_size
+ .byte 1 # DW_AT_decl_file
+ .byte 1 # DW_AT_decl_line
+ .byte 3 # Abbrev [3] 0x27:0x9 DW_TAG_member
+ .byte 8 # DW_AT_name
+ .long 67 # DW_AT_type
+ .byte 1 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .byte 0 # DW_AT_data_member_location
+ .byte 3 # Abbrev [3] 0x30:0x9 DW_TAG_member
+ .byte 11 # DW_AT_name
+ .long 67 # DW_AT_type
+ .byte 1 # DW_AT_decl_file
+ .byte 3 # DW_AT_decl_line
+ .byte 8 # DW_AT_data_member_location
+ .byte 3 # Abbrev [3] 0x39:0x9 DW_TAG_member
+ .byte 12 # DW_AT_name
+ .long 67 # DW_AT_type
+ .byte 1 # DW_AT_decl_file
+ .byte 4 # DW_AT_decl_line
+ .byte 16 # DW_AT_data_member_location
+ .byte 0 # End Of Children Mark
+ .byte 4 # Abbrev [4] 0x43:0x5 DW_TAG_pointer_type
+ .long 72 # DW_AT_type
+ .byte 5 # Abbrev [5] 0x48:0x4 DW_TAG_base_type
+ .byte 4 # DW_AT_name
+ .byte 6 # DW_AT_encoding
+ .byte 1 # DW_AT_byte_size
+ .byte 0 # End Of Children Mark
+.Ldebug_info_dwo_end1:
+ .section .debug_abbrev,"",@progbits
+ .byte 1 # Abbreviation Code
+ .byte 74 # DW_TAG_skeleton_unit
+ .byte 0 # DW_CHILDREN_no
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 114 # DW_AT_str_offsets_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 27 # DW_AT_comp_dir
+ .byte 37 # DW_FORM_strx1
+ .byte 118 # DW_AT_dwo_name
+ .byte 37 # DW_FORM_strx1
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 115 # DW_AT_addr_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"",@progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 4 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .quad 5962099678818150071
+ .byte 1 # Abbrev [1] 0x14:0x14 DW_TAG_skeleton_unit
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .byte 0 # DW_AT_comp_dir
+ .byte 1 # DW_AT_dwo_name
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .long .Laddr_table_base0 # DW_AT_addr_base
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"",@progbits
+ .long 12 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS",@progbits,1
+.Lskel_string0:
+ .asciz "." # string offset=0
+.Lskel_string1:
+ .asciz "main" # string offset=53
+.Lskel_string2:
+ .asciz "int" # string offset=58
+.Lskel_string3:
+ .asciz "char" # string offset=62
+.Lskel_string4:
+ .asciz "Foo2" # string offset=67
+.Lskel_string5:
+ .asciz "Foo2a" # string offset=72
+.Lskel_string6:
+ .asciz "main.dwo" # string offset=78
+ .section .debug_str_offsets,"",@progbits
+ .long .Lskel_string0
+ .long .Lskel_string6
+ .section .debug_str_offsets.dwo,"e",@progbits
+ .long 68 # Length of String Offsets Set
+ .short 5
+ .short 0
+ .section .debug_str.dwo,"eMS",@progbits,1
+.Linfo_string0:
+ .asciz "main" # string offset=0
+.Linfo_string1:
+ .asciz "int" # string offset=5
+.Linfo_string2:
+ .asciz "argc" # string offset=9
+.Linfo_string3:
+ .asciz "argv" # string offset=14
+.Linfo_string4:
+ .asciz "char" # string offset=19
+.Linfo_string5:
+ .asciz "f2" # string offset=24
+.Linfo_string6:
+ .asciz "/home/ayermolo/local/tasks/T138552329/typeDedupSplit" # string offset=27
+.Linfo_string7:
+ .asciz "main.dwo" # string offset=80
+.Linfo_string8:
+ .asciz "c1" # string offset=89
+.Linfo_string9:
+ .asciz "Foo2" # string offset=92
+.Linfo_string10:
+ .asciz "f3" # string offset=97
+.Linfo_string11:
+ .asciz "c2" # string offset=100
+.Linfo_string12:
+ .asciz "c3" # string offset=103
+.Linfo_string13:
+ .asciz "Foo2a" # string offset=106
+.Linfo_string14:
+ .asciz "clang version 18.0.0git (git@github.com:ayermolo/llvm-project.git db35fa8fc524127079662802c4735dbf397f86d0)" # string offset=112
+.Linfo_string15:
+ .asciz "main.cpp" # string offset=220
+ .section .debug_str_offsets.dwo,"e",@progbits
+ .long 0
+ .long 5
+ .long 9
+ .long 14
+ .long 19
+ .long 24
+ .long 27
+ .long 80
+ .long 89
+ .long 92
+ .long 97
+ .long 100
+ .long 103
+ .long 106
+ .long 112
+ .long 220
+ .section .debug_info.dwo,"e",@progbits
+ .long .Ldebug_info_dwo_end2-.Ldebug_info_dwo_start2 # Length of Unit
+.Ldebug_info_dwo_start2:
+ .short 5 # DWARF version number
+ .byte 5 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long 0 # Offset Into Abbrev. Section
+ .quad 5962099678818150071
+ .byte 6 # Abbrev [6] 0x14:0x67 DW_TAG_compile_unit
+ .byte 14 # DW_AT_producer
+ .short 33 # DW_AT_language
+ .byte 15 # DW_AT_name
+ .byte 7 # DW_AT_dwo_name
+ .byte 7 # Abbrev [7] 0x1a:0x3c DW_TAG_subprogram
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .byte 1 # DW_AT_frame_base
+ .byte 86
+ .byte 0 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 5 # DW_AT_decl_line
+ .long 86 # DW_AT_type
+ # DW_AT_external
+ .byte 8 # Abbrev [8] 0x29:0xb DW_TAG_formal_parameter
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 120
+ .byte 2 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 5 # DW_AT_decl_line
+ .long 86 # DW_AT_type
+ .byte 8 # Abbrev [8] 0x34:0xb DW_TAG_formal_parameter
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 112
+ .byte 3 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 5 # DW_AT_decl_line
+ .long 90 # DW_AT_type
+ .byte 9 # Abbrev [9] 0x3f:0xb DW_TAG_variable
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 104
+ .byte 5 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 6 # DW_AT_decl_line
+ .long 104 # DW_AT_type
+ .byte 9 # Abbrev [9] 0x4a:0xb DW_TAG_variable
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 80
+ .byte 10 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 7 # DW_AT_decl_line
+ .long 113 # DW_AT_type
+ .byte 0 # End Of Children Mark
+ .byte 5 # Abbrev [5] 0x56:0x4 DW_TAG_base_type
+ .byte 1 # DW_AT_name
+ .byte 5 # DW_AT_encoding
+ .byte 4 # DW_AT_byte_size
+ .byte 4 # Abbrev [4] 0x5a:0x5 DW_TAG_pointer_type
+ .long 95 # DW_AT_type
+ .byte 4 # Abbrev [4] 0x5f:0x5 DW_TAG_pointer_type
+ .long 100 # DW_AT_type
+ .byte 5 # Abbrev [5] 0x64:0x4 DW_TAG_base_type
+ .byte 4 # DW_AT_name
+ .byte 6 # DW_AT_encoding
+ .byte 1 # DW_AT_byte_size
+ .byte 10 # Abbrev [10] 0x68:0x9 DW_TAG_structure_type
+ # DW_AT_declaration
+ .quad 5322170643381124694 # DW_AT_signature
+ .byte 10 # Abbrev [10] 0x71:0x9 DW_TAG_structure_type
+ # DW_AT_declaration
+ .quad 1175092228111723119 # DW_AT_signature
+ .byte 0 # End Of Children Mark
+.Ldebug_info_dwo_end2:
+ .section .debug_abbrev.dwo,"e",@progbits
+ .byte 1 # Abbreviation Code
+ .byte 65 # DW_TAG_type_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 27 # DW_AT_comp_dir
+ .byte 37 # DW_FORM_strx1
+ .byte 118 # DW_AT_dwo_name
+ .byte 37 # DW_FORM_strx1
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 2 # Abbreviation Code
+ .byte 19 # DW_TAG_structure_type
+ .byte 1 # DW_CHILDREN_yes
+ .byte 54 # DW_AT_calling_convention
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 3 # Abbreviation Code
+ .byte 13 # DW_TAG_member
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 56 # DW_AT_data_member_location
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 4 # Abbreviation Code
+ .byte 15 # DW_TAG_pointer_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 5 # Abbreviation Code
+ .byte 36 # DW_TAG_base_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 62 # DW_AT_encoding
+ .byte 11 # DW_FORM_data1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 6 # Abbreviation Code
+ .byte 17 # DW_TAG_compile_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 37 # DW_AT_producer
+ .byte 37 # DW_FORM_strx1
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 118 # DW_AT_dwo_name
+ .byte 37 # DW_FORM_strx1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 7 # Abbreviation Code
+ .byte 46 # DW_TAG_subprogram
+ .byte 1 # DW_CHILDREN_yes
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 64 # DW_AT_frame_base
+ .byte 24 # DW_FORM_exprloc
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 63 # DW_AT_external
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 8 # Abbreviation Code
+ .byte 5 # DW_TAG_formal_parameter
+ .byte 0 # DW_CHILDREN_no
+ .byte 2 # DW_AT_location
+ .byte 24 # DW_FORM_exprloc
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 9 # Abbreviation Code
+ .byte 52 # DW_TAG_variable
+ .byte 0 # DW_CHILDREN_no
+ .byte 2 # DW_AT_location
+ .byte 24 # DW_FORM_exprloc
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 10 # Abbreviation Code
+ .byte 19 # DW_TAG_structure_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 60 # DW_AT_declaration
+ .byte 25 # DW_FORM_flag_present
+ .byte 105 # DW_AT_signature
+ .byte 32 # DW_FORM_ref_sig8
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_line.dwo,"e",@progbits
+.Ltmp2:
+ .long .Ldebug_line_end0-.Ldebug_line_start0 # unit length
+.Ldebug_line_start0:
+ .short 5
+ .byte 8
+ .byte 0
+ .long .Lprologue_end0-.Lprologue_start0
+.Lprologue_start0:
+ .byte 1
+ .byte 1
+ .byte 1
+ .byte -5
+ .byte 14
+ .byte 1
+ .byte 1
+ .byte 1
+ .byte 8
+ .byte 2
+ .ascii "/home/ayermolo/local/tasks/T138552329/typeDedupSplit"
+ .byte 0
+ .byte 46
+ .byte 0
+ .byte 3
+ .byte 1
+ .byte 8
+ .byte 2
+ .byte 15
+ .byte 5
+ .byte 30
+ .byte 2
+ .ascii "main.cpp"
+ .byte 0
+ .byte 0
+ .byte 0x9c, 0x5c, 0xea, 0x5b
+ .byte 0xb7, 0x8d, 0x3f, 0xc2
+ .byte 0x65, 0xcd, 0x17, 0x51
+ .byte 0x10, 0xbf, 0xe9, 0x03
+ .ascii "header.h"
+ .byte 0
+ .byte 1
+ .byte 0xfe, 0xa7, 0xbb, 0x1f
+ .byte 0x22, 0xc4, 0x7f, 0x12
+ .byte 0x9e, 0x15, 0x69, 0x5f
+ .byte 0x71, 0x37, 0xa1, 0xe7
+.Lprologue_end0:
+.Ldebug_line_end0:
+ .section .debug_addr,"",@progbits
+ .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution
+.Ldebug_addr_start0:
+ .short 5 # DWARF version number
+ .byte 8 # Address size
+ .byte 0 # Segment selector size
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"",@progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 0 # Header: local type unit count
+ .long 2 # Header: foreign type unit count
+ .long 5 # Header: bucket count
+ .long 5 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .quad 5322170643381124694 # Type unit 0
+ .quad 1175092228111723119 # Type unit 1
+ .long 0 # Bucket 0
+ .long 1 # Bucket 1
+ .long 0 # Bucket 2
+ .long 3 # Bucket 3
+ .long 4 # Bucket 4
+ .long 2090263771 # Hash in Bucket 1
+ .long 2090499946 # Hash in Bucket 1
+ .long 193495088 # Hash in Bucket 3
+ .long 259227804 # Hash in Bucket 4
+ .long 2090147939 # Hash in Bucket 4
+ .long .Lskel_string4 # String in Bucket 1: Foo2
+ .long .Lskel_string1 # String in Bucket 1: main
+ .long .Lskel_string2 # String in Bucket 3: int
+ .long .Lskel_string5 # String in Bucket 4: Foo2a
+ .long .Lskel_string3 # String in Bucket 4: char
+ .long .Lnames3-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 1
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 3
+ .long .Lnames4-.Lnames_entries0 # Offset in Bucket 4
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 4
+.Lnames_abbrev_start0:
+ .ascii "\350\004" # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\354\004" # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 2 # DW_IDX_type_unit
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\310\013" # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\210\t" # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\214\t" # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 2 # DW_IDX_type_unit
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames3:
+ .ascii "\354\004" # Abbreviation code
+ .byte 0 # DW_IDX_type_unit
+ .long 33 # DW_IDX_die_offset
+ .ascii "\350\004" # Abbreviation code
+ .long 104 # DW_IDX_die_offset
+ .byte 0 # End of list: Foo2
+.Lnames0:
+ .ascii "\310\013" # Abbreviation code
+ .long 26 # DW_IDX_die_offset
+ .byte 0 # End of list: main
+.Lnames1:
+ .ascii "\210\t" # Abbreviation code
+ .long 86 # DW_IDX_die_offset
+ .byte 0 # End of list: int
+.Lnames4:
+ .ascii "\354\004" # Abbreviation code
+ .byte 1 # DW_IDX_type_unit
+ .long 33 # DW_IDX_die_offset
+ .ascii "\350\004" # Abbreviation code
+ .long 113 # DW_IDX_die_offset
+ .byte 0 # End of list: Foo2a
+.Lnames2:
+ .ascii "\214\t" # Abbreviation code
+ .byte 0 # DW_IDX_type_unit
+ .long 54 # DW_IDX_die_offset
+ .ascii "\214\t" # Abbreviation code
+ .byte 1 # DW_IDX_type_unit
+ .long 72 # DW_IDX_die_offset
+ .ascii "\210\t" # Abbreviation code
+ .long 100 # DW_IDX_die_offset
+ .byte 0 # End of list: char
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 18.0.0git (git@github.com:ayermolo/llvm-project.git db35fa8fc524127079662802c4735dbf397f86d0)"
+ .section ".note.GNU-stack","",@progbits
+ .addrsig
+ .section .debug_line,"",@progbits
+.Lline_table_start0:
bolt/test/X86/Inputs/dwarf5-types-debug-names-helper.s
@@ -0,0 +1,405 @@
+# clang++ helper.cpp -g2 -gdwarf-5 -gpubnames -fdebug-types-section
+# header.h
+# struct Foo2a {
+# char *c1;
+# };
+# helper.cpp
+# #include "header.h"
+# int foo() {
+# Foo2a f;
+# return 0;
+# }
+
+
+ .text
+ .file "helper.cpp"
+ .globl _Z3foov # -- Begin function _Z3foov
+ .p2align 4, 0x90
+ .type _Z3foov,@function
+_Z3foov: # @_Z3foov
+.Lfunc_begin0:
+ .file 0 "/typeDedupSmall" "helper.cpp" md5 0x305ec66c221c583021f8375b300e2591
+ .loc 0 2 0 # helper.cpp:2:0
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+.Ltmp0:
+ .loc 0 4 3 prologue_end # helper.cpp:4:3
+ xorl %eax, %eax
+ .loc 0 4 3 epilogue_begin is_stmt 0 # helper.cpp:4:3
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size _Z3foov, .Lfunc_end0-_Z3foov
+ .cfi_endproc
+ # -- End function
+ .file 1 "." "header.h" md5 0x53699580704254cb1dd2a83230f8a7ea
+ .section .debug_info,"G",@progbits,1175092228111723119,comdat
+.Ltu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 2 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .quad 1175092228111723119 # Type Signature
+ .long 35 # Type DIE Offset
+ .byte 1 # Abbrev [1] 0x18:0x25 DW_TAG_type_unit
+ .short 33 # DW_AT_language
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .byte 2 # Abbrev [2] 0x23:0x10 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 9 # DW_AT_name
+ .byte 8 # DW_AT_byte_size
+ .byte 1 # DW_AT_decl_file
+ .byte 1 # DW_AT_decl_line
+ .byte 3 # Abbrev [3] 0x29:0x9 DW_TAG_member
+ .byte 7 # DW_AT_name
+ .long 51 # DW_AT_type
+ .byte 1 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .byte 0 # DW_AT_data_member_location
+ .byte 0 # End Of Children Mark
+ .byte 4 # Abbrev [4] 0x33:0x5 DW_TAG_pointer_type
+ .long 56 # DW_AT_type
+ .byte 5 # Abbrev [5] 0x38:0x4 DW_TAG_base_type
+ .byte 8 # DW_AT_name
+ .byte 6 # DW_AT_encoding
+ .byte 1 # DW_AT_byte_size
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end0:
+ .section .debug_abbrev,"",@progbits
+ .byte 1 # Abbreviation Code
+ .byte 65 # DW_TAG_type_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 114 # DW_AT_str_offsets_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 2 # Abbreviation Code
+ .byte 19 # DW_TAG_structure_type
+ .byte 1 # DW_CHILDREN_yes
+ .byte 54 # DW_AT_calling_convention
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 3 # Abbreviation Code
+ .byte 13 # DW_TAG_member
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 56 # DW_AT_data_member_location
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 4 # Abbreviation Code
+ .byte 15 # DW_TAG_pointer_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 5 # Abbreviation Code
+ .byte 36 # DW_TAG_base_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 62 # DW_AT_encoding
+ .byte 11 # DW_FORM_data1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 6 # Abbreviation Code
+ .byte 17 # DW_TAG_compile_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 37 # DW_AT_producer
+ .byte 37 # DW_FORM_strx1
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 114 # DW_AT_str_offsets_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 27 # DW_AT_comp_dir
+ .byte 37 # DW_FORM_strx1
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 115 # DW_AT_addr_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 7 # Abbreviation Code
+ .byte 46 # DW_TAG_subprogram
+ .byte 1 # DW_CHILDREN_yes
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 64 # DW_AT_frame_base
+ .byte 24 # DW_FORM_exprloc
+ .byte 110 # DW_AT_linkage_name
+ .byte 37 # DW_FORM_strx1
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 63 # DW_AT_external
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 8 # Abbreviation Code
+ .byte 52 # DW_TAG_variable
+ .byte 0 # DW_CHILDREN_no
+ .byte 2 # DW_AT_location
+ .byte 24 # DW_FORM_exprloc
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 9 # Abbreviation Code
+ .byte 19 # DW_TAG_structure_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 60 # DW_AT_declaration
+ .byte 25 # DW_FORM_flag_present
+ .byte 105 # DW_AT_signature
+ .byte 32 # DW_FORM_ref_sig8
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"",@progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end1-.Ldebug_info_start1 # Length of Unit
+.Ldebug_info_start1:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .byte 6 # Abbrev [6] 0xc:0x41 DW_TAG_compile_unit
+ .byte 0 # DW_AT_producer
+ .short 33 # DW_AT_language
+ .byte 1 # DW_AT_name
+ .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .byte 2 # DW_AT_comp_dir
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .long .Laddr_table_base0 # DW_AT_addr_base
+ .byte 7 # Abbrev [7] 0x23:0x1c DW_TAG_subprogram
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .byte 1 # DW_AT_frame_base
+ .byte 86
+ .byte 3 # DW_AT_linkage_name
+ .byte 4 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .long 63 # DW_AT_type
+ # DW_AT_external
+ .byte 8 # Abbrev [8] 0x33:0xb DW_TAG_variable
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 120
+ .byte 6 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 3 # DW_AT_decl_line
+ .long 67 # DW_AT_type
+ .byte 0 # End Of Children Mark
+ .byte 5 # Abbrev [5] 0x3f:0x4 DW_TAG_base_type
+ .byte 5 # DW_AT_name
+ .byte 5 # DW_AT_encoding
+ .byte 4 # DW_AT_byte_size
+ .byte 9 # Abbrev [9] 0x43:0x9 DW_TAG_structure_type
+ # DW_AT_declaration
+ .quad 1175092228111723119 # DW_AT_signature
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end1:
+ .section .debug_str_offsets,"",@progbits
+ .long 44 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS",@progbits,1
+.Linfo_string0:
+ .asciz "clang version 18.0.0git (git@github.com:ayermolo/llvm-project.git db35fa8fc524127079662802c4735dbf397f86d0)" # string offset=0
+.Linfo_string1:
+ .asciz "helper.cpp" # string offset=108
+.Linfo_string2:
+ .asciz "/home/typeDedupSmall" # string offset=119
+.Linfo_string3:
+ .asciz "foo" # string offset=172
+.Linfo_string4:
+ .asciz "_Z3foov" # string offset=176
+.Linfo_string5:
+ .asciz "int" # string offset=184
+.Linfo_string6:
+ .asciz "f" # string offset=188
+.Linfo_string7:
+ .asciz "Foo2a" # string offset=190
+.Linfo_string8:
+ .asciz "c1" # string offset=196
+.Linfo_string9:
+ .asciz "char" # string offset=199
+ .section .debug_str_offsets,"",@progbits
+ .long .Linfo_string0
+ .long .Linfo_string1
+ .long .Linfo_string2
+ .long .Linfo_string4
+ .long .Linfo_string3
+ .long .Linfo_string5
+ .long .Linfo_string6
+ .long .Linfo_string8
+ .long .Linfo_string9
+ .long .Linfo_string7
+ .section .debug_addr,"",@progbits
+ .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution
+.Ldebug_addr_start0:
+ .short 5 # DWARF version number
+ .byte 8 # Address size
+ .byte 0 # Segment selector size
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"",@progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 1 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 5 # Header: bucket count
+ .long 5 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long .Ltu_begin0 # Type unit 0
+ .long 0 # Bucket 0
+ .long 0 # Bucket 1
+ .long 0 # Bucket 2
+ .long 1 # Bucket 3
+ .long 2 # Bucket 4
+ .long 193495088 # Hash in Bucket 3
+ .long 193491849 # Hash in Bucket 4
+ .long 259227804 # Hash in Bucket 4
+ .long 2090147939 # Hash in Bucket 4
+ .long -1257882357 # Hash in Bucket 4
+ .long .Linfo_string5 # String in Bucket 3: int
+ .long .Linfo_string3 # String in Bucket 4: foo
+ .long .Linfo_string7 # String in Bucket 4: Foo2a
+ .long .Linfo_string9 # String in Bucket 4: char
+ .long .Linfo_string4 # String in Bucket 4: _Z3foov
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 3
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 4
+ .long .Lnames3-.Lnames_entries0 # Offset in Bucket 4
+ .long .Lnames4-.Lnames_entries0 # Offset in Bucket 4
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 4
+.Lnames_abbrev_start0:
+ .ascii "\350\004" # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\354\004" # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 2 # DW_IDX_type_unit
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\210\t" # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\310\013" # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\214\t" # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 2 # DW_IDX_type_unit
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames2:
+ .ascii "\210\t" # Abbreviation code
+ .long 63 # DW_IDX_die_offset
+ .byte 0 # End of list: int
+.Lnames0:
+ .ascii "\310\013" # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # End of list: foo
+.Lnames3:
+ .ascii "\354\004" # Abbreviation code
+ .byte 0 # DW_IDX_type_unit
+ .long 35 # DW_IDX_die_offset
+ .ascii "\350\004" # Abbreviation code
+ .long 67 # DW_IDX_die_offset
+ .byte 0 # End of list: Foo2a
+.Lnames4:
+ .ascii "\214\t" # Abbreviation code
+ .byte 0 # DW_IDX_type_unit
+ .long 56 # DW_IDX_die_offset
+ .byte 0 # End of list: char
+.Lnames1:
+ .ascii "\310\013" # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # End of list: _Z3foov
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 18.0.0git (git@github.com:ayermolo/llvm-project.git db35fa8fc524127079662802c4735dbf397f86d0)"
+ .section ".note.GNU-stack","",@progbits
+ .addrsig
+ .section .debug_line,"",@progbits
+.Lline_table_start0:
bolt/test/X86/Inputs/dwarf5-types-debug-names-main.s
@@ -0,0 +1,391 @@
+# clang++ -g2 -gdwarf-5 -gpubnames -fdebug-types-section
+# header.h
+# struct Foo2a {
+# char *c1;
+# };
+# main.cpp
+# #include "header.h"
+# int main() {
+# Foo2a f3;
+# return 0;
+# }
+
+ .text
+ .file "main.cpp"
+ .globl main # -- Begin function main
+ .p2align 4, 0x90
+ .type main,@function
+main: # @main
+.Lfunc_begin0:
+ .file 0 "/typeDedupSmall" "main.cpp" md5 0x6e787b94dac2f817bb35cfde8006dc82
+ .loc 0 2 0 # main.cpp:2:0
+ .cfi_startproc
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+ movl $0, -4(%rbp)
+.Ltmp0:
+ .loc 0 4 2 prologue_end # main.cpp:4:2
+ xorl %eax, %eax
+ .loc 0 4 2 epilogue_begin is_stmt 0 # main.cpp:4:2
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size main, .Lfunc_end0-main
+ .cfi_endproc
+ # -- End function
+ .file 1 "." "header.h" md5 0x53699580704254cb1dd2a83230f8a7ea
+ .section .debug_info,"G",@progbits,1175092228111723119,comdat
+.Ltu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 2 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .quad 1175092228111723119 # Type Signature
+ .long 35 # Type DIE Offset
+ .byte 1 # Abbrev [1] 0x18:0x25 DW_TAG_type_unit
+ .short 33 # DW_AT_language
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .byte 2 # Abbrev [2] 0x23:0x10 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 8 # DW_AT_name
+ .byte 8 # DW_AT_byte_size
+ .byte 1 # DW_AT_decl_file
+ .byte 1 # DW_AT_decl_line
+ .byte 3 # Abbrev [3] 0x29:0x9 DW_TAG_member
+ .byte 6 # DW_AT_name
+ .long 51 # DW_AT_type
+ .byte 1 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .byte 0 # DW_AT_data_member_location
+ .byte 0 # End Of Children Mark
+ .byte 4 # Abbrev [4] 0x33:0x5 DW_TAG_pointer_type
+ .long 56 # DW_AT_type
+ .byte 5 # Abbrev [5] 0x38:0x4 DW_TAG_base_type
+ .byte 7 # DW_AT_name
+ .byte 6 # DW_AT_encoding
+ .byte 1 # DW_AT_byte_size
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end0:
+ .section .debug_abbrev,"",@progbits
+ .byte 1 # Abbreviation Code
+ .byte 65 # DW_TAG_type_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 114 # DW_AT_str_offsets_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 2 # Abbreviation Code
+ .byte 19 # DW_TAG_structure_type
+ .byte 1 # DW_CHILDREN_yes
+ .byte 54 # DW_AT_calling_convention
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 3 # Abbreviation Code
+ .byte 13 # DW_TAG_member
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 56 # DW_AT_data_member_location
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 4 # Abbreviation Code
+ .byte 15 # DW_TAG_pointer_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 5 # Abbreviation Code
+ .byte 36 # DW_TAG_base_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 62 # DW_AT_encoding
+ .byte 11 # DW_FORM_data1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 6 # Abbreviation Code
+ .byte 17 # DW_TAG_compile_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 37 # DW_AT_producer
+ .byte 37 # DW_FORM_strx1
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 114 # DW_AT_str_offsets_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 27 # DW_AT_comp_dir
+ .byte 37 # DW_FORM_strx1
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 115 # DW_AT_addr_base
+ .byte 23 # DW_FORM_sec_offset
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 7 # Abbreviation Code
+ .byte 46 # DW_TAG_subprogram
+ .byte 1 # DW_CHILDREN_yes
+ .byte 17 # DW_AT_low_pc
+ .byte 27 # DW_FORM_addrx
+ .byte 18 # DW_AT_high_pc
+ .byte 6 # DW_FORM_data4
+ .byte 64 # DW_AT_frame_base
+ .byte 24 # DW_FORM_exprloc
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 63 # DW_AT_external
+ .byte 25 # DW_FORM_flag_present
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 8 # Abbreviation Code
+ .byte 52 # DW_TAG_variable
+ .byte 0 # DW_CHILDREN_no
+ .byte 2 # DW_AT_location
+ .byte 24 # DW_FORM_exprloc
+ .byte 3 # DW_AT_name
+ .byte 37 # DW_FORM_strx1
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 9 # Abbreviation Code
+ .byte 19 # DW_TAG_structure_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 60 # DW_AT_declaration
+ .byte 25 # DW_FORM_flag_present
+ .byte 105 # DW_AT_signature
+ .byte 32 # DW_FORM_ref_sig8
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"",@progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end1-.Ldebug_info_start1 # Length of Unit
+.Ldebug_info_start1:
+ .short 5 # DWARF version number
+ .byte 1 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .byte 6 # Abbrev [6] 0xc:0x40 DW_TAG_compile_unit
+ .byte 0 # DW_AT_producer
+ .short 33 # DW_AT_language
+ .byte 1 # DW_AT_name
+ .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .byte 2 # DW_AT_comp_dir
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .long .Laddr_table_base0 # DW_AT_addr_base
+ .byte 7 # Abbrev [7] 0x23:0x1b DW_TAG_subprogram
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .byte 1 # DW_AT_frame_base
+ .byte 86
+ .byte 3 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .long 62 # DW_AT_type
+ # DW_AT_external
+ .byte 8 # Abbrev [8] 0x32:0xb DW_TAG_variable
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 112
+ .byte 5 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 3 # DW_AT_decl_line
+ .long 66 # DW_AT_type
+ .byte 0 # End Of Children Mark
+ .byte 5 # Abbrev [5] 0x3e:0x4 DW_TAG_base_type
+ .byte 4 # DW_AT_name
+ .byte 5 # DW_AT_encoding
+ .byte 4 # DW_AT_byte_size
+ .byte 9 # Abbrev [9] 0x42:0x9 DW_TAG_structure_type
+ # DW_AT_declaration
+ .quad 1175092228111723119 # DW_AT_signature
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end1:
+ .section .debug_str_offsets,"",@progbits
+ .long 40 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS",@progbits,1
+.Linfo_string0:
+ .asciz "clang version 18.0.0git (git@github.com:ayermolo/llvm-project.git db35fa8fc524127079662802c4735dbf397f86d0)" # string offset=0
+.Linfo_string1:
+ .asciz "main.cpp" # string offset=108
+.Linfo_string2:
+ .asciz "/home/typeDedupSmall" # string offset=117
+.Linfo_string3:
+ .asciz "main" # string offset=170
+.Linfo_string4:
+ .asciz "int" # string offset=175
+.Linfo_string5:
+ .asciz "f3" # string offset=179
+.Linfo_string6:
+ .asciz "Foo2a" # string offset=182
+.Linfo_string7:
+ .asciz "c1" # string offset=188
+.Linfo_string8:
+ .asciz "char" # string offset=191
+ .section .debug_str_offsets,"",@progbits
+ .long .Linfo_string0
+ .long .Linfo_string1
+ .long .Linfo_string2
+ .long .Linfo_string3
+ .long .Linfo_string4
+ .long .Linfo_string5
+ .long .Linfo_string7
+ .long .Linfo_string8
+ .long .Linfo_string6
+ .section .debug_addr,"",@progbits
+ .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution
+.Ldebug_addr_start0:
+ .short 5 # DWARF version number
+ .byte 8 # Address size
+ .byte 0 # Segment selector size
+.Laddr_table_base0:
+ .quad .Lfunc_begin0
+.Ldebug_addr_end0:
+ .section .debug_names,"",@progbits
+ .long .Lnames_end0-.Lnames_start0 # Header: unit length
+.Lnames_start0:
+ .short 5 # Header: version
+ .short 0 # Header: padding
+ .long 1 # Header: compilation unit count
+ .long 1 # Header: local type unit count
+ .long 0 # Header: foreign type unit count
+ .long 4 # Header: bucket count
+ .long 4 # Header: name count
+ .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size
+ .long 8 # Header: augmentation string size
+ .ascii "LLVM0700" # Header: augmentation string
+ .long .Lcu_begin0 # Compilation unit 0
+ .long .Ltu_begin0 # Type unit 0
+ .long 1 # Bucket 0
+ .long 0 # Bucket 1
+ .long 3 # Bucket 2
+ .long 4 # Bucket 3
+ .long 193495088 # Hash in Bucket 0
+ .long 259227804 # Hash in Bucket 0
+ .long 2090499946 # Hash in Bucket 2
+ .long 2090147939 # Hash in Bucket 3
+ .long .Linfo_string4 # String in Bucket 0: int
+ .long .Linfo_string6 # String in Bucket 0: Foo2a
+ .long .Linfo_string3 # String in Bucket 2: main
+ .long .Linfo_string8 # String in Bucket 3: char
+ .long .Lnames1-.Lnames_entries0 # Offset in Bucket 0
+ .long .Lnames2-.Lnames_entries0 # Offset in Bucket 0
+ .long .Lnames0-.Lnames_entries0 # Offset in Bucket 2
+ .long .Lnames3-.Lnames_entries0 # Offset in Bucket 3
+.Lnames_abbrev_start0:
+ .ascii "\350\004" # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\354\004" # Abbrev code
+ .byte 19 # DW_TAG_structure_type
+ .byte 2 # DW_IDX_type_unit
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\210\t" # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\310\013" # Abbrev code
+ .byte 46 # DW_TAG_subprogram
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .ascii "\214\t" # Abbrev code
+ .byte 36 # DW_TAG_base_type
+ .byte 2 # DW_IDX_type_unit
+ .byte 11 # DW_FORM_data1
+ .byte 3 # DW_IDX_die_offset
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev
+ .byte 0 # End of abbrev list
+.Lnames_abbrev_end0:
+.Lnames_entries0:
+.Lnames1:
+ .ascii "\210\t" # Abbreviation code
+ .long 62 # DW_IDX_die_offset
+ .byte 0 # End of list: int
+.Lnames2:
+ .ascii "\354\004" # Abbreviation code
+ .byte 0 # DW_IDX_type_unit
+ .long 35 # DW_IDX_die_offset
+ .ascii "\350\004" # Abbreviation code
+ .long 66 # DW_IDX_die_offset
+ .byte 0 # End of list: Foo2a
+.Lnames0:
+ .ascii "\310\013" # Abbreviation code
+ .long 35 # DW_IDX_die_offset
+ .byte 0 # End of list: main
+.Lnames3:
+ .ascii "\214\t" # Abbreviation code
+ .byte 0 # DW_IDX_type_unit
+ .long 56 # DW_IDX_die_offset
+ .byte 0 # End of list: char
+ .p2align 2, 0x0
+.Lnames_end0:
+ .ident "clang version 18.0.0git (git@github.com:ayermolo/llvm-project.git db35fa8fc524127079662802c4735dbf397f86d0)"
+ .section ".note.GNU-stack","",@progbits
+ .addrsig
+ .section .debug_line,"",@progbits
+.Lline_table_start0:
bolt/test/X86/dwarf5-debug-names-generate-debug-names.test
@@ -0,0 +1,154 @@
+; REQUIRES: system-linux
+
+; RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5_main.s -o %tmain.o
+; RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5_helper.s -o %thelper.o
+; RUN: %clang %cflags -dwarf-5 %tmain.o %thelper.o -o %t.exe -Wl,-q
+; RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections --create-debug-names-section=true
+; RUN: llvm-dwarfdump --debug-info -r 0 --debug-names %t.bolt > %t.txt
+; RUN: cat %t.txt | FileCheck --check-prefix=BOLT %s
+
+;; Tests BOLT generates .debug_names with --create-debug-names-section.
+;; Also applicable when binary has CUs that do not contribute to .debug_names pre-bolt.
+
+; BOLT: [[OFFSET1:0x[0-9a-f]*]]: Compile Unit
+; BOLT: [[OFFSET2:0x[0-9a-f]*]]: Compile Unit
+; BOLT: Name Index @ 0x0 {
+; BOLT-NEXT: Header {
+; BOLT-NEXT: Length: 0x103
+; BOLT-NEXT: Format: DWARF32
+; BOLT-NEXT: Version: 5
+; BOLT-NEXT: CU count: 2
+; BOLT-NEXT: Local TU count: 0
+; BOLT-NEXT: Foreign TU count: 0
+; BOLT-NEXT: Bucket count: 8
+; BOLT-NEXT: Name count: 8
+; BOLT-NEXT: Abbreviations table size: 0x19
+; BOLT-NEXT: Augmentation: 'BOLT'
+; BOLT-NEXT: }
+; BOLT-NEXT: Compilation Unit offsets [
+; BOLT-NEXT: CU[0]: [[OFFSET1]]
+; BOLT-NEXT: CU[1]: [[OFFSET2]]
+; BOLT-NEXT: ]
+; BOLT-NEXT: Abbreviations [
+; BOLT-NEXT: Abbreviation [[ABBREV1:0x[0-9a-f]*]] {
+; BOLT-NEXT: Tag: DW_TAG_base_type
+; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+; BOLT-NEXT: }
+; BOLT-NEXT: Abbreviation [[ABBREV2:0x[0-9a-f]*]] {
+; BOLT-NEXT: Tag: DW_TAG_subprogram
+; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+; BOLT-NEXT: }
+; BOLT-NEXT: Abbreviation [[ABBREV3:0x[0-9a-f]*]] {
+; BOLT-NEXT: Tag: DW_TAG_variable
+; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+; BOLT-NEXT: }
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 0 [
+; BOLT-NEXT: Name 1 {
+; BOLT-NEXT: Hash: 0xB888030
+; BOLT-NEXT: String: {{.+}} "int"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV1]]
+; BOLT-NEXT: Tag: DW_TAG_base_type
+; BOLT-NEXT: DW_IDX_compile_unit: 0x01
+; BOLT-NEXT: DW_IDX_die_offset: 0x00000033
+; BOLT-NEXT: }
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV1]]
+; BOLT-NEXT: Tag: DW_TAG_base_type
+; BOLT-NEXT: DW_IDX_compile_unit: 0x00
+; BOLT-NEXT: DW_IDX_die_offset: 0x0000007f
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 1 [
+; BOLT-NEXT: Name 2 {
+; BOLT-NEXT: Hash: 0xB887389
+; BOLT-NEXT: String: {{.+}} "foo"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV2]]
+; BOLT-NEXT: Tag: DW_TAG_subprogram
+; BOLT-NEXT: DW_IDX_compile_unit: 0x01
+; BOLT-NEXT: DW_IDX_die_offset: 0x0000005e
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: Name 3 {
+; BOLT-NEXT: Hash: 0x8C06E589
+; BOLT-NEXT: String: {{.+}} "_Z3usePiS_"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV2]]
+; BOLT-NEXT: Tag: DW_TAG_subprogram
+; BOLT-NEXT: DW_IDX_compile_unit: 0x00
+; BOLT-NEXT: DW_IDX_die_offset: 0x00000028
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 2 [
+; BOLT-NEXT: Name 4 {
+; BOLT-NEXT: Hash: 0xB88B3D2
+; BOLT-NEXT: String: {{.+}} "use"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV2]]
+; BOLT-NEXT: Tag: DW_TAG_subprogram
+; BOLT-NEXT: DW_IDX_compile_unit: 0x00
+; BOLT-NEXT: DW_IDX_die_offset: 0x00000028
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: Name 5 {
+; BOLT-NEXT: Hash: 0x7C9A7F6A
+; BOLT-NEXT: String: {{.+}} "main"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV2]]
+; BOLT-NEXT: Tag: DW_TAG_subprogram
+; BOLT-NEXT: DW_IDX_compile_unit: 0x00
+; BOLT-NEXT: DW_IDX_die_offset: 0x00000049
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: Name 6 {
+; BOLT-NEXT: Hash: 0xFDE4B5D2
+; BOLT-NEXT: String: {{.+}} "fooVar"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV3]]
+; BOLT-NEXT: Tag: DW_TAG_variable
+; BOLT-NEXT: DW_IDX_compile_unit: 0x01
+; BOLT-NEXT: DW_IDX_die_offset: 0x00000028
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 3 [
+; BOLT-NEXT: Name 7 {
+; BOLT-NEXT: Hash: 0x7C952063
+; BOLT-NEXT: String: {{.+}} "char"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV1]]
+; BOLT-NEXT: Tag: DW_TAG_base_type
+; BOLT-NEXT: DW_IDX_compile_unit: 0x00
+; BOLT-NEXT: DW_IDX_die_offset: 0x00000092
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 4 [
+; BOLT-NEXT: EMPTY
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 5 [
+; BOLT-NEXT: EMPTY
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 6 [
+; BOLT-NEXT: Name 8 {
+; BOLT-NEXT: Hash: 0xB5063CFE
+; BOLT-NEXT: String: {{.+}} "_Z3fooi"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV2]]
+; BOLT-NEXT: Tag: DW_TAG_subprogram
+; BOLT-NEXT: DW_IDX_compile_unit: 0x01
+; BOLT-NEXT: DW_IDX_die_offset: 0x0000005e
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 7 [
+; BOLT-NEXT: EMPTY
+; BOLT-NEXT: ]
+; BOLT-NEXT: }
bolt/test/X86/dwarf5-debug-names.test
@@ -0,0 +1,263 @@
+; RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-debug-names-main.s -o %tmain.o
+; RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-debug-names-helper.s -o %thelper.o
+; RUN: %clang %cflags -gdwarf-5 %tmain.o %thelper.o -o %tmain.exe
+; RUN: llvm-bolt %tmain.exe -o %tmain.exe.bolt --update-debug-sections
+; RUN: llvm-dwarfdump --debug-info -r 0 --debug-names %tmain.exe.bolt > %tlog.txt
+; RUN: cat %tlog.txt | FileCheck -check-prefix=BOLT %s
+
+;; Tests that BOLT correctly generates .debug_names section with two CUs
+
+; BOLT: [[OFFSET1:0x[0-9a-f]*]]: Compile Unit
+; BOLT: [[OFFSET2:0x[0-9a-f]*]]: Compile Unit
+; BOLT: Name Index @ 0x0 {
+; BOLT-NEXT: Header {
+; BOLT-NEXT: Length: 0x1C2
+; BOLT-NEXT: Format: DWARF32
+; BOLT-NEXT: Version: 5
+; BOLT-NEXT: CU count: 2
+; BOLT-NEXT: Local TU count: 0
+; BOLT-NEXT: Foreign TU count: 0
+; BOLT-NEXT: Bucket count: 14
+; BOLT-NEXT: Name count: 15
+; BOLT-NEXT: Abbreviations table size: 0x29
+; BOLT-NEXT: Augmentation: 'BOLT'
+; BOLT-NEXT: }
+; BOLT-NEXT: Compilation Unit offsets [
+; BOLT-NEXT: CU[0]: [[OFFSET1]]
+; BOLT-NEXT: CU[1]: [[OFFSET2]]
+; BOLT-NEXT: ]
+; BOLT-NEXT: Abbreviations [
+; BOLT-NEXT: Abbreviation [[ABBREV1:0x[0-9a-f]*]] {
+; BOLT-NEXT: Tag: DW_TAG_structure_type
+; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+; BOLT-NEXT: }
+; BOLT-NEXT: Abbreviation [[ABBREV2:0x[0-9a-f]*]] {
+; BOLT-NEXT: Tag: DW_TAG_namespace
+; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+; BOLT-NEXT: }
+; BOLT-NEXT: Abbreviation [[ABBREV3:0x[0-9a-f]*]] {
+; BOLT-NEXT: Tag: DW_TAG_subprogram
+; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+; BOLT-NEXT: }
+; BOLT-NEXT: Abbreviation [[ABBREV4:0x[0-9a-f]*]] {
+; BOLT-NEXT: Tag: DW_TAG_base_type
+; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+; BOLT-NEXT: }
+; BOLT-NEXT: Abbreviation [[ABBREV5:0x[0-9a-f]*]] {
+; BOLT-NEXT: Tag: DW_TAG_variable
+; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+; BOLT-NEXT: }
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 0 [
+; BOLT-NEXT: Name 1 {
+; BOLT-NEXT: Hash: 0x59796C
+; BOLT-NEXT: String: {{.+}} "t3"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV1]]
+; BOLT-NEXT: Tag: DW_TAG_structure_type
+; BOLT-NEXT: DW_IDX_compile_unit: 0x00
+; BOLT-NEXT: DW_IDX_die_offset: 0x0000002f
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 1 [
+; BOLT-NEXT: Name 2 {
+; BOLT-NEXT: Hash: 0x7C96E4DB
+; BOLT-NEXT: String: {{.+}} "Foo2"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV1]]
+; BOLT-NEXT: Tag: DW_TAG_structure_type
+; BOLT-NEXT: DW_IDX_compile_unit: 0x00
+; BOLT-NEXT: DW_IDX_die_offset: 0x000000eb
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 2 [
+; BOLT-NEXT: Name 3 {
+; BOLT-NEXT: Hash: 0x8CFC710C
+; BOLT-NEXT: String: {{.+}} "(anonymous namespace)"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV2]]
+; BOLT-NEXT: Tag: DW_TAG_namespace
+; BOLT-NEXT: DW_IDX_compile_unit: 0x00
+; BOLT-NEXT: DW_IDX_die_offset: 0x00000061
+; BOLT-NEXT: }
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV2]]
+; BOLT-NEXT: Tag: DW_TAG_namespace
+; BOLT-NEXT: DW_IDX_compile_unit: 0x00
+; BOLT-NEXT: DW_IDX_die_offset: 0x00000061
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: Name 4 {
+; BOLT-NEXT: Hash: 0xBA564846
+; BOLT-NEXT: String: {{.+}} "Foo2Int"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV1]]
+; BOLT-NEXT: Tag: DW_TAG_structure_type
+; BOLT-NEXT: DW_IDX_compile_unit: 0x01
+; BOLT-NEXT: DW_IDX_die_offset: 0x0000005a
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 3 [
+; BOLT-NEXT: EMPTY
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 4 [
+; BOLT-NEXT: EMPTY
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 5 [
+; BOLT-NEXT: Name 5 {
+; BOLT-NEXT: Hash: 0xB887389
+; BOLT-NEXT: String: {{.+}} "Foo"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV1]]
+; BOLT-NEXT: Tag: DW_TAG_structure_type
+; BOLT-NEXT: DW_IDX_compile_unit: 0x00
+; BOLT-NEXT: DW_IDX_die_offset: 0x000000c9
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: Name 6 {
+; BOLT-NEXT: Hash: 0xB887389
+; BOLT-NEXT: String: {{.+}} "foo"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV3]]
+; BOLT-NEXT: Tag: DW_TAG_subprogram
+; BOLT-NEXT: DW_IDX_compile_unit: 0x01
+; BOLT-NEXT: DW_IDX_die_offset: 0x00000033
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: Name 7 {
+; BOLT-NEXT: Hash: 0x7C952063
+; BOLT-NEXT: String: {{.+}} "char"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV4]]
+; BOLT-NEXT: Tag: DW_TAG_base_type
+; BOLT-NEXT: DW_IDX_compile_unit: 0x01
+; BOLT-NEXT: DW_IDX_die_offset: 0x0000009f
+; BOLT-NEXT: }
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV4]]
+; BOLT-NEXT: Tag: DW_TAG_base_type
+; BOLT-NEXT: DW_IDX_compile_unit: 0x00
+; BOLT-NEXT: DW_IDX_die_offset: 0x000000c5
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 6 [
+; BOLT-NEXT: Name 8 {
+; BOLT-NEXT: Hash: 0x392140FA
+; BOLT-NEXT: String: {{.+}} "t2<&fooint>"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV1]]
+; BOLT-NEXT: Tag: DW_TAG_structure_type
+; BOLT-NEXT: DW_IDX_compile_unit: 0x00
+; BOLT-NEXT: DW_IDX_die_offset: 0x0000003f
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: Name 9 {
+; BOLT-NEXT: Hash: 0xFDE48034
+; BOLT-NEXT: String: {{.+}} "fooint"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV5]]
+; BOLT-NEXT: Tag: DW_TAG_variable
+; BOLT-NEXT: DW_IDX_compile_unit: 0x01
+; BOLT-NEXT: DW_IDX_die_offset: 0x00000024
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 7 [
+; BOLT-NEXT: Name 10 {
+; BOLT-NEXT: Hash: 0xB5063D0B
+; BOLT-NEXT: String: {{.+}} "_Z3foov"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV3]]
+; BOLT-NEXT: Tag: DW_TAG_subprogram
+; BOLT-NEXT: DW_IDX_compile_unit: 0x01
+; BOLT-NEXT: DW_IDX_die_offset: 0x00000033
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 8 [
+; BOLT-NEXT: Name 11 {
+; BOLT-NEXT: Hash: 0x5979AC
+; BOLT-NEXT: String: {{.+}} "v1"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV5]]
+; BOLT-NEXT: Tag: DW_TAG_variable
+; BOLT-NEXT: DW_IDX_compile_unit: 0x00
+; BOLT-NEXT: DW_IDX_die_offset: 0x00000024
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 9 [
+; BOLT-NEXT: EMPTY
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 10 [
+; BOLT-NEXT: Name 12 {
+; BOLT-NEXT: Hash: 0xB888030
+; BOLT-NEXT: String: {{.+}} "int"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV4]]
+; BOLT-NEXT: Tag: DW_TAG_base_type
+; BOLT-NEXT: DW_IDX_compile_unit: 0x01
+; BOLT-NEXT: DW_IDX_die_offset: 0x0000002f
+; BOLT-NEXT: }
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV4]]
+; BOLT-NEXT: Tag: DW_TAG_base_type
+; BOLT-NEXT: DW_IDX_compile_unit: 0x00
+; BOLT-NEXT: DW_IDX_die_offset: 0x0000005d
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: Name 13 {
+; BOLT-NEXT: Hash: 0xF73809C
+; BOLT-NEXT: String: {{.+}} "Foo2a"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV1]]
+; BOLT-NEXT: Tag: DW_TAG_structure_type
+; BOLT-NEXT: DW_IDX_compile_unit: 0x01
+; BOLT-NEXT: DW_IDX_die_offset: 0x00000078
+; BOLT-NEXT: }
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV1]]
+; BOLT-NEXT: Tag: DW_TAG_structure_type
+; BOLT-NEXT: DW_IDX_compile_unit: 0x00
+; BOLT-NEXT: DW_IDX_die_offset: 0x00000104
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: Name 14 {
+; BOLT-NEXT: Hash: 0x7C9A7F6A
+; BOLT-NEXT: String: {{.+}} "main"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV3]]
+; BOLT-NEXT: Tag: DW_TAG_subprogram
+; BOLT-NEXT: DW_IDX_compile_unit: 0x00
+; BOLT-NEXT: DW_IDX_die_offset: 0x00000073
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 11 [
+; BOLT-NEXT: EMPTY
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 12 [
+; BOLT-NEXT: Name 15 {
+; BOLT-NEXT: Hash: 0x59796A
+; BOLT-NEXT: String: {{.+}} "t1"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV1]]
+; BOLT-NEXT: Tag: DW_TAG_structure_type
+; BOLT-NEXT: DW_IDX_compile_unit: 0x00
+; BOLT-NEXT: DW_IDX_die_offset: 0x00000062
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 13 [
+; BOLT-NEXT: EMPTY
+; BOLT-NEXT: ]
+; BOLT-NEXT: }
bolt/test/X86/dwarf5-df-debug-names-generate-debug-names.test
@@ -0,0 +1,192 @@
+; RUN: rm -rf %t
+; RUN: mkdir %t
+; RUN: cd %t
+; RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-df-dualcu-main.s \
+; RUN: -split-dwarf-file=main.dwo -o main.o
+; RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-df-dualcu-helper.s \
+; RUN: -split-dwarf-file=helper.dwo -o helper.o
+; RUN: %clang %cflags -gdwarf-5 -gsplit-dwarf=split main.o helper.o -o main.exe -fno-pic -no-pie
+; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections --create-debug-names-section=true
+; RUN: llvm-dwarfdump --debug-info --debug-names main.exe.bolt > %t/foo.txt
+; RUN: cat %t/foo.txt | FileCheck -check-prefix=BOLT %s
+
+;; Tests BOLT generates .debug_names with --create-debug-names-section.
+;; Also applicable when binary has split dwarf CUs that do not contribute to .debug_names pre-bolt.
+
+; BOLT: [[OFFSET1:0x[0-9a-f]*]]: Compile Unit
+; BOLT: [[OFFSET2:0x[0-9a-f]*]]: Compile Unit
+; BOLT: Name Index @ 0x0 {
+; BOLT-NEXT: Header {
+; BOLT-NEXT: Length: 0x148
+; BOLT-NEXT: Format: DWARF32
+; BOLT-NEXT: Version: 5
+; BOLT-NEXT: CU count: 2
+; BOLT-NEXT: Local TU count: 0
+; BOLT-NEXT: Foreign TU count: 0
+; BOLT-NEXT: Bucket count: 11
+; BOLT-NEXT: Name count: 11
+; BOLT-NEXT: Abbreviations table size: 0x19
+; BOLT-NEXT: Augmentation: 'BOLT'
+; BOLT-NEXT: }
+; BOLT-NEXT: Compilation Unit offsets [
+; BOLT-NEXT: CU[0]: [[OFFSET1]]
+; BOLT-NEXT: CU[1]: [[OFFSET2]]
+; BOLT-NEXT: ]
+; BOLT-NEXT: Abbreviations [
+; BOLT-NEXT: Abbreviation [[ABBREV1:0x[0-9a-f]*]] {
+; BOLT-NEXT: Tag: DW_TAG_variable
+; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+; BOLT-NEXT: }
+; BOLT-NEXT: Abbreviation [[ABBREV2:0x[0-9a-f]*]] {
+; BOLT-NEXT: Tag: DW_TAG_base_type
+; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+; BOLT-NEXT: }
+; BOLT-NEXT: Abbreviation [[ABBREV3:0x[0-9a-f]*]] {
+; BOLT-NEXT: Tag: DW_TAG_subprogram
+; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+; BOLT-NEXT: }
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 0 [
+; BOLT-NEXT: Name 1 {
+; BOLT-NEXT: Hash: 0x2B61E
+; BOLT-NEXT: String: {{.+}} "y"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV1]]
+; BOLT-NEXT: Tag: DW_TAG_variable
+; BOLT-NEXT: DW_IDX_compile_unit: 0x00
+; BOLT-NEXT: DW_IDX_die_offset: 0x00000029
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: Name 2 {
+; BOLT-NEXT: Hash: 0x7C952063
+; BOLT-NEXT: String: {{.+}} "char"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV2]]
+; BOLT-NEXT: Tag: DW_TAG_base_type
+; BOLT-NEXT: DW_IDX_compile_unit: 0x00
+; BOLT-NEXT: DW_IDX_die_offset: 0x0000008c
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 1 [
+; BOLT-NEXT: Name 3 {
+; BOLT-NEXT: Hash: 0x2B609
+; BOLT-NEXT: String: {{.+}} "d"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV1]]
+; BOLT-NEXT: Tag: DW_TAG_variable
+; BOLT-NEXT: DW_IDX_compile_unit: 0x01
+; BOLT-NEXT: DW_IDX_die_offset: 0x00000029
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: Name 4 {
+; BOLT-NEXT: Hash: 0x2B61F
+; BOLT-NEXT: String: {{.+}} "z"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV1]]
+; BOLT-NEXT: Tag: DW_TAG_variable
+; BOLT-NEXT: DW_IDX_compile_unit: 0x01
+; BOLT-NEXT: DW_IDX_die_offset: 0x0000001a
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 2 [
+; BOLT-NEXT: Name 5 {
+; BOLT-NEXT: Hash: 0xB88B3D2
+; BOLT-NEXT: String: {{.+}} "use"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV3]]
+; BOLT-NEXT: Tag: DW_TAG_subprogram
+; BOLT-NEXT: DW_IDX_compile_unit: 0x00
+; BOLT-NEXT: DW_IDX_die_offset: 0x00000034
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 3 [
+; BOLT-NEXT: Name 6 {
+; BOLT-NEXT: Hash: 0x45A3B006
+; BOLT-NEXT: String: {{.+}} "_Z6helperii"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV3]]
+; BOLT-NEXT: Tag: DW_TAG_subprogram
+; BOLT-NEXT: DW_IDX_compile_unit: 0x01
+; BOLT-NEXT: DW_IDX_die_offset: 0x00000034
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 4 [
+; BOLT-NEXT: EMPTY
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 5 [
+; BOLT-NEXT: Name 7 {
+; BOLT-NEXT: Hash: 0x8C06E589
+; BOLT-NEXT: String: {{.+}} "_Z3usePiS_"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV3]]
+; BOLT-NEXT: Tag: DW_TAG_subprogram
+; BOLT-NEXT: DW_IDX_compile_unit: 0x00
+; BOLT-NEXT: DW_IDX_die_offset: 0x00000034
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 6 [
+; BOLT-NEXT: Name 8 {
+; BOLT-NEXT: Hash: 0xB888030
+; BOLT-NEXT: String: {{.+}} "int"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV2]]
+; BOLT-NEXT: Tag: DW_TAG_base_type
+; BOLT-NEXT: DW_IDX_compile_unit: 0x00
+; BOLT-NEXT: DW_IDX_die_offset: 0x00000025
+; BOLT-NEXT: }
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV2]]
+; BOLT-NEXT: Tag: DW_TAG_base_type
+; BOLT-NEXT: DW_IDX_compile_unit: 0x01
+; BOLT-NEXT: DW_IDX_die_offset: 0x00000025
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 7 [
+; BOLT-NEXT: Name 9 {
+; BOLT-NEXT: Hash: 0x1D853E5
+; BOLT-NEXT: String: {{.+}} "helper"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV3]]
+; BOLT-NEXT: Tag: DW_TAG_subprogram
+; BOLT-NEXT: DW_IDX_compile_unit: 0x01
+; BOLT-NEXT: DW_IDX_die_offset: 0x00000034
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: Name 10 {
+; BOLT-NEXT: Hash: 0x7C9A7F6A
+; BOLT-NEXT: String: {{.+}} "main"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV3]]
+; BOLT-NEXT: Tag: DW_TAG_subprogram
+; BOLT-NEXT: DW_IDX_compile_unit: 0x00
+; BOLT-NEXT: DW_IDX_die_offset: 0x00000057
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 8 [
+; BOLT-NEXT: EMPTY
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 9 [
+; BOLT-NEXT: EMPTY
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 10 [
+; BOLT-NEXT: Name 11 {
+; BOLT-NEXT: Hash: 0x2B61D
+; BOLT-NEXT: String: {{.+}} "x"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV1]]
+; BOLT-NEXT: Tag: DW_TAG_variable
+; BOLT-NEXT: DW_IDX_compile_unit: 0x00
+; BOLT-NEXT: DW_IDX_die_offset: 0x0000001a
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: ]
bolt/test/X86/dwarf5-df-debug-names.test
@@ -0,0 +1,149 @@
+; RUN: rm -rf %t
+; RUN: mkdir %t
+; RUN: cd %t
+; RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-df-debug-names-main.s \
+; RUN: -split-dwarf-file=main.dwo -o main.o
+; RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-df-debug-names-helper.s \
+; RUN: -split-dwarf-file=helper.dwo -o helper.o
+; RUN: %clang %cflags -gdwarf-5 -gsplit-dwarf=split main.o helper.o -o main.exe
+; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections
+; RUN: llvm-dwarfdump --debug-info --debug-names main.exe.bolt > log.txt
+; RUN: cat log.txt | FileCheck -check-prefix=BOLT %s
+
+;; Tests that BOLT correctly generates .debug_names section with two CUs for split dwarf.
+
+; BOLT: [[OFFSET:0x[0-9a-f]*]]: Compile Unit
+; BOLT: [[OFFSET1:0x[0-9a-f]*]]: Compile Unit
+: BOLT: Name Index @ 0x0 {
+: BOLT-NEXT: Header {
+: BOLT-NEXT: Length: 0xF4
+: BOLT-NEXT: Format: DWARF32
+: BOLT-NEXT: Version: 5
+: BOLT-NEXT: CU count: 2
+: BOLT-NEXT: Local TU count: 0
+: BOLT-NEXT: Foreign TU count: 0
+: BOLT-NEXT: Bucket count: 7
+: BOLT-NEXT: Name count: 7
+: BOLT-NEXT: Abbreviations table size: 0x21
+: BOLT-NEXT: Augmentation: 'BOLT'
+: BOLT-NEXT: }
+: BOLT-NEXT: Compilation Unit offsets [
+: BOLT-NEXT: CU[0]: [[OFFSET]]
+: BOLT-NEXT: CU[1]: [[OFFSET1]]
+: BOLT-NEXT: ]
+: BOLT-NEXT: Abbreviations [
+: BOLT-NEXT: Abbreviation [[ABBREV1:0x[0-9a-f]*]] {
+: BOLT-NEXT: Tag: DW_TAG_structure_type
+: BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+: BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+: BOLT-NEXT: }
+: BOLT-NEXT: Abbreviation [[ABBREV2:0x[0-9a-f]*]] {
+: BOLT-NEXT: Tag: DW_TAG_base_type
+: BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+: BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+: BOLT-NEXT: }
+: BOLT-NEXT: Abbreviation [[ABBREV3:0x[0-9a-f]*]] {
+: BOLT-NEXT: Tag: DW_TAG_variable
+: BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+: BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+: BOLT-NEXT: }
+: BOLT-NEXT: Abbreviation [[ABBREV4:0x[0-9a-f]*]] {
+: BOLT-NEXT: Tag: DW_TAG_subprogram
+: BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1
+: BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+: BOLT-NEXT: }
+: BOLT-NEXT: ]
+: BOLT-NEXT: Bucket 0 [
+: BOLT-NEXT: EMPTY
+: BOLT-NEXT: ]
+: BOLT-NEXT: Bucket 1 [
+: BOLT-NEXT: Name 1 {
+: BOLT-NEXT: Hash: 0x7C96E4DB
+: BOLT-NEXT: String: {{.+}} "Foo2"
+: BOLT-NEXT: Entry @ {{.+}} {
+: BOLT-NEXT: Abbrev: [[ABBREV1]]
+: BOLT-NEXT: Tag: DW_TAG_structure_type
+: BOLT-NEXT: DW_IDX_compile_unit: 0x00
+: BOLT-NEXT: DW_IDX_die_offset: 0x00000068
+: BOLT-NEXT: }
+: BOLT-NEXT: }
+: BOLT-NEXT: ]
+: BOLT-NEXT: Bucket 2 [
+: BOLT-NEXT: Name 2 {
+: BOLT-NEXT: Hash: 0xBA564846
+: BOLT-NEXT: String: {{.+}} "Foo2Int"
+: BOLT-NEXT: Entry @ {{.+}} {
+: BOLT-NEXT: Abbrev: [[ABBREV1]]
+: BOLT-NEXT: Tag: DW_TAG_structure_type
+: BOLT-NEXT: DW_IDX_compile_unit: 0x01
+: BOLT-NEXT: DW_IDX_die_offset: 0x00000025
+: BOLT-NEXT: }
+: BOLT-NEXT: }
+: BOLT-NEXT: ]
+: BOLT-NEXT: Bucket 3 [
+: BOLT-NEXT: Name 3 {
+: BOLT-NEXT: Hash: 0xB888030
+: BOLT-NEXT: String: {{.+}} "int"
+: BOLT-NEXT: Entry @ {{.+}} {
+: BOLT-NEXT: Abbrev: [[ABBREV2]]
+: BOLT-NEXT: Tag: DW_TAG_base_type
+: BOLT-NEXT: DW_IDX_compile_unit: 0x01
+: BOLT-NEXT: DW_IDX_die_offset: 0x00000043
+: BOLT-NEXT: }
+: BOLT-NEXT: Entry @ {{.+}} {
+: BOLT-NEXT: Abbrev: [[ABBREV2]]
+: BOLT-NEXT: Tag: DW_TAG_base_type
+: BOLT-NEXT: DW_IDX_compile_unit: 0x00
+: BOLT-NEXT: DW_IDX_die_offset: 0x00000056
+: BOLT-NEXT: }
+: BOLT-NEXT: }
+: BOLT-NEXT: Name 4 {
+: BOLT-NEXT: Hash: 0xF73809C
+: BOLT-NEXT: String: {{.+}} "Foo2a"
+: BOLT-NEXT: Entry @ {{.+}} {
+: BOLT-NEXT: Abbrev: [[ABBREV1]]
+: BOLT-NEXT: Tag: DW_TAG_structure_type
+: BOLT-NEXT: DW_IDX_compile_unit: 0x00
+: BOLT-NEXT: DW_IDX_die_offset: 0x00000078
+: BOLT-NEXT: }
+: BOLT-NEXT: }
+: BOLT-NEXT: Name 5 {
+: BOLT-NEXT: Hash: 0x7C96CB76
+: BOLT-NEXT: String: {{.+}} "fint"
+: BOLT-NEXT: Entry @ {{.+}} {
+: BOLT-NEXT: Abbrev: [[ABBREV3]]
+: BOLT-NEXT: Tag: DW_TAG_variable
+: BOLT-NEXT: DW_IDX_compile_unit: 0x01
+: BOLT-NEXT: DW_IDX_die_offset: 0x0000001a
+: BOLT-NEXT: }
+: BOLT-NEXT: }
+: BOLT-NEXT: Name 6 {
+: BOLT-NEXT: Hash: 0x7C9A7F6A
+: BOLT-NEXT: String: {{.+}} "main"
+: BOLT-NEXT: Entry @ {{.+}} {
+: BOLT-NEXT: Abbrev: [[ABBREV4]]
+: BOLT-NEXT: Tag: DW_TAG_subprogram
+: BOLT-NEXT: DW_IDX_compile_unit: 0x00
+: BOLT-NEXT: DW_IDX_die_offset: 0x0000001a
+: BOLT-NEXT: }
+: BOLT-NEXT: }
+: BOLT-NEXT: ]
+: BOLT-NEXT: Bucket 4 [
+: BOLT-NEXT: EMPTY
+: BOLT-NEXT: ]
+: BOLT-NEXT: Bucket 5 [
+: BOLT-NEXT: Name 7 {
+: BOLT-NEXT: Hash: 0x7C952063
+: BOLT-NEXT: String: {{.+}} "char"
+: BOLT-NEXT: Entry @ {{.+}} {
+: BOLT-NEXT: Abbrev: [[ABBREV2]]
+: BOLT-NEXT: Tag: DW_TAG_base_type
+: BOLT-NEXT: DW_IDX_compile_unit: 0x00
+: BOLT-NEXT: DW_IDX_die_offset: 0x00000064
+: BOLT-NEXT: }
+: BOLT-NEXT: }
+: BOLT-NEXT: ]
+: BOLT-NEXT: Bucket 6 [
+: BOLT-NEXT: EMPTY
+: BOLT-NEXT: ]
+: BOLT-NEXT: }
bolt/test/X86/dwarf5-df-main-debug-names-ftu-ltu-mix.test
@@ -0,0 +1,56 @@
+; RUN: rm -rf %t
+; RUN: mkdir %t
+; RUN: cd %t
+; RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-df-debug-names-ftu-ltu-mix-main.s \
+; RUN: -split-dwarf-file=main.dwo -o main.o
+; RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-debug-names-ftu-ltu-mix-helper.s -o helper.o
+; RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-debug-names-ftu-ltu-mix-helper1.s -o helper1.o
+; RUN: %clang %cflags -gdwarf-5 -gsplit-dwarf=split main.o helper.o helper1.o -o main.exe -fno-pic -no-pie
+; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections --create-debug-names-section=true
+; RUN: llvm-dwarfdump --debug-names main.exe.bolt | FileCheck -check-prefix=BOLT %s
+
+;; Tests BOLT correctly sets foreign TU Index when there are local TUs.
+
+; BOLT: Compilation Unit offsets [
+; BOLT-NEXT: CU[0]: {{.+}}
+; BOLT-NEXT: CU[1]: {{.+}}
+; BOLT-NEXT: CU[2]: {{.+}}
+; BOLT-NEXT: ]
+; BOLT-NEXT: Local Type Unit offsets [
+; BOLT-NEXT: LocalTU[0]: {{.+}}
+; BOLT-NEXT: LocalTU[1]: {{.+}}
+; BOLT-NEXT: ]
+; BOLT-NEXT: Foreign Type Unit signatures [
+; BOLT-NEXT: ForeignTU[0]: 0x889c84450dac881f
+; BOLT-NEXT: ]
+; BOLT: Name 3 {
+; BOLT-NEXT: Hash: 0x6A05C500
+; BOLT-NEXT: String: {{.+}} "globalMono1"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: 0x5
+; BOLT-NEXT: Tag: DW_TAG_variable
+; BOLT-NEXT: DW_IDX_compile_unit: 0x02
+; BOLT-NEXT: DW_IDX_die_offset: 0x0000001e
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT: Name 6 {
+; BOLT-NEXT: Hash: 0xF283AF92
+; BOLT-NEXT: String: {{.+}} "ASplit"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: 0x7
+; BOLT-NEXT: Tag: DW_TAG_structure_type
+; BOLT-NEXT: DW_IDX_type_unit: 0x02
+; BOLT-NEXT: DW_IDX_compile_unit: 0x00
+; BOLT-NEXT: DW_IDX_die_offset: 0x00000021
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT: Name 7 {
+; BOLT-NEXT: Hash: 0xF17F51F
+; BOLT-NEXT: String: {{.+}} "AMono"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: 0x4
+; BOLT-NEXT: Tag: DW_TAG_structure_type
+; BOLT-NEXT: DW_IDX_type_unit: 0x00
+; BOLT-NEXT: DW_IDX_die_offset: 0x00000023
+; BOLT-NEXT: }
+; BOLT-NEXT: }
bolt/test/X86/dwarf5-df-one-cu-debug-names.test
@@ -0,0 +1,101 @@
+; RUN: rm -rf %t
+; RUN: mkdir %t
+; RUN: cd %t
+; RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-df-debug-names-main.s \
+; RUN: -split-dwarf-file=main.dwo -o main.o
+; RUN: %clang %cflags -gdwarf-5 -gsplit-dwarf=split main.o -o main.exe
+; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections
+; RUN: llvm-dwarfdump --debug-info --debug-names main.exe.bolt > log.txt
+; RUN: cat log.txt | FileCheck -check-prefix=BOLT %s
+
+;; Tests that BOLT correctly generates .debug_names section with one CU for split dwarf.
+
+; BOLT: [[OFFSET:0x[0-9a-f]*]]: Compile Unit
+; BOLT: Name Index @ 0x0 {
+; BOLT-NEXT: Header {
+; BOLT-NEXT: Length: 0xA9
+; BOLT-NEXT: Format: DWARF32
+; BOLT-NEXT: Version: 5
+; BOLT-NEXT: CU count: 1
+; BOLT-NEXT: Local TU count: 0
+; BOLT-NEXT: Foreign TU count: 0
+; BOLT-NEXT: Bucket count: 5
+; BOLT-NEXT: Name count: 5
+; BOLT-NEXT: Abbreviations table size: 0x13
+; BOLT-NEXT: Augmentation: 'BOLT'
+; BOLT-NEXT: }
+; BOLT-NEXT: Compilation Unit offsets [
+; BOLT-NEXT: CU[0]: 0x00000000
+; BOLT-NEXT: ]
+; BOLT-NEXT: Abbreviations [
+; BOLT-NEXT: Abbreviation [[ABBREV1:0x[0-9a-f]*]] {
+; BOLT-NEXT: Tag: DW_TAG_structure_type
+; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+; BOLT-NEXT: }
+; BOLT-NEXT: Abbreviation [[ABBREV2:0x[0-9a-f]*]] {
+; BOLT-NEXT: Tag: DW_TAG_subprogram
+; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+; BOLT-NEXT: }
+; BOLT-NEXT: Abbreviation [[ABBREV3:0x[0-9a-f]*]] {
+; BOLT-NEXT: Tag: DW_TAG_base_type
+; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4
+; BOLT-NEXT: }
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 0 [
+; BOLT-NEXT: EMPTY
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 1 [
+; BOLT-NEXT: Name 1 {
+; BOLT-NEXT: Hash: 0x7C96E4DB
+; BOLT-NEXT: String: {{.+}} "Foo2"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV1]]
+; BOLT-NEXT: Tag: DW_TAG_structure_type
+; BOLT-NEXT: DW_IDX_die_offset: 0x00000068
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: Name 2 {
+; BOLT-NEXT: Hash: 0x7C9A7F6A
+; BOLT-NEXT: String: {{.+}} "main"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV2]]
+; BOLT-NEXT: Tag: DW_TAG_subprogram
+; BOLT-NEXT: DW_IDX_die_offset: 0x0000001a
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 2 [
+; BOLT-NEXT: EMPTY
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 3 [
+; BOLT-NEXT: Name 3 {
+; BOLT-NEXT: Hash: 0xB888030
+; BOLT-NEXT: String: {{.+}} "int"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV3]]
+; BOLT-NEXT: Tag: DW_TAG_base_type
+; BOLT-NEXT: DW_IDX_die_offset: 0x00000056
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: ]
+; BOLT-NEXT: Bucket 4 [
+; BOLT-NEXT: Name 4 {
+; BOLT-NEXT: Hash: 0xF73809C
+; BOLT-NEXT: String: {{.+}} "Foo2a"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV1]]
+; BOLT-NEXT: Tag: DW_TAG_structure_type
+; BOLT-NEXT: DW_IDX_die_offset: 0x00000078
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: Name 5 {
+; BOLT-NEXT: Hash: 0x7C952063
+; BOLT-NEXT: String: {{.+}} "char"
+; BOLT-NEXT: Entry @ {{.+}} {
+; BOLT-NEXT: Abbrev: [[ABBREV3]]
+; BOLT-NEXT: Tag: DW_TAG_base_type
+; BOLT-NEXT: DW_IDX_die_offset: 0x00000064
+; BOLT-NEXT: }
+; BOLT-NEXT: }
+; BOLT-NEXT: ]
+; BOLT-NEXT: }
bolt/test/X86/dwarf5-df-types-debug-names.test
@@ -0,0 +1,234 @@
+; RUN: rm -rf %t
[diff truncated]