mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-01 05:01:59 +01:00
[dsymutil] Generate Apple accelerator tables
This patch adds support for generating accelerator tables in dsymutil. This feature was already present in our internal repository but not yet upstreamed because it requires changes to the Apple accelerator table implementation. Differential revision: https://reviews.llvm.org/D42501 llvm-svn: 323655
This commit is contained in:
parent
e67245cd45
commit
2967253e75
@ -406,6 +406,68 @@ public:
|
||||
#endif
|
||||
};
|
||||
|
||||
/// Accelerator table data implementation for simple accelerator tables with
|
||||
/// a DIE offset but no actual DIE pointer.
|
||||
class AppleAccelTableStaticOffsetData : public AppleAccelTableData {
|
||||
public:
|
||||
AppleAccelTableStaticOffsetData(uint32_t Offset) : Offset(Offset) {}
|
||||
|
||||
void emit(AsmPrinter *Asm) const override;
|
||||
|
||||
static constexpr AppleAccelTableHeader::Atom Atoms[] = {
|
||||
AppleAccelTableHeader::Atom(dwarf::DW_ATOM_die_offset,
|
||||
dwarf::DW_FORM_data4)};
|
||||
|
||||
#ifndef NDEBUG
|
||||
void print(raw_ostream &OS) const override {
|
||||
OS << " Static Offset: " << Offset << "\n";
|
||||
}
|
||||
|
||||
#endif
|
||||
protected:
|
||||
uint64_t order() const override { return Offset; }
|
||||
|
||||
uint32_t Offset;
|
||||
};
|
||||
|
||||
/// Accelerator table data implementation for type accelerator tables with
|
||||
/// a DIE offset but no actual DIE pointer.
|
||||
class AppleAccelTableStaticTypeData : public AppleAccelTableStaticOffsetData {
|
||||
public:
|
||||
AppleAccelTableStaticTypeData(uint32_t Offset, uint16_t Tag,
|
||||
bool ObjCClassIsImplementation,
|
||||
uint32_t QualifiedNameHash)
|
||||
: AppleAccelTableStaticOffsetData(Offset),
|
||||
QualifiedNameHash(QualifiedNameHash), Tag(Tag),
|
||||
ObjCClassIsImplementation(ObjCClassIsImplementation) {}
|
||||
|
||||
void emit(AsmPrinter *Asm) const override;
|
||||
|
||||
static constexpr AppleAccelTableHeader::Atom Atoms[] = {
|
||||
AppleAccelTableHeader::Atom(dwarf::DW_ATOM_die_offset,
|
||||
dwarf::DW_FORM_data4),
|
||||
AppleAccelTableHeader::Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2),
|
||||
AppleAccelTableHeader::Atom(5, dwarf::DW_FORM_data1),
|
||||
AppleAccelTableHeader::Atom(6, dwarf::DW_FORM_data4)};
|
||||
|
||||
#ifndef NDEBUG
|
||||
void print(raw_ostream &OS) const override {
|
||||
OS << " Static Offset: " << Offset << "\n";
|
||||
OS << " QualifiedNameHash: " << format("%x\n", QualifiedNameHash) << "\n";
|
||||
OS << " Tag: " << dwarf::TagString(Tag) << "\n";
|
||||
OS << " ObjCClassIsImplementation: "
|
||||
<< (ObjCClassIsImplementation ? "true" : "false");
|
||||
OS << "\n";
|
||||
}
|
||||
#endif
|
||||
protected:
|
||||
uint64_t order() const override { return Offset; }
|
||||
|
||||
uint32_t QualifiedNameHash;
|
||||
uint16_t Tag;
|
||||
bool ObjCClassIsImplementation;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_LIB_CODEGEN_ASMPRINTER_DWARFACCELTABLE_H
|
||||
|
@ -72,6 +72,8 @@ void AppleAccelTableHeader::setBucketAndHashCount(uint32_t HashCount) {
|
||||
|
||||
constexpr AppleAccelTableHeader::Atom AppleAccelTableTypeData::Atoms[];
|
||||
constexpr AppleAccelTableHeader::Atom AppleAccelTableOffsetData::Atoms[];
|
||||
constexpr AppleAccelTableHeader::Atom AppleAccelTableStaticOffsetData::Atoms[];
|
||||
constexpr AppleAccelTableHeader::Atom AppleAccelTableStaticTypeData::Atoms[];
|
||||
|
||||
void AppleAccelTableBase::emitHeader(AsmPrinter *Asm) { Header.emit(Asm); }
|
||||
|
||||
@ -219,3 +221,15 @@ void AppleAccelTableTypeData::emit(AsmPrinter *Asm) const {
|
||||
Asm->EmitInt16(Die->getTag());
|
||||
Asm->EmitInt8(0);
|
||||
}
|
||||
|
||||
void AppleAccelTableStaticOffsetData::emit(AsmPrinter *Asm) const {
|
||||
Asm->EmitInt32(Offset);
|
||||
}
|
||||
|
||||
void AppleAccelTableStaticTypeData::emit(AsmPrinter *Asm) const {
|
||||
Asm->EmitInt32(Offset);
|
||||
Asm->EmitInt16(Tag);
|
||||
Asm->EmitInt8(ObjCClassIsImplementation ? dwarf::DW_FLAG_type_implementation
|
||||
: 0);
|
||||
Asm->EmitInt32(QualifiedNameHash);
|
||||
}
|
||||
|
BIN
test/tools/dsymutil/Inputs/objc.macho.x86_64
Executable file
BIN
test/tools/dsymutil/Inputs/objc.macho.x86_64
Executable file
Binary file not shown.
BIN
test/tools/dsymutil/Inputs/objc.macho.x86_64.o
Normal file
BIN
test/tools/dsymutil/Inputs/objc.macho.x86_64.o
Normal file
Binary file not shown.
@ -78,7 +78,7 @@ CHECK: DW_AT_name ("arg")
|
||||
CHECK: DW_AT_type (0x0000000000000063
|
||||
CHECK: DW_AT_location (0x00000000
|
||||
CHECK: [0x0000000000000000, 0x000000000000000e): DW_OP_reg5 RDI, DW_OP_piece 0x4)
|
||||
CHECK: DW_TAG_inlined_subroutine
|
||||
CHECK:[[INC1:0x[0-9a-f]*]]{{.*}}DW_TAG_inlined_subroutine
|
||||
CHECK: DW_AT_abstract_origin (cu + 0x00a7 "inc")
|
||||
CHECK: DW_AT_low_pc (0x0000000100000f63)
|
||||
CHECK: DW_AT_high_pc (0x0000000100000f72)
|
||||
@ -120,7 +120,7 @@ CHECK: [0x0000000000000019, 0x000000000000001d): DW_OP_reg5 RDI, DW_OP_
|
||||
CHECK: DW_TAG_lexical_block
|
||||
CHECK: DW_AT_low_pc (0x0000000100000f94)
|
||||
CHECK: DW_AT_high_pc (0x0000000100000fa7)
|
||||
CHECK: DW_TAG_inlined_subroutine
|
||||
CHECK:[[INC2:0x[0-9a-f]*]]{{.*}}DW_TAG_inlined_subroutine
|
||||
CHECK: DW_AT_abstract_origin (cu + 0x009a "inc")
|
||||
CHECK: DW_AT_ranges (0x00000000
|
||||
CHECK: [0x0000000100000f94, 0x0000000100000f9a)
|
||||
@ -197,3 +197,194 @@ CHECK-NEXT: length = 0x0000001f version = 0x0002 unit_offset = 0x00000000 unit_s
|
||||
CHECK-NEXT: Offset Name
|
||||
CHECK-NEXT: 0x00000063 "int"
|
||||
CHECK-NEXT: 0x00000079 "char"
|
||||
|
||||
CHECK: .apple_names contents:
|
||||
CHECK-NEXT: Header {
|
||||
CHECK-NEXT: Magic: 0x48415348
|
||||
CHECK-NEXT: Version: 0x1
|
||||
CHECK-NEXT: Hash function: 0x0
|
||||
CHECK-NEXT: Bucket count: 7
|
||||
CHECK-NEXT: Hashes count: 7
|
||||
CHECK-NEXT: HeaderData length: 12
|
||||
CHECK-NEXT: }
|
||||
CHECK-NEXT: DIE offset base: 0
|
||||
CHECK-NEXT: Number of atoms: 1
|
||||
CHECK-NEXT: Atoms [
|
||||
CHECK-NEXT: Atom 0 {
|
||||
CHECK-NEXT: Type: DW_ATOM_die_offset
|
||||
CHECK-NEXT: Form: DW_FORM_data4
|
||||
CHECK-NEXT: }
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: Bucket 0 [
|
||||
CHECK-NEXT: Hash 0xb8860c2 [
|
||||
CHECK-NEXT: Name@0x74 {
|
||||
CHECK-NEXT: String: 0x0000007e "baz"
|
||||
CHECK-NEXT: Data 0 [
|
||||
CHECK-NEXT: Atom[0]: 0x000000c0
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: }
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: Hash 0xb88801f [
|
||||
CHECK-NEXT: Name@0x84 {
|
||||
CHECK-NEXT: String: 0x0000008a "inc"
|
||||
CHECK-NEXT: Data 0 [
|
||||
CHECK-NEXT: Atom[0]: 0x00000110
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: Data 1 [
|
||||
CHECK-NEXT: Atom[0]: 0x000001c7
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: }
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: Bucket 1 [
|
||||
CHECK-NEXT: EMPTY
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: Bucket 2 [
|
||||
CHECK-NEXT: Hash 0xfed12c6a [
|
||||
CHECK-NEXT: Name@0x98 {
|
||||
CHECK-NEXT: String: 0x00000072 "private_int"
|
||||
CHECK-NEXT: Data 0 [
|
||||
CHECK-NEXT: Atom[0]: 0x000000a7
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: }
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: Bucket 3 [
|
||||
CHECK-NEXT: Hash 0xb88b5c8 [
|
||||
CHECK-NEXT: Name@0xa8 {
|
||||
CHECK-NEXT: String: 0x00000097 "val"
|
||||
CHECK-NEXT: Data 0 [
|
||||
CHECK-NEXT: Atom[0]: 0x00000160
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: }
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: Hash 0x7c9a7f6a [
|
||||
CHECK-NEXT: Name@0xb8 {
|
||||
CHECK-NEXT: String: 0x00000051 "main"
|
||||
CHECK-NEXT: Data 0 [
|
||||
CHECK-NEXT: Atom[0]: 0x00000026
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: }
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: Bucket 4 [
|
||||
CHECK-NEXT: EMPTY
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: Bucket 5 [
|
||||
CHECK-NEXT: Hash 0xb887389 [
|
||||
CHECK-NEXT: Name@0xc8 {
|
||||
CHECK-NEXT: String: 0x00000082 "foo"
|
||||
CHECK-NEXT: Data 0 [
|
||||
CHECK-NEXT: Atom[0]: 0x000000d9
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: }
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: Bucket 6 [
|
||||
CHECK-NEXT: Hash 0xb8860ba [
|
||||
CHECK-NEXT: Name@0xd8 {
|
||||
CHECK-NEXT: String: 0x0000009b "bar"
|
||||
CHECK-NEXT: Data 0 [
|
||||
CHECK-NEXT: Atom[0]: 0x0000017f
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: }
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: ]
|
||||
|
||||
CHECK: apple_types contents:
|
||||
CHECK-NEXT: Header {
|
||||
CHECK-NEXT: Magic: 0x48415348
|
||||
CHECK-NEXT: Version: 0x1
|
||||
CHECK-NEXT: Hash function: 0x0
|
||||
CHECK-NEXT: Bucket count: 2
|
||||
CHECK-NEXT: Hashes count: 2
|
||||
CHECK-NEXT: HeaderData length: 24
|
||||
CHECK-NEXT: }
|
||||
CHECK-NEXT: DIE offset base: 0
|
||||
CHECK-NEXT: Number of atoms: 4
|
||||
CHECK-NEXT: Atoms [
|
||||
CHECK-NEXT: Atom 0 {
|
||||
CHECK-NEXT: Type: DW_ATOM_die_offset
|
||||
CHECK-NEXT: Form: DW_FORM_data4
|
||||
CHECK-NEXT: }
|
||||
CHECK-NEXT: Atom 1 {
|
||||
CHECK-NEXT: Type: DW_ATOM_die_tag
|
||||
CHECK-NEXT: Form: DW_FORM_data2
|
||||
CHECK-NEXT: }
|
||||
CHECK-NEXT: Atom 2 {
|
||||
CHECK-NEXT: Type: DW_ATOM_type_flags
|
||||
CHECK-NEXT: Form: DW_FORM_data1
|
||||
CHECK-NEXT: }
|
||||
CHECK-NEXT: Atom 3 {
|
||||
CHECK-NEXT: Type: DW_ATOM_qual_name_hash
|
||||
CHECK-NEXT: Form: DW_FORM_data4
|
||||
CHECK-NEXT: }
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: Bucket 0 [
|
||||
CHECK-NEXT: Hash 0xb888030 [
|
||||
CHECK-NEXT: Name@0x44 {
|
||||
CHECK-NEXT: String: 0x00000060 "int"
|
||||
CHECK-NEXT: Data 0 [
|
||||
CHECK-NEXT: Atom[0]: 0x00000063
|
||||
CHECK-NEXT: Atom[1]: 0x0024
|
||||
CHECK-NEXT: Atom[2]: 0x00
|
||||
CHECK-NEXT: Atom[3]: 0x0c3a28a4
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: }
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: Bucket 1 [
|
||||
CHECK-NEXT: Hash 0x7c952063 [
|
||||
CHECK-NEXT: Name@0x5b {
|
||||
CHECK-NEXT: String: 0x00000064 "char"
|
||||
CHECK-NEXT: Data 0 [
|
||||
CHECK-NEXT: Atom[0]: 0x00000079
|
||||
CHECK-NEXT: Atom[1]: 0x0024
|
||||
CHECK-NEXT: Atom[2]: 0x00
|
||||
CHECK-NEXT: Atom[3]: 0x937bd757
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: }
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: ]
|
||||
|
||||
CHECK: .apple_namespaces contents:
|
||||
CHECK-NEXT: Header {
|
||||
CHECK-NEXT: Magic: 0x48415348
|
||||
CHECK-NEXT: Version: 0x1
|
||||
CHECK-NEXT: Hash function: 0x0
|
||||
CHECK-NEXT: Bucket count: 1
|
||||
CHECK-NEXT: Hashes count: 0
|
||||
CHECK-NEXT: HeaderData length: 12
|
||||
CHECK-NEXT: }
|
||||
CHECK-NEXT: DIE offset base: 0
|
||||
CHECK-NEXT: Number of atoms: 1
|
||||
CHECK-NEXT: Atoms [
|
||||
CHECK-NEXT: Atom 0 {
|
||||
CHECK-NEXT: Type: DW_ATOM_die_offset
|
||||
CHECK-NEXT: Form: DW_FORM_data4
|
||||
CHECK-NEXT: }
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: Bucket 0 [
|
||||
CHECK-NEXT: EMPTY
|
||||
CHECK-NEXT: ]
|
||||
|
||||
CHECK: .apple_objc contents:
|
||||
CHECK-NEXT: Header {
|
||||
CHECK-NEXT: Magic: 0x48415348
|
||||
CHECK-NEXT: Version: 0x1
|
||||
CHECK-NEXT: Hash function: 0x0
|
||||
CHECK-NEXT: Bucket count: 1
|
||||
CHECK-NEXT: Hashes count: 0
|
||||
CHECK-NEXT: HeaderData length: 12
|
||||
CHECK-NEXT: }
|
||||
CHECK-NEXT: DIE offset base: 0
|
||||
CHECK-NEXT: Number of atoms: 1
|
||||
CHECK-NEXT: Atoms [
|
||||
CHECK-NEXT: Atom 0 {
|
||||
CHECK-NEXT: Type: DW_ATOM_die_offset
|
||||
CHECK-NEXT: Form: DW_FORM_data4
|
||||
CHECK-NEXT: }
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: Bucket 0 [
|
||||
CHECK-NEXT: EMPTY
|
||||
CHECK-NEXT: ]
|
||||
|
52
test/tools/dsymutil/X86/objc.test
Normal file
52
test/tools/dsymutil/X86/objc.test
Normal file
@ -0,0 +1,52 @@
|
||||
RUN: llvm-dsymutil -f -oso-prepend-path=%p/.. %p/../Inputs/objc.macho.x86_64 -o - \
|
||||
RUN: | llvm-dwarfdump -apple-types -apple-objc - | FileCheck %s
|
||||
|
||||
CHECK: .apple_types contents:
|
||||
CHECK: String: 0x00000066 "A"
|
||||
CHECK-NEXT: Data 0 [
|
||||
CHECK-NEXT: Atom[0]: 0x0000012d
|
||||
CHECK-NEXT: Atom[1]: 0x0013
|
||||
CHECK-NEXT: Atom[2]: 0x02
|
||||
CHECK-NEXT: Atom[3]: 0x0b87b15a
|
||||
CHECK-NEXT: ]
|
||||
|
||||
CHECK: .apple_objc contents:
|
||||
CHECK-NEXT: Header {
|
||||
CHECK-NEXT: Magic: 0x48415348
|
||||
CHECK-NEXT: Version: 0x1
|
||||
CHECK-NEXT: Hash function: 0x0
|
||||
CHECK-NEXT: Bucket count: 2
|
||||
CHECK-NEXT: Hashes count: 2
|
||||
CHECK-NEXT: HeaderData length: 12
|
||||
CHECK-NEXT: }
|
||||
CHECK-NEXT: DIE offset base: 0
|
||||
CHECK-NEXT: Number of atoms: 1
|
||||
CHECK-NEXT: Atoms [
|
||||
CHECK-NEXT: Atom 0 {
|
||||
CHECK-NEXT: Type: DW_ATOM_die_offset
|
||||
CHECK-NEXT: Form: DW_FORM_data4
|
||||
CHECK-NEXT: }
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: Bucket 0 [
|
||||
CHECK-NEXT: Hash 0x2b5e6 [
|
||||
CHECK-NEXT: Name@0x38 {
|
||||
CHECK-NEXT: String: 0x00000066 "A"
|
||||
CHECK-NEXT: Data 0 [
|
||||
CHECK-NEXT: Atom[0]: 0x00000027
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: Data 1 [
|
||||
CHECK-NEXT: Atom[0]: 0x0000007a
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: }
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: Bucket 1 [
|
||||
CHECK-NEXT: Hash 0x3fa0f4b5 [
|
||||
CHECK-NEXT: Name@0x4c {
|
||||
CHECK-NEXT: String: 0x0000009d "A(Category)"
|
||||
CHECK-NEXT: Data 0 [
|
||||
CHECK-NEXT: Atom[0]: 0x0000007a
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: }
|
||||
CHECK-NEXT: ]
|
||||
CHECK-NEXT: ]
|
@ -30,6 +30,7 @@
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/BinaryFormat/Dwarf.h"
|
||||
#include "llvm/BinaryFormat/MachO.h"
|
||||
#include "llvm/CodeGen/AccelTable.h"
|
||||
#include "llvm/CodeGen/AsmPrinter.h"
|
||||
#include "llvm/CodeGen/DIE.h"
|
||||
#include "llvm/Config/config.h"
|
||||
@ -62,6 +63,7 @@
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/DJB.h"
|
||||
#include "llvm/Support/DataExtractor.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
@ -357,29 +359,56 @@ public:
|
||||
/// debug_loc section.
|
||||
void noteLocationAttribute(PatchLocation Attr, int64_t PcOffset);
|
||||
|
||||
/// Add a name accelerator entry for \p Die with \p Name which is stored in
|
||||
/// the string table at \p Offset.
|
||||
void addNameAccelerator(const DIE *Die, const char *Name, uint32_t Offset,
|
||||
/// Add a name accelerator entry for \a Die with \a Name.
|
||||
void addNamespaceAccelerator(const DIE *Die, DwarfStringPoolEntryRef Name);
|
||||
|
||||
/// Add a name accelerator entry for \a Die with \a Name.
|
||||
void addNameAccelerator(const DIE *Die, DwarfStringPoolEntryRef Name,
|
||||
bool SkipPubnamesSection = false);
|
||||
|
||||
/// Add various accelerator entries for \p Die with \p Name which is stored
|
||||
/// in the string table at \p Offset. \p Name must be an Objective-C
|
||||
/// selector.
|
||||
void addObjCAccelerator(const DIE *Die, DwarfStringPoolEntryRef Name,
|
||||
bool SkipPubnamesSection = false);
|
||||
|
||||
/// Add a type accelerator entry for \p Die with \p Name which is stored in
|
||||
/// the string table at \p Offset.
|
||||
void addTypeAccelerator(const DIE *Die, const char *Name, uint32_t Offset);
|
||||
void addTypeAccelerator(const DIE *Die, DwarfStringPoolEntryRef Name,
|
||||
bool ObjcClassImplementation,
|
||||
uint32_t QualifiedNameHash);
|
||||
|
||||
struct AccelInfo {
|
||||
StringRef Name; ///< Name of the entry.
|
||||
const DIE *Die; ///< DIE this entry describes.
|
||||
uint32_t NameOffset; ///< Offset of Name in the string pool.
|
||||
bool SkipPubSection; ///< Emit this entry only in the apple_* sections.
|
||||
/// Name of the entry.
|
||||
DwarfStringPoolEntryRef Name;
|
||||
|
||||
AccelInfo(StringRef Name, const DIE *Die, uint32_t NameOffset,
|
||||
/// DIE this entry describes.
|
||||
const DIE *Die;
|
||||
|
||||
/// Hash of the fully qualified name.
|
||||
uint32_t QualifiedNameHash;
|
||||
|
||||
/// Emit this entry only in the apple_* sections.
|
||||
bool SkipPubSection;
|
||||
|
||||
/// Is this an ObjC class implem?
|
||||
bool ObjcClassImplementation;
|
||||
|
||||
AccelInfo(DwarfStringPoolEntryRef Name, const DIE *Die,
|
||||
bool SkipPubSection = false)
|
||||
: Name(Name), Die(Die), NameOffset(NameOffset),
|
||||
SkipPubSection(SkipPubSection) {}
|
||||
: Name(Name), Die(Die), SkipPubSection(SkipPubSection) {}
|
||||
|
||||
AccelInfo(DwarfStringPoolEntryRef Name, const DIE *Die,
|
||||
uint32_t QualifiedNameHash, bool ObjCClassIsImplementation)
|
||||
: Name(Name), Die(Die), QualifiedNameHash(QualifiedNameHash),
|
||||
SkipPubSection(false),
|
||||
ObjcClassImplementation(ObjCClassIsImplementation) {}
|
||||
};
|
||||
|
||||
const std::vector<AccelInfo> &getPubnames() const { return Pubnames; }
|
||||
const std::vector<AccelInfo> &getPubtypes() const { return Pubtypes; }
|
||||
const std::vector<AccelInfo> &getNamespaces() const { return Namespaces; }
|
||||
const std::vector<AccelInfo> &getObjC() const { return ObjC; }
|
||||
|
||||
/// Get the full path for file \a FileNum in the line table
|
||||
StringRef getResolvedPath(unsigned FileNum) {
|
||||
@ -442,6 +471,8 @@ private:
|
||||
/// @{
|
||||
std::vector<AccelInfo> Pubnames;
|
||||
std::vector<AccelInfo> Pubtypes;
|
||||
std::vector<AccelInfo> Namespaces;
|
||||
std::vector<AccelInfo> ObjC;
|
||||
/// @}
|
||||
|
||||
/// Cached resolved paths from the line table.
|
||||
@ -518,18 +549,28 @@ void CompileUnit::noteLocationAttribute(PatchLocation Attr, int64_t PcOffset) {
|
||||
LocationAttributes.emplace_back(Attr, PcOffset);
|
||||
}
|
||||
|
||||
/// Add a name accelerator entry for \p Die with \p Name
|
||||
/// which is stored in the string table at \p Offset.
|
||||
void CompileUnit::addNameAccelerator(const DIE *Die, const char *Name,
|
||||
uint32_t Offset, bool SkipPubSection) {
|
||||
Pubnames.emplace_back(Name, Die, Offset, SkipPubSection);
|
||||
void CompileUnit::addNamespaceAccelerator(const DIE *Die,
|
||||
DwarfStringPoolEntryRef Name) {
|
||||
Namespaces.emplace_back(Name, Die);
|
||||
}
|
||||
|
||||
/// Add a type accelerator entry for \p Die with \p Name
|
||||
/// which is stored in the string table at \p Offset.
|
||||
void CompileUnit::addTypeAccelerator(const DIE *Die, const char *Name,
|
||||
uint32_t Offset) {
|
||||
Pubtypes.emplace_back(Name, Die, Offset, false);
|
||||
void CompileUnit::addObjCAccelerator(const DIE *Die,
|
||||
DwarfStringPoolEntryRef Name,
|
||||
bool SkipPubSection) {
|
||||
ObjC.emplace_back(Name, Die, SkipPubSection);
|
||||
}
|
||||
|
||||
void CompileUnit::addNameAccelerator(const DIE *Die,
|
||||
DwarfStringPoolEntryRef Name,
|
||||
bool SkipPubSection) {
|
||||
Pubnames.emplace_back(Name, Die, SkipPubSection);
|
||||
}
|
||||
|
||||
void CompileUnit::addTypeAccelerator(const DIE *Die,
|
||||
DwarfStringPoolEntryRef Name,
|
||||
bool ObjcClassImplementation,
|
||||
uint32_t QualifiedNameHash) {
|
||||
Pubtypes.emplace_back(Name, Die, QualifiedNameHash, ObjcClassImplementation);
|
||||
}
|
||||
|
||||
namespace {
|
||||
@ -642,6 +683,19 @@ public:
|
||||
void emitFDE(uint32_t CIEOffset, uint32_t AddreSize, uint32_t Address,
|
||||
StringRef Bytes);
|
||||
|
||||
/// Emit Apple namespaces accelerator table.
|
||||
void
|
||||
emitAppleNamespaces(AppleAccelTable<AppleAccelTableStaticOffsetData> &Table);
|
||||
|
||||
/// Emit Apple names accelerator table.
|
||||
void emitAppleNames(AppleAccelTable<AppleAccelTableStaticOffsetData> &Table);
|
||||
|
||||
/// Emit Apple Objective-C accelerator table.
|
||||
void emitAppleObjc(AppleAccelTable<AppleAccelTableStaticOffsetData> &Table);
|
||||
|
||||
/// Emit Apple type accelerator table.
|
||||
void emitAppleTypes(AppleAccelTable<AppleAccelTableStaticTypeData> &Table);
|
||||
|
||||
uint32_t getFrameSectionSize() const { return FrameSectionSize; }
|
||||
};
|
||||
|
||||
@ -779,11 +833,49 @@ void DwarfStreamer::emitStrings(const NonRelocatableStringpool &Pool) {
|
||||
for (auto Entry : Entries) {
|
||||
if (Entry.getIndex() == -1U)
|
||||
break;
|
||||
Asm->OutStreamer->EmitBytes(
|
||||
StringRef(Entry.getString().data(), Entry.getString().size() + 1));
|
||||
// Emit the string itself.
|
||||
Asm->OutStreamer->EmitBytes(Entry.getString());
|
||||
// Emit a null terminator.
|
||||
Asm->EmitInt8(0);
|
||||
}
|
||||
}
|
||||
|
||||
void DwarfStreamer::emitAppleNamespaces(
|
||||
AppleAccelTable<AppleAccelTableStaticOffsetData> &Table) {
|
||||
Asm->OutStreamer->SwitchSection(MOFI->getDwarfAccelNamespaceSection());
|
||||
Table.finalizeTable(Asm.get(), "namespac");
|
||||
auto *SectionBegin = Asm->createTempSymbol("namespac_begin");
|
||||
Asm->OutStreamer->EmitLabel(SectionBegin);
|
||||
Table.emit(Asm.get(), SectionBegin);
|
||||
}
|
||||
|
||||
void DwarfStreamer::emitAppleNames(
|
||||
AppleAccelTable<AppleAccelTableStaticOffsetData> &Table) {
|
||||
Asm->OutStreamer->SwitchSection(MOFI->getDwarfAccelNamesSection());
|
||||
Table.finalizeTable(Asm.get(), "names");
|
||||
auto *SectionBegin = Asm->createTempSymbol("names_begin");
|
||||
Asm->OutStreamer->EmitLabel(SectionBegin);
|
||||
Table.emit(Asm.get(), SectionBegin);
|
||||
}
|
||||
|
||||
void DwarfStreamer::emitAppleObjc(
|
||||
AppleAccelTable<AppleAccelTableStaticOffsetData> &Table) {
|
||||
Asm->OutStreamer->SwitchSection(MOFI->getDwarfAccelObjCSection());
|
||||
Table.finalizeTable(Asm.get(), "objc");
|
||||
auto *SectionBegin = Asm->createTempSymbol("objc_begin");
|
||||
Asm->OutStreamer->EmitLabel(SectionBegin);
|
||||
Table.emit(Asm.get(), SectionBegin);
|
||||
}
|
||||
|
||||
void DwarfStreamer::emitAppleTypes(
|
||||
AppleAccelTable<AppleAccelTableStaticTypeData> &Table) {
|
||||
Asm->OutStreamer->SwitchSection(MOFI->getDwarfAccelTypesSection());
|
||||
Table.finalizeTable(Asm.get(), "types");
|
||||
auto *SectionBegin = Asm->createTempSymbol("types_begin");
|
||||
Asm->OutStreamer->EmitLabel(SectionBegin);
|
||||
Table.emit(Asm.get(), SectionBegin);
|
||||
}
|
||||
|
||||
/// Emit the swift_ast section stored in \p Buffers.
|
||||
void DwarfStreamer::emitSwiftAST(StringRef Buffer) {
|
||||
MCSection *SwiftASTSection = MOFI->getDwarfSwiftASTSection();
|
||||
@ -1137,8 +1229,11 @@ void DwarfStreamer::emitPubSectionForUnit(
|
||||
HeaderEmitted = true;
|
||||
}
|
||||
Asm->EmitInt32(Name.Die->getOffset());
|
||||
Asm->OutStreamer->EmitBytes(
|
||||
StringRef(Name.Name.data(), Name.Name.size() + 1));
|
||||
|
||||
// Emit the string itself.
|
||||
Asm->OutStreamer->EmitBytes(Name.Name.getString());
|
||||
// Emit a null terminator.
|
||||
Asm->EmitInt8(0);
|
||||
}
|
||||
|
||||
if (!HeaderEmitted)
|
||||
@ -1396,8 +1491,7 @@ private:
|
||||
/// clone*Attributes helpers about the attributes of a particular DIE.
|
||||
struct AttributesInfo {
|
||||
/// Names.
|
||||
const char *Name = nullptr;
|
||||
const char *MangledName = nullptr;
|
||||
DwarfStringPoolEntryRef Name, MangledName, NameWithoutTemplate;
|
||||
|
||||
/// Offsets in the string pool.
|
||||
uint32_t NameOffset = 0;
|
||||
@ -1415,6 +1509,9 @@ private:
|
||||
/// Does the DIE have a low_pc attribute?
|
||||
bool HasLowPc = false;
|
||||
|
||||
/// Does the DIE have a ranges attribute?
|
||||
bool HasRanges = false;
|
||||
|
||||
/// Is this DIE only a declaration?
|
||||
bool IsDeclaration = false;
|
||||
|
||||
@ -1470,10 +1567,18 @@ private:
|
||||
/// described by \p Die and store them in \Info if they are not
|
||||
/// already there.
|
||||
/// \returns is a name was found.
|
||||
bool getDIENames(const DWARFDie &Die, AttributesInfo &Info);
|
||||
bool getDIENames(const DWARFDie &Die, AttributesInfo &Info,
|
||||
bool StripTemplate = false);
|
||||
|
||||
/// Create a copy of abbreviation Abbrev.
|
||||
void copyAbbrev(const DWARFAbbreviationDeclaration &Abbrev, bool hasODR);
|
||||
|
||||
uint32_t hashFullyQualifiedName(DWARFDie DIE, CompileUnit &U,
|
||||
int RecurseDepth = 0);
|
||||
|
||||
/// Helper for cloneDIE.
|
||||
void addObjCAccelerator(CompileUnit &Unit, const DIE *Die,
|
||||
DwarfStringPoolEntryRef Name, bool SkipPubSection);
|
||||
};
|
||||
|
||||
/// Assign an abbreviation number to \p Abbrev
|
||||
@ -1569,6 +1674,12 @@ private:
|
||||
/// debug_frame section.
|
||||
uint32_t LastCIEOffset = 0;
|
||||
|
||||
/// Apple accelerator tables.
|
||||
AppleAccelTable<AppleAccelTableStaticOffsetData> AppleNames;
|
||||
AppleAccelTable<AppleAccelTableStaticOffsetData> AppleNamespaces;
|
||||
AppleAccelTable<AppleAccelTableStaticOffsetData> AppleObjc;
|
||||
AppleAccelTable<AppleAccelTableStaticTypeData> AppleTypes;
|
||||
|
||||
/// Mapping the PCM filename to the DwoId.
|
||||
StringMap<uint64_t> ClangModules;
|
||||
|
||||
@ -1829,16 +1940,30 @@ PointerIntPair<DeclContext *, 1> DeclContextTree::getChildDeclContext(
|
||||
}
|
||||
|
||||
bool DwarfLinker::DIECloner::getDIENames(const DWARFDie &Die,
|
||||
AttributesInfo &Info) {
|
||||
AttributesInfo &Info,
|
||||
bool StripTemplate) {
|
||||
// This function will be called on DIEs having low_pcs and
|
||||
// ranges. As getting the name might be more expansive, filter out
|
||||
// blocks directly.
|
||||
if (Die.getTag() == dwarf::DW_TAG_lexical_block)
|
||||
return false;
|
||||
|
||||
// FIXME: a bit wasteful as the first getName might return the
|
||||
// short name.
|
||||
if (!Info.MangledName &&
|
||||
(Info.MangledName = Die.getName(DINameKind::LinkageName)))
|
||||
Info.MangledNameOffset =
|
||||
Linker.StringPool.getStringOffset(Info.MangledName);
|
||||
if (!Info.MangledName)
|
||||
if (const char *MangledName = Die.getName(DINameKind::LinkageName))
|
||||
Info.MangledName = Linker.StringPool.getEntry(MangledName);
|
||||
|
||||
if (!Info.Name && (Info.Name = Die.getName(DINameKind::ShortName)))
|
||||
Info.NameOffset = Linker.StringPool.getStringOffset(Info.Name);
|
||||
if (!Info.Name)
|
||||
if (const char *Name = Die.getName(DINameKind::ShortName))
|
||||
Info.Name = Linker.StringPool.getEntry(Name);
|
||||
|
||||
if (StripTemplate && Info.Name && Info.MangledName != Info.Name) {
|
||||
// FIXME: dsymutil compatibility. This is wrong for operator<
|
||||
auto Split = Info.Name.getString().split('<');
|
||||
if (!Split.second.empty())
|
||||
Info.NameWithoutTemplate = Linker.StringPool.getEntry(Split.first);
|
||||
}
|
||||
|
||||
return Info.Name || Info.MangledName;
|
||||
}
|
||||
@ -2623,6 +2748,7 @@ unsigned DwarfLinker::DIECloner::cloneAddressAttribute(
|
||||
DIE &Die, AttributeSpec AttrSpec, const DWARFFormValue &Val,
|
||||
const CompileUnit &Unit, AttributesInfo &Info) {
|
||||
uint64_t Addr = *Val.getAsAddress();
|
||||
|
||||
if (AttrSpec.Attr == dwarf::DW_AT_low_pc) {
|
||||
if (Die.getTag() == dwarf::DW_TAG_inlined_subroutine ||
|
||||
Die.getTag() == dwarf::DW_TAG_lexical_block)
|
||||
@ -2684,8 +2810,10 @@ unsigned DwarfLinker::DIECloner::cloneScalarAttribute(
|
||||
PatchLocation Patch =
|
||||
Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr),
|
||||
dwarf::Form(AttrSpec.Form), DIEInteger(Value));
|
||||
if (AttrSpec.Attr == dwarf::DW_AT_ranges)
|
||||
if (AttrSpec.Attr == dwarf::DW_AT_ranges) {
|
||||
Unit.noteRangeAttribute(Die, Patch);
|
||||
Info.HasRanges = true;
|
||||
}
|
||||
|
||||
// A more generic way to check for location attributes would be
|
||||
// nice, but it's very unlikely that any other attribute needs a
|
||||
@ -2825,6 +2953,55 @@ static bool isTypeTag(uint16_t Tag) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool isObjCSelector(StringRef Name) {
|
||||
return Name.size() > 2 && (Name[0] == '-' || Name[0] == '+') &&
|
||||
(Name[1] == '[');
|
||||
}
|
||||
|
||||
void DwarfLinker::DIECloner::addObjCAccelerator(CompileUnit &Unit,
|
||||
const DIE *Die,
|
||||
DwarfStringPoolEntryRef Name,
|
||||
bool SkipPubSection) {
|
||||
assert(isObjCSelector(Name.getString()) && "not an objc selector");
|
||||
// Objective C method or class function.
|
||||
// "- [Class(Category) selector :withArg ...]"
|
||||
StringRef ClassNameStart(Name.getString().drop_front(2));
|
||||
size_t FirstSpace = ClassNameStart.find(' ');
|
||||
if (FirstSpace == StringRef::npos)
|
||||
return;
|
||||
|
||||
StringRef SelectorStart(ClassNameStart.data() + FirstSpace + 1);
|
||||
if (!SelectorStart.size())
|
||||
return;
|
||||
|
||||
StringRef Selector(SelectorStart.data(), SelectorStart.size() - 1);
|
||||
Unit.addNameAccelerator(Die, Linker.StringPool.getEntry(Selector),
|
||||
SkipPubSection);
|
||||
|
||||
// Add an entry for the class name that points to this
|
||||
// method/class function.
|
||||
StringRef ClassName(ClassNameStart.data(), FirstSpace);
|
||||
Unit.addObjCAccelerator(Die, Linker.StringPool.getEntry(ClassName),
|
||||
SkipPubSection);
|
||||
|
||||
if (ClassName[ClassName.size() - 1] == ')') {
|
||||
size_t OpenParens = ClassName.find('(');
|
||||
if (OpenParens != StringRef::npos) {
|
||||
StringRef ClassNameNoCategory(ClassName.data(), OpenParens);
|
||||
Unit.addObjCAccelerator(
|
||||
Die, Linker.StringPool.getEntry(ClassNameNoCategory), SkipPubSection);
|
||||
|
||||
std::string MethodNameNoCategory(Name.getString().data(), OpenParens + 2);
|
||||
// FIXME: The missing space here may be a bug, but
|
||||
// dsymutil-classic also does it this way.
|
||||
MethodNameNoCategory.append(SelectorStart);
|
||||
Unit.addNameAccelerator(Die,
|
||||
Linker.StringPool.getEntry(MethodNameNoCategory),
|
||||
SkipPubSection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
shouldSkipAttribute(DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
|
||||
uint16_t Tag, bool InDebugMap, bool SkipPC,
|
||||
@ -2965,25 +3142,46 @@ DIE *DwarfLinker::DIECloner::cloneDIE(
|
||||
// FIXME: This is slightly wrong. An inline_subroutine without a
|
||||
// low_pc, but with AT_ranges might be interesting to get into the
|
||||
// accelerator tables too. For now stick with dsymutil's behavior.
|
||||
if ((Info.InDebugMap || AttrInfo.HasLowPc) &&
|
||||
if ((Info.InDebugMap || AttrInfo.HasLowPc || AttrInfo.HasRanges) &&
|
||||
Tag != dwarf::DW_TAG_compile_unit &&
|
||||
getDIENames(InputDIE, AttrInfo)) {
|
||||
getDIENames(InputDIE, AttrInfo,
|
||||
Tag != dwarf::DW_TAG_inlined_subroutine)) {
|
||||
if (AttrInfo.MangledName && AttrInfo.MangledName != AttrInfo.Name)
|
||||
Unit.addNameAccelerator(Die, AttrInfo.MangledName,
|
||||
AttrInfo.MangledNameOffset,
|
||||
Tag == dwarf::DW_TAG_inlined_subroutine);
|
||||
if (AttrInfo.Name)
|
||||
Unit.addNameAccelerator(Die, AttrInfo.Name, AttrInfo.NameOffset,
|
||||
if (AttrInfo.Name) {
|
||||
if (AttrInfo.NameWithoutTemplate)
|
||||
Unit.addNameAccelerator(Die, AttrInfo.NameWithoutTemplate,
|
||||
/* SkipPubSection */ true);
|
||||
Unit.addNameAccelerator(Die, AttrInfo.Name,
|
||||
Tag == dwarf::DW_TAG_inlined_subroutine);
|
||||
}
|
||||
if (AttrInfo.Name && isObjCSelector(AttrInfo.Name.getString()))
|
||||
addObjCAccelerator(Unit, Die, AttrInfo.Name, /* SkipPubSection =*/true);
|
||||
|
||||
} else if (Tag == dwarf::DW_TAG_namespace) {
|
||||
if (!AttrInfo.Name)
|
||||
AttrInfo.Name = Linker.StringPool.getEntry("(anonymous namespace)");
|
||||
Unit.addNamespaceAccelerator(Die, AttrInfo.Name);
|
||||
} else if (isTypeTag(Tag) && !AttrInfo.IsDeclaration &&
|
||||
getDIENames(InputDIE, AttrInfo)) {
|
||||
if (AttrInfo.Name)
|
||||
Unit.addTypeAccelerator(Die, AttrInfo.Name, AttrInfo.NameOffset);
|
||||
getDIENames(InputDIE, AttrInfo) && AttrInfo.Name &&
|
||||
AttrInfo.Name.getString()[0]) {
|
||||
uint32_t Hash = hashFullyQualifiedName(InputDIE, Unit);
|
||||
uint64_t RuntimeLang =
|
||||
dwarf::toUnsigned(InputDIE.find(dwarf::DW_AT_APPLE_runtime_class))
|
||||
.getValueOr(0);
|
||||
bool ObjCClassIsImplementation =
|
||||
(RuntimeLang == dwarf::DW_LANG_ObjC ||
|
||||
RuntimeLang == dwarf::DW_LANG_ObjC_plus_plus) &&
|
||||
dwarf::toUnsigned(InputDIE.find(dwarf::DW_AT_APPLE_objc_complete_type))
|
||||
.getValueOr(0);
|
||||
Unit.addTypeAccelerator(Die, AttrInfo.Name, ObjCClassIsImplementation,
|
||||
Hash);
|
||||
}
|
||||
|
||||
// Determine whether there are any children that we want to keep.
|
||||
bool HasChildren = false;
|
||||
for (auto Child: InputDIE.children()) {
|
||||
for (auto Child : InputDIE.children()) {
|
||||
unsigned Idx = U.getDIEIndex(Child);
|
||||
if (Unit.getInfo(Idx).Keep) {
|
||||
HasChildren = true;
|
||||
@ -3263,8 +3461,32 @@ void DwarfLinker::patchLineTableForUnit(CompileUnit &Unit,
|
||||
}
|
||||
|
||||
void DwarfLinker::emitAcceleratorEntriesForUnit(CompileUnit &Unit) {
|
||||
Streamer->emitPubNamesForUnit(Unit);
|
||||
Streamer->emitPubTypesForUnit(Unit);
|
||||
// Add namespaces.
|
||||
for (const auto &Namespace : Unit.getNamespaces())
|
||||
AppleNamespaces.addName(Namespace.Name,
|
||||
Namespace.Die->getOffset() + Unit.getStartOffset());
|
||||
|
||||
/// Add names.
|
||||
if (!Options.Minimize)
|
||||
Streamer->emitPubNamesForUnit(Unit);
|
||||
for (const auto &Pubname : Unit.getPubnames())
|
||||
AppleNames.addName(Pubname.Name,
|
||||
Pubname.Die->getOffset() + Unit.getStartOffset());
|
||||
|
||||
/// Add types.
|
||||
if (!Options.Minimize)
|
||||
Streamer->emitPubTypesForUnit(Unit);
|
||||
for (const auto &Pubtype : Unit.getPubtypes())
|
||||
AppleTypes.addName(
|
||||
Pubtype.Name, Pubtype.Die->getOffset() + Unit.getStartOffset(),
|
||||
Pubtype.Die->getTag(),
|
||||
Pubtype.ObjcClassImplementation ? dwarf::DW_FLAG_type_implementation
|
||||
: 0,
|
||||
Pubtype.QualifiedNameHash);
|
||||
|
||||
/// Add ObjC names.
|
||||
for (const auto &ObjC : Unit.getObjC())
|
||||
AppleObjc.addName(ObjC.Name, ObjC.Die->getOffset() + Unit.getStartOffset());
|
||||
}
|
||||
|
||||
/// Read the frame info stored in the object, and emit the
|
||||
@ -3367,6 +3589,50 @@ void DwarfLinker::DIECloner::copyAbbrev(
|
||||
Linker.AssignAbbrev(Copy);
|
||||
}
|
||||
|
||||
uint32_t DwarfLinker::DIECloner::hashFullyQualifiedName(DWARFDie DIE,
|
||||
CompileUnit &U,
|
||||
int RecurseDepth) {
|
||||
const char *Name = nullptr;
|
||||
DWARFUnit *OrigUnit = &U.getOrigUnit();
|
||||
CompileUnit *CU = &U;
|
||||
Optional<DWARFFormValue> Ref;
|
||||
|
||||
while (1) {
|
||||
if (const char *CurrentName = DIE.getName(DINameKind::ShortName))
|
||||
Name = CurrentName;
|
||||
|
||||
if (!(Ref = DIE.find(dwarf::DW_AT_specification)) &&
|
||||
!(Ref = DIE.find(dwarf::DW_AT_abstract_origin)))
|
||||
break;
|
||||
|
||||
if (!Ref->isFormClass(DWARFFormValue::FC_Reference))
|
||||
break;
|
||||
|
||||
CompileUnit *RefCU;
|
||||
if (auto RefDIE = resolveDIEReference(Linker, CompileUnits, *Ref,
|
||||
U.getOrigUnit(), DIE, RefCU)) {
|
||||
CU = RefCU;
|
||||
OrigUnit = &RefCU->getOrigUnit();
|
||||
DIE = RefDIE;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned Idx = OrigUnit->getDIEIndex(DIE);
|
||||
if (!Name && DIE.getTag() == dwarf::DW_TAG_namespace)
|
||||
Name = "(anonymous namespace)";
|
||||
|
||||
if (CU->getInfo(Idx).ParentIdx == 0 ||
|
||||
// FIXME: dsymutil-classic compatibility. Ignore modules.
|
||||
CU->getOrigUnit().getDIEAtIndex(CU->getInfo(Idx).ParentIdx).getTag() ==
|
||||
dwarf::DW_TAG_module)
|
||||
return djbHash(Name ? Name : "", djbHash(RecurseDepth ? "" : "::"));
|
||||
|
||||
DWARFDie Die = OrigUnit->getDIEAtIndex(CU->getInfo(Idx).ParentIdx);
|
||||
return djbHash((Name ? Name : ""),
|
||||
djbHash((Name ? "::" : ""),
|
||||
hashFullyQualifiedName(Die, *CU, ++RecurseDepth)));
|
||||
}
|
||||
|
||||
static uint64_t getDwoId(const DWARFDie &CUDie,
|
||||
const DWARFUnit &Unit) {
|
||||
auto DwoId = dwarf::toUnsigned(CUDie.find({dwarf::DW_AT_dwo_id,
|
||||
@ -3565,9 +3831,9 @@ void DwarfLinker::DIECloner::cloneAllCompileUnits(DWARFContext &DwarfContext) {
|
||||
// an empty line table for the unit, even if the unit doesn't
|
||||
// actually exist in the DIE tree.
|
||||
Linker.patchLineTableForUnit(*CurrentUnit, DwarfContext);
|
||||
Linker.emitAcceleratorEntriesForUnit(*CurrentUnit);
|
||||
Linker.patchRangesForUnit(*CurrentUnit, DwarfContext);
|
||||
Linker.Streamer->emitLocationsForUnit(*CurrentUnit, DwarfContext);
|
||||
Linker.emitAcceleratorEntriesForUnit(*CurrentUnit);
|
||||
}
|
||||
|
||||
if (Linker.Options.NoOutput)
|
||||
@ -3695,6 +3961,10 @@ bool DwarfLinker::link(const DebugMap &Map) {
|
||||
if (!Options.NoOutput) {
|
||||
Streamer->emitAbbrevs(Abbreviations, MaxDwarfVersion);
|
||||
Streamer->emitStrings(StringPool);
|
||||
Streamer->emitAppleNames(AppleNames);
|
||||
Streamer->emitAppleNamespaces(AppleNamespaces);
|
||||
Streamer->emitAppleTypes(AppleTypes);
|
||||
Streamer->emitAppleObjc(AppleObjc);
|
||||
}
|
||||
|
||||
return Options.NoOutput ? true : Streamer->finish(Map);
|
||||
|
@ -39,6 +39,9 @@ struct LinkOptions {
|
||||
/// Do not unique types according to ODR
|
||||
bool NoODR;
|
||||
|
||||
/// Minimize
|
||||
bool Minimize = false;
|
||||
|
||||
/// Do not check swiftmodule timestamp
|
||||
bool NoTimestamp = false;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user