diff options
Diffstat (limited to 'llvm_mode/afl-ld.c')
-rw-r--r-- | llvm_mode/afl-ld.c | 68 |
1 files changed, 58 insertions, 10 deletions
diff --git a/llvm_mode/afl-ld.c b/llvm_mode/afl-ld.c index cdecaa9c..7cbf89dc 100644 --- a/llvm_mode/afl-ld.c +++ b/llvm_mode/afl-ld.c @@ -59,6 +59,8 @@ static u8 cwd[4096]; static u8* tmp_dir; static u8* ar_dir; static u8 ar_dir_cnt; +static u8* libdirs[254]; +static u8 libdir_cnt; static u8 be_quiet, /* Quiet mode (no stderr output) */ debug, /* AFL_DEBUG */ @@ -183,7 +185,8 @@ int is_duplicate(u8** params, u32 ld_param_cnt, u8* ar_file) { so we exploit this property to keep the code "simple". */ static void edit_params(int argc, char** argv) { - u32 i, have_lto = 0; + u32 i, have_lto = 0, libdir_index; + u8 libdir_file[4096]; if (tmp_dir == NULL) { @@ -201,8 +204,8 @@ static void edit_params(int argc, char** argv) { final_file = alloc_printf("%s/.afl-%u-%u-3.bc", tmp_dir, getpid(), (u32)time(NULL)); - ld_params = ck_alloc((argc + 128) * sizeof(u8*)); - link_params = ck_alloc((argc + 256) * sizeof(u8*)); + ld_params = ck_alloc((argc + 4096) * sizeof(u8*)); + link_params = ck_alloc((argc + 4096) * sizeof(u8*)); inst_params = ck_alloc(12 * sizeof(u8*)); opt_params = ck_alloc(12 * sizeof(u8*)); @@ -237,6 +240,12 @@ static void edit_params(int argc, char** argv) { inst_params[inst_param_cnt++] = "-o"; inst_params[inst_param_cnt++] = final_file; // output: .bc file + // first we must collect all library search paths + for (i = 1; i < argc; i++) + if (strlen(argv[i]) > 2 && argv[i][0] == '-' && argv[i][1] == 'L') + libdirs[libdir_cnt++] = argv[i] + 2; + + // then we inspect all options to the target linker for (i = 1; i < argc; i++) { if (strncmp(argv[i], "-flto", 5) == 0) have_lto = 1; @@ -257,11 +266,44 @@ static void edit_params(int argc, char** argv) { exit(0); } + + // if a -l library is linked and no .so is found but an .a archive is there + // then the archive will be used. So we have to emulate this and check + // if an archive will be used and if yes we will instrument it too + libdir_file[0] = 0; + libdir_index = libdir_cnt; + if (strncmp(argv[i], "-l", 2) == 0 && libdir_cnt > 0 && strncmp(argv[i], "-lgcc", 5) != 0) { + + u8 found = 0; + + for (uint32_t j = 0; j < libdir_cnt && !found; j++) { + + snprintf(libdir_file, sizeof(libdir_file), "%s/lib%s%s", libdirs[j], argv[i] + 2, ".so"); + if (access(libdir_file, R_OK) != 0) { // no .so found? + + snprintf(libdir_file, sizeof(libdir_file), "%s/lib%s%s", libdirs[j], argv[i] + 2, ".a"); + if (access(libdir_file, R_OK) == 0) { // but .a found? + + libdir_index = j; + found = 1; + if (debug) SAYF(cMGN "[D] " cRST "Found %s\n", libdir_file); + + } + + } else { + + found = 1; + if (debug) SAYF(cMGN "[D] " cRST "Found %s\n", libdir_file); + + } + + } + + } // is the parameter an .a AR archive? If so, unpack and check its files - if (argv[i][0] != '-' && strlen(argv[i]) > 2 && - argv[i][strlen(argv[i]) - 1] == 'a' && - argv[i][strlen(argv[i]) - 2] == '.') { + if (libdir_index < libdir_cnt || (argv[i][0] != '-' && strlen(argv[i]) > 2 && + argv[i][strlen(argv[i]) - 1] == 'a' && argv[i][strlen(argv[i]) - 2] == '.')) { // This gets a bit odd. I encountered several .a files being linked and // where the same "foo.o" was in both .a archives. llvm-link does not @@ -270,10 +312,14 @@ static void edit_params(int argc, char** argv) { u8 this_wd[4096], *this_ar; u8 ar_params_cnt = 4; u8* ar_params[ar_params_cnt]; + u8* file = argv[i]; s32 pid, status; DIR* arx; struct dirent* dir_ent; + if (libdir_index < libdir_cnt) + file = libdir_file; + if (ar_dir_cnt == 0) { // first archive, we setup up the basics ar_dir = alloc_printf("%s/.afl-%u-%u.dir", tmp_dir, getpid(), @@ -287,10 +333,10 @@ static void edit_params(int argc, char** argv) { FATAL("can not get the current working directory"); if (chdir(ar_dir) != 0) FATAL("can not chdir to temporary directory %s", ar_dir); - if (argv[i][0] == '/') - this_ar = argv[i]; + if (file[0] == '/') + this_ar = file; else - this_ar = alloc_printf("%s/%s", this_wd, argv[i]); + this_ar = alloc_printf("%s/%s", this_wd, file); ar_params[0] = alloc_printf("%s/%s", LLVM_BINDIR, "llvm-ar"); ar_params[1] = "x"; ar_params[2] = this_ar; @@ -382,7 +428,7 @@ static void edit_params(int argc, char** argv) { ld_params[ld_param_cnt++] = "-plugin-opt=O2"; else ld_params[ld_param_cnt++] = argv[i]; - + } else { if (we_link == 0) { // we have to honor order ... @@ -572,6 +618,8 @@ int main(int argc, char** argv) { edit_params(argc, argv); // here most of the magic happens :-) + if (debug) SAYF(cMGN "[D] " cRST "param counts: ar:%u lib:%u ld:%u link:%u opt:%u instr:%u\n", ar_dir_cnt, libdir_cnt, ld_param_cnt, link_param_cnt, opt_param_cnt, inst_param_cnt); + if (!just_version) { if (we_link == 0) { |