From: hanseld <ha...@us...> - 2008-01-15 09:35:42
|
Update of /cvsroot/oprofile/oprofile/libopagent In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv19518/libopagent Modified Files: Tag: JIT_SUPPORT Makefile.am Added Files: Tag: JIT_SUPPORT opagent.c opagent.h Removed Files: Tag: JIT_SUPPORT libopagent.h libopagent.c Log Message: Renamed libopagent.[ch] to opagent.[ch] --- NEW FILE: opagent.c --- /** * @file opagent.c * Interface to report symbol names and dynamically generated code to Oprofile * * @remark Copyright 2007 OProfile authors * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * @author Jens Wilke * * Copyright IBM Corporation 2007 * */ /****************************************************************** * ATTENTION: * When adding new functions to this interface, you MUST update * opagent.ver. * * If a change is made to an existing exported function, perform the * the following steps. As an example, assume op_open_agent() * is being updated to include a 'dump_code' parameter. * 1. Update the opagent.ver file with a new version node, and * add the op_open_agent to it. Note that op_open_agent * is also still declared in the original version node. * 2. Add '__asm__(".symver <blah>") directives to this .c source file. * For this example, the directives would be as follows: * __asm__(".symver op_open_agent_1_0,op_open_agent@OPAGENT_1.0"); * __asm__(".symver op_open_agent_2_0,op_open_agent@@OPAGENT_2.0"); * 3. Update the declaration of op_open_agent in the header file with * the additional parameter. * 4. Change the name of the original op_open_agent to "op_open_agent_1_0" * in this .c source file. * 5. Add the new op_open_agent_2_0(int dump_code) function in this * .c source file. * * See libopagent/Makefile.am for more information. *******************************************************************/ #include <stdio.h> #include <errno.h> #include <string.h> #include <stdint.h> #include <limits.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <time.h> #include "opagent.h" #include "bfdheader.h" #include "op_config.h" #include "jitdump.h" #define AGENT_DIR OP_SESSION_DIR_DEFAULT "jitdump" #define MSG_MAXLEN 20 op_agent_t op_open_agent(void) { char pad_bytes[7] = {0, 0, 0, 0, 0, 0, 0}; int pad_cnt; char dump_path[PATH_MAX]; char err_msg[PATH_MAX + 16]; struct stat dirstat; int rc; struct jitheader header; int fd; struct timeval tv; FILE * dumpfile = NULL; rc = stat(AGENT_DIR, &dirstat); if (rc || !S_ISDIR(dirstat.st_mode)) { if (!rc) errno = ENOTDIR; fprintf(stderr,"libopagent: Jitdump agent directory %s " "missing\n", AGENT_DIR); fprintf(stderr,"libopagent: do opcontrol --setup or " "opcontrol --reset, first\n"); return NULL; } snprintf(dump_path, PATH_MAX, "%s/%i.dump", AGENT_DIR, getpid()); snprintf(err_msg, PATH_MAX + 16, "Error opening %s\n", dump_path); // make the dump file only accessible for the user for security reason. fd = creat(dump_path, S_IRUSR|S_IWUSR); if (fd == -1) { fprintf(stderr, "%s\n", err_msg); return NULL; } dumpfile = fdopen(fd, "w"); if (!dumpfile) { fprintf(stderr, "%s\n", err_msg); return NULL; } header.magic = JITHEADER_MAGIC; header.version = JITHEADER_VERSION; header.totalsize = sizeof(header) + strlen(BFD_TARGET_NAME) + 1; /* calculate amount of padding '\0' */ pad_cnt = (((header.totalsize + 7) & 7) ^ 7); header.totalsize += pad_cnt; header.bfd_arch = BFD_ARCH; header.bfd_mach = BFD_MACH; if (gettimeofday(&tv, NULL)) { fprintf(stderr, "gettimeofday failed\n"); return NULL; } header.timestamp = tv.tv_sec; snprintf(err_msg, PATH_MAX + 16, "Error writing to %s", dump_path); if (!fwrite(&header, sizeof(header), 1, dumpfile)) { fprintf(stderr, "%s\n", err_msg); return NULL; } if (!fwrite(BFD_TARGET_NAME, strlen(BFD_TARGET_NAME) + 1, 1, dumpfile)) { fprintf(stderr, "%s\n", err_msg); return NULL; } /* write padding '\0' if necessary */ if (pad_cnt && !fwrite(pad_bytes, pad_cnt, 1, dumpfile)) { fprintf(stderr, "%s\n", err_msg); return NULL; } fflush(dumpfile); return (op_agent_t)dumpfile; } int op_close_agent(op_agent_t hdl) { struct jr_code_close rec; struct timeval tv; FILE * dumpfile = (FILE *) hdl; if (!dumpfile) { errno = EINVAL; return -1; } rec.id = JIT_CODE_CLOSE; rec.total_size = sizeof(rec); if (gettimeofday(&tv, NULL)) { fprintf(stderr, "gettimeofday failed\n"); return -1; } rec.timestamp = tv.tv_sec; if (!fwrite(&rec, sizeof(rec), 1, dumpfile)) return -1; fclose(dumpfile); dumpfile = NULL; return 0; } int op_write_native_code(op_agent_t hdl, char const * symbol_name, uint64_t vma, void const * code, unsigned int const size) { struct jr_code_load rec; struct timeval tv; size_t sz_symb_name; char pad_bytes[7] = { 0, 0, 0, 0, 0, 0, 0 }; FILE * dumpfile = (FILE *) hdl; if (!dumpfile) { errno = EINVAL; fprintf(stderr, "Invalid hdl argument\n"); return -1; } sz_symb_name = strlen(symbol_name) + 1; rec.id = JIT_CODE_LOAD; rec.code_size = size; rec.vma = vma; rec.code_addr = (u64) (uintptr_t) code; rec.total_size = code ? sizeof(rec) + sz_symb_name + size : sizeof(rec) + sz_symb_name; /* calculate amount of padding '\0' */ rec.pad_cnt = (((rec.total_size + 7) & 7) ^ 7); rec.total_size += rec.pad_cnt; if (gettimeofday(&tv, NULL)) { fprintf(stderr, "gettimeofday failed\n"); return -1; } rec.timestamp = tv.tv_sec; /* locking makes sure that we continuously write this record, if * we are called within a multi-threaded context */ flockfile(dumpfile); /* Write record, symbol name, code (optionally), and (if necessary) * additonal padding \0 bytes. */ if (fwrite_unlocked(&rec, sizeof(rec), 1, dumpfile) && fwrite_unlocked(symbol_name, sz_symb_name, 1, dumpfile)) { if (code) fwrite_unlocked(code, size, 1, dumpfile); if (rec.pad_cnt) fwrite_unlocked(pad_bytes, rec.pad_cnt, 1, dumpfile); /* Always flush to ensure conversion code to elf will see * data as soon as possible */ fflush_unlocked(dumpfile); funlockfile(dumpfile); return 0; } fflush_unlocked(dumpfile); funlockfile(dumpfile); return -1; } int op_write_debug_line_info(op_agent_t hdl, void const * code, size_t nr_entry, struct debug_line_info const * compile_map) { struct jr_code_debug_info rec; long cur_pos, last_pos; struct timeval tv; size_t i; size_t padding_count; char padd_bytes[7] = {0, 0, 0, 0, 0, 0, 0}; int rc = -1; FILE * dumpfile = (FILE *) hdl; if (!dumpfile) { errno = EINVAL; fprintf(stderr, "Invalid hdl argument\n"); return -1; } /* write nothing if no entries are provided */ if (nr_entry == 0) goto out; rec.id = JIT_CODE_DEBUG_INFO; rec.code_addr = (uint64_t)(uintptr_t)code; /* will be fixed after writing debug line info */ rec.total_size = 0; rec.nr_entry = nr_entry; if (gettimeofday(&tv, NULL)) { fprintf(stderr, "gettimeofday failed\n"); return -1; } rec.timestamp = tv.tv_sec; flockfile(dumpfile); if ((cur_pos = ftell(dumpfile)) == -1l) goto error; if (!fwrite_unlocked(&rec, sizeof(rec), 1, dumpfile)) goto error; for (i = 0; i < nr_entry; ++i) { if (!fwrite_unlocked(&compile_map[i].vma, sizeof(compile_map[i].vma), 1, dumpfile) || !fwrite_unlocked(&compile_map[i].lineno, sizeof(compile_map[i].lineno), 1, dumpfile) || !fwrite_unlocked(compile_map[i].filename, strlen(compile_map[i].filename) + 1, 1, dumpfile)) goto error; } if ((last_pos = ftell(dumpfile)) == -1l) goto error; rec.total_size = last_pos - cur_pos; padding_count = (((rec.total_size + 7) & 7) ^ 7); rec.total_size += padding_count; if (padding_count && !fwrite(padd_bytes, padding_count, 1, dumpfile)) goto error; if (fseek(dumpfile, cur_pos, SEEK_SET) == -1l) goto error; if (!fwrite_unlocked(&rec, sizeof(rec), 1, dumpfile)) goto error; if (fseek(dumpfile, last_pos + padding_count, SEEK_SET) == -1) goto error; out: rc = 0; error: fflush_unlocked(dumpfile); funlockfile(dumpfile); return rc; } int op_unload_native_code(op_agent_t hdl, uint64_t vma) { struct jr_code_unload rec; struct timeval tv; FILE * dumpfile = (FILE *) hdl; if (!dumpfile) { errno = EINVAL; fprintf(stderr, "Invalid hdl argument\n"); return -1; } rec.id = JIT_CODE_UNLOAD; rec.vma = vma; rec.total_size = sizeof(rec); if (gettimeofday(&tv, NULL)) { fprintf(stderr, "gettimeofday failed\n"); return -1; } rec.timestamp = tv.tv_sec; if (!fwrite(&rec, sizeof(rec), 1, dumpfile)) return -1; fflush(dumpfile); return 0; } --- NEW FILE: opagent.h --- /** * @file opagent.h * Interface to report symbol names and dynamically generated code to Oprofile * * @remark Copyright 2007 OProfile authors * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * @author Jens Wilke * * Copyright IBM Corporation 2007 * */ #ifndef _LIB_OPAGENT_H #define _LIB_OPAGENT_H #include <sys/types.h> struct debug_line_info { unsigned long vma; unsigned int lineno; /* The filename format is unspecified, absolute path, relative etc. */ char const * filename; }; typedef void * op_agent_t; /** * This function must be called by agents before any other function. * Creates and opens a JIT dump file in /var/lib/oprofile/jitdump * using the naming convention <process_id>.dump. * * Returns a valid op_agent_t handle or NULL. If NULL is returned, errno * is set to indicate the nature of the error. **/ op_agent_t op_open_agent(void); /** * Frees all resources and closes open file handles. * * hdl: Handle returned from an earlier call to op_open_agent() * * Returns 0 on success; -1 otherwise. If -1 is returned, errno is * set to indicate the nature of the error. **/ int op_close_agent(op_agent_t hdl); /** * Signal the dynamic generation of native code from a virtual machine. * Writes a JIT dump record to the open JIT dump file using * the passed information. * * hdl: Handle returned from an earlier call to op_open_agent() * symbol_name: The name of the symbol being dynamically compiled. * This name can (and should) contain all necessary * information to disambiguate it from symbols of the * same name; e.g., class, method signature. * vma: The virtual memory address of the executable code. * code: Pointer to the location of the compiled code. * Theoretically, this may be a different location from * that given by the vma argument. For some JIT compilers, * obtaining the code may be impractical. For this (or any other) * reason, the agent can choose to pass NULL for this paraemter. * If NULL is passed, no code will be copied into the JIT dump * file. * code_size: Size of the compiled code. * * Returns 0 on success; -1 otherwise. If -1 is returned, errno is * set to indicate the nature of the error. **/ int op_write_native_code(op_agent_t hdl, char const * symbol_name, uint64_t vma, void const * code, const unsigned int code_size); /** * Add debug line information to a piece of code. An op_write_native_code() * with the same code pointer should have occurred before this call. It's not * necessary to provide one lineno information entry per machine instruction; * the array can contain hole. * * hdl: Handle returned from an earlier call to op_open_agent() * code: Pointer to the location of the code with debug info * nr_entry: Number of entries in compile_map * compile_map: Array of struct debug_line_info. See the JVMTI agent * library implementation for an example of what information * should be retrieved from a VM to fill out this data structure. * * Returns 0 on success; -1 otherwise. If -1 is returned, errno is * set to indicate the nature of the error. **/ int op_write_debug_line_info(op_agent_t hdl, void const * code, size_t nr_entry, struct debug_line_info const * compile_map); /** * Signal the invalidation of native code from a virtual machine. * * hdl: Handle returned from an earlier call to op_open_agent() * vma: The virtual memory address of the compiled code being unloaded. * An op_write_native_code() with the same vma should have * occurred before this call. * * Returns 0 on success; -1 otherwise. If -1 is returned, errno is * set to indicate the nature of the error. **/ int op_unload_native_code(op_agent_t hdl, uint64_t vma); /* idea how to post additional information for a piece of code. we use the code address as reference int op_write_loader_name(const void* code_addr, char const * loader_name); */ #endif Index: Makefile.am =================================================================== RCS file: /cvsroot/oprofile/oprofile/libopagent/Attic/Makefile.am,v retrieving revision 1.1.2.4 retrieving revision 1.1.2.5 diff -u -p -d -r1.1.2.4 -r1.1.2.5 --- Makefile.am 8 Jan 2008 15:39:42 -0000 1.1.2.4 +++ Makefile.am 15 Jan 2008 09:35:15 -0000 1.1.2.5 @@ -1,10 +1,10 @@ pkglib_LTLIBRARIES = libopagent.la -# install libopagent.h to include directory -include_HEADERS = libopagent.h +# install opagent.h to include directory +include_HEADERS = opagent.h -libopagent_la_SOURCES = libopagent.c \ - libopagent.h +libopagent_la_SOURCES = opagent.c \ + opagent.h nodist_libopagent_la_SOURCES = bfdheader.h jitheader.h @@ -16,7 +16,8 @@ libopagent_la_CFLAGS = -fPIC -I ${top_sr # change existing functions; then just increment the minor version. # See http://www.gnu.org/software/binutils/manual/ld-2.9.1/html_node/ld_25.html # for details about the --version-script option. -libopagent_la_LDFLAGS = -version-info 1:0:0 -Wl,--version-script=opagent_symbols.ver +libopagent_la_LDFLAGS = -version-info 1:0:0 \ + -Wl,--version-script=${top_srcdir}/libopagent/opagent_symbols.ver # the bfdheader.h is generated by bfddefines at compile time --- libopagent.h DELETED --- --- libopagent.c DELETED --- |