struct bt_iter_pos *pos;
       int i = 0;
       enum target_xfer_status res;
+      /* Records the lowest available address of all blocks that
+        intersects the requested range.  */
+      ULONGEST low_addr_available = 0;
 
       gdb_assert (ctf_iter != NULL);
       /* Save the current position.  */
                }
            }
 
+         if (offset < maddr && maddr < (offset + len))
+           if (low_addr_available == 0 || low_addr_available > maddr)
+             low_addr_available = maddr;
+
          if (bt_iter_next (bt_ctf_get_iter (ctf_iter)) < 0)
            break;
        }
 
       /* Requested memory is unavailable in the context of traceframes,
         and this address falls within a read-only section, fallback
-        to reading from executable.  */
+        to reading from executable, up to LOW_ADDR_AVAILABLE  */
+      if (offset < low_addr_available)
+       len = min (len, low_addr_available - offset);
       res = exec_read_partial_read_only (readbuf, offset, len, xfered_len);
 
       if (res == TARGET_XFER_OK)
 
 proc gdb_collect_args_test {} {
     with_test_prefix "unavailable arguments" {
        global gdb_prompt
+       global testfile srcdir subdir binfile
+       global trace_file_targets
 
        prepare_for_trace_test
 
        gdb_test "tfind none" \
            "#0  end .*" \
            "cease trace debugging"
+
+       set tracefile [standard_output_file ${testfile}]
+       gdb_test "tsave ${tracefile}.args.tfile" \
+           "Trace data saved to file '${tracefile}.args.tfile'\.\\r" \
+           "tsave ${testfile}.args.tfile"
+       gdb_test "tsave -ctf ${tracefile}.args.ctf" \
+           "Trace data saved to directory '${tracefile}.args.ctf'\.\\r" \
+           "save ctf trace file"
+
+       foreach target_name ${trace_file_targets} {
+           # Restart GDB and read the trace data in ${TARGET_NAME} target.
+           gdb_exit
+           gdb_start
+           gdb_reinitialize_dir $srcdir/$subdir
+           gdb_file_cmd $binfile
+           gdb_test "target ${target_name} ${tracefile}.args.${target_name}" ".*" \
+               "change to ${target_name} target"
+
+           with_test_prefix "${target_name}" {
+               gdb_test "tfind start" "#0  args_test_func .*" \
+                   "tfind test frame"
+               gdb_collect_args_test_1
+           }
+       }
     }
 }
 
 proc gdb_collect_locals_test { func msg } {
     with_test_prefix "unavailable locals: $msg" {
        global gdb_prompt
+       global testfile srcdir subdir binfile
+       global trace_file_targets
 
        prepare_for_trace_test
 
        gdb_test "tfind none" \
            "#0  end .*" \
            "cease trace debugging"
+
+       set tracefile [standard_output_file ${testfile}]
+       gdb_test "tsave ${tracefile}.locals.tfile" \
+           "Trace data saved to file '${tracefile}.locals.tfile'\.\\r" \
+           "tsave ${testfile}.locals.tfile"
+       gdb_test "tsave -ctf ${tracefile}.locals.ctf" \
+           "Trace data saved to directory '${tracefile}.locals.ctf'\.\\r" \
+           "save ctf trace file"
+
+       foreach target_name ${trace_file_targets} {
+           # Restart GDB and read the trace data in ${TARGET_NAME} target.
+           gdb_exit
+           gdb_start
+           gdb_reinitialize_dir $srcdir/$subdir
+           gdb_file_cmd $binfile
+           gdb_test "target ${target_name} ${tracefile}.locals.${target_name}" ".*" \
+               "change to ${target_name} target"
+
+           with_test_prefix "${target_name}" {
+               gdb_test "tfind start" "#0  $func .*" \
+                   "tfind test frame"
+               gdb_collect_locals_test_1 $func
+           }
+       }
     }
 }
 
 
 proc gdb_unavailable_registers_test { } {
     with_test_prefix "unavailable registers" {
+       global testfile srcdir subdir binfile
+       global trace_file_targets
 
        prepare_for_trace_test
 
        gdb_unavailable_registers_test_1
 
        gdb_test "tfind none" "#0  end .*" "cease trace debugging"
+
+       set tracefile [standard_output_file ${testfile}]
+       gdb_test "tsave ${tracefile}.registers.tfile" \
+           "Trace data saved to file '${tracefile}.registers.tfile'\.\\r" \
+           "tsave ${testfile}.registers.tfile"
+       gdb_test "tsave -ctf ${tracefile}.registers.ctf" \
+           "Trace data saved to directory '${tracefile}.registers.ctf'\.\\r" \
+           "save ctf trace file"
+
+       foreach target_name ${trace_file_targets} {
+           # Restart GDB and read the trace data in ${TARGET_NAME} target.
+           gdb_exit
+           gdb_start
+           gdb_reinitialize_dir $srcdir/$subdir
+           gdb_file_cmd $binfile
+           gdb_test "target ${target_name} ${tracefile}.registers.${target_name}" ".*" \
+               "change to ${target_name} target"
+
+           with_test_prefix "${target_name}" {
+               gdb_test "tfind start" "#0  globals_test_func .*" \
+                   "tfind test frame"
+               gdb_unavailable_registers_test_1
+           }
+       }
     }
 }
 
 
 proc gdb_unavailable_floats { } {
     with_test_prefix "unavailable floats" {
+       global testfile srcdir subdir binfile
+       global trace_file_targets
+
        prepare_for_trace_test
 
        # We'll simply re-use the globals_test_function for this test
        gdb_unavailable_floats_1
 
        gdb_test "tfind none" "#0  end .*" "cease trace debugging"
+
+       set tracefile [standard_output_file ${testfile}]
+       gdb_test "tsave ${tracefile}.floats.tfile" \
+           "Trace data saved to file '${tracefile}.floats.tfile'\.\\r" \
+           "tsave ${testfile}.floats.tfile"
+       gdb_test "tsave -ctf ${tracefile}.floats.ctf" \
+           "Trace data saved to directory '${tracefile}.floats.ctf'\.\\r" \
+           "save ctf trace file"
+
+       foreach target_name ${trace_file_targets} {
+           # Restart GDB and read the trace data in ${TARGET_NAME} target.
+           gdb_exit
+           gdb_start
+           gdb_reinitialize_dir $srcdir/$subdir
+           gdb_file_cmd $binfile
+           gdb_test "target ${target_name} ${tracefile}.floats.${target_name}" ".*" \
+               "change to ${target_name} target"
+
+           with_test_prefix "${target_name}" {
+               gdb_test "tfind start" "#0  globals_test_func .*" \
+                   "tfind test frame"
+               gdb_unavailable_floats_1
+           }
+       }
     }
 }
 
 
 proc gdb_collect_globals_test { } {
     with_test_prefix "collect globals" {
+       global testfile binfile srcdir subdir
+       global trace_file_targets
+
        prepare_for_trace_test
 
        set testline [gdb_get_line_number "set globals_test_func tracepoint here"]
        gdb_test "tfind none" \
            "#0  end .*" \
            "cease trace debugging"
+
+       set tracefile [standard_output_file ${testfile}]
+       gdb_test "tsave ${tracefile}.globals.tfile" \
+           "Trace data saved to file '${tracefile}.globals.tfile'\.\\r" \
+           "tsave ${testfile}.globals.tfile"
+       gdb_test "tsave -ctf ${tracefile}.globals.ctf" \
+           "Trace data saved to directory '${tracefile}.globals.ctf'\.\\r" \
+           "save ctf trace file"
+
+       foreach target_name ${trace_file_targets} {
+           # Restart GDB and read the trace data in ${TARGET_NAME} target.
+           gdb_exit
+           gdb_start
+           gdb_reinitialize_dir $srcdir/$subdir
+           gdb_file_cmd $binfile
+           gdb_test "target ${target_name} ${tracefile}.globals.${target_name}" ".*" \
+               "change to ${target_name} target"
+
+           with_test_prefix "${target_name}" {
+               gdb_test "tfind start" "#0  globals_test_func .*" \
+                   "tfind test frame"
+               gdb_collect_globals_test_1
+           }
+       }
+
     }
 }
 
     return 1
 }
 
+set trace_file_targets [list "tfile"]
+gdb_test_multiple "target ctf" "" {
+    -re "Undefined target command: \"ctf\"\.  Try \"help target\"\.\r\n$gdb_prompt $" {
+    }
+    -re "No CTF directory specified.*\r\n$gdb_prompt $" {
+       lappend trace_file_targets "ctf"
+    }
+}
+
 # Body of test encased in a proc so we can return prematurely.
 gdb_trace_collection_test
 
 
     {
       int pos = 0;
       enum target_xfer_status res;
+      /* Records the lowest available address of all blocks that
+        intersects the requested range.  */
+      ULONGEST low_addr_available = 0;
 
       /* Iterate through the traceframe's blocks, looking for
         memory.  */
              return TARGET_XFER_OK;
            }
 
+         if (offset < maddr && maddr < (offset + len))
+           if (low_addr_available == 0 || low_addr_available > maddr)
+             low_addr_available = maddr;
+
          /* Skip over this block.  */
          pos += (8 + 2 + mlen);
        }
 
       /* Requested memory is unavailable in the context of traceframes,
         and this address falls within a read-only section, fallback
-        to reading from executable.  */
+        to reading from executable, up to LOW_ADDR_AVAILABLE.  */
+      if (offset < low_addr_available)
+       len = min (len, low_addr_available - offset);
       res = exec_read_partial_read_only (readbuf, offset, len, xfered_len);
 
       if (res == TARGET_XFER_OK)