aboutsummaryrefslogtreecommitdiff
path: root/gold/layout.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2007-09-26 05:44:38 +0000
committerIan Lance Taylor <iant@google.com>2007-09-26 05:44:38 +0000
commit3151305a47fc17a35bc76cc50578b3e8f9b93d9d (patch)
tree7579f01394de3af6a03a35d162ae8c59fefaf9a8 /gold/layout.cc
parent4dffcebc10670489b064181a62e9588e72fb566a (diff)
downloadgdb-3151305a47fc17a35bc76cc50578b3e8f9b93d9d.zip
gdb-3151305a47fc17a35bc76cc50578b3e8f9b93d9d.tar.gz
gdb-3151305a47fc17a35bc76cc50578b3e8f9b93d9d.tar.bz2
Add basic exception frame header, plus test.
Diffstat (limited to 'gold/layout.cc')
-rw-r--r--gold/layout.cc55
1 files changed, 54 insertions, 1 deletions
diff --git a/gold/layout.cc b/gold/layout.cc
index d45970d..a05ebf1 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -31,6 +31,7 @@
#include "output.h"
#include "symtab.h"
#include "dynobj.h"
+#include "ehframe.h"
#include "layout.h"
namespace gold
@@ -65,7 +66,8 @@ Layout::Layout(const General_options& options)
section_name_map_(), segment_list_(), section_list_(),
unattached_section_list_(), special_output_list_(),
tls_segment_(NULL), symtab_section_(NULL),
- dynsym_section_(NULL), dynamic_section_(NULL), dynamic_data_(NULL)
+ dynsym_section_(NULL), dynamic_section_(NULL), dynamic_data_(NULL),
+ eh_frame_section_(NULL)
{
// Make space for more than enough segments for a typical file.
// This is just for efficiency--it's OK if we wind up needing more.
@@ -206,6 +208,17 @@ Layout::layout(Relobj* object, unsigned int shndx, const char* name,
shdr.get_sh_type(),
shdr.get_sh_flags());
+ // Special GNU handling of sections named .eh_frame.
+ if (!parameters->output_is_object()
+ && strcmp(name, ".eh_frame") == 0
+ && shdr.get_sh_size() > 0
+ && shdr.get_sh_type() == elfcpp::SHT_PROGBITS
+ && shdr.get_sh_flags() == elfcpp::SHF_ALLOC)
+ {
+ this->layout_eh_frame(object, shndx, name, shdr, os, off);
+ return os;
+ }
+
// FIXME: Handle SHF_LINK_ORDER somewhere.
*off = os->add_input_section(object, shndx, name, shdr);
@@ -213,6 +226,46 @@ Layout::layout(Relobj* object, unsigned int shndx, const char* name,
return os;
}
+// Special GNU handling of sections named .eh_frame. They will
+// normally hold exception frame data.
+
+template<int size, bool big_endian>
+void
+Layout::layout_eh_frame(Relobj* object,
+ unsigned int shndx,
+ const char* name,
+ const elfcpp::Shdr<size, big_endian>& shdr,
+ Output_section* os, off_t* off)
+{
+ if (this->eh_frame_section_ == NULL)
+ {
+ this->eh_frame_section_ = os;
+
+ if (this->options_.create_eh_frame_hdr())
+ {
+ Stringpool::Key hdr_name_key;
+ const char* hdr_name = this->namepool_.add(".eh_frame_hdr",
+ &hdr_name_key);
+ Output_section* hdr_os =
+ this->get_output_section(hdr_name, hdr_name_key,
+ elfcpp::SHT_PROGBITS,
+ elfcpp::SHF_ALLOC);
+
+ Eh_frame_hdr* hdr_posd = new Eh_frame_hdr(object->target(), os);
+ hdr_os->add_output_section_data(hdr_posd);
+
+ Output_segment* hdr_oseg =
+ new Output_segment(elfcpp::PT_GNU_EH_FRAME, elfcpp::PF_R);
+ this->segment_list_.push_back(hdr_oseg);
+ hdr_oseg->add_output_section(hdr_os, elfcpp::PF_R);
+ }
+ }
+
+ gold_assert(this->eh_frame_section_ == os);
+
+ *off = os->add_input_section(object, shndx, name, shdr);
+}
+
// Add POSD to an output section using NAME, TYPE, and FLAGS.
void