1//===- ScriptOptions.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/ScriptOptions.h>
10#include <mcld/LinkerScript.h>
11#include <mcld/ADT/StringEntry.h>
12#include <mcld/Support/MsgHandling.h>
13
14namespace {
15
16//===----------------------------------------------------------------------===//
17// Script Options
18// Script options are used to modify the default link script. Some positional
19// options, such as --defsym, also can modify default link script is not listed
20// here. These special options belong to Positional Options.
21//===----------------------------------------------------------------------===//
22static llvm::cl::list<std::string>
23ArgWrapList("wrap",
24            llvm::cl::ZeroOrMore,
25            llvm::cl::desc("Use a wrap function fo symbol."),
26            llvm::cl::value_desc("symbol"));
27
28static llvm::cl::list<std::string>
29ArgPortList("portable",
30            llvm::cl::ZeroOrMore,
31            llvm::cl::desc("Use a portable function fo symbol."),
32            llvm::cl::value_desc("symbol"));
33
34static llvm::cl::list<std::string>
35ArgAddressMapList("section-start",
36                  llvm::cl::ZeroOrMore,
37                  llvm::cl::desc("Locate a output section at the given absolute address"),
38                  llvm::cl::value_desc("Set address of section"),
39                  llvm::cl::Prefix);
40
41static llvm::cl::opt<unsigned long long>
42ArgBssSegAddr("Tbss",
43              llvm::cl::desc("Set the address of the bss segment"),
44              llvm::cl::init(-1U));
45
46static llvm::cl::opt<unsigned long long>
47ArgDataSegAddr("Tdata",
48               llvm::cl::desc("Set the address of the data segment"),
49               llvm::cl::init(-1U));
50
51static llvm::cl::opt<unsigned long long>
52ArgTextSegAddr("Ttext",
53               llvm::cl::desc("Set the address of the text segment"),
54               llvm::cl::init(-1U));
55
56static llvm::cl::alias
57ArgTextSegAddrAlias("Ttext-segment",
58                    llvm::cl::desc("alias for -Ttext"),
59                    llvm::cl::aliasopt(ArgTextSegAddr));
60
61} // anonymous namespace
62
63using namespace mcld;
64
65//===----------------------------------------------------------------------===//
66// ScriptOptions
67//===----------------------------------------------------------------------===//
68ScriptOptions::ScriptOptions()
69  : m_WrapList(ArgWrapList),
70    m_PortList(ArgPortList),
71    m_AddressMapList(ArgAddressMapList),
72    m_BssSegAddr(ArgBssSegAddr),
73    m_DataSegAddr(ArgDataSegAddr),
74    m_TextSegAddr(ArgTextSegAddr) {
75}
76
77bool ScriptOptions::parse(LinkerScript& pScript)
78{
79  // set up rename map, for --wrap
80  llvm::cl::list<std::string>::iterator wname;
81  llvm::cl::list<std::string>::iterator wnameEnd = ArgWrapList.end();
82  for (wname = ArgWrapList.begin(); wname != wnameEnd; ++wname) {
83    bool exist = false;
84
85    // add wname -> __wrap_wname
86    StringEntry<llvm::StringRef>* to_wrap =
87                                     pScript.renameMap().insert(*wname, exist);
88
89    std::string to_wrap_str = "__wrap_" + *wname;
90    to_wrap->setValue(to_wrap_str);
91
92    if (exist)
93      warning(mcld::diag::rewrap) << *wname << to_wrap_str;
94
95    // add __real_wname -> wname
96    std::string from_real_str = "__real_" + *wname;
97    StringEntry<llvm::StringRef>* from_real =
98                              pScript.renameMap().insert(from_real_str, exist);
99    from_real->setValue(*wname);
100    if (exist)
101      mcld::warning(mcld::diag::rewrap) << *wname << from_real_str;
102  }
103
104  // set up rename map, for --portable
105  llvm::cl::list<std::string>::iterator pname;
106  llvm::cl::list<std::string>::iterator pnameEnd = ArgPortList.end();
107  for (pname = ArgPortList.begin(); pname != pnameEnd; ++pname) {
108    bool exist = false;
109
110    // add pname -> pname_portable
111    StringEntry<llvm::StringRef>* to_port =
112                                     pScript.renameMap().insert(*pname, exist);
113
114    std::string to_port_str = *pname + "_portable";
115    to_port->setValue(to_port_str);
116
117    if (exist)
118      warning(mcld::diag::rewrap) << *pname << to_port_str;
119
120    // add __real_pname -> pname
121    std::string from_real_str = "__real_" + *pname;
122    StringEntry<llvm::StringRef>* from_real =
123                              pScript.renameMap().insert(from_real_str, exist);
124
125    from_real->setValue(*pname);
126    if (exist)
127      warning(mcld::diag::rewrap) << *pname << from_real_str;
128  } // end of for
129
130  // set --section-start SECTION=ADDRESS
131  for (llvm::cl::list<std::string>::iterator
132       it = ArgAddressMapList.begin(), ie = ArgAddressMapList.end();
133       it != ie; ++it) {
134    // FIXME: Add a cl::parser
135    size_t pos = (*it).find_last_of('=');
136    llvm::StringRef script(*it);
137    uint64_t address = 0x0;
138    script.substr(pos + 1).getAsInteger(0, address);
139    bool exist = false;
140    StringEntry<uint64_t>* addr_mapping =
141                     pScript.addressMap().insert(script.substr(0, pos), exist);
142    addr_mapping->setValue(address);
143  }
144
145  // set -Tbss [address]
146  if (-1U != ArgBssSegAddr) {
147    bool exist = false;
148    StringEntry<uint64_t>* bss_mapping =
149                                    pScript.addressMap().insert(".bss", exist);
150    bss_mapping->setValue(ArgBssSegAddr);
151  }
152
153  // set -Tdata [address]
154  if (-1U != ArgDataSegAddr) {
155    bool exist = false;
156    StringEntry<uint64_t>* data_mapping =
157                                   pScript.addressMap().insert(".data", exist);
158    data_mapping->setValue(ArgDataSegAddr);
159  }
160
161  // set -Ttext [address]
162  if (-1U != ArgTextSegAddr) {
163    bool exist = false;
164    StringEntry<uint64_t>* text_mapping =
165                                   pScript.addressMap().insert(".text", exist);
166    text_mapping->setValue(ArgTextSegAddr);
167  }
168
169  return true;
170}
171
172