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
24namespace mcld {
25
26// DebugString represents the output .debug_str section, which is at most on
27// in each linking
28static llvm::ManagedStatic<DebugString> g_DebugString;
29
30static 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
40void 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
61size_t DebugString::computeOffsetSize() {
62  size_t size = m_StringTable.finalizeOffset();
63  m_pSection->setSize(size);
64  return size;
65}
66
67void 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
86void DebugString::emit(MemoryRegion& pRegion) {
87  return m_StringTable.emit(pRegion);
88}
89
90DebugString* DebugString::Create(LDSection& pSection) {
91  g_DebugString->setOutputSection(pSection);
92  return &(*g_DebugString);
93}
94
95}  // namespace mcld
96