[llvm] c245c21 - [llvm-readelf] Support dumping the BB address map section with --bb-addr-map.
Rahman Lavaee via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 8 16:20:32 PST 2021
Author: Rahman Lavaee
Date: 2021-03-08T16:20:11-08:00
New Revision: c245c21c436b5d29da62a7c416f08f8631f5df95
URL: https://github.com/llvm/llvm-project/commit/c245c21c436b5d29da62a7c416f08f8631f5df95
DIFF: https://github.com/llvm/llvm-project/commit/c245c21c436b5d29da62a7c416f08f8631f5df95.diff
LOG: [llvm-readelf] Support dumping the BB address map section with --bb-addr-map.
This patch lets llvm-readelf dump the content of the BB address map
section in the following format:
```
Function {
At: <address>
BB entries [
{
Offset: <offset>
Size: <size>
Metadata: <metadata>
},
...
]
}
...
```
Reviewed By: jhenderson
Differential Revision: https://reviews.llvm.org/D95511
Added:
llvm/test/tools/llvm-readobj/ELF/bb-addr-map.test
Modified:
llvm/docs/CommandGuide/llvm-readelf.rst
llvm/docs/CommandGuide/llvm-readobj.rst
llvm/include/llvm/Object/ELF.h
llvm/include/llvm/Object/ELFTypes.h
llvm/include/llvm/ObjectYAML/ELFYAML.h
llvm/lib/Object/ELF.cpp
llvm/tools/llvm-readobj/ELFDumper.cpp
llvm/tools/llvm-readobj/ObjDumper.h
llvm/tools/llvm-readobj/llvm-readobj.cpp
llvm/unittests/Object/ELFObjectFileTest.cpp
Removed:
################################################################################
diff --git a/llvm/docs/CommandGuide/llvm-readelf.rst b/llvm/docs/CommandGuide/llvm-readelf.rst
index b566ad2ff5bc..cf4222f00c54 100644
--- a/llvm/docs/CommandGuide/llvm-readelf.rst
+++ b/llvm/docs/CommandGuide/llvm-readelf.rst
@@ -32,6 +32,11 @@ OPTIONS
Display architecture-specific information, e.g. the ARM attributes section on ARM.
+.. option:: --bb-addr-map
+
+ Display the contents of the basic block address map section(s), which contain the
+ address of each function, along with the relative offset of each basic block.
+
.. option:: --color
Use colors in the output for warnings and errors.
diff --git a/llvm/docs/CommandGuide/llvm-readobj.rst b/llvm/docs/CommandGuide/llvm-readobj.rst
index ba5511bb765a..201d1df803c0 100644
--- a/llvm/docs/CommandGuide/llvm-readobj.rst
+++ b/llvm/docs/CommandGuide/llvm-readobj.rst
@@ -148,6 +148,11 @@ The following options are implemented only for the ELF file format.
Display architecture-specific information, e.g. the ARM attributes section on ARM.
+.. option:: --bb-addr-map
+
+ Display the contents of the basic block address map section(s), which contain the
+ address of each function, along with the relative offset of each basic block.
+
.. option:: --demangle, -C
Display demangled symbol names in the output.
diff --git a/llvm/include/llvm/Object/ELF.h b/llvm/include/llvm/Object/ELF.h
index 03e64e1d34dc..c5f966891bd0 100644
--- a/llvm/include/llvm/Object/ELF.h
+++ b/llvm/include/llvm/Object/ELF.h
@@ -392,6 +392,8 @@ class ELFFile {
Expected<ArrayRef<T>> getSectionContentsAsArray(const Elf_Shdr &Sec) const;
Expected<ArrayRef<uint8_t>> getSectionContents(const Elf_Shdr &Sec) const;
Expected<ArrayRef<uint8_t>> getSegmentContents(const Elf_Phdr &Phdr) const;
+ Expected<std::vector<Elf_BBAddrMap>>
+ decodeBBAddrMap(const Elf_Shdr &Sec) const;
};
using ELF32LEFile = ELFFile<ELF32LE>;
diff --git a/llvm/include/llvm/Object/ELFTypes.h b/llvm/include/llvm/Object/ELFTypes.h
index f64e7c06e03b..32548f1435f7 100644
--- a/llvm/include/llvm/Object/ELFTypes.h
+++ b/llvm/include/llvm/Object/ELFTypes.h
@@ -43,6 +43,7 @@ template <class ELFT> struct Elf_Nhdr_Impl;
template <class ELFT> class Elf_Note_Impl;
template <class ELFT> class Elf_Note_Iterator_Impl;
template <class ELFT> struct Elf_CGProfile_Impl;
+template <class ELFT> struct Elf_BBAddrMap_Impl;
template <endianness E, bool Is64> struct ELFType {
private:
@@ -74,6 +75,7 @@ template <endianness E, bool Is64> struct ELFType {
using Note = Elf_Note_Impl<ELFType<E, Is64>>;
using NoteIterator = Elf_Note_Iterator_Impl<ELFType<E, Is64>>;
using CGProfile = Elf_CGProfile_Impl<ELFType<E, Is64>>;
+ using BBAddrMap = Elf_BBAddrMap_Impl<ELFType<E, Is64>>;
using DynRange = ArrayRef<Dyn>;
using ShdrRange = ArrayRef<Shdr>;
using SymRange = ArrayRef<Sym>;
@@ -128,13 +130,14 @@ using ELF64BE = ELFType<support::big, true>;
using Elf_Note = typename ELFT::Note; \
using Elf_Note_Iterator = typename ELFT::NoteIterator; \
using Elf_CGProfile = typename ELFT::CGProfile; \
+ using Elf_BBAddrMap = typename ELFT::BBAddrMap; \
using Elf_Dyn_Range = typename ELFT::DynRange; \
using Elf_Shdr_Range = typename ELFT::ShdrRange; \
using Elf_Sym_Range = typename ELFT::SymRange; \
using Elf_Rel_Range = typename ELFT::RelRange; \
using Elf_Rela_Range = typename ELFT::RelaRange; \
using Elf_Relr_Range = typename ELFT::RelrRange; \
- using Elf_Phdr_Range = typename ELFT::PhdrRange; \
+ using Elf_Phdr_Range = typename ELFT::PhdrRange;
#define LLVM_ELF_COMMA ,
#define LLVM_ELF_IMPORT_TYPES(E, W) \
@@ -788,6 +791,28 @@ template <class ELFT> struct Elf_Mips_ABIFlags {
Elf_Word flags2; // General flags
};
+// Struct representing the BBAddrMap for one function.
+template <class ELFT> struct Elf_BBAddrMap_Impl {
+ LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
+ uintX_t Addr; // Function address
+ // Struct representing the BBAddrMap information for one basic block.
+ struct BBEntry {
+ uint32_t Offset; // Offset of basic block relative to function start.
+ uint32_t Size; // Size of the basic block.
+
+ // The following fields are decoded from the Metadata field. The encoding
+ // happens in AsmPrinter.cpp:getBBAddrMapMetadata.
+ bool HasReturn; // If this block ends with a return (or tail call).
+ bool HasTailCall; // If this block ends with a tail call.
+ bool IsEHPad; // If this is an exception handling block.
+
+ BBEntry(uint32_t Offset, uint32_t Size, uint32_t Metadata)
+ : Offset(Offset), Size(Size), HasReturn(Metadata & 1),
+ HasTailCall(Metadata & (1 << 1)), IsEHPad(Metadata & (1 << 2)){};
+ };
+ std::vector<BBEntry> BBEntries; // Basic block entries for this function.
+};
+
} // end namespace object.
} // end namespace llvm.
diff --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h
index 29b3c1da03da..874aa32acdc0 100644
--- a/llvm/include/llvm/ObjectYAML/ELFYAML.h
+++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h
@@ -161,7 +161,7 @@ struct BBAddrMapEntry {
llvm::yaml::Hex64 Metadata;
};
llvm::yaml::Hex64 Address;
- Optional<uint32_t> NumBlocks;
+ Optional<uint64_t> NumBlocks;
Optional<std::vector<BBEntry>> BBEntries;
};
diff --git a/llvm/lib/Object/ELF.cpp b/llvm/lib/Object/ELF.cpp
index ffeec3112b7e..ca2ed4449120 100644
--- a/llvm/lib/Object/ELF.cpp
+++ b/llvm/lib/Object/ELF.cpp
@@ -612,6 +612,58 @@ ELFFile<ELFT>::toMappedAddr(uint64_t VAddr, WarningHandler WarnHandler) const {
return base() + Offset;
}
+template <class ELFT>
+Expected<std::vector<typename ELFT::BBAddrMap>>
+ELFFile<ELFT>::decodeBBAddrMap(const Elf_Shdr &Sec) const {
+ Expected<ArrayRef<uint8_t>> ContentsOrErr = getSectionContents(Sec);
+ if (!ContentsOrErr)
+ return ContentsOrErr.takeError();
+ ArrayRef<uint8_t> Content = *ContentsOrErr;
+ DataExtractor Data(Content, isLE(), ELFT::Is64Bits ? 8 : 4);
+ std::vector<Elf_BBAddrMap> FunctionEntries;
+
+ 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.
+ // Also returns zero if ULEBSizeErr is already in an error state.
+ auto ReadULEB128AsUInt32 = [&Data, &Cur, &ULEBSizeErr]() -> uint32_t {
+ // Bail out and do not extract data if ULEBSizeErr is already set.
+ if (ULEBSizeErr)
+ return 0;
+ uint64_t Offset = Cur.tell();
+ uint64_t Value = Data.getULEB128(Cur);
+ if (Value > UINT32_MAX) {
+ ULEBSizeErr = createError(
+ "ULEB128 value at offset 0x" + Twine::utohexstr(Offset) +
+ " exceeds UINT32_MAX (0x" + Twine::utohexstr(Value) + ")");
+ return 0;
+ }
+ return static_cast<uint32_t>(Value);
+ };
+
+ while (!ULEBSizeErr && Cur && Cur.tell() < Content.size()) {
+ uintX_t Address = static_cast<uintX_t>(Data.getAddress(Cur));
+ uint32_t NumBlocks = ReadULEB128AsUInt32();
+ std::vector<typename Elf_BBAddrMap::BBEntry> BBEntries;
+ for (uint32_t BlockID = 0; !ULEBSizeErr && Cur && (BlockID < NumBlocks);
+ ++BlockID) {
+ uint32_t Offset = ReadULEB128AsUInt32();
+ uint32_t Size = ReadULEB128AsUInt32();
+ uint32_t Metadata = ReadULEB128AsUInt32();
+ BBEntries.push_back({Offset, Size, Metadata});
+ }
+ FunctionEntries.push_back({Address, BBEntries});
+ }
+ // Either Cur is in the error state, or ULEBSizeError is set (not both), but
+ // we join the two errors here to be safe.
+ if (!Cur || ULEBSizeErr)
+ return joinErrors(Cur.takeError(), std::move(ULEBSizeErr));
+ return FunctionEntries;
+}
+
template class llvm::object::ELFFile<ELF32LE>;
template class llvm::object::ELFFile<ELF32BE>;
template class llvm::object::ELFFile<ELF64LE>;
diff --git a/llvm/test/tools/llvm-readobj/ELF/bb-addr-map.test b/llvm/test/tools/llvm-readobj/ELF/bb-addr-map.test
new file mode 100644
index 000000000000..f9b9dc0980e5
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/ELF/bb-addr-map.test
@@ -0,0 +1,119 @@
+## This test checks how we handle the --bb-addr-map option.
+
+## Check 64-bit:
+# RUN: yaml2obj %s -DBITS=64 -DADDR=0xFFFFFFFF1 -o %t1.x64.o
+# RUN: llvm-readobj %t1.x64.o --bb-addr-map | FileCheck %s -DADDR=0xFFFFFFFF1 --check-prefix=LLVM
+# RUN: llvm-readelf %t1.x64.o --bb-addr-map | FileCheck %s --check-prefix=GNU
+
+## Check 32-bit:
+# RUN: yaml2obj %s -DBITS=32 -o %t1.x32.o
+# RUN: llvm-readobj %t1.x32.o --bb-addr-map | FileCheck -DADDR=0x11111 %s --check-prefix=LLVM
+# 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
+
+# LLVM: BBAddrMap [
+# LLVM-NEXT: Function {
+# LLVM-NEXT: At: [[ADDR]]
+# 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: }
+# LLVM-NEXT: {
+# LLVM-NEXT: Offset: 0x3
+# LLVM-NEXT: Size: 0x4
+# LLVM-NEXT: HasReturn: Yes
+# LLVM-NEXT: HasTailCall: No
+# LLVM-NEXT: IsEHPad: Yes
+# LLVM-NEXT: }
+# LLVM-NEXT: ]
+# LLVM-NEXT: }
+# LLVM-NEXT: Function {
+# LLVM-NEXT: At: 0x22222
+# 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: }
+# LLVM-NEXT: ]
+# LLVM-NEXT: }
+# LLVM-NEXT: ]
+# LLVM-NEXT: BBAddrMap [
+# LLVM-NEXT: Function {
+# LLVM-NEXT: At: 0x33333
+# 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: }
+# LLVM-NEXT: ]
+# LLVM-NEXT: }
+# LLVM-NEXT: ]
+
+# GNU: GNUStyle::printBBAddrMaps not implemented
+
+# TRUNCATED: BBAddrMap [
+# TRUNCATED-NEXT: warning: '[[FILE]]': unable to dump SHT_LLVM_BB_ADDR_MAP section with index 1: unable to decode LEB128 at offset [[OFFSET]]: malformed uleb128, extends past end
+# TRUNCATED-NEXT: ]
+## Check that the other valid section is properly dumped.
+# TRUNCATED-NEXT: BBAddrMap [
+# TRUNCATED-NEXT: Function {
+# TRUNCATED-NEXT: At: 0x33333
+# TRUNCATED-NEXT: BB entries [
+# TRUNCATED-NEXT: {
+# TRUNCATED-NEXT: Offset: 0x9
+# TRUNCATED-NEXT: Size: 0xA
+# TRUNCATED-NEXT: HasReturn: Yes
+# TRUNCATED-NEXT: HasTailCall: Yes
+# TRUNCATED-NEXT: IsEHPad: No
+# TRUNCATED-NEXT: }
+# TRUNCATED-NEXT: ]
+# TRUNCATED-NEXT: }
+# TRUNCATED-NEXT: ]
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS[[BITS]]
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+Sections:
+ - Name: bb_addr_map_1
+ Type: SHT_LLVM_BB_ADDR_MAP
+ ShSize: [[SIZE=<none>]]
+ Entries:
+ - Address: [[ADDR=0x11111]]
+ BBEntries:
+ - AddressOffset: 0x0
+ Size: 0x1
+ Metadata: 0xF0000002
+ - AddressOffset: 0x3
+ Size: 0x4
+ Metadata: 0x5
+ - 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
+ Entries:
+ - Address: 0x33333
+ BBEntries:
+ - AddressOffset: 0x9
+ Size: 0xa
+ Metadata: 0xb
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index 03288e4a45c9..2535ae7830ae 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -550,6 +550,7 @@ template <typename ELFT> class GNUELFDumper : public ELFDumper<ELFT> {
void printVersionDependencySection(const Elf_Shdr *Sec) override;
void printHashHistograms() override;
void printCGProfile() override;
+ void printBBAddrMaps() override;
void printAddrsig() override;
void printNotes() override;
void printELFLinkerOptions() override;
@@ -660,6 +661,7 @@ template <typename ELFT> class LLVMELFDumper : public ELFDumper<ELFT> {
void printVersionDependencySection(const Elf_Shdr *Sec) override;
void printHashHistograms() override;
void printCGProfile() override;
+ void printBBAddrMaps() override;
void printAddrsig() override;
void printNotes() override;
void printELFLinkerOptions() override;
@@ -4617,6 +4619,10 @@ template <class ELFT> void GNUELFDumper<ELFT>::printCGProfile() {
OS << "GNUStyle::printCGProfile not implemented\n";
}
+template <class ELFT> void GNUELFDumper<ELFT>::printBBAddrMaps() {
+ OS << "GNUStyle::printBBAddrMaps not implemented\n";
+}
+
static Expected<std::vector<uint64_t>> toULEB128Array(ArrayRef<uint8_t> Data) {
std::vector<uint64_t> Ret;
const uint8_t *Cur = Data.begin();
@@ -6520,6 +6526,34 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printCGProfile() {
}
}
+template <class ELFT> void LLVMELFDumper<ELFT>::printBBAddrMaps() {
+ for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) {
+ if (Sec.sh_type != SHT_LLVM_BB_ADDR_MAP)
+ continue;
+ ListScope L(W, "BBAddrMap");
+ Expected<std::vector<Elf_BBAddrMap>> BBAddrMapOrErr =
+ this->Obj.decodeBBAddrMap(Sec);
+ if (!BBAddrMapOrErr) {
+ this->reportUniqueWarning("unable to dump " + this->describe(Sec) + ": " +
+ toString(BBAddrMapOrErr.takeError()));
+ continue;
+ }
+ for (const Elf_BBAddrMap &AM : *BBAddrMapOrErr) {
+ DictScope D(W, "Function");
+ W.printHex("At", AM.Addr);
+ ListScope L(W, "BB entries");
+ for (const typename Elf_BBAddrMap::BBEntry &BBE : AM.BBEntries) {
+ DictScope L(W);
+ W.printHex("Offset", BBE.Offset);
+ W.printHex("Size", BBE.Size);
+ W.printBoolean("HasReturn", BBE.HasReturn);
+ W.printBoolean("HasTailCall", BBE.HasTailCall);
+ W.printBoolean("IsEHPad", BBE.IsEHPad);
+ }
+ }
+ }
+}
+
template <class ELFT> void LLVMELFDumper<ELFT>::printAddrsig() {
ListScope L(W, "Addrsig");
if (!this->DotAddrsigSec)
diff --git a/llvm/tools/llvm-readobj/ObjDumper.h b/llvm/tools/llvm-readobj/ObjDumper.h
index d4e166b504cf..e707c36713d4 100644
--- a/llvm/tools/llvm-readobj/ObjDumper.h
+++ b/llvm/tools/llvm-readobj/ObjDumper.h
@@ -72,6 +72,7 @@ class ObjDumper {
virtual void printGroupSections() {}
virtual void printHashHistograms() {}
virtual void printCGProfile() {}
+ virtual void printBBAddrMaps() {}
virtual void printAddrsig() {}
virtual void printNotes() {}
virtual void printELFLinkerOptions() {}
diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp
index 841313ebe2b1..5d6ee25961f2 100644
--- a/llvm/tools/llvm-readobj/llvm-readobj.cpp
+++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp
@@ -367,6 +367,10 @@ namespace opts {
cl::alias ELFCGProfile("elf-cg-profile", cl::desc("Alias for --cg-profile"),
cl::aliasopt(CGProfile));
+ // --bb-addr-map
+ cl::opt<bool> BBAddrMap("bb-addr-map",
+ cl::desc("Display the BB address map section"));
+
// -addrsig
cl::opt<bool> Addrsig("addrsig",
cl::desc("Display address-significance table"));
@@ -542,6 +546,8 @@ static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer,
Dumper->printHashHistograms();
if (opts::CGProfile)
Dumper->printCGProfile();
+ if (opts::BBAddrMap)
+ Dumper->printBBAddrMaps();
if (opts::Addrsig)
Dumper->printAddrsig();
if (opts::Notes)
diff --git a/llvm/unittests/Object/ELFObjectFileTest.cpp b/llvm/unittests/Object/ELFObjectFileTest.cpp
index 8021b724afbc..bf59d4aa705b 100644
--- a/llvm/unittests/Object/ELFObjectFileTest.cpp
+++ b/llvm/unittests/Object/ELFObjectFileTest.cpp
@@ -482,3 +482,111 @@ TEST(ELFObjectFileTest, InvalidSymbolTest) {
DoCheck(0xFFFFFFFF, "can't read an entry at 0x17ffffffe8: it goes past the "
"end of the section (0x18)");
}
+
+// Tests for error paths of the ELFFile::decodeBBAddrMap API.
+TEST(ELFObjectFileTest, InvalidBBAddrMap) {
+ StringRef CommonYamlString(R"(
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+Sections:
+ - Name: .llvm_bb_addr_map
+ Type: SHT_LLVM_BB_ADDR_MAP
+ Entries:
+ - Address: 0x11111
+ BBEntries:
+ - AddressOffset: 0x0
+ Size: 0x1
+ Metadata: 0x2
+)");
+
+ auto DoCheck = [&](StringRef YamlString, const char *ErrMsg) {
+ SmallString<0> Storage;
+ Expected<ELFObjectFile<ELF64LE>> ElfOrErr =
+ toBinary<ELF64LE>(Storage, YamlString);
+ ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
+ const ELFFile<ELF64LE> &Elf = ElfOrErr->getELFFile();
+
+ Expected<const typename ELF64LE::Shdr *> BBAddrMapSecOrErr =
+ Elf.getSection(1);
+ ASSERT_THAT_EXPECTED(BBAddrMapSecOrErr, Succeeded());
+ EXPECT_THAT_ERROR(Elf.decodeBBAddrMap(**BBAddrMapSecOrErr).takeError(),
+ FailedWithMessage(ErrMsg));
+ };
+
+ // Check that we can detect the malformed encoding when the section is
+ // truncated.
+ SmallString<128> TruncatedYamlString(CommonYamlString);
+ TruncatedYamlString += R"(
+ ShSize: 0x8
+)";
+ DoCheck(TruncatedYamlString, "unable to decode LEB128 at offset 0x00000008: "
+ "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);
+ OverInt32LimitYamlStrings[0] += R"(
+ - AddressOffset: 0x100000000
+ Size: 0xFFFFFFFF
+ Metadata: 0xFFFFFFFF
+)";
+
+ OverInt32LimitYamlStrings[1] += R"(
+ - AddressOffset: 0xFFFFFFFF
+ Size: 0x100000000
+ Metadata: 0xFFFFFFFF
+)";
+
+ OverInt32LimitYamlStrings[2] += R"(
+ - AddressOffset: 0xFFFFFFFF
+ Size: 0xFFFFFFFF
+ Metadata: 0x100000000
+)";
+
+ DoCheck(OverInt32LimitYamlStrings[0],
+ "ULEB128 value at offset 0xc exceeds UINT32_MAX (0x100000000)");
+ DoCheck(OverInt32LimitYamlStrings[1],
+ "ULEB128 value at offset 0x11 exceeds UINT32_MAX (0x100000000)");
+ DoCheck(OverInt32LimitYamlStrings[2],
+ "ULEB128 value at offset 0x16 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
+ // unhandled errors.
+ SmallVector<SmallString<128>, 3> OverInt32LimitAndTruncated(
+ 3, OverInt32LimitYamlStrings[1]);
+ // Truncate before the end of the 5-byte field.
+ OverInt32LimitAndTruncated[0] += R"(
+ ShSize: 0x15
+)";
+ // Truncate at the end of the 5-byte field.
+ OverInt32LimitAndTruncated[1] += R"(
+ ShSize: 0x16
+)";
+ // Truncate after the end of the 5-byte field.
+ OverInt32LimitAndTruncated[2] += R"(
+ ShSize: 0x17
+)";
+
+ DoCheck(OverInt32LimitAndTruncated[0],
+ "unable to decode LEB128 at offset 0x00000011: malformed uleb128, "
+ "extends past end");
+ DoCheck(OverInt32LimitAndTruncated[1],
+ "ULEB128 value at offset 0x11 exceeds UINT32_MAX (0x100000000)");
+ DoCheck(OverInt32LimitAndTruncated[2],
+ "ULEB128 value at offset 0x11 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);
+ OverLimitNumBlocks += R"(
+ NumBlocks: 0x100000000
+)";
+
+ DoCheck(OverLimitNumBlocks,
+ "ULEB128 value at offset 0x8 exceeds UINT32_MAX (0x100000000)");
+}
More information about the llvm-commits
mailing list