00001
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 #include "config.h"
00054 #include <stdio.h>
00055 #include <errno.h>
00056 #include <string.h>
00057 #include <stdint.h>
00058 #include <limits.h>
00059 #include <sys/types.h>
00060 #include <sys/stat.h>
00061 #include <fcntl.h>
00062 #include <unistd.h>
00063 #include <time.h>
00064 #include <bfd.h>
00065
00066 #include "opagent.h"
00067 #include "op_config.h"
00068 #include "jitdump.h"
00069
00070
00071 static char * _bfd_target_name;
00072 static int _bfd_arch;
00073 static unsigned int _bfd_mach;
00074
00075
00076 static int define_bfd_vars(void)
00077 {
00078 bfd * bfd;
00079 bfd_boolean r;
00080 int len;
00081 #define MAX_PATHLENGTH 2048
00082 char mypath[MAX_PATHLENGTH];
00083
00084 len = readlink("/proc/self/exe", mypath, sizeof(mypath));
00085
00086 if (len < 0) {
00087 fprintf(stderr, "libopagent: readlink /proc/self/exe failed\n");
00088 return -1;
00089 }
00090 if (len >= MAX_PATHLENGTH) {
00091 fprintf(stderr, "libopagent: readlink /proc/self/exe returned"
00092 " path length longer than %d.\n", MAX_PATHLENGTH);
00093
00094 return -1;
00095 }
00096 mypath[len] = '\0';
00097
00098 bfd_init();
00099 bfd = bfd_openr(mypath, NULL);
00100 if (bfd == NULL) {
00101 bfd_perror("bfd_openr error. Cannot get required BFD info");
00102 return -1;
00103 }
00104 r = bfd_check_format(bfd, bfd_object);
00105 if (!r) {
00106 bfd_perror("bfd_get_arch error. Cannot get required BFD info");
00107 return -1;
00108 }
00109 _bfd_target_name = bfd->xvec->name;
00110 _bfd_arch = bfd_get_arch(bfd);
00111 _bfd_mach = bfd_get_mach(bfd);
00112
00113 return 0;
00114 }
00118 #define OP_MAJOR_VERSION 1
00119 #define OP_MINOR_VERSION 0
00120
00121 #define AGENT_DIR OP_SESSION_DIR_DEFAULT "jitdump"
00122
00123 #define MSG_MAXLEN 20
00124
00125 op_agent_t op_open_agent(void)
00126 {
00127 char pad_bytes[7] = {0, 0, 0, 0, 0, 0, 0};
00128 int pad_cnt;
00129 char dump_path[PATH_MAX];
00130 char err_msg[PATH_MAX + 16];
00131 struct stat dirstat;
00132 int rc;
00133 struct jitheader header;
00134 int fd;
00135 struct timeval tv;
00136 FILE * dumpfile = NULL;
00137
00138 rc = stat(AGENT_DIR, &dirstat);
00139 if (rc || !S_ISDIR(dirstat.st_mode)) {
00140 if (!rc)
00141 errno = ENOTDIR;
00142 fprintf(stderr,"libopagent: Jitdump agent directory %s "
00143 "missing\n", AGENT_DIR);
00144 fprintf(stderr,"libopagent: do opcontrol --setup or "
00145 "opcontrol --reset, first\n");
00146 return NULL;
00147 }
00148 snprintf(dump_path, PATH_MAX, "%s/%i.dump", AGENT_DIR, getpid());
00149 snprintf(err_msg, PATH_MAX + 16, "Error opening %s\n", dump_path);
00150
00151 fd = creat(dump_path, S_IRUSR|S_IWUSR);
00152 if (fd == -1) {
00153 fprintf(stderr, "%s\n", err_msg);
00154 return NULL;
00155 }
00156 dumpfile = fdopen(fd, "w");
00157 if (!dumpfile) {
00158 fprintf(stderr, "%s\n", err_msg);
00159 return NULL;
00160 }
00161 if (define_bfd_vars())
00162 return NULL;
00163 header.magic = JITHEADER_MAGIC;
00164 header.version = JITHEADER_VERSION;
00165 header.totalsize = sizeof(header) + strlen(_bfd_target_name) + 1;
00166
00167 pad_cnt = PADDING_8ALIGNED(header.totalsize);
00168 header.totalsize += pad_cnt;
00169 header.bfd_arch = _bfd_arch;
00170 header.bfd_mach = _bfd_mach;
00171 if (gettimeofday(&tv, NULL)) {
00172 fprintf(stderr, "gettimeofday failed\n");
00173 return NULL;
00174 }
00175
00176 header.timestamp = tv.tv_sec;
00177 snprintf(err_msg, PATH_MAX + 16, "Error writing to %s", dump_path);
00178 if (!fwrite(&header, sizeof(header), 1, dumpfile)) {
00179 fprintf(stderr, "%s\n", err_msg);
00180 return NULL;
00181 }
00182 if (!fwrite(_bfd_target_name, strlen(_bfd_target_name) + 1, 1,
00183 dumpfile)) {
00184 fprintf(stderr, "%s\n", err_msg);
00185 return NULL;
00186 }
00187
00188 if (pad_cnt && !fwrite(pad_bytes, pad_cnt, 1, dumpfile)) {
00189 fprintf(stderr, "%s\n", err_msg);
00190 return NULL;
00191 }
00192 fflush(dumpfile);
00193 return (op_agent_t)dumpfile;
00194 }
00195
00196
00197 int op_close_agent(op_agent_t hdl)
00198 {
00199 struct jr_code_close rec;
00200 struct timeval tv;
00201 FILE * dumpfile = (FILE *) hdl;
00202 if (!dumpfile) {
00203 errno = EINVAL;
00204 return -1;
00205 }
00206 rec.id = JIT_CODE_CLOSE;
00207 rec.total_size = sizeof(rec);
00208 if (gettimeofday(&tv, NULL)) {
00209 fprintf(stderr, "gettimeofday failed\n");
00210 return -1;
00211 }
00212 rec.timestamp = tv.tv_sec;
00213
00214 if (!fwrite(&rec, sizeof(rec), 1, dumpfile))
00215 return -1;
00216 fclose(dumpfile);
00217 dumpfile = NULL;
00218 return 0;
00219 }
00220
00221
00222 int op_write_native_code(op_agent_t hdl, char const * symbol_name,
00223 uint64_t vma, void const * code, unsigned int const size)
00224 {
00225 struct jr_code_load rec;
00226 struct timeval tv;
00227 size_t sz_symb_name;
00228 char pad_bytes[7] = { 0, 0, 0, 0, 0, 0, 0 };
00229 size_t padding_count;
00230 FILE * dumpfile = (FILE *) hdl;
00231
00232 if (!dumpfile) {
00233 errno = EINVAL;
00234 fprintf(stderr, "Invalid hdl argument\n");
00235 return -1;
00236 }
00237 sz_symb_name = strlen(symbol_name) + 1;
00238
00239 rec.id = JIT_CODE_LOAD;
00240 rec.code_size = size;
00241 rec.vma = vma;
00242 rec.code_addr = (u64) (uintptr_t) code;
00243 rec.total_size = code ? sizeof(rec) + sz_symb_name + size :
00244 sizeof(rec) + sz_symb_name;
00245
00246 padding_count = PADDING_8ALIGNED(rec.total_size);
00247 rec.total_size += padding_count;
00248 if (gettimeofday(&tv, NULL)) {
00249 fprintf(stderr, "gettimeofday failed\n");
00250 return -1;
00251 }
00252
00253 rec.timestamp = tv.tv_sec;
00254
00255
00256
00257 flockfile(dumpfile);
00258
00259
00260
00261 if (fwrite_unlocked(&rec, sizeof(rec), 1, dumpfile) &&
00262 fwrite_unlocked(symbol_name, sz_symb_name, 1, dumpfile)) {
00263 if (code)
00264 fwrite_unlocked(code, size, 1, dumpfile);
00265 if (padding_count)
00266 fwrite_unlocked(pad_bytes, padding_count, 1, dumpfile);
00267
00268
00269 fflush_unlocked(dumpfile);
00270 funlockfile(dumpfile);
00271 return 0;
00272 }
00273 fflush_unlocked(dumpfile);
00274 funlockfile(dumpfile);
00275 return -1;
00276 }
00277
00278
00279 int op_write_debug_line_info(op_agent_t hdl, void const * code,
00280 size_t nr_entry,
00281 struct debug_line_info const * compile_map)
00282 {
00283 struct jr_code_debug_info rec;
00284 long cur_pos, last_pos;
00285 struct timeval tv;
00286 size_t i;
00287 size_t padding_count;
00288 char padd_bytes[7] = {0, 0, 0, 0, 0, 0, 0};
00289 int rc = -1;
00290 FILE * dumpfile = (FILE *) hdl;
00291
00292 if (!dumpfile) {
00293 errno = EINVAL;
00294 fprintf(stderr, "Invalid hdl argument\n");
00295 return -1;
00296 }
00297
00298
00299 if (nr_entry == 0)
00300 return 0;
00301
00302 rec.id = JIT_CODE_DEBUG_INFO;
00303 rec.code_addr = (uint64_t)(uintptr_t)code;
00304
00305 rec.total_size = 0;
00306 rec.nr_entry = nr_entry;
00307 if (gettimeofday(&tv, NULL)) {
00308 fprintf(stderr, "gettimeofday failed\n");
00309 return -1;
00310 }
00311
00312 rec.timestamp = tv.tv_sec;
00313
00314 flockfile(dumpfile);
00315
00316 if ((cur_pos = ftell(dumpfile)) == -1l)
00317 goto error;
00318 if (!fwrite_unlocked(&rec, sizeof(rec), 1, dumpfile))
00319 goto error;
00320 for (i = 0; i < nr_entry; ++i) {
00321 if (!fwrite_unlocked(&compile_map[i].vma,
00322 sizeof(compile_map[i].vma), 1,
00323 dumpfile) ||
00324 !fwrite_unlocked(&compile_map[i].lineno,
00325 sizeof(compile_map[i].lineno), 1,
00326 dumpfile) ||
00327 !fwrite_unlocked(compile_map[i].filename,
00328 strlen(compile_map[i].filename) + 1, 1,
00329 dumpfile))
00330 goto error;
00331 }
00332
00333 if ((last_pos = ftell(dumpfile)) == -1l)
00334 goto error;
00335 rec.total_size = last_pos - cur_pos;
00336 padding_count = PADDING_8ALIGNED(rec.total_size);
00337 rec.total_size += padding_count;
00338 if (padding_count && !fwrite(padd_bytes, padding_count, 1, dumpfile))
00339 goto error;
00340 if (fseek(dumpfile, cur_pos, SEEK_SET) == -1l)
00341 goto error;
00342 if (!fwrite_unlocked(&rec, sizeof(rec), 1, dumpfile))
00343 goto error;
00344 if (fseek(dumpfile, last_pos + padding_count, SEEK_SET) == -1)
00345 goto error;
00346
00347 rc = 0;
00348 error:
00349 fflush_unlocked(dumpfile);
00350 funlockfile(dumpfile);
00351 return rc;
00352 }
00353
00354
00355 int op_unload_native_code(op_agent_t hdl, uint64_t vma)
00356 {
00357 struct jr_code_unload rec;
00358 struct timeval tv;
00359 FILE * dumpfile = (FILE *) hdl;
00360
00361 if (!dumpfile) {
00362 errno = EINVAL;
00363 fprintf(stderr, "Invalid hdl argument\n");
00364 return -1;
00365 }
00366
00367 rec.id = JIT_CODE_UNLOAD;
00368 rec.vma = vma;
00369 rec.total_size = sizeof(rec);
00370 if (gettimeofday(&tv, NULL)) {
00371 fprintf(stderr, "gettimeofday failed\n");
00372 return -1;
00373 }
00374 rec.timestamp = tv.tv_sec;
00375
00376 if (!fwrite(&rec, sizeof(rec), 1, dumpfile))
00377 return -1;
00378 fflush(dumpfile);
00379 return 0;
00380 }
00381
00382 int op_major_version(void)
00383 {
00384 return OP_MAJOR_VERSION;
00385 }
00386
00387 int op_minor_version(void)
00388 {
00389 return OP_MINOR_VERSION;
00390 }