[PATCH 2/3 v3] src/readelf.c: Add support for print_debug_* output buffering

Aaron Merey amerey@redhat.com
Mon Jun 30 03:51:57 GMT 2025


Safely handle stdout output during concurrent calls to print_debug_*
functions.

For any print_debug_* function and any function that could be called
from print_debug_* which also prints to stdout: add a FILE * argument
and replace all printf, puts, putchar with fprintf.  All printing
to stdout will now be written to this FILE instead.

The FILE * is an interface to a per-thread dynamically-sized buffer.
libthread.a manages the allocation, printing and deallocation of
these buffers.

Signed-off-by: Aaron Merey <amerey@redhat.com>

---
v3: Reorder this patch to be 2/3 in the series instead of 3/3.

Remove unnecessary handling of null FILE *

 src/readelf.c | 2252 +++++++++++++++++++++++++------------------------
 1 file changed, 1150 insertions(+), 1102 deletions(-)

diff --git a/src/readelf.c b/src/readelf.c
index b7dba390..efb445ed 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -340,7 +340,7 @@ static void dump_strings (Ebl *ebl);
 static void print_strings (Ebl *ebl);
 static void dump_archive_index (Elf *, const char *);
 static void print_dwarf_addr (Dwfl_Module *dwflmod, int address_size,
-			      Dwarf_Addr address, Dwarf_Addr raw);
+			      Dwarf_Addr address, Dwarf_Addr raw, FILE *out);
 static void print_flag_info(void);
 
 enum dyn_idx
@@ -2535,7 +2535,7 @@ handle_relocs_relr (Ebl *ebl, Dwfl_Module *mod, Elf_Scn *scn, GElf_Shdr *shdr)
 	      if ((entry & 1) == 0)
 		{
 		  printf ("  ");
-		  print_dwarf_addr (mod, 4, entry, entry);
+		  print_dwarf_addr (mod, 4, entry, entry, stdout);
 		  printf (" *\n");
 
 		  base = entry + 4;
@@ -2548,7 +2548,7 @@ handle_relocs_relr (Ebl *ebl, Dwfl_Module *mod, Elf_Scn *scn, GElf_Shdr *shdr)
 		    if ((entry & 1) != 0)
 		      {
 			printf ("  ");
-			print_dwarf_addr (mod, 4, addr, addr);
+			print_dwarf_addr (mod, 4, addr, addr, stdout);
 			printf ("\n");
 		      }
 		  base += 4 * (4 * 8 - 1);
@@ -2574,7 +2574,7 @@ handle_relocs_relr (Ebl *ebl, Dwfl_Module *mod, Elf_Scn *scn, GElf_Shdr *shdr)
 	      if ((entry & 1) == 0)
 		{
 		  printf ("  ");
-		  print_dwarf_addr (mod, 8, entry, entry);
+		  print_dwarf_addr (mod, 8, entry, entry, stdout);
 		  printf (" *\n");
 
 		  base = entry + 8;
@@ -2587,7 +2587,7 @@ handle_relocs_relr (Ebl *ebl, Dwfl_Module *mod, Elf_Scn *scn, GElf_Shdr *shdr)
 		    if ((entry & 1) != 0)
 		      {
 			printf ("  ");
-			print_dwarf_addr (mod, 8, addr, addr);
+			print_dwarf_addr (mod, 8, addr, addr, stdout);
 			printf ("\n");
 		      }
 		  base += 8 * (8 * 8 - 1);
@@ -4295,7 +4295,8 @@ get_debug_elf_data (Dwarf *dbg, Ebl *ebl, int idx, Elf_Scn *scn)
 
 static void
 print_dwarf_addr (Dwfl_Module *dwflmod,
-		  int address_size, Dwarf_Addr address, Dwarf_Addr raw)
+		  int address_size, Dwarf_Addr address, Dwarf_Addr raw,
+		  FILE *out)
 {
   /* See if there is a name we can give for this address.  */
   GElf_Sym sym;
@@ -4325,33 +4326,35 @@ print_dwarf_addr (Dwfl_Module *dwflmod,
        ? (off != 0
 	  ? (scn != NULL
 	     ? (address_size == 0
-		? printf ("%s+%#" PRIx64 " <%s+%#" PRIx64 ">",
-			  scn, address, name, off)
-		: printf ("%s+%#0*" PRIx64 " <%s+%#" PRIx64 ">",
-			  scn, 2 + address_size * 2, address,
-			  name, off))
+		? fprintf (out, "%s+%#" PRIx64 " <%s+%#" PRIx64 ">",
+			   scn, address, name, off)
+		: fprintf (out, "%s+%#0*" PRIx64 " <%s+%#" PRIx64 ">",
+			   scn, 2 + address_size * 2, address,
+			   name, off))
 	     : (address_size == 0
-		? printf ("%#" PRIx64 " <%s+%#" PRIx64 ">",
-			  address, name, off)
-		: printf ("%#0*" PRIx64 " <%s+%#" PRIx64 ">",
-			  2 + address_size * 2, address,
-			  name, off)))
+		? fprintf (out, "%#" PRIx64 " <%s+%#" PRIx64 ">",
+			   address, name, off)
+		: fprintf (out, "%#0*" PRIx64 " <%s+%#" PRIx64 ">",
+			   2 + address_size * 2, address,
+			   name, off)))
 	  : (scn != NULL
 	     ? (address_size == 0
-		? printf ("%s+%#" PRIx64 " <%s>", scn, address, name)
-		: printf ("%s+%#0*" PRIx64 " <%s>",
+		? fprintf (out, "%s+%#" PRIx64 " <%s>", scn, address, name)
+		: fprintf (out, "%s+%#0*" PRIx64 " <%s>",
 			   scn, 2 + address_size * 2, address, name))
 	     : (address_size == 0
-		? printf ("%#" PRIx64 " <%s>", address, name)
-		: printf ("%#0*" PRIx64 " <%s>",
-			  2 + address_size * 2, address, name))))
+		? fprintf (out, "%#" PRIx64 " <%s>", address, name)
+		: fprintf (out, "%#0*" PRIx64 " <%s>",
+			   2 + address_size * 2, address, name))))
        : (scn != NULL
 	  ? (address_size == 0
-	     ? printf ("%s+%#" PRIx64, scn, address)
-	     : printf ("%s+%#0*" PRIx64, scn, 2 + address_size * 2, address))
+	     ? fprintf (out, "%s+%#" PRIx64, scn, address)
+	     : fprintf (out, "%s+%#0*" PRIx64,
+			scn, 2 + address_size * 2, address))
 	  : (address_size == 0
-	     ? printf ("%#" PRIx64, address)
-	     : printf ("%#0*" PRIx64, 2 + address_size * 2, address)))) < 0)
+	     ? fprintf (out, "%#" PRIx64, address)
+	     : fprintf (out, "%#0*" PRIx64,
+			2 + address_size * 2, address)))) < 0)
     error_exit (0, _("sprintf failure"));
 }
 
@@ -4856,29 +4859,29 @@ dwarf_line_content_description_name (unsigned int kind)
 
 
 static void
-print_block (size_t n, const void *block)
+print_block (size_t n, const void *block, FILE *out)
 {
   if (n == 0)
-    puts (_("empty block"));
+    fputs (_("empty block\n"), out);
   else
     {
-      printf (_("%zu byte block:"), n);
+      fprintf (out, _("%zu byte block:"), n);
       const unsigned char *data = block;
       do
-	printf (" %02x", *data++);
+	fprintf (out, " %02x", *data++);
       while (--n > 0);
-      putchar ('\n');
+      fputc ('\n', out);
     }
 }
 
 static void
-print_bytes (size_t n, const unsigned char *bytes)
+print_bytes (size_t n, const unsigned char *bytes, FILE *out)
 {
   while (n-- > 0)
     {
-      printf ("%02x", *bytes++);
+      fprintf (out, "%02x", *bytes++);
       if (n > 0)
-	printf (" ");
+	fprintf (out, " ");
     }
 }
 
@@ -4911,13 +4914,14 @@ get_indexed_addr (Dwarf_CU *cu, Dwarf_Word idx, Dwarf_Addr *addr)
 static void
 print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	   unsigned int vers, unsigned int addrsize, unsigned int offset_size,
-	   struct Dwarf_CU *cu, Dwarf_Word len, const unsigned char *data)
+	   struct Dwarf_CU *cu, Dwarf_Word len, const unsigned char *data,
+	   FILE *out)
 {
   const unsigned int ref_size = vers < 3 ? addrsize : offset_size;
 
   if (len == 0)
     {
-      printf ("%*s(empty)\n", indent, "");
+      fprintf (out, "%*s(empty)\n", indent, "");
       return;
     }
 
@@ -4955,10 +4959,10 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  data += addrsize;
 	  CONSUME (addrsize);
 
-	  printf ("%*s[%2" PRIuMAX "] %s ",
-		  indent, "", (uintmax_t) offset, op_name);
-	  print_dwarf_addr (dwflmod, 0, addr, addr);
-	  printf ("\n");
+	  fprintf (out, "%*s[%2" PRIuMAX "] %s ",
+		   indent, "", (uintmax_t) offset, op_name);
+	  print_dwarf_addr (dwflmod, 0, addr, addr, out);
+	  fprintf (out, "\n");
 
 	  offset += 1 + addrsize;
 	  break;
@@ -4976,9 +4980,9 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  data += ref_size;
 	  CONSUME (ref_size);
 	  /* addr is a DIE offset, so format it as one.  */
-	  printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "]\n",
-		  indent, "", (uintmax_t) offset,
-		  op_name, (uintmax_t) addr);
+	  fprintf (out, "%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "]\n",
+		   indent, "", (uintmax_t) offset,
+		   op_name, (uintmax_t) addr);
 	  offset += 1 + ref_size;
 	  break;
 
@@ -4988,9 +4992,9 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	case DW_OP_const1u:
 	  // XXX value might be modified by relocation
 	  NEED (1);
-	  printf ("%*s[%2" PRIuMAX "] %s %" PRIu8 "\n",
-		  indent, "", (uintmax_t) offset,
-		  op_name, *((uint8_t *) data));
+	  fprintf (out, "%*s[%2" PRIuMAX "] %s %" PRIu8 "\n",
+		   indent, "", (uintmax_t) offset,
+		   op_name, *((uint8_t *) data));
 	  ++data;
 	  --len;
 	  offset += 2;
@@ -4999,9 +5003,9 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	case DW_OP_const2u:
 	  NEED (2);
 	  // XXX value might be modified by relocation
-	  printf ("%*s[%2" PRIuMAX "] %s %" PRIu16 "\n",
-		  indent, "", (uintmax_t) offset,
-		  op_name, read_2ubyte_unaligned (dbg, data));
+	  fprintf (out, "%*s[%2" PRIuMAX "] %s %" PRIu16 "\n",
+		   indent, "", (uintmax_t) offset,
+		   op_name, read_2ubyte_unaligned (dbg, data));
 	  CONSUME (2);
 	  data += 2;
 	  offset += 3;
@@ -5010,9 +5014,9 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	case DW_OP_const4u:
 	  NEED (4);
 	  // XXX value might be modified by relocation
-	  printf ("%*s[%2" PRIuMAX "] %s %" PRIu32 "\n",
-		  indent, "", (uintmax_t) offset,
-		  op_name, read_4ubyte_unaligned (dbg, data));
+	  fprintf (out, "%*s[%2" PRIuMAX "] %s %" PRIu32 "\n",
+		   indent, "", (uintmax_t) offset,
+		   op_name, read_4ubyte_unaligned (dbg, data));
 	  CONSUME (4);
 	  data += 4;
 	  offset += 5;
@@ -5021,9 +5025,9 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	case DW_OP_const8u:
 	  NEED (8);
 	  // XXX value might be modified by relocation
-	  printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 "\n",
-		  indent, "", (uintmax_t) offset,
-		  op_name, (uint64_t) read_8ubyte_unaligned (dbg, data));
+	  fprintf (out, "%*s[%2" PRIuMAX "] %s %" PRIu64 "\n",
+		   indent, "", (uintmax_t) offset,
+		   op_name, (uint64_t) read_8ubyte_unaligned (dbg, data));
 	  CONSUME (8);
 	  data += 8;
 	  offset += 9;
@@ -5032,9 +5036,9 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	case DW_OP_const1s:
 	  NEED (1);
 	  // XXX value might be modified by relocation
-	  printf ("%*s[%2" PRIuMAX "] %s %" PRId8 "\n",
-		  indent, "", (uintmax_t) offset,
-		  op_name, *((int8_t *) data));
+	  fprintf (out, "%*s[%2" PRIuMAX "] %s %" PRId8 "\n",
+		   indent, "", (uintmax_t) offset,
+		   op_name, *((int8_t *) data));
 	  ++data;
 	  --len;
 	  offset += 2;
@@ -5043,9 +5047,9 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	case DW_OP_const2s:
 	  NEED (2);
 	  // XXX value might be modified by relocation
-	  printf ("%*s[%2" PRIuMAX "] %s %" PRId16 "\n",
-		  indent, "", (uintmax_t) offset,
-		  op_name, read_2sbyte_unaligned (dbg, data));
+	  fprintf (out, "%*s[%2" PRIuMAX "] %s %" PRId16 "\n",
+		   indent, "", (uintmax_t) offset,
+		   op_name, read_2sbyte_unaligned (dbg, data));
 	  CONSUME (2);
 	  data += 2;
 	  offset += 3;
@@ -5054,9 +5058,9 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	case DW_OP_const4s:
 	  NEED (4);
 	  // XXX value might be modified by relocation
-	  printf ("%*s[%2" PRIuMAX "] %s %" PRId32 "\n",
-		  indent, "", (uintmax_t) offset,
-		  op_name, read_4sbyte_unaligned (dbg, data));
+	  fprintf (out, "%*s[%2" PRIuMAX "] %s %" PRId32 "\n",
+		   indent, "", (uintmax_t) offset,
+		   op_name, read_4sbyte_unaligned (dbg, data));
 	  CONSUME (4);
 	  data += 4;
 	  offset += 5;
@@ -5065,9 +5069,9 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	case DW_OP_const8s:
 	  NEED (8);
 	  // XXX value might be modified by relocation
-	  printf ("%*s[%2" PRIuMAX "] %s %" PRId64 "\n",
-		  indent, "", (uintmax_t) offset,
-		  op_name, read_8sbyte_unaligned (dbg, data));
+	  fprintf (out, "%*s[%2" PRIuMAX "] %s %" PRId64 "\n",
+		   indent, "", (uintmax_t) offset,
+		   op_name, read_8sbyte_unaligned (dbg, data));
 	  CONSUME (8);
 	  data += 8;
 	  offset += 9;
@@ -5081,8 +5085,8 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  uint64_t uleb;
 	  NEED (1);
 	  get_uleb128 (uleb, data, data + len);
-	  printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 "\n",
-		  indent, "", (uintmax_t) offset, op_name, uleb);
+	  fprintf (out, "%*s[%2" PRIuMAX "] %s %" PRIu64 "\n",
+		   indent, "", (uintmax_t) offset, op_name, uleb);
 	  CONSUME (data - start);
 	  offset += 1 + (data - start);
 	  break;
@@ -5094,16 +5098,16 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  start = data;
 	  NEED (1);
 	  get_uleb128 (uleb, data, data + len);
-	  printf ("%*s[%2" PRIuMAX "] %s [%" PRIu64 "] ",
-		  indent, "", (uintmax_t) offset, op_name, uleb);
+	  fprintf (out, "%*s[%2" PRIuMAX "] %s [%" PRIu64 "] ",
+		   indent, "", (uintmax_t) offset, op_name, uleb);
 	  CONSUME (data - start);
 	  offset += 1 + (data - start);
 	  if (get_indexed_addr (cu, uleb, &addr) != 0)
-	    printf ("???\n");
+	    fprintf (out, "???\n");
 	  else
 	    {
-	      print_dwarf_addr (dwflmod, 0, addr, addr);
-	      printf ("\n");
+	      print_dwarf_addr (dwflmod, 0, addr, addr, out);
+	      fprintf (out, "\n");
 	    }
 	  break;
 
@@ -5114,8 +5118,8 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  get_uleb128 (uleb, data, data + len);
 	  NEED (1);
 	  get_uleb128 (uleb2, data, data + len);
-	  printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 ", %" PRIu64 "\n",
-		  indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
+	  fprintf (out, "%*s[%2" PRIuMAX "] %s %" PRIu64 ", %" PRIu64 "\n",
+		   indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
 	  CONSUME (data - start);
 	  offset += 1 + (data - start);
 	  break;
@@ -5127,8 +5131,8 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  int64_t sleb;
 	  NEED (1);
 	  get_sleb128 (sleb, data, data + len);
-	  printf ("%*s[%2" PRIuMAX "] %s %" PRId64 "\n",
-		  indent, "", (uintmax_t) offset, op_name, sleb);
+	  fprintf (out, "%*s[%2" PRIuMAX "] %s %" PRId64 "\n",
+		   indent, "", (uintmax_t) offset, op_name, sleb);
 	  CONSUME (data - start);
 	  offset += 1 + (data - start);
 	  break;
@@ -5139,17 +5143,17 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  get_uleb128 (uleb, data, data + len);
 	  NEED (1);
 	  get_sleb128 (sleb, data, data + len);
-	  printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 " %" PRId64 "\n",
-		  indent, "", (uintmax_t) offset, op_name, uleb, sleb);
+	  fprintf (out, "%*s[%2" PRIuMAX "] %s %" PRIu64 " %" PRId64 "\n",
+		   indent, "", (uintmax_t) offset, op_name, uleb, sleb);
 	  CONSUME (data - start);
 	  offset += 1 + (data - start);
 	  break;
 
 	case DW_OP_call2:
 	  NEED (2);
-	  printf ("%*s[%2" PRIuMAX "] %s [%6" PRIx16 "]\n",
-		  indent, "", (uintmax_t) offset, op_name,
-		  read_2ubyte_unaligned (dbg, data));
+	  fprintf (out, "%*s[%2" PRIuMAX "] %s [%6" PRIx16 "]\n",
+		   indent, "", (uintmax_t) offset, op_name,
+		   read_2ubyte_unaligned (dbg, data));
 	  CONSUME (2);
 	  data += 2;
 	  offset += 3;
@@ -5157,9 +5161,9 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 
 	case DW_OP_call4:
 	  NEED (4);
-	  printf ("%*s[%2" PRIuMAX "] %s [%6" PRIx32 "]\n",
-		  indent, "", (uintmax_t) offset, op_name,
-		  read_4ubyte_unaligned (dbg, data));
+	  fprintf (out, "%*s[%2" PRIuMAX "] %s [%6" PRIx32 "]\n",
+		   indent, "", (uintmax_t) offset, op_name,
+		   read_4ubyte_unaligned (dbg, data));
 	  CONSUME (4);
 	  data += 4;
 	  offset += 5;
@@ -5168,9 +5172,9 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	case DW_OP_skip:
 	case DW_OP_bra:
 	  NEED (2);
-	  printf ("%*s[%2" PRIuMAX "] %s %" PRIuMAX "\n",
-		  indent, "", (uintmax_t) offset, op_name,
-		  (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data) + 3));
+	  fprintf (out, "%*s[%2" PRIuMAX "] %s %" PRIuMAX "\n",
+		   indent, "", (uintmax_t) offset, op_name,
+		   (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data) + 3));
 	  CONSUME (2);
 	  data += 2;
 	  offset += 3;
@@ -5180,10 +5184,10 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  start = data;
 	  NEED (1);
 	  get_uleb128 (uleb, data, data + len);
-	  printf ("%*s[%2" PRIuMAX "] %s: ",
-		  indent, "", (uintmax_t) offset, op_name);
+	  fprintf (out, "%*s[%2" PRIuMAX "] %s: ",
+		   indent, "", (uintmax_t) offset, op_name);
 	  NEED (uleb);
-	  print_block (uleb, data);
+	  print_block (uleb, data, out);
 	  data += uleb;
 	  CONSUME (data - start);
 	  offset += 1 + (data - start);
@@ -5205,9 +5209,9 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  NEED (1);
 	  get_sleb128 (sleb, data, data + len);
 
-	  printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "] %+" PRId64 "\n",
-		  indent, "", (intmax_t) offset,
-		  op_name, (uintmax_t) addr, sleb);
+	  fprintf (out, "%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "] %+" PRId64 "\n",
+		   indent, "", (intmax_t) offset,
+		   op_name, (uintmax_t) addr, sleb);
 	  CONSUME (data - start);
 	  offset += 1 + (data - start);
 	  break;
@@ -5218,11 +5222,11 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  start = data;
 	  NEED (1);
 	  get_uleb128 (uleb, data, data + len);
-	  printf ("%*s[%2" PRIuMAX "] %s:\n",
-		  indent, "", (uintmax_t) offset, op_name);
+	  fprintf (out, "%*s[%2" PRIuMAX "] %s:\n",
+		   indent, "", (uintmax_t) offset, op_name);
 	  NEED (uleb);
 	  print_ops (dwflmod, dbg, indent + 5, indent + 5, vers,
-		     addrsize, offset_size, cu, uleb, data);
+		     addrsize, offset_size, cu, uleb, data, out);
 	  data += uleb;
 	  CONSUME (data - start);
 	  offset += 1 + (data - start);
@@ -5240,9 +5244,9 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  NEED (1);
 	  uint8_t usize = *(uint8_t *) data++;
 	  NEED (usize);
-	  printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "] ",
-		  indent, "", (uintmax_t) offset, op_name, uleb);
-	  print_block (usize, data);
+	  fprintf (out, "%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "] ",
+		   indent, "", (uintmax_t) offset, op_name, uleb);
+	  print_block (usize, data, out);
 	  data += usize;
 	  CONSUME (data - start);
 	  offset += 1 + (data - start);
@@ -5259,8 +5263,8 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  get_uleb128 (uleb2, data, data + len);
 	  if (! print_unresolved_addresses && cu != NULL)
 	    uleb2 += cu->start;
-	  printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 " [%6" PRIx64 "]\n",
-		  indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
+	  fprintf (out, "%*s[%2" PRIuMAX "] %s %" PRIu64 " [%6" PRIx64 "]\n",
+		   indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
 	  CONSUME (data - start);
 	  offset += 1 + (data - start);
 	  break;
@@ -5276,9 +5280,9 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  get_uleb128 (uleb, data, data + len);
 	  if (! print_unresolved_addresses && cu != NULL)
 	    uleb += cu->start;
-	  printf ("%*s[%2" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n",
-		  indent, "", (uintmax_t) offset,
-		  op_name, usize, uleb);
+	  fprintf (out, "%*s[%2" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n",
+		   indent, "", (uintmax_t) offset,
+		   op_name, usize, uleb);
 	  CONSUME (data - start);
 	  offset += 1 + (data - start);
 	  break;
@@ -5290,9 +5294,9 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  usize = *(uint8_t *) data++;
 	  NEED (1);
 	  get_uleb128 (uleb, data, data + len);
-	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n",
-		  indent, "", (uintmax_t) offset,
-		  op_name, usize, uleb);
+	  fprintf (out, "%*s[%4" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n",
+		   indent, "", (uintmax_t) offset,
+		   op_name, usize, uleb);
 	  CONSUME (data - start);
 	  offset += 1 + (data - start);
 	  break;
@@ -5308,8 +5312,8 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  get_uleb128 (uleb, data, data + len);
 	  if (uleb != 0 && ! print_unresolved_addresses && cu != NULL)
 	    uleb += cu->start;
-	  printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "]\n",
-		  indent, "", (uintmax_t) offset, op_name, uleb);
+	  fprintf (out, "%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "]\n",
+		   indent, "", (uintmax_t) offset, op_name, uleb);
 	  CONSUME (data - start);
 	  offset += 1 + (data - start);
 	  break;
@@ -5321,8 +5325,8 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  uintmax_t param_off = (uintmax_t) read_4ubyte_unaligned (dbg, data);
 	  if (! print_unresolved_addresses && cu != NULL)
 	    param_off += cu->start;
-	  printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "]\n",
-		  indent, "", (uintmax_t) offset, op_name, param_off);
+	  fprintf (out, "%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "]\n",
+		   indent, "", (uintmax_t) offset, op_name, param_off);
 	  CONSUME (4);
 	  data += 4;
 	  offset += 5;
@@ -5330,8 +5334,8 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 
 	default:
 	  /* No Operand.  */
-	  printf ("%*s[%2" PRIuMAX "] %s\n",
-		  indent, "", (uintmax_t) offset, op_name);
+	  fprintf (out, "%*s[%2" PRIuMAX "] %s\n",
+		   indent, "", (uintmax_t) offset, op_name);
 	  ++offset;
 	  break;
 	}
@@ -5340,8 +5344,8 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
       continue;
 
     invalid:
-      printf (_("%*s[%2" PRIuMAX "] %s  <TRUNCATED>\n"),
-	      indent, "", (uintmax_t) offset, op_name);
+      fprintf (out, _("%*s[%2" PRIuMAX "] %s  <TRUNCATED>\n"),
+	       indent, "", (uintmax_t) offset, op_name);
       break;
     }
 }
@@ -5739,7 +5743,8 @@ listptr_attr (struct listptr_table *table, size_t idxp,
 static void
 print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 			    Ebl *ebl, GElf_Ehdr *ehdr __attribute__ ((unused)),
-			    Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+			    Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg,
+			    FILE *out)
 {
   Elf_Data *elf_data = get_debug_elf_data (dbg, ebl, IDX_debug_abbrev, scn);
   if (elf_data == NULL)
@@ -5747,16 +5752,16 @@ print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 
   const size_t sh_size = elf_data->d_size;
 
-  printf (_("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
-		   " [ Code]\n"),
-	  elf_ndxscn (scn), section_name (ebl, shdr),
-	  (uint64_t) shdr->sh_offset);
+  fprintf (out, _("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
+		  " [ Code]\n"),
+	   elf_ndxscn (scn), section_name (ebl, shdr),
+	   (uint64_t) shdr->sh_offset);
 
   Dwarf_Off offset = 0;
   while (offset < sh_size)
     {
-      printf (_("\nAbbreviation section at offset %" PRIu64 ":\n"),
-	      offset);
+      fprintf (out, _("\nAbbreviation section at offset %" PRIu64 ":\n"),
+	       offset);
 
       while (1)
 	{
@@ -5768,9 +5773,9 @@ print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	    {
 	      if (unlikely (res < 0))
 		{
-		  printf (_("\
+		  fprintf (out, _("\
  *** error while reading abbreviation: %s\n"),
-			  dwarf_errmsg (-1));
+			   dwarf_errmsg (-1));
 		  return;
 		}
 
@@ -5784,11 +5789,11 @@ print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	  unsigned int tag = dwarf_getabbrevtag (&abbrev);
 	  int has_children = dwarf_abbrevhaschildren (&abbrev);
 
-	  printf (_(" [%5u] offset: %" PRId64
+	  fprintf (out, _(" [%5u] offset: %" PRId64
 			   ", children: %s, tag: %s\n"),
-		  code, (int64_t) offset,
-		  has_children ? yes_str : no_str,
-		  dwarf_tag_name (tag));
+		   code, (int64_t) offset,
+		   has_children ? yes_str : no_str,
+		   dwarf_tag_name (tag));
 
 	  size_t cnt = 0;
 	  unsigned int name;
@@ -5798,11 +5803,11 @@ print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	  while (dwarf_getabbrevattr_data (&abbrev, cnt, &name, &form,
 					   &data, &enoffset) == 0)
 	    {
-	      printf ("          attr: %s, form: %s",
-		      dwarf_attr_name (name), dwarf_form_name (form));
+	      fprintf (out, "          attr: %s, form: %s",
+		       dwarf_attr_name (name), dwarf_form_name (form));
 	      if (form == DW_FORM_implicit_const)
-		printf (" (%" PRId64 ")", data);
-	      printf (", offset: %#" PRIx64 "\n", (uint64_t) enoffset);
+		fprintf (out, " (%" PRId64 ")", data);
+	      fprintf (out, ", offset: %#" PRIx64 "\n", (uint64_t) enoffset);
 	      ++cnt;
 	    }
 
@@ -5815,16 +5820,17 @@ print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 static void
 print_debug_addr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 			  Ebl *ebl, GElf_Ehdr *ehdr,
-			  Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+			  Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg,
+			  FILE *out)
 {
   Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_addr, scn);
   if (data == NULL)
     return;
 
-  printf (_("\
+  fprintf (out, _("\
 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
-	  elf_ndxscn (scn), section_name (ebl, shdr),
-	  (uint64_t) shdr->sh_offset);
+	   elf_ndxscn (scn), section_name (ebl, shdr),
+	   (uint64_t) shdr->sh_offset);
 
   if (shdr->sh_size == 0)
     return;
@@ -5849,7 +5855,7 @@ print_debug_addr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
       Dwarf_Off off = (Dwarf_Off) (readp
 				   - (const unsigned char *) data->d_buf);
 
-      printf ("Table at offset %" PRIx64 " ", off);
+      fprintf (out, "Table at offset %" PRIx64 " ", off);
 
       struct listptr *listptr = get_listptr (&known_addrbases, idx++);
       const unsigned char *next_unitp;
@@ -5866,7 +5872,7 @@ print_debug_addr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	  /* We will have to assume it is just addresses to the end... */
 	  address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
 	  next_unitp = readendp;
-	  printf ("Unknown CU:\n");
+	  fprintf (out, "Unknown CU:\n");
 	}
       else
 	{
@@ -5874,9 +5880,9 @@ print_debug_addr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	  if (dwarf_cu_die (listptr->cu, &cudie,
 			    NULL, NULL, NULL, NULL,
 			    NULL, NULL) == NULL)
-	    printf ("Unknown CU (%s):\n", dwarf_errmsg (-1));
+	    fprintf (out, "Unknown CU (%s):\n", dwarf_errmsg (-1));
 	  else
-	    printf ("for CU [%6" PRIx64 "]:\n", dwarf_dieoffset (&cudie));
+	    fprintf (out, "for CU [%6" PRIx64 "]:\n", dwarf_dieoffset (&cudie));
 
 	  if (listptr->offset == off)
 	    {
@@ -5923,15 +5929,15 @@ print_debug_addr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	      unit_length = (uint64_t) (next_unitp - readp);
 
 	      /* Pretend we have a header.  */
-	      printf ("\n");
-	      printf (_(" Length:         %8" PRIu64 "\n"),
-		      unit_length);
-	      printf (_(" DWARF version:  %8" PRIu16 "\n"), version);
-	      printf (_(" Address size:   %8" PRIu64 "\n"),
-		      (uint64_t) address_size);
-	      printf (_(" Segment size:   %8" PRIu64 "\n"),
-		      (uint64_t) segment_size);
-	      printf ("\n");
+	      fprintf (out, "\n");
+	      fprintf (out, _(" Length:         %8" PRIu64 "\n"),
+		       unit_length);
+	      fprintf (out, _(" DWARF version:  %8" PRIu16 "\n"), version);
+	      fprintf (out, _(" Address size:   %8" PRIu64 "\n"),
+		       (uint64_t) address_size);
+	      fprintf (out, _(" Segment size:   %8" PRIu64 "\n"),
+		       (uint64_t) segment_size);
+	      fprintf (out, "\n");
 	    }
 	  else
 	    {
@@ -5947,9 +5953,9 @@ print_debug_addr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 		    }
 		  unit_length = read_8ubyte_unaligned_inc (dbg, readp);
 		}
-	      printf ("\n");
-	      printf (_(" Length:         %8" PRIu64 "\n"),
-		      unit_length);
+	      fprintf (out, "\n");
+	      fprintf (out, _(" Length:         %8" PRIu64 "\n"),
+		       unit_length);
 
 	      /* We need at least 2-bytes (version) + 1-byte
 		 (addr_size) + 1-byte (segment_size) = 4 bytes to
@@ -5963,7 +5969,7 @@ print_debug_addr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	      next_unitp = readp + unit_length;
 
 	      version = read_2ubyte_unaligned_inc (dbg, readp);
-	      printf (_(" DWARF version:  %8" PRIu16 "\n"), version);
+	      fprintf (out, _(" DWARF version:  %8" PRIu16 "\n"), version);
 
 	      if (version != 5)
 		{
@@ -5972,8 +5978,8 @@ print_debug_addr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 		}
 
 	      address_size = *readp++;
-	      printf (_(" Address size:   %8" PRIu64 "\n"),
-		      (uint64_t) address_size);
+	      fprintf (out, _(" Address size:   %8" PRIu64 "\n"),
+		       (uint64_t) address_size);
 
 	      if (address_size != 4 && address_size != 8)
 		{
@@ -5982,9 +5988,9 @@ print_debug_addr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 		}
 
 	      segment_size = *readp++;
-	      printf (_(" Segment size:   %8" PRIu64 "\n"),
-		      (uint64_t) segment_size);
-	      printf ("\n");
+	      fprintf (out, _(" Segment size:   %8" PRIu64 "\n"),
+		       (uint64_t) segment_size);
+	      fprintf (out, "\n");
 
 	      if (segment_size != 0)
 		{
@@ -6010,16 +6016,16 @@ print_debug_addr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 
       unsigned int uidx = 0;
       size_t index_offset =  readp - (const unsigned char *) data->d_buf;
-      printf (" Addresses start at offset 0x%zx:\n", index_offset);
+      fprintf (out, " Addresses start at offset 0x%zx:\n", index_offset);
       while (readp <= next_unitp - address_size)
 	{
 	  Dwarf_Addr addr = read_addr_unaligned_inc (address_size, dbg,
 						     readp);
-	  printf (" [%*u] ", digits, uidx++);
-	  print_dwarf_addr (dwflmod, address_size, addr, addr);
-	  printf ("\n");
+	  fprintf (out, " [%*u] ", digits, uidx++);
+	  print_dwarf_addr (dwflmod, address_size, addr, addr, out);
+	  fprintf (out, "\n");
 	}
-      printf ("\n");
+      fprintf (out, "\n");
 
       if (readp != next_unitp)
 	error (0, 0, "extra %zd bytes at end of unit",
@@ -6035,7 +6041,7 @@ print_debug_addr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
    takes care of it.  */
 static void
 print_decoded_aranges_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
-			       GElf_Shdr *shdr, Dwarf *dbg)
+			       GElf_Shdr *shdr, Dwarf *dbg, FILE *out)
 {
   Dwarf_Aranges *aranges;
   size_t cnt;
@@ -6056,13 +6062,13 @@ print_decoded_aranges_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
       return;
     }
 
-  printf (ngettext ("\
+  fprintf (out, ngettext ("\
 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entry:\n",
-		    "\
+		     "\
 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entries:\n",
-		    cnt),
-	  elf_ndxscn (scn), section_name (ebl, shdr),
-	  (uint64_t) shdr->sh_offset, cnt);
+		     cnt),
+	   elf_ndxscn (scn), section_name (ebl, shdr),
+	   (uint64_t) shdr->sh_offset, cnt);
 
   /* Compute floor(log16(cnt)).  */
   size_t tmp = cnt;
@@ -6078,7 +6084,7 @@ print_decoded_aranges_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
       Dwarf_Arange *runp = dwarf_onearange (aranges, n);
       if (unlikely (runp == NULL))
 	{
-	  printf ("cannot get arange %zu: %s\n", n, dwarf_errmsg (-1));
+	  fprintf (out, "cannot get arange %zu: %s\n", n, dwarf_errmsg (-1));
 	  return;
 	}
 
@@ -6087,13 +6093,13 @@ print_decoded_aranges_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
       Dwarf_Off offset;
 
       if (unlikely (dwarf_getarangeinfo (runp, &start, &length, &offset) != 0))
-	printf (_(" [%*zu] ???\n"), digits, n);
+	fprintf (out, _(" [%*zu] ???\n"), digits, n);
       else
-	printf (_(" [%*zu] start: %0#*" PRIx64
-			 ", length: %5" PRIu64 ", CU DIE offset: %6"
-			 PRId64 "\n"),
-		digits, n, ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 10 : 18,
-		(uint64_t) start, (uint64_t) length, (int64_t) offset);
+	fprintf (out, _(" [%*zu] start: %0#*" PRIx64
+			  ", length: %5" PRIu64 ", CU DIE offset: %6"
+			  PRId64 "\n"),
+		 digits, n, ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 10 : 18,
+		 (uint64_t) start, (uint64_t) length, (int64_t) offset);
     }
 }
 
@@ -6102,11 +6108,11 @@ print_decoded_aranges_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
 static void
 print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 			     Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
-			     GElf_Shdr *shdr, Dwarf *dbg)
+			     GElf_Shdr *shdr, Dwarf *dbg, FILE *out)
 {
   if (decodedaranges)
     {
-      print_decoded_aranges_section (ebl, ehdr, scn, shdr, dbg);
+      print_decoded_aranges_section (ebl, ehdr, scn, shdr, dbg, out);
       return;
     }
 
@@ -6114,10 +6120,10 @@ print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
   if (data == NULL)
     return;
 
-  printf (_("\
+  fprintf (out, _("\
 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
-	  elf_ndxscn (scn), section_name (ebl, shdr),
-	  (uint64_t) shdr->sh_offset);
+	   elf_ndxscn (scn), section_name (ebl, shdr),
+	   (uint64_t) shdr->sh_offset);
 
   const unsigned char *readp = data->d_buf;
   const unsigned char *readendp = readp + data->d_size;
@@ -6127,7 +6133,7 @@ print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
       const unsigned char *hdrstart = readp;
       size_t start_offset = hdrstart - (const unsigned char *) data->d_buf;
 
-      printf (_("\nTable at offset %zu:\n"), start_offset);
+      fprintf (out, _("\nTable at offset %zu:\n"), start_offset);
       if (readp + 4 > readendp)
 	{
 	invalid_data:
@@ -6147,8 +6153,8 @@ print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	}
 
       const unsigned char *nexthdr = readp + length;
-      printf (_("\n Length:        %6" PRIu64 "\n"),
-	      (uint64_t) length);
+      fprintf (out, _("\n Length:        %6" PRIu64 "\n"),
+	       (uint64_t) length);
 
       if (unlikely (length > (size_t) (readendp - readp)))
 	goto invalid_data;
@@ -6159,8 +6165,8 @@ print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
       if (readp + 2 > readendp)
 	goto invalid_data;
       uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, readp);
-      printf (_(" DWARF version: %6" PRIuFAST16 "\n"),
-	      version);
+      fprintf (out, _(" DWARF version: %6" PRIuFAST16 "\n"),
+	       version);
       if (version != 2)
 	{
 	  error (0, 0, _("unsupported aranges version"));
@@ -6174,14 +6180,14 @@ print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	offset = read_8ubyte_unaligned_inc (dbg, readp);
       else
 	offset = read_4ubyte_unaligned_inc (dbg, readp);
-      printf (_(" CU offset:     %6" PRIx64 "\n"),
-	      (uint64_t) offset);
+      fprintf (out, _(" CU offset:     %6" PRIx64 "\n"),
+	       (uint64_t) offset);
 
       if (readp + 1 > readendp)
 	goto invalid_data;
       unsigned int address_size = *readp++;
-      printf (_(" Address size:  %6" PRIu64 "\n"),
-	      (uint64_t) address_size);
+      fprintf (out, _(" Address size:  %6" PRIu64 "\n"),
+	       (uint64_t) address_size);
       if (address_size != 4 && address_size != 8)
 	{
 	  error (0, 0, _("unsupported address size"));
@@ -6191,8 +6197,8 @@ print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
       if (readp + 1 > readendp)
 	goto invalid_data;
       unsigned int segment_size = *readp++;
-      printf (_(" Segment size:  %6" PRIu64 "\n\n"),
-	      (uint64_t) segment_size);
+      fprintf (out, _(" Segment size:  %6" PRIu64 "\n\n"),
+	       (uint64_t) segment_size);
       if (segment_size != 0 && segment_size != 4 && segment_size != 8)
 	{
 	  error (0, 0, _("unsupported segment size"));
@@ -6229,24 +6235,24 @@ print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	  if (range_address == 0 && range_length == 0 && segment == 0)
 	    break;
 
-	  printf ("   ");
+	  fprintf (out, "   ");
 	  print_dwarf_addr (dwflmod, address_size, range_address,
-			    range_address);
-	  printf ("..");
+			    range_address, out);
+	  fprintf (out, "..");
 	  print_dwarf_addr (dwflmod, address_size,
 			    range_address + range_length - 1,
-			    range_length);
+			    range_length, out);
 	  if (segment_size != 0)
-	    printf (" (%" PRIx64 ")\n", (uint64_t) segment);
+	    fprintf (out, " (%" PRIx64 ")\n", (uint64_t) segment);
 	  else
-	    printf ("\n");
+	    fprintf (out, "\n");
 	}
 
     next_table:
       if (readp != nexthdr)
 	{
 	  size_t padding = nexthdr - readp;
-	  printf (_("   %zu padding bytes\n"), padding);
+	  fprintf (out, _("   %zu padding bytes\n"), padding);
 	  readp = nexthdr;
 	}
     }
@@ -6279,16 +6285,17 @@ print_debug_rnglists_section (Dwfl_Module *dwflmod,
 			      Ebl *ebl,
 			      GElf_Ehdr *ehdr __attribute__ ((unused)),
 			      Elf_Scn *scn, GElf_Shdr *shdr,
-			      Dwarf *dbg __attribute__((unused)))
+			      Dwarf *dbg __attribute__((unused)),
+			      FILE *out)
 {
   Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_rnglists, scn);
   if (data == NULL)
     return;
 
-  printf (_("\
+  fprintf (out, _("\
 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
-	  elf_ndxscn (scn), section_name (ebl, shdr),
-	  (uint64_t) shdr->sh_offset);
+	   elf_ndxscn (scn), section_name (ebl, shdr),
+	   (uint64_t) shdr->sh_offset);
 
   /* For the listptr to get the base address/CU.  */
   sort_listptr (&known_rnglistptr, "rnglistptr");
@@ -6308,8 +6315,8 @@ print_debug_rnglists_section (Dwfl_Module *dwflmod,
 	}
 
       ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
-      printf (_("Table at Offset 0x%" PRIx64 ":\n\n"),
-	      (uint64_t) offset);
+      fprintf (out, _("Table at Offset 0x%" PRIx64 ":\n\n"),
+	       (uint64_t) offset);
 
       uint64_t unit_length = read_4ubyte_unaligned_inc (dbg, readp);
       unsigned int offset_size = 4;
@@ -6321,7 +6328,7 @@ print_debug_rnglists_section (Dwfl_Module *dwflmod,
 	  unit_length = read_8ubyte_unaligned_inc (dbg, readp);
 	  offset_size = 8;
 	}
-      printf (_(" Length:         %8" PRIu64 "\n"), unit_length);
+      fprintf (out, _(" Length:         %8" PRIu64 "\n"), unit_length);
 
       /* We need at least 2-bytes + 1-byte + 1-byte + 4-bytes = 8
 	 bytes to complete the header.  And this unit cannot go beyond
@@ -6334,7 +6341,7 @@ print_debug_rnglists_section (Dwfl_Module *dwflmod,
       const unsigned char *nexthdr = readp + unit_length;
 
       uint16_t version = read_2ubyte_unaligned_inc (dbg, readp);
-      printf (_(" DWARF version:  %8" PRIu16 "\n"), version);
+      fprintf (out, _(" DWARF version:  %8" PRIu16 "\n"), version);
 
       if (version != 5)
 	{
@@ -6343,8 +6350,8 @@ print_debug_rnglists_section (Dwfl_Module *dwflmod,
 	}
 
       uint8_t address_size = *readp++;
-      printf (_(" Address size:   %8" PRIu64 "\n"),
-	      (uint64_t) address_size);
+      fprintf (out, _(" Address size:   %8" PRIu64 "\n"),
+	       (uint64_t) address_size);
 
       if (address_size != 4 && address_size != 8)
 	{
@@ -6353,8 +6360,8 @@ print_debug_rnglists_section (Dwfl_Module *dwflmod,
 	}
 
       uint8_t segment_size = *readp++;
-      printf (_(" Segment size:   %8" PRIu64 "\n"),
-	      (uint64_t) segment_size);
+      fprintf (out, _(" Segment size:   %8" PRIu64 "\n"),
+	       (uint64_t) segment_size);
 
       if (segment_size != 0 && segment_size != 4 && segment_size != 8)
         {
@@ -6363,8 +6370,8 @@ print_debug_rnglists_section (Dwfl_Module *dwflmod,
         }
 
       uint32_t offset_entry_count = read_4ubyte_unaligned_inc (dbg, readp);
-      printf (_(" Offset entries: %8" PRIu64 "\n"),
-	      (uint64_t) offset_entry_count);
+      fprintf (out, _(" Offset entries: %8" PRIu64 "\n"),
+	       (uint64_t) offset_entry_count);
 
       /* We need the CU that uses this unit to get the initial base address. */
       Dwarf_Addr cu_base = 0;
@@ -6379,17 +6386,17 @@ print_debug_rnglists_section (Dwfl_Module *dwflmod,
 	  if (dwarf_cu_die (cu, &cudie,
 			    NULL, NULL, NULL, NULL,
 			    NULL, NULL) == NULL)
-	    printf (_(" Unknown CU base: "));
+	    fprintf (out, _(" Unknown CU base: "));
 	  else
-	    printf (_(" CU [%6" PRIx64 "] base: "),
-		    dwarf_dieoffset (&cudie));
-	  print_dwarf_addr (dwflmod, address_size, cu_base, cu_base);
-	  printf ("\n");
+	    fprintf (out, _(" CU [%6" PRIx64 "] base: "),
+		     dwarf_dieoffset (&cudie));
+	  print_dwarf_addr (dwflmod, address_size, cu_base, cu_base, out);
+	  fprintf (out, "\n");
 	}
       else
-	printf (_(" Not associated with a CU.\n"));
+	fprintf (out, _(" Not associated with a CU.\n"));
 
-      printf ("\n");
+      fprintf (out, "\n");
 
       const unsigned char *offset_array_start = readp;
       if (offset_entry_count > 0)
@@ -6402,24 +6409,24 @@ print_debug_rnglists_section (Dwfl_Module *dwflmod,
 	      offset_entry_count = max_entries;
 	    }
 
-	  printf (_("  Offsets starting at 0x%" PRIx64 ":\n"),
-		  (uint64_t) (offset_array_start
-			      - (unsigned char *) data->d_buf));
+	  fprintf (out, _("  Offsets starting at 0x%" PRIx64 ":\n"),
+		   (uint64_t) (offset_array_start
+			       - (unsigned char *) data->d_buf));
 	  for (uint32_t idx = 0; idx < offset_entry_count; idx++)
 	    {
-	      printf ("   [%6" PRIu32 "] ", idx);
+	      fprintf (out, "   [%6" PRIu32 "] ", idx);
 	      if (offset_size == 4)
 		{
 		  uint32_t off = read_4ubyte_unaligned_inc (dbg, readp);
-		  printf ("0x%" PRIx32 "\n", off);
+		  fprintf (out, "0x%" PRIx32 "\n", off);
 		}
 	      else
 		{
 		  uint64_t off = read_8ubyte_unaligned_inc (dbg, readp);
-		  printf ("0x%" PRIx64 "\n", off);
+		  fprintf (out, "0x%" PRIx64 "\n", off);
 		}
 	    }
-	  printf ("\n");
+	  fprintf (out, "\n");
 	}
 
       Dwarf_Addr base = cu_base;
@@ -6436,18 +6443,18 @@ print_debug_rnglists_section (Dwfl_Module *dwflmod,
 	  if (start_of_list)
 	    {
 	      base = cu_base;
-	      printf ("  Offset: %" PRIx64 ", Index: %" PRIx64 "\n",
-		      (uint64_t) (readp - (unsigned char *) data->d_buf - 1),
-		      (uint64_t) (readp - offset_array_start - 1));
+	      fprintf (out, "  Offset: %" PRIx64 ", Index: %" PRIx64 "\n",
+		       (uint64_t) (readp - (unsigned char *) data->d_buf - 1),
+		       (uint64_t) (readp - offset_array_start - 1));
 	      start_of_list = false;
 	    }
 
-	  printf ("    %s", dwarf_range_list_encoding_name (kind));
+	  fprintf (out, "    %s", dwarf_range_list_encoding_name (kind));
 	  switch (kind)
 	    {
 	    case DW_RLE_end_of_list:
 	      start_of_list = true;
-	      printf ("\n\n");
+	      fprintf (out, "\n\n");
 	      break;
 
 	    case DW_RLE_base_addressx:
@@ -6458,17 +6465,18 @@ print_debug_rnglists_section (Dwfl_Module *dwflmod,
 		  goto next_table;
 		}
 	      get_uleb128 (op1, readp, nexthdr);
-	      printf (" %" PRIx64 "\n", op1);
+	      fprintf (out, " %" PRIx64 "\n", op1);
 	      if (! print_unresolved_addresses)
 		{
 		  Dwarf_Addr addr;
 		  if (get_indexed_addr (cu, op1, &addr) != 0)
-		    printf ("      ???\n");
+		    fprintf (out, "      ???\n");
 		  else
 		    {
-		      printf ("      ");
-		      print_dwarf_addr (dwflmod, address_size, addr, addr);
-		      printf ("\n");
+		      fprintf (out, "      ");
+		      print_dwarf_addr (dwflmod, address_size, addr,
+				        addr, out);
+		      fprintf (out, "\n");
 		    }
 		}
 	      break;
@@ -6480,7 +6488,7 @@ print_debug_rnglists_section (Dwfl_Module *dwflmod,
 	      if ((uint64_t) (nexthdr - readp) < 1)
 		goto invalid_range;
 	      get_uleb128 (op2, readp, nexthdr);
-	      printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
+	      fprintf (out, " %" PRIx64 ", %" PRIx64 "\n", op1, op2);
 	      if (! print_unresolved_addresses)
 		{
 		  Dwarf_Addr addr1;
@@ -6488,17 +6496,18 @@ print_debug_rnglists_section (Dwfl_Module *dwflmod,
 		  if (get_indexed_addr (cu, op1, &addr1) != 0
 		      || get_indexed_addr (cu, op2, &addr2) != 0)
 		    {
-		      printf ("      ???..\n");
-		      printf ("      ???\n");
+		      fprintf (out, "      ???..\n");
+		      fprintf (out, "      ???\n");
 		    }
 		  else
 		    {
-		      printf ("      ");
-		      print_dwarf_addr (dwflmod, address_size, addr1, addr1);
-		      printf ("..\n      ");
+		      fprintf (out, "      ");
 		      print_dwarf_addr (dwflmod, address_size,
-					addr2 - 1, addr2);
-		      printf ("\n");
+					addr1, addr1, out);
+		      fprintf (out, "..\n      ");
+		      print_dwarf_addr (dwflmod, address_size,
+					addr2 - 1, addr2, out);
+		      fprintf (out, "\n");
 		    }
 		}
 	      break;
@@ -6510,25 +6519,25 @@ print_debug_rnglists_section (Dwfl_Module *dwflmod,
 	      if ((uint64_t) (nexthdr - readp) < 1)
 		goto invalid_range;
 	      get_uleb128 (op2, readp, nexthdr);
-	      printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
+	      fprintf (out, " %" PRIx64 ", %" PRIx64 "\n", op1, op2);
 	      if (! print_unresolved_addresses)
 		{
 		  Dwarf_Addr addr1;
 		  Dwarf_Addr addr2;
 		  if (get_indexed_addr (cu, op1, &addr1) != 0)
 		    {
-		      printf ("      ???..\n");
-		      printf ("      ???\n");
+		      fprintf (out, "      ???..\n");
+		      fprintf (out, "      ???\n");
 		    }
 		  else
 		    {
 		      addr2 = addr1 + op2;
-		      printf ("      ");
-		      print_dwarf_addr (dwflmod, address_size, addr1, addr1);
-		      printf ("..\n      ");
+		      fprintf (out, "      ");
+		      print_dwarf_addr (dwflmod, address_size, addr1, addr1, out);
+		      fprintf (out, "..\n      ");
 		      print_dwarf_addr (dwflmod, address_size,
-					addr2 - 1, addr2);
-		      printf ("\n");
+					addr2 - 1, addr2, out);
+		      fprintf (out, "\n");
 		    }
 		}
 	      break;
@@ -6540,16 +6549,16 @@ print_debug_rnglists_section (Dwfl_Module *dwflmod,
 	      if ((uint64_t) (nexthdr - readp) < 1)
 		goto invalid_range;
 	      get_uleb128 (op2, readp, nexthdr);
-	      printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
+	      fprintf (out, " %" PRIx64 ", %" PRIx64 "\n", op1, op2);
 	      if (! print_unresolved_addresses)
 		{
 		  op1 += base;
 		  op2 += base;
-		  printf ("      ");
-		  print_dwarf_addr (dwflmod, address_size, op1, op1);
-		  printf ("..\n      ");
-		  print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
-		  printf ("\n");
+		  fprintf (out, "      ");
+		  print_dwarf_addr (dwflmod, address_size, op1, op1, out);
+		  fprintf (out, "..\n      ");
+		  print_dwarf_addr (dwflmod, address_size, op2 - 1, op2, out);
+		  fprintf (out, "\n");
 		}
 	      break;
 
@@ -6567,12 +6576,12 @@ print_debug_rnglists_section (Dwfl_Module *dwflmod,
 		  op1 = read_8ubyte_unaligned_inc (dbg, readp);
 		}
 	      base = op1;
-	      printf (" 0x%" PRIx64 "\n", base);
+	      fprintf (out, " 0x%" PRIx64 "\n", base);
 	      if (! print_unresolved_addresses)
 		{
-		  printf ("      ");
-		  print_dwarf_addr (dwflmod, address_size, base, base);
-		  printf ("\n");
+		  fprintf (out, "      ");
+		  print_dwarf_addr (dwflmod, address_size, base, base, out);
+		  fprintf (out, "\n");
 		}
 	      break;
 
@@ -6591,14 +6600,14 @@ print_debug_rnglists_section (Dwfl_Module *dwflmod,
 		  op1 = read_8ubyte_unaligned_inc (dbg, readp);
 		  op2 = read_8ubyte_unaligned_inc (dbg, readp);
 		}
-	      printf (" 0x%" PRIx64 "..0x%" PRIx64 "\n", op1, op2);
+	      fprintf (out, " 0x%" PRIx64 "..0x%" PRIx64 "\n", op1, op2);
 	      if (! print_unresolved_addresses)
 		{
-		  printf ("      ");
-		  print_dwarf_addr (dwflmod, address_size, op1, op1);
-		  printf ("..\n      ");
-		  print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
-		  printf ("\n");
+		  fprintf (out, "      ");
+		  print_dwarf_addr (dwflmod, address_size, op1, op1, out);
+		  fprintf (out, "..\n      ");
+		  print_dwarf_addr (dwflmod, address_size, op2 - 1, op2, out);
+		  fprintf (out, "\n");
 		}
 	      break;
 
@@ -6618,15 +6627,15 @@ print_debug_rnglists_section (Dwfl_Module *dwflmod,
 	      if ((uint64_t) (nexthdr - readp) < 1)
 		goto invalid_range;
 	      get_uleb128 (op2, readp, nexthdr);
-	      printf (" 0x%" PRIx64 ", %" PRIx64 "\n", op1, op2);
+	      fprintf (out, " 0x%" PRIx64 ", %" PRIx64 "\n", op1, op2);
 	      if (! print_unresolved_addresses)
 		{
 		  op2 = op1 + op2;
-		  printf ("      ");
-		  print_dwarf_addr (dwflmod, address_size, op1, op1);
-		  printf ("..\n      ");
-		  print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
-		  printf ("\n");
+		  fprintf (out, "      ");
+		  print_dwarf_addr (dwflmod, address_size, op1, op1, out);
+		  fprintf (out, "..\n      ");
+		  print_dwarf_addr (dwflmod, address_size, op2 - 1, op2, out);
+		  fprintf (out, "\n");
 		}
 	      break;
 
@@ -6639,7 +6648,7 @@ print_debug_rnglists_section (Dwfl_Module *dwflmod,
       if (readp != nexthdr)
 	{
           size_t padding = nexthdr - readp;
-          printf (_("   %zu padding bytes\n\n"), padding);
+          fprintf (out, _("   %zu padding bytes\n\n"), padding);
 	  readp = nexthdr;
 	}
     }
@@ -6650,16 +6659,16 @@ static void
 print_debug_ranges_section (Dwfl_Module *dwflmod,
 			    Ebl *ebl, GElf_Ehdr *ehdr,
 			    Elf_Scn *scn, GElf_Shdr *shdr,
-			    Dwarf *dbg)
+			    Dwarf *dbg, FILE *out)
 {
   Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_ranges, scn);
   if (data == NULL)
     return;
 
-  printf (_("\
+  fprintf (out, _("\
 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
-	  elf_ndxscn (scn), section_name (ebl, shdr),
-	  (uint64_t) shdr->sh_offset);
+	   elf_ndxscn (scn), section_name (ebl, shdr),
+	   (uint64_t) shdr->sh_offset);
 
   sort_listptr (&known_rangelistptr, "rangelistptr");
   size_t listptr_idx = 0;
@@ -6687,18 +6696,18 @@ print_debug_ranges_section (Dwfl_Module *dwflmod,
 	  if (dwarf_cu_die (cu, &cudie,
 			    NULL, NULL, NULL, NULL,
 			    NULL, NULL) == NULL)
-	    printf (_("\n Unknown CU base: "));
+	    fprintf (out, _("\n Unknown CU base: "));
 	  else
-	    printf (_("\n CU [%6" PRIx64 "] base: "),
-		    dwarf_dieoffset (&cudie));
-	  print_dwarf_addr (dwflmod, address_size, base, base);
-	  printf ("\n");
+	    fprintf (out, _("\n CU [%6" PRIx64 "] base: "),
+		     dwarf_dieoffset (&cudie));
+	  print_dwarf_addr (dwflmod, address_size, base, base, out);
+	  fprintf (out, "\n");
 	}
       last_cu = cu;
 
       if (unlikely (data->d_size - offset < (size_t) address_size * 2))
 	{
-	  printf (_(" [%6tx]  <INVALID DATA>\n"), offset);
+	  fprintf (out, _(" [%6tx]  <INVALID DATA>\n"), offset);
 	  break;
 	}
 
@@ -6720,40 +6729,40 @@ print_debug_ranges_section (Dwfl_Module *dwflmod,
       if (begin == (Dwarf_Addr) -1l) /* Base address entry.  */
 	{
 	  if (first)
-	    printf (" [%6tx] ", offset);
+	    fprintf (out, " [%6tx] ", offset);
 	  else
-	    printf ("          ");
-	  puts (_("base address"));
-	  printf ("          ");
-	  print_dwarf_addr (dwflmod, address_size, end, end);
-	  printf ("\n");
+	    fprintf (out, "          ");
+	  fputs (_("base address\n"), out);
+	  fprintf (out, "          ");
+	  print_dwarf_addr (dwflmod, address_size, end, end, out);
+	  fprintf (out, "\n");
 	  base = end;
 	  first = false;
 	}
       else if (begin == 0 && end == 0) /* End of list entry.  */
 	{
 	  if (first)
-	    printf (_(" [%6tx] empty list\n"), offset);
+	    fprintf (out, _(" [%6tx] empty list\n"), offset);
 	  first = true;
 	}
       else
 	{
 	  /* We have an address range entry.  */
 	  if (first)		/* First address range entry in a list.  */
-	    printf (" [%6tx] ", offset);
+	    fprintf (out, " [%6tx] ", offset);
 	  else
-	    printf ("          ");
+	    fprintf (out, "          ");
 
-	  printf ("range %" PRIx64 ", %" PRIx64 "\n", begin, end);
+	  fprintf (out, "range %" PRIx64 ", %" PRIx64 "\n", begin, end);
 	  if (! print_unresolved_addresses)
 	    {
-	      printf ("          ");
+	      fprintf (out, "          ");
 	      print_dwarf_addr (dwflmod, address_size, base + begin,
-			        base + begin);
-	      printf ("..\n          ");
+			        base + begin, out);
+	      fprintf (out, "..\n          ");
 	      print_dwarf_addr (dwflmod, address_size,
-				base + end - 1, base + end);
-	      printf ("\n");
+				base + end - 1, base + end, out);
+	      fprintf (out, "\n");
 	    }
 
 	  first = false;
@@ -6867,11 +6876,12 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 		   int data_align,
 		   unsigned int version, unsigned int ptr_size,
 		   unsigned int encoding,
-		   Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, Dwarf *dbg)
+		   Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, Dwarf *dbg,
+		   FILE *out)
 {
   char regnamebuf[REGNAMESZ];
 
-  puts ("\n   Program:");
+  fputs ("\n   Program:\n", out);
   Dwarf_Word pc = vma_base;
   while (readp < endp)
     {
@@ -6887,35 +6897,35 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 	    int64_t sop2;
 
 	  case DW_CFA_nop:
-	    puts ("     nop");
+	    fputs ("     nop\n", out);
 	    break;
 	  case DW_CFA_set_loc:
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
 	    readp = read_encoded (encoding, readp, endp, &op1, dbg);
-	    printf ("     set_loc %#" PRIx64 " to %#" PRIx64 "\n",
-		    op1, pc = vma_base + op1);
+	    fprintf (out, "     set_loc %#" PRIx64 " to %#" PRIx64 "\n",
+		     op1, pc = vma_base + op1);
 	    break;
 	  case DW_CFA_advance_loc1:
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
-	    printf ("     advance_loc1 %u to %#" PRIx64 "\n",
-		    *readp, pc += *readp * code_align);
+	    fprintf (out, "     advance_loc1 %u to %#" PRIx64 "\n",
+		     *readp, pc += *readp * code_align);
 	    ++readp;
 	    break;
 	  case DW_CFA_advance_loc2:
 	    if ((uint64_t) (endp - readp) < 2)
 	      goto invalid;
 	    op1 = read_2ubyte_unaligned_inc (dbg, readp);
-	    printf ("     advance_loc2 %" PRIu64 " to %#" PRIx64 "\n",
-		    op1, pc += op1 * code_align);
+	    fprintf (out, "     advance_loc2 %" PRIu64 " to %#" PRIx64 "\n",
+		     op1, pc += op1 * code_align);
 	    break;
 	  case DW_CFA_advance_loc4:
 	    if ((uint64_t) (endp - readp) < 4)
 	      goto invalid;
 	    op1 = read_4ubyte_unaligned_inc (dbg, readp);
-	    printf ("     advance_loc4 %" PRIu64 " to %#" PRIx64 "\n",
-		    op1, pc += op1 * code_align);
+	    fprintf (out, "     advance_loc4 %" PRIu64 " to %#" PRIx64 "\n",
+		     op1, pc += op1 * code_align);
 	    break;
 	  case DW_CFA_offset_extended:
 	    if ((uint64_t) (endp - readp) < 1)
@@ -6924,30 +6934,30 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
 	    get_uleb128 (op2, readp, endp);
-	    printf ("     offset_extended r%" PRIu64 " (%s) at cfa%+" PRId64
-		    "\n",
-		    op1, regname (ebl, op1, regnamebuf), op2 * data_align);
+	    fprintf (out, "     offset_extended r%" PRIu64 " (%s) at cfa%+" PRId64
+		     "\n",
+		     op1, regname (ebl, op1, regnamebuf), op2 * data_align);
 	    break;
 	  case DW_CFA_restore_extended:
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
 	    get_uleb128 (op1, readp, endp);
-	    printf ("     restore_extended r%" PRIu64 " (%s)\n",
-		    op1, regname (ebl, op1, regnamebuf));
+	    fprintf (out, "     restore_extended r%" PRIu64 " (%s)\n",
+		     op1, regname (ebl, op1, regnamebuf));
 	    break;
 	  case DW_CFA_undefined:
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
 	    get_uleb128 (op1, readp, endp);
-	    printf ("     undefined r%" PRIu64 " (%s)\n", op1,
-		    regname (ebl, op1, regnamebuf));
+	    fprintf (out, "     undefined r%" PRIu64 " (%s)\n", op1,
+		     regname (ebl, op1, regnamebuf));
 	    break;
 	  case DW_CFA_same_value:
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
 	    get_uleb128 (op1, readp, endp);
-	    printf ("     same_value r%" PRIu64 " (%s)\n", op1,
-		    regname (ebl, op1, regnamebuf));
+	    fprintf (out, "     same_value r%" PRIu64 " (%s)\n", op1,
+		     regname (ebl, op1, regnamebuf));
 	    break;
 	  case DW_CFA_register:
 	    if ((uint64_t) (endp - readp) < 1)
@@ -6956,15 +6966,16 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
 	    get_uleb128 (op2, readp, endp);
-	    printf ("     register r%" PRIu64 " (%s) in r%" PRIu64 " (%s)\n",
-		    op1, regname (ebl, op1, regnamebuf), op2,
-		    regname (ebl, op2, regnamebuf));
+	    fprintf (out,
+		     "     register r%" PRIu64 " (%s) in r%" PRIu64 " (%s)\n",
+		     op1, regname (ebl, op1, regnamebuf), op2,
+		     regname (ebl, op2, regnamebuf));
 	    break;
 	  case DW_CFA_remember_state:
-	    puts ("     remember_state");
+	    fputs ("     remember_state\n", out);
 	    break;
 	  case DW_CFA_restore_state:
-	    puts ("     restore_state");
+	    fputs ("     restore_state\n", out);
 	    break;
 	  case DW_CFA_def_cfa:
 	    if ((uint64_t) (endp - readp) < 1)
@@ -6973,35 +6984,36 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
 	    get_uleb128 (op2, readp, endp);
-	    printf ("     def_cfa r%" PRIu64 " (%s) at offset %" PRIu64 "\n",
-		    op1, regname (ebl, op1, regnamebuf), op2);
+	    fprintf (out,
+		     "     def_cfa r%" PRIu64 " (%s) at offset %" PRIu64 "\n",
+		     op1, regname (ebl, op1, regnamebuf), op2);
 	    break;
 	  case DW_CFA_def_cfa_register:
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
 	    get_uleb128 (op1, readp, endp);
-	    printf ("     def_cfa_register r%" PRIu64 " (%s)\n",
-		    op1, regname (ebl, op1, regnamebuf));
+	    fprintf (out, "     def_cfa_register r%" PRIu64 " (%s)\n",
+		     op1, regname (ebl, op1, regnamebuf));
 	    break;
 	  case DW_CFA_def_cfa_offset:
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
 	    get_uleb128 (op1, readp, endp);
-	    printf ("     def_cfa_offset %" PRIu64 "\n", op1);
+	    fprintf (out, "     def_cfa_offset %" PRIu64 "\n", op1);
 	    break;
 	  case DW_CFA_def_cfa_expression:
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
 	    get_uleb128 (op1, readp, endp);	/* Length of DW_FORM_block.  */
-	    printf ("     def_cfa_expression %" PRIu64 "\n", op1);
+	    fprintf (out, "     def_cfa_expression %" PRIu64 "\n", op1);
 	    if ((uint64_t) (endp - readp) < op1)
 	      {
 	    invalid:
-	        fputs (_("         <INVALID DATA>\n"), stdout);
+	        fputs (_("         <INVALID DATA>\n"), out);
 		return;
 	      }
 	    print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, NULL,
-		       op1, readp);
+		       op1, readp, out);
 	    readp += op1;
 	    break;
 	  case DW_CFA_expression:
@@ -7011,12 +7023,12 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
 	    get_uleb128 (op2, readp, endp);	/* Length of DW_FORM_block.  */
-	    printf ("     expression r%" PRIu64 " (%s) \n",
-		    op1, regname (ebl, op1, regnamebuf));
+	    fprintf (out, "     expression r%" PRIu64 " (%s) \n",
+		     op1, regname (ebl, op1, regnamebuf));
 	    if ((uint64_t) (endp - readp) < op2)
 	      goto invalid;
 	    print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, NULL,
-		       op2, readp);
+		       op2, readp, out);
 	    readp += op2;
 	    break;
 	  case DW_CFA_offset_extended_sf:
@@ -7026,9 +7038,9 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
 	    get_sleb128 (sop2, readp, endp);
-	    printf ("     offset_extended_sf r%" PRIu64 " (%s) at cfa%+"
-		    PRId64 "\n",
-		    op1, regname (ebl, op1, regnamebuf), sop2 * data_align);
+	    fprintf (out, "     offset_extended_sf r%" PRIu64 " (%s) at cfa%+"
+		     PRId64 "\n",
+		     op1, regname (ebl, op1, regnamebuf), sop2 * data_align);
 	    break;
 	  case DW_CFA_def_cfa_sf:
 	    if ((uint64_t) (endp - readp) < 1)
@@ -7037,14 +7049,16 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
 	    get_sleb128 (sop2, readp, endp);
-	    printf ("     def_cfa_sf r%" PRIu64 " (%s) at offset %" PRId64 "\n",
-		    op1, regname (ebl, op1, regnamebuf), sop2 * data_align);
+	    fprintf (out,
+		     "     def_cfa_sf r%" PRIu64 " (%s) at offset %" PRId64 "\n",
+		     op1, regname (ebl, op1, regnamebuf), sop2 * data_align);
 	    break;
 	  case DW_CFA_def_cfa_offset_sf:
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
 	    get_sleb128 (sop1, readp, endp);
-	    printf ("     def_cfa_offset_sf %" PRId64 "\n", sop1 * data_align);
+	    fprintf (out,
+		     "     def_cfa_offset_sf %" PRId64 "\n", sop1 * data_align);
 	    break;
 	  case DW_CFA_val_offset:
 	    if ((uint64_t) (endp - readp) < 1)
@@ -7053,8 +7067,8 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
 	    get_uleb128 (op2, readp, endp);
-	    printf ("     val_offset %" PRIu64 " at offset %" PRIu64 "\n",
-		    op1, op2 * data_align);
+	    fprintf (out, "     val_offset %" PRIu64 " at offset %" PRIu64 "\n",
+		     op1, op2 * data_align);
 	    break;
 	  case DW_CFA_val_offset_sf:
 	    if ((uint64_t) (endp - readp) < 1)
@@ -7063,8 +7077,9 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
 	    get_sleb128 (sop2, readp, endp);
-	    printf ("     val_offset_sf %" PRIu64 " at offset %" PRId64 "\n",
-		    op1, sop2 * data_align);
+	    fprintf (out,
+		     "     val_offset_sf %" PRIu64 " at offset %" PRId64 "\n",
+		     op1, sop2 * data_align);
 	    break;
 	  case DW_CFA_val_expression:
 	    if ((uint64_t) (endp - readp) < 1)
@@ -7073,53 +7088,54 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
 	    get_uleb128 (op2, readp, endp);	/* Length of DW_FORM_block.  */
-	    printf ("     val_expression r%" PRIu64 " (%s)\n",
-		    op1, regname (ebl, op1, regnamebuf));
+	    fprintf (out, "     val_expression r%" PRIu64 " (%s)\n",
+		     op1, regname (ebl, op1, regnamebuf));
 	    if ((uint64_t) (endp - readp) < op2)
 	      goto invalid;
 	    print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0,
-		       NULL, op2, readp);
+		       NULL, op2, readp, out);
 	    readp += op2;
 	    break;
 	  case DW_CFA_MIPS_advance_loc8:
 	    if ((uint64_t) (endp - readp) < 8)
 	      goto invalid;
 	    op1 = read_8ubyte_unaligned_inc (dbg, readp);
-	    printf ("     MIPS_advance_loc8 %" PRIu64 " to %#" PRIx64 "\n",
-		    op1, pc += op1 * code_align);
+	    fprintf (out,
+		     "     MIPS_advance_loc8 %" PRIu64 " to %#" PRIx64 "\n",
+		     op1, pc += op1 * code_align);
 	    break;
 	  case DW_CFA_GNU_window_save:  /* DW_CFA_AARCH64_negate_ra_state  */
 	    if (ehdr->e_machine == EM_AARCH64)
-	      puts ("     AARCH64_negate_ra_state");
+	      fputs ("     AARCH64_negate_ra_state\n", out);
 	    else
-	      puts ("     GNU_window_save");
+	      fputs ("     GNU_window_save\n", out);
 	    break;
 	  case DW_CFA_GNU_args_size:
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
 	    get_uleb128 (op1, readp, endp);
-	    printf ("     args_size %" PRIu64 "\n", op1);
+	    fprintf (out, "     args_size %" PRIu64 "\n", op1);
 	    break;
 	  default:
-	    printf ("     ??? (%u)\n", opcode);
+	    fprintf (out, "     ??? (%u)\n", opcode);
 	    break;
 	  }
       else if (opcode < DW_CFA_offset)
-	printf ("     advance_loc %u to %#" PRIx64 "\n",
-		opcode & 0x3f, pc += (opcode & 0x3f) * code_align);
+	fprintf (out, "     advance_loc %u to %#" PRIx64 "\n",
+		 opcode & 0x3f, pc += (opcode & 0x3f) * code_align);
       else if (opcode < DW_CFA_restore)
 	{
 	  uint64_t offset;
 	  if ((uint64_t) (endp - readp) < 1)
 	    goto invalid;
 	  get_uleb128 (offset, readp, endp);
-	  printf ("     offset r%u (%s) at cfa%+" PRId64 "\n",
-		  opcode & 0x3f, regname (ebl, opcode & 0x3f, regnamebuf),
-		  offset * data_align);
+	  fprintf (out, "     offset r%u (%s) at cfa%+" PRId64 "\n",
+		   opcode & 0x3f, regname (ebl, opcode & 0x3f, regnamebuf),
+		   offset * data_align);
 	}
       else
-	printf ("     restore r%u (%s)\n",
-		opcode & 0x3f, regname (ebl, opcode & 0x3f, regnamebuf));
+	fprintf (out, "     restore r%u (%s)\n",
+		 opcode & 0x3f, regname (ebl, opcode & 0x3f, regnamebuf));
     }
 }
 
@@ -7144,36 +7160,36 @@ encoded_ptr_size (int encoding, unsigned int ptr_size)
 
 
 static unsigned int
-print_encoding (unsigned int val)
+print_encoding (unsigned int val, FILE *out)
 {
   switch (val & 0xf)
     {
     case DW_EH_PE_absptr:
-      fputs ("absptr", stdout);
+      fputs ("absptr", out);
       break;
     case DW_EH_PE_uleb128:
-      fputs ("uleb128", stdout);
+      fputs ("uleb128", out);
       break;
     case DW_EH_PE_udata2:
-      fputs ("udata2", stdout);
+      fputs ("udata2", out);
       break;
     case DW_EH_PE_udata4:
-      fputs ("udata4", stdout);
+      fputs ("udata4", out);
       break;
     case DW_EH_PE_udata8:
-      fputs ("udata8", stdout);
+      fputs ("udata8", out);
       break;
     case DW_EH_PE_sleb128:
-      fputs ("sleb128", stdout);
+      fputs ("sleb128", out);
       break;
     case DW_EH_PE_sdata2:
-      fputs ("sdata2", stdout);
+      fputs ("sdata2", out);
       break;
     case DW_EH_PE_sdata4:
-      fputs ("sdata4", stdout);
+      fputs ("sdata4", out);
       break;
     case DW_EH_PE_sdata8:
-      fputs ("sdata8", stdout);
+      fputs ("sdata8", out);
       break;
     default:
       /* We did not use any of the bits after all.  */
@@ -7185,24 +7201,24 @@ print_encoding (unsigned int val)
 
 
 static unsigned int
-print_relinfo (unsigned int val)
+print_relinfo (unsigned int val, FILE *out)
 {
   switch (val & 0x70)
     {
     case DW_EH_PE_pcrel:
-      fputs ("pcrel", stdout);
+      fputs ("pcrel", out);
       break;
     case DW_EH_PE_textrel:
-      fputs ("textrel", stdout);
+      fputs ("textrel", out);
       break;
     case DW_EH_PE_datarel:
-      fputs ("datarel", stdout);
+      fputs ("datarel", out);
       break;
     case DW_EH_PE_funcrel:
-      fputs ("funcrel", stdout);
+      fputs ("funcrel", out);
       break;
     case DW_EH_PE_aligned:
-      fputs ("aligned", stdout);
+      fputs ("aligned", out);
       break;
     default:
       return val;
@@ -7213,37 +7229,39 @@ print_relinfo (unsigned int val)
 
 
 static void
-print_encoding_base (const char *pfx, unsigned int fde_encoding)
+print_encoding_base (const char *pfx, unsigned int fde_encoding,
+		     FILE *out)
 {
-  printf ("(%s", pfx);
+  fprintf (out, "(%s", pfx);
 
   if (fde_encoding == DW_EH_PE_omit)
-    puts ("omit)");
+    fputs ("omit)\n", out);
   else
     {
       unsigned int w = fde_encoding;
 
-      w = print_encoding (w);
+      w = print_encoding (w, out);
 
       if (w & 0x70)
 	{
 	  if (w != fde_encoding)
-	    fputc (' ', stdout);
+	    fputc (' ', out);
 
-	  w = print_relinfo (w);
+	  w = print_relinfo (w, out);
 	}
 
       if (w != 0)
-	printf ("%s%x", w != fde_encoding ? " " : "", w);
+	fprintf (out, "%s%x", w != fde_encoding ? " " : "", w);
 
-      puts (")");
+      fputs (")\n", out);
     }
 }
 
 
 static void
 print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
-			   Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+			   Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg,
+			   FILE *out)
 {
   size_t shstrndx;
   /* We know this call will succeed since it did in the caller.  */
@@ -7278,13 +7296,13 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
     }
 
   if (is_eh_frame)
-    printf (_("\
+    fprintf (out, _("\
 \nCall frame information section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
-	    elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
+	     elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
   else
-    printf (_("\
+    fprintf (out, _("\
 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
-	    elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
+	     elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
 
   struct cieinfo
   {
@@ -7328,7 +7346,7 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 
       if (unlikely (unit_length == 0))
 	{
-	  printf (_("\n [%6tx] Zero terminator\n"), offset);
+	  fprintf (out, _("\n [%6tx] Zero terminator\n"), offset);
 	  continue;
 	}
 
@@ -7406,21 +7424,21 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 	  else
 	    get_uleb128 (return_address_register, readp, cieend);
 
-	  printf ("\n [%6tx] CIE length=%" PRIu64 "\n"
-		  "   CIE_id:                   %" PRIu64 "\n"
-		  "   version:                  %u\n"
-		  "   augmentation:             \"%s\"\n",
-		  offset, (uint64_t) unit_length, (uint64_t) cie_id,
-		  version, augmentation);
+	  fprintf (out, "\n [%6tx] CIE length=%" PRIu64 "\n"
+		   "   CIE_id:                   %" PRIu64 "\n"
+		   "   version:                  %u\n"
+		   "   augmentation:             \"%s\"\n",
+		   offset, (uint64_t) unit_length, (uint64_t) cie_id,
+		   version, augmentation);
 	  if (version >= 4)
-	    printf ("   address_size:             %u\n"
-		    "   segment_size:             %u\n",
-		    ptr_size, segment_size);
-	  printf ("   code_alignment_factor:    %u\n"
-		  "   data_alignment_factor:    %d\n"
-		  "   return_address_register:  %u\n",
-		  code_alignment_factor,
-		  data_alignment_factor, return_address_register);
+	    fprintf (out, "   address_size:             %u\n"
+		     "   segment_size:             %u\n",
+		     ptr_size, segment_size);
+	  fprintf (out, "   code_alignment_factor:    %u\n"
+		   "   data_alignment_factor:    %d\n"
+		   "   return_address_register:  %u\n",
+		   code_alignment_factor,
+		   data_alignment_factor, return_address_register);
 
 	  if (augmentation[0] == 'z')
 	    {
@@ -7441,20 +7459,20 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 	      const char *cp = augmentation + 1;
 	      while (*cp != '\0' && cp < augmentation + augmentationlen + 1)
 		{
-		  printf ("   %-26s%#x ", hdr, *readp);
+		  fprintf (out, "   %-26s%#x ", hdr, *readp);
 		  hdr = "";
 
 		  if (*cp == 'R')
 		    {
 		      fde_encoding = *readp++;
 		      print_encoding_base (_("FDE address encoding: "),
-					   fde_encoding);
+					   fde_encoding, out);
 		    }
 		  else if (*cp == 'L')
 		    {
 		      lsda_encoding = *readp++;
 		      print_encoding_base (_("LSDA pointer encoding: "),
-					   lsda_encoding);
+					   lsda_encoding, out);
 		    }
 		  else if (*cp == 'P')
 		    {
@@ -7468,25 +7486,25 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 					    &val, dbg);
 
 		      while (++startp < readp)
-			printf ("%#x ", *startp);
+			fprintf (out, "%#x ", *startp);
 
-		      putchar ('(');
-		      print_encoding (encoding);
-		      putchar (' ');
+		      fputc ('(', out);
+		      print_encoding (encoding, out);
+		      fputc (' ', out);
 		      switch (encoding & 0xf)
 			{
 			case DW_EH_PE_sleb128:
 			case DW_EH_PE_sdata2:
 			case DW_EH_PE_sdata4:
-			  printf ("%" PRId64 ")\n", val);
+			  fprintf (out, "%" PRId64 ")\n", val);
 			  break;
 			default:
-			  printf ("%#" PRIx64 ")\n", val);
+			  fprintf (out, "%#" PRIx64 ")\n", val);
 			  break;
 			}
 		    }
 		  else
-		    printf ("(%x)\n", *readp++);
+		    fprintf (out, "(%x)\n", *readp++);
 
 		  ++cp;
 		}
@@ -7518,7 +7536,7 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 	      cie = cie->next;
 	  if (unlikely (cie == NULL))
 	    {
-	      puts ("invalid CIE reference in FDE");
+	      fputs ("invalid CIE reference in FDE\n", out);
 	      return;
 	    }
 
@@ -7548,13 +7566,13 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 			 + (base - (const unsigned char *) data->d_buf)
 			 - bias);
 
-	  printf ("\n [%6tx] FDE length=%" PRIu64 " cie=[%6tx]\n"
-		  "   CIE_pointer:              %" PRIu64 "\n"
-		  "   initial_location:         ",
-		  offset, (uint64_t) unit_length,
-		  cie->cie_offset, (uint64_t) cie_id);
+	  fprintf (out, "\n [%6tx] FDE length=%" PRIu64 " cie=[%6tx]\n"
+		   "   CIE_pointer:              %" PRIu64 "\n"
+		   "   initial_location:         ",
+		   offset, (uint64_t) unit_length,
+		   cie->cie_offset, (uint64_t) cie_id);
 	  print_dwarf_addr (dwflmod, cie->address_size,
-			    pc_start, initial_location);
+			    pc_start, initial_location, out);
 	  if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
 	    {
 	      vma_base = (((uint64_t) shdr->sh_offset
@@ -7563,19 +7581,19 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 			  & (ptr_size == 4
 			     ? UINT64_C (0xffffffff)
 			     : UINT64_C (0xffffffffffffffff)));
-	      printf (_(" (offset: %#" PRIx64 ")"),
-		      (uint64_t) vma_base);
+	      fprintf (out, _(" (offset: %#" PRIx64 ")"),
+		       (uint64_t) vma_base);
 	    }
 
-	  printf ("\n   address_range:            %#" PRIx64,
-		  (uint64_t) address_range);
+	  fprintf (out, "\n   address_range:            %#" PRIx64,
+		   (uint64_t) address_range);
 	  if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
-	    printf (_(" (end offset: %#" PRIx64 ")"),
-		    ((uint64_t) vma_base + (uint64_t) address_range)
-		    & (ptr_size == 4
-		       ? UINT64_C (0xffffffff)
-		       : UINT64_C (0xffffffffffffffff)));
-	  putchar ('\n');
+	    fprintf (out, _(" (end offset: %#" PRIx64 ")"),
+		     ((uint64_t) vma_base + (uint64_t) address_range)
+		     & (ptr_size == 4
+		        ? UINT64_C (0xffffffff)
+		        : UINT64_C (0xffffffffffffffff)));
+	  fputc ('\n', out);
 
 	  if (cie->augmentation[0] == 'z')
 	    {
@@ -7607,9 +7625,9 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 					    &readp[augmentationlen],
 					    &lsda_pointer, dbg);
 			  u = p - readp;
-			  printf (_("\
+			  fprintf (out, _("\
    %-26sLSDA pointer: %#" PRIx64 "\n"),
-				  hdr, lsda_pointer);
+				   hdr, lsda_pointer);
 			  hdr = "";
 			}
 		      ++cp;
@@ -7617,7 +7635,7 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 
 		  while (u < augmentationlen)
 		    {
-		      printf ("   %-26s%#x\n", hdr, readp[u++]);
+		      fprintf (out, "   %-26s%#x\n", hdr, readp[u++]);
 		      hdr = "";
 		    }
 		}
@@ -7628,11 +7646,12 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 
       /* Handle the initialization instructions.  */
       if (ptr_size != 4 && ptr_size !=8)
-	printf ("invalid CIE pointer size (%u), must be 4 or 8.\n", ptr_size);
+	fprintf (out, "invalid CIE pointer size (%u), must be 4 or 8.\n",
+		 ptr_size);
       else
 	print_cfa_program (readp, cieend, vma_base, code_alignment_factor,
 			   data_alignment_factor, version, ptr_size,
-			   fde_encoding, dwflmod, ebl, ehdr, dbg);
+			   fde_encoding, dwflmod, ebl, ehdr, dbg, out);
       readp = cieend;
     }
 }
@@ -7677,6 +7696,7 @@ struct attrcb_args
   unsigned int addrsize;
   unsigned int offset_size;
   struct Dwarf_CU *cu;
+  FILE *out;
 };
 
 
@@ -7687,6 +7707,7 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
   const int level = cbargs->level;
   Dwarf_Die *die = &cbargs->dies[level];
   bool is_split = cbargs->is_split;
+  FILE *out = cbargs->out;
 
   unsigned int attr = dwarf_whatattr (attrp);
   if (unlikely (attr == 0))
@@ -7739,16 +7760,16 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
 	      Dwarf_Word word;
 	      if (dwarf_formudata (attrp, &word) != 0)
 		goto attrval_out;
-	      printf ("           %*s%-20s (%s) [%" PRIx64 "] ",
-		      (int) (level * 2), "", dwarf_attr_name (attr),
-		      dwarf_form_name (form), word);
+	      fprintf (out, "           %*s%-20s (%s) [%" PRIx64 "] ",
+		       (int) (level * 2), "", dwarf_attr_name (attr),
+		       dwarf_form_name (form), word);
 	    }
 	  else
-	    printf ("           %*s%-20s (%s) ",
-		    (int) (level * 2), "", dwarf_attr_name (attr),
-		    dwarf_form_name (form));
-	  print_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, addr, addr);
-	  printf ("\n");
+	    fprintf (out, "           %*s%-20s (%s) ",
+		     (int) (level * 2), "", dwarf_attr_name (attr),
+		     dwarf_form_name (form));
+	  print_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, addr, addr, out);
+	  fprintf (out, "\n");
 	}
       break;
 
@@ -7768,9 +7789,9 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
       const char *str = dwarf_formstring (attrp);
       if (unlikely (str == NULL))
 	goto attrval_out;
-      printf ("           %*s%-20s (%s) \"%s\"\n",
-	      (int) (level * 2), "", dwarf_attr_name (attr),
-	      dwarf_form_name (form), str);
+      fprintf (out, "           %*s%-20s (%s) \"%s\"\n",
+	       (int) (level * 2), "", dwarf_attr_name (attr),
+	       dwarf_form_name (form), str);
       break;
 
     case DW_FORM_ref_addr:
@@ -7788,22 +7809,22 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
       if (unlikely (dwarf_formref_die (attrp, &ref) == NULL))
 	goto attrval_out;
 
-      printf ("           %*s%-20s (%s) ",
-	      (int) (level * 2), "", dwarf_attr_name (attr),
-	      dwarf_form_name (form));
+      fprintf (out, "           %*s%-20s (%s) ",
+	       (int) (level * 2), "", dwarf_attr_name (attr),
+	       dwarf_form_name (form));
       if (is_split)
-	printf ("{%6" PRIxMAX "}\n", (uintmax_t) dwarf_dieoffset (&ref));
+	fprintf (out, "{%6" PRIxMAX "}\n", (uintmax_t) dwarf_dieoffset (&ref));
       else
-	printf ("[%6" PRIxMAX "]\n", (uintmax_t) dwarf_dieoffset (&ref));
+	fprintf (out, "[%6" PRIxMAX "]\n", (uintmax_t) dwarf_dieoffset (&ref));
       break;
 
     case DW_FORM_ref_sig8:
       if (cbargs->silent)
 	break;
-      printf ("           %*s%-20s (%s) {%6" PRIx64 "}\n",
-	      (int) (level * 2), "", dwarf_attr_name (attr),
-	      dwarf_form_name (form),
-	      (uint64_t) read_8ubyte_unaligned (attrp->cu->dbg, attrp->valp));
+      fprintf (out, "           %*s%-20s (%s) {%6" PRIx64 "}\n",
+	       (int) (level * 2), "", dwarf_attr_name (attr),
+	       dwarf_form_name (form),
+	       (uint64_t) read_8ubyte_unaligned (attrp->cu->dbg, attrp->valp));
       break;
 
     case DW_FORM_sec_offset:
@@ -7831,9 +7852,9 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
 		  || (form != DW_FORM_data4 && form != DW_FORM_data8)))
 	    {
 	      if (!cbargs->silent)
-		printf ("           %*s%-20s (%s) %" PRIuMAX "\n",
-			(int) (level * 2), "", dwarf_attr_name (attr),
-			dwarf_form_name (form), (uintmax_t) num);
+		fprintf (out, "           %*s%-20s (%s) %" PRIuMAX "\n",
+			 (int) (level * 2), "", dwarf_attr_name (attr),
+			 dwarf_form_name (form), (uintmax_t) num);
 	      return DWARF_CB_OK;
 	    }
 	  FALLTHROUGH;
@@ -7886,16 +7907,16 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
 	    if (!cbargs->silent)
 	      {
 		if (cbargs->cu->version < 5 || form == DW_FORM_sec_offset)
-		  printf ("           %*s%-20s (%s) location list [%6"
-			  PRIxMAX "]%s\n",
-			  (int) (level * 2), "", dwarf_attr_name (attr),
-			  dwarf_form_name (form), (uintmax_t) num,
-			  nlpt ? "" : " <WARNING offset too big>");
+		  fprintf (out, "           %*s%-20s (%s) location list [%6"
+			   PRIxMAX "]%s\n",
+			   (int) (level * 2), "", dwarf_attr_name (attr),
+			   dwarf_form_name (form), (uintmax_t) num,
+			   nlpt ? "" : " <WARNING offset too big>");
 		else
-		  printf ("           %*s%-20s (%s) location index [%6"
-			  PRIxMAX "]\n",
-			  (int) (level * 2), "", dwarf_attr_name (attr),
-			  dwarf_form_name (form), (uintmax_t) num);
+		  fprintf (out, "           %*s%-20s (%s) location index [%6"
+			   PRIxMAX "]\n",
+			   (int) (level * 2), "", dwarf_attr_name (attr),
+			   dwarf_form_name (form), (uintmax_t) num);
 	      }
 	  }
 	  return DWARF_CB_OK;
@@ -7907,10 +7928,10 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
                                         cbargs->cu, num, attr);
 
 	    if (!cbargs->silent)
-	      printf ("           %*s%-20s (%s) location list [%6" PRIxMAX "]%s\n",
-		      (int) (level * 2), "", dwarf_attr_name (attr),
-		      dwarf_form_name (form), (uintmax_t) num,
-		      nlpt ? "" : " <WARNING offset too big>");
+	      fprintf (out, "           %*s%-20s (%s) location list [%6" PRIxMAX "]%s\n",
+		       (int) (level * 2), "", dwarf_attr_name (attr),
+		       dwarf_form_name (form), (uintmax_t) num,
+		       nlpt ? "" : " <WARNING offset too big>");
 	  }
 	  return DWARF_CB_OK;
 
@@ -7940,16 +7961,16 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
 	    if (!cbargs->silent)
 	      {
 		if (cbargs->cu->version < 5 || form == DW_FORM_sec_offset)
-		  printf ("           %*s%-20s (%s) range list [%6"
-			  PRIxMAX "]%s\n",
-			  (int) (level * 2), "", dwarf_attr_name (attr),
-			  dwarf_form_name (form), (uintmax_t) num,
-			  nlpt ? "" : " <WARNING offset too big>");
+		  fprintf (out, "           %*s%-20s (%s) range list [%6"
+			   PRIxMAX "]%s\n",
+			   (int) (level * 2), "", dwarf_attr_name (attr),
+			   dwarf_form_name (form), (uintmax_t) num,
+			   nlpt ? "" : " <WARNING offset too big>");
 		else
-		  printf ("           %*s%-20s (%s) range index [%6"
-			  PRIxMAX "]\n",
-			  (int) (level * 2), "", dwarf_attr_name (attr),
-			  dwarf_form_name (form), (uintmax_t) num);
+		  fprintf (out, "           %*s%-20s (%s) range index [%6"
+			   PRIxMAX "]\n",
+			   (int) (level * 2), "", dwarf_attr_name (attr),
+			   dwarf_form_name (form), (uintmax_t) num);
 	      }
 	  }
 	  return DWARF_CB_OK;
@@ -7960,11 +7981,11 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
 					cbargs->addrsize, cbargs->offset_size,
 					cbargs->cu, num, attr);
 	    if (!cbargs->silent)
-	      printf ("           %*s%-20s (%s) range list [%6"
-		      PRIxMAX "]%s\n",
-		      (int) (level * 2), "", dwarf_attr_name (attr),
-		      dwarf_form_name (form), (uintmax_t) num,
-		      nlpt ? "" : " <WARNING offset too big>");
+	      fprintf (out, "           %*s%-20s (%s) range list [%6"
+		       PRIxMAX "]%s\n",
+		       (int) (level * 2), "", dwarf_attr_name (attr),
+		       dwarf_form_name (form), (uintmax_t) num,
+		       nlpt ? "" : " <WARNING offset too big>");
 	  }
 	  return DWARF_CB_OK;
 
@@ -7976,11 +7997,11 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
 					    cbargs->offset_size,
 					    cbargs->cu, num, attr);
 	    if (!cbargs->silent)
-	      printf ("           %*s%-20s (%s) address base [%6"
-		      PRIxMAX "]%s\n",
-		      (int) (level * 2), "", dwarf_attr_name (attr),
-		      dwarf_form_name (form), (uintmax_t) num,
-		      addrbase ? "" : " <WARNING offset too big>");
+	      fprintf (out, "           %*s%-20s (%s) address base [%6"
+		       PRIxMAX "]%s\n",
+		       (int) (level * 2), "", dwarf_attr_name (attr),
+		       dwarf_form_name (form), (uintmax_t) num,
+		       addrbase ? "" : " <WARNING offset too big>");
 	  }
 	  return DWARF_CB_OK;
 
@@ -7991,11 +8012,11 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
 					      cbargs->offset_size,
 					      cbargs->cu, num, attr);
 	    if (!cbargs->silent)
-	      printf ("           %*s%-20s (%s) str offsets base [%6"
-		      PRIxMAX "]%s\n",
-		      (int) (level * 2), "", dwarf_attr_name (attr),
-		      dwarf_form_name (form), (uintmax_t) num,
-		      stroffbase ? "" : " <WARNING offset too big>");
+	      fprintf (out, "           %*s%-20s (%s) str offsets base [%6"
+		       PRIxMAX "]%s\n",
+		       (int) (level * 2), "", dwarf_attr_name (attr),
+		       dwarf_form_name (form), (uintmax_t) num,
+		       stroffbase ? "" : " <WARNING offset too big>");
 	  }
 	  return DWARF_CB_OK;
 
@@ -8088,19 +8109,20 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
       Dwarf_Addr highpc;
       if (attr == DW_AT_high_pc && dwarf_highpc (die, &highpc) == 0)
 	{
-	  printf ("           %*s%-20s (%s) %" PRIuMAX " (",
-		  (int) (level * 2), "", dwarf_attr_name (attr),
-		  dwarf_form_name (form), (uintmax_t) num);
-	  print_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, highpc, highpc);
-	  printf (")\n");
+	  fprintf (out, "           %*s%-20s (%s) %" PRIuMAX " (",
+		   (int) (level * 2), "", dwarf_attr_name (attr),
+		   dwarf_form_name (form), (uintmax_t) num);
+	  print_dwarf_addr (cbargs->dwflmod, cbargs->addrsize,
+			    highpc, highpc, out);
+	  fprintf (out, ")\n");
 	}
       else
 	{
 	  if (as_hex_id)
 	    {
-	      printf ("           %*s%-20s (%s) 0x%.16" PRIx64 "\n",
-		      (int) (level * 2), "", dwarf_attr_name (attr),
-		      dwarf_form_name (form), num);
+	      fprintf (out, "           %*s%-20s (%s) 0x%.16" PRIx64 "\n",
+		       (int) (level * 2), "", dwarf_attr_name (attr),
+		       dwarf_form_name (form), num);
 	    }
 	  else
 	    {
@@ -8119,52 +8141,52 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
 
 	      if (valuestr == NULL)
 		{
-		  printf ("           %*s%-20s (%s) ",
-			  (int) (level * 2), "", dwarf_attr_name (attr),
-			  dwarf_form_name (form));
+		  fprintf (out, "           %*s%-20s (%s) ",
+			   (int) (level * 2), "", dwarf_attr_name (attr),
+			   dwarf_form_name (form));
 		}
 	      else
 		{
-		  printf ("           %*s%-20s (%s) %s (",
-			  (int) (level * 2), "", dwarf_attr_name (attr),
-			  dwarf_form_name (form), valuestr);
+		  fprintf (out, "           %*s%-20s (%s) %s (",
+			   (int) (level * 2), "", dwarf_attr_name (attr),
+			   dwarf_form_name (form), valuestr);
 		}
 
 	      switch (bytes)
 		{
 		case 1:
 		  if (is_signed)
-		    printf ("%" PRId8, (int8_t) snum);
+		    fprintf (out, "%" PRId8, (int8_t) snum);
 		  else
-		    printf ("%" PRIu8, (uint8_t) num);
+		    fprintf (out, "%" PRIu8, (uint8_t) num);
 		  break;
 
 		case 2:
 		  if (is_signed)
-		    printf ("%" PRId16, (int16_t) snum);
+		    fprintf (out, "%" PRId16, (int16_t) snum);
 		  else
-		    printf ("%" PRIu16, (uint16_t) num);
+		    fprintf (out, "%" PRIu16, (uint16_t) num);
 		  break;
 
 		case 4:
 		  if (is_signed)
-		    printf ("%" PRId32, (int32_t) snum);
+		    fprintf (out, "%" PRId32, (int32_t) snum);
 		  else
-		    printf ("%" PRIu32, (uint32_t) num);
+		    fprintf (out, "%" PRIu32, (uint32_t) num);
 		  break;
 
 		case 8:
 		  if (is_signed)
-		    printf ("%" PRId64, (int64_t) snum);
+		    fprintf (out, "%" PRId64, (int64_t) snum);
 		  else
-		    printf ("%" PRIu64, (uint64_t) num);
+		    fprintf (out, "%" PRIu64, (uint64_t) num);
 		  break;
 
 		default:
 		  if (is_signed)
-		    printf ("%" PRIdMAX, (intmax_t) snum);
+		    fprintf (out, "%" PRIdMAX, (intmax_t) snum);
 		  else
-		    printf ("%" PRIuMAX, (uintmax_t) num);
+		    fprintf (out, "%" PRIuMAX, (uintmax_t) num);
 		  break;
 		}
 
@@ -8173,12 +8195,12 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
 	      if (attr == DW_AT_const_value
 		  && (form == DW_FORM_sdata || form == DW_FORM_implicit_const)
 		  && !is_signed)
-		printf (" (%" PRIdMAX ")", (intmax_t) num);
+		fprintf (out, " (%" PRIdMAX ")", (intmax_t) num);
 
 	      if (valuestr == NULL)
-		printf ("\n");
+		fprintf (out, "\n");
 	      else
-		printf (")\n");
+		fprintf (out, ")\n");
 	    }
 	}
       break;
@@ -8190,17 +8212,17 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
       if (unlikely (dwarf_formflag (attrp, &flag) != 0))
 	goto attrval_out;
 
-      printf ("           %*s%-20s (%s) %s\n",
-	      (int) (level * 2), "", dwarf_attr_name (attr),
-	      dwarf_form_name (form), flag ? yes_str : no_str);
+      fprintf (out, "           %*s%-20s (%s) %s\n",
+	       (int) (level * 2), "", dwarf_attr_name (attr),
+	       dwarf_form_name (form), flag ? yes_str : no_str);
       break;
 
     case DW_FORM_flag_present:
       if (cbargs->silent)
 	break;
-      printf ("           %*s%-20s (%s) %s\n",
-	      (int) (level * 2), "", dwarf_attr_name (attr),
-	      dwarf_form_name (form), yes_str);
+      fprintf (out, "           %*s%-20s (%s) %s\n",
+	       (int) (level * 2), "", dwarf_attr_name (attr),
+	       dwarf_form_name (form), yes_str);
       break;
 
     case DW_FORM_exprloc:
@@ -8215,16 +8237,16 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
       if (unlikely (dwarf_formblock (attrp, &block) != 0))
 	goto attrval_out;
 
-      printf ("           %*s%-20s (%s) ",
-	      (int) (level * 2), "", dwarf_attr_name (attr),
-	      dwarf_form_name (form));
+      fprintf (out, "           %*s%-20s (%s) ",
+	       (int) (level * 2), "", dwarf_attr_name (attr),
+	       dwarf_form_name (form));
 
       switch (attr)
 	{
 	default:
 	  if (form != DW_FORM_exprloc)
 	    {
-	      print_block (block.length, block.data);
+	      print_block (block.length, block.data, out);
 	      break;
 	    }
 	  FALLTHROUGH;
@@ -8256,19 +8278,19 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
 	      || (form != DW_FORM_data16
 		  && attrp->cu->version < 4)) /* blocks were expressions.  */
 	    {
-	      putchar ('\n');
+	      fputc ('\n', out);
 	      print_ops (cbargs->dwflmod, cbargs->dbg,
 			 12 + level * 2, 12 + level * 2,
 			 cbargs->version, cbargs->addrsize, cbargs->offset_size,
-			 attrp->cu, block.length, block.data);
+			 attrp->cu, block.length, block.data, out);
 	    }
 	  else
-	    print_block (block.length, block.data);
+	    print_block (block.length, block.data, out);
 	  break;
 
 	case DW_AT_discr_list:
 	  if (block.length == 0)
-	    puts ("<default>");
+	    fputs ("<default>\n", out);
 	  else if (form != DW_FORM_data16)
 	    {
 	      const unsigned char *readp = block.data;
@@ -8302,7 +8324,7 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
 	      while (readp < readendp)
 		{
 		  int d = (int) *readp++;
-		  printf ("%s ", dwarf_discr_list_name (d));
+		  fprintf (out, "%s ", dwarf_discr_list_name (d));
 		  if (readp >= readendp)
 		    goto attrval_out;
 
@@ -8313,12 +8335,12 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
 		      if (is_signed)
 			{
 			  get_sleb128 (sval, readp, readendp);
-			  printf ("%" PRId64 "", sval);
+			  fprintf (out, "%" PRId64 "", sval);
 			}
 		      else
 			{
 			  get_uleb128 (val, readp, readendp);
-			  printf ("%" PRIu64 "", val);
+			  fprintf (out, "%" PRIu64 "", val);
 			}
 		    }
 		  else if (d == DW_DSC_range)
@@ -8326,34 +8348,34 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
 		      if (is_signed)
 			{
 			  get_sleb128 (sval, readp, readendp);
-			  printf ("%" PRId64 "..", sval);
+			  fprintf (out, "%" PRId64 "..", sval);
 			  if (readp >= readendp)
 			    goto attrval_out;
 			  get_sleb128 (sval, readp, readendp);
-			  printf ("%" PRId64 "", sval);
+			  fprintf (out, "%" PRId64 "", sval);
 			}
 		      else
 			{
 			  get_uleb128 (val, readp, readendp);
-			  printf ("%" PRIu64 "..", val);
+			  fprintf (out, "%" PRIu64 "..", val);
 			  if (readp >= readendp)
 			    goto attrval_out;
 			  get_uleb128 (val, readp, readendp);
-			  printf ("%" PRIu64 "", val);
+			  fprintf (out, "%" PRIu64 "", val);
 			}
 		    }
 		  else
 		    {
-		      print_block (readendp - readp, readp);
+		      print_block (readendp - readp, readp, out);
 		      break;
 		    }
 		  if (readp < readendp)
-		    printf (", ");
+		    fprintf (out, ", ");
 		}
-	      putchar ('\n');
+	      fputc ('\n', out);
 	    }
 	  else
-	    print_block (block.length, block.data);
+	    print_block (block.length, block.data, out);
 	  break;
 	}
       break;
@@ -8361,9 +8383,9 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
     default:
       if (cbargs->silent)
 	break;
-      printf ("           %*s%-20s (%s) ???\n",
-	      (int) (level * 2), "", dwarf_attr_name (attr),
-	      dwarf_form_name (form));
+      fprintf (out, "           %*s%-20s (%s) ???\n",
+	       (int) (level * 2), "", dwarf_attr_name (attr),
+	       dwarf_form_name (form));
       break;
     }
 
@@ -8374,7 +8396,7 @@ static void
 print_debug_units (Dwfl_Module *dwflmod,
 		   Ebl *ebl, GElf_Ehdr *ehdr __attribute__ ((unused)),
 		   Elf_Scn *scn, GElf_Shdr *shdr,
-		   Dwarf *dbg, bool debug_types)
+		   Dwarf *dbg, bool debug_types, FILE *out)
 {
   const bool silent = !(print_debug_sections & section_info) && !debug_types;
   const char *secname = section_name (ebl, shdr);
@@ -8387,9 +8409,9 @@ print_debug_units (Dwfl_Module *dwflmod,
       return;
 
   if (!silent)
-    printf (_("\
+    fprintf (out, _("\
 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n [Offset]\n"),
-	    elf_ndxscn (scn), secname, (uint64_t) shdr->sh_offset);
+	     elf_ndxscn (scn), secname, (uint64_t) shdr->sh_offset);
 
   /* If the section is empty we don't have to do anything.  */
   if (!silent && shdr->sh_size == 0)
@@ -8457,35 +8479,35 @@ print_debug_units (Dwfl_Module *dwflmod,
 	  dieoffset = dwarf_dieoffset (dwarf_offdie_types (dbg, cu->start
 							   + subdie_off,
 							   &typedie));
-	  printf (_(" Type unit at offset %" PRIu64 ":\n"
-			   " Version: %" PRIu16
-			   ", Abbreviation section offset: %" PRIu64
-			   ", Address size: %" PRIu8
-			   ", Offset size: %" PRIu8
-			   "\n Type signature: %#" PRIx64
-			   ", Type offset: %#" PRIx64 " [%" PRIx64 "]\n"),
-		  (uint64_t) offset, version, abbroffset, addrsize, offsize,
-		  unit_id, (uint64_t) subdie_off, dieoffset);
+	  fprintf (out, _(" Type unit at offset %" PRIu64 ":\n"
+			    " Version: %" PRIu16
+			    ", Abbreviation section offset: %" PRIu64
+			    ", Address size: %" PRIu8
+			    ", Offset size: %" PRIu8
+			    "\n Type signature: %#" PRIx64
+			    ", Type offset: %#" PRIx64 " [%" PRIx64 "]\n"),
+		   (uint64_t) offset, version, abbroffset, addrsize, offsize,
+		   unit_id, (uint64_t) subdie_off, dieoffset);
 	}
       else
 	{
-	  printf (_(" Compilation unit at offset %" PRIu64 ":\n"
-			   " Version: %" PRIu16
-			   ", Abbreviation section offset: %" PRIu64
-			   ", Address size: %" PRIu8
-			   ", Offset size: %" PRIu8 "\n"),
-		  (uint64_t) offset, version, abbroffset, addrsize, offsize);
+	  fprintf (out, _(" Compilation unit at offset %" PRIu64 ":\n"
+			    " Version: %" PRIu16
+			    ", Abbreviation section offset: %" PRIu64
+			    ", Address size: %" PRIu8
+			    ", Offset size: %" PRIu8 "\n"),
+		   (uint64_t) offset, version, abbroffset, addrsize, offsize);
 
 	  if (version >= 5 || (unit_type != DW_UT_compile
 			       && unit_type != DW_UT_partial))
 	    {
-	      printf (_(" Unit type: %s (%" PRIu8 ")"),
-			       dwarf_unit_name (unit_type), unit_type);
+	      fprintf (out, _(" Unit type: %s (%" PRIu8 ")"),
+			        dwarf_unit_name (unit_type), unit_type);
 	      if (unit_type == DW_UT_type
 		  || unit_type == DW_UT_skeleton
 		  || unit_type == DW_UT_split_compile
 		  || unit_type == DW_UT_split_type)
-		printf (", Unit id: 0x%.16" PRIx64 "", unit_id);
+		fprintf (out, ", Unit id: 0x%.16" PRIx64 "", unit_id);
 	      if (unit_type == DW_UT_type
 		  || unit_type == DW_UT_split_type)
 		{
@@ -8494,10 +8516,10 @@ print_debug_units (Dwfl_Module *dwflmod,
 		  dwarf_cu_info (cu, NULL, NULL, NULL, &typedie,
 				 NULL, NULL, NULL);
 		  dieoffset = dwarf_dieoffset (&typedie);
-		  printf (", Unit DIE off: %#" PRIx64 " [%" PRIx64 "]",
-			  subdie_off, dieoffset);
+		  fprintf (out, ", Unit DIE off: %#" PRIx64 " [%" PRIx64 "]",
+			   subdie_off, dieoffset);
 		}
-	      printf ("\n");
+	      fprintf (out, "\n");
 	    }
 	}
     }
@@ -8526,6 +8548,7 @@ print_debug_units (Dwfl_Module *dwflmod,
   args.cu = dies[0].cu;
   args.dbg = dbg;
   args.is_split = is_split;
+  args.out = out;
 
   /* We might return here again for the split CU subdie.  */
   do_cu:
@@ -8554,11 +8577,11 @@ print_debug_units (Dwfl_Module *dwflmod,
 	{
 	  unsigned int code = dwarf_getabbrevcode (dies[level].abbrev);
 	  if (is_split)
-	    printf (" {%6" PRIx64 "}  ", (uint64_t) offset);
+	    fprintf (out, " {%6" PRIx64 "}  ", (uint64_t) offset);
 	  else
-	    printf (" [%6" PRIx64 "]  ", (uint64_t) offset);
-	  printf ("%*s%-20s abbrev: %u\n", (int) (level * 2), "",
-		  dwarf_tag_name (tag), code);
+	    fprintf (out, " [%6" PRIx64 "]  ", (uint64_t) offset);
+	  fprintf (out, "%*s%-20s abbrev: %u\n", (int) (level * 2), "",
+		   dwarf_tag_name (tag), code);
 	}
 
       /* Print the attribute values.  */
@@ -8632,18 +8655,18 @@ print_debug_units (Dwfl_Module *dwflmod,
 
 	  if (!silent)
 	    {
-	      printf (_(" Split compilation unit at offset %"
-			       PRIu64 ":\n"
-			       " Version: %" PRIu16
-			       ", Abbreviation section offset: %" PRIu64
-			       ", Address size: %" PRIu8
-			       ", Offset size: %" PRIu8 "\n"),
-		      (uint64_t) offset, version, abbroffset,
-		      addrsize, offsize);
-	      printf (_(" Unit type: %s (%" PRIu8 ")"),
-		      dwarf_unit_name (unit_type), unit_type);
-	      printf (", Unit id: 0x%.16" PRIx64 "", unit_id);
-	      printf ("\n");
+	      fprintf (out, _(" Split compilation unit at offset %"
+			        PRIu64 ":\n"
+			        " Version: %" PRIu16
+			        ", Abbreviation section offset: %" PRIu64
+			        ", Address size: %" PRIu8
+			        ", Offset size: %" PRIu8 "\n"),
+		       (uint64_t) offset, version, abbroffset,
+		       addrsize, offsize);
+	      fprintf (out, _(" Unit type: %s (%" PRIu8 ")"),
+		       dwarf_unit_name (unit_type), unit_type);
+	      fprintf (out, ", Unit id: 0x%.16" PRIx64 "", unit_id);
+	      fprintf (out, "\n");
 	    }
 
 	  unit_type = DW_UT_split_compile;
@@ -8666,28 +8689,31 @@ print_debug_units (Dwfl_Module *dwflmod,
 
 static void
 print_debug_info_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
-			  Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+			  Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg,
+			  FILE *out)
 {
-  print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, false);
+  print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, false, out);
 }
 
 static void
 print_debug_types_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
-			   Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+			   Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg,
+			   FILE *out)
 {
-  print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, true);
+  print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, true, out);
 }
 
 
 static void
 print_decoded_line_section (Dwfl_Module *dwflmod, Ebl *ebl,
 			    GElf_Ehdr *ehdr __attribute__ ((unused)),
-			    Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+			    Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg,
+			    FILE *out)
 {
-  printf (_("\
+  fprintf (out, _("\
 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n\n"),
-	  elf_ndxscn (scn), section_name (ebl, shdr),
-	  (uint64_t) shdr->sh_offset);
+	   elf_ndxscn (scn), section_name (ebl, shdr),
+	   (uint64_t) shdr->sh_offset);
 
   size_t address_size
     = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
@@ -8702,8 +8728,8 @@ print_decoded_line_section (Dwfl_Module *dwflmod, Ebl *ebl,
       Dwarf_Die cudie;
       if (cu != NULL && dwarf_cu_info (cu, NULL, NULL, &cudie,
 				       NULL, NULL, NULL, NULL) == 0)
-	printf (" CU [%" PRIx64 "] %s\n",
-		dwarf_dieoffset (&cudie), dwarf_diename (&cudie));
+	fprintf (out, " CU [%" PRIx64 "] %s\n",
+		 dwarf_dieoffset (&cudie), dwarf_diename (&cudie));
       else
 	{
 	  /* DWARF5 lines can be independent of any CU, but they probably
@@ -8731,34 +8757,35 @@ print_decoded_line_section (Dwfl_Module *dwflmod, Ebl *ebl,
 	    }
 
 	  if (cu != NULL)
-	    printf (" CU [%" PRIx64 "] %s\n",
-		    dwarf_dieoffset (&cudie), dwarf_diename (&cudie));
+	    fprintf (out, " CU [%" PRIx64 "] %s\n",
+		     dwarf_dieoffset (&cudie), dwarf_diename (&cudie));
 	  else
-	    printf (" No CU\n");
+	    fprintf (out, " No CU\n");
 	}
 
-      printf ("  line:col SBPE* disc isa op address"
-	      " (Statement Block Prologue Epilogue *End)\n");
+      fprintf (out, "  line:col SBPE* disc isa op address"
+	       " (Statement Block Prologue Epilogue *End)\n");
       const char *last_file = "";
       for (size_t n = 0; n < nlines; n++)
 	{
 	  Dwarf_Line *line = dwarf_onesrcline (lines, n);
 	  if (line == NULL)
 	    {
-	      printf ("  dwarf_onesrcline: %s\n", dwarf_errmsg (-1));
+	      fprintf (out, "  dwarf_onesrcline: %s\n", dwarf_errmsg (-1));
 	      continue;
 	    }
 	  Dwarf_Word mtime, length;
 	  const char *file = dwarf_linesrc (line, &mtime, &length);
 	  if (file == NULL)
 	    {
-	      printf ("  <%s> (mtime: ?, length: ?)\n", dwarf_errmsg (-1));
+	      fprintf (out, "  <%s> (mtime: ?, length: ?)\n",
+		       dwarf_errmsg (-1));
 	      last_file = "";
 	    }
 	  else if (strcmp (last_file, file) != 0)
 	    {
-	      printf ("  %s (mtime: %" PRIu64 ", length: %" PRIu64 ")\n",
-		      file, mtime, length);
+	      fprintf (out, "  %s (mtime: %" PRIu64 ", length: %" PRIu64 ")\n",
+		       file, mtime, length);
 	      last_file = file;
 	    }
 
@@ -8779,20 +8806,20 @@ print_decoded_line_section (Dwfl_Module *dwflmod, Ebl *ebl,
 	  dwarf_linediscriminator (line, &disc);
 
 	  /* End sequence is special, it is one byte past.  */
-	  printf ("  %4d:%-3d %c%c%c%c%c %4d %3d %2d ",
-		  lineno, colno,
-		  (statement ? 'S' : ' '),
-		  (block ? 'B' : ' '),
-		  (prologue_end ? 'P' : ' '),
-		  (epilogue_begin ? 'E' : ' '),
-		  (endseq ? '*' : ' '),
-		  disc, isa, lineop);
+	  fprintf (out, "  %4d:%-3d %c%c%c%c%c %4d %3d %2d ",
+		   lineno, colno,
+		   (statement ? 'S' : ' '),
+		   (block ? 'B' : ' '),
+		   (prologue_end ? 'P' : ' '),
+		   (epilogue_begin ? 'E' : ' '),
+		   (endseq ? '*' : ' '),
+		   disc, isa, lineop);
 	  print_dwarf_addr (dwflmod, address_size,
-			    address - (endseq ? 1 : 0), address);
-	  printf ("\n");
+			    address - (endseq ? 1 : 0), address, out);
+	  fprintf (out, "\n");
 
 	  if (endseq)
-	    printf("\n");
+	    fprintf(out, "\n");
 	}
     }
 }
@@ -8803,7 +8830,7 @@ print_decoded_line_section (Dwfl_Module *dwflmod, Ebl *ebl,
 static const unsigned char *
 print_form_data (Dwarf *dbg, int form, const unsigned char *readp,
 		 const unsigned char *readendp, unsigned int offset_len,
-		 Dwarf_Off str_offsets_base)
+		 Dwarf_Off str_offsets_base, FILE *out)
 {
   Dwarf_Word val;
   unsigned char *endp;
@@ -8819,42 +8846,42 @@ print_form_data (Dwarf *dbg, int form, const unsigned char *readp,
 	  return readendp;
 	}
       val = *readp++;
-      printf (" %" PRIx8, (unsigned int) val);
+      fprintf (out, " %" PRIx8, (unsigned int) val);
       break;
 
     case DW_FORM_data2:
       if (readendp - readp < 2)
 	goto invalid_data;
       val = read_2ubyte_unaligned_inc (dbg, readp);
-      printf(" %" PRIx16, (unsigned int) val);
+      fprintf(out, " %" PRIx16, (unsigned int) val);
       break;
 
     case DW_FORM_data4:
       if (readendp - readp < 4)
 	goto invalid_data;
       val = read_4ubyte_unaligned_inc (dbg, readp);
-      printf (" %" PRIx32, (unsigned int) val);
+      fprintf (out, " %" PRIx32, (unsigned int) val);
       break;
 
     case DW_FORM_data8:
       if (readendp - readp < 8)
 	goto invalid_data;
       val = read_8ubyte_unaligned_inc (dbg, readp);
-      printf (" %" PRIx64, val);
+      fprintf (out, " %" PRIx64, val);
       break;
 
     case DW_FORM_sdata:
       if (readendp - readp < 1)
 	goto invalid_data;
       get_sleb128 (val, readp, readendp);
-      printf (" %" PRIx64, val);
+      fprintf (out, " %" PRIx64, val);
       break;
 
     case DW_FORM_udata:
       if (readendp - readp < 1)
 	goto invalid_data;
       get_uleb128 (val, readp, readendp);
-      printf (" %" PRIx64, val);
+      fprintf (out, " %" PRIx64, val);
       break;
 
     case DW_FORM_block:
@@ -8863,7 +8890,7 @@ print_form_data (Dwarf *dbg, int form, const unsigned char *readp,
       get_uleb128 (val, readp, readendp);
       if ((size_t) (readendp - readp) < val)
 	goto invalid_data;
-      print_bytes (val, readp);
+      print_bytes (val, readp, out);
       readp += val;
       break;
 
@@ -8873,7 +8900,7 @@ print_form_data (Dwarf *dbg, int form, const unsigned char *readp,
       val = *readp++;
       if ((size_t) (readendp - readp) < val)
 	goto invalid_data;
-      print_bytes (val, readp);
+      print_bytes (val, readp, out);
       readp += val;
       break;
 
@@ -8883,7 +8910,7 @@ print_form_data (Dwarf *dbg, int form, const unsigned char *readp,
       val = read_2ubyte_unaligned_inc (dbg, readp);
       if ((size_t) (readendp - readp) < val)
 	goto invalid_data;
-      print_bytes (val, readp);
+      print_bytes (val, readp, out);
       readp += val;
       break;
 
@@ -8893,14 +8920,14 @@ print_form_data (Dwarf *dbg, int form, const unsigned char *readp,
       val = read_4ubyte_unaligned_inc (dbg, readp);
       if ((size_t) (readendp - readp) < val)
 	goto invalid_data;
-      print_bytes (val, readp);
+      print_bytes (val, readp, out);
       readp += val;
       break;
 
     case DW_FORM_data16:
       if (readendp - readp < 16)
 	goto invalid_data;
-      print_bytes (16, readp);
+      print_bytes (16, readp, out);
       readp += 16;
       break;
 
@@ -8908,14 +8935,14 @@ print_form_data (Dwarf *dbg, int form, const unsigned char *readp,
       if (readendp - readp < 1)
 	goto invalid_data;
       val = *readp++;
-      printf ("%s", val != 0 ? yes_str : no_str);
+      fprintf (out, "%s", val != 0 ? yes_str : no_str);
       break;
 
     case DW_FORM_string:
       endp = memchr (readp, '\0', readendp - readp);
       if (endp == NULL)
 	goto invalid_data;
-      printf ("%s", readp);
+      fprintf (out, "%s", readp);
       readp = endp + 1;
       break;
 
@@ -8942,7 +8969,7 @@ print_form_data (Dwarf *dbg, int form, const unsigned char *readp,
 	str = "???";
       else
 	str = (char *) data->d_buf + val;
-      printf ("%s (%" PRIu64 ")", str, val);
+      fprintf (out, "%s (%" PRIu64 ")", str, val);
       break;
 
     case DW_FORM_sec_offset:
@@ -8952,7 +8979,7 @@ print_form_data (Dwarf *dbg, int form, const unsigned char *readp,
 	val = read_8ubyte_unaligned_inc (dbg, readp);
       else
 	val = read_4ubyte_unaligned_inc (dbg, readp);
-      printf ("[%" PRIx64 "]", val);
+      fprintf (out, "[%" PRIx64 "]", val);
       break;
 
     case DW_FORM_strx:
@@ -8989,7 +9016,7 @@ print_form_data (Dwarf *dbg, int form, const unsigned char *readp,
 		str = (char *) data->d_buf + idx;
 	    }
 	}
-      printf ("%s (%" PRIu64 ")", str, val);
+      fprintf (out, "%s (%" PRIu64 ")", str, val);
       break;
 
     case DW_FORM_strx1:
@@ -9043,11 +9070,12 @@ run_advance_pc (unsigned int op_advance,
 
 static void
 print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
-			  Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+			  Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg,
+			  FILE *out)
 {
   if (decodedline)
     {
-      print_decoded_line_section (dwflmod, ebl, ehdr, scn, shdr, dbg);
+      print_decoded_line_section (dwflmod, ebl, ehdr, scn, shdr, dbg, out);
       return;
     }
 
@@ -9055,10 +9083,10 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
   if (data == NULL)
     return;
 
-  printf (_("\
+  fprintf (out, _("\
 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
-	  elf_ndxscn (scn), section_name (ebl, shdr),
-	  (uint64_t) shdr->sh_offset);
+	   elf_ndxscn (scn), section_name (ebl, shdr),
+	   (uint64_t) shdr->sh_offset);
 
   if (shdr->sh_size == 0)
     return;
@@ -9074,7 +9102,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
     {
       size_t start_offset = linep - (const unsigned char *) data->d_buf;
 
-      printf (_("\nTable at offset %zu:\n"), start_offset);
+      fprintf (out, _("\nTable at offset %zu:\n"), start_offset);
 
       if (unlikely (linep + 4 > lineendp))
 	goto invalid_data;
@@ -9165,25 +9193,25 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
       uint_fast8_t opcode_base = *linep++;
 
       /* Print what we got so far.  */
-      printf (_("\n"
-		       " Length:                         %" PRIu64 "\n"
-		       " DWARF version:                  %" PRIuFAST16 "\n"
-		       " Prologue length:                %" PRIu64 "\n"
-		       " Address size:                   %zd\n"
-		       " Segment selector size:          %zd\n"
-		       " Min instruction length:         %" PRIuFAST8 "\n"
-		       " Max operations per instruction: %" PRIuFAST8 "\n"
-		       " Initial value if 'is_stmt':     %" PRIuFAST8 "\n"
-		       " Line base:                      %" PRIdFAST8 "\n"
-		       " Line range:                     %" PRIuFAST8 "\n"
-		       " Opcode base:                    %" PRIuFAST8 "\n"
-		       "\n"
-		       "Opcodes:\n"),
-	      (uint64_t) unit_length, version, (uint64_t) header_length,
-	      address_size, (size_t) segment_selector_size,
-	      minimum_instr_len, max_ops_per_instr,
-	      default_is_stmt, line_base,
-	      line_range, opcode_base);
+      fprintf (out, _("\n"
+		        " Length:                         %" PRIu64 "\n"
+		        " DWARF version:                  %" PRIuFAST16 "\n"
+		        " Prologue length:                %" PRIu64 "\n"
+		        " Address size:                   %zd\n"
+		        " Segment selector size:          %zd\n"
+		        " Min instruction length:         %" PRIuFAST8 "\n"
+		        " Max operations per instruction: %" PRIuFAST8 "\n"
+		        " Initial value if 'is_stmt':     %" PRIuFAST8 "\n"
+		        " Line base:                      %" PRIdFAST8 "\n"
+		        " Line range:                     %" PRIuFAST8 "\n"
+		        " Opcode base:                    %" PRIuFAST8 "\n"
+		        "\n"
+		        "Opcodes:\n"),
+	       (uint64_t) unit_length, version, (uint64_t) header_length,
+	       address_size, (size_t) segment_selector_size,
+	       minimum_instr_len, max_ops_per_instr,
+	       default_is_stmt, line_base,
+	       line_range, opcode_base);
 
       if (version < 2 || version > 5)
 	{
@@ -9228,10 +9256,10 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 	}
       const uint8_t *standard_opcode_lengths = linep - 1;
       for (uint_fast8_t cnt = 1; cnt < opcode_base; ++cnt)
-	printf (ngettext ("  [%*" PRIuFAST8 "]  %hhu argument\n",
-			  "  [%*" PRIuFAST8 "]  %hhu arguments\n",
-			  (int) linep[cnt - 1]),
-		opcode_base_l10, cnt, linep[cnt - 1]);
+	fprintf (out, ngettext ("  [%*" PRIuFAST8 "]  %hhu argument\n",
+			   "  [%*" PRIuFAST8 "]  %hhu arguments\n",
+			   (int) linep[cnt - 1]),
+		 opcode_base_l10, cnt, linep[cnt - 1]);
       linep += opcode_base - 1;
 
       if (unlikely (linep >= lineendp))
@@ -9239,13 +9267,13 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 
       Dwarf_Off str_offsets_base = str_offsets_base_off (dbg, NULL);
 
-      puts (_("\nDirectory table:"));
+      fputs (_("\nDirectory table:\n"), out);
       if (version > 4)
 	{
 	  struct encpair { uint16_t desc; uint16_t form; };
 	  struct encpair enc[256];
 
-	  printf (_("      ["));
+	  fprintf (out, _("      ["));
 	  if ((size_t) (lineendp - linep) < 1)
 	    goto invalid_data;
 	  unsigned char directory_entry_format_count = *linep++;
@@ -9262,13 +9290,13 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 	      enc[i].desc = desc;
 	      enc[i].form = form;
 
-	      printf ("%s(%s)",
-		      dwarf_line_content_description_name (desc),
-		      dwarf_form_name (form));
+	      fprintf (out, "%s(%s)",
+		       dwarf_line_content_description_name (desc),
+		       dwarf_form_name (form));
 	      if (i + 1 < directory_entry_format_count)
-		printf (", ");
+		fprintf (out, ", ");
 	    }
-	  printf ("]\n");
+	  fprintf (out, "]\n");
 
 	  uint64_t directories_count;
 	  if ((size_t) (lineendp - linep) < 1)
@@ -9281,16 +9309,16 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 
 	  for (uint64_t i = 0; i < directories_count; i++)
 	    {
-	      printf (" %-5" PRIu64 " ", i);
+	      fprintf (out, " %-5" PRIu64 " ", i);
 	      for (int j = 0; j < directory_entry_format_count; j++)
 		{
 		  linep = print_form_data (dbg, enc[j].form,
 					   linep, lineendp, length,
-					   str_offsets_base);
+					   str_offsets_base, out);
 		  if (j + 1 < directory_entry_format_count)
-		    printf (", ");
+		    fprintf (out, ", ");
 		}
-	      printf ("\n");
+	      fprintf (out, "\n");
 	      if (linep >= lineendp)
 		goto invalid_unit;
 	    }
@@ -9303,7 +9331,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 	      if (unlikely (endp == NULL))
 		goto invalid_unit;
 
-	      printf (" %s\n", (char *) linep);
+	      fprintf (out, " %s\n", (char *) linep);
 
 	      linep = endp + 1;
 	    }
@@ -9316,13 +9344,13 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
       if (unlikely (linep >= lineendp))
 	goto invalid_unit;
 
-      puts (_("\nFile name table:"));
+      fputs (_("\nFile name table:\n"), out);
       if (version > 4)
 	{
 	  struct encpair { uint16_t desc; uint16_t form; };
 	  struct encpair enc[256];
 
-	  printf (_("      ["));
+	  fprintf (out, _("      ["));
 	  if ((size_t) (lineendp - linep) < 1)
 	    goto invalid_data;
 	  unsigned char file_name_format_count = *linep++;
@@ -9342,13 +9370,13 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 	      enc[i].desc = desc;
 	      enc[i].form = form;
 
-	      printf ("%s(%s)",
-		      dwarf_line_content_description_name (desc),
-		      dwarf_form_name (form));
+	      fprintf (out, "%s(%s)",
+		       dwarf_line_content_description_name (desc),
+		       dwarf_form_name (form));
 	      if (i + 1 < file_name_format_count)
-		printf (", ");
+		fprintf (out, ", ");
 	    }
-	  printf ("]\n");
+	  fprintf (out, "]\n");
 
 	  uint64_t file_name_count;
 	  if ((size_t) (lineendp - linep) < 1)
@@ -9361,23 +9389,23 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 
 	  for (uint64_t i = 0; i < file_name_count; i++)
 	    {
-	      printf (" %-5" PRIu64 " ", i);
+	      fprintf (out, " %-5" PRIu64 " ", i);
 	      for (int j = 0; j < file_name_format_count; j++)
 		{
 		  linep = print_form_data (dbg, enc[j].form,
 					   linep, lineendp, length,
-					   str_offsets_base);
+					   str_offsets_base, out);
 		  if (j + 1 < file_name_format_count)
-		    printf (", ");
+		    fprintf (out, ", ");
 		}
-	      printf ("\n");
+	      fprintf (out, "\n");
 	      if (linep > lineendp)
 		goto invalid_unit;
 	    }
 	}
       else
 	{
-	  puts (_(" Entry Dir   Time      Size      Name"));
+	  fputs (_(" Entry Dir   Time      Size      Name\n"), out);
 	  for (unsigned int cnt = 1; linep < lineendp && *linep != 0; ++cnt)
 	    {
 	      /* First comes the file name.  */
@@ -9405,8 +9433,8 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 		goto invalid_unit;
 	      get_uleb128 (fsize, linep, lineendp);
 
-	      printf (" %-5u %-5u %-9u %-9u %s\n",
-		      cnt, diridx, mtime, fsize, fname);
+	      fprintf (out, " %-5u %-5u %-9u %-9u %s\n",
+		       cnt, diridx, mtime, fsize, fname);
 	    }
 	  if (linep >= lineendp || *linep != '\0')
 	    goto invalid_unit;
@@ -9423,11 +9451,11 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 
       if (linep == lineendp)
 	{
-	  puts (_("\nNo line number statements."));
+	  fputs (_("\nNo line number statements.\n"), out);
 	  continue;
 	}
 
-      puts (_("\nLine number statements:"));
+      fputs (_("\nLine number statements:\n"), out);
       Dwarf_Word address = 0;
       unsigned int op_index = 0;
       size_t line = 1;
@@ -9456,7 +9484,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 	  /* Read the opcode.  */
 	  unsigned int opcode = *linep++;
 
-	  printf (" [%6" PRIx64 "]", (uint64_t)offset);
+	  fprintf (out, " [%6" PRIx64 "]", (uint64_t)offset);
 	  /* Is this a special opcode?  */
 	  if (likely (opcode >= opcode_base))
 	    {
@@ -9476,15 +9504,15 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 	      line += line_increment;
 	      advance_pc ((opcode - opcode_base) / line_range);
 
-	      printf (_(" special opcode %u: address+%u = "),
-		      opcode, op_addr_advance);
-	      print_dwarf_addr (dwflmod, 0, address, address);
+	      fprintf (out, _(" special opcode %u: address+%u = "),
+		       opcode, op_addr_advance);
+	      print_dwarf_addr (dwflmod, 0, address, address, out);
 	      if (op_index > 0)
-		printf (_(", op_index = %u, line%+d = %zu\n"),
-			op_index, line_increment, line);
+		fprintf (out, _(", op_index = %u, line%+d = %zu\n"),
+			 op_index, line_increment, line);
 	      else
-		printf (_(", line%+d = %zu\n"),
-			line_increment, line);
+		fprintf (out, _(", line%+d = %zu\n"),
+			 line_increment, line);
 	    }
 	  else if (opcode == 0)
 	    {
@@ -9501,12 +9529,12 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 	      /* The sub-opcode.  */
 	      opcode = *linep++;
 
-	      printf (_(" extended opcode %u: "), opcode);
+	      fprintf (out, _(" extended opcode %u: "), opcode);
 
 	      switch (opcode)
 		{
 		case DW_LNE_end_sequence:
-		  puts (_(" end of sequence"));
+		  fputs (_(" end of sequence\n"), out);
 
 		  /* Reset the registers we care about.  */
 		  address = 0;
@@ -9524,9 +9552,9 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 		  else
 		    address = read_8ubyte_unaligned_inc (dbg, linep);
 		  {
-		    printf (_(" set address to "));
-		    print_dwarf_addr (dwflmod, 0, address, address);
-		    printf ("\n");
+		    fprintf (out, _(" set address to "));
+		    print_dwarf_addr (dwflmod, 0, address, address, out);
+		    fprintf (out, "\n");
 		  }
 		  break;
 
@@ -9552,10 +9580,10 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 		      goto invalid_unit;
 		    get_uleb128 (filelength, linep, lineendp);
 
-		    printf (_("\
+		    fprintf (out, _("\
  define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
-			    diridx, (uint64_t) mtime, (uint64_t) filelength,
-			    fname);
+			     diridx, (uint64_t) mtime, (uint64_t) filelength,
+			     fname);
 		  }
 		  break;
 
@@ -9566,7 +9594,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 		    goto invalid_unit;
 
 		  get_uleb128 (u128, linep, lineendp);
-		  printf (_(" set discriminator to %u\n"), u128);
+		  fprintf (out, _(" set discriminator to %u\n"), u128);
 		  break;
 
 		case DW_LNE_NVIDIA_inlined_call:
@@ -9593,9 +9621,9 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 		    else
 		      function_str = (char *) str_data->d_buf + function_name;
 
-		    printf (_(" set inlined context %u,"
-		              " function name %s (0x%x)\n"),
-			    context, function_str, function_name);
+		    fprintf (out, _(" set inlined context %u,"
+		               " function name %s (0x%x)\n"),
+			     context, function_str, function_name);
 		    break;
 		  }
 
@@ -9617,14 +9645,14 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 		    else
 		      function_str = (char *) str_data->d_buf + function_name;
 
-		    printf (_(" set function name %s (0x%x)\n"),
-			    function_str, function_name);
+		    fprintf (out, _(" set function name %s (0x%x)\n"),
+			     function_str, function_name);
 		  }
 		  break;
 
 		default:
 		  /* Unknown, ignore it.  */
-		  puts (_(" unknown opcode"));
+		  fputs (_(" unknown opcode\n"), out);
 		  linep += len - 1;
 		  break;
 		}
@@ -9636,7 +9664,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 		{
 		case DW_LNS_copy:
 		  /* Takes no argument.  */
-		  puts (_(" copy"));
+		  fputs (_(" copy\n"), out);
 		  break;
 
 		case DW_LNS_advance_pc:
@@ -9647,12 +9675,12 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 		  get_uleb128 (u128, linep, lineendp);
 		  advance_pc (u128);
 		  {
-		    printf (_(" advance address by %u to "),
-			    op_addr_advance);
-		    print_dwarf_addr (dwflmod, 0, address, address);
+		    fprintf (out, _(" advance address by %u to "),
+			     op_addr_advance);
+		    print_dwarf_addr (dwflmod, 0, address, address, out);
 		    if (op_index > 0)
-		      printf (_(", op_index to %u"), op_index);
-		    printf ("\n");
+		      fprintf (out, _(", op_index to %u"), op_index);
+		    fprintf (out, "\n");
 		  }
 		  break;
 
@@ -9663,9 +9691,9 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 		    goto invalid_unit;
 		  get_sleb128 (s128, linep, lineendp);
 		  line += s128;
-		  printf (_("\
+		  fprintf (out, _("\
  advance line by constant %d to %" PRId64 "\n"),
-			  s128, (int64_t) line);
+			   s128, (int64_t) line);
 		  break;
 
 		case DW_LNS_set_file:
@@ -9673,8 +9701,8 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 		  if (lineendp - linep < 1)
 		    goto invalid_unit;
 		  get_uleb128 (u128, linep, lineendp);
-		  printf (_(" set file to %" PRIu64 "\n"),
-			  (uint64_t) u128);
+		  fprintf (out, _(" set file to %" PRIu64 "\n"),
+			   (uint64_t) u128);
 		  break;
 
 		case DW_LNS_set_column:
@@ -9684,20 +9712,20 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 		    goto invalid_unit;
 
 		  get_uleb128 (u128, linep, lineendp);
-		  printf (_(" set column to %" PRIu64 "\n"),
-			  (uint64_t) u128);
+		  fprintf (out, _(" set column to %" PRIu64 "\n"),
+			   (uint64_t) u128);
 		  break;
 
 		case DW_LNS_negate_stmt:
 		  /* Takes no argument.  */
 		  is_stmt = 1 - is_stmt;
-		  printf (_(" set '%s' to %" PRIuFAST8 "\n"),
-			  "is_stmt", is_stmt);
+		  fprintf (out, _(" set '%s' to %" PRIuFAST8 "\n"),
+			   "is_stmt", is_stmt);
 		  break;
 
 		case DW_LNS_set_basic_block:
 		  /* Takes no argument.  */
-		  puts (_(" set basic block flag"));
+		  fputs (_(" set basic block flag\n"), out);
 		  break;
 
 		case DW_LNS_const_add_pc:
@@ -9708,12 +9736,12 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 
 		  advance_pc ((255 - opcode_base) / line_range);
 		  {
-		    printf (_(" advance address by constant %u to "),
-			    op_addr_advance);
-		    print_dwarf_addr (dwflmod, 0, address, address);
+		    fprintf (out, _(" advance address by constant %u to "),
+			     op_addr_advance);
+		    print_dwarf_addr (dwflmod, 0, address, address, out);
 		    if (op_index > 0)
-		      printf (_(", op_index to %u"), op_index);
-		    printf ("\n");
+		      fprintf (out, _(", op_index to %u"), op_index);
+		    fprintf (out, "\n");
 		  }
 		  break;
 
@@ -9728,22 +9756,22 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 		  address += u128;
 		  op_index = 0;
 		  {
-		    printf (_("\
+		    fprintf (out, _("\
  advance address by fixed value %u to \n"),
-			    u128);
-		    print_dwarf_addr (dwflmod, 0, address, address);
-		    printf ("\n");
+			     u128);
+		    print_dwarf_addr (dwflmod, 0, address, address, out);
+		    fprintf (out, "\n");
 		  }
 		  break;
 
 		case DW_LNS_set_prologue_end:
 		  /* Takes no argument.  */
-		  puts (_(" set prologue end flag"));
+		  fputs (_(" set prologue end flag\n"), out);
 		  break;
 
 		case DW_LNS_set_epilogue_begin:
 		  /* Takes no argument.  */
-		  puts (_(" set epilogue begin flag"));
+		  fputs (_(" set epilogue begin flag\n"), out);
 		  break;
 
 		case DW_LNS_set_isa:
@@ -9753,7 +9781,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 		    goto invalid_unit;
 
 		  get_uleb128 (u128, linep, lineendp);
-		  printf (_(" set isa to %u\n"), u128);
+		  fprintf (out, _(" set isa to %u\n"), u128);
 		  break;
 		}
 	    }
@@ -9762,17 +9790,18 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 	      /* This is a new opcode the generator but not we know about.
 		 Read the parameters associated with it but then discard
 		 everything.  Read all the parameters for this opcode.  */
-	      printf (ngettext (" unknown opcode with %" PRIu8 " parameter:",
-				" unknown opcode with %" PRIu8 " parameters:",
-				standard_opcode_lengths[opcode]),
-		      standard_opcode_lengths[opcode]);
+	      fprintf (out,
+		       ngettext (" unknown opcode with %" PRIu8 " parameter:",
+				 " unknown opcode with %" PRIu8 " parameters:",
+				 standard_opcode_lengths[opcode]),
+		       standard_opcode_lengths[opcode]);
 	      for (int n = standard_opcode_lengths[opcode];
 		   n > 0 && linep < lineendp; --n)
 		{
 		  get_uleb128 (u128, linep, lineendp);
 		  if (n != standard_opcode_lengths[opcode])
-		    fputc (',', stdout);
-		  printf (" %u", u128);
+		    fputc (',', out);
+		  fprintf (out, " %u", u128);
 		}
 
 	      /* Next round, ignore this opcode.  */
@@ -9791,16 +9820,16 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
 			      Ebl *ebl,
 			      GElf_Ehdr *ehdr __attribute__ ((unused)),
 			      Elf_Scn *scn, GElf_Shdr *shdr,
-			      Dwarf *dbg)
+			      Dwarf *dbg, FILE *out)
 {
   Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_loclists, scn);
   if (data == NULL)
     return;
 
-  printf (_("\
+  fprintf (out, _("\
 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
-	  elf_ndxscn (scn), section_name (ebl, shdr),
-	  (uint64_t) shdr->sh_offset);
+	   elf_ndxscn (scn), section_name (ebl, shdr),
+	   (uint64_t) shdr->sh_offset);
 
   /* For the listptr to get the base address/CU.  */
   sort_listptr (&known_loclistsptr, "loclistsptr");
@@ -9820,8 +9849,8 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
 	}
 
       ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
-      printf (_("Table at Offset 0x%" PRIx64 ":\n\n"),
-	      (uint64_t) offset);
+      fprintf (out, _("Table at Offset 0x%" PRIx64 ":\n\n"),
+	       (uint64_t) offset);
 
       uint64_t unit_length = read_4ubyte_unaligned_inc (dbg, readp);
       unsigned int offset_size = 4;
@@ -9833,7 +9862,7 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
 	  unit_length = read_8ubyte_unaligned_inc (dbg, readp);
 	  offset_size = 8;
 	}
-      printf (_(" Length:         %8" PRIu64 "\n"), unit_length);
+      fprintf (out, _(" Length:         %8" PRIu64 "\n"), unit_length);
 
       /* We need at least 2-bytes + 1-byte + 1-byte + 4-bytes = 8
 	 bytes to complete the header.  And this unit cannot go beyond
@@ -9846,7 +9875,7 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
       const unsigned char *nexthdr = readp + unit_length;
 
       uint16_t version = read_2ubyte_unaligned_inc (dbg, readp);
-      printf (_(" DWARF version:  %8" PRIu16 "\n"), version);
+      fprintf (out, _(" DWARF version:  %8" PRIu16 "\n"), version);
 
       if (version != 5)
 	{
@@ -9855,8 +9884,8 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
 	}
 
       uint8_t address_size = *readp++;
-      printf (_(" Address size:   %8" PRIu64 "\n"),
-	      (uint64_t) address_size);
+      fprintf (out, _(" Address size:   %8" PRIu64 "\n"),
+	       (uint64_t) address_size);
 
       if (address_size != 4 && address_size != 8)
 	{
@@ -9865,8 +9894,8 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
 	}
 
       uint8_t segment_size = *readp++;
-      printf (_(" Segment size:   %8" PRIu64 "\n"),
-	      (uint64_t) segment_size);
+      fprintf (out, _(" Segment size:   %8" PRIu64 "\n"),
+	       (uint64_t) segment_size);
 
       if (segment_size != 0)
         {
@@ -9875,8 +9904,8 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
         }
 
       uint32_t offset_entry_count = read_4ubyte_unaligned_inc (dbg, readp);
-      printf (_(" Offset entries: %8" PRIu64 "\n"),
-	      (uint64_t) offset_entry_count);
+      fprintf (out, _(" Offset entries: %8" PRIu64 "\n"),
+	       (uint64_t) offset_entry_count);
 
       /* We need the CU that uses this unit to get the initial base address. */
       Dwarf_Addr cu_base = 0;
@@ -9891,17 +9920,17 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
 	  if (dwarf_cu_die (cu, &cudie,
 			    NULL, NULL, NULL, NULL,
 			    NULL, NULL) == NULL)
-	    printf (_(" Unknown CU base: "));
+	    fprintf (out, _(" Unknown CU base: "));
 	  else
-	    printf (_(" CU [%6" PRIx64 "] base: "),
-		    dwarf_dieoffset (&cudie));
-	  print_dwarf_addr (dwflmod, address_size, cu_base, cu_base);
-	  printf ("\n");
+	    fprintf (out, _(" CU [%6" PRIx64 "] base: "),
+		     dwarf_dieoffset (&cudie));
+	  print_dwarf_addr (dwflmod, address_size, cu_base, cu_base, out);
+	  fprintf (out, "\n");
 	}
       else
-	printf (_(" Not associated with a CU.\n"));
+	fprintf (out, _(" Not associated with a CU.\n"));
 
-      printf ("\n");
+      fprintf (out, "\n");
 
       const unsigned char *offset_array_start = readp;
       if (offset_entry_count > 0)
@@ -9914,24 +9943,24 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
 	      offset_entry_count = max_entries;
 	    }
 
-	  printf (_("  Offsets starting at 0x%" PRIx64 ":\n"),
-		  (uint64_t) (offset_array_start
-			      - (unsigned char *) data->d_buf));
+	  fprintf (out, _("  Offsets starting at 0x%" PRIx64 ":\n"),
+		   (uint64_t) (offset_array_start
+			       - (unsigned char *) data->d_buf));
 	  for (uint32_t idx = 0; idx < offset_entry_count; idx++)
 	    {
-	      printf ("   [%6" PRIu32 "] ", idx);
+	      fprintf (out, "   [%6" PRIu32 "] ", idx);
 	      if (offset_size == 4)
 		{
 		  uint32_t off = read_4ubyte_unaligned_inc (dbg, readp);
-		  printf ("0x%" PRIx32 "\n", off);
+		  fprintf (out, "0x%" PRIx32 "\n", off);
 		}
 	      else
 		{
 		  uint64_t off = read_8ubyte_unaligned_inc (dbg, readp);
-		  printf ("0x%" PRIx64 "\n", off);
+		  fprintf (out, "0x%" PRIx64 "\n", off);
 		}
 	    }
-	  printf ("\n");
+	  fprintf (out, "\n");
 	}
 
       Dwarf_Addr base = cu_base;
@@ -9953,9 +9982,9 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
 	      else
 		locendp = (const unsigned char *) data->d_buf + next_off;
 
-	      printf ("  Offset: %" PRIx64 ", Index: %" PRIx64 "\n",
-		      (uint64_t) (readp - (unsigned char *) data->d_buf),
-		      (uint64_t) (readp - offset_array_start));
+	      fprintf (out, "  Offset: %" PRIx64 ", Index: %" PRIx64 "\n",
+		       (uint64_t) (readp - (unsigned char *) data->d_buf),
+		       (uint64_t) (readp - offset_array_start));
 
 	      while (locp < locendp)
 		{
@@ -9963,14 +9992,15 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
 		  get_uleb128 (v1, locp, locendp);
 		  if (locp >= locendp)
 		    {
-		      printf (_("    <INVALID DATA>\n"));
+		      fprintf (out, _("    <INVALID DATA>\n"));
 		      break;
 		    }
 		  get_uleb128 (v2, locp, locendp);
-		  printf ("    view pair %" PRId64 ", %" PRId64 "\n", v1, v2);
+		  fprintf (out,
+			   "    view pair %" PRId64 ", %" PRId64 "\n", v1, v2);
 		}
 
-	      printf ("\n");
+	      fprintf (out, "\n");
 	      readp = (unsigned char *) locendp;
 	      continue;
 	    }
@@ -9985,18 +10015,18 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
 	  if (start_of_list)
 	    {
 	      base = cu_base;
-	      printf ("  Offset: %" PRIx64 ", Index: %" PRIx64 "\n",
-		      (uint64_t) (readp - (unsigned char *) data->d_buf - 1),
-		      (uint64_t) (readp - offset_array_start - 1));
+	      fprintf (out, "  Offset: %" PRIx64 ", Index: %" PRIx64 "\n",
+		       (uint64_t) (readp - (unsigned char *) data->d_buf - 1),
+		       (uint64_t) (readp - offset_array_start - 1));
 	      start_of_list = false;
 	    }
 
-	  printf ("    %s", dwarf_loc_list_encoding_name (kind));
+	  fprintf (out, "    %s", dwarf_loc_list_encoding_name (kind));
 	  switch (kind)
 	    {
 	    case DW_LLE_end_of_list:
 	      start_of_list = true;
-	      printf ("\n\n");
+	      fprintf (out, "\n\n");
 	      break;
 
 	    case DW_LLE_base_addressx:
@@ -10007,17 +10037,17 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
 		  goto next_table;
 		}
 	      get_uleb128 (op1, readp, nexthdr);
-	      printf (" %" PRIx64 "\n", op1);
+	      fprintf (out, " %" PRIx64 "\n", op1);
 	      if (! print_unresolved_addresses)
 		{
 		  Dwarf_Addr addr;
 		  if (get_indexed_addr (cu, op1, &addr) != 0)
-		    printf ("      ???\n");
+		    fprintf (out, "      ???\n");
 		  else
 		    {
-		      printf ("      ");
-		      print_dwarf_addr (dwflmod, address_size, addr, addr);
-		      printf ("\n");
+		      fprintf (out, "      ");
+		      print_dwarf_addr (dwflmod, address_size, addr, addr, out);
+		      fprintf (out, "\n");
 		    }
 		}
 	      break;
@@ -10029,7 +10059,7 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
 	      if ((uint64_t) (nexthdr - readp) < 1)
 		goto invalid_entry;
 	      get_uleb128 (op2, readp, nexthdr);
-	      printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
+	      fprintf (out, " %" PRIx64 ", %" PRIx64 "\n", op1, op2);
 	      if (! print_unresolved_addresses)
 		{
 		  Dwarf_Addr addr1;
@@ -10037,17 +10067,18 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
 		  if (get_indexed_addr (cu, op1, &addr1) != 0
 		      || get_indexed_addr (cu, op2, &addr2) != 0)
 		    {
-		      printf ("      ???..\n");
-		      printf ("      ???\n");
+		      fprintf (out, "      ???..\n");
+		      fprintf (out, "      ???\n");
 		    }
 		  else
 		    {
-		      printf ("      ");
-		      print_dwarf_addr (dwflmod, address_size, addr1, addr1);
-		      printf ("..\n      ");
+		      fprintf (out, "      ");
+		      print_dwarf_addr (dwflmod, address_size,
+					addr1, addr1, out);
+		      fprintf (out, "..\n      ");
 		      print_dwarf_addr (dwflmod, address_size,
-					addr2 - 1, addr2);
-		      printf ("\n");
+					addr2 - 1, addr2, out);
+		      fprintf (out, "\n");
 		    }
 		}
 	      if ((uint64_t) (nexthdr - readp) < 1)
@@ -10056,7 +10087,7 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
 	      if ((uint64_t) (nexthdr - readp) < len)
 		goto invalid_entry;
 	      print_ops (dwflmod, dbg, 8, 8, version,
-			 address_size, offset_size, cu, len, readp);
+			 address_size, offset_size, cu, len, readp, out);
 	      readp += len;
 	      break;
 
@@ -10067,25 +10098,25 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
 	      if ((uint64_t) (nexthdr - readp) < 1)
 		goto invalid_entry;
 	      get_uleb128 (op2, readp, nexthdr);
-	      printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
+	      fprintf (out, " %" PRIx64 ", %" PRIx64 "\n", op1, op2);
 	      if (! print_unresolved_addresses)
 		{
 		  Dwarf_Addr addr1;
 		  Dwarf_Addr addr2;
 		  if (get_indexed_addr (cu, op1, &addr1) != 0)
 		    {
-		      printf ("      ???..\n");
-		      printf ("      ???\n");
+		      fprintf (out, "      ???..\n");
+		      fprintf (out, "      ???\n");
 		    }
 		  else
 		    {
 		      addr2 = addr1 + op2;
-		      printf ("      ");
-		      print_dwarf_addr (dwflmod, address_size, addr1, addr1);
-		      printf ("..\n      ");
+		      fprintf (out, "      ");
+		      print_dwarf_addr (dwflmod, address_size, addr1, addr1, out);
+		      fprintf (out, "..\n      ");
 		      print_dwarf_addr (dwflmod, address_size,
-					addr2 - 1, addr2);
-		      printf ("\n");
+					addr2 - 1, addr2, out);
+		      fprintf (out, "\n");
 		    }
 		}
 	      if ((uint64_t) (nexthdr - readp) < 1)
@@ -10094,7 +10125,7 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
 	      if ((uint64_t) (nexthdr - readp) < len)
 		goto invalid_entry;
 	      print_ops (dwflmod, dbg, 8, 8, version,
-			 address_size, offset_size, cu, len, readp);
+			 address_size, offset_size, cu, len, readp, out);
 	      readp += len;
 	      break;
 
@@ -10105,16 +10136,16 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
 	      if ((uint64_t) (nexthdr - readp) < 1)
 		goto invalid_entry;
 	      get_uleb128 (op2, readp, nexthdr);
-	      printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
+	      fprintf (out, " %" PRIx64 ", %" PRIx64 "\n", op1, op2);
 	      if (! print_unresolved_addresses)
 		{
 		  op1 += base;
 		  op2 += base;
-		  printf ("      ");
-		  print_dwarf_addr (dwflmod, address_size, op1, op1);
-		  printf ("..\n      ");
-		  print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
-		  printf ("\n");
+		  fprintf (out, "      ");
+		  print_dwarf_addr (dwflmod, address_size, op1, op1, out);
+		  fprintf (out, "..\n      ");
+		  print_dwarf_addr (dwflmod, address_size, op2 - 1, op2, out);
+		  fprintf (out, "\n");
 		}
 	      if ((uint64_t) (nexthdr - readp) < 1)
 		goto invalid_entry;
@@ -10122,7 +10153,7 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
 	      if ((uint64_t) (nexthdr - readp) < len)
 		goto invalid_entry;
 	      print_ops (dwflmod, dbg, 8, 8, version,
-			 address_size, offset_size, cu, len, readp);
+			 address_size, offset_size, cu, len, readp, out);
 	      readp += len;
 	      break;
 
@@ -10133,7 +10164,7 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
 	      if ((uint64_t) (nexthdr - readp) < len)
 		goto invalid_entry;
 	      print_ops (dwflmod, dbg, 8, 8, version,
-			 address_size, offset_size, cu, len, readp);
+			 address_size, offset_size, cu, len, readp, out);
 	      readp += len;
 	      break;
 
@@ -10151,12 +10182,12 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
 		  op1 = read_8ubyte_unaligned_inc (dbg, readp);
 		}
 	      base = op1;
-	      printf (" 0x%" PRIx64 "\n", base);
+	      fprintf (out, " 0x%" PRIx64 "\n", base);
 	      if (! print_unresolved_addresses)
 		{
-		  printf ("      ");
-		  print_dwarf_addr (dwflmod, address_size, base, base);
-		  printf ("\n");
+		  fprintf (out, "      ");
+		  print_dwarf_addr (dwflmod, address_size, base, base, out);
+		  fprintf (out, "\n");
 		}
 	      break;
 
@@ -10175,14 +10206,14 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
 		  op1 = read_8ubyte_unaligned_inc (dbg, readp);
 		  op2 = read_8ubyte_unaligned_inc (dbg, readp);
 		}
-	      printf (" 0x%" PRIx64 "..0x%" PRIx64 "\n", op1, op2);
+	      fprintf (out, " 0x%" PRIx64 "..0x%" PRIx64 "\n", op1, op2);
 	      if (! print_unresolved_addresses)
 		{
-		  printf ("      ");
-		  print_dwarf_addr (dwflmod, address_size, op1, op1);
-		  printf ("..\n      ");
-		  print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
-		  printf ("\n");
+		  fprintf (out, "      ");
+		  print_dwarf_addr (dwflmod, address_size, op1, op1, out);
+		  fprintf (out, "..\n      ");
+		  print_dwarf_addr (dwflmod, address_size, op2 - 1, op2, out);
+		  fprintf (out, "\n");
 		}
 	      if ((uint64_t) (nexthdr - readp) < 1)
 		goto invalid_entry;
@@ -10190,7 +10221,7 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
 	      if ((uint64_t) (nexthdr - readp) < len)
 		goto invalid_entry;
 	      print_ops (dwflmod, dbg, 8, 8, version,
-			 address_size, offset_size, cu, len, readp);
+			 address_size, offset_size, cu, len, readp, out);
 	      readp += len;
 	      break;
 
@@ -10210,15 +10241,15 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
 	      if ((uint64_t) (nexthdr - readp) < 1)
 		goto invalid_entry;
 	      get_uleb128 (op2, readp, nexthdr);
-	      printf (" 0x%" PRIx64 ", %" PRIx64 "\n", op1, op2);
+	      fprintf (out, " 0x%" PRIx64 ", %" PRIx64 "\n", op1, op2);
 	      if (! print_unresolved_addresses)
 		{
 		  op2 = op1 + op2;
-		  printf ("      ");
-		  print_dwarf_addr (dwflmod, address_size, op1, op1);
-		  printf ("..\n      ");
-		  print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
-		  printf ("\n");
+		  fprintf (out, "      ");
+		  print_dwarf_addr (dwflmod, address_size, op1, op1, out);
+		  fprintf (out, "..\n      ");
+		  print_dwarf_addr (dwflmod, address_size, op2 - 1, op2, out);
+		  fprintf (out, "\n");
 		}
 	      if ((uint64_t) (nexthdr - readp) < 1)
 		goto invalid_entry;
@@ -10226,7 +10257,7 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
 	      if ((uint64_t) (nexthdr - readp) < len)
 		goto invalid_entry;
 	      print_ops (dwflmod, dbg, 8, 8, version,
-			 address_size, offset_size, cu, len, readp);
+			 address_size, offset_size, cu, len, readp, out);
 	      readp += len;
 	      break;
 
@@ -10237,7 +10268,7 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
 	      if ((uint64_t) (nexthdr - readp) < 1)
 		goto invalid_entry;
 	      get_uleb128 (op2, readp, nexthdr);
-	      printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
+	      fprintf (out, " %" PRIx64 ", %" PRIx64 "\n", op1, op2);
 	      break;
 
 	    default:
@@ -10249,7 +10280,7 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
       if (readp != nexthdr)
 	{
           size_t padding = nexthdr - readp;
-          printf (_("   %zu padding bytes\n\n"), padding);
+          fprintf (out, _("   %zu padding bytes\n\n"), padding);
 	  readp = nexthdr;
 	}
     }
@@ -10259,16 +10290,17 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
 static void
 print_debug_loc_section (Dwfl_Module *dwflmod,
 			 Ebl *ebl, GElf_Ehdr *ehdr,
-			 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+			 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg,
+			 FILE *out)
 {
   Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_loc, scn);
   if (data == NULL)
     return;
 
-  printf (_("\
+  fprintf (out, _("\
 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
-	  elf_ndxscn (scn), section_name (ebl, shdr),
-	  (uint64_t) shdr->sh_offset);
+	   elf_ndxscn (scn), section_name (ebl, shdr),
+	   (uint64_t) shdr->sh_offset);
 
   sort_listptr (&known_locsptr, "loclistptr");
   size_t listptr_idx = 0;
@@ -10298,12 +10330,12 @@ print_debug_loc_section (Dwfl_Module *dwflmod,
 	if (dwarf_cu_die (cu, &cudie,
 			  NULL, NULL, NULL, NULL,
 			  NULL, NULL) == NULL)
-	  printf (_("\n Unknown CU base: "));
+	  fprintf (out, _("\n Unknown CU base: "));
 	else
-	  printf (_("\n CU [%6" PRIx64 "] base: "),
-		  dwarf_dieoffset (&cudie));
-	print_dwarf_addr (dwflmod, address_size, base, base);
-	printf ("\n");
+	  fprintf (out, _("\n CU [%6" PRIx64 "] base: "),
+		   dwarf_dieoffset (&cudie));
+	print_dwarf_addr (dwflmod, address_size, base, base, out);
+	fprintf (out, "\n");
        }
       last_cu = cu;
 
@@ -10326,15 +10358,15 @@ print_debug_loc_section (Dwfl_Module *dwflmod,
 	      get_uleb128 (v1, locp, locendp);
 	      if (locp >= locendp)
 		{
-		  printf (_(" [%6tx]  <INVALID DATA>\n"), offset);
+		  fprintf (out, _(" [%6tx]  <INVALID DATA>\n"), offset);
 		  break;
 		}
 	      get_uleb128 (v2, locp, locendp);
 	      if (first)		/* First view pair in a list.  */
-		printf (" [%6tx] ", offset);
+		fprintf (out, " [%6tx] ", offset);
 	      else
-		printf ("          ");
-	      printf ("view pair %" PRId64 ", %" PRId64 "\n", v1, v2);
+		fprintf (out, "          ");
+	      fprintf (out, "view pair %" PRId64 ", %" PRId64 "\n", v1, v2);
 	      first = false;
 	    }
 
@@ -10352,7 +10384,7 @@ print_debug_loc_section (Dwfl_Module *dwflmod,
 	  && unlikely (data->d_size - offset < (size_t) address_size * 2))
         {
 	invalid_data:
-	  printf (_(" [%6tx]  <INVALID DATA>\n"), offset);
+	  fprintf (out, _(" [%6tx]  <INVALID DATA>\n"), offset);
 	  break;
 	}
 
@@ -10433,20 +10465,20 @@ print_debug_loc_section (Dwfl_Module *dwflmod,
       if (begin == (Dwarf_Addr) -1l) /* Base address entry.  */
 	{
 	  if (first)
-	    printf (" [%6tx] ", offset);
+	    fprintf (out, " [%6tx] ", offset);
 	  else
-	    printf ("          ");
-	  puts (_("base address"));
-	  printf ("          ");
-	  print_dwarf_addr (dwflmod, address_size, end, end);
-	  printf ("\n");
+	    fprintf (out, "          ");
+	  fputs (_("base address\n"), out);
+	  fprintf (out, "          ");
+	  print_dwarf_addr (dwflmod, address_size, end, end, out);
+	  fprintf (out, "\n");
 	  base = end;
 	  first = false;
 	}
       else if (begin == 0 && end == 0) /* End of list entry.  */
 	{
 	  if (first)
-	    printf (_(" [%6tx] empty list\n"), offset);
+	    fprintf (out, _(" [%6tx] empty list\n"), offset);
 	  first = true;
 	}
       else
@@ -10455,31 +10487,31 @@ print_debug_loc_section (Dwfl_Module *dwflmod,
 	  uint_fast16_t len = read_2ubyte_unaligned_inc (dbg, readp);
 
 	  if (first)		/* First entry in a list.  */
-	    printf (" [%6tx] ", offset);
+	    fprintf (out, " [%6tx] ", offset);
 	  else
-	    printf ("          ");
+	    fprintf (out, "          ");
 
-	  printf ("range %" PRIx64 ", %" PRIx64 "\n", begin, end);
+	  fprintf (out, "range %" PRIx64 ", %" PRIx64 "\n", begin, end);
 	  if (! print_unresolved_addresses)
 	    {
 	      Dwarf_Addr dab = use_base ? base + begin : begin;
 	      Dwarf_Addr dae = use_base ? base + end : end;
-	      printf ("          ");
-	      print_dwarf_addr (dwflmod, address_size, dab, dab);
-	      printf ("..\n          ");
-	      print_dwarf_addr (dwflmod, address_size, dae - 1, dae);
-	      printf ("\n");
+	      fprintf (out, "          ");
+	      print_dwarf_addr (dwflmod, address_size, dab, dab, out);
+	      fprintf (out, "..\n          ");
+	      print_dwarf_addr (dwflmod, address_size, dae - 1, dae, out);
+	      fprintf (out, "\n");
 	    }
 
 	  if (endp - readp <= (ptrdiff_t) len)
 	    {
-	      fputs (_("   <INVALID DATA>\n"), stdout);
+	      fputs (_("   <INVALID DATA>\n"), out);
 	      break;
 	    }
 
 	  print_ops (dwflmod, dbg, 11, 11,
 		     cu != NULL ? cu->version : 3,
-		     address_size, offset_size, cu, len, readp);
+		     address_size, offset_size, cu, len, readp, out);
 
 	  first = false;
 	  readp += len;
@@ -10514,17 +10546,18 @@ static void
 print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 			     Ebl *ebl,
 			     GElf_Ehdr *ehdr __attribute__ ((unused)),
-			     Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+			     Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg,
+			     FILE *out)
 {
   Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_macinfo, scn);
   if (data == NULL)
     return;
 
-  printf (_("\
+  fprintf (out, _("\
 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
-	  elf_ndxscn (scn), section_name (ebl, shdr),
-	  (uint64_t) shdr->sh_offset);
-  fputc ('\n', stdout);
+	   elf_ndxscn (scn), section_name (ebl, shdr),
+	   (uint64_t) shdr->sh_offset);
+  fputc ('\n', out);
 
   /* There is no function in libdw to iterate over the raw content of
      the section but it is easy enough to do.  */
@@ -10604,20 +10637,20 @@ print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	  endp = memchr (readp, '\0', readendp - readp);
 	  if (unlikely (endp == NULL))
 	    {
-	      printf (_("\
+	      fprintf (out, _("\
 %*s*** non-terminated string at end of section"),
-		      level, "");
+		       level, "");
 	      return;
 	    }
 
 	  if (opcode == DW_MACINFO_define)
-	    printf ("%*s#define %s, line %u\n",
-		    level, "", (char *) readp, u128);
+	    fprintf (out, "%*s#define %s, line %u\n",
+		     level, "", (char *) readp, u128);
 	  else if (opcode == DW_MACINFO_undef)
-	    printf ("%*s#undef %s, line %u\n",
-		    level, "", (char *) readp, u128);
+	    fprintf (out, "%*s#undef %s, line %u\n",
+		     level, "", (char *) readp, u128);
 	  else
-	    printf (" #vendor-ext %s, number %u\n", (char *) readp, u128);
+	    fprintf (out, " #vendor-ext %s, number %u\n", (char *) readp, u128);
 
 	  readp = endp + 1;
 	  break;
@@ -10627,9 +10660,9 @@ print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	  get_uleb128 (u128, readp, readendp);
 	  if (readendp - readp < 1)
 	    {
-	      printf (_("\
+	      fprintf (out, _("\
 %*s*** missing DW_MACINFO_start_file argument at end of section"),
-		      level, "");
+		       level, "");
 	      return;
 	    }
 	  get_uleb128 (u128_2, readp, readendp);
@@ -10651,21 +10684,21 @@ print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 			 ?: "???");
 	    }
 
-	  printf ("%*sstart_file %u, [%u] %s\n",
-		  level, "", u128, u128_2, fname);
+	  fprintf (out, "%*sstart_file %u, [%u] %s\n",
+		   level, "", u128, u128_2, fname);
 	  ++level;
 	  break;
 
 	case DW_MACINFO_end_file:
 	  --level;
-	  printf ("%*send_file\n", level, "");
+	  fprintf (out, "%*send_file\n", level, "");
 	  /* Nothing more to do.  */
 	  break;
 
 	default:
 	  // XXX gcc seems to generate files with a trailing zero.
 	  if (unlikely (opcode != 0 || readp != readendp))
-	    printf ("%*s*** invalid opcode %u\n", level, "", opcode);
+	    fprintf (out, "%*s*** invalid opcode %u\n", level, "", opcode);
 	  break;
 	}
     }
@@ -10676,17 +10709,18 @@ static void
 print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 			   Ebl *ebl,
 			   GElf_Ehdr *ehdr __attribute__ ((unused)),
-			   Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+			   Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg,
+			   FILE *out)
 {
   Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_macro, scn);
   if (data == NULL)
     return;
 
-  printf (_("\
+  fprintf (out, _("\
 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
-	  elf_ndxscn (scn), section_name (ebl, shdr),
-	  (uint64_t) shdr->sh_offset);
-  fputc ('\n', stdout);
+	   elf_ndxscn (scn), section_name (ebl, shdr),
+	   (uint64_t) shdr->sh_offset);
+  fputc ('\n', out);
 
   /* Get the source file information for all CUs.  Uses same
      datastructure as macinfo.  But uses offset field to directly
@@ -10722,8 +10756,8 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 
   while (readp < readendp)
     {
-      printf (_(" Offset:             0x%" PRIx64 "\n"),
-	      (uint64_t) (readp - (const unsigned char *) data->d_buf));
+      fprintf (out, _(" Offset:             0x%" PRIx64 "\n"),
+	       (uint64_t) (readp - (const unsigned char *) data->d_buf));
 
       // Header, 2 byte version, 1 byte flag, optional .debug_line offset,
       // optional vendor extension macro entry table.
@@ -10734,49 +10768,49 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	  return;
 	}
       const uint16_t vers = read_2ubyte_unaligned_inc (dbg, readp);
-      printf (_(" Version:            %" PRIu16 "\n"), vers);
+      fprintf (out, _(" Version:            %" PRIu16 "\n"), vers);
 
       // Version 4 is the GNU extension for DWARF4.  DWARF5 will use version
       // 5 when it gets standardized.
       if (vers != 4 && vers != 5)
 	{
-	  printf (_("  unknown version, cannot parse section\n"));
+	  fprintf (out, _("  unknown version, cannot parse section\n"));
 	  return;
 	}
 
       if (readp + 1 > readendp)
 	goto invalid_data;
       const unsigned char flag = *readp++;
-      printf (_(" Flag:               0x%" PRIx8), flag);
+      fprintf (out, _(" Flag:               0x%" PRIx8), flag);
       if (flag != 0)
 	{
-	  printf (" (");
+	  fprintf (out, " (");
 	  if ((flag & 0x01) != 0)
 	    {
-	      printf ("offset_size");
+	      fprintf (out, "offset_size");
 	      if ((flag & 0xFE) !=  0)
-		printf (", ");
+		fprintf (out, ", ");
 	    }
 	  if ((flag & 0x02) != 0)
 	    {
-	      printf ("debug_line_offset");
+	      fprintf (out, "debug_line_offset");
 	      if ((flag & 0xFC) !=  0)
-		printf (", ");
+		fprintf (out, ", ");
 	    }
 	  if ((flag & 0x04) != 0)
 	    {
-	      printf ("operands_table");
+	      fprintf (out, "operands_table");
 	      if ((flag & 0xF8) !=  0)
-		printf (", ");
+		fprintf (out, ", ");
 	    }
 	  if ((flag & 0xF8) != 0)
-	    printf ("unknown");
-	  printf (")");
+	    fprintf (out, "unknown");
+	  fprintf (out, ")");
 	}
-      printf ("\n");
+      fprintf (out, "\n");
 
       unsigned int offset_len = (flag & 0x01) ? 8 : 4;
-      printf (_(" Offset length:      %" PRIu8 "\n"), offset_len);
+      fprintf (out, _(" Offset length:      %" PRIu8 "\n"), offset_len);
       Dwarf_Off line_offset = -1;
       if (flag & 0x02)
 	{
@@ -10784,8 +10818,8 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	    line_offset = read_8ubyte_unaligned_inc (dbg, readp);
 	  else
 	    line_offset = read_4ubyte_unaligned_inc (dbg, readp);
-	  printf (_(" .debug_line offset: 0x%" PRIx64 "\n"),
-		  line_offset);
+	  fprintf (out, _(" .debug_line offset: 0x%" PRIx64 "\n"),
+		   line_offset);
 	}
 
       struct mac_culist *cu = NULL;
@@ -10809,14 +10843,14 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	  if (readp + 1 > readendp)
 	    goto invalid_data;
 	  unsigned int tlen = *readp++;
-	  printf (_("  extension opcode table, %" PRIu8 " items:\n"),
-		  tlen);
+	  fprintf (out, _("  extension opcode table, %" PRIu8 " items:\n"),
+		   tlen);
 	  for (unsigned int i = 0; i < tlen; i++)
 	    {
 	      if (readp + 1 > readendp)
 		goto invalid_data;
 	      unsigned int opcode = *readp++;
-	      printf (_("    [%" PRIx8 "]"), opcode);
+	      fprintf (out, _("    [%" PRIx8 "]"), opcode);
 	      if (opcode < DW_MACRO_lo_user
 		  || opcode > DW_MACRO_hi_user)
 		goto invalid_data;
@@ -10828,26 +10862,26 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	      unsigned int args = *readp++;
 	      if (args > 0)
 		{
-		  printf (_(" %" PRIu8 " arguments:"), args);
+		  fprintf (out, _(" %" PRIu8 " arguments:"), args);
 		  while (args > 0)
 		    {
 		      if (readp + 1 > readendp)
 			goto invalid_data;
 		      unsigned int form = *readp++;
-		      printf (" %s", dwarf_form_name (form));
+		      fprintf (out, " %s", dwarf_form_name (form));
 		      if (! libdw_valid_user_form (form))
 			goto invalid_data;
 		      args--;
 		      if (args > 0)
-			putchar (',');
+			fputc (',', out);
 		    }
 		}
 	      else
-		printf (_(" no arguments."));
-	      putchar ('\n');
+		fprintf (out, _(" no arguments."));
+	      fputc ('\n', out);
 	    }
 	}
-      putchar ('\n');
+      fputc ('\n', out);
 
       int level = 1;
       if (readp + 1 > readendp)
@@ -10881,14 +10915,14 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 		    fname = (dwarf_filesrc (cu->files, u128_2,
 					    NULL, NULL) ?: "???");
 		}
-	      printf ("%*sstart_file %u, [%u] %s\n",
-		      level, "", u128, u128_2, fname);
+	      fprintf (out, "%*sstart_file %u, [%u] %s\n",
+		       level, "", u128, u128_2, fname);
 	      ++level;
 	      break;
 
 	    case DW_MACRO_end_file:
 	      --level;
-	      printf ("%*send_file\n", level, "");
+	      fprintf (out, "%*send_file\n", level, "");
 	      break;
 
 	    case DW_MACRO_define:
@@ -10896,8 +10930,8 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	      endp = memchr (readp, '\0', readendp - readp);
 	      if (endp == NULL)
 		goto invalid_data;
-	      printf ("%*s#define %s, line %u\n",
-		      level, "", readp, u128);
+	      fprintf (out, "%*s#define %s, line %u\n",
+		       level, "", readp, u128);
 	      readp = endp + 1;
 	      break;
 
@@ -10906,8 +10940,8 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	      endp = memchr (readp, '\0', readendp - readp);
 	      if (endp == NULL)
 		goto invalid_data;
-	      printf ("%*s#undef %s, line %u\n",
-		      level, "", readp, u128);
+	      fprintf (out, "%*s#undef %s, line %u\n",
+		       level, "", readp, u128);
 	      readp = endp + 1;
 	      break;
 
@@ -10919,8 +10953,8 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 		off = read_8ubyte_unaligned_inc (dbg, readp);
 	      else
 		off = read_4ubyte_unaligned_inc (dbg, readp);
-	      printf ("%*s#define %s, line %u (indirect)\n",
-		      level, "", dwarf_getstring (dbg, off, NULL), u128);
+	      fprintf (out, "%*s#define %s, line %u (indirect)\n",
+		       level, "", dwarf_getstring (dbg, off, NULL), u128);
 	      break;
 
 	    case DW_MACRO_undef_strp:
@@ -10931,8 +10965,8 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 		off = read_8ubyte_unaligned_inc (dbg, readp);
 	      else
 		off = read_4ubyte_unaligned_inc (dbg, readp);
-	      printf ("%*s#undef %s, line %u (indirect)\n",
-		      level, "", dwarf_getstring (dbg, off, NULL), u128);
+	      fprintf (out, "%*s#undef %s, line %u (indirect)\n",
+		       level, "", dwarf_getstring (dbg, off, NULL), u128);
 	      break;
 
 	    case DW_MACRO_import:
@@ -10942,26 +10976,26 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 		off = read_8ubyte_unaligned_inc (dbg, readp);
 	      else
 		off = read_4ubyte_unaligned_inc (dbg, readp);
-	      printf ("%*s#include offset 0x%" PRIx64 "\n",
-		      level, "", off);
+	      fprintf (out, "%*s#include offset 0x%" PRIx64 "\n",
+		       level, "", off);
 	      break;
 
 	    case DW_MACRO_define_sup:
 	      get_uleb128 (u128, readp, readendp);
-	      printf ("%*s#define ", level, "");
+	      fprintf (out, "%*s#define ", level, "");
 	      readp =  print_form_data (dbg, DW_FORM_strp_sup,
 					readp, readendp, offset_len,
-					str_offsets_base);
-	      printf (", line %u (sup)\n", u128);
+					str_offsets_base, out);
+	      fprintf (out, ", line %u (sup)\n", u128);
 	      break;
 
 	    case DW_MACRO_undef_sup:
 	      get_uleb128 (u128, readp, readendp);
-	      printf ("%*s#undef ", level, "");
+	      fprintf (out, "%*s#undef ", level, "");
 	      readp =  print_form_data (dbg, DW_FORM_strp_sup,
 					readp, readendp, offset_len,
-					str_offsets_base);
-	      printf (", line %u (sup)\n", u128);
+					str_offsets_base, out);
+	      fprintf (out, ", line %u (sup)\n", u128);
 	      break;
 
 	    case DW_MACRO_import_sup:
@@ -10972,30 +11006,30 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	      else
 		off = read_4ubyte_unaligned_inc (dbg, readp);
 	      // XXX Needs support for reading from supplementary object file.
-	      printf ("%*s#include offset 0x%" PRIx64 " (sup)\n",
-		      level, "", off);
+	      fprintf (out, "%*s#include offset 0x%" PRIx64 " (sup)\n",
+		       level, "", off);
 	      break;
 
 	    case DW_MACRO_define_strx:
 	      get_uleb128 (u128, readp, readendp);
-	      printf ("%*s#define ", level, "");
+	      fprintf (out, "%*s#define ", level, "");
 	      readp =  print_form_data (dbg, DW_FORM_strx,
 					readp, readendp, offset_len,
-					str_offsets_base);
-	      printf (", line %u (strx)\n", u128);
+					str_offsets_base, out);
+	      fprintf (out, ", line %u (strx)\n", u128);
 	      break;
 
 	    case DW_MACRO_undef_strx:
 	      get_uleb128 (u128, readp, readendp);
-	      printf ("%*s#undef ", level, "");
+	      fprintf (out, "%*s#undef ", level, "");
 	      readp =  print_form_data (dbg, DW_FORM_strx,
 					readp, readendp, offset_len,
-					str_offsets_base);
-	      printf (", line %u (strx)\n", u128);
+					str_offsets_base, out);
+	      fprintf (out, ", line %u (strx)\n", u128);
 	      break;
 
 	    default:
-	      printf ("%*svendor opcode 0x%" PRIx8, level, "", opcode);
+	      fprintf (out, "%*svendor opcode 0x%" PRIx8, level, "", opcode);
 	      if (opcode < DW_MACRO_lo_user
 		  || opcode > DW_MACRO_lo_user
 		  || vendor[opcode - DW_MACRO_lo_user] == NULL)
@@ -11011,34 +11045,39 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 		{
 		  unsigned int form = *op_desc++;
 		  readp = print_form_data (dbg, form, readp, readendp,
-					   offset_len, str_offsets_base);
+					   offset_len, str_offsets_base, out);
 		  args--;
 		  if (args > 0)
-		    printf (", ");
+		    fprintf (out, ", ");
 		}
-	      putchar ('\n');
+	      fputc ('\n', out);
 	    }
 
 	  if (readp + 1 > readendp)
 	    goto invalid_data;
 	  opcode = *readp++;
 	  if (opcode == 0)
-	    putchar ('\n');
+	    fputc ('\n', out);
 	}
     }
 }
 
 
+typedef struct {
+  int n;
+  FILE *out;
+} pubnames_arg;
+
 /* Callback for printing global names.  */
 static int
 print_pubnames (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global,
 		void *arg)
 {
-  int *np = (int *) arg;
+  pubnames_arg *p = (pubnames_arg *) arg;
 
-  printf (_(" [%5d] DIE offset: %6" PRId64
-		   ", CU DIE offset: %6" PRId64 ", name: %s\n"),
-	  (*np)++, global->die_offset, global->cu_offset, global->name);
+  fprintf (p->out, _(" [%5d] DIE offset: %6" PRId64
+		    ", CU DIE offset: %6" PRId64 ", name: %s\n"),
+	   (p->n)++, global->die_offset, global->cu_offset, global->name);
 
   return 0;
 }
@@ -11049,18 +11088,19 @@ static void
 print_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 			      Ebl *ebl,
 			      GElf_Ehdr *ehdr __attribute__ ((unused)),
-			      Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+			      Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg,
+			      FILE *out)
 {
   /* Check section actually exists.  */
   if (get_debug_elf_data (dbg, ebl, IDX_debug_pubnames, scn) == NULL)
       return;
 
-  printf (_("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
-	  elf_ndxscn (scn), section_name (ebl, shdr),
-	  (uint64_t) shdr->sh_offset);
+  fprintf (out, _("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
+	   elf_ndxscn (scn), section_name (ebl, shdr),
+	   (uint64_t) shdr->sh_offset);
 
-  int n = 0;
-  (void) dwarf_getpubnames (dbg, print_pubnames, &n, 0);
+  pubnames_arg arg = { 0, out };
+  (void) dwarf_getpubnames (dbg, print_pubnames, &arg, 0);
 }
 
 /* Print the content of the DWARF string section '.debug_str'
@@ -11070,7 +11110,8 @@ print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 			 Ebl *ebl,
 			 GElf_Ehdr *ehdr __attribute__ ((unused)),
 			 Elf_Scn *scn, GElf_Shdr *shdr,
-			 Dwarf *dbg __attribute__ ((unused)))
+			 Dwarf *dbg __attribute__ ((unused)),
+			 FILE *out)
 {
   const char *name = section_name (ebl, shdr);
   int idx = ((name != NULL && strstr (name, "debug_line_str") != NULL)
@@ -11091,12 +11132,12 @@ print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
     }
   digits = MAX (4, digits);
 
-  printf (_("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
-		   " %*s  String\n"),
-	  elf_ndxscn (scn),
-	  section_name (ebl, shdr), (uint64_t) shdr->sh_offset,
-	  /* TRANS: the debugstr| prefix makes the string unique.  */
-	  digits + 2, sgettext ("debugstr|Offset"));
+  fprintf (out, _("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
+		  " %*s  String\n"),
+	   elf_ndxscn (scn),
+	   section_name (ebl, shdr), (uint64_t) shdr->sh_offset,
+	   /* TRANS: the debugstr| prefix makes the string unique.  */
+	   digits + 2, sgettext ("debugstr|Offset"));
 
   Dwarf_Off offset = 0;
   while (offset < sh_size)
@@ -11106,11 +11147,12 @@ print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
       const char *endp = memchr (str, '\0', sh_size - offset);
       if (unlikely (endp == NULL))
 	{
-	  printf (_(" *** error, missing string terminator\n"));
+	  fprintf (out, _(" *** error, missing string terminator\n"));
 	  break;
 	}
 
-      printf (" [%*" PRIx64 "]  \"%s\"\n", digits, (uint64_t) offset, str);
+      fprintf (out, " [%*" PRIx64 "]  \"%s\"\n",
+	       digits, (uint64_t) offset, str);
       len = endp - str;
       offset += len + 1;
     }
@@ -11120,16 +11162,17 @@ static void
 print_debug_str_offsets_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 				 Ebl *ebl,
 				 GElf_Ehdr *ehdr __attribute__ ((unused)),
-				 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+				 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg,
+				 FILE *out)
 {
   Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_str_offsets, scn);
   if (data == NULL)
     return;
 
-  printf (_("\
+  fprintf (out, _("\
 \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
-	  elf_ndxscn (scn), section_name (ebl, shdr),
-	  (uint64_t) shdr->sh_offset);
+	   elf_ndxscn (scn), section_name (ebl, shdr),
+	   (uint64_t) shdr->sh_offset);
 
   if (shdr->sh_size == 0)
     return;
@@ -11154,7 +11197,7 @@ print_debug_str_offsets_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
       Dwarf_Off off = (Dwarf_Off) (readp
 				   - (const unsigned char *) data->d_buf);
 
-      printf ("Table at offset %" PRIx64 " ", off);
+      fprintf (out, "Table at offset %" PRIx64 " ", off);
 
       struct listptr *listptr = get_listptr (&known_stroffbases, idx++);
       const unsigned char *next_unitp = readendp;
@@ -11189,7 +11232,7 @@ print_debug_str_offsets_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	      has_header = cu->version > 4;
 	      offset_size = cu->offset_size;
 	    }
-	  printf ("\n");
+	  fprintf (out, "\n");
 	}
       else
 	{
@@ -11201,9 +11244,9 @@ print_debug_str_offsets_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	  if (dwarf_cu_die (listptr->cu, &cudie,
 			    NULL, NULL, NULL, NULL,
 			    NULL, NULL) == NULL)
-	    printf ("Unknown CU (%s):\n", dwarf_errmsg (-1));
+	    fprintf (out, "Unknown CU (%s):\n", dwarf_errmsg (-1));
 	  else
-	    printf ("for CU [%6" PRIx64 "]:\n", dwarf_dieoffset (&cudie));
+	    fprintf (out, "for CU [%6" PRIx64 "]:\n", dwarf_dieoffset (&cudie));
 	}
 
       if (has_header)
@@ -11227,11 +11270,11 @@ print_debug_str_offsets_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	  else
 	    offset_size = 4;
 
-	  printf ("\n");
-	  printf (_(" Length:        %8" PRIu64 "\n"),
-		  unit_length);
-	  printf (_(" Offset size:   %8" PRIu8 "\n"),
-		  offset_size);
+	  fprintf (out, "\n");
+	  fprintf (out, _(" Length:        %8" PRIu64 "\n"),
+		   unit_length);
+	  fprintf (out, _(" Offset size:   %8" PRIu8 "\n"),
+		   offset_size);
 
 	  /* We need at least 2-bytes (version) + 2-bytes (padding) =
 	     4 bytes to complete the header.  And this unit cannot go
@@ -11244,7 +11287,7 @@ print_debug_str_offsets_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	  next_unitp = readp + unit_length;
 
 	  version = read_2ubyte_unaligned_inc (dbg, readp);
-	  printf (_(" DWARF version: %8" PRIu16 "\n"), version);
+	  fprintf (out, _(" DWARF version: %8" PRIu16 "\n"), version);
 
 	  if (version != 5)
 	    {
@@ -11253,7 +11296,7 @@ print_debug_str_offsets_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	    }
 
 	  padding = read_2ubyte_unaligned_inc (dbg, readp);
-	  printf (_(" Padding:       %8" PRIx16 "\n"), padding);
+	  fprintf (out, _(" Padding:       %8" PRIx16 "\n"), padding);
 
 	  if (listptr != NULL
 	      && listptr->offset != (Dwarf_Off) (readp - start))
@@ -11262,7 +11305,7 @@ print_debug_str_offsets_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	      goto next_unit;
 	    }
 
-	  printf ("\n");
+	  fprintf (out, "\n");
 	}
 
       int digits = 1;
@@ -11275,7 +11318,7 @@ print_debug_str_offsets_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 
       unsigned int uidx = 0;
       size_t index_offset =  readp - (const unsigned char *) data->d_buf;
-      printf (" Offsets start at 0x%zx:\n", index_offset);
+      fprintf (out, " Offsets start at 0x%zx:\n", index_offset);
       while (readp <= next_unitp - offset_size)
 	{
 	  Dwarf_Word offset;
@@ -11284,10 +11327,10 @@ print_debug_str_offsets_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	  else
 	    offset = read_8ubyte_unaligned_inc (dbg, readp);
 	  const char *str = dwarf_getstring (dbg, offset, NULL);
-	  printf (" [%*u] [%*" PRIx64 "]  \"%s\"\n",
-		  digits, uidx++, (int) offset_size * 2, offset, str ?: "???");
+	  fprintf (out, " [%*u] [%*" PRIx64 "]  \"%s\"\n",
+		   digits, uidx++, (int) offset_size * 2, offset, str ?: "???");
 	}
-      printf ("\n");
+      fprintf (out, "\n");
 
       if (readp != next_unitp)
 	error (0, 0, "extra %zd bytes at end of unit",
@@ -11305,11 +11348,12 @@ static void
 print_debug_frame_hdr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 			       Ebl *ebl __attribute__ ((unused)),
 			       GElf_Ehdr *ehdr __attribute__ ((unused)),
-			       Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+			       Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg,
+			       FILE *out)
 {
-  printf (_("\
+  fprintf (out, _("\
 \nCall frame search table section [%2zu] '.eh_frame_hdr':\n"),
-	  elf_ndxscn (scn));
+	   elf_ndxscn (scn));
 
   Elf_Data *data = elf_rawdata (scn, NULL);
 
@@ -11336,14 +11380,14 @@ print_debug_frame_hdr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
   unsigned int fde_count_enc = *readp++;
   unsigned int table_enc = *readp++;
 
-  printf (" version:          %u\n"
-	  " eh_frame_ptr_enc: %#x ",
-	  version, eh_frame_ptr_enc);
-  print_encoding_base ("", eh_frame_ptr_enc);
-  printf (" fde_count_enc:    %#x ", fde_count_enc);
-  print_encoding_base ("", fde_count_enc);
-  printf (" table_enc:        %#x ", table_enc);
-  print_encoding_base ("", table_enc);
+  fprintf (out, " version:          %u\n"
+	   " eh_frame_ptr_enc: %#x ",
+	   version, eh_frame_ptr_enc);
+  print_encoding_base ("", eh_frame_ptr_enc, out);
+  fprintf (out, " fde_count_enc:    %#x ", fde_count_enc);
+  print_encoding_base ("", fde_count_enc, out);
+  fprintf (out, " table_enc:        %#x ", table_enc);
+  print_encoding_base ("", table_enc, out);
 
   uint64_t eh_frame_ptr = 0;
   if (eh_frame_ptr_enc != DW_EH_PE_omit)
@@ -11353,13 +11397,13 @@ print_debug_frame_hdr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
       if (unlikely (readp == NULL))
 	goto invalid_data;
 
-      printf (" eh_frame_ptr:     %#" PRIx64, eh_frame_ptr);
+      fprintf (out, " eh_frame_ptr:     %#" PRIx64, eh_frame_ptr);
       if ((eh_frame_ptr_enc & 0x70) == DW_EH_PE_pcrel)
-	printf (" (offset: %#" PRIx64 ")",
-		/* +4 because of the 4 byte header of the section.  */
-		(uint64_t) shdr->sh_offset + 4 + eh_frame_ptr);
+	fprintf (out, " (offset: %#" PRIx64 ")",
+		 /* +4 because of the 4 byte header of the section.  */
+		 (uint64_t) shdr->sh_offset + 4 + eh_frame_ptr);
 
-      putchar ('\n');
+      fputc ('\n', out);
     }
 
   uint64_t fde_count = 0;
@@ -11369,13 +11413,13 @@ print_debug_frame_hdr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
       if (unlikely (readp == NULL))
 	goto invalid_data;
 
-      printf (" fde_count:        %" PRIu64 "\n", fde_count);
+      fprintf (out, " fde_count:        %" PRIu64 "\n", fde_count);
     }
 
   if (fde_count == 0 || table_enc == DW_EH_PE_omit)
     return;
 
-  puts (" Table:");
+  fputs (" Table:\n", out);
 
   /* Optimize for the most common case.  */
   if (table_enc == (DW_EH_PE_datarel | DW_EH_PE_sdata4))
@@ -11386,10 +11430,10 @@ print_debug_frame_hdr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 				   + (int64_t) initial_location);
 	int32_t address = read_4sbyte_unaligned_inc (dbg, readp);
 	// XXX Possibly print symbol name or section offset for initial_offset
-	printf ("  %#" PRIx32 " (offset: %#6" PRIx64 ") -> %#" PRIx32
-		" fde=[%6" PRIx64 "]\n",
-		initial_location, initial_offset,
-		address, address - (eh_frame_ptr + 4));
+	fprintf (out, "  %#" PRIx32 " (offset: %#6" PRIx64 ") -> %#" PRIx32
+		 " fde=[%6" PRIx64 "]\n",
+		 initial_location, initial_offset,
+		 address, address - (eh_frame_ptr + 4));
       }
   else
     while (0 && readp < dataend)
@@ -11407,11 +11451,12 @@ print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
 			     GElf_Ehdr *ehdr __attribute__ ((unused)),
 			     Elf_Scn *scn,
 			     GElf_Shdr *shdr __attribute__ ((unused)),
-			     Dwarf *dbg __attribute__ ((unused)))
+			     Dwarf *dbg __attribute__ ((unused)),
+			     FILE *out)
 {
-  printf (_("\
-\nException handling table section [%2zu] '.gcc_except_table':\n"),
-	  elf_ndxscn (scn));
+  fprintf (out, _("\
+ \nException handling table section [%2zu] '.gcc_except_table':\n"),
+	   elf_ndxscn (scn));
 
   Elf_Data *data = elf_rawdata (scn, NULL);
 
@@ -11432,20 +11477,20 @@ print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
       return;
     }
   unsigned int lpstart_encoding = *readp++;
-  printf (_(" LPStart encoding:    %#x "), lpstart_encoding);
-  print_encoding_base ("", lpstart_encoding);
+  fprintf (out, _(" LPStart encoding:    %#x "), lpstart_encoding);
+  print_encoding_base ("", lpstart_encoding, out);
   if (lpstart_encoding != DW_EH_PE_omit)
     {
       uint64_t lpstart;
       readp = read_encoded (lpstart_encoding, readp, dataend, &lpstart, dbg);
-      printf (" LPStart:             %#" PRIx64 "\n", lpstart);
+      fprintf (out, " LPStart:             %#" PRIx64 "\n", lpstart);
     }
 
   if (unlikely (readp + 1 > dataend))
     goto invalid_data;
   unsigned int ttype_encoding = *readp++;
-  printf (_(" TType encoding:      %#x "), ttype_encoding);
-  print_encoding_base ("", ttype_encoding);
+  fprintf (out, _(" TType encoding:      %#x "), ttype_encoding);
+  print_encoding_base ("", ttype_encoding, out);
   const unsigned char *ttype_base = NULL;
   if (ttype_encoding != DW_EH_PE_omit)
     {
@@ -11453,7 +11498,7 @@ print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
       if (readp >= dataend)
 	goto invalid_data;
       get_uleb128 (ttype_base_offset, readp, dataend);
-      printf (" TType base offset:   %#x\n", ttype_base_offset);
+      fprintf (out, " TType base offset:   %#x\n", ttype_base_offset);
       if ((size_t) (dataend - readp) > ttype_base_offset)
         ttype_base = readp + ttype_base_offset;
     }
@@ -11461,8 +11506,8 @@ print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
   if (unlikely (readp + 1 > dataend))
     goto invalid_data;
   unsigned int call_site_encoding = *readp++;
-  printf (_(" Call site encoding:  %#x "), call_site_encoding);
-  print_encoding_base ("", call_site_encoding);
+  fprintf (out, _(" Call site encoding:  %#x "), call_site_encoding);
+  print_encoding_base ("", call_site_encoding, out);
   unsigned int call_site_table_len;
   if (readp >= dataend)
     goto invalid_data;
@@ -11476,7 +11521,7 @@ print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
   while (readp < action_table)
     {
       if (u == 0)
-	puts (_("\n Call site table:"));
+	fputs (_("\n Call site table:"), out);
 
       uint64_t call_site_start;
       readp = read_encoded (call_site_encoding, readp, dataend,
@@ -11492,11 +11537,11 @@ print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	goto invalid_data;
       get_uleb128 (action, readp, dataend);
       max_action = MAX (action, max_action);
-      printf (_(" [%4u] Call site start:   %#" PRIx64 "\n"
-		       "        Call site length:  %" PRIu64 "\n"
-		       "        Landing pad:       %#" PRIx64 "\n"
-		       "        Action:            %u\n"),
-	      u++, call_site_start, call_site_length, landing_pad, action);
+      fprintf (out, _(" [%4u] Call site start:   %#" PRIx64 "\n"
+		        "        Call site length:  %" PRIu64 "\n"
+		        "        Landing pad:       %#" PRIx64 "\n"
+		        "        Action:            %u\n"),
+	       u++, call_site_start, call_site_length, landing_pad, action);
     }
   if (readp != action_table)
     goto invalid_data;
@@ -11504,7 +11549,7 @@ print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
   unsigned int max_ar_filter = 0;
   if (max_action > 0)
     {
-      puts ("\n Action table:");
+      fputs ("\n Action table:", out);
 
       size_t maxdata = (size_t) (dataend - action_table);
       if (max_action > maxdata || maxdata - max_action < 1)
@@ -11529,15 +11574,15 @@ print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	    goto invalid_action_table;
 	  get_sleb128 (ar_disp, readp, action_table_end);
 
-	  printf (" [%4u] ar_filter:  % d\n"
-		  "        ar_disp:    % -5d",
-		  u, ar_filter, ar_disp);
+	  fprintf (out, " [%4u] ar_filter:  % d\n"
+		   "        ar_disp:    % -5d",
+		   u, ar_filter, ar_disp);
 	  if (abs (ar_disp) & 1)
-	    printf (" -> [%4u]\n", u + (ar_disp + 1) / 2);
+	    fprintf (out, " -> [%4u]\n", u + (ar_disp + 1) / 2);
 	  else if (ar_disp != 0)
-	    puts (" -> ???");
+	    fputs (" -> ???", out);
 	  else
-	    putchar ('\n');
+	    fputc ('\n', out);
 	  ++u;
 	}
       while (readp < action_table_end);
@@ -11546,7 +11591,7 @@ print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
   if (max_ar_filter > 0 && ttype_base != NULL)
     {
       unsigned char dsize;
-      puts ("\n TType table:");
+      fputs ("\n TType table:", out);
 
       // XXX Not *4, size of encoding;
       switch (ttype_encoding & 7)
@@ -11578,7 +11623,7 @@ print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	  uint64_t ttype;
 	  readp = read_encoded (ttype_encoding, readp, ttype_base, &ttype,
 				dbg);
-	  printf (" [%4u] %#" PRIx64 "\n", max_ar_filter--, ttype);
+	  fprintf (out, " [%4u] %#" PRIx64 "\n", max_ar_filter--, ttype);
 	}
       while (readp < ttype_base);
     }
@@ -11590,12 +11635,13 @@ print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
 static void
 print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl,
 			 GElf_Ehdr *ehdr __attribute__ ((unused)),
-			 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+			 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg,
+			 FILE *out)
 {
-  printf (_("\nGDB section [%2zu] '%s' at offset %#" PRIx64
-		   " contains %" PRId64 " bytes :\n"),
-	  elf_ndxscn (scn), section_name (ebl, shdr),
-	  (uint64_t) shdr->sh_offset, (uint64_t) shdr->sh_size);
+  fprintf (out, _("\nGDB section [%2zu] '%s' at offset %#" PRIx64
+		    " contains %" PRId64 " bytes :\n"),
+	   elf_ndxscn (scn), section_name (ebl, shdr),
+	   (uint64_t) shdr->sh_offset, (uint64_t) shdr->sh_size);
 
   Elf_Data *data = elf_rawdata (scn, NULL);
 
@@ -11621,7 +11667,7 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl,
     }
 
   int32_t vers = read_4ubyte_unaligned (dbg, readp);
-  printf (_(" Version:         %" PRId32 "\n"), vers);
+  fprintf (out, _(" Version:         %" PRId32 "\n"), vers);
 
   // The only difference between version 4 and version 5 is the
   // hash used for generating the table.  Version 6 contains symbols
@@ -11631,7 +11677,7 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl,
   // regarding the main function.
   if (vers < 4 || vers > 9)
     {
-      printf (_("  unknown version, cannot parse section\n"));
+      fprintf (out, _("  unknown version, cannot parse section\n"));
       return;
     }
 
@@ -11640,28 +11686,28 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl,
     goto invalid_data;
 
   uint32_t cu_off = read_4ubyte_unaligned (dbg, readp);
-  printf (_(" CU offset:       %#" PRIx32 "\n"), cu_off);
+  fprintf (out, _(" CU offset:       %#" PRIx32 "\n"), cu_off);
 
   readp += 4;
   if (unlikely (readp + 4 > dataend))
     goto invalid_data;
 
   uint32_t tu_off = read_4ubyte_unaligned (dbg, readp);
-  printf (_(" TU offset:       %#" PRIx32 "\n"), tu_off);
+  fprintf (out, _(" TU offset:       %#" PRIx32 "\n"), tu_off);
 
   readp += 4;
   if (unlikely (readp + 4 > dataend))
     goto invalid_data;
 
   uint32_t addr_off = read_4ubyte_unaligned (dbg, readp);
-  printf (_(" address offset:  %#" PRIx32 "\n"), addr_off);
+  fprintf (out, _(" address offset:  %#" PRIx32 "\n"), addr_off);
 
   readp += 4;
   if (unlikely (readp + 4 > dataend))
     goto invalid_data;
 
   uint32_t sym_off = read_4ubyte_unaligned (dbg, readp);
-  printf (_(" symbol offset:   %#" PRIx32 "\n"), sym_off);
+  fprintf (out, _(" symbol offset:   %#" PRIx32 "\n"), sym_off);
 
   readp += 4;
   if (unlikely (readp + 4 > dataend))
@@ -11671,7 +11717,7 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl,
   if (vers >= 9)
     {
       shortcut_off = read_4ubyte_unaligned (dbg, readp);
-      printf (_(" shortcut offset: %#" PRIx32 "\n"), shortcut_off);
+      fprintf (out, _(" shortcut offset: %#" PRIx32 "\n"), shortcut_off);
 
       readp += 4;
       if (unlikely (readp + 4 > dataend))
@@ -11679,7 +11725,7 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl,
     }
 
   uint32_t const_off = read_4ubyte_unaligned (dbg, readp);
-  printf (_(" constant offset: %#" PRIx32 "\n"), const_off);
+  fprintf (out, _(" constant offset: %#" PRIx32 "\n"), const_off);
 
   if (unlikely ((size_t) (dataend - (const unsigned char *) data->d_buf)
 		< const_off))
@@ -11693,9 +11739,9 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl,
 
   size_t cu_nr = (nextp - readp) / 16;
 
-  printf (_("\n CU list at offset %#" PRIx32
-		   " contains %zu entries:\n"),
-	  cu_off, cu_nr);
+  fprintf (out, _("\n CU list at offset %#" PRIx32
+		    " contains %zu entries:\n"),
+	   cu_off, cu_nr);
 
   size_t n = 0;
   while (dataend - readp >= 16 && n < cu_nr)
@@ -11706,8 +11752,8 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl,
       uint64_t len = read_8ubyte_unaligned (dbg, readp);
       readp += 8;
 
-      printf (" [%4zu] start: %0#8" PRIx64
-	      ", length: %5" PRIu64 "\n", n, off, len);
+      fprintf (out, " [%4zu] start: %0#8" PRIx64
+	       ", length: %5" PRIu64 "\n", n, off, len);
       n++;
     }
 
@@ -11718,9 +11764,9 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl,
 
   size_t tu_nr = (nextp - readp) / 24;
 
-  printf (_("\n TU list at offset %#" PRIx32
-		   " contains %zu entries:\n"),
-	  tu_off, tu_nr);
+  fprintf (out, _("\n TU list at offset %#" PRIx32
+		    " contains %zu entries:\n"),
+	   tu_off, tu_nr);
 
   n = 0;
   while (dataend - readp >= 24 && n < tu_nr)
@@ -11734,9 +11780,9 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl,
       uint64_t sig = read_8ubyte_unaligned (dbg, readp);
       readp += 8;
 
-      printf (" [%4zu] CU offset: %5" PRId64
-	      ", type offset: %5" PRId64
-	      ", signature: %0#8" PRIx64 "\n", n, off, type, sig);
+      fprintf (out, " [%4zu] CU offset: %5" PRId64
+	       ", type offset: %5" PRId64
+	       ", signature: %0#8" PRIx64 "\n", n, off, type, sig);
       n++;
     }
 
@@ -11747,9 +11793,9 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl,
 
   size_t addr_nr = (nextp - readp) / 20;
 
-  printf (_("\n Address list at offset %#" PRIx32
-		   " contains %zu entries:\n"),
-	  addr_off, addr_nr);
+  fprintf (out, _("\n Address list at offset %#" PRIx32
+		    " contains %zu entries:\n"),
+	   addr_off, addr_nr);
 
   n = 0;
   while (dataend - readp >= 20 && n < addr_nr)
@@ -11763,11 +11809,11 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl,
       uint32_t idx = read_4ubyte_unaligned (dbg, readp);
       readp += 4;
 
-      printf (" [%4zu] ", n);
-      print_dwarf_addr (dwflmod, 8, low, low);
-      printf ("..");
-      print_dwarf_addr (dwflmod, 8, high - 1, high);
-      printf (", CU index: %5" PRId32 "\n", idx);
+      fprintf (out, " [%4zu] ", n);
+      print_dwarf_addr (dwflmod, 8, low, low, out);
+      fprintf (out, "..");
+      print_dwarf_addr (dwflmod, 8, high - 1, high, out);
+      fprintf (out, ", CU index: %5" PRId32 "\n", idx);
       n++;
     }
 
@@ -11790,9 +11836,9 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl,
   readp = data->d_buf + sym_off;
   size_t sym_nr = (nextp - readp) / 8;
 
-  printf (_("\n Symbol table at offset %#" PRIx32
-		   " contains %zu slots:\n"),
-	  sym_off, sym_nr);
+  fprintf (out, _("\n Symbol table at offset %#" PRIx32
+		    " contains %zu slots:\n"),
+	   sym_off, sym_nr);
 
   n = 0;
   while (dataend - readp >= 8 && n < sym_nr)
@@ -11810,7 +11856,7 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl,
 			|| memchr (sym, '\0', dataend - sym) == NULL))
 	    goto invalid_data;
 
-	  printf (" [%4zu] symbol: %s, CUs: ", n, sym);
+	  fprintf (out, " [%4zu] symbol: %s, CUs: ", n, sym);
 
 	  const unsigned char *readcus = const_start + vector;
 	  if (unlikely ((size_t) (dataend - const_start) < vector))
@@ -11828,36 +11874,36 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl,
 	      kind = (cu_kind >> 28) & 7;
 	      is_static = cu_kind & (1U << 31);
 	      if (cu > cu_nr - 1)
-		printf ("%" PRId32 "T", cu - (uint32_t) cu_nr);
+		fprintf (out, "%" PRId32 "T", cu - (uint32_t) cu_nr);
 	      else
-		printf ("%" PRId32, cu);
+		fprintf (out, "%" PRId32, cu);
 	      if (kind != 0)
 		{
-		  printf (" (");
+		  fprintf (out, " (");
 		  switch (kind)
 		    {
 		    case 1:
-		      printf ("type");
+		      fprintf (out, "type");
 		      break;
 		    case 2:
-		      printf ("var");
+		      fprintf (out, "var");
 		      break;
 		    case 3:
-		      printf ("func");
+		      fprintf (out, "func");
 		      break;
 		    case 4:
-		      printf ("other");
+		      fprintf (out, "other");
 		      break;
 		    default:
-		      printf ("unknown-0x%" PRIx32, kind);
+		      fprintf (out, "unknown-0x%" PRIx32, kind);
 		      break;
 		    }
-		  printf (":%c)", (is_static ? 'S' : 'G'));
+		  fprintf (out, ":%c)", (is_static ? 'S' : 'G'));
 		}
 	      if (cus > 0)
-		printf (", ");
+		fprintf (out, ", ");
 	    }
-	  printf ("\n");
+	  fprintf (out, "\n");
 	}
       n++;
     }
@@ -11875,8 +11921,9 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl,
   if (unlikely (shortcut_nr != 2))
     goto invalid_data;
 
-  printf (_("\nShortcut table at offset %#" PRIx32 " contains %zu slots:\n"),
-	  shortcut_off, shortcut_nr);
+  fprintf (out,
+	   _("\nShortcut table at offset %#" PRIx32 " contains %zu slots:\n"),
+	   shortcut_off, shortcut_nr);
 
   uint32_t lang = read_4ubyte_unaligned (dbg, readp);
   readp += 4;
@@ -11887,8 +11934,8 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl,
   lang_str = string_or_unknown (lang_str, lang, DW_LANG_lo_user,
 				DW_LANG_hi_user, true);
 
-  printf (_("Language of main: %s\n"), lang_str);
-  printf (_("Name of main: "));
+  fprintf (out, _("Language of main: %s\n"), lang_str);
+  fprintf (out, _("Name of main: "));
 
   if (lang != 0)
     {
@@ -11900,10 +11947,10 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl,
 		    || memchr (sym, '\0', dataend - sym) == NULL))
 	goto invalid_data;
 
-      printf ("%s\n", sym);
+      fprintf (out, "%s\n", sym);
     }
   else
-    printf ("<unknown>\n");
+    fprintf (out, "<unknown>\n");
 }
 
 /* Returns true and sets split DWARF CU id if there is a split compile
@@ -12150,11 +12197,12 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
 		  || strcmp (name, ".gnu.debuglto_.debug_info") == 0)
 		{
 		  print_debug_info_section (dwflmod, ebl, ehdr,
-					    scn, shdr, dbg);
+					    scn, shdr, dbg, stdout);
 		  break;
 		}
 	    }
 	}
+
       print_debug_sections &= ~section_info;
       implicit_debug_sections &= ~section_info;
     }
@@ -12173,7 +12221,7 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
 	    const char *name;
 	    enum section_e bitmask;
 	    void (*fp) (Dwfl_Module *, Ebl *,
-			GElf_Ehdr *, Elf_Scn *, GElf_Shdr *, Dwarf *);
+			GElf_Ehdr *, Elf_Scn *, GElf_Shdr *, Dwarf *, FILE *);
 	  } debug_sections[] =
 	    {
 #define NEW_SECTION(name) \
@@ -12241,7 +12289,7 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
 		{
 		  if ((print_debug_sections | implicit_debug_sections)
 		      & debug_sections[n].bitmask)
-		    debug_sections[n].fp (dwflmod, ebl, ehdr, scn, shdr, dbg);
+		    debug_sections[n].fp (dwflmod, ebl, ehdr, scn, shdr, dbg, stdout);
 		  break;
 		}
 	    }
-- 
2.49.0



More information about the Elfutils-devel mailing list