errval_t get_architecture_config(enum cpu_type type, genpaddr_t *arch_page_size, const char **monitor_binary, const char **cpu_binary) { extern char* cmd_kernel_binary; extern char* cmd_monitor_binary; switch (type) { case CPU_X86_64: { *arch_page_size = X86_64_BASE_PAGE_SIZE; *monitor_binary = (cmd_kernel_binary == NULL) ? "/" BF_BINARY_PREFIX "x86_64/sbin/monitor" : get_binary_path("/" BF_BINARY_PREFIX "x86_64/sbin/%s", cmd_monitor_binary); *cpu_binary = (cmd_kernel_binary == NULL) ? "/" BF_BINARY_PREFIX "x86_64/sbin/cpu" : get_binary_path("/" BF_BINARY_PREFIX "x86_64/sbin/%s", cmd_kernel_binary); } break; case CPU_X86_32: { *arch_page_size = X86_32_BASE_PAGE_SIZE; *monitor_binary = (cmd_kernel_binary == NULL) ? "/" BF_BINARY_PREFIX "x86_32/sbin/monitor" : get_binary_path("/" BF_BINARY_PREFIX "x86_32/sbin/%s", cmd_monitor_binary); *cpu_binary = (cmd_kernel_binary == NULL) ? "/" BF_BINARY_PREFIX "x86_32/sbin/cpu" : get_binary_path("/" BF_BINARY_PREFIX "x86_32/sbin/%s", cmd_kernel_binary); } break; case CPU_K1OM: { *arch_page_size = X86_64_BASE_PAGE_SIZE; *monitor_binary = (cmd_kernel_binary == NULL) ? "/" BF_BINARY_PREFIX "k1om/sbin/monitor" : get_binary_path("/" BF_BINARY_PREFIX "k1om/sbin/%s", cmd_monitor_binary); *cpu_binary = (cmd_kernel_binary == NULL) ? "/" BF_BINARY_PREFIX "k1om/sbin/cpu" : get_binary_path("/" BF_BINARY_PREFIX "k1om/sbin/%s", cmd_kernel_binary); } break; default: return SPAWN_ERR_UNKNOWN_TARGET_ARCH; } return SYS_ERR_OK; }
//FIXME: This code could be greatly improved/simplifyied with // http://cairo.sourcearchive.com/documentation/1.9.4/backtrace-symbols_8c-source.html std::vector<std::string> resolveBacktrace( xbt_backtrace_location_t const* loc, std::size_t count) { std::vector<std::string> result; if (count == 0) return result; if (xbt_binary_name == nullptr) XBT_WARN("XBT not initialized, the backtrace will not be resolved."); // Drop the first one: loc++; count--; char** backtrace_syms = backtrace_symbols(loc, count); std::string binary_name = get_binary_path(); if (binary_name.empty()) { for (std::size_t i = 0; i < count; i++) result.push_back(simgrid::xbt::string_printf("%p", loc[i])); return std::move(result); } // Create the system command for add2line: std::ostringstream stream; stream << ADDR2LINE << " -f -e " << binary_name << ' '; std::vector<std::string> addrs(count); for (std::size_t i = 0; i < count; i++) { /* retrieve this address */ XBT_DEBUG("Retrieving address number %zd from '%s'", i, backtrace_syms[i]); char buff[256]; snprintf(buff, 256, "%s", strchr(backtrace_syms[i], '[') + 1); char* p = strchr(buff, ']'); *p = '\0'; if (strcmp(buff, "(nil)")) addrs[i] = buff; else addrs[i] = "0x0"; XBT_DEBUG("Set up a new address: %zd, '%s'", i, addrs[i].c_str()); /* Add it to the command line args */ stream << addrs[i] << ' '; } std::string cmd = stream.str(); /* size (in char) of pointers on this arch */ int addr_len = addrs[0].size(); XBT_VERB("Fire a first command: '%s'", cmd.c_str()); FILE* pipe = popen(cmd.c_str(), "r"); if (!pipe) { xbt_die("Cannot fork addr2line to display the backtrace"); } /* To read the output of addr2line */ char line_func[1024], line_pos[1024]; for (std::size_t i = 0; i < count; i++) { XBT_DEBUG("Looking for symbol %zd, addr = '%s'", i, addrs[i].c_str()); if (fgets(line_func, 1024, pipe)) { line_func[strlen(line_func) - 1] = '\0'; } else { XBT_VERB("Cannot run fgets to look for symbol %zd, addr %s", i, addrs[i].c_str()); strncpy(line_func, "???",3); } if (fgets(line_pos, 1024, pipe)) { line_pos[strlen(line_pos) - 1] = '\0'; } else { XBT_VERB("Cannot run fgets to look for symbol %zd, addr %s", i, addrs[i].c_str()); strncpy(line_pos, backtrace_syms[i],1024); } if (strcmp("??", line_func) != 0) { auto name = simgrid::xbt::demangle(line_func); XBT_DEBUG("Found static symbol %s at %s", name.get(), line_pos); result.push_back(simgrid::xbt::string_printf( "%s at %s, %p", name.get(), line_pos, loc[i] )); } else { /* Damn. The symbol is in a dynamic library. Let's get wild */ char maps_buff[512]; long int offset = 0; char *p, *p2; int found = 0; /* let's look for the offset of this library in our addressing space */ char* maps_name = bprintf("/proc/%d/maps", (int) getpid()); FILE* maps = fopen(maps_name, "r"); long int addr = strtol(addrs[i].c_str(), &p, 16); if (*p != '\0') { XBT_CRITICAL("Cannot parse backtrace address '%s' (addr=%#lx)", addrs[i].c_str(), addr); } XBT_DEBUG("addr=%s (as string) =%#lx (as number)", addrs[i].c_str(), addr); while (!found) { long int first, last; if (fgets(maps_buff, 512, maps) == nullptr) break; if (i == 0) { maps_buff[strlen(maps_buff) - 1] = '\0'; XBT_DEBUG("map line: %s", maps_buff); } sscanf(maps_buff, "%lx", &first); p = strchr(maps_buff, '-') + 1; sscanf(p, "%lx", &last); if (first < addr && addr < last) { offset = first; found = 1; } if (found) { XBT_DEBUG("%#lx in [%#lx-%#lx]", addr, first, last); XBT_DEBUG("Symbol found, map lines not further displayed (even if looking for next ones)"); } } fclose(maps); free(maps_name); addrs[i].clear(); if (!found) { XBT_VERB("Problem while reading the maps file. Following backtrace will be mangled."); XBT_DEBUG("No dynamic. Static symbol: %s", backtrace_syms[i]); result.push_back(simgrid::xbt::string_printf("?? (%s)", backtrace_syms[i])); continue; } /* Ok, Found the offset of the maps line containing the searched symbol. We now need to substract this from the address we got from backtrace. */ addrs[i] = simgrid::xbt::string_printf("0x%0*lx", addr_len - 2, addr - offset); XBT_DEBUG("offset=%#lx new addr=%s", offset, addrs[i].c_str()); /* Got it. We have our new address. Let's get the library path and we are set */ p = xbt_strdup(backtrace_syms[i]); if (p[0] == '[') { /* library path not displayed in the map file either... */ free(p); snprintf(line_func,3, "??"); } else { p2 = strrchr(p, '('); if (p2) *p2 = '\0'; p2 = strrchr(p, ' '); if (p2) *p2 = '\0'; /* Here we go, fire an addr2line up */ char* subcmd = bprintf("%s -f -e %s %s", ADDR2LINE, p, addrs[i].c_str()); free(p); XBT_VERB("Fire a new command: '%s'", subcmd); FILE* subpipe = popen(subcmd, "r"); if (!subpipe) { xbt_die("Cannot fork addr2line to display the backtrace"); } if (fgets(line_func, 1024, subpipe)) { line_func[strlen(line_func) - 1] = '\0'; } else { XBT_VERB("Cannot read result of subcommand %s", subcmd); strncpy(line_func, "???",3); } if (fgets(line_pos, 1024, subpipe)) { line_pos[strlen(line_pos) - 1] = '\0'; } else { XBT_VERB("Cannot read result of subcommand %s", subcmd); strncpy(line_pos, backtrace_syms[i],1024); } pclose(subpipe); free(subcmd); } /* check whether the trick worked */ if (strcmp("??", line_func)) { auto name = simgrid::xbt::demangle(line_func); XBT_DEBUG("Found dynamic symbol %s at %s", name.get(), line_pos); result.push_back(simgrid::xbt::string_printf( "%s at %s, %p", name.get(), line_pos, loc[i])); } else { /* damn, nothing to do here. Let's print the raw address */ XBT_DEBUG("Dynamic symbol not found. Raw address = %s", backtrace_syms[i]); result.push_back(simgrid::xbt::string_printf( "?? at %s", backtrace_syms[i])); } } addrs[i].clear(); /* Mask the bottom of the stack */ if (!strncmp("main", line_func, strlen("main")) || !strncmp("xbt_thread_context_wrapper", line_func, strlen("xbt_thread_context_wrapper")) || !strncmp("smx_ctx_sysv_wrapper", line_func, strlen("smx_ctx_sysv_wrapper"))) break; } pclose(pipe); free(backtrace_syms); return result; }