Home | History | Annotate | Download | only in lib
      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 
     14 namespace {
     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 //===----------------------------------------------------------------------===//
     22 static llvm::cl::list<std::string>
     23 ArgWrapList("wrap",
     24             llvm::cl::ZeroOrMore,
     25             llvm::cl::desc("Use a wrap function fo symbol."),
     26             llvm::cl::value_desc("symbol"));
     27 
     28 static llvm::cl::list<std::string>
     29 ArgPortList("portable",
     30             llvm::cl::ZeroOrMore,
     31             llvm::cl::desc("Use a portable function fo symbol."),
     32             llvm::cl::value_desc("symbol"));
     33 
     34 static llvm::cl::list<std::string>
     35 ArgAddressMapList("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 
     41 static llvm::cl::opt<unsigned long long>
     42 ArgBssSegAddr("Tbss",
     43               llvm::cl::desc("Set the address of the bss segment"),
     44               llvm::cl::init(-1U));
     45 
     46 static llvm::cl::opt<unsigned long long>
     47 ArgDataSegAddr("Tdata",
     48                llvm::cl::desc("Set the address of the data segment"),
     49                llvm::cl::init(-1U));
     50 
     51 static llvm::cl::opt<unsigned long long>
     52 ArgTextSegAddr("Ttext",
     53                llvm::cl::desc("Set the address of the text segment"),
     54                llvm::cl::init(-1U));
     55 
     56 static llvm::cl::alias
     57 ArgTextSegAddrAlias("Ttext-segment",
     58                     llvm::cl::desc("alias for -Ttext"),
     59                     llvm::cl::aliasopt(ArgTextSegAddr));
     60 
     61 } // anonymous namespace
     62 
     63 using namespace mcld;
     64 
     65 //===----------------------------------------------------------------------===//
     66 // ScriptOptions
     67 //===----------------------------------------------------------------------===//
     68 ScriptOptions::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 
     77 bool 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