[Propeller] Encode address offsets of basic blocks relative to the end of the previous basic blocks.

This is a resurrection of D106421 with the change that it keeps backward-compatibility. This means decoding the previous version of `LLVM_BB_ADDR_MAP` will work. This is required as the profile mapping tool is not released with LLVM (AutoFDO). As suggested by @jhenderson we rename the original  section type value to `SHT_LLVM_BB_ADDR_MAP_V0` and assign a new value to the `SHT_LLVM_BB_ADDR_MAP` section type. The new encoding adds a version byte to each function entry to specify the encoding version for that function.  This patch also adds a feature byte to be used with more flexibility in the future. An use-case example for the feature field is encoding multi-section functions more concisely using a different format.

Conceptually, the new encoding emits basic block offsets and sizes as label differences between each two consecutive basic block begin and end label. When decoding, offsets must be aggregated along with basic block sizes to calculate the final offsets of basic blocks relative to the function address.

This encoding uses smaller values compared to the existing one (offsets relative to function symbol).
Smaller values tend to occupy fewer bytes in ULEB128 encoding. As a result, we get about 17% total reduction in the size of the bb-address-map section (from about 11MB to 9MB for the clang PGO binary).
The extra two bytes (version and feature fields) incur a small 3% size overhead to the `LLVM_BB_ADDR_MAP` section size.

Reviewed By: jhenderson

Differential Revision: https://reviews.llvm.org/D121346
This commit is contained in:
Rahman Lavaee 2022-06-28 07:41:40 -07:00
parent 3f028c02ba
commit 0aa6df6575
21 changed files with 495 additions and 229 deletions

View File

@ -401,11 +401,23 @@ This section stores the binary address of basic blocks along with other related
metadata. This information can be used to map binary profiles (like perf
profiles) directly to machine basic blocks.
This section is emitted with ``-basic-block-sections=labels`` and will contain
a BB address map table for every function which may be constructed as follows:
a BB address map table for every function.
The ``SHT_LLVM_BB_ADDR_MAP`` type provides backward compatibility to allow
reading older versions of the BB address map generated by older compilers. Each
function entry starts with a version byte which specifies the encoding version
to use. The following versioning schemes are currently supported.
Version 1 (newest): basic block address offsets are computed relative to the end
of previous blocks.
Example:
.. code-block:: gas
.section ".llvm_bb_addr_map","",@llvm_bb_addr_map
.byte 1 # version number
.byte 0 # feature byte (reserved for future use)
.quad .Lfunc_begin0 # address of the function
.byte 2 # number of basic blocks
# BB record for BB_0
@ -413,11 +425,30 @@ a BB address map table for every function which may be constructed as follows:
.uleb128 .LBB_END0_0-.Lfunc_begin0 # BB_0 size
.byte x # BB_0 metadata
# BB record for BB_1
.uleb128 .LBB0_1-.Lfunc_begin0 # BB_1 offset relative to function entry
.uleb128 .LBB_END0_1-.Lfunc_begin0 # BB_1 size
.uleb128 .LBB0_1-.LBB_END0_0 # BB_1 offset relative to the end of last block (BB_0).
.uleb128 .LBB_END0_1-.LBB0_1 # BB_1 size
.byte y # BB_1 metadata
This creates a BB address map table for a function with two basic blocks.
Version 0: basic block address offsets are computed relative to the function
address. This uses the unversioned ``SHT_LLVM_BB_ADDR_MAP_V0`` section type and
is semantically equivalent to using ``SHT_LLVM_BB_ADDR_MAP`` with a zero
version field.
Example:
.. code-block:: gas
.section ".llvm_bb_addr_map","",@llvm_bb_addr_map_v0
.quad .Lfunc_begin0 # address of the function
.byte 2 # number of basic blocks
# BB record for BB_0
.uleb128 .Lfunc_beign0-.Lfunc_begin0 # BB_0 offset relative to the function entry (always zero)
.uleb128 .LBB_END0_0-.Lfunc_begin0 # BB_0 size
.byte x # BB_0 metadata
# BB record for BB_1
.uleb128 .LBB0_1-.Lfunc_begin0 # BB_1 offset relative to the function entry
.uleb128 .LBB_END0_1-.LBB0_1 # BB_1 size
.byte y # BB_1 metadata
CodeView-Dependent
------------------

View File

@ -981,12 +981,15 @@ enum : unsigned {
SHT_LLVM_ADDRSIG = 0x6fff4c03, // List of address-significant symbols
// for safe ICF.
SHT_LLVM_DEPENDENT_LIBRARIES =
0x6fff4c04, // LLVM Dependent Library Specifiers.
SHT_LLVM_SYMPART = 0x6fff4c05, // Symbol partition specification.
SHT_LLVM_PART_EHDR = 0x6fff4c06, // ELF header for loadable partition.
SHT_LLVM_PART_PHDR = 0x6fff4c07, // Phdrs for loadable partition.
SHT_LLVM_BB_ADDR_MAP = 0x6fff4c08, // LLVM Basic Block Address Map.
0x6fff4c04, // LLVM Dependent Library Specifiers.
SHT_LLVM_SYMPART = 0x6fff4c05, // Symbol partition specification.
SHT_LLVM_PART_EHDR = 0x6fff4c06, // ELF header for loadable partition.
SHT_LLVM_PART_PHDR = 0x6fff4c07, // Phdrs for loadable partition.
SHT_LLVM_BB_ADDR_MAP_V0 =
0x6fff4c08, // LLVM Basic Block Address Map (old version kept for
// backward-compatibility).
SHT_LLVM_CALL_GRAPH_PROFILE = 0x6fff4c09, // LLVM Call Graph Profile.
SHT_LLVM_BB_ADDR_MAP = 0x6fff4c0a, // LLVM Basic Block Address Map.
// Android's experimental support for SHT_RELR sections.
// https://android.googlesource.com/platform/bionic/+/b7feec74547f84559a1467aca02708ff61346d2a/libc/include/elf.h#512
SHT_ANDROID_RELR = 0x6fffff00, // Relocation entries; only offsets.

View File

@ -172,6 +172,9 @@ private:
/// for the LocalLabelVal and adds it to the map if needed.
unsigned GetInstance(unsigned LocalLabelVal);
/// LLVM_BB_ADDR_MAP version to emit.
uint8_t BBAddrMapVersion = 1;
/// The file name of the log file from the environment variable
/// AS_SECURE_LOG_FILE. Which must be set before the .secure_log_unique
/// directive is used or it is an error.
@ -679,6 +682,8 @@ public:
// Create and save a copy of STI and return a reference to the copy.
MCSubtargetInfo &getSubtargetCopy(const MCSubtargetInfo &STI);
uint8_t getBBAddrMapVersion() const { return BBAddrMapVersion; }
/// @}
/// \name Dwarf Management

View File

@ -161,6 +161,8 @@ struct BBAddrMapEntry {
llvm::yaml::Hex64 Size;
llvm::yaml::Hex64 Metadata;
};
uint8_t Version;
llvm::yaml::Hex8 Feature;
llvm::yaml::Hex64 Address;
Optional<uint64_t> NumBlocks;
Optional<std::vector<BBEntry>> BBEntries;

View File

@ -1327,19 +1327,27 @@ void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
OutStreamer->pushSection();
OutStreamer->switchSection(BBAddrMapSection);
OutStreamer->AddComment("version");
OutStreamer->emitInt8(OutStreamer->getContext().getBBAddrMapVersion());
OutStreamer->AddComment("feature");
OutStreamer->emitInt8(0);
OutStreamer->AddComment("function address");
OutStreamer->emitSymbolValue(FunctionSymbol, getPointerSize());
// Emit the total number of basic blocks in this function.
OutStreamer->AddComment("number of basic blocks");
OutStreamer->emitULEB128IntValue(MF.size());
const MCSymbol *PrevMBBEndSymbol = FunctionSymbol;
// Emit BB Information for each basic block in the funciton.
for (const MachineBasicBlock &MBB : MF) {
const MCSymbol *MBBSymbol =
MBB.isEntryBlock() ? FunctionSymbol : MBB.getSymbol();
// Emit the basic block offset.
emitLabelDifferenceAsULEB128(MBBSymbol, FunctionSymbol);
// Emit the basic block offset relative to the end of the previous block.
// This is zero unless the block is padded due to alignment.
emitLabelDifferenceAsULEB128(MBBSymbol, PrevMBBEndSymbol);
// Emit the basic block size. When BBs have alignments, their size cannot
// always be computed from their offsets.
emitLabelDifferenceAsULEB128(MBB.getEndSymbol(), MBBSymbol);
OutStreamer->emitULEB128IntValue(getBBAddrMapMetadata(MBB));
PrevMBBEndSymbol = MBB.getEndSymbol();
}
OutStreamer->popSection();
}

View File

@ -60,7 +60,7 @@
// Basic Block Labels
// ==================
//
// With -fbasic-block-sections=labels, we emit the offsets of BB addresses of
// With -fbasic-block-sections=labels, we encode the offsets of BB addresses of
// every function into the .llvm_bb_addr_map section. Along with the function
// symbols, this allows for mapping of virtual addresses in PMU profiles back to
// the corresponding basic blocks. This logic is implemented in AsmPrinter. This

View File

@ -165,6 +165,8 @@ void MCSectionELF::printSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
OS << "llvm_sympart";
else if (Type == ELF::SHT_LLVM_BB_ADDR_MAP)
OS << "llvm_bb_addr_map";
else if (Type == ELF::SHT_LLVM_BB_ADDR_MAP_V0)
OS << "llvm_bb_addr_map_v0";
else
report_fatal_error("unsupported type 0x" + Twine::utohexstr(Type) +
" for section " + getName());

View File

@ -295,6 +295,7 @@ StringRef llvm::object::getELFSectionTypeName(uint32_t Machine, unsigned Type) {
STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_SYMPART);
STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_PART_EHDR);
STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_PART_PHDR);
STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_BB_ADDR_MAP_V0);
STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_BB_ADDR_MAP);
STRINGIFY_ENUM_CASE(ELF, SHT_GNU_ATTRIBUTES);
STRINGIFY_ENUM_CASE(ELF, SHT_GNU_HASH);
@ -640,7 +641,6 @@ ELFFile<ELFT>::decodeBBAddrMap(const Elf_Shdr &Sec) const {
DataExtractor::Cursor Cur(0);
Error ULEBSizeErr = Error::success();
// Helper to extract and decode the next ULEB128 value as uint32_t.
// Returns zero and sets ULEBSizeErr if the ULEB128 value exceeds the uint32_t
// limit.
@ -660,18 +660,34 @@ ELFFile<ELFT>::decodeBBAddrMap(const Elf_Shdr &Sec) const {
return static_cast<uint32_t>(Value);
};
uint8_t Version = 0;
while (!ULEBSizeErr && Cur && Cur.tell() < Content.size()) {
if (Sec.sh_type == ELF::SHT_LLVM_BB_ADDR_MAP) {
Version = Data.getU8(Cur);
if (!Cur)
break;
if (Version > 1)
return createError("unsupported SHT_LLVM_BB_ADDR_MAP version: " +
Twine(static_cast<int>(Version)));
Data.getU8(Cur); // Feature byte
}
uintX_t Address = static_cast<uintX_t>(Data.getAddress(Cur));
uint32_t NumBlocks = ReadULEB128AsUInt32();
std::vector<BBAddrMap::BBEntry> BBEntries;
uint32_t PrevBBEndOffset = 0;
for (uint32_t BlockID = 0; !ULEBSizeErr && Cur && (BlockID < NumBlocks);
++BlockID) {
uint32_t Offset = ReadULEB128AsUInt32();
uint32_t Size = ReadULEB128AsUInt32();
uint32_t Metadata = ReadULEB128AsUInt32();
if (Version >= 1) {
// Offset is calculated relative to the end of the previous BB.
Offset += PrevBBEndOffset;
PrevBBEndOffset = Offset + Size;
}
BBEntries.push_back({Offset, Size, Metadata});
}
FunctionEntries.push_back({Address, BBEntries});
FunctionEntries.push_back({Address, std::move(BBEntries)});
}
// Either Cur is in the error state, or ULEBSizeError is set (not both), but
// we join the two errors here to be safe.

View File

@ -678,7 +678,8 @@ readBBAddrMapImpl(const ELFFile<ELFT> &EF,
std::vector<BBAddrMap> BBAddrMaps;
const auto &Sections = cantFail(EF.sections());
for (const Elf_Shdr &Sec : Sections) {
if (Sec.sh_type != ELF::SHT_LLVM_BB_ADDR_MAP)
if (Sec.sh_type != ELF::SHT_LLVM_BB_ADDR_MAP &&
Sec.sh_type != ELF::SHT_LLVM_BB_ADDR_MAP_V0)
continue;
if (TextSectionIndex) {
Expected<const Elf_Shdr *> TextSecOrErr = EF.getSection(Sec.sh_link);

View File

@ -1393,6 +1393,16 @@ void ELFState<ELFT>::writeSectionContent(
return;
for (const ELFYAML::BBAddrMapEntry &E : *Section.Entries) {
// Write version and feature values.
if (Section.Type == llvm::ELF::SHT_LLVM_BB_ADDR_MAP) {
if (E.Version > 1)
WithColor::warning() << "unsupported SHT_LLVM_BB_ADDR_MAP version: "
<< static_cast<int>(E.Version)
<< "; encoding using the most recent version";
CBA.write(E.Version);
CBA.write(E.Feature);
SHeader.sh_size += 2;
}
// 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). This

View File

@ -654,6 +654,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_V0);
ECase(SHT_LLVM_BB_ADDR_MAP);
ECase(SHT_GNU_ATTRIBUTES);
ECase(SHT_GNU_HASH);
@ -1639,6 +1640,7 @@ 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_V0:
case ELF::SHT_LLVM_BB_ADDR_MAP:
if (!IO.outputting())
Section.reset(new ELFYAML::BBAddrMapSection());
@ -1768,6 +1770,8 @@ void MappingTraits<ELFYAML::StackSizeEntry>::mapping(
void MappingTraits<ELFYAML::BBAddrMapEntry>::mapping(
IO &IO, ELFYAML::BBAddrMapEntry &E) {
assert(IO.getContext() && "The IO context is not initialized");
IO.mapRequired("Version", E.Version);
IO.mapOptional("Feature", E.Feature, Hex8(0));
IO.mapOptional("Address", E.Address, Hex64(0));
IO.mapOptional("NumBlocks", E.NumBlocks);
IO.mapOptional("BBEntries", E.BBEntries);

View File

@ -18,4 +18,6 @@ entry:
; CHECK: func:
; CHECK: .Lfunc_begin1:
; CHECK: .section .llvm_bb_addr_map,"o",@llvm_bb_addr_map,.text{{$}}
; CHECK: .quad .Lfunc_begin1
; CHECK-NEXT: .byte 1 # version
; CHECK-NEXT: .byte 0 # feature
; CHECK-NEXT: .quad .Lfunc_begin1 # function address

View File

@ -10,7 +10,9 @@ define dso_local i32 @_Z3barv() {
; CHECK-LABEL: _Z3barv:
; CHECK-NEXT: [[BAR_BEGIN:.Lfunc_begin[0-9]+]]:
; CHECK: .section .llvm_bb_addr_map,"o",@llvm_bb_addr_map,.text._Z3barv{{$}}
; CHECK-NEXT: .quad [[BAR_BEGIN]]
; CHECK-NEXT: .byte 1 # version
; CHECK-NEXT: .byte 0 # feature
; CHECK-NEXT: .quad [[BAR_BEGIN]] # function address
define dso_local i32 @_Z3foov() {
@ -21,7 +23,9 @@ define dso_local i32 @_Z3foov() {
; CHECK-LABEL: _Z3foov:
; CHECK-NEXT: [[FOO_BEGIN:.Lfunc_begin[0-9]+]]:
; CHECK: .section .llvm_bb_addr_map,"o",@llvm_bb_addr_map,.text._Z3foov{{$}}
; CHECK-NEXT: .quad [[FOO_BEGIN]]
; CHECK-NEXT: .byte 1 # version
; CHECK-NEXT: .byte 0 # feature
; CHECK-NEXT: .quad [[FOO_BEGIN]] # function address
define linkonce_odr dso_local i32 @_Z4fooTIiET_v() comdat {
@ -32,4 +36,6 @@ define linkonce_odr dso_local i32 @_Z4fooTIiET_v() comdat {
; CHECK-LABEL: _Z4fooTIiET_v:
; CHECK-NEXT: [[FOOCOMDAT_BEGIN:.Lfunc_begin[0-9]+]]:
; CHECK: .section .llvm_bb_addr_map,"Go",@llvm_bb_addr_map,_Z4fooTIiET_v,comdat,.text._Z4fooTIiET_v{{$}}
; CHECK-NEXT: .quad [[FOOCOMDAT_BEGIN]]
; CHECK-NEXT: .byte 1 # version
; CHECK-NEXT: .byte 0 # feature
; CHECK-NEXT: .quad [[FOOCOMDAT_BEGIN]] # function address

View File

@ -46,17 +46,19 @@ declare i32 @__gxx_personality_v0(...)
; UNIQ: .section .llvm_bb_addr_map,"o",@llvm_bb_addr_map,.text._Z3bazb{{$}}
;; Verify that with -unique-section-names=false, the unique id of the text section gets assigned to the llvm_bb_addr_map section.
; NOUNIQ: .section .llvm_bb_addr_map,"o",@llvm_bb_addr_map,.text,unique,1
; CHECK-NEXT: .quad .Lfunc_begin0
; CHECK-NEXT: .byte 4
; CHECK-NEXT: .byte 1 # version
; CHECK-NEXT: .byte 0 # feature
; CHECK-NEXT: .quad .Lfunc_begin0 # function address
; CHECK-NEXT: .byte 4 # number of basic blocks
; CHECK-NEXT: .uleb128 .Lfunc_begin0-.Lfunc_begin0
; CHECK-NEXT: .uleb128 .LBB_END0_0-.Lfunc_begin0
; CHECK-NEXT: .byte 8
; CHECK-NEXT: .uleb128 .LBB0_1-.Lfunc_begin0
; CHECK-NEXT: .uleb128 .LBB0_1-.LBB_END0_0
; CHECK-NEXT: .uleb128 .LBB_END0_1-.LBB0_1
; CHECK-NEXT: .byte 8
; CHECK-NEXT: .uleb128 .LBB0_2-.Lfunc_begin0
; CHECK-NEXT: .uleb128 .LBB0_2-.LBB_END0_1
; CHECK-NEXT: .uleb128 .LBB_END0_2-.LBB0_2
; CHECK-NEXT: .byte 1
; CHECK-NEXT: .uleb128 .LBB0_3-.Lfunc_begin0
; CHECK-NEXT: .uleb128 .LBB0_3-.LBB_END0_2
; CHECK-NEXT: .uleb128 .LBB_END0_3-.LBB0_3
; CHECK-NEXT: .byte 5

View File

@ -80,18 +80,19 @@ Sections:
Type: SHT_LLVM_BB_ADDR_MAP
Link: .text
Entries:
- Address: 0x4000
- Version: 1
Address: 0x4000
BBEntries:
- AddressOffset: 0x0
Size: 0x1
Metadata: 0x1
- AddressOffset: 0x1
- AddressOffset: 0x0
Size: 0x6
Metadata: 0x0
- AddressOffset: 0x8
Size: 0x3
- AddressOffset: 0x1
Size: 0x4
Metadata: 0x0
- AddressOffset: 0xc
- AddressOffset: 0x0
Size: 0x1
Metadata: 0x2
Symbols:
@ -130,33 +131,35 @@ Sections:
Type: SHT_LLVM_BB_ADDR_MAP
Link: .text.foo
Entries:
- Address: 0x4000
- Version: 1
Address: 0x4000
BBEntries:
- AddressOffset: 0x0
Size: 0x1
Metadata: 0x1
- AddressOffset: 0x1
- AddressOffset: 0x0
Size: 0x6
Metadata: 0x0
- AddressOffset: 0x8
Size: 0x3
- AddressOffset: 0x1
Size: 0x4
Metadata: 0x0
- AddressOffset: 0xc
- AddressOffset: 0x0
Size: 0x1
Metadata: 0x2
- Name: bb_addr_map.bar
Type: SHT_LLVM_BB_ADDR_MAP
Link: .text.bar
Entries:
- Address: 0x5000
- Version: 1
Address: 0x5000
BBEntries:
- AddressOffset: 0x0
Size: 0x1
Metadata: 0x1
- AddressOffset: 0x5
- AddressOffset: 0x4
Size: 0x2
Metadata: 0x0
- AddressOffset: 0x7
- AddressOffset: 0x0
Size: 0x6
Metadata: 0x0

View File

@ -1,75 +1,62 @@
## This test checks how we handle the --bb-addr-map option.
# Check 64-bit:
# RUN: yaml2obj %s -DBITS=64 -DADDR=0x999999999 -o %t1.x64.o
# RUN: llvm-readobj %t1.x64.o --bb-addr-map 2>&1 | FileCheck %s -DADDR=0x999999999 -DFILE=%t1.x64.o --check-prefix=LLVM
## Check 64-bit:
# RUN: yaml2obj --docnum=1 %s -DBITS=64 -DADDR=0x999999999 -o %t1.x64.o
# RUN: llvm-readobj %t1.x64.o --bb-addr-map 2>&1 | FileCheck %s -DADDR=0x999999999 -DFILE=%t1.x64.o --check-prefix=CHECK
# RUN: llvm-readelf %t1.x64.o --bb-addr-map | FileCheck %s --check-prefix=GNU
## Check 64-bit:
# RUN: yaml2obj --docnum=1 %s -DBITS=64 -DADDR=0x999999999 -o %t1.v1.x64.o
# RUN: llvm-readobj %t1.v1.x64.o --bb-addr-map 2>&1 | FileCheck %s -DADDR=0x999999999 -DFILE=%t1.v1.x64.o --check-prefix=CHECK
## Check 32-bit:
# RUN: yaml2obj %s -DBITS=32 -o %t1.x32.o
# RUN: llvm-readobj %t1.x32.o --bb-addr-map 2>&1 | FileCheck -DADDR=0x11111 %s -DFILE=%t1.x32.o --check-prefix=LLVM
# RUN: yaml2obj --docnum=1 %s -DBITS=32 -o %t1.x32.o
# RUN: llvm-readobj %t1.x32.o --bb-addr-map 2>&1 | FileCheck -DADDR=0x11111 %s -DFILE=%t1.x32.o --check-prefix=CHECK
# RUN: llvm-readelf %t1.x32.o --bb-addr-map | FileCheck %s --check-prefix=GNU
## Check that a malformed section can be handled.
# RUN: yaml2obj %s -DBITS=32 -DSIZE=4 -o %t2.o
# RUN: llvm-readobj %t2.o --bb-addr-map 2>&1 | FileCheck %s -DOFFSET=0x00000004 -DFILE=%t2.o --check-prefix=TRUNCATED
# RUN: yaml2obj --docnum=1 %s -DBITS=32 -DSIZE=6 -o %t2.o
# RUN: llvm-readobj %t2.o --bb-addr-map 2>&1 | FileCheck %s -DOFFSET=0x00000006 -DFILE=%t2.o --check-prefix=TRUNCATED
# LLVM: BBAddrMap [
# LLVM-NEXT: Function {
# LLVM-NEXT: At: [[ADDR]]
# LLVM-NEXT: warning: '[[FILE]]': could not identify function symbol for address ([[ADDR]]) in SHT_LLVM_BB_ADDR_MAP section with index 3
# LLVM-NEXT: Name: <?>
# LLVM-NEXT: BB entries [
# LLVM-NEXT: {
# LLVM-NEXT: Offset: 0x0
# LLVM-NEXT: Size: 0x1
# LLVM-NEXT: HasReturn: No
# LLVM-NEXT: HasTailCall: Yes
# LLVM-NEXT: IsEHPad: No
# LLVM-NEXT: CanFallThrough: No
# LLVM-NEXT: }
# LLVM-NEXT: {
# LLVM-NEXT: Offset: 0x3
# LLVM-NEXT: Size: 0x4
# LLVM-NEXT: HasReturn: Yes
# LLVM-NEXT: HasTailCall: No
# LLVM-NEXT: IsEHPad: Yes
# LLVM-NEXT: CanFallThrough: No
# LLVM-NEXT: }
# LLVM-NEXT: ]
# LLVM-NEXT: }
# LLVM-NEXT: Function {
# LLVM-NEXT: At: 0x22222
# LLVM-NEXT: Name: foo
# LLVM-NEXT: BB entries [
# LLVM-NEXT: {
# LLVM-NEXT: Offset: 0x6
# LLVM-NEXT: Size: 0x7
# LLVM-NEXT: HasReturn: No
# LLVM-NEXT: HasTailCall: No
# LLVM-NEXT: IsEHPad: No
# LLVM-NEXT: CanFallThrough: Yes
# LLVM-NEXT: }
# LLVM-NEXT: ]
# LLVM-NEXT: }
# LLVM-NEXT: ]
# LLVM-NEXT: BBAddrMap [
# LLVM-NEXT: Function {
# LLVM-NEXT: At: 0x33333
# LLVM-NEXT: Name: bar
# LLVM-NEXT: BB entries [
# LLVM-NEXT: {
# LLVM-NEXT: Offset: 0x9
# LLVM-NEXT: Size: 0xA
# LLVM-NEXT: HasReturn: Yes
# LLVM-NEXT: HasTailCall: Yes
# LLVM-NEXT: IsEHPad: No
# LLVM-NEXT: CanFallThrough: Yes
# LLVM-NEXT: }
# LLVM-NEXT: ]
# LLVM-NEXT: }
# LLVM-NEXT: ]
# CHECK: BBAddrMap [
# CHECK-NEXT: Function {
# CHECK-NEXT: At: [[ADDR]]
# CHECK-NEXT: warning: '[[FILE]]': could not identify function symbol for address ([[ADDR]]) in SHT_LLVM_BB_ADDR_MAP section with index 3
# CHECK-NEXT: Name: <?>
# CHECK-NEXT: BB entries [
# CHECK-NEXT: {
# CHECK-NEXT: Offset: 0x0
# CHECK-NEXT: Size: 0x1
# CHECK-NEXT: HasReturn: No
# CHECK-NEXT: HasTailCall: Yes
# CHECK-NEXT: IsEHPad: No
# CHECK-NEXT: CanFallThrough: No
# CHECK-NEXT: }
# CHECK-NEXT: {
# CHECK-NEXT: Offset: 0x4
# CHECK-NEXT: Size: 0x4
# CHECK-NEXT: HasReturn: Yes
# CHECK-NEXT: HasTailCall: No
# CHECK-NEXT: IsEHPad: Yes
# CHECK-NEXT: CanFallThrough: No
# CHECK-NEXT: }
# CHECK-NEXT: ]
# CHECK-NEXT: }
# CHECK-NEXT: Function {
# CHECK-NEXT: At: 0x22222
# CHECK-NEXT: Name: foo
# CHECK-NEXT: BB entries [
# CHECK-NEXT: {
# CHECK-NEXT: Offset: 0x6
# CHECK-NEXT: Size: 0x7
# CHECK-NEXT: HasReturn: No
# CHECK-NEXT: HasTailCall: No
# CHECK-NEXT: IsEHPad: No
# CHECK-NEXT: CanFallThrough: Yes
# CHECK-NEXT: }
# CHECK-NEXT: ]
# CHECK-NEXT: }
# CHECK-NEXT: ]
# GNU: GNUStyle::printBBAddrMaps not implemented
@ -90,6 +77,14 @@
# TRUNCATED-NEXT: IsEHPad: No
# TRUNCATED-NEXT: CanFallThrough: Yes
# TRUNCATED-NEXT: }
# TRUNCATED-NEXT: {
# TRUNCATED-NEXT: Offset: 0x1F
# TRUNCATED-NEXT: Size: 0xD
# TRUNCATED-NEXT: HasReturn: No
# TRUNCATED-NEXT: HasTailCall: Yes
# TRUNCATED-NEXT: IsEHPad: Yes
# TRUNCATED-NEXT: CanFallThrough: Yes
# TRUNCATED-NEXT: }
# TRUNCATED-NEXT: ]
# TRUNCATED-NEXT: }
# TRUNCATED-NEXT: ]
@ -106,12 +101,13 @@ Sections:
- Name: .text.bar
Type: SHT_PROGBITS
Flags: [SHF_ALLOC]
- Name: bb_addr_map_1
- Name: .llvm_bb_addr_map
Type: SHT_LLVM_BB_ADDR_MAP
ShSize: [[SIZE=<none>]]
Link: .text
Entries:
- Address: [[ADDR=0x11111]]
- Version: 1
Address: [[ADDR=0x11111]]
BBEntries:
- AddressOffset: 0x0
Size: 0x1
@ -119,23 +115,28 @@ Sections:
- AddressOffset: 0x3
Size: 0x4
Metadata: 0x5
- Address: 0x22222
- Version: 1
Address: 0x22222
BBEntries:
- AddressOffset: 0x6
Size: 0x7
Metadata: 0x8
- Name: dummy_section
Type: SHT_PROGBITS
Size: 16
- Name: bb_addr_map_2
Type: SHT_LLVM_BB_ADDR_MAP
Link: .text.bar
- Name: dummy_section
Type: SHT_PROGBITS
Size: 16
- Name: '.llvm_bb_addr_map (1)'
Type: SHT_LLVM_BB_ADDR_MAP
Link: .text.bar
Entries:
- Address: 0x33333
- Version: 1
Address: 0x33333
BBEntries:
- AddressOffset: 0x9
Size: 0xa
Metadata: 0xb
- AddressOffset: 0xc
Size: 0xd
Metadata: 0xe
Symbols:
- Name: foo
Section: .text
@ -145,3 +146,67 @@ Symbols:
Section: .text.bar
Type: STT_FUNC
Value: 0x33333
## Check that using the SHT_LLVM_BB_ADDR_MAP_V0 section type generates the same
## result as using the SHT_LLVM_BB_ADDR_MAP section type with Version=0.
## The Version field is required even for SHT_LLVM_BB_ADDR_MAP_V0 but it
## should not impact the result. This unideal behavior will be gone once
## SHT_LLVM_BB_ADDR_MAP_V0 is deprecated.
# RUN: yaml2obj --docnum=2 %s -DVERSION=255 -DSECTION_TYPE=SHT_LLVM_BB_ADDR_MAP_V0 -o %t2.type0
# RUN: llvm-readobj %t2.type0 --bb-addr-map 2>&1 | FileCheck %s --check-prefix=V0
# RUN: yaml2obj --docnum=2 %s -DVERSION=0 -DSECTION_TYPE=SHT_LLVM_BB_ADDR_MAP -o %t2.version0
# RUN: llvm-readobj %t2.version0 --bb-addr-map 2>&1 | FileCheck %s --check-prefix=V0
# V0: BBAddrMap [
# V0-NEXT: Function {
# V0-NEXT: At: 0x11111
# V0-NEXT: Name: foo
# V0-NEXT: BB entries [
# V0-NEXT: {
# V0-NEXT: Offset: 0x1
# V0-NEXT: Size: 0x2
# V0-NEXT: HasReturn:
# V0-NEXT: HasTailCall:
# V0-NEXT: IsEHPad:
# V0-NEXT: CanFallThrough:
# V0-NEXT: }
# V0-NEXT: {
# V0-NEXT: Offset: 0x4
# V0-NEXT: Size: 0x5
# V0-NEXT: HasReturn:
# V0-NEXT: HasTailCall:
# V0-NEXT: IsEHPad:
# V0-NEXT: CanFallThrough:
# V0-NEXT: }
# V0-NEXT: ]
# V0-NEXT: }
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Sections:
- Name: .text.foo
Type: SHT_PROGBITS
Flags: [SHF_ALLOC]
- Name: .llvm_bb_addr_map
Type: [[SECTION_TYPE]]
Link: .text.foo
Entries:
- Version: [[VERSION]]
Address: 0x11111
BBEntries:
- AddressOffset: 0x1
Size: 0x2
Metadata: 0x3
- AddressOffset: 0x4
Size: 0x5
Metadata: 0x6
Symbols:
- Name: foo
Section: .text.foo
Type: STT_FUNC
Value: 0x11111

View File

@ -7,29 +7,33 @@
# VALID: --- !ELF
# VALID-NEXT: FileHeader:
# VALID-NEXT: Class: ELFCLASS64
# VALID-NEXT: Data: ELFDATA2LSB
# VALID-NEXT: Type: ET_EXEC
# 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: - Version: 1
# VALID-NEXT: Feature: 0xFF
# VALID-NEXT: BBEntries:
# VALID-NEXT: - AddressOffset: 0x1
# VALID-NEXT: Size: 0x2
# VALID-NEXT: Metadata: 0x3
# VALID-NEXT: - AddressOffset: 0x4
# VALID-NEXT: Size: 0x5
# VALID-NEXT: Metadata: 0x6
# VALID-NEXT: - AddressOffset: 0xFFFFFFFFFFFFFFF7
# VALID-NEXT: Size: 0xFFFFFFFFFFFFFFF8
# VALID-NEXT: Metadata: 0xFFFFFFFFFFFFFFF9
# VALID-NEXT: - Address: 0xFFFFFFFFFFFFFF20
# VALID-NEXT: - AddressOffset: 0x1
# VALID-NEXT: Size: 0x2
# VALID-NEXT: Metadata: 0x3
# VALID-NEXT: - AddressOffset: 0x4
# VALID-NEXT: Size: 0x5
# VALID-NEXT: Metadata: 0x6
# VALID-NEXT: - AddressOffset: 0xFFFFFFFFFFFFFFF7
# VALID-NEXT: Size: 0xFFFFFFFFFFFFFFF8
# VALID-NEXT: Metadata: 0xFFFFFFFFFFFFFFF9
# VALID-NEXT: - Version: 1
# VALID-NEXT: Feature: 0xEE
# VALID-NEXT: Address: 0xFFFFFFFFFFFFFF20
# VALID-NEXT: BBEntries:
# VALID-NEXT: - AddressOffset: 0xA
# VALID-NEXT: Size: 0xB
# VALID-NEXT: Metadata: 0xC
# VALID-NEXT: - AddressOffset: 0xA
# VALID-NEXT: Size: 0xB
# VALID-NEXT: Metadata: 0xC
--- !ELF
FileHeader:
@ -37,27 +41,31 @@ FileHeader:
Data: ELFDATA2LSB
Type: ET_EXEC
Sections:
- Name: .llvm_bb_addr_map
Type: SHT_LLVM_BB_ADDR_MAP
ShSize: [[SIZE=<none>]]
- Name: .llvm_bb_addr_map
Type: SHT_LLVM_BB_ADDR_MAP
ShSize: [[SIZE=<none>]]
Entries:
- Address: 0x0
- Version: 1
Feature: 0xFF
Address: 0x0
BBEntries:
- AddressOffset: 0x1
Size: 0x2
Metadata: 0x3
- AddressOffset: 0x4
Size: 0x5
Metadata: 0x6
- AddressOffset: 0xFFFFFFFFFFFFFFF7
Size: 0xFFFFFFFFFFFFFFF8
Metadata: 0xFFFFFFFFFFFFFFF9
- Version: 1
Feature: 0xEE
Address: 0xFFFFFFFFFFFFFF20
NumBlocks: [[NUMBLOCKS=<none>]]
BBEntries:
- AddressOffset: 0x1
Size: 0x2
Metadata: 0x3
- AddressOffset: 0x4
Size: 0x5
Metadata: 0x6
- AddressOffset: 0xFFFFFFFFFFFFFFF7
Size: 0xFFFFFFFFFFFFFFF8
Metadata: 0xFFFFFFFFFFFFFFF9
- Address: 0xFFFFFFFFFFFFFF20
BBEntries:
- AddressOffset: 0xA
Size: 0xB
Metadata: 0xC
- AddressOffset: 0xA
Size: 0xB
Metadata: 0xC
## Check obj2yaml can dump empty .llvm_bb_addr_map sections.
@ -95,18 +103,20 @@ Sections:
# 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: - 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: 0x1
# MULTI-NEXT: Size: 0x2
# MULTI-NEXT: Metadata: 0x3
# MULTI-NEXT: - Name: '.llvm_bb_addr_map (1)'
# MULTI-NEXT: Type: SHT_LLVM_BB_ADDR_MAP
## Fields 'Address' and 'Feature' are omitted when they are zero.
# MULTI-NEXT: - Version: 0
# MULTI-NEXT: BBEntries:
# MULTI-NEXT: - AddressOffset: 0x1
# MULTI-NEXT: Size: 0x2
# MULTI-NEXT: Metadata: 0x3
# MULTI-NEXT: - Name: '.llvm_bb_addr_map (1)'
# MULTI-NEXT: Type: SHT_LLVM_BB_ADDR_MAP
# MULTI-NEXT: Entries:
# MULTI-NEXT: - Address: 0x20
# MULTI-NEXT: - Version: 0
# MULTI-NEXT: Address: 0x20
# MULTI-NEXT: BBEntries: []
--- !ELF
@ -115,19 +125,23 @@ FileHeader:
Data: ELFDATA2LSB
Type: ET_EXEC
Sections:
- Name: .llvm_bb_addr_map
Type: SHT_LLVM_BB_ADDR_MAP
- 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: 0x0
## Check that obj2yaml does not emit the 'Address' and 'Feature' fields when
## they are zero.
- Version: 0
Feature: 0x0
Address: 0x0
BBEntries:
- AddressOffset: 0x1
Size: 0x2
Metadata: 0x3
- Name: '.llvm_bb_addr_map (1)'
Type: SHT_LLVM_BB_ADDR_MAP
- AddressOffset: 0x1
Size: 0x2
Metadata: 0x3
- Name: '.llvm_bb_addr_map (1)'
Type: SHT_LLVM_BB_ADDR_MAP
Entries:
- Address: 0x20
- Version: 0
Address: 0x20
## Check that obj2yaml uses the "Content" tag to describe an .llvm_bb_addr_map section
## when it can't extract the entries, for example, when the section is truncated, or
@ -141,11 +155,47 @@ Sections:
# INVALID: --- !ELF
# INVALID-NEXT: FileHeader:
# INVALID-NEXT: Class: ELFCLASS64
# INVALID-NEXT: Data: ELFDATA2LSB
# INVALID-NEXT: Type: ET_EXEC
# 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: - Name: .llvm_bb_addr_map
# INVALID-NEXT: Type: SHT_LLVM_BB_ADDR_MAP
# BADNUMBLOCKS-NEXT: Content: {{([[:xdigit:]]+)}}{{$}}
# TRUNCATED-NEXT: Content: '{{([[:xdigit:]]{16})}}'{{$}}
# TRUNCATED-NEXT: Content: {{([[:xdigit:]]{16})}}{{$}}
## Check obj2yaml for SHT_LLVM_BB_ADDR_MAP_V0.
# RUN: yaml2obj --docnum=4 %s -o %t6
# RUN: obj2yaml %t6 | FileCheck %s --check-prefix=V0
# V0: --- !ELF
# V0-NEXT: FileHeader:
# V0-NEXT: Class: ELFCLASS64
# V0-NEXT: Data: ELFDATA2LSB
# V0-NEXT: Type: ET_EXEC
# V0-NEXT: Sections:
# V0-NEXT: - Name: .llvm_bb_addr_map
# V0-NEXT: Type: SHT_LLVM_BB_ADDR_MAP_V0
# V0-NEXT: Entries:
# V0-NEXT: - Version: 0
# V0-NEXT: Address: 0x1111
# V0-NEXT: BBEntries:
# V0-NEXT: - AddressOffset: 0x1
# V0-NEXT: Size: 0x2
# V0-NEXT: Metadata: 0x3
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Sections:
- Name: .llvm_bb_addr_map
Type: SHT_LLVM_BB_ADDR_MAP_V0
Entries:
- Version: 0
Address: 0x1111
BBEntries:
- AddressOffset: 0x1
Size: 0x2
Metadata: 0x3

View File

@ -7,7 +7,7 @@
# CHECK: Section {
# CHECK: Index: 1
# CHECK-NEXT: Name: .llvm_bb_addr_map (1)
# CHECK-NEXT: Type: SHT_LLVM_BB_ADDR_MAP (0x6FFF4C08)
# CHECK-NEXT: Type: SHT_LLVM_BB_ADDR_MAP (0x6FFF4C0A)
# CHECK-NEXT: Flags [ (0x0)
# CHECK-NEXT: ]
# CHECK-NEXT: Address: 0x0
@ -36,7 +36,7 @@
# Case 4: Specify Entries.
# CHECK: Name: .llvm_bb_addr_map (1)
# CHECK: SectionData (
# CHECK-NEXT: 0000: 20000000 00000000 01010203
# CHECK-NEXT: 0000: 01002000 00000000 00000101 0203
# CHECK-NEXT: )
# Case 5: Specify Entries and omit the Address field.
@ -44,13 +44,13 @@
# CHECK: Address:
# CHECK-SAME: {{^ 0x0$}}
# CHECK: SectionData (
# CHECK-NEXT: 0000: 00000000 00000000 01010203
# CHECK-NEXT: 0000: 00000000 00000000 00000101 0203
# CHECK-NEXT: )
# Case 6: Override the NumBlocks field.
# CHECK: Name: .llvm_bb_addr_map (1)
# CHECK: SectionData (
# CHECK-NEXT: 0000: 20000000 00000000 02010203
# CHECK-NEXT: 0000: 01002000 00000000 00000201 0203
# CHECK-NEXT: )
--- !ELF
@ -71,47 +71,50 @@ Sections:
## 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
- 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
- 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
- Name: '.llvm_bb_addr_map (4)'
Type: SHT_LLVM_BB_ADDR_MAP
Entries:
- Address: 0x0000000000000020
- Version: 1
Address: 0x0000000000000020
BBEntries:
- AddressOffset: 0x00000001
Size: 0x00000002
Metadata: 0x00000003
- 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
- Name: '.llvm_bb_addr_map (5)'
Type: SHT_LLVM_BB_ADDR_MAP
Entries:
- BBEntries:
- AddressOffset: 0x00000001
Size: 0x00000002
Metadata: 0x00000003
- Version: 0
BBEntries:
- AddressOffset: 0x00000001
Size: 0x00000002
Metadata: 0x00000003
## 6) We can override the NumBlocks field with a value different from the
## actual number of BB Entries.
- Name: '.llvm_bb_addr_map (6)'
Type: SHT_LLVM_BB_ADDR_MAP
- Name: '.llvm_bb_addr_map (6)'
Type: SHT_LLVM_BB_ADDR_MAP
Entries:
- Address: 0x0000000000000020
- Version: 1
Address: 0x0000000000000020
NumBlocks: 2
BBEntries:
- AddressOffset: 0x00000001
Size: 0x00000002
Metadata: 0x00000003
- 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
@ -131,3 +134,19 @@ Sections:
Entries: []
Content: [[CONTENT=<none>]]
Size: [[SIZE=<none>]]
## Check that yaml2obj generates a warning when we use unsupported versions.
# RUN: yaml2obj --docnum=3 %s 2>&1 | FileCheck %s --check-prefix=INVALID-VERSION
# INVALID-VERSION: warning: unsupported SHT_LLVM_BB_ADDR_MAP version: 2; encoding using the most recent version
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Sections:
- Name: '.llvm_bb_addr_map'
Type: SHT_LLVM_BB_ADDR_MAP
Entries:
## Specify unsupported version
- Version: 2

View File

@ -7028,8 +7028,10 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printCGProfile() {
template <class ELFT> void LLVMELFDumper<ELFT>::printBBAddrMaps() {
bool IsRelocatable = this->Obj.getHeader().e_type == ELF::ET_REL;
for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) {
if (Sec.sh_type != SHT_LLVM_BB_ADDR_MAP)
if (Sec.sh_type != SHT_LLVM_BB_ADDR_MAP &&
Sec.sh_type != SHT_LLVM_BB_ADDR_MAP_V0) {
continue;
}
Optional<const Elf_Shdr *> FunctionSec = None;
if (IsRelocatable)
FunctionSec =

View File

@ -626,6 +626,7 @@ 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_V0:
case ELF::SHT_LLVM_BB_ADDR_MAP:
return [this](const Elf_Shdr *S) { return dumpBBAddrMapSection(S); };
case ELF::SHT_STRTAB:
@ -889,7 +890,18 @@ ELFDumper<ELFT>::dumpBBAddrMapSection(const Elf_Shdr *Shdr) {
std::vector<ELFYAML::BBAddrMapEntry> Entries;
DataExtractor::Cursor Cur(0);
uint8_t Version = 0;
uint8_t Feature = 0;
while (Cur && Cur.tell() < Content.size()) {
if (Shdr->sh_type == ELF::SHT_LLVM_BB_ADDR_MAP) {
Version = Data.getU8(Cur);
if (Cur && Version > 1)
return createStringError(
errc::invalid_argument,
"invalid SHT_LLVM_BB_ADDR_MAP section version: " +
Twine(static_cast<int>(Version)));
Feature = Data.getU8(Cur);
}
uint64_t Address = Data.getAddress(Cur);
uint64_t NumBlocks = Data.getULEB128(Cur);
std::vector<ELFYAML::BBAddrMapEntry::BBEntry> BBEntries;
@ -900,7 +912,8 @@ ELFDumper<ELFT>::dumpBBAddrMapSection(const Elf_Shdr *Shdr) {
uint64_t Metadata = Data.getULEB128(Cur);
BBEntries.push_back({Offset, Size, Metadata});
}
Entries.push_back({Address, /*NumBlocks=*/{}, BBEntries});
Entries.push_back(
{Version, Feature, Address, /*NumBlocks=*/{}, std::move(BBEntries)});
}
if (!Cur) {

View File

@ -505,14 +505,10 @@ FileHeader:
Data: ELFDATA2LSB
Type: ET_EXEC
Sections:
- Name: .llvm_bb_addr_map
Type: SHT_LLVM_BB_ADDR_MAP
- Type: SHT_LLVM_BB_ADDR_MAP
Name: .llvm_bb_addr_map
Entries:
- Address: 0x11111
BBEntries:
- AddressOffset: 0x0
Size: 0x1
Metadata: 0x2
)");
auto DoCheck = [&](StringRef YamlString, const char *ErrMsg) {
@ -529,19 +525,41 @@ Sections:
FailedWithMessage(ErrMsg));
};
// Check that we can detect unsupported versions.
SmallString<128> UnsupportedVersionYamlString(CommonYamlString);
UnsupportedVersionYamlString += R"(
Version: 2
BBEntries:
- AddressOffset: 0x0
Size: 0x1
Metadata: 0x2
)";
DoCheck(UnsupportedVersionYamlString,
"unsupported SHT_LLVM_BB_ADDR_MAP version: 2");
SmallString<128> CommonVersionedYamlString(CommonYamlString);
CommonVersionedYamlString += R"(
Version: 1
BBEntries:
- AddressOffset: 0x0
Size: 0x1
Metadata: 0x2
)";
// Check that we can detect the malformed encoding when the section is
// truncated.
SmallString<128> TruncatedYamlString(CommonYamlString);
SmallString<128> TruncatedYamlString(CommonVersionedYamlString);
TruncatedYamlString += R"(
ShSize: 0x8
ShSize: 0xa
)";
DoCheck(TruncatedYamlString, "unable to decode LEB128 at offset 0x00000008: "
DoCheck(TruncatedYamlString, "unable to decode LEB128 at offset 0x0000000a: "
"malformed uleb128, extends past end");
// Check that we can detect when the encoded BB entry fields exceed the UINT32
// limit.
SmallVector<SmallString<128>, 3> OverInt32LimitYamlStrings(3,
CommonYamlString);
SmallVector<SmallString<128>, 3> OverInt32LimitYamlStrings(
3, CommonVersionedYamlString);
OverInt32LimitYamlStrings[0] += R"(
- AddressOffset: 0x100000000
Size: 0xFFFFFFFF
@ -561,11 +579,11 @@ Sections:
)";
DoCheck(OverInt32LimitYamlStrings[0],
"ULEB128 value at offset 0xc exceeds UINT32_MAX (0x100000000)");
"ULEB128 value at offset 0xe exceeds UINT32_MAX (0x100000000)");
DoCheck(OverInt32LimitYamlStrings[1],
"ULEB128 value at offset 0x11 exceeds UINT32_MAX (0x100000000)");
"ULEB128 value at offset 0x13 exceeds UINT32_MAX (0x100000000)");
DoCheck(OverInt32LimitYamlStrings[2],
"ULEB128 value at offset 0x16 exceeds UINT32_MAX (0x100000000)");
"ULEB128 value at offset 0x18 exceeds UINT32_MAX (0x100000000)");
// Check the proper error handling when the section has fields exceeding
// UINT32 and is also truncated. This is for checking that we don't generate
@ -574,34 +592,34 @@ Sections:
3, OverInt32LimitYamlStrings[1]);
// Truncate before the end of the 5-byte field.
OverInt32LimitAndTruncated[0] += R"(
ShSize: 0x15
ShSize: 0x17
)";
// Truncate at the end of the 5-byte field.
OverInt32LimitAndTruncated[1] += R"(
ShSize: 0x16
ShSize: 0x18
)";
// Truncate after the end of the 5-byte field.
OverInt32LimitAndTruncated[2] += R"(
ShSize: 0x17
ShSize: 0x19
)";
DoCheck(OverInt32LimitAndTruncated[0],
"unable to decode LEB128 at offset 0x00000011: malformed uleb128, "
"unable to decode LEB128 at offset 0x00000013: malformed uleb128, "
"extends past end");
DoCheck(OverInt32LimitAndTruncated[1],
"ULEB128 value at offset 0x11 exceeds UINT32_MAX (0x100000000)");
"ULEB128 value at offset 0x13 exceeds UINT32_MAX (0x100000000)");
DoCheck(OverInt32LimitAndTruncated[2],
"ULEB128 value at offset 0x11 exceeds UINT32_MAX (0x100000000)");
"ULEB128 value at offset 0x13 exceeds UINT32_MAX (0x100000000)");
// Check for proper error handling when the 'NumBlocks' field is overridden
// with an out-of-range value.
SmallString<128> OverLimitNumBlocks(CommonYamlString);
SmallString<128> OverLimitNumBlocks(CommonVersionedYamlString);
OverLimitNumBlocks += R"(
NumBlocks: 0x100000000
)";
DoCheck(OverLimitNumBlocks,
"ULEB128 value at offset 0x8 exceeds UINT32_MAX (0x100000000)");
"ULEB128 value at offset 0xa exceeds UINT32_MAX (0x100000000)");
}
// Test for the ELFObjectFile::readBBAddrMap API.
@ -617,7 +635,8 @@ Sections:
Type: SHT_LLVM_BB_ADDR_MAP
Link: 1
Entries:
- Address: 0x11111
- Version: 1
Address: 0x11111
BBEntries:
- AddressOffset: 0x0
Size: 0x1
@ -626,16 +645,18 @@ Sections:
Type: SHT_LLVM_BB_ADDR_MAP
Link: 1
Entries:
- Address: 0x22222
- Version: 1
Address: 0x22222
BBEntries:
- AddressOffset: 0x0
Size: 0x2
Metadata: 0x4
- Name: .llvm_bb_addr_map
Type: SHT_LLVM_BB_ADDR_MAP
Type: SHT_LLVM_BB_ADDR_MAP_V0
# Link: 0 (by default)
Entries:
- Address: 0x33333
- Version: 0
Address: 0x33333
BBEntries:
- AddressOffset: 0x0
Size: 0x3
@ -697,8 +718,9 @@ Sections:
)";
DoCheckFails(InvalidLinkedYamlString, /*TextSectionIndex=*/1,
"unable to get the linked-to section for SHT_LLVM_BB_ADDR_MAP "
"section with index 3: invalid section index: 10");
"unable to get the linked-to section for "
"SHT_LLVM_BB_ADDR_MAP_V0 section with index 3: invalid section "
"index: 10");
// Linked sections are not checked when we don't target a specific text
// section.
DoCheckSucceeds(InvalidLinkedYamlString, /*TextSectionIndex=*/None,
@ -711,7 +733,7 @@ Sections:
)";
DoCheckFails(TruncatedYamlString, /*TextSectionIndex=*/None,
"unable to read SHT_LLVM_BB_ADDR_MAP section with index 3: "
"unable to read SHT_LLVM_BB_ADDR_MAP_V0 section with index 3: "
"unable to decode LEB128 at offset 0x00000008: malformed "
"uleb128, extends past end");
// Check that we can read the other section's bb-address-maps which are