Parse statically defined tracepoint markers from .note.stapsdt section

Summary:
    Parse statically defined tracepoints(SDT) markers from the ELF file, and store them.
    Add an option to print SDTs (-print-sdt).
    Add test case for parsing and printing SDTs.

(cherry picked from FBD15366712)
This commit is contained in:
Laith Saed Sakka 2019-05-15 17:19:18 -07:00 committed by Maksim Panchenko
parent f1fde44154
commit 4755825447
4 changed files with 91 additions and 0 deletions

View File

@ -395,6 +395,9 @@ public:
/// List of functions that always trap.
std::vector<const BinaryFunction *> TrappedFunctions;
/// List of the SDT markers in the elf file
std::vector<SDTMarkerInfo> SDTMarkers;
BinaryContext(std::unique_ptr<MCContext> Ctx,
std::unique_ptr<DWARFContext> DwCtx,
std::unique_ptr<Triple> TheTriple,

View File

@ -441,4 +441,13 @@ inline raw_ostream &operator<<(raw_ostream &OS, const BinarySection &Section) {
} // namespace bolt
} // namespace llvm
struct SDTMarkerInfo {
uint64_t PC;
uint64_t Base;
uint64_t Semaphore;
llvm::StringRef Provider;
llvm::StringRef Name;
llvm::StringRef Args;
};
#endif

View File

@ -294,6 +294,13 @@ PrintLoopInfo("print-loops",
cl::Hidden,
cl::cat(BoltCategory));
static cl::opt<bool>
PrintSDTMarkers("print-sdt",
cl::desc("print all SDT markers"),
cl::ZeroOrMore,
cl::Hidden,
cl::cat(BoltCategory));
static cl::opt<cl::boolOrDefault>
RelocationMode("relocs",
cl::desc("use relocations in the binary (default=autodetect)"),
@ -874,6 +881,64 @@ void RewriteInstance::discoverStorage() {
BC->LayoutStartAddress = NextAvailableAddress;
}
void RewriteInstance::parseSDTNotes() {
if (!SDTSection)
return;
StringRef Buf = SDTSection->getContents();
auto DE = DataExtractor(Buf, BC->AsmInfo->isLittleEndian(),
BC->AsmInfo->getCodePointerSize());
uint32_t Offset = 0;
while (DE.isValidOffset(Offset)) {
auto NameSz = DE.getU32(&Offset);
DE.getU32(&Offset); // skip over DescSz
auto Type = DE.getU32(&Offset);
Offset = alignTo(Offset, 4);
if (Type != 3)
errs() << "BOLT-WARNING: SDT note type \"" << Type
<< "\" is not expected\n";
if (NameSz == 0)
errs() << "BOLT-WARNING: SDT note has empty name\n";
StringRef Name = DE.getCStr(&Offset);
if (!Name.equals("stapsdt"))
errs() << "BOLT-WARNING: SDT note name \"" << Name
<< "\" is not expected\n";
// Parse description
SDTMarkerInfo Marker;
Marker.PC = DE.getU64(&Offset);
Marker.Base = DE.getU64(&Offset);
Marker.Semaphore = DE.getU64(&Offset);
Marker.Provider = DE.getCStr(&Offset);
Marker.Name = DE.getCStr(&Offset);
Marker.Args = DE.getCStr(&Offset);
Offset = alignTo(Offset, 4);
BC->SDTMarkers.push_back(Marker);
}
if (opts::PrintSDTMarkers)
printSDTMarkers();
}
void RewriteInstance::printSDTMarkers() {
outs() << "BOLT-INFO: Number of SDT markers is " << BC->SDTMarkers.size()
<< "\n";
for (auto &Marker : BC->SDTMarkers) {
outs() << "BOLT-INFO: PC: " << utohexstr(Marker.PC)
<< ", Base: " << utohexstr(Marker.Base)
<< ", Semaphore: " << utohexstr(Marker.Semaphore)
<< ", Provider: " << Marker.Provider << ", Name: " << Marker.Name
<< ", Args: " << Marker.Args << "\n";
}
}
void RewriteInstance::parseBuildID() {
if (!BuildIDSection)
return;
@ -1753,6 +1818,7 @@ void RewriteInstance::readSpecialSections() {
PLTGOTSection = BC->getUniqueSectionByName(".plt.got");
RelaPLTSection = BC->getUniqueSectionByName(".rela.plt");
BuildIDSection = BC->getUniqueSectionByName(".note.gnu.build-id");
SDTSection = BC->getUniqueSectionByName(".note.stapsdt");
if (opts::PrintSections) {
outs() << "BOLT-INFO: Sections from original binary:\n";
@ -1781,6 +1847,7 @@ void RewriteInstance::readSpecialSections() {
// Parse build-id
parseBuildID();
if (DA.started()) {
if (auto FileBuildID = getPrintableBuildID()) {
outs() << "BOLT-INFO: binary build-id is: " << *FileBuildID << "\n";
@ -1790,6 +1857,8 @@ void RewriteInstance::readSpecialSections() {
"not read one from input binary\n";
}
}
parseSDTNotes();
}
void RewriteInstance::adjustCommandLineOptions() {

View File

@ -258,6 +258,12 @@ private:
/// Return true if the function \p BF should be disassembled.
bool shouldDisassemble(BinaryFunction &BF) const;
/// Parse .note.stapsdt section
void parseSDTNotes();
/// Print all SDT markers
void printSDTMarkers();
public:
/// Standard ELF sections we overwrite.
static constexpr const char *SectionsToOverwrite[] = {
@ -384,6 +390,10 @@ private:
/// .note.gnu.build-id section.
ErrorOr<BinarySection &> BuildIDSection{std::errc::bad_address};
/// .note.stapsdt section.
/// Contains information about statically defined tracing points
ErrorOr<BinarySection &> SDTSection{std::errc::bad_address};
/// A reference to the build-id bytes in the original binary
StringRef BuildID;