Skip to content
This repository was archived by the owner on Feb 3, 2020. It is now read-only.

ExternalDispatcher: add handlers for external functions - #18

Open
cinemamoon5 wants to merge 1 commit into
S2E:masterfrom
cinemamoon5:analyze-libexif
Open

ExternalDispatcher: add handlers for external functions#18
cinemamoon5 wants to merge 1 commit into
S2E:masterfrom
cinemamoon5:analyze-libexif

Conversation

@cinemamoon5

Copy link
Copy Markdown

A response to issue "S2E/s2e-env#346" I reported before "https://groups.google.com/forum/#!topic/s2e-dev/CccWw4cPQK4"

This is a very simple fix in ExternalDispathcer::resolveSymbol function that finds external function using dlsym function.
Please let me know if it needs some changes.

@claassistantio

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission, we really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


Moon seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

if(!addr) {
addr = dlsym(RTLD_DEFAULT, str);
if(addr) {
llvm::sys::DynamicLibrary::AddSymbol(str, addr);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This should work for symbol resolution. You may also need to extend function invocation to handle functions that take or return floating point data (float/double/long double). These may be passed in FP registers and the current implementation does not support that.

@cinemamoon5 cinemamoon5 Dec 13, 2019

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I think I need to implement several function prototypes like "external_func_t" to deal with functions returning/taking floating point data. I guess I can get function return/parameter types from llvm::Function class.
Is it a efficient/right approach to this?

And... is the original KLEE supporting external functions with floating point data? They generate stubs before calling external functions. Probably, the stub enables KLEE to support external functions with floating point data.

Thank you.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yeah, they generated stubs, but that's very expensive to do, it was showing on the profile and I removed them.
The KLEE version in S2E is very specialized, it does not need to handle all types of functions and can only restrict itself to those used by helpers. Therefore, you can hard-code all these external functions, e.g,:
switch (functionName) {
case "log": return logl(..);
case "sin": ...
}

See the issue description to get a complete list of these functions.
It's important to have a whitelist though, that helps catching ones we don't support and that may have a weird calling convention.

@vitalych vitalych left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

.

 - handlers for functions with floating point data
@cinemamoon5

Copy link
Copy Markdown
Author

Could you review my modification again?

@vitalych

Copy link
Copy Markdown
Member

Sure, did you get a chance to sign the CLA? I won't be able to merge your fixes without it.

return false;
bool ExternalDispatcher::call(const std::string& targetName, void *targetAddr, const Arguments &args, uint64_t *result,
std::stringstream &err) {
if (targetName == "exp2" || targetName == "log" || targetName == "tan" ||

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

A dictionary of name => function pointer would be more efficient

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Or perhaps look at the argument types instead:
if (retType == double && paramCount==1 && param[0] == double) {
...
}

virtual bool call(external_fcn_t targetFunction, const Arguments &args, uint64_t *result, std::stringstream &err);
virtual bool call(const std::string& targetName, void* targetAddr, const Arguments &args, uint64_t *result, std::stringstream &err);

uint64_t double_to_rawbits(double value);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

These look like utility functions. They don't need to be inside a class.


virtual void *resolveSymbol(const std::string &name);
virtual bool call(external_fcn_t targetFunction, const Arguments &args, uint64_t *result, std::stringstream &err);
virtual bool call(const std::string& targetName, void* targetAddr, const Arguments &args, uint64_t *result, std::stringstream &err);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please run clang-format.

std::stringstream &err) {
if (targetName == "exp2" || targetName == "log" || targetName == "tan" ||
targetName == "rint" || targetName == "fabs" || targetName == "floor" ||
targetName == "ceil" || targetName == "sin" || targetName == "cos") { // double func(double)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could you assert that the LLVM function prototype actually takes double and not floats? AFAIK, you can have cos(double), cos(float), etc.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Actually, if you use if (retType == double && paramCount==1 && param[0] == double) {..., it is not necessary.


uint64_t ExternalDispatcher::double_to_rawbits(double value) {
uint64_t bits = 0;
memcpy(&bits, &value, 8);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Use sizeof(bits) instead of 8.

@vitalych

vitalych commented Jan 6, 2020

Copy link
Copy Markdown
Member

@cinemamoon5 any progress on this?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants