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: Define call gates for function pointers in source defining the pointee #451

Merged
merged 2 commits into from
Nov 12, 2024

Conversation

ayrtonm
Copy link
Contributor

@ayrtonm ayrtonm commented Oct 17, 2024

We previously defined call gates for pointers to static functions by appending a macro to the rewritten source files. In that case we had to do this because the static function may not be referenced from outside the translation unit. For pointers to globally-visible functions we defined the call gates in the call gate .so for simplicity. This commit changes the latter call gates so they're defined like the former. This change simplifies control-flow since the call gate no longer requires cross-DSO calls and makes it possible to support programs that are intended to be compiled with -fvisibility=hidden since functions that may have hidden visibility are only referenced by call gates within the DSO that defines them. Partially addresses #435.

@kkysen kkysen self-requested a review October 17, 2024 19:45
Base automatically changed from sjc/static_addr_taken_used to main October 17, 2024 20:25
@ayrtonm ayrtonm force-pushed the am/fvisibility branch 3 times, most recently from 0324836 to 3dcc745 Compare October 22, 2024 17:22
@ayrtonm
Copy link
Contributor Author

ayrtonm commented Oct 28, 2024

Turns out we still need to distinguish between static and non-static address-taken functions even if they're both defined in a compartment .c because in the non-static case the call gate's target function may also be called directly from another compartment. When that happens the -Wl,--wrap=some_function we pass for the direct call changes the function that the indirect call gate references. To fix this I need to explicitly use __real_some_function in the indirect call gates.

@ayrtonm
Copy link
Contributor Author

ayrtonm commented Oct 28, 2024

I also needed to distinguish between call gates for non-static address-taken functions in the same DSO and those for functions in another DSO. PR needs cleanup and updating comments but it should be working now.

@ayrtonm
Copy link
Contributor Author

ayrtonm commented Oct 28, 2024

TODO: check should_not_modify_file before adding the used attribute and create a map between input and output files in copy_files.

…ource files defining the target

These call gates were originally defined in the call gate .so for simplicity.
Moving them to the source file defining the original address-taken function
simplifies control-flow since it no longer requies cross-DSO calls and makes it
possible to support programs that are intended to be compiled with
-fvisibility=hidden since functions that may have hidden are only referenced by
call gates within the DSO that defines them. Closes #435.
/* Invoke the macro we just defined in the source file defining the target function */
auto filename = fn_decl_pass.fn_definitions[fn_name];
std::ofstream source_file(filename, std::ios::app);
source_file << "IA2_DEFINE_WRAPPER(" << fn_name << ")\n";
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we document how IA2_DEFINE_WRAPPER() and IA2_DEFINE_WRAPPER_* work somewhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The comment was kind of misleading so I clarified it. This is one of those places where we're still trying to figure out what's the best way to interpose call gates as we get feedback from applying it to codebases so I don't think writing excessive documentation for things that may soon be out of date is a good use of our time.

Copy link
Contributor

@kkysen kkysen left a comment

Choose a reason for hiding this comment

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

When I try this on dav1d, I'm able to successfully compile with -fvisibility=hidden again. The DEFINE_WRAPPER(...)s appear to be working. However, at runtime, I'm getting symbol lookup errors for these symbols:

  • dav1d_num_logical_processors
  • dav1d_init_cpu
  • dav1d_get_cpu_flags_x86

These symbols are all marked COLD (__attribute__((cold))), but when I tried removing this, the error persisted. I tried __attribute__((used)), too, which didn't work either. Adding DAV1D_API (__attribute__((visibility ("default")))) did work, but I'm not really sure why this is needed.

@@ -920,6 +922,7 @@ class FnDecl : public RefactoringCallback {
std::set<Function> declared_fns[MAX_PKEYS];
std::map<Function, AbiSignature> abi_signatures;
std::map<Function, Pkey> fn_pkeys;
std::map<Function, Filename> fn_definitions;
Copy link
Contributor

Choose a reason for hiding this comment

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

Is fn_definitions supposed to be sorted?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it shouldn't need to be

* define one call gate for each so we need to track them in case a function
* has its address taken in multiple places
*/
std::set<Function> generated_wrappers = {};
Copy link
Contributor

Choose a reason for hiding this comment

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

Same for generated_wrappers; it doesn't need to be sorted, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it shouldn't need to be

@ayrtonm ayrtonm merged commit 5d20517 into main Nov 12, 2024
34 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants