Skip to content

Commit

Permalink
Fix cgreen-devs#251: cgreen-runner handle non-lib files
Browse files Browse the repository at this point in the history
Remove dependency to nm and rather use libbfd, which is the same lib
used by nm. There is no additional depency, but cmake will fail if it
cannot find libbfd. There was no check for nm before.

Unit test still use nm to count the number of symbols. It provides a
double check on this implementation.

Before we would get:
$ ./build/tools/cgreen-runner ./build/tests/libbreadcrumb_tests.so
Running "libbreadcrumb_tests" (9 tests)...
  "Breadcrumb": 9 passes in 3ms.
Completed "libbreadcrumb_tests": 9 passes in 3ms.

$ ./build/tools/cgreen-runner ./build/tests/Makefile
/usr/bin/nm: ./build/tests/Makefile: file format not recognized
No tests found in './build/tests/Makefile'.

$ ./build/tools/cgreen-runner /usr/lib/libgit2.so
/usr/bin/nm: /usr/lib/libgit2.so: no symbols
No tests found in '/usr/lib/libgit2.so'.

After this patch we get:
$ ./build/tools/cgreen-runner ./build/tests/libbreadcrumb_tests.so
Running "libbreadcrumb_tests" (9 tests)...
  "Breadcrumb": 9 passes in 3ms.
Completed "libbreadcrumb_tests": 9 passes in 3ms.

$ ./build/tools/cgreen-runner ./build/tests/Makefile
No tests found in './build/tests/Makefile'.

$ ./build/tools/cgreen-runner /usr/lib/libgit2.so
No tests found in '/usr/lib/libgit2.so'.
  • Loading branch information
fnadeau committed May 9, 2021
1 parent 4c92193 commit 613d6dd
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 33 deletions.
58 changes: 58 additions & 0 deletions cmake/Modules/FindLibBfd.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# - Try to find libbfd
# Once done this will define
#
# LIBBFD_FOUND - system has libbfd
# LIBBFD_INCLUDE_DIRS - the libbfd include directory
# LIBBFD_LIBRARIES - Link these to use libbfd
# LIBBFD_DEFINITIONS - Compiler switches required for using libbfd
#
# Based on:
#
# Copyright (c) 2008 Bernhard Walle <bernhard.walle@gmx.de>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#


if (LIBBFD_LIBRARIES AND LIBBFD_INCLUDE_DIRS)
set (LIBBFD_FIND_QUIETLY TRUE)
endif ()

find_path (LIBBFD_INCLUDE_DIRS
NAMES
bfd.h
dis-asm.h
PATHS
/usr/include
/usr/local/include
/opt/local/include
/opt/include
ENV CPATH)

# Ugly, yes ugly...
find_library (LIBBFD_BFD_LIBRARY
NAMES
bfd
PATHS
/usr/lib
/usr/lib64
/usr/local/lib
/usr/local/lib64
/usr/include
/opt/local/lib
/opt/usr/lib64
ENV LIBRARY_PATH
ENV LD_LIBRARY_PATH)

include (FindPackageHandleStandardArgs)


# handle the QUIETLY and REQUIRED arguments and set LIBBFD_FOUND to TRUE if all listed variables are TRUE
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibBfd DEFAULT_MSG
LIBBFD_BFD_LIBRARY
LIBBFD_INCLUDE_DIRS)

set(LIBBFD_LIBRARIES "${LIBBFD_BFD_LIBRARY}")
mark_as_advanced(LIBBFD_INCLUDE_DIRS LIBBFD_LIBRARIES LIBBFD_BFD_LIBRARY)
8 changes: 7 additions & 1 deletion tools/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
include_directories(${CGREEN_PUBLIC_INCLUDE_DIRS} ${PROJECT_BINARY_DIR})

find_package(LibBfd)

set(RUNNER_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/cgreen-runner.c
${CMAKE_CURRENT_SOURCE_DIR}/gopt.c
Expand All @@ -15,7 +17,11 @@ include(DefineRelativeFilePaths)
cmake_define_relative_file_paths ("${RUNNER_SRCS}")

add_executable(cgreen-runner ${RUNNER_SRCS})
target_link_libraries(cgreen-runner ${CGREEN_SHARED_LIBRARY} ${CMAKE_DL_LIBS})
target_link_libraries(cgreen-runner
${CGREEN_SHARED_LIBRARY}
${CMAKE_DL_LIBS}
${LIBBFD_LIBRARIES}
)

install(TARGETS cgreen-runner
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
Expand Down
101 changes: 69 additions & 32 deletions tools/discoverer.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

#include "io.h"

// bfd.h needs to have PACKAGE and PACKAGE_VERSION defined
#define PACKAGE "cgreen-runner"
#define PACKAGE_VERSION "unknown"
#include <bfd.h>

#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
Expand All @@ -21,52 +26,84 @@ static bool contains_cgreen_spec(const char *line) {
return cgreen_spec_start_of(line) != NULL;
}

static bool is_definition(const char *line) {
return strstr(line, " D ") != NULL;
}

static bool complete_line_read(char line[]) {
return line[strlen(line)-1] == '\n';
}
static void add_all_tests_from(asymbol **symbols, long symbol_count, CgreenVector *tests, bool verbose) {

for (long index = 0; index < symbol_count; ++index, ++symbols) {
bfd *cur_bfd;

static void strip_newline_from(char *name) {
if (name[strlen(name)-1] == '\n')
name[strlen(name)-1] = '\0';
}

static void add_all_tests_from(FILE *nm_output_pipe, CgreenVector *tests, bool verbose) {
char line[1000];
int length = read_line(nm_output_pipe, line, sizeof(line)-1);
while (length > -1) { /* TODO: >0 ? */
if (!complete_line_read(line))
PANIC("Too long line in nm output");
if (contains_cgreen_spec(line) && is_definition(line)) {
strip_newline_from(line);
TestItem *test_item = create_test_item_from(cgreen_spec_start_of(line));
if ((*symbols != NULL)
&& ((cur_bfd = bfd_asymbol_bfd(*symbols)) != NULL)
&& (!bfd_is_target_special_symbol(cur_bfd, *symbols))
&& contains_cgreen_spec((*symbols)->name)) {
TestItem *test_item = create_test_item_from(cgreen_spec_start_of((*symbols)->name));
if (verbose)
printf("Discovered %s:%s (%s)\n", test_item->context_name, test_item->test_name,
test_item->specification_name);
test_item->specification_name);
cgreen_vector_add(tests, test_item);
}
length = read_line(nm_output_pipe, line, sizeof(line)-1);
}
}

/* Read in the dynamic symbols. */

static asymbol **get_symbols_table(bfd *abfd, long *symbol_count, bool verbose)
{
long storage = bfd_get_dynamic_symtab_upper_bound(abfd);
if (storage < 0) {
if (!(bfd_get_file_flags(abfd) & DYNAMIC))
if (verbose)
printf("%s: not a dynamic object\n", bfd_get_filename(abfd));

*symbol_count = 0;
return NULL;
}

asymbol **symbols = (asymbol **) malloc(storage);
if (symbols == NULL) {
if (verbose)
printf("malloc failed while retrieving symbols\n");
*symbol_count = 0;
return NULL;
}

*symbol_count = bfd_canonicalize_dynamic_symtab(abfd, symbols);
if (*symbol_count < 0) {
if (verbose)
printf("%s: failed to get symbols count\n", bfd_get_filename(abfd));
*symbol_count = 0;
free(symbols);
return NULL;
}

return symbols;
}

CgreenVector *discover_tests_in(const char *filename, bool verbose) {
FILE *library = open_file(filename, "r");
if (library == NULL)
bfd* abfd = bfd_openr(filename, NULL);
if (!abfd) {
if (verbose)
printf("%s: bfd_openr failed\n", filename);
return NULL;
close_file(library);
}

bfd_check_format(abfd, bfd_object);
if ((bfd_get_file_flags(abfd) & HAS_SYMS) == 0) {
if (verbose)
printf("%s: incorrect format\n", filename);
bfd_close(abfd);
return NULL;
}

asymbol **symbols;
long symbol_count;
symbols = get_symbols_table(abfd, &symbol_count, verbose);

char nm_command[1000];
sprintf(nm_command, "/usr/bin/nm '%s'", filename);
FILE *nm_output_pipe = open_process(nm_command, "r");
if (nm_output_pipe == NULL)
if ((symbols == NULL) || (symbol_count <= 0)) {
bfd_close(abfd);
return NULL;
}

CgreenVector *tests = create_cgreen_vector((GenericDestructor)&destroy_test_item);
add_all_tests_from(nm_output_pipe, tests, verbose);
close_process(nm_output_pipe);
add_all_tests_from(symbols, symbol_count, tests, verbose);
return tests;
}

0 comments on commit 613d6dd

Please sign in to comment.