├── .gitignore
├── UI
├── Icons
│ └── cache-icon.png
├── TraceDataWindows.cpp
├── Resources.qrc
├── FlatProfileView.h
├── SymbolResolver.h
├── Precompiled.cpp
├── Precompiled.h
├── CacheSimGUIMain.cpp
├── TreeProfileView.ui
├── FlatProfileView.ui
├── TreeProfileView.h
├── CacheSimMainWindow.h
├── NumberFormatters.h
├── AnnotationView.h
├── NumberFormatters.cpp
├── BaseProfileView.h
├── CacheSimMainWindow.ui
├── FlatModel.h
├── TreeModel.h
├── TreeProfileView.cpp
├── TraceTab.h
├── FlatProfileView.cpp
├── ObjectStack.h
├── ObjectStack.cpp
├── TraceData.h
├── CacheSimMainWindow.cpp
├── BaseProfileView.cpp
├── CMakeLists.txt
├── SymbolResolverWindows.cpp
├── TraceTab.ui
├── FlatModel.cpp
├── AnnotationView.cpp
├── TraceTab.cpp
├── TreeModel.cpp
└── SymbolResolverLinux.cpp
├── .gitmodules
├── CacheSim
├── PlatformLinux.cpp
├── PlatformWindows.cpp
├── Platform.h
├── Precompiled.cpp
├── Precompiled.h
├── Md5.h
├── CMakeLists.txt
├── CacheSimInternals.cpp
├── CacheSimData.h
├── CacheSimInternals.h
└── CacheSim.h
├── Examples
├── CMakeLists.txt
├── ThreadedExample
│ ├── CMakeLists.txt
│ └── ThreadedExample.cpp
└── HelloWorld
│ ├── CMakeLists.txt
│ └── HelloWorld.cpp
├── udis86
├── udis86.h
├── CMakeLists.txt
├── syn.h
├── udint.h
├── extern.h
├── decode.h
├── syn-att.c
├── syn.c
├── syn-intel.c
└── types.h
├── CMakeLists.txt
├── UnitTest
├── CMakeLists.txt
└── TestCacheSim.cpp
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | build
2 |
--------------------------------------------------------------------------------
/UI/Icons/cache-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/InsomniacGames/ig-cachesim/HEAD/UI/Icons/cache-icon.png
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "googletest"]
2 | path = googletest
3 | url = https://github.com/google/googletest.git
4 |
--------------------------------------------------------------------------------
/UI/TraceDataWindows.cpp:
--------------------------------------------------------------------------------
1 | #include "Precompiled.h"
2 | #include "CacheSim/CacheSimData.h"
3 | #include "TraceData.h"
4 |
5 |
--------------------------------------------------------------------------------
/UI/Resources.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | Icons/cache-icon.png
4 |
5 |
6 |
--------------------------------------------------------------------------------
/CacheSim/PlatformLinux.cpp:
--------------------------------------------------------------------------------
1 | #include "Platform.h"
2 | #include
3 |
4 | void* VirtualMemoryAlloc(size_t size)
5 | {
6 | return mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
7 | }
8 |
9 | void VirtualMemoryFree(void* data, size_t size)
10 | {
11 | munmap(data, size);
12 | }
13 |
--------------------------------------------------------------------------------
/CacheSim/PlatformWindows.cpp:
--------------------------------------------------------------------------------
1 | #include "Platform.h"
2 | #include
3 |
4 | void* VirtualMemoryAlloc(size_t size)
5 | {
6 | return VirtualAlloc(nullptr, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
7 | }
8 |
9 | void VirtualMemoryFree(void* data, size_t size)
10 | {
11 | (void)size;
12 | VirtualFree(data, 0, MEM_RELEASE);
13 | }
14 |
--------------------------------------------------------------------------------
/CacheSim/Platform.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | void* VirtualMemoryAlloc(size_t size);
6 | void VirtualMemoryFree(void* data, size_t size);
7 |
8 | inline void* VirtualMemoryRealloc(void* old_data, size_t old_size, size_t new_size)
9 | {
10 | size_t copy_length = (old_size < new_size) ? old_size : new_size;
11 |
12 | void* new_data = VirtualMemoryAlloc(new_size);
13 | memcpy(new_data, old_data, copy_length);
14 |
15 | VirtualMemoryFree(old_data, old_size);
16 | return new_data;
17 | }
--------------------------------------------------------------------------------
/UI/FlatProfileView.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "Precompiled.h"
3 | #include "BaseProfileView.h"
4 |
5 | class Ui_FlatProfileView;
6 |
7 | namespace CacheSim
8 | {
9 | struct SerializedNode;
10 | class TraceData;
11 | class FlatModel;
12 |
13 | class FlatProfileView : public BaseProfileView
14 | {
15 | Q_OBJECT;
16 |
17 | public:
18 | explicit FlatProfileView(const TraceData* traceData, QWidget* parent = nullptr);
19 | ~FlatProfileView();
20 |
21 | private:
22 | Q_SLOT void filterTextEdited();
23 |
24 | private:
25 | const TraceData* m_TraceData;
26 | FlatModel* m_Model = nullptr;
27 | QSortFilterProxyModel* m_FlatProxy = nullptr;
28 | Ui_FlatProfileView* ui;
29 | };
30 | }
--------------------------------------------------------------------------------
/UI/SymbolResolver.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Precompiled.h"
4 | #include "CacheSim/CacheSimData.h"
5 |
6 | #include
7 |
8 | namespace CacheSim
9 | {
10 | struct UnresolvedAddressData
11 | {
12 | const SerializedModuleEntry* m_Modules = nullptr;
13 | const QString* m_ModuleNames = nullptr;
14 | uint32_t m_ModuleCount = 0;
15 | const uintptr_t* m_Stacks = nullptr;
16 | uint32_t m_StackCount = 0;
17 | const SerializedNode* m_Nodes = nullptr;
18 | uint32_t m_NodeCount = 0;
19 | };
20 |
21 | struct ResolvedSymbol
22 | {
23 | uintptr_t m_Rip;
24 | QString m_FileName;
25 | QString m_SymbolName;
26 | uint32_t m_ModuleIndex;
27 | uint32_t m_LineNumber;
28 | uint32_t m_Displacement;
29 | };
30 |
31 | using SymbolResolveProgressCallbackType = std::function;
32 |
33 | bool ResolveSymbols(const UnresolvedAddressData& input, QVector* resolvedSymbolsOut, SymbolResolveProgressCallbackType reportProgress);
34 | }
--------------------------------------------------------------------------------
/UI/Precompiled.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017, Insomniac Games
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | Redistributions in binary form must reproduce the above copyright notice, this
12 | list of conditions and the following disclaimer in the documentation and/or
13 | other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #include "Precompiled.h"
28 |
--------------------------------------------------------------------------------
/CacheSim/Precompiled.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017, Insomniac Games
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | Redistributions in binary form must reproduce the above copyright notice, this
12 | list of conditions and the following disclaimer in the documentation and/or
13 | other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #include "Precompiled.h"
28 |
--------------------------------------------------------------------------------
/Examples/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2017, Insomniac Games
2 | #
3 | # All rights reserved.
4 | #
5 | # Redistribution and use in source and binary forms, with or without
6 | # modification, are permitted provided that the following conditions are met:
7 | #
8 | # Redistributions of source code must retain the above copyright notice, this
9 | # list of conditions and the following disclaimer.
10 | #
11 | # Redistributions in binary form must reproduce the above copyright notice, this
12 | # list of conditions and the following disclaimer in the documentation and/or
13 | # other materials provided with the distribution.
14 | #
15 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
26 | add_subdirectory(HelloWorld)
27 | add_subdirectory(ThreadedExample)
28 |
--------------------------------------------------------------------------------
/CacheSim/Precompiled.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | /*
4 | Copyright (c) 2017, Insomniac Games
5 | All rights reserved.
6 |
7 | Redistribution and use in source and binary forms, with or without
8 | modification, are permitted provided that the following conditions are met:
9 |
10 | Redistributions of source code must retain the above copyright notice, this
11 | list of conditions and the following disclaimer.
12 |
13 | Redistributions in binary form must reproduce the above copyright notice, this
14 | list of conditions and the following disclaimer in the documentation and/or
15 | other materials provided with the distribution.
16 |
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
21 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | #if defined(_MSC_VER)
30 | #include
31 | #endif
32 | #include
33 | #include
34 | #include
35 |
--------------------------------------------------------------------------------
/UI/Precompiled.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017, Insomniac Games
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | Redistributions in binary form must reproduce the above copyright notice, this
12 | list of conditions and the following disclaimer in the documentation and/or
13 | other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #pragma once
28 |
29 | #if defined(_MSC_VER)
30 | #include
31 | #endif
32 |
33 | #include
34 | #include
35 | #include
36 | #include
37 |
38 | #include
39 |
--------------------------------------------------------------------------------
/udis86/udis86.h:
--------------------------------------------------------------------------------
1 | /* udis86 - udis86.h
2 | *
3 | * Copyright (c) 2002-2009 Vivek Thampi
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without modification,
7 | * are permitted provided that the following conditions are met:
8 | *
9 | * * Redistributions of source code must retain the above copyright notice,
10 | * this list of conditions and the following disclaimer.
11 | * * Redistributions in binary form must reproduce the above copyright notice,
12 | * this list of conditions and the following disclaimer in the documentation
13 | * and/or other materials provided with the distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 | #ifndef UDIS86_H
27 | #define UDIS86_H
28 |
29 | #include "types.h"
30 | #include "extern.h"
31 | #include "itab.h"
32 |
33 | #endif
34 |
--------------------------------------------------------------------------------
/UI/CacheSimGUIMain.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017, Insomniac Games
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | Redistributions in binary form must reproduce the above copyright notice, this
12 | list of conditions and the following disclaimer in the documentation and/or
13 | other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #include "Precompiled.h"
28 | #include "CacheSimMainWindow.h"
29 |
30 | int main(int argc, char** argv)
31 | {
32 | (void)(argv, argc);
33 | int qargc = 0;
34 | QApplication app(qargc, nullptr);
35 | CacheSim::MainWindow mainWindow;
36 | mainWindow.setVisible(true);
37 | return app.exec();
38 | }
39 |
--------------------------------------------------------------------------------
/udis86/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2017, Insomniac Games
2 | #
3 | # All rights reserved.
4 | #
5 | # Redistribution and use in source and binary forms, with or without
6 | # modification, are permitted provided that the following conditions are met:
7 | #
8 | # Redistributions of source code must retain the above copyright notice, this
9 | # list of conditions and the following disclaimer.
10 | #
11 | # Redistributions in binary form must reproduce the above copyright notice, this
12 | # list of conditions and the following disclaimer in the documentation and/or
13 | # other materials provided with the distribution.
14 | #
15 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
26 | add_library(udis86 SHARED
27 | decode.c
28 | itab.c
29 | syn.c
30 | syn-att.c
31 | syn-intel.c
32 | udis86.c)
33 |
34 | target_compile_definitions(udis86
35 | PUBLIC "_USRDLL"
36 | PRIVATE "LIBUDIS86_EXPORTS" "_USRDLL")
37 |
38 | set_target_properties(udis86 PROPERTIES FOLDER "CacheSim")
39 |
--------------------------------------------------------------------------------
/UI/TreeProfileView.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | TreeProfileView
4 |
5 |
6 |
7 | 0
8 | 0
9 | 561
10 | 430
11 |
12 |
13 |
14 | Form
15 |
16 |
17 | -
18 |
19 |
20 | true
21 |
22 |
23 | QAbstractItemView::SingleSelection
24 |
25 |
26 | QAbstractItemView::SelectRows
27 |
28 |
29 | QAbstractItemView::ScrollPerPixel
30 |
31 |
32 | QAbstractItemView::ScrollPerPixel
33 |
34 |
35 | true
36 |
37 |
38 | true
39 |
40 |
41 | false
42 |
43 |
44 |
45 | -
46 |
47 |
48 | Type to filter...
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2017, Insomniac Games
2 | #
3 | # All rights reserved.
4 | #
5 | # Redistribution and use in source and binary forms, with or without
6 | # modification, are permitted provided that the following conditions are met:
7 | #
8 | # Redistributions of source code must retain the above copyright notice, this
9 | # list of conditions and the following disclaimer.
10 | #
11 | # Redistributions in binary form must reproduce the above copyright notice, this
12 | # list of conditions and the following disclaimer in the documentation and/or
13 | # other materials provided with the distribution.
14 | #
15 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
26 | cmake_minimum_required(VERSION 3.4)
27 |
28 | project(CacheSim VERSION 1.0 LANGUAGES C CXX)
29 |
30 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
31 |
32 | set_property(GLOBAL PROPERTY USE_FOLDERS ON)
33 |
34 | add_subdirectory(udis86)
35 | add_subdirectory(CacheSim)
36 | add_subdirectory(UI)
37 | add_subdirectory(UnitTest)
38 |
39 | add_subdirectory(Examples)
40 |
--------------------------------------------------------------------------------
/UI/FlatProfileView.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | FlatProfileView
4 |
5 |
6 |
7 | 0
8 | 0
9 | 561
10 | 430
11 |
12 |
13 |
14 | Form
15 |
16 |
17 | -
18 |
19 |
20 | true
21 |
22 |
23 | QAbstractItemView::SingleSelection
24 |
25 |
26 | QAbstractItemView::SelectRows
27 |
28 |
29 | QAbstractItemView::ScrollPerPixel
30 |
31 |
32 | QAbstractItemView::ScrollPerPixel
33 |
34 |
35 | true
36 |
37 |
38 | false
39 |
40 |
41 | false
42 |
43 |
44 | false
45 |
46 |
47 |
48 | -
49 |
50 |
51 | Type to filter...
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/Examples/ThreadedExample/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2017, Insomniac Games
2 | #
3 | # All rights reserved.
4 | #
5 | # Redistribution and use in source and binary forms, with or without
6 | # modification, are permitted provided that the following conditions are met:
7 | #
8 | # Redistributions of source code must retain the above copyright notice, this
9 | # list of conditions and the following disclaimer.
10 | #
11 | # Redistributions in binary form must reproduce the above copyright notice, this
12 | # list of conditions and the following disclaimer in the documentation and/or
13 | # other materials provided with the distribution.
14 | #
15 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
26 | add_executable(ThreadedExample
27 | ThreadedExample.cpp)
28 |
29 | target_include_directories(ThreadedExample
30 | PRIVATE "${CMAKE_SOURCE_DIR}"
31 | )
32 |
33 | if (UNIX)
34 | target_compile_options(ThreadedExample PRIVATE "-std=c++11" -g -pthread)
35 | target_link_libraries(ThreadedExample LINK_PRIVATE dl pthread)
36 | set_target_properties(ThreadedExample PROPERTIES LINK_FLAGS ${LINK_FLAGS} -Wl,--no-as-needed)
37 | endif (UNIX)
38 |
39 | set_target_properties(ThreadedExample PROPERTIES FOLDER "Examples")
40 |
--------------------------------------------------------------------------------
/Examples/HelloWorld/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2017, Insomniac Games
2 | #
3 | # All rights reserved.
4 | #
5 | # Redistribution and use in source and binary forms, with or without
6 | # modification, are permitted provided that the following conditions are met:
7 | #
8 | # Redistributions of source code must retain the above copyright notice, this
9 | # list of conditions and the following disclaimer.
10 | #
11 | # Redistributions in binary form must reproduce the above copyright notice, this
12 | # list of conditions and the following disclaimer in the documentation and/or
13 | # other materials provided with the distribution.
14 | #
15 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
26 | add_executable(HelloWorldExample
27 | HelloWorld.cpp)
28 |
29 | target_include_directories(HelloWorldExample
30 | PRIVATE "${CMAKE_SOURCE_DIR}"
31 | )
32 |
33 | if (UNIX)
34 | target_compile_options(HelloWorldExample PRIVATE "-std=c++11" -g -pthread)
35 | target_link_libraries(HelloWorldExample LINK_PRIVATE dl pthread)
36 | set_target_properties(HelloWorldExample PROPERTIES LINK_FLAGS ${LINK_FLAGS} -Wl,--no-as-needed)
37 | endif (UNIX)
38 |
39 | set_target_properties(HelloWorldExample PROPERTIES FOLDER "Examples")
40 |
--------------------------------------------------------------------------------
/UI/TreeProfileView.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017, Insomniac Games
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | Redistributions in binary form must reproduce the above copyright notice, this
12 | list of conditions and the following disclaimer in the documentation and/or
13 | other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #pragma once
28 | #include "Precompiled.h"
29 | #include "BaseProfileView.h"
30 |
31 | class Ui_TreeProfileView;
32 |
33 | namespace CacheSim
34 | {
35 | class TreeModel;
36 |
37 | class TreeProfileView : public BaseProfileView
38 | {
39 | Q_OBJECT;
40 |
41 | public:
42 | explicit TreeProfileView(TreeModel* model, QWidget* parent = nullptr);
43 | ~TreeProfileView();
44 |
45 | private:
46 | Q_SLOT void filterTextEdited();
47 |
48 | private:
49 | TreeModel* m_Model = nullptr;
50 | QSortFilterProxyModel* m_FilterProxy = nullptr;
51 | Ui_TreeProfileView* ui;
52 | };
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/CacheSim/Md5.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | /*
4 | Copyright (c) 2017, Insomniac Games
5 | All rights reserved.
6 |
7 | Redistribution and use in source and binary forms, with or without
8 | modification, are permitted provided that the following conditions are met:
9 |
10 | Redistributions of source code must retain the above copyright notice, this
11 | list of conditions and the following disclaimer.
12 |
13 | Redistributions in binary form must reproduce the above copyright notice, this
14 | list of conditions and the following disclaimer in the documentation and/or
15 | other materials provided with the distribution.
16 |
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
21 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | typedef unsigned char md5_byte_t; /*!< 8-bit byte */
30 | typedef unsigned int md5_word_t; /*!< 32-bit word */
31 |
32 | /*! Define the state of the MD5 Algorithm. */
33 | typedef struct md5_state_s
34 | {
35 | md5_word_t count[2]; /*!< message length in bits, lsw first */
36 | md5_word_t abcd[4]; /*!< digest buffer */
37 | md5_byte_t buf[64]; /*!< accumulate block */
38 | } md5_state_t;
39 |
40 | void md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/);
41 | void md5_init(md5_state_t *pms);
42 | void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
43 | void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
44 |
--------------------------------------------------------------------------------
/Examples/HelloWorld/HelloWorld.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017, Insomniac Games
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | Redistributions in binary form must reproduce the above copyright notice, this
12 | list of conditions and the following disclaimer in the documentation and/or
13 | other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | // HelloWorld.cpp - the simplest possible demo example of CacheSim
28 |
29 | #include "CacheSim/CacheSim.h"
30 | #include
31 |
32 | int main(int argc, char* argv[])
33 | {
34 | CacheSim::DynamicLoader cachesim;
35 |
36 | if (!cachesim.Init())
37 | return 1;
38 |
39 | // This needs to happen to map win32 thread ids to physical cores for cache simulation.
40 | // If a thread is not mapped, it will not be simulated.
41 | cachesim.SetThreadCoreMapping(cachesim.GetCurrentThreadId(), 0);
42 |
43 | cachesim.Start();
44 |
45 | printf("Hello, world (with cache simulation)!\n");
46 |
47 | cachesim.End();
48 |
49 | return 0;
50 | }
51 |
--------------------------------------------------------------------------------
/UI/CacheSimMainWindow.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017, Insomniac Games
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | Redistributions in binary form must reproduce the above copyright notice, this
12 | list of conditions and the following disclaimer in the documentation and/or
13 | other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #pragma once
28 |
29 | #include "Precompiled.h"
30 | #include "ui_CacheSimMainWindow.h"
31 |
32 | namespace CacheSim
33 | {
34 |
35 | class MainWindow : public QMainWindow, private Ui_CacheSimMainWindow
36 | {
37 | Q_OBJECT;
38 |
39 | public:
40 | explicit MainWindow(QWidget* parent = nullptr);
41 | ~MainWindow();
42 |
43 | public:
44 | Q_SLOT void openTrace();
45 | Q_SLOT void closeTrace();
46 |
47 | void closeEvent(QCloseEvent* ev) override;
48 |
49 | private:
50 | Q_SLOT void longTaskStarted(int id, QString description);
51 | Q_SLOT void longTaskFinished(int id);
52 |
53 | int m_LatestTask = -1;
54 | int m_TasksRunning = 0;
55 |
56 | };
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/UI/NumberFormatters.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017, Insomniac Games
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | Redistributions in binary form must reproduce the above copyright notice, this
12 | list of conditions and the following disclaimer in the documentation and/or
13 | other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #pragma once
28 | #include "Precompiled.h"
29 |
30 | namespace CacheSim
31 | {
32 | class DecimalFormatDelegate : public QStyledItemDelegate
33 | {
34 | private:
35 | QLocale m_Locale;
36 |
37 | public:
38 | explicit DecimalFormatDelegate(QObject* parent = nullptr);
39 |
40 | QString displayText(const QVariant &value, const QLocale &locale) const override;
41 | };
42 |
43 | class IntegerFormatDelegate : public QStyledItemDelegate
44 | {
45 | QLocale m_Locale;
46 |
47 | public:
48 | explicit IntegerFormatDelegate(QObject* parent = nullptr);
49 |
50 | QString displayText(const QVariant &value, const QLocale &locale) const override;
51 | };
52 | }
53 |
--------------------------------------------------------------------------------
/UnitTest/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2017, Insomniac Games
2 | #
3 | # All rights reserved.
4 | #
5 | # Redistribution and use in source and binary forms, with or without
6 | # modification, are permitted provided that the following conditions are met:
7 | #
8 | # Redistributions of source code must retain the above copyright notice, this
9 | # list of conditions and the following disclaimer.
10 | #
11 | # Redistributions in binary form must reproduce the above copyright notice, this
12 | # list of conditions and the following disclaimer in the documentation and/or
13 | # other materials provided with the distribution.
14 | #
15 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
26 | add_executable(CacheSimUnitTest
27 | TestCacheSim.cpp)
28 |
29 |
30 | target_include_directories(CacheSimUnitTest
31 | PRIVATE
32 | "${CMAKE_SOURCE_DIR}/googletest/googletest"
33 | "${CMAKE_SOURCE_DIR}/googletest/googletest/src"
34 | "${CMAKE_SOURCE_DIR}/googletest/googletest/include"
35 | "${CMAKE_SOURCE_DIR}")
36 |
37 | if (UNIX)
38 | target_compile_options(CacheSimUnitTest PRIVATE "-std=c++11" -g -pthread)
39 | target_link_libraries(CacheSimUnitTest LINK_PRIVATE CacheSim udis86)
40 | else (UNIX)
41 | target_link_libraries(CacheSimUnitTest CacheSim udis86)
42 | endif (UNIX)
43 |
44 |
45 | set_target_properties(CacheSimUnitTest PROPERTIES FOLDER "Unit Tests")
46 |
--------------------------------------------------------------------------------
/UI/AnnotationView.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017, Insomniac Games
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | Redistributions in binary form must reproduce the above copyright notice, this
12 | list of conditions and the following disclaimer in the documentation and/or
13 | other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #pragma once
28 |
29 | #include "Precompiled.h"
30 | #include "TraceData.h"
31 |
32 | namespace CacheSim
33 | {
34 |
35 | class AnnotationView : public QWidget
36 | {
37 | using Base = QWidget;
38 |
39 | public:
40 | explicit AnnotationView(TraceData::FileInfo fileInfo, QWidget* parent = nullptr);
41 | ~AnnotationView();
42 |
43 | public:
44 | bool event(QEvent* ev) override;
45 |
46 | private:
47 | void paintEvent(QPaintEvent *event) override;
48 |
49 | int lineAtPosition(const QPoint& point);
50 |
51 | private:
52 | int m_GutterWidth = 0;
53 | TraceData::FileInfo m_FileInfo;
54 |
55 | struct LineInfo
56 | {
57 | QString m_Text;
58 | int m_SampleIndex = -1;
59 | };
60 | QVector m_Lines;
61 | QLocale m_Locale;
62 | };
63 | }
64 |
--------------------------------------------------------------------------------
/udis86/syn.h:
--------------------------------------------------------------------------------
1 | /* udis86 - libudis86/syn.h
2 | *
3 | * Copyright (c) 2002-2009
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without modification,
7 | * are permitted provided that the following conditions are met:
8 | *
9 | * * Redistributions of source code must retain the above copyright notice,
10 | * this list of conditions and the following disclaimer.
11 | * * Redistributions in binary form must reproduce the above copyright notice,
12 | * this list of conditions and the following disclaimer in the documentation
13 | * and/or other materials provided with the distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 | #ifndef UD_SYN_H
27 | #define UD_SYN_H
28 |
29 | #include "types.h"
30 | #ifndef __UD_STANDALONE__
31 | # include
32 | #endif /* __UD_STANDALONE__ */
33 |
34 | extern const char* ud_reg_tab[];
35 |
36 | uint64_t ud_syn_rel_target(struct ud*, struct ud_operand*);
37 |
38 | #ifdef __GNUC__
39 | int ud_asmprintf(struct ud *u, const char *fmt, ...)
40 | __attribute__ ((format (printf, 2, 3)));
41 | #else
42 | int ud_asmprintf(struct ud *u, const char *fmt, ...);
43 | #endif
44 |
45 | void ud_syn_print_addr(struct ud *u, uint64_t addr);
46 | void ud_syn_print_imm(struct ud* u, const struct ud_operand *op);
47 | void ud_syn_print_mem_disp(struct ud* u, const struct ud_operand *, int sign);
48 |
49 | #endif /* UD_SYN_H */
50 |
51 | /*
52 | vim: set ts=2 sw=2 expandtab
53 | */
54 |
--------------------------------------------------------------------------------
/UI/NumberFormatters.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017, Insomniac Games
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | Redistributions in binary form must reproduce the above copyright notice, this
12 | list of conditions and the following disclaimer in the documentation and/or
13 | other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #include "Precompiled.h"
28 | #include "NumberFormatters.h"
29 |
30 | CacheSim::DecimalFormatDelegate::DecimalFormatDelegate(QObject* parent /*= nullptr*/)
31 | : QStyledItemDelegate(parent)
32 | , m_Locale(QLocale::system())
33 | {
34 | m_Locale.setNumberOptions(QLocale::DefaultNumberOptions);
35 | }
36 |
37 | QString CacheSim::DecimalFormatDelegate::displayText(const QVariant &value, const QLocale &locale) const
38 | {
39 | (void)locale;
40 | return m_Locale.toString(value.toDouble(), 'f', 2);
41 | }
42 |
43 | CacheSim::IntegerFormatDelegate::IntegerFormatDelegate(QObject* parent /*= nullptr*/)
44 | : QStyledItemDelegate(parent)
45 | , m_Locale(QLocale::system())
46 | {
47 | m_Locale.setNumberOptions(QLocale::DefaultNumberOptions);
48 | }
49 |
50 | QString CacheSim::IntegerFormatDelegate::displayText(const QVariant &value, const QLocale &locale) const
51 | {
52 | (void)locale;
53 | return m_Locale.toString(value.toUInt());
54 | }
55 |
--------------------------------------------------------------------------------
/UI/BaseProfileView.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017, Insomniac Games
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | Redistributions in binary form must reproduce the above copyright notice, this
12 | list of conditions and the following disclaimer in the documentation and/or
13 | other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #pragma once
28 | #include "Precompiled.h"
29 |
30 | namespace CacheSim
31 | {
32 | class BaseProfileView : public QWidget
33 | {
34 | Q_OBJECT;
35 |
36 | protected:
37 | explicit BaseProfileView(QWidget* parent = nullptr);
38 | ~BaseProfileView();
39 |
40 | protected:
41 | QAction* showReverseAction() const { return m_ShowReverseAction; }
42 | QAction* annotateAction() const { return m_AnnotateAction; }
43 |
44 | public:
45 | Q_SIGNAL void showReverse(QString symbolName);
46 | Q_SIGNAL void annotateSymbol(QString symbolName);
47 |
48 | protected:
49 | void setItemView(QAbstractItemView* view);
50 |
51 | private:
52 | Q_SLOT void showReverseTriggered();
53 | Q_SLOT void annotateTriggered();
54 | Q_SLOT void customContextMenuRequested(const QPoint &pos);
55 |
56 | private:
57 | QString selectedSymbol() const;
58 |
59 | private:
60 | QAbstractItemView* m_ItemView = nullptr;
61 | QAction* m_ShowReverseAction = nullptr;
62 | QAction* m_AnnotateAction = nullptr;
63 | };
64 | }
65 |
--------------------------------------------------------------------------------
/UI/CacheSimMainWindow.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | CacheSimMainWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 811
10 | 812
11 |
12 |
13 |
14 | CacheSim GUI
15 |
16 |
17 |
18 | :/CacheSim/Icons/Icons/cache-icon.png:/CacheSim/Icons/Icons/cache-icon.png
19 |
20 |
21 |
22 |
23 | 2
24 |
25 |
26 | 2
27 |
28 |
29 | 2
30 |
31 |
32 | 2
33 |
34 | -
35 |
36 |
37 | -1
38 |
39 |
40 | true
41 |
42 |
43 | true
44 |
45 |
46 | true
47 |
48 |
49 |
50 |
51 |
52 |
70 |
71 |
72 |
73 | &Open Trace
74 |
75 |
76 | Ctrl+O
77 |
78 |
79 |
80 |
81 | Quit
82 |
83 |
84 | Ctrl+Q
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/UI/FlatModel.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017, Insomniac Games
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | Redistributions in binary form must reproduce the above copyright notice, this
12 | list of conditions and the following disclaimer in the documentation and/or
13 | other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #pragma once
28 | #include "Precompiled.h"
29 | #include "CacheSim/CacheSimInternals.h"
30 |
31 | namespace CacheSim
32 | {
33 | class TraceData;
34 |
35 | class FlatModel final : public QAbstractListModel
36 | {
37 | Q_OBJECT;
38 |
39 | public:
40 | enum Column
41 | {
42 | kColumnSymbol,
43 | kColumnD1Hit,
44 | kColumnI1Hit,
45 | kColumnL2IMiss,
46 | kColumnL2DMiss,
47 | kColumnBadness,
48 | kColumnInstructionsExecuted,
49 | kColumnPFD1,
50 | kColumnPFL2,
51 | kColumnCount
52 | };
53 |
54 | public:
55 | explicit FlatModel(QObject* parent = nullptr);
56 | ~FlatModel();
57 |
58 | public:
59 | void setData(const TraceData* data);
60 |
61 | int rowCount(const QModelIndex &parent = QModelIndex()) const override;
62 | int columnCount(const QModelIndex &parent = QModelIndex()) const override;
63 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
64 | QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
65 |
66 | private:
67 | Q_SLOT void dataStoreChanged();
68 |
69 | private:
70 | const TraceData* m_Data = nullptr;
71 |
72 | struct Node
73 | {
74 | Node();
75 |
76 | QString m_SymbolName;
77 | uint32_t m_Stats[CacheSim::kAccessResultCount];
78 | };
79 |
80 | QVector m_Rows;
81 | };
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/UI/TreeModel.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017, Insomniac Games
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | Redistributions in binary form must reproduce the above copyright notice, this
12 | list of conditions and the following disclaimer in the documentation and/or
13 | other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #pragma once
28 | #include "Precompiled.h"
29 |
30 | namespace CacheSim
31 | {
32 | class TraceData;
33 | class ObjectStack;
34 |
35 | class TreeModel : public QAbstractItemModel
36 | {
37 | Q_OBJECT;
38 |
39 | public:
40 | enum Column
41 | {
42 | kColumnSymbol,
43 | kColumnFileName,
44 | kColumnD1Hit,
45 | kColumnI1Hit,
46 | kColumnL2IMiss,
47 | kColumnL2DMiss,
48 | kColumnBadness,
49 | kColumnInstructionsExecuted,
50 | kColumnPFD1,
51 | kColumnPFL2,
52 | kColumnCount
53 | };
54 |
55 | public:
56 | explicit TreeModel(QObject* parent = nullptr);
57 | ~TreeModel();
58 |
59 | QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
60 | QModelIndex parent(const QModelIndex &child) const override;
61 | int rowCount(const QModelIndex &parent = QModelIndex()) const override;
62 | int columnCount(const QModelIndex &parent = QModelIndex()) const override;
63 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
64 | QVariant headerData(int section, Qt::Orientation orientation, int role /*= Qt::DisplayRole*/) const override;
65 |
66 | public:
67 | void setTraceData(const TraceData* traceData, QString rootSymbol = QString::null);
68 |
69 | private:
70 | class Node;
71 | Node* createTree(const TraceData* traceData, QString rootSymbol);
72 |
73 |
74 | private:
75 | ObjectStack* m_Allocator = nullptr;
76 | Node* m_RootNode = nullptr;
77 | };
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/CacheSim/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2017, Insomniac Games
2 | # All rights reserved.
3 | #
4 | # Redistribution and use in source and binary forms, with or without
5 | # modification, are permitted provided that the following conditions are met:
6 | #
7 | # Redistributions of source code must retain the above copyright notice, this
8 | # list of conditions and the following disclaimer.
9 | #
10 | # Redistributions in binary form must reproduce the above copyright notice, this
11 | # list of conditions and the following disclaimer in the documentation and/or
12 | # other materials provided with the distribution.
13 | #
14 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 |
25 | set(SRC_FILES
26 | CacheSim.h
27 | CacheSimCommon.inl
28 | CacheSimData.h
29 | CacheSimInternals.cpp
30 | CacheSimInternals.h
31 | GenericHashTable.h
32 | Md5.cpp
33 | Md5.h
34 | Platform.h
35 | Precompiled.cpp
36 | Precompiled.h
37 | ../README.md
38 | )
39 |
40 | set_source_files_properties(../README.md CacheSimCommon.inl PROPERTIES HEADER_FILE_ONLY TRUE)
41 |
42 | set(LIB_LIST udis86)
43 |
44 | if ( MSVC )
45 | set(SRC_FILES ${SRC_FILES} CacheSimWindows.cpp PlatformWindows.cpp)
46 | else ( MSVC )
47 | set(SRC_FILES ${SRC_FILES} CacheSimLinux.cpp PlatformLinux.cpp )
48 | endif (MSVC)
49 |
50 | add_library(CacheSim SHARED ${SRC_FILES})
51 |
52 | if (MSVC)
53 | target_compile_definitions(CacheSim
54 | INTERFACE "IG_CACHESIM_API=__declspec(dllimport)"
55 | PRIVATE "IG_CACHESIM_API=__declspec(dllexport)" "NOMINMAX" "WIN32_LEAN_AND_MEAN" "_CRT_SECURE_NO_WARNINGS")
56 | target_compile_options(CacheSim
57 | PRIVATE "/W4")
58 | else (MSVC)
59 | set(LIB_LIST ${LIB_LIST} dl pthread)
60 | target_compile_options(CacheSim PRIVATE
61 | "-std=c++11"
62 | -g
63 | -fvisibility=hidden)
64 | target_compile_definitions(CacheSim
65 | INTERFACE ""
66 | PRIVATE "IG_CACHESIM_API=__attribute__ ((visibility (\"default\")))")
67 | set(CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS} -Wl,-zdefs)
68 | endif (MSVC)
69 |
70 | target_link_libraries(CacheSim ${LIB_LIST})
71 | target_include_directories(CacheSim PRIVATE "${CMAKE_SOURCE_DIR}")
72 | set_target_properties(CacheSim PROPERTIES FOLDER "CacheSim")
73 |
--------------------------------------------------------------------------------
/UI/TreeProfileView.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017, Insomniac Games
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | Redistributions in binary form must reproduce the above copyright notice, this
12 | list of conditions and the following disclaimer in the documentation and/or
13 | other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #include "Precompiled.h"
28 | #include "TreeProfileView.h"
29 | #include "NumberFormatters.h"
30 | #include "TreeModel.h"
31 |
32 | #include "ui_TreeProfileView.h"
33 |
34 | CacheSim::TreeProfileView::TreeProfileView(TreeModel* model, QWidget* parent /*= nullptr*/)
35 | : BaseProfileView(parent)
36 | , m_Model(model)
37 | , m_FilterProxy(new QSortFilterProxyModel(this))
38 | , ui(new Ui_TreeProfileView)
39 | {
40 | ui->setupUi(this);
41 |
42 | setItemView(ui->m_TreeView);
43 |
44 | m_FilterProxy->setSourceModel(m_Model);
45 |
46 | DecimalFormatDelegate* decimalDelegate = new DecimalFormatDelegate(this);
47 | IntegerFormatDelegate* integerDelegate = new IntegerFormatDelegate(this);
48 | QTreeView* treeView = ui->m_TreeView;
49 | treeView->setItemDelegateForColumn(TreeModel::kColumnBadness, decimalDelegate);
50 | treeView->setItemDelegateForColumn(TreeModel::kColumnD1Hit, integerDelegate);
51 | treeView->setItemDelegateForColumn(TreeModel::kColumnI1Hit, integerDelegate);
52 | treeView->setItemDelegateForColumn(TreeModel::kColumnL2IMiss, integerDelegate);
53 | treeView->setItemDelegateForColumn(TreeModel::kColumnL2DMiss, integerDelegate);
54 | treeView->setItemDelegateForColumn(TreeModel::kColumnInstructionsExecuted, integerDelegate);
55 |
56 | treeView->setModel(m_FilterProxy);
57 | treeView->sortByColumn(TreeModel::kColumnL2DMiss, Qt::DescendingOrder);
58 |
59 | connect(ui->m_Filter, &QLineEdit::textChanged, this, &TreeProfileView::filterTextEdited);
60 | }
61 |
62 | CacheSim::TreeProfileView::~TreeProfileView()
63 | {
64 |
65 | }
66 |
67 | void CacheSim::TreeProfileView::filterTextEdited()
68 | {
69 | m_FilterProxy->setFilterFixedString(ui->m_Filter->text());
70 | }
71 |
72 | #include "aux_TreeProfileView.moc"
73 |
--------------------------------------------------------------------------------
/UI/TraceTab.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017, Insomniac Games
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | Redistributions in binary form must reproduce the above copyright notice, this
12 | list of conditions and the following disclaimer in the documentation and/or
13 | other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #pragma once
28 | #include "Precompiled.h"
29 |
30 | class Ui_TraceTab;
31 |
32 | namespace CacheSim
33 | {
34 | class TraceData;
35 | class TreeModel;
36 | class BaseProfileView;
37 |
38 | class TraceTab : public QWidget
39 | {
40 | Q_OBJECT;
41 |
42 | public:
43 | explicit TraceTab(QString fileName, QWidget* parent = nullptr);
44 | ~TraceTab();
45 |
46 | public:
47 | Q_SLOT void openFlatProfile();
48 | Q_SLOT void openTreeProfile();
49 | Q_SLOT void openReverseViewForSymbol(QString symbol);
50 | Q_SLOT void openAnnotationForSymbol(QString symbol);
51 | Q_SIGNAL void closeTrace();
52 | Q_SIGNAL void beginLongTask(int id, QString description);
53 | Q_SIGNAL void endLongTask(int id);
54 |
55 | private:
56 | Q_SLOT void traceLoadSucceeded();
57 | Q_SLOT void traceLoadFailed(QString reason);
58 | Q_SLOT void resolveSymbolsClicked();
59 | Q_SLOT void symbolResolutionCompleted();
60 | Q_SLOT void symbolResolutionProgressed(int completed, int total);
61 | Q_SLOT void symbolResolutionFailed(QString reason);
62 | Q_SLOT void tabCloseRequested(int index);
63 | Q_SLOT void closeCurrentTab();
64 | Q_SIGNAL void treeModelReady(TreeModel* model, QString title, bool isMainView);
65 | Q_SLOT void createViewFromTreeModel(TreeModel* model, QString title, bool isMainView);
66 |
67 | void updateSymbolStatus();
68 | void doCreateTreeView(QString rootSymbolOpt, QString label);
69 | int addProfileView(BaseProfileView* view, QString label);
70 |
71 | private:
72 | QAction* m_CloseTabAction = nullptr;
73 | TraceData* m_Data = nullptr;
74 |
75 | int m_FlatProfileTabIndex = -1;
76 | int m_TreeProfileTabIndex = -1;
77 | QAtomicInt m_PendingJobs;
78 | QAtomicInt m_JobCounter;
79 | Ui_TraceTab* ui;
80 | };
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/CacheSim/CacheSimInternals.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017, Insomniac Games
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | Redistributions in binary form must reproduce the above copyright notice, this
12 | list of conditions and the following disclaimer in the documentation and/or
13 | other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #include "Precompiled.h"
28 | #include "CacheSim/CacheSimInternals.h"
29 |
30 | CacheSim::AccessResult CacheSim::JaguarModule::Access(int core_index, uintptr_t addr, AccessMode mode)
31 | {
32 | if (kWrite == mode)
33 | {
34 | // Kick the line out of every other L1 and the other L2 package.
35 | for (int i = 0; i < 4; ++i)
36 | {
37 | if (i == core_index)
38 | continue;
39 |
40 | m_CoreD1[i].Invalidate(addr);
41 | m_CoreI1[i].Invalidate(addr);
42 | }
43 |
44 | m_OtherModule->m_Level2.Invalidate(addr);
45 | }
46 |
47 | // Start at the L2, because the cache hierarchy is inclusive.
48 | bool l2_hit = m_Level2.Access(addr);
49 | bool l1_hit = false;
50 |
51 | if (kCodeRead == mode)
52 | {
53 | l1_hit = m_CoreI1[core_index].Access(addr);
54 | }
55 | else
56 | {
57 | l1_hit = m_CoreD1[core_index].Access(addr);
58 | }
59 |
60 | if (l2_hit && l1_hit)
61 | {
62 | if (kCodeRead == mode)
63 | return kI1Hit;
64 | else
65 | return kD1Hit;
66 | }
67 | else if (l2_hit)
68 | {
69 | return kL2Hit;
70 | }
71 | else
72 | {
73 | if (kCodeRead == mode)
74 | return kL2IMiss;
75 | else
76 | return kL2DMiss;
77 | }
78 | }
79 |
80 | CacheSim::AccessResult CacheSim::JaguarCacheSim::Access(int core_index, uintptr_t addr, size_t size, AccessMode mode)
81 | {
82 | AccessResult r = AccessResult::kD1Hit;
83 |
84 | // Handle straddling cache lines by looping.
85 | uint64_t line_base = addr & ~63ull;
86 | uint64_t line_end = (addr + size) & ~63ull;
87 |
88 | int module_index = (core_index / 4) & 1;
89 | while (line_base <= line_end)
90 | {
91 | AccessResult r2 = m_Modules[module_index].Access(core_index & 3, line_base, mode);
92 | if (r2 > r)
93 | r = r2;
94 | line_base += 64;
95 | }
96 |
97 | return r;
98 | }
99 |
--------------------------------------------------------------------------------
/udis86/udint.h:
--------------------------------------------------------------------------------
1 | /* udis86 - libudis86/udint.h -- definitions for internal use only
2 | *
3 | * Copyright (c) 2002-2009 Vivek Thampi
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without modification,
7 | * are permitted provided that the following conditions are met:
8 | *
9 | * * Redistributions of source code must retain the above copyright notice,
10 | * this list of conditions and the following disclaimer.
11 | * * Redistributions in binary form must reproduce the above copyright notice,
12 | * this list of conditions and the following disclaimer in the documentation
13 | * and/or other materials provided with the distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 | #ifndef _UDINT_H_
27 | #define _UDINT_H_
28 |
29 | #ifdef HAVE_CONFIG_H
30 | # include
31 | #endif /* HAVE_CONFIG_H */
32 |
33 | #if defined(UD_DEBUG) && HAVE_ASSERT_H
34 | # include
35 | # define UD_ASSERT(_x) assert(_x)
36 | #else
37 | # define UD_ASSERT(_x)
38 | #endif /* !HAVE_ASSERT_H */
39 |
40 | #if defined(UD_DEBUG)
41 | #define UDERR(u, msg) \
42 | do { \
43 | (u)->error = 1; \
44 | fprintf(stderr, "decode-error: %s:%d: %s", \
45 | __FILE__, __LINE__, (msg)); \
46 | } while (0)
47 | #else
48 | #define UDERR(u, m) \
49 | do { \
50 | (u)->error = 1; \
51 | } while (0)
52 | #endif /* !LOGERR */
53 |
54 | #define UD_RETURN_ON_ERROR(u) \
55 | do { \
56 | if ((u)->error != 0) { \
57 | return (u)->error; \
58 | } \
59 | } while (0)
60 |
61 | #define UD_RETURN_WITH_ERROR(u, m) \
62 | do { \
63 | UDERR(u, m); \
64 | return (u)->error; \
65 | } while (0)
66 |
67 | #ifndef __UD_STANDALONE__
68 | # define UD_NON_STANDALONE(x) x
69 | #else
70 | # define UD_NON_STANDALONE(x)
71 | #endif
72 |
73 | /* printf formatting int64 specifier */
74 | #ifdef FMT64
75 | # undef FMT64
76 | #endif
77 | #if defined(_MSC_VER) || defined(__BORLANDC__)
78 | # define FMT64 "I64"
79 | #else
80 | # if defined(__APPLE__)
81 | # define FMT64 "ll"
82 | # elif defined(__amd64__) || defined(__x86_64__)
83 | # define FMT64 "l"
84 | # else
85 | # define FMT64 "ll"
86 | # endif /* !x64 */
87 | #endif
88 |
89 | /* define an inline macro */
90 | #if defined(_MSC_VER) || defined(__BORLANDC__)
91 | # define UD_INLINE __inline /* MS Visual Studio requires __inline
92 | instead of inline for C code */
93 | #else
94 | # define UD_INLINE inline
95 | #endif
96 |
97 | #endif /* _UDINT_H_ */
98 |
--------------------------------------------------------------------------------
/UI/FlatProfileView.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017, Insomniac Games
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | Redistributions in binary form must reproduce the above copyright notice, this
12 | list of conditions and the following disclaimer in the documentation and/or
13 | other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #include "Precompiled.h"
28 | #include "FlatProfileView.h"
29 | #include "FlatModel.h"
30 | #include "NumberFormatters.h"
31 |
32 | #include "ui_FlatProfileView.h"
33 |
34 | CacheSim::FlatProfileView::FlatProfileView(const TraceData* traceData, QWidget* parent /*= nullptr*/)
35 | : BaseProfileView(parent)
36 | , m_TraceData(traceData)
37 | , m_FlatProxy(new QSortFilterProxyModel(this))
38 | , ui(new Ui_FlatProfileView)
39 | {
40 | ui->setupUi(this);
41 |
42 | setItemView(ui->m_FlatTableView);
43 |
44 | DecimalFormatDelegate* decimalDelegate = new DecimalFormatDelegate(this);
45 | IntegerFormatDelegate* integerDelegate = new IntegerFormatDelegate(this);
46 | QTableView* tableView = ui->m_FlatTableView;
47 | tableView->setItemDelegateForColumn(FlatModel::kColumnBadness, decimalDelegate);
48 | tableView->setItemDelegateForColumn(FlatModel::kColumnD1Hit, integerDelegate);
49 | tableView->setItemDelegateForColumn(FlatModel::kColumnI1Hit, integerDelegate);
50 | tableView->setItemDelegateForColumn(FlatModel::kColumnL2IMiss, integerDelegate);
51 | tableView->setItemDelegateForColumn(FlatModel::kColumnL2DMiss, integerDelegate);
52 | tableView->setItemDelegateForColumn(FlatModel::kColumnInstructionsExecuted, integerDelegate);
53 |
54 | m_Model = new FlatModel(this);
55 | m_Model->setData(traceData);
56 |
57 | m_FlatProxy->setSourceModel(m_Model);
58 |
59 | tableView->setModel(m_FlatProxy);
60 | tableView->sortByColumn(FlatModel::kColumnL2DMiss, Qt::DescendingOrder);
61 |
62 | QHeaderView* verticalHeader = tableView->verticalHeader();
63 | verticalHeader->sectionResizeMode(QHeaderView::Fixed);
64 | verticalHeader->setDefaultSectionSize(tableView->viewport()->fontMetrics().height() * 1.25);
65 |
66 | connect(ui->m_FlatFilter, &QLineEdit::textChanged, this, &FlatProfileView::filterTextEdited);
67 | }
68 |
69 | CacheSim::FlatProfileView::~FlatProfileView()
70 | {
71 | delete ui;
72 | }
73 |
74 | void CacheSim::FlatProfileView::filterTextEdited()
75 | {
76 | m_FlatProxy->setFilterFixedString(ui->m_FlatFilter->text());
77 | }
78 |
79 | #include "aux_FlatProfileView.moc"
80 |
81 |
--------------------------------------------------------------------------------
/UI/ObjectStack.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017, Insomniac Games
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | Redistributions in binary form must reproduce the above copyright notice, this
12 | list of conditions and the following disclaimer in the documentation and/or
13 | other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #pragma once
28 | #include "Precompiled.h"
29 |
30 | namespace CacheSim
31 | {
32 | class ObjectStack
33 | {
34 | struct Finalizer
35 | {
36 | void (*m_Destructor)(void *object);
37 | Finalizer* m_Next;
38 | size_t m_ElemSize;
39 | size_t m_ElemCount;
40 | char m_Object[0];
41 | };
42 | static_assert(sizeof(Finalizer) == 32, "wat");
43 |
44 | struct Page
45 | {
46 | size_t m_Size;
47 | size_t m_Allocated;
48 | Page* m_Next;
49 | char m_Data[0];
50 |
51 | size_t avail() const
52 | {
53 | return m_Size - m_Allocated;
54 | }
55 | };
56 | static_assert(sizeof(Page) == 24, "wat");
57 |
58 | Finalizer* m_FinalizerChain;
59 | Page* m_CurrentPage;
60 |
61 | public:
62 | ObjectStack();
63 | ~ObjectStack();
64 |
65 | public:
66 | void reset();
67 |
68 | private:
69 | void* allocRaw(size_t byte_count);
70 | void* allocFinalized(size_t byte_count, size_t elem_count, void (*dtor)(void*));
71 |
72 | Page* allocPage(size_t min_size, Page* next);
73 | void freePage(Page* p);
74 |
75 | private:
76 | template
77 | T* allocStorage(size_t elem_count)
78 | {
79 | if (std::is_trivially_destructible::value)
80 | return static_cast(allocRaw(sizeof(T) * elem_count));
81 | else
82 | return static_cast(allocFinalized(sizeof(T), elem_count, [](void* ptr) -> void { (void) ptr; static_cast(ptr)->~T(); }));
83 | }
84 |
85 | public:
86 | template
87 | T* alloc()
88 | {
89 | return new (allocStorage(1)) T;
90 | }
91 |
92 | template
93 | T* allocArray(size_t count)
94 | {
95 | T* base = allocStorage(count);
96 | for (size_t i = 0; i < count; ++i)
97 | {
98 | new (base + i) T;
99 | }
100 |
101 | return base;
102 | }
103 |
104 | template
105 | T* alloc(Args&&... args)
106 | {
107 | return new (allocStorage(1)) T(std::forward(args)...);
108 | }
109 | };
110 | }
111 |
--------------------------------------------------------------------------------
/UI/ObjectStack.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017, Insomniac Games
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | Redistributions in binary form must reproduce the above copyright notice, this
12 | list of conditions and the following disclaimer in the documentation and/or
13 | other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #include "Precompiled.h"
28 | #include "ObjectStack.h"
29 |
30 | CacheSim::ObjectStack::ObjectStack()
31 | : m_FinalizerChain(nullptr)
32 | , m_CurrentPage(nullptr)
33 | {}
34 |
35 | CacheSim::ObjectStack::~ObjectStack()
36 | {
37 | reset();
38 | }
39 |
40 | void CacheSim::ObjectStack::reset()
41 | {
42 | Finalizer* f = m_FinalizerChain;
43 | while (f)
44 | {
45 | void* object_ptr = (char*)f + sizeof(Finalizer);
46 | size_t size = f->m_ElemSize;
47 | size_t count = f->m_ElemCount;
48 | char *elem_ptr = (char*)object_ptr + (size * (count - 1));
49 | while (count--)
50 | {
51 | f->m_Destructor(elem_ptr);
52 | elem_ptr -= size;
53 | }
54 |
55 | f = f->m_Next;
56 | }
57 | m_FinalizerChain = nullptr;
58 |
59 | Page* p = m_CurrentPage;
60 | while (p)
61 | {
62 | Page* next = p->m_Next;
63 | freePage(p);
64 | p = next;
65 | }
66 | m_CurrentPage = nullptr;
67 | }
68 |
69 | void* CacheSim::ObjectStack::allocRaw(size_t byte_count)
70 | {
71 | if (!m_CurrentPage || m_CurrentPage->avail() < byte_count)
72 | {
73 | m_CurrentPage = allocPage(byte_count, m_CurrentPage);
74 | }
75 |
76 | char* dest = m_CurrentPage->m_Data + m_CurrentPage->m_Allocated;
77 |
78 | m_CurrentPage->m_Allocated += (byte_count + 15) & ~15ull;
79 |
80 | return dest;
81 | }
82 |
83 | void* CacheSim::ObjectStack::allocFinalized(size_t byte_count, size_t elem_count, void (*dtor)(void*))
84 | {
85 | Finalizer* f = (Finalizer*) allocRaw(byte_count + sizeof(Finalizer));
86 | f->m_Next = m_FinalizerChain;
87 | f->m_Destructor = dtor;
88 | f->m_ElemSize = byte_count;
89 | f->m_ElemCount = elem_count;
90 | m_FinalizerChain = f;
91 | return f->m_Object;
92 | }
93 |
94 | CacheSim::ObjectStack::Page* CacheSim::ObjectStack::allocPage(size_t min_size, Page* next)
95 | {
96 | static const size_t kDefaultPageSize = 1024 * 1024;
97 |
98 | size_t size = std::max(sizeof(Page) + min_size, kDefaultPageSize);
99 | Page* p = (Page*) new char[size];
100 | p->m_Size = size;
101 | p->m_Allocated = 0;
102 | p->m_Next = next;
103 | return p;
104 | }
105 |
106 | void CacheSim::ObjectStack::freePage(Page* p)
107 | {
108 | delete[] (char*) p;
109 | }
110 |
--------------------------------------------------------------------------------
/UI/TraceData.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017, Insomniac Games
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | Redistributions in binary form must reproduce the above copyright notice, this
12 | list of conditions and the following disclaimer in the documentation and/or
13 | other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #pragma once
28 |
29 | #include "Precompiled.h"
30 | #include "CacheSim/CacheSimData.h"
31 |
32 | namespace CacheSim
33 | {
34 | class TraceData : public QObject
35 | {
36 | Q_OBJECT;
37 |
38 | public:
39 | struct ResolveResult
40 | {
41 | QVector m_StringData;
42 | QVector m_Symbols;
43 | };
44 |
45 | public:
46 | explicit TraceData(QObject* parent = nullptr);
47 | ~TraceData();
48 |
49 | public:
50 | bool isResolved() const;
51 |
52 | public:
53 | Q_SLOT void beginLoadTrace(QString fn);
54 | Q_SLOT void beginResolveSymbols();
55 |
56 | Q_SIGNAL void traceLoadSucceeded();
57 | Q_SIGNAL void traceLoadFailed(QString errorMessasge);
58 |
59 | Q_SIGNAL void symbolResolutionProgressed(int completed, int total);
60 | Q_SIGNAL void symbolResolutionCompleted();
61 | Q_SIGNAL void symbolResolutionFailed(QString errorMessage);
62 | Q_SIGNAL void memoryMappedDataChanged();
63 |
64 | const SerializedHeader* header() const { return reinterpret_cast(m_Data); }
65 |
66 | public:
67 | QString symbolNameForAddress(uintptr_t rip) const;
68 | QString fileNameForAddress(uintptr_t rip) const;
69 | QString internedSymbolString(uint32_t offset) const;
70 |
71 | struct LineData
72 | {
73 | int m_LineNumber;
74 | uint32_t m_Stats[kAccessResultCount];
75 | };
76 |
77 | struct FileInfo
78 | {
79 | QString m_FileName;
80 | int m_FirstLine = 0;
81 | int m_LastLine = 0;
82 | QVector m_Samples;
83 | };
84 |
85 | FileInfo findFileData(QString symbol) const;
86 |
87 | private:
88 | Q_SLOT void symbolsResolved();
89 |
90 | private:
91 | // Emit a load failed on the next tick of the event loop.
92 | void emitLoadFailure(QString errorMessage);
93 |
94 | ResolveResult symbolResolveTask();
95 |
96 | private:
97 | QFile m_File;
98 | char* m_Data = nullptr;
99 | uint64_t m_DataSize = 0;
100 |
101 | QFutureWatcher* m_Watcher = nullptr;
102 | mutable QHash m_SymbolStringCache;
103 | mutable QHash m_StringToSymbolNameIndex;
104 | };
105 |
106 | }
107 |
--------------------------------------------------------------------------------
/UI/CacheSimMainWindow.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017, Insomniac Games
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | Redistributions in binary form must reproduce the above copyright notice, this
12 | list of conditions and the following disclaimer in the documentation and/or
13 | other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #include "Precompiled.h"
28 | #include "CacheSimMainWindow.h"
29 | #include "TraceTab.h"
30 |
31 | CacheSim::MainWindow::MainWindow(QWidget* parent /*= nullptr*/)
32 | : QMainWindow(parent)
33 | {
34 | setupUi(this);
35 |
36 | connect(m_OpenTraceAction, &QAction::triggered, this, &MainWindow::openTrace);
37 | connect(m_QuitAction, &QAction::triggered, qApp, &QApplication::quit);
38 | connect(m_Tabs, &QTabWidget::tabCloseRequested, this, &MainWindow::closeTrace);
39 | }
40 |
41 | CacheSim::MainWindow::~MainWindow()
42 | {
43 |
44 | }
45 |
46 | void CacheSim::MainWindow::openTrace()
47 | {
48 | QString fn = QFileDialog::getOpenFileName(this, QStringLiteral("Select trace file"), QString(), QStringLiteral("*.csim"));
49 |
50 | if (fn.isEmpty())
51 | {
52 | return;
53 | }
54 |
55 | TraceTab* tab = new TraceTab(fn, this);
56 | m_Tabs->addTab(tab, QFileInfo(fn).baseName());
57 |
58 | connect(tab, &TraceTab::closeTrace, this, &MainWindow::closeTrace);
59 | connect(tab, &TraceTab::beginLongTask, this, &MainWindow::longTaskStarted);
60 | connect(tab, &TraceTab::endLongTask, this, &MainWindow::longTaskFinished);
61 | }
62 |
63 | void CacheSim::MainWindow::closeTrace()
64 | {
65 | if (0 == m_TasksRunning)
66 | {
67 | int index = m_Tabs->currentIndex();
68 | QWidget* widget = m_Tabs->widget(index);
69 | m_Tabs->removeTab(index);
70 | delete widget;
71 | }
72 | else
73 | {
74 | statusBar()->showMessage(QStringLiteral("Can't close tabs while async compute is running!"), 4000);
75 | }
76 | }
77 |
78 | void CacheSim::MainWindow::closeEvent(QCloseEvent* ev)
79 | {
80 | if (0 == m_TasksRunning)
81 | {
82 | QMainWindow::closeEvent(ev);
83 | }
84 | else
85 | {
86 | ev->ignore();
87 | statusBar()->showMessage(QStringLiteral("Can't close app while async compute is running!"), 4000);
88 | }
89 | }
90 |
91 | void CacheSim::MainWindow::longTaskStarted(int id, QString description)
92 | {
93 | statusBar()->showMessage(description, 4000);
94 | m_LatestTask = id;
95 | ++m_TasksRunning;
96 | QApplication::setOverrideCursor(Qt::BusyCursor);
97 | }
98 |
99 | void CacheSim::MainWindow::longTaskFinished(int id)
100 | {
101 | if (id == m_LatestTask)
102 | {
103 | statusBar()->showMessage(QStringLiteral("Ready"), 4000);
104 | }
105 | --m_TasksRunning;
106 | QApplication::restoreOverrideCursor();
107 | }
108 |
109 | #include "aux_CacheSimMainWindow.moc"
110 |
--------------------------------------------------------------------------------
/UI/BaseProfileView.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017, Insomniac Games
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | Redistributions in binary form must reproduce the above copyright notice, this
12 | list of conditions and the following disclaimer in the documentation and/or
13 | other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #include "Precompiled.h"
28 | #include "BaseProfileView.h"
29 |
30 | CacheSim::BaseProfileView::BaseProfileView(QWidget* parent /*= nullptr*/)
31 | : QWidget(parent)
32 | {
33 | m_ShowReverseAction = new QAction(QStringLiteral("Show call tree"), this);
34 | m_ShowReverseAction->setShortcut(Qt::Key_R | Qt::CTRL);
35 | m_ShowReverseAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
36 | connect(m_ShowReverseAction, &QAction::triggered, this, &BaseProfileView::showReverseTriggered);
37 |
38 | m_AnnotateAction = new QAction(QStringLiteral("Annotate"), this);
39 | m_AnnotateAction->setShortcut(Qt::Key_A | Qt::CTRL | Qt::SHIFT);
40 | m_AnnotateAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
41 | connect(m_AnnotateAction, &QAction::triggered, this, &BaseProfileView::annotateTriggered);
42 |
43 | this->addAction(m_ShowReverseAction);
44 | this->addAction(m_AnnotateAction);
45 | }
46 |
47 | CacheSim::BaseProfileView::~BaseProfileView()
48 | {
49 |
50 | }
51 |
52 | void CacheSim::BaseProfileView::setItemView(QAbstractItemView* view)
53 | {
54 | m_ItemView = view;
55 | view->setContextMenuPolicy(Qt::CustomContextMenu);
56 | connect(view, &QAbstractItemView::customContextMenuRequested, this, &BaseProfileView::customContextMenuRequested);
57 | }
58 |
59 | void CacheSim::BaseProfileView::showReverseTriggered()
60 | {
61 | QString sym = selectedSymbol();
62 | if (!sym.isEmpty())
63 | {
64 | Q_EMIT showReverse(sym);
65 | }
66 | }
67 |
68 | void CacheSim::BaseProfileView::customContextMenuRequested(const QPoint &pos)
69 | {
70 | QModelIndex index = m_ItemView->indexAt(pos);
71 | if (!index.isValid())
72 | return;
73 |
74 | QMenu* menu = new QMenu(this);
75 | menu->addAction(showReverseAction());
76 | menu->addAction(annotateAction());
77 | menu->popup(m_ItemView->viewport()->mapToGlobal(pos));
78 | }
79 |
80 | QString CacheSim::BaseProfileView::selectedSymbol() const
81 | {
82 | QModelIndexList selection = m_ItemView->selectionModel()->selectedIndexes();
83 | if (selection.isEmpty())
84 | {
85 | return QString::null;
86 | }
87 |
88 | QModelIndex first = selection[0];
89 | return m_ItemView->model()->data(first).toString();
90 | }
91 |
92 | void CacheSim::BaseProfileView::annotateTriggered()
93 | {
94 | QString sym = selectedSymbol();
95 | if (!sym.isEmpty())
96 | {
97 | Q_EMIT annotateSymbol(sym);
98 | }
99 | }
100 |
101 | #include "aux_BaseProfileView.moc"
102 |
--------------------------------------------------------------------------------
/UI/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2017, Insomniac Games
2 | #
3 | # All rights reserved.
4 | #
5 | # Redistribution and use in source and binary forms, with or without
6 | # modification, are permitted provided that the following conditions are met:
7 | #
8 | # Redistributions of source code must retain the above copyright notice, this
9 | # list of conditions and the following disclaimer.
10 | #
11 | # Redistributions in binary form must reproduce the above copyright notice, this
12 | # list of conditions and the following disclaimer in the documentation and/or
13 | # other materials provided with the distribution.
14 | #
15 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
26 | find_package(Qt5 COMPONENTS Widgets REQUIRED)
27 |
28 | set(moc_inputs
29 | CacheSimMainWindow.h
30 | CacheSimMainWindow.h
31 | SymbolResolver.h
32 | TraceTab.h
33 | TraceData.h
34 | FlatModel.h
35 | TreeModel.h
36 | FlatProfileView.h
37 | TreeProfileView.h
38 | BaseProfileView.h
39 | )
40 |
41 | foreach(moc_input IN LISTS moc_inputs)
42 | get_filename_component(basename "${moc_input}" NAME_WE)
43 | list(APPEND moc_output "${CMAKE_CURRENT_BINARY_DIR}/aux_${basename}.moc")
44 | qt5_generate_moc("${moc_input}" "${CMAKE_CURRENT_BINARY_DIR}/aux_${basename}.moc")
45 | endforeach()
46 |
47 | set(ui_inputs
48 | CacheSimMainWindow.ui
49 | TraceTab.ui
50 | FlatProfileView.ui
51 | TreeProfileView.ui
52 | )
53 |
54 | foreach(ui_input IN LISTS ui_inputs)
55 | get_filename_component(basename "${ui_input}" NAME_WE)
56 | list(APPEND uic_output "${CMAKE_CURRENT_BINARY_DIR}/ui_${basename}.h")
57 | qt5_wrap_ui("${CMAKE_CURRENT_BINARY_DIR}/ui_${basename}.h" "${ui_input}")
58 | endforeach()
59 |
60 | set(CMAKE_AUTORCC TRUE)
61 |
62 | if (WIN32)
63 | set(PLATFORM_SRC_FILES SymbolResolverWindows.cpp)
64 | else (WIN32)
65 | set(PLATFORM_SRC_FILES SymbolResolverLinux.cpp)
66 | endif (WIN32)
67 |
68 | add_executable(CacheSimUI WIN32
69 | AnnotationView.cpp AnnotationView.h
70 | BaseProfileView.cpp BaseProfileView.h
71 | CacheSimGUIMain.cpp
72 | CacheSimMainWindow.cpp CacheSimMainWindow.h
73 | FlatModel.cpp FlatModel.h
74 | FlatProfileView.cpp FlatProfileView.h
75 | NumberFormatters.cpp NumberFormatters.h
76 | ObjectStack.cpp ObjectStack.h
77 | Precompiled.cpp Precompiled.h
78 | TraceData.cpp TraceData.h
79 | TraceTab.cpp TraceTab.h
80 | TreeModel.cpp TreeModel.h
81 | TreeProfileView.cpp TreeProfileView.h
82 | ${PLATFORM_SRC_FILES}
83 |
84 | Resources.qrc
85 |
86 | ${moc_output}
87 | ${uic_output}
88 | )
89 |
90 | if (WIN32)
91 | target_compile_definitions(CacheSimUI
92 | PRIVATE "IG_CACHESIM_API=__declspec(dllimport)" "NOMINMAX" "WIN32_LEAN_AND_MEAN")
93 |
94 | target_compile_options(CacheSimUI
95 | PRIVATE "/W4" "/wd4127" "/wd4458" "/wd4200" "/wd4718")
96 |
97 | target_link_libraries(CacheSimUI
98 | PRIVATE Qt5::Widgets "dbghelp")
99 | else (WIN32)
100 | target_link_libraries(CacheSimUI
101 | PRIVATE Qt5::Widgets)
102 | target_compile_options(CacheSimUI
103 | PRIVATE -g)
104 | endif (WIN32)
105 |
106 | target_include_directories(CacheSimUI
107 | PRIVATE "${CMAKE_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}")
108 |
109 |
110 | set_target_properties(CacheSimUI PROPERTIES FOLDER "UI")
111 |
--------------------------------------------------------------------------------
/Examples/ThreadedExample/ThreadedExample.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017, Insomniac Games
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | Redistributions in binary form must reproduce the above copyright notice, this
12 | list of conditions and the following disclaimer in the documentation and/or
13 | other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | // HelloWorld.cpp - the simplest possible demo example of CacheSim
28 |
29 | #include "CacheSim/CacheSim.h"
30 | #include
31 | #include
32 | #include
33 | #include
34 |
35 | CacheSim::DynamicLoader cachesim;
36 | volatile bool run = true;
37 | volatile bool workFinished = false;
38 | volatile bool canExit = false;
39 |
40 | void DoSomeWork()
41 | {
42 | cachesim.SetThreadCoreMapping(cachesim.GetCurrentThreadId(), 2);
43 | printf("Thread ID: %jd", (uintmax_t)cachesim.GetCurrentThreadId());
44 | std::list values;
45 | for (int i = 0; i < 10000; i++)
46 | {
47 | values.push_back(new uint64_t(i));
48 | if ((i % 500) == 0)
49 | {
50 | printf("DoSomeWork: %jd\n", (uintmax_t)i);
51 | }
52 | }
53 | uint64_t total = 0;
54 | int i = 0;
55 | for (auto& val : values)
56 | {
57 | total += *val;
58 | if ((i % 500) == 0)
59 | {
60 | printf("DoSomeWork: %jd\n", (uintmax_t)i);
61 | }
62 | i++;
63 | delete val;
64 | }
65 | while (run == true) { std::this_thread::yield(); }
66 | lgamma(1.f);
67 | workFinished = true;
68 | while (canExit == false) { std::this_thread::yield(); }
69 | }
70 |
71 | int main(int argc, char* argv[])
72 | {
73 |
74 | if (!cachesim.Init())
75 | return 1;
76 |
77 | printf("Start\n");
78 |
79 | std::thread thread(
80 | [&]() {
81 | cachesim.SetThreadCoreMapping(cachesim.GetCurrentThreadId(), 1);
82 | printf("Thread ID: %jd", (uintmax_t)cachesim.GetCurrentThreadId());
83 | int count = 0;
84 | while (run) {
85 | std::string s;
86 | s.append("Hi!\n");
87 | count++;
88 | printf("%s %d\n", s.c_str(), count);
89 | }
90 | while (canExit == false) { std::this_thread::yield(); }
91 | });
92 |
93 | std::thread thread2(
94 | DoSomeWork
95 | );
96 |
97 | // This needs to happen to map thread ids to physical cores for cache simulation.
98 | // If a thread is not mapped, it will not be simulated.
99 | cachesim.SetThreadCoreMapping(cachesim.GetCurrentThreadId(), 0);
100 |
101 | cachesim.Start();
102 |
103 | printf("Hello, world (with cache simulation)!\n");
104 |
105 | std::chrono::milliseconds delay(500);
106 | std::this_thread::sleep_for(delay);
107 |
108 | // All this code is obviously racey and such, but I think it gets the point across.
109 | run = false;
110 | while (workFinished == false)
111 | {
112 | std::this_thread::sleep_for(delay);
113 | }
114 |
115 | // This must be called before the threads being traced destruct (on windows) or their TLS data will go away
116 | cachesim.End();
117 | canExit = true;
118 | thread.join();
119 | thread2.join();
120 | return 0;
121 | }
122 |
--------------------------------------------------------------------------------
/UnitTest/TestCacheSim.cpp:
--------------------------------------------------------------------------------
1 | #include "gtest/gtest.h"
2 | #include "gtest-all.cc"
3 |
4 | #include "CacheSim/CacheSimInternals.h"
5 | extern "C"
6 | {
7 | #include "udis86/udis86.h"
8 | }
9 |
10 | namespace
11 | {
12 | class CacheTest : public ::testing::Test
13 | {
14 | public:
15 | CacheSim::JaguarCacheSim cache;
16 |
17 | public:
18 | virtual void SetUp() override
19 | {
20 | cache.Init();
21 | }
22 |
23 | virtual void TearDown() override
24 | {
25 | }
26 | };
27 | }
28 |
29 | TEST_F(CacheTest, BasicHit)
30 | {
31 | EXPECT_EQ(CacheSim::kL2DMiss, cache.Access(0, 0x12345678abcd, 8, CacheSim::kRead));
32 | EXPECT_EQ(CacheSim::kD1Hit, cache.Access(0, 0x12345678abcd, 8, CacheSim::kRead));
33 | }
34 |
35 | TEST_F(CacheTest, BasicCodeHit)
36 | {
37 | EXPECT_EQ(CacheSim::kL2IMiss, cache.Access(0, 0x12345678abcd, 8, CacheSim::kCodeRead));
38 | EXPECT_EQ(CacheSim::kI1Hit, cache.Access(0, 0x12345678abcd, 8, CacheSim::kCodeRead));
39 | }
40 |
41 | TEST_F(CacheTest, BasicAssoc)
42 | {
43 | uintptr_t la = 0x40;
44 | uintptr_t lb = la + 512 * 0x40;
45 |
46 | EXPECT_EQ(CacheSim::kL2DMiss, cache.Access(0, la, 8, CacheSim::kRead));
47 | EXPECT_EQ(CacheSim::kD1Hit, cache.Access(0, la, 8, CacheSim::kRead));
48 | EXPECT_EQ(CacheSim::kL2DMiss, cache.Access(0, lb, 8, CacheSim::kRead));
49 | EXPECT_EQ(CacheSim::kD1Hit, cache.Access(0, la, 8, CacheSim::kRead));
50 | EXPECT_EQ(CacheSim::kD1Hit, cache.Access(0, lb, 8, CacheSim::kRead));
51 | }
52 |
53 | TEST_F(CacheTest, CoreInvalidating)
54 | {
55 | uintptr_t la = 0x40;
56 |
57 | EXPECT_EQ(CacheSim::kL2DMiss, cache.Access(0, la, 8, CacheSim::kRead));
58 | EXPECT_EQ(CacheSim::kL2Hit, cache.Access(1, la, 8, CacheSim::kRead));
59 | EXPECT_EQ(CacheSim::kL2Hit, cache.Access(2, la, 8, CacheSim::kRead));
60 | EXPECT_EQ(CacheSim::kL2Hit, cache.Access(3, la, 8, CacheSim::kRead));
61 |
62 | EXPECT_EQ(CacheSim::kD1Hit, cache.Access(0, la, 8, CacheSim::kRead));
63 | EXPECT_EQ(CacheSim::kD1Hit, cache.Access(1, la, 8, CacheSim::kRead));
64 | EXPECT_EQ(CacheSim::kD1Hit, cache.Access(2, la, 8, CacheSim::kRead));
65 | EXPECT_EQ(CacheSim::kD1Hit, cache.Access(3, la, 8, CacheSim::kRead));
66 |
67 | EXPECT_EQ(CacheSim::kD1Hit, cache.Access(0, la, 8, CacheSim::kWrite));
68 | EXPECT_EQ(CacheSim::kL2Hit, cache.Access(1, la, 8, CacheSim::kRead));
69 | EXPECT_EQ(CacheSim::kL2Hit, cache.Access(2, la, 8, CacheSim::kRead));
70 | EXPECT_EQ(CacheSim::kL2Hit, cache.Access(3, la, 8, CacheSim::kRead));
71 | }
72 |
73 | TEST_F(CacheTest, CoreInvalidatingModule)
74 | {
75 | uintptr_t la = 0x40;
76 |
77 | EXPECT_EQ(CacheSim::kL2DMiss, cache.Access(0, la, 8, CacheSim::kRead));
78 | EXPECT_EQ(CacheSim::kD1Hit, cache.Access(0, la, 8, CacheSim::kRead));
79 |
80 | // Simulate other package invalidating L2 line
81 | EXPECT_EQ(CacheSim::kL2DMiss, cache.Access(5, la, 8, CacheSim::kWrite));
82 | EXPECT_EQ(CacheSim::kD1Hit, cache.Access(5, la, 8, CacheSim::kRead));
83 | EXPECT_EQ(CacheSim::kL2DMiss, cache.Access(0, la, 8, CacheSim::kRead));
84 | EXPECT_EQ(CacheSim::kD1Hit, cache.Access(0, la, 8, CacheSim::kRead));
85 | }
86 |
87 | TEST_F(CacheTest, FullAssoc)
88 | {
89 | uintptr_t base = 0x40;
90 | uintptr_t multiplier = 0x40 * 512; // Make sure it hits the same way in L1
91 |
92 | EXPECT_EQ(CacheSim::kL2DMiss, cache.Access(0, base, 8, CacheSim::kRead));
93 |
94 | for (int i = 1; i <= 8; ++i)
95 | {
96 | EXPECT_EQ(CacheSim::kL2DMiss, cache.Access(0, base + i * multiplier, 8, CacheSim::kRead));
97 | }
98 |
99 | for (int i = 1; i <= 8; ++i)
100 | {
101 | EXPECT_EQ(CacheSim::kD1Hit, cache.Access(0, base + i * multiplier, 8, CacheSim::kRead));
102 | }
103 |
104 | EXPECT_EQ(CacheSim::kL2Hit, cache.Access(0, base, 8, CacheSim::kRead));
105 | }
106 |
107 | TEST(Disassembler, Movhps)
108 | {
109 | static const uint8_t insn[] = { 0x0f, 0x16, 0x0f };
110 | struct ud ud;
111 | ud_init(&ud);
112 | ud_set_mode(&ud, 64);
113 | ud_set_input_buffer(&ud, (const uint8_t*)insn, 16);
114 | int ilen = ud_disassemble(&ud);
115 | ASSERT_EQ(3, ilen);
116 |
117 | ASSERT_EQ(UD_Imovhps, ud.mnemonic);
118 | ASSERT_EQ(UD_OP_REG, ud.operand[0].type);
119 | ASSERT_EQ(UD_R_XMM1, ud.operand[0].base);
120 | ASSERT_EQ(128, ud.operand[0].size);
121 |
122 | ASSERT_EQ(UD_OP_MEM, ud.operand[1].type);
123 | ASSERT_EQ(UD_R_RDI, ud.operand[1].base);
124 | ASSERT_EQ(64, ud.operand[1].size);
125 | }
126 |
127 | #if 0
128 | TEST(RunTheThing, Minimal)
129 | {
130 | CacheSimInit();
131 | CacheSimSetThreadCoreMapping(GetCurrentThreadId(), 0);
132 | CacheSimStartCapture();
133 |
134 | static volatile int a;
135 |
136 | a = 1;
137 |
138 | CacheSimEndCapture(true);
139 | }
140 | #endif
141 |
142 | int main(int argc, char* argv[])
143 | {
144 | ::testing::InitGoogleTest(&argc, argv);
145 | return RUN_ALL_TESTS();
146 | }
147 |
--------------------------------------------------------------------------------
/udis86/extern.h:
--------------------------------------------------------------------------------
1 | /* udis86 - libudis86/extern.h
2 | *
3 | * Copyright (c) 2002-2009, 2013 Vivek Thampi
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without modification,
7 | * are permitted provided that the following conditions are met:
8 | *
9 | * * Redistributions of source code must retain the above copyright notice,
10 | * this list of conditions and the following disclaimer.
11 | * * Redistributions in binary form must reproduce the above copyright notice,
12 | * this list of conditions and the following disclaimer in the documentation
13 | * and/or other materials provided with the distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 | #ifndef UD_EXTERN_H
27 | #define UD_EXTERN_H
28 |
29 | #include "types.h"
30 |
31 | #if defined(_MSC_VER) && defined(_USRDLL)
32 | # ifdef LIBUDIS86_EXPORTS
33 | # define LIBUDIS86_DLLEXTERN __declspec(dllexport)
34 | # else
35 | # define LIBUDIS86_DLLEXTERN __declspec(dllimport)
36 | # endif
37 | #else
38 | # define LIBUDIS86_DLLEXTERN
39 | #endif
40 |
41 | /* ============================= PUBLIC API ================================= */
42 |
43 | extern LIBUDIS86_DLLEXTERN void ud_init(struct ud*);
44 |
45 | extern LIBUDIS86_DLLEXTERN void ud_set_mode(struct ud*, uint8_t);
46 |
47 | extern LIBUDIS86_DLLEXTERN void ud_set_pc(struct ud*, uint64_t);
48 |
49 | extern LIBUDIS86_DLLEXTERN void ud_set_input_hook(struct ud*, int (*)(struct ud*));
50 |
51 | extern LIBUDIS86_DLLEXTERN void ud_set_input_buffer(struct ud*, const uint8_t*, size_t);
52 |
53 | #ifndef __UD_STANDALONE__
54 | extern LIBUDIS86_DLLEXTERN void ud_set_input_file(struct ud*, FILE*);
55 | #endif /* __UD_STANDALONE__ */
56 |
57 | extern LIBUDIS86_DLLEXTERN void ud_set_vendor(struct ud*, unsigned);
58 |
59 | extern LIBUDIS86_DLLEXTERN void ud_set_syntax(struct ud*, void (*)(struct ud*));
60 |
61 | extern LIBUDIS86_DLLEXTERN void ud_input_skip(struct ud*, size_t);
62 |
63 | extern LIBUDIS86_DLLEXTERN int ud_input_end(const struct ud*);
64 |
65 | extern LIBUDIS86_DLLEXTERN unsigned int ud_decode(struct ud*);
66 |
67 | extern LIBUDIS86_DLLEXTERN unsigned int ud_disassemble(struct ud*);
68 |
69 | extern LIBUDIS86_DLLEXTERN void ud_translate_intel(struct ud*);
70 |
71 | extern LIBUDIS86_DLLEXTERN void ud_translate_att(struct ud*);
72 |
73 | extern LIBUDIS86_DLLEXTERN const char* ud_insn_asm(const struct ud* u);
74 |
75 | extern LIBUDIS86_DLLEXTERN const uint8_t* ud_insn_ptr(const struct ud* u);
76 |
77 | extern LIBUDIS86_DLLEXTERN uint64_t ud_insn_off(const struct ud*);
78 |
79 | extern LIBUDIS86_DLLEXTERN const char* ud_insn_hex(struct ud*);
80 |
81 | extern LIBUDIS86_DLLEXTERN unsigned int ud_insn_len(const struct ud* u);
82 |
83 | extern LIBUDIS86_DLLEXTERN const struct ud_operand* ud_insn_opr(const struct ud *u, unsigned int n);
84 |
85 | extern LIBUDIS86_DLLEXTERN int ud_opr_is_sreg(const struct ud_operand *opr);
86 |
87 | extern LIBUDIS86_DLLEXTERN int ud_opr_is_gpr(const struct ud_operand *opr);
88 |
89 | extern LIBUDIS86_DLLEXTERN enum ud_mnemonic_code ud_insn_mnemonic(const struct ud *u);
90 |
91 | extern LIBUDIS86_DLLEXTERN const char* ud_lookup_mnemonic(enum ud_mnemonic_code c);
92 |
93 | extern LIBUDIS86_DLLEXTERN const struct ud_eflags* ud_lookup_eflags(struct ud *u);
94 |
95 | extern LIBUDIS86_DLLEXTERN const enum ud_type* ud_lookup_implicit_reg_used_list(struct ud *u);
96 |
97 | extern LIBUDIS86_DLLEXTERN const enum ud_type* ud_lookup_implicit_reg_defined_list(struct ud *u);
98 |
99 | extern LIBUDIS86_DLLEXTERN void ud_set_user_opaque_data(struct ud*, void*);
100 |
101 | extern LIBUDIS86_DLLEXTERN void* ud_get_user_opaque_data(const struct ud*);
102 |
103 | extern LIBUDIS86_DLLEXTERN void ud_set_asm_buffer(struct ud *u, char *buf, size_t size);
104 |
105 | extern LIBUDIS86_DLLEXTERN void ud_set_sym_resolver(struct ud *u,
106 | const char* (*resolver)(struct ud*,
107 | uint64_t addr,
108 | int64_t *offset));
109 |
110 | /* ========================================================================== */
111 |
112 | #endif /* UD_EXTERN_H */
113 |
--------------------------------------------------------------------------------
/CacheSim/CacheSimData.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | /*
4 | Copyright (c) 2017, Insomniac Games
5 | All rights reserved.
6 |
7 | Redistribution and use in source and binary forms, with or without
8 | modification, are permitted provided that the following conditions are met:
9 |
10 | Redistributions of source code must retain the above copyright notice, this
11 | list of conditions and the following disclaimer.
12 |
13 | Redistributions in binary form must reproduce the above copyright notice, this
14 | list of conditions and the following disclaimer in the documentation and/or
15 | other materials provided with the distribution.
16 |
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
21 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | #include "CacheSimInternals.h"
30 | #include
31 |
32 | /// Describes structures that go in the output standard DataFileWriter-based files
33 | /// after a cache simulation has been run.
34 | namespace CacheSim
35 | {
36 |
37 | struct SerializedModuleEntry
38 | {
39 | uint64_t m_ImageBase;
40 | uint64_t m_ImageSegmentOffset; // Linux only
41 | uint32_t m_SizeBytes;
42 | uint32_t m_StringOffset;
43 | };
44 | static_assert(sizeof(SerializedModuleEntry) == 24, "bump version if you're changing this");
45 |
46 | struct SerializedNode
47 | {
48 | uint64_t m_Rip;
49 | uint32_t m_StackIndex;
50 | uint32_t m_Stats[kAccessResultCount];
51 | uint32_t m_Padding;
52 | };
53 | static_assert(sizeof(SerializedNode) == 48, "bump version if you're changing this");
54 |
55 | inline double BadnessValue(const uint32_t (&stats)[kAccessResultCount])
56 | {
57 | uint64_t misses = stats[CacheSim::kL2DMiss];
58 | uint32_t instructions = stats[CacheSim::kInstructionsExecuted];
59 | return double(misses * misses) / instructions;
60 | }
61 |
62 | struct SerializedSymbol
63 | {
64 | uintptr_t m_Rip;
65 | uint8_t m_Pad[4];
66 | uint32_t m_FileName;
67 | uint32_t m_SymbolName;
68 | uint32_t m_ModuleIndex;
69 | uint32_t m_LineNumber;
70 | uint32_t m_Displacement;
71 | };
72 | static_assert(sizeof(SerializedSymbol) == 32, "bump version if you're changing this");
73 |
74 | static constexpr uint32_t kCurrentVersion = 0x2;
75 |
76 | template
77 | const T* serializedOffset(const void* base, uint32_t offset)
78 | {
79 | return reinterpret_cast(reinterpret_cast(base) + offset);
80 | }
81 |
82 | struct SerializedHeader
83 | {
84 | public:
85 | uint32_t m_Magic;
86 | uint32_t m_Version;
87 |
88 | uint32_t m_ModuleOffset;
89 | uint32_t m_ModuleCount;
90 | uint32_t m_ModuleStringOffset;
91 | uint32_t m_FrameOffset;
92 | uint32_t m_FrameCount;
93 | uint32_t m_StatsOffset;
94 | uint32_t m_StatsCount;
95 |
96 | uint32_t m_SymbolOffset; // If these are all 0 it means the file is not yet resolved and it lacks this last section.
97 | uint32_t m_SymbolCount;
98 |
99 | uint32_t m_SymbolTextOffset;
100 |
101 | public:
102 | uint32_t GetModuleCount() const { return m_ModuleCount; }
103 | const SerializedModuleEntry* GetModules() const { return serializedOffset(this, m_ModuleOffset); }
104 |
105 | const char* GetModuleName(const SerializedModuleEntry& module) const
106 | {
107 | return serializedOffset(this, m_ModuleStringOffset + module.m_StringOffset);
108 | }
109 |
110 | const uintptr_t* GetStacks() const { return serializedOffset(this, m_FrameOffset); }
111 | uint32_t GetStackCount() const { return m_FrameCount; }
112 |
113 | const SerializedNode* GetStats() const { return serializedOffset(this, m_StatsOffset); }
114 | uint32_t GetStatCount() const { return m_StatsCount; }
115 |
116 | const SerializedSymbol* GetSymbols() const { return serializedOffset(this, m_SymbolOffset); }
117 | uint32_t GetSymbolCount() const { return m_SymbolCount; }
118 |
119 | const SerializedSymbol* FindSymbol(const uintptr_t rip) const
120 | {
121 | const SerializedSymbol* b = GetSymbols();
122 | const SerializedSymbol* e = b + GetSymbolCount();
123 |
124 | const SerializedSymbol* s = std::lower_bound(b, e, rip, [](const SerializedSymbol& sym, uintptr_t rip) -> bool
125 | {
126 | return sym.m_Rip < rip;
127 | });
128 |
129 | if (s == e || s->m_Rip != rip)
130 | {
131 | return nullptr;
132 | }
133 |
134 | return s;
135 | }
136 | };
137 |
138 | }
139 |
--------------------------------------------------------------------------------
/UI/SymbolResolverWindows.cpp:
--------------------------------------------------------------------------------
1 | #include "Precompiled.h"
2 | #include "SymbolResolver.h"
3 |
4 | #include
5 |
6 | bool CacheSim::ResolveSymbols(const UnresolvedAddressData& input, QVector* resolvedSymbolsOut, SymbolResolveProgressCallbackType reportProgress)
7 | {
8 | const HANDLE hproc = (HANDLE)0x1; // Really doesn't matter. But can't be null.
9 |
10 | {
11 | DWORD sym_options = SymGetOptions();
12 | //sym_options |= SYMOPT_LOAD_LINES | SYMOPT_DEFERRED_LOADS | SYMOPT_FAIL_CRITICAL_ERRORS;
13 | sym_options |= SYMOPT_LOAD_LINES | SYMOPT_FAIL_CRITICAL_ERRORS | SYMOPT_DEBUG | SYMOPT_DISABLE_SYMSRV_AUTODETECT | SYMOPT_DEFERRED_LOADS;
14 | sym_options &= ~(SYMOPT_UNDNAME);
15 |
16 | SymSetOptions(sym_options);
17 | }
18 |
19 | if (!SymInitialize(hproc, nullptr, FALSE))
20 | {
21 | qDebug() << "Failed to initialize DbgHelp library; Last Error:" << GetLastError();
22 | return false;
23 | }
24 |
25 | {
26 | // Ugh.
27 | QString symDirPath = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + QStringLiteral("\\CacheSimSymbols");
28 | QDir symDir(symDirPath);
29 | if (!symDir.exists())
30 | {
31 | symDir.mkpath(QStringLiteral("."));
32 | }
33 |
34 | QFileInfo firstModule(QString::fromUtf8(input.m_ModuleNames[0].toUtf8()));
35 |
36 | QString symbolPath = QStringLiteral("%1;srv*%2*https://msdl.microsoft.com/download/symbols")
37 | .arg(firstModule.absolutePath().replace(QLatin1Char('/'), QLatin1Char('\\')))
38 | .arg(symDir.absolutePath().replace(QLatin1Char('/'), QLatin1Char('\\')));
39 | if (!SymSetSearchPath(hproc, symbolPath.toUtf8().constData()))
40 | {
41 | qDebug() << "Failed to set symbol path; err:" << GetLastError();
42 | return false;
43 | }
44 | }
45 |
46 | //SymRegisterCallback(hproc, DbgHelpCallback, 0);
47 |
48 | for (uint32_t modIndex = 0; modIndex < input.m_ModuleCount; ++modIndex)
49 | {
50 | const SerializedModuleEntry& module = input.m_Modules[modIndex];
51 |
52 | if (0 == SymLoadModule64(hproc, nullptr, input.m_ModuleNames[modIndex].toUtf8(), nullptr, module.m_ImageBase, module.m_SizeBytes))
53 | {
54 | //Warn("Failed to load module \"%s\" (base: %016llx, size: %lld); error=%u\n", mod.m_ModuleName, mod.m_ImageBase, mod.m_SizeBytes, GetLastError());
55 | }
56 | }
57 |
58 | SYMBOL_INFO* sym = static_cast(malloc(sizeof(SYMBOL_INFO) + 1024 * sizeof sym->Name[0]));
59 |
60 | QSet ripLookup;
61 | int resolve_count = 0;
62 | int fail_count = 0;
63 |
64 | auto resolve_symbol = [&](uintptr_t rip) -> void
65 | {
66 | if (ripLookup.contains(rip))
67 | return;
68 |
69 | ++resolve_count;
70 |
71 | sym->SizeOfStruct = sizeof(SYMBOL_INFO);
72 | sym->MaxNameLen = 1024;
73 |
74 | DWORD64 disp64 = 0;
75 | DWORD disp32 = 0;
76 | IMAGEHLP_LINE64 line_info = { sizeof line_info, 0 };
77 |
78 | ResolvedSymbol out_sym;
79 | out_sym.m_Rip = rip;
80 |
81 | if (SymFromAddr(hproc, rip, &disp64, sym))
82 | {
83 | out_sym.m_SymbolName = sym->Name;
84 |
85 | if (SymGetLineFromAddr64(hproc, rip, &disp32, &line_info))
86 | {
87 | out_sym.m_FileName = line_info.FileName;
88 | out_sym.m_LineNumber = line_info.LineNumber;
89 | out_sym.m_Displacement = disp32;
90 | }
91 | }
92 |
93 | if (out_sym.m_SymbolName.isEmpty())
94 | {
95 | out_sym.m_SymbolName = QStringLiteral("[%1]").arg(rip, 16, 16, QLatin1Char('0'));
96 | ++fail_count;
97 | }
98 |
99 | // Try to find the module..
100 | out_sym.m_ModuleIndex = ~0u;
101 | for (uint32_t i = 0; i < input.m_ModuleCount; ++i)
102 | {
103 | const SerializedModuleEntry& mod = input.m_Modules[i];
104 | if (rip >= mod.m_ImageBase && rip <= mod.m_ImageBase + mod.m_SizeBytes)
105 | {
106 | out_sym.m_ModuleIndex = i;
107 | break;
108 | }
109 | }
110 |
111 | ripLookup.insert(rip);
112 | resolvedSymbolsOut->push_back(out_sym);
113 | };
114 |
115 | int total = input.m_StackCount + input.m_NodeCount;
116 | int completed = 0;
117 |
118 | reportProgress(completed, total);
119 |
120 | for (uint32_t i = 0; i < input.m_StackCount; ++i, ++completed)
121 | {
122 | if (uintptr_t rip = input.m_Stacks[i])
123 | {
124 | resolve_symbol(rip);
125 | }
126 |
127 | if (0 == (completed & 0x400))
128 | {
129 | reportProgress(completed, total);
130 | }
131 | }
132 |
133 | // Resolve any instructions used in leaf functions.
134 | for (uint32_t i = 0; i < input.m_NodeCount; ++i, ++completed)
135 | {
136 | resolve_symbol(input.m_Nodes[i].m_Rip);
137 |
138 | if (0 == (completed & 0x400))
139 | {
140 | reportProgress(completed, total);
141 | }
142 | }
143 |
144 | reportProgress(completed, total);
145 |
146 | if (fail_count)
147 | {
148 | //Warn("%d out of %d symbols failed to resolve\n", fail_count, resolve_count);
149 | }
150 |
151 |
152 | free(sym);
153 | sym = nullptr;
154 |
155 | return true;
156 | }
157 |
158 | #if 0
159 | static BOOL CALLBACK DbgHelpCallback(
160 | _In_ HANDLE hProcess,
161 | _In_ ULONG ActionCode,
162 | _In_opt_ ULONG64 CallbackData,
163 | _In_opt_ ULONG64 UserContext)
164 | {
165 | UNREFERENCED_VARIABLE((hProcess, UserContext));
166 |
167 | if (CBA_DEBUG_INFO == ActionCode)
168 | {
169 | printf("dbghelp: %s", (const char*)CallbackData);
170 | }
171 |
172 | return FALSE;
173 | }
174 | #endif
175 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | CacheSim
2 | ========
3 |
4 | This is CacheSim, a cache simulator developed by Insomniac Games. In its current form it simulates
5 | an AMD Jaguar cache configuration. It requires a 64-bit Windows machine to work. It has been tested on
6 | Windows 8, 8.1 and 10, but may require tweaking to run on your particular version of Windows.
7 |
8 | For more information on how CacheSim was developed and how it works internally,
9 | you can check out [this GDC 2017 slide deck](https://deplinenoise.wordpress.com/2017/03/02/slides-insomniac-games-cachesim/).
10 |
11 | The talk is available on the GDC vault with full video as well.
12 |
13 | Getting the Source
14 | ------------------
15 |
16 | 1. Clone this project
17 | 2. `git submodule init`
18 | 3. `git submodule update`
19 |
20 | The latter two commands will fetch Google Test which is required to build the unit tests.
21 |
22 | Build Instructions
23 | ------------------
24 |
25 | You'll need the following:
26 |
27 | * Visual Studio 2015
28 | * CMake
29 | * Qt 5.7 or later
30 |
31 | To build CacheSim:
32 |
33 | 1. Launch the Qt command line environment
34 | 2. CD into the CacheSim directory
35 | 3. Create a `build` directory: `mkdir build`
36 | 4. Change into this build directory: `cd build`
37 | 5. Run `cmake -G "Visual Studio 14 2015 Win64" ..`
38 | 6. `start CacheSim.sln` to open the solution and build in Visual Studio
39 |
40 | Note that the only supported build configuration is 64-bit (x64). Bug reports about
41 | missing 32-bit support will be ignored.
42 |
43 | License
44 | -------
45 |
46 | Copyright (c) 2017, Insomniac Games All rights reserved.
47 |
48 | Redistribution and use in source and binary forms, with or without
49 | modification, are permitted provided that the following conditions are met:
50 |
51 | Redistributions of source code must retain the above copyright notice, this
52 | list of conditions and the following disclaimer.
53 |
54 | Redistributions in binary form must reproduce the above copyright notice, this
55 | list of conditions and the following disclaimer in the documentation and/or
56 | other materials provided with the distribution.
57 |
58 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
59 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
60 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
61 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
62 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
64 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
65 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
66 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
67 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
68 |
69 | Third Party Software
70 | --------------------
71 |
72 | CacheSim includes a version of udis86, which has the following license:
73 |
74 | Copyright (c) 2002-2009 Vivek Thampi
75 | All rights reserved.
76 |
77 | Redistribution and use in source and binary forms, with or without modification,
78 | are permitted provided that the following conditions are met:
79 |
80 | * Redistributions of source code must retain the above copyright notice,
81 | this list of conditions and the following disclaimer.
82 | * Redistributions in binary form must reproduce the above copyright notice,
83 | this list of conditions and the following disclaimer in the documentation
84 | and/or other materials provided with the distribution.
85 |
86 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
87 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
88 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
89 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
90 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
91 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
92 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
93 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
94 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
95 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
96 |
97 | CacheSim includes a version of MD5 written by L. Peter Deutsch which has the
98 | following license:
99 |
100 | Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
101 |
102 | This software is provided 'as-is', without any express or implied
103 | warranty. In no event will the authors be held liable for any damages
104 | arising from the use of this software.
105 |
106 | Permission is granted to anyone to use this software for any purpose,
107 | including commercial applications, and to alter it and redistribute it
108 | freely, subject to the following restrictions:
109 |
110 | 1. The origin of this software must not be misrepresented; you must not
111 | claim that you wrote the original software. If you use this software
112 | in a product, an acknowledgment in the product documentation would be
113 | appreciated but is not required.
114 | 2. Altered source versions must be plainly marked as such, and must not be
115 | misrepresented as being the original software.
116 | 3. This notice may not be removed or altered from any source distribution.
117 |
118 |
--------------------------------------------------------------------------------
/UI/TraceTab.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | TraceTab
4 |
5 |
6 |
7 | 0
8 | 0
9 | 676
10 | 759
11 |
12 |
13 |
14 | Form
15 |
16 |
17 |
18 | 0
19 |
20 |
21 | 4
22 |
23 |
24 | 0
25 |
26 |
27 | 0
28 |
29 | -
30 |
31 |
32 | 0
33 |
34 |
35 | true
36 |
37 |
38 |
39 | Info
40 |
41 |
42 |
43 | 8
44 |
45 |
46 | 8
47 |
48 |
49 | 8
50 |
51 |
52 | 8
53 |
54 |
55 | 8
56 |
57 |
-
58 |
59 |
-
60 |
61 |
62 | &Resolve
63 |
64 |
65 | Ctrl+R
66 |
67 |
68 |
69 | -
70 |
71 |
72 | Symbol Status
73 |
74 |
75 |
76 | -
77 |
78 |
79 | status
80 |
81 |
82 |
83 | -
84 |
85 |
86 | Qt::Horizontal
87 |
88 |
89 |
90 | 456
91 | 20
92 |
93 |
94 |
95 |
96 |
97 |
98 | -
99 |
100 |
-
101 |
102 |
103 | &Flat Profile
104 |
105 |
106 | Ctrl+F
107 |
108 |
109 |
110 | -
111 |
112 |
113 | Open a flat profile of all symbols
114 |
115 |
116 |
117 | -
118 |
119 |
120 | Qt::Horizontal
121 |
122 |
123 |
124 | 228
125 | 20
126 |
127 |
128 |
129 |
130 |
131 |
132 | -
133 |
134 |
-
135 |
136 |
137 | &Tree Profile
138 |
139 |
140 |
141 | -
142 |
143 |
144 | Open a profiling view that breaks down the data in a call tree
145 |
146 |
147 |
148 | -
149 |
150 |
151 | Qt::Horizontal
152 |
153 |
154 |
155 | 228
156 | 20
157 |
158 |
159 |
160 |
161 |
162 |
163 | -
164 |
165 |
166 | Qt::Vertical
167 |
168 |
169 |
170 | 20
171 | 627
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
--------------------------------------------------------------------------------
/UI/FlatModel.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017, Insomniac Games
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | Redistributions in binary form must reproduce the above copyright notice, this
12 | list of conditions and the following disclaimer in the documentation and/or
13 | other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #include "Precompiled.h"
28 | #include "FlatModel.h"
29 | #include "TraceData.h"
30 | #include "CacheSim/CacheSimData.h"
31 |
32 | static const QString kColumnLabels[CacheSim::FlatModel::kColumnCount] =
33 | {
34 | QStringLiteral("Symbol"),
35 | QStringLiteral("D1Hit"),
36 | QStringLiteral("I1Hit"),
37 | QStringLiteral("L2IMiss"),
38 | QStringLiteral("L2DMiss"),
39 | QStringLiteral("Badness"),
40 | QStringLiteral("InstructionsExecuted"),
41 | QStringLiteral("PF-D1"),
42 | QStringLiteral("PF-L2"),
43 | };
44 |
45 | CacheSim::FlatModel::FlatModel(QObject* parent /*= nullptr*/)
46 | : QAbstractListModel(parent)
47 | {
48 | }
49 |
50 | CacheSim::FlatModel::~FlatModel()
51 | {
52 | }
53 |
54 | void CacheSim::FlatModel::setData(const TraceData* data)
55 | {
56 | if (m_Data)
57 | {
58 | disconnect(m_Data, &TraceData::memoryMappedDataChanged, this, &FlatModel::dataStoreChanged);
59 | }
60 |
61 | m_Data = data;
62 | dataStoreChanged();
63 |
64 | if (m_Data)
65 | {
66 | connect(m_Data, &TraceData::memoryMappedDataChanged, this, &FlatModel::dataStoreChanged);
67 | }
68 | }
69 |
70 | int CacheSim::FlatModel::rowCount(const QModelIndex &parent /*= QModelIndex()*/) const
71 | {
72 | (void) parent;
73 | return m_Rows.count();
74 | }
75 |
76 | int CacheSim::FlatModel::columnCount(const QModelIndex &parent /*= QModelIndex()*/) const
77 | {
78 | (void) parent;
79 | return kColumnCount;
80 | }
81 |
82 | QVariant CacheSim::FlatModel::data(const QModelIndex &index, int role /*= Qt::DisplayRole*/) const
83 | {
84 | int row = index.row();
85 | if (row < 0 || row >= m_Rows.count())
86 | {
87 | return QVariant();
88 | }
89 |
90 | const Node& node = m_Rows[row];
91 |
92 | if (role == Qt::DisplayRole)
93 | {
94 | switch (index.column())
95 | {
96 | case kColumnSymbol: return node.m_SymbolName;
97 | case kColumnD1Hit: return node.m_Stats[CacheSim::kD1Hit];
98 | case kColumnI1Hit: return node.m_Stats[CacheSim::kI1Hit];
99 | case kColumnL2IMiss: return node.m_Stats[CacheSim::kL2IMiss];
100 | case kColumnL2DMiss: return node.m_Stats[CacheSim::kL2DMiss];
101 | case kColumnBadness: return BadnessValue(node.m_Stats);
102 | case kColumnInstructionsExecuted: return node.m_Stats[CacheSim::kInstructionsExecuted];
103 | case kColumnPFD1: return node.m_Stats[CacheSim::kPrefetchHitD1];
104 | case kColumnPFL2: return node.m_Stats[CacheSim::kPrefetchHitL2];
105 | }
106 | }
107 | else if (role == Qt::TextAlignmentRole)
108 | {
109 | if (index.column() > kColumnSymbol)
110 | {
111 | return Qt::AlignRight;
112 | }
113 | return Qt::AlignLeft;
114 | }
115 | else if (role == Qt::ToolTipRole)
116 | {
117 | if (index.column() == kColumnSymbol)
118 | {
119 | return node.m_SymbolName;
120 | }
121 | }
122 |
123 | return QVariant();
124 | }
125 |
126 | QVariant CacheSim::FlatModel::headerData(int section, Qt::Orientation orientation, int role /*= Qt::DisplayRole*/) const
127 | {
128 | if (role == Qt::DisplayRole && orientation == Qt::Horizontal)
129 | {
130 | return kColumnLabels[section];
131 | }
132 |
133 | return QVariant();
134 | }
135 |
136 | void CacheSim::FlatModel::dataStoreChanged()
137 | {
138 | beginResetModel();
139 |
140 | m_Rows.clear();
141 |
142 | // Aggregate all symbols based on name.
143 | QHash symbolNameToRow;
144 |
145 | const SerializedHeader* header = m_Data->header();
146 | uint32_t count = header->GetStatCount();
147 | const SerializedNode* nodes = header->GetStats();
148 |
149 | for (uint32_t i = 0; i < count; ++i)
150 | {
151 | const SerializedNode& node = nodes[i];
152 | if (const SerializedSymbol* symbol = header->FindSymbol(node.m_Rip))
153 | {
154 | int row;
155 | QString symbolName = m_Data->symbolNameForAddress(node.m_Rip);
156 | auto it = symbolNameToRow.find(symbolName);
157 | if (it != symbolNameToRow.end())
158 | {
159 | row = it.value();
160 | }
161 | else
162 | {
163 | row = m_Rows.count();
164 | m_Rows.push_back(Node());
165 | m_Rows[row].m_SymbolName = symbolName;
166 | symbolNameToRow.insert(symbolName, row);
167 | }
168 |
169 | Node& target = m_Rows[row];
170 |
171 | for (int k = 0; k < CacheSim::kAccessResultCount; ++k)
172 | {
173 | target.m_Stats[k] += node.m_Stats[k];
174 | }
175 | }
176 | }
177 |
178 | qDebug() << "collapsed" << count << "nodes to" << m_Rows.count() << "flat entries based on symbol";
179 | endResetModel();
180 | }
181 |
182 | CacheSim::FlatModel::Node::Node()
183 | {
184 | memset(m_Stats, 0, sizeof m_Stats);
185 | }
186 |
187 | #include "aux_FlatModel.moc"
188 |
--------------------------------------------------------------------------------
/CacheSim/CacheSimInternals.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | /*
4 | Copyright (c) 2017, Insomniac Games
5 | All rights reserved.
6 |
7 | Redistribution and use in source and binary forms, with or without
8 | modification, are permitted provided that the following conditions are met:
9 |
10 | Redistributions of source code must retain the above copyright notice, this
11 | list of conditions and the following disclaimer.
12 |
13 | Redistributions in binary form must reproduce the above copyright notice, this
14 | list of conditions and the following disclaimer in the documentation and/or
15 | other materials provided with the distribution.
16 |
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
21 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | #include "CacheSim.h"
30 |
31 | #include // for std::swap
32 |
33 | namespace CacheSim
34 | {
35 | enum AccessResult
36 | {
37 | kD1Hit = 0, ///< Access hit the D1
38 | kI1Hit, ///< Access hit the I1
39 | kL2Hit, ///< Access hit the L2
40 | kL2IMiss, ///< Access missed the L2 due to an instruction fetch
41 | kL2DMiss, ///< Access missed the L2 due to a data access
42 | kPrefetchHitD1,
43 | kPrefetchHitL2,
44 | kInstructionsExecuted,
45 | kAccessResultCount
46 | };
47 |
48 | enum AccessMode
49 | {
50 | kRead,
51 | kCodeRead,
52 | kWrite
53 | };
54 |
55 | template
56 | struct SetData
57 | {
58 | uint64_t m_Addr[kWays]; ///< Virtual address cached, or zero (invalid).
59 | };
60 |
61 | template
62 | class Cache
63 | {
64 | public:
65 |
66 | static constexpr size_t kLineSize = 64; ///< We're on x86.
67 | static constexpr size_t kSetSizeShift = 6; ///< Log2(kLineSize)
68 | static constexpr size_t kSetCount = kCacheSizeBytes / kLineSize / kWays;
69 | static constexpr size_t kSetMask = kSetCount - 1;
70 |
71 | static_assert((kWays & (kWays - 1)) == 0, "Way count must be power of 2");
72 | static_assert((kSetCount & (~size_t(kSetMask))) == kSetCount, "Set count must be power of 2");
73 | static_assert(kSetCount * kLineSize * kWays == kCacheSizeBytes, "Size must divide perfectly");
74 |
75 | void Init()
76 | {
77 | memset(m_Sets, 0, sizeof m_Sets);
78 | }
79 |
80 | SetData m_Sets[kSetCount];
81 |
82 | bool Access(uint64_t addr)
83 | {
84 | uint64_t base = addr >> kSetSizeShift;
85 |
86 | const uint32_t line_index = base & kSetMask;
87 |
88 | SetData* set = &m_Sets[line_index];
89 |
90 | for (size_t way = 0; way < kWays; ++way)
91 | {
92 | const uint64_t stored_addr = set->m_Addr[way];
93 |
94 | if (stored_addr == base)
95 | {
96 | // Shift the hit way to the front of the set to reflect MRU status.
97 | // This isn't optimal, but it doesn't really matter much in the grand scheme of things.
98 | while (way > 0)
99 | {
100 | std::swap(set->m_Addr[way], set->m_Addr[way-1]);
101 | --way;
102 | }
103 | return true;
104 | }
105 | }
106 |
107 | // Miss: Move everything in the way to the right and insert this thing as the MRU.
108 | for (size_t i = kWays - 1; i > 0; --i)
109 | {
110 | set->m_Addr[i] = set->m_Addr[i - 1];
111 |
112 | }
113 | set->m_Addr[0] = base;
114 | return false;
115 | }
116 |
117 | void Invalidate(uint64_t addr)
118 | {
119 | uint64_t base = addr >> kSetSizeShift;
120 |
121 | const uint32_t line_index = base & kSetMask;
122 |
123 | SetData* set = &m_Sets[line_index];
124 |
125 | for (size_t way = 0; way < kWays; ++way)
126 | {
127 | if (set->m_Addr[way] == base)
128 | {
129 | // Take the invalidated way out of the array by moving in elements from the right (that then survive longer)
130 | for (size_t rw = way; rw < kWays - 1; ++rw)
131 | {
132 | set->m_Addr[rw] = set->m_Addr[rw + 1];
133 | }
134 |
135 | // Mark the last way as 0 so we don't hit it later.
136 | set->m_Addr[kWays - 1] = 0;
137 | break;
138 | }
139 | }
140 | }
141 | };
142 |
143 | /// Simulate the Jaguar 32 KB L1 cache
144 | /// 512 lines or 64 bytes each, 8 ways per line
145 | using JaguarD1 = Cache<32 * 1024, 8>;
146 | /// I1 is 2-way set assoc, 32 KB
147 | using JaguarI1 = Cache<32 * 1024, 2>;
148 | /// Jaguar L2 is 2 MB, 16 way set assoc.
149 | using JaguarL2 = Cache<2 * 1024 * 1024, 16>;
150 |
151 | class JaguarModule
152 | {
153 | public:
154 | enum { kCoreCount = 4 };
155 |
156 | private:
157 | JaguarD1 m_CoreD1[kCoreCount];
158 | JaguarI1 m_CoreI1[kCoreCount];
159 | JaguarL2 m_Level2;
160 | JaguarModule* m_OtherModule;
161 |
162 | public:
163 | void Init(JaguarModule* other_module)
164 | {
165 | for (int i = 0; i < kCoreCount; ++i)
166 | {
167 | m_CoreD1[i].Init();
168 | m_CoreI1[i].Init();
169 | }
170 | m_Level2.Init();
171 | m_OtherModule = other_module;
172 | }
173 |
174 | IG_CACHESIM_API AccessResult Access(int core_index, uintptr_t addr, AccessMode mode);
175 | };
176 |
177 | class JaguarCacheSim
178 | {
179 | private:
180 | JaguarModule m_Modules[2];
181 |
182 | public:
183 | void Init()
184 | {
185 | m_Modules[0].Init(&m_Modules[1]);
186 | m_Modules[1].Init(&m_Modules[0]);
187 | }
188 |
189 | IG_CACHESIM_API AccessResult Access(int core_index, uintptr_t addr, size_t size, AccessMode mode);
190 | };
191 |
192 | }
193 |
--------------------------------------------------------------------------------
/udis86/decode.h:
--------------------------------------------------------------------------------
1 | /* udis86 - libudis86/decode.h
2 | *
3 | * Copyright (c) 2002-2009 Vivek Thampi
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without modification,
7 | * are permitted provided that the following conditions are met:
8 | *
9 | * * Redistributions of source code must retain the above copyright notice,
10 | * this list of conditions and the following disclaimer.
11 | * * Redistributions in binary form must reproduce the above copyright notice,
12 | * this list of conditions and the following disclaimer in the documentation
13 | * and/or other materials provided with the distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 | #ifndef UD_DECODE_H
27 | #define UD_DECODE_H
28 |
29 | #include "types.h"
30 | #include "udint.h"
31 | #include "itab.h"
32 |
33 | #define MAX_INSN_LENGTH 15
34 |
35 | /* itab prefix bits */
36 | #define P_none ( 0 )
37 |
38 | #define P_inv64 ( 1 << 0 )
39 | #define P_INV64(n) ( ( n >> 0 ) & 1 )
40 | #define P_def64 ( 1 << 1 )
41 | #define P_DEF64(n) ( ( n >> 1 ) & 1 )
42 |
43 | #define P_oso ( 1 << 2 )
44 | #define P_OSO(n) ( ( n >> 2 ) & 1 )
45 | #define P_aso ( 1 << 3 )
46 | #define P_ASO(n) ( ( n >> 3 ) & 1 )
47 |
48 | #define P_rexb ( 1 << 4 )
49 | #define P_REXB(n) ( ( n >> 4 ) & 1 )
50 | #define P_rexw ( 1 << 5 )
51 | #define P_REXW(n) ( ( n >> 5 ) & 1 )
52 | #define P_rexr ( 1 << 6 )
53 | #define P_REXR(n) ( ( n >> 6 ) & 1 )
54 | #define P_rexx ( 1 << 7 )
55 | #define P_REXX(n) ( ( n >> 7 ) & 1 )
56 |
57 | #define P_seg ( 1 << 8 )
58 | #define P_SEG(n) ( ( n >> 8 ) & 1 )
59 |
60 | #define P_vexl ( 1 << 9 )
61 | #define P_VEXL(n) ( ( n >> 9 ) & 1 )
62 | #define P_vexw ( 1 << 10 )
63 | #define P_VEXW(n) ( ( n >> 10 ) & 1 )
64 |
65 | #define P_str ( 1 << 11 )
66 | #define P_STR(n) ( ( n >> 11 ) & 1 )
67 | #define P_strz ( 1 << 12 )
68 | #define P_STR_ZF(n) ( ( n >> 12 ) & 1 )
69 |
70 | /* operand type constants -- order is important! */
71 |
72 | enum ud_operand_code {
73 | OP_NONE,
74 |
75 | OP_A, OP_E, OP_M, OP_G,
76 | OP_I, OP_F,
77 |
78 | OP_R0, OP_R1, OP_R2, OP_R3,
79 | OP_R4, OP_R5, OP_R6, OP_R7,
80 |
81 | OP_AL, OP_CL, OP_DL,
82 | OP_AX, OP_CX, OP_DX,
83 | OP_eAX, OP_eCX, OP_eDX,
84 | OP_rAX, OP_rCX, OP_rDX,
85 |
86 | OP_ES, OP_CS, OP_SS, OP_DS,
87 | OP_FS, OP_GS,
88 |
89 | OP_ST0, OP_ST1, OP_ST2, OP_ST3,
90 | OP_ST4, OP_ST5, OP_ST6, OP_ST7,
91 |
92 | OP_J, OP_S, OP_O,
93 | OP_I1, OP_I3, OP_sI,
94 |
95 | OP_V, OP_W, OP_Q, OP_P,
96 | OP_U, OP_N, OP_MU, OP_H,
97 | OP_L,
98 |
99 | OP_R, OP_C, OP_D,
100 |
101 | OP_MR
102 | } UD_ATTR_PACKED;
103 |
104 |
105 | /*
106 | * Operand size constants
107 | *
108 | * Symbolic constants for various operand sizes. Some of these constants
109 | * are given a value equal to the width of the data (SZ_B == 8), such
110 | * that they maybe used interchangeably in the internals. Modifying them
111 | * will most certainly break things!
112 | */
113 | typedef uint16_t ud_operand_size_t;
114 |
115 | #define SZ_NA 0
116 | #define SZ_Z 1
117 | #define SZ_V 2
118 | #define SZ_Y 3
119 | #define SZ_X 4
120 | #define SZ_RDQ 7
121 | #define SZ_B 8
122 | #define SZ_W 16
123 | #define SZ_D 32
124 | #define SZ_Q 64
125 | #define SZ_T 80
126 | #define SZ_O 12
127 | #define SZ_DQ 128 /* double quad */
128 | #define SZ_QQ 256 /* quad quad */
129 |
130 | /*
131 | * Complex size types; that encode sizes for operands of type MR (memory or
132 | * register); for internal use only. Id space above 256.
133 | */
134 | #define SZ_BD ((SZ_B << 8) | SZ_D)
135 | #define SZ_BV ((SZ_B << 8) | SZ_V)
136 | #define SZ_WD ((SZ_W << 8) | SZ_D)
137 | #define SZ_WV ((SZ_W << 8) | SZ_V)
138 | #define SZ_WY ((SZ_W << 8) | SZ_Y)
139 | #define SZ_DY ((SZ_D << 8) | SZ_Y)
140 | #define SZ_WO ((SZ_W << 8) | SZ_O)
141 | #define SZ_DO ((SZ_D << 8) | SZ_O)
142 | #define SZ_QO ((SZ_Q << 8) | SZ_O)
143 |
144 |
145 | /* resolve complex size type.
146 | */
147 | static UD_INLINE ud_operand_size_t
148 | Mx_mem_size(ud_operand_size_t size)
149 | {
150 | return (size >> 8) & 0xff;
151 | }
152 |
153 | static UD_INLINE ud_operand_size_t
154 | Mx_reg_size(ud_operand_size_t size)
155 | {
156 | return size & 0xff;
157 | }
158 |
159 | /* A single operand of an entry in the instruction table.
160 | * (internal use only)
161 | */
162 | struct ud_itab_entry_operand
163 | {
164 | enum ud_operand_code type;
165 | ud_operand_size_t size;
166 | };
167 |
168 |
169 | /* A single entry in an instruction table.
170 | *(internal use only)
171 | */
172 | struct ud_itab_entry
173 | {
174 | enum ud_mnemonic_code mnemonic;
175 | struct ud_itab_entry_operand operand1;
176 | struct ud_itab_entry_operand operand2;
177 | struct ud_itab_entry_operand operand3;
178 | struct ud_itab_entry_operand operand4;
179 | uint8_t operand1_access;
180 | uint8_t operand2_access;
181 | uint32_t prefix;
182 | struct ud_eflags eflags;
183 | enum ud_type implicit_register_uses[32];
184 | enum ud_type implicit_register_defs[32];
185 | };
186 |
187 | struct ud_lookup_table_list_entry {
188 | const uint16_t *table;
189 | enum ud_table_type type;
190 | const char *meta;
191 | };
192 |
193 | extern struct ud_itab_entry ud_itab[];
194 | extern struct ud_lookup_table_list_entry ud_lookup_table_list[];
195 |
196 | #endif /* UD_DECODE_H */
197 |
198 | /* vim:cindent
199 | * vim:expandtab
200 | * vim:ts=4
201 | * vim:sw=4
202 | */
203 |
--------------------------------------------------------------------------------
/udis86/syn-att.c:
--------------------------------------------------------------------------------
1 | /* udis86 - libudis86/syn-att.c
2 | *
3 | * Copyright (c) 2002-2009 Vivek Thampi
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without modification,
7 | * are permitted provided that the following conditions are met:
8 | *
9 | * * Redistributions of source code must retain the above copyright notice,
10 | * this list of conditions and the following disclaimer.
11 | * * Redistributions in binary form must reproduce the above copyright notice,
12 | * this list of conditions and the following disclaimer in the documentation
13 | * and/or other materials provided with the distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 | #include "types.h"
27 | #include "extern.h"
28 | #include "decode.h"
29 | #include "itab.h"
30 | #include "syn.h"
31 | #include "udint.h"
32 |
33 | /* -----------------------------------------------------------------------------
34 | * opr_cast() - Prints an operand cast.
35 | * -----------------------------------------------------------------------------
36 | */
37 | static void
38 | opr_cast(struct ud* u, struct ud_operand* op)
39 | {
40 | switch(op->size) {
41 | case 16 : case 32 :
42 | ud_asmprintf(u, "*"); break;
43 | default: break;
44 | }
45 | }
46 |
47 | /* -----------------------------------------------------------------------------
48 | * gen_operand() - Generates assembly output for each operand.
49 | * -----------------------------------------------------------------------------
50 | */
51 | static void
52 | gen_operand(struct ud* u, struct ud_operand* op)
53 | {
54 | switch(op->type) {
55 | case UD_OP_CONST:
56 | ud_asmprintf(u, "$0x%x", op->lval.udword);
57 | break;
58 |
59 | case UD_OP_REG:
60 | ud_asmprintf(u, "%%%s", ud_reg_tab[op->base - UD_R_AL]);
61 | break;
62 |
63 | case UD_OP_MEM:
64 | if (u->br_far) {
65 | opr_cast(u, op);
66 | }
67 | if (u->pfx_seg) {
68 | ud_asmprintf(u, "%%%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]);
69 | }
70 | if (op->offset != 0) {
71 | ud_syn_print_mem_disp(u, op, 0);
72 | }
73 | if (op->base) {
74 | ud_asmprintf(u, "(%%%s", ud_reg_tab[op->base - UD_R_AL]);
75 | }
76 | if (op->index) {
77 | if (op->base) {
78 | ud_asmprintf(u, ",");
79 | } else {
80 | ud_asmprintf(u, "(");
81 | }
82 | ud_asmprintf(u, "%%%s", ud_reg_tab[op->index - UD_R_AL]);
83 | }
84 | if (op->scale) {
85 | ud_asmprintf(u, ",%d", op->scale);
86 | }
87 | if (op->base || op->index) {
88 | ud_asmprintf(u, ")");
89 | }
90 | break;
91 |
92 | case UD_OP_IMM:
93 | ud_asmprintf(u, "$");
94 | ud_syn_print_imm(u, op);
95 | break;
96 |
97 | case UD_OP_JIMM:
98 | ud_syn_print_addr(u, ud_syn_rel_target(u, op));
99 | break;
100 |
101 | case UD_OP_PTR:
102 | switch (op->size) {
103 | case 32:
104 | ud_asmprintf(u, "$0x%x, $0x%x", op->lval.ptr.seg,
105 | op->lval.ptr.off & 0xFFFF);
106 | break;
107 | case 48:
108 | ud_asmprintf(u, "$0x%x, $0x%x", op->lval.ptr.seg,
109 | op->lval.ptr.off);
110 | break;
111 | }
112 | break;
113 |
114 | default: return;
115 | }
116 | }
117 |
118 | /* =============================================================================
119 | * translates to AT&T syntax
120 | * =============================================================================
121 | */
122 | extern void
123 | ud_translate_att(struct ud *u)
124 | {
125 | int size = 0;
126 | int star = 0;
127 |
128 | /* check if P_OSO prefix is used */
129 | if (! P_OSO(u->itab_entry->prefix) && u->pfx_opr) {
130 | switch (u->dis_mode) {
131 | case 16:
132 | ud_asmprintf(u, "o32 ");
133 | break;
134 | case 32:
135 | case 64:
136 | ud_asmprintf(u, "o16 ");
137 | break;
138 | }
139 | }
140 |
141 | /* check if P_ASO prefix was used */
142 | if (! P_ASO(u->itab_entry->prefix) && u->pfx_adr) {
143 | switch (u->dis_mode) {
144 | case 16:
145 | ud_asmprintf(u, "a32 ");
146 | break;
147 | case 32:
148 | ud_asmprintf(u, "a16 ");
149 | break;
150 | case 64:
151 | ud_asmprintf(u, "a32 ");
152 | break;
153 | }
154 | }
155 |
156 | if (u->pfx_lock)
157 | ud_asmprintf(u, "lock ");
158 | if (u->pfx_rep) {
159 | ud_asmprintf(u, "rep ");
160 | } else if (u->pfx_rep) {
161 | ud_asmprintf(u, "repe ");
162 | } else if (u->pfx_repne) {
163 | ud_asmprintf(u, "repne ");
164 | }
165 |
166 | /* special instructions */
167 | switch (u->mnemonic) {
168 | case UD_Iretf:
169 | ud_asmprintf(u, "lret ");
170 | break;
171 | case UD_Idb:
172 | ud_asmprintf(u, ".byte 0x%x", u->operand[0].lval.ubyte);
173 | return;
174 | case UD_Ijmp:
175 | case UD_Icall:
176 | if (u->br_far) ud_asmprintf(u, "l");
177 | if (u->operand[0].type == UD_OP_REG) {
178 | star = 1;
179 | }
180 | ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic));
181 | break;
182 | case UD_Ibound:
183 | case UD_Ienter:
184 | if (u->operand[0].type != UD_NONE)
185 | gen_operand(u, &u->operand[0]);
186 | if (u->operand[1].type != UD_NONE) {
187 | ud_asmprintf(u, ",");
188 | gen_operand(u, &u->operand[1]);
189 | }
190 | return;
191 | default:
192 | ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic));
193 | }
194 |
195 | if (size == 8) {
196 | ud_asmprintf(u, "b");
197 | } else if (size == 16) {
198 | ud_asmprintf(u, "w");
199 | } else if (size == 64) {
200 | ud_asmprintf(u, "q");
201 | }
202 |
203 | if (star) {
204 | ud_asmprintf(u, " *");
205 | } else {
206 | ud_asmprintf(u, " ");
207 | }
208 |
209 | if (u->operand[3].type != UD_NONE) {
210 | gen_operand(u, &u->operand[3]);
211 | ud_asmprintf(u, ", ");
212 | }
213 | if (u->operand[2].type != UD_NONE) {
214 | gen_operand(u, &u->operand[2]);
215 | ud_asmprintf(u, ", ");
216 | }
217 | if (u->operand[1].type != UD_NONE) {
218 | gen_operand(u, &u->operand[1]);
219 | ud_asmprintf(u, ", ");
220 | }
221 | if (u->operand[0].type != UD_NONE) {
222 | gen_operand(u, &u->operand[0]);
223 | }
224 | }
225 |
226 | /*
227 | vim: set ts=2 sw=2 expandtab
228 | */
229 |
--------------------------------------------------------------------------------
/udis86/syn.c:
--------------------------------------------------------------------------------
1 | /* udis86 - libudis86/syn.c
2 | *
3 | * Copyright (c) 2002-2013 Vivek Thampi
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without modification,
7 | * are permitted provided that the following conditions are met:
8 | *
9 | * * Redistributions of source code must retain the above copyright notice,
10 | * this list of conditions and the following disclaimer.
11 | * * Redistributions in binary form must reproduce the above copyright notice,
12 | * this list of conditions and the following disclaimer in the documentation
13 | * and/or other materials provided with the distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 | #include "types.h"
27 | #include "decode.h"
28 | #include "syn.h"
29 | #include "udint.h"
30 | #include
31 | #include
32 |
33 | #pragma warning(disable:4267)
34 |
35 | /*
36 | * Register Table - Order Matters (types.h)!
37 | *
38 | */
39 | const char* ud_reg_tab[] =
40 | {
41 | "al", "cl", "dl", "bl",
42 | "ah", "ch", "dh", "bh",
43 | "spl", "bpl", "sil", "dil",
44 | "r8b", "r9b", "r10b", "r11b",
45 | "r12b", "r13b", "r14b", "r15b",
46 |
47 | "ax", "cx", "dx", "bx",
48 | "sp", "bp", "si", "di",
49 | "r8w", "r9w", "r10w", "r11w",
50 | "r12w", "r13w", "r14w", "r15w",
51 |
52 | "eax", "ecx", "edx", "ebx",
53 | "esp", "ebp", "esi", "edi",
54 | "r8d", "r9d", "r10d", "r11d",
55 | "r12d", "r13d", "r14d", "r15d",
56 |
57 | "rax", "rcx", "rdx", "rbx",
58 | "rsp", "rbp", "rsi", "rdi",
59 | "r8", "r9", "r10", "r11",
60 | "r12", "r13", "r14", "r15",
61 |
62 | "es", "cs", "ss", "ds",
63 | "fs", "gs",
64 |
65 | "cr0", "cr1", "cr2", "cr3",
66 | "cr4", "cr5", "cr6", "cr7",
67 | "cr8", "cr9", "cr10", "cr11",
68 | "cr12", "cr13", "cr14", "cr15",
69 |
70 | "dr0", "dr1", "dr2", "dr3",
71 | "dr4", "dr5", "dr6", "dr7",
72 | "dr8", "dr9", "dr10", "dr11",
73 | "dr12", "dr13", "dr14", "dr15",
74 |
75 | "mm0", "mm1", "mm2", "mm3",
76 | "mm4", "mm5", "mm6", "mm7",
77 |
78 | "st0", "st1", "st2", "st3",
79 | "st4", "st5", "st6", "st7",
80 |
81 | "xmm0", "xmm1", "xmm2", "xmm3",
82 | "xmm4", "xmm5", "xmm6", "xmm7",
83 | "xmm8", "xmm9", "xmm10", "xmm11",
84 | "xmm12", "xmm13", "xmm14", "xmm15",
85 |
86 | "ymm0", "ymm1", "ymm2", "ymm3",
87 | "ymm4", "ymm5", "ymm6", "ymm7",
88 | "ymm8", "ymm9", "ymm10", "ymm11",
89 | "ymm12", "ymm13", "ymm14", "ymm15",
90 |
91 | "rip"
92 | };
93 |
94 |
95 | uint64_t
96 | ud_syn_rel_target(struct ud *u, struct ud_operand *opr)
97 | {
98 | uint64_t trunc_mask = 0xffffffffffffffffull;
99 | if (u->dis_mode < 32) trunc_mask >>= (64 - u->opr_mode);
100 | switch (opr->size) {
101 | case 8 : return (u->pc + opr->lval.sbyte) & trunc_mask;
102 | case 16: {
103 | int delta = (opr->lval.sword & trunc_mask);
104 | if ((u->pc + delta) > 0xffff)
105 | return (u->pc & 0xf0000) + ((u->pc + delta) & 0xffff);
106 | return (u->pc + delta);
107 | }
108 | case 32: return (u->pc + opr->lval.sdword) & trunc_mask;
109 | default: UD_ASSERT(!"invalid relative offset size.");
110 | return 0ull;
111 | }
112 | }
113 |
114 |
115 | /*
116 | * asmprintf
117 | * Printf style function for printing translated assembly
118 | * output. Returns the number of characters written and
119 | * moves the buffer pointer forward. On an overflow,
120 | * returns a negative number and truncates the output.
121 | */
122 | int
123 | ud_asmprintf(struct ud *u, const char *fmt, ...)
124 | {
125 | int ret;
126 | int avail;
127 | va_list ap;
128 | va_start(ap, fmt);
129 | avail = u->asm_buf_size - u->asm_buf_fill - 1 /* nullchar */;
130 | ret = vsnprintf((char*) u->asm_buf + u->asm_buf_fill, avail, fmt, ap);
131 | if (ret < 0 || ret > avail) {
132 | u->asm_buf_fill = u->asm_buf_size - 1;
133 | } else {
134 | u->asm_buf_fill += ret;
135 | }
136 | va_end(ap);
137 | return ret;
138 | }
139 |
140 |
141 | void
142 | ud_syn_print_addr(struct ud *u, uint64_t addr)
143 | {
144 | const char *name = NULL;
145 | if (u->sym_resolver) {
146 | int64_t offset = 0;
147 | name = u->sym_resolver(u, addr, &offset);
148 | if (name) {
149 | if (offset) {
150 | ud_asmprintf(u, "%s%+" FMT64 "d", name, offset);
151 | } else {
152 | ud_asmprintf(u, "%s", name);
153 | }
154 | return;
155 | }
156 | }
157 | ud_asmprintf(u, "0x%" FMT64 "x", addr);
158 | }
159 |
160 |
161 | void
162 | ud_syn_print_imm(struct ud* u, const struct ud_operand *op)
163 | {
164 | uint64_t v;
165 | if (op->_oprcode == OP_sI && op->size != u->opr_mode) {
166 | if (op->size == 8) {
167 | v = (int64_t)op->lval.sbyte;
168 | } else {
169 | UD_ASSERT(op->size == 32);
170 | v = (int64_t)op->lval.sdword;
171 | }
172 | if (u->opr_mode < 64) {
173 | v = v & ((1ull << u->opr_mode) - 1ull);
174 | }
175 | } else {
176 | switch (op->size) {
177 | case 8 : v = op->lval.ubyte; break;
178 | case 16: v = op->lval.uword; break;
179 | case 32: v = op->lval.udword; break;
180 | case 64: v = op->lval.uqword; break;
181 | default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */
182 | }
183 | }
184 | ud_asmprintf(u, "0x%" FMT64 "x", v);
185 | }
186 |
187 |
188 | void
189 | ud_syn_print_mem_disp(struct ud* u, const struct ud_operand *op, int sign)
190 | {
191 | UD_ASSERT(op->offset != 0);
192 | if (op->base == UD_NONE && op->index == UD_NONE) {
193 | uint64_t v;
194 | UD_ASSERT(op->scale == UD_NONE && op->offset != 8);
195 | /* unsigned mem-offset */
196 | switch (op->offset) {
197 | case 16: v = op->lval.uword; break;
198 | case 32: v = op->lval.udword; break;
199 | case 64: v = op->lval.uqword; break;
200 | default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */
201 | }
202 | ud_asmprintf(u, "0x%" FMT64 "x", v);
203 | } else {
204 | int64_t v;
205 | UD_ASSERT(op->offset != 64);
206 | switch (op->offset) {
207 | case 8 : v = op->lval.sbyte; break;
208 | case 16: v = op->lval.sword; break;
209 | case 32: v = op->lval.sdword; break;
210 | default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */
211 | }
212 | if (v < 0) {
213 | ud_asmprintf(u, "-0x%" FMT64 "x", -v);
214 | } else if (v > 0) {
215 | ud_asmprintf(u, "%s0x%" FMT64 "x", sign? "+" : "", v);
216 | }
217 | }
218 | }
219 |
220 | /*
221 | vim: set ts=2 sw=2 expandtab
222 | */
223 |
--------------------------------------------------------------------------------
/udis86/syn-intel.c:
--------------------------------------------------------------------------------
1 | /* udis86 - libudis86/syn-intel.c
2 | *
3 | * Copyright (c) 2002-2013 Vivek Thampi
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without modification,
7 | * are permitted provided that the following conditions are met:
8 | *
9 | * * Redistributions of source code must retain the above copyright notice,
10 | * this list of conditions and the following disclaimer.
11 | * * Redistributions in binary form must reproduce the above copyright notice,
12 | * this list of conditions and the following disclaimer in the documentation
13 | * and/or other materials provided with the distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 | #include "types.h"
27 | #include "extern.h"
28 | #include "decode.h"
29 | #include "itab.h"
30 | #include "syn.h"
31 | #include "udint.h"
32 |
33 | /* -----------------------------------------------------------------------------
34 | * opr_cast_intel() - Prints an operand cast.
35 | * -----------------------------------------------------------------------------
36 | */
37 | static void
38 | opr_cast_intel(struct ud* u, struct ud_operand* op)
39 | {
40 | if (u->br_far) {
41 | ud_asmprintf(u, "far ");
42 | }
43 | switch(op->size) {
44 | case 8: ud_asmprintf(u, "byte " ); break;
45 | case 16: ud_asmprintf(u, "word " ); break;
46 | case 32: ud_asmprintf(u, "dword "); break;
47 | case 64: ud_asmprintf(u, "qword "); break;
48 | case 80: ud_asmprintf(u, "tword "); break;
49 | case 128: ud_asmprintf(u, "oword "); break;
50 | case 256: ud_asmprintf(u, "yword "); break;
51 | default: break;
52 | }
53 | }
54 |
55 | /* -----------------------------------------------------------------------------
56 | * gen_operand() - Generates assembly output for each operand.
57 | * -----------------------------------------------------------------------------
58 | */
59 | static void gen_operand(struct ud* u, struct ud_operand* op, int syn_cast)
60 | {
61 | switch(op->type) {
62 | case UD_OP_REG:
63 | ud_asmprintf(u, "%s", ud_reg_tab[op->base - UD_R_AL]);
64 | break;
65 |
66 | case UD_OP_MEM:
67 | if (syn_cast) {
68 | opr_cast_intel(u, op);
69 | }
70 | ud_asmprintf(u, "[");
71 | if (u->pfx_seg) {
72 | ud_asmprintf(u, "%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]);
73 | }
74 | if (op->base) {
75 | ud_asmprintf(u, "%s", ud_reg_tab[op->base - UD_R_AL]);
76 | }
77 | if (op->index) {
78 | ud_asmprintf(u, "%s%s", op->base != UD_NONE? "+" : "",
79 | ud_reg_tab[op->index - UD_R_AL]);
80 | if (op->scale) {
81 | ud_asmprintf(u, "*%d", op->scale);
82 | }
83 | }
84 | if (op->offset != 0) {
85 | ud_syn_print_mem_disp(u, op, (op->base != UD_NONE ||
86 | op->index != UD_NONE) ? 1 : 0);
87 | }
88 | ud_asmprintf(u, "]");
89 | break;
90 |
91 | case UD_OP_IMM:
92 | ud_syn_print_imm(u, op);
93 | break;
94 |
95 |
96 | case UD_OP_JIMM:
97 | ud_syn_print_addr(u, ud_syn_rel_target(u, op));
98 | break;
99 |
100 | case UD_OP_PTR:
101 | switch (op->size) {
102 | case 32:
103 | ud_asmprintf(u, "word 0x%x:0x%x", op->lval.ptr.seg,
104 | op->lval.ptr.off & 0xFFFF);
105 | break;
106 | case 48:
107 | ud_asmprintf(u, "dword 0x%x:0x%x", op->lval.ptr.seg,
108 | op->lval.ptr.off);
109 | break;
110 | }
111 | break;
112 |
113 | case UD_OP_CONST:
114 | if (syn_cast) opr_cast_intel(u, op);
115 | ud_asmprintf(u, "%d", op->lval.udword);
116 | break;
117 |
118 | default: return;
119 | }
120 | }
121 |
122 | /* =============================================================================
123 | * translates to intel syntax
124 | * =============================================================================
125 | */
126 | extern void
127 | ud_translate_intel(struct ud* u)
128 | {
129 | /* check if P_OSO prefix is used */
130 | if (!P_OSO(u->itab_entry->prefix) && u->pfx_opr) {
131 | switch (u->dis_mode) {
132 | case 16: ud_asmprintf(u, "o32 "); break;
133 | case 32:
134 | case 64: ud_asmprintf(u, "o16 "); break;
135 | }
136 | }
137 |
138 | /* check if P_ASO prefix was used */
139 | if (!P_ASO(u->itab_entry->prefix) && u->pfx_adr) {
140 | switch (u->dis_mode) {
141 | case 16: ud_asmprintf(u, "a32 "); break;
142 | case 32: ud_asmprintf(u, "a16 "); break;
143 | case 64: ud_asmprintf(u, "a32 "); break;
144 | }
145 | }
146 |
147 | if (u->pfx_seg &&
148 | u->operand[0].type != UD_OP_MEM &&
149 | u->operand[1].type != UD_OP_MEM ) {
150 | ud_asmprintf(u, "%s ", ud_reg_tab[u->pfx_seg - UD_R_AL]);
151 | }
152 |
153 | if (u->pfx_lock) {
154 | ud_asmprintf(u, "lock ");
155 | }
156 | if (u->pfx_rep) {
157 | ud_asmprintf(u, "rep ");
158 | } else if (u->pfx_repe) {
159 | ud_asmprintf(u, "repe ");
160 | } else if (u->pfx_repne) {
161 | ud_asmprintf(u, "repne ");
162 | }
163 |
164 | /* print the instruction mnemonic */
165 | ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic));
166 |
167 | if (u->operand[0].type != UD_NONE) {
168 | int cast = 0;
169 | ud_asmprintf(u, " ");
170 | if (u->operand[0].type == UD_OP_MEM) {
171 | if (u->operand[1].type == UD_OP_IMM ||
172 | u->operand[1].type == UD_OP_CONST ||
173 | u->operand[1].type == UD_NONE ||
174 | (u->operand[0].size != u->operand[1].size)) {
175 | cast = 1;
176 | } else if (u->operand[1].type == UD_OP_REG &&
177 | u->operand[1].base == UD_R_CL) {
178 | switch (u->mnemonic) {
179 | case UD_Ircl:
180 | case UD_Irol:
181 | case UD_Iror:
182 | case UD_Ircr:
183 | case UD_Ishl:
184 | case UD_Ishr:
185 | case UD_Isar:
186 | cast = 1;
187 | break;
188 | default: break;
189 | }
190 | }
191 | }
192 | gen_operand(u, &u->operand[0], cast);
193 | }
194 |
195 | if (u->operand[1].type != UD_NONE) {
196 | int cast = 0;
197 | ud_asmprintf(u, ", ");
198 | if (u->operand[1].type == UD_OP_MEM &&
199 | u->operand[0].size != u->operand[1].size &&
200 | !ud_opr_is_sreg(&u->operand[0])) {
201 | cast = 1;
202 | }
203 | gen_operand(u, &u->operand[1], cast);
204 | }
205 |
206 | if (u->operand[2].type != UD_NONE) {
207 | int cast = 0;
208 | ud_asmprintf(u, ", ");
209 | if (u->operand[2].type == UD_OP_MEM &&
210 | u->operand[2].size != u->operand[1].size) {
211 | cast = 1;
212 | }
213 | gen_operand(u, &u->operand[2], cast);
214 | }
215 |
216 | if (u->operand[3].type != UD_NONE) {
217 | ud_asmprintf(u, ", ");
218 | gen_operand(u, &u->operand[3], 0);
219 | }
220 | }
221 |
222 | /*
223 | vim: set ts=2 sw=2 expandtab
224 | */
225 |
--------------------------------------------------------------------------------
/CacheSim/CacheSim.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017, Insomniac Games
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | Redistributions in binary form must reproduce the above copyright notice, this
12 | list of conditions and the following disclaimer in the documentation and/or
13 | other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #pragma once
28 |
29 | #include
30 | #include
31 | #if defined(_MSC_VER)
32 | #include
33 | #ifndef IG_CACHESIM_API
34 | #define IG_CACHESIM_API __declspec(dllimport)
35 | #endif
36 | #else
37 | #include
38 | #include
39 | #ifndef IG_CACHESIM_API
40 | #define IG_CACHESIM_API
41 | #endif
42 | #endif
43 |
44 |
45 | #if defined(_MSC_VER)
46 | #define CACHE_SIM_LIB_NAME "CacheSim.dll"
47 | #define IG_LoadLib(NAME) LoadLibraryA(NAME)
48 | #define IG_UnloadLib(HANDLE) FreeLibrary(HANDLE)
49 | #define IG_GetFuncAddress(HANDLE, NAME) GetProcAddress(HANDLE, NAME)
50 | #define IG_ThreadYield() Sleep(0)
51 | namespace CacheSim
52 | {
53 | inline int32_t AtomicCompareExchange(volatile int32_t* addr, int32_t new_val, int32_t old_val) { return _InterlockedCompareExchange((volatile LONG*)addr, new_val, old_val); }
54 | inline int32_t AtomicIncrement(volatile int32_t* addr) { return _InterlockedIncrement((volatile LONG*)addr); }
55 | inline void PrintError(const char* error) { MessageBoxA(NULL, error, "Error", MB_OK | MB_ICONERROR); }
56 | inline void SleepMilliseconds(int ms) { Sleep(ms); }
57 | }
58 | #else
59 | #define CACHE_SIM_LIB_NAME "libCacheSim.so"
60 | #define IG_LoadLib(NAME) dlopen(NAME, RTLD_NOW)
61 | #define IG_UnloadLib(HANDLE) dlclose(HANDLE)
62 | #define IG_GetFuncAddress(HANDLE, NAME) dlsym(HANDLE, NAME)
63 | #define IG_ThreadYield() sched_yield()
64 | namespace CacheSim
65 | {
66 | inline int32_t AtomicCompareExchange(volatile int32_t* addr, int32_t new_val, int32_t old_val) { return __sync_val_compare_and_swap(addr, old_val, new_val); }
67 | inline int32_t AtomicIncrement(volatile int32_t* addr) { return __sync_fetch_and_add(addr, 1); }
68 | inline void SleepMilliseconds(int ms) { usleep(ms * 1000); }
69 | inline void PrintError(const char* error) { fprintf(stderr, "%s\n", error); }
70 | }
71 | #endif
72 |
73 | /*! \file
74 | This DLL is loaded at runtime by the engine to perform cache simulation.
75 | As such there's no static binding to these functions, they're looked up with GetProcAddress().
76 | */
77 |
78 | extern "C"
79 | {
80 | /// Initializes the API. Only call once.
81 | IG_CACHESIM_API void CacheSimInit();
82 |
83 | /// Returns a thread ID suitable for use with CachesimSetThreadCoreMapping
84 | IG_CACHESIM_API uint64_t CacheSimGetCurrentThreadId();
85 |
86 | /// Set what Jaguar core (0-7) this Win32 thread ID will map to.
87 | /// Threads without a jaguar core id will not be recorded, so you'll need to set up atleast one.
88 | /// A core id of -1 will disable recording the thread (e.g., upon thread completion)
89 | IG_CACHESIM_API void CacheSimSetThreadCoreMapping(uint64_t thread_id, int logical_core_id);
90 |
91 | /// Start recording a capture, buffering it to memory.
92 | IG_CACHESIM_API bool CacheSimStartCapture();
93 |
94 | /// Stop recording and optionally save the capture to disk.
95 | IG_CACHESIM_API void CacheSimEndCapture(bool save);
96 |
97 | /// Remove the exception handler machinery.
98 | IG_CACHESIM_API void CacheSimRemoveHandler(void);
99 | }
100 |
101 | //--------------------------------------------------------------------------------------------------
102 | /// Shim helper to load the cache simulator dynamically.
103 |
104 | namespace CacheSim
105 | {
106 | class DynamicLoader
107 | {
108 | private:
109 | #if defined(_MSC_VER)
110 | HMODULE m_Module = nullptr;
111 | #else
112 | void* m_Module = nullptr;
113 | #endif
114 | decltype(&CacheSimInit) m_InitFn = nullptr;
115 | decltype(&CacheSimStartCapture) m_StartCaptureFn = nullptr;
116 | decltype(&CacheSimEndCapture) m_EndCaptureFn = nullptr;
117 | decltype(&CacheSimRemoveHandler) m_RemoveHandlerFn = nullptr;
118 | decltype(&CacheSimSetThreadCoreMapping) m_SetThreadCoreMapping = nullptr;
119 | decltype(&CacheSimGetCurrentThreadId) m_GetCurrentThreadId = nullptr;
120 |
121 | public:
122 | DynamicLoader()
123 | {}
124 |
125 | public:
126 | bool Init()
127 | {
128 | if (!m_Module)
129 | {
130 | m_Module = IG_LoadLib(CACHE_SIM_LIB_NAME);
131 | if (!m_Module)
132 | {
133 | char msg[512];
134 | #if defined(_MSC_VER)
135 | _snprintf_s(msg, sizeof msg, "Failed to load CacheSim.dll - Win32 error: %u\n", GetLastError());
136 | #else
137 | snprintf(msg, sizeof msg, "Failed to load libCacheSim.so - Linux error: %s\n", dlerror());
138 | #endif
139 | PrintError(msg);
140 | return false;
141 | }
142 |
143 | m_InitFn = (decltype(&CacheSimInit)) IG_GetFuncAddress(m_Module, "CacheSimInit");
144 | m_StartCaptureFn = (decltype(&CacheSimStartCapture)) IG_GetFuncAddress(m_Module, "CacheSimStartCapture");
145 | m_EndCaptureFn = (decltype(&CacheSimEndCapture)) IG_GetFuncAddress(m_Module, "CacheSimEndCapture");
146 | m_RemoveHandlerFn = (decltype(&CacheSimRemoveHandler)) IG_GetFuncAddress(m_Module, "CacheSimRemoveHandler");
147 | m_SetThreadCoreMapping = (decltype(&CacheSimSetThreadCoreMapping)) IG_GetFuncAddress(m_Module, "CacheSimSetThreadCoreMapping");
148 | m_GetCurrentThreadId = (decltype(&CacheSimGetCurrentThreadId)) IG_GetFuncAddress(m_Module, "CacheSimGetCurrentThreadId");
149 |
150 | if (!(m_InitFn && m_StartCaptureFn && m_EndCaptureFn && m_RemoveHandlerFn && m_SetThreadCoreMapping && m_GetCurrentThreadId))
151 | {
152 | PrintError("CacheSim API mismatch");
153 | IG_UnloadLib(m_Module);
154 | m_Module = nullptr;
155 | return false;
156 | }
157 |
158 | m_InitFn();
159 | }
160 |
161 | return true;
162 | }
163 |
164 |
165 | inline bool Start()
166 | {
167 | return m_StartCaptureFn();
168 | }
169 |
170 | inline void End()
171 | {
172 | m_EndCaptureFn(1);
173 | }
174 |
175 | inline void Cancel()
176 | {
177 | m_EndCaptureFn(0);
178 | }
179 |
180 | inline void RemoveHandler()
181 | {
182 | m_RemoveHandlerFn();
183 | }
184 |
185 | inline void SetThreadCoreMapping(uint64_t thread_id, int logical_core)
186 | {
187 | m_SetThreadCoreMapping(thread_id, logical_core);
188 | }
189 |
190 | inline uint64_t GetCurrentThreadId()
191 | {
192 | return m_GetCurrentThreadId();
193 | }
194 | };
195 | }
196 |
--------------------------------------------------------------------------------
/UI/AnnotationView.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017, Insomniac Games
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | Redistributions in binary form must reproduce the above copyright notice, this
12 | list of conditions and the following disclaimer in the documentation and/or
13 | other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #include "Precompiled.h"
28 | #include "AnnotationView.h"
29 |
30 | static constexpr int kContextLines = 5;
31 | static constexpr int kLineSpacing = 2;
32 | static constexpr double kBadnessClamp = 50.0;
33 |
34 | CacheSim::AnnotationView::AnnotationView(TraceData::FileInfo fileInfo, QWidget* parent /*= nullptr*/)
35 | : QWidget(parent)
36 | , m_FileInfo(fileInfo)
37 | {
38 | QFont font(QStringLiteral("Consolas"), 9);
39 | setFont(font);
40 | QFontMetrics metrics(font);
41 |
42 | m_Locale.setNumberOptions(QLocale::DefaultNumberOptions);
43 |
44 | int maxWidth = 0;
45 |
46 | QFile f(m_FileInfo.m_FileName);
47 | if (f.open(QIODevice::ReadOnly))
48 | {
49 | QTextStream s(&f);
50 |
51 | int lineNo = 0;
52 | while (++lineNo < m_FileInfo.m_FirstLine - kContextLines)
53 | {
54 | s.readLine();
55 | }
56 |
57 | while (lineNo < m_FileInfo.m_LastLine + kContextLines && !s.atEnd())
58 | {
59 | LineInfo lineInfo;
60 | lineInfo.m_Text = s.readLine();
61 |
62 | auto it = std::lower_bound(fileInfo.m_Samples.constBegin(), fileInfo.m_Samples.constEnd(), lineNo, [](const TraceData::LineData& data, int line)
63 | {
64 | return data.m_LineNumber < line;
65 | });
66 |
67 | if (it != fileInfo.m_Samples.constEnd() && it->m_LineNumber == lineNo)
68 | {
69 | lineInfo.m_SampleIndex = std::distance(fileInfo.m_Samples.constBegin(), it);
70 | }
71 |
72 | m_Lines.push_back(lineInfo);
73 | maxWidth = std::max(maxWidth, metrics.boundingRect(lineInfo.m_Text).width());
74 | ++lineNo;
75 | }
76 | }
77 |
78 | m_GutterWidth = metrics.boundingRect(QStringLiteral("99999999")).width();
79 | maxWidth += m_GutterWidth;
80 |
81 | this->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
82 | this->setMinimumSize(maxWidth, (fontMetrics().height() + kLineSpacing) * m_Lines.count());
83 | }
84 |
85 | CacheSim::AnnotationView::~AnnotationView()
86 | {
87 |
88 | }
89 |
90 | static QColor lerpColors(const QColor& a, const QColor& b, double t)
91 | {
92 | double ar = a.redF();
93 | double ag = a.greenF();
94 | double ab = a.blueF();
95 | double br = b.redF();
96 | double bg = b.greenF();
97 | double bb = b.blueF();
98 |
99 | return QColor::fromRgbF(ar + (br - ar) * t, ag + (bg - ag) * t, ab + (bb - ab) * t);
100 | }
101 |
102 | void CacheSim::AnnotationView::paintEvent(QPaintEvent *event)
103 | {
104 | (void) event;
105 |
106 | QPainter p(this);
107 |
108 | p.setFont(font());
109 |
110 | int fh = fontMetrics().height();
111 | int lh = fh + kLineSpacing;
112 |
113 | QRect br = event->rect();
114 |
115 | int firstLine = std::max(br.y() / lh, 0);
116 | int lastLine = std::min(firstLine + (br.height() + lh - 1) / lh, m_Lines.count() - 1);
117 |
118 | int line_y = firstLine * lh;
119 | int text_y = fontMetrics().ascent() + line_y;
120 |
121 | QColor ok = palette().background().color();
122 | QColor noData = ok.darker(110);
123 | QColor bad = QColor("#ff8080");
124 |
125 | QBrush backgroundBrush(ok);
126 |
127 | for (int i = firstLine; i <= lastLine; ++i)
128 | {
129 | LineInfo lineInfo = m_Lines.value(i);
130 |
131 | if (lineInfo.m_SampleIndex >= 0)
132 | {
133 | double badness = std::min(BadnessValue(m_FileInfo.m_Samples[lineInfo.m_SampleIndex].m_Stats), kBadnessClamp);
134 | double ratio = badness / kBadnessClamp;
135 | backgroundBrush.setColor(lerpColors(ok, bad, ratio));
136 | }
137 | else
138 | {
139 | backgroundBrush.setColor(noData);
140 | }
141 |
142 | p.setBackground(backgroundBrush);
143 | p.fillRect(0, line_y, br.width(), lh, backgroundBrush);
144 | p.drawText(0, text_y, QString::number(i + m_FileInfo.m_FirstLine - kContextLines));
145 | p.drawText(m_GutterWidth, text_y, m_Lines.value(i).m_Text);
146 |
147 | text_y += lh;
148 | line_y += lh;
149 | }
150 | }
151 |
152 | int CacheSim::AnnotationView::lineAtPosition(const QPoint& point)
153 | {
154 | int fh = fontMetrics().height();
155 | int lh = fh + kLineSpacing;
156 | int line = point.y() / lh;
157 | return line;
158 | }
159 |
160 | bool CacheSim::AnnotationView::event(QEvent* ev)
161 | {
162 | if (ev->type() == QEvent::ToolTip)
163 | {
164 | QHelpEvent *helpEvent = static_cast(ev);
165 | int line = lineAtPosition(helpEvent->pos());
166 | if (line >= 0 && line < m_Lines.size())
167 | {
168 | if (m_Lines[line].m_SampleIndex == -1)
169 | {
170 | QToolTip::showText(helpEvent->globalPos(), QStringLiteral("(no data)"));
171 | }
172 | else
173 | {
174 | const TraceData::LineData& lineData = m_FileInfo.m_Samples[m_Lines[line].m_SampleIndex];
175 | QString text = QStringLiteral(
176 | ""
177 | "| Line Number | %1 |
"
178 | "| I1 Hits | %2 |
"
179 | "| D1 Hits | %3 |
"
180 | "| L2 Data Misses | %4 |
"
181 | "| L2 Instruction Misses | %5 |
"
182 | "| Badness | %6 |
"
183 | "| Instructions Executed | %7 |
"
184 | "| Prefetch Hit D1 | %8 |
"
185 | "| Prefetch Hit L2 | %9 |
"
186 | "
")
187 | .arg(lineData.m_LineNumber)
188 | .arg(m_Locale.toString(lineData.m_Stats[kI1Hit]))
189 | .arg(m_Locale.toString(lineData.m_Stats[kD1Hit]))
190 | .arg(m_Locale.toString(lineData.m_Stats[kL2DMiss]))
191 | .arg(m_Locale.toString(lineData.m_Stats[kL2IMiss]))
192 | .arg(m_Locale.toString(BadnessValue(lineData.m_Stats), 'f', 2))
193 | .arg(m_Locale.toString(lineData.m_Stats[kInstructionsExecuted]))
194 | .arg(m_Locale.toString(lineData.m_Stats[kPrefetchHitD1]))
195 | .arg(m_Locale.toString(lineData.m_Stats[kPrefetchHitL2]))
196 | ;
197 | QToolTip::showText(helpEvent->globalPos(), text);
198 | return true;
199 | }
200 | }
201 | else
202 | {
203 | QToolTip::hideText();
204 | ev->ignore();
205 | return true;
206 | }
207 | }
208 |
209 | return Base::event(ev);
210 | }
211 |
--------------------------------------------------------------------------------
/UI/TraceTab.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017, Insomniac Games
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | Redistributions in binary form must reproduce the above copyright notice, this
12 | list of conditions and the following disclaimer in the documentation and/or
13 | other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #include "Precompiled.h"
28 | #include "TraceTab.h"
29 | #include "TraceData.h"
30 | #include "FlatProfileView.h"
31 | #include "TreeProfileView.h"
32 | #include "TreeModel.h"
33 | #include "AnnotationView.h"
34 |
35 | #include "ui_TraceTab.h"
36 |
37 | CacheSim::TraceTab::TraceTab(QString fileName, QWidget* parent /*= nullptr*/)
38 | : QWidget(parent)
39 | , m_Data(new TraceData(this))
40 | , m_PendingJobs(0)
41 | , m_JobCounter(0)
42 | , ui(new Ui_TraceTab)
43 | {
44 | ui->setupUi(this);
45 |
46 | connect(this, &TraceTab::treeModelReady, this, &TraceTab::createViewFromTreeModel, Qt::QueuedConnection);
47 |
48 | connect(m_Data, &TraceData::traceLoadSucceeded, this, &TraceTab::traceLoadSucceeded);
49 | connect(m_Data, &TraceData::traceLoadFailed, this, &TraceTab::traceLoadFailed);
50 | connect(m_Data, &TraceData::symbolResolutionProgressed, this, &TraceTab::symbolResolutionProgressed);
51 | connect(m_Data, &TraceData::symbolResolutionCompleted, this, &TraceTab::symbolResolutionCompleted);
52 | connect(m_Data, &TraceData::symbolResolutionFailed, this, &TraceTab::symbolResolutionFailed);
53 | connect(ui->m_ResolveSymbolsButton, &QPushButton::clicked, this, &TraceTab::resolveSymbolsClicked);
54 |
55 | this->setEnabled(false);
56 | m_Data->beginLoadTrace(fileName);
57 |
58 | connect(ui->m_TabWidget, &QTabWidget::tabCloseRequested, this, &TraceTab::tabCloseRequested);
59 |
60 | connect(ui->m_FlatProfileButton, &QPushButton::clicked, this, &TraceTab::openFlatProfile);
61 | connect(ui->m_TreeProfileButton, &QPushButton::clicked, this, &TraceTab::openTreeProfile);
62 |
63 | m_CloseTabAction = new QAction(QStringLiteral("Close tab"), this);
64 | this->addAction(m_CloseTabAction);
65 | ui->m_TabWidget->addAction(m_CloseTabAction);
66 | m_CloseTabAction->setShortcut(Qt::Key_W | Qt::CTRL);
67 | m_CloseTabAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
68 | connect(m_CloseTabAction, &QAction::triggered, this, &TraceTab::closeCurrentTab);
69 | }
70 |
71 | CacheSim::TraceTab::~TraceTab()
72 | {
73 | delete ui;
74 | }
75 |
76 | void CacheSim::TraceTab::openFlatProfile()
77 | {
78 | if (-1 == m_FlatProfileTabIndex)
79 | {
80 | m_FlatProfileTabIndex = addProfileView(new FlatProfileView(m_Data), QStringLiteral("Flat Profile"));
81 | }
82 |
83 | ui->m_TabWidget->setCurrentIndex(m_FlatProfileTabIndex);
84 | }
85 |
86 | void CacheSim::TraceTab::openTreeProfile()
87 | {
88 | if (-1 != m_TreeProfileTabIndex)
89 | {
90 | ui->m_TabWidget->setCurrentIndex(m_TreeProfileTabIndex);
91 | return;
92 | }
93 |
94 | ui->m_TreeProfileButton->setEnabled(false);
95 |
96 | doCreateTreeView(QString::null, QStringLiteral("Top-down tree"));
97 | }
98 |
99 | void CacheSim::TraceTab::createViewFromTreeModel(TreeModel* model, QString title, bool isMainTree)
100 | {
101 | TreeProfileView* v = new TreeProfileView(model);
102 | model->setParent(v);
103 |
104 | int index = addProfileView(v, title);
105 |
106 | if (isMainTree)
107 | {
108 | m_TreeProfileTabIndex = index;
109 | ui->m_TreeProfileButton->setEnabled(true);
110 | }
111 | }
112 |
113 | void CacheSim::TraceTab::openReverseViewForSymbol(QString symbol)
114 | {
115 | doCreateTreeView(symbol, QStringLiteral("Reverse: %1").arg(symbol));
116 | }
117 |
118 | void CacheSim::TraceTab::openAnnotationForSymbol(QString symbol)
119 | {
120 | TraceData::FileInfo fileInfo = m_Data->findFileData(symbol);
121 | if (!fileInfo.m_FileName.isEmpty() && QFileInfo::exists(fileInfo.m_FileName))
122 | {
123 | QScrollArea* scrollArea = new QScrollArea(this);
124 | AnnotationView* v = new AnnotationView(fileInfo, scrollArea);
125 | scrollArea->setWidget(v);
126 | v->addAction(m_CloseTabAction);
127 | int index = ui->m_TabWidget->addTab(scrollArea, QStringLiteral("Source: %1").arg(symbol));
128 | ui->m_TabWidget->setCurrentIndex(index);
129 | }
130 | }
131 |
132 | void CacheSim::TraceTab::traceLoadSucceeded()
133 | {
134 | this->setEnabled(true);
135 | updateSymbolStatus();
136 | }
137 |
138 | void CacheSim::TraceTab::traceLoadFailed(QString reason)
139 | {
140 |
141 | }
142 |
143 | void CacheSim::TraceTab::resolveSymbolsClicked()
144 | {
145 | ui->m_ResolveSymbolsButton->setEnabled(false);
146 | m_Data->beginResolveSymbols();
147 | }
148 |
149 | void CacheSim::TraceTab::symbolResolutionCompleted()
150 | {
151 | ui->m_ResolveSymbolsButton->setEnabled(true);
152 | updateSymbolStatus();
153 | }
154 |
155 | void CacheSim::TraceTab::symbolResolutionProgressed(int completed, int total)
156 | {
157 | QLocale loc = QLocale::system();
158 | ui->m_SymbolStatus->setText(QStringLiteral("Resolving: %1% done (%2/%3)").arg(loc.toString(100.0*completed/total, 'f', 2)).arg(loc.toString(completed)).arg(loc.toString(total)));
159 | }
160 |
161 | void CacheSim::TraceTab::symbolResolutionFailed(QString reason)
162 | {
163 | QMessageBox::warning(this, QStringLiteral("Symbol resolution failed"), reason);
164 | ui->m_ResolveSymbolsButton->setEnabled(true);
165 | updateSymbolStatus();
166 | }
167 |
168 | void CacheSim::TraceTab::tabCloseRequested(int index)
169 | {
170 | if (0 == index)
171 | {
172 | Q_EMIT closeTrace();
173 | }
174 | else
175 | {
176 | QWidget* w = ui->m_TabWidget->widget(index);
177 | ui->m_TabWidget->removeTab(index);
178 | delete w;
179 | }
180 |
181 | if (index == m_FlatProfileTabIndex)
182 | {
183 | m_FlatProfileTabIndex = -1;
184 | }
185 | else if (index == m_TreeProfileTabIndex)
186 | {
187 | m_TreeProfileTabIndex = -1;
188 | }
189 | }
190 |
191 | void CacheSim::TraceTab::closeCurrentTab()
192 | {
193 | int index = ui->m_TabWidget->currentIndex();
194 | tabCloseRequested(index);
195 | }
196 |
197 | void CacheSim::TraceTab::updateSymbolStatus()
198 | {
199 | ui->m_SymbolStatus->setText(m_Data->isResolved() ? QStringLiteral("Resolved") : QStringLiteral("Unresolved"));
200 | }
201 |
202 | void CacheSim::TraceTab::doCreateTreeView(QString rootSymbolOpt, QString title)
203 | {
204 | const int id = m_JobCounter++;
205 | Q_EMIT beginLongTask(id, QStringLiteral("Computing tree profile"));
206 |
207 | ++m_PendingJobs;
208 |
209 | QtConcurrent::run([self = this, data = m_Data, tr = QThread::currentThread(), id = id, title = title, sym=rootSymbolOpt]()
210 | {
211 | TreeModel* model = new TreeModel(nullptr);
212 | model->setTraceData(data, sym);
213 | model->moveToThread(tr);
214 | Q_EMIT self->treeModelReady(model, title, /* isMain=*/sym.isEmpty());
215 | Q_EMIT self->endLongTask(id);
216 | --self->m_PendingJobs;
217 | });
218 | }
219 |
220 | int CacheSim::TraceTab::addProfileView(BaseProfileView* view, QString label)
221 | {
222 | int index = ui->m_TabWidget->addTab(view, label);
223 |
224 | connect(view, &BaseProfileView::showReverse, this, &TraceTab::openReverseViewForSymbol);
225 | connect(view, &BaseProfileView::annotateSymbol, this, &TraceTab::openAnnotationForSymbol);
226 | view->addAction(m_CloseTabAction);
227 | ui->m_TabWidget->setCurrentIndex(index);
228 |
229 | return index;
230 | }
231 |
232 | #include "aux_TraceTab.moc"
233 |
234 |
--------------------------------------------------------------------------------
/UI/TreeModel.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017, Insomniac Games
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | Redistributions in binary form must reproduce the above copyright notice, this
12 | list of conditions and the following disclaimer in the documentation and/or
13 | other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #include "Precompiled.h"
28 | #include "TreeModel.h"
29 | #include "TraceData.h"
30 | #include "ObjectStack.h"
31 |
32 | #include "CacheSim/CacheSimInternals.h"
33 | #include "CacheSim/CacheSimData.h"
34 |
35 | static const QString kColumnLabels[CacheSim::TreeModel::kColumnCount] =
36 | {
37 | QStringLiteral("Symbol"),
38 | QStringLiteral("File"),
39 | QStringLiteral("D1Hit"),
40 | QStringLiteral("I1Hit"),
41 | QStringLiteral("L2IMiss"),
42 | QStringLiteral("L2DMiss"),
43 | QStringLiteral("Badness"),
44 | QStringLiteral("Instructions"),
45 | QStringLiteral("PF-D1"),
46 | QStringLiteral("PF-L2"),
47 | };
48 |
49 | class CacheSim::TreeModel::Node
50 | {
51 | public:
52 | Node* m_Parent;
53 | QString m_SymbolName;
54 | QString m_FileName;
55 | uint32_t m_Stats[CacheSim::kAccessResultCount];
56 | QVector m_Children;
57 |
58 | explicit Node(Node* parent) : m_Parent(parent), m_Stats { 0 }
59 | {}
60 |
61 | ~Node()
62 | {
63 | }
64 |
65 | Node* child(QString name, bool* isNew, ObjectStack* stack)
66 | {
67 | Q_FOREACH(Node* n, m_Children)
68 | {
69 | if (n->m_SymbolName == name)
70 | {
71 | *isNew = false;
72 | return n;
73 | }
74 | }
75 |
76 | *isNew = true;
77 | Node* node = stack->alloc(this);
78 | node->m_SymbolName = name;
79 | m_Children.push_back(node);
80 | return node;
81 | }
82 |
83 | int rowInParentSpace() const
84 | {
85 | if (m_Parent)
86 | {
87 | return m_Parent->m_Children.indexOf(const_cast(this));
88 | }
89 | return 0;
90 | }
91 |
92 | };
93 |
94 | CacheSim::TreeModel::TreeModel(QObject* parent /*= nullptr*/)
95 | : QAbstractItemModel(parent)
96 | , m_Allocator(new ObjectStack)
97 | {
98 | }
99 |
100 | CacheSim::TreeModel::~TreeModel()
101 | {
102 | m_RootNode = nullptr;
103 | delete m_Allocator;
104 | }
105 |
106 | QModelIndex CacheSim::TreeModel::index(int row, int column, const QModelIndex &parent /*= QModelIndex()*/) const
107 | {
108 | Node* node = m_RootNode;
109 |
110 | if (parent.isValid())
111 | {
112 | node = static_cast(parent.internalPointer());
113 | }
114 |
115 | if (row < 0 || row >= node->m_Children.size())
116 | return QModelIndex();
117 |
118 | return createIndex(row, column, node->m_Children[row]);
119 | }
120 |
121 | QModelIndex CacheSim::TreeModel::parent(const QModelIndex &child) const
122 | {
123 | if (!child.isValid())
124 | return QModelIndex();
125 |
126 | Node* p = static_cast(child.internalPointer());
127 | Node* parent = p->m_Parent;
128 | if (!parent || parent == m_RootNode)
129 | return QModelIndex();
130 |
131 | return createIndex(parent->rowInParentSpace(), kColumnSymbol, parent);
132 | }
133 |
134 | int CacheSim::TreeModel::rowCount(const QModelIndex &parent /*= QModelIndex()*/) const
135 | {
136 | Node* p = parent.isValid() ? static_cast(parent.internalPointer()) : m_RootNode;
137 |
138 | if (!parent.isValid() || parent.column() == kColumnSymbol)
139 | return p->m_Children.count();
140 |
141 | return 0;
142 | }
143 |
144 | int CacheSim::TreeModel::columnCount(const QModelIndex &parent /*= QModelIndex()*/) const
145 | {
146 | (void) parent;
147 | return kColumnCount;
148 | }
149 |
150 | QVariant CacheSim::TreeModel::data(const QModelIndex &index, int role /*= Qt::DisplayRole*/) const
151 | {
152 | Node* node = static_cast(index.internalPointer());
153 | if (!node)
154 | return QVariant();
155 |
156 | if (role == Qt::DisplayRole)
157 | {
158 | switch (index.column())
159 | {
160 | case kColumnSymbol: return node->m_SymbolName;
161 | case kColumnFileName: return node->m_FileName;
162 | case kColumnD1Hit: return node->m_Stats[CacheSim::kD1Hit];
163 | case kColumnI1Hit: return node->m_Stats[CacheSim::kI1Hit];
164 | case kColumnL2IMiss: return node->m_Stats[CacheSim::kL2IMiss];
165 | case kColumnL2DMiss: return node->m_Stats[CacheSim::kL2DMiss];
166 | case kColumnBadness: return BadnessValue(node->m_Stats);
167 | case kColumnInstructionsExecuted: return node->m_Stats[CacheSim::kInstructionsExecuted];
168 | case kColumnPFD1: return node->m_Stats[CacheSim::kPrefetchHitD1];
169 | case kColumnPFL2: return node->m_Stats[CacheSim::kPrefetchHitL2];
170 | }
171 | }
172 | else if (role == Qt::TextAlignmentRole)
173 | {
174 | if (index.column() > kColumnFileName)
175 | {
176 | return Qt::AlignRight;
177 | }
178 | return Qt::AlignLeft;
179 | }
180 | else if (role == Qt::ToolTipRole)
181 | {
182 | if (index.column() == kColumnSymbol)
183 | {
184 | return node->m_SymbolName;
185 | }
186 | else if (index.column() == kColumnFileName)
187 | {
188 | return node->m_FileName;
189 | }
190 | }
191 |
192 | return QVariant();
193 |
194 | }
195 |
196 | QVariant CacheSim::TreeModel::headerData(int section, Qt::Orientation orientation, int role /*= Qt::DisplayRole*/) const
197 | {
198 | if (role == Qt::DisplayRole && orientation == Qt::Horizontal && section >= 0 && section < kColumnCount)
199 | {
200 | return kColumnLabels[section];
201 | }
202 |
203 | return QVariant();
204 | }
205 |
206 | void CacheSim::TreeModel::setTraceData(const TraceData* traceData, QString rootSymbol)
207 | {
208 | beginResetModel();
209 |
210 | m_Allocator->reset();
211 | m_RootNode = nullptr;
212 |
213 | m_RootNode = createTree(traceData, rootSymbol);
214 |
215 | endResetModel();
216 | }
217 |
218 | CacheSim::TreeModel::Node* CacheSim::TreeModel::createTree(const TraceData* traceData, QString rootSymbol)
219 | {
220 | const SerializedNode* nodes = traceData->header()->GetStats();
221 | const uint32_t nodeCount = traceData->header()->GetStatCount();
222 |
223 | const uintptr_t* stackFrames = traceData->header()->GetStacks();
224 |
225 | QVector frames;
226 |
227 | Node* root = m_Allocator->alloc(nullptr);
228 |
229 | for (uint32_t i = 0; i < nodeCount; ++i)
230 | {
231 | frames.clear();
232 |
233 | const SerializedNode& node = nodes[i];
234 |
235 | // If we're trying to limit the tree to a particular root symbol, do that.
236 | if (!rootSymbol.isEmpty())
237 | {
238 | if (rootSymbol != traceData->symbolNameForAddress(node.m_Rip))
239 | {
240 | continue;
241 | }
242 | }
243 |
244 | frames.push_back(node.m_Rip);
245 |
246 | const uintptr_t* fp = stackFrames + node.m_StackIndex;
247 | while (uintptr_t rip = *fp++)
248 | {
249 | frames.push_back(rip);
250 | }
251 |
252 | if (rootSymbol.isEmpty()) // top down, unless we're looking at a specific symbol in which case we'll reverse the tree
253 | {
254 | std::reverse(frames.begin(), frames.end());
255 | }
256 |
257 | Node* branch = root;
258 |
259 | Q_FOREACH(uintptr_t rip, frames)
260 | {
261 | QString symbolName;
262 |
263 | const SerializedSymbol* sym = traceData->header()->FindSymbol(rip);
264 |
265 | if (sym)
266 | {
267 | symbolName = traceData->internedSymbolString(sym->m_SymbolName);
268 | }
269 | else
270 | {
271 | symbolName = QStringLiteral("[%1]").arg(rip, 16, 16, QLatin1Char('0'));
272 | }
273 |
274 | bool isNew;
275 | branch = branch->child(symbolName, &isNew, m_Allocator);
276 |
277 | if (isNew && sym)
278 | {
279 | branch->m_FileName = traceData->internedSymbolString(sym->m_FileName);
280 | }
281 |
282 | for (int k = 0; k < CacheSim::kAccessResultCount; ++k)
283 | {
284 | branch->m_Stats[k] += node.m_Stats[k];
285 | }
286 | }
287 | }
288 |
289 | return root;
290 | }
291 |
292 | #include "aux_TreeModel.moc"
293 |
--------------------------------------------------------------------------------
/UI/SymbolResolverLinux.cpp:
--------------------------------------------------------------------------------
1 | #include "Precompiled.h"
2 | #include "SymbolResolver.h"
3 | #include "CacheSim/CacheSimData.h"
4 | #include
5 | #include
6 |
7 | static bool ResolveSymbolViaObjdump(char** symbolNameOut, size_t* bufferSizeOut, const char* module, uintptr_t address)
8 | {
9 | std::stringstream command;
10 |
11 | command << "objdump " << module << " ";
12 | command << std::showbase << std::hex;
13 | command << "-C -d --start-address=" << address;
14 | command << " --stop-address=" << (address + 1);
15 |
16 | FILE* fd = popen(command.str().c_str(), "r");
17 | if ( fd == nullptr )
18 | {
19 | qDebug() << "Cannot find function info with addr2line or objdump either.";
20 | pclose(fd);
21 | return false;
22 | }
23 |
24 | char* buffer = nullptr;
25 | size_t length;
26 | while (getline(&buffer, &length, fd) != -1)
27 | {
28 | char* symbolStart = strchr(buffer, '<');
29 | if ( symbolStart == nullptr )
30 | {
31 | continue;
32 | }
33 | symbolStart++; // Start /after/ the '<'
34 | char* symbolEnd = strrchr(symbolStart, '>');
35 | if ( symbolEnd == nullptr || symbolEnd < symbolStart )
36 | {
37 | continue;
38 | }
39 |
40 | *symbolEnd = '\0';
41 | symbolEnd = strpbrk(symbolStart, "+-");
42 | if ( symbolEnd )
43 | {
44 | *symbolEnd = '\0';
45 | }
46 |
47 | size_t symbolLength = strlen(symbolStart) + 1;
48 | if ( symbolLength > *bufferSizeOut )
49 | {
50 | *symbolNameOut = (char*)realloc(*symbolNameOut, symbolLength);
51 | *bufferSizeOut = symbolLength;
52 | }
53 |
54 | strcpy(*symbolNameOut, symbolStart);
55 | pclose(fd);
56 | free(buffer);
57 | return true;
58 | }
59 | pclose(fd);
60 | free(buffer);
61 | return false;
62 | }
63 |
64 | #define DebugBreak() asm volatile("int $3")
65 | bool CacheSim::ResolveSymbols(const UnresolvedAddressData& input, QVector* resolvedSymbolsOut, SymbolResolveProgressCallbackType reportProgress)
66 | {
67 | struct ModuleFrames
68 | {
69 | const SerializedModuleEntry* m_Entry;
70 | QVector m_Frames;
71 | };
72 |
73 | QVector moduleFrameList;
74 | for ( int i = 0; i < input.m_ModuleCount; i++ )
75 | {
76 | ModuleFrames frames;
77 | frames.m_Entry = &input.m_Modules[i];
78 | moduleFrameList.push_back(frames);
79 | }
80 |
81 | std::sort(moduleFrameList.begin(), moduleFrameList.end(), [](const ModuleFrames& l, const ModuleFrames& r) -> bool
82 | {
83 | return l.m_Entry->m_ImageBase < r.m_Entry->m_ImageBase;
84 | });
85 |
86 |
87 | int resolve_count = 0;
88 | int fail_count = 0;
89 |
90 | QSet ripLookup;
91 | const auto& addRipToModuleFrames = [&](uintptr_t rip) -> void
92 | {
93 | if ( ripLookup.contains(rip) )
94 | {
95 | return;
96 | }
97 | ripLookup.insert(rip);
98 |
99 | for ( int i = 0; i < input.m_ModuleCount; i++ )
100 | {
101 | ModuleFrames& module = moduleFrameList[i];
102 | if ( rip >= module.m_Entry->m_ImageBase + module.m_Entry->m_ImageSegmentOffset)
103 | {
104 | if ( rip < (module.m_Entry->m_ImageBase + module.m_Entry->m_ImageSegmentOffset + module.m_Entry->m_SizeBytes) )
105 | {
106 | module.m_Frames.push_back(rip);
107 | break;
108 | }
109 | else
110 | continue;
111 | }
112 | else
113 | {
114 | qDebug() << "Failed to find module for address " << rip;
115 | fail_count++;
116 | }
117 | }
118 | };
119 |
120 |
121 | int total = 2 * (input.m_StackCount + input.m_NodeCount); // Two passes, once to sort the data and once to process it
122 | int completed = 0;
123 |
124 | // Sort instructions in stacks
125 | for (uint32_t i = 0; i < input.m_StackCount; ++i, ++completed)
126 | {
127 | if (uintptr_t rip = input.m_Stacks[i])
128 | {
129 | addRipToModuleFrames(rip);
130 | }
131 |
132 | if (0 == (completed & 0x400))
133 | {
134 | reportProgress(completed, total);
135 | }
136 | }
137 |
138 | // Sort any instructions used in leaf functions.
139 | for (uint32_t i = 0; i < input.m_NodeCount; ++i, ++completed)
140 | {
141 | addRipToModuleFrames(input.m_Nodes[i].m_Rip);
142 |
143 | if (0 == (completed & 0x400))
144 | {
145 | reportProgress(completed, total);
146 | }
147 | }
148 |
149 | reportProgress(completed, total);
150 |
151 | for ( int i = 0; i < moduleFrameList.count(); i++ )
152 | {
153 | if ( moduleFrameList[i].m_Frames.count() == 0 )
154 | {
155 | continue;
156 | }
157 |
158 | ptrdiff_t moduleIndex = moduleFrameList[i].m_Entry - input.m_Modules;
159 |
160 | // Figure out the actual file with the debug info. If there's anything in /usr/lib/debug, use that version instead
161 | // resolve any symlinks
162 | char resolvedBaseFilename[1024];
163 | if ( realpath(input.m_ModuleNames[moduleIndex].toLatin1().data(), resolvedBaseFilename) == nullptr )
164 | {
165 | strcpy(resolvedBaseFilename, input.m_ModuleNames[moduleIndex].toLatin1().data());
166 | }
167 |
168 | const char* debugLibBase = "/usr/lib/debug";
169 | std::stringstream symbolFilename;
170 | symbolFilename << debugLibBase;
171 | symbolFilename << resolvedBaseFilename;
172 | if ( access(symbolFilename.str().c_str(), R_OK) == -1 )
173 | {
174 | // Didn't find a special symbol library, so use the code library
175 | symbolFilename.str(input.m_ModuleNames[moduleIndex].toLatin1().data());
176 | }
177 |
178 | int frameIndex = 0;
179 | do
180 | {
181 | std::stringstream command;
182 | command << "addr2line -C -f -e " << symbolFilename.str() << " ";
183 | command << std::showbase << std::hex;
184 |
185 | uintptr_t imageBase = moduleFrameList[i].m_Entry->m_ImageBase;
186 | const int numFramesPerStep = 1000; // popen has an undocumented maximum string length. This ensures we don't exceed it
187 | const int maxFrameIndex = std::min(frameIndex + numFramesPerStep, moduleFrameList[i].m_Frames.count());
188 |
189 | for ( int j = frameIndex; j < maxFrameIndex; j++ )
190 | {
191 | command << (moduleFrameList[i].m_Frames[j] - imageBase) << " ";
192 | }
193 | FILE* fd = popen(command.str().c_str(), "r");
194 |
195 | if ( fd == nullptr )
196 | {
197 | qDebug() << "Cannot resolve symbols. addr2line not found.";
198 | pclose(fd);
199 | return false;
200 | }
201 |
202 | char* symbolBuffer = nullptr;
203 | size_t symbolBufferSize;
204 | while ( getline(&symbolBuffer, &symbolBufferSize, fd) != -1 )
205 | {
206 | if ( strcmp(symbolBuffer, "??\n") == 0 )
207 | {
208 | // Attempt to use objdump to get the data
209 | if ( !ResolveSymbolViaObjdump(&symbolBuffer, &symbolBufferSize, input.m_ModuleNames[moduleIndex].toLatin1().data(), moduleFrameList[i].m_Frames[frameIndex] - moduleFrameList[i].m_Entry->m_ImageBase))
210 | {
211 | int needed = snprintf(symbolBuffer, symbolBufferSize, "[0x%016lx in %s]", moduleFrameList[i].m_Frames[frameIndex], symbolFilename.str().c_str());
212 | if ( needed >= symbolBufferSize )
213 | {
214 | symbolBufferSize = needed + 1;
215 | symbolBuffer = (char*)realloc(symbolBuffer, symbolBufferSize);
216 | snprintf(symbolBuffer, symbolBufferSize, "[%016lx in %s]", moduleFrameList[i].m_Frames[frameIndex], symbolFilename.str().c_str());
217 | }
218 | }
219 | }
220 |
221 | char* lineBuffer = nullptr;
222 | size_t length;
223 | getline(&lineBuffer, &length, fd);
224 |
225 | char* filename = nullptr;
226 | int lineNumber;
227 | int elementsFilled = sscanf(lineBuffer, "%m[^:]:%d %*s", &filename, &lineNumber);
228 | free(lineBuffer);
229 | if ( elementsFilled == 0 )
230 | {
231 | qDebug() << "Unexpected response from addr2line. Aborting.";
232 | pclose(fd);
233 | return false;
234 | }
235 | else if ( elementsFilled == 1 )
236 | {
237 | lineNumber = -1;
238 | }
239 |
240 | ResolvedSymbol out_sym;
241 | out_sym.m_Rip = moduleFrameList[i].m_Frames[frameIndex];
242 | out_sym.m_SymbolName = symbolBuffer;
243 | out_sym.m_FileName = filename;
244 | out_sym.m_LineNumber = lineNumber;
245 | out_sym.m_ModuleIndex = i;
246 | out_sym.m_Displacement = -1;
247 | resolvedSymbolsOut->push_back(out_sym);
248 | ++frameIndex;
249 | ++resolve_count;
250 | ++completed;
251 | free(filename);
252 | if (0 == (completed & 0x400))
253 | {
254 | reportProgress(completed, total);
255 | }
256 | }
257 | free(symbolBuffer);
258 | pclose(fd);
259 | } while ( frameIndex < moduleFrameList[i].m_Frames.count() );
260 | }
261 |
262 | return true;
263 | }
264 |
--------------------------------------------------------------------------------
/udis86/types.h:
--------------------------------------------------------------------------------
1 | /* udis86 - libudis86/types.h
2 | *
3 | * Copyright (c) 2002-2013 Vivek Thampi
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without modification,
7 | * are permitted provided that the following conditions are met:
8 | *
9 | * * Redistributions of source code must retain the above copyright notice,
10 | * this list of conditions and the following disclaimer.
11 | * * Redistributions in binary form must reproduce the above copyright notice,
12 | * this list of conditions and the following disclaimer in the documentation
13 | * and/or other materials provided with the distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 | #ifndef UD_TYPES_H
27 | #define UD_TYPES_H
28 |
29 | #include
30 |
31 | #ifdef __KERNEL__
32 | /*
33 | * -D__KERNEL__ is automatically passed on the command line when
34 | * building something as part of the Linux kernel. Assume standalone
35 | * mode.
36 | */
37 | # include
38 | # include
39 | # ifndef __UD_STANDALONE__
40 | # define __UD_STANDALONE__ 1
41 | # endif
42 | #endif /* __KERNEL__ */
43 |
44 | #if !defined(__UD_STANDALONE__)
45 | # include
46 | # include
47 | #endif
48 |
49 | /* gcc specific extensions */
50 | #ifdef __GNUC__
51 | # define UD_ATTR_PACKED __attribute__((packed))
52 | #else
53 | # define UD_ATTR_PACKED
54 | #endif /* UD_ATTR_PACKED */
55 |
56 |
57 | /* -----------------------------------------------------------------------------
58 | * All possible "types" of objects in udis86. Order is Important!
59 | * -----------------------------------------------------------------------------
60 | */
61 | enum ud_type
62 | {
63 | UD_NONE,
64 |
65 | /* 8 bit GPRs */
66 | UD_R_AL, UD_R_CL, UD_R_DL, UD_R_BL,
67 | UD_R_AH, UD_R_CH, UD_R_DH, UD_R_BH,
68 | UD_R_SPL, UD_R_BPL, UD_R_SIL, UD_R_DIL,
69 | UD_R_R8B, UD_R_R9B, UD_R_R10B, UD_R_R11B,
70 | UD_R_R12B, UD_R_R13B, UD_R_R14B, UD_R_R15B,
71 |
72 | /* 16 bit GPRs */
73 | UD_R_AX, UD_R_CX, UD_R_DX, UD_R_BX,
74 | UD_R_SP, UD_R_BP, UD_R_SI, UD_R_DI,
75 | UD_R_R8W, UD_R_R9W, UD_R_R10W, UD_R_R11W,
76 | UD_R_R12W, UD_R_R13W, UD_R_R14W, UD_R_R15W,
77 |
78 | /* 32 bit GPRs */
79 | UD_R_EAX, UD_R_ECX, UD_R_EDX, UD_R_EBX,
80 | UD_R_ESP, UD_R_EBP, UD_R_ESI, UD_R_EDI,
81 | UD_R_R8D, UD_R_R9D, UD_R_R10D, UD_R_R11D,
82 | UD_R_R12D, UD_R_R13D, UD_R_R14D, UD_R_R15D,
83 |
84 | /* 64 bit GPRs */
85 | UD_R_RAX, UD_R_RCX, UD_R_RDX, UD_R_RBX,
86 | UD_R_RSP, UD_R_RBP, UD_R_RSI, UD_R_RDI,
87 | UD_R_R8, UD_R_R9, UD_R_R10, UD_R_R11,
88 | UD_R_R12, UD_R_R13, UD_R_R14, UD_R_R15,
89 |
90 | /* segment registers */
91 | UD_R_ES, UD_R_CS, UD_R_SS, UD_R_DS,
92 | UD_R_FS, UD_R_GS,
93 |
94 | /* control registers*/
95 | UD_R_CR0, UD_R_CR1, UD_R_CR2, UD_R_CR3,
96 | UD_R_CR4, UD_R_CR5, UD_R_CR6, UD_R_CR7,
97 | UD_R_CR8, UD_R_CR9, UD_R_CR10, UD_R_CR11,
98 | UD_R_CR12, UD_R_CR13, UD_R_CR14, UD_R_CR15,
99 |
100 | /* debug registers */
101 | UD_R_DR0, UD_R_DR1, UD_R_DR2, UD_R_DR3,
102 | UD_R_DR4, UD_R_DR5, UD_R_DR6, UD_R_DR7,
103 | UD_R_DR8, UD_R_DR9, UD_R_DR10, UD_R_DR11,
104 | UD_R_DR12, UD_R_DR13, UD_R_DR14, UD_R_DR15,
105 |
106 | /* mmx registers */
107 | UD_R_MM0, UD_R_MM1, UD_R_MM2, UD_R_MM3,
108 | UD_R_MM4, UD_R_MM5, UD_R_MM6, UD_R_MM7,
109 |
110 | /* x87 registers */
111 | UD_R_ST0, UD_R_ST1, UD_R_ST2, UD_R_ST3,
112 | UD_R_ST4, UD_R_ST5, UD_R_ST6, UD_R_ST7,
113 |
114 | /* extended multimedia registers */
115 | UD_R_XMM0, UD_R_XMM1, UD_R_XMM2, UD_R_XMM3,
116 | UD_R_XMM4, UD_R_XMM5, UD_R_XMM6, UD_R_XMM7,
117 | UD_R_XMM8, UD_R_XMM9, UD_R_XMM10, UD_R_XMM11,
118 | UD_R_XMM12, UD_R_XMM13, UD_R_XMM14, UD_R_XMM15,
119 |
120 | /* 256B multimedia registers */
121 | UD_R_YMM0, UD_R_YMM1, UD_R_YMM2, UD_R_YMM3,
122 | UD_R_YMM4, UD_R_YMM5, UD_R_YMM6, UD_R_YMM7,
123 | UD_R_YMM8, UD_R_YMM9, UD_R_YMM10, UD_R_YMM11,
124 | UD_R_YMM12, UD_R_YMM13, UD_R_YMM14, UD_R_YMM15,
125 |
126 | UD_R_RIP,
127 |
128 | /* Operand Types */
129 | UD_OP_REG, UD_OP_MEM, UD_OP_PTR, UD_OP_IMM,
130 | UD_OP_JIMM, UD_OP_CONST
131 | };
132 |
133 | enum ud_eflag_state
134 | {
135 | UD_FLAG_UNCHANGED,
136 | UD_FLAG_TESTED,
137 | UD_FLAG_MODIFIED,
138 | UD_FLAG_RESET,
139 | UD_FLAG_SET,
140 | UD_FLAG_UNDEFINED,
141 | UD_FLAG_PRIOR
142 | };
143 |
144 | enum ud_operand_access
145 | {
146 | UD_OP_ACCESS_READ = 1,
147 | UD_OP_ACCESS_WRITE = 2
148 | };
149 |
150 | /* This structure describes the state of the EFLAGS register
151 | * once an instruction has been executed.
152 | */
153 | struct ud_eflags
154 | {
155 | enum ud_eflag_state of_state;
156 | enum ud_eflag_state sf_state;
157 | enum ud_eflag_state zf_state;
158 | enum ud_eflag_state af_state;
159 | enum ud_eflag_state pf_state;
160 | enum ud_eflag_state cf_state;
161 | enum ud_eflag_state tf_state;
162 | enum ud_eflag_state if_state;
163 | enum ud_eflag_state df_state;
164 | enum ud_eflag_state nt_state;
165 | enum ud_eflag_state rf_state;
166 | };
167 |
168 | #include "itab.h"
169 |
170 | union ud_lval {
171 | int8_t sbyte;
172 | uint8_t ubyte;
173 | int16_t sword;
174 | uint16_t uword;
175 | int32_t sdword;
176 | uint32_t udword;
177 | int64_t sqword;
178 | uint64_t uqword;
179 | struct {
180 | uint16_t seg;
181 | uint32_t off;
182 | } ptr;
183 | };
184 |
185 | /* -----------------------------------------------------------------------------
186 | * struct ud_operand - Disassembled instruction Operand.
187 | * -----------------------------------------------------------------------------
188 | */
189 | struct ud_operand {
190 | enum ud_type type;
191 | uint16_t size;
192 | enum ud_type base;
193 | enum ud_type index;
194 | uint8_t scale;
195 | uint8_t offset;
196 | union ud_lval lval;
197 | uint8_t signed_lval;
198 | uint8_t access;
199 | /*
200 | * internal use only
201 | */
202 | uint64_t _legacy; /* this will be removed in 1.8 */
203 | uint8_t _oprcode;
204 | };
205 |
206 | /* -----------------------------------------------------------------------------
207 | * struct ud - The udis86 object.
208 | * -----------------------------------------------------------------------------
209 | */
210 | struct ud
211 | {
212 | /*
213 | * input buffering
214 | */
215 | int (*inp_hook) (struct ud*);
216 | #ifndef __UD_STANDALONE__
217 | FILE* inp_file;
218 | #endif
219 | const uint8_t* inp_buf;
220 | size_t inp_buf_size;
221 | size_t inp_buf_index;
222 | uint8_t inp_curr;
223 | size_t inp_ctr;
224 | uint8_t inp_sess[64];
225 | int inp_end;
226 | int inp_peek;
227 |
228 | void (*translator)(struct ud*);
229 | uint64_t insn_offset;
230 | char insn_hexcode[64];
231 |
232 | /*
233 | * Assembly output buffer
234 | */
235 | char *asm_buf;
236 | size_t asm_buf_size;
237 | size_t asm_buf_fill;
238 | char asm_buf_int[128];
239 |
240 | /*
241 | * Symbol resolver for use in the translation phase.
242 | */
243 | const char* (*sym_resolver)(struct ud*, uint64_t addr, int64_t *offset);
244 |
245 | uint8_t dis_mode;
246 | uint64_t pc;
247 | uint8_t vendor;
248 | enum ud_mnemonic_code mnemonic;
249 | struct ud_operand operand[4];
250 | uint8_t error;
251 | uint8_t _rex;
252 | uint8_t pfx_rex;
253 | uint8_t pfx_seg;
254 | uint8_t pfx_opr;
255 | uint8_t pfx_adr;
256 | uint8_t pfx_lock;
257 | uint8_t pfx_str;
258 | uint8_t pfx_rep;
259 | uint8_t pfx_repe;
260 | uint8_t pfx_repne;
261 | uint8_t opr_mode;
262 | uint8_t adr_mode;
263 | uint8_t br_far;
264 | uint8_t br_near;
265 | uint8_t have_modrm;
266 | uint8_t modrm;
267 | uint8_t modrm_offset;
268 | uint8_t vex_op;
269 | uint8_t vex_b1;
270 | uint8_t vex_b2;
271 | uint8_t primary_opcode;
272 | void * user_opaque_data;
273 | struct ud_itab_entry * itab_entry;
274 | struct ud_lookup_table_list_entry *le;
275 | };
276 |
277 | /* -----------------------------------------------------------------------------
278 | * Type-definitions
279 | * -----------------------------------------------------------------------------
280 | */
281 | typedef enum ud_type ud_type_t;
282 | typedef enum ud_mnemonic_code ud_mnemonic_code_t;
283 |
284 | typedef struct ud ud_t;
285 | typedef struct ud_operand ud_operand_t;
286 |
287 | #define UD_SYN_INTEL ud_translate_intel
288 | #define UD_SYN_ATT ud_translate_att
289 | #define UD_EOI (-1)
290 | #define UD_INP_CACHE_SZ 32
291 | #define UD_VENDOR_AMD 0
292 | #define UD_VENDOR_INTEL 1
293 | #define UD_VENDOR_ANY 2
294 |
295 | #endif
296 |
297 | /*
298 | vim: set ts=2 sw=2 expandtab
299 | */
300 |
--------------------------------------------------------------------------------