Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F177480133
D61447.1794527375.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
13 KB
Referenced Files
None
Subscribers
None
D61447.1794527375.diff
View Options
diff --git a/usr.sbin/pmc/cmd_pmc_frontend.cc b/usr.sbin/pmc/cmd_pmc_frontend.cc
--- a/usr.sbin/pmc/cmd_pmc_frontend.cc
+++ b/usr.sbin/pmc/cmd_pmc_frontend.cc
@@ -140,7 +140,7 @@
}
virtual void
- print()
+ print(bool interactive)
{
title("IBS Frontend Analysis");
@@ -159,7 +159,7 @@
for (auto &kv : samples) {
std::vector<field> r;
- r.emplace_back(kv.second.func.binary);
+ r.emplace_back(basename(kv.second.func.binary));
r.emplace_back(kv.second.func.to_string());
r.emplace_back(kv.second.latency);
r.emplace_back(kv.second.samples);
@@ -173,7 +173,10 @@
}
t.sort(sortcol);
- t.print();
+ if (interactive)
+ t.display("Frontend Analysis");
+ else
+ t.print();
}
protected:
std::unordered_map<uint64_t, frontend> samples;
@@ -182,6 +185,7 @@
static struct option longopts[] = {
PMCFILTER_LOPTS,
+ { "format", required_argument, NULL, 'F' },
{ "sort", required_argument, NULL, 's' },
{ NULL, 0, NULL, 0 }
};
@@ -192,6 +196,7 @@
printf("Usage: pmc frontend [options] [pmclog]\n\n");
printf("Analyze frontend bottlenecks\n\n");
printf("Options:\n");
+ printf("\t-F,--format Output format (console, tui)\n");
printf("\t-s,--sort Sort by event\n\n");
PMCFILTER_PRINTOPTS();
}
@@ -202,10 +207,14 @@
pmcfilter filter = pmcfilter();
const char *logfile = "default.log";
int option, logfd;
+ std::string format;
- while ((option = getopt_long(argc, argv, PMCFILTER_SOPTS, longopts, NULL)) != -1) {
+ while ((option = getopt_long(argc, argv, "F:s:" PMCFILTER_SOPTS, longopts, NULL)) != -1) {
switch (option) {
PMCFILTER_CASE(filter)
+ case 'F':
+ format = optarg;
+ break;
case 's':
sortcol = atoi(optarg);
break;
@@ -224,7 +233,8 @@
if (argc == 1)
logfile = argv[0];
- setup_screen();
+ bool interactive = display_getmode(format, {"console", "tui"}) == "tui";
+ setup_screen(interactive);
if ((logfd = open(logfile, O_RDONLY)) < 0) {
errx(EX_OSERR, "ERROR: Cannot open \"%s\" for reading: %s.", logfile,
@@ -234,7 +244,7 @@
frontend_view v = frontend_view();
v.setfilter(filter);
v.process(logfd);
- v.print();
+ v.print(interactive);
close(logfd);
diff --git a/usr.sbin/pmc/view.hh b/usr.sbin/pmc/view.hh
--- a/usr.sbin/pmc/view.hh
+++ b/usr.sbin/pmc/view.hh
@@ -155,10 +155,11 @@
struct image
{
- image() : isdynamic(false), vaddr(0), start(0), end(0),
+ image() : loaded(false), isdynamic(false), vaddr(0), start(0), end(0),
offset(0), name(""), binary(""), path(""), loader(""),
dwarf(""), symbols(), dbg_fd(-1), dbg_elf(NULL) { }
~image() { }
+ bool loaded;
bool isdynamic;
uint64_t vaddr;
uint64_t start;
@@ -182,7 +183,7 @@
filterevent(false), filtercpu(false),
kernelonly(false), useronly(false),
pids(), tids(), programs(), threads(),
- ibs_ldlat(0), ibs_oplat(0) { CPU_ZERO(&cpus); }
+ ibs_ldlat(0), ibs_oplat(0), ibs_mmio(false) { CPU_ZERO(&cpus); }
~pmcfilter() { }
bool filterpid;
bool filtertid;
@@ -250,6 +251,8 @@
printf("\t-c,--cpus Filter by CPU id\n"); \
printf("\t-k,--kernel Show only kernel events\n"); \
printf("\t-u,--user Show only user events\n"); \
+ printf("\nGeneral Options:\n"); \
+ printf("\t-h,--help Display this help\n"); \
printf("\nIBS Fetch Options:\n"); \
printf("\t--ldlat Filter by load latency\n"); \
printf("\nIBS Op Options:\n"); \
@@ -262,15 +265,19 @@
{ "pids", required_argument, NULL, 'p' }, \
{ "threads", required_argument, NULL, 'T' }, \
{ "processes", required_argument, NULL, 'P' }, \
- { "events", required_argument, NULL, 'e' }, \
+ { "event", required_argument, NULL, 'e' }, \
{ "cpus", required_argument, NULL, 'c' }, \
{ "kernel", no_argument, NULL, 'k' }, \
{ "user", no_argument, NULL, 'u' }, \
{ "ldlat", required_argument, NULL, 10 }, \
{ "oplat", required_argument, NULL, 11 }, \
- { "mmio", no_argument, NULL, 12 }
-#define PMCFILTER_SOPTS "t:p:T:P:e:c:ku"
+ { "mmio", no_argument, NULL, 12 }, \
+ { "help", no_argument, NULL, 'h' }
+#define PMCFILTER_SOPTS "t:p:T:P:e:c:kuh"
#define PMCFILTER_CASE(_filt) \
+ case 'h': \
+ usage(); \
+ exit(EX_OK); \
case 't': \
_filt.addtids(optarg); \
break; \
@@ -354,10 +361,10 @@
}
virtual void callchain(__unused struct pmclog_ev_callchain &p) { }
// Console/File output
- virtual void print() { };
- virtual int process_sysinfo(int logfd, const pmchdr_infohdr &infohdr);
- virtual int process_pmcinfo(int logfd, const pmchdr_infohdr &infohdr);
- virtual int process_cpuidinfo(int logfd, const pmchdr_infohdr &infohdr);
+ virtual void print(__unused bool interactive) { };
+ virtual int process_sysinfo(const pmchdr_infohdr &infohdr);
+ virtual int process_pmcinfo(const pmchdr_infohdr &infohdr);
+ virtual int process_cpuidinfo(const pmchdr_infohdr &infohdr);
// Process log
virtual void process(int logfd);
virtual void process(struct pmclog_ev &p);
@@ -389,6 +396,7 @@
void printvm(pid_t pid);
// Fields available to views
uint64_t tscfreq;
+ uint8_t pageshift;
std::unordered_map<uint32_t, uint32_t> pmcid;
std::unordered_map<uint32_t, struct pmcinfo> pmcinfo;
std::unordered_map<pid_t, struct procinfo> procs;
@@ -396,6 +404,7 @@
std::unordered_map<std::string, image> images;
std::string sysroot;
pmcfilter filter;
+ int logfd;
// Extended info
int arch;
std::string cpumodel;
@@ -404,7 +413,7 @@
std::vector<struct pmcinfox> extpmcinfo;
std::map<uint32_t, struct cpuidleaf> cpuid; // x86 Only
private:
- image loadimage(const std::string &path);
+ image loadimage(const std::string &path, bool iskernel = false);
void mapimage(pid_t pid, const image &im, uint64_t linkaddr);
void loadsymboltable(image *im, Elf *e, Elf_Scn *scn, GElf_Shdr *sh);
void loadsymbols(image *im);
diff --git a/usr.sbin/pmc/view.cc b/usr.sbin/pmc/view.cc
--- a/usr.sbin/pmc/view.cc
+++ b/usr.sbin/pmc/view.cc
@@ -89,8 +89,8 @@
return ss.str();
}
-pmcview::pmcview() : tscfreq(0), pmcid(), pmcinfo(), procs(), tidtopid(),
- images(), sysroot(""), filter()
+pmcview::pmcview() : tscfreq(0), pageshift(0), pmcid(), pmcinfo(), procs(),
+ tidtopid(), images(), sysroot(""), filter()
{
char *root;
@@ -136,7 +136,7 @@
}
int
-pmcview::process_sysinfo(int logfd, const pmchdr_infohdr &infohdr)
+pmcview::process_sysinfo(const pmchdr_infohdr &infohdr)
{
int status;
pmchdr_sysinfo sysinfo;
@@ -156,7 +156,7 @@
}
int
-pmcview::process_pmcinfo(int logfd, const pmchdr_infohdr &infohdr)
+pmcview::process_pmcinfo(const pmchdr_infohdr &infohdr)
{
int status;
union {
@@ -164,6 +164,9 @@
__unused char reserve_max_size[256];
};
+ if (infohdr.length > 256)
+ errx(EX_IOERR, "PMC info headers are too large");
+
status = readlog(logfd, &pmcinfo, infohdr.length);
if (status < 0 || status != infohdr.length)
errx(EX_IOERR, "readlog");
@@ -174,7 +177,7 @@
}
int
-pmcview::process_cpuidinfo(int logfd, const pmchdr_infohdr &infohdr)
+pmcview::process_cpuidinfo(const pmchdr_infohdr &infohdr)
{
int status;
uint32_t *cpuidinfo;
@@ -199,6 +202,9 @@
root = maxleaf & 0xFFFF0000;
count = maxleaf & 0x0000FFFF;
+ if (4 * (int)(count + 1) + offset > len)
+ errx(EX_DATAERR, "PMC CPUID leaf count too large");
+
for (uint32_t i = 0; i <= count; i++) {
cpuid[root + i] = { cpuidinfo[4 * i + offset],
cpuidinfo[4 * i + 1 + offset],
@@ -215,12 +221,14 @@
}
void
-pmcview::process(int logfd)
+pmcview::process(int _logfd)
{
int status;
pmchdr_header hdr;
struct pmclog_parse_state *ps;
+ logfd = _logfd;
+
// Read header
status = readlog(logfd, &hdr, sizeof(hdr));
if (status < 0 || status != sizeof(hdr))
@@ -243,11 +251,11 @@
if (infohdr.type == INFOHDR_TYPE_DONE) {
break;
} else if (infohdr.type == INFOHDR_TYPE_SYSINFO) {
- process_sysinfo(logfd, infohdr);
+ process_sysinfo(infohdr);
} else if (infohdr.type == INFOHDR_TYPE_PMCINFO) {
- process_pmcinfo(logfd, infohdr);
+ process_pmcinfo(infohdr);
} else if (infohdr.type == INFOHDR_TYPE_CPUID) {
- process_cpuidinfo(logfd, infohdr);
+ process_cpuidinfo(infohdr);
}
}
@@ -308,7 +316,7 @@
case PMCLOG_TYPE_CALLCHAIN:
process(p.pl_u.pl_cc);
return;
- case PMCLOG_TYPE_PMCATTACH: [[fallthrough]];
+ case PMCLOG_TYPE_PMCATTACH:
case PMCLOG_TYPE_PMCDETACH:
case PMCLOG_TYPE_USERDATA:
case PMCLOG_TYPE_PROCCSW:
@@ -368,7 +376,7 @@
pmcview::process(struct pmclog_ev_procexit &p)
{
/*
- * XXX: Seems we can recieve samples after the process exits we need
+ * XXX: Seems we can receive samples after the process exits we need
* some way to delay cleanup, then after the delayed cleanup discard
* delayed events.
*/
@@ -436,13 +444,14 @@
* if the dwarf symbols are available.
*/
image
-pmcview::loadimage(const std::string &path)
+pmcview::loadimage(const std::string &path, bool iskernel)
{
std::string fullpath;
image im;
GElf_Ehdr eh;
Elf *e;
const char *elf;
+ size_t filesz;
uint64_t start;
uint64_t end;
size_t shstrndx;
@@ -486,11 +495,11 @@
if (eh.e_type != ET_EXEC && eh.e_type != ET_DYN && eh.e_type != ET_REL) {
warnx("WARNING: ELF file type is unsupported for \"%s\".",
- fullpath.c_str());;
+ fullpath.c_str());
goto done;
}
- elf = elf_rawfile(e, NULL);
+ elf = elf_rawfile(e, &filesz);
if (elf == NULL) {
warnx("WARNING: Cannot read the ELF file for \"%s\": %s.",
fullpath.c_str(), elf_errmsg(-1));
@@ -514,19 +523,39 @@
}
if (ph.p_type == PT_INTERP) {
- im.loader = elf + ph.p_offset;
+ int chklen;
+ const char *loader;
+
+ if (ph.p_offset > filesz) {
+ warnx("WARNING: Program header exceeds elf end for \"%s\".",
+ fullpath.c_str());
+ goto done;
+ }
+
+ chklen = ((filesz - ph.p_offset) < 256) ? (filesz - ph.p_offset) : 256;
+ loader = elf + ph.p_offset;
+ im.loader.assign(elf + ph.p_offset, strnlen(loader, chklen));
}
if (ph.p_type == PT_LOAD) {
if ((ph.p_flags & PF_X) != 0 && !foundexec) {
- im.vaddr = ph.p_vaddr & ~(ph.p_align - 1);
+ uint64_t alignment;
+
+ alignment = iskernel ? ph.p_align :
+ (pageshift != 0 ? 1ULL << pageshift :
+ (uint64_t)getpagesize());
+ im.vaddr = rounddown2(ph.p_vaddr, alignment);
foundexec = true;
}
}
}
}
- elf_getshdrstrndx(e, &shstrndx);
+ if (elf_getshdrstrndx(e, &shstrndx) != 0) {
+ warnx("WARNING: Could not retrieve section index for string table for \"%s\".",
+ fullpath.c_str());
+ goto done;
+ }
start = ~(0x0ULL);
end = 0;
@@ -566,7 +595,7 @@
im.name = basename(fullpath);
/*
- * If the dwarf symbols aren't embedded check:
+ * If the DWARF symbols aren't embedded check:
* 1. SYSROOT + /path + .debug
* 2. SYSROOT + /usr/lib/debug + /path + .debug
*/
@@ -622,22 +651,13 @@
if ((fname = elf_strptr(e, sh->sh_link, sym.st_name)) == NULL)
continue;
- // XXX: Extra checks to make sure we don't get corrupted
- for (int i = 0; fname[i] != 0 && i < 32; i++) {
- if (!isascii(fname[i])) {
- printf("EEEK SYMBOL\n");
- printf("%s\n", fname);
- assert(false);
- }
- }
-
si.offset = sym.st_value;
si.length = sym.st_size;
- si.binary = im->name;
+ si.binary = im->path;
si.name = fname;
im->symbols[si.offset] = si;
- }
+ }
}
void
@@ -727,8 +747,9 @@
{
// Kernel map-in events should be mapped to pid 0
pid_t pid = (p.pl_pid == -1) ? 0 : p.pl_pid;
+ pageshift = 12; //p.pl_pageshift;
- image im = loadimage(p.pl_pathname);
+ image im = loadimage(p.pl_pathname, pid == 0);
mapimage(pid, im, p.pl_start);
}
@@ -756,6 +777,7 @@
uintfptr_t *cc = &p.pl_pc[1];
ibsfetchinfo ibsf;
ibsopinfo ibso;
+ uint16_t cclen;
/*
* Callchain events are always attributed to one of the kernel
@@ -771,6 +793,9 @@
type = hdr[2 * i];
len = hdr[2 * i + 1];
+ if (cc + len - &p.pl_pc[0] > p.pl_npc)
+ errx(EX_DATAERR, "Multipart payload lenght exceeds callchain size");
+
switch (type) {
case PMC_CC_MULTIPART_IBS_FETCH:
ibsf.len = len;
@@ -795,6 +820,18 @@
cc += len;
}
+
+ /*
+ * Compute the length for the remaining entries which contain
+ * the stack.
+ */
+ cclen = p.pl_npc - (cc - &p.pl_pc[0]);
+ } else {
+ /*
+ * Default case for non-multipart payloads
+ */
+ cc = &p.pl_pc[0];
+ cclen = p.pl_npc;
}
/*
@@ -845,7 +882,7 @@
if (ibsf.len) {
if (filter.ibs_ldlat > IBS_FETCH_CTL_TO_LAT(ibsf.ctl))
return;
- callchain(p, ibsf, cc, len);
+ callchain(p, ibsf, cc, cclen);
} else if (ibso.len) {
if (filter.ibs_oplat > IBS_OP_DATA_TO_COMPTORET(ibso.data))
return;
@@ -859,9 +896,9 @@
((ibso.data3 & IBS_OP_DATA3_WCMEMACCESS) == 0))
return;
}
- callchain(p, ibso, cc, len);
+ callchain(p, ibso, cc, cclen);
} else {
- callchain(p, cc, len);
+ callchain(p, cc, cclen);
}
}
@@ -911,10 +948,14 @@
addr -= vm->lowpc - im->start;
// Load symbols if they haven't been loaded
- if (im->symbols.size() == 0) {
+ if (!im->loaded) {
+ im->loaded = true;
loadsymbols(im);
}
+ if (im->symbols.size() == 0)
+ return syminfo();
+
// Look for the first symbol
auto s = im->symbols.upper_bound(addr);
if (s != im->symbols.begin())
@@ -940,10 +981,9 @@
#endif
si = syminfo();
- si.binary = im->name;
- std::stringstream str = std::stringstream();
- str << "0x" << std::hex << addr;
- si.name = str.str();
+ si.binary = im->path;
+ si.offset = addr;
+ si.name = "";
return si;
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Nov 12, 11:49 PM (14 h, 22 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41686649
Default Alt Text
D61447.1794527375.diff (13 KB)
Attached To
Mode
D61447: pmc: Fix a few bugs and usability improvements to the pmc command
Attached
Detach File
Event Timeline