• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *
spu_bfd_iovec_open(bfd * nbfd,void * open_closure)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
spu_bfd_iovec_close(bfd * nbfd,void * stream)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
spu_bfd_iovec_pread(bfd * abfd,void * stream,void * buf,file_ptr nbytes,file_ptr offset)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 *
spu_open_bfd(string const name,int fd,uint64_t offset_to_spu_elf)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