| //===- DebugString.cpp ----------------------------------------------------===// |
| // |
| // The MCLinker Project |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| #include "mcld/LD/DebugString.h" |
| #include "mcld/LD/LDSection.h" |
| #include "mcld/LD/LDSymbol.h" |
| #include "mcld/LD/RelocData.h" |
| #include "mcld/LD/ResolveInfo.h" |
| #include "mcld/LD/SectionData.h" |
| #include "mcld/Fragment/Fragment.h" |
| #include "mcld/Fragment/RegionFragment.h" |
| #include "mcld/Fragment/Relocation.h" |
| #include "mcld/Target/TargetLDBackend.h" |
| #include "mcld/LD/Relocator.h" |
| |
| #include <llvm/Support/Casting.h> |
| #include <llvm/Support/ManagedStatic.h> |
| |
| namespace mcld { |
| |
| // DebugString represents the output .debug_str section, which is at most on |
| // in each linking |
| static llvm::ManagedStatic<DebugString> g_DebugString; |
| |
| static inline size_t string_length(const char* pStr) { |
| const char* p = pStr; |
| size_t len = 0; |
| for (; *p != 0; ++p) |
| ++len; |
| return len; |
| } |
| |
| //========================== |
| // DebugString |
| void DebugString::merge(LDSection& pSection) { |
| // get the fragment contents |
| llvm::StringRef strings; |
| SectionData::iterator it, end = pSection.getSectionData()->end(); |
| for (it = pSection.getSectionData()->begin(); it != end; ++it) { |
| if ((*it).getKind() == Fragment::Region) { |
| RegionFragment* frag = llvm::cast<RegionFragment>(&(*it)); |
| strings = frag->getRegion().data(); |
| } |
| } |
| |
| // get the debug strings and add them into merged string table |
| const char* str = strings.data(); |
| const char* str_end = str + pSection.size(); |
| while (str < str_end) { |
| size_t len = string_length(str); |
| m_StringTable.insertString(llvm::StringRef(str, len)); |
| str = str + len + 1; |
| } |
| } |
| |
| size_t DebugString::computeOffsetSize() { |
| size_t size = m_StringTable.finalizeOffset(); |
| m_pSection->setSize(size); |
| return size; |
| } |
| |
| void DebugString::applyOffset(Relocation& pReloc, TargetLDBackend& pBackend) { |
| // get the refered string |
| ResolveInfo* info = pReloc.symInfo(); |
| // the symbol should point to the first region fragment in the debug |
| // string section, get the input .debut_str region |
| llvm::StringRef d_str; |
| if (info->outSymbol()->fragRef()->frag()->getKind() == Fragment::Region) { |
| RegionFragment* frag = |
| llvm::cast<RegionFragment>(info->outSymbol()->fragRef()->frag()); |
| d_str = frag->getRegion(); |
| } |
| uint32_t offset = pBackend.getRelocator()->getDebugStringOffset(pReloc); |
| const char* str = d_str.data() + offset; |
| |
| // apply the relocation |
| pBackend.getRelocator()->applyDebugStringOffset(pReloc, |
| m_StringTable.getOutputOffset(llvm::StringRef(str, string_length(str)))); |
| } |
| |
| void DebugString::emit(MemoryRegion& pRegion) { |
| return m_StringTable.emit(pRegion); |
| } |
| |
| DebugString* DebugString::Create(LDSection& pSection) { |
| g_DebugString->setOutputSection(pSection); |
| return &(*g_DebugString); |
| } |
| |
| } // namespace mcld |