/* * read kernel symbol from /proc/kallsyms */ int kallsyms_parse(void *arg, int(*process_symbol)(void *arg, const char *name, char type, unsigned long start)) { int ret = 0; FILE *file; char *line = NULL; file = fopen(KALLSYMS_PATH, "r"); if (file == NULL) handle_error("open " KALLSYMS_PATH " failed"); while (!feof(file)) { char *symbol_name; char symbol_type; int line_len, len; unsigned long start; size_t n; line_len = getline(&line, &n, file); if (line_len < 0 || !line) break; line[--line_len] = '\0'; /* \n */ len = hex2u64(line, &start); len++; if (len + 2 >= line_len) continue; symbol_type = line[len]; len += 2; symbol_name = line + len; len = line_len - len; if (len >= KSYM_NAME_LEN) { ret = -1; break; } ret = process_symbol(arg, symbol_name, symbol_type, start); if (ret) break; } free(line); fclose(file); return ret; }
static int perf_event__synthesize_mmap_events(union perf_event *event, pid_t pid, pid_t tgid, perf_event__handler_t process, struct perf_session *session) { char filename[PATH_MAX]; FILE *fp; snprintf(filename, sizeof(filename), "/proc/%d/maps", pid); fp = fopen(filename, "r"); if (fp == NULL) { /* * We raced with a task exiting - just return: */ pr_debug("couldn't open %s\n", filename); return -1; } event->header.type = PERF_RECORD_MMAP; /* * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c */ event->header.misc = PERF_RECORD_MISC_USER; while (1) { char bf[BUFSIZ], *pbf = bf; int n; size_t size; if (fgets(bf, sizeof(bf), fp) == NULL) break; /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */ n = hex2u64(pbf, &event->mmap.start); if (n < 0) continue; pbf += n + 1; n = hex2u64(pbf, &event->mmap.len); if (n < 0) continue; pbf += n + 3; if (*pbf == 'x') { /* vm_exec */ char *execname = strchr(bf, '/'); /* Catch VDSO */ if (execname == NULL) execname = strstr(bf, "[vdso]"); if (execname == NULL) continue; pbf += 3; n = hex2u64(pbf, &event->mmap.pgoff); size = strlen(execname); execname[size - 1] = '\0'; /* Remove \n */ memcpy(event->mmap.filename, execname, size); size = ALIGN(size, sizeof(u64)); event->mmap.len -= event->mmap.start; event->mmap.header.size = (sizeof(event->mmap) - (sizeof(event->mmap.filename) - size)); memset(event->mmap.filename + size, 0, session->id_hdr_size); event->mmap.header.size += session->id_hdr_size; event->mmap.pid = tgid; event->mmap.tid = pid; process(event, &synth_sample, session); } } fclose(fp); return 0; }
static int event__synthesize_mmap_events(pid_t pid, pid_t tgid, int (*process)(event_t *event)) { char filename[PATH_MAX]; FILE *fp; snprintf(filename, sizeof(filename), "/proc/%d/maps", pid); fp = fopen(filename, "r"); if (fp == NULL) { /* * We raced with a task exiting - just return: */ pr_debug("couldn't open %s\n", filename); return -1; } while (1) { char bf[BUFSIZ], *pbf = bf; event_t ev = { .header = { .type = PERF_RECORD_MMAP }, }; int n; size_t size; if (fgets(bf, sizeof(bf), fp) == NULL) break; /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */ n = hex2u64(pbf, &ev.mmap.start); if (n < 0) continue; pbf += n + 1; n = hex2u64(pbf, &ev.mmap.len); if (n < 0) continue; pbf += n + 3; if (*pbf == 'x') { /* vm_exec */ char *execname = strchr(bf, '/'); /* Catch VDSO */ if (execname == NULL) execname = strstr(bf, "[vdso]"); if (execname == NULL) continue; size = strlen(execname); execname[size - 1] = '\0'; /* Remove \n */ memcpy(ev.mmap.filename, execname, size); size = ALIGN(size, sizeof(u64)); ev.mmap.len -= ev.mmap.start; ev.mmap.header.size = (sizeof(ev.mmap) - (sizeof(ev.mmap.filename) - size)); ev.mmap.pid = tgid; ev.mmap.tid = pid; process(&ev); } } fclose(fp); return 0; }
HRESULT CaPerfDataWriter::writePidMmaps(pid_t pid, pid_t tgid, gtUInt16 sampleRecSize) { char filename[OS_MAX_PATH]; FILE* fp; if (! m_pMmapEvent) { m_pMmapEvent = (ca_event_t*)calloc(1, sizeof(m_pMmapEvent->mmap) + sampleRecSize); if (m_pMmapEvent == NULL) { return E_FAIL; } } snprintf(filename, sizeof(filename), "/proc/%d/maps", pid); fp = fopen(filename, "r"); if (fp == NULL) { /* * We raced with a task exiting - just return: */ OS_OUTPUT_FORMAT_DEBUG_LOG(OS_DEBUG_LOG_ERROR, L"couldn't open %hs", filename); return -1; } m_pMmapEvent->header.type = PERF_RECORD_MMAP; /* * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c */ m_pMmapEvent->header.misc = PERF_RECORD_MISC_USER; while (1) { char bf[BUFSIZ], *pbf = bf; int n; size_t size; if (fgets(bf, sizeof(bf), fp) == NULL) { break; } /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */ n = hex2u64(pbf, &m_pMmapEvent->mmap.start); if (n < 0) { continue; } pbf += n + 1; n = hex2u64(pbf, &m_pMmapEvent->mmap.len); if (n < 0) { continue; } pbf += n + 3; if (*pbf == 'x') /* vm_exec */ { char* execname = strchr(bf, '/'); /* Catch VDSO */ if (execname == NULL) { execname = strstr(bf, "[vdso]"); } if (execname == NULL) { continue; } pbf += 3; n = hex2u64(pbf, &m_pMmapEvent->mmap.pgoff); size = strlen(execname); execname[size - 1] = '\0'; /* Remove \n */ memcpy(m_pMmapEvent->mmap.filename, execname, size); size = ALIGN_FOR_SIZE_T(size, sizeof(gtUInt64)); m_pMmapEvent->mmap.len -= m_pMmapEvent->mmap.start; m_pMmapEvent->mmap.header.size = (sizeof(m_pMmapEvent->mmap) - (sizeof(m_pMmapEvent->mmap.filename) - size)); memset(m_pMmapEvent->mmap.filename + size, 0, sampleRecSize); m_pMmapEvent->mmap.header.size += sampleRecSize; m_pMmapEvent->mmap.pid = tgid; m_pMmapEvent->mmap.tid = pid; writePMUSampleData(m_pMmapEvent, m_pMmapEvent->header.size); } } fclose(fp); return 0; }
HRESULT CaPerfDataWriter::readKernelModules() { char* line = NULL; size_t n; FILE* file; const char* modules = NULL; char path[OS_MAX_PATH]; if (! m_guestOs) { // sprintf(path, "%s/proc/modules", self->root_dir); sprintf(path, "/proc/modules"); modules = path; } else { #if 0 // TODO: // modules = symbol_conf.default_guest_modules; #else return E_FAIL; #endif } file = fopen(modules, "r"); if (file == NULL) { return E_FAIL; } while (!feof(file)) { // char name[OS_MAX_PATH]; // gtUInt64 start; char* sep; int line_len; struct kModule module; line_len = getline(&line, &n, file); if (line_len < 0) { break; } if (!line) { return E_FAIL; } line[--line_len] = '\0'; /* \n */ sep = strrchr(line, 'x'); if (sep == NULL) { continue; } hex2u64(sep + 1, &module.m_startAddress); sep = strchr(line, ' '); if (sep == NULL) { continue; } *sep = '\0'; snprintf(module.m_modName, sizeof(module.m_modName), "[%s]", line); m_kModuleNameMap.insert(kModuleNameMap::value_type(module.m_modName, module)); // TODO: build id stuff ?? // dso__kernel_module_get_build_id(map->dso, self->root_dir); } free(line); fclose(file); // set the modules path setModulesPath(); return S_OK; }
HRESULT CaPerfDataWriter::findKernelSymbol(const char* symbol, gtUByte type, gtUInt64* startAddress) { (void)(symbol); // unused const char* filename = m_kernelSymbolFile.c_str(); FILE* file; char* line = NULL; size_t n; if (!filename || !startAddress) { return E_INVALIDARG; } if ((file = fopen(filename, "r")) == NULL) { return E_FAIL; } HRESULT ret = S_OK; // read the kernel symbol file /proc/kallsyms while (!feof(file)) { gtUInt64 start; int lineLen, len; char symbolType; lineLen = getline(&line, &n, file); if (lineLen < 0 || !line) { break; } line[--lineLen] = '\0'; /* \n */ len = hex2u64(line, &start); len++; if (len + 2 >= lineLen) { continue; } symbolType = toupper(line[len]); len += 2; len = lineLen - len; if (len >= CA_KERNEL_SYMBOL_LEN) { ret = E_FAIL; break; } // check for the symbol type if (KERNEL_FUNCTION == type) { if (symbolType == 'T' || symbolType == 'W') { *startAddress = start; break; } } else if (KERNEL_VARIABLE == type) { if (symbolType == 'D' || symbolType == 'd') { *startAddress = start; break; } } else { ret = E_FAIL; break; } } free(line); fclose(file); return ret; }
static void pid_synthesize_mmap_samples(pid_t pid, pid_t tgid) { char filename[PATH_MAX]; FILE *fp; snprintf(filename, sizeof(filename), "/proc/%d/maps", pid); fp = fopen(filename, "r"); if (fp == NULL) { /* * We raced with a task exiting - just return: */ if (verbose) fprintf(stderr, "couldn't open %s\n", filename); return; } while (1) { char bf[BUFSIZ], *pbf = bf; struct mmap_event mmap_ev = { .header = { .type = PERF_RECORD_MMAP }, }; int n; size_t size; if (fgets(bf, sizeof(bf), fp) == NULL) break; /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */ n = hex2u64(pbf, &mmap_ev.start); if (n < 0) continue; pbf += n + 1; n = hex2u64(pbf, &mmap_ev.len); if (n < 0) continue; pbf += n + 3; if (*pbf == 'x') { /* vm_exec */ char *execname = strchr(bf, '/'); /* Catch VDSO */ if (execname == NULL) execname = strstr(bf, "[vdso]"); if (execname == NULL) continue; size = strlen(execname); execname[size - 1] = '\0'; /* Remove \n */ memcpy(mmap_ev.filename, execname, size); size = ALIGN(size, sizeof(u64)); mmap_ev.len -= mmap_ev.start; mmap_ev.header.size = (sizeof(mmap_ev) - (sizeof(mmap_ev.filename) - size)); mmap_ev.pid = tgid; mmap_ev.tid = pid; write_output(&mmap_ev, mmap_ev.header.size); } } fclose(fp); }
static int event__synthesize_mmap_events(pid_t pid, pid_t tgid, event__handler_t process, struct perf_session *session) { char filename[PATH_MAX]; FILE *fp; snprintf(filename, sizeof(filename), "/proc/%d/maps", pid); fp = fopen(filename, "r"); if (fp == NULL) { /* * We raced with a task exiting - just return: */ pr_debug("couldn't open %s\n", filename); return -1; } while (1) { char bf[BUFSIZ], *pbf = bf; event_t ev = { .header = { .type = PERF_RECORD_MMAP, /* * Just like the kernel, see __perf_event_mmap * in kernel/perf_event.c */ .misc = PERF_RECORD_MISC_USER, }, }; int n; size_t size; if (fgets(bf, sizeof(bf), fp) == NULL) break; /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */ n = hex2u64(pbf, &ev.mmap.start); if (n < 0) continue; pbf += n + 1; n = hex2u64(pbf, &ev.mmap.len); if (n < 0) continue; pbf += n + 3; if (*pbf == 'x') { /* vm_exec */ u64 vm_pgoff; char *execname = strchr(bf, '/'); /* Catch VDSO */ if (execname == NULL) execname = strstr(bf, "[vdso]"); if (execname == NULL) continue; pbf += 3; n = hex2u64(pbf, &vm_pgoff); /* pgoff is in bytes, not pages */ if (n >= 0) ev.mmap.pgoff = vm_pgoff << getpagesize(); else ev.mmap.pgoff = 0; size = strlen(execname); execname[size - 1] = '\0'; /* Remove \n */ memcpy(ev.mmap.filename, execname, size); size = ALIGN(size, sizeof(u64)); ev.mmap.len -= ev.mmap.start; ev.mmap.header.size = (sizeof(ev.mmap) - (sizeof(ev.mmap.filename) - size)); ev.mmap.pid = tgid; ev.mmap.tid = pid; process(&ev, session); } } fclose(fp); return 0; }
static int dso__load_perf_map(struct dso *self, symbol_filter_t filter, int verbose) { char *line = NULL; size_t n; FILE *file; int nr_syms = 0; file = fopen(self->name, "r"); if (file == NULL) goto out_failure; while (!feof(file)) { u64 start, size; struct symbol *sym; int line_len, len; line_len = getline(&line, &n, file); if (line_len < 0) break; if (!line) goto out_failure; line[--line_len] = '\0'; /* \n */ len = hex2u64(line, &start); len++; if (len + 2 >= line_len) continue; len += hex2u64(line + len, &size); len++; if (len + 2 >= line_len) continue; sym = symbol__new(start, size, line + len, self->sym_priv_size, start, verbose); if (sym == NULL) goto out_delete_line; if (filter && filter(self, sym)) symbol__delete(sym, self->sym_priv_size); else { dso__insert_symbol(self, sym); nr_syms++; } } free(line); fclose(file); return nr_syms; out_delete_line: free(line); out_failure: return -1; }
static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verbose) { struct rb_node *nd, *prevnd; char *line = NULL; size_t n; FILE *file = fopen("/proc/kallsyms", "r"); int count = 0; if (file == NULL) goto out_failure; while (!feof(file)) { u64 start; struct symbol *sym; int line_len, len; char symbol_type; line_len = getline(&line, &n, file); if (line_len < 0) break; if (!line) goto out_failure; line[--line_len] = '\0'; /* \n */ len = hex2u64(line, &start); len++; if (len + 2 >= line_len) continue; symbol_type = toupper(line[len]); /* * We're interested only in code ('T'ext) */ if (symbol_type != 'T' && symbol_type != 'W') continue; /* * Well fix up the end later, when we have all sorted. */ sym = symbol__new(start, 0xdead, line + len + 2, self->sym_priv_size, 0, verbose); if (sym == NULL) goto out_delete_line; if (filter && filter(self, sym)) symbol__delete(sym, self->sym_priv_size); else { dso__insert_symbol(self, sym); count++; } } /* * Now that we have all sorted out, just set the ->end of all * symbols */ prevnd = rb_first(&self->syms); if (prevnd == NULL) goto out_delete_line; for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) { struct symbol *prev = rb_entry(prevnd, struct symbol, rb_node), *curr = rb_entry(nd, struct symbol, rb_node); prev->end = curr->start - 1; prevnd = nd; } free(line); fclose(file); return count; out_delete_line: free(line); out_failure: return -1; }