@@ -672,14 +672,15 @@ bool parseAddressRange(const char *Str, uint64_t &StartAddress,
672
672
return true ;
673
673
}
674
674
675
+ static constexpr uint32_t NameMax = 4096 ;
676
+ static char TargetPath[NameMax] = {};
677
+
675
678
// / Get full path to the real binary by getting current virtual address
676
679
// / and searching for the appropriate link in address range in
677
680
// / /proc/self/map_files
678
681
static char *getBinaryPath () {
679
682
const uint32_t BufSize = 1024 ;
680
- const uint32_t NameMax = 4096 ;
681
683
const char DirPath[] = " /proc/self/map_files/" ;
682
- static char TargetPath[NameMax] = {};
683
684
char Buf[BufSize];
684
685
685
686
if (__bolt_instr_binpath[0 ] != ' \0 ' )
@@ -719,22 +720,31 @@ static char *getBinaryPath() {
719
720
return nullptr ;
720
721
}
721
722
722
- ProfileWriterContext readDescriptions () {
723
+ ProfileWriterContext readDescriptions (const uint8_t *BinContents,
724
+ uint64_t Size) {
723
725
ProfileWriterContext Result;
724
- const char *BinPath = getBinaryPath ();
725
- assert (BinPath && BinPath[0 ] != ' \0 ' , " failed to find binary path" );
726
726
727
- uint64_t FD = __open (BinPath, O_RDONLY,
728
- /* mode=*/ 0666 );
729
- assert (static_cast <int64_t >(FD) >= 0 , " failed to open binary path" );
727
+ assert ((BinContents == nullptr ) == (Size == 0 ),
728
+ " either empty or valid library content buffer" );
729
+
730
+ if (BinContents) {
731
+ Result.FileDesc = -1 ;
732
+ } else {
733
+ const char *BinPath = getBinaryPath ();
734
+ assert (BinPath && BinPath[0 ] != ' \0 ' , " failed to find binary path" );
730
735
731
- Result.FileDesc = FD;
736
+ uint64_t FD = __open (BinPath, O_RDONLY,
737
+ /* mode=*/ 0666 );
738
+ assert (static_cast <int64_t >(FD) >= 0 , " failed to open binary path" );
732
739
733
- // mmap our binary to memory
734
- uint64_t Size = __lseek (FD, 0 , SEEK_END);
735
- const uint8_t *BinContents = reinterpret_cast <uint8_t *>(
736
- __mmap (0 , Size, PROT_READ, MAP_PRIVATE, FD, 0 ));
737
- assert (BinContents != MAP_FAILED, " readDescriptions: Failed to mmap self!" );
740
+ Result.FileDesc = FD;
741
+
742
+ // mmap our binary to memory
743
+ Size = __lseek (FD, 0 , SEEK_END);
744
+ BinContents = reinterpret_cast <uint8_t *>(
745
+ __mmap (0 , Size, PROT_READ, MAP_PRIVATE, FD, 0 ));
746
+ assert (BinContents != MAP_FAILED, " readDescriptions: Failed to mmap self!" );
747
+ }
738
748
Result.MMapPtr = BinContents;
739
749
Result.MMapSize = Size;
740
750
const Elf64_Ehdr *Hdr = reinterpret_cast <const Elf64_Ehdr *>(BinContents);
@@ -1509,7 +1519,7 @@ extern "C" void __bolt_instr_clear_counters() {
1509
1519
}
1510
1520
1511
1521
// / This is the entry point for profile writing.
1512
- // / There are three ways of getting here:
1522
+ // / There are four ways of getting here:
1513
1523
// /
1514
1524
// / * Program execution ended, finalization methods are running and BOLT
1515
1525
// / hooked into FINI from your binary dynamic section;
@@ -1518,9 +1528,18 @@ extern "C" void __bolt_instr_clear_counters() {
1518
1528
// / * BOLT prints this function address so you can attach a debugger and
1519
1529
// / call this function directly to get your profile written to disk
1520
1530
// / on demand.
1531
+ // / * Application can, at interesting runtime point, iterate through all
1532
+ // / the loaded native libraries and for each call dlopen() and dlsym()
1533
+ // / to get a pointer to this function and call through the acquired
1534
+ // / function pointer to dump profile data.
1521
1535
// /
1522
1536
extern " C" void __attribute ((force_align_arg_pointer))
1523
- __bolt_instr_data_dump(int FD) {
1537
+ __bolt_instr_data_dump(int FD, const char *LibPath = nullptr ,
1538
+ const uint8_t *LibContents = nullptr ,
1539
+ uint64_t LibSize = 0 ) {
1540
+ if (LibPath)
1541
+ strCopy (TargetPath, LibPath, NameMax);
1542
+
1524
1543
// Already dumping
1525
1544
if (!GlobalWriteProfileMutex->acquire ())
1526
1545
return ;
@@ -1531,7 +1550,7 @@ __bolt_instr_data_dump(int FD) {
1531
1550
assert (ret == 0 , " Failed to ftruncate!" );
1532
1551
BumpPtrAllocator HashAlloc;
1533
1552
HashAlloc.setMaxSize (0x6400000 );
1534
- ProfileWriterContext Ctx = readDescriptions ();
1553
+ ProfileWriterContext Ctx = readDescriptions (LibContents, LibSize );
1535
1554
Ctx.CallFlowTable = new (HashAlloc, 0 ) CallFlowHashTable (HashAlloc);
1536
1555
1537
1556
DEBUG (printStats (Ctx));
@@ -1551,8 +1570,10 @@ __bolt_instr_data_dump(int FD) {
1551
1570
Ctx.CallFlowTable ->forEachElement (visitCallFlowEntry, FD, &Ctx);
1552
1571
1553
1572
__fsync (FD);
1554
- __munmap ((void *)Ctx.MMapPtr , Ctx.MMapSize );
1555
- __close (Ctx.FileDesc );
1573
+ if (Ctx.FileDesc != -1 ) {
1574
+ __munmap ((void *)Ctx.MMapPtr , Ctx.MMapSize );
1575
+ __close (Ctx.FileDesc );
1576
+ }
1556
1577
HashAlloc.destroy ();
1557
1578
GlobalWriteProfileMutex->release ();
1558
1579
DEBUG (report (" Finished writing profile.\n " ));
0 commit comments