void TraceData::parseReport(const std::string& filename) { release(); std::ifstream file; std::istream& in = filename.empty() ? std::cin : file; if (!filename.empty()) { file.open(filename.c_str(), std::ios_base::in); if (file.fail()) { throw std::ios_base::failure(Formatter() << "Failed to open file: " << filename); } } char buffer[4096]; in.getline(buffer, sizeof(buffer)); if (in.eof()) throw std::runtime_error(Formatter() << "Empty input file: " << filename); if (buffer[0] == (char)SP_RTRACE_PROTO_HS_ID) { throw std::runtime_error("Can't process sp-rtrace binary files. " "Convert to text format with sp-rtrace-postproc and try again."); } sp_rtrace_parser_parse_header(buffer, &header); while (true && (filename_maps.empty() || filename_pageflags.empty()) ) { in.getline(buffer, sizeof(buffer)); if (in.eof()) break; sp_rtrace_record_t rec; int rec_type = sp_rtrace_parser_parse_record(buffer, &rec); switch (rec_type) { case SP_RTRACE_RECORD_ATTACHMENT: if (!strcmp(rec.attachment.name, ATTACHMENT_MAPS)) filename_maps = rec.attachment.path; else if (!strcmp(rec.attachment.name, ATTACHMENT_PAGEFLAGS)) filename_pageflags = rec.attachment.path; break; } sp_rtrace_parser_free_record(rec_type, &rec); } if (access(filename_maps.c_str(), F_OK) == -1) throw std::runtime_error(Formatter() << "Failed to access maps file '" << filename_maps << "': " << strerror(errno)); if (access(filename_pageflags.c_str(), F_OK) == -1) throw std::runtime_error(Formatter() << "Failed to access pageflags file '" << filename_pageflags << "': " << strerror(errno)); // map the pageflags file to memory pageflags_fd = open(filename_pageflags.c_str(), O_RDONLY); if (pageflags_fd == -1) throw std::runtime_error(Formatter() << "Failed to open pageflags file '" << filename_pageflags << "': " << strerror(errno)); struct stat ps; if (fstat(pageflags_fd, &ps) == -1) throw std::runtime_error(Formatter() << "Failed to stat pageflags file '" << filename_pageflags << "': " << strerror(errno)); pageflags_size = ps.st_size; pageflags_addr = mmap(NULL, pageflags_size, PROT_READ, MAP_SHARED, pageflags_fd, 0); if (pageflags_addr == MAP_FAILED) throw std::runtime_error(Formatter() << "Failed to mmap pageflags file '" << filename_pageflags << "': " << strerror(errno)); // scan the mapped areas from maps/pageflags files scanMemoryAreas(); // scan the allocation events in.seekg(0); std::list<CallEvent*> last_events; sp_rtrace_btframe_t frames[512]; sp_rtrace_btframe_t* pframe = frames; while (true) { in.getline(buffer, sizeof(buffer)); if (in.eof()) break; sp_rtrace_record_t rec; int rec_type = sp_rtrace_parser_parse_record(buffer, &rec); if (rec_type == SP_RTRACE_RECORD_TRACE) { /* don't collect backtrace records if there is no preceeding allocation * function event */ if (last_events.empty()) { sp_rtrace_parser_free_record(rec_type, &rec); } else { *pframe++ = rec.frame; } continue; } // Store backtrace record for last cached events if ((pframe > frames || !*buffer) && !last_events.empty()) { storeTrace(last_events, frames, pframe - frames); last_events.clear(); } if (rec_type == SP_RTRACE_RECORD_CALL) { if (rec.call.type == SP_RTRACE_FTYPE_ALLOC) { MemoryArea* area = findMemoryArea(rec.call.res_id); if (area) { last_events.push_back(area->addEvent(rec.call)); continue; } } } pframe = frames; sp_rtrace_parser_free_record(rec_type, &rec); } if ((pframe > frames || !*buffer) && !last_events.empty()) { fprintf(stderr, "last parse\n"); storeTrace(last_events, frames, pframe - frames); last_events.clear(); } // sort the allocation events inside areas for (MemoryArea::vector_t::iterator iter = memory_areas.begin(); iter != memory_areas.end(); iter++) { iter->get()->sortEvents(); } }