struct ld_procmaps *ld_load_maps(pid_t pid, int verbose, size_t *num) { char filename[OS_MAX_BUFFER]; char appname[OS_MAX_BUFFER]; FILE *ff = NULL; const size_t bufsz = 4096; char *buf = NULL; size_t mapmax = 0; size_t mapnum = 0; struct ld_procmaps *maps = NULL; if (pid == 0) { LOG_ERROR_INVALID_PID(pid); return NULL; } snprintf(filename, OS_MAX_BUFFER, "/proc/%d/maps", pid); snprintf(appname, OS_MAX_BUFFER, "/proc/%d/exe", pid); if (verbose > 2) { fprintf(stderr, "[%s:%d] Using Proc Maps from %s\n", __func__, __LINE__, filename); fprintf(stderr, "[%s:%d] Using Proc Exe from %s\n", __func__, __LINE__, appname); } do { buf = calloc(sizeof(char), bufsz); if (!buf) { LOG_ERROR_OUT_OF_MEMORY; break; } ff = fopen(filename, "r"); if (!ff) { LOG_ERROR_FILE_OPEN(filename); break; } while (fgets(buf, bufsz, ff)) mapmax++; if (verbose > 0) fprintf(stderr, "[%s:%d] Max number of mappings present: "LU"\n", __func__, __LINE__, mapmax); fseek(ff, 0L, SEEK_SET); maps = calloc(sizeof(*maps), mapmax); if (!maps) { LOG_ERROR_OUT_OF_MEMORY; break; } if (verbose > 1) fprintf(stderr, "[%s:%d] Allocated memory to load proc maps.\n", __func__, __LINE__); memset(buf, 0, bufsz); mapnum = 0; while (fgets(buf, bufsz, ff)) { struct ld_procmaps *pm = &maps[mapnum]; if (verbose > 3) fprintf(stderr, "[%s:%d] Parsing %s\n", __func__, __LINE__, buf); if (ld_procmaps_parse(buf, bufsz, pm, appname, verbose) < 0) { if (verbose > 1) { fprintf(stderr, "[%s:%d] Parsing failure. Ignoring.\n", __func__, __LINE__); } continue; } if (verbose > 4) ld_procmaps_dump(pm); mapnum++; } if (num) *num = mapnum; else if (verbose > 3) fprintf(stderr, "[%s:%d] Cannot return size of maps object.\n", __func__, __LINE__); } while (0); if (buf) free(buf); if (ff) fclose(ff); return maps; }
hotpatch_t *hotpatch_create(pid_t pid, int verbose) { int rc = 0; hotpatch_t *hp = NULL; do { char filename[OS_MAX_BUFFER]; if (pid <= 0) { LOG_ERROR_INVALID_PID(pid); break; } memset(filename, 0, sizeof(filename)); snprintf(filename, sizeof(filename), "/proc/%d/exe", pid); if (verbose > 3) fprintf(stderr, "[%s:%d] Exe symlink for pid %d : %s\n", __func__, __LINE__, pid, filename); hp = malloc(sizeof(*hp)); if (!hp) { LOG_ERROR_OUT_OF_MEMORY; rc = -1; break; } memset(hp, 0, sizeof(*hp)); hp->verbose = verbose; hp->pid = pid; hp->is64 = HOTPATCH_EXE_IS_NEITHER; hp->exe_symbols = exe_load_symbols(filename, hp->verbose, &hp->exe_symbols_num, &hp->exe_entry_point, &hp->exe_interp, &hp->is64); if (!hp->exe_symbols) { fprintf(stderr, "[%s:%d] Unable to find any symbols in exe.\n", __func__, __LINE__); rc = -1; break; } if (hp->exe_entry_point == 0) { fprintf(stderr, "[%s:%d] Entry point is 0. Invalid.\n", __func__, __LINE__); rc = -1; break; } LOG_INFO_HEADERS_LOADED(verbose); hp->ld_maps = ld_load_maps(hp->pid, hp->verbose, &hp->ld_maps_num); if (!hp->ld_maps) { fprintf(stderr, "[%s:%d] Unable to load data in " "/proc/%d/maps.\n", __func__, __LINE__, pid); rc = -1; break; } if (verbose > 2) fprintf(stderr, "[%s:%d] /proc/%d/maps loaded.\n", __func__, __LINE__, pid); if (hp->exe_symbols && hp->exe_symbols_num > 0) { qsort(hp->exe_symbols, hp->exe_symbols_num, sizeof(*hp->exe_symbols), elf_symbol_cmpqsort); } if (hotpatch_gather_functions(hp) < 0) { fprintf(stderr, "[%s:%d] Unable to find all the functions" " needed. Cannot proceed.\n", __func__, __LINE__); rc = -1; break; } if (rc < 0) { hotpatch_destroy(hp); hp = NULL; } } while (0); return hp; }