1//===- OutputSectDesc.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/Script/OutputSectDesc.h>
10#include <mcld/Script/RpnExpr.h>
11#include <mcld/Script/StringList.h>
12#include <mcld/Script/StrToken.h>
13#include <mcld/Script/InputSectDesc.h>
14#include <mcld/Support/raw_ostream.h>
15#include <mcld/LinkerScript.h>
16#include <mcld/Module.h>
17#include <llvm/Support/Casting.h>
18#include <cassert>
19
20using namespace mcld;
21
22//===----------------------------------------------------------------------===//
23// OutputSectDesc
24//===----------------------------------------------------------------------===//
25OutputSectDesc::OutputSectDesc(const std::string& pName,
26                               const Prolog& pProlog)
27  : ScriptCommand(ScriptCommand::OUTPUT_SECT_DESC),
28    m_Name(pName),
29    m_Prolog(pProlog)
30{
31}
32
33OutputSectDesc::~OutputSectDesc()
34{
35  for (iterator it = begin(), ie = end(); it != ie; ++it) {
36    if (*it != NULL)
37      delete *it;
38  }
39}
40
41void OutputSectDesc::dump() const
42{
43  mcld::outs() << m_Name << "\t";
44
45  if (m_Prolog.hasVMA()) {
46    m_Prolog.vma().dump();
47    mcld::outs() << "\t";
48  }
49
50  switch (m_Prolog.type()) {
51  case NOLOAD:
52    mcld::outs() << "(NOLOAD)";
53    break;
54  case DSECT:
55    mcld::outs() << "(DSECT)";
56    break;
57  case COPY:
58    mcld::outs() << "(COPY)";
59    break;
60  case INFO:
61    mcld::outs() << "(INFO)";
62    break;
63  case OVERLAY:
64    mcld::outs() << "(OVERLAY)";
65    break;
66  default:
67    break;
68  }
69  mcld::outs() << ":\n";
70
71  if (m_Prolog.hasLMA()) {
72    mcld::outs() << "\tAT ( ";
73    m_Prolog.lma().dump();
74    mcld::outs() << " )\n";
75  }
76
77  if (m_Prolog.hasAlign()) {
78    mcld::outs() << "\tALIGN ( ";
79    m_Prolog.align().dump();
80    mcld::outs() << " )\n";
81  }
82
83  if (m_Prolog.hasSubAlign()) {
84    mcld::outs() << "\tSUBALIGN ( ";
85    m_Prolog.subAlign().dump();
86    mcld::outs() << " )\n";
87  }
88
89  switch (m_Prolog.constraint()) {
90  case ONLY_IF_RO:
91    mcld::outs() << "\tONLY_IF_RO\n";
92    break;
93  case ONLY_IF_RW:
94    mcld::outs() << "\tONLY_IF_RW\n";
95    break;
96  default:
97    break;
98  }
99
100  mcld::outs() << "\t{\n";
101  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
102    switch ((*it)->getKind()) {
103    case ScriptCommand::ASSIGNMENT:
104    case ScriptCommand::INPUT_SECT_DESC:
105      mcld::outs() << "\t\t";
106      (*it)->dump();
107      break;
108    default:
109      assert(0);
110      break;
111    }
112  }
113  mcld::outs() << "\t}";
114
115  if (m_Epilog.hasRegion())
116    mcld::outs() << "\t>" << m_Epilog.region();
117  if (m_Epilog.hasLMARegion())
118    mcld::outs() << "\tAT>" << m_Epilog.lmaRegion();
119
120  if (m_Epilog.hasPhdrs()) {
121    for (StringList::const_iterator it = m_Epilog.phdrs().begin(),
122      ie = m_Epilog.phdrs().end(); it != ie; ++it) {
123      assert((*it)->kind() == StrToken::String);
124      mcld::outs() << ":" << (*it)->name() << " ";
125    }
126  }
127
128  if (m_Epilog.hasFillExp()) {
129    mcld::outs() << "= ";
130    m_Epilog.fillExp().dump();
131  }
132  mcld::outs() << "\n";
133}
134
135void OutputSectDesc::push_back(ScriptCommand* pCommand)
136{
137  switch (pCommand->getKind()) {
138  case ScriptCommand::ASSIGNMENT:
139  case ScriptCommand::INPUT_SECT_DESC:
140    m_OutputSectCmds.push_back(pCommand);
141    break;
142  default:
143    assert(0);
144    break;
145  }
146}
147
148void OutputSectDesc::setEpilog(const Epilog& pEpilog)
149{
150  m_Epilog.m_pRegion    = pEpilog.m_pRegion;
151  m_Epilog.m_pLMARegion = pEpilog.m_pLMARegion;
152  m_Epilog.m_pPhdrs     = pEpilog.m_pPhdrs;
153  m_Epilog.m_pFillExp   = pEpilog.m_pFillExp;
154}
155
156void OutputSectDesc::activate(Module& pModule)
157{
158  // Assignment in an output section
159  OutputSectCmds assignments;
160
161  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
162    switch ((*it)->getKind()) {
163    case ScriptCommand::ASSIGNMENT:
164      assignments.push_back(*it);
165      break;
166    case ScriptCommand::INPUT_SECT_DESC: {
167      (*it)->activate(pModule);
168
169      for (iterator assign = assignments.begin(), assignEnd = assignments.end();
170        assign != assignEnd; ++assign) {
171        (*assign)->activate(pModule);
172      }
173      assignments.clear();
174      break;
175    }
176    default:
177      assert(0);
178      break;
179    }
180  }
181
182  if (!assignments.empty()) {
183    InputSectDesc::Spec spec;;
184    spec.m_pWildcardFile = NULL;
185    spec.m_pExcludeFiles = NULL;
186    spec.m_pWildcardSections = NULL;
187    InputSectDesc inputDesc(InputSectDesc::Keep, spec, *this);
188    pModule.getScript().sectionMap().insert(inputDesc, *this);
189
190    for (iterator assign = assignments.begin(), assignEnd = assignments.end();
191      assign != assignEnd; ++assign) {
192      (*assign)->activate(pModule);
193    }
194    assignments.clear();
195  }
196}
197