1 //===- DebugString.cpp ----------------------------------------------------===// 2 // 3 // The MCLinker Project 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 #include "mcld/LD/DebugString.h" 10 #include "mcld/LD/LDSection.h" 11 #include "mcld/LD/LDSymbol.h" 12 #include "mcld/LD/RelocData.h" 13 #include "mcld/LD/ResolveInfo.h" 14 #include "mcld/LD/SectionData.h" 15 #include "mcld/Fragment/Fragment.h" 16 #include "mcld/Fragment/RegionFragment.h" 17 #include "mcld/Fragment/Relocation.h" 18 #include "mcld/Target/TargetLDBackend.h" 19 #include "mcld/LD/Relocator.h" 20 21 #include <llvm/Support/Casting.h> 22 #include <llvm/Support/ManagedStatic.h> 23 24 namespace mcld { 25 26 // DebugString represents the output .debug_str section, which is at most on 27 // in each linking 28 static llvm::ManagedStatic<DebugString> g_DebugString; 29 30 static inline size_t string_length(const char* pStr) { 31 const char* p = pStr; 32 size_t len = 0; 33 for (; *p != 0; ++p) 34 ++len; 35 return len; 36 } 37 38 //========================== 39 // DebugString 40 void DebugString::merge(LDSection& pSection) { 41 // get the fragment contents 42 llvm::StringRef strings; 43 SectionData::iterator it, end = pSection.getSectionData()->end(); 44 for (it = pSection.getSectionData()->begin(); it != end; ++it) { 45 if ((*it).getKind() == Fragment::Region) { 46 RegionFragment* frag = llvm::cast<RegionFragment>(&(*it)); 47 strings = frag->getRegion().data(); 48 } 49 } 50 51 // get the debug strings and add them into merged string table 52 const char* str = strings.data(); 53 const char* str_end = str + pSection.size(); 54 while (str < str_end) { 55 size_t len = string_length(str); 56 m_StringTable.insertString(llvm::StringRef(str, len)); 57 str = str + len + 1; 58 } 59 } 60 61 size_t DebugString::computeOffsetSize() { 62 size_t size = m_StringTable.finalizeOffset(); 63 m_pSection->setSize(size); 64 return size; 65 } 66 67 void DebugString::applyOffset(Relocation& pReloc, TargetLDBackend& pBackend) { 68 // get the refered string 69 ResolveInfo* info = pReloc.symInfo(); 70 // the symbol should point to the first region fragment in the debug 71 // string section, get the input .debut_str region 72 llvm::StringRef d_str; 73 if (info->outSymbol()->fragRef()->frag()->getKind() == Fragment::Region) { 74 RegionFragment* frag = 75 llvm::cast<RegionFragment>(info->outSymbol()->fragRef()->frag()); 76 d_str = frag->getRegion(); 77 } 78 uint32_t offset = pBackend.getRelocator()->getDebugStringOffset(pReloc); 79 const char* str = d_str.data() + offset; 80 81 // apply the relocation 82 pBackend.getRelocator()->applyDebugStringOffset(pReloc, 83 m_StringTable.getOutputOffset(llvm::StringRef(str, string_length(str)))); 84 } 85 86 void DebugString::emit(MemoryRegion& pRegion) { 87 return m_StringTable.emit(pRegion); 88 } 89 90 DebugString* DebugString::Create(LDSection& pSection) { 91 g_DebugString->setOutputSection(pSection); 92 return &(*g_DebugString); 93 } 94 95 } // namespace mcld 96