aboutsummaryrefslogtreecommitdiff
path: root/gold/output.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gold/output.cc')
-rw-r--r--gold/output.cc63
1 files changed, 48 insertions, 15 deletions
diff --git a/gold/output.cc b/gold/output.cc
index 0e28629..4c6959e 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -294,12 +294,14 @@ Output_segment_headers::do_sized_write(Output_file* of)
Output_file_header::Output_file_header(const Target* target,
const Symbol_table* symtab,
- const Output_segment_headers* osh)
+ const Output_segment_headers* osh,
+ const char* entry)
: target_(target),
symtab_(symtab),
segment_header_(osh),
section_header_(NULL),
- shstrtab_(NULL)
+ shstrtab_(NULL),
+ entry_(entry)
{
const int size = parameters->get_size();
int ehdr_size;
@@ -415,19 +417,7 @@ Output_file_header::do_sized_write(Output_file* of)
oehdr.put_e_machine(this->target_->machine_code());
oehdr.put_e_version(elfcpp::EV_CURRENT);
- // FIXME: Need to support -e, and target specific entry symbol.
- Symbol* sym = this->symtab_->lookup("_start");
- typename Sized_symbol<size>::Value_type v;
- if (sym == NULL)
- v = 0;
- else
- {
- Sized_symbol<size>* ssym;
- ssym = this->symtab_->get_sized_symbol SELECT_SIZE_NAME(size) (
- sym SELECT_SIZE(size));
- v = ssym->value();
- }
- oehdr.put_e_entry(v);
+ oehdr.put_e_entry(this->entry<size>());
oehdr.put_e_phoff(this->segment_header_->offset());
oehdr.put_e_shoff(this->section_header_->offset());
@@ -447,6 +437,49 @@ Output_file_header::do_sized_write(Output_file* of)
of->write_output_view(0, ehdr_size, view);
}
+// Return the value to use for the entry address. THIS->ENTRY_ is the
+// symbol specified on the command line, if any.
+
+template<int size>
+typename elfcpp::Elf_types<size>::Elf_Addr
+Output_file_header::entry()
+{
+ const bool should_issue_warning = (this->entry_ != NULL
+ && parameters->output_is_executable());
+
+ // FIXME: Need to support target specific entry symbol.
+ const char* entry = this->entry_;
+ if (entry == NULL)
+ entry = "_start";
+
+ Symbol* sym = this->symtab_->lookup(entry);
+
+ typename Sized_symbol<size>::Value_type v;
+ if (sym != NULL)
+ {
+ Sized_symbol<size>* ssym;
+ ssym = this->symtab_->get_sized_symbol<size>(sym);
+ if (!ssym->is_defined() && should_issue_warning)
+ gold_warning("entry symbol '%s' exists but is not defined", entry);
+ v = ssym->value();
+ }
+ else
+ {
+ // We couldn't find the entry symbol. See if we can parse it as
+ // a number. This supports, e.g., -e 0x1000.
+ char* endptr;
+ v = strtoull(entry, &endptr, 0);
+ if (*endptr != '\0')
+ {
+ if (should_issue_warning)
+ gold_warning("cannot find entry symbol '%s'", entry);
+ v = 0;
+ }
+ }
+
+ return v;
+}
+
// Output_data_const methods.
void