1 /** 2 * @file libutil++/bfd_spu_support.cpp 3 * Special BFD functions for processing a Cell BE SPU profile 4 * 5 * @remark Copyright 2007 OProfile authors 6 * @remark Read the file COPYING 7 * 8 * @author Maynard Johnson 9 * (C) Copyright IBM Corporation 2007 10 */ 11 12 #include "bfd_support.h" 13 #include "op_bfd.h" 14 #include "config.h" 15 #include "cverb.h" 16 17 #include <stdlib.h> 18 #include <stdio.h> 19 #include <iostream> 20 #include <fstream> 21 #include <sstream> 22 #include <string> 23 #include <cstring> 24 #include <sys/types.h> 25 26 struct spu_elf { 27 FILE * stream; 28 off_t spu_offset; 29 }; 30 31 using namespace std; 32 33 extern verbose vbfd; 34 35 #ifdef HAVE_BFD_OPENR_IOVEC_WITH_7PARMS 36 37 namespace { 38 39 static void * 40 spu_bfd_iovec_open(bfd * nbfd, void * open_closure) 41 { 42 /* Checking nbfd isn't really necessary, except to silence 43 * compile warning. In fact, nbfd will always be non-NULL. 44 */ 45 if (nbfd) 46 return open_closure; 47 else 48 return NULL; 49 } 50 51 static int 52 spu_bfd_iovec_close(bfd * nbfd, void * stream) 53 { 54 spu_elf * my_stream = (spu_elf *) stream; 55 56 fclose(my_stream->stream); 57 free(my_stream); 58 /* Checking nbfd isn't really necessary, except to silence 59 * compile warning. In fact, nbfd will always be non-NULL. 60 */ 61 if (nbfd) 62 return 1; 63 else 64 return 0; 65 } 66 67 static file_ptr 68 spu_bfd_iovec_pread(bfd * abfd, void * stream, void * buf, 69 file_ptr nbytes, file_ptr offset) 70 { 71 spu_elf * my_stream = (spu_elf *) stream; 72 fseek(my_stream->stream, my_stream->spu_offset + offset, 73 SEEK_SET); 74 nbytes = fread(buf, sizeof(char), nbytes, my_stream->stream); 75 /* Checking abfd isn't really necessary, except to silence 76 * compile warning. In fact, abfd will always be non-NULL. 77 */ 78 if (abfd) 79 return nbytes; 80 else 81 return 0; 82 } 83 } // namespace anon 84 #endif 85 86 bfd * 87 spu_open_bfd(string const name, int fd, uint64_t offset_to_spu_elf) 88 { 89 90 bfd * nbfd = NULL; 91 spu_elf * spu_elf_stream = (spu_elf *)malloc(sizeof(spu_elf)); 92 93 FILE * fp = fdopen(fd, "r"); 94 spu_elf_stream->stream = fp; 95 spu_elf_stream->spu_offset = offset_to_spu_elf; 96 #ifdef HAVE_BFD_OPENR_IOVEC_WITH_7PARMS 97 nbfd = bfd_openr_iovec(strdup(name.c_str()), "elf32-spu", 98 spu_bfd_iovec_open, spu_elf_stream, 99 spu_bfd_iovec_pread, spu_bfd_iovec_close, NULL); 100 #else 101 ostringstream os; 102 os << "Attempt to process a Cell Broadband Engine SPU profile without" 103 << "proper BFD support.\n" 104 << "Rebuild the opreport utility with the correct BFD library.\n" 105 << "See the OProfile user manual for more information.\n"; 106 throw op_runtime_error(os.str()); 107 #endif 108 if (!nbfd) { 109 cverb << vbfd << "spu_open_bfd failed for " << name << endl; 110 return NULL; 111 } 112 113 bfd_check_format(nbfd, bfd_object); 114 115 return nbfd; 116 } 117