blob: e84c582b151b8c469e70f4a24f19af63dad06c6c [file] [log] [blame]
Brenden Blanco7009b552015-05-26 11:48:17 -07001#include <cstring>
2#include <memory>
3#include <string>
4#include <vector>
5#include <unistd.h>
6
7#define KERNEL_MODULES_DIR "/lib/modules"
8
9namespace ebpf {
10
11struct FileDeleter {
12 void operator() (FILE *fp) {
13 fclose(fp);
14 }
15};
16typedef std::unique_ptr<FILE, FileDeleter> FILEPtr;
17
18// Helper with pushd/popd semantics
19class DirStack {
20 public:
21 explicit DirStack(const char *dst) : ok_(false) {
22 if (getcwd(cwd_, sizeof(cwd_)) == NULL) {
23 ::perror("getcwd");
24 return;
25 }
26 if (::chdir(dst)) {
27 fprintf(stderr, "chdir(%s): %s\n", dst, strerror(errno));
28 return;
29 }
30 ok_ = true;
31 }
32 ~DirStack() {
33 if (!ok_) return;
34 if (::chdir(cwd_)) {
35 fprintf(stderr, "chdir(%s): %s\n", cwd_, strerror(errno));
36 }
37 }
38 bool ok() const { return ok_; }
39 const char * cwd() const { return cwd_; }
40 private:
41 bool ok_;
42 char cwd_[256];
43};
44
45// Scoped class to manage the creation/deletion of tmpdirs
46class TmpDir {
47 public:
48 explicit TmpDir(const std::string &prefix = "/tmp/bcc-")
49 : ok_(false), prefix_(prefix) {
50 prefix_ += "XXXXXX";
51 if (::mkdtemp((char *)prefix_.data()) == NULL)
52 ::perror("mkdtemp");
53 else
54 ok_ = true;
55 }
56 ~TmpDir() {
57 auto fn = [] (const char *path, const struct stat *, int) -> int {
58 return ::remove(path);
59 };
60 if (::ftw(prefix_.c_str(), fn, 20) < 0)
61 ::perror("ftw");
62 else
63 ::remove(prefix_.c_str());
64 }
65 bool ok() const { return ok_; }
66 const std::string & str() const { return prefix_; }
67 private:
68 bool ok_;
69 std::string prefix_;
70};
71
72// Compute the kbuild flags for the currently running kernel
73// Do this by:
74// 1. Create temp Makefile with stub dummy.c
75// 2. Run module build on that makefile, saving the computed flags to a file
76// 3. Cache the file for fast flag lookup in subsequent runs
77// Note: Depending on environment, different cache locations may be desired. In
78// case we eventually support non-root user programs, cache in $HOME.
79class KBuildHelper {
80 private:
81 int learn_flags(const std::string &tmpdir, const char *uname_release, const char *cachefile);
82 public:
83 KBuildHelper();
84 int get_flags(const char *uname_release, std::vector<std::string> *cflags);
85 private:
86 std::string cache_dir_;
87};
88
89} // namespace ebpf