Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rewriter: Redeclare static functions that have their address taken with used #441

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion runtime/libia2/include/ia2.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@
#define IA2_CALL(opaque, id) opaque
#define IA2_CAST(func, ty) (ty) (void *) func
#else
#define IA2_DEFINE_WRAPPER(func) IA2_DEFINE_WRAPPER_##func
#define IA2_DEFINE_WRAPPER(func) \
__attribute__((__used__)) static void *keep_##func = (void *)func; \
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't love adding a function pointer to data just to mark a function as used. We don't have any other way?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't put much thought into this. There might be a way to get __attribute__((used)) typeof(func) func; before the function definition, but I'd need to think about how that would work with the types func's signature depends on.

IA2_DEFINE_WRAPPER_##func
#define IA2_SIGHANDLER(func) ia2_sighandler_##func
/// Create a wrapped signal handler for `sa_sigaction`
///
Expand Down
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ add_subdirectory(shared_data)
add_subdirectory(global_fn_ptr)
add_subdirectory(rewrite_macros)
add_subdirectory(sighandler)
add_subdirectory(static_addr_taken)

# The following tests are not supported on ARM64 yet
if (NOT LIBIA2_AARCH64)
Expand Down
14 changes: 14 additions & 0 deletions tests/static_addr_taken/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
define_shared_lib(
SRCS lib.c
NEEDS_LD_WRAP
PKEY 2
)

define_test(
SRCS main.c
NEEDS_LD_WRAP
PKEY 1
CRITERION_TEST
)

define_ia2_wrapper()
10 changes: 10 additions & 0 deletions tests/static_addr_taken/include/static_fns.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#pragma once

typedef void (*fn_ptr_ty)(void);

static void inline_noop(void) {
printf("called %s defined in header\n", __func__);
}

fn_ptr_ty *get_ptrs_in_main(void);
fn_ptr_ty *get_ptrs_in_lib(void);
40 changes: 40 additions & 0 deletions tests/static_addr_taken/lib.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include <criterion/criterion.h>
#include <criterion/logging.h>
#include <ia2.h>

//#include <test_fault_handler.h>

#define IA2_COMPARTMENT 2
#include <ia2_compartment_init.inc>

#include "static_fns.h"

static void duplicate_noop(void) {
printf("called %s in library\n", __func__);
}

static void identical_name(void) {
static int x = 4;
printf("%s in library read x = %d\n", __func__, x);
}

static fn_ptr_ty ptrs[3] IA2_SHARED_DATA = {
inline_noop, duplicate_noop, identical_name
};

fn_ptr_ty *get_ptrs_in_lib(void) {
return ptrs;
}

Test(static_addr_taken, call_ptrs_in_lib) {
for (int i = 0; i < 3; i++) {
ptrs[i]();
}
}

Test(static_addr_taken, call_ptr_from_main) {
fn_ptr_ty *main_ptrs = get_ptrs_in_main();
for (int i = 0; i < 3; i++) {
main_ptrs[i]();
}
}
44 changes: 44 additions & 0 deletions tests/static_addr_taken/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#include <criterion/criterion.h>
#include <criterion/logging.h>
#include <ia2.h>

//#define IA2_DEFINE_TEST_HANDLER
//#include <test_fault_handler.h>

INIT_RUNTIME(2);
#define IA2_COMPARTMENT 1
#include <ia2_compartment_init.inc>

#include "static_fns.h"

#define LOCAL static

LOCAL void duplicate_noop(void) {
printf("called %s in main binary\n", __func__);
}

static void identical_name(void) {
static int x = 3;
printf("%s in main binary read x = %d\n", __func__, x);
}

static fn_ptr_ty ptrs[3] IA2_SHARED_DATA = {
inline_noop, duplicate_noop, identical_name
};

fn_ptr_ty *get_ptrs_in_main(void) {
return ptrs;
}

Test(static_addr_taken, call_ptrs_in_main) {
for (int i = 0; i < 3; i++) {
ptrs[i]();
}
}

Test(static_addr_taken, call_ptr_from_lib) {
fn_ptr_ty *lib_ptrs = get_ptrs_in_lib();
for (int i = 0; i < 3; i++) {
lib_ptrs[i]();
}
}
19 changes: 1 addition & 18 deletions tools/rewriter/SourceRewriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -666,24 +666,6 @@ class FnPtrExpr : public RefactoringCallback {

auto [it, new_fn] = internal_addr_taken_fns[filename].insert(
std::make_pair(fn_name, new_type));

// TODO: Note that this only checks if a function is added to the
// internal_addr_taken_fns map. To make the rewriter idempotent we should
// check for an existing used attribute.
if (new_fn) {
auto decl_start = fn_decl->getBeginLoc();
if (!decl_start.isFileID()) {
llvm::errs() << "Error: non-file loc for function " << fn_name << '\n';
} else {
Replacement old_used_attr(sm, decl_start, 0,
llvm::StringRef("__attribute__((used)) "));
Replacement used_attr = replace_new_file(filename, old_used_attr);
auto err = file_replacements[filename].add(used_attr);
if (err) {
llvm::errs() << "Error adding replacements: " << err << '\n';
}
}
}
}

// This check must come after modifying the maps in this pass but before the
Expand All @@ -701,6 +683,7 @@ class FnPtrExpr : public RefactoringCallback {
return;
}

// Add the IA2_FN annotation around the function pointer expression
clang::CharSourceRange expansion_range = sm.getExpansionRange(loc);
Replacement old_r{sm, expansion_range, new_expr};
Replacement r = replace_new_file(filename, old_r);
Expand Down
Loading