// Copyright 2006 The Android Open Source Project
#ifndef PARSE_OPTIONS_INL_H
#define PARSE_OPTIONS_INL_H
// Define a typedef for TraceReaderType and include "parse_options.h"
// before including this header file in a C++ source file.
//
// For example:
//
// struct symbol {
// int elapsed;
// };
//
// typedef TraceReader<symbol> TraceReaderType;
typedef TraceReaderType::symbol_type symbol_type;
typedef TraceReaderType::region_type region_type;
typedef TraceReaderType::ProcessState ProcessState;
symbol_type *kernel_sym;
symbol_type *library_sym;
// Returns true if the given event is included (or not excluded)
// from the list of valid events specified by the user on the
// command line.
inline bool IsValidEvent(BBEvent *event, symbol_type *sym)
{
if (include_some_pids && pid_include_vector.GetBit(event->pid) == 0)
return false;
if (exclude_some_pids && pid_exclude_vector.GetBit(event->pid))
return false;
if (include_some_procedures) {
if (sym == NULL || included_procedures.Find(sym->name) == 0)
return false;
}
if (exclude_some_procedures) {
if (sym == NULL || excluded_procedures.Find(sym->name))
return false;
}
return true;
}
inline bool IsValidPid(int pid) {
if (include_some_pids && pid_include_vector.GetBit(pid) == 0)
return false;
if (exclude_some_pids && pid_exclude_vector.GetBit(pid))
return false;
return true;
}
inline symbol_type *GetSymbol(TraceReaderType *trace, int pid, uint32_t addr,
uint64_t time)
{
symbol_type *sym = trace->LookupFunction(pid, addr, time);
if (lump_kernel && (sym->region->flags & region_type::kIsKernelRegion)) {
if (kernel_sym == NULL) {
kernel_sym = sym;
sym->name = ":kernel";
} else {
sym = kernel_sym;
}
}
if (lump_libraries && (sym->region->flags & region_type::kIsLibraryRegion)) {
if (library_sym == NULL) {
library_sym = sym;
sym->name = ":libs";
} else {
sym = library_sym;
}
}
return sym;
}
inline bool IsIncludedProcedure(symbol_type *sym)
{
if (include_kernel_syms && (sym->region->flags & region_type::kIsKernelRegion))
return true;
if (include_library_syms && (sym->region->flags & region_type::kIsLibraryRegion))
return true;
return included_procedures.Find(sym->name);
}
inline bool IsExcludedProcedure(symbol_type *sym)
{
if (exclude_kernel_syms && (sym->region->flags & region_type::kIsKernelRegion))
return true;
if (exclude_library_syms && (sym->region->flags & region_type::kIsLibraryRegion))
return true;
return excluded_procedures.Find(sym->name);
}
// Returns true on end-of-file.
inline bool GetNextValidEvent(TraceReaderType *trace,
BBEvent *event,
BBEvent *first_ignored_event,
symbol_type **sym_ptr)
{
symbol_type *sym = NULL;
first_ignored_event->time = 0;
if (trace->ReadBB(event))
return true;
bool recheck = true;
while (recheck) {
recheck = false;
if (include_some_pids) {
while (pid_include_vector.GetBit(event->pid) == 0) {
if (first_ignored_event->time == 0)
*first_ignored_event = *event;
if (trace->ReadBB(event))
return true;
}
} else if (exclude_some_pids) {
while (pid_exclude_vector.GetBit(event->pid)) {
if (first_ignored_event->time == 0)
*first_ignored_event = *event;
if (trace->ReadBB(event))
return true;
}
}
if (include_some_procedures) {
sym = GetSymbol(trace, event->pid, event->bb_addr, event->time);
while (!IsIncludedProcedure(sym)) {
if (first_ignored_event->time == 0)
*first_ignored_event = *event;
if (trace->ReadBB(event))
return true;
recheck = true;
sym = GetSymbol(trace, event->pid, event->bb_addr, event->time);
}
} else if (exclude_some_procedures) {
sym = GetSymbol(trace, event->pid, event->bb_addr, event->time);
while (IsExcludedProcedure(sym)) {
if (first_ignored_event->time == 0)
*first_ignored_event = *event;
if (trace->ReadBB(event))
return true;
recheck = true;
sym = GetSymbol(trace, event->pid, event->bb_addr, event->time);
}
}
}
if (sym == NULL)
sym = GetSymbol(trace, event->pid, event->bb_addr, event->time);
*sym_ptr = sym;
return false;
}
#endif // PARSE_OPTIONS_INL_H