std::string CaptureFD::readIncremental() { std::string filename = file_.path().string(); // Yes, I know that I could just keep the file open instead. So sue me. folly::File f(openNoInt(filename.c_str(), O_RDONLY), true); auto size = size_t(lseek(f.fd(), 0, SEEK_END) - readOffset_); std::unique_ptr<char[]> buf(new char[size]); auto bytes_read = folly::preadFull(f.fd(), buf.get(), size, readOffset_); PCHECK(ssize_t(size) == bytes_read); readOffset_ += off_t(size); chunkCob_(StringPiece(buf.get(), buf.get() + size)); return std::string(buf.get(), size); }
Symbolizer::Symbolizer(ElfCacheBase* cache) : cache_(cache ?: defaultElfCache()) { } void Symbolizer::symbolize(const uintptr_t* addresses, SymbolizedFrame* frames, size_t addressCount) { size_t remaining = 0; for (size_t i = 0; i < addressCount; ++i) { auto& frame = frames[i]; if (!frame.found) { ++remaining; frame.clear(); } } if (remaining == 0) { // we're done return; } int fd = openNoInt("/proc/self/maps", O_RDONLY); if (fd == -1) { return; } char buf[PATH_MAX + 100]; // Long enough for any line LineReader reader(fd, buf, sizeof(buf)); while (remaining != 0) { StringPiece line; if (reader.readLine(line) != LineReader::kReading) { break; } // Parse line uintptr_t from; uintptr_t to; StringPiece fileName; if (!parseProcMapsLine(line, from, to, fileName)) { continue; } bool first = true; std::shared_ptr<ElfFile> elfFile; // See if any addresses are here for (size_t i = 0; i < addressCount; ++i) { auto& frame = frames[i]; if (frame.found) { continue; } uintptr_t address = addresses[i]; if (from > address || address >= to) { continue; } // Found frame.found = true; --remaining; // Open the file on first use if (first) { first = false; elfFile = cache_->getFile(fileName); } if (!elfFile) { continue; } // Undo relocation frame.set(elfFile, address - from); } } closeNoInt(fd); }
void Symbolizer::symbolize(const uintptr_t* addresses, SymbolizedFrame* frames, size_t addressCount) { size_t remaining = 0; for (size_t i = 0; i < addressCount; ++i) { auto& frame = frames[i]; if (!frame.found) { ++remaining; frame.name.clear(); frame.location = Dwarf::LocationInfo(); } } if (remaining == 0) { // we're done return; } int fd = openNoInt("/proc/self/maps", O_RDONLY); if (fd == -1) { return; } char buf[PATH_MAX + 100]; // Long enough for any line LineReader reader(fd, buf, sizeof(buf)); char fileNameBuf[PATH_MAX]; while (remaining != 0) { StringPiece line; if (reader.readLine(line) != LineReader::kReading) { break; } // Parse line uintptr_t from; uintptr_t to; StringPiece fileName; if (!parseProcMapsLine(line, from, to, fileName)) { continue; } bool first = true; ElfFile* elfFile = nullptr; // See if any addresses are here for (size_t i = 0; i < addressCount; ++i) { auto& frame = frames[i]; if (frame.found) { continue; } uintptr_t address = addresses[i]; if (from > address || address >= to) { continue; } // Found frame.found = true; --remaining; // Open the file on first use if (first) { first = false; if (fileCount_ < kMaxFiles && !fileName.empty() && fileName.size() < sizeof(fileNameBuf)) { memcpy(fileNameBuf, fileName.data(), fileName.size()); fileNameBuf[fileName.size()] = '\0'; auto& f = files_[fileCount_++]; if (f.openNoThrow(fileNameBuf) != -1) { elfFile = &f; } } } if (!elfFile) { continue; } // Undo relocation uintptr_t fileAddress = address - from + elfFile->getBaseAddress(); auto sym = elfFile->getDefinitionByAddress(fileAddress); if (!sym.first) { continue; } auto name = elfFile->getSymbolName(sym); if (name) { frame.name = name; } Dwarf(elfFile).findAddress(fileAddress, frame.location); } } closeNoInt(fd); }