[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 metadata. This information can be used to map binary profiles (like perf
profiles) directly to machine basic blocks. profiles) directly to machine basic blocks.
This section is emitted with ``-basic-block-sections=labels`` and will contain 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 .. code-block:: gas
.section ".llvm_bb_addr_map","",@llvm_bb_addr_map .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 .quad .Lfunc_begin0 # address of the function
.byte 2 # number of basic blocks .byte 2 # number of basic blocks
# BB record for BB_0 # 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 .uleb128 .LBB_END0_0-.Lfunc_begin0 # BB_0 size
.byte x # BB_0 metadata .byte x # BB_0 metadata
# BB record for BB_1 # BB record for BB_1
.uleb128 .LBB0_1-.Lfunc_begin0 # BB_1 offset relative to function entry .uleb128 .LBB0_1-.LBB_END0_0 # BB_1 offset relative to the end of last block (BB_0).
.uleb128 .LBB_END0_1-.Lfunc_begin0 # BB_1 size .uleb128 .LBB_END0_1-.LBB0_1 # BB_1 size
.byte y # BB_1 metadata .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 CodeView-Dependent
------------------ ------------------

View File

@ -981,12 +981,15 @@ enum : unsigned {
SHT_LLVM_ADDRSIG = 0x6fff4c03, // List of address-significant symbols SHT_LLVM_ADDRSIG = 0x6fff4c03, // List of address-significant symbols
// for safe ICF. // for safe ICF.
SHT_LLVM_DEPENDENT_LIBRARIES = SHT_LLVM_DEPENDENT_LIBRARIES =
0x6fff4c04, // LLVM Dependent Library Specifiers. 0x6fff4c04, // LLVM Dependent Library Specifiers.
SHT_LLVM_SYMPART = 0x6fff4c05, // Symbol partition specification. SHT_LLVM_SYMPART = 0x6fff4c05, // Symbol partition specification.
SHT_LLVM_PART_EHDR = 0x6fff4c06, // ELF header for loadable partition. SHT_LLVM_PART_EHDR = 0x6fff4c06, // ELF header for loadable partition.
SHT_LLVM_PART_PHDR = 0x6fff4c07, // Phdrs for loadable partition. SHT_LLVM_PART_PHDR = 0x6fff4c07, // Phdrs for loadable partition.
SHT_LLVM_BB_ADDR_MAP = 0x6fff4c08, // LLVM Basic Block Address Map. 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_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. // Android's experimental support for SHT_RELR sections.
// https://android.googlesource.com/platform/bionic/+/b7feec74547f84559a1467aca02708ff61346d2a/libc/include/elf.h#512 // https://android.googlesource.com/platform/bionic/+/b7feec74547f84559a1467aca02708ff61346d2a/libc/include/elf.h#512
SHT_ANDROID_RELR = 0x6fffff00, // Relocation entries; only offsets. 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. /// for the LocalLabelVal and adds it to the map if needed.
unsigned GetInstance(unsigned LocalLabelVal); 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 /// The file name of the log file from the environment variable
/// AS_SECURE_LOG_FILE. Which must be set before the .secure_log_unique /// AS_SECURE_LOG_FILE. Which must be set before the .secure_log_unique
/// directive is used or it is an error. /// 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. // Create and save a copy of STI and return a reference to the copy.
MCSubtargetInfo &getSubtargetCopy(const MCSubtargetInfo &STI); MCSubtargetInfo &getSubtargetCopy(const MCSubtargetInfo &STI);
uint8_t getBBAddrMapVersion() const { return BBAddrMapVersion; }
/// @} /// @}
/// \name Dwarf Management /// \name Dwarf Management

View File

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

View File

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

View File

@ -60,7 +60,7 @@
// Basic Block Labels // 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 // 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 // symbols, this allows for mapping of virtual addresses in PMU profiles back to
// the corresponding basic blocks. This logic is implemented in AsmPrinter. This // 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"; OS << "llvm_sympart";
else if (Type == ELF::SHT_LLVM_BB_ADDR_MAP) else if (Type == ELF::SHT_LLVM_BB_ADDR_MAP)
OS << "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 else
report_fatal_error("unsupported type 0x" + Twine::utohexstr(Type) + report_fatal_error("unsupported type 0x" + Twine::utohexstr(Type) +
" for section " + getName()); " 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_SYMPART);
STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_PART_EHDR); STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_PART_EHDR);
STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_PART_PHDR); 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_LLVM_BB_ADDR_MAP);
STRINGIFY_ENUM_CASE(ELF, SHT_GNU_ATTRIBUTES); STRINGIFY_ENUM_CASE(ELF, SHT_GNU_ATTRIBUTES);
STRINGIFY_ENUM_CASE(ELF, SHT_GNU_HASH); STRINGIFY_ENUM_CASE(ELF, SHT_GNU_HASH);
@ -640,7 +641,6 @@ ELFFile<ELFT>::decodeBBAddrMap(const Elf_Shdr &Sec) const {
DataExtractor::Cursor Cur(0); DataExtractor::Cursor Cur(0);
Error ULEBSizeErr = Error::success(); Error ULEBSizeErr = Error::success();
// Helper to extract and decode the next ULEB128 value as uint32_t. // 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 // Returns zero and sets ULEBSizeErr if the ULEB128 value exceeds the uint32_t
// limit. // limit.
@ -660,18 +660,34 @@ ELFFile<ELFT>::decodeBBAddrMap(const Elf_Shdr &Sec) const {
return static_cast<uint32_t>(Value); return static_cast<uint32_t>(Value);
}; };
uint8_t Version = 0;
while (!ULEBSizeErr && Cur && Cur.tell() < Content.size()) { 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)); uintX_t Address = static_cast<uintX_t>(Data.getAddress(Cur));
uint32_t NumBlocks = ReadULEB128AsUInt32(); uint32_t NumBlocks = ReadULEB128AsUInt32();
std::vector<BBAddrMap::BBEntry> BBEntries; std::vector<BBAddrMap::BBEntry> BBEntries;
uint32_t PrevBBEndOffset = 0;
for (uint32_t BlockID = 0; !ULEBSizeErr && Cur && (BlockID < NumBlocks); for (uint32_t BlockID = 0; !ULEBSizeErr && Cur && (BlockID < NumBlocks);
++BlockID) { ++BlockID) {
uint32_t Offset = ReadULEB128AsUInt32(); uint32_t Offset = ReadULEB128AsUInt32();
uint32_t Size = ReadULEB128AsUInt32(); uint32_t Size = ReadULEB128AsUInt32();
uint32_t Metadata = 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}); 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 // Either Cur is in the error state, or ULEBSizeError is set (not both), but
// we join the two errors here to be safe. // we join the two errors here to be safe.

View File

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

View File

@ -1393,6 +1393,16 @@ void ELFState<ELFT>::writeSectionContent(
return; return;
for (const ELFYAML::BBAddrMapEntry &E : *Section.Entries) { 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. // Write the address of the function.
CBA.write<uintX_t>(E.Address, ELFT::TargetEndianness); CBA.write<uintX_t>(E.Address, ELFT::TargetEndianness);
// Write number of BBEntries (number of basic blocks in the function). This // 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_SYMPART);
ECase(SHT_LLVM_PART_EHDR); ECase(SHT_LLVM_PART_EHDR);
ECase(SHT_LLVM_PART_PHDR); ECase(SHT_LLVM_PART_PHDR);
ECase(SHT_LLVM_BB_ADDR_MAP_V0);
ECase(SHT_LLVM_BB_ADDR_MAP); ECase(SHT_LLVM_BB_ADDR_MAP);
ECase(SHT_GNU_ATTRIBUTES); ECase(SHT_GNU_ATTRIBUTES);
ECase(SHT_GNU_HASH); ECase(SHT_GNU_HASH);
@ -1639,6 +1640,7 @@ void MappingTraits<std::unique_ptr<ELFYAML::Chunk>>::mapping(
Section.reset(new ELFYAML::CallGraphProfileSection()); Section.reset(new ELFYAML::CallGraphProfileSection());
sectionMapping(IO, *cast<ELFYAML::CallGraphProfileSection>(Section.get())); sectionMapping(IO, *cast<ELFYAML::CallGraphProfileSection>(Section.get()));
break; break;
case ELF::SHT_LLVM_BB_ADDR_MAP_V0:
case ELF::SHT_LLVM_BB_ADDR_MAP: case ELF::SHT_LLVM_BB_ADDR_MAP:
if (!IO.outputting()) if (!IO.outputting())
Section.reset(new ELFYAML::BBAddrMapSection()); Section.reset(new ELFYAML::BBAddrMapSection());
@ -1768,6 +1770,8 @@ void MappingTraits<ELFYAML::StackSizeEntry>::mapping(
void MappingTraits<ELFYAML::BBAddrMapEntry>::mapping( void MappingTraits<ELFYAML::BBAddrMapEntry>::mapping(
IO &IO, ELFYAML::BBAddrMapEntry &E) { IO &IO, ELFYAML::BBAddrMapEntry &E) {
assert(IO.getContext() && "The IO context is not initialized"); 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("Address", E.Address, Hex64(0));
IO.mapOptional("NumBlocks", E.NumBlocks); IO.mapOptional("NumBlocks", E.NumBlocks);
IO.mapOptional("BBEntries", E.BBEntries); IO.mapOptional("BBEntries", E.BBEntries);

View File

@ -18,4 +18,6 @@ entry:
; CHECK: func: ; CHECK: func:
; CHECK: .Lfunc_begin1: ; CHECK: .Lfunc_begin1:
; CHECK: .section .llvm_bb_addr_map,"o",@llvm_bb_addr_map,.text{{$}} ; 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-LABEL: _Z3barv:
; CHECK-NEXT: [[BAR_BEGIN:.Lfunc_begin[0-9]+]]: ; CHECK-NEXT: [[BAR_BEGIN:.Lfunc_begin[0-9]+]]:
; CHECK: .section .llvm_bb_addr_map,"o",@llvm_bb_addr_map,.text._Z3barv{{$}} ; 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() { define dso_local i32 @_Z3foov() {
@ -21,7 +23,9 @@ define dso_local i32 @_Z3foov() {
; CHECK-LABEL: _Z3foov: ; CHECK-LABEL: _Z3foov:
; CHECK-NEXT: [[FOO_BEGIN:.Lfunc_begin[0-9]+]]: ; CHECK-NEXT: [[FOO_BEGIN:.Lfunc_begin[0-9]+]]:
; CHECK: .section .llvm_bb_addr_map,"o",@llvm_bb_addr_map,.text._Z3foov{{$}} ; 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 { 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-LABEL: _Z4fooTIiET_v:
; CHECK-NEXT: [[FOOCOMDAT_BEGIN:.Lfunc_begin[0-9]+]]: ; 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: .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{{$}} ; 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. ;; 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 ; NOUNIQ: .section .llvm_bb_addr_map,"o",@llvm_bb_addr_map,.text,unique,1
; CHECK-NEXT: .quad .Lfunc_begin0 ; CHECK-NEXT: .byte 1 # version
; CHECK-NEXT: .byte 4 ; 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 .Lfunc_begin0-.Lfunc_begin0
; CHECK-NEXT: .uleb128 .LBB_END0_0-.Lfunc_begin0 ; CHECK-NEXT: .uleb128 .LBB_END0_0-.Lfunc_begin0
; CHECK-NEXT: .byte 8 ; 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: .uleb128 .LBB_END0_1-.LBB0_1
; CHECK-NEXT: .byte 8 ; 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: .uleb128 .LBB_END0_2-.LBB0_2
; CHECK-NEXT: .byte 1 ; 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: .uleb128 .LBB_END0_3-.LBB0_3
; CHECK-NEXT: .byte 5 ; CHECK-NEXT: .byte 5

View File

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

View File

@ -1,75 +1,62 @@
## This test checks how we handle the --bb-addr-map option. ## This test checks how we handle the --bb-addr-map option.
# Check 64-bit: ## Check 64-bit:
# RUN: yaml2obj %s -DBITS=64 -DADDR=0x999999999 -o %t1.x64.o # 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=LLVM # 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 # 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: ## Check 32-bit:
# RUN: yaml2obj %s -DBITS=32 -o %t1.x32.o # 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=LLVM # 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 # RUN: llvm-readelf %t1.x32.o --bb-addr-map | FileCheck %s --check-prefix=GNU
## Check that a malformed section can be handled. ## Check that a malformed section can be handled.
# RUN: yaml2obj %s -DBITS=32 -DSIZE=4 -o %t2.o # 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=0x00000004 -DFILE=%t2.o --check-prefix=TRUNCATED # RUN: llvm-readobj %t2.o --bb-addr-map 2>&1 | FileCheck %s -DOFFSET=0x00000006 -DFILE=%t2.o --check-prefix=TRUNCATED
# LLVM: BBAddrMap [ # CHECK: BBAddrMap [
# LLVM-NEXT: Function { # CHECK-NEXT: Function {
# LLVM-NEXT: At: [[ADDR]] # CHECK-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 # CHECK-NEXT: warning: '[[FILE]]': could not identify function symbol for address ([[ADDR]]) in SHT_LLVM_BB_ADDR_MAP section with index 3
# LLVM-NEXT: Name: <?> # CHECK-NEXT: Name: <?>
# LLVM-NEXT: BB entries [ # CHECK-NEXT: BB entries [
# LLVM-NEXT: { # CHECK-NEXT: {
# LLVM-NEXT: Offset: 0x0 # CHECK-NEXT: Offset: 0x0
# LLVM-NEXT: Size: 0x1 # CHECK-NEXT: Size: 0x1
# LLVM-NEXT: HasReturn: No # CHECK-NEXT: HasReturn: No
# LLVM-NEXT: HasTailCall: Yes # CHECK-NEXT: HasTailCall: Yes
# LLVM-NEXT: IsEHPad: No # CHECK-NEXT: IsEHPad: No
# LLVM-NEXT: CanFallThrough: No # CHECK-NEXT: CanFallThrough: No
# LLVM-NEXT: } # CHECK-NEXT: }
# LLVM-NEXT: { # CHECK-NEXT: {
# LLVM-NEXT: Offset: 0x3 # CHECK-NEXT: Offset: 0x4
# LLVM-NEXT: Size: 0x4 # CHECK-NEXT: Size: 0x4
# LLVM-NEXT: HasReturn: Yes # CHECK-NEXT: HasReturn: Yes
# LLVM-NEXT: HasTailCall: No # CHECK-NEXT: HasTailCall: No
# LLVM-NEXT: IsEHPad: Yes # CHECK-NEXT: IsEHPad: Yes
# LLVM-NEXT: CanFallThrough: No # CHECK-NEXT: CanFallThrough: No
# LLVM-NEXT: } # CHECK-NEXT: }
# LLVM-NEXT: ] # CHECK-NEXT: ]
# LLVM-NEXT: } # CHECK-NEXT: }
# LLVM-NEXT: Function { # CHECK-NEXT: Function {
# LLVM-NEXT: At: 0x22222 # CHECK-NEXT: At: 0x22222
# LLVM-NEXT: Name: foo # CHECK-NEXT: Name: foo
# LLVM-NEXT: BB entries [ # CHECK-NEXT: BB entries [
# LLVM-NEXT: { # CHECK-NEXT: {
# LLVM-NEXT: Offset: 0x6 # CHECK-NEXT: Offset: 0x6
# LLVM-NEXT: Size: 0x7 # CHECK-NEXT: Size: 0x7
# LLVM-NEXT: HasReturn: No # CHECK-NEXT: HasReturn: No
# LLVM-NEXT: HasTailCall: No # CHECK-NEXT: HasTailCall: No
# LLVM-NEXT: IsEHPad: No # CHECK-NEXT: IsEHPad: No
# LLVM-NEXT: CanFallThrough: Yes # CHECK-NEXT: CanFallThrough: Yes
# LLVM-NEXT: } # CHECK-NEXT: }
# LLVM-NEXT: ] # CHECK-NEXT: ]
# LLVM-NEXT: } # CHECK-NEXT: }
# LLVM-NEXT: ] # CHECK-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: ]
# GNU: GNUStyle::printBBAddrMaps not implemented # GNU: GNUStyle::printBBAddrMaps not implemented
@ -90,6 +77,14 @@
# TRUNCATED-NEXT: IsEHPad: No # TRUNCATED-NEXT: IsEHPad: No
# TRUNCATED-NEXT: CanFallThrough: Yes # TRUNCATED-NEXT: CanFallThrough: Yes
# TRUNCATED-NEXT: } # 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: } # TRUNCATED-NEXT: }
# TRUNCATED-NEXT: ] # TRUNCATED-NEXT: ]
@ -106,12 +101,13 @@ Sections:
- Name: .text.bar - Name: .text.bar
Type: SHT_PROGBITS Type: SHT_PROGBITS
Flags: [SHF_ALLOC] Flags: [SHF_ALLOC]
- Name: bb_addr_map_1 - Name: .llvm_bb_addr_map
Type: SHT_LLVM_BB_ADDR_MAP Type: SHT_LLVM_BB_ADDR_MAP
ShSize: [[SIZE=<none>]] ShSize: [[SIZE=<none>]]
Link: .text Link: .text
Entries: Entries:
- Address: [[ADDR=0x11111]] - Version: 1
Address: [[ADDR=0x11111]]
BBEntries: BBEntries:
- AddressOffset: 0x0 - AddressOffset: 0x0
Size: 0x1 Size: 0x1
@ -119,23 +115,28 @@ Sections:
- AddressOffset: 0x3 - AddressOffset: 0x3
Size: 0x4 Size: 0x4
Metadata: 0x5 Metadata: 0x5
- Address: 0x22222 - Version: 1
Address: 0x22222
BBEntries: BBEntries:
- AddressOffset: 0x6 - AddressOffset: 0x6
Size: 0x7 Size: 0x7
Metadata: 0x8 Metadata: 0x8
- Name: dummy_section - Name: dummy_section
Type: SHT_PROGBITS Type: SHT_PROGBITS
Size: 16 Size: 16
- Name: bb_addr_map_2 - Name: '.llvm_bb_addr_map (1)'
Type: SHT_LLVM_BB_ADDR_MAP Type: SHT_LLVM_BB_ADDR_MAP
Link: .text.bar Link: .text.bar
Entries: Entries:
- Address: 0x33333 - Version: 1
Address: 0x33333
BBEntries: BBEntries:
- AddressOffset: 0x9 - AddressOffset: 0x9
Size: 0xa Size: 0xa
Metadata: 0xb Metadata: 0xb
- AddressOffset: 0xc
Size: 0xd
Metadata: 0xe
Symbols: Symbols:
- Name: foo - Name: foo
Section: .text Section: .text
@ -145,3 +146,67 @@ Symbols:
Section: .text.bar Section: .text.bar
Type: STT_FUNC Type: STT_FUNC
Value: 0x33333 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: --- !ELF
# VALID-NEXT: FileHeader: # VALID-NEXT: FileHeader:
# VALID-NEXT: Class: ELFCLASS64 # VALID-NEXT: Class: ELFCLASS64
# VALID-NEXT: Data: ELFDATA2LSB # VALID-NEXT: Data: ELFDATA2LSB
# VALID-NEXT: Type: ET_EXEC # VALID-NEXT: Type: ET_EXEC
# VALID-NEXT: Sections: # VALID-NEXT: Sections:
# VALID-NEXT: - Name: .llvm_bb_addr_map # VALID-NEXT: - Name: .llvm_bb_addr_map
# VALID-NEXT: Type: SHT_LLVM_BB_ADDR_MAP # VALID-NEXT: Type: SHT_LLVM_BB_ADDR_MAP
# VALID-NEXT: Entries: # VALID-NEXT: Entries:
## The 'Address' field is omitted when it's zero. ## The 'Address' field is omitted when it's zero.
# VALID-NEXT: - Version: 1
# VALID-NEXT: Feature: 0xFF
# VALID-NEXT: BBEntries: # VALID-NEXT: BBEntries:
# VALID-NEXT: - AddressOffset: 0x1 # VALID-NEXT: - AddressOffset: 0x1
# VALID-NEXT: Size: 0x2 # VALID-NEXT: Size: 0x2
# VALID-NEXT: Metadata: 0x3 # VALID-NEXT: Metadata: 0x3
# VALID-NEXT: - AddressOffset: 0x4 # VALID-NEXT: - AddressOffset: 0x4
# VALID-NEXT: Size: 0x5 # VALID-NEXT: Size: 0x5
# VALID-NEXT: Metadata: 0x6 # VALID-NEXT: Metadata: 0x6
# VALID-NEXT: - AddressOffset: 0xFFFFFFFFFFFFFFF7 # VALID-NEXT: - AddressOffset: 0xFFFFFFFFFFFFFFF7
# VALID-NEXT: Size: 0xFFFFFFFFFFFFFFF8 # VALID-NEXT: Size: 0xFFFFFFFFFFFFFFF8
# VALID-NEXT: Metadata: 0xFFFFFFFFFFFFFFF9 # VALID-NEXT: Metadata: 0xFFFFFFFFFFFFFFF9
# VALID-NEXT: - Address: 0xFFFFFFFFFFFFFF20 # VALID-NEXT: - Version: 1
# VALID-NEXT: Feature: 0xEE
# VALID-NEXT: Address: 0xFFFFFFFFFFFFFF20
# VALID-NEXT: BBEntries: # VALID-NEXT: BBEntries:
# VALID-NEXT: - AddressOffset: 0xA # VALID-NEXT: - AddressOffset: 0xA
# VALID-NEXT: Size: 0xB # VALID-NEXT: Size: 0xB
# VALID-NEXT: Metadata: 0xC # VALID-NEXT: Metadata: 0xC
--- !ELF --- !ELF
FileHeader: FileHeader:
@ -37,27 +41,31 @@ FileHeader:
Data: ELFDATA2LSB Data: ELFDATA2LSB
Type: ET_EXEC Type: ET_EXEC
Sections: Sections:
- Name: .llvm_bb_addr_map - Name: .llvm_bb_addr_map
Type: SHT_LLVM_BB_ADDR_MAP Type: SHT_LLVM_BB_ADDR_MAP
ShSize: [[SIZE=<none>]] ShSize: [[SIZE=<none>]]
Entries: 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>]] NumBlocks: [[NUMBLOCKS=<none>]]
BBEntries: BBEntries:
- AddressOffset: 0x1 - AddressOffset: 0xA
Size: 0x2 Size: 0xB
Metadata: 0x3 Metadata: 0xC
- AddressOffset: 0x4
Size: 0x5
Metadata: 0x6
- AddressOffset: 0xFFFFFFFFFFFFFFF7
Size: 0xFFFFFFFFFFFFFFF8
Metadata: 0xFFFFFFFFFFFFFFF9
- Address: 0xFFFFFFFFFFFFFF20
BBEntries:
- AddressOffset: 0xA
Size: 0xB
Metadata: 0xC
## Check obj2yaml can dump empty .llvm_bb_addr_map sections. ## Check obj2yaml can dump empty .llvm_bb_addr_map sections.
@ -95,18 +103,20 @@ Sections:
# MULTI-NEXT: Data: ELFDATA2LSB # MULTI-NEXT: Data: ELFDATA2LSB
# MULTI-NEXT: Type: ET_EXEC # MULTI-NEXT: Type: ET_EXEC
# MULTI-NEXT: Sections: # MULTI-NEXT: Sections:
# MULTI-NEXT: - Name: .llvm_bb_addr_map # MULTI-NEXT: - Name: .llvm_bb_addr_map
# MULTI-NEXT: Type: SHT_LLVM_BB_ADDR_MAP # MULTI-NEXT: Type: SHT_LLVM_BB_ADDR_MAP
# MULTI-NEXT: Entries: # MULTI-NEXT: Entries:
## The 'Address' field is omitted when it's zero. ## Fields 'Address' and 'Feature' are omitted when they are zero.
# MULTI-NEXT: - BBEntries: # MULTI-NEXT: - Version: 0
# MULTI-NEXT: - AddressOffset: 0x1 # MULTI-NEXT: BBEntries:
# MULTI-NEXT: Size: 0x2 # MULTI-NEXT: - AddressOffset: 0x1
# MULTI-NEXT: Metadata: 0x3 # MULTI-NEXT: Size: 0x2
# MULTI-NEXT: - Name: '.llvm_bb_addr_map (1)' # MULTI-NEXT: Metadata: 0x3
# MULTI-NEXT: Type: SHT_LLVM_BB_ADDR_MAP # MULTI-NEXT: - Name: '.llvm_bb_addr_map (1)'
# MULTI-NEXT: Type: SHT_LLVM_BB_ADDR_MAP
# MULTI-NEXT: Entries: # MULTI-NEXT: Entries:
# MULTI-NEXT: - Address: 0x20 # MULTI-NEXT: - Version: 0
# MULTI-NEXT: Address: 0x20
# MULTI-NEXT: BBEntries: [] # MULTI-NEXT: BBEntries: []
--- !ELF --- !ELF
@ -115,19 +125,23 @@ FileHeader:
Data: ELFDATA2LSB Data: ELFDATA2LSB
Type: ET_EXEC Type: ET_EXEC
Sections: Sections:
- Name: .llvm_bb_addr_map - Name: .llvm_bb_addr_map
Type: SHT_LLVM_BB_ADDR_MAP Type: SHT_LLVM_BB_ADDR_MAP
Entries: Entries:
## Check that obj2yaml does not emit the Address field when it's zero. ## Check that obj2yaml does not emit the 'Address' and 'Feature' fields when
- Address: 0x0 ## they are zero.
- Version: 0
Feature: 0x0
Address: 0x0
BBEntries: BBEntries:
- AddressOffset: 0x1 - AddressOffset: 0x1
Size: 0x2 Size: 0x2
Metadata: 0x3 Metadata: 0x3
- Name: '.llvm_bb_addr_map (1)' - Name: '.llvm_bb_addr_map (1)'
Type: SHT_LLVM_BB_ADDR_MAP Type: SHT_LLVM_BB_ADDR_MAP
Entries: Entries:
- Address: 0x20 - Version: 0
Address: 0x20
## Check that obj2yaml uses the "Content" tag to describe an .llvm_bb_addr_map section ## 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 ## when it can't extract the entries, for example, when the section is truncated, or
@ -141,11 +155,47 @@ Sections:
# INVALID: --- !ELF # INVALID: --- !ELF
# INVALID-NEXT: FileHeader: # INVALID-NEXT: FileHeader:
# INVALID-NEXT: Class: ELFCLASS64 # INVALID-NEXT: Class: ELFCLASS64
# INVALID-NEXT: Data: ELFDATA2LSB # INVALID-NEXT: Data: ELFDATA2LSB
# INVALID-NEXT: Type: ET_EXEC # INVALID-NEXT: Type: ET_EXEC
# INVALID-NEXT: Sections: # INVALID-NEXT: Sections:
# INVALID-NEXT: - Name: .llvm_bb_addr_map # INVALID-NEXT: - Name: .llvm_bb_addr_map
# INVALID-NEXT: Type: SHT_LLVM_BB_ADDR_MAP # INVALID-NEXT: Type: SHT_LLVM_BB_ADDR_MAP
# BADNUMBLOCKS-NEXT: Content: {{([[:xdigit:]]+)}}{{$}} # 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: Section {
# CHECK: Index: 1 # CHECK: Index: 1
# CHECK-NEXT: Name: .llvm_bb_addr_map (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: Flags [ (0x0)
# CHECK-NEXT: ] # CHECK-NEXT: ]
# CHECK-NEXT: Address: 0x0 # CHECK-NEXT: Address: 0x0
@ -36,7 +36,7 @@
# Case 4: Specify Entries. # Case 4: Specify Entries.
# CHECK: Name: .llvm_bb_addr_map (1) # CHECK: Name: .llvm_bb_addr_map (1)
# CHECK: SectionData ( # CHECK: SectionData (
# CHECK-NEXT: 0000: 20000000 00000000 01010203 # CHECK-NEXT: 0000: 01002000 00000000 00000101 0203
# CHECK-NEXT: ) # CHECK-NEXT: )
# Case 5: Specify Entries and omit the Address field. # Case 5: Specify Entries and omit the Address field.
@ -44,13 +44,13 @@
# CHECK: Address: # CHECK: Address:
# CHECK-SAME: {{^ 0x0$}} # CHECK-SAME: {{^ 0x0$}}
# CHECK: SectionData ( # CHECK: SectionData (
# CHECK-NEXT: 0000: 00000000 00000000 01010203 # CHECK-NEXT: 0000: 00000000 00000000 00000101 0203
# CHECK-NEXT: ) # CHECK-NEXT: )
# Case 6: Override the NumBlocks field. # Case 6: Override the NumBlocks field.
# CHECK: Name: .llvm_bb_addr_map (1) # CHECK: Name: .llvm_bb_addr_map (1)
# CHECK: SectionData ( # CHECK: SectionData (
# CHECK-NEXT: 0000: 20000000 00000000 02010203 # CHECK-NEXT: 0000: 01002000 00000000 00000201 0203
# CHECK-NEXT: ) # CHECK-NEXT: )
--- !ELF --- !ELF
@ -71,47 +71,50 @@ Sections:
## 2) We can produce an empty .llvm_bb_addr_map section from a description ## 2) We can produce an empty .llvm_bb_addr_map section from a description
## with empty section content. ## with empty section content.
- Name: '.llvm_bb_addr_map (2)' - Name: '.llvm_bb_addr_map (2)'
Type: SHT_LLVM_BB_ADDR_MAP Type: SHT_LLVM_BB_ADDR_MAP
## 3) We can produce a zero .llvm_bb_addr_map section of a specific size when ## 3) We can produce a zero .llvm_bb_addr_map section of a specific size when
## we specify the size only. ## we specify the size only.
- Name: '.llvm_bb_addr_map (3)' - Name: '.llvm_bb_addr_map (3)'
Type: SHT_LLVM_BB_ADDR_MAP Type: SHT_LLVM_BB_ADDR_MAP
Size: 8 Size: 8
## 4) We can produce an .llvm_bb_addr_map section from a description with ## 4) We can produce an .llvm_bb_addr_map section from a description with
## Entries. ## Entries.
- Name: '.llvm_bb_addr_map (4)' - Name: '.llvm_bb_addr_map (4)'
Type: SHT_LLVM_BB_ADDR_MAP Type: SHT_LLVM_BB_ADDR_MAP
Entries: Entries:
- Address: 0x0000000000000020 - Version: 1
Address: 0x0000000000000020
BBEntries: BBEntries:
- AddressOffset: 0x00000001 - AddressOffset: 0x00000001
Size: 0x00000002 Size: 0x00000002
Metadata: 0x00000003 Metadata: 0x00000003
## 5) When specifying the description with Entries, the 'Address' field will be ## 5) When specifying the description with Entries, the 'Address' field will be
## zero when omitted. ## zero when omitted.
- Name: '.llvm_bb_addr_map (5)' - Name: '.llvm_bb_addr_map (5)'
Type: SHT_LLVM_BB_ADDR_MAP Type: SHT_LLVM_BB_ADDR_MAP
Entries: Entries:
- BBEntries: - Version: 0
- AddressOffset: 0x00000001 BBEntries:
Size: 0x00000002 - AddressOffset: 0x00000001
Metadata: 0x00000003 Size: 0x00000002
Metadata: 0x00000003
## 6) We can override the NumBlocks field with a value different from the ## 6) We can override the NumBlocks field with a value different from the
## actual number of BB Entries. ## actual number of BB Entries.
- Name: '.llvm_bb_addr_map (6)' - Name: '.llvm_bb_addr_map (6)'
Type: SHT_LLVM_BB_ADDR_MAP Type: SHT_LLVM_BB_ADDR_MAP
Entries: Entries:
- Address: 0x0000000000000020 - Version: 1
Address: 0x0000000000000020
NumBlocks: 2 NumBlocks: 2
BBEntries: BBEntries:
- AddressOffset: 0x00000001 - AddressOffset: 0x00000001
Size: 0x00000002 Size: 0x00000002
Metadata: 0x00000003 Metadata: 0x00000003
## Check we can't use Entries at the same time as either Content or Size. ## 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 -DCONTENT="00" %s 2>&1 | FileCheck %s --check-prefix=INVALID
@ -131,3 +134,19 @@ Sections:
Entries: [] Entries: []
Content: [[CONTENT=<none>]] Content: [[CONTENT=<none>]]
Size: [[SIZE=<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() { template <class ELFT> void LLVMELFDumper<ELFT>::printBBAddrMaps() {
bool IsRelocatable = this->Obj.getHeader().e_type == ELF::ET_REL; bool IsRelocatable = this->Obj.getHeader().e_type == ELF::ET_REL;
for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) { 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; continue;
}
Optional<const Elf_Shdr *> FunctionSec = None; Optional<const Elf_Shdr *> FunctionSec = None;
if (IsRelocatable) if (IsRelocatable)
FunctionSec = FunctionSec =

View File

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

View File

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