@@ -672,14 +672,15 @@ bool parseAddressRange(const char *Str, uint64_t &StartAddress,
672672 return true ;
673673}
674674
675+ static constexpr uint32_t NameMax = 4096 ;
676+ static char TargetPath[NameMax] = {};
677+
675678// / Get full path to the real binary by getting current virtual address
676679// / and searching for the appropriate link in address range in
677680// / /proc/self/map_files
678681static char *getBinaryPath () {
679682 const uint32_t BufSize = 1024 ;
680- const uint32_t NameMax = 4096 ;
681683 const char DirPath[] = " /proc/self/map_files/" ;
682- static char TargetPath[NameMax] = {};
683684 char Buf[BufSize];
684685
685686 if (__bolt_instr_binpath[0 ] != ' \0 ' )
@@ -719,22 +720,31 @@ static char *getBinaryPath() {
719720 return nullptr ;
720721}
721722
722- ProfileWriterContext readDescriptions () {
723+ ProfileWriterContext readDescriptions (const uint8_t *BinContents,
724+ uint64_t Size) {
723725 ProfileWriterContext Result;
724- const char *BinPath = getBinaryPath ();
725- assert (BinPath && BinPath[0 ] != ' \0 ' , " failed to find binary path" );
726726
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" );
730735
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" );
732739
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+ }
738748 Result.MMapPtr = BinContents;
739749 Result.MMapSize = Size;
740750 const Elf64_Ehdr *Hdr = reinterpret_cast <const Elf64_Ehdr *>(BinContents);
@@ -1509,7 +1519,7 @@ extern "C" void __bolt_instr_clear_counters() {
15091519}
15101520
15111521// / This is the entry point for profile writing.
1512- // / There are three ways of getting here:
1522+ // / There are four ways of getting here:
15131523// /
15141524// / * Program execution ended, finalization methods are running and BOLT
15151525// / hooked into FINI from your binary dynamic section;
@@ -1518,9 +1528,18 @@ extern "C" void __bolt_instr_clear_counters() {
15181528// / * BOLT prints this function address so you can attach a debugger and
15191529// / call this function directly to get your profile written to disk
15201530// / 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.
15211535// /
15221536extern " 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+
15241543 // Already dumping
15251544 if (!GlobalWriteProfileMutex->acquire ())
15261545 return ;
@@ -1531,7 +1550,7 @@ __bolt_instr_data_dump(int FD) {
15311550 assert (ret == 0 , " Failed to ftruncate!" );
15321551 BumpPtrAllocator HashAlloc;
15331552 HashAlloc.setMaxSize (0x6400000 );
1534- ProfileWriterContext Ctx = readDescriptions ();
1553+ ProfileWriterContext Ctx = readDescriptions (LibContents, LibSize );
15351554 Ctx.CallFlowTable = new (HashAlloc, 0 ) CallFlowHashTable (HashAlloc);
15361555
15371556 DEBUG (printStats (Ctx));
@@ -1551,8 +1570,10 @@ __bolt_instr_data_dump(int FD) {
15511570 Ctx.CallFlowTable ->forEachElement (visitCallFlowEntry, FD, &Ctx);
15521571
15531572 __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+ }
15561577 HashAlloc.destroy ();
15571578 GlobalWriteProfileMutex->release ();
15581579 DEBUG (report (" Finished writing profile.\n " ));
0 commit comments