Skip to content

Commit

Permalink
tests for all kinds of debuginfo lookups
Browse files Browse the repository at this point in the history
  • Loading branch information
michalgr committed Nov 7, 2022
1 parent 7a0735d commit 65e9ef7
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 34 deletions.
7 changes: 5 additions & 2 deletions src/cc/bcc_elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -657,8 +657,11 @@ static int find_debug_via_buildid(Elf *e, struct bcc_elf_file *out) {
// mm/nnnnnn...nnnn.debug
// Where mm are the first two characters of the buildid, and nnnn are the
// rest of the build id, followed by .debug.
snprintf(fullpath, sizeof(fullpath), "/usr/lib/debug/.build-id/%c%c/%s.debug",
buildid[0], buildid[1], buildid + 2);
const char *bcc_debuginfo_root = getenv("BCC_DEBUGINFO_ROOT");
if (bcc_debuginfo_root == NULL)
bcc_debuginfo_root = "/usr/lib/debug";
snprintf(fullpath, sizeof(fullpath), "%s/.build-id/%c%c/%s.debug",
bcc_debuginfo_root, buildid[0], buildid[1], buildid + 2);
return bcc_elf_file_open(fullpath, out);
}

Expand Down
55 changes: 32 additions & 23 deletions tests/cc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,51 +46,60 @@ set(TEST_LIBBCC_SOURCES

file(COPY dummy_proc_map.txt DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
add_library(usdt_test_lib SHARED usdt_test_lib.cc)
add_library(debuginfo_test_lib SHARED debuginfo_test_lib.cc)

add_custom_command(OUTPUT debuginfo.so
COMMAND ${CMAKE_OBJCOPY}
ARGS --add-symbol debuginfo_only_symbol=.text:0
${CMAKE_CURRENT_BINARY_DIR}/libdebuginfo_test_lib.so
${CMAKE_CURRENT_BINARY_DIR}/debuginfo.so
DEPENDS debuginfo_test_lib)
add_custom_target(debuginfo DEPENDS debuginfo.so)

add_custom_command(OUTPUT with_gnu_debuglink.so
COMMAND ${CMAKE_OBJCOPY}
ARGS --add-gnu-debuglink=debuginfo.so
${CMAKE_CURRENT_BINARY_DIR}/libdebuginfo_test_lib.so
${CMAKE_CURRENT_BINARY_DIR}/with_gnu_debuglink.so
DEPENDS debuginfo debuginfo_test_lib)
add_custom_target(with_gnu_debuglink DEPENDS with_gnu_debuglink.so)
SET(DEBUGINFO_TARGETS debuginfo_test_lib debuginfo with_gnu_debuglink)

if(LIBLZMA_FOUND)
add_custom_command(OUTPUT libusdt_test_lib.so.xz
add_custom_command(OUTPUT debuginfo.so.xz
COMMAND xz
ARGS -k ${CMAKE_CURRENT_BINARY_DIR}/libusdt_test_lib.so
DEPENDS usdt_test_lib)
add_custom_target(libusdt_test_lib_so_xz DEPENDS libusdt_test_lib.so.xz)
ARGS -k ${CMAKE_CURRENT_BINARY_DIR}/debuginfo.so
DEPENDS debuginfo)
add_custom_target(debuginfo_xz DEPENDS debuginfo.so.xz)

add_custom_command(OUTPUT with_gnu_debugdata.so
COMMAND ${CMAKE_OBJCOPY}
ARGS --add-section .gnu_debugdata=${CMAKE_CURRENT_BINARY_DIR}/libusdt_test_lib.so.xz
--remove-section '.dynsym'
--strip-symbol 'lib_probed_function'
${CMAKE_CURRENT_BINARY_DIR}/libusdt_test_lib.so
ARGS --add-section .gnu_debugdata=${CMAKE_CURRENT_BINARY_DIR}/debuginfo.so.xz
${CMAKE_CURRENT_BINARY_DIR}/libdebuginfo_test_lib.so
${CMAKE_CURRENT_BINARY_DIR}/with_gnu_debugdata.so
DEPENDS libusdt_test_lib_so_xz)
add_custom_target(with_gnu_debugdata_so DEPENDS with_gnu_debugdata.so)
DEPENDS debuginfo_xz debuginfo_test_lib)
add_custom_target(with_gnu_debugdata DEPENDS with_gnu_debugdata.so)
list(APPEND DEBUGINFO_TARGETS with_gnu_debugdata)
endif(LIBLZMA_FOUND)

if(NOT CMAKE_USE_LIBBPF_PACKAGE)
add_executable(test_libbcc ${TEST_LIBBCC_SOURCES})
add_dependencies(test_libbcc bcc-shared)
if(LIBLZMA_FOUND)
add_dependencies(test_libbcc with_gnu_debugdata_so)
endif(LIBLZMA_FOUND)
add_dependencies(test_libbcc bcc-shared ${DEBUGINFO_TARGETS})

target_link_libraries(test_libbcc ${PROJECT_BINARY_DIR}/src/cc/libbcc.so dl usdt_test_lib)
set_target_properties(test_libbcc PROPERTIES INSTALL_RPATH ${PROJECT_BINARY_DIR}/src/cc)
target_compile_definitions(test_libbcc PRIVATE -DLIBBCC_NAME=\"libbcc.so\"
-DLIB_WITH_MINI_DEBUG_INFO=\"${CMAKE_CURRENT_BINARY_DIR}/with_gnu_debugdata.so\")
target_compile_definitions(test_libbcc PRIVATE -DLIBBCC_NAME=\"libbcc.so\")

add_test(NAME test_libbcc COMMAND ${TEST_WRAPPER} c_test_all sudo ${CMAKE_CURRENT_BINARY_DIR}/test_libbcc)
endif()

if(LIBBPF_FOUND)
add_executable(test_libbcc_no_libbpf ${TEST_LIBBCC_SOURCES})
add_dependencies(test_libbcc_no_libbpf bcc-shared)
if(LIBLZMA_FOUND)
add_dependencies(test_libbcc_no_libbpf with_gnu_debugdata_so)
endif(LIBLZMA_FOUND)

add_dependencies(test_libbcc_no_libbpf bcc-shared ${DEBUGINFO_TARGETS})

target_link_libraries(test_libbcc_no_libbpf ${PROJECT_BINARY_DIR}/src/cc/libbcc.so dl usdt_test_lib ${LIBBPF_LIBRARIES})
set_target_properties(test_libbcc_no_libbpf PROPERTIES INSTALL_RPATH ${PROJECT_BINARY_DIR}/src/cc)
target_compile_definitions(test_libbcc_no_libbpf PRIVATE -DLIBBCC_NAME=\"libbcc.so\"
-DLIB_WITH_MINI_DEBUG_INFO=\"${CMAKE_CURRENT_BINARY_DIR}/with_gnu_debugdata.so\")
target_compile_definitions(test_libbcc_no_libbpf PRIVATE -DLIBBCC_NAME=\"libbcc.so\")

add_test(NAME test_libbcc_no_libbpf COMMAND ${TEST_WRAPPER} c_test_all_no_libbpf sudo ${CMAKE_CURRENT_BINARY_DIR}/test_libbcc_no_libbpf)
endif()
Expand Down
4 changes: 4 additions & 0 deletions tests/cc/debuginfo_test_lib.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
extern "C" {

int symbol() { return 0; }
}
90 changes: 81 additions & 9 deletions tests/cc/test_c_api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,29 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <fcntl.h>
#include <dlfcn.h>
#include <fcntl.h>
#include <link.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <link.h>
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#include <cstdlib>

#include "bcc_elf.h"
#include "bcc_perf_map.h"
#include "bcc_proc.h"
#include "bcc_syms.h"
#include "catch.hpp"
#include "common.h"
#include "vendor/tinyformat.hpp"

#include "catch.hpp"


using namespace std;

static pid_t spawn_child(void *, bool, bool, int (*)(void *));
Expand Down Expand Up @@ -111,15 +112,86 @@ TEST_CASE("resolve symbol name in external library using loaded libraries", "[c_
bcc_procutils_free(sym.module);
}

#ifdef HAVE_LIBLZMA
TEST_CASE("resolve symbol name via mini debug info", "[c_api]") {
namespace {

void system(const std::string &command) {
if (::system(command.c_str())) {
abort();
}
}

class TmpDir {
public:
TmpDir() : path_("/tmp/bcc-test-XXXXXX") {
if (::mkdtemp(&path_[0]) == nullptr) {
abort();
}
}

~TmpDir() { system("rm -rf " + path_); }

const std::string &path() const { return path_; }

private:
std::string path_;
};

void test_debuginfo_only_symbol(const std::string &lib) {
struct bcc_symbol sym;
REQUIRE(bcc_resolve_symname(LIB_WITH_MINI_DEBUG_INFO, "lib_probed_function",
0x0, 0, nullptr, &sym) == 0);
REQUIRE(bcc_resolve_symname(lib.c_str(), "debuginfo_only_symbol", 0x0, 0,
nullptr, &sym) == 0);
REQUIRE(sym.module[0] == '/');
REQUIRE(sym.offset != 0);
bcc_procutils_free(sym.module);
}

} // namespace

TEST_CASE("resolve symbol name via symfs", "[c_api]") {
TmpDir tmpdir;
std::string lib_path = tmpdir.path() + "/lib.so";
std::string symfs = tmpdir.path() + "/symfs";
std::string symfs_lib_dir = symfs + "/" + tmpdir.path();
std::string symfs_lib_path = symfs_lib_dir + "/lib.so";

system("mkdir -p " + symfs);
system("cp " CMAKE_CURRENT_BINARY_DIR "/libdebuginfo_test_lib.so " +
lib_path);
system("mkdir -p " + symfs_lib_dir);
system("cp " CMAKE_CURRENT_BINARY_DIR "/debuginfo.so " + symfs_lib_path);

::setenv("BCC_SYMFS", symfs.c_str(), 1);
test_debuginfo_only_symbol(lib_path);
::unsetenv("BCC_SYMFS");
}

TEST_CASE("resolve symbol name via buildid", "[c_api]") {
char build_id[128] = {0};
REQUIRE(bcc_elf_get_buildid(CMAKE_CURRENT_BINARY_DIR
"/libdebuginfo_test_lib.so",
build_id) == 0);

TmpDir tmpdir;
std::string debugso_dir =
tmpdir.path() + "/.build-id/" + build_id[0] + build_id[1];
std::string debugso = debugso_dir + "/" + (build_id + 2) + ".debug";
system("mkdir -p " + debugso_dir);
system("cp " CMAKE_CURRENT_BINARY_DIR "/debuginfo.so " + debugso);

::setenv("BCC_DEBUGINFO_ROOT", tmpdir.path().c_str(), 1);
test_debuginfo_only_symbol(CMAKE_CURRENT_BINARY_DIR
"/libdebuginfo_test_lib.so");
::unsetenv("BCC_DEBUGINFO_ROOT");
}

TEST_CASE("resolve symbol name via gnu_debuglink", "[c_api]") {
test_debuginfo_only_symbol(CMAKE_CURRENT_BINARY_DIR "/with_gnu_debuglink.so");
}

#ifdef HAVE_LIBLZMA
TEST_CASE("resolve symbol name via mini debug info", "[c_api]") {
test_debuginfo_only_symbol(CMAKE_CURRENT_BINARY_DIR "/with_gnu_debugdata.so");
}
#endif

extern "C" int _a_test_function(const char *a_string) {
Expand Down

0 comments on commit 65e9ef7

Please sign in to comment.