Implement LOADADDR and SIZEOF.

This commit is contained in:
Ian Lance Taylor 2008-02-13 01:18:53 +00:00
parent a6ebc90ecc
commit 7508a0934e
1 changed files with 125 additions and 39 deletions

View File

@ -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*);
value_from_output_section(const Expression_eval_info *eei,
Output_section* os)
{
*eei->result_section_pointer = os;
return os->address();
}
void
print(FILE* f) const
{ fprintf(f, "ADDR(%s)", this->section_name_.c_str()); }
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
@ -888,18 +986,6 @@ script_exp_function_alignof(const char*, size_t)
gold_fatal(_("ALIGNOF not implemented"));
}
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)
{