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

Aaron Merey amerey@redhat.com
Thu May 22 22:28:54 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>
---
v2:
Minor change to print_dwarf_addr declaration so patch applies cleanly
to main branch.

 src/readelf.c | 2258 +++++++++++++++++++++++++------------------------
 1 file changed, 1157 insertions(+), 1101 deletions(-)

diff --git a/src/readelf.c b/src/readelf.c
index 38381156..8f233a77 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -361,7 +361,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
@@ -2609,7 +2609,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, NULL);
 		  printf (" *\n");
 
 		  base = entry + 4;
@@ -2622,7 +2622,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, NULL);
 			printf ("\n");
 		      }
 		  base += 4 * (4 * 8 - 1);
@@ -2648,7 +2648,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, NULL);
 		  printf (" *\n");
 
 		  base = entry + 8;
@@ -2661,7 +2661,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, NULL);
 			printf ("\n");
 		      }
 		  base += 8 * (8 * 8 - 1);
@@ -4369,8 +4369,12 @@ 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)
 {
+  if (out == NULL)
+    out = stdout;
+
   /* See if there is a name we can give for this address.  */
   GElf_Sym sym;
   GElf_Off off = 0;
@@ -4399,33 +4403,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"));
 }
 
@@ -4930,29 +4936,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, " ");
     }
 }
 
@@ -4985,13 +4991,17 @@ 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)
 {
+  if (out == NULL)
+    out = stdout;
+
   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;
     }
 
@@ -5029,10 +5039,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;
@@ -5050,9 +5060,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;
 
@@ -5062,9 +5072,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;
@@ -5073,9 +5083,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;
@@ -5084,9 +5094,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;
@@ -5095,9 +5105,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;
@@ -5106,9 +5116,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;
@@ -5117,9 +5127,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;
@@ -5128,9 +5138,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;
@@ -5139,9 +5149,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;
@@ -5155,8 +5165,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;
@@ -5168,16 +5178,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;
 
@@ -5188,8 +5198,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;
@@ -5201,8 +5211,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;
@@ -5213,17 +5223,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;
@@ -5231,9 +5241,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;
@@ -5242,9 +5252,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;
@@ -5254,10 +5264,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);
@@ -5279,9 +5289,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;
@@ -5292,11 +5302,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);
@@ -5314,9 +5324,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);
@@ -5333,8 +5343,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;
@@ -5350,9 +5360,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;
@@ -5364,9 +5374,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;
@@ -5382,8 +5392,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;
@@ -5395,8 +5405,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;
@@ -5404,8 +5414,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;
 	}
@@ -5414,8 +5424,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;
     }
 }
@@ -5813,7 +5823,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)
@@ -5821,16 +5832,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)
 	{
@@ -5842,9 +5853,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;
 		}
 
@@ -5858,11 +5869,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;
@@ -5872,11 +5883,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;
 	    }
 
@@ -5889,16 +5900,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;
@@ -5923,7 +5935,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;
@@ -5940,7 +5952,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
 	{
@@ -5948,9 +5960,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)
 	    {
@@ -5997,15 +6009,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
 	    {
@@ -6021,9 +6033,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
@@ -6037,7 +6049,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)
 		{
@@ -6046,8 +6058,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)
 		{
@@ -6056,9 +6068,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)
 		{
@@ -6084,16 +6096,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",
@@ -6109,7 +6121,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;
@@ -6130,13 +6142,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;
@@ -6152,7 +6164,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;
 	}
 
@@ -6161,13 +6173,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);
     }
 }
 
@@ -6176,11 +6188,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;
     }
 
@@ -6188,10 +6200,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;
@@ -6201,7 +6213,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:
@@ -6221,8 +6233,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;
@@ -6233,8 +6245,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"));
@@ -6248,14 +6260,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"));
@@ -6265,8 +6277,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"));
@@ -6303,24 +6315,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;
 	}
     }
@@ -6353,16 +6365,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");
@@ -6382,8 +6395,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;
@@ -6395,7 +6408,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
@@ -6408,7 +6421,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)
 	{
@@ -6417,8 +6430,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)
 	{
@@ -6427,8 +6440,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)
         {
@@ -6437,8 +6450,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;
@@ -6453,17 +6466,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)
@@ -6476,24 +6489,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;
@@ -6510,18 +6523,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:
@@ -6532,17 +6545,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;
@@ -6554,7 +6568,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;
@@ -6562,17 +6576,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;
@@ -6584,25 +6599,26 @@ 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;
@@ -6614,16 +6630,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;
 
@@ -6641,12 +6657,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;
 
@@ -6665,14 +6681,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;
 
@@ -6692,15 +6708,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;
 
@@ -6713,7 +6729,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;
 	}
     }
@@ -6724,16 +6740,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;
@@ -6761,18 +6777,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;
 	}
 
@@ -6794,40 +6810,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;
@@ -6941,11 +6957,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)
     {
@@ -6961,35 +6978,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)
@@ -6998,30 +7015,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)
@@ -7030,15 +7047,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)
@@ -7047,35 +7065,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:
@@ -7085,12 +7104,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:
@@ -7100,9 +7119,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)
@@ -7111,14 +7130,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)
@@ -7127,8 +7148,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)
@@ -7137,8 +7158,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)
@@ -7147,53 +7169,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));
     }
 }
 
@@ -7218,36 +7241,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.  */
@@ -7259,24 +7282,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;
@@ -7287,37 +7310,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.  */
@@ -7352,13 +7377,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
   {
@@ -7402,7 +7427,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;
 	}
 
@@ -7480,21 +7505,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')
 	    {
@@ -7515,20 +7540,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')
 		    {
@@ -7542,25 +7567,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;
 		}
@@ -7592,7 +7617,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;
 	    }
 
@@ -7622,13 +7647,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
@@ -7637,19 +7662,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')
 	    {
@@ -7681,9 +7706,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;
@@ -7691,7 +7716,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 = "";
 		    }
 		}
@@ -7702,11 +7727,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;
     }
 }
@@ -7751,6 +7777,7 @@ struct attrcb_args
   unsigned int addrsize;
   unsigned int offset_size;
   struct Dwarf_CU *cu;
+  FILE *out;
 };
 
 
@@ -7761,6 +7788,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))
@@ -7813,16 +7841,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;
 
@@ -7842,9 +7870,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:
@@ -7862,22 +7890,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:
@@ -7905,9 +7933,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;
@@ -7960,16 +7988,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;
@@ -7981,10 +8009,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;
 
@@ -8014,16 +8042,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;
@@ -8034,11 +8062,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;
 
@@ -8050,11 +8078,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;
 
@@ -8065,11 +8093,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;
 
@@ -8162,19 +8190,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
 	    {
@@ -8193,52 +8222,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;
 		}
 
@@ -8247,12 +8276,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;
@@ -8264,17 +8293,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:
@@ -8289,16 +8318,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;
@@ -8330,19 +8359,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;
@@ -8376,7 +8405,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;
 
@@ -8387,12 +8416,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)
@@ -8400,34 +8429,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;
@@ -8435,9 +8464,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;
     }
 
@@ -8448,7 +8477,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);
@@ -8461,9 +8490,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)
@@ -8531,35 +8560,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)
 		{
@@ -8568,10 +8597,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");
 	    }
 	}
     }
@@ -8600,6 +8629,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:
@@ -8628,11 +8658,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.  */
@@ -8706,18 +8736,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;
@@ -8740,28 +8770,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;
@@ -8776,8 +8809,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
@@ -8805,34 +8838,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;
 	    }
 
@@ -8853,20 +8887,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");
 	}
     }
 }
@@ -8877,7 +8911,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;
@@ -8893,42 +8927,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:
@@ -8937,7 +8971,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;
 
@@ -8947,7 +8981,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;
 
@@ -8957,7 +8991,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;
 
@@ -8967,14 +9001,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;
 
@@ -8982,14 +9016,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;
 
@@ -9016,7 +9050,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:
@@ -9026,7 +9060,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:
@@ -9063,7 +9097,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:
@@ -9117,11 +9151,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;
     }
 
@@ -9129,10 +9164,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;
@@ -9148,7 +9183,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;
@@ -9239,25 +9274,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)
 	{
@@ -9302,10 +9337,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))
@@ -9313,13 +9348,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++;
@@ -9336,13 +9371,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)
@@ -9355,16 +9390,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;
 	    }
@@ -9377,7 +9412,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;
 	    }
@@ -9390,13 +9425,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++;
@@ -9416,13 +9451,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)
@@ -9435,23 +9470,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.  */
@@ -9479,8 +9514,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;
@@ -9497,11 +9532,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;
@@ -9530,7 +9565,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))
 	    {
@@ -9550,15 +9585,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)
 	    {
@@ -9575,12 +9610,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;
@@ -9598,9 +9633,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;
 
@@ -9626,10 +9661,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;
 
@@ -9640,7 +9675,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:
@@ -9667,9 +9702,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;
 		  }
 
@@ -9691,14 +9726,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;
 		}
@@ -9710,7 +9745,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:
@@ -9721,12 +9756,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;
 
@@ -9737,9 +9772,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:
@@ -9747,8 +9782,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:
@@ -9758,20 +9793,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:
@@ -9782,12 +9817,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;
 
@@ -9802,22 +9837,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:
@@ -9827,7 +9862,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;
 		}
 	    }
@@ -9836,17 +9871,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.  */
@@ -9865,16 +9901,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");
@@ -9894,8 +9930,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;
@@ -9907,7 +9943,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
@@ -9920,7 +9956,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)
 	{
@@ -9929,8 +9965,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)
 	{
@@ -9939,8 +9975,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)
         {
@@ -9949,8 +9985,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;
@@ -9965,17 +10001,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)
@@ -9988,24 +10024,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;
@@ -10027,9 +10063,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)
 		{
@@ -10037,14 +10073,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;
 	    }
@@ -10059,18 +10096,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:
@@ -10081,17 +10118,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;
@@ -10103,7 +10140,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;
@@ -10111,17 +10148,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)
@@ -10130,7 +10168,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;
 
@@ -10141,25 +10179,26 @@ 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,
-					addr2 - 1, addr2);
-		      printf ("\n");
+					addr1, addr1, out);
+		      fprintf (out, "..\n      ");
+		      print_dwarf_addr (dwflmod, address_size,
+					addr2 - 1, addr2, out);
+		      fprintf (out, "\n");
 		    }
 		}
 	      if ((uint64_t) (nexthdr - readp) < 1)
@@ -10168,7 +10207,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;
 
@@ -10179,16 +10218,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;
@@ -10196,7 +10235,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;
 
@@ -10207,7 +10246,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;
 
@@ -10225,12 +10264,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;
 
@@ -10249,14 +10288,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;
@@ -10264,7 +10303,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;
 
@@ -10284,15 +10323,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;
@@ -10300,7 +10339,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;
 
@@ -10311,7 +10350,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:
@@ -10323,7 +10362,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;
 	}
     }
@@ -10333,16 +10372,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;
@@ -10372,12 +10412,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;
 
@@ -10400,15 +10440,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;
 	    }
 
@@ -10426,7 +10466,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;
 	}
 
@@ -10507,20 +10547,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
@@ -10529,31 +10569,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;
@@ -10588,17 +10628,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.  */
@@ -10678,20 +10719,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;
@@ -10701,9 +10742,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);
@@ -10725,21 +10766,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;
 	}
     }
@@ -10750,17 +10791,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
@@ -10796,8 +10838,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.
@@ -10808,49 +10850,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)
 	{
@@ -10858,8 +10900,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;
@@ -10883,14 +10925,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;
@@ -10902,26 +10944,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)
@@ -10955,14 +10997,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:
@@ -10970,8 +11012,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;
 
@@ -10980,8 +11022,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;
 
@@ -10993,8 +11035,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:
@@ -11005,8 +11047,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:
@@ -11016,26 +11058,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:
@@ -11046,30 +11088,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)
@@ -11085,34 +11127,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;
 }
@@ -11123,18 +11170,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'
@@ -11144,7 +11192,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)
@@ -11165,12 +11214,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)
@@ -11180,11 +11229,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;
     }
@@ -11194,16 +11244,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;
@@ -11228,7 +11279,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;
@@ -11263,7 +11314,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
 	{
@@ -11275,9 +11326,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)
@@ -11301,11 +11352,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
@@ -11318,7 +11369,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)
 	    {
@@ -11327,7 +11378,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))
@@ -11336,7 +11387,7 @@ print_debug_str_offsets_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	      goto next_unit;
 	    }
 
-	  printf ("\n");
+	  fprintf (out, "\n");
 	}
 
       int digits = 1;
@@ -11349,7 +11400,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;
@@ -11358,10 +11409,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",
@@ -11379,11 +11430,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);
 
@@ -11410,14 +11462,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)
@@ -11427,13 +11479,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;
@@ -11443,13 +11495,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))
@@ -11460,10 +11512,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)
@@ -11481,11 +11533,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);
 
@@ -11506,20 +11559,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)
     {
@@ -11527,7 +11580,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;
     }
@@ -11535,8 +11588,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;
@@ -11550,7 +11603,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,
@@ -11566,11 +11619,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;
@@ -11578,7 +11631,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)
@@ -11603,15 +11656,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);
@@ -11620,7 +11673,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)
@@ -11652,7 +11705,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);
     }
@@ -11664,12 +11717,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);
 
@@ -11695,7 +11749,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
@@ -11705,7 +11759,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;
     }
 
@@ -11714,28 +11768,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))
@@ -11745,7 +11799,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))
@@ -11753,7 +11807,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))
@@ -11767,9 +11821,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)
@@ -11780,8 +11834,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++;
     }
 
@@ -11792,9 +11846,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)
@@ -11808,9 +11862,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++;
     }
 
@@ -11821,9 +11875,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)
@@ -11837,11 +11891,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++;
     }
 
@@ -11864,9 +11918,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)
@@ -11884,7 +11938,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))
@@ -11902,36 +11956,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++;
     }
@@ -11949,8 +12003,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;
@@ -11961,8 +12016,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)
     {
@@ -11974,10 +12029,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
@@ -12286,11 +12341,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;
     }
@@ -12309,7 +12365,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) \
-- 
2.49.0



More information about the Elfutils-devel mailing list