gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gold / script.cc
index 33a89816b8dd21327db33c30ab668bd4d8d49481..d88758d077c54f438457c58c573e80063b78550c 100644 (file)
@@ -1,6 +1,6 @@
 // script.cc -- handle linker scripts for gold.
 
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright (C) 2006-2020 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -146,13 +146,7 @@ class Token
   }
 
   uint64_t
-  integer_value() const
-  {
-    gold_assert(this->classification_ == TOKEN_INTEGER);
-    // Null terminate.
-    std::string s(this->value_, this->value_length_);
-    return strtoull(s.c_str(), NULL, 0);
-  }
+  integer_value() const;
 
  private:
   // The token classification.
@@ -171,6 +165,35 @@ class Token
   int charpos_;
 };
 
+// Return the value of a TOKEN_INTEGER.
+
+uint64_t
+Token::integer_value() const
+{
+  gold_assert(this->classification_ == TOKEN_INTEGER);
+
+  size_t len = this->value_length_;
+
+  uint64_t multiplier = 1;
+  char last = this->value_[len - 1];
+  if (last == 'm' || last == 'M')
+    {
+      multiplier = 1024 * 1024;
+      --len;
+    }
+  else if (last == 'k' || last == 'K')
+    {
+      multiplier = 1024;
+      --len;
+    }
+
+  char *end;
+  uint64_t ret = strtoull(this->value_, &end, 0);
+  gold_assert(static_cast<size_t>(end - this->value_) == len);
+
+  return ret * multiplier;
+}
+
 // This class handles lexing a file into a sequence of tokens.
 
 class Lex
@@ -474,9 +497,7 @@ Lex::can_continue_name(const char* c)
 // For a number we accept 0x followed by hex digits, or any sequence
 // of digits.  The old linker accepts leading '$' for hex, and
 // trailing HXBOD.  Those are for MRI compatibility and we don't
-// accept them.  The old linker also accepts trailing MK for mega or
-// kilo.  FIXME: Those are mentioned in the documentation, and we
-// should accept them.
+// accept them.
 
 // Return whether C1 C2 C3 can start a hex number.
 
@@ -703,8 +724,15 @@ Lex::gather_token(Token::Classification classification,
                  const char** pp)
 {
   const char* new_match = NULL;
-  while ((new_match = (this->*can_continue_fn)(match)))
+  while ((new_match = (this->*can_continue_fn)(match)) != NULL)
     match = new_match;
+
+  // A special case: integers may be followed by a single M or K,
+  // case-insensitive.
+  if (classification == Token::TOKEN_INTEGER
+      && (*match == 'm' || *match == 'M' || *match == 'k' || *match == 'K'))
+    ++match;
+
   *pp = match;
   return this->make_token(classification, start, match - start, start);
 }
@@ -736,12 +764,6 @@ Lex::get_token(const char** pp)
 
   while (true)
     {
-      if (*p == '\0')
-       {
-         *pp = p;
-         return this->make_eof_token(p);
-       }
-
       // Skip whitespace quickly.
       while (*p == ' ' || *p == '\t' || *p == '\r')
        ++p;
@@ -754,8 +776,18 @@ Lex::get_token(const char** pp)
          continue;
        }
 
+      char c0 = *p;
+
+      if (c0 == '\0')
+       {
+         *pp = p;
+         return this->make_eof_token(p);
+       }
+
+      char c1 = p[1];
+
       // Skip C style comments.
-      if (p[0] == '/' && p[1] == '*')
+      if (c0 == '/' && c1 == '*')
        {
          int lineno = this->lineno_;
          int charpos = p - this->linestart_ + 1;
@@ -769,7 +801,7 @@ Lex::get_token(const char** pp)
        }
 
       // Skip line comments.
-      if (*p == '#')
+      if (c0 == '#')
        {
          *pp = p + 1;
          if (!this->skip_line_comment(pp))
@@ -779,7 +811,7 @@ Lex::get_token(const char** pp)
        }
 
       // Check for a name.
-      if (this->can_start_name(p[0], p[1]))
+      if (this->can_start_name(c0, c1))
        return this->gather_token(Token::TOKEN_STRING,
                                  &Lex::can_continue_name,
                                  p, p + 1, pp);
@@ -792,35 +824,38 @@ Lex::get_token(const char** pp)
          return this->gather_quoted_string(pp);
        }
 
+      // Be careful not to lookahead past the end of the buffer.
+      char c2 = (c1 == '\0' ? '\0' : p[2]);
+
       // Check for a number.
 
-      if (this->can_start_hex(p[0], p[1], p[2]))
+      if (this->can_start_hex(c0, c1, c2))
        return this->gather_token(Token::TOKEN_INTEGER,
                                  &Lex::can_continue_hex,
                                  p, p + 3, pp);
 
-      if (Lex::can_start_number(p[0]))
+      if (Lex::can_start_number(c0))
        return this->gather_token(Token::TOKEN_INTEGER,
                                  &Lex::can_continue_number,
                                  p, p + 1, pp);
 
       // Check for operators.
 
-      int opcode = Lex::three_char_operator(p[0], p[1], p[2]);
+      int opcode = Lex::three_char_operator(c0, c1, c2);
       if (opcode != 0)
        {
          *pp = p + 3;
          return this->make_token(opcode, p);
        }
 
-      opcode = Lex::two_char_operator(p[0], p[1]);
+      opcode = Lex::two_char_operator(c0, c1);
       if (opcode != 0)
        {
          *pp = p + 2;
          return this->make_token(opcode, p);
        }
 
-      opcode = Lex::one_char_operator(p[0]);
+      opcode = Lex::one_char_operator(c0);
       if (opcode != 0)
        {
          *pp = p + 1;
@@ -952,30 +987,41 @@ Symbol_assignment::sized_finalize(Symbol_table* symtab, const Layout* layout,
                                  Output_section* dot_section)
 {
   Output_section* section;
+  elfcpp::STT type = elfcpp::STT_NOTYPE;
+  elfcpp::STV vis = elfcpp::STV_DEFAULT;
+  unsigned char nonvis = 0;
   uint64_t final_val = this->val_->eval_maybe_dot(symtab, layout, true,
                                                  is_dot_available,
                                                  dot_value, dot_section,
-                                                 &section, NULL);
+                                                 &section, NULL, &type,
+                                                 &vis, &nonvis, false, NULL);
   Sized_symbol<size>* ssym = symtab->get_sized_symbol<size>(this->sym_);
   ssym->set_value(final_val);
+  ssym->set_type(type);
+  ssym->set_visibility(vis);
+  ssym->set_nonvis(nonvis);
   if (section != NULL)
     ssym->set_output_section(section);
 }
 
-// Set the symbol value if the expression yields an absolute value.
+// Set the symbol value if the expression yields an absolute value or
+// a value relative to DOT_SECTION.
 
 void
 Symbol_assignment::set_if_absolute(Symbol_table* symtab, const Layout* layout,
-                                  bool is_dot_available, uint64_t dot_value)
+                                  bool is_dot_available, uint64_t dot_value,
+                                  Output_section* dot_section)
 {
   if (this->sym_ == NULL)
     return;
 
   Output_section* val_section;
+  bool is_valid;
   uint64_t val = this->val_->eval_maybe_dot(symtab, layout, false,
                                            is_dot_available, dot_value,
-                                           NULL, &val_section, NULL);
-  if (val_section != NULL)
+                                           dot_section, &val_section, NULL,
+                                           NULL, NULL, NULL, false, &is_valid);
+  if (!is_valid || (val_section != NULL && val_section != dot_section))
     return;
 
   if (parameters->target().get_size() == 32)
@@ -998,6 +1044,8 @@ Symbol_assignment::set_if_absolute(Symbol_table* symtab, const Layout* layout,
     }
   else
     gold_unreachable();
+  if (val_section != NULL)
+    this->sym_->set_output_section(val_section);
 }
 
 // Print for debugging.
@@ -1064,6 +1112,29 @@ Script_options::is_pending_assignment(const char* name)
   return false;
 }
 
+// Populates the set with symbols defined in defsym LHS.
+
+void Script_options::find_defsym_defs(Unordered_set<std::string>& defsym_set)
+{
+  for (Symbol_assignments::const_iterator p = this->symbol_assignments_.begin();
+       p != this->symbol_assignments_.end();
+       ++p)
+    {
+      defsym_set.insert((*p)->name());
+    }
+}
+
+void
+Script_options::set_defsym_uses_in_real_elf(Symbol_table* symtab) const
+{
+  for (Symbol_assignments::const_iterator p = this->symbol_assignments_.begin();
+       p != this->symbol_assignments_.end();
+       ++p)
+    {
+      (*p)->value()->set_expr_sym_in_real_elf(symtab);
+    }
+}
+
 // Add a symbol to be defined.
 
 void
@@ -1187,7 +1258,7 @@ Script_options::set_section_addresses(Symbol_table* symtab, Layout* layout)
   for (Symbol_assignments::iterator p = this->symbol_assignments_.begin();
        p != this->symbol_assignments_.end();
        ++p)
-    (*p)->set_if_absolute(symtab, layout, false, 0);
+    (*p)->set_if_absolute(symtab, layout, false, 0, NULL);
 
   return this->script_sections_.set_section_addresses(symtab, layout);
 }
@@ -1502,18 +1573,26 @@ read_input_script(Workqueue* workqueue, Symbol_table* symtab, Layout* layout,
   return true;
 }
 
-// Helper function for read_version_script() and
-// read_commandline_script().  Processes the given file in the mode
-// indicated by first_token and lex_mode.
+// Helper function for read_version_script(), read_commandline_script() and
+// script_include_directive().  Processes the given file in the mode indicated
+// by first_token and lex_mode.
 
 static bool
 read_script_file(const char* filename, Command_line* cmdline,
                  Script_options* script_options,
                  int first_token, Lex::Mode lex_mode)
 {
-  // TODO: if filename is a relative filename, search for it manually
-  // using "." + cmdline->options()->search_path() -- not dirsearch.
   Dirsearch dirsearch;
+  std::string name = filename;
+
+  // If filename is a relative filename, search for it manually using "." +
+  // cmdline->options()->library_path() -- not dirsearch.
+  if (!IS_ABSOLUTE_PATH(filename))
+    {
+      const General_options::Dir_list& search_path =
+          cmdline->options().library_path();
+      name = Dirsearch::find_file_in_dir_list(name, search_path, ".");
+    }
 
   // The file locking code wants to record a Task, but we haven't
   // started the workqueue yet.  This is only for debugging purposes,
@@ -1524,7 +1603,7 @@ read_script_file(const char* filename, Command_line* cmdline,
   Position_dependent_options posdep = cmdline->position_dependent_options();
   if (posdep.format_enum() == General_options::OBJECT_FORMAT_BINARY)
     posdep.set_format_enum(General_options::OBJECT_FORMAT_ELF);
-  Input_file_argument input_argument(filename,
+  Input_file_argument input_argument(name.c_str(),
                                     Input_file_argument::INPUT_FILE_TYPE_FILE,
                                     "", false, posdep);
   Input_file input_file(&input_argument);
@@ -1706,6 +1785,7 @@ script_keyword_parsecodes[] =
   { "FLOAT", FLOAT },
   { "FORCE_COMMON_ALLOCATION", FORCE_COMMON_ALLOCATION },
   { "GROUP", GROUP },
+  { "HIDDEN", HIDDEN },
   { "HLL", HLL },
   { "INCLUDE", INCLUDE },
   { "INFO", INFO },
@@ -1743,6 +1823,7 @@ script_keyword_parsecodes[] =
   { "SIZEOF_HEADERS", SIZEOF_HEADERS },
   { "SORT", SORT_BY_NAME },
   { "SORT_BY_ALIGNMENT", SORT_BY_ALIGNMENT },
+  { "SORT_BY_INIT_PRIORITY", SORT_BY_INIT_PRIORITY },
   { "SORT_BY_NAME", SORT_BY_NAME },
   { "SPECIAL", SPECIAL },
   { "SQUAD", SQUAD },
@@ -2646,7 +2727,7 @@ script_add_library(void* closurev, const char* name, size_t length)
 
   if (name_string[0] != 'l')
     gold_error(_("library name must be prefixed with -l"));
-    
+
   Input_file_argument file(name_string.c_str() + 1,
                           Input_file_argument::INPUT_FILE_TYPE_LIBRARY,
                           "", false,
@@ -3318,10 +3399,14 @@ script_parse_memory_attr(void* closurev, const char* attrs, size_t attrlen,
 }
 
 extern "C" void
-script_include_directive(void* closurev, const char*, size_t)
+script_include_directive(int first_token, void* closurev,
+                        const char* filename, size_t length)
 {
-  // FIXME: Implement ?
-  yyerror (closurev, _("GOLD does not currently support INCLUDE directives"));
+  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
+  std::string name(filename, length);
+  Command_line* cmdline = closure->command_line();
+  read_script_file(name.c_str(), cmdline, &cmdline->script_options(),
+                   first_token, Lex::LINKER_SCRIPT);
 }
 
 // Functions for memory regions.
This page took 0.029092 seconds and 4 git commands to generate.