This is an archive of the discontinued LLVM Phabricator instance.

appendToGlobalCtors: allow for llvm.global_ctors functions of varying type
Needs ReviewPublic

Authored by aeden on Jul 18 2019, 4:51 PM.

Details

Summary

When calling global constructor functions, the dynamic linker may pass arguments without breaking the ABI, such as (argc, argv, envp) in the case of glibc.

The utility function llvm::appendToGlobalCtors accepts a pointer to an llvm::Function, but if it is not of the type FunctionType::get(IRB.getVoidTy(), false), then the resulting LLVM IR will be invalid, possibly leading to a "LLVM constant table mismatch" error in the future.

Diff Detail

Event Timeline

aeden created this revision.Jul 18 2019, 4:51 PM
Herald added a project: Restricted Project. · View Herald TranscriptJul 18 2019, 4:51 PM

Can we test this?

aeden added a comment.Oct 9 2019, 6:25 PM

In the meantime I've "worked around this" by casting my ConstantExpr * into a Function * and passing it off as one when calling appendToGlobalCtors. This happens to work only because the pointer is only ever used as a Constant * (possible Q: Why should appendToGlobalCtors take a Function * in the first place?)

rnk added a comment.Oct 14 2019, 2:19 PM

Q: Why should appendToGlobalCtors take a Function * in the first place?

Probably just type safety for the existing clients. Clang doesn't actually use this utility anyway. It probably builds the array in bulk rather than repeatedly appending to the initializer.

Relaxing it to Constant and asserting that it has the right type (pointer to void function) seems reasonable. I would prefer that the caller be the one to insert the cast from the void(int, char**, char**) prototype to the void prototype, since only the caller can know that it is safe.

And it would need a test to proceed. A unit test would be best.

lib/Transforms/Utils/ModuleUtils.cpp
45

This is probably not quite right, it should probably be a pointer to function type.

aeden added a comment.Mar 10 2020, 9:26 AM

Relaxing it to Constant and asserting that it has the right type (pointer to void function) seems reasonable. I would prefer that the caller be the one to insert the cast from the void(int, char**, char**) prototype to the void prototype, since only the caller can know that it is safe.

Okay, sure.

And it would need a test to proceed. A unit test would be best.

I've been really busy recently and haven't had a chance to do this. Sorry!

dexonsmith resigned from this revision.Oct 16 2020, 12:33 PM