wallace created this revision.
wallace added reviewers: jj10306, clayborg, zrthxn.
Herald added a project: All.
wallace requested review of this revision.
Herald added a project: LLDB.
Herald added a subscriber: lldb-commits.

In order to support quick arbitrary access to instructions in the trace, we need
each instruction to have an id. It could be an index or any other value that the
trace plugin defines.

This will be useful for reverse debugging or for creating callstacks, as each
frame will need an instruction id associated with them.

I've updated the `thread trace dump instructions` command accordingly. It now
prints the instruction id instead of relative offset. I've also added a new --id
argument that allows starting the dump from an arbitrary position.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D122254

Files:
  lldb/include/lldb/Target/TraceCursor.h
  lldb/include/lldb/Target/TraceInstructionDumper.h
  lldb/source/Commands/CommandObjectThread.cpp
  lldb/source/Commands/Options.td
  lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp
  lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.h
  lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
  lldb/source/Target/TraceInstructionDumper.cpp
  lldb/test/API/commands/trace/TestTraceDumpInstructions.py
  lldb/test/API/commands/trace/TestTraceStartStop.py
  lldb/test/API/commands/trace/TestTraceTimestampCounters.py

Index: lldb/test/API/commands/trace/TestTraceTimestampCounters.py
===================================================================
--- lldb/test/API/commands/trace/TestTraceTimestampCounters.py
+++ lldb/test/API/commands/trace/TestTraceTimestampCounters.py
@@ -19,7 +19,7 @@
 
         self.expect("n")
         self.expect("thread trace dump instructions --tsc -c 1",
-            patterns=["\[0\] \[tsc=0x[0-9a-fA-F]+\] 0x0000000000400511    movl"])
+            patterns=["0: \[tsc=0x[0-9a-fA-F]+\] 0x0000000000400511    movl"])
 
     @testSBAPIAndCommands
     @skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64']))
@@ -32,7 +32,7 @@
 
         self.expect("n")
         self.expect("thread trace dump instructions --tsc -c 1",
-            patterns=["\[0\] \[tsc=0x[0-9a-fA-F]+\] 0x0000000000400511    movl"])
+            patterns=["0: \[tsc=0x[0-9a-fA-F]+\] 0x0000000000400511    movl"])
 
     @testSBAPIAndCommands
     @skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64']))
@@ -45,7 +45,7 @@
 
         self.expect("n")
         self.expect("thread trace dump instructions --tsc -c 1",
-            patterns=["\[0\] \[tsc=unavailable\] 0x0000000000400511    movl"])
+            patterns=["0: \[tsc=unavailable\] 0x0000000000400511    movl"])
 
     @testSBAPIAndCommands
     @skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64']))
Index: lldb/test/API/commands/trace/TestTraceStartStop.py
===================================================================
--- lldb/test/API/commands/trace/TestTraceStartStop.py
+++ lldb/test/API/commands/trace/TestTraceStartStop.py
@@ -114,29 +114,29 @@
         self.expect("thread trace dump instructions -f",
             patterns=[f'''thread #1: tid = .*
   a.out`main \+ 4 at main.cpp:2
-    \[ 0\] {ADDRESS_REGEX}    movl'''])
+    0: {ADDRESS_REGEX}    movl'''])
 
         # We can reconstruct the instructions up to the second line
         self.expect("n")
         self.expect("thread trace dump instructions -f",
             patterns=[f'''thread #1: tid = .*
   a.out`main \+ 4 at main.cpp:2
-    \[ 0\] {ADDRESS_REGEX}    movl .*
+    0: {ADDRESS_REGEX}    movl .*
   a.out`main \+ 11 at main.cpp:4
-    \[ 1\] {ADDRESS_REGEX}    movl .*
-    \[ 2\] {ADDRESS_REGEX}    jmp  .* ; <\+28> at main.cpp:4
-    \[ 3\] {ADDRESS_REGEX}    cmpl .*
-    \[ 4\] {ADDRESS_REGEX}    jle  .* ; <\+20> at main.cpp:5'''])
+    1: {ADDRESS_REGEX}    movl .*
+    2: {ADDRESS_REGEX}    jmp  .* ; <\+28> at main.cpp:4
+    3: {ADDRESS_REGEX}    cmpl .*
+    4: {ADDRESS_REGEX}    jle  .* ; <\+20> at main.cpp:5'''])
 
         self.expect("thread trace dump instructions",
             patterns=[f'''thread #1: tid = .*
   a.out`main \+ 32 at main.cpp:4
-    \[  0\] {ADDRESS_REGEX}    jle  .* ; <\+20> at main.cpp:5
-    \[ -1\] {ADDRESS_REGEX}    cmpl .*
-    \[ -2\] {ADDRESS_REGEX}    jmp  .* ; <\+28> at main.cpp:4
-    \[ -3\] {ADDRESS_REGEX}    movl .*
+    4: {ADDRESS_REGEX}    jle  .* ; <\+20> at main.cpp:5
+    3: {ADDRESS_REGEX}    cmpl .*
+    2: {ADDRESS_REGEX}    jmp  .* ; <\+28> at main.cpp:4
+    1: {ADDRESS_REGEX}    movl .*
   a.out`main \+ 4 at main.cpp:2
-    \[ -4\] {ADDRESS_REGEX}    movl .* '''])
+    0: {ADDRESS_REGEX}    movl .* '''])
 
         # We stop tracing
         self.expect("thread trace stop")
@@ -152,12 +152,12 @@
         self.expect("thread trace dump instructions -f",
             patterns=[f'''thread #1: tid = .*
   a.out`main \+ 20 at main.cpp:5
-    \[ 0\] {ADDRESS_REGEX}    xorl'''])
+    0: {ADDRESS_REGEX}    xorl'''])
 
         self.expect("thread trace dump instructions",
             patterns=[f'''thread #1: tid = .*
   a.out`main \+ 20 at main.cpp:5
-    \[  0\] {ADDRESS_REGEX}    xorl'''])
+    0: {ADDRESS_REGEX}    xorl'''])
 
         self.expect("c")
         # Now the process has finished, so the commands should fail
Index: lldb/test/API/commands/trace/TestTraceDumpInstructions.py
===================================================================
--- lldb/test/API/commands/trace/TestTraceDumpInstructions.py
+++ lldb/test/API/commands/trace/TestTraceDumpInstructions.py
@@ -37,49 +37,67 @@
 
         self.expect("thread trace dump instructions --raw --count 21 --forwards",
             substrs=['''thread #1: tid = 3842849
-    [ 0] 0x0000000000400511
-    [ 1] 0x0000000000400518
-    [ 2] 0x000000000040051f
-    [ 3] 0x0000000000400529
-    [ 4] 0x000000000040052d
-    [ 5] 0x0000000000400521
-    [ 6] 0x0000000000400525
-    [ 7] 0x0000000000400529
-    [ 8] 0x000000000040052d
-    [ 9] 0x0000000000400521
-    [10] 0x0000000000400525
-    [11] 0x0000000000400529
-    [12] 0x000000000040052d
-    [13] 0x0000000000400521
-    [14] 0x0000000000400525
-    [15] 0x0000000000400529
-    [16] 0x000000000040052d
-    [17] 0x0000000000400521
-    [18] 0x0000000000400525
-    [19] 0x0000000000400529
-    [20] 0x000000000040052d'''])
+    0: 0x0000000000400511
+    1: 0x0000000000400518
+    2: 0x000000000040051f
+    3: 0x0000000000400529
+    4: 0x000000000040052d
+    5: 0x0000000000400521
+    6: 0x0000000000400525
+    7: 0x0000000000400529
+    8: 0x000000000040052d
+    9: 0x0000000000400521
+    10: 0x0000000000400525
+    11: 0x0000000000400529
+    12: 0x000000000040052d
+    13: 0x0000000000400521
+    14: 0x0000000000400525
+    15: 0x0000000000400529
+    16: 0x000000000040052d
+    17: 0x0000000000400521
+    18: 0x0000000000400525
+    19: 0x0000000000400529
+    20: 0x000000000040052d'''])
 
         # We check if we can pass count and skip
         self.expect("thread trace dump instructions --count 5 --skip 6 --raw --forwards",
             substrs=['''thread #1: tid = 3842849
-    [ 6] 0x0000000000400525
-    [ 7] 0x0000000000400529
-    [ 8] 0x000000000040052d
-    [ 9] 0x0000000000400521
-    [10] 0x0000000000400525'''])
+    6: 0x0000000000400525
+    7: 0x0000000000400529
+    8: 0x000000000040052d
+    9: 0x0000000000400521
+    10: 0x0000000000400525'''])
 
         self.expect("thread trace dump instructions --count 5 --skip 6 --raw",
             substrs=['''thread #1: tid = 3842849
-    [ -6] 0x0000000000400525
-    [ -7] 0x0000000000400521
-    [ -8] 0x000000000040052d
-    [ -9] 0x0000000000400529
-    [-10] 0x0000000000400525'''])
+    14: 0x0000000000400525
+    13: 0x0000000000400521
+    12: 0x000000000040052d
+    11: 0x0000000000400529
+    10: 0x0000000000400525'''])
+
+        # We check if we can pass count and skip and instruction id in hex
+        self.expect("thread trace dump instructions --count 5 --skip 6 --raw --id 0xA",
+            substrs=['''thread #1: tid = 3842849
+    4: 0x000000000040052d
+    3: 0x0000000000400529
+    2: 0x000000000040051f
+    1: 0x0000000000400518
+    0: 0x0000000000400511'''])
+
+        # We check if we can pass count and skip and instruction id in decimal
+        self.expect("thread trace dump instructions --count 5 --skip 6 --raw --id 10",
+            substrs=['''thread #1: tid = 3842849
+    4: 0x000000000040052d
+    3: 0x0000000000400529
+    2: 0x000000000040051f
+    1: 0x0000000000400518
+    0: 0x0000000000400511'''])
 
         # We check if we can access the thread by index id
         self.expect("thread trace dump instructions 1 --raw",
             substrs=['''thread #1: tid = 3842849
-    [  0] 0x000000000040052d'''])
+    20: 0x000000000040052d'''])
 
         # We check that we get an error when using an invalid thread index id
         self.expect("thread trace dump instructions 10", error=True,
@@ -94,49 +112,49 @@
         self.expect("thread trace dump instructions 1 2 --count 2",
             substrs=['''thread #1: tid = 3842849
   a.out`main + 32 at main.cpp:4
-    [ 0] 0x000000000040052d    jle    0x400521                  ; <+20> at main.cpp:5
-    [-1] 0x0000000000400529    cmpl   $0x3, -0x8(%rbp)
+    20: 0x000000000040052d    jle    0x400521                  ; <+20> at main.cpp:5
+    19: 0x0000000000400529    cmpl   $0x3, -0x8(%rbp)
 thread #2: tid = 3842850
   a.out`main + 32 at main.cpp:4
-    [ 0] 0x000000000040052d    jle    0x400521                  ; <+20> at main.cpp:5
-    [-1] 0x0000000000400529    cmpl   $0x3, -0x8(%rbp)'''])
+    20: 0x000000000040052d    jle    0x400521                  ; <+20> at main.cpp:5
+    19: 0x0000000000400529    cmpl   $0x3, -0x8(%rbp)'''])
 
         # We use custom --count and --skip, saving the command to history for later
         self.expect("thread trace dump instructions 1 2 --count 2 --skip 2", inHistory=True,
             substrs=['''thread #1: tid = 3842849
   a.out`main + 24 at main.cpp:4
-    [-2] 0x0000000000400525    addl   $0x1, -0x8(%rbp)
+    18: 0x0000000000400525    addl   $0x1, -0x8(%rbp)
   a.out`main + 20 at main.cpp:5
-    [-3] 0x0000000000400521    xorl   $0x1, -0x4(%rbp)
+    17: 0x0000000000400521    xorl   $0x1, -0x4(%rbp)
 thread #2: tid = 3842850
   a.out`main + 24 at main.cpp:4
-    [-2] 0x0000000000400525    addl   $0x1, -0x8(%rbp)
+    18: 0x0000000000400525    addl   $0x1, -0x8(%rbp)
   a.out`main + 20 at main.cpp:5
-    [-3] 0x0000000000400521    xorl   $0x1, -0x4(%rbp)'''])
+    17: 0x0000000000400521    xorl   $0x1, -0x4(%rbp)'''])
 
         # We use a repeat command twice and ensure the previous count is used and the
         # start position moves with each command.
         self.expect("", inHistory=True,
             substrs=['''thread #1: tid = 3842849
   a.out`main + 32 at main.cpp:4
-    [-4] 0x000000000040052d    jle    0x400521                  ; <+20> at main.cpp:5
-    [-5] 0x0000000000400529    cmpl   $0x3, -0x8(%rbp)
+    16: 0x000000000040052d    jle    0x400521                  ; <+20> at main.cpp:5
+    15: 0x0000000000400529    cmpl   $0x3, -0x8(%rbp)
 thread #2: tid = 3842850
   a.out`main + 32 at main.cpp:4
-    [-4] 0x000000000040052d    jle    0x400521                  ; <+20> at main.cpp:5
-    [-5] 0x0000000000400529    cmpl   $0x3, -0x8(%rbp)'''])
+    16: 0x000000000040052d    jle    0x400521                  ; <+20> at main.cpp:5
+    15: 0x0000000000400529    cmpl   $0x3, -0x8(%rbp)'''])
 
         self.expect("", inHistory=True,
             substrs=['''thread #1: tid = 3842849
   a.out`main + 24 at main.cpp:4
-    [-6] 0x0000000000400525    addl   $0x1, -0x8(%rbp)
+    14: 0x0000000000400525    addl   $0x1, -0x8(%rbp)
   a.out`main + 20 at main.cpp:5
-    [-7] 0x0000000000400521    xorl   $0x1, -0x4(%rbp)
+    13: 0x0000000000400521    xorl   $0x1, -0x4(%rbp)
 thread #2: tid = 3842850
   a.out`main + 24 at main.cpp:4
-    [-6] 0x0000000000400525    addl   $0x1, -0x8(%rbp)
+    14: 0x0000000000400525    addl   $0x1, -0x8(%rbp)
   a.out`main + 20 at main.cpp:5
-    [-7] 0x0000000000400521    xorl   $0x1, -0x4(%rbp)'''])
+    13: 0x0000000000400521    xorl   $0x1, -0x4(%rbp)'''])
 
     def testInvalidBounds(self):
         self.expect("trace load -v " +
@@ -146,10 +164,10 @@
         self.expect("thread trace dump instructions --count 20 --forwards",
             substrs=['''thread #1: tid = 3842849
   a.out`main + 4 at main.cpp:2
-    [ 0] 0x0000000000400511    movl   $0x0, -0x4(%rbp)
+    0: 0x0000000000400511    movl   $0x0, -0x4(%rbp)
   a.out`main + 11 at main.cpp:4
-    [ 1] 0x0000000000400518    movl   $0x0, -0x8(%rbp)
-    [ 2] 0x000000000040051f    jmp    0x400529                  ; <+28> at main.cpp:4'''])
+    1: 0x0000000000400518    movl   $0x0, -0x8(%rbp)
+    2: 0x000000000040051f    jmp    0x400529                  ; <+28> at main.cpp:4'''])
 
         # Should print no instructions if the position is out of bounds
         self.expect("thread trace dump instructions --skip 23",
@@ -164,15 +182,15 @@
             os.path.join(self.getSourceDir(), "intelpt-trace", "trace_bad_image.json"))
         self.expect("thread trace dump instructions --forwards",
             substrs=['''thread #1: tid = 3842849
-    [ 0] 0x0000000000400511    error: no memory mapped at this address
-    [ 1] 0x0000000000400518    error: no memory mapped at this address'''])
+    0: 0x0000000000400511    error: no memory mapped at this address
+    1: 0x0000000000400518    error: no memory mapped at this address'''])
 
     def testWrongCPU(self):
         self.expect("trace load " +
             os.path.join(self.getSourceDir(), "intelpt-trace", "trace_wrong_cpu.json"))
         self.expect("thread trace dump instructions --forwards",
             substrs=['''thread #1: tid = 3842849
-    [ 0] error: unknown cpu'''])
+    0: error: unknown cpu'''])
 
     def testMultiFileTraceWithMissingModule(self):
         self.expect("trace load " +
@@ -195,147 +213,147 @@
         self.expect("thread trace dump instructions --count 50 --forwards",
             substrs=['''thread #1: tid = 815455
   a.out`main + 15 at main.cpp:10
-    [ 0] 0x000000000040066f    callq  0x400540                  ; symbol stub for: foo()
+    0: 0x000000000040066f    callq  0x400540                  ; symbol stub for: foo()
   a.out`symbol stub for: foo()
-    [ 1] 0x0000000000400540    jmpq   *0x200ae2(%rip)           ; _GLOBAL_OFFSET_TABLE_ + 40
-    [ 2] 0x0000000000400546    pushq  $0x2
-    [ 3] 0x000000000040054b    jmp    0x400510
+    1: 0x0000000000400540    jmpq   *0x200ae2(%rip)           ; _GLOBAL_OFFSET_TABLE_ + 40
+    2: 0x0000000000400546    pushq  $0x2
+    3: 0x000000000040054b    jmp    0x400510
   a.out`(none)
-    [ 4] 0x0000000000400510    pushq  0x200af2(%rip)            ; _GLOBAL_OFFSET_TABLE_ + 8
-    [ 5] 0x0000000000400516    jmpq   *0x200af4(%rip)           ; _GLOBAL_OFFSET_TABLE_ + 16
-    [ 6] 0x00007ffff7df1950    error: no memory mapped at this address
+    4: 0x0000000000400510    pushq  0x200af2(%rip)            ; _GLOBAL_OFFSET_TABLE_ + 8
+    5: 0x0000000000400516    jmpq   *0x200af4(%rip)           ; _GLOBAL_OFFSET_TABLE_ + 16
+    6: 0x00007ffff7df1950    error: no memory mapped at this address
     ...missing instructions
   a.out`main + 20 at main.cpp:10
-    [ 7] 0x0000000000400674    movl   %eax, -0xc(%rbp)
+    7: 0x0000000000400674    movl   %eax, -0xc(%rbp)
   a.out`main + 23 at main.cpp:12
-    [ 8] 0x0000000000400677    movl   -0xc(%rbp), %eax
-    [ 9] 0x000000000040067a    addl   $0x1, %eax
-    [10] 0x000000000040067f    movl   %eax, -0xc(%rbp)
+    8: 0x0000000000400677    movl   -0xc(%rbp), %eax
+    9: 0x000000000040067a    addl   $0x1, %eax
+    10: 0x000000000040067f    movl   %eax, -0xc(%rbp)
   a.out`main + 34 [inlined] inline_function() at main.cpp:4
-    [11] 0x0000000000400682    movl   $0x0, -0x4(%rbp)
+    11: 0x0000000000400682    movl   $0x0, -0x4(%rbp)
   a.out`main + 41 [inlined] inline_function() + 7 at main.cpp:5
-    [12] 0x0000000000400689    movl   -0x4(%rbp), %eax
-    [13] 0x000000000040068c    addl   $0x1, %eax
-    [14] 0x0000000000400691    movl   %eax, -0x4(%rbp)
+    12: 0x0000000000400689    movl   -0x4(%rbp), %eax
+    13: 0x000000000040068c    addl   $0x1, %eax
+    14: 0x0000000000400691    movl   %eax, -0x4(%rbp)
   a.out`main + 52 [inlined] inline_function() + 18 at main.cpp:6
-    [15] 0x0000000000400694    movl   -0x4(%rbp), %eax
+    15: 0x0000000000400694    movl   -0x4(%rbp), %eax
   a.out`main + 55 at main.cpp:14
-    [16] 0x0000000000400697    movl   -0xc(%rbp), %ecx
-    [17] 0x000000000040069a    addl   %eax, %ecx
-    [18] 0x000000000040069c    movl   %ecx, -0xc(%rbp)
+    16: 0x0000000000400697    movl   -0xc(%rbp), %ecx
+    17: 0x000000000040069a    addl   %eax, %ecx
+    18: 0x000000000040069c    movl   %ecx, -0xc(%rbp)
   a.out`main + 63 at main.cpp:16
-    [19] 0x000000000040069f    callq  0x400540                  ; symbol stub for: foo()
+    19: 0x000000000040069f    callq  0x400540                  ; symbol stub for: foo()
   a.out`symbol stub for: foo()
-    [20] 0x0000000000400540    jmpq   *0x200ae2(%rip)           ; _GLOBAL_OFFSET_TABLE_ + 40
+    20: 0x0000000000400540    jmpq   *0x200ae2(%rip)           ; _GLOBAL_OFFSET_TABLE_ + 40
   libfoo.so`foo() at foo.cpp:3
-    [21] 0x00007ffff7bd96e0    pushq  %rbp
-    [22] 0x00007ffff7bd96e1    movq   %rsp, %rbp
+    21: 0x00007ffff7bd96e0    pushq  %rbp
+    22: 0x00007ffff7bd96e1    movq   %rsp, %rbp
   libfoo.so`foo() + 4 at foo.cpp:4
-    [23] 0x00007ffff7bd96e4    subq   $0x10, %rsp
-    [24] 0x00007ffff7bd96e8    callq  0x7ffff7bd95d0            ; symbol stub for: bar()
+    23: 0x00007ffff7bd96e4    subq   $0x10, %rsp
+    24: 0x00007ffff7bd96e8    callq  0x7ffff7bd95d0            ; symbol stub for: bar()
   libfoo.so`symbol stub for: bar()
-    [25] 0x00007ffff7bd95d0    jmpq   *0x200a4a(%rip)           ; _GLOBAL_OFFSET_TABLE_ + 32
+    25: 0x00007ffff7bd95d0    jmpq   *0x200a4a(%rip)           ; _GLOBAL_OFFSET_TABLE_ + 32
   libbar.so`bar() at bar.cpp:1
-    [26] 0x00007ffff79d7690    pushq  %rbp
-    [27] 0x00007ffff79d7691    movq   %rsp, %rbp
+    26: 0x00007ffff79d7690    pushq  %rbp
+    27: 0x00007ffff79d7691    movq   %rsp, %rbp
   libbar.so`bar() + 4 at bar.cpp:2
-    [28] 0x00007ffff79d7694    movl   $0x1, -0x4(%rbp)
+    28: 0x00007ffff79d7694    movl   $0x1, -0x4(%rbp)
   libbar.so`bar() + 11 at bar.cpp:3
-    [29] 0x00007ffff79d769b    movl   -0x4(%rbp), %eax
-    [30] 0x00007ffff79d769e    addl   $0x1, %eax
-    [31] 0x00007ffff79d76a3    movl   %eax, -0x4(%rbp)
+    29: 0x00007ffff79d769b    movl   -0x4(%rbp), %eax
+    30: 0x00007ffff79d769e    addl   $0x1, %eax
+    31: 0x00007ffff79d76a3    movl   %eax, -0x4(%rbp)
   libbar.so`bar() + 22 at bar.cpp:4
-    [32] 0x00007ffff79d76a6    movl   -0x4(%rbp), %eax
-    [33] 0x00007ffff79d76a9    popq   %rbp
-    [34] 0x00007ffff79d76aa    retq''',
+    32: 0x00007ffff79d76a6    movl   -0x4(%rbp), %eax
+    33: 0x00007ffff79d76a9    popq   %rbp
+    34: 0x00007ffff79d76aa    retq''',
   '''libfoo.so`foo() + 13 at foo.cpp:4
-    [35] 0x00007ffff7bd96ed    movl   %eax, -0x4(%rbp)
+    35: 0x00007ffff7bd96ed    movl   %eax, -0x4(%rbp)
   libfoo.so`foo() + 16 at foo.cpp:5
-    [36] 0x00007ffff7bd96f0    movl   -0x4(%rbp), %eax
-    [37] 0x00007ffff7bd96f3    addl   $0x1, %eax
-    [38] 0x00007ffff7bd96f8    movl   %eax, -0x4(%rbp)
+    36: 0x00007ffff7bd96f0    movl   -0x4(%rbp), %eax
+    37: 0x00007ffff7bd96f3    addl   $0x1, %eax
+    38: 0x00007ffff7bd96f8    movl   %eax, -0x4(%rbp)
   libfoo.so`foo() + 27 at foo.cpp:6
-    [39] 0x00007ffff7bd96fb    movl   -0x4(%rbp), %eax
-    [40] 0x00007ffff7bd96fe    addq   $0x10, %rsp
-    [41] 0x00007ffff7bd9702    popq   %rbp
-    [42] 0x00007ffff7bd9703    retq''',
+    39: 0x00007ffff7bd96fb    movl   -0x4(%rbp), %eax
+    40: 0x00007ffff7bd96fe    addq   $0x10, %rsp
+    41: 0x00007ffff7bd9702    popq   %rbp
+    42: 0x00007ffff7bd9703    retq''',
   '''a.out`main + 68 at main.cpp:16
-    [43] 0x00000000004006a4    movl   -0xc(%rbp), %ecx
-    [44] 0x00000000004006a7    addl   %eax, %ecx
-    [45] 0x00000000004006a9    movl   %ecx, -0xc(%rbp)'''])
+    43: 0x00000000004006a4    movl   -0xc(%rbp), %ecx
+    44: 0x00000000004006a7    addl   %eax, %ecx
+    45: 0x00000000004006a9    movl   %ecx, -0xc(%rbp)'''])
 
 
         self.expect("thread trace dump instructions --count 50",
             substrs=['''thread #1: tid = 815455
   a.out`main + 73 at main.cpp:16
-    [  0] 0x00000000004006a9    movl   %ecx, -0xc(%rbp)
-    [ -1] 0x00000000004006a7    addl   %eax, %ecx
-    [ -2] 0x00000000004006a4    movl   -0xc(%rbp), %ecx
+    45: 0x00000000004006a9    movl   %ecx, -0xc(%rbp)
+    44: 0x00000000004006a7    addl   %eax, %ecx
+    43: 0x00000000004006a4    movl   -0xc(%rbp), %ecx
   libfoo.so`foo() + 35 at foo.cpp:6
-    [ -3] 0x00007ffff7bd9703    retq''',
-    '''[ -4] 0x00007ffff7bd9702    popq   %rbp
-    [ -5] 0x00007ffff7bd96fe    addq   $0x10, %rsp
-    [ -6] 0x00007ffff7bd96fb    movl   -0x4(%rbp), %eax
+    42: 0x00007ffff7bd9703    retq''',
+    '''41: 0x00007ffff7bd9702    popq   %rbp
+    40: 0x00007ffff7bd96fe    addq   $0x10, %rsp
+    39: 0x00007ffff7bd96fb    movl   -0x4(%rbp), %eax
   libfoo.so`foo() + 24 at foo.cpp:5
-    [ -7] 0x00007ffff7bd96f8    movl   %eax, -0x4(%rbp)
-    [ -8] 0x00007ffff7bd96f3    addl   $0x1, %eax
-    [ -9] 0x00007ffff7bd96f0    movl   -0x4(%rbp), %eax
+    38: 0x00007ffff7bd96f8    movl   %eax, -0x4(%rbp)
+    37: 0x00007ffff7bd96f3    addl   $0x1, %eax
+    36: 0x00007ffff7bd96f0    movl   -0x4(%rbp), %eax
   libfoo.so`foo() + 13 at foo.cpp:4
-    [-10] 0x00007ffff7bd96ed    movl   %eax, -0x4(%rbp)
+    35: 0x00007ffff7bd96ed    movl   %eax, -0x4(%rbp)
   libbar.so`bar() + 26 at bar.cpp:4
-    [-11] 0x00007ffff79d76aa    retq''',
-    '''[-12] 0x00007ffff79d76a9    popq   %rbp
-    [-13] 0x00007ffff79d76a6    movl   -0x4(%rbp), %eax
+    34: 0x00007ffff79d76aa    retq''',
+    '''33: 0x00007ffff79d76a9    popq   %rbp
+    32: 0x00007ffff79d76a6    movl   -0x4(%rbp), %eax
   libbar.so`bar() + 19 at bar.cpp:3
-    [-14] 0x00007ffff79d76a3    movl   %eax, -0x4(%rbp)
-    [-15] 0x00007ffff79d769e    addl   $0x1, %eax
-    [-16] 0x00007ffff79d769b    movl   -0x4(%rbp), %eax
+    31: 0x00007ffff79d76a3    movl   %eax, -0x4(%rbp)
+    30: 0x00007ffff79d769e    addl   $0x1, %eax
+    29: 0x00007ffff79d769b    movl   -0x4(%rbp), %eax
   libbar.so`bar() + 4 at bar.cpp:2
-    [-17] 0x00007ffff79d7694    movl   $0x1, -0x4(%rbp)
+    28: 0x00007ffff79d7694    movl   $0x1, -0x4(%rbp)
   libbar.so`bar() + 1 at bar.cpp:1
-    [-18] 0x00007ffff79d7691    movq   %rsp, %rbp
-    [-19] 0x00007ffff79d7690    pushq  %rbp
+    27: 0x00007ffff79d7691    movq   %rsp, %rbp
+    26: 0x00007ffff79d7690    pushq  %rbp
   libfoo.so`symbol stub for: bar()
-    [-20] 0x00007ffff7bd95d0    jmpq   *0x200a4a(%rip)           ; _GLOBAL_OFFSET_TABLE_ + 32
+    25: 0x00007ffff7bd95d0    jmpq   *0x200a4a(%rip)           ; _GLOBAL_OFFSET_TABLE_ + 32
   libfoo.so`foo() + 8 at foo.cpp:4
-    [-21] 0x00007ffff7bd96e8    callq  0x7ffff7bd95d0            ; symbol stub for: bar()
-    [-22] 0x00007ffff7bd96e4    subq   $0x10, %rsp
+    24: 0x00007ffff7bd96e8    callq  0x7ffff7bd95d0            ; symbol stub for: bar()
+    23: 0x00007ffff7bd96e4    subq   $0x10, %rsp
   libfoo.so`foo() + 1 at foo.cpp:3
-    [-23] 0x00007ffff7bd96e1    movq   %rsp, %rbp
-    [-24] 0x00007ffff7bd96e0    pushq  %rbp
+    22: 0x00007ffff7bd96e1    movq   %rsp, %rbp
+    21: 0x00007ffff7bd96e0    pushq  %rbp
   a.out`symbol stub for: foo()
-    [-25] 0x0000000000400540    jmpq   *0x200ae2(%rip)           ; _GLOBAL_OFFSET_TABLE_ + 40
+    20: 0x0000000000400540    jmpq   *0x200ae2(%rip)           ; _GLOBAL_OFFSET_TABLE_ + 40
   a.out`main + 63 at main.cpp:16
-    [-26] 0x000000000040069f    callq  0x400540                  ; symbol stub for: foo()
+    19: 0x000000000040069f    callq  0x400540                  ; symbol stub for: foo()
   a.out`main + 60 at main.cpp:14
-    [-27] 0x000000000040069c    movl   %ecx, -0xc(%rbp)
-    [-28] 0x000000000040069a    addl   %eax, %ecx
-    [-29] 0x0000000000400697    movl   -0xc(%rbp), %ecx
+    18: 0x000000000040069c    movl   %ecx, -0xc(%rbp)
+    17: 0x000000000040069a    addl   %eax, %ecx
+    16: 0x0000000000400697    movl   -0xc(%rbp), %ecx
   a.out`main + 52 [inlined] inline_function() + 18 at main.cpp:6
-    [-30] 0x0000000000400694    movl   -0x4(%rbp), %eax
+    15: 0x0000000000400694    movl   -0x4(%rbp), %eax
   a.out`main + 49 [inlined] inline_function() + 15 at main.cpp:5
-    [-31] 0x0000000000400691    movl   %eax, -0x4(%rbp)
-    [-32] 0x000000000040068c    addl   $0x1, %eax
-    [-33] 0x0000000000400689    movl   -0x4(%rbp), %eax
+    14: 0x0000000000400691    movl   %eax, -0x4(%rbp)
+    13: 0x000000000040068c    addl   $0x1, %eax
+    12: 0x0000000000400689    movl   -0x4(%rbp), %eax
   a.out`main + 34 [inlined] inline_function() at main.cpp:4
-    [-34] 0x0000000000400682    movl   $0x0, -0x4(%rbp)
+    11: 0x0000000000400682    movl   $0x0, -0x4(%rbp)
   a.out`main + 31 at main.cpp:12
-    [-35] 0x000000000040067f    movl   %eax, -0xc(%rbp)
-    [-36] 0x000000000040067a    addl   $0x1, %eax
-    [-37] 0x0000000000400677    movl   -0xc(%rbp), %eax
+    10: 0x000000000040067f    movl   %eax, -0xc(%rbp)
+    9: 0x000000000040067a    addl   $0x1, %eax
+    8: 0x0000000000400677    movl   -0xc(%rbp), %eax
   a.out`main + 20 at main.cpp:10
-    [-38] 0x0000000000400674    movl   %eax, -0xc(%rbp)
+    7: 0x0000000000400674    movl   %eax, -0xc(%rbp)
     ...missing instructions
-    [-39] 0x00007ffff7df1950    error: no memory mapped at this address
+    6: 0x00007ffff7df1950    error: no memory mapped at this address
   a.out`(none)
-    [-40] 0x0000000000400516    jmpq   *0x200af4(%rip)           ; _GLOBAL_OFFSET_TABLE_ + 16
-    [-41] 0x0000000000400510    pushq  0x200af2(%rip)            ; _GLOBAL_OFFSET_TABLE_ + 8
+    5: 0x0000000000400516    jmpq   *0x200af4(%rip)           ; _GLOBAL_OFFSET_TABLE_ + 16
+    4: 0x0000000000400510    pushq  0x200af2(%rip)            ; _GLOBAL_OFFSET_TABLE_ + 8
   a.out`symbol stub for: foo() + 11
-    [-42] 0x000000000040054b    jmp    0x400510
-    [-43] 0x0000000000400546    pushq  $0x2
-    [-44] 0x0000000000400540    jmpq   *0x200ae2(%rip)           ; _GLOBAL_OFFSET_TABLE_ + 40
+    3: 0x000000000040054b    jmp    0x400510
+    2: 0x0000000000400546    pushq  $0x2
+    1: 0x0000000000400540    jmpq   *0x200ae2(%rip)           ; _GLOBAL_OFFSET_TABLE_ + 40
   a.out`main + 15 at main.cpp:10
-    [-45] 0x000000000040066f    callq  0x400540                  ; symbol stub for: foo()'''])
+    0: 0x000000000040066f    callq  0x400540                  ; symbol stub for: foo()'''])
 
         self.expect("thread trace dump instructions --skip 100 --forwards", inHistory=True,
             substrs=['''thread #1: tid = 815455
Index: lldb/source/Target/TraceInstructionDumper.cpp
===================================================================
--- lldb/source/Target/TraceInstructionDumper.cpp
+++ lldb/source/Target/TraceInstructionDumper.cpp
@@ -18,11 +18,34 @@
 using namespace lldb_private;
 using namespace llvm;
 
-TraceInstructionDumper::TraceInstructionDumper(lldb::TraceCursorUP &&cursor_up,
-                                               int initial_index, bool raw,
-                                               bool show_tsc)
-    : m_cursor_up(std::move(cursor_up)), m_index(initial_index), m_raw(raw),
-      m_show_tsc(show_tsc) {}
+TraceInstructionDumper::TraceInstructionDumper(
+    lldb::TraceCursorUP &&cursor_up, bool forwards, bool raw, bool show_tsc,
+    llvm::Optional<uint64_t> id, llvm::Optional<size_t> skip, Stream &s)
+    : m_cursor_up(std::move(cursor_up)), m_raw(raw), m_show_tsc(show_tsc) {
+  // We first set the cursor in its initial position
+  if (id) {
+    if (!m_cursor_up->GoToId(*id)) {
+      s.Printf("    invalid instruction id\n");
+      SetNoMoreData();
+      return;
+    }
+  } else if (forwards) {
+    m_cursor_up->Seek(0, TraceCursor::SeekType::Set);
+  } else {
+    m_cursor_up->Seek(0, TraceCursor::SeekType::End);
+  }
+
+  m_cursor_up->SetForwards(forwards);
+  if (skip) {
+    int64_t to_skip = skip.getValue();
+    if (m_cursor_up->Seek((forwards ? 1 : -1) * to_skip,
+                          TraceCursor::SeekType::Current) < to_skip) {
+      // This happens when the skip value was more than the number of
+      // available instructions.
+      SetNoMoreData();
+    }
+  }
+}
 
 /// \return
 ///     Return \b true if the cursor could move one step.
@@ -31,19 +54,9 @@
     SetNoMoreData();
     return false;
   }
-  m_index += m_cursor_up->IsForwards() ? 1 : -1;
   return true;
 }
 
-/// \return
-///     The number of characters that would be needed to print the given
-///     integer.
-static int GetNumberOfChars(int num) {
-  if (num == 0)
-    return 1;
-  return (num < 0 ? 1 : 0) + static_cast<int>(log10(abs(num))) + 1;
-}
-
 /// Helper struct that holds symbol, disassembly and address information of an
 /// instruction.
 struct InstructionSymbolInfo {
@@ -169,16 +182,14 @@
   s.Printf("thread #%u: tid = %" PRIu64 "\n", thread_sp->GetIndexID(),
            thread_sp->GetID());
 
-  int digits_count = GetNumberOfChars(
-      m_cursor_up->IsForwards() ? m_index + count - 1 : m_index - count + 1);
   bool was_prev_instruction_an_error = false;
 
   auto printMissingInstructionsMessage = [&]() {
     s.Printf("    ...missing instructions\n");
   };
 
-  auto printInstructionIndex = [&]() {
-    s.Printf("    [%*d] ", digits_count, m_index);
+  auto printInstructionHeader = [&](uint64_t id) {
+    s.Printf("    %" PRIu64 ": ", id);
 
     if (m_show_tsc) {
       s.Printf("[tsc=");
@@ -256,7 +267,7 @@
 
       was_prev_instruction_an_error = true;
 
-      printInstructionIndex();
+      printInstructionHeader(m_cursor_up->GetId());
       s << toString(std::move(err));
     } else {
       if (m_cursor_up->IsForwards() && was_prev_instruction_an_error)
@@ -277,7 +288,7 @@
         DumpInstructionSymbolContext(s, prev_insn_info, insn_info);
       }
 
-      printInstructionIndex();
+      printInstructionHeader(m_cursor_up->GetId());
       s.Printf("0x%016" PRIx64, m_cursor_up->GetLoadAddress());
 
       if (!m_raw)
Index: lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
+++ lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
@@ -118,7 +118,6 @@
            Decode(thread)->GetInstructions().size());
   s.Printf("  Total approximate memory usage: %0.2lf KiB\n",
            (double)mem_used / 1024);
-  return;
 }
 
 Optional<size_t> TraceIntelPT::GetRawTraceSize(Thread &thread) {
Index: lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.h
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.h
+++ lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.h
@@ -20,7 +20,7 @@
   TraceCursorIntelPT(lldb::ThreadSP thread_sp,
                      DecodedThreadSP decoded_thread_sp);
 
-  size_t Seek(int64_t offset, SeekType origin) override;
+  int64_t Seek(int64_t offset, SeekType origin) override;
 
   virtual bool Next() override;
 
@@ -35,6 +35,10 @@
 
   bool IsError() override;
 
+  bool GoToId(uint64_t id) override;
+
+  uint64_t GetId() const override;
+
 private:
   size_t GetInternalInstructionSize();
 
Index: lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp
+++ lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp
@@ -51,7 +51,7 @@
   return false;
 }
 
-size_t TraceCursorIntelPT::Seek(int64_t offset, SeekType origin) {
+int64_t TraceCursorIntelPT::Seek(int64_t offset, SeekType origin) {
   int64_t last_index = GetInternalInstructionSize() - 1;
 
   auto fitPosToBounds = [&](int64_t raw_pos) -> int64_t {
@@ -101,3 +101,12 @@
   return m_decoded_thread_sp->GetInstructions()[m_pos].GetControlFlowType(
       next_load_address);
 }
+
+bool TraceCursorIntelPT::GoToId(uint64_t id) {
+  if (m_decoded_thread_sp->GetInstructions().size() <= id)
+    return false;
+  m_pos = id;
+  return true;
+}
+
+uint64_t TraceCursorIntelPT::GetId() const { return m_pos; }
Index: lldb/source/Commands/Options.td
===================================================================
--- lldb/source/Commands/Options.td
+++ lldb/source/Commands/Options.td
@@ -1097,7 +1097,8 @@
 }
 
 let Command = "thread trace dump instructions" in {
-  def thread_trace_dump_instructions_forwards: Option<"forwards", "f">, Group<1>,
+  def thread_trace_dump_instructions_forwards: Option<"forwards", "f">,
+    Group<1>,
     Desc<"If specified, the trace is traversed forwards chronologically "
     "starting at the oldest instruction. Otherwise, it starts at the most "
     "recent one and the traversal is backwards.">;
@@ -1105,23 +1106,26 @@
     Arg<"Count">,
     Desc<"The number of instructions to display starting at the most recent "
     "instruction, or the oldest if --forwards is provided.">;
-  def thread_trace_dump_instructions_skip: Option<"skip", "s">,
-    Group<1>,
+  def thread_trace_dump_instructions_id: Option<"id", "i">, Group<1>,
     Arg<"Index">,
-    Desc<"How many instruction to skip from the end of the trace to start "
-    "dumping instructions, or from the beginning if --forwards is provided">;
+    Desc<"Custom starting instruction id from where to start traversing. This "
+    "id can be provided in decimal or hexadecimal representation.">;
+  def thread_trace_dump_instructions_skip: Option<"skip", "s">, Group<1>,
+    Arg<"Index">,
+    Desc<"How many instruction to skip from the starting position of the trace "
+    "before starting the traversal.">;
   def thread_trace_dump_instructions_raw : Option<"raw", "r">,
     Group<1>,
-    Desc<"Dump only instruction address without disassembly nor symbol information.">;
-  def thread_trace_dump_instructions_show_tsc : Option<"tsc", "t">,
-    Group<1>,
-    Desc<"For each instruction, print the corresponding timestamp counter if available.">;
+    Desc<"Dump only instruction address without disassembly nor symbol "
+    "information.">;
+  def thread_trace_dump_instructions_show_tsc : Option<"tsc", "t">, Group<1>,
+    Desc<"For each instruction, print the corresponding timestamp counter if "
+    "available.">;
   def thread_trace_dump_instructions_continue: Option<"continue", "C">,
     Group<1>,
-    Desc<"Continue dumping instructions right where the previous invocation of this "
-    "command was left, or from the beginning if this is the first invocation. The --skip "
-    "argument is discarded and the other arguments are preserved from the previous "
-    "invocation when possible.">;
+    Desc<"Continue dumping instructions right where the previous invocation of "
+    "this command was left, or from the beginning if this is the first "
+    "invocation. The --skip and --id arguments are discared if provided.">;
 }
 
 let Command = "thread trace dump info" in {
Index: lldb/source/Commands/CommandObjectThread.cpp
===================================================================
--- lldb/source/Commands/CommandObjectThread.cpp
+++ lldb/source/Commands/CommandObjectThread.cpp
@@ -2135,6 +2135,16 @@
           m_skip = skip;
         break;
       }
+      case 'i': {
+        uint64_t id;
+        if (option_arg.empty() || option_arg.getAsInteger(0, id))
+          error.SetErrorStringWithFormat(
+              "invalid integer value for option '%s'",
+              option_arg.str().c_str());
+        else
+          m_id = id;
+        break;
+      }
       case 'r': {
         m_raw = true;
         break;
@@ -2159,7 +2169,8 @@
 
     void OptionParsingStarting(ExecutionContext *execution_context) override {
       m_count = kDefaultCount;
-      m_skip = 0;
+      m_skip = llvm::None;
+      m_id = llvm::None;
       m_raw = false;
       m_forwards = false;
       m_show_tsc = false;
@@ -2174,7 +2185,8 @@
 
     // Instance variables to hold the values for command options.
     size_t m_count;
-    size_t m_skip;
+    llvm::Optional<size_t> m_skip;
+    llvm::Optional<uint64_t> m_id;
     bool m_raw;
     bool m_forwards;
     bool m_show_tsc;
@@ -2213,6 +2225,21 @@
     return CommandObjectIterateOverThreads::DoExecute(args, result);
   }
 
+  TraceInstructionDumper &GetOrCreateDumper(TraceSP trace_sp,
+                                            ThreadSP thread_sp, Stream &s) {
+    // We already have a cursor for this thread
+    auto it = m_dumpers.find(thread_sp->GetID());
+    if (it != m_dumpers.end())
+      return *it->second;
+
+    auto dumper = std::make_unique<TraceInstructionDumper>(
+        trace_sp->GetCursor(*thread_sp), m_options.m_forwards, m_options.m_raw,
+        m_options.m_show_tsc, m_options.m_id, m_options.m_skip, s);
+
+    return *m_dumpers.emplace(thread_sp->GetID(), std::move(dumper))
+                .first->second;
+  }
+
   bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override {
     Stream &s = result.GetOutputStream();
 
@@ -2220,32 +2247,8 @@
     ThreadSP thread_sp =
         m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid);
 
-    if (!m_dumpers.count(thread_sp->GetID())) {
-      lldb::TraceCursorUP cursor_up = trace_sp->GetCursor(*thread_sp);
-      // Set up the cursor and return the presentation index of the first
-      // instruction to dump after skipping instructions.
-      auto setUpCursor = [&]() {
-        cursor_up->SetForwards(m_options.m_forwards);
-        if (m_options.m_forwards)
-          return cursor_up->Seek(m_options.m_skip, TraceCursor::SeekType::Set);
-        return -cursor_up->Seek(-m_options.m_skip, TraceCursor::SeekType::End);
-      };
-
-      int initial_index = setUpCursor();
-
-      auto dumper = std::make_unique<TraceInstructionDumper>(
-          std::move(cursor_up), initial_index, m_options.m_raw,
-          m_options.m_show_tsc);
-
-      // This happens when the seek value was more than the number of available
-      // instructions.
-      if (std::abs(initial_index) < (int)m_options.m_skip)
-        dumper->SetNoMoreData();
-
-      m_dumpers[thread_sp->GetID()] = std::move(dumper);
-    }
-
-    m_dumpers[thread_sp->GetID()]->DumpInstructions(s, m_options.m_count);
+    GetOrCreateDumper(trace_sp, thread_sp, s)
+        .DumpInstructions(s, m_options.m_count);
     return true;
   }
 
Index: lldb/include/lldb/Target/TraceInstructionDumper.h
===================================================================
--- lldb/include/lldb/Target/TraceInstructionDumper.h
+++ lldb/include/lldb/Target/TraceInstructionDumper.h
@@ -22,10 +22,10 @@
   /// \param[in] cursor
   ///     The cursor whose instructions will be dumped.
   ///
-  /// \param[in] initial_index
-  ///     Presentation index to use for referring to the current instruction
-  ///     of the cursor. If the direction is forwards, the index will increase,
-  ///     and if the direction is backwards, the index will decrease.
+  /// \param[in] forwards
+  ///     If \b true, the cursor will be iterated forwards starting from the
+  ///     oldest instruction. Otherwise, the iteration starts from the most
+  ///     recent instruction.
   ///
   /// \param[in] raw
   ///     Dump only instruction addresses without disassembly nor symbol
@@ -34,8 +34,16 @@
   /// \param[in] show_tsc
   ///     For each instruction, print the corresponding timestamp counter if
   ///     available.
-  TraceInstructionDumper(lldb::TraceCursorUP &&cursor_up, int initial_index = 0,
-                         bool raw = false, bool show_tsc = false);
+  ///
+  /// \param[in] id
+  ///     Optional custom id to start traversing from.
+  ///
+  /// \param[in] skip
+  ///     Optional number of instructions to skip from the starting position
+  ///     of the cursor.
+  TraceInstructionDumper(lldb::TraceCursorUP &&cursor_up, bool forwards,
+                         bool raw, bool show_tsc, llvm::Optional<uint64_t> id,
+                         llvm::Optional<size_t> skip, Stream &s);
 
   /// Dump \a count instructions of the thread trace starting at the current
   /// cursor position.
@@ -50,14 +58,15 @@
   ///     The number of instructions to print.
   void DumpInstructions(Stream &s, size_t count);
 
-  /// Indicate the dumper that no more data is available in the trace.
-  void SetNoMoreData();
-
   /// \return
   ///     \b true if there's still more data to traverse in the trace.
   bool HasMoreData();
 
 private:
+  /// Indicate the dumper that no more data is available in the trace.
+  /// This will prevent further iterations.
+  void SetNoMoreData();
+
   /// Move the cursor one step.
   ///
   /// \return
@@ -65,7 +74,6 @@
   bool TryMoveOneStep();
 
   lldb::TraceCursorUP m_cursor_up;
-  int m_index;
   bool m_raw;
   bool m_show_tsc;
   /// If \b true, all the instructions have been traversed.
Index: lldb/include/lldb/Target/TraceCursor.h
===================================================================
--- lldb/include/lldb/Target/TraceCursor.h
+++ lldb/include/lldb/Target/TraceCursor.h
@@ -152,7 +152,15 @@
   ///
   /// \return
   ///     The number of trace items moved from the origin.
-  virtual size_t Seek(ssize_t offset, SeekType origin) = 0;
+  virtual int64_t Seek(int64_t offset, SeekType origin) = 0;
+
+  /// Make the cursor point to the item whose identifier is \p id. See \a
+  /// Trace::GetId() for more information.
+  ///
+  /// \return
+  ///     \b true if the given identifier exists and the cursor effectively
+  ///     moved, \b false otherwise.
+  virtual bool GoToId(uint64_t id) = 0;
 
   /// \return
   ///   The \a ExecutionContextRef of the backing thread from the creation time
@@ -197,6 +205,13 @@
   ///     to an error in the trace, return \b 0.
   virtual lldb::TraceInstructionControlFlowType
   GetInstructionControlFlowType() = 0;
+
+  /// \return
+  ///     A unique identifier for the instruction or error this cursor is
+  ///     pointing to. Each Trace plug-in can decide the nature of these
+  ///     identifiers and thus no assumptions can be made regarding its ordering
+  ///     and sequentiality.
+  virtual uint64_t GetId() const = 0;
   /// \}
 
 protected:
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to