diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 297ce125168..f4d531f5bf8 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -6962,6 +6962,14 @@ bfd_get_section_limit (const bfd *abfd, const asection *sec)
           / bfd_octets_per_byte (abfd, sec));
 }
 
+static inline bfd_size_type
+bfd_get_section_alloc_size (const bfd *abfd, const asection *sec)
+{
+  if (abfd->direction != write_direction && sec->rawsize > sec->size)
+    return sec->rawsize;
+  return sec->size;
+}
+
 /* Functions to handle insertion and deletion of a bfd's sections.  These
    only handle the list pointers, ie. do not adjust section_count,
    target_index etc.  */
diff --git a/bfd/bfd.c b/bfd/bfd.c
index 12cb4bca0ec..97ce2b10450 100644
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -518,6 +518,14 @@ CODE_FRAGMENT
 .	   / bfd_octets_per_byte (abfd, sec));
 .}
 .
+.static inline bfd_size_type
+.bfd_get_section_alloc_size (const bfd *abfd, const asection *sec)
+.{
+.  if (abfd->direction != write_direction && sec->rawsize > sec->size)
+.    return sec->rawsize;
+.  return sec->size;
+.}
+.
 .{* Functions to handle insertion and deletion of a bfd's sections.  These
 .   only handle the list pointers, ie. do not adjust section_count,
 .   target_index etc.  *}
diff --git a/bfd/coff-alpha.c b/bfd/coff-alpha.c
index ea217f77ace..2ac47754aa1 100644
--- a/bfd/coff-alpha.c
+++ b/bfd/coff-alpha.c
@@ -745,6 +745,7 @@ alpha_ecoff_get_relocated_section_contents (bfd *abfd,
   if (reloc_size < 0)
     return NULL;
 
+  bfd_byte *orig_data = data;
   if (!bfd_get_full_section_contents (input_bfd, input_section, &data))
     return NULL;
 
@@ -756,7 +757,7 @@ alpha_ecoff_get_relocated_section_contents (bfd *abfd,
 
   reloc_vector = (arelent **) bfd_malloc (reloc_size);
   if (reloc_vector == NULL)
-    return NULL;
+    goto error_return;
 
   reloc_count = bfd_canonicalize_reloc (input_bfd, input_section,
 					reloc_vector, symbols);
@@ -1138,6 +1139,8 @@ alpha_ecoff_get_relocated_section_contents (bfd *abfd,
 
  error_return:
   free (reloc_vector);
+  if (orig_data == NULL)
+    free (data);
   return NULL;
 }
 
diff --git a/bfd/coff-sh.c b/bfd/coff-sh.c
index d030c475539..c0f6fb42f6d 100644
--- a/bfd/coff-sh.c
+++ b/bfd/coff-sh.c
@@ -2922,6 +2922,13 @@ sh_coff_get_relocated_section_contents (bfd *output_bfd,
 						       relocatable,
 						       symbols);
 
+  bfd_byte *orig_data = data;
+  if (data == NULL)
+    {
+      data = bfd_malloc (input_section->size);
+      if (data == NULL)
+	return NULL;
+    }
   memcpy (data, coff_section_data (input_bfd, input_section)->contents,
 	  (size_t) input_section->size);
 
@@ -2997,6 +3004,8 @@ sh_coff_get_relocated_section_contents (bfd *output_bfd,
   free (internal_relocs);
   free (internal_syms);
   free (sections);
+  if (orig_data == NULL)
+    free (data);
   return NULL;
 }
 
diff --git a/bfd/compress.c b/bfd/compress.c
index 6a30af5f8e6..86422ba01f4 100644
--- a/bfd/compress.c
+++ b/bfd/compress.c
@@ -720,7 +720,8 @@ DESCRIPTION
 bool
 bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
 {
-  bfd_size_type sz = bfd_get_section_limit_octets (abfd, sec);
+  bfd_size_type readsz = bfd_get_section_limit_octets (abfd, sec);
+  bfd_size_type allocsz = bfd_get_section_alloc_size (abfd, sec);
   bfd_byte *p = *ptr;
   bool ret;
   bfd_size_type save_size;
@@ -729,7 +730,7 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
   unsigned int compression_header_size;
   const unsigned int compress_status = sec->compress_status;
 
-  if (sz == 0)
+  if (allocsz == 0)
     {
       *ptr = NULL;
       return true;
@@ -744,7 +745,7 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
       _bfd_error_handler
 	/* xgettext:c-format */
 	(_("error: %pB(%pA) is too large (%#" PRIx64 " bytes)"),
-	 abfd, sec, (uint64_t) sz);
+	 abfd, sec, (uint64_t) readsz);
       return false;
     }
 
@@ -753,7 +754,7 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
     case COMPRESS_SECTION_NONE:
       if (p == NULL)
 	{
-	  p = (bfd_byte *) bfd_malloc (sz);
+	  p = (bfd_byte *) bfd_malloc (allocsz);
 	  if (p == NULL)
 	    {
 	      /* PR 20801: Provide a more helpful error message.  */
@@ -761,12 +762,12 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
 		_bfd_error_handler
 		  /* xgettext:c-format */
 		  (_("error: %pB(%pA) is too large (%#" PRIx64 " bytes)"),
-		  abfd, sec, (uint64_t) sz);
+		  abfd, sec, (uint64_t) allocsz);
 	      return false;
 	    }
 	}
 
-      if (!bfd_get_section_contents (abfd, sec, p, 0, sz))
+      if (!bfd_get_section_contents (abfd, sec, p, 0, readsz))
 	{
 	  if (*ptr != p)
 	    free (p);
@@ -799,7 +800,7 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
 	goto fail_compressed;
 
       if (p == NULL)
-	p = (bfd_byte *) bfd_malloc (sz);
+	p = (bfd_byte *) bfd_malloc (allocsz);
       if (p == NULL)
 	goto fail_compressed;
 
@@ -811,7 +812,7 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
       bool is_zstd = compress_status == DECOMPRESS_SECTION_ZSTD;
       if (!decompress_contents (
 	      is_zstd, compressed_buffer + compression_header_size,
-	      sec->compressed_size - compression_header_size, p, sz))
+	      sec->compressed_size - compression_header_size, p, readsz))
 	{
 	  bfd_set_error (bfd_error_bad_value);
 	  if (p != *ptr)
@@ -830,14 +831,14 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
 	return false;
       if (p == NULL)
 	{
-	  p = (bfd_byte *) bfd_malloc (sz);
+	  p = (bfd_byte *) bfd_malloc (allocsz);
 	  if (p == NULL)
 	    return false;
 	  *ptr = p;
 	}
       /* PR 17512; file: 5bc29788.  */
       if (p != sec->contents)
-	memcpy (p, sec->contents, sz);
+	memcpy (p, sec->contents, readsz);
       return true;
 
     default:
diff --git a/bfd/elf-m10200.c b/bfd/elf-m10200.c
index cd13ec94c77..948da5d9bc8 100644
--- a/bfd/elf-m10200.c
+++ b/bfd/elf-m10200.c
@@ -1289,6 +1289,13 @@ mn10200_elf_get_relocated_section_contents (bfd *output_bfd,
 
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
 
+  bfd_byte *orig_data = data;
+  if (data == NULL)
+    {
+      data = bfd_malloc (input_section->size);
+      if (data == NULL)
+	return NULL;
+    }
   memcpy (data, elf_section_data (input_section)->this_hdr.contents,
 	  (size_t) input_section->size);
 
@@ -1360,6 +1367,8 @@ mn10200_elf_get_relocated_section_contents (bfd *output_bfd,
     free (isymbuf);
   if (elf_section_data (input_section)->relocs != internal_relocs)
     free (internal_relocs);
+  if (orig_data == NULL)
+    free (data);
   return NULL;
 }
 
diff --git a/bfd/elf-m10300.c b/bfd/elf-m10300.c
index 3010b54cbf8..687223d83af 100644
--- a/bfd/elf-m10300.c
+++ b/bfd/elf-m10300.c
@@ -4431,6 +4431,13 @@ mn10300_elf_get_relocated_section_contents (bfd *output_bfd,
 
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
 
+  bfd_byte *orig_data = data;
+  if (data == NULL)
+    {
+      data = bfd_malloc (input_section->size);
+      if (data == NULL)
+	return NULL;
+    }
   memcpy (data, elf_section_data (input_section)->this_hdr.contents,
 	  (size_t) input_section->size);
 
@@ -4500,6 +4507,8 @@ mn10300_elf_get_relocated_section_contents (bfd *output_bfd,
     free (isymbuf);
   if (internal_relocs != elf_section_data (input_section)->relocs)
     free (internal_relocs);
+  if (orig_data == NULL)
+    free (data);
   return NULL;
 }
 
diff --git a/bfd/elf32-avr.c b/bfd/elf32-avr.c
index f8b89930ef5..9ab73528c50 100644
--- a/bfd/elf32-avr.c
+++ b/bfd/elf32-avr.c
@@ -3216,6 +3216,13 @@ elf32_avr_get_relocated_section_contents (bfd *output_bfd,
 						       symbols);
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
 
+  bfd_byte *orig_data = data;
+  if (data == NULL)
+    {
+      data = bfd_malloc (input_section->size);
+      if (data == NULL)
+	return NULL;
+    }
   memcpy (data, elf_section_data (input_section)->this_hdr.contents,
 	  (size_t) input_section->size);
 
@@ -3285,6 +3292,8 @@ elf32_avr_get_relocated_section_contents (bfd *output_bfd,
     free (isymbuf);
   if (elf_section_data (input_section)->relocs != internal_relocs)
     free (internal_relocs);
+  if (orig_data == NULL)
+    free (data);
   return NULL;
 }
 
diff --git a/bfd/elf32-cr16.c b/bfd/elf32-cr16.c
index 88d161eeef7..555736cc2f8 100644
--- a/bfd/elf32-cr16.c
+++ b/bfd/elf32-cr16.c
@@ -1481,6 +1481,13 @@ elf32_cr16_get_relocated_section_contents (bfd *output_bfd,
 
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
 
+  bfd_byte *orig_data = data;
+  if (data == NULL)
+    {
+      data = bfd_malloc (input_section->size);
+      if (data == NULL)
+	return NULL;
+    }
   memcpy (data, elf_section_data (input_section)->this_hdr.contents,
 	  (size_t) input_section->size);
 
@@ -1551,6 +1558,8 @@ elf32_cr16_get_relocated_section_contents (bfd *output_bfd,
     free (isymbuf);
   if (elf_section_data (input_section)->relocs != internal_relocs)
     free (internal_relocs);
+  if (orig_data == NULL)
+    free (data);
   return NULL;
 }
 
diff --git a/bfd/elf32-crx.c b/bfd/elf32-crx.c
index cc6962f7b0e..a7406c003ad 100644
--- a/bfd/elf32-crx.c
+++ b/bfd/elf32-crx.c
@@ -742,6 +742,13 @@ elf32_crx_get_relocated_section_contents (bfd *output_bfd,
 
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
 
+  bfd_byte *orig_data = data;
+  if (data == NULL)
+    {
+      data = bfd_malloc (input_section->size);
+      if (data == NULL)
+	return NULL;
+    }
   memcpy (data, elf_section_data (input_section)->this_hdr.contents,
 	  (size_t) input_section->size);
 
@@ -813,6 +820,8 @@ elf32_crx_get_relocated_section_contents (bfd *output_bfd,
     free (isymbuf);
   if (elf_section_data (input_section)->relocs != internal_relocs)
     free (internal_relocs);
+  if (orig_data == NULL)
+    free (data);
   return NULL;
 }
 
diff --git a/bfd/elf32-h8300.c b/bfd/elf32-h8300.c
index 6c65520d720..5afb8a7ecac 100644
--- a/bfd/elf32-h8300.c
+++ b/bfd/elf32-h8300.c
@@ -1623,6 +1623,13 @@ elf32_h8_get_relocated_section_contents (bfd *output_bfd,
 
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
 
+  bfd_byte *orig_data = data;
+  if (data == NULL)
+    {
+      data = bfd_malloc (input_section->size);
+      if (data == NULL)
+	return NULL;
+    }
   memcpy (data, elf_section_data (input_section)->this_hdr.contents,
 	  (size_t) input_section->size);
 
@@ -1693,6 +1700,8 @@ elf32_h8_get_relocated_section_contents (bfd *output_bfd,
     free (isymbuf);
   if (elf_section_data (input_section)->relocs != internal_relocs)
     free (internal_relocs);
+  if (orig_data == NULL)
+    free (data);
   return NULL;
 }
 
diff --git a/bfd/elf32-nds32.c b/bfd/elf32-nds32.c
index 35e0302ed74..5d22002d1b9 100644
--- a/bfd/elf32-nds32.c
+++ b/bfd/elf32-nds32.c
@@ -13100,6 +13100,7 @@ nds32_elf_get_relocated_section_contents (bfd *abfd,
     return NULL;
 
   /* Read in the section.  */
+  bfd_byte *orig_data = data;
   if (!nds32_get_section_contents (input_bfd, input_section, &data, false))
     return NULL;
 
@@ -13108,7 +13109,7 @@ nds32_elf_get_relocated_section_contents (bfd *abfd,
 
   reloc_vector = (arelent **) bfd_malloc (reloc_size);
   if (reloc_vector == NULL)
-    return NULL;
+    goto error_return;
 
   reloc_count = bfd_canonicalize_reloc (input_bfd, input_section,
 					reloc_vector, symbols);
@@ -13202,6 +13203,8 @@ nds32_elf_get_relocated_section_contents (bfd *abfd,
 
  error_return:
   free (reloc_vector);
+  if (orig_data == NULL)
+    free (data);
   return NULL;
 }
 
diff --git a/bfd/elf32-sh.c b/bfd/elf32-sh.c
index 73b861e18f3..8ababcf5199 100644
--- a/bfd/elf32-sh.c
+++ b/bfd/elf32-sh.c
@@ -5085,6 +5085,13 @@ sh_elf_get_relocated_section_contents (bfd *output_bfd,
 
   symtab_hdr = &elf_symtab_hdr (input_bfd);
 
+  bfd_byte *orig_data = data;
+  if (data == NULL)
+    {
+      data = bfd_malloc (input_section->size);
+      if (data == NULL)
+	return NULL;
+    }
   memcpy (data, elf_section_data (input_section)->this_hdr.contents,
 	  (size_t) input_section->size);
 
@@ -5155,6 +5162,8 @@ sh_elf_get_relocated_section_contents (bfd *output_bfd,
     free (isymbuf);
   if (elf_section_data (input_section)->relocs != internal_relocs)
     free (internal_relocs);
+  if (orig_data == NULL)
+    free (data);
   return NULL;
 }
 
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index f77ccde8409..f0db5ff193b 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -13301,6 +13301,7 @@ _bfd_elf_mips_get_relocated_section_contents
     return NULL;
 
   /* Read in the section.  */
+  bfd_byte *orig_data = data;
   if (!bfd_get_full_section_contents (input_bfd, input_section, &data))
     return NULL;
 
@@ -13331,6 +13332,8 @@ _bfd_elf_mips_get_relocated_section_contents
 	  else
 	    hip = &hi->next;
 	}
+      if (orig_data == NULL)
+	free (data);
       data = NULL;
       goto out;
     }
diff --git a/bfd/linker.c b/bfd/linker.c
index 0c2e3c10a67..df99ce9991a 100644
--- a/bfd/linker.c
+++ b/bfd/linker.c
@@ -2551,9 +2551,8 @@ default_indirect_link_order (bfd *output_bfd,
 {
   asection *input_section;
   bfd *input_bfd;
-  bfd_byte *contents = NULL;
+  bfd_byte *alloced = NULL;
   bfd_byte *new_contents;
-  bfd_size_type sec_size;
   file_ptr loc;
 
   BFD_ASSERT ((output_section->flags & SEC_HAS_CONTENTS) != 0);
@@ -2654,16 +2653,11 @@ default_indirect_link_order (bfd *output_bfd,
   else
     {
       /* Get and relocate the section contents.  */
-      sec_size = (input_section->rawsize > input_section->size
-		  ? input_section->rawsize
-		  : input_section->size);
-      contents = (bfd_byte *) bfd_malloc (sec_size);
-      if (contents == NULL && sec_size != 0)
-	goto error_return;
       new_contents = (bfd_get_relocated_section_contents
-		      (output_bfd, info, link_order, contents,
+		      (output_bfd, info, link_order, NULL,
 		       bfd_link_relocatable (info),
 		       _bfd_generic_link_get_symbols (input_bfd)));
+      alloced = new_contents;
       if (!new_contents)
 	goto error_return;
     }
@@ -2675,11 +2669,11 @@ default_indirect_link_order (bfd *output_bfd,
 				  new_contents, loc, input_section->size))
     goto error_return;
 
-  free (contents);
+  free (alloced);
   return true;
 
  error_return:
-  free (contents);
+  free (alloced);
   return false;
 }
 
diff --git a/bfd/reloc.c b/bfd/reloc.c
index 6446acc7a30..3b5520f7d25 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -8532,6 +8532,7 @@ bfd_generic_get_relocated_section_contents (bfd *abfd,
     return NULL;
 
   /* Read in the section.  */
+  bfd_byte *orig_data = data;
   if (!bfd_get_full_section_contents (input_bfd, input_section, &data))
     return NULL;
 
@@ -8543,7 +8544,7 @@ bfd_generic_get_relocated_section_contents (bfd *abfd,
 
   reloc_vector = (arelent **) bfd_malloc (reloc_size);
   if (reloc_vector == NULL)
-    return NULL;
+    goto error_return;
 
   reloc_count = bfd_canonicalize_reloc (input_bfd,
 					input_section,
@@ -8680,6 +8681,8 @@ bfd_generic_get_relocated_section_contents (bfd *abfd,
 
  error_return:
   free (reloc_vector);
+  if (orig_data == NULL)
+    free (data);
   return NULL;
 }
 
diff --git a/bfd/reloc16.c b/bfd/reloc16.c
index 3ae8492a23b..7c8586cf19c 100644
--- a/bfd/reloc16.c
+++ b/bfd/reloc16.c
@@ -251,11 +251,11 @@ bfd_coff_reloc16_get_relocated_section_contents
   /* Get enough memory to hold the stuff.  */
   bfd *input_bfd = link_order->u.indirect.section->owner;
   asection *input_section = link_order->u.indirect.section;
-  long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section);
+  long reloc_size;
   arelent **reloc_vector;
   long reloc_count;
-  bfd_size_type sz;
 
+  reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section);
   if (reloc_size < 0)
     return NULL;
 
@@ -267,23 +267,26 @@ bfd_coff_reloc16_get_relocated_section_contents
 						       symbols);
 
   /* Read in the section.  */
-  sz = input_section->rawsize ? input_section->rawsize : input_section->size;
-  if (!bfd_get_section_contents (input_bfd, input_section, data, 0, sz))
+  bfd_byte *orig_data = data;
+  if (!bfd_get_full_section_contents (input_bfd, input_section, &data))
     return NULL;
 
-  reloc_vector = (arelent **) bfd_malloc ((bfd_size_type) reloc_size);
-  if (!reloc_vector && reloc_size != 0)
+  if (data == NULL)
     return NULL;
 
+  if (reloc_size == 0)
+    return data;
+
+  reloc_vector = (arelent **) bfd_malloc (reloc_size);
+  if (reloc_vector == NULL)
+    goto error_return;
+
   reloc_count = bfd_canonicalize_reloc (input_bfd,
 					input_section,
 					reloc_vector,
 					symbols);
   if (reloc_count < 0)
-    {
-      free (reloc_vector);
-      return NULL;
-    }
+    goto error_return;
 
   if (reloc_count > 0)
     {
@@ -324,6 +327,12 @@ bfd_coff_reloc16_get_relocated_section_contents
 	    }
 	}
     }
-  free ((char *) reloc_vector);
+  free (reloc_vector);
   return data;
+
+ error_return:
+  free (reloc_vector);
+  if (orig_data == NULL)
+    free (data);
+  return NULL;
 }
diff --git a/bfd/simple.c b/bfd/simple.c
index 67e326d4625..4c8b05832a5 100644
--- a/bfd/simple.c
+++ b/bfd/simple.c
@@ -209,7 +209,7 @@ bfd_simple_get_relocated_section_contents (bfd *abfd,
   struct bfd_link_info link_info;
   struct bfd_link_order link_order;
   struct bfd_link_callbacks callbacks;
-  bfd_byte *contents, *data;
+  bfd_byte *contents;
   struct saved_offsets saved_offsets;
   bfd *link_next;
 
@@ -257,28 +257,19 @@ bfd_simple_get_relocated_section_contents (bfd *abfd,
   link_order.size = sec->size;
   link_order.u.indirect.section = sec;
 
-  data = NULL;
   contents = NULL;
-  if (outbuf == NULL)
-    {
-      bfd_size_type amt = sec->rawsize > sec->size ? sec->rawsize : sec->size;
-      data = (bfd_byte *) bfd_malloc (amt);
-      if (data == NULL)
-	goto out1;
-      outbuf = data;
-    }
 
   saved_offsets.section_count = abfd->section_count;
   saved_offsets.sections = malloc (sizeof (*saved_offsets.sections)
 				   * saved_offsets.section_count);
   if (saved_offsets.sections == NULL)
-    goto out2;
+    goto out1;
   bfd_map_over_sections (abfd, simple_save_output_info, &saved_offsets);
 
   if (symbol_table == NULL)
     {
       if (!bfd_generic_link_read_symbols (abfd))
-	goto out3;
+	goto out2;
       symbol_table = _bfd_generic_link_get_symbols (abfd);
     }
 
@@ -288,12 +279,9 @@ bfd_simple_get_relocated_section_contents (bfd *abfd,
 						 outbuf,
 						 false,
 						 symbol_table);
- out3:
+ out2:
   bfd_map_over_sections (abfd, simple_restore_output_info, &saved_offsets);
   free (saved_offsets.sections);
- out2:
-  if (contents == NULL)
-    free (data);
  out1:
   _bfd_generic_link_hash_table_free (abfd);
   abfd->link.next = link_next;
