18cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/** 28cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @file libutil++/bfd_spu_support.cpp 38cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * Special BFD functions for processing a Cell BE SPU profile 48cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * 58cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @remark Copyright 2007 OProfile authors 68cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @remark Read the file COPYING 78cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * 88cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @author Maynard Johnson 98cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * (C) Copyright IBM Corporation 2007 108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */ 118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "bfd_support.h" 138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_bfd.h" 148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "config.h" 158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "cverb.h" 168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <stdlib.h> 188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <stdio.h> 198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <iostream> 208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <fstream> 218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <sstream> 228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <string> 238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <cstring> 248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <sys/types.h> 258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstruct spu_elf { 278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd FILE * stream; 288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd off_t spu_offset; 298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}; 308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddusing namespace std; 328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddextern verbose vbfd; 348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#ifdef HAVE_BFD_OPENR_IOVEC_WITH_7PARMS 368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddnamespace { 388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic void * 408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddspu_bfd_iovec_open(bfd * nbfd, void * open_closure) 418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /* Checking nbfd isn't really necessary, except to silence 438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * compile warning. In fact, nbfd will always be non-NULL. 448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */ 458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (nbfd) 468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return open_closure; 478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd else 488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return NULL; 498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic int 528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddspu_bfd_iovec_close(bfd * nbfd, void * stream) 538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd spu_elf * my_stream = (spu_elf *) stream; 558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd fclose(my_stream->stream); 578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd free(my_stream); 588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /* Checking nbfd isn't really necessary, except to silence 598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * compile warning. In fact, nbfd will always be non-NULL. 608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */ 618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (nbfd) 628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return 1; 638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd else 648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return 0; 658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstatic file_ptr 688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddspu_bfd_iovec_pread(bfd * abfd, void * stream, void * buf, 698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd file_ptr nbytes, file_ptr offset) 708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd spu_elf * my_stream = (spu_elf *) stream; 728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd fseek(my_stream->stream, my_stream->spu_offset + offset, 738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd SEEK_SET); 748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd nbytes = fread(buf, sizeof(char), nbytes, my_stream->stream); 758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd /* Checking abfd isn't really necessary, except to silence 768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * compile warning. In fact, abfd will always be non-NULL. 778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */ 788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (abfd) 798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return nbytes; 808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd else 818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return 0; 828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} // namespace anon 848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#endif 858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddbfd * 878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddspu_open_bfd(string const name, int fd, uint64_t offset_to_spu_elf) 888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{ 898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd bfd * nbfd = NULL; 918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd spu_elf * spu_elf_stream = (spu_elf *)malloc(sizeof(spu_elf)); 928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd FILE * fp = fdopen(fd, "r"); 948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd spu_elf_stream->stream = fp; 958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd spu_elf_stream->spu_offset = offset_to_spu_elf; 968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#ifdef HAVE_BFD_OPENR_IOVEC_WITH_7PARMS 978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd nbfd = bfd_openr_iovec(strdup(name.c_str()), "elf32-spu", 988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd spu_bfd_iovec_open, spu_elf_stream, 998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd spu_bfd_iovec_pread, spu_bfd_iovec_close, NULL); 1008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#else 1018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd ostringstream os; 1028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd os << "Attempt to process a Cell Broadband Engine SPU profile without" 1038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << "proper BFD support.\n" 1048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << "Rebuild the opreport utility with the correct BFD library.\n" 1058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd << "See the OProfile user manual for more information.\n"; 1068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd throw op_runtime_error(os.str()); 1078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#endif 1088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd if (!nbfd) { 1098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd cverb << vbfd << "spu_open_bfd failed for " << name << endl; 1108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return NULL; 1118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd } 1128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd bfd_check_format(nbfd, bfd_object); 1148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd 1158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd return nbfd; 1168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} 117