forked from OSchip/llvm-project
[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:
parent
3f028c02ba
commit
0aa6df6575
|
@ -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
|
||||
------------------
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue