duran 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README.rdoc +11 -0
- data/Rakefile +29 -0
- data/VERSION +1 -0
- data/client_src/dr_include/dr_api.h +102 -0
- data/client_src/dr_include/dr_app.h +92 -0
- data/client_src/dr_include/dr_config.h +650 -0
- data/client_src/dr_include/dr_defines.h +391 -0
- data/client_src/dr_include/dr_events.h +1057 -0
- data/client_src/dr_include/dr_ir_instr.h +1214 -0
- data/client_src/dr_include/dr_ir_instrlist.h +149 -0
- data/client_src/dr_include/dr_ir_macros.h +2426 -0
- data/client_src/dr_include/dr_ir_opcodes.h +768 -0
- data/client_src/dr_include/dr_ir_opnd.h +1170 -0
- data/client_src/dr_include/dr_ir_utils.h +708 -0
- data/client_src/dr_include/dr_proc.h +327 -0
- data/client_src/dr_include/dr_tools.h +1304 -0
- data/client_src/duran.c +57 -0
- data/client_src/extconf.rb +28 -0
- data/lib/duran.rb +18 -0
- data/lib/duran/app.rb +8 -0
- data/lib/duran/defines.rb +39 -0
- data/lib/duran/events.rb +156 -0
- data/lib/duran/ir_opcodes.rb +616 -0
- data/lib/duran/ir_opnd.rb +329 -0
- data/lib/duran/ir_utils.rb +133 -0
- data/lib/duran/proc.rb +49 -0
- data/lib/duran/structs.rb +20 -0
- data/lib/duran/structs/exception.rb +23 -0
- data/lib/duran/structs/fault_fragment_info.rb +34 -0
- data/lib/duran/structs/instruction.rb +15 -0
- data/lib/duran/structs/machine_context.rb +80 -0
- data/lib/duran/structs/memory_info.rb +12 -0
- data/lib/duran/structs/module_data.rb +61 -0
- data/lib/duran/structs/module_names.rb +24 -0
- data/lib/duran/structs/operand.rb +15 -0
- data/lib/duran/structs/restore_state_info.rb +30 -0
- data/lib/duran/structs/signal_info.rb +41 -0
- data/lib/duran/structs/tracedump.rb +50 -0
- data/lib/duran/tools.rb +214 -0
- metadata +104 -0
data/lib/duran/proc.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
|
2
|
+
module Duran
|
3
|
+
# XXX feature_bit_t is an enum, but there's gaps and i'm feeling lazy atm
|
4
|
+
typedef :uint, :feature_bit_t
|
5
|
+
|
6
|
+
enum :cache_size_t, [
|
7
|
+
:CACHE_SIZE_8_KB, #/**< L1 or L2 cache size of 8 KB. */
|
8
|
+
:CACHE_SIZE_16_KB, #/**< L1 or L2 cache size of 16 KB. */
|
9
|
+
:CACHE_SIZE_32_KB, #/**< L1 or L2 cache size of 32 KB. */
|
10
|
+
:CACHE_SIZE_64_KB, #/**< L1 or L2 cache size of 64 KB. */
|
11
|
+
:CACHE_SIZE_128_KB, #/**< L1 or L2 cache size of 128 KB. */
|
12
|
+
:CACHE_SIZE_256_KB, #/**< L1 or L2 cache size of 256 KB. */
|
13
|
+
:CACHE_SIZE_512_KB, #/**< L1 or L2 cache size of 512 KB. */
|
14
|
+
:CACHE_SIZE_1_MB, #/**< L1 or L2 cache size of 1 MB. */
|
15
|
+
:CACHE_SIZE_2_MB, #/**< L1 or L2 cache size of 2 MB. */
|
16
|
+
:CACHE_SIZE_UNKNOWN #/**< Unknown L1 or L2 cache size. */
|
17
|
+
]
|
18
|
+
|
19
|
+
enum :vendor_t, [:intel, :amd, :unknown]
|
20
|
+
|
21
|
+
|
22
|
+
attach_function :proc_get_cache_line_size, [], :size_t
|
23
|
+
attach_function :proc_is_cache_aligned, [:pointer], :bool
|
24
|
+
attach_function :proc_bump_to_end_of_cache_line, [:ptr_uint_t], :ptr_uint_t
|
25
|
+
attach_function :proc_get_containing_page, [:pointer], :pointer
|
26
|
+
attach_function :proc_get_vendor, [], :vendor_t
|
27
|
+
attach_function :proc_get_family, [], :uint
|
28
|
+
attach_function :proc_get_type, [], :uint
|
29
|
+
attach_function :proc_get_model, [], :uint
|
30
|
+
attach_function :proc_get_stepping, [], :uint
|
31
|
+
attach_function :proc_get_brand_string, [], :string
|
32
|
+
attach_function :proc_get_L1_icache_size, [], :cache_size_t
|
33
|
+
attach_function :proc_get_L1_dcache_size, [], :cache_size_t
|
34
|
+
attach_function :proc_get_L2_cache_size, [], :cache_size_t
|
35
|
+
attach_function :proc_get_cache_size_str, [:cache_size_t], :string
|
36
|
+
attach_function :proc_fpstate_save_size, [], :size_t
|
37
|
+
attach_function :proc_save_fpstate, [:pointer], :size_t
|
38
|
+
attach_function :proc_restore_fpstate, [:pointer], :void
|
39
|
+
attach_function :proc_has_feature, [:feature_bit_t], :bool
|
40
|
+
attach_function :proc_get_all_feature_bits, [], :pointer
|
41
|
+
|
42
|
+
attach_function :dr_insert_save_fpstate,
|
43
|
+
[:dr_ctx_t, :pointer, :pointer, Operand], :void
|
44
|
+
|
45
|
+
attach_function :dr_insert_restore_fpstate,
|
46
|
+
[:dr_ctx_t, :pointer, :pointer, Operand], :void
|
47
|
+
|
48
|
+
end
|
49
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
module Duran
|
3
|
+
class DRYStruct < FFI::Struct
|
4
|
+
include FFI::DRY::StructHelper
|
5
|
+
end
|
6
|
+
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'duran/structs/operand'
|
10
|
+
require 'duran/structs/instruction'
|
11
|
+
require 'duran/structs/machine_context'
|
12
|
+
require 'duran/structs/fault_fragment_info'
|
13
|
+
require 'duran/structs/restore_state_info'
|
14
|
+
require 'duran/structs/exception'
|
15
|
+
require 'duran/structs/signal_info'
|
16
|
+
require 'duran/structs/memory_info'
|
17
|
+
require 'duran/structs/module_names'
|
18
|
+
require 'duran/structs/module_data'
|
19
|
+
require 'duran/structs/tracedump'
|
20
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
module Duran
|
3
|
+
class Exception < DRYStruct
|
4
|
+
dsl_layout do
|
5
|
+
struct :mcontext, MachineContext, :desc => "Context at exception point"
|
6
|
+
|
7
|
+
field :record, :pointer, :desc => "Ptr. to the Win32 EXCEPTION_RECORD"
|
8
|
+
|
9
|
+
# aligns to 8 bytes to avoid differences in padding... XXX TODO confirm!
|
10
|
+
|
11
|
+
struct :raw_mcontext, MachineContext, :desc => \
|
12
|
+
"The raw pre-translated machine state at the exception interruption "+
|
13
|
+
"point inside the code cache. Clients are cautioned when examining "+
|
14
|
+
"code cache instructions to not rely on any details of code inserted "+
|
15
|
+
"other than their own."
|
16
|
+
|
17
|
+
struct :fault_fragment_info, FaultFragmentInfo, :desc => \
|
18
|
+
"Information about the code fragment inside the code cache at "+
|
19
|
+
"the exception interruption point. "
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Duran
|
2
|
+
# See _dr_fault_fragment_info_t in dr_events.h
|
3
|
+
#
|
4
|
+
# Data structure passed within dr_exception_t, dr_siginfo_t, and
|
5
|
+
# dr_restore_state_info_t.
|
6
|
+
# Contains information about the code fragment inside the code cache
|
7
|
+
# at the exception/signal/translation interruption point.
|
8
|
+
class FaultFragmentInfo < DRYStruct
|
9
|
+
dsl_layout do
|
10
|
+
field :tag, :pointer, :desc => \
|
11
|
+
"The tag of the code fragment inside the code cache at the "+
|
12
|
+
"exception/signal/translation interruption point. NULL for "+
|
13
|
+
"interruption not in the code cache."
|
14
|
+
|
15
|
+
field :cache_start_pc, :pointer, :desc => \
|
16
|
+
"The start address of the code fragment inside the code cache at "+
|
17
|
+
"the exception/signal/translation interruption point. NULL for "+
|
18
|
+
"interruption not in the code cache. "+
|
19
|
+
"Clients are cautioned when examining code cache instructions to not"+
|
20
|
+
"rely on any details of code inserted other than their own. "
|
21
|
+
|
22
|
+
field :is_trace, :bool, :desc => \
|
23
|
+
"Indicates whether the interrupted code fragment is a trace"
|
24
|
+
|
25
|
+
field :app_code_consistent, :bool, :desc => \
|
26
|
+
"Indicates whether the original application code containing the "+
|
27
|
+
"code corresponding to the exception/signal/translation interruption "+
|
28
|
+
"point is guaranteed to still be in the same state it was when the "+
|
29
|
+
"code was placed in the code cache. This guarantee varies "+
|
30
|
+
"depending on the type of cache consistency being used by DR."
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
|
2
|
+
module Duran
|
3
|
+
# Internal structure of instr_t is below abstraction layer, but we
|
4
|
+
# provide its size so that it can be used in stack variables
|
5
|
+
# instead of always allocated on the heap.
|
6
|
+
class Instruction < DRYStruct
|
7
|
+
dsl_layout do
|
8
|
+
if ::Duran::ARCH == :x64
|
9
|
+
array :black_box_uint, [:uint, 26]
|
10
|
+
else
|
11
|
+
array :black_box_uint, [:uint, 16]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
|
2
|
+
module Duran
|
3
|
+
class MachineContext < DRYStruct
|
4
|
+
NUM_XMM_SLOTS =
|
5
|
+
::Duran::ARCH == :x64 ? ( ::Duran::PLATFORM == :windows ? 6 : 16) : 8
|
6
|
+
|
7
|
+
# comment from dr_defines.h:
|
8
|
+
#
|
9
|
+
# The SSE registers xmm0-xmm5 (-xmm15 on Linux) are volatile
|
10
|
+
# (caller-saved) for 64-bit and WOW64, and are actually zeroed out on
|
11
|
+
# Windows system calls. These fields are ignored for 32-bit processes
|
12
|
+
# that are not WOW64, or if the underlying processor does not support
|
13
|
+
# SSE. Use dr_mcontext_xmm_fields_valid() to determine whether the
|
14
|
+
# fields are valid.
|
15
|
+
class XMM_t < FFI::Struct
|
16
|
+
# Really a union, but FFI structs and unions with arrays are lots
|
17
|
+
# of broken so we fake it with our own helper methods.
|
18
|
+
layout :u8_stub, [:uchar, 16]
|
19
|
+
|
20
|
+
def u8
|
21
|
+
self[:u8_stub].to_a
|
22
|
+
end
|
23
|
+
|
24
|
+
def u64
|
25
|
+
self[:u8_stub].to_ptr.get_array_of_uint64(0,2)
|
26
|
+
end
|
27
|
+
|
28
|
+
def u32
|
29
|
+
self[:u8_stub].to_ptr.get_array_of_uint32(0,4)
|
30
|
+
end
|
31
|
+
|
32
|
+
alias_method :reg, (::Duran::ARCH == :x64 ? :u64 : :u32)
|
33
|
+
end
|
34
|
+
|
35
|
+
dsl_layout do
|
36
|
+
field :xdi, :reg_t, :desc => "platform-independent rdi/edi register"
|
37
|
+
field :xsi, :reg_t, :desc => "platform-independent rsi/esi register"
|
38
|
+
field :xbp, :reg_t, :desc => "platform-independent rbp/ebp register"
|
39
|
+
field :xsp, :reg_t, :desc => "platform-independent rsp/esp register"
|
40
|
+
field :xbx, :reg_t, :desc => "platform-independent rbx/ebx register"
|
41
|
+
field :xdx, :reg_t, :desc => "platform-independent rdx/edx register"
|
42
|
+
field :xcx, :reg_t, :desc => "platform-independent rcx/ecx register"
|
43
|
+
field :xax, :reg_t, :desc => "platform-independent rax/eax register"
|
44
|
+
if ::Duran::ARCH == :x64
|
45
|
+
field :r8, :reg_t, :desc => "r8 register"
|
46
|
+
field :r9, :reg_t, :desc => "r9 register"
|
47
|
+
field :r10, :reg_t, :desc => "r10 register"
|
48
|
+
field :r11, :reg_t, :desc => "r11 register"
|
49
|
+
field :r12, :reg_t, :desc => "r12 register"
|
50
|
+
field :r13, :reg_t, :desc => "r13 register"
|
51
|
+
field :r14, :reg_t, :desc => "r14 register"
|
52
|
+
field :r15, :reg_t, :desc => "r15 register"
|
53
|
+
end
|
54
|
+
array :xmm_stub, [:uchar, NUM_XMM_SLOTS*XMM_t.size]
|
55
|
+
field :xflags, :reg_t, :desc => 'platform-independent rflags/eflags register'
|
56
|
+
field :xip, :pointer, :desc => "platform-independent rip/eip register"
|
57
|
+
end
|
58
|
+
|
59
|
+
alias_method :pc, :xip
|
60
|
+
alias_method :pc=, :xip=
|
61
|
+
|
62
|
+
# Create e/r aliases for all the platform-independent register accessors
|
63
|
+
# named based on our architecture.
|
64
|
+
reg_pfx = ::Duran::ARCH == :x64 ? "r" : "e"
|
65
|
+
[:di, :si, :bp, :sp, :bx, :dx, :cx, :ax, :flags, :ip].each do |reg_sfx|
|
66
|
+
alias_method :"#{reg_pfx}#{reg_sfx}", :"x#{reg_sfx}"
|
67
|
+
alias_method :"#{reg_pfx}#{reg_sfx}=", :"x#{reg_sfx}="
|
68
|
+
end
|
69
|
+
|
70
|
+
def xmm
|
71
|
+
off=0
|
72
|
+
Array.new(NUM_XMM_SLOTS) do
|
73
|
+
r = XMM_t.new(self[:xmm_stub].to_ptr+off)
|
74
|
+
off += XMM_t.size
|
75
|
+
r
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Duran
|
2
|
+
enum :mem_type, [:free, :image, :data]
|
3
|
+
|
4
|
+
class MemoryInfo < DRYStruct
|
5
|
+
dsl_layout do
|
6
|
+
field :base_pc, :pointer, :desc => "Starting address of memory region"
|
7
|
+
field :mem_size, :size_t, :desc => "Size of region"
|
8
|
+
field :prot, :uint, :desc => "Protection of region (MEMPROT_* flags)"
|
9
|
+
field :mem_type, :uint, :desc => "Type of region"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
|
2
|
+
module Duran
|
3
|
+
|
4
|
+
class ModuleData < DRYStruct
|
5
|
+
|
6
|
+
class VersionNumber < DRYStruct
|
7
|
+
dsl_layout do
|
8
|
+
field :p2, :ushort
|
9
|
+
field :p1, :ushort
|
10
|
+
field :p4, :ushort
|
11
|
+
field :p3, :ushort
|
12
|
+
end
|
13
|
+
|
14
|
+
def ms
|
15
|
+
to_ptr.get_uint32(0)
|
16
|
+
end
|
17
|
+
|
18
|
+
def ls
|
19
|
+
to_ptr.get_uint32(4)
|
20
|
+
end
|
21
|
+
|
22
|
+
def version
|
23
|
+
to_ptr.get_uint64(0)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
dsl_layout do
|
28
|
+
field :start_addr, :app_pc,
|
29
|
+
:desc => 'starting address of this module'
|
30
|
+
|
31
|
+
field :end_addr, :app_pc,
|
32
|
+
:desc => 'ending address of this module'
|
33
|
+
|
34
|
+
field :entry_point, :app_pc,
|
35
|
+
:desc => 'entry point for this module as specified in the headers'
|
36
|
+
|
37
|
+
field :flags, :uint, :desc => 'Reserved, set to 0'
|
38
|
+
|
39
|
+
struct :names, ModuleNames,
|
40
|
+
:desc => 'struct containing names for this module.'
|
41
|
+
|
42
|
+
field :full_path, :string,
|
43
|
+
:desc => 'full path to the file backing this module'
|
44
|
+
|
45
|
+
if ::Duran::PLATFORM == :windows
|
46
|
+
struct :file_version, VersionNumber,
|
47
|
+
:desc => "file version number from .rsrc section"
|
48
|
+
|
49
|
+
struct :product_version, VersionNumber,
|
50
|
+
:desc => "product version number from .rsrc section"
|
51
|
+
|
52
|
+
field :module_internal_size, :size_t,
|
53
|
+
:desc => "module internal size (from PE headers SizeOfImage)"
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
alias_method :handle, :start_addr
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
|
2
|
+
module Duran
|
3
|
+
class ModuleNames < DRYStruct
|
4
|
+
dsl_layout do
|
5
|
+
field :module_name, :string,
|
6
|
+
:desc => "The name of the module from the PE or ELF header."
|
7
|
+
|
8
|
+
field :file_name, :string,
|
9
|
+
:desc => "The file name used to load this module."
|
10
|
+
|
11
|
+
if PLATFORM == :windows
|
12
|
+
field :exe_name, :string,
|
13
|
+
:desc => "The executable name used to launch the process."
|
14
|
+
|
15
|
+
field :rsrc_name, :string,
|
16
|
+
:desc => "The internal name given to the module in its resource."
|
17
|
+
|
18
|
+
else # :linux
|
19
|
+
field :inode, :uint64, :desc => "The inode of the module mapped in."
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Duran
|
2
|
+
# Internal structure of opnd_t is below abstraction layer
|
3
|
+
# but FFI needs to know field sizes to copy it around
|
4
|
+
class Operand < DRYStruct
|
5
|
+
dsl_layout do
|
6
|
+
if ::Duran::ARCH == :x64
|
7
|
+
field :black_box_uint, :uint
|
8
|
+
field :black_box_uint64, :uint64
|
9
|
+
else
|
10
|
+
array :black_box_uint, [:uint, 3]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
|
2
|
+
module Duran
|
3
|
+
# see _dr_restore_state_info_t in dr_events.h
|
4
|
+
#
|
5
|
+
# Data structure passed to a restore_state_ex event handler (see
|
6
|
+
# dr_register_restore_state_ex_event()). Contains the machine
|
7
|
+
# context at the translation point and other translation
|
8
|
+
# information.
|
9
|
+
class RestoreStateInfo < DRYStruct
|
10
|
+
dsl_layout do
|
11
|
+
struct :mcontext, MachineContext, :desc => \
|
12
|
+
"The application machine state at the translation point."
|
13
|
+
|
14
|
+
field :raw_mcontext_valid, :bool, :desc => \
|
15
|
+
"Whether raw_mcontext is valid."
|
16
|
+
|
17
|
+
struct :raw_mcontext, MachineContext, :desc => \
|
18
|
+
"The raw pre-translated machine state at the translation "+
|
19
|
+
"interruption point inside the code cache. Clients are "+
|
20
|
+
"cautioned when examining code cache instructions to not rely on "+
|
21
|
+
"any details of code inserted other than their own."
|
22
|
+
|
23
|
+
struct :fault_fragment, FaultFragmentInfo, :desc => \
|
24
|
+
"Information about the code fragment inside the code cache "+
|
25
|
+
"at the translation interruption point."
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
@@ -0,0 +1,41 @@
|
|
1
|
+
|
2
|
+
module Duran
|
3
|
+
|
4
|
+
# Data structure passed with a signal event. Contains the machine
|
5
|
+
# context at the signal interruption point and other signal
|
6
|
+
# information.
|
7
|
+
class SignalInfo < DRYStruct
|
8
|
+
dsl_layout do
|
9
|
+
field :sig, :int, :desc => "The signal number."
|
10
|
+
|
11
|
+
field :context, :pointer, :desc => \
|
12
|
+
"The context of the thread receiving the signal."
|
13
|
+
|
14
|
+
struct :mcontext, MachineContext, :desc => \
|
15
|
+
"The application machine state at the signal interruption point."
|
16
|
+
|
17
|
+
struct :raw_mcontext, MachineContext, :desc => \
|
18
|
+
"The raw pre-translated machine state at the signal interruption "+
|
19
|
+
"point inside the code cache. NULL for delayable signals. Clients "+
|
20
|
+
"are cautioned when examining code cache instructions to not rely on "+
|
21
|
+
"any details of code inserted other than their own."
|
22
|
+
|
23
|
+
field :raw_mcontext_valid, :bool, :desc => "Whether raw_context is valid"
|
24
|
+
|
25
|
+
field :access_address, :pointer, :desc => \
|
26
|
+
"For SIGBUS and SIGSEGV, the address whose access caused the signal "+
|
27
|
+
"to be raised (as calculated by DR)."
|
28
|
+
|
29
|
+
field :blocked, :bool, :desc => \
|
30
|
+
"Indicates this signal is blocked. DR_SIGNAL_BYPASS is not allowed, "+
|
31
|
+
"and a second event will be sent if the signal is later delivered to "+
|
32
|
+
"the application. Events are only sent for blocked non-delayable "+
|
33
|
+
"signals, not for delayable signals."
|
34
|
+
|
35
|
+
struct :fault_fragment_info, FaultFragmentInfo, :desc => \
|
36
|
+
"Information about the code fragment inside the code cache "+
|
37
|
+
"at the signal interruption point."
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
|
2
|
+
module Duran
|
3
|
+
class TracedumpFileHeader < DRYStruct
|
4
|
+
dsl_layout do
|
5
|
+
field :version, :int,
|
6
|
+
:desc => "The DynamoRIO version that created the file"
|
7
|
+
|
8
|
+
field :x64, :bool,
|
9
|
+
:desc => "Whether a 64-bit DynamoRIO library created the file."
|
10
|
+
|
11
|
+
field :linkcount_size, :int,
|
12
|
+
:desc => "Size of the linkcount (linkcounts are deprecated)"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class TraceDumpTraceHeader < DRYStruct
|
17
|
+
dsl_layout do
|
18
|
+
field :frag_id, :int, :desc => "Identifier for the trace"
|
19
|
+
field :tag, :app_pc, :desc => "Application address for start of trace"
|
20
|
+
field :cache_start, :app_pc, :desc => "Code cache start address."
|
21
|
+
field :entry_offs, :int, :desc => "Offset into trace of normal entry."
|
22
|
+
field :num_exits, :int, :desc => "Number of exits from the trace."
|
23
|
+
field :code_size, :int, :desc => "Length of the trace in the code cache"
|
24
|
+
field :num_bbs, :uint, :desc => "Number of bbs making up the trace"
|
25
|
+
field :x64, :bool, :desc => "Whether the trace contains 64-bit code"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class TraceDumpStubData < DRYStruct
|
30
|
+
class Count < FFI::Union
|
31
|
+
layout :count32, :uint32, :count64, :uint64
|
32
|
+
|
33
|
+
def count32; self[:count32]; end
|
34
|
+
def count32=(val); self[:count32]=val; end
|
35
|
+
def count64; self[:count64]; end
|
36
|
+
def count64=(val); self[:count64]=val; end
|
37
|
+
end
|
38
|
+
|
39
|
+
dsl_layout do
|
40
|
+
field :cti_offs, :int, :desc => "Offset from the start of the fragment"
|
41
|
+
field :stub_pc, :app_pc, :desc => "Code cache address of the stub"
|
42
|
+
field :target, :app_pc, :desc => "Target of the stub"
|
43
|
+
field :linked, :bool, :desc => "Whether the stub is linked to its target"
|
44
|
+
field :stub_size, :int, :desc => "Length of stub_code array"
|
45
|
+
struct :count, Count , :desc => "32 or 64 bit execution count"
|
46
|
+
field :stub_code, :byte, :desc => "variable sized"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|