15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- ELFObjectWriter.cpp ------------------------------------------------===//
25460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
35460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//                     The MCLinker Project
45460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
55460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// This file is distributed under the University of Illinois Open Source
65460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// License. See LICENSE.TXT for details.
75460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
85460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===//
937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ELFObjectWriter.h"
1037b74a387bb3993387029859c2d9d051c41c724eStephen Hines
1137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LinkerConfig.h"
1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LinkerScript.h"
1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Module.h"
1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/ADT/SizeTraits.h"
1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/AlignFragment.h"
1637b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/FillFragment.h"
1737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/NullFragment.h"
1837b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/RegionFragment.h"
1937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/Stub.h"
2037b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/DebugString.h"
2137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/EhFrame.h"
2237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ELFFileFormat.h"
2337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ELFSegment.h"
2437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ELFSegmentFactory.h"
2537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDSection.h"
2637b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDSymbol.h"
2737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/RelocData.h"
2837b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/SectionData.h"
2937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MsgHandling.h"
3037b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Target/GNUInfo.h"
3137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Target/GNULDBackend.h"
3222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
3337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <llvm/Support/Casting.h>
3437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <llvm/Support/ELF.h>
350dea6bc96bb52346737966839ac68644f7939f58Stephen Hines#include <llvm/Support/Errc.h>
366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <llvm/Support/ErrorHandling.h>
37d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
3837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld {
395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// ELFObjectWriter
4222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
4322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoELFObjectWriter::ELFObjectWriter(GNULDBackend& pBackend,
44d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao                                 const LinkerConfig& pConfig)
4537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : ObjectWriter(), m_Backend(pBackend), m_Config(pConfig) {
465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4837b74a387bb3993387029859c2d9d051c41c724eStephen HinesELFObjectWriter::~ELFObjectWriter() {
495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5187f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid ELFObjectWriter::writeSection(Module& pModule,
5237b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                   FileOutputBuffer& pOutput,
5337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                   LDSection* section) {
5487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  MemoryRegion region;
556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // Request output region
566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  switch (section->kind()) {
5737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case LDFileFormat::Note:
5837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      if (section->getSectionData() == NULL)
5937b74a387bb3993387029859c2d9d051c41c724eStephen Hines        return;
606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // Fall through
6137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case LDFileFormat::TEXT:
6237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case LDFileFormat::DATA:
6337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case LDFileFormat::Relocation:
6437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case LDFileFormat::Target:
6537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case LDFileFormat::Debug:
6637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case LDFileFormat::DebugString:
6737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case LDFileFormat::GCCExceptTable:
6837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case LDFileFormat::EhFrame: {
6937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      region = pOutput.request(section->offset(), section->size());
7037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      if (region.size() == 0) {
7137b74a387bb3993387029859c2d9d051c41c724eStephen Hines        return;
7237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      }
7337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      break;
746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
7537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case LDFileFormat::Null:
7637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case LDFileFormat::NamePool:
7737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case LDFileFormat::BSS:
7837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case LDFileFormat::MetaData:
7937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case LDFileFormat::Version:
8037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case LDFileFormat::EhFrameHdr:
8137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case LDFileFormat::StackNote:
8237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      // Ignore these sections
8337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      return;
8437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    default:
8537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::errs() << "WARNING: unsupported section kind: " << section->kind()
8637b74a387bb3993387029859c2d9d051c41c724eStephen Hines                   << " of section " << section->name() << ".\n";
8737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      return;
886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // Write out sections with data
9137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  switch (section->kind()) {
9237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case LDFileFormat::GCCExceptTable:
9337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case LDFileFormat::TEXT:
9437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case LDFileFormat::DATA:
9537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case LDFileFormat::Debug:
9637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case LDFileFormat::Note:
9737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      emitSectionData(*section, region);
9837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      break;
9937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case LDFileFormat::EhFrame:
10037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      emitEhFrame(pModule, *section->getEhFrame(), region);
10137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      break;
10237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case LDFileFormat::Relocation:
10337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      // sort relocation for the benefit of the dynamic linker.
10437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      target().sortRelocation(*section);
10537b74a387bb3993387029859c2d9d051c41c724eStephen Hines
10637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      emitRelocation(m_Config, *section, region);
10737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      break;
10837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case LDFileFormat::Target:
10937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      target().emitSectionData(*section, region);
11037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      break;
11137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case LDFileFormat::DebugString:
11237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      section->getDebugString()->emit(region);
11337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      break;
11437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    default:
11537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm_unreachable("invalid section kind");
1166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
1176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
1186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1190dea6bc96bb52346737966839ac68644f7939f58Stephen Hinesstd::error_code ELFObjectWriter::writeObject(Module& pModule,
12037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                             FileOutputBuffer& pOutput) {
1216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  bool is_dynobj = m_Config.codeGenType() == LinkerConfig::DynObj;
1226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  bool is_exec = m_Config.codeGenType() == LinkerConfig::Exec;
1236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  bool is_binary = m_Config.codeGenType() == LinkerConfig::Binary;
1246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  bool is_object = m_Config.codeGenType() == LinkerConfig::Object;
1256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  assert(is_dynobj || is_exec || is_binary || is_object);
1276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (is_dynobj || is_exec) {
129f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // Allow backend to sort symbols before emitting
130f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    target().orderSymbolTable(pModule);
131f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // Write out the interpreter section: .interp
1336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    target().emitInterp(pOutput);
1346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // Write out name pool sections: .dynsym, .dynstr, .hash
1366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    target().emitDynNamePools(pModule, pOutput);
1376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
1386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (is_object || is_dynobj || is_exec) {
1406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // Write out name pool sections: .symtab, .strtab
1416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    target().emitRegNamePools(pModule, pOutput);
1426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
1436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (is_binary) {
1456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // Iterate over the loadable segments and write the corresponding sections
1466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    ELFSegmentFactory::iterator seg, segEnd = target().elfSegmentTable().end();
1476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    for (seg = target().elfSegmentTable().begin(); seg != segEnd; ++seg) {
14987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (llvm::ELF::PT_LOAD == (*seg)->type()) {
15087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        ELFSegment::iterator sect, sectEnd = (*seg)->end();
15187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        for (sect = (*seg)->begin(); sect != sectEnd; ++sect)
15287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          writeSection(pModule, pOutput, *sect);
15322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      }
15422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
1556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  } else {
1566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // Write out regular ELF sections
1576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    Module::iterator sect, sectEnd = pModule.end();
1586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    for (sect = pModule.begin(); sect != sectEnd; ++sect)
15987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      writeSection(pModule, pOutput, *sect);
16022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
1616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    emitShStrTab(target().getOutputFormat()->getShStrTab(), pModule, pOutput);
1626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (m_Config.targets().is32Bits()) {
1646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      // Write out ELF header
1656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      // Write out section header table
1666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      writeELFHeader<32>(m_Config, pModule, pOutput);
1676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      if (is_dynobj || is_exec)
1686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        emitProgramHeader<32>(pOutput);
1696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      emitSectionHeader<32>(pModule, m_Config, pOutput);
17137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    } else if (m_Config.targets().is64Bits()) {
1726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      // Write out ELF header
1736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      // Write out section header table
1746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      writeELFHeader<64>(m_Config, pModule, pOutput);
1756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      if (is_dynobj || is_exec)
1766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        emitProgramHeader<64>(pOutput);
1776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      emitSectionHeader<64>(pModule, m_Config, pOutput);
17937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    } else {
1800dea6bc96bb52346737966839ac68644f7939f58Stephen Hines      return llvm::make_error_code(llvm::errc::function_not_supported);
18137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    }
1826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
1836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1840dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  return std::error_code();
1856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
1866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
18787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// getOutputSize - count the final output size
18837b74a387bb3993387029859c2d9d051c41c724eStephen Hinessize_t ELFObjectWriter::getOutputSize(const Module& pModule) const {
18987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (m_Config.targets().is32Bits()) {
19087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return getLastStartOffset<32>(pModule) +
19187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines           sizeof(ELFSizeTraits<32>::Shdr) * pModule.size();
19287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  } else if (m_Config.targets().is64Bits()) {
19387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return getLastStartOffset<64>(pModule) +
19487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines           sizeof(ELFSizeTraits<64>::Shdr) * pModule.size();
19587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  } else {
19687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    assert(0 && "Invalid ELF Class");
19787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return 0;
19887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
19987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
20087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
2016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// writeELFHeader - emit ElfXX_Ehdr
20237b74a387bb3993387029859c2d9d051c41c724eStephen Hinestemplate <size_t SIZE>
2036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid ELFObjectWriter::writeELFHeader(const LinkerConfig& pConfig,
2046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                     const Module& pModule,
20537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                     FileOutputBuffer& pOutput) const {
2066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  typedef typename ELFSizeTraits<SIZE>::Ehdr ElfXX_Ehdr;
2076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  typedef typename ELFSizeTraits<SIZE>::Shdr ElfXX_Shdr;
2086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  typedef typename ELFSizeTraits<SIZE>::Phdr ElfXX_Phdr;
2096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // ELF header must start from 0x0
21187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  MemoryRegion region = pOutput.request(0, sizeof(ElfXX_Ehdr));
21237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  ElfXX_Ehdr* header = reinterpret_cast<ElfXX_Ehdr*>(region.begin());
2136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
21437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  memcpy(header->e_ident, llvm::ELF::ElfMagic, llvm::ELF::EI_MAG3 + 1);
2156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
21637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  header->e_ident[llvm::ELF::EI_CLASS] =
21737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      (SIZE == 32) ? llvm::ELF::ELFCLASS32 : llvm::ELF::ELFCLASS64;
21837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  header->e_ident[llvm::ELF::EI_DATA] =
21937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pConfig.targets().isLittleEndian()
22037b74a387bb3993387029859c2d9d051c41c724eStephen Hines          ? llvm::ELF::ELFDATA2LSB : llvm::ELF::ELFDATA2MSB;
22137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  header->e_ident[llvm::ELF::EI_VERSION] = target().getInfo().ELFVersion();
22237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  header->e_ident[llvm::ELF::EI_OSABI] = target().getInfo().OSABI();
22337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  header->e_ident[llvm::ELF::EI_ABIVERSION] = target().getInfo().ABIVersion();
2246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // FIXME: add processor-specific and core file types.
22637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  switch (pConfig.codeGenType()) {
2276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    case LinkerConfig::Object:
22837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      header->e_type = llvm::ELF::ET_REL;
2296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      break;
2306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    case LinkerConfig::DynObj:
23137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      header->e_type = llvm::ELF::ET_DYN;
2326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      break;
2336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    case LinkerConfig::Exec:
23437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      header->e_type = llvm::ELF::ET_EXEC;
2356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      break;
2366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    default:
23737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::errs() << "unspported output file type: " << pConfig.codeGenType()
23837b74a387bb3993387029859c2d9d051c41c724eStephen Hines                   << ".\n";
23937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      header->e_type = llvm::ELF::ET_NONE;
2406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
24137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  header->e_machine = target().getInfo().machine();
24237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  header->e_version = header->e_ident[llvm::ELF::EI_VERSION];
24337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  header->e_entry = getEntryPoint(pConfig, pModule);
2446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (LinkerConfig::Object != pConfig.codeGenType())
24637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    header->e_phoff = sizeof(ElfXX_Ehdr);
2476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  else
24837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    header->e_phoff = 0x0;
2496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
25037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  header->e_shoff = getLastStartOffset<SIZE>(pModule);
25137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  header->e_flags = target().getInfo().flags();
25237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  header->e_ehsize = sizeof(ElfXX_Ehdr);
2536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  header->e_phentsize = sizeof(ElfXX_Phdr);
25437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  header->e_phnum = target().elfSegmentTable().size();
2556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  header->e_shentsize = sizeof(ElfXX_Shdr);
25637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  header->e_shnum = pModule.size();
25737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  header->e_shstrndx = pModule.getSection(".shstrtab")->index();
2586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
2596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// getEntryPoint
2616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesuint64_t ELFObjectWriter::getEntryPoint(const LinkerConfig& pConfig,
26237b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                        const Module& pModule) const {
26387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  llvm::StringRef entry_name = target().getEntry(pModule);
2646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t result = 0x0;
2656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
26687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  bool issue_warning = (pModule.getScript().hasEntry() &&
2676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                        LinkerConfig::Object != pConfig.codeGenType() &&
2686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                        LinkerConfig::DynObj != pConfig.codeGenType());
2696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const LDSymbol* entry_symbol = pModule.getNamePool().findSymbol(entry_name);
2716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // found the symbol
27337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (entry_symbol != NULL) {
2746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (entry_symbol->desc() != ResolveInfo::Define && issue_warning) {
27537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      llvm::errs() << "WARNING: entry symbol '" << entry_symbol->name()
2766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                   << "' exists but is not defined.\n";
2776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
2786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    result = entry_symbol->value();
27937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else {
28037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    // not in the symbol pool
2816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // We should parse entry as a number.
2826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // @ref GNU ld manual, Options -e. e.g., -e 0x1000.
2836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    char* endptr;
2846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    result = strtoull(entry_name.data(), &endptr, 0);
2856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (*endptr != '\0') {
2866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      if (issue_warning) {
28737b74a387bb3993387029859c2d9d051c41c724eStephen Hines        llvm::errs() << "cannot find entry symbol '" << entry_name.data()
2886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                     << "'.\n";
28922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      }
2906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      result = 0x0;
29122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
2926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
2936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return result;
2946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
29522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
2966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// emitSectionHeader - emit ElfXX_Shdr
29737b74a387bb3993387029859c2d9d051c41c724eStephen Hinestemplate <size_t SIZE>
2986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid ELFObjectWriter::emitSectionHeader(const Module& pModule,
2996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                        const LinkerConfig& pConfig,
30037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                        FileOutputBuffer& pOutput) const {
3016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  typedef typename ELFSizeTraits<SIZE>::Shdr ElfXX_Shdr;
30222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
3036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // emit section header
3046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  unsigned int sectNum = pModule.size();
3056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  unsigned int header_size = sizeof(ElfXX_Shdr) * sectNum;
30637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  MemoryRegion region =
30737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pOutput.request(getLastStartOffset<SIZE>(pModule), header_size);
30837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  ElfXX_Shdr* shdr = reinterpret_cast<ElfXX_Shdr*>(region.begin());
30922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
3106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // Iterate the SectionTable in LDContext
3116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  unsigned int sectIdx = 0;
31237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  unsigned int shstridx = 0;  // NULL section has empty name
3136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  for (; sectIdx < sectNum; ++sectIdx) {
31437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    const LDSection* ld_sect = pModule.getSectionTable().at(sectIdx);
31537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    shdr[sectIdx].sh_name = shstridx;
31637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    shdr[sectIdx].sh_type = ld_sect->type();
31737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    shdr[sectIdx].sh_flags = ld_sect->flag();
31837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    shdr[sectIdx].sh_addr = ld_sect->addr();
31937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    shdr[sectIdx].sh_offset = ld_sect->offset();
32037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    shdr[sectIdx].sh_size = ld_sect->size();
3216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shdr[sectIdx].sh_addralign = ld_sect->align();
32237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    shdr[sectIdx].sh_entsize = getSectEntrySize<SIZE>(*ld_sect);
32337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    shdr[sectIdx].sh_link = getSectLink(*ld_sect, pConfig);
32437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    shdr[sectIdx].sh_info = getSectInfo(*ld_sect);
3256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // adjust strshidx
3276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shstridx += ld_sect->name().size() + 1;
32822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
3296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
3306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// emitProgramHeader - emit ElfXX_Phdr
33237b74a387bb3993387029859c2d9d051c41c724eStephen Hinestemplate <size_t SIZE>
33337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid ELFObjectWriter::emitProgramHeader(FileOutputBuffer& pOutput) const {
3346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  typedef typename ELFSizeTraits<SIZE>::Ehdr ElfXX_Ehdr;
3356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  typedef typename ELFSizeTraits<SIZE>::Phdr ElfXX_Phdr;
3366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t start_offset, phdr_size;
33822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
3396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  start_offset = sizeof(ElfXX_Ehdr);
3406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  phdr_size = sizeof(ElfXX_Phdr);
3416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // Program header must start directly after ELF header
34237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  MemoryRegion region = pOutput.request(
34337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      start_offset, target().elfSegmentTable().size() * phdr_size);
3446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
34537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  ElfXX_Phdr* phdr = reinterpret_cast<ElfXX_Phdr*>(region.begin());
3466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // Iterate the elf segment table in GNULDBackend
3486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  size_t index = 0;
3496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  ELFSegmentFactory::const_iterator seg = target().elfSegmentTable().begin(),
35037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                    segEnd = target().elfSegmentTable().end();
3516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  for (; seg != segEnd; ++seg, ++index) {
35237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    phdr[index].p_type = (*seg)->type();
35337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    phdr[index].p_flags = (*seg)->flag();
35487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    phdr[index].p_offset = (*seg)->offset();
35537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    phdr[index].p_vaddr = (*seg)->vaddr();
35637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    phdr[index].p_paddr = (*seg)->paddr();
35787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    phdr[index].p_filesz = (*seg)->filesz();
35837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    phdr[index].p_memsz = (*seg)->memsz();
35937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    phdr[index].p_align = (*seg)->align();
36022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
3616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
36222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
3636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// emitShStrTab - emit section string table
36437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid ELFObjectWriter::emitShStrTab(const LDSection& pShStrTab,
36537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                   const Module& pModule,
36637b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                   FileOutputBuffer& pOutput) {
3676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // write out data
36887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  MemoryRegion region = pOutput.request(pShStrTab.offset(), pShStrTab.size());
36937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  char* data = reinterpret_cast<char*>(region.begin());
3706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  size_t shstrsize = 0;
3716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Module::const_iterator section, sectEnd = pModule.end();
3726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  for (section = pModule.begin(); section != sectEnd; ++section) {
37337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    ::memcpy(reinterpret_cast<char*>(data + shstrsize),
37437b74a387bb3993387029859c2d9d051c41c724eStephen Hines             (*section)->name().data(),
37537b74a387bb3993387029859c2d9d051c41c724eStephen Hines             (*section)->name().size());
3766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shstrsize += (*section)->name().size() + 1;
3776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
3786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
3796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// emitSectionData
38137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid ELFObjectWriter::emitSectionData(const LDSection& pSection,
38237b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      MemoryRegion& pRegion) const {
3836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const SectionData* sd = NULL;
3846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  switch (pSection.kind()) {
3856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    case LDFileFormat::Relocation:
3866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      assert(pSection.hasRelocData());
3876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      return;
3886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    case LDFileFormat::EhFrame:
3896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      assert(pSection.hasEhFrame());
390f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      sd = pSection.getEhFrame()->getSectionData();
3916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      break;
3926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    default:
3936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      assert(pSection.hasSectionData());
3946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sd = pSection.getSectionData();
3956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      break;
3966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
3976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  emitSectionData(*sd, pRegion);
3986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
3996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
40087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines/// emitEhFrame
40187f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid ELFObjectWriter::emitEhFrame(Module& pModule,
40237b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                  EhFrame& pFrame,
40337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                  MemoryRegion& pRegion) const {
40487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  emitSectionData(*pFrame.getSectionData(), pRegion);
40587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
40687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Patch FDE field (offset to CIE)
40787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  for (EhFrame::cie_iterator i = pFrame.cie_begin(), e = pFrame.cie_end();
40837b74a387bb3993387029859c2d9d051c41c724eStephen Hines       i != e;
40937b74a387bb3993387029859c2d9d051c41c724eStephen Hines       ++i) {
41087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    EhFrame::CIE& cie = **i;
41137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    for (EhFrame::fde_iterator fi = cie.begin(), fe = cie.end(); fi != fe;
41237b74a387bb3993387029859c2d9d051c41c724eStephen Hines         ++fi) {
41387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      EhFrame::FDE& fde = **fi;
41487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (fde.getRecordType() == EhFrame::RECORD_GENERATED) {
41587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // Patch PLT offset
41687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        LDSection* plt_sect = pModule.getSection(".plt");
41737b74a387bb3993387029859c2d9d051c41c724eStephen Hines        assert(plt_sect && "We have no plt but have corresponding eh_frame?");
41887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        uint64_t plt_offset = plt_sect->offset();
41987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // FDE entry for PLT is always 32-bit
42087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        uint64_t fde_offset = pFrame.getSection().offset() + fde.getOffset() +
42187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                              EhFrame::getDataStartOffset<32>();
42287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        int32_t offset = fde_offset - plt_offset;
42387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        if (plt_offset < fde_offset)
42487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          offset = -offset;
42587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        memcpy(pRegion.begin() + fde.getOffset() +
42637b74a387bb3993387029859c2d9d051c41c724eStephen Hines                   EhFrame::getDataStartOffset<32>(),
42737b74a387bb3993387029859c2d9d051c41c724eStephen Hines               &offset,
42837b74a387bb3993387029859c2d9d051c41c724eStephen Hines               4);
42987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        uint32_t size = plt_sect->size();
43087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        memcpy(pRegion.begin() + fde.getOffset() +
43137b74a387bb3993387029859c2d9d051c41c724eStephen Hines                   EhFrame::getDataStartOffset<32>() + 4,
43237b74a387bb3993387029859c2d9d051c41c724eStephen Hines               &size,
43337b74a387bb3993387029859c2d9d051c41c724eStephen Hines               4);
43487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
43587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      uint64_t fde_cie_ptr_offset = fde.getOffset() +
43687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                    EhFrame::getDataStartOffset<32>() -
43737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                    /*ID*/ 4;
43887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      uint64_t cie_start_offset = cie.getOffset();
43987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      int32_t offset = fde_cie_ptr_offset - cie_start_offset;
44087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (fde_cie_ptr_offset < cie_start_offset)
44187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        offset = -offset;
44287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      memcpy(pRegion.begin() + fde_cie_ptr_offset, &offset, 4);
44337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    }  // for loop fde_iterator
44437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  }    // for loop cie_iterator
44587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
44687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
4476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// emitRelocation
4486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid ELFObjectWriter::emitRelocation(const LinkerConfig& pConfig,
4496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                     const LDSection& pSection,
45037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                     MemoryRegion& pRegion) const {
4516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const RelocData* sect_data = pSection.getRelocData();
45237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(sect_data != NULL && "SectionData is NULL in emitRelocation!");
4536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
45437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (pSection.type() == llvm::ELF::SHT_REL) {
4556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (pConfig.targets().is32Bits())
4566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      emitRel<32>(pConfig, *sect_data, pRegion);
4576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else if (pConfig.targets().is64Bits())
4586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      emitRel<64>(pConfig, *sect_data, pRegion);
4596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else {
4606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      fatal(diag::unsupported_bitclass) << pConfig.targets().triple().str()
4616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                        << pConfig.targets().bitclass();
4626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
46337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else if (pSection.type() == llvm::ELF::SHT_RELA) {
4646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (pConfig.targets().is32Bits())
4656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      emitRela<32>(pConfig, *sect_data, pRegion);
4666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else if (pConfig.targets().is64Bits())
4676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      emitRela<64>(pConfig, *sect_data, pRegion);
4686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else {
4696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      fatal(diag::unsupported_bitclass) << pConfig.targets().triple().str()
4706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                        << pConfig.targets().bitclass();
4716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
4726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  } else
4736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    llvm::report_fatal_error("unsupported relocation section type!");
4746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
4756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
4766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// emitRel - emit ElfXX_Rel
47737b74a387bb3993387029859c2d9d051c41c724eStephen Hinestemplate <size_t SIZE>
4786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid ELFObjectWriter::emitRel(const LinkerConfig& pConfig,
4796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                              const RelocData& pRelocData,
48037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                              MemoryRegion& pRegion) const {
48137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  typedef typename ELFSizeTraits<SIZE>::Rel ElfXX_Rel;
4826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  typedef typename ELFSizeTraits<SIZE>::Addr ElfXX_Addr;
4836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  typedef typename ELFSizeTraits<SIZE>::Word ElfXX_Word;
4846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
48587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ElfXX_Rel* rel = reinterpret_cast<ElfXX_Rel*>(pRegion.begin());
4866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
4876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const Relocation* relocation = 0;
4886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const FragmentRef* frag_ref = 0;
4896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
49037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  for (RelocData::const_iterator it = pRelocData.begin(), ie = pRelocData.end();
49137b74a387bb3993387029859c2d9d051c41c724eStephen Hines       it != ie;
49237b74a387bb3993387029859c2d9d051c41c724eStephen Hines       ++it, ++rel) {
49387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    ElfXX_Addr r_offset = 0;
49487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    ElfXX_Word r_sym = 0;
4956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
4966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    relocation = &(llvm::cast<Relocation>(*it));
4976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    frag_ref = &(relocation->targetRef());
4986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
49937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (LinkerConfig::DynObj == pConfig.codeGenType() ||
50037b74a387bb3993387029859c2d9d051c41c724eStephen Hines        LinkerConfig::Exec == pConfig.codeGenType()) {
50187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      r_offset = static_cast<ElfXX_Addr>(
50237b74a387bb3993387029859c2d9d051c41c724eStephen Hines          frag_ref->frag()->getParent()->getSection().addr() +
50337b74a387bb3993387029859c2d9d051c41c724eStephen Hines          frag_ref->getOutputOffset());
50437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    } else {
50587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      r_offset = static_cast<ElfXX_Addr>(frag_ref->getOutputOffset());
5066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
50787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
50837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (relocation->symInfo() == NULL)
50987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      r_sym = 0;
5106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else
51187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      r_sym = static_cast<ElfXX_Word>(
51237b74a387bb3993387029859c2d9d051c41c724eStephen Hines          target().getSymbolIdx(relocation->symInfo()->outSymbol()));
5136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
51487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    target().emitRelocation(*rel, relocation->type(), r_sym, r_offset);
5156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
5166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
5176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
5186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// emitRela - emit ElfXX_Rela
51937b74a387bb3993387029859c2d9d051c41c724eStephen Hinestemplate <size_t SIZE>
5206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid ELFObjectWriter::emitRela(const LinkerConfig& pConfig,
5216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                               const RelocData& pRelocData,
52237b74a387bb3993387029859c2d9d051c41c724eStephen Hines                               MemoryRegion& pRegion) const {
5236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  typedef typename ELFSizeTraits<SIZE>::Rela ElfXX_Rela;
5246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  typedef typename ELFSizeTraits<SIZE>::Addr ElfXX_Addr;
5256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  typedef typename ELFSizeTraits<SIZE>::Word ElfXX_Word;
5266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
52787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ElfXX_Rela* rel = reinterpret_cast<ElfXX_Rela*>(pRegion.begin());
5286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
5296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const Relocation* relocation = 0;
5306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const FragmentRef* frag_ref = 0;
5316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
53237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  for (RelocData::const_iterator it = pRelocData.begin(), ie = pRelocData.end();
53337b74a387bb3993387029859c2d9d051c41c724eStephen Hines       it != ie;
53437b74a387bb3993387029859c2d9d051c41c724eStephen Hines       ++it, ++rel) {
53587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    ElfXX_Addr r_offset = 0;
53687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    ElfXX_Word r_sym = 0;
5376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
5386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    relocation = &(llvm::cast<Relocation>(*it));
5396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    frag_ref = &(relocation->targetRef());
5406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
54137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (LinkerConfig::DynObj == pConfig.codeGenType() ||
54237b74a387bb3993387029859c2d9d051c41c724eStephen Hines        LinkerConfig::Exec == pConfig.codeGenType()) {
54387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      r_offset = static_cast<ElfXX_Addr>(
54437b74a387bb3993387029859c2d9d051c41c724eStephen Hines          frag_ref->frag()->getParent()->getSection().addr() +
54537b74a387bb3993387029859c2d9d051c41c724eStephen Hines          frag_ref->getOutputOffset());
54637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    } else {
54787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      r_offset = static_cast<ElfXX_Addr>(frag_ref->getOutputOffset());
5486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
5496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
55037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (relocation->symInfo() == NULL)
55187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      r_sym = 0;
5526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else
55387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      r_sym = static_cast<ElfXX_Word>(
55437b74a387bb3993387029859c2d9d051c41c724eStephen Hines          target().getSymbolIdx(relocation->symInfo()->outSymbol()));
5556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
55637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    target().emitRelocation(
55737b74a387bb3993387029859c2d9d051c41c724eStephen Hines        *rel, relocation->type(), r_sym, r_offset, relocation->addend());
5586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
5596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
5606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
5616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// getSectEntrySize - compute ElfXX_Shdr::sh_entsize
56237b74a387bb3993387029859c2d9d051c41c724eStephen Hinestemplate <size_t SIZE>
56337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesuint64_t ELFObjectWriter::getSectEntrySize(const LDSection& pSection) const {
5646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  typedef typename ELFSizeTraits<SIZE>::Word ElfXX_Word;
56537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  typedef typename ELFSizeTraits<SIZE>::Sym ElfXX_Sym;
56637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  typedef typename ELFSizeTraits<SIZE>::Rel ElfXX_Rel;
5676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  typedef typename ELFSizeTraits<SIZE>::Rela ElfXX_Rela;
56837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  typedef typename ELFSizeTraits<SIZE>::Dyn ElfXX_Dyn;
5696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
5706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (llvm::ELF::SHT_DYNSYM == pSection.type() ||
5716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      llvm::ELF::SHT_SYMTAB == pSection.type())
5726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return sizeof(ElfXX_Sym);
5736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (llvm::ELF::SHT_REL == pSection.type())
5746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return sizeof(ElfXX_Rel);
5756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (llvm::ELF::SHT_RELA == pSection.type())
5766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return sizeof(ElfXX_Rela);
57737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (llvm::ELF::SHT_HASH == pSection.type() ||
5786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      llvm::ELF::SHT_GNU_HASH == pSection.type())
5796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return sizeof(ElfXX_Word);
5806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (llvm::ELF::SHT_DYNAMIC == pSection.type())
5816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return sizeof(ElfXX_Dyn);
58287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // FIXME: We should get the entsize from input since the size of each
58387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // character is specified in the section header's sh_entsize field.
58487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // For example, traditional string is 0x1, UCS-2 is 0x2, ... and so on.
58587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Ref: http://www.sco.com/developers/gabi/2003-12-17/ch4.sheader.html
58687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (pSection.flag() & llvm::ELF::SHF_STRINGS)
58787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return 0x1;
5886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return 0x0;
5896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
5906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
5916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// getSectLink - compute ElfXX_Shdr::sh_link
5926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesuint64_t ELFObjectWriter::getSectLink(const LDSection& pSection,
59337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      const LinkerConfig& pConfig) const {
5946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (llvm::ELF::SHT_SYMTAB == pSection.type())
5956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return target().getOutputFormat()->getStrTab().index();
5966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (llvm::ELF::SHT_DYNSYM == pSection.type())
5976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return target().getOutputFormat()->getDynStrTab().index();
5986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (llvm::ELF::SHT_DYNAMIC == pSection.type())
5996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return target().getOutputFormat()->getDynStrTab().index();
60037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (llvm::ELF::SHT_HASH == pSection.type() ||
6016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      llvm::ELF::SHT_GNU_HASH == pSection.type())
6026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return target().getOutputFormat()->getDynSymTab().index();
6036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (llvm::ELF::SHT_REL == pSection.type() ||
6046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      llvm::ELF::SHT_RELA == pSection.type()) {
6056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (LinkerConfig::Object == pConfig.codeGenType())
6066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      return target().getOutputFormat()->getSymTab().index();
6076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else
6086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      return target().getOutputFormat()->getDynSymTab().index();
6096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
6106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // FIXME: currently we link ARM_EXIDX section to output text section here
6116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (llvm::ELF::SHT_ARM_EXIDX == pSection.type())
6126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return target().getOutputFormat()->getText().index();
6136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return llvm::ELF::SHN_UNDEF;
6146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
6156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// getSectInfo - compute ElfXX_Shdr::sh_info
61737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesuint64_t ELFObjectWriter::getSectInfo(const LDSection& pSection) const {
6186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (llvm::ELF::SHT_SYMTAB == pSection.type() ||
6196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      llvm::ELF::SHT_DYNSYM == pSection.type())
6206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return pSection.getInfo();
6216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (llvm::ELF::SHT_REL == pSection.type() ||
6236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      llvm::ELF::SHT_RELA == pSection.type()) {
6246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    const LDSection* info_link = pSection.getLink();
62537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (info_link != NULL)
6266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      return info_link->index();
6276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
6286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return 0x0;
6306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
6316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// getLastStartOffset
63337b74a387bb3993387029859c2d9d051c41c724eStephen Hinestemplate <>
63437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesuint64_t ELFObjectWriter::getLastStartOffset<32>(const Module& pModule) const {
6356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const LDSection* lastSect = pModule.back();
6366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  assert(lastSect != NULL);
6376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return Align<32>(lastSect->offset() + lastSect->size());
6386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
6396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// getLastStartOffset
64137b74a387bb3993387029859c2d9d051c41c724eStephen Hinestemplate <>
64237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesuint64_t ELFObjectWriter::getLastStartOffset<64>(const Module& pModule) const {
6436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const LDSection* lastSect = pModule.back();
6446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  assert(lastSect != NULL);
6456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return Align<64>(lastSect->offset() + lastSect->size());
6466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
6476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// emitSectionData
6496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid ELFObjectWriter::emitSectionData(const SectionData& pSD,
65037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      MemoryRegion& pRegion) const {
6516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  SectionData::const_iterator fragIter, fragEnd = pSD.end();
6526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  size_t cur_offset = 0;
6536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  for (fragIter = pSD.begin(); fragIter != fragEnd; ++fragIter) {
6546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    size_t size = fragIter->size();
65537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    switch (fragIter->getKind()) {
6566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      case Fragment::Region: {
65737b74a387bb3993387029859c2d9d051c41c724eStephen Hines        const RegionFragment& region_frag =
65837b74a387bb3993387029859c2d9d051c41c724eStephen Hines            llvm::cast<RegionFragment>(*fragIter);
65987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        const char* from = region_frag.getRegion().begin();
66087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        memcpy(pRegion.begin() + cur_offset, from, size);
6616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        break;
6626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      }
6636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      case Fragment::Alignment: {
6646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        // TODO: emit values with different sizes (> 1 byte), and emit nops
6656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        const AlignFragment& align_frag = llvm::cast<AlignFragment>(*fragIter);
6666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        uint64_t count = size / align_frag.getValueSize();
6676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        switch (align_frag.getValueSize()) {
6686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines          case 1u:
66937b74a387bb3993387029859c2d9d051c41c724eStephen Hines            std::memset(
67037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                pRegion.begin() + cur_offset, align_frag.getValue(), count);
6716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines            break;
6726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines          default:
67337b74a387bb3993387029859c2d9d051c41c724eStephen Hines            llvm::report_fatal_error(
67437b74a387bb3993387029859c2d9d051c41c724eStephen Hines                "unsupported value size for align fragment emission yet.\n");
6756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines            break;
6766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        }
6776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        break;
6786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      }
6796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      case Fragment::Fillment: {
6806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        const FillFragment& fill_frag = llvm::cast<FillFragment>(*fragIter);
68137b74a387bb3993387029859c2d9d051c41c724eStephen Hines        if (0 == size || 0 == fill_frag.getValueSize() ||
6826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines            0 == fill_frag.size()) {
6836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines          // ignore virtual fillment
6846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines          break;
6856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        }
6866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        uint64_t num_tiles = fill_frag.size() / fill_frag.getValueSize();
6886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        for (uint64_t i = 0; i != num_tiles; ++i) {
68987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          std::memset(pRegion.begin() + cur_offset,
6906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                      fill_frag.getValue(),
6916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                      fill_frag.getValueSize());
6926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        }
6936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        break;
6946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      }
6956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      case Fragment::Stub: {
6966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        const Stub& stub_frag = llvm::cast<Stub>(*fragIter);
69787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        memcpy(pRegion.begin() + cur_offset, stub_frag.getContent(), size);
6986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        break;
6996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      }
7006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      case Fragment::Null: {
7016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        assert(0x0 == size);
7026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        break;
7036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      }
7046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      case Fragment::Target:
70537b74a387bb3993387029859c2d9d051c41c724eStephen Hines        llvm::report_fatal_error(
70637b74a387bb3993387029859c2d9d051c41c724eStephen Hines            "Target fragment should not be in a regular section.\n");
7076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        break;
7086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      default:
70937b74a387bb3993387029859c2d9d051c41c724eStephen Hines        llvm::report_fatal_error(
71037b74a387bb3993387029859c2d9d051c41c724eStephen Hines            "invalid fragment should not be in a regular section.\n");
7116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        break;
7126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
7136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    cur_offset += size;
7146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
71522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
7165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
71737b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace mcld
718