C++程序  |  96行  |  2.96 KB

//===- 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