1533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines//===- ScriptOptions.cpp --------------------------------------------------===//
2533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines//
3533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines//                     The MCLinker Project
4533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines//
5533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines// This file is distributed under the University of Illinois Open Source
6533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines// License. See LICENSE.TXT for details.
7533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines//
8533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines//===----------------------------------------------------------------------===//
9533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines#include <mcld/ScriptOptions.h>
10533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines#include <mcld/LinkerScript.h>
11533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines#include <mcld/ADT/StringEntry.h>
12533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines#include <mcld/Support/MsgHandling.h>
13533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines
14533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hinesnamespace {
15533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines
16533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines//===----------------------------------------------------------------------===//
17533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines// Script Options
18533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines// Script options are used to modify the default link script. Some positional
19533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines// options, such as --defsym, also can modify default link script is not listed
20533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines// here. These special options belong to Positional Options.
21533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines//===----------------------------------------------------------------------===//
22533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hinesstatic llvm::cl::list<std::string>
23533eae20118036f425f27bf0536ef0ccbb090b65Stephen HinesArgWrapList("wrap",
24533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines            llvm::cl::ZeroOrMore,
25533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines            llvm::cl::desc("Use a wrap function fo symbol."),
26533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines            llvm::cl::value_desc("symbol"));
27533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines
28533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hinesstatic llvm::cl::list<std::string>
29533eae20118036f425f27bf0536ef0ccbb090b65Stephen HinesArgPortList("portable",
30533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines            llvm::cl::ZeroOrMore,
31533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines            llvm::cl::desc("Use a portable function fo symbol."),
32533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines            llvm::cl::value_desc("symbol"));
33533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines
34533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hinesstatic llvm::cl::list<std::string>
35533eae20118036f425f27bf0536ef0ccbb090b65Stephen HinesArgAddressMapList("section-start",
36533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines                  llvm::cl::ZeroOrMore,
37533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines                  llvm::cl::desc("Locate a output section at the given absolute address"),
38533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines                  llvm::cl::value_desc("Set address of section"),
39533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines                  llvm::cl::Prefix);
40533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines
41533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hinesstatic llvm::cl::opt<unsigned long long>
42533eae20118036f425f27bf0536ef0ccbb090b65Stephen HinesArgBssSegAddr("Tbss",
43533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines              llvm::cl::desc("Set the address of the bss segment"),
44533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines              llvm::cl::init(-1U));
45533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines
46533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hinesstatic llvm::cl::opt<unsigned long long>
47533eae20118036f425f27bf0536ef0ccbb090b65Stephen HinesArgDataSegAddr("Tdata",
48533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines               llvm::cl::desc("Set the address of the data segment"),
49533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines               llvm::cl::init(-1U));
50533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines
51533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hinesstatic llvm::cl::opt<unsigned long long>
52533eae20118036f425f27bf0536ef0ccbb090b65Stephen HinesArgTextSegAddr("Ttext",
53533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines               llvm::cl::desc("Set the address of the text segment"),
54533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines               llvm::cl::init(-1U));
55533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines
56533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hinesstatic llvm::cl::alias
57533eae20118036f425f27bf0536ef0ccbb090b65Stephen HinesArgTextSegAddrAlias("Ttext-segment",
58533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines                    llvm::cl::desc("alias for -Ttext"),
59533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines                    llvm::cl::aliasopt(ArgTextSegAddr));
60533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines
61533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines} // anonymous namespace
62533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines
63533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hinesusing namespace mcld;
64533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines
65533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines//===----------------------------------------------------------------------===//
66533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines// ScriptOptions
67533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines//===----------------------------------------------------------------------===//
68533eae20118036f425f27bf0536ef0ccbb090b65Stephen HinesScriptOptions::ScriptOptions()
69533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines  : m_WrapList(ArgWrapList),
70533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    m_PortList(ArgPortList),
71533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    m_AddressMapList(ArgAddressMapList),
72533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    m_BssSegAddr(ArgBssSegAddr),
73533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    m_DataSegAddr(ArgDataSegAddr),
74533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    m_TextSegAddr(ArgTextSegAddr) {
75533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines}
76533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines
77533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hinesbool ScriptOptions::parse(LinkerScript& pScript)
78533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines{
79533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines  // set up rename map, for --wrap
80533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines  llvm::cl::list<std::string>::iterator wname;
81533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines  llvm::cl::list<std::string>::iterator wnameEnd = ArgWrapList.end();
82533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines  for (wname = ArgWrapList.begin(); wname != wnameEnd; ++wname) {
83533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    bool exist = false;
84533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines
85533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    // add wname -> __wrap_wname
86533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    StringEntry<llvm::StringRef>* to_wrap =
87533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines                                     pScript.renameMap().insert(*wname, exist);
88533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines
89533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    std::string to_wrap_str = "__wrap_" + *wname;
90533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    to_wrap->setValue(to_wrap_str);
91533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines
92533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    if (exist)
93533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines      warning(mcld::diag::rewrap) << *wname << to_wrap_str;
94533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines
95533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    // add __real_wname -> wname
96533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    std::string from_real_str = "__real_" + *wname;
97533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    StringEntry<llvm::StringRef>* from_real =
98533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines                              pScript.renameMap().insert(from_real_str, exist);
99533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    from_real->setValue(*wname);
100533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    if (exist)
101533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines      mcld::warning(mcld::diag::rewrap) << *wname << from_real_str;
102533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines  }
103533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines
104533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines  // set up rename map, for --portable
105533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines  llvm::cl::list<std::string>::iterator pname;
106533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines  llvm::cl::list<std::string>::iterator pnameEnd = ArgPortList.end();
107533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines  for (pname = ArgPortList.begin(); pname != pnameEnd; ++pname) {
108533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    bool exist = false;
109533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines
110533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    // add pname -> pname_portable
111533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    StringEntry<llvm::StringRef>* to_port =
112533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines                                     pScript.renameMap().insert(*pname, exist);
113533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines
114533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    std::string to_port_str = *pname + "_portable";
115533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    to_port->setValue(to_port_str);
116533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines
117533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    if (exist)
118533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines      warning(mcld::diag::rewrap) << *pname << to_port_str;
119533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines
120533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    // add __real_pname -> pname
121533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    std::string from_real_str = "__real_" + *pname;
122533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    StringEntry<llvm::StringRef>* from_real =
123533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines                              pScript.renameMap().insert(from_real_str, exist);
124533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines
125533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    from_real->setValue(*pname);
126533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    if (exist)
127533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines      warning(mcld::diag::rewrap) << *pname << from_real_str;
128533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines  } // end of for
129533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines
130533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines  // set --section-start SECTION=ADDRESS
131533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines  for (llvm::cl::list<std::string>::iterator
132533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines       it = ArgAddressMapList.begin(), ie = ArgAddressMapList.end();
133533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines       it != ie; ++it) {
134533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    // FIXME: Add a cl::parser
135533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    size_t pos = (*it).find_last_of('=');
136533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    llvm::StringRef script(*it);
137533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    uint64_t address = 0x0;
138533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    script.substr(pos + 1).getAsInteger(0, address);
139533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    bool exist = false;
140533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    StringEntry<uint64_t>* addr_mapping =
141533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines                     pScript.addressMap().insert(script.substr(0, pos), exist);
142533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    addr_mapping->setValue(address);
143533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines  }
144533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines
145533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines  // set -Tbss [address]
146533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines  if (-1U != ArgBssSegAddr) {
147533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    bool exist = false;
148533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    StringEntry<uint64_t>* bss_mapping =
149533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines                                    pScript.addressMap().insert(".bss", exist);
150533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    bss_mapping->setValue(ArgBssSegAddr);
151533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines  }
152533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines
153533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines  // set -Tdata [address]
154533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines  if (-1U != ArgDataSegAddr) {
155533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    bool exist = false;
156533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    StringEntry<uint64_t>* data_mapping =
157533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines                                   pScript.addressMap().insert(".data", exist);
158533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    data_mapping->setValue(ArgDataSegAddr);
159533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines  }
160533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines
161533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines  // set -Ttext [address]
162533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines  if (-1U != ArgTextSegAddr) {
163533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    bool exist = false;
164533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    StringEntry<uint64_t>* text_mapping =
165533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines                                   pScript.addressMap().insert(".text", exist);
166533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines    text_mapping->setValue(ArgTextSegAddr);
167533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines  }
168533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines
169533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines  return true;
170533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines}
171533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines
172