mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-23 10:03:47 +08:00
2010-04-09 Doug Kwan <dougkwan@google.com>
* layout.cc (Layout::choose_output_section): Handle script section types. (Layout::make_output_section_for_script): Add section type parameter. Handle script section types. * layout.h (Layout::make_output_section_for_script): Add section type parameter. * output.cc (Output_section::Output_section): Initialize data member is_noload_. (Output_section::do_reset_address_and_file_offset): Do not set address to 0 if section is a NOLOAD section. * output.h (Output_section::is_noload): New method. (Output_section::set_is_noload): Ditto. (Output_section::is_noload_): New data member. * script-c.h (Script_section_type): New enum type. (struct Parser_output_section_header): Add new file section_type. * script-sections.cc (Sections_element::output_section_name): Add parameter for returning script section type. (Output_section_definition::output_section_name): Ditto. (Output_section_definition::section_type)P; New method. (Output_section_definiton::script_section_type_name): Ditto. (Output_section_definition::script_section_type_): New data member. (Output_section_definition::Output_section_definition): Initialize data member Output_section_definition::script_section_type_. (Output_section_definition::create_sections): Pass script section type to Layout::make_output_section_for_script. (Output_section_definition::output_section_name): Return script section type to caller. (Output_section_definition::set_section_address): Do not advance dot value and load address if section type is NOLOAD. Set address of NOLOAD sections regardless of section flags. (Output_section_definition::print): Print section type if it is not SCRIPT_SECTION_TYPE_NONE. (Output_section_definition::section_type): New method. (Output_section_definition::script_section_type_name): Ditto. (Script_sections::output_section_name): Add new parameter PSECTION_TYPE for returning script section type. Pass it to section elements. Handle discard sections. (Sort_output_sections::operator()): Handle NOLOAD sections. * script-sections.h (Script_sections::Section_type): New enum type. (Script_sections::output_section_name): Add a new parameter for returning script section type. * script.cc (script_keyword_parsecodes): Add keywords COPY, DSECT, INFO and NOLOAD. * yyscript.y (union): Add new field SECTION_TYPE. (COPY, DSECT, INFO, NOLOAD): New tokens. (opt_address_and_section_type): Change type to output_section_header. (section_type): New non-terminal (section_header): Handle section type. (opt_address_and_section_type): Return section type value.
This commit is contained in:
parent
86da934b14
commit
1e5d2fb127
@ -502,13 +502,27 @@ Layout::choose_output_section(const Relobj* relobj, const char* name,
|
||||
Script_sections* ss = this->script_options_->script_sections();
|
||||
const char* file_name = relobj == NULL ? NULL : relobj->name().c_str();
|
||||
Output_section** output_section_slot;
|
||||
name = ss->output_section_name(file_name, name, &output_section_slot);
|
||||
Script_sections::Section_type script_section_type;
|
||||
name = ss->output_section_name(file_name, name, &output_section_slot,
|
||||
&script_section_type);
|
||||
if (name == NULL)
|
||||
{
|
||||
// The SECTIONS clause says to discard this input section.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// We can only handle script section types ST_NONE and ST_NOLOAD.
|
||||
switch (script_section_type)
|
||||
{
|
||||
case Script_sections::ST_NONE:
|
||||
break;
|
||||
case Script_sections::ST_NOLOAD:
|
||||
flags &= elfcpp::SHF_ALLOC;
|
||||
break;
|
||||
default:
|
||||
gold_unreachable();
|
||||
}
|
||||
|
||||
// If this is an orphan section--one not mentioned in the linker
|
||||
// script--then OUTPUT_SECTION_SLOT will be NULL, and we do the
|
||||
// default processing below.
|
||||
@ -533,6 +547,25 @@ Layout::choose_output_section(const Relobj* relobj, const char* name,
|
||||
is_dynamic_linker_section, is_relro,
|
||||
is_last_relro, is_first_non_relro);
|
||||
os->set_found_in_sections_clause();
|
||||
|
||||
// Special handling for NOLOAD sections.
|
||||
if (script_section_type == Script_sections::ST_NOLOAD)
|
||||
{
|
||||
os->set_is_noload();
|
||||
|
||||
// The constructor of Output_section sets addresses of non-ALLOC
|
||||
// sections to 0 by default. We don't want that for NOLOAD
|
||||
// sections even if they have no SHF_ALLOC flag.
|
||||
if ((os->flags() & elfcpp::SHF_ALLOC) == 0
|
||||
&& os->is_address_valid())
|
||||
{
|
||||
gold_assert(os->address() == 0
|
||||
&& !os->is_offset_valid()
|
||||
&& !os->is_data_size_valid());
|
||||
os->reset_address_and_file_offset();
|
||||
}
|
||||
}
|
||||
|
||||
*output_section_slot = os;
|
||||
return os;
|
||||
}
|
||||
@ -1157,13 +1190,20 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
|
||||
// Make an output section for a script.
|
||||
|
||||
Output_section*
|
||||
Layout::make_output_section_for_script(const char* name)
|
||||
Layout::make_output_section_for_script(
|
||||
const char* name,
|
||||
Script_sections::Section_type section_type)
|
||||
{
|
||||
name = this->namepool_.add(name, false, NULL);
|
||||
elfcpp::Elf_Xword sh_flags = elfcpp::SHF_ALLOC;
|
||||
if (section_type == Script_sections::ST_NOLOAD)
|
||||
sh_flags = 0;
|
||||
Output_section* os = this->make_output_section(name, elfcpp::SHT_PROGBITS,
|
||||
elfcpp::SHF_ALLOC, false,
|
||||
sh_flags, false,
|
||||
false, false, false, false);
|
||||
os->set_found_in_sections_clause();
|
||||
if (section_type == Script_sections::ST_NOLOAD)
|
||||
os->set_is_noload();
|
||||
return os;
|
||||
}
|
||||
|
||||
|
@ -600,7 +600,8 @@ class Layout
|
||||
|
||||
// Make a section for a linker script to hold data.
|
||||
Output_section*
|
||||
make_output_section_for_script(const char* name);
|
||||
make_output_section_for_script(const char* name,
|
||||
Script_sections::Section_type section_type);
|
||||
|
||||
// Make a segment. This is used by the linker script code.
|
||||
Output_segment*
|
||||
|
@ -1911,6 +1911,7 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
|
||||
generate_code_fills_at_write_(false),
|
||||
is_entsize_zero_(false),
|
||||
section_offsets_need_adjustment_(false),
|
||||
is_noload_(false),
|
||||
tls_offset_(0),
|
||||
checkpoint_(NULL),
|
||||
merge_section_map_(),
|
||||
@ -2588,8 +2589,9 @@ Output_section::do_reset_address_and_file_offset()
|
||||
{
|
||||
// An unallocated section has no address. Forcing this means that
|
||||
// we don't need special treatment for symbols defined in debug
|
||||
// sections. We do the same in the constructor.
|
||||
if ((this->flags_ & elfcpp::SHF_ALLOC) == 0)
|
||||
// sections. We do the same in the constructor. This does not
|
||||
// apply to NOLOAD sections though.
|
||||
if (((this->flags_ & elfcpp::SHF_ALLOC) == 0) && !this->is_noload_)
|
||||
this->set_address(0);
|
||||
|
||||
for (Input_section_list::iterator p = this->input_sections_.begin();
|
||||
|
@ -2894,6 +2894,16 @@ class Output_section : public Output_data
|
||||
void
|
||||
adjust_section_offsets();
|
||||
|
||||
// Whether this is a NOLOAD section.
|
||||
bool
|
||||
is_noload() const
|
||||
{ return this->is_noload_; }
|
||||
|
||||
// Set NOLOAD flag.
|
||||
void
|
||||
set_is_noload()
|
||||
{ this->is_noload_ = true; }
|
||||
|
||||
// Print merge statistics to stderr.
|
||||
void
|
||||
print_merge_stats();
|
||||
@ -3659,6 +3669,8 @@ class Output_section : public Output_data
|
||||
bool is_entsize_zero_ : 1;
|
||||
// Whether section offsets need adjustment due to relaxation.
|
||||
bool section_offsets_need_adjustment_ : 1;
|
||||
// Whether this is a NOLOAD section.
|
||||
bool is_noload_ : 1;
|
||||
// For SHT_TLS sections, the offset of this section relative to the base
|
||||
// of the TLS segment.
|
||||
uint64_t tls_offset_;
|
||||
|
@ -61,6 +61,18 @@ typedef Expression* Expression_ptr;
|
||||
typedef void* Expression_ptr;
|
||||
#endif
|
||||
|
||||
/* Script_section type. */
|
||||
enum Script_section_type
|
||||
{
|
||||
/* No section type. */
|
||||
SCRIPT_SECTION_TYPE_NONE,
|
||||
SCRIPT_SECTION_TYPE_NOLOAD,
|
||||
SCRIPT_SECTION_TYPE_DSECT,
|
||||
SCRIPT_SECTION_TYPE_COPY,
|
||||
SCRIPT_SECTION_TYPE_INFO,
|
||||
SCRIPT_SECTION_TYPE_OVERLAY
|
||||
};
|
||||
|
||||
/* A constraint for whether to use a particular output section
|
||||
definition. */
|
||||
|
||||
@ -83,6 +95,8 @@ struct Parser_output_section_header
|
||||
{
|
||||
/* The address. This may be NULL. */
|
||||
Expression_ptr address;
|
||||
/* Section type. May be NULL string. */
|
||||
enum Script_section_type section_type;
|
||||
/* The load address, from the AT specifier. This may be NULL. */
|
||||
Expression_ptr load_address;
|
||||
/* The alignment, from the ALIGN specifier. This may be NULL. */
|
||||
|
@ -356,7 +356,8 @@ class Sections_element
|
||||
// section name. This only real implementation is in
|
||||
// Output_section_definition.
|
||||
virtual const char*
|
||||
output_section_name(const char*, const char*, Output_section***)
|
||||
output_section_name(const char*, const char*, Output_section***,
|
||||
Script_sections::Section_type*)
|
||||
{ return NULL; }
|
||||
|
||||
// Initialize OSP with an output section.
|
||||
@ -1617,7 +1618,7 @@ class Output_section_definition : public Sections_element
|
||||
// section name.
|
||||
const char*
|
||||
output_section_name(const char* file_name, const char* section_name,
|
||||
Output_section***);
|
||||
Output_section***, Script_sections::Section_type*);
|
||||
|
||||
// Initialize OSP with an output section.
|
||||
void
|
||||
@ -1665,7 +1666,14 @@ class Output_section_definition : public Sections_element
|
||||
void
|
||||
print(FILE*) const;
|
||||
|
||||
// Return the output section type if specified or Script_sections::ST_NONE.
|
||||
Script_sections::Section_type
|
||||
section_type() const;
|
||||
|
||||
private:
|
||||
static const char*
|
||||
script_section_type_name(Script_section_type);
|
||||
|
||||
typedef std::vector<Output_section_element*> Output_section_elements;
|
||||
|
||||
// The output section name.
|
||||
@ -1698,6 +1706,8 @@ class Output_section_definition : public Sections_element
|
||||
uint64_t evaluated_addralign_;
|
||||
// The output section is relro.
|
||||
bool is_relro_;
|
||||
// The output section type if specified.
|
||||
enum Script_section_type script_section_type_;
|
||||
};
|
||||
|
||||
// Constructor.
|
||||
@ -1719,7 +1729,8 @@ Output_section_definition::Output_section_definition(
|
||||
evaluated_address_(0),
|
||||
evaluated_load_address_(0),
|
||||
evaluated_addralign_(0),
|
||||
is_relro_(false)
|
||||
is_relro_(false),
|
||||
script_section_type_(header->section_type)
|
||||
{
|
||||
}
|
||||
|
||||
@ -1815,7 +1826,8 @@ Output_section_definition::create_sections(Layout* layout)
|
||||
if ((*p)->needs_output_section())
|
||||
{
|
||||
const char* name = this->name_.c_str();
|
||||
this->output_section_ = layout->make_output_section_for_script(name);
|
||||
this->output_section_ =
|
||||
layout->make_output_section_for_script(name, this->section_type());
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1873,9 +1885,11 @@ Output_section_definition::finalize_symbols(Symbol_table* symtab,
|
||||
// Return the output section name to use for an input section name.
|
||||
|
||||
const char*
|
||||
Output_section_definition::output_section_name(const char* file_name,
|
||||
const char* section_name,
|
||||
Output_section*** slot)
|
||||
Output_section_definition::output_section_name(
|
||||
const char* file_name,
|
||||
const char* section_name,
|
||||
Output_section*** slot,
|
||||
Script_sections::Section_type *psection_type)
|
||||
{
|
||||
// Ask each element whether it matches NAME.
|
||||
for (Output_section_elements::const_iterator p = this->elements_.begin();
|
||||
@ -1887,6 +1901,7 @@ Output_section_definition::output_section_name(const char* file_name,
|
||||
// We found a match for NAME, which means that it should go
|
||||
// into this output section.
|
||||
*slot = &this->output_section_;
|
||||
*psection_type = this->section_type();
|
||||
return this->name_.c_str();
|
||||
}
|
||||
}
|
||||
@ -1906,6 +1921,9 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab,
|
||||
uint64_t* load_address)
|
||||
{
|
||||
uint64_t address;
|
||||
uint64_t old_dot_value = *dot_value;
|
||||
uint64_t old_load_address = *load_address;
|
||||
|
||||
if (this->address_ == NULL)
|
||||
address = *dot_value;
|
||||
else
|
||||
@ -1941,10 +1959,11 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab,
|
||||
|
||||
*dot_value = address;
|
||||
|
||||
// The address of non-SHF_ALLOC sections is forced to zero,
|
||||
// regardless of what the linker script wants.
|
||||
// Except for NOLOAD sections, the address of non-SHF_ALLOC sections is
|
||||
// forced to zero, regardless of what the linker script wants.
|
||||
if (this->output_section_ != NULL
|
||||
&& (this->output_section_->flags() & elfcpp::SHF_ALLOC) != 0)
|
||||
&& ((this->output_section_->flags() & elfcpp::SHF_ALLOC) != 0
|
||||
|| this->output_section_->is_noload()))
|
||||
this->output_section_->set_address(address);
|
||||
|
||||
this->evaluated_address_ = address;
|
||||
@ -2029,6 +2048,13 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab,
|
||||
this->output_section_->set_is_relro();
|
||||
else
|
||||
this->output_section_->clear_is_relro();
|
||||
|
||||
// If this is a NOLOAD section, keep dot and load address unchanged.
|
||||
if (this->output_section_->is_noload())
|
||||
{
|
||||
*dot_value = old_dot_value;
|
||||
*load_address = old_load_address;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2186,6 +2212,10 @@ Output_section_definition::print(FILE* f) const
|
||||
fprintf(f, " ");
|
||||
}
|
||||
|
||||
if (this->script_section_type_ != SCRIPT_SECTION_TYPE_NONE)
|
||||
fprintf(f, "(%s) ",
|
||||
this->script_section_type_name(this->script_section_type_));
|
||||
|
||||
fprintf(f, ": ");
|
||||
|
||||
if (this->load_address_ != NULL)
|
||||
@ -2235,6 +2265,52 @@ Output_section_definition::print(FILE* f) const
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
|
||||
Script_sections::Section_type
|
||||
Output_section_definition::section_type() const
|
||||
{
|
||||
switch (this->script_section_type_)
|
||||
{
|
||||
case SCRIPT_SECTION_TYPE_NONE:
|
||||
return Script_sections::ST_NONE;
|
||||
case SCRIPT_SECTION_TYPE_NOLOAD:
|
||||
return Script_sections::ST_NOLOAD;
|
||||
case SCRIPT_SECTION_TYPE_COPY:
|
||||
case SCRIPT_SECTION_TYPE_DSECT:
|
||||
case SCRIPT_SECTION_TYPE_INFO:
|
||||
case SCRIPT_SECTION_TYPE_OVERLAY:
|
||||
// There are not really support so we treat them as ST_NONE. The
|
||||
// parse should have issued errors for them already.
|
||||
return Script_sections::ST_NONE;
|
||||
default:
|
||||
gold_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
// Return the name of a script section type.
|
||||
|
||||
const char*
|
||||
Output_section_definition::script_section_type_name (
|
||||
Script_section_type script_section_type)
|
||||
{
|
||||
switch (script_section_type)
|
||||
{
|
||||
case SCRIPT_SECTION_TYPE_NONE:
|
||||
return "NONE";
|
||||
case SCRIPT_SECTION_TYPE_NOLOAD:
|
||||
return "NOLOAD";
|
||||
case SCRIPT_SECTION_TYPE_DSECT:
|
||||
return "DSECT";
|
||||
case SCRIPT_SECTION_TYPE_COPY:
|
||||
return "COPY";
|
||||
case SCRIPT_SECTION_TYPE_INFO:
|
||||
return "INFO";
|
||||
case SCRIPT_SECTION_TYPE_OVERLAY:
|
||||
return "OVERLAY";
|
||||
default:
|
||||
gold_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
// An output section created to hold orphaned input sections. These
|
||||
// do not actually appear in linker scripts. However, for convenience
|
||||
// when setting the output section addresses, we put a marker to these
|
||||
@ -2724,16 +2800,19 @@ Script_sections::finalize_symbols(Symbol_table* symtab, const Layout* layout)
|
||||
// and section name.
|
||||
|
||||
const char*
|
||||
Script_sections::output_section_name(const char* file_name,
|
||||
const char* section_name,
|
||||
Output_section*** output_section_slot)
|
||||
Script_sections::output_section_name(
|
||||
const char* file_name,
|
||||
const char* section_name,
|
||||
Output_section*** output_section_slot,
|
||||
Script_sections::Section_type *psection_type)
|
||||
{
|
||||
for (Sections_elements::const_iterator p = this->sections_elements_->begin();
|
||||
p != this->sections_elements_->end();
|
||||
++p)
|
||||
{
|
||||
const char* ret = (*p)->output_section_name(file_name, section_name,
|
||||
output_section_slot);
|
||||
output_section_slot,
|
||||
psection_type);
|
||||
|
||||
if (ret != NULL)
|
||||
{
|
||||
@ -2742,6 +2821,7 @@ Script_sections::output_section_name(const char* file_name,
|
||||
if (strcmp(ret, "/DISCARD/") == 0)
|
||||
{
|
||||
*output_section_slot = NULL;
|
||||
*psection_type = Script_sections::ST_NONE;
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
@ -2752,6 +2832,7 @@ Script_sections::output_section_name(const char* file_name,
|
||||
// gets the name of the input section.
|
||||
|
||||
*output_section_slot = NULL;
|
||||
*psection_type = Script_sections::ST_NONE;
|
||||
|
||||
return section_name;
|
||||
}
|
||||
@ -2967,6 +3048,12 @@ Sort_output_sections::operator()(const Output_section* os1,
|
||||
if (os1->type() == elfcpp::SHT_NOBITS && os2->type() == elfcpp::SHT_PROGBITS)
|
||||
return false;
|
||||
|
||||
// Sort non-NOLOAD before NOLOAD.
|
||||
if (os1->is_noload() && !os2->is_noload())
|
||||
return true;
|
||||
if (!os1->is_noload() && os2->is_noload())
|
||||
return true;
|
||||
|
||||
// Otherwise we don't care.
|
||||
return false;
|
||||
}
|
||||
|
@ -52,6 +52,20 @@ class Script_sections
|
||||
typedef std::list<Sections_element*> Sections_elements;
|
||||
|
||||
public:
|
||||
|
||||
// Logical script section types. We map section types returned by the
|
||||
// parser into these since some section types have the same semantics.
|
||||
enum Section_type
|
||||
{
|
||||
// No section type specified.
|
||||
ST_NONE,
|
||||
// Section is NOLOAD. We allocate space in the output but section
|
||||
// is not loaded in runtime.
|
||||
ST_NOLOAD,
|
||||
// No space is allocated to section.
|
||||
ST_NOALLOC
|
||||
};
|
||||
|
||||
Script_sections();
|
||||
|
||||
// Start a SECTIONS clause.
|
||||
@ -147,9 +161,13 @@ class Script_sections
|
||||
// 3) If the input section is not mapped by the SECTIONS clause,
|
||||
// this returns SECTION_NAME, and sets *OUTPUT_SECTION_SLOT to
|
||||
// NULL.
|
||||
// PSCRIPT_SECTION_TYPE points to a location for returning the section
|
||||
// type specified in script. This can be SCRIPT_SECTION_TYPE_NONE if
|
||||
// no type is specified.
|
||||
const char*
|
||||
output_section_name(const char* file_name, const char* section_name,
|
||||
Output_section*** output_section_slot);
|
||||
Output_section*** output_section_slot,
|
||||
Section_type* pscript_section_type);
|
||||
|
||||
// Place a marker for an orphan output section into the SECTIONS
|
||||
// clause.
|
||||
|
@ -1646,11 +1646,13 @@ script_keyword_parsecodes[] =
|
||||
{ "BYTE", BYTE },
|
||||
{ "CONSTANT", CONSTANT },
|
||||
{ "CONSTRUCTORS", CONSTRUCTORS },
|
||||
{ "COPY", COPY },
|
||||
{ "CREATE_OBJECT_SYMBOLS", CREATE_OBJECT_SYMBOLS },
|
||||
{ "DATA_SEGMENT_ALIGN", DATA_SEGMENT_ALIGN },
|
||||
{ "DATA_SEGMENT_END", DATA_SEGMENT_END },
|
||||
{ "DATA_SEGMENT_RELRO_END", DATA_SEGMENT_RELRO_END },
|
||||
{ "DEFINED", DEFINED },
|
||||
{ "DSECT", DSECT },
|
||||
{ "ENTRY", ENTRY },
|
||||
{ "EXCLUDE_FILE", EXCLUDE_FILE },
|
||||
{ "EXTERN", EXTERN },
|
||||
@ -1660,6 +1662,7 @@ script_keyword_parsecodes[] =
|
||||
{ "GROUP", GROUP },
|
||||
{ "HLL", HLL },
|
||||
{ "INCLUDE", INCLUDE },
|
||||
{ "INFO", INFO },
|
||||
{ "INHIBIT_COMMON_ALLOCATION", INHIBIT_COMMON_ALLOCATION },
|
||||
{ "INPUT", INPUT },
|
||||
{ "KEEP", KEEP },
|
||||
@ -1673,6 +1676,7 @@ script_keyword_parsecodes[] =
|
||||
{ "NEXT", NEXT },
|
||||
{ "NOCROSSREFS", NOCROSSREFS },
|
||||
{ "NOFLOAT", NOFLOAT },
|
||||
{ "NOLOAD", NOLOAD },
|
||||
{ "ONLY_IF_RO", ONLY_IF_RO },
|
||||
{ "ONLY_IF_RW", ONLY_IF_RW },
|
||||
{ "OPTION", OPTION },
|
||||
|
@ -77,6 +77,7 @@
|
||||
struct Version_dependency_list* deplist;
|
||||
struct Version_expression_list* versyms;
|
||||
struct Version_tree* versnode;
|
||||
enum Script_section_type section_type;
|
||||
}
|
||||
|
||||
/* Operators, including a precedence table for expressions. */
|
||||
@ -121,11 +122,13 @@
|
||||
%token BYTE
|
||||
%token CONSTANT
|
||||
%token CONSTRUCTORS
|
||||
%token COPY
|
||||
%token CREATE_OBJECT_SYMBOLS
|
||||
%token DATA_SEGMENT_ALIGN
|
||||
%token DATA_SEGMENT_END
|
||||
%token DATA_SEGMENT_RELRO_END
|
||||
%token DEFINED
|
||||
%token DSECT
|
||||
%token ENTRY
|
||||
%token EXCLUDE_FILE
|
||||
%token EXTERN
|
||||
@ -137,6 +140,7 @@
|
||||
%token HLL
|
||||
%token INCLUDE
|
||||
%token INHIBIT_COMMON_ALLOCATION
|
||||
%token INFO
|
||||
%token INPUT
|
||||
%token KEEP
|
||||
%token LENGTH /* LENGTH, l, len */
|
||||
@ -150,6 +154,7 @@
|
||||
%token NEXT
|
||||
%token NOCROSSREFS
|
||||
%token NOFLOAT
|
||||
%token NOLOAD
|
||||
%token ONLY_IF_RO
|
||||
%token ONLY_IF_RW
|
||||
%token ORIGIN /* ORIGIN, o, org */
|
||||
@ -197,9 +202,10 @@
|
||||
|
||||
/* Non-terminal types, where needed. */
|
||||
|
||||
%type <expr> parse_exp exp opt_address_and_section_type
|
||||
%type <expr> parse_exp exp
|
||||
%type <expr> opt_at opt_align opt_subalign opt_fill
|
||||
%type <output_section_header> section_header
|
||||
%type <output_section_header> section_header opt_address_and_section_type
|
||||
%type <section_type> section_type
|
||||
%type <output_section_trailer> section_trailer
|
||||
%type <constraint> opt_constraint
|
||||
%type <string_list> opt_phdr
|
||||
@ -343,7 +349,8 @@ section_header:
|
||||
{ script_pop_lex_mode(closure); }
|
||||
opt_constraint
|
||||
{
|
||||
$$.address = $2;
|
||||
$$.address = $2.address;
|
||||
$$.section_type = $2.section_type;
|
||||
$$.load_address = $3;
|
||||
$$.align = $4;
|
||||
$$.subalign = $5;
|
||||
@ -356,18 +363,61 @@ section_header:
|
||||
'(' in section_header. */
|
||||
|
||||
opt_address_and_section_type:
|
||||
':'
|
||||
{ $$ = NULL; }
|
||||
| '(' ')' ':'
|
||||
{ $$ = NULL; }
|
||||
| exp ':'
|
||||
{ $$ = $1; }
|
||||
| exp '(' ')' ':'
|
||||
{ $$ = $1; }
|
||||
| exp '(' string ')' ':'
|
||||
':'
|
||||
{
|
||||
yyerror(closure, "section types are not supported");
|
||||
$$ = $1;
|
||||
$$.address = NULL;
|
||||
$$.section_type = SCRIPT_SECTION_TYPE_NONE;
|
||||
}
|
||||
| '(' ')' ':'
|
||||
{
|
||||
$$.address = NULL;
|
||||
$$.section_type = SCRIPT_SECTION_TYPE_NONE;
|
||||
}
|
||||
| exp ':'
|
||||
{
|
||||
$$.address = $1;
|
||||
$$.section_type = SCRIPT_SECTION_TYPE_NONE;
|
||||
}
|
||||
| exp '(' ')' ':'
|
||||
{
|
||||
$$.address = $1;
|
||||
$$.section_type = SCRIPT_SECTION_TYPE_NONE;
|
||||
}
|
||||
| '(' section_type ')' ':'
|
||||
{
|
||||
$$.address = NULL;
|
||||
$$.section_type = $2;
|
||||
}
|
||||
| exp '(' section_type ')' ':'
|
||||
{
|
||||
$$.address = $1;
|
||||
$$.section_type = $3;
|
||||
}
|
||||
;
|
||||
|
||||
/* We only support NOLOAD. */
|
||||
section_type:
|
||||
NOLOAD
|
||||
{ $$ = SCRIPT_SECTION_TYPE_NOLOAD; }
|
||||
| DSECT
|
||||
{
|
||||
yyerror(closure, "DSECT section type is unsupported");
|
||||
$$ = SCRIPT_SECTION_TYPE_DSECT;
|
||||
}
|
||||
| COPY
|
||||
{
|
||||
yyerror(closure, "COPY section type is unsupported");
|
||||
$$ = SCRIPT_SECTION_TYPE_COPY;
|
||||
}
|
||||
| INFO
|
||||
{
|
||||
yyerror(closure, "INFO section type is unsupported");
|
||||
$$ = SCRIPT_SECTION_TYPE_INFO;
|
||||
}
|
||||
| OVERLAY
|
||||
{
|
||||
yyerror(closure, "OVERLAY section type is unsupported");
|
||||
$$ = SCRIPT_SECTION_TYPE_OVERLAY;
|
||||
}
|
||||
;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user