gdb/
[deliverable/binutils-gdb.git] / gold / output.cc
index 145fca159df5f00e0fb4bc7c3e6af3c592b9d5ac..2f9db62268d9f1be31b756da21a37f669bc31169 100644 (file)
@@ -1,6 +1,6 @@
 // output.cc -- manage the output file for gold
 
-// Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
 # define MAP_ANONYMOUS  MAP_ANON
 #endif
 
+#ifndef HAVE_POSIX_FALLOCATE
+// A dummy, non general, version of posix_fallocate.  Here we just set
+// the file size and hope that there is enough disk space.  FIXME: We
+// could allocate disk space by walking block by block and writing a
+// zero byte into each block.
+static int
+posix_fallocate(int o, off_t offset, off_t len)
+{
+  return ftruncate(o, offset + len);
+}
+#endif // !defined(HAVE_POSIX_FALLOCATE)
+
 namespace gold
 {
 
@@ -838,11 +850,11 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::
   Output_section* os = this->u1_.relobj->output_section(lsi);
   gold_assert(os != NULL);
   Address offset = this->u1_.relobj->get_output_section_offset(lsi);
-  if (offset != -1U)
+  if (offset != invalid_address)
     return offset + addend;
   // This is a merge section.
   offset = os->output_address(this->u1_.relobj, lsi, addend);
-  gold_assert(offset != -1U);
+  gold_assert(offset != invalid_address);
   return offset;
 }
 
@@ -858,13 +870,13 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::get_address() const
       Output_section* os = this->u2_.relobj->output_section(this->shndx_);
       gold_assert(os != NULL);
       Address off = this->u2_.relobj->get_output_section_offset(this->shndx_);
-      if (off != -1U)
+      if (off != invalid_address)
        address += os->address() + off;
       else
        {
          address = os->output_address(this->u2_.relobj, this->shndx_,
                                       address);
-         gold_assert(address != -1U);
+         gold_assert(address != invalid_address);
        }
     }
   else if (this->u2_.od != NULL)
@@ -2043,7 +2055,7 @@ Output_section::output_address(const Relobj* object, unsigned int shndx,
       if (p->output_offset(object, shndx, offset, &output_offset))
        {
          if (output_offset == -1)
-           return -1U;
+           return -1ULL;
          return addr + output_offset;
        }
       addr += p->data_size();
@@ -2057,12 +2069,13 @@ Output_section::output_address(const Relobj* object, unsigned int shndx,
   gold_unreachable();
 }
 
-// Return the output address of the start of the merged section for
+// Find the output address of the start of the merged section for
 // input section SHNDX in object OBJECT.
 
-uint64_t
-Output_section::starting_output_address(const Relobj* object,
-                                       unsigned int shndx) const
+bool
+Output_section::find_starting_output_address(const Relobj* object,
+                                            unsigned int shndx,
+                                            uint64_t* paddr) const
 {
   uint64_t addr = this->address() + this->first_input_offset_;
   for (Input_section_list::const_iterator p = this->input_sections_.begin();
@@ -2076,11 +2089,16 @@ Output_section::starting_output_address(const Relobj* object,
       // Unfortunately we don't know for sure that input offset 0 is
       // mapped at all.
       if (p->is_merge_section_for(object, shndx))
-       return addr;
+       {
+         *paddr = addr;
+         return true;
+       }
 
       addr += p->data_size();
     }
-  gold_unreachable();
+
+  // We couldn't find a merge output section for this input section.
+  return false;
 }
 
 // Set the data size of an Output_section.  This is where we handle
@@ -2651,8 +2669,7 @@ Output_segment::add_output_section(Output_section* os,
   // and the PT_TLS segment -- we do this grouping only for the
   // PT_LOAD segment.
   if (this->type_ != elfcpp::PT_TLS
-      && (os->flags() & elfcpp::SHF_TLS) != 0
-      && !this->output_data_.empty())
+      && (os->flags() & elfcpp::SHF_TLS) != 0)
     {
       pdl = &this->output_data_;
       bool nobits = os->type() == elfcpp::SHT_NOBITS;
@@ -2777,7 +2794,9 @@ Output_segment::maximum_alignment()
       // segment is a relro section, then the segment must be aligned
       // to at least the common page size.  This ensures that the
       // PT_GNU_RELRO segment will start at a page boundary.
-      if (parameters->options().relro() && this->is_first_section_relro())
+      if (this->type_ == elfcpp::PT_LOAD
+         && parameters->options().relro()
+         && this->is_first_section_relro())
        {
          addralign = parameters->target().common_pagesize();
          if (addralign > this->max_align_)
@@ -3381,12 +3400,16 @@ Output_file::map()
     }
   else
     {
-      // Write out one byte to make the file the right size.
-      if (::lseek(o, this->file_size_ - 1, SEEK_SET) < 0)
-        gold_fatal(_("%s: lseek: %s"), this->name_, strerror(errno));
-      char b = 0;
-      if (::write(o, &b, 1) != 1)
-        gold_fatal(_("%s: write: %s"), this->name_, strerror(errno));
+      // Ensure that we have disk space available for the file.  If we
+      // don't do this, it is possible that we will call munmap,
+      // close, and exit with dirty buffers still in the cache with no
+      // assigned disk blocks.  If the disk is out of space at that
+      // point, the output file will wind up incomplete, but we will
+      // have already exited.  The alternative to fallocate would be
+      // to use fdatasync, but that would be a more significant
+      // performance hit.
+      if (::posix_fallocate(o, 0, this->file_size_) < 0)
+       gold_fatal(_("%s: %s"), this->name_, strerror(errno));
 
       // Map the file into memory.
       this->map_is_anonymous_ = false;
@@ -3490,6 +3513,86 @@ Output_section::add_input_section<64, true>(
     bool have_sections_script);
 #endif
 
+#ifdef HAVE_TARGET_32_LITTLE
+template
+class Output_reloc<elfcpp::SHT_REL, false, 32, false>;
+#endif
+
+#ifdef HAVE_TARGET_32_BIG
+template
+class Output_reloc<elfcpp::SHT_REL, false, 32, true>;
+#endif
+
+#ifdef HAVE_TARGET_64_LITTLE
+template
+class Output_reloc<elfcpp::SHT_REL, false, 64, false>;
+#endif
+
+#ifdef HAVE_TARGET_64_BIG
+template
+class Output_reloc<elfcpp::SHT_REL, false, 64, true>;
+#endif
+
+#ifdef HAVE_TARGET_32_LITTLE
+template
+class Output_reloc<elfcpp::SHT_REL, true, 32, false>;
+#endif
+
+#ifdef HAVE_TARGET_32_BIG
+template
+class Output_reloc<elfcpp::SHT_REL, true, 32, true>;
+#endif
+
+#ifdef HAVE_TARGET_64_LITTLE
+template
+class Output_reloc<elfcpp::SHT_REL, true, 64, false>;
+#endif
+
+#ifdef HAVE_TARGET_64_BIG
+template
+class Output_reloc<elfcpp::SHT_REL, true, 64, true>;
+#endif
+
+#ifdef HAVE_TARGET_32_LITTLE
+template
+class Output_reloc<elfcpp::SHT_RELA, false, 32, false>;
+#endif
+
+#ifdef HAVE_TARGET_32_BIG
+template
+class Output_reloc<elfcpp::SHT_RELA, false, 32, true>;
+#endif
+
+#ifdef HAVE_TARGET_64_LITTLE
+template
+class Output_reloc<elfcpp::SHT_RELA, false, 64, false>;
+#endif
+
+#ifdef HAVE_TARGET_64_BIG
+template
+class Output_reloc<elfcpp::SHT_RELA, false, 64, true>;
+#endif
+
+#ifdef HAVE_TARGET_32_LITTLE
+template
+class Output_reloc<elfcpp::SHT_RELA, true, 32, false>;
+#endif
+
+#ifdef HAVE_TARGET_32_BIG
+template
+class Output_reloc<elfcpp::SHT_RELA, true, 32, true>;
+#endif
+
+#ifdef HAVE_TARGET_64_LITTLE
+template
+class Output_reloc<elfcpp::SHT_RELA, true, 64, false>;
+#endif
+
+#ifdef HAVE_TARGET_64_BIG
+template
+class Output_reloc<elfcpp::SHT_RELA, true, 64, true>;
+#endif
+
 #ifdef HAVE_TARGET_32_LITTLE
 template
 class Output_data_reloc<elfcpp::SHT_REL, false, 32, false>;
This page took 0.027418 seconds and 4 git commands to generate.