Skip to content

Commit 6b96000

Browse files
author
Pavel Kosov
committed
Respect pgoff and rely on it for all types of binaries
This fixes incorrect attribution of events to symbols for ET_DYN objects (shared libraries and PIEs), and also simplifies the code. Generally, the program linker assigns virtual addresses to segments, and virtual addresses of symbols stored in ELF are also in terms of that. Upon mmapping a segment, its first byte conicides with the start of the memory mapping. So to get the value of the program counter in terms of the DSO's virtual addresses, one has to add the virtual address of the segment to the raw PC's offset from the start of the mapping. Like it is done in perf (see linux/tools/perf/util/map.h): ``` static inline u64 map__map_ip(struct map *map, u64 ip) { return ip - map->start + map->pgoff; } ``` (The addresses are translated in thread__find_map() via invoking the map_ip callback that has a comment saying /* ip -> dso rip */.) OS Laboratory. Huawei Russian Research Institute. Saint-Petersburg Reviewed By: thopre Differential Revision: https://reviews.llvm.org/D113648
1 parent 0a7b38c commit 6b96000

File tree

1 file changed

+20
-10
lines changed

1 file changed

+20
-10
lines changed

lnt/testing/profile/cPerf.cpp

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ void Assert(bool Expr, const char *ExprStr, const char *File, int Line) {
132132

133133
// Returns true if the ELF file given by filename
134134
// is a shared object (DYN).
135-
bool IsSharedObject(std::string Fname) {
135+
bool IsSharedObject(char *Fname) {
136136
// We replicate the first part of an ELF header here
137137
// so as not to rely on <elf.h>.
138138
struct PartialElfHeader {
@@ -141,7 +141,7 @@ bool IsSharedObject(std::string Fname) {
141141
};
142142
const int ET_DYN = 3;
143143

144-
FILE *stream = fopen(Fname.c_str(), "r");
144+
FILE *stream = fopen(Fname, "r");
145145
if (stream == NULL)
146146
return false;
147147

@@ -213,6 +213,8 @@ struct perf_event_mmap {
213213
char filename[1];
214214
};
215215

216+
#define PROT_EXEC 4
217+
216218
struct perf_event_mmap2 {
217219
struct perf_event_header header;
218220

@@ -240,7 +242,7 @@ struct perf_sample_id {
240242
//===----------------------------------------------------------------------===//
241243

242244
struct Map {
243-
uint64_t Start, End;
245+
uint64_t Start, End, Adjust;
244246
const char *Filename;
245247
};
246248

@@ -544,7 +546,12 @@ unsigned char *PerfReader::readEvent(unsigned char *Buf) {
544546
if (E->header.type == PERF_RECORD_MMAP) {
545547
perf_event_mmap *E = (perf_event_mmap *)Buf;
546548
auto MapID = Maps.size();
547-
Maps.push_back({E->start, E->start + E->extent, E->filename});
549+
// EXEC ELF objects aren't relocated. DYN ones are,
550+
// so if it's a DYN object adjust by subtracting the
551+
// map base.
552+
bool IsSO = IsSharedObject(E->filename);
553+
Maps.push_back({E->start, E->start + E->extent,
554+
IsSO ? E->start - E->pgoff : 0, E->filename});
548555

549556
// FIXME: use EventLayouts.begin()->second!
550557
perf_sample_id *ID =
@@ -554,8 +561,15 @@ unsigned char *PerfReader::readEvent(unsigned char *Buf) {
554561
}
555562
if (E->header.type == PERF_RECORD_MMAP2) {
556563
perf_event_mmap2 *E = (perf_event_mmap2 *)Buf;
564+
if (!(E->prot & PROT_EXEC))
565+
break;
557566
auto MapID = Maps.size();
558-
Maps.push_back({E->start, E->start + E->extent, E->filename});
567+
// EXEC ELF objects aren't relocated. DYN ones are,
568+
// so if it's a DYN object adjust by subtracting the
569+
// map base.
570+
bool IsSO = IsSharedObject(E->filename);
571+
Maps.push_back({E->start, E->start + E->extent,
572+
IsSO ? E->start - E->pgoff : 0, E->filename});
559573

560574
// FIXME: use EventLayouts.begin()->second!
561575
perf_sample_id *ID =
@@ -705,11 +719,7 @@ void PerfReader::emitMaps() {
705719
if (AllUnderThreshold)
706720
continue;
707721

708-
// EXEC ELF objects aren't relocated. DYN ones are,
709-
// so if it's a DYN object adjust by subtracting the
710-
// map base.
711-
bool IsSO = IsSharedObject(Maps[MapID].Filename);
712-
uint64_t Adjust = IsSO ? Maps[MapID].Start : 0;
722+
uint64_t Adjust = Maps[MapID].Adjust;
713723

714724
NmOutput Syms(Nm, BinaryCacheRoot);
715725
Syms.reset(&Maps[MapID]);

0 commit comments

Comments
 (0)