├── .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 | 53 | 54 | 55 | 0 56 | 0 57 | 811 58 | 21 59 | 60 | 61 | 62 | 63 | &File 64 | 65 | 66 | 67 | 68 | 69 | 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 | "" 178 | "" 179 | "" 180 | "" 181 | "" 182 | "" 183 | "" 184 | "" 185 | "" 186 | "
Line Number %1
I1 Hits %2
D1 Hits %3
L2 Data Misses %4
L2 Instruction Misses %5
Badness %6
Instructions Executed %7
Prefetch Hit D1 %8
Prefetch Hit L2 %9
") 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 | --------------------------------------------------------------------------------