Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 7 additions & 25 deletions libcoz/inspect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "util.h"

#include "ccutil/log.h"
#include "path_filter.h"

using namespace std;

Expand Down Expand Up @@ -357,42 +358,23 @@ bool in_scope(const string& name, const unordered_set<string>& scope) {
return in_scope_normalized(normalized, scope);
}

static bool path_has_prefix(const string& path, const string& prefix) {
if(prefix.empty())
return false;
if(prefix.size() > path.size())
return false;
if(path.compare(0, prefix.size(), prefix) != 0)
return false;
return path.size() == prefix.size() || path[prefix.size()] == '/';
}

static bool is_system_path(const string& normalized) {
static const vector<string> prefixes = {
"/usr/include",
"/usr/lib",
"/usr/local/include",
"/usr/local/lib",
"/lib",
"/lib64"
};
for(const auto& prefix : prefixes) {
if(path_has_prefix(normalized, prefix))
return true;
}
return false;
}

static bool file_matches_scope(const string& name,
const unordered_set<string>& scope,
bool allow_system_sources) {
if(name.empty())
return false;
string normalized = canonicalize_path(name);
if(is_coz_header(normalized))
return false;
if(!allow_system_sources && is_system_path(normalized))
return false;
if(scope.empty())
return true;
// Filter Rust toolchain/dependency paths unless user specified an explicit source scope
bool default_scope = (scope.size() == 1 && scope.count("%") == 1);
if(default_scope && is_rust_path(normalized))
return false;
return in_scope_normalized(normalized, scope);
}

Expand Down
65 changes: 65 additions & 0 deletions libcoz/path_filter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright (c) 2015, Charlie Curtsinger and Emery Berger,
* University of Massachusetts Amherst
* This file is part of the Coz project. See LICENSE.md file at the top-level
* directory of this distribution and at http://github.com/plasma-umass/coz.
*/

#ifndef COZ_PATH_FILTER_H
#define COZ_PATH_FILTER_H

#include <cstdlib>
#include <string>
#include <vector>

inline bool path_has_prefix(const std::string& path, const std::string& prefix) {
if(prefix.empty())
return false;
if(prefix.size() > path.size())
return false;
if(path.compare(0, prefix.size(), prefix) != 0)
return false;
return path.size() == prefix.size() || path[prefix.size()] == '/';
}

inline bool is_system_path(const std::string& normalized) {
static const std::vector<std::string> prefixes = {
"/usr/include",
"/usr/lib",
"/usr/local/include",
"/usr/local/lib",
"/lib",
"/lib64"
};
for(const auto& prefix : prefixes) {
if(path_has_prefix(normalized, prefix))
return true;
}
return false;
}

inline bool is_rust_path(const std::string& normalized) {
// /rustc/<hash>/... paths are synthetic, always start with /rustc
if(path_has_prefix(normalized, "/rustc"))
return true;
// .rustup and .cargo are only Rust toolchain paths when under $HOME
const char* home = std::getenv("HOME");
if(home && home[0] != '\0') {
std::string h(home);
if(path_has_prefix(normalized, h + "/.rustup"))
return true;
if(path_has_prefix(normalized, h + "/.cargo/registry"))
return true;
if(path_has_prefix(normalized, h + "/.cargo/git"))
return true;
}
return false;
}

inline bool is_coz_header(const std::string& path) {
const std::string suffix = "/coz.h";
return path.size() >= suffix.size() &&
path.compare(path.size() - suffix.size(), suffix.size(), suffix) == 0;
}

#endif // COZ_PATH_FILTER_H
8 changes: 1 addition & 7 deletions rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,12 +203,11 @@ struct coz_counter_t {
/// `typedef coz_counter_t* (*coz_get_counter_t)(int, const char*);`
type GetCounterFn = unsafe extern "C" fn(libc::c_int, *const libc::c_char) -> *mut coz_counter_t;

#[cfg(target_os = "linux")]
fn coz_get_counter(ty: libc::c_int, name: &CStr) -> Option<*mut coz_counter_t> {
static GET_COUNTER: OnceCell<Option<GetCounterFn>> = OnceCell::new();
let func = GET_COUNTER.get_or_init(|| {
let name = CStr::from_bytes_with_nul(b"_coz_get_counter\0").unwrap();
// SAFETY: We are calling an external function that does exist in Linux.
// SAFETY: dlsym is available on all POSIX platforms (Linux, macOS, etc.).
// No specific invariants that we must uphold have been defined.
let func = unsafe { libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr()) };
if func.is_null() {
Expand All @@ -225,8 +224,3 @@ fn coz_get_counter(ty: libc::c_int, name: &CStr) -> Option<*mut coz_counter_t> {
// No specific invariants that we must uphold have been defined.
func.map(|f| unsafe { f(ty, name.as_ptr()) })
}

#[cfg(not(target_os = "linux"))]
fn coz_get_counter(_ty: libc::c_int, _name: &CStr) -> Option<*mut coz_counter_t> {
None
}
18 changes: 18 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
add_executable(path_filter_test
${CMAKE_SOURCE_DIR}/tests/path_filter/path_filter_test.cpp)
target_include_directories(path_filter_test PRIVATE
${CMAKE_SOURCE_DIR}/libcoz)
target_compile_features(path_filter_test PRIVATE cxx_std_11)

add_test(NAME path_filter
COMMAND path_filter_test)

add_executable(dwarf_scope_test
${CMAKE_SOURCE_DIR}/tests/dwarf/dwarf_scope_test.cpp)
target_include_directories(dwarf_scope_test PRIVATE
Expand All @@ -21,3 +30,12 @@ add_test(NAME dwarf_scope_filter
${TEST_OUTPUT_DIR})
set_tests_properties(dwarf_scope_filter PROPERTIES
ENVIRONMENT "PYTHONUNBUFFERED=1")

set(RUST_FILTER_OUTPUT_DIR "${CMAKE_BINARY_DIR}/tests/rust_filter")

add_test(NAME rust_source_filter
COMMAND ${CMAKE_SOURCE_DIR}/tests/run_rust_filter_test.sh
$<TARGET_FILE:coz>
${RUST_FILTER_OUTPUT_DIR})
set_tests_properties(rust_source_filter PROPERTIES
ENVIRONMENT "PYTHONUNBUFFERED=1")
Loading