@@ -1926,10 +1926,27 @@ BinaryContext::getBaseAddressForMapping(uint64_t MMapAddress,
19261926 // Find a segment with a matching file offset.
19271927 for (auto &KV : SegmentMapInfo) {
19281928 const SegmentInfo &SegInfo = KV.second ;
1929- if (alignDown (SegInfo.FileOffset , SegInfo.Alignment ) == FileOffset) {
1930- // Use segment's aligned memory offset to calculate the base address.
1931- const uint64_t MemOffset = alignDown (SegInfo.Address , SegInfo.Alignment );
1932- return MMapAddress - MemOffset;
1929+ // FileOffset is got from perf event,
1930+ // and it is equal to alignDown(SegInfo.FileOffset, pagesize).
1931+ // If the pagesize is not equal to SegInfo.Alignment.
1932+ // FileOffset and SegInfo.FileOffset should be aligned first,
1933+ // and then judge whether they are equal.
1934+ if (alignDown (SegInfo.FileOffset , SegInfo.Alignment ) ==
1935+ alignDown (FileOffset, SegInfo.Alignment )) {
1936+ // The function's offset from base address in VAS is aligned by pagesize
1937+ // instead of SegInfo.Alignment. Pagesize can't be got from perf events.
1938+ // However, The ELF document says that SegInfo.FileOffset should equal
1939+ // to SegInfo.Address, modulo the pagesize.
1940+ // Reference: https://refspecs.linuxfoundation.org/elf/elf.pdf
1941+
1942+ // So alignDown(SegInfo.Address, pagesize) can be calculated by:
1943+ // alignDown(SegInfo.Address, pagesize)
1944+ // = SegInfo.Address - (SegInfo.Address % pagesize)
1945+ // = SegInfo.Address - (SegInfo.FileOffset % pagesize)
1946+ // = SegInfo.Address - SegInfo.FileOffset +
1947+ // alignDown(SegInfo.FileOffset, pagesize)
1948+ // = SegInfo.Address - SegInfo.FileOffset + FileOffset
1949+ return MMapAddress - (SegInfo.Address - SegInfo.FileOffset + FileOffset);
19331950 }
19341951 }
19351952
0 commit comments