HPCToolkit
Fatbin.cpp
Go to the documentation of this file.
1 // * BeginRiceCopyright *****************************************************
2 //
3 // $HeadURL$
4 // $Id$
5 //
6 // --------------------------------------------------------------------------
7 // Part of HPCToolkit (hpctoolkit.org)
8 //
9 // Information about sources of support for research and development of
10 // HPCToolkit is at 'hpctoolkit.org' and in 'README.Acknowledgments'.
11 // --------------------------------------------------------------------------
12 //
13 // Copyright ((c)) 2002-2019, Rice University
14 // All rights reserved.
15 //
16 // Redistribution and use in source and binary forms, with or without
17 // modification, are permitted provided that the following conditions are
18 // met:
19 //
20 // * Redistributions of source code must retain the above copyright
21 // notice, this list of conditions and the following disclaimer.
22 //
23 // * Redistributions in binary form must reproduce the above copyright
24 // notice, this list of conditions and the following disclaimer in the
25 // documentation and/or other materials provided with the distribution.
26 //
27 // * Neither the name of Rice University (RICE) nor the names of its
28 // contributors may be used to endorse or promote products derived from
29 // this software without specific prior written permission.
30 //
31 // This software is provided by RICE and contributors "as is" and any
32 // express or implied warranties, including, but not limited to, the
33 // implied warranties of merchantability and fitness for a particular
34 // purpose are disclaimed. In no event shall RICE or contributors be
35 // liable for any direct, indirect, incidental, special, exemplary, or
36 // consequential damages (including, but not limited to, procurement of
37 // substitute goods or services; loss of use, data, or profits; or
38 // business interruption) however caused and on any theory of liability,
39 // whether in contract, strict liability, or tort (including negligence
40 // or otherwise) arising in any way out of the use of this software, even
41 // if advised of the possibility of such damage.
42 //
43 // ******************************************************* EndRiceCopyright *
44 
45 
46 //***************************************************************************
47 //
48 // File: Fatbin.cpp
49 //
50 // Purpose:
51 // unpack cuda fatbin
52 //
53 // Description:
54 //
55 //***************************************************************************
56 
57 //******************************************************************************
58 // system includes
59 //******************************************************************************
60 
61 #include <stdio.h>
62 #include <string.h>
63 
64 
65 
66 //******************************************************************************
67 // local includes
68 //******************************************************************************
69 
70 #include <lib/support/StrUtil.hpp>
71 #include <include/hpctoolkit-config.h>
72 
73 #include <Elf_X.h>
74 
75 #include "InputFile.hpp"
76 #include "ElfHelper.hpp"
77 
78 
79 
80 //******************************************************************************
81 // macros
82 //******************************************************************************
83 
84 
85 #define CUDA_FATBIN_SECTION ".nvFatBinSegment"
86 #define CUDA_FATBIN_DATASECTION ".nv_fatbin"
87 
88 #define CUDA_FATBIN_MAGIC 0x466243b1
89 #define CUDA_FATBIN_VERSION 1
90 
91 
92 
93 //******************************************************************************
94 // type definitions
95 //******************************************************************************
96 
97 typedef struct NvidiaFatBinHeader_s {
98  int32_t magicNumber;
99  int32_t version;
100  const unsigned long long* data;
101  void* unused;
103 
104 
105 typedef std::vector<NvidiaFatBinHeader_t *> FatbinSectionVector;
106 
107 
108 
109 //******************************************************************************
110 // local variables
111 //******************************************************************************
112 
114 
115 
116 
117 //******************************************************************************
118 // private functions
119 //******************************************************************************
120 
121 #ifdef DYNINST_USE_CUDA
122 
123 static bool
124 isCubin(Elf *elf)
125 {
126  // open the header of the Elf object
127  GElf_Ehdr ehdr_v;
128  GElf_Ehdr *obj_ehdr = gelf_getehdr(elf, &ehdr_v);
129 
130  // check the header of the Elf object to see if it is a Cubin
131  return (obj_ehdr && (obj_ehdr->e_machine == EM_CUDA));
132 }
133 
134 
135 static bool
136 recordIfNvFatbin
137 (
138  char *obj_ptr,
139  Elf *elf,
140  GElf_Ehdr *ehdr,
141  Elf_Scn *scn,
142  GElf_Shdr *shdr
143  )
144 {
145 #if 0
146  bool isFatbin = strcmp(elf_strptr(elf, ehdr->e_shstrndx, shdr->sh_name),
148  if (isFatbin) {
149  NvidiaFatBinHeader_t *fatbin =
150  (NvidiaFatBinHeader_t *) elfSectionGetData(obj_ptr, shdr);
151  std::string empty;
152  ElfFile *elfFile = new ElfFile;
153  if (elfFile->open((char *) fatbin->data, (size_t) shdr->sh_size, empty)) {
154  fatbinSectionVector.push_back(fatbin);
155  }
156  }
157  return isFatbin;
158 #else
159  return false;
160 #endif
161 }
162 
163 
164 static bool
165 recordIfCubin
166 (
167  ElfFile *loadModule,
168  char *obj_ptr,
169  Elf *elf,
170  GElf_Ehdr *ehdr,
171  Elf_Scn *scn,
172  GElf_Shdr *shdr,
173  ElfFileVector *elfFileVector
174  )
175 {
176  char *sectionData = elfSectionGetData(obj_ptr, shdr);
177 
178  std::string filename = loadModule->getFileName() + "@" +
179  StrUtil::toStr(shdr->sh_addr, 16);
180 
181  ElfFile *elfFile = new ElfFile;
182 
183  // check if section represents an Elf object
184  if (elfFile->open(sectionData, shdr->sh_size, filename)) {
185 
186  // if the Elf file is a CUBIN, add it to the vector of load
187  // modules to be analyzed
188  if (isCubin(elfFile->getElf())) {
189  elfFileVector->push_back(elfFile);
190  return true;
191  } else {
192  delete elfFile;
193  }
194  }
195  return false;
196 }
197 #endif
198 
199 
200 // cubin text segments all start at offset 0 and are thus overlapping.
201 // relocate each text segment so that it begins at its offset in the
202 // cubin. when this function returns, text segments no longer overlap.
203 static bool
205 (
206  ElfFile *elfFile,
207  char *obj_ptr,
208  Elf *elf,
209  ElfSectionVector *sections,
210  ElfFileVector *elfFileVector
211  )
212 {
213  int count = 0;
214 
215 #ifdef DYNINST_USE_CUDA
216  GElf_Ehdr ehdr_v;
217  GElf_Ehdr *ehdr = gelf_getehdr(elf, &ehdr_v);
218 
219  if (ehdr) {
220  for (auto si = sections->begin(); si != sections->end(); si++) {
221  Elf_Scn *scn = *si;
222  GElf_Shdr shdr_v;
223  GElf_Shdr *shdr = gelf_getshdr(scn, &shdr_v);
224  if (!shdr) continue;
225 
226  if (recordIfNvFatbin(obj_ptr, elf, ehdr, scn, shdr)) {
227  count++;
228  } else if (recordIfCubin(elfFile, obj_ptr, elf, ehdr, scn,
229  shdr, elfFileVector)) {
230  count++;
231  }
232  }
233  }
234 #endif
235  return count > 0;
236 }
237 
238 
239 
240 //******************************************************************************
241 // interface functions
242 //******************************************************************************
243 
244 bool
246 (
247  ElfFile *elfFile,
248  ElfFileVector *elfFileVector
249 )
250 {
251  bool success = false;
252  Elf *elf = elfFile->getElf();
253 
254  ElfSectionVector *sections = elfGetSectionVector(elf);
255 
256  if (sections) {
257  success = findCubinSections(elfFile, elfFile->getMemory(), elf,
258  sections, elfFileVector);
259  }
260  return success;
261 }
262 
263 
264 
265 //******************************************************************************
266 // debugging support
267 //******************************************************************************
268 
269 void
271 (
272  ElfFile *elfFile,
273  const char *suffix
274 )
275 {
276  std::string filename = elfFile->getFileName() + suffix;
277  FILE *f = fopen(filename.c_str(), "w");
278  fwrite(elfFile->getMemory(), elfFile->getLength(), 1, f);
279  fclose(f);
280 }
281 
282 
283 #ifdef DYNINST_USE_CUDA
284 void
285 writeCubins(
286  ElfFileVector *elfFileVector
287 )
288 {
289  for(unsigned int i = 0; i < elfFileVector->size(); i++) {
290  ElfFile *elfFile = (*elfFileVector)[i];
291  if (isCubin(elfFile->getElf())) {
292  writeElfFile(elfFile, ".cubin");
293  }
294  }
295 }
296 #endif
void writeElfFile(ElfFile *elfFile, const char *suffix)
Definition: Fatbin.cpp:271
const unsigned long long * data
Definition: Fatbin.cpp:100
char * getMemory()
Definition: ElfHelper.hpp:86
string toStr(const int x, int base)
Definition: StrUtil.cpp:243
#define CUDA_FATBIN_DATASECTION
Definition: Fatbin.cpp:86
Elf * getElf()
Definition: ElfHelper.hpp:85
static bool findCubinSections(ElfFile *elfFile, char *obj_ptr, Elf *elf, ElfSectionVector *sections, ElfFileVector *elfFileVector)
Definition: Fatbin.cpp:205
bool open(char *_memPtr, size_t _memLen, std::string _fileName)
Definition: ElfHelper.cpp:96
std::string getFileName()
Definition: ElfHelper.hpp:88
struct NvidiaFatBinHeader_s NvidiaFatBinHeader_t
std::vector< NvidiaFatBinHeader_t * > FatbinSectionVector
Definition: Fatbin.cpp:105
bool findCubins(ElfFile *elfFile, ElfFileVector *elfFileVector)
Definition: Fatbin.cpp:246
ElfSectionVector * elfGetSectionVector(Elf *elf)
Definition: ElfHelper.cpp:142
static FatbinSectionVector fatbinSectionVector
Definition: Fatbin.cpp:113
size_t MONITOR_EXT_WRAP_NAME() fwrite(const void *ptr, size_t size, size_t count, FILE *stream)
Definition: io-over.c:260
size_t getLength()
Definition: ElfHelper.hpp:87
int32_t magicNumber
Definition: Fatbin.cpp:98
char * elfSectionGetData(char *obj_ptr, GElf_Shdr *shdr)
Definition: ElfHelper.cpp:165