Skip to content

Commit

Permalink
Use syscall when name_to_handle_at is not available
Browse files Browse the repository at this point in the history
This makes cgroupid function to work fine when building with alpine.
  • Loading branch information
krnowak authored and ajor committed Oct 16, 2018
1 parent d123315 commit b84eca1
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 54 deletions.
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Expand Up @@ -8,6 +8,7 @@ add_executable(bpftrace
map.cpp
mapkey.cpp
printf.cpp
resolve_cgroupid.cpp
tracepoint_format_parser.cpp
types.cpp
list.cpp
Expand Down
1 change: 1 addition & 0 deletions src/act_helpers.h
Expand Up @@ -9,6 +9,7 @@
// Here are some helper macros helping to ensure if the C++
// counterpart has members of the same type and offset.

#include <cstddef>
#include <type_traits>

namespace act_helpers
Expand Down
56 changes: 2 additions & 54 deletions src/bpftrace.cpp
Expand Up @@ -14,11 +14,11 @@
#include "bcc_syms.h"
#include "perf_reader.h"

#include "act_helpers.h"
#include "bpforc.h"
#include "bpftrace.h"
#include "attached_probe.h"
#include "triggers.h"
#include "resolve_cgroupid.h"

namespace bpftrace {

Expand Down Expand Up @@ -1288,63 +1288,11 @@ uint64_t BPFtrace::resolve_kname(const std::string &name)
return addr;
}

#ifdef HAVE_NAME_TO_HANDLE_AT

namespace
{

// Not embedding file_handle directly in cgid_file_handle, because C++
// has problems with zero-sized array as struct members and
// file_handle's f_handle is a zero-sized array.
//
// Also, not embedding file_handle through the public inheritance,
// since checking for member offsets with offsetof within a
// non-standard-layout type is conditionally-supported (so compilers
// are not required to support it). And we want to do it to make sure
// we got the wrapper right.
//
// Hence open coding the file_handle members directly in
// cgid_file_handle and the static asserts following it.
struct cgid_file_handle
{
file_handle *as_file_handle_ptr()
{
return reinterpret_cast<file_handle*>(this);
}

unsigned int handle_bytes = sizeof(uint64_t);
int handle_type;
uint64_t cgid;
};

ACTH_ASSERT_SAME_SIZE(cgid_file_handle, file_handle, uint64_t);
ACTH_ASSERT_SAME_MEMBER(cgid_file_handle, handle_bytes, file_handle, handle_bytes);
ACTH_ASSERT_SAME_MEMBER(cgid_file_handle, handle_type, file_handle, handle_type);
ACTH_ASSERT_SAME_OFFSET(cgid_file_handle, cgid, file_handle, f_handle);

}

uint64_t BPFtrace::resolve_cgroupid(const std::string &path)
{
cgid_file_handle cfh;
int mount_id;
auto err = name_to_handle_at(AT_FDCWD, path.c_str(), cfh.as_file_handle_ptr(), &mount_id, 0);
if (err < 0) {
throw std::runtime_error("cgroup '" + path + "' not found");
}

return cfh.cgid;
return bpftrace_linux::resolve_cgroupid(path);
}

#else

uint64_t BPFtrace::resolve_cgroupid(const std::string &path)
{
throw std::runtime_error("cgroupid is not supported on this system");
}

#endif

uint64_t BPFtrace::resolve_uname(const std::string &name, const std::string &path)
{
uint64_t addr = 0;
Expand Down
91 changes: 91 additions & 0 deletions src/resolve_cgroupid.cpp
@@ -0,0 +1,91 @@
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif

#ifdef HAVE_NAME_TO_HANDLE_AT

# include <sys/types.h>
# include <sys/stat.h>

#else

# include <unistd.h>
# include <sys/syscall.h>

#endif

#include <fcntl.h>

#include <stdexcept>

#include "act_helpers.h"
#include "resolve_cgroupid.h"

namespace
{

#ifndef HAVE_NAME_TO_HANDLE_AT

struct file_handle
{
unsigned int handle_bytes;
int handle_type;
char f_handle[0];
};

int name_to_handle_at(int dirfd, const char *pathname,
struct file_handle *handle,
int *mount_id, int flags)
{
return (int)syscall(SYS_name_to_handle_at, dirfd, pathname, handle, mount_id, flags);
}

#endif

// Not embedding file_handle directly in cgid_file_handle, because C++
// has problems with zero-sized array as struct members and
// file_handle's f_handle is a zero-sized array.
//
// Also, not embedding file_handle through the public inheritance,
// since checking for member offsets with offsetof within a
// non-standard-layout type is conditionally-supported (so compilers
// are not required to support it). And we want to do it to make sure
// we got the wrapper right.
//
// Hence open coding the file_handle members directly in
// cgid_file_handle and the static asserts following it.
struct cgid_file_handle
{
file_handle *as_file_handle_ptr()
{
return reinterpret_cast<file_handle*>(this);
}

unsigned int handle_bytes = sizeof(std::uint64_t);
int handle_type;
std::uint64_t cgid;
};

ACTH_ASSERT_SAME_SIZE(cgid_file_handle, file_handle, std::uint64_t);
ACTH_ASSERT_SAME_MEMBER(cgid_file_handle, handle_bytes, file_handle, handle_bytes);
ACTH_ASSERT_SAME_MEMBER(cgid_file_handle, handle_type, file_handle, handle_type);
ACTH_ASSERT_SAME_OFFSET(cgid_file_handle, cgid, file_handle, f_handle);

}

namespace bpftrace_linux
{

std::uint64_t resolve_cgroupid(const std::string &path)
{
cgid_file_handle cfh;
int mount_id;
auto err = name_to_handle_at(AT_FDCWD, path.c_str(), cfh.as_file_handle_ptr(), &mount_id, 0);
if (err < 0) {
throw std::runtime_error("cgroup '" + path + "' not found");
}

return cfh.cgid;
}

}
11 changes: 11 additions & 0 deletions src/resolve_cgroupid.h
@@ -0,0 +1,11 @@
#pragma once

#include <cstdint>
#include <string>

namespace bpftrace_linux
{

std::uint64_t resolve_cgroupid(const std::string &path);

}
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Expand Up @@ -20,6 +20,7 @@ add_executable(bpftrace_test
${CMAKE_SOURCE_DIR}/src/map.cpp
${CMAKE_SOURCE_DIR}/src/mapkey.cpp
${CMAKE_SOURCE_DIR}/src/printf.cpp
${CMAKE_SOURCE_DIR}/src/resolve_cgroupid.cpp
${CMAKE_SOURCE_DIR}/src/tracepoint_format_parser.cpp
${CMAKE_SOURCE_DIR}/src/types.cpp
)
Expand Down

0 comments on commit b84eca1

Please sign in to comment.