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 
string_length(const char * pStr)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
merge(LDSection & pSection)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 
computeOffsetSize()61 size_t DebugString::computeOffsetSize() {
62   size_t size = m_StringTable.finalizeOffset();
63   m_pSection->setSize(size);
64   return size;
65 }
66 
applyOffset(Relocation & pReloc,TargetLDBackend & pBackend)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 
emit(MemoryRegion & pRegion)86 void DebugString::emit(MemoryRegion& pRegion) {
87   return m_StringTable.emit(pRegion);
88 }
89 
Create(LDSection & pSection)90 DebugString* DebugString::Create(LDSection& pSection) {
91   g_DebugString->setOutputSection(pSection);
92   return &(*g_DebugString);
93 }
94 
95 }  // namespace mcld
96