Home | History | Annotate | Download | only in LD
      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