summaryrefslogtreecommitdiffstats
path: root/gold/expression.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2008-02-13 01:18:53 +0000
committerIan Lance Taylor <iant@google.com>2008-02-13 01:18:53 +0000
commit7508a0934ec2fad27f393d3b1a6e1207dab3fd2d (patch)
tree2d9b95b3aa7934416470f8841817baaae1972f2c /gold/expression.cc
parenta6ebc90ecc8544f725c96de0de6b993a178b28df (diff)
downloadppe42-binutils-7508a0934ec2fad27f393d3b1a6e1207dab3fd2d.tar.gz
ppe42-binutils-7508a0934ec2fad27f393d3b1a6e1207dab3fd2d.zip
Implement LOADADDR and SIZEOF.
Diffstat (limited to 'gold/expression.cc')
-rw-r--r--gold/expression.cc164
1 files changed, 125 insertions, 39 deletions
diff --git a/gold/expression.cc b/gold/expression.cc
index d7536016b0..74cac37272 100644
--- a/gold/expression.cc
+++ b/gold/expression.cc
@@ -610,6 +610,52 @@ script_exp_function_min(Expression* left, Expression* right)
return new Min_expression(left, right);
}
+// Class Section_expression. This is a parent class used for
+// functions which take the name of an output section.
+
+class Section_expression : public Expression
+{
+ public:
+ Section_expression(const char* section_name, size_t section_name_len)
+ : section_name_(section_name, section_name_len)
+ { }
+
+ uint64_t
+ value(const Expression_eval_info*);
+
+ void
+ print(FILE* f) const
+ { fprintf(f, "%s(%s)", this->function_name(), this->section_name_.c_str()); }
+
+ protected:
+ // The child class must implement this.
+ virtual uint64_t
+ value_from_output_section(const Expression_eval_info*,
+ Output_section*) = 0;
+
+ // The child class must implement this.
+ virtual const char*
+ function_name() const = 0;
+
+ private:
+ std::string section_name_;
+};
+
+uint64_t
+Section_expression::value(const Expression_eval_info* eei)
+{
+ const char* section_name = this->section_name_.c_str();
+ Output_section* os = eei->layout->find_output_section(section_name);
+ if (os == NULL)
+ {
+ gold_error("%s called on nonexistent output section '%s'",
+ this->function_name(), section_name);
+ return 0;
+ }
+
+ return this->value_from_output_section(eei, os);
+}
+
// Align function.
class Align_expression : public Binary_expression
@@ -682,43 +728,29 @@ script_exp_function_assert(Expression* expr, const char* message,
return new Assert_expression(expr, message, length);
}
-// Addr function.
+// ADDR function.
-class Addr_expression : public Expression
+class Addr_expression : public Section_expression
{
public:
Addr_expression(const char* section_name, size_t section_name_len)
- : section_name_(section_name, section_name_len)
+ : Section_expression(section_name, section_name_len)
{ }
+ protected:
uint64_t
- value(const Expression_eval_info*);
-
- void
- print(FILE* f) const
- { fprintf(f, "ADDR(%s)", this->section_name_.c_str()); }
+ value_from_output_section(const Expression_eval_info *eei,
+ Output_section* os)
+ {
+ *eei->result_section_pointer = os;
+ return os->address();
+ }
- private:
- std::string section_name_;
+ const char*
+ function_name() const
+ { return "ADDR"; }
};
-uint64_t
-Addr_expression::value(const Expression_eval_info* eei)
-{
- const char* section_name = this->section_name_.c_str();
- Output_section* os = eei->layout->find_output_section(section_name);
- if (os == NULL)
- {
- gold_error("ADDR called on nonexistent output section '%s'",
- section_name);
- return 0;
- }
-
- *eei->result_section_pointer = os;
-
- return os->address();
-}
-
extern "C" Expression*
script_exp_function_addr(const char* section_name, size_t section_name_len)
{
@@ -831,6 +863,72 @@ script_exp_function_data_segment_end(Expression* val)
return val;
}
+// LOADADDR function
+
+class Loadaddr_expression : public Section_expression
+{
+ public:
+ Loadaddr_expression(const char* section_name, size_t section_name_len)
+ : Section_expression(section_name, section_name_len)
+ { }
+
+ protected:
+ uint64_t
+ value_from_output_section(const Expression_eval_info *eei,
+ Output_section* os)
+ {
+ if (os->has_load_address())
+ return os->load_address();
+ else
+ {
+ *eei->result_section_pointer = os;
+ return os->address();
+ }
+ }
+
+ const char*
+ function_name() const
+ { return "LOADADDR"; }
+};
+
+extern "C" Expression*
+script_exp_function_loadaddr(const char* section_name, size_t section_name_len)
+{
+ return new Loadaddr_expression(section_name, section_name_len);
+}
+
+// SIZEOF function
+
+class Sizeof_expression : public Section_expression
+{
+ public:
+ Sizeof_expression(const char* section_name, size_t section_name_len)
+ : Section_expression(section_name, section_name_len)
+ { }
+
+ protected:
+ uint64_t
+ value_from_output_section(const Expression_eval_info *,
+ Output_section* os)
+ {
+ // We can not use data_size here, as the size of the section may
+ // not have been finalized. Instead we get whatever the current
+ // size is. This will work correctly for backward references in
+ // linker scripts.
+ return os->current_data_size();
+ }
+
+ const char*
+ function_name() const
+ { return "SIZEOF"; }
+};
+
+extern "C" Expression*
+script_exp_function_sizeof(const char* section_name, size_t section_name_len)
+{
+ return new Sizeof_expression(section_name, section_name_len);
+}
+
// SIZEOF_HEADERS.
class Sizeof_headers_expression : public Expression
@@ -889,18 +987,6 @@ script_exp_function_alignof(const char*, size_t)
}
extern "C" Expression*
-script_exp_function_sizeof(const char*, size_t)
-{
- gold_fatal(_("SIZEOF not implemented"));
-}
-
-extern "C" Expression*
-script_exp_function_loadaddr(const char*, size_t)
-{
- gold_fatal(_("LOADADDR not implemented"));
-}
-
-extern "C" Expression*
script_exp_function_origin(const char*, size_t)
{
gold_fatal(_("ORIGIN not implemented"));
OpenPOWER on IntegriCloud