1 /*========================== begin_copyright_notice ============================
2 
3 Copyright (C) 2017-2021 Intel Corporation
4 
5 SPDX-License-Identifier: MIT
6 
7 ============================= end_copyright_notice ===========================*/
8 
9 /*========================== begin_copyright_notice ============================
10 
11 This file is distributed under the University of Illinois Open Source License.
12 See LICENSE.TXT for details.
13 
14 ============================= end_copyright_notice ===========================*/
15 
16 #include "llvm/Config/llvm-config.h"
17 #include "common/LLVMWarningsPush.hpp"
18 #include "llvm/IR/Module.h"
19 #include "llvm/IR/DIBuilder.h"
20 #include "llvm/IR/Verifier.h"
21 #include "llvm/MC/MCDwarf.h"
22 #include "llvm/MC/MCSymbol.h"
23 #include "llvm/BinaryFormat/ELF.h"
24 #include "common/LLVMWarningsPop.hpp"
25 
26 #include "VISADebugEmitter.hpp"
27 #include "DwarfDebug.hpp"
28 #include "StreamEmitter.hpp"
29 #include "VISAModule.hpp"
30 
31 #include "Probe/Assertion.h"
32 #include "secure_mem.h"
33 
34 #include "CLElfLib/CLElfTypes.h"
35 
36 #define DEBUG_TYPE "dwarfdebug"
37 
38 using namespace llvm;
39 using namespace IGC;
40 using namespace CLElfLib;   // ElfReader related typedefs
41 
Create()42 IDebugEmitter* IDebugEmitter::Create()
43 {
44     return new DebugEmitter();
45 }
46 
Release(IDebugEmitter * pDebugEmitter)47 void IDebugEmitter::Release(IDebugEmitter* pDebugEmitter)
48 {
49     delete pDebugEmitter;
50 }
51 
DebugEmitter()52 DebugEmitter::DebugEmitter() : IDebugEmitter(), m_outStream(m_str)
53 {
54 }
~DebugEmitter()55 DebugEmitter::~DebugEmitter()
56 {
57     Reset();
58 }
59 
Reset()60 void DebugEmitter::Reset()
61 {
62     m_str.clear();
63     m_pVISAModule = nullptr;
64 
65     m_pStreamEmitter.reset();
66     m_pDwarfDebug.reset();
67 
68     m_initialized = false;
69 }
70 
71 
Initialize(std::unique_ptr<VISAModule> VM,const DebugEmitterOpts & Opts)72 void DebugEmitter::Initialize(std::unique_ptr<VISAModule> VM,
73                               const DebugEmitterOpts& Opts)
74 {
75     IGC_ASSERT_MESSAGE(false == m_initialized, "DebugEmitter is already initialized!");
76     // IGC_ASSERT(!doneOnce);
77     m_initialized = true;
78 
79     m_pVISAModule = VM.get();
80     m_debugEnabled = Opts.DebugEnabled;
81     // VISA module will be initialized even when debugger is disabled.
82     // Its overhead is minimum and it will be used in debug mode to
83     // assertion test on calling DebugEmitter in the right order.
84     toFree.push_back(std::move(VM));
85 
86     if (!m_debugEnabled)
87     {
88         return;
89     }
90 
91     const auto &dataLayout = m_pVISAModule->GetDataLayout();
92     m_pStreamEmitter = std::make_unique<StreamEmitter>(
93                         m_outStream, dataLayout, m_pVISAModule->GetTargetTriple(), Opts);
94     m_pDwarfDebug = std::make_unique<DwarfDebug>(m_pStreamEmitter.get(), m_pVISAModule);
95 
96     registerVISA(m_pVISAModule);
97 }
98 
processCurrentFunction(bool finalize,const DbgDecoder * decodedDbg)99 void DebugEmitter::processCurrentFunction(bool finalize, const DbgDecoder* decodedDbg) {
100 
101     auto EmitIpLabel = [&](unsigned int ip)
102     {
103         // Emit label before %ip
104         if (m_pStreamEmitter->GetEmitterSettings().EnableRelocation)
105         {
106             auto instLabel = m_pDwarfDebug->GetLabelBeforeIp(ip);
107             m_pStreamEmitter->EmitLabel(instLabel);
108         }
109     };
110 
111     m_pVISAModule->buildDirectElfMaps(*decodedDbg);
112     auto co = m_pVISAModule->getCompileUnit(*decodedDbg);
113 
114     // Emit src line mapping directly instead of
115     // relying on dbgmerge. elf generated will have
116     // text section and debug_line sections populated.
117     const auto& VISAIndexToInst = m_pVISAModule->VISAIndexToInst;
118     const auto& VISAIndexToSize = m_pVISAModule->VISAIndexToSize;
119     decltype(m_pVISAModule->GenISAToVISAIndex) GenISAToVISAIndex;
120     unsigned int subEnd = m_pVISAModule->GetCurrentVISAId();
121     unsigned int prevLastGenOff = lastGenOff;
122     m_pDwarfDebug->lowPc = lastGenOff;
123 
124     // SIMD width
125     m_pDwarfDebug->simdWidth = m_pVISAModule->GetSIMDSize();
126 
127     if (co->subs.size() == 0)
128     {
129         GenISAToVISAIndex = m_pVISAModule->GenISAToVISAIndex;
130         if (GenISAToVISAIndex.size() > 0)
131             lastGenOff = GenISAToVISAIndex.back().GenOffset;
132         m_pDwarfDebug->lowPc = co->relocOffset;
133     }
134     else
135     {
136         for (auto item : m_pVISAModule->GenISAToVISAIndex)
137         {
138             if ((item.GenOffset >= lastGenOff) || ((item.GenOffset | lastGenOff) == 0))
139             {
140                 if (item.VisaOffset <= subEnd || item.VisaOffset == 0xffffffff)
141                 {
142                     GenISAToVISAIndex.push_back(item);
143                     auto size = m_pVISAModule->GenISAInstSizeBytes[item.GenOffset];
144                     lastGenOff = item.GenOffset + size;
145                     continue;
146                 }
147 
148                 if (item.VisaOffset > subEnd)
149                     break;
150             }
151         }
152     }
153 
154     auto genxISA = m_pVISAModule->getGenBinary();
155     DebugLoc prevSrcLoc = DebugLoc();
156     unsigned int pc = prevLastGenOff;
157 
158     if (!GenISAToVISAIndex.empty()) {
159         IGC_ASSERT(GenISAToVISAIndex.rbegin()->GenOffset <= genxISA.size());
160         IGC_ASSERT(pc < genxISA.size());
161         IGC_ASSERT(GenISAToVISAIndex.begin()->GenOffset >= pc);
162     }
163     for (auto item : GenISAToVISAIndex)
164     {
165         for (unsigned int i = pc; i != item.GenOffset; i++)
166         {
167             EmitIpLabel(i);
168             m_pStreamEmitter->EmitInt8(genxISA[i]);
169         }
170 
171         pc = item.GenOffset;
172 
173         auto instIt = VISAIndexToInst.end();
174         auto sizeIt = VISAIndexToSize.find(item.VisaOffset);
175         if (sizeIt != VISAIndexToSize.end())
176         {
177             // Lookup all VISA instructions that may
178             // map to an llvm::Instruction. This is useful
179             // when an llvm::Instruction leads to multiple
180             // VISA instructions, and VISA optimizer
181             // optimizes some of those away. Src line
182             // mapping for all VISA instructions is the
183             // same. So lookup any one that still exists.
184             auto startIdx = sizeIt->second.VisaOffset;
185             auto numVISAInsts = sizeIt->second.VisaInstrNum;
186             // Loop till at least one VISA instruction
187             // is found.
188             for (unsigned int visaId = startIdx;
189                 visaId != (startIdx + numVISAInsts); visaId++)
190             {
191                 instIt = VISAIndexToInst.find(visaId);
192                 if (instIt != VISAIndexToInst.end())
193                     break;
194             }
195         }
196 
197         if (instIt == VISAIndexToInst.end())
198             continue;
199         if (!m_pVISAModule->IsExecutableInst(*instIt->second))
200             continue;
201 
202         const auto& loc = instIt->second->getDebugLoc();
203         if (!loc || loc == prevSrcLoc)
204             continue;
205 
206         const auto* scope = loc->getScope();
207         auto src = m_pDwarfDebug->getOrCreateSourceID(scope->getFilename(), scope->getDirectory(), m_pStreamEmitter->GetDwarfCompileUnitID());
208 
209         unsigned int Flags = 0;
210         if (!m_pDwarfDebug->isStmtExists(loc.getLine(), loc.getInlinedAt(), true))
211         {
212             Flags |= DWARF2_FLAG_IS_STMT;
213         }
214 
215         if (!m_pDwarfDebug->prologueEndExists(loc.get()->getScope()->getSubprogram(),
216                                               loc.getInlinedAt(), true))
217         {
218             Flags |= DWARF2_FLAG_PROLOGUE_END;
219         }
220         m_pStreamEmitter->EmitDwarfLocDirective(src, loc.getLine(), loc.getCol(), Flags, 0, 0, scope->getFilename());
221 
222         prevSrcLoc = loc;
223     }
224 
225     if (finalize)
226     {
227         size_t unpaddedSize = m_pVISAModule->getUnpaddedProgramSize();
228 
229         IGC_ASSERT(unpaddedSize <= genxISA.size());
230         IGC_ASSERT((pc < genxISA.size() && pc < unpaddedSize) || pc == unpaddedSize);
231 
232         for (unsigned int i = pc; i != unpaddedSize; i++)
233         {
234             m_pStreamEmitter->EmitInt8(genxISA[i]);
235             lastGenOff++;
236         }
237     }
238     else if (pc != lastGenOff)
239     {
240         IGC_ASSERT(lastGenOff <= genxISA.size());
241         IGC_ASSERT((pc < genxISA.size() && pc < lastGenOff) || pc == lastGenOff);
242         // for subroutines
243         for (unsigned int i = pc; i != lastGenOff; i++)
244         {
245             EmitIpLabel(i);
246             m_pStreamEmitter->EmitInt8(genxISA[i]);
247         }
248     }
249 
250     m_pDwarfDebug->highPc = lastGenOff;
251 }
252 
SetDISPCache(DwarfDISubprogramCache * DISPCache)253 void DebugEmitter::SetDISPCache(DwarfDISubprogramCache *DISPCache) {
254     IGC_ASSERT(m_pDwarfDebug);
255     m_pDwarfDebug->setDISPCache(DISPCache);
256 }
257 
Finalize(bool finalize,const DbgDecoder * decodedDbg)258 std::vector<char> DebugEmitter::Finalize(bool finalize,
259                                          const DbgDecoder* decodedDbg)
260 {
261     if (!m_debugEnabled)
262     {
263         return {};
264     }
265 
266     IGC_ASSERT_MESSAGE(m_pVISAModule, "active visa object must be selected before finalization");
267     IGC_ASSERT(m_pDwarfDebug);
268     m_pDwarfDebug->setDecodedDbg(decodedDbg);
269 
270     if (!doneOnce)
271     {
272         m_pDwarfDebug->beginModule();
273         doneOnce = true;
274     }
275 
276     const Function* pFunc = m_pVISAModule->GetEntryFunction();
277     // Collect debug information for given function.
278     m_pStreamEmitter->SwitchSection(m_pStreamEmitter->GetTextSection());
279 
280     LLVM_DEBUG(dbgs() << "[DwarfDebug] beginFunction called for <" <<
281                pFunc->getName() << "> ---\n");
282     m_pDwarfDebug->beginFunction(pFunc, m_pVISAModule);
283     LLVM_DEBUG(dbgs() << "[DwarfDebug] beginFunction end ***\n");
284 
285     processCurrentFunction(finalize, decodedDbg);
286 
287     // Emit post-function debug information
288     LLVM_DEBUG(dbgs() << "[DwarfDebug] endFunction start ---\n");
289     m_pDwarfDebug->endFunction(pFunc);
290     LLVM_DEBUG(dbgs() << "[DwarfDebug] endFunction done ***\n");
291 
292     if (!finalize)
293     {
294         LLVM_DEBUG(dbgs() << "[DwarfDebug] non-finalized exit ***\n");
295         return {};
296     }
297     LLVM_DEBUG(dbgs() << "[DwarfDebug] starting finalization ---\n");
298 
299     IGC_ASSERT(doneOnce);
300 
301     // Finalize debug information.
302     m_pDwarfDebug->endModule();
303 
304     m_pStreamEmitter->Finalize();
305     LLVM_DEBUG(dbgs() << "[DwarfDebug] finalized***\n");
306 
307     LLVM_DEBUG(dbgs() << "Finalized Visa Module:\n");
308     LLVM_DEBUG(m_pVISAModule->dump());
309 
310     // Add program header table to satisfy latest gdb
311     bool is64Bit = m_pVISAModule->getPointerSize() == 8;
312     unsigned int phtSize = sizeof(llvm::ELF::Elf32_Phdr);
313     if (is64Bit)
314         phtSize = sizeof(llvm::ELF::Elf64_Phdr);
315 
316     const Function* PrimaryEntry = m_pDwarfDebug->GetPrimaryEntry();
317     std::string EntryNameWithDot = ("." + PrimaryEntry->getName()).str();
318     size_t ContentSize = m_str.size();
319     if (m_pStreamEmitter->GetEmitterSettings().ZeBinCompatible)
320         ContentSize += EntryNameWithDot.size();
321 
322     size_t elfWithProgramHeaderSize = phtSize + ContentSize;
323     std::vector<char> Result(elfWithProgramHeaderSize);
324 
325     if (!m_pStreamEmitter->GetEmitterSettings().ZeBinCompatible)
326     {
327         // Text section remains with its standard name .text
328         std::copy(m_str.begin(), m_str.end(), Result.begin());
329     }
330     else
331     {
332         // Text section's name to be extended by a kernel name.
333         size_t endOfDotTextNameOffset = 0;
334         prepareElfForZeBinary(is64Bit, m_str.begin(), m_str.size(),
335                               EntryNameWithDot.size(), &endOfDotTextNameOffset);
336 
337         // First copy ELF binary from the beginning to the .text name (included) located in the .str.tab
338         std::copy(m_str.begin(), m_str.begin() + endOfDotTextNameOffset, Result.begin());
339         // Next concatenate .text with a kernel name (a dot joining both names also added).
340         std::copy(EntryNameWithDot.begin(), EntryNameWithDot.end(),
341                   Result.begin() + endOfDotTextNameOffset);
342         // Finally copy remaining part of ELF binary.
343         std::copy(m_str.begin() + endOfDotTextNameOffset + 1, m_str.end(),
344                   Result.begin() + endOfDotTextNameOffset + 1 + EntryNameWithDot.size());
345     }
346 
347     writeProgramHeaderTable(is64Bit, Result.data(), ContentSize);
348     setElfType(is64Bit, Result.data());
349 
350     m_errs = m_pStreamEmitter->getErrors();
351     Reset();
352 
353     return std::move(Result);
354 }
355 
prepareElfForZeBinary(bool is64Bit,char * pElfBuffer,size_t elfBufferSize,size_t kernelNameWithDotSize,size_t * pEndOfDotTextNameInStrtab)356 void DebugEmitter::prepareElfForZeBinary(bool is64Bit, char* pElfBuffer, size_t elfBufferSize, size_t kernelNameWithDotSize,
357     size_t* pEndOfDotTextNameInStrtab)
358 {
359     // ELF binary header contains 'SectionHeadersOffset' (e_shoff in ELF spec.), which is an offset
360     // to section headers placed one by one. A location (index) of the header with names (including section name)
361     // is stored in the ELF binary header at 'SectionNameTableIndex' (e_shstrndx). A section header under this index
362     // contains an offset to location of the String Table data, which may look as showed in the line below:
363     //  .debug_abbrev .text.stackcall .debug_ranges .debug_str .debug_info
364     // ^NULL         ^NULL           ^NULL         ^NULL      ^NULL       ^NULL
365     //
366     // Each section header contain 'Name' (sh_name) fields which is a byte offset to this data showed above.
367     // The String Table is a simple chunk of memory, where the names are placed one by one and separated by NULL (\0).
368     // String Table contains NULL (\0) also at the beginning (i.e. 'Name' equal 0 means no name).
369 
370     if (is64Bit)
371     {
372         SElf64Header* pElf64Header = (SElf64Header*)pElfBuffer;
373 
374         // First simply validate ELF binary
375         IGC_ASSERT_MESSAGE(pElf64Header &&
376             (pElf64Header->Identity[ID_IDX_MAGIC0] == ELF_MAG0) &&
377             (pElf64Header->Identity[ID_IDX_MAGIC1] == ELF_MAG1) &&
378             (pElf64Header->Identity[ID_IDX_MAGIC2] == ELF_MAG2) &&
379             (pElf64Header->Identity[ID_IDX_MAGIC3] == ELF_MAG3) &&
380             (pElf64Header->Identity[ID_IDX_CLASS] == EH_CLASS_64), "ELF file header incorrect");
381 
382         // Using the Section Name Table Index, calculate the offset to the String Table (.strtab) header.
383         size_t entrySize = pElf64Header->SectionHeaderEntrySize;
384         size_t nameSectionHeaderOffset = (size_t)pElf64Header->SectionHeadersOffset + (pElf64Header->SectionNameTableIndex * entrySize);
385         IGC_ASSERT_MESSAGE(pElf64Header->SectionNameTableIndex < pElf64Header->NumSectionHeaderEntries, "ELF header incorrect");
386         IGC_ASSERT_MESSAGE(nameSectionHeaderOffset < elfBufferSize, "ELF header incorrect");
387 
388         // Using the offset found above get a header of the String Table section
389         SElf64SectionHeader* pNamesSectionHeader = (SElf64SectionHeader*)((char*)pElf64Header + nameSectionHeaderOffset);
390         SElf64SectionHeader* pSectionHeader = NULL;
391         size_t indexedSectionHeaderOffset = 0;
392         Elf64_Word textSectionHeaderName = 0;
393         char* pSectionName = NULL;
394         size_t sectionNameOffset = 0;
395         size_t textSectionNameOffset = 0;
396 
397         // Scan section headers to find the Text section using simple section name comparison.
398         for (unsigned int elfSectionIdx = 1; elfSectionIdx < pElf64Header->NumSectionHeaderEntries; elfSectionIdx++)
399         {
400             // Calculate a byte offset to the current section's header
401             indexedSectionHeaderOffset = (size_t)pElf64Header->SectionHeadersOffset + (elfSectionIdx * entrySize);
402 
403             // Get a header of the current section
404             pSectionHeader = (SElf64SectionHeader*)((char*)pElf64Header + indexedSectionHeaderOffset);
405 
406             // Using the byte offset from the current section's header, find the current section's name
407             // in the String Table.
408             sectionNameOffset = (size_t)pNamesSectionHeader->DataOffset + pSectionHeader->Name;
409             pSectionName = (char*)pElf64Header + sectionNameOffset;
410 
411             // Check if the Text section is found.
412             if (pSectionName && (strcmp(pSectionName, ".text") == 0))
413             {
414                 textSectionHeaderName = pSectionHeader->Name;   // Remember for the next loop over sections.
415                 textSectionNameOffset = sectionNameOffset;      // Remember for the next loop over sections.
416                 pNamesSectionHeader->DataSize += kernelNameWithDotSize; //.strtab size increases not .text section
417 
418                 // Return an offset (from the beginning of ELF binary) to the first character after '.text'
419                 *pEndOfDotTextNameInStrtab = sectionNameOffset + sizeof(".text") - 1;
420                 break; // Text section found, its location saved.
421             }
422         }
423 
424         // Update headers of ELF sections due to a longer Text section name
425         // (i.e. in strtab .text will be replaced with .text.kernelName).
426         // - change location of each section name located after the Text section name in .strtab
427         // - change data offset of each section located after the .strtab section
428         for (unsigned int elfSectionIdx = 1; elfSectionIdx < pElf64Header->NumSectionHeaderEntries; elfSectionIdx++)
429         {
430             indexedSectionHeaderOffset = (size_t)pElf64Header->SectionHeadersOffset + (elfSectionIdx * entrySize);
431 
432             pSectionHeader = (SElf64SectionHeader*)((char*)pElf64Header + indexedSectionHeaderOffset);
433             if (pSectionHeader->Name > textSectionHeaderName)
434             {
435                 pSectionHeader->Name += kernelNameWithDotSize;
436             }
437             if (pSectionHeader->DataOffset > textSectionNameOffset)
438             {
439                 pSectionHeader->DataOffset += kernelNameWithDotSize;
440                 // This data offset update may be not enough if such a section contains elf global offsets
441                 // (i.e. relative to the beginning of the elf binary).
442                 // However, as long as .strtab is the last section in our ELF binary then there is no side-effects.
443                 // If location of this section changes in the future, then a copy (or move) of this section content
444                 // will be required. This future need must be verified if the assertion below hits (then
445                 // assertion below must be changed based on results of such verification).
446                 IGC_ASSERT(0);
447             }
448         }
449 
450         if (pSectionHeader)
451         {
452             // ELF binary header also must be updated to reflect offsets changes.
453             if (pElf64Header->SectionHeadersOffset > pSectionHeader->DataOffset)
454             {
455                 pElf64Header->SectionHeadersOffset += kernelNameWithDotSize;
456             }
457             if (pElf64Header->ProgramHeadersOffset > pSectionHeader->DataOffset)
458             {
459                 pElf64Header->ProgramHeadersOffset += kernelNameWithDotSize;
460             }
461         }
462     }
463     else
464     {
465         IGC_ASSERT_MESSAGE(is64Bit, "64-bit ELF file only supported");
466     }
467 }
468 
setElfType(bool is64Bit,void * pBuffer)469 void DebugEmitter::setElfType(bool is64Bit, void* pBuffer)
470 {
471     // Set 1-step elf's e_type to ET_EXEC
472     if (!pBuffer)
473         return;
474 
475     if (is64Bit)
476     {
477         void* etypeOff = ((char*)pBuffer) + (offsetof(llvm::ELF::Elf64_Ehdr, e_type));
478         if (m_pStreamEmitter->GetEmitterSettings().EnableRelocation)
479         {
480             *((llvm::ELF::Elf64_Half*)etypeOff) = llvm::ELF::ET_REL;
481         }
482         else
483         {
484             *((llvm::ELF::Elf64_Half*)etypeOff) = llvm::ELF::ET_EXEC;
485         }
486     }
487     else
488     {
489         void* etypeOff = ((char*)pBuffer) + (offsetof(llvm::ELF::Elf32_Ehdr, e_type));
490         if (m_pStreamEmitter->GetEmitterSettings().EnableRelocation)
491         {
492             *((llvm::ELF::Elf32_Half*)etypeOff) = llvm::ELF::ET_REL;
493         }
494         else
495         {
496             *((llvm::ELF::Elf32_Half*)etypeOff) = llvm::ELF::ET_EXEC;
497         }
498     }
499 }
500 
writeProgramHeaderTable(bool is64Bit,void * pBuffer,unsigned int size)501 void DebugEmitter::writeProgramHeaderTable(bool is64Bit, void* pBuffer, unsigned int size)
502 {
503     // Write program header table at end of elf
504     if (is64Bit)
505     {
506         llvm::ELF::Elf64_Phdr hdr;
507         hdr.p_type = llvm::ELF::PT_LOAD;
508         hdr.p_flags = 0;
509         hdr.p_offset = 0;
510         hdr.p_vaddr = 0;
511         hdr.p_paddr = 0;
512         hdr.p_filesz = size;
513         hdr.p_memsz = size;
514         hdr.p_align = 4;
515         void* phOffAddr = ((char*)pBuffer) + (offsetof(llvm::ELF::Elf64_Ehdr, e_phoff));
516         *(llvm::ELF::Elf64_Off*)(phOffAddr) = size;
517         ((char*)pBuffer)[offsetof(llvm::ELF::Elf64_Ehdr, e_phentsize)] = sizeof(llvm::ELF::Elf64_Phdr);
518         ((char*)pBuffer)[offsetof(llvm::ELF::Elf64_Ehdr, e_phnum)] = 1;
519         memcpy_s((char*)pBuffer + size, sizeof(llvm::ELF::Elf64_Phdr), &hdr, sizeof(hdr));
520     }
521     else
522     {
523         llvm::ELF::Elf32_Phdr hdr;
524         hdr.p_type = llvm::ELF::PT_LOAD;
525         hdr.p_offset = 0;
526         hdr.p_vaddr = 0;
527         hdr.p_paddr = 0;
528         hdr.p_filesz = size;
529         hdr.p_memsz = size;
530         hdr.p_flags = 0;
531         hdr.p_align = 4;
532         void* phOffAddr = ((char*)pBuffer) + (offsetof(llvm::ELF::Elf32_Ehdr, e_phoff));
533         *(llvm::ELF::Elf32_Off*)(phOffAddr) = size;
534         ((char*)pBuffer)[offsetof(llvm::ELF::Elf32_Ehdr, e_phentsize)] = sizeof(llvm::ELF::Elf32_Phdr);
535         ((char*)pBuffer)[offsetof(llvm::ELF::Elf32_Ehdr, e_phnum)] = 1;
536         memcpy_s((char*)pBuffer + size, sizeof(llvm::ELF::Elf32_Phdr), &hdr, sizeof(hdr));
537     }
538 }
539 
BeginInstruction(Instruction * pInst)540 void DebugEmitter::BeginInstruction(Instruction* pInst)
541 {
542     BeginEncodingMark();
543     if (!m_debugEnabled)
544     {
545         return;
546     }
547     m_pVISAModule->BeginInstruction(pInst);
548 }
549 
EndInstruction(Instruction * pInst)550 void DebugEmitter::EndInstruction(Instruction* pInst)
551 {
552     EndEncodingMark();
553     if (!m_debugEnabled)
554     {
555         return;
556     }
557     m_pVISAModule->EndInstruction(pInst);
558 }
559 
BeginEncodingMark()560 void DebugEmitter::BeginEncodingMark()
561 {
562     m_pVISAModule->BeginEncodingMark();
563 }
564 
EndEncodingMark()565 void DebugEmitter::EndEncodingMark()
566 {
567     m_pVISAModule->EndEncodingMark();
568 }
569 // TODO: do we really need it?
registerVISA(IGC::VISAModule * VM)570 void DebugEmitter::registerVISA(IGC::VISAModule* VM)
571 {
572     m_pDwarfDebug->registerVISA(VM);
573 }
setCurrentVISA(IGC::VISAModule * VM)574 void DebugEmitter::setCurrentVISA(IGC::VISAModule* VM) {
575     // TODO: add assertion statement to check that this module is registered/owned
576     m_pVISAModule = VM;
577 }
resetModule(std::unique_ptr<IGC::VISAModule> VM)578 void DebugEmitter::resetModule(std::unique_ptr<IGC::VISAModule> VM) {
579     m_pVISAModule = VM.get();
580     toFree.push_back(std::move(VM));
581 }
582 
getErrors() const583 const std::string& DebugEmitter::getErrors() const {
584     return m_errs;
585 }
586