Skip to content

Commit

Permalink
add an a linker plugin experiment, move tools to a subdirectory
Browse files Browse the repository at this point in the history
  • Loading branch information
dmitmel committed Dec 20, 2023
1 parent f2abdfa commit abff044
Show file tree
Hide file tree
Showing 9 changed files with 205 additions and 4 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.pio/
.cache/clangd/
**/.cache/clangd/
local.mk
.ccls
compile_commands.json
Expand Down
18 changes: 17 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.14)
cmake_minimum_required(VERSION 3.17)

if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/cmake/arm_gcc_toolchain.cmake")
Expand All @@ -21,6 +21,7 @@ option(FETCHCONTENT_QUIET "" OFF) # Output download progress and other logs
option(FETCHCONTENT_UPDATES_DISCONNECTED "" ON) # Don't check for updates every time

include(FetchContent)
include(ExternalProject)

set(DEPENDENCIES_DIR "" CACHE FILEPATH "The directory in which the dependencies will be downloaded and unpacked")
if(DEPENDENCIES_DIR STREQUAL "")
Expand Down Expand Up @@ -74,6 +75,16 @@ FetchContent_Declare(stm32_mw_usb_host
DOWNLOAD_NAME "stm32_mw_usb_host_v3.3.4.tar.gz"
)

# TODO comments
ExternalProject_Add(tools
PREFIX "${CMAKE_BINARY_DIR}/_deps/tools-prefix"
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/tools"
SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/tools"
DOWNLOAD_COMMAND ""
INSTALL_COMMAND "" # An empty string suppresses this step since at least CMake 3.10
BUILD_ALWAYS YES # TODO
)

get_property(project_languages GLOBAL PROPERTY ENABLED_LANGUAGES)
foreach(lang IN LISTS project_languages)
foreach(config IN ITEMS "DEBUG" "MINSIZEREL" "RELEASE" "RELWITHDEBINFO")
Expand Down Expand Up @@ -295,6 +306,11 @@ set(linker_map_file $<TARGET_FILE:firmware>.map)
target_link_options(firmware PRIVATE LINKER:--cref,-Map=${linker_map_file})
set_property(TARGET firmware APPEND PROPERTY ADDITIONAL_CLEAN_FILES "${linker_map_file}")

add_dependencies(firmware tools)
set(linker_plugin_file "${CMAKE_CURRENT_BINARY_DIR}/tools/libtest_linker_plugin.so")
target_link_options(firmware PRIVATE LINKER:-plugin,${linker_plugin_file})
set_property(TARGET firmware APPEND PROPERTY LINK_DEPENDS "${linker_plugin_file}")

include(CheckCCompilerFlag)
# A replacement for the CheckLinkerFlag module, added in CMake v3.18, which
# only needs CMake v3.14.
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,14 @@ cmake freshcmake $(BUILD_DIR_STAMP):
# This rule simply checks that the build system has been generated.
ensurecmake: $(BUILD_DIR_STAMP)

.PHONY: all firmware upload clean
.PHONY: all firmware tools upload clean
# The targets from the actual build system that will be exposed to the user.
# $(BUILD_DIR_STAMP) is an order-only dependency here: Make will ensure that it
# is made the first time, but won't care about file modification times later.
# Afterwards, it is CMake's responsibility to regenerate the files when it
# detects a change in any `CMakeLists.txt`. The plus sign before the command
# tells Make to execute it even in the dry-run mode.
all firmware upload clean: | $(BUILD_DIR_STAMP)
all firmware tools upload clean: | $(BUILD_DIR_STAMP)
+$(BUILD_TOOL) -C '$(BUILD_DIR)' $@

.PHONY: distclean
Expand Down
24 changes: 24 additions & 0 deletions tools/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
cmake_minimum_required(VERSION 3.5)
project(stmes_tools C CXX)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

set(CMAKE_C_STANDARD 99)
set(CMAKE_C_EXTENSIONS YES)
set(CMAKE_C_STANDARD_REQUIRED YES)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_EXTENSIONS YES)
set(CMAKE_CXX_STANDARD_REQUIRED YES)

add_library(test_linker_plugin SHARED test_linker_plugin.cc)

# TODO: Share this with the top-level CMakeLists.txt somehow
target_compile_options(test_linker_plugin PRIVATE
-Wall -Wextra -Wpedantic -pedantic-errors
-Werror=return-type
-Wdouble-promotion
-Wmissing-declarations
-Werror=float-conversion
$<$<COMPILE_LANGUAGE:C>:-Werror=strict-prototypes>
)
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
161 changes: 161 additions & 0 deletions tools/test_linker_plugin.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
// TODO comments

#include <list>
#include <memory>
#include <string>
#include <unistd.h>

#define HAVE_STDINT_H 1
#define HAVE_INTTYPES_H 1
#include <plugin-api.h>

Check failure on line 10 in tools/test_linker_plugin.cc

View workflow job for this annotation

GitHub Actions / Build (Debug, gcc)

plugin-api.h: No such file or directory

Check failure on line 10 in tools/test_linker_plugin.cc

View workflow job for this annotation

GitHub Actions / Build (Release, gcc)

plugin-api.h: No such file or directory

Check failure on line 10 in tools/test_linker_plugin.cc

View workflow job for this annotation

GitHub Actions / Build (Debug, clang)

plugin-api.h: No such file or directory

#define PACKAGE
#define PACKAGE_VERSION
#include <bfd.h>

// TODO check status

static const struct {
ld_plugin_tag num;
const char* name;
} LD_PLUGIN_TAG_NAMES[] = {
{ LDPT_NULL, "LDPT_NULL" },
{ LDPT_NULL, "LDPT_NULL" },
{ LDPT_API_VERSION, "LDPT_API_VERSION" },
{ LDPT_GOLD_VERSION, "LDPT_GOLD_VERSION" },
{ LDPT_LINKER_OUTPUT, "LDPT_LINKER_OUTPUT" },
{ LDPT_OPTION, "LDPT_OPTION" },
{ LDPT_REGISTER_CLAIM_FILE_HOOK, "LDPT_REGISTER_CLAIM_FILE_HOOK" },
{ LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK, "LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK" },
{ LDPT_REGISTER_CLEANUP_HOOK, "LDPT_REGISTER_CLEANUP_HOOK" },
{ LDPT_ADD_SYMBOLS, "LDPT_ADD_SYMBOLS" },
{ LDPT_GET_SYMBOLS, "LDPT_GET_SYMBOLS" },
{ LDPT_ADD_INPUT_FILE, "LDPT_ADD_INPUT_FILE" },
{ LDPT_MESSAGE, "LDPT_MESSAGE" },
{ LDPT_GET_INPUT_FILE, "LDPT_GET_INPUT_FILE" },
{ LDPT_RELEASE_INPUT_FILE, "LDPT_RELEASE_INPUT_FILE" },
{ LDPT_ADD_INPUT_LIBRARY, "LDPT_ADD_INPUT_LIBRARY" },
{ LDPT_OUTPUT_NAME, "LDPT_OUTPUT_NAME" },
{ LDPT_SET_EXTRA_LIBRARY_PATH, "LDPT_SET_EXTRA_LIBRARY_PATH" },
{ LDPT_GNU_LD_VERSION, "LDPT_GNU_LD_VERSION" },
{ LDPT_GET_VIEW, "LDPT_GET_VIEW" },
{ LDPT_GET_INPUT_SECTION_COUNT, "LDPT_GET_INPUT_SECTION_COUNT" },
{ LDPT_GET_INPUT_SECTION_TYPE, "LDPT_GET_INPUT_SECTION_TYPE" },
{ LDPT_GET_INPUT_SECTION_NAME, "LDPT_GET_INPUT_SECTION_NAME" },
{ LDPT_GET_INPUT_SECTION_CONTENTS, "LDPT_GET_INPUT_SECTION_CONTENTS" },
{ LDPT_UPDATE_SECTION_ORDER, "LDPT_UPDATE_SECTION_ORDER" },
{ LDPT_ALLOW_SECTION_ORDERING, "LDPT_ALLOW_SECTION_ORDERING" },
{ LDPT_GET_SYMBOLS_V2, "LDPT_GET_SYMBOLS_V2" },
{ LDPT_ALLOW_UNIQUE_SEGMENT_FOR_SECTIONS, "LDPT_ALLOW_UNIQUE_SEGMENT_FOR_SECTIONS" },
{ LDPT_UNIQUE_SEGMENT_FOR_SECTIONS, "LDPT_UNIQUE_SEGMENT_FOR_SECTIONS" },
{ LDPT_GET_SYMBOLS_V3, "LDPT_GET_SYMBOLS_V3" },
{ LDPT_GET_INPUT_SECTION_ALIGNMENT, "LDPT_GET_INPUT_SECTION_ALIGNMENT" },
{ LDPT_GET_INPUT_SECTION_SIZE, "LDPT_GET_INPUT_SECTION_SIZE" },
{ LDPT_REGISTER_NEW_INPUT_HOOK, "LDPT_REGISTER_NEW_INPUT_HOOK" },
{ LDPT_GET_WRAP_SYMBOLS, "LDPT_GET_WRAP_SYMBOLS" },
{ LDPT_ADD_SYMBOLS_V2, "LDPT_ADD_SYMBOLS_V2" },
{ LDPT_GET_API_VERSION, "LDPT_GET_API_VERSION" },
{ LDPT_REGISTER_CLAIM_FILE_HOOK_V2, "LDPT_REGISTER_CLAIM_FILE_HOOK_V2" },
};

static struct {
ld_plugin_message message;
ld_plugin_register_claim_file register_claim_file;
ld_plugin_register_all_symbols_read register_all_symbols_read;
ld_plugin_register_cleanup register_cleanup;
ld_plugin_get_view get_view;
} api = {};

#define LOG(...) (api.message(LDPL_INFO, __VA_ARGS__))

// struct LinkedFile {
// std::string name;
// int fd;
// off_t offset;
// off_t size;
// void* handle;
// LinkedFile() {}
// explicit LinkedFile(const ld_plugin_input_file& raw)
// : name(raw.name), fd(raw.fd), offset(raw.offset), size(raw.filesize), handle(raw.handle) {}
// };

// static std::list<LinkedFile> linked_files;

extern "C" ld_plugin_status onload(ld_plugin_tv* tv);
static ld_plugin_status claim_file_hook(const ld_plugin_input_file* file, int* claimed);
static ld_plugin_status all_symbols_read_hook();
static ld_plugin_status cleanup_hook();

ld_plugin_status onload(ld_plugin_tv* tv) {
ld_plugin_tv* first_tv = tv;

for (; tv->tv_tag != LDPT_NULL; tv++) {
switch (tv->tv_tag) {
case LDPT_MESSAGE: api.message = tv->tv_u.tv_message; break;
case LDPT_REGISTER_CLAIM_FILE_HOOK:
api.register_claim_file = tv->tv_u.tv_register_claim_file;
break;
case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
api.register_all_symbols_read = tv->tv_u.tv_register_all_symbols_read;
break;
case LDPT_REGISTER_CLEANUP_HOOK: api.register_cleanup = tv->tv_u.tv_register_cleanup; break;
case LDPT_GET_VIEW: api.get_view = tv->tv_u.tv_get_view; break;
default: break;
}
}

LOG("hi!");

for (tv = first_tv; tv->tv_tag != 0; tv++) {
for (const auto& tag : LD_PLUGIN_TAG_NAMES) {
if (tag.num == tv->tv_tag) {
switch (tv->tv_tag) {
case LDPT_NULL:
case LDPT_API_VERSION:
case LDPT_GNU_LD_VERSION:
case LDPT_LINKER_OUTPUT: LOG("%s(%d)", tag.name, tv->tv_u.tv_val); break;
case LDPT_OPTION:
case LDPT_OUTPUT_NAME: LOG("%s(%s)", tag.name, tv->tv_u.tv_string); break;
default: LOG("%s(%p)", tag.name, (void*)tv->tv_u.tv_string); break;
}
break;
}
}
}

api.register_cleanup(&cleanup_hook);
api.register_all_symbols_read(&all_symbols_read_hook);
api.register_claim_file(&claim_file_hook);

return LDPS_OK;
}

ld_plugin_status claim_file_hook(const ld_plugin_input_file* file, int* claimed) {
*claimed = false;
// linked_files.push_back(LinkedFile(*file));
// LOG("%s %d %d", file->name, file->offset, *claimed);
LOG("%s", file->name);
std::unique_ptr<char[]> alloced_contents = nullptr;
const void* view = nullptr;
if (api.get_view) {
api.get_view(file->handle, &view);
} else {
alloced_contents.reset(new char[file->filesize]);
pread(file->fd, alloced_contents.get(), file->filesize, file->offset);
view = alloced_contents.get();
}
return LDPS_OK;
}

ld_plugin_status all_symbols_read_hook() {
// for (const auto& file : linked_files) {
// LOG("%s %p", file.name.c_str(), file.handle);
// // api.get_symbols(file.handle, 0, nullptr);
// }
return LDPS_OK;
}

ld_plugin_status cleanup_hook() {
// linked_files.clear();
return LDPS_OK;
}

0 comments on commit abff044

Please sign in to comment.