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

SPI and FPVA fixes #25

Merged
merged 13 commits into from
Mar 23, 2022
Merged

SPI and FPVA fixes #25

merged 13 commits into from
Mar 23, 2022

Conversation

Ethane98
Copy link
Contributor

@Ethane98 Ethane98 commented Feb 21, 2022

Merge in various bug fixes and improvements to SPI and the FPVA plugin from forked repo.

Addresses issues #9 #23 #21

Copy link

@kupsch kupsch left a comment

Choose a reason for hiding this comment

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

The debug macro changes could be made after merging this

char** syms = backtrace_symbols(buffer, num);
for (int i = 0; i < num; i++) {
sp_debug("%lx - %s", *(unsigned long*)buffer[i], syms[i]);
sp_debug("agent", "%lx - %s", *(unsigned long*)buffer[i], syms[i]);
Copy link

Choose a reason for hiding this comment

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

use %p instead of %lx and cast to (unsigned long*)

size += 20; // the worse case, we emulate pc insn
}
}
sp_debug("EST SIZE - %lu", (unsigned long)size);
Copy link

Choose a reason for hiding this comment

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

use %zu instead of %lu and the cast to (unsigned long)

name.c_str(), obj->name().c_str());

if ((strcmp(name.c_str(), "recv") != 0) && (strcmp(name.c_str(), "read") != 0) && obj->name().find("libc-") != std::string::npos &&
if ((strcmp(name.c_str(), "recv") != 0) && (strcmp(name.c_str(), "read") != 0) && obj->name().find("libc-") != std::string::npos &&
Copy link

Choose a reason for hiding this comment

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

fix indentation

// Find function by name.
// Find function by mangled name.
bool
SpParser::FindFunctionByMangledName(string name, FuncSet* found_funcs) {
Copy link

Choose a reason for hiding this comment

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

pass found_funcs by reference (or return it w/o passing as a parameter) as the value should not be null.

@@ -70,7 +68,9 @@ namespace sp {
sb::Symtab* symtab)
: ph::PatchObject(o, a, cm, cb),
load_addr_(la),
symtab_(symtab) {}
symtab_(symtab),
small_freebufs_ {} {}
Copy link

Choose a reason for hiding this comment

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

use default initialization for small_freebufs_ and remove from constructor initializer list.
place function body on its own line.

//cur_func = g_parser->FindFunction(func->GetMangledName());
g_parser->FindFunctionByMangledName(func->GetMangledName(), &found_funcs);

for (FuncSet::iterator i = found_funcs.begin(); i != found_funcs.end(); i++) {
Copy link

Choose a reason for hiding this comment

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

In a future revision switch for loops on containers to range-based for loops for (auto i: found_funcs) {. Simpler and less error prone.

g_parser->FindFunctionByMangledName(func->GetMangledName(), &found_funcs);

for (FuncSet::iterator i = found_funcs.begin(); i != found_funcs.end(); i++) {
if (strcmp(FUNC_CAST(*i)->GetObject()->name().c_str(), func->GetObject()->name().c_str()) == 0)
Copy link

Choose a reason for hiding this comment

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

Compare using operator == directly on the strings. It is faster and easier to understand.

Comment on lines 89 to 95
if ((strcmp(debug_type, "injector") == 0 && getenv("SP_DEBUG_INJECTOR")) || \
(strcmp(debug_type, "common") == 0 && getenv("SP_DEBUG_COMMON")) || \
(strcmp(debug_type, "patchapi") == 0 && getenv("SP_DEBUG_PATCHAPI")) || \
(strcmp(debug_type, "ipc") == 0 && getenv("SP_DEBUG_IPC")) || \
(strcmp(debug_type, "worker") == 0 && getenv("SP_DEBUG_WORKER")) || \
(strcmp(debug_type, "sigtrap") == 0 && getenv("SP_DEBUG_SIGTRAP")) || \
(strcmp(debug_type, "agent") == 0 && getenv("SP_DEBUG_AGENT"))) { \
Copy link

Choose a reason for hiding this comment

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

This is very inefficient in time and code size for something that get expanded and called a lot. strcmp and getenv are not fast functions and strcmp would be call 1-7 times and getenv once for each sp_debug. Change this at make an enum value for each debug_type enum DebugType {injectorDebug, commonDebug, ..., unknownDebug, numDebugTypes}, then make an array of of bool debugTypeEnabled[numDebugTypes] (initialized once using getenv), char *debugTypeToEnvVar[numDebugTypes], char *debugTypeToName[numDebugTypes]. Now the macro body's definition becomes

do {
if (debugType >= numDebugTypes)  {
    /* call a function that logs the provided out of range debugType? */
    debugType = unknownDebugType;
}
if (debugTypeEnabled[debugType]) {
        char* nodir = basename((char*)__FILE__);
          fprintf(g_debug_fp, "%s [%d]: ", nodir, __LINE__);
          fprintf(g_debug_fp, __VA_ARGS__);
          fprintf(g_debug_fp, "\n");
          fflush(g_debug_fp);
}
} while (0)

Then I would make a macro for each of the debug types

#define sp_debug_injector(...) sp_debug(injectorDebug, __VA_ARGS__)
#define sp_debug_common(...) sp_debug(commonDebug, __VA_ARGS__)
...

Comment on lines 96 to 110
if (getenv("SP_DEBUG")) { \
char* nodir = basename((char*)__FILE__); \
fprintf(stderr, "%s [%d]: ", nodir, __LINE__); \
fprintf(stderr, __VA_ARGS__); \
fprintf(stderr, "\n"); \
fflush(stderr); \
} \
else if (getenv("SP_FDEBUG")) { \
char* nodir = basename((char*)__FILE__); \
fprintf(g_debug_fp, "%s [%d]: ", nodir, __LINE__); \
fprintf(g_debug_fp, __VA_ARGS__); \
fprintf(g_debug_fp, "\n"); \
fflush(g_debug_fp); \
}\
} \
Copy link

Choose a reason for hiding this comment

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

set g_debug_fp to stderr if SP_DEBUG environment variable is set, or FILE* returned by fopen if SP_FDEBUG is environment variable is set. Only set debugTypeEnabled values is either is set, and only fclose file is g_debug_fp is not nullptr or stderr.

std::string
GetExeObjName() {
std::string path = GetExeName();
return path.substr(path.find_last_of("//") + 1);
Copy link

Choose a reason for hiding this comment

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

"/" instead of "//"

Copy link

@kupsch kupsch left a comment

Choose a reason for hiding this comment

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

There a couple of comments that you should look at. After fixing those that are problems I approve.

Also you could consider replacing getenv("X") with a function getenv_bool("X") that returned a bool. This function then uniformly decides on the truth. Just calling and returning getenv would define truth as the environment variable being defined (as it is currently), but you could also define it as not (undefined v || v is "" || v is "0" || v is "false") which might be less error prone for users.

@@ -67,7 +69,7 @@ namespace sp {
core_limit.rlim_cur = RLIM_INFINITY;
core_limit.rlim_max = RLIM_INFINITY;
if (setrlimit(RLIMIT_CORE, &core_limit) < 0) {
sp_perror("ERROR: failed to setup core dump ability\n");
sp_perror("RROR: failed to setup core dump ability\n");
Copy link

Choose a reason for hiding this comment

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

spelling

if (debugType >= numDebugTypes) { \
debugType = unknownDebugType; \
} \
if (debugTypeEnabled[debugType]) { \
if (getenv("SP_DEBUG")) { \
Copy link

Choose a reason for hiding this comment

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

Put the output FILE in a variable and use it. Then the two branches are identical. The output FILE variable can then be computed once eliminating the getenv on every sp_debug.

name.c_str());


FuncSet* found_funcs = new FuncSet();
Copy link

Choose a reason for hiding this comment

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

This is a memory leak. Nothing every frees this memory. Change to FuncSet found_funcs; and return found_funcs;.

@Ethane98 Ethane98 merged commit ffe7370 into dyninst:master Mar 23, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants