forked from OSchip/llvm-project
[obj2yaml] [yaml2obj] Add yaml support for SHT_LLVM_BB_ADDR_MAP section.
YAML support allows us to better test the feature in the subsequent patches. The implementation is quite similar to the .stack_sizes section. Reviewed By: jhenderson, grimar Differential Revision: https://reviews.llvm.org/D88717
This commit is contained in:
parent
062b5c598f
commit
82e7c4ce45
|
@ -126,6 +126,16 @@ struct DynamicEntry {
|
|||
llvm::yaml::Hex64 Val;
|
||||
};
|
||||
|
||||
struct BBAddrMapEntry {
|
||||
struct BBEntry {
|
||||
llvm::yaml::Hex32 AddressOffset;
|
||||
llvm::yaml::Hex32 Size;
|
||||
llvm::yaml::Hex32 Metadata;
|
||||
};
|
||||
llvm::yaml::Hex64 Address;
|
||||
Optional<std::vector<BBEntry>> BBEntries;
|
||||
};
|
||||
|
||||
struct StackSizeEntry {
|
||||
llvm::yaml::Hex64 Address;
|
||||
llvm::yaml::Hex64 Size;
|
||||
|
@ -159,7 +169,8 @@ struct Chunk {
|
|||
Fill,
|
||||
LinkerOptions,
|
||||
DependentLibraries,
|
||||
CallGraphProfile
|
||||
CallGraphProfile,
|
||||
BBAddrMap
|
||||
};
|
||||
|
||||
ChunkKind Kind;
|
||||
|
@ -240,6 +251,16 @@ struct Fill : Chunk {
|
|||
static bool classof(const Chunk *S) { return S->Kind == ChunkKind::Fill; }
|
||||
};
|
||||
|
||||
struct BBAddrMapSection : Section {
|
||||
Optional<std::vector<BBAddrMapEntry>> Entries;
|
||||
|
||||
BBAddrMapSection() : Section(ChunkKind::BBAddrMap) {}
|
||||
|
||||
static bool classof(const Chunk *S) {
|
||||
return S->Kind == ChunkKind::BBAddrMap;
|
||||
}
|
||||
};
|
||||
|
||||
struct StackSizesSection : Section {
|
||||
Optional<std::vector<StackSizeEntry>> Entries;
|
||||
|
||||
|
@ -640,6 +661,8 @@ struct Object {
|
|||
} // end namespace llvm
|
||||
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::StackSizeEntry)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::BBAddrMapEntry)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::BBAddrMapEntry::BBEntry)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::DynamicEntry)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::LinkerOption)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::CallGraphEntry)
|
||||
|
@ -801,6 +824,14 @@ template <> struct MappingTraits<ELFYAML::StackSizeEntry> {
|
|||
static void mapping(IO &IO, ELFYAML::StackSizeEntry &Rel);
|
||||
};
|
||||
|
||||
template <> struct MappingTraits<ELFYAML::BBAddrMapEntry> {
|
||||
static void mapping(IO &IO, ELFYAML::BBAddrMapEntry &Rel);
|
||||
};
|
||||
|
||||
template <> struct MappingTraits<ELFYAML::BBAddrMapEntry::BBEntry> {
|
||||
static void mapping(IO &IO, ELFYAML::BBAddrMapEntry::BBEntry &Rel);
|
||||
};
|
||||
|
||||
template <> struct MappingTraits<ELFYAML::GnuHashHeader> {
|
||||
static void mapping(IO &IO, ELFYAML::GnuHashHeader &Rel);
|
||||
};
|
||||
|
|
|
@ -272,6 +272,9 @@ template <class ELFT> class ELFState {
|
|||
void writeSectionContent(Elf_Shdr &SHeader,
|
||||
const ELFYAML::StackSizesSection &Section,
|
||||
ContiguousBlobAccumulator &CBA);
|
||||
void writeSectionContent(Elf_Shdr &SHeader,
|
||||
const ELFYAML::BBAddrMapSection &Section,
|
||||
ContiguousBlobAccumulator &CBA);
|
||||
void writeSectionContent(Elf_Shdr &SHeader,
|
||||
const ELFYAML::HashSection &Section,
|
||||
ContiguousBlobAccumulator &CBA);
|
||||
|
@ -756,6 +759,8 @@ void ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
|
|||
writeSectionContent(SHeader, *S, CBA);
|
||||
} else if (auto S = dyn_cast<ELFYAML::CallGraphProfileSection>(Sec)) {
|
||||
writeSectionContent(SHeader, *S, CBA);
|
||||
} else if (auto S = dyn_cast<ELFYAML::BBAddrMapSection>(Sec)) {
|
||||
writeSectionContent(SHeader, *S, CBA);
|
||||
} else {
|
||||
llvm_unreachable("Unknown section type");
|
||||
}
|
||||
|
@ -1316,6 +1321,29 @@ void ELFState<ELFT>::writeSectionContent(
|
|||
}
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void ELFState<ELFT>::writeSectionContent(
|
||||
Elf_Shdr &SHeader, const ELFYAML::BBAddrMapSection &Section,
|
||||
ContiguousBlobAccumulator &CBA) {
|
||||
if (!Section.Entries)
|
||||
return;
|
||||
|
||||
for (const ELFYAML::BBAddrMapEntry &E : *Section.Entries) {
|
||||
// Write the address of the function.
|
||||
CBA.write<uintX_t>(E.Address, ELFT::TargetEndianness);
|
||||
// Write number of BBEntries (number of basic blocks in the function).
|
||||
size_t NumBlocks = E.BBEntries ? E.BBEntries->size() : 0;
|
||||
SHeader.sh_size += sizeof(uintX_t) + CBA.writeULEB128(NumBlocks);
|
||||
if (!NumBlocks)
|
||||
continue;
|
||||
// Write all BBEntries.
|
||||
for (const ELFYAML::BBAddrMapEntry::BBEntry &BBE : *E.BBEntries)
|
||||
SHeader.sh_size += CBA.writeULEB128(BBE.AddressOffset) +
|
||||
CBA.writeULEB128(BBE.Size) +
|
||||
CBA.writeULEB128(BBE.Metadata);
|
||||
}
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void ELFState<ELFT>::writeSectionContent(
|
||||
Elf_Shdr &SHeader, const ELFYAML::LinkerOptionsSection &Section,
|
||||
|
|
|
@ -492,6 +492,7 @@ void ScalarEnumerationTraits<ELFYAML::ELF_SHT>::enumeration(
|
|||
ECase(SHT_LLVM_SYMPART);
|
||||
ECase(SHT_LLVM_PART_EHDR);
|
||||
ECase(SHT_LLVM_PART_PHDR);
|
||||
ECase(SHT_LLVM_BB_ADDR_MAP);
|
||||
ECase(SHT_GNU_ATTRIBUTES);
|
||||
ECase(SHT_GNU_HASH);
|
||||
ECase(SHT_GNU_verdef);
|
||||
|
@ -1146,6 +1147,12 @@ static void sectionMapping(IO &IO, ELFYAML::RawContentSection &Section) {
|
|||
IO.mapOptional("Info", Section.Info);
|
||||
}
|
||||
|
||||
static void sectionMapping(IO &IO, ELFYAML::BBAddrMapSection &Section) {
|
||||
commonSectionMapping(IO, Section);
|
||||
IO.mapOptional("Content", Section.Content);
|
||||
IO.mapOptional("Entries", Section.Entries);
|
||||
}
|
||||
|
||||
static void sectionMapping(IO &IO, ELFYAML::StackSizesSection &Section) {
|
||||
commonSectionMapping(IO, Section);
|
||||
IO.mapOptional("Entries", Section.Entries);
|
||||
|
@ -1405,6 +1412,11 @@ void MappingTraits<std::unique_ptr<ELFYAML::Chunk>>::mapping(
|
|||
Section.reset(new ELFYAML::CallGraphProfileSection());
|
||||
sectionMapping(IO, *cast<ELFYAML::CallGraphProfileSection>(Section.get()));
|
||||
break;
|
||||
case ELF::SHT_LLVM_BB_ADDR_MAP:
|
||||
if (!IO.outputting())
|
||||
Section.reset(new ELFYAML::BBAddrMapSection());
|
||||
sectionMapping(IO, *cast<ELFYAML::BBAddrMapSection>(Section.get()));
|
||||
break;
|
||||
default:
|
||||
if (!IO.outputting()) {
|
||||
StringRef Name;
|
||||
|
@ -1485,6 +1497,12 @@ std::string MappingTraits<std::unique_ptr<ELFYAML::Chunk>>::validate(
|
|||
return "";
|
||||
}
|
||||
|
||||
if (const auto *BBAM = dyn_cast<ELFYAML::BBAddrMapSection>(C.get())) {
|
||||
if ((BBAM->Content || BBAM->Size) && BBAM->Entries)
|
||||
return "\"Entries\" cannot be used with \"Content\" or \"Size\"";
|
||||
return "";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
@ -1520,6 +1538,21 @@ void MappingTraits<ELFYAML::StackSizeEntry>::mapping(
|
|||
IO.mapRequired("Size", E.Size);
|
||||
}
|
||||
|
||||
void MappingTraits<ELFYAML::BBAddrMapEntry>::mapping(
|
||||
IO &IO, ELFYAML::BBAddrMapEntry &E) {
|
||||
assert(IO.getContext() && "The IO context is not initialized");
|
||||
IO.mapOptional("Address", E.Address, Hex64(0));
|
||||
IO.mapOptional("BBEntries", E.BBEntries);
|
||||
}
|
||||
|
||||
void MappingTraits<ELFYAML::BBAddrMapEntry::BBEntry>::mapping(
|
||||
IO &IO, ELFYAML::BBAddrMapEntry::BBEntry &E) {
|
||||
assert(IO.getContext() && "The IO context is not initialized");
|
||||
IO.mapRequired("AddressOffset", E.AddressOffset);
|
||||
IO.mapRequired("Size", E.Size);
|
||||
IO.mapRequired("Metadata", E.Metadata);
|
||||
}
|
||||
|
||||
void MappingTraits<ELFYAML::GnuHashHeader>::mapping(IO &IO,
|
||||
ELFYAML::GnuHashHeader &E) {
|
||||
assert(IO.getContext() && "The IO context is not initialized");
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
## Check how obj2yaml produces YAML .llvm_bb_addr_map descriptions.
|
||||
|
||||
## Check that obj2yaml uses the "Entries" tag to describe an .llvm_bb_addr_map section.
|
||||
|
||||
# RUN: yaml2obj --docnum=1 %s -o %t1
|
||||
# RUN: obj2yaml %t1 | FileCheck %s --check-prefix=VALID
|
||||
|
||||
# VALID: --- !ELF
|
||||
# VALID-NEXT: FileHeader:
|
||||
# VALID-NEXT: Class: ELFCLASS64
|
||||
# VALID-NEXT: Data: ELFDATA2LSB
|
||||
# VALID-NEXT: Type: ET_EXEC
|
||||
# VALID-NEXT: Sections:
|
||||
# VALID-NEXT: - Name: .llvm_bb_addr_map
|
||||
# VALID-NEXT: Type: SHT_LLVM_BB_ADDR_MAP
|
||||
# VALID-NEXT: Entries:
|
||||
## The 'Address' field is omitted when it's zero.
|
||||
# VALID-NEXT: BBEntries:
|
||||
# VALID-NEXT: - AddressOffset: 0x00000001
|
||||
# VALID-NEXT: Size: 0x00000002
|
||||
# VALID-NEXT: Metadata: 0x00000003
|
||||
# VALID-NEXT: - AddressOffset: 0x00000004
|
||||
# VALID-NEXT: Size: 0x00000005
|
||||
# VALID-NEXT: Metadata: 0x00000006
|
||||
# VALID-NEXT: - AddressOffset: 0x00000007
|
||||
# VALID-NEXT: Size: 0x00000008
|
||||
# VALID-NEXT: Metadata: 0x00000009
|
||||
# VALID-NEXT: - Address: 0x0000000000000020
|
||||
# VALID-NEXT: BBEntries:
|
||||
# VALID-NEXT: - AddressOffset: 0x0000000A
|
||||
# VALID-NEXT: Size: 0x0000000B
|
||||
# VALID-NEXT: Metadata: 0x0000000C
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_EXEC
|
||||
Sections:
|
||||
- Name: .llvm_bb_addr_map
|
||||
Type: SHT_LLVM_BB_ADDR_MAP
|
||||
Entries:
|
||||
- Address: 0x0000000000000000
|
||||
BBEntries:
|
||||
- AddressOffset: 0x00000001
|
||||
Size: 0x00000002
|
||||
Metadata: 0x00000003
|
||||
- AddressOffset: 0x00000004
|
||||
Size: 0x00000005
|
||||
Metadata: 0x00000006
|
||||
- AddressOffset: 0x00000007
|
||||
Size: 0x00000008
|
||||
Metadata: 0x00000009
|
||||
- Address: 0x0000000000000020
|
||||
BBEntries:
|
||||
- AddressOffset: 0x0000000A
|
||||
Size: 0x0000000B
|
||||
Metadata: 0x0000000C
|
||||
|
||||
## Check that obj2yaml uses the "Content" tag to describe an .llvm_bb_addr_map section
|
||||
## when it can't extract the entries. For instance, when truncated data is given as
|
||||
## 'Content'.
|
||||
|
||||
# RUN: yaml2obj --docnum=2 %s -o %t2
|
||||
# RUN: obj2yaml %t2 | FileCheck %s --check-prefix=INVALID
|
||||
|
||||
# INVALID: --- !ELF
|
||||
# INVALID-NEXT: FileHeader:
|
||||
# INVALID-NEXT: Class: ELFCLASS64
|
||||
# INVALID-NEXT: Data: ELFDATA2LSB
|
||||
# INVALID-NEXT: Type: ET_EXEC
|
||||
# INVALID-NEXT: Sections:
|
||||
# INVALID-NEXT: - Name: .llvm_bb_addr_map
|
||||
# INVALID-NEXT: Type: SHT_LLVM_BB_ADDR_MAP
|
||||
# INVALID-NEXT: Content: '10000000000000'
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_EXEC
|
||||
Sections:
|
||||
- Name: .llvm_bb_addr_map
|
||||
Type: SHT_LLVM_BB_ADDR_MAP
|
||||
Content: '10000000000000'
|
||||
|
||||
## Check obj2yaml can dump empty .llvm_bb_addr_map sections.
|
||||
|
||||
# RUN: yaml2obj --docnum=3 %s -o %t3
|
||||
# RUN: obj2yaml %t3 | FileCheck %s --check-prefix=EMPTY
|
||||
|
||||
# EMPTY: --- !ELF
|
||||
# EMPTY-NEXT: FileHeader:
|
||||
# EMPTY-NEXT: Class: ELFCLASS64
|
||||
# EMPTY-NEXT: Data: ELFDATA2LSB
|
||||
# EMPTY-NEXT: Type: ET_EXEC
|
||||
# EMPTY-NEXT: Sections:
|
||||
# EMPTY-NEXT: - Name: .llvm_bb_addr_map
|
||||
# EMPTY-NEXT: Type: SHT_LLVM_BB_ADDR_MAP
|
||||
# EMPTY-NOT: Content:
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_EXEC
|
||||
Sections:
|
||||
- Name: .llvm_bb_addr_map
|
||||
Type: SHT_LLVM_BB_ADDR_MAP
|
||||
Content: ""
|
||||
|
||||
## Check obj2yaml can dump multiple .llvm_bb_addr_map sections.
|
||||
|
||||
# RUN: yaml2obj --docnum=4 %s -o %t4
|
||||
# RUN: obj2yaml %t4 | FileCheck %s --check-prefix=MULTI
|
||||
|
||||
# MULTI: --- !ELF
|
||||
# MULTI-NEXT: FileHeader:
|
||||
# MULTI-NEXT: Class: ELFCLASS64
|
||||
# MULTI-NEXT: Data: ELFDATA2LSB
|
||||
# MULTI-NEXT: Type: ET_EXEC
|
||||
# MULTI-NEXT: Sections:
|
||||
# MULTI-NEXT: - Name: .llvm_bb_addr_map
|
||||
# MULTI-NEXT: Type: SHT_LLVM_BB_ADDR_MAP
|
||||
# MULTI-NEXT: Entries:
|
||||
## The 'Address' field is omitted when it's zero.
|
||||
# MULTI-NEXT: - BBEntries:
|
||||
# MULTI-NEXT: - AddressOffset: 0x00000001
|
||||
# MULTI-NEXT: Size: 0x00000002
|
||||
# MULTI-NEXT: Metadata: 0x00000003
|
||||
# MULTI-NEXT: - Name: '.llvm_bb_addr_map (1)'
|
||||
# MULTI-NEXT: Type: SHT_LLVM_BB_ADDR_MAP
|
||||
# MULTI-NEXT: Entries:
|
||||
# MULTI-NEXT: - Address: 0x0000000000000020
|
||||
# MULTI-NEXT: BBEntries: []
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_EXEC
|
||||
Sections:
|
||||
- Name: .llvm_bb_addr_map
|
||||
Type: SHT_LLVM_BB_ADDR_MAP
|
||||
Entries:
|
||||
## Check that obj2yaml does not emit the Address field when it's zero.
|
||||
- Address: 0x0000000000000000
|
||||
BBEntries:
|
||||
- AddressOffset: 0x00000001
|
||||
Size: 0x00000002
|
||||
Metadata: 0x00000003
|
||||
- Name: '.llvm_bb_addr_map (1)'
|
||||
Type: SHT_LLVM_BB_ADDR_MAP
|
||||
Entries:
|
||||
- Address: 0x0000000000000020
|
|
@ -0,0 +1,116 @@
|
|||
## Check how yaml2obj produces .llvm_bb_addr_map sections.
|
||||
|
||||
# RUN: yaml2obj --docnum=1 %s -o %t1
|
||||
# RUN: llvm-readobj --sections --section-data %t1 | FileCheck %s
|
||||
|
||||
## Case 1: Specify content.
|
||||
# CHECK: Section {
|
||||
# CHECK: Index: 1
|
||||
# CHECK-NEXT: Name: .llvm_bb_addr_map (1)
|
||||
# CHECK-NEXT: Type: SHT_LLVM_BB_ADDR_MAP (0x6FFF4C08)
|
||||
# CHECK-NEXT: Flags [ (0x0)
|
||||
# CHECK-NEXT: ]
|
||||
# CHECK-NEXT: Address: 0x0
|
||||
# CHECK-NEXT: Offset: 0x40
|
||||
# CHECK-NEXT: Size: 12
|
||||
# CHECK-NEXT: Link: 0
|
||||
# CHECK-NEXT: Info: 0
|
||||
# CHECK-NEXT: AddressAlignment: 0
|
||||
# CHECK-NEXT: EntrySize: 0
|
||||
# CHECK-NEXT: SectionData (
|
||||
# CHECK-NEXT: 0000: 00000000 00000000 01010203
|
||||
# CHECK-NEXT: )
|
||||
# CHECK-NEXT: }
|
||||
|
||||
## Case 2: Empty.
|
||||
# CHECK: Name: .llvm_bb_addr_map (1)
|
||||
# CHECK: Size:
|
||||
# CHECK-SAME: {{^ 0$}}
|
||||
|
||||
## Case 3: Specify Size only.
|
||||
# CHECK: Name: .llvm_bb_addr_map (1)
|
||||
# CHECK: SectionData (
|
||||
# CHECK-NEXT: 0000: 00000000 00000000
|
||||
# CHECK-NEXT: )
|
||||
|
||||
# Case 4: Specify Entries.
|
||||
# CHECK: Name: .llvm_bb_addr_map (1)
|
||||
# CHECK: SectionData (
|
||||
# CHECK-NEXT: 0000: 20000000 00000000 01010203
|
||||
# CHECK-NEXT: )
|
||||
|
||||
# Case 5: Specify Entries and omit the Address field.
|
||||
# CHECK: Name: .llvm_bb_addr_map (1)
|
||||
# CHECK: Address:
|
||||
# CHECK-SAME: {{^ 0x0$}}
|
||||
# CHECK: SectionData (
|
||||
# CHECK-NEXT: 0000: 00000000 00000000 01010203
|
||||
# CHECK-NEXT: )
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_EXEC
|
||||
Sections:
|
||||
|
||||
## Test the following cases:
|
||||
|
||||
## 1) We can produce an .llvm_bb_addr_map section from a description with section
|
||||
## content.
|
||||
## Specify Content.
|
||||
- Name: '.llvm_bb_addr_map (1)'
|
||||
Type: SHT_LLVM_BB_ADDR_MAP
|
||||
Content: "000000000000000001010203"
|
||||
|
||||
## 2) We can produce an empty .llvm_bb_addr_map section from a description
|
||||
## with empty section content.
|
||||
- Name: '.llvm_bb_addr_map (2)'
|
||||
Type: SHT_LLVM_BB_ADDR_MAP
|
||||
|
||||
## 3) We can produce a zero .llvm_bb_addr_map section of a specific size when
|
||||
## we specify the size only.
|
||||
- Name: '.llvm_bb_addr_map (3)'
|
||||
Type: SHT_LLVM_BB_ADDR_MAP
|
||||
Size: 8
|
||||
|
||||
## 4) We can produce an .llvm_bb_addr_map section from a description with
|
||||
## Entries.
|
||||
- Name: '.llvm_bb_addr_map (4)'
|
||||
Type: SHT_LLVM_BB_ADDR_MAP
|
||||
Entries:
|
||||
- Address: 0x0000000000000020
|
||||
BBEntries:
|
||||
- AddressOffset: 0x00000001
|
||||
Size: 0x00000002
|
||||
Metadata: 0x00000003
|
||||
|
||||
## 5) When specifying the description with Entries, the 'Address' field will be
|
||||
## zero when omitted.
|
||||
- Name: '.llvm_bb_addr_map (5)'
|
||||
Type: SHT_LLVM_BB_ADDR_MAP
|
||||
Entries:
|
||||
- BBEntries:
|
||||
- AddressOffset: 0x00000001
|
||||
Size: 0x00000002
|
||||
Metadata: 0x00000003
|
||||
|
||||
|
||||
## Check we can't use Entries at the same time as either Content or Size.
|
||||
# RUN: not yaml2obj --docnum=2 -DCONTENT="00" %s 2>&1 | FileCheck %s --check-prefix=INVALID
|
||||
# RUN: not yaml2obj --docnum=2 -DSIZE="0" %s 2>&1 | FileCheck %s --check-prefix=INVALID
|
||||
|
||||
# INVALID: error: "Entries" cannot be used with "Content" or "Size"
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_EXEC
|
||||
Sections:
|
||||
## Specify Content and Size
|
||||
- Name: '.llvm_bb_addr_map'
|
||||
Type: SHT_LLVM_BB_ADDR_MAP
|
||||
Entries: []
|
||||
Content: [[CONTENT=<none>]]
|
||||
Size: [[SIZE=<none>]]
|
|
@ -100,6 +100,8 @@ class ELFDumper {
|
|||
Expected<ELFYAML::MipsABIFlags *> dumpMipsABIFlags(const Elf_Shdr *Shdr);
|
||||
Expected<ELFYAML::StackSizesSection *>
|
||||
dumpStackSizesSection(const Elf_Shdr *Shdr);
|
||||
Expected<ELFYAML::BBAddrMapSection *>
|
||||
dumpBBAddrMapSection(const Elf_Shdr *Shdr);
|
||||
Expected<ELFYAML::RawContentSection *>
|
||||
dumpPlaceholderSection(const Elf_Shdr *Shdr);
|
||||
|
||||
|
@ -505,6 +507,8 @@ ELFDumper<ELFT>::dumpSections() {
|
|||
case ELF::SHT_LLVM_CALL_GRAPH_PROFILE:
|
||||
return
|
||||
[this](const Elf_Shdr *S) { return dumpCallGraphProfileSection(S); };
|
||||
case ELF::SHT_LLVM_BB_ADDR_MAP:
|
||||
return [this](const Elf_Shdr *S) { return dumpBBAddrMapSection(S); };
|
||||
case ELF::SHT_STRTAB:
|
||||
case ELF::SHT_SYMTAB:
|
||||
case ELF::SHT_DYNSYM:
|
||||
|
@ -762,6 +766,50 @@ ELFDumper<ELFT>::dumpStackSizesSection(const Elf_Shdr *Shdr) {
|
|||
return S.release();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
Expected<ELFYAML::BBAddrMapSection *>
|
||||
ELFDumper<ELFT>::dumpBBAddrMapSection(const Elf_Shdr *Shdr) {
|
||||
auto S = std::make_unique<ELFYAML::BBAddrMapSection>();
|
||||
if (Error E = dumpCommonSection(Shdr, *S))
|
||||
return std::move(E);
|
||||
|
||||
auto ContentOrErr = Obj.getSectionContents(*Shdr);
|
||||
if (!ContentOrErr)
|
||||
return ContentOrErr.takeError();
|
||||
|
||||
ArrayRef<uint8_t> Content = *ContentOrErr;
|
||||
if (Content.empty())
|
||||
return S.release();
|
||||
|
||||
DataExtractor Data(Content, Obj.isLE(), ELFT::Is64Bits ? 8 : 4);
|
||||
|
||||
std::vector<ELFYAML::BBAddrMapEntry> Entries;
|
||||
DataExtractor::Cursor Cur(0);
|
||||
while (Cur && Cur.tell() < Content.size()) {
|
||||
uint64_t Address = Data.getAddress(Cur);
|
||||
uint32_t NumBlocks = Data.getULEB128(Cur);
|
||||
std::vector<ELFYAML::BBAddrMapEntry::BBEntry> BBEntries;
|
||||
// Read the specified number of BB entries, or until decoding fails.
|
||||
for (uint32_t BlockID = 0; Cur && BlockID < NumBlocks; ++BlockID) {
|
||||
uint32_t Offset = Data.getULEB128(Cur);
|
||||
uint32_t Size = Data.getULEB128(Cur);
|
||||
uint32_t Metadata = Data.getULEB128(Cur);
|
||||
BBEntries.push_back({Offset, Size, Metadata});
|
||||
}
|
||||
Entries.push_back({Address, BBEntries});
|
||||
}
|
||||
|
||||
if (!Cur) {
|
||||
// If the section cannot be decoded, we dump it as an array of bytes.
|
||||
consumeError(Cur.takeError());
|
||||
S->Content = yaml::BinaryRef(Content);
|
||||
} else {
|
||||
S->Entries = std::move(Entries);
|
||||
}
|
||||
|
||||
return S.release();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
Expected<ELFYAML::AddrsigSection *>
|
||||
ELFDumper<ELFT>::dumpAddrsigSection(const Elf_Shdr *Shdr) {
|
||||
|
|
Loading…
Reference in New Issue