diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml new file mode 100644 index 000000000..3c80e88d9 --- /dev/null +++ b/.github/workflows/linux.yml @@ -0,0 +1,38 @@ +name: Linux Clang + +on: + pull_request: + types: [ready_for_review, synchronize] + push: + branches: + - main + +env: + # Path to the solution file relative to the root of the project. + SOLUTION_FILE_PATH: ./ + + # Configuration type to build. + # You can convert this to a build matrix if you need coverage of multiple configuration types. + # https://docs.github.com/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix + BUILD_CONFIGURATION: release + BUILD_PLATFORM: x64 + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v5 + + - name: Install Dependencies + run: sudo apt-get update && sudo apt-get install -y libgl1-mesa-dev libx11-dev libxcursor-dev libxrandr-dev libxinerama-dev libxi-dev + + - name: Generate premake5 solution + working-directory: ${{env.SOLUTION_FILE_PATH}} + run: ./gen_proj_linux.sh + + - name: Build + working-directory: ${{env.GITHUB_WORKSPACE}} + # Add additional options to the MSBuild command line here (like platform or verbosity level). + # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference + run: make -j$(nproc) config=${{env.BUILD_CONFIGURATION}}_${{env.BUILD_PLATFORM}} diff --git a/.github/workflows/msbuild.yml b/.github/workflows/windows.yml similarity index 84% rename from .github/workflows/msbuild.yml rename to .github/workflows/windows.yml index 035933159..005d0dbd9 100644 --- a/.github/workflows/msbuild.yml +++ b/.github/workflows/windows.yml @@ -1,15 +1,15 @@ -name: MSBuild +name: Windows MSBuild on: pull_request: - types: ready_for_review + types: [ready_for_review, synchronize] push: branches: - main env: # Path to the solution file relative to the root of the project. - SOLUTION_FILE_PATH: Sources\Overload + SOLUTION_FILE_PATH: .\ # Configuration type to build. # You can convert this to a build matrix if you need coverage of multiple configuration types. @@ -21,11 +21,11 @@ jobs: runs-on: windows-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Generate premake5 solution working-directory: ${{env.SOLUTION_FILE_PATH}} - run: ..\..\Dependencies\premake5\bin\premake5.exe vs2022 + run: .\gen_proj_win32.bat - name: Add MSBuild to PATH uses: microsoft/setup-msbuild@v2 diff --git a/.gitignore b/.gitignore index 239abbb96..4ec7df48f 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ imgui.ini *.vcxproj* *.sln *.vcxitems* -/Releases/ \ No newline at end of file +/Releases/ +Makefile \ No newline at end of file diff --git a/Dependencies/assimp/contrib/zlib/gzguts.h b/Dependencies/assimp/contrib/zlib/gzguts.h index 57faf3716..60ed8891c 100644 --- a/Dependencies/assimp/contrib/zlib/gzguts.h +++ b/Dependencies/assimp/contrib/zlib/gzguts.h @@ -35,6 +35,10 @@ # include #endif +#ifdef __unix__ +# include +#endif + #if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32) # include #endif diff --git a/Dependencies/glfw/premake5.lua b/Dependencies/glfw/premake5.lua index f0020659a..26f89b860 100644 --- a/Dependencies/glfw/premake5.lua +++ b/Dependencies/glfw/premake5.lua @@ -17,9 +17,27 @@ project "glfw" "include" } - defines { - "_GLFW_WIN32" - } + filter { "system:windows" } + defines { "_GLFW_WIN32" } + removefiles { + "src/cocoa_*", + "src/posix_time.h", + "src/x11_*", + "src/glx_*", + "src/nsgl_*" + } + filter {} + + filter { "system:linux" } + defines { "_GLFW_X11", "_GNU_SOURCE" } + removefiles { + "src/win32_*", + "src/cocoa_*", + "src/posix_time.h", + "src/wgl_*", + "src/nsgl_*" + } + filter {} filter { "configurations:Debug" } defines { "DEBUG" } diff --git a/Dependencies/premake5/bin/premake5 b/Dependencies/premake5/bin/premake5 new file mode 100755 index 000000000..1b601b0ae Binary files /dev/null and b/Dependencies/premake5/bin/premake5 differ diff --git a/Dependencies/sol/include/sol/function_types_stateless.hpp b/Dependencies/sol/include/sol/function_types_stateless.hpp index a2f66ba0a..fe0f3f0b2 100644 --- a/Dependencies/sol/include/sol/function_types_stateless.hpp +++ b/Dependencies/sol/include/sol/function_types_stateless.hpp @@ -320,7 +320,13 @@ namespace sol { namespace function_detail { } template - static int call(lua_State* L) noexcept(std::is_nothrow_copy_assignable_v) { + static int call(lua_State* L) +#if SOL_IS_ON(SOL_COMPILER_CLANG) + // apparent regression in clang 18 - llvm/llvm-project#91362 +#else + noexcept(std::is_nothrow_copy_assignable_v) +#endif + { int nr; if constexpr (no_trampoline) { nr = real_call(L); @@ -360,7 +366,13 @@ namespace sol { namespace function_detail { } template - static int call(lua_State* L) noexcept(std::is_nothrow_copy_assignable_v) { + static int call(lua_State* L) +#if SOL_IS_ON(SOL_COMPILER_CLANG) + // apparent regression in clang 18 - llvm/llvm-project#91362 +#else + noexcept(std::is_nothrow_copy_assignable_v) +#endif + { int nr; if constexpr (no_trampoline) { nr = real_call(L); diff --git a/Dependencies/tracy/client/TracyFastVector.hpp b/Dependencies/tracy/client/TracyFastVector.hpp index 38accc926..cc753da25 100644 --- a/Dependencies/tracy/client/TracyFastVector.hpp +++ b/Dependencies/tracy/client/TracyFastVector.hpp @@ -2,6 +2,7 @@ #define __TRACYFASTVECTOR_HPP__ #include +#include #include #include "../common/TracyAlloc.hpp" diff --git a/Dependencies/tracy/libbacktrace/LICENSE b/Dependencies/tracy/libbacktrace/LICENSE new file mode 100644 index 000000000..097d2774e --- /dev/null +++ b/Dependencies/tracy/libbacktrace/LICENSE @@ -0,0 +1,29 @@ +# Copyright (C) 2012-2016 Free Software Foundation, Inc. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: + +# (1) Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. + +# (2) Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. + +# (3) The name of the author may not be used to +# endorse or promote products derived from this software without +# specific prior written permission. + +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. diff --git a/Dependencies/tracy/libbacktrace/alloc.cpp b/Dependencies/tracy/libbacktrace/alloc.cpp new file mode 100644 index 000000000..a365a4860 --- /dev/null +++ b/Dependencies/tracy/libbacktrace/alloc.cpp @@ -0,0 +1,174 @@ +/* alloc.c -- Memory allocation without mmap. + Copyright (C) 2012-2021 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Google. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + (1) Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + (2) Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + (3) The name of the author may not be used to + endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. */ + +#include "config.h" + +#include +#include +#include + +#include "backtrace.hpp" +#include "internal.hpp" + +#include "../common/TracyAlloc.hpp" + +namespace tracy +{ + +/* Allocation routines to use on systems that do not support anonymous + mmap. This implementation just uses malloc, which means that the + backtrace functions may not be safely invoked from a signal + handler. */ + +/* Allocate memory like malloc. If ERROR_CALLBACK is NULL, don't + report an error. */ + +void * +backtrace_alloc (struct backtrace_state *state ATTRIBUTE_UNUSED, + size_t size, backtrace_error_callback error_callback, + void *data) +{ + void *ret; + + ret = tracy_malloc (size); + if (ret == NULL) + { + if (error_callback) + error_callback (data, "malloc", errno); + } + return ret; +} + +/* Free memory. */ + +void +backtrace_free (struct backtrace_state *state ATTRIBUTE_UNUSED, + void *p, size_t size ATTRIBUTE_UNUSED, + backtrace_error_callback error_callback ATTRIBUTE_UNUSED, + void *data ATTRIBUTE_UNUSED) +{ + tracy_free (p); +} + +/* Grow VEC by SIZE bytes. */ + +void * +backtrace_vector_grow (struct backtrace_state *state ATTRIBUTE_UNUSED, + size_t size, backtrace_error_callback error_callback, + void *data, struct backtrace_vector *vec) +{ + void *ret; + + if (size > vec->alc) + { + size_t alc; + void *base; + + if (vec->size == 0) + alc = 32 * size; + else if (vec->size >= 4096) + alc = vec->size + 4096; + else + alc = 2 * vec->size; + + if (alc < vec->size + size) + alc = vec->size + size; + + base = tracy_realloc (vec->base, alc); + if (base == NULL) + { + error_callback (data, "realloc", errno); + return NULL; + } + + vec->base = base; + vec->alc = alc - vec->size; + } + + ret = (char *) vec->base + vec->size; + vec->size += size; + vec->alc -= size; + return ret; +} + +/* Finish the current allocation on VEC. */ + +void * +backtrace_vector_finish (struct backtrace_state *state, + struct backtrace_vector *vec, + backtrace_error_callback error_callback, + void *data) +{ + void *ret; + + /* With this allocator we call realloc in backtrace_vector_grow, + which means we can't easily reuse the memory here. So just + release it. */ + if (!backtrace_vector_release (state, vec, error_callback, data)) + return NULL; + ret = vec->base; + vec->base = NULL; + vec->size = 0; + vec->alc = 0; + return ret; +} + +/* Release any extra space allocated for VEC. */ + +int +backtrace_vector_release (struct backtrace_state *state ATTRIBUTE_UNUSED, + struct backtrace_vector *vec, + backtrace_error_callback error_callback, + void *data) +{ + vec->alc = 0; + + if (vec->size == 0) + { + /* As of C17, realloc with size 0 is marked as an obsolescent feature, use + free instead. */ + tracy_free (vec->base); + vec->base = NULL; + return 1; + } + + vec->base = tracy_realloc (vec->base, vec->size); + if (vec->base == NULL) + { + error_callback (data, "realloc", errno); + return 0; + } + + return 1; +} + +} diff --git a/Dependencies/tracy/libbacktrace/backtrace.hpp b/Dependencies/tracy/libbacktrace/backtrace.hpp new file mode 100644 index 000000000..e4be297a9 --- /dev/null +++ b/Dependencies/tracy/libbacktrace/backtrace.hpp @@ -0,0 +1,186 @@ +/* backtrace.h -- Public header file for stack backtrace library. + Copyright (C) 2012-2021 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Google. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + (1) Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + (2) Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + (3) The name of the author may not be used to + endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. */ + +#ifndef BACKTRACE_H +#define BACKTRACE_H + +#include +#include +#include + +namespace tracy +{ + +/* The backtrace state. This struct is intentionally not defined in + the public interface. */ + +struct backtrace_state; + +/* The type of the error callback argument to backtrace functions. + This function, if not NULL, will be called for certain error cases. + The DATA argument is passed to the function that calls this one. + The MSG argument is an error message. The ERRNUM argument, if + greater than 0, holds an errno value. The MSG buffer may become + invalid after this function returns. + + As a special case, the ERRNUM argument will be passed as -1 if no + debug info can be found for the executable, or if the debug info + exists but has an unsupported version, but the function requires + debug info (e.g., backtrace_full, backtrace_pcinfo). The MSG in + this case will be something along the lines of "no debug info". + Similarly, ERRNUM will be passed as -1 if there is no symbol table, + but the function requires a symbol table (e.g., backtrace_syminfo). + This may be used as a signal that some other approach should be + tried. */ + +typedef void (*backtrace_error_callback) (void *data, const char *msg, + int errnum); + +/* Create state information for the backtrace routines. This must be + called before any of the other routines, and its return value must + be passed to all of the other routines. FILENAME is the path name + of the executable file; if it is NULL the library will try + system-specific path names. If not NULL, FILENAME must point to a + permanent buffer. If THREADED is non-zero the state may be + accessed by multiple threads simultaneously, and the library will + use appropriate atomic operations. If THREADED is zero the state + may only be accessed by one thread at a time. This returns a state + pointer on success, NULL on error. If an error occurs, this will + call the ERROR_CALLBACK routine. + + Calling this function allocates resources that cannot be freed. + There is no backtrace_free_state function. The state is used to + cache information that is expensive to recompute. Programs are + expected to call this function at most once and to save the return + value for all later calls to backtrace functions. */ + +extern struct backtrace_state *backtrace_create_state ( + const char *filename, int threaded, + backtrace_error_callback error_callback, void *data); + +/* The type of the callback argument to the backtrace_full function. + DATA is the argument passed to backtrace_full. PC is the program + counter. FILENAME is the name of the file containing PC, or NULL + if not available. LINENO is the line number in FILENAME containing + PC, or 0 if not available. FUNCTION is the name of the function + containing PC, or NULL if not available. This should return 0 to + continuing tracing. The FILENAME and FUNCTION buffers may become + invalid after this function returns. */ + +typedef int (*backtrace_full_callback) (void *data, uintptr_t pc, uintptr_t lowaddr, + const char *filename, int lineno, + const char *function); + +/* Get a full stack backtrace. SKIP is the number of frames to skip; + passing 0 will start the trace with the function calling + backtrace_full. DATA is passed to the callback routine. If any + call to CALLBACK returns a non-zero value, the stack backtrace + stops, and backtrace returns that value; this may be used to limit + the number of stack frames desired. If all calls to CALLBACK + return 0, backtrace returns 0. The backtrace_full function will + make at least one call to either CALLBACK or ERROR_CALLBACK. This + function requires debug info for the executable. */ + +extern int backtrace_full (struct backtrace_state *state, int skip, + backtrace_full_callback callback, + backtrace_error_callback error_callback, + void *data); + +/* The type of the callback argument to the backtrace_simple function. + DATA is the argument passed to simple_backtrace. PC is the program + counter. This should return 0 to continue tracing. */ + +typedef int (*backtrace_simple_callback) (void *data, uintptr_t pc); + +/* Get a simple backtrace. SKIP is the number of frames to skip, as + in backtrace. DATA is passed to the callback routine. If any call + to CALLBACK returns a non-zero value, the stack backtrace stops, + and backtrace_simple returns that value. Otherwise + backtrace_simple returns 0. The backtrace_simple function will + make at least one call to either CALLBACK or ERROR_CALLBACK. This + function does not require any debug info for the executable. */ + +extern int backtrace_simple (struct backtrace_state *state, int skip, + backtrace_simple_callback callback, + backtrace_error_callback error_callback, + void *data); + +/* Print the current backtrace in a user readable format to a FILE. + SKIP is the number of frames to skip, as in backtrace_full. Any + error messages are printed to stderr. This function requires debug + info for the executable. */ + +extern void backtrace_print (struct backtrace_state *state, int skip, FILE *); + +/* Given PC, a program counter in the current program, call the + callback function with filename, line number, and function name + information. This will normally call the callback function exactly + once. However, if the PC happens to describe an inlined call, and + the debugging information contains the necessary information, then + this may call the callback function multiple times. This will make + at least one call to either CALLBACK or ERROR_CALLBACK. This + returns the first non-zero value returned by CALLBACK, or 0. */ + +extern int backtrace_pcinfo (struct backtrace_state *state, uintptr_t pc, + backtrace_full_callback callback, + backtrace_error_callback error_callback, + void *data); + +/* The type of the callback argument to backtrace_syminfo. DATA and + PC are the arguments passed to backtrace_syminfo. SYMNAME is the + name of the symbol for the corresponding code. SYMVAL is the + value and SYMSIZE is the size of the symbol. SYMNAME will be NULL + if no error occurred but the symbol could not be found. */ + +typedef void (*backtrace_syminfo_callback) (void *data, uintptr_t pc, + const char *symname, + uintptr_t symval, + uintptr_t symsize); + +/* Given ADDR, an address or program counter in the current program, + call the callback information with the symbol name and value + describing the function or variable in which ADDR may be found. + This will call either CALLBACK or ERROR_CALLBACK exactly once. + This returns 1 on success, 0 on failure. This function requires + the symbol table but does not require the debug info. Note that if + the symbol table is present but ADDR could not be found in the + table, CALLBACK will be called with a NULL SYMNAME argument. + Returns 1 on success, 0 on error. */ + +extern int backtrace_syminfo (struct backtrace_state *state, uintptr_t addr, + backtrace_syminfo_callback callback, + backtrace_error_callback error_callback, + void *data); + +} + +#endif diff --git a/Dependencies/tracy/libbacktrace/config.h b/Dependencies/tracy/libbacktrace/config.h new file mode 100644 index 000000000..87e38a95b --- /dev/null +++ b/Dependencies/tracy/libbacktrace/config.h @@ -0,0 +1,26 @@ +#include +#if defined(__linux__) && !defined(__GLIBC__) && !defined(__WORDSIZE) +// include __WORDSIZE headers for musl +# include +#endif +#if __WORDSIZE == 64 +# define BACKTRACE_ELF_SIZE 64 +#else +# define BACKTRACE_ELF_SIZE 32 +#endif + +#define HAVE_DLFCN_H 1 +#define HAVE_FCNTL 1 +#define HAVE_INTTYPES_H 1 +#define HAVE_LSTAT 1 +#define HAVE_READLINK 1 +#define HAVE_DL_ITERATE_PHDR 1 +#define HAVE_ATOMIC_FUNCTIONS 1 +#define HAVE_DECL_STRNLEN 1 + +#ifdef __APPLE__ +# define HAVE_MACH_O_DYLD_H 1 +#elif defined BSD +# define HAVE_KERN_PROC 1 +# define HAVE_KERN_PROC_ARGS 1 +#endif diff --git a/Dependencies/tracy/libbacktrace/dwarf.cpp b/Dependencies/tracy/libbacktrace/dwarf.cpp new file mode 100644 index 000000000..b6d681aa9 --- /dev/null +++ b/Dependencies/tracy/libbacktrace/dwarf.cpp @@ -0,0 +1,4448 @@ +/* dwarf.c -- Get file/line information from DWARF for backtraces. + Copyright (C) 2012-2021 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Google. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + (1) Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + (2) Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + (3) The name of the author may not be used to + endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. */ + +#include "config.h" + +#include +#include +#include +#include + +#include "filenames.hpp" + +#include "backtrace.hpp" +#include "internal.hpp" + +namespace tracy +{ + +/* DWARF constants. */ + +enum dwarf_tag { + DW_TAG_entry_point = 0x3, + DW_TAG_compile_unit = 0x11, + DW_TAG_inlined_subroutine = 0x1d, + DW_TAG_subprogram = 0x2e, + DW_TAG_skeleton_unit = 0x4a, +}; + +enum dwarf_form { + DW_FORM_addr = 0x01, + DW_FORM_block2 = 0x03, + DW_FORM_block4 = 0x04, + DW_FORM_data2 = 0x05, + DW_FORM_data4 = 0x06, + DW_FORM_data8 = 0x07, + DW_FORM_string = 0x08, + DW_FORM_block = 0x09, + DW_FORM_block1 = 0x0a, + DW_FORM_data1 = 0x0b, + DW_FORM_flag = 0x0c, + DW_FORM_sdata = 0x0d, + DW_FORM_strp = 0x0e, + DW_FORM_udata = 0x0f, + DW_FORM_ref_addr = 0x10, + DW_FORM_ref1 = 0x11, + DW_FORM_ref2 = 0x12, + DW_FORM_ref4 = 0x13, + DW_FORM_ref8 = 0x14, + DW_FORM_ref_udata = 0x15, + DW_FORM_indirect = 0x16, + DW_FORM_sec_offset = 0x17, + DW_FORM_exprloc = 0x18, + DW_FORM_flag_present = 0x19, + DW_FORM_ref_sig8 = 0x20, + DW_FORM_strx = 0x1a, + DW_FORM_addrx = 0x1b, + DW_FORM_ref_sup4 = 0x1c, + DW_FORM_strp_sup = 0x1d, + DW_FORM_data16 = 0x1e, + DW_FORM_line_strp = 0x1f, + DW_FORM_implicit_const = 0x21, + DW_FORM_loclistx = 0x22, + DW_FORM_rnglistx = 0x23, + DW_FORM_ref_sup8 = 0x24, + DW_FORM_strx1 = 0x25, + DW_FORM_strx2 = 0x26, + DW_FORM_strx3 = 0x27, + DW_FORM_strx4 = 0x28, + DW_FORM_addrx1 = 0x29, + DW_FORM_addrx2 = 0x2a, + DW_FORM_addrx3 = 0x2b, + DW_FORM_addrx4 = 0x2c, + DW_FORM_GNU_addr_index = 0x1f01, + DW_FORM_GNU_str_index = 0x1f02, + DW_FORM_GNU_ref_alt = 0x1f20, + DW_FORM_GNU_strp_alt = 0x1f21 +}; + +enum dwarf_attribute { + DW_AT_sibling = 0x01, + DW_AT_location = 0x02, + DW_AT_name = 0x03, + DW_AT_ordering = 0x09, + DW_AT_subscr_data = 0x0a, + DW_AT_byte_size = 0x0b, + DW_AT_bit_offset = 0x0c, + DW_AT_bit_size = 0x0d, + DW_AT_element_list = 0x0f, + DW_AT_stmt_list = 0x10, + DW_AT_low_pc = 0x11, + DW_AT_high_pc = 0x12, + DW_AT_language = 0x13, + DW_AT_member = 0x14, + DW_AT_discr = 0x15, + DW_AT_discr_value = 0x16, + DW_AT_visibility = 0x17, + DW_AT_import = 0x18, + DW_AT_string_length = 0x19, + DW_AT_common_reference = 0x1a, + DW_AT_comp_dir = 0x1b, + DW_AT_const_value = 0x1c, + DW_AT_containing_type = 0x1d, + DW_AT_default_value = 0x1e, + DW_AT_inline = 0x20, + DW_AT_is_optional = 0x21, + DW_AT_lower_bound = 0x22, + DW_AT_producer = 0x25, + DW_AT_prototyped = 0x27, + DW_AT_return_addr = 0x2a, + DW_AT_start_scope = 0x2c, + DW_AT_bit_stride = 0x2e, + DW_AT_upper_bound = 0x2f, + DW_AT_abstract_origin = 0x31, + DW_AT_accessibility = 0x32, + DW_AT_address_class = 0x33, + DW_AT_artificial = 0x34, + DW_AT_base_types = 0x35, + DW_AT_calling_convention = 0x36, + DW_AT_count = 0x37, + DW_AT_data_member_location = 0x38, + DW_AT_decl_column = 0x39, + DW_AT_decl_file = 0x3a, + DW_AT_decl_line = 0x3b, + DW_AT_declaration = 0x3c, + DW_AT_discr_list = 0x3d, + DW_AT_encoding = 0x3e, + DW_AT_external = 0x3f, + DW_AT_frame_base = 0x40, + DW_AT_friend = 0x41, + DW_AT_identifier_case = 0x42, + DW_AT_macro_info = 0x43, + DW_AT_namelist_items = 0x44, + DW_AT_priority = 0x45, + DW_AT_segment = 0x46, + DW_AT_specification = 0x47, + DW_AT_static_link = 0x48, + DW_AT_type = 0x49, + DW_AT_use_location = 0x4a, + DW_AT_variable_parameter = 0x4b, + DW_AT_virtuality = 0x4c, + DW_AT_vtable_elem_location = 0x4d, + DW_AT_allocated = 0x4e, + DW_AT_associated = 0x4f, + DW_AT_data_location = 0x50, + DW_AT_byte_stride = 0x51, + DW_AT_entry_pc = 0x52, + DW_AT_use_UTF8 = 0x53, + DW_AT_extension = 0x54, + DW_AT_ranges = 0x55, + DW_AT_trampoline = 0x56, + DW_AT_call_column = 0x57, + DW_AT_call_file = 0x58, + DW_AT_call_line = 0x59, + DW_AT_description = 0x5a, + DW_AT_binary_scale = 0x5b, + DW_AT_decimal_scale = 0x5c, + DW_AT_small = 0x5d, + DW_AT_decimal_sign = 0x5e, + DW_AT_digit_count = 0x5f, + DW_AT_picture_string = 0x60, + DW_AT_mutable = 0x61, + DW_AT_threads_scaled = 0x62, + DW_AT_explicit = 0x63, + DW_AT_object_pointer = 0x64, + DW_AT_endianity = 0x65, + DW_AT_elemental = 0x66, + DW_AT_pure = 0x67, + DW_AT_recursive = 0x68, + DW_AT_signature = 0x69, + DW_AT_main_subprogram = 0x6a, + DW_AT_data_bit_offset = 0x6b, + DW_AT_const_expr = 0x6c, + DW_AT_enum_class = 0x6d, + DW_AT_linkage_name = 0x6e, + DW_AT_string_length_bit_size = 0x6f, + DW_AT_string_length_byte_size = 0x70, + DW_AT_rank = 0x71, + DW_AT_str_offsets_base = 0x72, + DW_AT_addr_base = 0x73, + DW_AT_rnglists_base = 0x74, + DW_AT_dwo_name = 0x76, + DW_AT_reference = 0x77, + DW_AT_rvalue_reference = 0x78, + DW_AT_macros = 0x79, + DW_AT_call_all_calls = 0x7a, + DW_AT_call_all_source_calls = 0x7b, + DW_AT_call_all_tail_calls = 0x7c, + DW_AT_call_return_pc = 0x7d, + DW_AT_call_value = 0x7e, + DW_AT_call_origin = 0x7f, + DW_AT_call_parameter = 0x80, + DW_AT_call_pc = 0x81, + DW_AT_call_tail_call = 0x82, + DW_AT_call_target = 0x83, + DW_AT_call_target_clobbered = 0x84, + DW_AT_call_data_location = 0x85, + DW_AT_call_data_value = 0x86, + DW_AT_noreturn = 0x87, + DW_AT_alignment = 0x88, + DW_AT_export_symbols = 0x89, + DW_AT_deleted = 0x8a, + DW_AT_defaulted = 0x8b, + DW_AT_loclists_base = 0x8c, + DW_AT_lo_user = 0x2000, + DW_AT_hi_user = 0x3fff, + DW_AT_MIPS_fde = 0x2001, + DW_AT_MIPS_loop_begin = 0x2002, + DW_AT_MIPS_tail_loop_begin = 0x2003, + DW_AT_MIPS_epilog_begin = 0x2004, + DW_AT_MIPS_loop_unroll_factor = 0x2005, + DW_AT_MIPS_software_pipeline_depth = 0x2006, + DW_AT_MIPS_linkage_name = 0x2007, + DW_AT_MIPS_stride = 0x2008, + DW_AT_MIPS_abstract_name = 0x2009, + DW_AT_MIPS_clone_origin = 0x200a, + DW_AT_MIPS_has_inlines = 0x200b, + DW_AT_HP_block_index = 0x2000, + DW_AT_HP_unmodifiable = 0x2001, + DW_AT_HP_prologue = 0x2005, + DW_AT_HP_epilogue = 0x2008, + DW_AT_HP_actuals_stmt_list = 0x2010, + DW_AT_HP_proc_per_section = 0x2011, + DW_AT_HP_raw_data_ptr = 0x2012, + DW_AT_HP_pass_by_reference = 0x2013, + DW_AT_HP_opt_level = 0x2014, + DW_AT_HP_prof_version_id = 0x2015, + DW_AT_HP_opt_flags = 0x2016, + DW_AT_HP_cold_region_low_pc = 0x2017, + DW_AT_HP_cold_region_high_pc = 0x2018, + DW_AT_HP_all_variables_modifiable = 0x2019, + DW_AT_HP_linkage_name = 0x201a, + DW_AT_HP_prof_flags = 0x201b, + DW_AT_HP_unit_name = 0x201f, + DW_AT_HP_unit_size = 0x2020, + DW_AT_HP_widened_byte_size = 0x2021, + DW_AT_HP_definition_points = 0x2022, + DW_AT_HP_default_location = 0x2023, + DW_AT_HP_is_result_param = 0x2029, + DW_AT_sf_names = 0x2101, + DW_AT_src_info = 0x2102, + DW_AT_mac_info = 0x2103, + DW_AT_src_coords = 0x2104, + DW_AT_body_begin = 0x2105, + DW_AT_body_end = 0x2106, + DW_AT_GNU_vector = 0x2107, + DW_AT_GNU_guarded_by = 0x2108, + DW_AT_GNU_pt_guarded_by = 0x2109, + DW_AT_GNU_guarded = 0x210a, + DW_AT_GNU_pt_guarded = 0x210b, + DW_AT_GNU_locks_excluded = 0x210c, + DW_AT_GNU_exclusive_locks_required = 0x210d, + DW_AT_GNU_shared_locks_required = 0x210e, + DW_AT_GNU_odr_signature = 0x210f, + DW_AT_GNU_template_name = 0x2110, + DW_AT_GNU_call_site_value = 0x2111, + DW_AT_GNU_call_site_data_value = 0x2112, + DW_AT_GNU_call_site_target = 0x2113, + DW_AT_GNU_call_site_target_clobbered = 0x2114, + DW_AT_GNU_tail_call = 0x2115, + DW_AT_GNU_all_tail_call_sites = 0x2116, + DW_AT_GNU_all_call_sites = 0x2117, + DW_AT_GNU_all_source_call_sites = 0x2118, + DW_AT_GNU_macros = 0x2119, + DW_AT_GNU_deleted = 0x211a, + DW_AT_GNU_dwo_name = 0x2130, + DW_AT_GNU_dwo_id = 0x2131, + DW_AT_GNU_ranges_base = 0x2132, + DW_AT_GNU_addr_base = 0x2133, + DW_AT_GNU_pubnames = 0x2134, + DW_AT_GNU_pubtypes = 0x2135, + DW_AT_GNU_discriminator = 0x2136, + DW_AT_GNU_locviews = 0x2137, + DW_AT_GNU_entry_view = 0x2138, + DW_AT_VMS_rtnbeg_pd_address = 0x2201, + DW_AT_use_GNAT_descriptive_type = 0x2301, + DW_AT_GNAT_descriptive_type = 0x2302, + DW_AT_GNU_numerator = 0x2303, + DW_AT_GNU_denominator = 0x2304, + DW_AT_GNU_bias = 0x2305, + DW_AT_upc_threads_scaled = 0x3210, + DW_AT_PGI_lbase = 0x3a00, + DW_AT_PGI_soffset = 0x3a01, + DW_AT_PGI_lstride = 0x3a02, + DW_AT_APPLE_optimized = 0x3fe1, + DW_AT_APPLE_flags = 0x3fe2, + DW_AT_APPLE_isa = 0x3fe3, + DW_AT_APPLE_block = 0x3fe4, + DW_AT_APPLE_major_runtime_vers = 0x3fe5, + DW_AT_APPLE_runtime_class = 0x3fe6, + DW_AT_APPLE_omit_frame_ptr = 0x3fe7, + DW_AT_APPLE_property_name = 0x3fe8, + DW_AT_APPLE_property_getter = 0x3fe9, + DW_AT_APPLE_property_setter = 0x3fea, + DW_AT_APPLE_property_attribute = 0x3feb, + DW_AT_APPLE_objc_complete_type = 0x3fec, + DW_AT_APPLE_property = 0x3fed +}; + +enum dwarf_line_number_op { + DW_LNS_extended_op = 0x0, + DW_LNS_copy = 0x1, + DW_LNS_advance_pc = 0x2, + DW_LNS_advance_line = 0x3, + DW_LNS_set_file = 0x4, + DW_LNS_set_column = 0x5, + DW_LNS_negate_stmt = 0x6, + DW_LNS_set_basic_block = 0x7, + DW_LNS_const_add_pc = 0x8, + DW_LNS_fixed_advance_pc = 0x9, + DW_LNS_set_prologue_end = 0xa, + DW_LNS_set_epilogue_begin = 0xb, + DW_LNS_set_isa = 0xc, +}; + +enum dwarf_extended_line_number_op { + DW_LNE_end_sequence = 0x1, + DW_LNE_set_address = 0x2, + DW_LNE_define_file = 0x3, + DW_LNE_set_discriminator = 0x4, +}; + +enum dwarf_line_number_content_type { + DW_LNCT_path = 0x1, + DW_LNCT_directory_index = 0x2, + DW_LNCT_timestamp = 0x3, + DW_LNCT_size = 0x4, + DW_LNCT_MD5 = 0x5, + DW_LNCT_lo_user = 0x2000, + DW_LNCT_hi_user = 0x3fff +}; + +enum dwarf_range_list_entry { + DW_RLE_end_of_list = 0x00, + DW_RLE_base_addressx = 0x01, + DW_RLE_startx_endx = 0x02, + DW_RLE_startx_length = 0x03, + DW_RLE_offset_pair = 0x04, + DW_RLE_base_address = 0x05, + DW_RLE_start_end = 0x06, + DW_RLE_start_length = 0x07 +}; + +enum dwarf_unit_type { + DW_UT_compile = 0x01, + DW_UT_type = 0x02, + DW_UT_partial = 0x03, + DW_UT_skeleton = 0x04, + DW_UT_split_compile = 0x05, + DW_UT_split_type = 0x06, + DW_UT_lo_user = 0x80, + DW_UT_hi_user = 0xff +}; + +#if !defined(HAVE_DECL_STRNLEN) || !HAVE_DECL_STRNLEN + +/* If strnlen is not declared, provide our own version. */ + +static size_t +xstrnlen (const char *s, size_t maxlen) +{ + size_t i; + + for (i = 0; i < maxlen; ++i) + if (s[i] == '\0') + break; + return i; +} + +#define strnlen xstrnlen + +#endif + +/* A buffer to read DWARF info. */ + +struct dwarf_buf +{ + /* Buffer name for error messages. */ + const char *name; + /* Start of the buffer. */ + const unsigned char *start; + /* Next byte to read. */ + const unsigned char *buf; + /* The number of bytes remaining. */ + size_t left; + /* Whether the data is big-endian. */ + int is_bigendian; + /* Error callback routine. */ + backtrace_error_callback error_callback; + /* Data for error_callback. */ + void *data; + /* Non-zero if we've reported an underflow error. */ + int reported_underflow; +}; + +/* A single attribute in a DWARF abbreviation. */ + +struct attr +{ + /* The attribute name. */ + enum dwarf_attribute name; + /* The attribute form. */ + enum dwarf_form form; + /* The attribute value, for DW_FORM_implicit_const. */ + int64_t val; +}; + +/* A single DWARF abbreviation. */ + +struct abbrev +{ + /* The abbrev code--the number used to refer to the abbrev. */ + uint64_t code; + /* The entry tag. */ + enum dwarf_tag tag; + /* Non-zero if this abbrev has child entries. */ + int has_children; + /* The number of attributes. */ + size_t num_attrs; + /* The attributes. */ + struct attr *attrs; +}; + +/* The DWARF abbreviations for a compilation unit. This structure + only exists while reading the compilation unit. Most DWARF readers + seem to a hash table to map abbrev ID's to abbrev entries. + However, we primarily care about GCC, and GCC simply issues ID's in + numerical order starting at 1. So we simply keep a sorted vector, + and try to just look up the code. */ + +struct abbrevs +{ + /* The number of abbrevs in the vector. */ + size_t num_abbrevs; + /* The abbrevs, sorted by the code field. */ + struct abbrev *abbrevs; +}; + +/* The different kinds of attribute values. */ + +enum attr_val_encoding +{ + /* No attribute value. */ + ATTR_VAL_NONE, + /* An address. */ + ATTR_VAL_ADDRESS, + /* An index into the .debug_addr section, whose value is relative to + the DW_AT_addr_base attribute of the compilation unit. */ + ATTR_VAL_ADDRESS_INDEX, + /* A unsigned integer. */ + ATTR_VAL_UINT, + /* A sigd integer. */ + ATTR_VAL_SINT, + /* A string. */ + ATTR_VAL_STRING, + /* An index into the .debug_str_offsets section. */ + ATTR_VAL_STRING_INDEX, + /* An offset to other data in the containing unit. */ + ATTR_VAL_REF_UNIT, + /* An offset to other data within the .debug_info section. */ + ATTR_VAL_REF_INFO, + /* An offset to other data within the alt .debug_info section. */ + ATTR_VAL_REF_ALT_INFO, + /* An offset to data in some other section. */ + ATTR_VAL_REF_SECTION, + /* A type signature. */ + ATTR_VAL_REF_TYPE, + /* An index into the .debug_rnglists section. */ + ATTR_VAL_RNGLISTS_INDEX, + /* A block of data (not represented). */ + ATTR_VAL_BLOCK, + /* An expression (not represented). */ + ATTR_VAL_EXPR, +}; + +/* An attribute value. */ + +struct attr_val +{ + /* How the value is stored in the field u. */ + enum attr_val_encoding encoding; + union + { + /* ATTR_VAL_ADDRESS*, ATTR_VAL_UINT, ATTR_VAL_REF*. */ + uint64_t uint; + /* ATTR_VAL_SINT. */ + int64_t sint; + /* ATTR_VAL_STRING. */ + const char *string; + /* ATTR_VAL_BLOCK not stored. */ + } u; +}; + +/* The line number program header. */ + +struct line_header +{ + /* The version of the line number information. */ + int version; + /* Address size. */ + int addrsize; + /* The minimum instruction length. */ + unsigned int min_insn_len; + /* The maximum number of ops per instruction. */ + unsigned int max_ops_per_insn; + /* The line base for special opcodes. */ + int line_base; + /* The line range for special opcodes. */ + unsigned int line_range; + /* The opcode base--the first special opcode. */ + unsigned int opcode_base; + /* Opcode lengths, indexed by opcode - 1. */ + const unsigned char *opcode_lengths; + /* The number of directory entries. */ + size_t dirs_count; + /* The directory entries. */ + const char **dirs; + /* The number of filenames. */ + size_t filenames_count; + /* The filenames. */ + const char **filenames; +}; + +/* A format description from a line header. */ + +struct line_header_format +{ + int lnct; /* LNCT code. */ + enum dwarf_form form; /* Form of entry data. */ +}; + +/* Map a single PC value to a file/line. We will keep a vector of + these sorted by PC value. Each file/line will be correct from the + PC up to the PC of the next entry if there is one. We allocate one + extra entry at the end so that we can use bsearch. */ + +struct line +{ + /* PC. */ + uintptr_t pc; + /* File name. Many entries in the array are expected to point to + the same file name. */ + const char *filename; + /* Line number. */ + int lineno; + /* Index of the object in the original array read from the DWARF + section, before it has been sorted. The index makes it possible + to use Quicksort and maintain stability. */ + int idx; +}; + +/* A growable vector of line number information. This is used while + reading the line numbers. */ + +struct line_vector +{ + /* Memory. This is an array of struct line. */ + struct backtrace_vector vec; + /* Number of valid mappings. */ + size_t count; +}; + +/* A function described in the debug info. */ + +struct function +{ + /* The name of the function. */ + const char *name; + /* If this is an inlined function, the filename of the call + site. */ + const char *caller_filename; + /* If this is an inlined function, the line number of the call + site. */ + int caller_lineno; + /* Map PC ranges to inlined functions. */ + struct function_addrs *function_addrs; + size_t function_addrs_count; +}; + +/* An address range for a function. This maps a PC value to a + specific function. */ + +struct function_addrs +{ + /* Range is LOW <= PC < HIGH. */ + uintptr_t low; + uintptr_t high; + /* Function for this address range. */ + struct function *function; +}; + +/* A growable vector of function address ranges. */ + +struct function_vector +{ + /* Memory. This is an array of struct function_addrs. */ + struct backtrace_vector vec; + /* Number of address ranges present. */ + size_t count; +}; + +/* A DWARF compilation unit. This only holds the information we need + to map a PC to a file and line. */ + +struct unit +{ + /* The first entry for this compilation unit. */ + const unsigned char *unit_data; + /* The length of the data for this compilation unit. */ + size_t unit_data_len; + /* The offset of UNIT_DATA from the start of the information for + this compilation unit. */ + size_t unit_data_offset; + /* Offset of the start of the compilation unit from the start of the + .debug_info section. */ + size_t low_offset; + /* Offset of the end of the compilation unit from the start of the + .debug_info section. */ + size_t high_offset; + /* DWARF version. */ + int version; + /* Whether unit is DWARF64. */ + int is_dwarf64; + /* Address size. */ + int addrsize; + /* Offset into line number information. */ + off_t lineoff; + /* Offset of compilation unit in .debug_str_offsets. */ + uint64_t str_offsets_base; + /* Offset of compilation unit in .debug_addr. */ + uint64_t addr_base; + /* Offset of compilation unit in .debug_rnglists. */ + uint64_t rnglists_base; + /* Primary source file. */ + const char *filename; + /* Compilation command working directory. */ + const char *comp_dir; + /* Absolute file name, only set if needed. */ + const char *abs_filename; + /* The abbreviations for this unit. */ + struct abbrevs abbrevs; + + /* The fields above this point are read in during initialization and + may be accessed freely. The fields below this point are read in + as needed, and therefore require care, as different threads may + try to initialize them simultaneously. */ + + /* PC to line number mapping. This is NULL if the values have not + been read. This is (struct line *) -1 if there was an error + reading the values. */ + struct line *lines; + /* Number of entries in lines. */ + size_t lines_count; + /* PC ranges to function. */ + struct function_addrs *function_addrs; + size_t function_addrs_count; +}; + +/* An address range for a compilation unit. This maps a PC value to a + specific compilation unit. Note that we invert the representation + in DWARF: instead of listing the units and attaching a list of + ranges, we list the ranges and have each one point to the unit. + This lets us do a binary search to find the unit. */ + +struct unit_addrs +{ + /* Range is LOW <= PC < HIGH. */ + uintptr_t low; + uintptr_t high; + /* Compilation unit for this address range. */ + struct unit *u; +}; + +/* A growable vector of compilation unit address ranges. */ + +struct unit_addrs_vector +{ + /* Memory. This is an array of struct unit_addrs. */ + struct backtrace_vector vec; + /* Number of address ranges present. */ + size_t count; +}; + +/* A growable vector of compilation unit pointer. */ + +struct unit_vector +{ + struct backtrace_vector vec; + size_t count; +}; + +/* The information we need to map a PC to a file and line. */ + +struct dwarf_data +{ + /* The data for the next file we know about. */ + struct dwarf_data *next; + /* The data for .gnu_debugaltlink. */ + struct dwarf_data *altlink; + /* The base address for this file. */ + uintptr_t base_address; + /* A sorted list of address ranges. */ + struct unit_addrs *addrs; + /* Number of address ranges in list. */ + size_t addrs_count; + /* A sorted list of units. */ + struct unit **units; + /* Number of units in the list. */ + size_t units_count; + /* The unparsed DWARF debug data. */ + struct dwarf_sections dwarf_sections; + /* Whether the data is big-endian or not. */ + int is_bigendian; + /* A vector used for function addresses. We keep this here so that + we can grow the vector as we read more functions. */ + struct function_vector fvec; +}; + +/* Report an error for a DWARF buffer. */ + +static void +dwarf_buf_error (struct dwarf_buf *buf, const char *msg, int errnum) +{ + char b[200]; + + snprintf (b, sizeof b, "%s in %s at %d", + msg, buf->name, (int) (buf->buf - buf->start)); + buf->error_callback (buf->data, b, errnum); +} + +/* Require at least COUNT bytes in BUF. Return 1 if all is well, 0 on + error. */ + +static int +require (struct dwarf_buf *buf, size_t count) +{ + if (buf->left >= count) + return 1; + + if (!buf->reported_underflow) + { + dwarf_buf_error (buf, "DWARF underflow", 0); + buf->reported_underflow = 1; + } + + return 0; +} + +/* Advance COUNT bytes in BUF. Return 1 if all is well, 0 on + error. */ + +static int +advance (struct dwarf_buf *buf, size_t count) +{ + if (!require (buf, count)) + return 0; + buf->buf += count; + buf->left -= count; + return 1; +} + +/* Read one zero-terminated string from BUF and advance past the string. */ + +static const char * +read_string (struct dwarf_buf *buf) +{ + const char *p = (const char *)buf->buf; + size_t len = strnlen (p, buf->left); + + /* - If len == left, we ran out of buffer before finding the zero terminator. + Generate an error by advancing len + 1. + - If len < left, advance by len + 1 to skip past the zero terminator. */ + size_t count = len + 1; + + if (!advance (buf, count)) + return NULL; + + return p; +} + +/* Read one byte from BUF and advance 1 byte. */ + +static unsigned char +read_byte (struct dwarf_buf *buf) +{ + const unsigned char *p = buf->buf; + + if (!advance (buf, 1)) + return 0; + return p[0]; +} + +/* Read a signed char from BUF and advance 1 byte. */ + +static signed char +read_sbyte (struct dwarf_buf *buf) +{ + const unsigned char *p = buf->buf; + + if (!advance (buf, 1)) + return 0; + return (*p ^ 0x80) - 0x80; +} + +/* Read a uint16 from BUF and advance 2 bytes. */ + +static uint16_t +read_uint16 (struct dwarf_buf *buf) +{ + const unsigned char *p = buf->buf; + + if (!advance (buf, 2)) + return 0; + if (buf->is_bigendian) + return ((uint16_t) p[0] << 8) | (uint16_t) p[1]; + else + return ((uint16_t) p[1] << 8) | (uint16_t) p[0]; +} + +/* Read a 24 bit value from BUF and advance 3 bytes. */ + +static uint32_t +read_uint24 (struct dwarf_buf *buf) +{ + const unsigned char *p = buf->buf; + + if (!advance (buf, 3)) + return 0; + if (buf->is_bigendian) + return (((uint32_t) p[0] << 16) | ((uint32_t) p[1] << 8) + | (uint32_t) p[2]); + else + return (((uint32_t) p[2] << 16) | ((uint32_t) p[1] << 8) + | (uint32_t) p[0]); +} + +/* Read a uint32 from BUF and advance 4 bytes. */ + +static uint32_t +read_uint32 (struct dwarf_buf *buf) +{ + const unsigned char *p = buf->buf; + + if (!advance (buf, 4)) + return 0; + if (buf->is_bigendian) + return (((uint32_t) p[0] << 24) | ((uint32_t) p[1] << 16) + | ((uint32_t) p[2] << 8) | (uint32_t) p[3]); + else + return (((uint32_t) p[3] << 24) | ((uint32_t) p[2] << 16) + | ((uint32_t) p[1] << 8) | (uint32_t) p[0]); +} + +/* Read a uint64 from BUF and advance 8 bytes. */ + +static uint64_t +read_uint64 (struct dwarf_buf *buf) +{ + const unsigned char *p = buf->buf; + + if (!advance (buf, 8)) + return 0; + if (buf->is_bigendian) + return (((uint64_t) p[0] << 56) | ((uint64_t) p[1] << 48) + | ((uint64_t) p[2] << 40) | ((uint64_t) p[3] << 32) + | ((uint64_t) p[4] << 24) | ((uint64_t) p[5] << 16) + | ((uint64_t) p[6] << 8) | (uint64_t) p[7]); + else + return (((uint64_t) p[7] << 56) | ((uint64_t) p[6] << 48) + | ((uint64_t) p[5] << 40) | ((uint64_t) p[4] << 32) + | ((uint64_t) p[3] << 24) | ((uint64_t) p[2] << 16) + | ((uint64_t) p[1] << 8) | (uint64_t) p[0]); +} + +/* Read an offset from BUF and advance the appropriate number of + bytes. */ + +static uint64_t +read_offset (struct dwarf_buf *buf, int is_dwarf64) +{ + if (is_dwarf64) + return read_uint64 (buf); + else + return read_uint32 (buf); +} + +/* Read an address from BUF and advance the appropriate number of + bytes. */ + +static uint64_t +read_address (struct dwarf_buf *buf, int addrsize) +{ + switch (addrsize) + { + case 1: + return read_byte (buf); + case 2: + return read_uint16 (buf); + case 4: + return read_uint32 (buf); + case 8: + return read_uint64 (buf); + default: + dwarf_buf_error (buf, "unrecognized address size", 0); + return 0; + } +} + +/* Return whether a value is the highest possible address, given the + address size. */ + +static int +is_highest_address (uint64_t address, int addrsize) +{ + switch (addrsize) + { + case 1: + return address == (unsigned char) -1; + case 2: + return address == (uint16_t) -1; + case 4: + return address == (uint32_t) -1; + case 8: + return address == (uint64_t) -1; + default: + return 0; + } +} + +/* Read an unsigned LEB128 number. */ + +static uint64_t +read_uleb128 (struct dwarf_buf *buf) +{ + uint64_t ret; + unsigned int shift; + int overflow; + unsigned char b; + + ret = 0; + shift = 0; + overflow = 0; + do + { + const unsigned char *p; + + p = buf->buf; + if (!advance (buf, 1)) + return 0; + b = *p; + if (shift < 64) + ret |= ((uint64_t) (b & 0x7f)) << shift; + else if (!overflow) + { + dwarf_buf_error (buf, "LEB128 overflows uint64_t", 0); + overflow = 1; + } + shift += 7; + } + while ((b & 0x80) != 0); + + return ret; +} + +/* Read a signed LEB128 number. */ + +static int64_t +read_sleb128 (struct dwarf_buf *buf) +{ + uint64_t val; + unsigned int shift; + int overflow; + unsigned char b; + + val = 0; + shift = 0; + overflow = 0; + do + { + const unsigned char *p; + + p = buf->buf; + if (!advance (buf, 1)) + return 0; + b = *p; + if (shift < 64) + val |= ((uint64_t) (b & 0x7f)) << shift; + else if (!overflow) + { + dwarf_buf_error (buf, "signed LEB128 overflows uint64_t", 0); + overflow = 1; + } + shift += 7; + } + while ((b & 0x80) != 0); + + if ((b & 0x40) != 0 && shift < 64) + val |= ((uint64_t) -1) << shift; + + return (int64_t) val; +} + +/* Return the length of an LEB128 number. */ + +static size_t +leb128_len (const unsigned char *p) +{ + size_t ret; + + ret = 1; + while ((*p & 0x80) != 0) + { + ++p; + ++ret; + } + return ret; +} + +/* Read initial_length from BUF and advance the appropriate number of bytes. */ + +static uint64_t +read_initial_length (struct dwarf_buf *buf, int *is_dwarf64) +{ + uint64_t len; + + len = read_uint32 (buf); + if (len == 0xffffffff) + { + len = read_uint64 (buf); + *is_dwarf64 = 1; + } + else + *is_dwarf64 = 0; + + return len; +} + +/* Free an abbreviations structure. */ + +static void +free_abbrevs (struct backtrace_state *state, struct abbrevs *abbrevs, + backtrace_error_callback error_callback, void *data) +{ + size_t i; + + for (i = 0; i < abbrevs->num_abbrevs; ++i) + backtrace_free (state, abbrevs->abbrevs[i].attrs, + abbrevs->abbrevs[i].num_attrs * sizeof (struct attr), + error_callback, data); + backtrace_free (state, abbrevs->abbrevs, + abbrevs->num_abbrevs * sizeof (struct abbrev), + error_callback, data); + abbrevs->num_abbrevs = 0; + abbrevs->abbrevs = NULL; +} + +/* Read an attribute value. Returns 1 on success, 0 on failure. If + the value can be represented as a uint64_t, sets *VAL and sets + *IS_VALID to 1. We don't try to store the value of other attribute + forms, because we don't care about them. */ + +static int +read_attribute (enum dwarf_form form, uint64_t implicit_val, + struct dwarf_buf *buf, int is_dwarf64, int version, + int addrsize, const struct dwarf_sections *dwarf_sections, + struct dwarf_data *altlink, struct attr_val *val) +{ + /* Avoid warnings about val.u.FIELD may be used uninitialized if + this function is inlined. The warnings aren't valid but can + occur because the different fields are set and used + conditionally. */ + memset (val, 0, sizeof *val); + + switch (form) + { + case DW_FORM_addr: + val->encoding = ATTR_VAL_ADDRESS; + val->u.uint = read_address (buf, addrsize); + return 1; + case DW_FORM_block2: + val->encoding = ATTR_VAL_BLOCK; + return advance (buf, read_uint16 (buf)); + case DW_FORM_block4: + val->encoding = ATTR_VAL_BLOCK; + return advance (buf, read_uint32 (buf)); + case DW_FORM_data2: + val->encoding = ATTR_VAL_UINT; + val->u.uint = read_uint16 (buf); + return 1; + case DW_FORM_data4: + val->encoding = ATTR_VAL_UINT; + val->u.uint = read_uint32 (buf); + return 1; + case DW_FORM_data8: + val->encoding = ATTR_VAL_UINT; + val->u.uint = read_uint64 (buf); + return 1; + case DW_FORM_data16: + val->encoding = ATTR_VAL_BLOCK; + return advance (buf, 16); + case DW_FORM_string: + val->encoding = ATTR_VAL_STRING; + val->u.string = read_string (buf); + return val->u.string == NULL ? 0 : 1; + case DW_FORM_block: + val->encoding = ATTR_VAL_BLOCK; + return advance (buf, read_uleb128 (buf)); + case DW_FORM_block1: + val->encoding = ATTR_VAL_BLOCK; + return advance (buf, read_byte (buf)); + case DW_FORM_data1: + val->encoding = ATTR_VAL_UINT; + val->u.uint = read_byte (buf); + return 1; + case DW_FORM_flag: + val->encoding = ATTR_VAL_UINT; + val->u.uint = read_byte (buf); + return 1; + case DW_FORM_sdata: + val->encoding = ATTR_VAL_SINT; + val->u.sint = read_sleb128 (buf); + return 1; + case DW_FORM_strp: + { + uint64_t offset; + + offset = read_offset (buf, is_dwarf64); + if (offset >= dwarf_sections->size[DEBUG_STR]) + { + dwarf_buf_error (buf, "DW_FORM_strp out of range", 0); + return 0; + } + val->encoding = ATTR_VAL_STRING; + val->u.string = + (const char *) dwarf_sections->data[DEBUG_STR] + offset; + return 1; + } + case DW_FORM_line_strp: + { + uint64_t offset; + + offset = read_offset (buf, is_dwarf64); + if (offset >= dwarf_sections->size[DEBUG_LINE_STR]) + { + dwarf_buf_error (buf, "DW_FORM_line_strp out of range", 0); + return 0; + } + val->encoding = ATTR_VAL_STRING; + val->u.string = + (const char *) dwarf_sections->data[DEBUG_LINE_STR] + offset; + return 1; + } + case DW_FORM_udata: + val->encoding = ATTR_VAL_UINT; + val->u.uint = read_uleb128 (buf); + return 1; + case DW_FORM_ref_addr: + val->encoding = ATTR_VAL_REF_INFO; + if (version == 2) + val->u.uint = read_address (buf, addrsize); + else + val->u.uint = read_offset (buf, is_dwarf64); + return 1; + case DW_FORM_ref1: + val->encoding = ATTR_VAL_REF_UNIT; + val->u.uint = read_byte (buf); + return 1; + case DW_FORM_ref2: + val->encoding = ATTR_VAL_REF_UNIT; + val->u.uint = read_uint16 (buf); + return 1; + case DW_FORM_ref4: + val->encoding = ATTR_VAL_REF_UNIT; + val->u.uint = read_uint32 (buf); + return 1; + case DW_FORM_ref8: + val->encoding = ATTR_VAL_REF_UNIT; + val->u.uint = read_uint64 (buf); + return 1; + case DW_FORM_ref_udata: + val->encoding = ATTR_VAL_REF_UNIT; + val->u.uint = read_uleb128 (buf); + return 1; + case DW_FORM_indirect: + { + uint64_t form; + + form = read_uleb128 (buf); + if (form == DW_FORM_implicit_const) + { + dwarf_buf_error (buf, + "DW_FORM_indirect to DW_FORM_implicit_const", + 0); + return 0; + } + return read_attribute ((enum dwarf_form) form, 0, buf, is_dwarf64, + version, addrsize, dwarf_sections, altlink, + val); + } + case DW_FORM_sec_offset: + val->encoding = ATTR_VAL_REF_SECTION; + val->u.uint = read_offset (buf, is_dwarf64); + return 1; + case DW_FORM_exprloc: + val->encoding = ATTR_VAL_EXPR; + return advance (buf, read_uleb128 (buf)); + case DW_FORM_flag_present: + val->encoding = ATTR_VAL_UINT; + val->u.uint = 1; + return 1; + case DW_FORM_ref_sig8: + val->encoding = ATTR_VAL_REF_TYPE; + val->u.uint = read_uint64 (buf); + return 1; + case DW_FORM_strx: case DW_FORM_strx1: case DW_FORM_strx2: + case DW_FORM_strx3: case DW_FORM_strx4: + { + uint64_t offset; + + switch (form) + { + case DW_FORM_strx: + offset = read_uleb128 (buf); + break; + case DW_FORM_strx1: + offset = read_byte (buf); + break; + case DW_FORM_strx2: + offset = read_uint16 (buf); + break; + case DW_FORM_strx3: + offset = read_uint24 (buf); + break; + case DW_FORM_strx4: + offset = read_uint32 (buf); + break; + default: + /* This case can't happen. */ + return 0; + } + val->encoding = ATTR_VAL_STRING_INDEX; + val->u.uint = offset; + return 1; + } + case DW_FORM_addrx: case DW_FORM_addrx1: case DW_FORM_addrx2: + case DW_FORM_addrx3: case DW_FORM_addrx4: + { + uint64_t offset; + + switch (form) + { + case DW_FORM_addrx: + offset = read_uleb128 (buf); + break; + case DW_FORM_addrx1: + offset = read_byte (buf); + break; + case DW_FORM_addrx2: + offset = read_uint16 (buf); + break; + case DW_FORM_addrx3: + offset = read_uint24 (buf); + break; + case DW_FORM_addrx4: + offset = read_uint32 (buf); + break; + default: + /* This case can't happen. */ + return 0; + } + val->encoding = ATTR_VAL_ADDRESS_INDEX; + val->u.uint = offset; + return 1; + } + case DW_FORM_ref_sup4: + val->encoding = ATTR_VAL_REF_SECTION; + val->u.uint = read_uint32 (buf); + return 1; + case DW_FORM_ref_sup8: + val->encoding = ATTR_VAL_REF_SECTION; + val->u.uint = read_uint64 (buf); + return 1; + case DW_FORM_implicit_const: + val->encoding = ATTR_VAL_UINT; + val->u.uint = implicit_val; + return 1; + case DW_FORM_loclistx: + /* We don't distinguish this from DW_FORM_sec_offset. It + * shouldn't matter since we don't care about loclists. */ + val->encoding = ATTR_VAL_REF_SECTION; + val->u.uint = read_uleb128 (buf); + return 1; + case DW_FORM_rnglistx: + val->encoding = ATTR_VAL_RNGLISTS_INDEX; + val->u.uint = read_uleb128 (buf); + return 1; + case DW_FORM_GNU_addr_index: + val->encoding = ATTR_VAL_REF_SECTION; + val->u.uint = read_uleb128 (buf); + return 1; + case DW_FORM_GNU_str_index: + val->encoding = ATTR_VAL_REF_SECTION; + val->u.uint = read_uleb128 (buf); + return 1; + case DW_FORM_GNU_ref_alt: + val->u.uint = read_offset (buf, is_dwarf64); + if (altlink == NULL) + { + val->encoding = ATTR_VAL_NONE; + return 1; + } + val->encoding = ATTR_VAL_REF_ALT_INFO; + return 1; + case DW_FORM_strp_sup: case DW_FORM_GNU_strp_alt: + { + uint64_t offset; + + offset = read_offset (buf, is_dwarf64); + if (altlink == NULL) + { + val->encoding = ATTR_VAL_NONE; + return 1; + } + if (offset >= altlink->dwarf_sections.size[DEBUG_STR]) + { + dwarf_buf_error (buf, "DW_FORM_strp_sup out of range", 0); + return 0; + } + val->encoding = ATTR_VAL_STRING; + val->u.string = + (const char *) altlink->dwarf_sections.data[DEBUG_STR] + offset; + return 1; + } + default: + dwarf_buf_error (buf, "unrecognized DWARF form", -1); + return 0; + } +} + +/* If we can determine the value of a string attribute, set *STRING to + point to the string. Return 1 on success, 0 on error. If we don't + know the value, we consider that a success, and we don't change + *STRING. An error is only reported for some sort of out of range + offset. */ + +static int +resolve_string (const struct dwarf_sections *dwarf_sections, int is_dwarf64, + int is_bigendian, uint64_t str_offsets_base, + const struct attr_val *val, + backtrace_error_callback error_callback, void *data, + const char **string) +{ + switch (val->encoding) + { + case ATTR_VAL_STRING: + *string = val->u.string; + return 1; + + case ATTR_VAL_STRING_INDEX: + { + uint64_t offset; + struct dwarf_buf offset_buf; + + offset = val->u.uint * (is_dwarf64 ? 8 : 4) + str_offsets_base; + if (offset + (is_dwarf64 ? 8 : 4) + > dwarf_sections->size[DEBUG_STR_OFFSETS]) + { + error_callback (data, "DW_FORM_strx value out of range", 0); + return 0; + } + + offset_buf.name = ".debug_str_offsets"; + offset_buf.start = dwarf_sections->data[DEBUG_STR_OFFSETS]; + offset_buf.buf = dwarf_sections->data[DEBUG_STR_OFFSETS] + offset; + offset_buf.left = dwarf_sections->size[DEBUG_STR_OFFSETS] - offset; + offset_buf.is_bigendian = is_bigendian; + offset_buf.error_callback = error_callback; + offset_buf.data = data; + offset_buf.reported_underflow = 0; + + offset = read_offset (&offset_buf, is_dwarf64); + if (offset >= dwarf_sections->size[DEBUG_STR]) + { + dwarf_buf_error (&offset_buf, + "DW_FORM_strx offset out of range", + 0); + return 0; + } + *string = (const char *) dwarf_sections->data[DEBUG_STR] + offset; + return 1; + } + + default: + return 1; + } +} + +/* Set *ADDRESS to the real address for a ATTR_VAL_ADDRESS_INDEX. + Return 1 on success, 0 on error. */ + +static int +resolve_addr_index (const struct dwarf_sections *dwarf_sections, + uint64_t addr_base, int addrsize, int is_bigendian, + uint64_t addr_index, + backtrace_error_callback error_callback, void *data, + uintptr_t *address) +{ + uint64_t offset; + struct dwarf_buf addr_buf; + + offset = addr_index * addrsize + addr_base; + if (offset + addrsize > dwarf_sections->size[DEBUG_ADDR]) + { + error_callback (data, "DW_FORM_addrx value out of range", 0); + return 0; + } + + addr_buf.name = ".debug_addr"; + addr_buf.start = dwarf_sections->data[DEBUG_ADDR]; + addr_buf.buf = dwarf_sections->data[DEBUG_ADDR] + offset; + addr_buf.left = dwarf_sections->size[DEBUG_ADDR] - offset; + addr_buf.is_bigendian = is_bigendian; + addr_buf.error_callback = error_callback; + addr_buf.data = data; + addr_buf.reported_underflow = 0; + + *address = (uintptr_t) read_address (&addr_buf, addrsize); + return 1; +} + +/* Compare a unit offset against a unit for bsearch. */ + +static int +units_search (const void *vkey, const void *ventry) +{ + const size_t *key = (const size_t *) vkey; + const struct unit *entry = *((const struct unit *const *) ventry); + size_t offset; + + offset = *key; + if (offset < entry->low_offset) + return -1; + else if (offset >= entry->high_offset) + return 1; + else + return 0; +} + +/* Find a unit in PU containing OFFSET. */ + +static struct unit * +find_unit (struct unit **pu, size_t units_count, size_t offset) +{ + struct unit **u; + u = (struct unit**)bsearch (&offset, pu, units_count, sizeof (struct unit *), units_search); + return u == NULL ? NULL : *u; +} + +/* Compare function_addrs for qsort. When ranges are nested, make the + smallest one sort last. */ + +static int +function_addrs_compare (const void *v1, const void *v2) +{ + const struct function_addrs *a1 = (const struct function_addrs *) v1; + const struct function_addrs *a2 = (const struct function_addrs *) v2; + + if (a1->low < a2->low) + return -1; + if (a1->low > a2->low) + return 1; + if (a1->high < a2->high) + return 1; + if (a1->high > a2->high) + return -1; + return strcmp (a1->function->name, a2->function->name); +} + +/* Compare a PC against a function_addrs for bsearch. We always + allocate an entra entry at the end of the vector, so that this + routine can safely look at the next entry. Note that if there are + multiple ranges containing PC, which one will be returned is + unpredictable. We compensate for that in dwarf_fileline. */ + +static int +function_addrs_search (const void *vkey, const void *ventry) +{ + const uintptr_t *key = (const uintptr_t *) vkey; + const struct function_addrs *entry = (const struct function_addrs *) ventry; + uintptr_t pc; + + pc = *key; + if (pc < entry->low) + return -1; + else if (pc > (entry + 1)->low) + return 1; + else + return 0; +} + +/* Add a new compilation unit address range to a vector. This is + called via add_ranges. Returns 1 on success, 0 on failure. */ + +static int +add_unit_addr (struct backtrace_state *state, void *rdata, + uintptr_t lowpc, uintptr_t highpc, + backtrace_error_callback error_callback, void *data, + void *pvec) +{ + struct unit *u = (struct unit *) rdata; + struct unit_addrs_vector *vec = (struct unit_addrs_vector *) pvec; + struct unit_addrs *p; + + /* Try to merge with the last entry. */ + if (vec->count > 0) + { + p = (struct unit_addrs *) vec->vec.base + (vec->count - 1); + if ((lowpc == p->high || lowpc == p->high + 1) + && u == p->u) + { + if (highpc > p->high) + p->high = highpc; + return 1; + } + } + + p = ((struct unit_addrs *) + backtrace_vector_grow (state, sizeof (struct unit_addrs), + error_callback, data, &vec->vec)); + if (p == NULL) + return 0; + + p->low = lowpc; + p->high = highpc; + p->u = u; + + ++vec->count; + + return 1; +} + +/* Compare unit_addrs for qsort. When ranges are nested, make the + smallest one sort last. */ + +static int +unit_addrs_compare (const void *v1, const void *v2) +{ + const struct unit_addrs *a1 = (const struct unit_addrs *) v1; + const struct unit_addrs *a2 = (const struct unit_addrs *) v2; + + if (a1->low < a2->low) + return -1; + if (a1->low > a2->low) + return 1; + if (a1->high < a2->high) + return 1; + if (a1->high > a2->high) + return -1; + if (a1->u->lineoff < a2->u->lineoff) + return -1; + if (a1->u->lineoff > a2->u->lineoff) + return 1; + return 0; +} + +/* Compare a PC against a unit_addrs for bsearch. We always allocate + an entry entry at the end of the vector, so that this routine can + safely look at the next entry. Note that if there are multiple + ranges containing PC, which one will be returned is unpredictable. + We compensate for that in dwarf_fileline. */ + +static int +unit_addrs_search (const void *vkey, const void *ventry) +{ + const uintptr_t *key = (const uintptr_t *) vkey; + const struct unit_addrs *entry = (const struct unit_addrs *) ventry; + uintptr_t pc; + + pc = *key; + if (pc < entry->low) + return -1; + else if (pc > (entry + 1)->low) + return 1; + else + return 0; +} + +/* Sort the line vector by PC. We want a stable sort here to maintain + the order of lines for the same PC values. Since the sequence is + being sorted in place, their addresses cannot be relied on to + maintain stability. That is the purpose of the index member. */ + +static int +line_compare (const void *v1, const void *v2) +{ + const struct line *ln1 = (const struct line *) v1; + const struct line *ln2 = (const struct line *) v2; + + if (ln1->pc < ln2->pc) + return -1; + else if (ln1->pc > ln2->pc) + return 1; + else if (ln1->idx < ln2->idx) + return -1; + else if (ln1->idx > ln2->idx) + return 1; + else + return 0; +} + +/* Find a PC in a line vector. We always allocate an extra entry at + the end of the lines vector, so that this routine can safely look + at the next entry. Note that when there are multiple mappings for + the same PC value, this will return the last one. */ + +static int +line_search (const void *vkey, const void *ventry) +{ + const uintptr_t *key = (const uintptr_t *) vkey; + const struct line *entry = (const struct line *) ventry; + uintptr_t pc; + + pc = *key; + if (pc < entry->pc) + return -1; + else if (pc >= (entry + 1)->pc) + return 1; + else + return 0; +} + +/* Sort the abbrevs by the abbrev code. This function is passed to + both qsort and bsearch. */ + +static int +abbrev_compare (const void *v1, const void *v2) +{ + const struct abbrev *a1 = (const struct abbrev *) v1; + const struct abbrev *a2 = (const struct abbrev *) v2; + + if (a1->code < a2->code) + return -1; + else if (a1->code > a2->code) + return 1; + else + { + /* This really shouldn't happen. It means there are two + different abbrevs with the same code, and that means we don't + know which one lookup_abbrev should return. */ + return 0; + } +} + +/* Read the abbreviation table for a compilation unit. Returns 1 on + success, 0 on failure. */ + +static int +read_abbrevs (struct backtrace_state *state, uint64_t abbrev_offset, + const unsigned char *dwarf_abbrev, size_t dwarf_abbrev_size, + int is_bigendian, backtrace_error_callback error_callback, + void *data, struct abbrevs *abbrevs) +{ + struct dwarf_buf abbrev_buf; + struct dwarf_buf count_buf; + size_t num_abbrevs; + + abbrevs->num_abbrevs = 0; + abbrevs->abbrevs = NULL; + + if (abbrev_offset >= dwarf_abbrev_size) + { + error_callback (data, "abbrev offset out of range", 0); + return 0; + } + + abbrev_buf.name = ".debug_abbrev"; + abbrev_buf.start = dwarf_abbrev; + abbrev_buf.buf = dwarf_abbrev + abbrev_offset; + abbrev_buf.left = dwarf_abbrev_size - abbrev_offset; + abbrev_buf.is_bigendian = is_bigendian; + abbrev_buf.error_callback = error_callback; + abbrev_buf.data = data; + abbrev_buf.reported_underflow = 0; + + /* Count the number of abbrevs in this list. */ + + count_buf = abbrev_buf; + num_abbrevs = 0; + while (read_uleb128 (&count_buf) != 0) + { + if (count_buf.reported_underflow) + return 0; + ++num_abbrevs; + // Skip tag. + read_uleb128 (&count_buf); + // Skip has_children. + read_byte (&count_buf); + // Skip attributes. + while (read_uleb128 (&count_buf) != 0) + { + uint64_t form; + + form = read_uleb128 (&count_buf); + if ((enum dwarf_form) form == DW_FORM_implicit_const) + read_sleb128 (&count_buf); + } + // Skip form of last attribute. + read_uleb128 (&count_buf); + } + + if (count_buf.reported_underflow) + return 0; + + if (num_abbrevs == 0) + return 1; + + abbrevs->abbrevs = ((struct abbrev *) + backtrace_alloc (state, + num_abbrevs * sizeof (struct abbrev), + error_callback, data)); + if (abbrevs->abbrevs == NULL) + return 0; + abbrevs->num_abbrevs = num_abbrevs; + memset (abbrevs->abbrevs, 0, num_abbrevs * sizeof (struct abbrev)); + + num_abbrevs = 0; + while (1) + { + uint64_t code; + struct abbrev a; + size_t num_attrs; + struct attr *attrs; + + if (abbrev_buf.reported_underflow) + goto fail; + + code = read_uleb128 (&abbrev_buf); + if (code == 0) + break; + + a.code = code; + a.tag = (enum dwarf_tag) read_uleb128 (&abbrev_buf); + a.has_children = read_byte (&abbrev_buf); + + count_buf = abbrev_buf; + num_attrs = 0; + while (read_uleb128 (&count_buf) != 0) + { + uint64_t form; + + ++num_attrs; + form = read_uleb128 (&count_buf); + if ((enum dwarf_form) form == DW_FORM_implicit_const) + read_sleb128 (&count_buf); + } + + if (num_attrs == 0) + { + attrs = NULL; + read_uleb128 (&abbrev_buf); + read_uleb128 (&abbrev_buf); + } + else + { + attrs = ((struct attr *) + backtrace_alloc (state, num_attrs * sizeof *attrs, + error_callback, data)); + if (attrs == NULL) + goto fail; + num_attrs = 0; + while (1) + { + uint64_t name; + uint64_t form; + + name = read_uleb128 (&abbrev_buf); + form = read_uleb128 (&abbrev_buf); + if (name == 0) + break; + attrs[num_attrs].name = (enum dwarf_attribute) name; + attrs[num_attrs].form = (enum dwarf_form) form; + if ((enum dwarf_form) form == DW_FORM_implicit_const) + attrs[num_attrs].val = read_sleb128 (&abbrev_buf); + else + attrs[num_attrs].val = 0; + ++num_attrs; + } + } + + a.num_attrs = num_attrs; + a.attrs = attrs; + + abbrevs->abbrevs[num_abbrevs] = a; + ++num_abbrevs; + } + + backtrace_qsort (abbrevs->abbrevs, abbrevs->num_abbrevs, + sizeof (struct abbrev), abbrev_compare); + + return 1; + + fail: + free_abbrevs (state, abbrevs, error_callback, data); + return 0; +} + +/* Return the abbrev information for an abbrev code. */ + +static const struct abbrev * +lookup_abbrev (struct abbrevs *abbrevs, uint64_t code, + backtrace_error_callback error_callback, void *data) +{ + struct abbrev key; + void *p; + + /* With GCC, where abbrevs are simply numbered in order, we should + be able to just look up the entry. */ + if (code - 1 < abbrevs->num_abbrevs + && abbrevs->abbrevs[code - 1].code == code) + return &abbrevs->abbrevs[code - 1]; + + /* Otherwise we have to search. */ + memset (&key, 0, sizeof key); + key.code = code; + p = bsearch (&key, abbrevs->abbrevs, abbrevs->num_abbrevs, + sizeof (struct abbrev), abbrev_compare); + if (p == NULL) + { + error_callback (data, "invalid abbreviation code", 0); + return NULL; + } + return (const struct abbrev *) p; +} + +/* This struct is used to gather address range information while + reading attributes. We use this while building a mapping from + address ranges to compilation units and then again while mapping + from address ranges to function entries. Normally either + lowpc/highpc is set or ranges is set. */ + +struct pcrange { + uintptr_t lowpc; /* The low PC value. */ + int have_lowpc; /* Whether a low PC value was found. */ + int lowpc_is_addr_index; /* Whether lowpc is in .debug_addr. */ + uintptr_t highpc; /* The high PC value. */ + int have_highpc; /* Whether a high PC value was found. */ + int highpc_is_relative; /* Whether highpc is relative to lowpc. */ + int highpc_is_addr_index; /* Whether highpc is in .debug_addr. */ + uint64_t ranges; /* Offset in ranges section. */ + int have_ranges; /* Whether ranges is valid. */ + int ranges_is_index; /* Whether ranges is DW_FORM_rnglistx. */ +}; + +/* Update PCRANGE from an attribute value. */ + +static void +update_pcrange (const struct attr* attr, const struct attr_val* val, + struct pcrange *pcrange) +{ + switch (attr->name) + { + case DW_AT_low_pc: + if (val->encoding == ATTR_VAL_ADDRESS) + { + pcrange->lowpc = (uintptr_t) val->u.uint; + pcrange->have_lowpc = 1; + } + else if (val->encoding == ATTR_VAL_ADDRESS_INDEX) + { + pcrange->lowpc = (uintptr_t) val->u.uint; + pcrange->have_lowpc = 1; + pcrange->lowpc_is_addr_index = 1; + } + break; + + case DW_AT_high_pc: + if (val->encoding == ATTR_VAL_ADDRESS) + { + pcrange->highpc = (uintptr_t) val->u.uint; + pcrange->have_highpc = 1; + } + else if (val->encoding == ATTR_VAL_UINT) + { + pcrange->highpc = (uintptr_t) val->u.uint; + pcrange->have_highpc = 1; + pcrange->highpc_is_relative = 1; + } + else if (val->encoding == ATTR_VAL_ADDRESS_INDEX) + { + pcrange->highpc = (uintptr_t) val->u.uint; + pcrange->have_highpc = 1; + pcrange->highpc_is_addr_index = 1; + } + break; + + case DW_AT_ranges: + if (val->encoding == ATTR_VAL_UINT + || val->encoding == ATTR_VAL_REF_SECTION) + { + pcrange->ranges = val->u.uint; + pcrange->have_ranges = 1; + } + else if (val->encoding == ATTR_VAL_RNGLISTS_INDEX) + { + pcrange->ranges = val->u.uint; + pcrange->have_ranges = 1; + pcrange->ranges_is_index = 1; + } + break; + + default: + break; + } +} + +/* Call ADD_RANGE for a low/high PC pair. Returns 1 on success, 0 on + error. */ + +static int +add_low_high_range (struct backtrace_state *state, + const struct dwarf_sections *dwarf_sections, + uintptr_t base_address, int is_bigendian, + struct unit *u, const struct pcrange *pcrange, + int (*add_range) (struct backtrace_state *state, + void *rdata, uintptr_t lowpc, + uintptr_t highpc, + backtrace_error_callback error_callback, + void *data, void *vec), + void *rdata, + backtrace_error_callback error_callback, void *data, + void *vec) +{ + uintptr_t lowpc; + uintptr_t highpc; + + lowpc = pcrange->lowpc; + if (pcrange->lowpc_is_addr_index) + { + if (!resolve_addr_index (dwarf_sections, u->addr_base, u->addrsize, + is_bigendian, lowpc, error_callback, data, + &lowpc)) + return 0; + } + + highpc = pcrange->highpc; + if (pcrange->highpc_is_addr_index) + { + if (!resolve_addr_index (dwarf_sections, u->addr_base, u->addrsize, + is_bigendian, highpc, error_callback, data, + &highpc)) + return 0; + } + if (pcrange->highpc_is_relative) + highpc += lowpc; + + /* Add in the base address of the module when recording PC values, + so that we can look up the PC directly. */ + lowpc += base_address; + highpc += base_address; + + return add_range (state, rdata, lowpc, highpc, error_callback, data, vec); +} + +/* Call ADD_RANGE for each range read from .debug_ranges, as used in + DWARF versions 2 through 4. */ + +static int +add_ranges_from_ranges ( + struct backtrace_state *state, + const struct dwarf_sections *dwarf_sections, + uintptr_t base_address, int is_bigendian, + struct unit *u, uintptr_t base, + const struct pcrange *pcrange, + int (*add_range) (struct backtrace_state *state, void *rdata, + uintptr_t lowpc, uintptr_t highpc, + backtrace_error_callback error_callback, void *data, + void *vec), + void *rdata, + backtrace_error_callback error_callback, void *data, + void *vec) +{ + struct dwarf_buf ranges_buf; + + if (pcrange->ranges >= dwarf_sections->size[DEBUG_RANGES]) + { + error_callback (data, "ranges offset out of range", 0); + return 0; + } + + ranges_buf.name = ".debug_ranges"; + ranges_buf.start = dwarf_sections->data[DEBUG_RANGES]; + ranges_buf.buf = dwarf_sections->data[DEBUG_RANGES] + pcrange->ranges; + ranges_buf.left = dwarf_sections->size[DEBUG_RANGES] - pcrange->ranges; + ranges_buf.is_bigendian = is_bigendian; + ranges_buf.error_callback = error_callback; + ranges_buf.data = data; + ranges_buf.reported_underflow = 0; + + while (1) + { + uint64_t low; + uint64_t high; + + if (ranges_buf.reported_underflow) + return 0; + + low = read_address (&ranges_buf, u->addrsize); + high = read_address (&ranges_buf, u->addrsize); + + if (low == 0 && high == 0) + break; + + if (is_highest_address (low, u->addrsize)) + base = (uintptr_t) high; + else + { + if (!add_range (state, rdata, + (uintptr_t) low + base + base_address, + (uintptr_t) high + base + base_address, + error_callback, data, vec)) + return 0; + } + } + + if (ranges_buf.reported_underflow) + return 0; + + return 1; +} + +/* Call ADD_RANGE for each range read from .debug_rnglists, as used in + DWARF version 5. */ + +static int +add_ranges_from_rnglists ( + struct backtrace_state *state, + const struct dwarf_sections *dwarf_sections, + uintptr_t base_address, int is_bigendian, + struct unit *u, uintptr_t base, + const struct pcrange *pcrange, + int (*add_range) (struct backtrace_state *state, void *rdata, + uintptr_t lowpc, uintptr_t highpc, + backtrace_error_callback error_callback, void *data, + void *vec), + void *rdata, + backtrace_error_callback error_callback, void *data, + void *vec) +{ + uint64_t offset; + struct dwarf_buf rnglists_buf; + + if (!pcrange->ranges_is_index) + offset = pcrange->ranges; + else + offset = u->rnglists_base + pcrange->ranges * (u->is_dwarf64 ? 8 : 4); + if (offset >= dwarf_sections->size[DEBUG_RNGLISTS]) + { + error_callback (data, "rnglists offset out of range", 0); + return 0; + } + + rnglists_buf.name = ".debug_rnglists"; + rnglists_buf.start = dwarf_sections->data[DEBUG_RNGLISTS]; + rnglists_buf.buf = dwarf_sections->data[DEBUG_RNGLISTS] + offset; + rnglists_buf.left = dwarf_sections->size[DEBUG_RNGLISTS] - offset; + rnglists_buf.is_bigendian = is_bigendian; + rnglists_buf.error_callback = error_callback; + rnglists_buf.data = data; + rnglists_buf.reported_underflow = 0; + + if (pcrange->ranges_is_index) + { + offset = read_offset (&rnglists_buf, u->is_dwarf64); + offset += u->rnglists_base; + if (offset >= dwarf_sections->size[DEBUG_RNGLISTS]) + { + error_callback (data, "rnglists index offset out of range", 0); + return 0; + } + rnglists_buf.buf = dwarf_sections->data[DEBUG_RNGLISTS] + offset; + rnglists_buf.left = dwarf_sections->size[DEBUG_RNGLISTS] - offset; + } + + while (1) + { + unsigned char rle; + + rle = read_byte (&rnglists_buf); + if (rle == DW_RLE_end_of_list) + break; + switch (rle) + { + case DW_RLE_base_addressx: + { + uint64_t index; + + index = read_uleb128 (&rnglists_buf); + if (!resolve_addr_index (dwarf_sections, u->addr_base, + u->addrsize, is_bigendian, index, + error_callback, data, &base)) + return 0; + } + break; + + case DW_RLE_startx_endx: + { + uint64_t index; + uintptr_t low; + uintptr_t high; + + index = read_uleb128 (&rnglists_buf); + if (!resolve_addr_index (dwarf_sections, u->addr_base, + u->addrsize, is_bigendian, index, + error_callback, data, &low)) + return 0; + index = read_uleb128 (&rnglists_buf); + if (!resolve_addr_index (dwarf_sections, u->addr_base, + u->addrsize, is_bigendian, index, + error_callback, data, &high)) + return 0; + if (!add_range (state, rdata, low + base_address, + high + base_address, error_callback, data, + vec)) + return 0; + } + break; + + case DW_RLE_startx_length: + { + uint64_t index; + uintptr_t low; + uintptr_t length; + + index = read_uleb128 (&rnglists_buf); + if (!resolve_addr_index (dwarf_sections, u->addr_base, + u->addrsize, is_bigendian, index, + error_callback, data, &low)) + return 0; + length = read_uleb128 (&rnglists_buf); + low += base_address; + if (!add_range (state, rdata, low, low + length, + error_callback, data, vec)) + return 0; + } + break; + + case DW_RLE_offset_pair: + { + uint64_t low; + uint64_t high; + + low = read_uleb128 (&rnglists_buf); + high = read_uleb128 (&rnglists_buf); + if (!add_range (state, rdata, low + base + base_address, + high + base + base_address, + error_callback, data, vec)) + return 0; + } + break; + + case DW_RLE_base_address: + base = (uintptr_t) read_address (&rnglists_buf, u->addrsize); + break; + + case DW_RLE_start_end: + { + uintptr_t low; + uintptr_t high; + + low = (uintptr_t) read_address (&rnglists_buf, u->addrsize); + high = (uintptr_t) read_address (&rnglists_buf, u->addrsize); + if (!add_range (state, rdata, low + base_address, + high + base_address, error_callback, data, + vec)) + return 0; + } + break; + + case DW_RLE_start_length: + { + uintptr_t low; + uintptr_t length; + + low = (uintptr_t) read_address (&rnglists_buf, u->addrsize); + length = (uintptr_t) read_uleb128 (&rnglists_buf); + low += base_address; + if (!add_range (state, rdata, low, low + length, + error_callback, data, vec)) + return 0; + } + break; + + default: + dwarf_buf_error (&rnglists_buf, "unrecognized DW_RLE value", -1); + return 0; + } + } + + if (rnglists_buf.reported_underflow) + return 0; + + return 1; +} + +/* Call ADD_RANGE for each lowpc/highpc pair in PCRANGE. RDATA is + passed to ADD_RANGE, and is either a struct unit * or a struct + function *. VEC is the vector we are adding ranges to, and is + either a struct unit_addrs_vector * or a struct function_vector *. + Returns 1 on success, 0 on error. */ + +static int +add_ranges (struct backtrace_state *state, + const struct dwarf_sections *dwarf_sections, + uintptr_t base_address, int is_bigendian, + struct unit *u, uintptr_t base, const struct pcrange *pcrange, + int (*add_range) (struct backtrace_state *state, void *rdata, + uintptr_t lowpc, uintptr_t highpc, + backtrace_error_callback error_callback, + void *data, void *vec), + void *rdata, + backtrace_error_callback error_callback, void *data, + void *vec) +{ + if (pcrange->have_lowpc && pcrange->have_highpc) + return add_low_high_range (state, dwarf_sections, base_address, + is_bigendian, u, pcrange, add_range, rdata, + error_callback, data, vec); + + if (!pcrange->have_ranges) + { + /* Did not find any address ranges to add. */ + return 1; + } + + if (u->version < 5) + return add_ranges_from_ranges (state, dwarf_sections, base_address, + is_bigendian, u, base, pcrange, add_range, + rdata, error_callback, data, vec); + else + return add_ranges_from_rnglists (state, dwarf_sections, base_address, + is_bigendian, u, base, pcrange, add_range, + rdata, error_callback, data, vec); +} + +/* Find the address range covered by a compilation unit, reading from + UNIT_BUF and adding values to U. Returns 1 if all data could be + read, 0 if there is some error. */ + +static int +find_address_ranges (struct backtrace_state *state, uintptr_t base_address, + struct dwarf_buf *unit_buf, + const struct dwarf_sections *dwarf_sections, + int is_bigendian, struct dwarf_data *altlink, + backtrace_error_callback error_callback, void *data, + struct unit *u, struct unit_addrs_vector *addrs, + enum dwarf_tag *unit_tag) +{ + while (unit_buf->left > 0) + { + uint64_t code; + const struct abbrev *abbrev; + struct pcrange pcrange; + struct attr_val name_val; + int have_name_val; + struct attr_val comp_dir_val; + int have_comp_dir_val; + size_t i; + + code = read_uleb128 (unit_buf); + if (code == 0) + return 1; + + abbrev = lookup_abbrev (&u->abbrevs, code, error_callback, data); + if (abbrev == NULL) + return 0; + + if (unit_tag != NULL) + *unit_tag = abbrev->tag; + + memset (&pcrange, 0, sizeof pcrange); + memset (&name_val, 0, sizeof name_val); + have_name_val = 0; + memset (&comp_dir_val, 0, sizeof comp_dir_val); + have_comp_dir_val = 0; + for (i = 0; i < abbrev->num_attrs; ++i) + { + struct attr_val val; + + if (!read_attribute (abbrev->attrs[i].form, abbrev->attrs[i].val, + unit_buf, u->is_dwarf64, u->version, + u->addrsize, dwarf_sections, altlink, &val)) + return 0; + + switch (abbrev->attrs[i].name) + { + case DW_AT_low_pc: case DW_AT_high_pc: case DW_AT_ranges: + update_pcrange (&abbrev->attrs[i], &val, &pcrange); + break; + + case DW_AT_stmt_list: + if ((abbrev->tag == DW_TAG_compile_unit + || abbrev->tag == DW_TAG_skeleton_unit) + && (val.encoding == ATTR_VAL_UINT + || val.encoding == ATTR_VAL_REF_SECTION)) + u->lineoff = val.u.uint; + break; + + case DW_AT_name: + if (abbrev->tag == DW_TAG_compile_unit + || abbrev->tag == DW_TAG_skeleton_unit) + { + name_val = val; + have_name_val = 1; + } + break; + + case DW_AT_comp_dir: + if (abbrev->tag == DW_TAG_compile_unit + || abbrev->tag == DW_TAG_skeleton_unit) + { + comp_dir_val = val; + have_comp_dir_val = 1; + } + break; + + case DW_AT_str_offsets_base: + if ((abbrev->tag == DW_TAG_compile_unit + || abbrev->tag == DW_TAG_skeleton_unit) + && val.encoding == ATTR_VAL_REF_SECTION) + u->str_offsets_base = val.u.uint; + break; + + case DW_AT_addr_base: + if ((abbrev->tag == DW_TAG_compile_unit + || abbrev->tag == DW_TAG_skeleton_unit) + && val.encoding == ATTR_VAL_REF_SECTION) + u->addr_base = val.u.uint; + break; + + case DW_AT_rnglists_base: + if ((abbrev->tag == DW_TAG_compile_unit + || abbrev->tag == DW_TAG_skeleton_unit) + && val.encoding == ATTR_VAL_REF_SECTION) + u->rnglists_base = val.u.uint; + break; + + default: + break; + } + } + + // Resolve strings after we're sure that we have seen + // DW_AT_str_offsets_base. + if (have_name_val) + { + if (!resolve_string (dwarf_sections, u->is_dwarf64, is_bigendian, + u->str_offsets_base, &name_val, + error_callback, data, &u->filename)) + return 0; + } + if (have_comp_dir_val) + { + if (!resolve_string (dwarf_sections, u->is_dwarf64, is_bigendian, + u->str_offsets_base, &comp_dir_val, + error_callback, data, &u->comp_dir)) + return 0; + } + + if (abbrev->tag == DW_TAG_compile_unit + || abbrev->tag == DW_TAG_subprogram + || abbrev->tag == DW_TAG_skeleton_unit) + { + if (!add_ranges (state, dwarf_sections, base_address, + is_bigendian, u, pcrange.lowpc, &pcrange, + add_unit_addr, (void *) u, error_callback, data, + (void *) addrs)) + return 0; + + /* If we found the PC range in the DW_TAG_compile_unit or + DW_TAG_skeleton_unit, we can stop now. */ + if ((abbrev->tag == DW_TAG_compile_unit + || abbrev->tag == DW_TAG_skeleton_unit) + && (pcrange.have_ranges + || (pcrange.have_lowpc && pcrange.have_highpc))) + return 1; + } + + if (abbrev->has_children) + { + if (!find_address_ranges (state, base_address, unit_buf, + dwarf_sections, is_bigendian, altlink, + error_callback, data, u, addrs, NULL)) + return 0; + } + } + + return 1; +} + +/* Build a mapping from address ranges to the compilation units where + the line number information for that range can be found. Returns 1 + on success, 0 on failure. */ + +static int +build_address_map (struct backtrace_state *state, uintptr_t base_address, + const struct dwarf_sections *dwarf_sections, + int is_bigendian, struct dwarf_data *altlink, + backtrace_error_callback error_callback, void *data, + struct unit_addrs_vector *addrs, + struct unit_vector *unit_vec) +{ + struct dwarf_buf info; + struct backtrace_vector units; + size_t units_count; + size_t i; + struct unit **pu; + size_t unit_offset = 0; + struct unit_addrs *pa; + + memset (&addrs->vec, 0, sizeof addrs->vec); + memset (&unit_vec->vec, 0, sizeof unit_vec->vec); + addrs->count = 0; + unit_vec->count = 0; + + /* Read through the .debug_info section. FIXME: Should we use the + .debug_aranges section? gdb and addr2line don't use it, but I'm + not sure why. */ + + info.name = ".debug_info"; + info.start = dwarf_sections->data[DEBUG_INFO]; + info.buf = info.start; + info.left = dwarf_sections->size[DEBUG_INFO]; + info.is_bigendian = is_bigendian; + info.error_callback = error_callback; + info.data = data; + info.reported_underflow = 0; + + memset (&units, 0, sizeof units); + units_count = 0; + + while (info.left > 0) + { + const unsigned char *unit_data_start; + uint64_t len; + int is_dwarf64; + struct dwarf_buf unit_buf; + int version; + int unit_type; + uint64_t abbrev_offset; + int addrsize; + struct unit *u; + enum dwarf_tag unit_tag; + + if (info.reported_underflow) + goto fail; + + unit_data_start = info.buf; + + len = read_initial_length (&info, &is_dwarf64); + unit_buf = info; + unit_buf.left = len; + + if (!advance (&info, len)) + goto fail; + + version = read_uint16 (&unit_buf); + if (version < 2 || version > 5) + { + dwarf_buf_error (&unit_buf, "unrecognized DWARF version", -1); + goto fail; + } + + if (version < 5) + unit_type = 0; + else + { + unit_type = read_byte (&unit_buf); + if (unit_type == DW_UT_type || unit_type == DW_UT_split_type) + { + /* This unit doesn't have anything we need. */ + continue; + } + } + + pu = ((struct unit **) + backtrace_vector_grow (state, sizeof (struct unit *), + error_callback, data, &units)); + if (pu == NULL) + goto fail; + + u = ((struct unit *) + backtrace_alloc (state, sizeof *u, error_callback, data)); + if (u == NULL) + goto fail; + + *pu = u; + ++units_count; + + if (version < 5) + addrsize = 0; /* Set below. */ + else + addrsize = read_byte (&unit_buf); + + memset (&u->abbrevs, 0, sizeof u->abbrevs); + abbrev_offset = read_offset (&unit_buf, is_dwarf64); + if (!read_abbrevs (state, abbrev_offset, + dwarf_sections->data[DEBUG_ABBREV], + dwarf_sections->size[DEBUG_ABBREV], + is_bigendian, error_callback, data, &u->abbrevs)) + goto fail; + + if (version < 5) + addrsize = read_byte (&unit_buf); + + switch (unit_type) + { + case 0: + break; + case DW_UT_compile: case DW_UT_partial: + break; + case DW_UT_skeleton: case DW_UT_split_compile: + read_uint64 (&unit_buf); /* dwo_id */ + break; + default: + break; + } + + u->low_offset = unit_offset; + unit_offset += len + (is_dwarf64 ? 12 : 4); + u->high_offset = unit_offset; + u->unit_data = unit_buf.buf; + u->unit_data_len = unit_buf.left; + u->unit_data_offset = unit_buf.buf - unit_data_start; + u->version = version; + u->is_dwarf64 = is_dwarf64; + u->addrsize = addrsize; + u->filename = NULL; + u->comp_dir = NULL; + u->abs_filename = NULL; + u->lineoff = 0; + u->str_offsets_base = 0; + u->addr_base = 0; + u->rnglists_base = 0; + + /* The actual line number mappings will be read as needed. */ + u->lines = NULL; + u->lines_count = 0; + u->function_addrs = NULL; + u->function_addrs_count = 0; + + if (!find_address_ranges (state, base_address, &unit_buf, dwarf_sections, + is_bigendian, altlink, error_callback, data, + u, addrs, &unit_tag)) + goto fail; + + if (unit_buf.reported_underflow) + goto fail; + } + if (info.reported_underflow) + goto fail; + + /* Add a trailing addrs entry, but don't include it in addrs->count. */ + pa = ((struct unit_addrs *) + backtrace_vector_grow (state, sizeof (struct unit_addrs), + error_callback, data, &addrs->vec)); + if (pa == NULL) + goto fail; + pa->low = 0; + --pa->low; + pa->high = pa->low; + pa->u = NULL; + + unit_vec->vec = units; + unit_vec->count = units_count; + return 1; + + fail: + if (units_count > 0) + { + pu = (struct unit **) units.base; + for (i = 0; i < units_count; i++) + { + free_abbrevs (state, &pu[i]->abbrevs, error_callback, data); + backtrace_free (state, pu[i], sizeof **pu, error_callback, data); + } + backtrace_vector_free (state, &units, error_callback, data); + } + if (addrs->count > 0) + { + backtrace_vector_free (state, &addrs->vec, error_callback, data); + addrs->count = 0; + } + return 0; +} + +/* Add a new mapping to the vector of line mappings that we are + building. Returns 1 on success, 0 on failure. */ + +static int +add_line (struct backtrace_state *state, struct dwarf_data *ddata, + uintptr_t pc, const char *filename, int lineno, + backtrace_error_callback error_callback, void *data, + struct line_vector *vec) +{ + struct line *ln; + + /* If we are adding the same mapping, ignore it. This can happen + when using discriminators. */ + if (vec->count > 0) + { + ln = (struct line *) vec->vec.base + (vec->count - 1); + if (pc == ln->pc && filename == ln->filename && lineno == ln->lineno) + return 1; + } + + ln = ((struct line *) + backtrace_vector_grow (state, sizeof (struct line), error_callback, + data, &vec->vec)); + if (ln == NULL) + return 0; + + /* Add in the base address here, so that we can look up the PC + directly. */ + ln->pc = pc + ddata->base_address; + + ln->filename = filename; + ln->lineno = lineno; + ln->idx = vec->count; + + ++vec->count; + + return 1; +} + +/* Free the line header information. */ + +static void +free_line_header (struct backtrace_state *state, struct line_header *hdr, + backtrace_error_callback error_callback, void *data) +{ + if (hdr->dirs_count != 0) + backtrace_free (state, hdr->dirs, hdr->dirs_count * sizeof (const char *), + error_callback, data); + backtrace_free (state, hdr->filenames, + hdr->filenames_count * sizeof (char *), + error_callback, data); +} + +/* Read the directories and file names for a line header for version + 2, setting fields in HDR. Return 1 on success, 0 on failure. */ + +static int +read_v2_paths (struct backtrace_state *state, struct unit *u, + struct dwarf_buf *hdr_buf, struct line_header *hdr) +{ + const unsigned char *p; + const unsigned char *pend; + size_t i; + + /* Count the number of directory entries. */ + hdr->dirs_count = 0; + p = hdr_buf->buf; + pend = p + hdr_buf->left; + while (p < pend && *p != '\0') + { + p += strnlen((const char *) p, pend - p) + 1; + ++hdr->dirs_count; + } + + /* The index of the first entry in the list of directories is 1. Index 0 is + used for the current directory of the compilation. To simplify index + handling, we set entry 0 to the compilation unit directory. */ + ++hdr->dirs_count; + hdr->dirs = ((const char **) + backtrace_alloc (state, + hdr->dirs_count * sizeof (const char *), + hdr_buf->error_callback, + hdr_buf->data)); + if (hdr->dirs == NULL) + return 0; + + hdr->dirs[0] = u->comp_dir; + i = 1; + while (*hdr_buf->buf != '\0') + { + if (hdr_buf->reported_underflow) + return 0; + + hdr->dirs[i] = read_string (hdr_buf); + if (hdr->dirs[i] == NULL) + return 0; + ++i; + } + if (!advance (hdr_buf, 1)) + return 0; + + /* Count the number of file entries. */ + hdr->filenames_count = 0; + p = hdr_buf->buf; + pend = p + hdr_buf->left; + while (p < pend && *p != '\0') + { + p += strnlen ((const char *) p, pend - p) + 1; + p += leb128_len (p); + p += leb128_len (p); + p += leb128_len (p); + ++hdr->filenames_count; + } + + /* The index of the first entry in the list of file names is 1. Index 0 is + used for the DW_AT_name of the compilation unit. To simplify index + handling, we set entry 0 to the compilation unit file name. */ + ++hdr->filenames_count; + hdr->filenames = ((const char **) + backtrace_alloc (state, + hdr->filenames_count * sizeof (char *), + hdr_buf->error_callback, + hdr_buf->data)); + if (hdr->filenames == NULL) + return 0; + hdr->filenames[0] = u->filename; + i = 1; + while (*hdr_buf->buf != '\0') + { + const char *filename; + uint64_t dir_index; + + if (hdr_buf->reported_underflow) + return 0; + + filename = read_string (hdr_buf); + if (filename == NULL) + return 0; + dir_index = read_uleb128 (hdr_buf); + if (IS_ABSOLUTE_PATH (filename) + || (dir_index < hdr->dirs_count && hdr->dirs[dir_index] == NULL)) + hdr->filenames[i] = filename; + else + { + const char *dir; + size_t dir_len; + size_t filename_len; + char *s; + + if (dir_index < hdr->dirs_count) + dir = hdr->dirs[dir_index]; + else + { + dwarf_buf_error (hdr_buf, + ("invalid directory index in " + "line number program header"), + 0); + return 0; + } + dir_len = strlen (dir); + filename_len = strlen (filename); + s = ((char *) backtrace_alloc (state, dir_len + filename_len + 2, + hdr_buf->error_callback, + hdr_buf->data)); + if (s == NULL) + return 0; + memcpy (s, dir, dir_len); + /* FIXME: If we are on a DOS-based file system, and the + directory or the file name use backslashes, then we + should use a backslash here. */ + s[dir_len] = '/'; + memcpy (s + dir_len + 1, filename, filename_len + 1); + hdr->filenames[i] = s; + } + + /* Ignore the modification time and size. */ + read_uleb128 (hdr_buf); + read_uleb128 (hdr_buf); + + ++i; + } + + return 1; +} + +/* Read a single version 5 LNCT entry for a directory or file name in a + line header. Sets *STRING to the resulting name, ignoring other + data. Return 1 on success, 0 on failure. */ + +static int +read_lnct (struct backtrace_state *state, struct dwarf_data *ddata, + struct unit *u, struct dwarf_buf *hdr_buf, + const struct line_header *hdr, size_t formats_count, + const struct line_header_format *formats, const char **string) +{ + size_t i; + const char *dir; + const char *path; + + dir = NULL; + path = NULL; + for (i = 0; i < formats_count; i++) + { + struct attr_val val; + + if (!read_attribute (formats[i].form, 0, hdr_buf, u->is_dwarf64, + u->version, hdr->addrsize, &ddata->dwarf_sections, + ddata->altlink, &val)) + return 0; + switch (formats[i].lnct) + { + case DW_LNCT_path: + if (!resolve_string (&ddata->dwarf_sections, u->is_dwarf64, + ddata->is_bigendian, u->str_offsets_base, + &val, hdr_buf->error_callback, hdr_buf->data, + &path)) + return 0; + break; + case DW_LNCT_directory_index: + if (val.encoding == ATTR_VAL_UINT) + { + if (val.u.uint >= hdr->dirs_count) + { + dwarf_buf_error (hdr_buf, + ("invalid directory index in " + "line number program header"), + 0); + return 0; + } + dir = hdr->dirs[val.u.uint]; + } + break; + default: + /* We don't care about timestamps or sizes or hashes. */ + break; + } + } + + if (path == NULL) + { + dwarf_buf_error (hdr_buf, + "missing file name in line number program header", + 0); + return 0; + } + + if (dir == NULL) + *string = path; + else + { + size_t dir_len; + size_t path_len; + char *s; + + dir_len = strlen (dir); + path_len = strlen (path); + s = (char *) backtrace_alloc (state, dir_len + path_len + 2, + hdr_buf->error_callback, hdr_buf->data); + if (s == NULL) + return 0; + memcpy (s, dir, dir_len); + /* FIXME: If we are on a DOS-based file system, and the + directory or the path name use backslashes, then we should + use a backslash here. */ + s[dir_len] = '/'; + memcpy (s + dir_len + 1, path, path_len + 1); + *string = s; + } + + return 1; +} + +/* Read a set of DWARF 5 line header format entries, setting *PCOUNT + and *PPATHS. Return 1 on success, 0 on failure. */ + +static int +read_line_header_format_entries (struct backtrace_state *state, + struct dwarf_data *ddata, + struct unit *u, + struct dwarf_buf *hdr_buf, + struct line_header *hdr, + size_t *pcount, + const char ***ppaths) +{ + size_t formats_count; + struct line_header_format *formats; + size_t paths_count; + const char **paths; + size_t i; + int ret; + + formats_count = read_byte (hdr_buf); + if (formats_count == 0) + formats = NULL; + else + { + formats = ((struct line_header_format *) + backtrace_alloc (state, + (formats_count + * sizeof (struct line_header_format)), + hdr_buf->error_callback, + hdr_buf->data)); + if (formats == NULL) + return 0; + + for (i = 0; i < formats_count; i++) + { + formats[i].lnct = (int) read_uleb128(hdr_buf); + formats[i].form = (enum dwarf_form) read_uleb128 (hdr_buf); + } + } + + paths_count = read_uleb128 (hdr_buf); + if (paths_count == 0) + { + *pcount = 0; + *ppaths = NULL; + ret = 1; + goto exit; + } + + paths = ((const char **) + backtrace_alloc (state, paths_count * sizeof (const char *), + hdr_buf->error_callback, hdr_buf->data)); + if (paths == NULL) + { + ret = 0; + goto exit; + } + for (i = 0; i < paths_count; i++) + { + if (!read_lnct (state, ddata, u, hdr_buf, hdr, formats_count, + formats, &paths[i])) + { + backtrace_free (state, paths, + paths_count * sizeof (const char *), + hdr_buf->error_callback, hdr_buf->data); + ret = 0; + goto exit; + } + } + + *pcount = paths_count; + *ppaths = paths; + + ret = 1; + + exit: + if (formats != NULL) + backtrace_free (state, formats, + formats_count * sizeof (struct line_header_format), + hdr_buf->error_callback, hdr_buf->data); + + return ret; +} + +/* Read the line header. Return 1 on success, 0 on failure. */ + +static int +read_line_header (struct backtrace_state *state, struct dwarf_data *ddata, + struct unit *u, int is_dwarf64, struct dwarf_buf *line_buf, + struct line_header *hdr) +{ + uint64_t hdrlen; + struct dwarf_buf hdr_buf; + + hdr->version = read_uint16 (line_buf); + if (hdr->version < 2 || hdr->version > 5) + { + dwarf_buf_error (line_buf, "unsupported line number version", -1); + return 0; + } + + if (hdr->version < 5) + hdr->addrsize = u->addrsize; + else + { + hdr->addrsize = read_byte (line_buf); + /* We could support a non-zero segment_selector_size but I doubt + we'll ever see it. */ + if (read_byte (line_buf) != 0) + { + dwarf_buf_error (line_buf, + "non-zero segment_selector_size not supported", + -1); + return 0; + } + } + + hdrlen = read_offset (line_buf, is_dwarf64); + + hdr_buf = *line_buf; + hdr_buf.left = hdrlen; + + if (!advance (line_buf, hdrlen)) + return 0; + + hdr->min_insn_len = read_byte (&hdr_buf); + if (hdr->version < 4) + hdr->max_ops_per_insn = 1; + else + hdr->max_ops_per_insn = read_byte (&hdr_buf); + + /* We don't care about default_is_stmt. */ + read_byte (&hdr_buf); + + hdr->line_base = read_sbyte (&hdr_buf); + hdr->line_range = read_byte (&hdr_buf); + + hdr->opcode_base = read_byte (&hdr_buf); + hdr->opcode_lengths = hdr_buf.buf; + if (!advance (&hdr_buf, hdr->opcode_base - 1)) + return 0; + + if (hdr->version < 5) + { + if (!read_v2_paths (state, u, &hdr_buf, hdr)) + return 0; + } + else + { + if (!read_line_header_format_entries (state, ddata, u, &hdr_buf, hdr, + &hdr->dirs_count, + &hdr->dirs)) + return 0; + if (!read_line_header_format_entries (state, ddata, u, &hdr_buf, hdr, + &hdr->filenames_count, + &hdr->filenames)) + return 0; + } + + if (hdr_buf.reported_underflow) + return 0; + + return 1; +} + +/* Read the line program, adding line mappings to VEC. Return 1 on + success, 0 on failure. */ + +static int +read_line_program (struct backtrace_state *state, struct dwarf_data *ddata, + const struct line_header *hdr, struct dwarf_buf *line_buf, + struct line_vector *vec) +{ + uint64_t address; + unsigned int op_index; + const char *reset_filename; + const char *filename; + int lineno; + + address = 0; + op_index = 0; + if (hdr->filenames_count > 1) + reset_filename = hdr->filenames[1]; + else + reset_filename = ""; + filename = reset_filename; + lineno = 1; + while (line_buf->left > 0) + { + unsigned int op; + + op = read_byte (line_buf); + if (op >= hdr->opcode_base) + { + unsigned int advance; + + /* Special opcode. */ + op -= hdr->opcode_base; + advance = op / hdr->line_range; + address += (hdr->min_insn_len * (op_index + advance) + / hdr->max_ops_per_insn); + op_index = (op_index + advance) % hdr->max_ops_per_insn; + lineno += hdr->line_base + (int) (op % hdr->line_range); + add_line (state, ddata, address, filename, lineno, + line_buf->error_callback, line_buf->data, vec); + } + else if (op == DW_LNS_extended_op) + { + uint64_t len; + + len = read_uleb128 (line_buf); + op = read_byte (line_buf); + switch (op) + { + case DW_LNE_end_sequence: + /* FIXME: Should we mark the high PC here? It seems + that we already have that information from the + compilation unit. */ + address = 0; + op_index = 0; + filename = reset_filename; + lineno = 1; + break; + case DW_LNE_set_address: + address = read_address (line_buf, hdr->addrsize); + break; + case DW_LNE_define_file: + { + const char *f; + unsigned int dir_index; + + f = read_string (line_buf); + if (f == NULL) + return 0; + dir_index = read_uleb128 (line_buf); + /* Ignore that time and length. */ + read_uleb128 (line_buf); + read_uleb128 (line_buf); + if (IS_ABSOLUTE_PATH (f)) + filename = f; + else + { + const char *dir; + size_t dir_len; + size_t f_len; + char *p; + + if (dir_index < hdr->dirs_count) + dir = hdr->dirs[dir_index]; + else + { + dwarf_buf_error (line_buf, + ("invalid directory index " + "in line number program"), + 0); + return 0; + } + dir_len = strlen (dir); + f_len = strlen (f); + p = ((char *) + backtrace_alloc (state, dir_len + f_len + 2, + line_buf->error_callback, + line_buf->data)); + if (p == NULL) + return 0; + memcpy (p, dir, dir_len); + /* FIXME: If we are on a DOS-based file system, + and the directory or the file name use + backslashes, then we should use a backslash + here. */ + p[dir_len] = '/'; + memcpy (p + dir_len + 1, f, f_len + 1); + filename = p; + } + } + break; + case DW_LNE_set_discriminator: + /* We don't care about discriminators. */ + read_uleb128 (line_buf); + break; + default: + if (!advance (line_buf, len - 1)) + return 0; + break; + } + } + else + { + switch (op) + { + case DW_LNS_copy: + add_line (state, ddata, address, filename, lineno, + line_buf->error_callback, line_buf->data, vec); + break; + case DW_LNS_advance_pc: + { + uint64_t advance; + + advance = read_uleb128 (line_buf); + address += (hdr->min_insn_len * (op_index + advance) + / hdr->max_ops_per_insn); + op_index = (op_index + advance) % hdr->max_ops_per_insn; + } + break; + case DW_LNS_advance_line: + lineno += (int) read_sleb128 (line_buf); + break; + case DW_LNS_set_file: + { + uint64_t fileno; + + fileno = read_uleb128 (line_buf); + if (fileno >= hdr->filenames_count) + { + dwarf_buf_error (line_buf, + ("invalid file number in " + "line number program"), + 0); + return 0; + } + filename = hdr->filenames[fileno]; + } + break; + case DW_LNS_set_column: + read_uleb128 (line_buf); + break; + case DW_LNS_negate_stmt: + break; + case DW_LNS_set_basic_block: + break; + case DW_LNS_const_add_pc: + { + unsigned int advance; + + op = 255 - hdr->opcode_base; + advance = op / hdr->line_range; + address += (hdr->min_insn_len * (op_index + advance) + / hdr->max_ops_per_insn); + op_index = (op_index + advance) % hdr->max_ops_per_insn; + } + break; + case DW_LNS_fixed_advance_pc: + address += read_uint16 (line_buf); + op_index = 0; + break; + case DW_LNS_set_prologue_end: + break; + case DW_LNS_set_epilogue_begin: + break; + case DW_LNS_set_isa: + read_uleb128 (line_buf); + break; + default: + { + unsigned int i; + + for (i = hdr->opcode_lengths[op - 1]; i > 0; --i) + read_uleb128 (line_buf); + } + break; + } + } + } + + return 1; +} + +/* Read the line number information for a compilation unit. Returns 1 + on success, 0 on failure. */ + +static int +read_line_info (struct backtrace_state *state, struct dwarf_data *ddata, + backtrace_error_callback error_callback, void *data, + struct unit *u, struct line_header *hdr, struct line **lines, + size_t *lines_count) +{ + struct line_vector vec; + struct dwarf_buf line_buf; + uint64_t len; + int is_dwarf64; + struct line *ln; + + memset (&vec.vec, 0, sizeof vec.vec); + vec.count = 0; + + memset (hdr, 0, sizeof *hdr); + + if (u->lineoff != (off_t) (size_t) u->lineoff + || (size_t) u->lineoff >= ddata->dwarf_sections.size[DEBUG_LINE]) + { + error_callback (data, "unit line offset out of range", 0); + goto fail; + } + + line_buf.name = ".debug_line"; + line_buf.start = ddata->dwarf_sections.data[DEBUG_LINE]; + line_buf.buf = ddata->dwarf_sections.data[DEBUG_LINE] + u->lineoff; + line_buf.left = ddata->dwarf_sections.size[DEBUG_LINE] - u->lineoff; + line_buf.is_bigendian = ddata->is_bigendian; + line_buf.error_callback = error_callback; + line_buf.data = data; + line_buf.reported_underflow = 0; + + len = read_initial_length (&line_buf, &is_dwarf64); + line_buf.left = len; + + if (!read_line_header (state, ddata, u, is_dwarf64, &line_buf, hdr)) + goto fail; + + if (!read_line_program (state, ddata, hdr, &line_buf, &vec)) + goto fail; + + if (line_buf.reported_underflow) + goto fail; + + if (vec.count == 0) + { + /* This is not a failure in the sense of a generating an error, + but it is a failure in that sense that we have no useful + information. */ + goto fail; + } + + /* Allocate one extra entry at the end. */ + ln = ((struct line *) + backtrace_vector_grow (state, sizeof (struct line), error_callback, + data, &vec.vec)); + if (ln == NULL) + goto fail; + ln->pc = (uintptr_t) -1; + ln->filename = NULL; + ln->lineno = 0; + ln->idx = 0; + + if (!backtrace_vector_release (state, &vec.vec, error_callback, data)) + goto fail; + + ln = (struct line *) vec.vec.base; + backtrace_qsort (ln, vec.count, sizeof (struct line), line_compare); + + *lines = ln; + *lines_count = vec.count; + + return 1; + + fail: + backtrace_vector_free (state, &vec.vec, error_callback, data); + free_line_header (state, hdr, error_callback, data); + *lines = (struct line *) (uintptr_t) -1; + *lines_count = 0; + return 0; +} + +static const char *read_referenced_name (struct dwarf_data *, struct unit *, + uint64_t, backtrace_error_callback, + void *); + +/* Read the name of a function from a DIE referenced by ATTR with VAL. */ + +static const char * +read_referenced_name_from_attr (struct dwarf_data *ddata, struct unit *u, + struct attr *attr, struct attr_val *val, + backtrace_error_callback error_callback, + void *data) +{ + switch (attr->name) + { + case DW_AT_abstract_origin: + case DW_AT_specification: + break; + default: + return NULL; + } + + if (attr->form == DW_FORM_ref_sig8) + return NULL; + + if (val->encoding == ATTR_VAL_REF_INFO) + { + struct unit *unit + = find_unit (ddata->units, ddata->units_count, + val->u.uint); + if (unit == NULL) + return NULL; + + uint64_t offset = val->u.uint - unit->low_offset; + return read_referenced_name (ddata, unit, offset, error_callback, data); + } + + if (val->encoding == ATTR_VAL_UINT + || val->encoding == ATTR_VAL_REF_UNIT) + return read_referenced_name (ddata, u, val->u.uint, error_callback, data); + + if (val->encoding == ATTR_VAL_REF_ALT_INFO) + { + struct unit *alt_unit + = find_unit (ddata->altlink->units, ddata->altlink->units_count, + val->u.uint); + if (alt_unit == NULL) + return NULL; + + uint64_t offset = val->u.uint - alt_unit->low_offset; + return read_referenced_name (ddata->altlink, alt_unit, offset, + error_callback, data); + } + + return NULL; +} + +/* Read the name of a function from a DIE referenced by a + DW_AT_abstract_origin or DW_AT_specification tag. OFFSET is within + the same compilation unit. */ + +static const char * +read_referenced_name (struct dwarf_data *ddata, struct unit *u, + uint64_t offset, backtrace_error_callback error_callback, + void *data) +{ + struct dwarf_buf unit_buf; + uint64_t code; + const struct abbrev *abbrev; + const char *ret; + size_t i; + + /* OFFSET is from the start of the data for this compilation unit. + U->unit_data is the data, but it starts U->unit_data_offset bytes + from the beginning. */ + + if (offset < u->unit_data_offset + || offset - u->unit_data_offset >= u->unit_data_len) + { + error_callback (data, + "abstract origin or specification out of range", + 0); + return NULL; + } + + offset -= u->unit_data_offset; + + unit_buf.name = ".debug_info"; + unit_buf.start = ddata->dwarf_sections.data[DEBUG_INFO]; + unit_buf.buf = u->unit_data + offset; + unit_buf.left = u->unit_data_len - offset; + unit_buf.is_bigendian = ddata->is_bigendian; + unit_buf.error_callback = error_callback; + unit_buf.data = data; + unit_buf.reported_underflow = 0; + + code = read_uleb128 (&unit_buf); + if (code == 0) + { + dwarf_buf_error (&unit_buf, + "invalid abstract origin or specification", + 0); + return NULL; + } + + abbrev = lookup_abbrev (&u->abbrevs, code, error_callback, data); + if (abbrev == NULL) + return NULL; + + ret = NULL; + for (i = 0; i < abbrev->num_attrs; ++i) + { + struct attr_val val; + + if (!read_attribute (abbrev->attrs[i].form, abbrev->attrs[i].val, + &unit_buf, u->is_dwarf64, u->version, u->addrsize, + &ddata->dwarf_sections, ddata->altlink, &val)) + return NULL; + + switch (abbrev->attrs[i].name) + { + case DW_AT_name: + /* Third name preference: don't override. A name we found in some + other way, will normally be more useful -- e.g., this name is + normally not mangled. */ + if (ret != NULL) + break; + if (!resolve_string (&ddata->dwarf_sections, u->is_dwarf64, + ddata->is_bigendian, u->str_offsets_base, + &val, error_callback, data, &ret)) + return NULL; + break; + + case DW_AT_linkage_name: + case DW_AT_MIPS_linkage_name: + /* First name preference: override all. */ + { + const char *s; + + s = NULL; + if (!resolve_string (&ddata->dwarf_sections, u->is_dwarf64, + ddata->is_bigendian, u->str_offsets_base, + &val, error_callback, data, &s)) + return NULL; + if (s != NULL) + return s; + } + break; + + case DW_AT_specification: + /* Second name preference: override DW_AT_name, don't override + DW_AT_linkage_name. */ + { + const char *name; + + name = read_referenced_name_from_attr (ddata, u, &abbrev->attrs[i], + &val, error_callback, data); + if (name != NULL) + ret = name; + } + break; + + default: + break; + } + } + + return ret; +} + +/* Add a range to a unit that maps to a function. This is called via + add_ranges. Returns 1 on success, 0 on error. */ + +static int +add_function_range (struct backtrace_state *state, void *rdata, + uintptr_t lowpc, uintptr_t highpc, + backtrace_error_callback error_callback, void *data, + void *pvec) +{ + struct function *function = (struct function *) rdata; + struct function_vector *vec = (struct function_vector *) pvec; + struct function_addrs *p; + + if (vec->count > 0) + { + p = (struct function_addrs *) vec->vec.base + (vec->count - 1); + if ((lowpc == p->high || lowpc == p->high + 1) + && function == p->function) + { + if (highpc > p->high) + p->high = highpc; + return 1; + } + } + + p = ((struct function_addrs *) + backtrace_vector_grow (state, sizeof (struct function_addrs), + error_callback, data, &vec->vec)); + if (p == NULL) + return 0; + + p->low = lowpc; + p->high = highpc; + p->function = function; + + ++vec->count; + + return 1; +} + +/* Read one entry plus all its children. Add function addresses to + VEC. Returns 1 on success, 0 on error. */ + +static int +read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata, + struct unit *u, uintptr_t base, struct dwarf_buf *unit_buf, + const struct line_header *lhdr, + backtrace_error_callback error_callback, void *data, + struct function_vector *vec_function, + struct function_vector *vec_inlined) +{ + while (unit_buf->left > 0) + { + uint64_t code; + const struct abbrev *abbrev; + int is_function; + struct function *function; + struct function_vector *vec; + size_t i; + struct pcrange pcrange; + int have_linkage_name; + + code = read_uleb128 (unit_buf); + if (code == 0) + return 1; + + abbrev = lookup_abbrev (&u->abbrevs, code, error_callback, data); + if (abbrev == NULL) + return 0; + + is_function = (abbrev->tag == DW_TAG_subprogram + || abbrev->tag == DW_TAG_entry_point + || abbrev->tag == DW_TAG_inlined_subroutine); + + if (abbrev->tag == DW_TAG_inlined_subroutine) + vec = vec_inlined; + else + vec = vec_function; + + function = NULL; + if (is_function) + { + function = ((struct function *) + backtrace_alloc (state, sizeof *function, + error_callback, data)); + if (function == NULL) + return 0; + memset (function, 0, sizeof *function); + } + + memset (&pcrange, 0, sizeof pcrange); + have_linkage_name = 0; + for (i = 0; i < abbrev->num_attrs; ++i) + { + struct attr_val val; + + if (!read_attribute (abbrev->attrs[i].form, abbrev->attrs[i].val, + unit_buf, u->is_dwarf64, u->version, + u->addrsize, &ddata->dwarf_sections, + ddata->altlink, &val)) + return 0; + + /* The compile unit sets the base address for any address + ranges in the function entries. */ + if ((abbrev->tag == DW_TAG_compile_unit + || abbrev->tag == DW_TAG_skeleton_unit) + && abbrev->attrs[i].name == DW_AT_low_pc) + { + if (val.encoding == ATTR_VAL_ADDRESS) + base = (uintptr_t) val.u.uint; + else if (val.encoding == ATTR_VAL_ADDRESS_INDEX) + { + if (!resolve_addr_index (&ddata->dwarf_sections, + u->addr_base, u->addrsize, + ddata->is_bigendian, val.u.uint, + error_callback, data, &base)) + return 0; + } + } + + if (is_function) + { + switch (abbrev->attrs[i].name) + { + case DW_AT_call_file: + if (val.encoding == ATTR_VAL_UINT) + { + if (val.u.uint >= lhdr->filenames_count) + { + dwarf_buf_error (unit_buf, + ("invalid file number in " + "DW_AT_call_file attribute"), + 0); + return 0; + } + function->caller_filename = lhdr->filenames[val.u.uint]; + } + break; + + case DW_AT_call_line: + if (val.encoding == ATTR_VAL_UINT) + function->caller_lineno = val.u.uint; + break; + + case DW_AT_abstract_origin: + case DW_AT_specification: + /* Second name preference: override DW_AT_name, don't override + DW_AT_linkage_name. */ + if (have_linkage_name) + break; + { + const char *name; + + name + = read_referenced_name_from_attr (ddata, u, + &abbrev->attrs[i], &val, + error_callback, data); + if (name != NULL) + function->name = name; + } + break; + + case DW_AT_name: + /* Third name preference: don't override. */ + if (function->name != NULL) + break; + if (!resolve_string (&ddata->dwarf_sections, u->is_dwarf64, + ddata->is_bigendian, + u->str_offsets_base, &val, + error_callback, data, &function->name)) + return 0; + break; + + case DW_AT_linkage_name: + case DW_AT_MIPS_linkage_name: + /* First name preference: override all. */ + { + const char *s; + + s = NULL; + if (!resolve_string (&ddata->dwarf_sections, u->is_dwarf64, + ddata->is_bigendian, + u->str_offsets_base, &val, + error_callback, data, &s)) + return 0; + if (s != NULL) + { + function->name = s; + have_linkage_name = 1; + } + } + break; + + case DW_AT_low_pc: case DW_AT_high_pc: case DW_AT_ranges: + update_pcrange (&abbrev->attrs[i], &val, &pcrange); + break; + + default: + break; + } + } + } + + /* If we couldn't find a name for the function, we have no use + for it. */ + if (is_function && function->name == NULL) + { + backtrace_free (state, function, sizeof *function, + error_callback, data); + is_function = 0; + } + + if (is_function) + { + if (pcrange.have_ranges + || (pcrange.have_lowpc && pcrange.have_highpc)) + { + if (!add_ranges (state, &ddata->dwarf_sections, + ddata->base_address, ddata->is_bigendian, + u, base, &pcrange, add_function_range, + (void *) function, error_callback, data, + (void *) vec)) + return 0; + } + else + { + backtrace_free (state, function, sizeof *function, + error_callback, data); + is_function = 0; + } + } + + if (abbrev->has_children) + { + if (!is_function) + { + if (!read_function_entry (state, ddata, u, base, unit_buf, lhdr, + error_callback, data, vec_function, + vec_inlined)) + return 0; + } + else + { + struct function_vector fvec; + + /* Gather any information for inlined functions in + FVEC. */ + + memset (&fvec, 0, sizeof fvec); + + if (!read_function_entry (state, ddata, u, base, unit_buf, lhdr, + error_callback, data, vec_function, + &fvec)) + return 0; + + if (fvec.count > 0) + { + struct function_addrs *p; + struct function_addrs *faddrs; + + /* Allocate a trailing entry, but don't include it + in fvec.count. */ + p = ((struct function_addrs *) + backtrace_vector_grow (state, + sizeof (struct function_addrs), + error_callback, data, + &fvec.vec)); + if (p == NULL) + return 0; + p->low = 0; + --p->low; + p->high = p->low; + p->function = NULL; + + if (!backtrace_vector_release (state, &fvec.vec, + error_callback, data)) + return 0; + + faddrs = (struct function_addrs *) fvec.vec.base; + backtrace_qsort (faddrs, fvec.count, + sizeof (struct function_addrs), + function_addrs_compare); + + function->function_addrs = faddrs; + function->function_addrs_count = fvec.count; + } + } + } + } + + return 1; +} + +/* Read function name information for a compilation unit. We look + through the whole unit looking for function tags. */ + +static void +read_function_info (struct backtrace_state *state, struct dwarf_data *ddata, + const struct line_header *lhdr, + backtrace_error_callback error_callback, void *data, + struct unit *u, struct function_vector *fvec, + struct function_addrs **ret_addrs, + size_t *ret_addrs_count) +{ + struct function_vector lvec; + struct function_vector *pfvec; + struct dwarf_buf unit_buf; + struct function_addrs *p; + struct function_addrs *addrs; + size_t addrs_count; + + /* Use FVEC if it is not NULL. Otherwise use our own vector. */ + if (fvec != NULL) + pfvec = fvec; + else + { + memset (&lvec, 0, sizeof lvec); + pfvec = &lvec; + } + + unit_buf.name = ".debug_info"; + unit_buf.start = ddata->dwarf_sections.data[DEBUG_INFO]; + unit_buf.buf = u->unit_data; + unit_buf.left = u->unit_data_len; + unit_buf.is_bigendian = ddata->is_bigendian; + unit_buf.error_callback = error_callback; + unit_buf.data = data; + unit_buf.reported_underflow = 0; + + while (unit_buf.left > 0) + { + if (!read_function_entry (state, ddata, u, 0, &unit_buf, lhdr, + error_callback, data, pfvec, pfvec)) + return; + } + + if (pfvec->count == 0) + return; + + /* Allocate a trailing entry, but don't include it in + pfvec->count. */ + p = ((struct function_addrs *) + backtrace_vector_grow (state, sizeof (struct function_addrs), + error_callback, data, &pfvec->vec)); + if (p == NULL) + return; + p->low = 0; + --p->low; + p->high = p->low; + p->function = NULL; + + addrs_count = pfvec->count; + + if (fvec == NULL) + { + if (!backtrace_vector_release (state, &lvec.vec, error_callback, data)) + return; + addrs = (struct function_addrs *) pfvec->vec.base; + } + else + { + /* Finish this list of addresses, but leave the remaining space in + the vector available for the next function unit. */ + addrs = ((struct function_addrs *) + backtrace_vector_finish (state, &fvec->vec, + error_callback, data)); + if (addrs == NULL) + return; + fvec->count = 0; + } + + backtrace_qsort (addrs, addrs_count, sizeof (struct function_addrs), + function_addrs_compare); + + *ret_addrs = addrs; + *ret_addrs_count = addrs_count; +} + +/* See if PC is inlined in FUNCTION. If it is, print out the inlined + information, and update FILENAME and LINENO for the caller. + Returns whatever CALLBACK returns, or 0 to keep going. */ + +static int +report_inlined_functions (uintptr_t pc, struct function *function, const char* comp_dir, + backtrace_full_callback callback, void *data, + const char **filename, int *lineno) +{ + struct function_addrs *p; + struct function_addrs *match; + struct function *inlined; + int ret; + + if (function->function_addrs_count == 0) + return 0; + + /* Our search isn't safe if pc == -1, as that is the sentinel + value. */ + if (pc + 1 == 0) + return 0; + + p = ((struct function_addrs *) + bsearch (&pc, function->function_addrs, + function->function_addrs_count, + sizeof (struct function_addrs), + function_addrs_search)); + if (p == NULL) + return 0; + + /* Here pc >= p->low && pc < (p + 1)->low. The function_addrs are + sorted by low, so if pc > p->low we are at the end of a range of + function_addrs with the same low value. If pc == p->low walk + forward to the end of the range with that low value. Then walk + backward and use the first range that includes pc. */ + while (pc == (p + 1)->low) + ++p; + match = NULL; + while (1) + { + if (pc < p->high) + { + match = p; + break; + } + if (p == function->function_addrs) + break; + if ((p - 1)->low < p->low) + break; + --p; + } + if (match == NULL) + return 0; + + /* We found an inlined call. */ + + inlined = match->function; + + /* Report any calls inlined into this one. */ + ret = report_inlined_functions (pc, inlined, comp_dir, callback, data, + filename, lineno); + if (ret != 0) + return ret; + + /* Report this inlined call. */ + if (*filename[0] != '/' && comp_dir) + { + char buf[1024]; + snprintf (buf, 1024, "%s/%s", comp_dir, *filename); + ret = callback (data, pc, match->low, buf, *lineno, inlined->name); + } + else + { + ret = callback (data, pc, match->low, *filename, *lineno, inlined->name); + } + if (ret != 0) + return ret; + + /* Our caller will report the caller of the inlined function; tell + it the appropriate filename and line number. */ + *filename = inlined->caller_filename; + *lineno = inlined->caller_lineno; + + return 0; +} + +/* Look for a PC in the DWARF mapping for one module. On success, + call CALLBACK and return whatever it returns. On error, call + ERROR_CALLBACK and return 0. Sets *FOUND to 1 if the PC is found, + 0 if not. */ + +static int +dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata, + uintptr_t pc, backtrace_full_callback callback, + backtrace_error_callback error_callback, void *data, + int *found) +{ + struct unit_addrs *entry; + int found_entry; + struct unit *u; + int new_data; + struct line *lines; + struct line *ln; + struct function_addrs *p; + struct function_addrs *fmatch; + struct function *function; + const char *filename; + int lineno; + int ret; + + *found = 1; + + /* Find an address range that includes PC. Our search isn't safe if + PC == -1, as we use that as a sentinel value, so skip the search + in that case. */ + entry = (ddata->addrs_count == 0 || pc + 1 == 0 + ? NULL + : (struct unit_addrs*)bsearch (&pc, ddata->addrs, ddata->addrs_count, + sizeof (struct unit_addrs), unit_addrs_search)); + + if (entry == NULL) + { + *found = 0; + return 0; + } + + /* Here pc >= entry->low && pc < (entry + 1)->low. The unit_addrs + are sorted by low, so if pc > p->low we are at the end of a range + of unit_addrs with the same low value. If pc == p->low walk + forward to the end of the range with that low value. Then walk + backward and use the first range that includes pc. */ + while (pc == (entry + 1)->low) + ++entry; + found_entry = 0; + while (1) + { + if (pc < entry->high) + { + found_entry = 1; + break; + } + if (entry == ddata->addrs) + break; + if ((entry - 1)->low < entry->low) + break; + --entry; + } + if (!found_entry) + { + *found = 0; + return 0; + } + + /* We need the lines, lines_count, function_addrs, + function_addrs_count fields of u. If they are not set, we need + to set them. When running in threaded mode, we need to allow for + the possibility that some other thread is setting them + simultaneously. */ + + u = entry->u; + lines = u->lines; + + /* Skip units with no useful line number information by walking + backward. Useless line number information is marked by setting + lines == -1. */ + while (entry > ddata->addrs + && pc >= (entry - 1)->low + && pc < (entry - 1)->high) + { + if (state->threaded) + lines = (struct line *) backtrace_atomic_load_pointer (&u->lines); + + if (lines != (struct line *) (uintptr_t) -1) + break; + + --entry; + + u = entry->u; + lines = u->lines; + } + + if (state->threaded) + lines = backtrace_atomic_load_pointer (&u->lines); + + new_data = 0; + if (lines == NULL) + { + struct function_addrs *function_addrs; + size_t function_addrs_count; + struct line_header lhdr; + size_t count; + + /* We have never read the line information for this unit. Read + it now. */ + + function_addrs = NULL; + function_addrs_count = 0; + if (read_line_info (state, ddata, error_callback, data, entry->u, &lhdr, + &lines, &count)) + { + struct function_vector *pfvec; + + /* If not threaded, reuse DDATA->FVEC for better memory + consumption. */ + if (state->threaded) + pfvec = NULL; + else + pfvec = &ddata->fvec; + read_function_info (state, ddata, &lhdr, error_callback, data, + entry->u, pfvec, &function_addrs, + &function_addrs_count); + free_line_header (state, &lhdr, error_callback, data); + new_data = 1; + } + + /* Atomically store the information we just read into the unit. + If another thread is simultaneously writing, it presumably + read the same information, and we don't care which one we + wind up with; we just leak the other one. We do have to + write the lines field last, so that the acquire-loads above + ensure that the other fields are set. */ + + if (!state->threaded) + { + u->lines_count = count; + u->function_addrs = function_addrs; + u->function_addrs_count = function_addrs_count; + u->lines = lines; + } + else + { + backtrace_atomic_store_size_t (&u->lines_count, count); + backtrace_atomic_store_pointer (&u->function_addrs, function_addrs); + backtrace_atomic_store_size_t (&u->function_addrs_count, + function_addrs_count); + backtrace_atomic_store_pointer (&u->lines, lines); + } + } + + /* Now all fields of U have been initialized. */ + + if (lines == (struct line *) (uintptr_t) -1) + { + /* If reading the line number information failed in some way, + try again to see if there is a better compilation unit for + this PC. */ + if (new_data) + return dwarf_lookup_pc (state, ddata, pc, callback, error_callback, + data, found); + return callback (data, pc, 0, NULL, 0, NULL); + } + + /* Search for PC within this unit. */ + + ln = (struct line *) bsearch (&pc, lines, entry->u->lines_count, + sizeof (struct line), line_search); + if (ln == NULL) + { + /* The PC is between the low_pc and high_pc attributes of the + compilation unit, but no entry in the line table covers it. + This implies that the start of the compilation unit has no + line number information. */ + + if (entry->u->abs_filename == NULL) + { + const char *filename; + + filename = entry->u->filename; + if (filename != NULL + && !IS_ABSOLUTE_PATH (filename) + && entry->u->comp_dir != NULL) + { + size_t filename_len; + const char *dir; + size_t dir_len; + char *s; + + filename_len = strlen (filename); + dir = entry->u->comp_dir; + dir_len = strlen (dir); + s = (char *) backtrace_alloc (state, dir_len + filename_len + 2, + error_callback, data); + if (s == NULL) + { + *found = 0; + return 0; + } + memcpy (s, dir, dir_len); + /* FIXME: Should use backslash if DOS file system. */ + s[dir_len] = '/'; + memcpy (s + dir_len + 1, filename, filename_len + 1); + filename = s; + } + entry->u->abs_filename = filename; + } + + return callback (data, pc, 0, entry->u->abs_filename, 0, NULL); + } + + /* Search for function name within this unit. */ + + if (entry->u->function_addrs_count == 0) + return callback (data, pc, 0, ln->filename, ln->lineno, NULL); + + p = ((struct function_addrs *) + bsearch (&pc, entry->u->function_addrs, + entry->u->function_addrs_count, + sizeof (struct function_addrs), + function_addrs_search)); + if (p == NULL) + return callback (data, pc, 0, ln->filename, ln->lineno, NULL); + + /* Here pc >= p->low && pc < (p + 1)->low. The function_addrs are + sorted by low, so if pc > p->low we are at the end of a range of + function_addrs with the same low value. If pc == p->low walk + forward to the end of the range with that low value. Then walk + backward and use the first range that includes pc. */ + while (pc == (p + 1)->low) + ++p; + fmatch = NULL; + while (1) + { + if (pc < p->high) + { + fmatch = p; + break; + } + if (p == entry->u->function_addrs) + break; + if ((p - 1)->low < p->low) + break; + --p; + } + if (fmatch == NULL) + return callback (data, pc, 0, ln->filename, ln->lineno, NULL); + + function = fmatch->function; + + filename = ln->filename; + lineno = ln->lineno; + + ret = report_inlined_functions (pc, function, entry->u->comp_dir, callback, data, + &filename, &lineno); + if (ret != 0) + return ret; + + if (filename[0] != '/' && entry->u->comp_dir) + { + char buf[1024]; + snprintf (buf, 1024, "%s/%s", entry->u->comp_dir, filename); + return callback (data, pc, fmatch->low, buf, lineno, function->name); + } + else + { + return callback (data, pc, fmatch->low, filename, lineno, function->name); + } +} + +bool dwarf_fileline_dwarf_lookup_pc_in_all_entries(struct backtrace_state *state, uintptr_t pc, + backtrace_full_callback callback, backtrace_error_callback error_callback, void *data, + int& found, int ret) +{ + for (struct dwarf_data* ddata = (struct dwarf_data *)state->fileline_data; + ddata != NULL; + ddata = ddata->next) + { + ret = dwarf_lookup_pc(state, ddata, pc, callback, error_callback, data, &found); + if (ret != 0 || found) return true; + } + return false; +} + +/* Return the file/line information for a PC using the DWARF mapping + we built earlier. */ + +static int +dwarf_fileline (struct backtrace_state *state, uintptr_t pc, + backtrace_full_callback callback, + backtrace_error_callback error_callback, void *data) +{ + struct dwarf_data *ddata; + int found; + int ret = 0; + + if (!state->threaded) + { + if (dwarf_fileline_dwarf_lookup_pc_in_all_entries(state, pc, callback, error_callback, data, found, ret)) + { + return ret; + } + + // if we failed to obtain an entry in range, it can mean that the address map has been changed and new entries + // have been loaded in the meantime. Request a refresh and try again. + if (state->request_known_address_ranges_refresh_fn) + { + int new_range_count = state->request_known_address_ranges_refresh_fn(state, pc); + if (new_range_count > 0) + { + if (dwarf_fileline_dwarf_lookup_pc_in_all_entries(state, pc, callback, error_callback, data, found, ret)) + { + return ret; + } + } + } + + } + else + { + struct dwarf_data **pp; + + pp = (struct dwarf_data **) (void *) &state->fileline_data; + while (1) + { + ddata = backtrace_atomic_load_pointer (pp); + if (ddata == NULL) + break; + + ret = dwarf_lookup_pc (state, ddata, pc, callback, error_callback, + data, &found); + if (ret != 0 || found) + return ret; + + pp = &ddata->next; + } + } + + /* FIXME: See if any libraries have been dlopen'ed. */ + + return callback (data, pc, 0, NULL, 0, NULL); +} + +/* Initialize our data structures from the DWARF debug info for a + file. Return NULL on failure. */ + +static struct dwarf_data * +build_dwarf_data (struct backtrace_state *state, + uintptr_t base_address, + const struct dwarf_sections *dwarf_sections, + int is_bigendian, + struct dwarf_data *altlink, + backtrace_error_callback error_callback, + void *data) +{ + struct unit_addrs_vector addrs_vec; + struct unit_addrs *addrs; + size_t addrs_count; + struct unit_vector units_vec; + struct unit **units; + size_t units_count; + struct dwarf_data *fdata; + + if (!build_address_map (state, base_address, dwarf_sections, is_bigendian, + altlink, error_callback, data, &addrs_vec, + &units_vec)) + return NULL; + + if (!backtrace_vector_release (state, &addrs_vec.vec, error_callback, data)) + return NULL; + if (!backtrace_vector_release (state, &units_vec.vec, error_callback, data)) + return NULL; + addrs = (struct unit_addrs *) addrs_vec.vec.base; + units = (struct unit **) units_vec.vec.base; + addrs_count = addrs_vec.count; + units_count = units_vec.count; + backtrace_qsort (addrs, addrs_count, sizeof (struct unit_addrs), + unit_addrs_compare); + /* No qsort for units required, already sorted. */ + + fdata = ((struct dwarf_data *) + backtrace_alloc (state, sizeof (struct dwarf_data), + error_callback, data)); + if (fdata == NULL) + return NULL; + + fdata->next = NULL; + fdata->altlink = altlink; + fdata->base_address = base_address; + fdata->addrs = addrs; + fdata->addrs_count = addrs_count; + fdata->units = units; + fdata->units_count = units_count; + fdata->dwarf_sections = *dwarf_sections; + fdata->is_bigendian = is_bigendian; + memset (&fdata->fvec, 0, sizeof fdata->fvec); + + return fdata; +} + +/* Build our data structures from the DWARF sections for a module. + Set FILELINE_FN and STATE->FILELINE_DATA. Return 1 on success, 0 + on failure. */ + +int +backtrace_dwarf_add (struct backtrace_state *state, + uintptr_t base_address, + const struct dwarf_sections *dwarf_sections, + int is_bigendian, + struct dwarf_data *fileline_altlink, + backtrace_error_callback error_callback, + void *data, fileline *fileline_fn, + struct dwarf_data **fileline_entry) +{ + struct dwarf_data *fdata; + + fdata = build_dwarf_data (state, base_address, dwarf_sections, is_bigendian, + fileline_altlink, error_callback, data); + if (fdata == NULL) + return 0; + + if (fileline_entry != NULL) + *fileline_entry = fdata; + + if (!state->threaded) + { + struct dwarf_data **pp; + + for (pp = (struct dwarf_data **) (void *) &state->fileline_data; + *pp != NULL; + pp = &(*pp)->next) + ; + *pp = fdata; + } + else + { + while (1) + { + struct dwarf_data **pp; + + pp = (struct dwarf_data **) (void *) &state->fileline_data; + + while (1) + { + struct dwarf_data *p; + + p = backtrace_atomic_load_pointer (pp); + + if (p == NULL) + break; + + pp = &p->next; + } + + if (__sync_bool_compare_and_swap (pp, NULL, fdata)) + break; + } + } + + *fileline_fn = dwarf_fileline; + + return 1; +} + +} diff --git a/Dependencies/tracy/libbacktrace/elf.cpp b/Dependencies/tracy/libbacktrace/elf.cpp new file mode 100644 index 000000000..e88a33b08 --- /dev/null +++ b/Dependencies/tracy/libbacktrace/elf.cpp @@ -0,0 +1,7597 @@ +/* elf.c -- Get debug data from an ELF file for backtraces. + Copyright (C) 2012-2021 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Google. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + (1) Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + (2) Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + (3) The name of the author may not be used to + endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_DL_ITERATE_PHDR +#include +#endif + +#include "backtrace.hpp" +#include "internal.hpp" + +#include "../client/TracyFastVector.hpp" +#include "../common/TracyAlloc.hpp" + +#ifndef S_ISLNK + #ifndef S_IFLNK + #define S_IFLNK 0120000 + #endif + #ifndef S_IFMT + #define S_IFMT 0170000 + #endif + #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +#endif + +#ifndef __GNUC__ +#define __builtin_prefetch(p, r, l) +#ifndef unlikely +#define unlikely(x) (x) +#endif +#else +#ifndef unlikely +#define unlikely(x) __builtin_expect(!!(x), 0) +#endif +#endif + +namespace tracy +{ + +#ifdef TRACY_DEBUGINFOD +int GetDebugInfoDescriptor( const char* buildid_data, size_t buildid_size ); +#endif + +#if !defined(HAVE_DECL_STRNLEN) || !HAVE_DECL_STRNLEN + +/* If strnlen is not declared, provide our own version. */ + +static size_t +xstrnlen (const char *s, size_t maxlen) +{ + size_t i; + + for (i = 0; i < maxlen; ++i) + if (s[i] == '\0') + break; + return i; +} + +#define strnlen xstrnlen + +#endif + +#ifndef HAVE_LSTAT + +/* Dummy version of lstat for systems that don't have it. */ + +static int +xlstat (const char *path ATTRIBUTE_UNUSED, struct stat *st ATTRIBUTE_UNUSED) +{ + return -1; +} + +#define lstat xlstat + +#endif + +#ifndef HAVE_READLINK + +/* Dummy version of readlink for systems that don't have it. */ + +static ssize_t +xreadlink (const char *path ATTRIBUTE_UNUSED, char *buf ATTRIBUTE_UNUSED, + size_t bufsz ATTRIBUTE_UNUSED) +{ + return -1; +} + +#define readlink xreadlink + +#endif + +#ifndef HAVE_DL_ITERATE_PHDR + +/* Dummy version of dl_iterate_phdr for systems that don't have it. */ + +#define dl_phdr_info x_dl_phdr_info +#define dl_iterate_phdr x_dl_iterate_phdr + +struct dl_phdr_info +{ + uintptr_t dlpi_addr; + const char *dlpi_name; +}; + +static int +dl_iterate_phdr (int (*callback) (struct dl_phdr_info *, + size_t, void *) ATTRIBUTE_UNUSED, + void *data ATTRIBUTE_UNUSED) +{ + return 0; +} + +#endif /* ! defined (HAVE_DL_ITERATE_PHDR) */ + +/* The configure script must tell us whether we are 32-bit or 64-bit + ELF. We could make this code test and support either possibility, + but there is no point. This code only works for the currently + running executable, which means that we know the ELF mode at + configure time. */ + +#if BACKTRACE_ELF_SIZE != 32 && BACKTRACE_ELF_SIZE != 64 +#error "Unknown BACKTRACE_ELF_SIZE" +#endif + +/* might #include which might define our constants + with slightly different values. Undefine them to be safe. */ + +#undef EI_NIDENT +#undef EI_MAG0 +#undef EI_MAG1 +#undef EI_MAG2 +#undef EI_MAG3 +#undef EI_CLASS +#undef EI_DATA +#undef EI_VERSION +#undef ELF_MAG0 +#undef ELF_MAG1 +#undef ELF_MAG2 +#undef ELF_MAG3 +#undef ELFCLASS32 +#undef ELFCLASS64 +#undef ELFDATA2LSB +#undef ELFDATA2MSB +#undef EV_CURRENT +#undef ET_DYN +#undef EM_PPC64 +#undef EF_PPC64_ABI +#undef SHN_LORESERVE +#undef SHN_XINDEX +#undef SHN_UNDEF +#undef SHT_PROGBITS +#undef SHT_SYMTAB +#undef SHT_STRTAB +#undef SHT_DYNSYM +#undef SHF_COMPRESSED +#undef STT_OBJECT +#undef STT_FUNC +#undef NT_GNU_BUILD_ID +#undef ELFCOMPRESS_ZLIB +#undef ELFCOMPRESS_ZSTD + +/* Basic types. */ + +typedef uint16_t b_elf_half; /* Elf_Half. */ +typedef uint32_t b_elf_word; /* Elf_Word. */ +typedef int32_t b_elf_sword; /* Elf_Sword. */ + +#if BACKTRACE_ELF_SIZE == 32 + +typedef uint32_t b_elf_addr; /* Elf_Addr. */ +typedef uint32_t b_elf_off; /* Elf_Off. */ + +typedef uint32_t b_elf_wxword; /* 32-bit Elf_Word, 64-bit ELF_Xword. */ + +#else + +typedef uint64_t b_elf_addr; /* Elf_Addr. */ +typedef uint64_t b_elf_off; /* Elf_Off. */ +typedef uint64_t b_elf_xword; /* Elf_Xword. */ +typedef int64_t b_elf_sxword; /* Elf_Sxword. */ + +typedef uint64_t b_elf_wxword; /* 32-bit Elf_Word, 64-bit ELF_Xword. */ + +#endif + +/* Data structures and associated constants. */ + +#define EI_NIDENT 16 + +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */ + b_elf_half e_type; /* Identifies object file type */ + b_elf_half e_machine; /* Specifies required architecture */ + b_elf_word e_version; /* Identifies object file version */ + b_elf_addr e_entry; /* Entry point virtual address */ + b_elf_off e_phoff; /* Program header table file offset */ + b_elf_off e_shoff; /* Section header table file offset */ + b_elf_word e_flags; /* Processor-specific flags */ + b_elf_half e_ehsize; /* ELF header size in bytes */ + b_elf_half e_phentsize; /* Program header table entry size */ + b_elf_half e_phnum; /* Program header table entry count */ + b_elf_half e_shentsize; /* Section header table entry size */ + b_elf_half e_shnum; /* Section header table entry count */ + b_elf_half e_shstrndx; /* Section header string table index */ +} b_elf_ehdr; /* Elf_Ehdr. */ + +#define EI_MAG0 0 +#define EI_MAG1 1 +#define EI_MAG2 2 +#define EI_MAG3 3 +#define EI_CLASS 4 +#define EI_DATA 5 +#define EI_VERSION 6 + +#define ELFMAG0 0x7f +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' + +#define ELFCLASS32 1 +#define ELFCLASS64 2 + +#define ELFDATA2LSB 1 +#define ELFDATA2MSB 2 + +#define EV_CURRENT 1 + +#define ET_DYN 3 + +#define EM_PPC64 21 +#define EF_PPC64_ABI 3 + +typedef struct { + b_elf_word sh_name; /* Section name, index in string tbl */ + b_elf_word sh_type; /* Type of section */ + b_elf_wxword sh_flags; /* Miscellaneous section attributes */ + b_elf_addr sh_addr; /* Section virtual addr at execution */ + b_elf_off sh_offset; /* Section file offset */ + b_elf_wxword sh_size; /* Size of section in bytes */ + b_elf_word sh_link; /* Index of another section */ + b_elf_word sh_info; /* Additional section information */ + b_elf_wxword sh_addralign; /* Section alignment */ + b_elf_wxword sh_entsize; /* Entry size if section holds table */ +} b_elf_shdr; /* Elf_Shdr. */ + +#define SHN_UNDEF 0x0000 /* Undefined section */ +#define SHN_LORESERVE 0xFF00 /* Begin range of reserved indices */ +#define SHN_XINDEX 0xFFFF /* Section index is held elsewhere */ + +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_DYNSYM 11 + +#define SHF_COMPRESSED 0x800 + +#if BACKTRACE_ELF_SIZE == 32 + +typedef struct +{ + b_elf_word st_name; /* Symbol name, index in string tbl */ + b_elf_addr st_value; /* Symbol value */ + b_elf_word st_size; /* Symbol size */ + unsigned char st_info; /* Symbol binding and type */ + unsigned char st_other; /* Visibility and other data */ + b_elf_half st_shndx; /* Symbol section index */ +} b_elf_sym; /* Elf_Sym. */ + +#else /* BACKTRACE_ELF_SIZE != 32 */ + +typedef struct +{ + b_elf_word st_name; /* Symbol name, index in string tbl */ + unsigned char st_info; /* Symbol binding and type */ + unsigned char st_other; /* Visibility and other data */ + b_elf_half st_shndx; /* Symbol section index */ + b_elf_addr st_value; /* Symbol value */ + b_elf_xword st_size; /* Symbol size */ +} b_elf_sym; /* Elf_Sym. */ + +#endif /* BACKTRACE_ELF_SIZE != 32 */ + +#define STT_OBJECT 1 +#define STT_FUNC 2 + +typedef struct +{ + uint32_t namesz; + uint32_t descsz; + uint32_t type; + char name[1]; +} b_elf_note; + +#define NT_GNU_BUILD_ID 3 + +#if BACKTRACE_ELF_SIZE == 32 + +typedef struct +{ + b_elf_word ch_type; /* Compresstion algorithm */ + b_elf_word ch_size; /* Uncompressed size */ + b_elf_word ch_addralign; /* Alignment for uncompressed data */ +} b_elf_chdr; /* Elf_Chdr */ + +#else /* BACKTRACE_ELF_SIZE != 32 */ + +typedef struct +{ + b_elf_word ch_type; /* Compression algorithm */ + b_elf_word ch_reserved; /* Reserved */ + b_elf_xword ch_size; /* Uncompressed size */ + b_elf_xword ch_addralign; /* Alignment for uncompressed data */ +} b_elf_chdr; /* Elf_Chdr */ + +#endif /* BACKTRACE_ELF_SIZE != 32 */ + +#define ELFCOMPRESS_ZLIB 1 +#define ELFCOMPRESS_ZSTD 2 + +/* Names of sections, indexed by enum dwarf_section in internal.h. */ + +static const char * const dwarf_section_names[DEBUG_MAX] = +{ + ".debug_info", + ".debug_line", + ".debug_abbrev", + ".debug_ranges", + ".debug_str", + ".debug_addr", + ".debug_str_offsets", + ".debug_line_str", + ".debug_rnglists" +}; + +/* Information we gather for the sections we care about. */ + +struct debug_section_info +{ + /* Section file offset. */ + off_t offset; + /* Section size. */ + size_t size; + /* Section contents, after read from file. */ + const unsigned char *data; + /* Whether the SHF_COMPRESSED flag is set for the section. */ + int compressed; +}; + +/* Information we keep for an ELF symbol. */ + +struct elf_symbol +{ + /* The name of the symbol. */ + const char *name; + /* The address of the symbol. */ + uintptr_t address; + /* The size of the symbol. */ + size_t size; +}; + +/* Information to pass to elf_syminfo. */ + +struct elf_syminfo_data +{ + /* Symbols for the next module. */ + struct elf_syminfo_data *next; + /* The ELF symbols, sorted by address. */ + struct elf_symbol *symbols; + /* The number of symbols. */ + size_t count; +}; + +/* A view that works for either a file or memory. */ + +struct elf_view +{ + struct backtrace_view view; + int release; /* If non-zero, must call backtrace_release_view. */ +}; + +/* Information about PowerPC64 ELFv1 .opd section. */ + +struct elf_ppc64_opd_data +{ + /* Address of the .opd section. */ + b_elf_addr addr; + /* Section data. */ + const char *data; + /* Size of the .opd section. */ + size_t size; + /* Corresponding section view. */ + struct elf_view view; +}; + +/* Create a view of SIZE bytes from DESCRIPTOR/MEMORY at OFFSET. */ + +static int +elf_get_view (struct backtrace_state *state, int descriptor, + const unsigned char *memory, size_t memory_size, off_t offset, + uint64_t size, backtrace_error_callback error_callback, + void *data, struct elf_view *view) +{ + if (memory == NULL) + { + view->release = 1; + return backtrace_get_view (state, descriptor, offset, size, + error_callback, data, &view->view); + } + else + { + if ((uint64_t) offset + size > (uint64_t) memory_size) + { + error_callback (data, "out of range for in-memory file", 0); + return 0; + } + view->view.data = (const void *) (memory + offset); + view->view.base = NULL; + view->view.len = size; + view->release = 0; + return 1; + } +} + +/* Release a view read by elf_get_view. */ + +static void +elf_release_view (struct backtrace_state *state, struct elf_view *view, + backtrace_error_callback error_callback, void *data) +{ + if (view->release) + backtrace_release_view (state, &view->view, error_callback, data); +} + +/* Compute the CRC-32 of BUF/LEN. This uses the CRC used for + .gnu_debuglink files. */ + +static uint32_t +elf_crc32 (uint32_t crc, const unsigned char *buf, size_t len) +{ + static const uint32_t crc32_table[256] = + { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, + 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, + 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, + 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, + 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, + 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, + 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, + 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, + 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, + 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, + 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, + 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, + 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, + 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, + 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, + 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, + 0x2d02ef8d + }; + const unsigned char *end; + + crc = ~crc; + for (end = buf + len; buf < end; ++ buf) + crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8); + return ~crc; +} + +/* Return the CRC-32 of the entire file open at DESCRIPTOR. */ + +static uint32_t +elf_crc32_file (struct backtrace_state *state, int descriptor, + backtrace_error_callback error_callback, void *data) +{ + struct stat st; + struct backtrace_view file_view; + uint32_t ret; + + if (fstat (descriptor, &st) < 0) + { + error_callback (data, "fstat", errno); + return 0; + } + + if (!backtrace_get_view (state, descriptor, 0, st.st_size, error_callback, + data, &file_view)) + return 0; + + ret = elf_crc32 (0, (const unsigned char *) file_view.data, st.st_size); + + backtrace_release_view (state, &file_view, error_callback, data); + + return ret; +} + +/* A dummy callback function used when we can't find a symbol + table. */ + +static void +elf_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED, + uintptr_t addr ATTRIBUTE_UNUSED, + backtrace_syminfo_callback callback ATTRIBUTE_UNUSED, + backtrace_error_callback error_callback, void *data) +{ + error_callback (data, "no symbol table in ELF executable", -1); +} + +/* A callback function used when we can't find any debug info. */ + +static int +elf_nodebug (struct backtrace_state *state, uintptr_t pc, + backtrace_full_callback callback, + backtrace_error_callback error_callback, void *data) +{ + if (state->syminfo_fn != NULL && state->syminfo_fn != elf_nosyms) + { + struct backtrace_call_full bdata; + + /* Fetch symbol information so that we can least get the + function name. */ + + bdata.full_callback = callback; + bdata.full_error_callback = error_callback; + bdata.full_data = data; + bdata.ret = 0; + state->syminfo_fn (state, pc, backtrace_syminfo_to_full_callback, + backtrace_syminfo_to_full_error_callback, &bdata); + return bdata.ret; + } + + error_callback (data, "no debug info in ELF executable", -1); + return 0; +} + +/* Compare struct elf_symbol for qsort. */ + +static int +elf_symbol_compare (const void *v1, const void *v2) +{ + const struct elf_symbol *e1 = (const struct elf_symbol *) v1; + const struct elf_symbol *e2 = (const struct elf_symbol *) v2; + + if (e1->address < e2->address) + return -1; + else if (e1->address > e2->address) + return 1; + else + return 0; +} + +/* Compare an ADDR against an elf_symbol for bsearch. We allocate one + extra entry in the array so that this can look safely at the next + entry. */ + +static int +elf_symbol_search (const void *vkey, const void *ventry) +{ + const uintptr_t *key = (const uintptr_t *) vkey; + const struct elf_symbol *entry = (const struct elf_symbol *) ventry; + uintptr_t addr; + + addr = *key; + if (addr < entry->address) + return -1; + else if (addr >= entry->address + entry->size) + return 1; + else + return 0; +} + +/* Initialize the symbol table info for elf_syminfo. */ + +static int +elf_initialize_syminfo (struct backtrace_state *state, + uintptr_t base_address, + const unsigned char *symtab_data, size_t symtab_size, + const unsigned char *strtab, size_t strtab_size, + backtrace_error_callback error_callback, + void *data, struct elf_syminfo_data *sdata, + struct elf_ppc64_opd_data *opd) +{ + size_t sym_count; + const b_elf_sym *sym; + size_t elf_symbol_count; + size_t elf_symbol_size; + struct elf_symbol *elf_symbols; + size_t i; + unsigned int j; + + sym_count = symtab_size / sizeof (b_elf_sym); + + /* We only care about function symbols. Count them. */ + sym = (const b_elf_sym *) symtab_data; + elf_symbol_count = 0; + for (i = 0; i < sym_count; ++i, ++sym) + { + int info; + + info = sym->st_info & 0xf; + if ((info == STT_FUNC || info == STT_OBJECT) + && sym->st_shndx != SHN_UNDEF) + ++elf_symbol_count; + } + + elf_symbol_size = elf_symbol_count * sizeof (struct elf_symbol); + elf_symbols = ((struct elf_symbol *) + backtrace_alloc (state, elf_symbol_size, error_callback, + data)); + if (elf_symbols == NULL) + return 0; + + sym = (const b_elf_sym *) symtab_data; + j = 0; + for (i = 0; i < sym_count; ++i, ++sym) + { + int info; + + info = sym->st_info & 0xf; + if (info != STT_FUNC && info != STT_OBJECT) + continue; + if (sym->st_shndx == SHN_UNDEF) + continue; + if (sym->st_name >= strtab_size) + { + error_callback (data, "symbol string index out of range", 0); + backtrace_free (state, elf_symbols, elf_symbol_size, error_callback, + data); + return 0; + } + elf_symbols[j].name = (const char *) strtab + sym->st_name; + /* Special case PowerPC64 ELFv1 symbols in .opd section, if the symbol + is a function descriptor, read the actual code address from the + descriptor. */ + if (opd + && sym->st_value >= opd->addr + && sym->st_value < opd->addr + opd->size) + elf_symbols[j].address + = *(const b_elf_addr *) (opd->data + (sym->st_value - opd->addr)); + else + elf_symbols[j].address = sym->st_value; + elf_symbols[j].address += base_address; + elf_symbols[j].size = sym->st_size; + ++j; + } + + backtrace_qsort (elf_symbols, elf_symbol_count, sizeof (struct elf_symbol), + elf_symbol_compare); + + sdata->next = NULL; + sdata->symbols = elf_symbols; + sdata->count = elf_symbol_count; + + return 1; +} + +/* Add EDATA to the list in STATE. */ + +static void +elf_add_syminfo_data (struct backtrace_state *state, + struct elf_syminfo_data *edata) +{ + if (!state->threaded) + { + struct elf_syminfo_data **pp; + + for (pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data; + *pp != NULL; + pp = &(*pp)->next) + ; + *pp = edata; + } + else + { + while (1) + { + struct elf_syminfo_data **pp; + + pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data; + + while (1) + { + struct elf_syminfo_data *p; + + p = backtrace_atomic_load_pointer (pp); + + if (p == NULL) + break; + + pp = &p->next; + } + + if (__sync_bool_compare_and_swap (pp, NULL, edata)) + break; + } + } +} + +/* Return the symbol name and value for an ADDR. */ + +static void +elf_syminfo (struct backtrace_state *state, uintptr_t addr, + backtrace_syminfo_callback callback, + backtrace_error_callback error_callback ATTRIBUTE_UNUSED, + void *data) +{ + struct elf_syminfo_data *edata; + struct elf_symbol *sym = NULL; + + if (!state->threaded) + { + for (edata = (struct elf_syminfo_data *) state->syminfo_data; + edata != NULL; + edata = edata->next) + { + sym = ((struct elf_symbol *) + bsearch (&addr, edata->symbols, edata->count, + sizeof (struct elf_symbol), elf_symbol_search)); + if (sym != NULL) + break; + } + } + else + { + struct elf_syminfo_data **pp; + + pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data; + while (1) + { + edata = backtrace_atomic_load_pointer (pp); + if (edata == NULL) + break; + + sym = ((struct elf_symbol *) + bsearch (&addr, edata->symbols, edata->count, + sizeof (struct elf_symbol), elf_symbol_search)); + if (sym != NULL) + break; + + pp = &edata->next; + } + } + + if (sym == NULL) + callback (data, addr, NULL, 0, 0); + else + callback (data, addr, sym->name, sym->address, sym->size); +} + +/* Return whether FILENAME is a symlink. */ + +static int +elf_is_symlink (const char *filename) +{ + struct stat st; + + if (lstat (filename, &st) < 0) + return 0; + return S_ISLNK (st.st_mode); +} + +/* Return the results of reading the symlink FILENAME in a buffer + allocated by backtrace_alloc. Return the length of the buffer in + *LEN. */ + +static char * +elf_readlink (struct backtrace_state *state, const char *filename, + backtrace_error_callback error_callback, void *data, + size_t *plen) +{ + size_t len; + char *buf; + + len = 128; + while (1) + { + ssize_t rl; + + buf = (char*)backtrace_alloc (state, len, error_callback, data); + if (buf == NULL) + return NULL; + rl = readlink (filename, buf, len); + if (rl < 0) + { + backtrace_free (state, buf, len, error_callback, data); + return NULL; + } + if ((size_t) rl < len - 1) + { + buf[rl] = '\0'; + *plen = len; + return buf; + } + backtrace_free (state, buf, len, error_callback, data); + len *= 2; + } +} + +#define SYSTEM_BUILD_ID_DIR "/usr/lib/debug/.build-id/" + +/* Open a separate debug info file, using the build ID to find it. + Returns an open file descriptor, or -1. + + The GDB manual says that the only place gdb looks for a debug file + when the build ID is known is in /usr/lib/debug/.build-id. */ + +static int +elf_open_debugfile_by_buildid (struct backtrace_state *state, + const char *buildid_data, size_t buildid_size, + const char *filename, + backtrace_error_callback error_callback, + void *data) +{ + const char * const prefix = SYSTEM_BUILD_ID_DIR; + const size_t prefix_len = strlen (prefix); + const char * const suffix = ".debug"; + const size_t suffix_len = strlen (suffix); + size_t len; + char *bd_filename; + char *t; + size_t i; + int ret; + int does_not_exist; + + len = prefix_len + buildid_size * 2 + suffix_len + 2; + bd_filename = (char*)backtrace_alloc (state, len, error_callback, data); + if (bd_filename == NULL) + return -1; + + t = bd_filename; + memcpy (t, prefix, prefix_len); + t += prefix_len; + for (i = 0; i < buildid_size; i++) + { + unsigned char b; + unsigned char nib; + + b = (unsigned char) buildid_data[i]; + nib = (b & 0xf0) >> 4; + *t++ = nib < 10 ? '0' + nib : 'a' + nib - 10; + nib = b & 0x0f; + *t++ = nib < 10 ? '0' + nib : 'a' + nib - 10; + if (i == 0) + *t++ = '/'; + } + memcpy (t, suffix, suffix_len); + t[suffix_len] = '\0'; + + ret = backtrace_open (bd_filename, error_callback, data, &does_not_exist); + + backtrace_free (state, bd_filename, len, error_callback, data); + + /* gdb checks that the debuginfo file has the same build ID note. + That seems kind of pointless to me--why would it have the right + name but not the right build ID?--so skipping the check. */ + +#ifdef TRACY_DEBUGINFOD + if (ret == -1) + return GetDebugInfoDescriptor( buildid_data, buildid_size, filename ); + else + return ret; +#else + return ret; +#endif +} + +/* Try to open a file whose name is PREFIX (length PREFIX_LEN) + concatenated with PREFIX2 (length PREFIX2_LEN) concatenated with + DEBUGLINK_NAME. Returns an open file descriptor, or -1. */ + +static int +elf_try_debugfile (struct backtrace_state *state, const char *prefix, + size_t prefix_len, const char *prefix2, size_t prefix2_len, + const char *debuglink_name, + backtrace_error_callback error_callback, void *data) +{ + size_t debuglink_len; + size_t try_len; + char *Try; + int does_not_exist; + int ret; + + debuglink_len = strlen (debuglink_name); + try_len = prefix_len + prefix2_len + debuglink_len + 1; + Try = (char*)backtrace_alloc (state, try_len, error_callback, data); + if (Try == NULL) + return -1; + + memcpy (Try, prefix, prefix_len); + memcpy (Try + prefix_len, prefix2, prefix2_len); + memcpy (Try + prefix_len + prefix2_len, debuglink_name, debuglink_len); + Try[prefix_len + prefix2_len + debuglink_len] = '\0'; + + ret = backtrace_open (Try, error_callback, data, &does_not_exist); + + backtrace_free (state, Try, try_len, error_callback, data); + + return ret; +} + +/* Find a separate debug info file, using the debuglink section data + to find it. Returns an open file descriptor, or -1. */ + +static int +elf_find_debugfile_by_debuglink (struct backtrace_state *state, + const char *filename, + const char *debuglink_name, + backtrace_error_callback error_callback, + void *data) +{ + int ret; + char *alc; + size_t alc_len; + const char *slash; + int ddescriptor; + const char *prefix; + size_t prefix_len; + + /* Resolve symlinks in FILENAME. Since FILENAME is fairly likely to + be /proc/self/exe, symlinks are common. We don't try to resolve + the whole path name, just the base name. */ + ret = -1; + alc = NULL; + alc_len = 0; + while (elf_is_symlink (filename)) + { + char *new_buf; + size_t new_len; + + new_buf = elf_readlink (state, filename, error_callback, data, &new_len); + if (new_buf == NULL) + break; + + if (new_buf[0] == '/') + filename = new_buf; + else + { + slash = strrchr (filename, '/'); + if (slash == NULL) + filename = new_buf; + else + { + size_t clen; + char *c; + + slash++; + clen = slash - filename + strlen (new_buf) + 1; + c = (char*)backtrace_alloc (state, clen, error_callback, data); + if (c == NULL) + goto done; + + memcpy (c, filename, slash - filename); + memcpy (c + (slash - filename), new_buf, strlen (new_buf)); + c[slash - filename + strlen (new_buf)] = '\0'; + backtrace_free (state, new_buf, new_len, error_callback, data); + filename = c; + new_buf = c; + new_len = clen; + } + } + + if (alc != NULL) + backtrace_free (state, alc, alc_len, error_callback, data); + alc = new_buf; + alc_len = new_len; + } + + /* Look for DEBUGLINK_NAME in the same directory as FILENAME. */ + + slash = strrchr (filename, '/'); + if (slash == NULL) + { + prefix = ""; + prefix_len = 0; + } + else + { + slash++; + prefix = filename; + prefix_len = slash - filename; + } + + ddescriptor = elf_try_debugfile (state, prefix, prefix_len, "", 0, + debuglink_name, error_callback, data); + if (ddescriptor >= 0) + { + ret = ddescriptor; + goto done; + } + + /* Look for DEBUGLINK_NAME in a .debug subdirectory of FILENAME. */ + + ddescriptor = elf_try_debugfile (state, prefix, prefix_len, ".debug/", + strlen (".debug/"), debuglink_name, + error_callback, data); + if (ddescriptor >= 0) + { + ret = ddescriptor; + goto done; + } + + /* Look for DEBUGLINK_NAME in /usr/lib/debug. */ + + ddescriptor = elf_try_debugfile (state, "/usr/lib/debug/", + strlen ("/usr/lib/debug/"), prefix, + prefix_len, debuglink_name, + error_callback, data); + if (ddescriptor >= 0) + ret = ddescriptor; + + done: + if (alc != NULL && alc_len > 0) + backtrace_free (state, alc, alc_len, error_callback, data); + return ret; +} + +/* Open a separate debug info file, using the debuglink section data + to find it. Returns an open file descriptor, or -1. */ + +static int +elf_open_debugfile_by_debuglink (struct backtrace_state *state, + const char *filename, + const char *debuglink_name, + uint32_t debuglink_crc, + backtrace_error_callback error_callback, + void *data) +{ + int ddescriptor; + + ddescriptor = elf_find_debugfile_by_debuglink (state, filename, + debuglink_name, + error_callback, data); + if (ddescriptor < 0) + return -1; + + if (debuglink_crc != 0) + { + uint32_t got_crc; + + got_crc = elf_crc32_file (state, ddescriptor, error_callback, data); + if (got_crc != debuglink_crc) + { + backtrace_close (ddescriptor, error_callback, data); + return -1; + } + } + + return ddescriptor; +} + +/* A function useful for setting a breakpoint for an inflation failure + when this code is compiled with -g. */ + +static void +elf_uncompress_failed(void) +{ +} + +/* *PVAL is the current value being read from the stream, and *PBITS + is the number of valid bits. Ensure that *PVAL holds at least 15 + bits by reading additional bits from *PPIN, up to PINEND, as + needed. Updates *PPIN, *PVAL and *PBITS. Returns 1 on success, 0 + on error. */ + +static int +elf_fetch_bits (const unsigned char **ppin, const unsigned char *pinend, + uint64_t *pval, unsigned int *pbits) +{ + unsigned int bits; + const unsigned char *pin; + uint64_t val; + uint32_t next; + + bits = *pbits; + if (bits >= 15) + return 1; + pin = *ppin; + val = *pval; + + if (unlikely (pinend - pin < 4)) + { + elf_uncompress_failed (); + return 0; + } + +#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) \ + && defined(__ORDER_BIG_ENDIAN__) \ + && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ \ + || __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) + /* We've ensured that PIN is aligned. */ + next = *(const uint32_t *)pin; + +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + next = __builtin_bswap32 (next); +#endif +#else + next = pin[0] | (pin[1] << 8) | (pin[2] << 16) | (pin[3] << 24); +#endif + + val |= (uint64_t)next << bits; + bits += 32; + pin += 4; + + /* We will need the next four bytes soon. */ + __builtin_prefetch (pin, 0, 0); + + *ppin = pin; + *pval = val; + *pbits = bits; + return 1; +} + +/* This is like elf_fetch_bits, but it fetchs the bits backward, and ensures at + least 16 bits. This is for zstd. */ + +static int +elf_fetch_bits_backward (const unsigned char **ppin, + const unsigned char *pinend, + uint64_t *pval, unsigned int *pbits) +{ + unsigned int bits; + const unsigned char *pin; + uint64_t val; + uint32_t next; + + bits = *pbits; + if (bits >= 16) + return 1; + pin = *ppin; + val = *pval; + + if (unlikely (pin <= pinend)) + { + if (bits == 0) + { + elf_uncompress_failed (); + return 0; + } + return 1; + } + + pin -= 4; + +#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) \ + && defined(__ORDER_BIG_ENDIAN__) \ + && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ \ + || __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) + /* We've ensured that PIN is aligned. */ + next = *(const uint32_t *)pin; + +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + next = __builtin_bswap32 (next); +#endif +#else + next = pin[0] | (pin[1] << 8) | (pin[2] << 16) | (pin[3] << 24); +#endif + + val <<= 32; + val |= next; + bits += 32; + + if (unlikely (pin < pinend)) + { + val >>= (pinend - pin) * 8; + bits -= (pinend - pin) * 8; + } + + *ppin = pin; + *pval = val; + *pbits = bits; + return 1; +} + +/* Initialize backward fetching when the bitstream starts with a 1 bit in the + last byte in memory (which is the first one that we read). This is used by + zstd decompression. Returns 1 on success, 0 on error. */ + +static int +elf_fetch_backward_init (const unsigned char **ppin, + const unsigned char *pinend, + uint64_t *pval, unsigned int *pbits) +{ + const unsigned char *pin; + unsigned int stream_start; + uint64_t val; + unsigned int bits; + + pin = *ppin; + stream_start = (unsigned int)*pin; + if (unlikely (stream_start == 0)) + { + elf_uncompress_failed (); + return 0; + } + val = 0; + bits = 0; + + /* Align to a 32-bit boundary. */ + while ((((uintptr_t)pin) & 3) != 0) + { + val <<= 8; + val |= (uint64_t)*pin; + bits += 8; + --pin; + } + + val <<= 8; + val |= (uint64_t)*pin; + bits += 8; + + *ppin = pin; + *pval = val; + *pbits = bits; + if (!elf_fetch_bits_backward (ppin, pinend, pval, pbits)) + return 0; + + *pbits -= __builtin_clz (stream_start) - (sizeof (unsigned int) - 1) * 8 + 1; + + if (!elf_fetch_bits_backward (ppin, pinend, pval, pbits)) + return 0; + + return 1; +} + +/* Huffman code tables, like the rest of the zlib format, are defined + by RFC 1951. We store a Huffman code table as a series of tables + stored sequentially in memory. Each entry in a table is 16 bits. + The first, main, table has 256 entries. It is followed by a set of + secondary tables of length 2 to 128 entries. The maximum length of + a code sequence in the deflate format is 15 bits, so that is all we + need. Each secondary table has an index, which is the offset of + the table in the overall memory storage. + + The deflate format says that all codes of a given bit length are + lexicographically consecutive. Perhaps we could have 130 values + that require a 15-bit code, perhaps requiring three secondary + tables of size 128. I don't know if this is actually possible, but + it suggests that the maximum size required for secondary tables is + 3 * 128 + 3 * 64 ... == 768. The zlib enough program reports 660 + as the maximum. We permit 768, since in addition to the 256 for + the primary table, with two bytes per entry, and with the two + tables we need, that gives us a page. + + A single table entry needs to store a value or (for the main table + only) the index and size of a secondary table. Values range from 0 + to 285, inclusive. Secondary table indexes, per above, range from + 0 to 510. For a value we need to store the number of bits we need + to determine that value (one value may appear multiple times in the + table), which is 1 to 8. For a secondary table we need to store + the number of bits used to index into the table, which is 1 to 7. + And of course we need 1 bit to decide whether we have a value or a + secondary table index. So each entry needs 9 bits for value/table + index, 3 bits for size, 1 bit what it is. For simplicity we use 16 + bits per entry. */ + +/* Number of entries we allocate to for one code table. We get a page + for the two code tables we need. */ + +#define ZLIB_HUFFMAN_TABLE_SIZE (1024) + +/* Bit masks and shifts for the values in the table. */ + +#define ZLIB_HUFFMAN_VALUE_MASK 0x01ff +#define ZLIB_HUFFMAN_BITS_SHIFT 9 +#define ZLIB_HUFFMAN_BITS_MASK 0x7 +#define ZLIB_HUFFMAN_SECONDARY_SHIFT 12 + +/* For working memory while inflating we need two code tables, we need + an array of code lengths (max value 15, so we use unsigned char), + and an array of unsigned shorts used while building a table. The + latter two arrays must be large enough to hold the maximum number + of code lengths, which RFC 1951 defines as 286 + 30. */ + +#define ZLIB_TABLE_SIZE \ + (2 * ZLIB_HUFFMAN_TABLE_SIZE * sizeof (uint16_t) \ + + (286 + 30) * sizeof (uint16_t) \ + + (286 + 30) * sizeof (unsigned char)) + +#define ZLIB_TABLE_CODELEN_OFFSET \ + (2 * ZLIB_HUFFMAN_TABLE_SIZE * sizeof (uint16_t) \ + + (286 + 30) * sizeof (uint16_t)) + +#define ZLIB_TABLE_WORK_OFFSET \ + (2 * ZLIB_HUFFMAN_TABLE_SIZE * sizeof (uint16_t)) + +#ifdef BACKTRACE_GENERATE_FIXED_HUFFMAN_TABLE + +/* Used by the main function that generates the fixed table to learn + the table size. */ +static size_t final_next_secondary; + +#endif + +/* Build a Huffman code table from an array of lengths in CODES of + length CODES_LEN. The table is stored into *TABLE. ZDEBUG_TABLE + is the same as for elf_zlib_inflate, used to find some work space. + Returns 1 on success, 0 on error. */ + +static int +elf_zlib_inflate_table (unsigned char *codes, size_t codes_len, + uint16_t *zdebug_table, uint16_t *table) +{ + uint16_t count[16]; + uint16_t start[16]; + uint16_t prev[16]; + uint16_t firstcode[7]; + uint16_t *next; + size_t i; + size_t j; + unsigned int code; + size_t next_secondary; + + /* Count the number of code of each length. Set NEXT[val] to be the + next value after VAL with the same bit length. */ + + next = (uint16_t *) (((unsigned char *) zdebug_table) + + ZLIB_TABLE_WORK_OFFSET); + + memset (&count[0], 0, 16 * sizeof (uint16_t)); + for (i = 0; i < codes_len; ++i) + { + if (unlikely (codes[i] >= 16)) + { + elf_uncompress_failed (); + return 0; + } + + if (count[codes[i]] == 0) + { + start[codes[i]] = i; + prev[codes[i]] = i; + } + else + { + next[prev[codes[i]]] = i; + prev[codes[i]] = i; + } + + ++count[codes[i]]; + } + + /* For each length, fill in the table for the codes of that + length. */ + + memset (table, 0, ZLIB_HUFFMAN_TABLE_SIZE * sizeof (uint16_t)); + + /* Handle the values that do not require a secondary table. */ + + code = 0; + for (j = 1; j <= 8; ++j) + { + unsigned int jcnt; + unsigned int val; + + jcnt = count[j]; + if (jcnt == 0) + continue; + + if (unlikely (jcnt > (1U << j))) + { + elf_uncompress_failed (); + return 0; + } + + /* There are JCNT values that have this length, the values + starting from START[j] continuing through NEXT[VAL]. Those + values are assigned consecutive values starting at CODE. */ + + val = start[j]; + for (i = 0; i < jcnt; ++i) + { + uint16_t tval; + size_t ind; + unsigned int incr; + + /* In the compressed bit stream, the value VAL is encoded as + J bits with the value C. */ + + if (unlikely ((val & ~ZLIB_HUFFMAN_VALUE_MASK) != 0)) + { + elf_uncompress_failed (); + return 0; + } + + tval = val | ((j - 1) << ZLIB_HUFFMAN_BITS_SHIFT); + + /* The table lookup uses 8 bits. If J is less than 8, we + don't know what the other bits will be. We need to fill + in all possibilities in the table. Since the Huffman + code is unambiguous, those entries can't be used for any + other code. */ + + for (ind = code; ind < 0x100; ind += 1 << j) + { + if (unlikely (table[ind] != 0)) + { + elf_uncompress_failed (); + return 0; + } + table[ind] = tval; + } + + /* Advance to the next value with this length. */ + if (i + 1 < jcnt) + val = next[val]; + + /* The Huffman codes are stored in the bitstream with the + most significant bit first, as is required to make them + unambiguous. The effect is that when we read them from + the bitstream we see the bit sequence in reverse order: + the most significant bit of the Huffman code is the least + significant bit of the value we read from the bitstream. + That means that to make our table lookups work, we need + to reverse the bits of CODE. Since reversing bits is + tedious and in general requires using a table, we instead + increment CODE in reverse order. That is, if the number + of bits we are currently using, here named J, is 3, we + count as 000, 100, 010, 110, 001, 101, 011, 111, which is + to say the numbers from 0 to 7 but with the bits + reversed. Going to more bits, aka incrementing J, + effectively just adds more zero bits as the beginning, + and as such does not change the numeric value of CODE. + + To increment CODE of length J in reverse order, find the + most significant zero bit and set it to one while + clearing all higher bits. In other words, add 1 modulo + 2^J, only reversed. */ + + incr = 1U << (j - 1); + while ((code & incr) != 0) + incr >>= 1; + if (incr == 0) + code = 0; + else + { + code &= incr - 1; + code += incr; + } + } + } + + /* Handle the values that require a secondary table. */ + + /* Set FIRSTCODE, the number at which the codes start, for each + length. */ + + for (j = 9; j < 16; j++) + { + unsigned int jcnt; + unsigned int k; + + jcnt = count[j]; + if (jcnt == 0) + continue; + + /* There are JCNT values that have this length, the values + starting from START[j]. Those values are assigned + consecutive values starting at CODE. */ + + firstcode[j - 9] = code; + + /* Reverse add JCNT to CODE modulo 2^J. */ + for (k = 0; k < j; ++k) + { + if ((jcnt & (1U << k)) != 0) + { + unsigned int m; + unsigned int bit; + + bit = 1U << (j - k - 1); + for (m = 0; m < j - k; ++m, bit >>= 1) + { + if ((code & bit) == 0) + { + code += bit; + break; + } + code &= ~bit; + } + jcnt &= ~(1U << k); + } + } + if (unlikely (jcnt != 0)) + { + elf_uncompress_failed (); + return 0; + } + } + + /* For J from 9 to 15, inclusive, we store COUNT[J] consecutive + values starting at START[J] with consecutive codes starting at + FIRSTCODE[J - 9]. In the primary table we need to point to the + secondary table, and the secondary table will be indexed by J - 9 + bits. We count down from 15 so that we install the larger + secondary tables first, as the smaller ones may be embedded in + the larger ones. */ + + next_secondary = 0; /* Index of next secondary table (after primary). */ + for (j = 15; j >= 9; j--) + { + unsigned int jcnt; + unsigned int val; + size_t primary; /* Current primary index. */ + size_t secondary; /* Offset to current secondary table. */ + size_t secondary_bits; /* Bit size of current secondary table. */ + + jcnt = count[j]; + if (jcnt == 0) + continue; + + val = start[j]; + code = firstcode[j - 9]; + primary = 0x100; + secondary = 0; + secondary_bits = 0; + for (i = 0; i < jcnt; ++i) + { + uint16_t tval; + size_t ind; + unsigned int incr; + + if ((code & 0xff) != primary) + { + uint16_t tprimary; + + /* Fill in a new primary table entry. */ + + primary = code & 0xff; + + tprimary = table[primary]; + if (tprimary == 0) + { + /* Start a new secondary table. */ + + if (unlikely ((next_secondary & ZLIB_HUFFMAN_VALUE_MASK) + != next_secondary)) + { + elf_uncompress_failed (); + return 0; + } + + secondary = next_secondary; + secondary_bits = j - 8; + next_secondary += 1 << secondary_bits; + table[primary] = (secondary + + ((j - 8) << ZLIB_HUFFMAN_BITS_SHIFT) + + (1U << ZLIB_HUFFMAN_SECONDARY_SHIFT)); + } + else + { + /* There is an existing entry. It had better be a + secondary table with enough bits. */ + if (unlikely ((tprimary + & (1U << ZLIB_HUFFMAN_SECONDARY_SHIFT)) + == 0)) + { + elf_uncompress_failed (); + return 0; + } + secondary = tprimary & ZLIB_HUFFMAN_VALUE_MASK; + secondary_bits = ((tprimary >> ZLIB_HUFFMAN_BITS_SHIFT) + & ZLIB_HUFFMAN_BITS_MASK); + if (unlikely (secondary_bits < j - 8)) + { + elf_uncompress_failed (); + return 0; + } + } + } + + /* Fill in secondary table entries. */ + + tval = val | ((j - 8) << ZLIB_HUFFMAN_BITS_SHIFT); + + for (ind = code >> 8; + ind < (1U << secondary_bits); + ind += 1U << (j - 8)) + { + if (unlikely (table[secondary + 0x100 + ind] != 0)) + { + elf_uncompress_failed (); + return 0; + } + table[secondary + 0x100 + ind] = tval; + } + + if (i + 1 < jcnt) + val = next[val]; + + incr = 1U << (j - 1); + while ((code & incr) != 0) + incr >>= 1; + if (incr == 0) + code = 0; + else + { + code &= incr - 1; + code += incr; + } + } + } + +#ifdef BACKTRACE_GENERATE_FIXED_HUFFMAN_TABLE + final_next_secondary = next_secondary; +#endif + + return 1; +} + +#ifdef BACKTRACE_GENERATE_FIXED_HUFFMAN_TABLE + +/* Used to generate the fixed Huffman table for block type 1. */ + +#include + +static uint16_t table[ZLIB_TABLE_SIZE]; +static unsigned char codes[288]; + +int +main () +{ + size_t i; + + for (i = 0; i <= 143; ++i) + codes[i] = 8; + for (i = 144; i <= 255; ++i) + codes[i] = 9; + for (i = 256; i <= 279; ++i) + codes[i] = 7; + for (i = 280; i <= 287; ++i) + codes[i] = 8; + if (!elf_zlib_inflate_table (&codes[0], 288, &table[0], &table[0])) + { + fprintf (stderr, "elf_zlib_inflate_table failed\n"); + exit (EXIT_FAILURE); + } + + printf ("static const uint16_t elf_zlib_default_table[%#zx] =\n", + final_next_secondary + 0x100); + printf ("{\n"); + for (i = 0; i < final_next_secondary + 0x100; i += 8) + { + size_t j; + + printf (" "); + for (j = i; j < final_next_secondary + 0x100 && j < i + 8; ++j) + printf (" %#x,", table[j]); + printf ("\n"); + } + printf ("};\n"); + printf ("\n"); + + for (i = 0; i < 32; ++i) + codes[i] = 5; + if (!elf_zlib_inflate_table (&codes[0], 32, &table[0], &table[0])) + { + fprintf (stderr, "elf_zlib_inflate_table failed\n"); + exit (EXIT_FAILURE); + } + + printf ("static const uint16_t elf_zlib_default_dist_table[%#zx] =\n", + final_next_secondary + 0x100); + printf ("{\n"); + for (i = 0; i < final_next_secondary + 0x100; i += 8) + { + size_t j; + + printf (" "); + for (j = i; j < final_next_secondary + 0x100 && j < i + 8; ++j) + printf (" %#x,", table[j]); + printf ("\n"); + } + printf ("};\n"); + + return 0; +} + +#endif + +/* The fixed tables generated by the #ifdef'ed out main function + above. */ + +static const uint16_t elf_zlib_default_table[0x170] = +{ + 0xd00, 0xe50, 0xe10, 0xf18, 0xd10, 0xe70, 0xe30, 0x1230, + 0xd08, 0xe60, 0xe20, 0x1210, 0xe00, 0xe80, 0xe40, 0x1250, + 0xd04, 0xe58, 0xe18, 0x1200, 0xd14, 0xe78, 0xe38, 0x1240, + 0xd0c, 0xe68, 0xe28, 0x1220, 0xe08, 0xe88, 0xe48, 0x1260, + 0xd02, 0xe54, 0xe14, 0xf1c, 0xd12, 0xe74, 0xe34, 0x1238, + 0xd0a, 0xe64, 0xe24, 0x1218, 0xe04, 0xe84, 0xe44, 0x1258, + 0xd06, 0xe5c, 0xe1c, 0x1208, 0xd16, 0xe7c, 0xe3c, 0x1248, + 0xd0e, 0xe6c, 0xe2c, 0x1228, 0xe0c, 0xe8c, 0xe4c, 0x1268, + 0xd01, 0xe52, 0xe12, 0xf1a, 0xd11, 0xe72, 0xe32, 0x1234, + 0xd09, 0xe62, 0xe22, 0x1214, 0xe02, 0xe82, 0xe42, 0x1254, + 0xd05, 0xe5a, 0xe1a, 0x1204, 0xd15, 0xe7a, 0xe3a, 0x1244, + 0xd0d, 0xe6a, 0xe2a, 0x1224, 0xe0a, 0xe8a, 0xe4a, 0x1264, + 0xd03, 0xe56, 0xe16, 0xf1e, 0xd13, 0xe76, 0xe36, 0x123c, + 0xd0b, 0xe66, 0xe26, 0x121c, 0xe06, 0xe86, 0xe46, 0x125c, + 0xd07, 0xe5e, 0xe1e, 0x120c, 0xd17, 0xe7e, 0xe3e, 0x124c, + 0xd0f, 0xe6e, 0xe2e, 0x122c, 0xe0e, 0xe8e, 0xe4e, 0x126c, + 0xd00, 0xe51, 0xe11, 0xf19, 0xd10, 0xe71, 0xe31, 0x1232, + 0xd08, 0xe61, 0xe21, 0x1212, 0xe01, 0xe81, 0xe41, 0x1252, + 0xd04, 0xe59, 0xe19, 0x1202, 0xd14, 0xe79, 0xe39, 0x1242, + 0xd0c, 0xe69, 0xe29, 0x1222, 0xe09, 0xe89, 0xe49, 0x1262, + 0xd02, 0xe55, 0xe15, 0xf1d, 0xd12, 0xe75, 0xe35, 0x123a, + 0xd0a, 0xe65, 0xe25, 0x121a, 0xe05, 0xe85, 0xe45, 0x125a, + 0xd06, 0xe5d, 0xe1d, 0x120a, 0xd16, 0xe7d, 0xe3d, 0x124a, + 0xd0e, 0xe6d, 0xe2d, 0x122a, 0xe0d, 0xe8d, 0xe4d, 0x126a, + 0xd01, 0xe53, 0xe13, 0xf1b, 0xd11, 0xe73, 0xe33, 0x1236, + 0xd09, 0xe63, 0xe23, 0x1216, 0xe03, 0xe83, 0xe43, 0x1256, + 0xd05, 0xe5b, 0xe1b, 0x1206, 0xd15, 0xe7b, 0xe3b, 0x1246, + 0xd0d, 0xe6b, 0xe2b, 0x1226, 0xe0b, 0xe8b, 0xe4b, 0x1266, + 0xd03, 0xe57, 0xe17, 0xf1f, 0xd13, 0xe77, 0xe37, 0x123e, + 0xd0b, 0xe67, 0xe27, 0x121e, 0xe07, 0xe87, 0xe47, 0x125e, + 0xd07, 0xe5f, 0xe1f, 0x120e, 0xd17, 0xe7f, 0xe3f, 0x124e, + 0xd0f, 0xe6f, 0xe2f, 0x122e, 0xe0f, 0xe8f, 0xe4f, 0x126e, + 0x290, 0x291, 0x292, 0x293, 0x294, 0x295, 0x296, 0x297, + 0x298, 0x299, 0x29a, 0x29b, 0x29c, 0x29d, 0x29e, 0x29f, + 0x2a0, 0x2a1, 0x2a2, 0x2a3, 0x2a4, 0x2a5, 0x2a6, 0x2a7, + 0x2a8, 0x2a9, 0x2aa, 0x2ab, 0x2ac, 0x2ad, 0x2ae, 0x2af, + 0x2b0, 0x2b1, 0x2b2, 0x2b3, 0x2b4, 0x2b5, 0x2b6, 0x2b7, + 0x2b8, 0x2b9, 0x2ba, 0x2bb, 0x2bc, 0x2bd, 0x2be, 0x2bf, + 0x2c0, 0x2c1, 0x2c2, 0x2c3, 0x2c4, 0x2c5, 0x2c6, 0x2c7, + 0x2c8, 0x2c9, 0x2ca, 0x2cb, 0x2cc, 0x2cd, 0x2ce, 0x2cf, + 0x2d0, 0x2d1, 0x2d2, 0x2d3, 0x2d4, 0x2d5, 0x2d6, 0x2d7, + 0x2d8, 0x2d9, 0x2da, 0x2db, 0x2dc, 0x2dd, 0x2de, 0x2df, + 0x2e0, 0x2e1, 0x2e2, 0x2e3, 0x2e4, 0x2e5, 0x2e6, 0x2e7, + 0x2e8, 0x2e9, 0x2ea, 0x2eb, 0x2ec, 0x2ed, 0x2ee, 0x2ef, + 0x2f0, 0x2f1, 0x2f2, 0x2f3, 0x2f4, 0x2f5, 0x2f6, 0x2f7, + 0x2f8, 0x2f9, 0x2fa, 0x2fb, 0x2fc, 0x2fd, 0x2fe, 0x2ff, +}; + +static const uint16_t elf_zlib_default_dist_table[0x100] = +{ + 0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c, + 0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e, + 0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d, + 0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f, + 0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c, + 0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e, + 0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d, + 0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f, + 0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c, + 0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e, + 0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d, + 0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f, + 0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c, + 0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e, + 0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d, + 0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f, + 0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c, + 0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e, + 0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d, + 0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f, + 0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c, + 0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e, + 0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d, + 0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f, + 0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c, + 0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e, + 0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d, + 0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f, + 0x800, 0x810, 0x808, 0x818, 0x804, 0x814, 0x80c, 0x81c, + 0x802, 0x812, 0x80a, 0x81a, 0x806, 0x816, 0x80e, 0x81e, + 0x801, 0x811, 0x809, 0x819, 0x805, 0x815, 0x80d, 0x81d, + 0x803, 0x813, 0x80b, 0x81b, 0x807, 0x817, 0x80f, 0x81f, +}; + +/* Inflate a zlib stream from PIN/SIN to POUT/SOUT. Return 1 on + success, 0 on some error parsing the stream. */ + +static int +elf_zlib_inflate (const unsigned char *pin, size_t sin, uint16_t *zdebug_table, + unsigned char *pout, size_t sout) +{ + unsigned char *porigout; + const unsigned char *pinend; + unsigned char *poutend; + + /* We can apparently see multiple zlib streams concatenated + together, so keep going as long as there is something to read. + The last 4 bytes are the checksum. */ + porigout = pout; + pinend = pin + sin; + poutend = pout + sout; + while ((pinend - pin) > 4) + { + uint64_t val; + unsigned int bits; + int last; + + /* Read the two byte zlib header. */ + + if (unlikely ((pin[0] & 0xf) != 8)) /* 8 is zlib encoding. */ + { + /* Unknown compression method. */ + elf_uncompress_failed (); + return 0; + } + if (unlikely ((pin[0] >> 4) > 7)) + { + /* Window size too large. Other than this check, we don't + care about the window size. */ + elf_uncompress_failed (); + return 0; + } + if (unlikely ((pin[1] & 0x20) != 0)) + { + /* Stream expects a predefined dictionary, but we have no + dictionary. */ + elf_uncompress_failed (); + return 0; + } + val = (pin[0] << 8) | pin[1]; + if (unlikely (val % 31 != 0)) + { + /* Header check failure. */ + elf_uncompress_failed (); + return 0; + } + pin += 2; + + /* Align PIN to a 32-bit boundary. */ + + val = 0; + bits = 0; + while ((((uintptr_t) pin) & 3) != 0) + { + val |= (uint64_t)*pin << bits; + bits += 8; + ++pin; + } + + /* Read blocks until one is marked last. */ + + last = 0; + + while (!last) + { + unsigned int type; + const uint16_t *tlit; + const uint16_t *tdist; + + if (!elf_fetch_bits (&pin, pinend, &val, &bits)) + return 0; + + last = val & 1; + type = (val >> 1) & 3; + val >>= 3; + bits -= 3; + + if (unlikely (type == 3)) + { + /* Invalid block type. */ + elf_uncompress_failed (); + return 0; + } + + if (type == 0) + { + uint16_t len; + uint16_t lenc; + + /* An uncompressed block. */ + + /* If we've read ahead more than a byte, back up. */ + while (bits >= 8) + { + --pin; + bits -= 8; + } + + val = 0; + bits = 0; + if (unlikely ((pinend - pin) < 4)) + { + /* Missing length. */ + elf_uncompress_failed (); + return 0; + } + len = pin[0] | (pin[1] << 8); + lenc = pin[2] | (pin[3] << 8); + pin += 4; + lenc = ~lenc; + if (unlikely (len != lenc)) + { + /* Corrupt data. */ + elf_uncompress_failed (); + return 0; + } + if (unlikely (len > (unsigned int) (pinend - pin) + || len > (unsigned int) (poutend - pout))) + { + /* Not enough space in buffers. */ + elf_uncompress_failed (); + return 0; + } + memcpy (pout, pin, len); + pout += len; + pin += len; + + /* Align PIN. */ + while ((((uintptr_t) pin) & 3) != 0) + { + val |= (uint64_t)*pin << bits; + bits += 8; + ++pin; + } + + /* Go around to read the next block. */ + continue; + } + + if (type == 1) + { + tlit = elf_zlib_default_table; + tdist = elf_zlib_default_dist_table; + } + else + { + unsigned int nlit; + unsigned int ndist; + unsigned int nclen; + unsigned char codebits[19]; + unsigned char *plenbase; + unsigned char *plen; + unsigned char *plenend; + + /* Read a Huffman encoding table. The various magic + numbers here are from RFC 1951. */ + + if (!elf_fetch_bits (&pin, pinend, &val, &bits)) + return 0; + + nlit = (val & 0x1f) + 257; + val >>= 5; + ndist = (val & 0x1f) + 1; + val >>= 5; + nclen = (val & 0xf) + 4; + val >>= 4; + bits -= 14; + if (unlikely (nlit > 286 || ndist > 30)) + { + /* Values out of range. */ + elf_uncompress_failed (); + return 0; + } + + /* Read and build the table used to compress the + literal, length, and distance codes. */ + + memset(&codebits[0], 0, 19); + + /* There are always at least 4 elements in the + table. */ + + if (!elf_fetch_bits (&pin, pinend, &val, &bits)) + return 0; + + codebits[16] = val & 7; + codebits[17] = (val >> 3) & 7; + codebits[18] = (val >> 6) & 7; + codebits[0] = (val >> 9) & 7; + val >>= 12; + bits -= 12; + + if (nclen == 4) + goto codebitsdone; + + codebits[8] = val & 7; + val >>= 3; + bits -= 3; + + if (nclen == 5) + goto codebitsdone; + + if (!elf_fetch_bits (&pin, pinend, &val, &bits)) + return 0; + + codebits[7] = val & 7; + val >>= 3; + bits -= 3; + + if (nclen == 6) + goto codebitsdone; + + codebits[9] = val & 7; + val >>= 3; + bits -= 3; + + if (nclen == 7) + goto codebitsdone; + + codebits[6] = val & 7; + val >>= 3; + bits -= 3; + + if (nclen == 8) + goto codebitsdone; + + codebits[10] = val & 7; + val >>= 3; + bits -= 3; + + if (nclen == 9) + goto codebitsdone; + + codebits[5] = val & 7; + val >>= 3; + bits -= 3; + + if (nclen == 10) + goto codebitsdone; + + if (!elf_fetch_bits (&pin, pinend, &val, &bits)) + return 0; + + codebits[11] = val & 7; + val >>= 3; + bits -= 3; + + if (nclen == 11) + goto codebitsdone; + + codebits[4] = val & 7; + val >>= 3; + bits -= 3; + + if (nclen == 12) + goto codebitsdone; + + codebits[12] = val & 7; + val >>= 3; + bits -= 3; + + if (nclen == 13) + goto codebitsdone; + + codebits[3] = val & 7; + val >>= 3; + bits -= 3; + + if (nclen == 14) + goto codebitsdone; + + codebits[13] = val & 7; + val >>= 3; + bits -= 3; + + if (nclen == 15) + goto codebitsdone; + + if (!elf_fetch_bits (&pin, pinend, &val, &bits)) + return 0; + + codebits[2] = val & 7; + val >>= 3; + bits -= 3; + + if (nclen == 16) + goto codebitsdone; + + codebits[14] = val & 7; + val >>= 3; + bits -= 3; + + if (nclen == 17) + goto codebitsdone; + + codebits[1] = val & 7; + val >>= 3; + bits -= 3; + + if (nclen == 18) + goto codebitsdone; + + codebits[15] = val & 7; + val >>= 3; + bits -= 3; + + codebitsdone: + + if (!elf_zlib_inflate_table (codebits, 19, zdebug_table, + zdebug_table)) + return 0; + + /* Read the compressed bit lengths of the literal, + length, and distance codes. We have allocated space + at the end of zdebug_table to hold them. */ + + plenbase = (((unsigned char *) zdebug_table) + + ZLIB_TABLE_CODELEN_OFFSET); + plen = plenbase; + plenend = plen + nlit + ndist; + while (plen < plenend) + { + uint16_t t; + unsigned int b; + uint16_t v; + + if (!elf_fetch_bits (&pin, pinend, &val, &bits)) + return 0; + + t = zdebug_table[val & 0xff]; + + /* The compression here uses bit lengths up to 7, so + a secondary table is never necessary. */ + if (unlikely ((t & (1U << ZLIB_HUFFMAN_SECONDARY_SHIFT)) + != 0)) + { + elf_uncompress_failed (); + return 0; + } + + b = (t >> ZLIB_HUFFMAN_BITS_SHIFT) & ZLIB_HUFFMAN_BITS_MASK; + val >>= b + 1; + bits -= b + 1; + + v = t & ZLIB_HUFFMAN_VALUE_MASK; + if (v < 16) + *plen++ = v; + else if (v == 16) + { + unsigned int c; + unsigned int prev; + + /* Copy previous entry 3 to 6 times. */ + + if (unlikely (plen == plenbase)) + { + elf_uncompress_failed (); + return 0; + } + + /* We used up to 7 bits since the last + elf_fetch_bits, so we have at least 8 bits + available here. */ + + c = 3 + (val & 0x3); + val >>= 2; + bits -= 2; + if (unlikely ((unsigned int) (plenend - plen) < c)) + { + elf_uncompress_failed (); + return 0; + } + + prev = plen[-1]; + switch (c) + { + case 6: + *plen++ = prev; + ATTRIBUTE_FALLTHROUGH; + case 5: + *plen++ = prev; + ATTRIBUTE_FALLTHROUGH; + case 4: + *plen++ = prev; + } + *plen++ = prev; + *plen++ = prev; + *plen++ = prev; + } + else if (v == 17) + { + unsigned int c; + + /* Store zero 3 to 10 times. */ + + /* We used up to 7 bits since the last + elf_fetch_bits, so we have at least 8 bits + available here. */ + + c = 3 + (val & 0x7); + val >>= 3; + bits -= 3; + if (unlikely ((unsigned int) (plenend - plen) < c)) + { + elf_uncompress_failed (); + return 0; + } + + switch (c) + { + case 10: + *plen++ = 0; + ATTRIBUTE_FALLTHROUGH; + case 9: + *plen++ = 0; + ATTRIBUTE_FALLTHROUGH; + case 8: + *plen++ = 0; + ATTRIBUTE_FALLTHROUGH; + case 7: + *plen++ = 0; + ATTRIBUTE_FALLTHROUGH; + case 6: + *plen++ = 0; + ATTRIBUTE_FALLTHROUGH; + case 5: + *plen++ = 0; + ATTRIBUTE_FALLTHROUGH; + case 4: + *plen++ = 0; + } + *plen++ = 0; + *plen++ = 0; + *plen++ = 0; + } + else if (v == 18) + { + unsigned int c; + + /* Store zero 11 to 138 times. */ + + /* We used up to 7 bits since the last + elf_fetch_bits, so we have at least 8 bits + available here. */ + + c = 11 + (val & 0x7f); + val >>= 7; + bits -= 7; + if (unlikely ((unsigned int) (plenend - plen) < c)) + { + elf_uncompress_failed (); + return 0; + } + + memset (plen, 0, c); + plen += c; + } + else + { + elf_uncompress_failed (); + return 0; + } + } + + /* Make sure that the stop code can appear. */ + + plen = plenbase; + if (unlikely (plen[256] == 0)) + { + elf_uncompress_failed (); + return 0; + } + + /* Build the decompression tables. */ + + if (!elf_zlib_inflate_table (plen, nlit, zdebug_table, + zdebug_table)) + return 0; + if (!elf_zlib_inflate_table (plen + nlit, ndist, zdebug_table, + (zdebug_table + + ZLIB_HUFFMAN_TABLE_SIZE))) + return 0; + tlit = zdebug_table; + tdist = zdebug_table + ZLIB_HUFFMAN_TABLE_SIZE; + } + + /* Inflate values until the end of the block. This is the + main loop of the inflation code. */ + + while (1) + { + uint16_t t; + unsigned int b; + uint16_t v; + unsigned int lit; + + if (!elf_fetch_bits (&pin, pinend, &val, &bits)) + return 0; + + t = tlit[val & 0xff]; + b = (t >> ZLIB_HUFFMAN_BITS_SHIFT) & ZLIB_HUFFMAN_BITS_MASK; + v = t & ZLIB_HUFFMAN_VALUE_MASK; + + if ((t & (1U << ZLIB_HUFFMAN_SECONDARY_SHIFT)) == 0) + { + lit = v; + val >>= b + 1; + bits -= b + 1; + } + else + { + t = tlit[v + 0x100 + ((val >> 8) & ((1U << b) - 1))]; + b = (t >> ZLIB_HUFFMAN_BITS_SHIFT) & ZLIB_HUFFMAN_BITS_MASK; + lit = t & ZLIB_HUFFMAN_VALUE_MASK; + val >>= b + 8; + bits -= b + 8; + } + + if (lit < 256) + { + if (unlikely (pout == poutend)) + { + elf_uncompress_failed (); + return 0; + } + + *pout++ = lit; + + /* We will need to write the next byte soon. We ask + for high temporal locality because we will write + to the whole cache line soon. */ + __builtin_prefetch (pout, 1, 3); + } + else if (lit == 256) + { + /* The end of the block. */ + break; + } + else + { + unsigned int dist; + unsigned int len; + + /* Convert lit into a length. */ + + if (lit < 265) + len = lit - 257 + 3; + else if (lit == 285) + len = 258; + else if (unlikely (lit > 285)) + { + elf_uncompress_failed (); + return 0; + } + else + { + unsigned int extra; + + if (!elf_fetch_bits (&pin, pinend, &val, &bits)) + return 0; + + /* This is an expression for the table of length + codes in RFC 1951 3.2.5. */ + lit -= 265; + extra = (lit >> 2) + 1; + len = (lit & 3) << extra; + len += 11; + len += ((1U << (extra - 1)) - 1) << 3; + len += val & ((1U << extra) - 1); + val >>= extra; + bits -= extra; + } + + if (!elf_fetch_bits (&pin, pinend, &val, &bits)) + return 0; + + t = tdist[val & 0xff]; + b = (t >> ZLIB_HUFFMAN_BITS_SHIFT) & ZLIB_HUFFMAN_BITS_MASK; + v = t & ZLIB_HUFFMAN_VALUE_MASK; + + if ((t & (1U << ZLIB_HUFFMAN_SECONDARY_SHIFT)) == 0) + { + dist = v; + val >>= b + 1; + bits -= b + 1; + } + else + { + t = tdist[v + 0x100 + ((val >> 8) & ((1U << b) - 1))]; + b = ((t >> ZLIB_HUFFMAN_BITS_SHIFT) + & ZLIB_HUFFMAN_BITS_MASK); + dist = t & ZLIB_HUFFMAN_VALUE_MASK; + val >>= b + 8; + bits -= b + 8; + } + + /* Convert dist to a distance. */ + + if (dist == 0) + { + /* A distance of 1. A common case, meaning + repeat the last character LEN times. */ + + if (unlikely (pout == porigout)) + { + elf_uncompress_failed (); + return 0; + } + + if (unlikely ((unsigned int) (poutend - pout) < len)) + { + elf_uncompress_failed (); + return 0; + } + + memset (pout, pout[-1], len); + pout += len; + } + else if (unlikely (dist > 29)) + { + elf_uncompress_failed (); + return 0; + } + else + { + if (dist < 4) + dist = dist + 1; + else + { + unsigned int extra; + + if (!elf_fetch_bits (&pin, pinend, &val, &bits)) + return 0; + + /* This is an expression for the table of + distance codes in RFC 1951 3.2.5. */ + dist -= 4; + extra = (dist >> 1) + 1; + dist = (dist & 1) << extra; + dist += 5; + dist += ((1U << (extra - 1)) - 1) << 2; + dist += val & ((1U << extra) - 1); + val >>= extra; + bits -= extra; + } + + /* Go back dist bytes, and copy len bytes from + there. */ + + if (unlikely ((unsigned int) (pout - porigout) < dist)) + { + elf_uncompress_failed (); + return 0; + } + + if (unlikely ((unsigned int) (poutend - pout) < len)) + { + elf_uncompress_failed (); + return 0; + } + + if (dist >= len) + { + memcpy (pout, pout - dist, len); + pout += len; + } + else + { + while (len > 0) + { + unsigned int copy; + + copy = len < dist ? len : dist; + memcpy (pout, pout - dist, copy); + len -= copy; + pout += copy; + } + } + } + } + } + } + } + + /* We should have filled the output buffer. */ + if (unlikely (pout != poutend)) + { + elf_uncompress_failed (); + return 0; + } + + return 1; +} + +/* Verify the zlib checksum. The checksum is in the 4 bytes at + CHECKBYTES, and the uncompressed data is at UNCOMPRESSED / + UNCOMPRESSED_SIZE. Returns 1 on success, 0 on failure. */ + +static int +elf_zlib_verify_checksum (const unsigned char *checkbytes, + const unsigned char *uncompressed, + size_t uncompressed_size) +{ + unsigned int i; + unsigned int cksum; + const unsigned char *p; + uint32_t s1; + uint32_t s2; + size_t hsz; + + cksum = 0; + for (i = 0; i < 4; i++) + cksum = (cksum << 8) | checkbytes[i]; + + s1 = 1; + s2 = 0; + + /* Minimize modulo operations. */ + + p = uncompressed; + hsz = uncompressed_size; + while (hsz >= 5552) + { + for (i = 0; i < 5552; i += 16) + { + /* Manually unroll loop 16 times. */ + s1 = s1 + *p++; + s2 = s2 + s1; + s1 = s1 + *p++; + s2 = s2 + s1; + s1 = s1 + *p++; + s2 = s2 + s1; + s1 = s1 + *p++; + s2 = s2 + s1; + s1 = s1 + *p++; + s2 = s2 + s1; + s1 = s1 + *p++; + s2 = s2 + s1; + s1 = s1 + *p++; + s2 = s2 + s1; + s1 = s1 + *p++; + s2 = s2 + s1; + s1 = s1 + *p++; + s2 = s2 + s1; + s1 = s1 + *p++; + s2 = s2 + s1; + s1 = s1 + *p++; + s2 = s2 + s1; + s1 = s1 + *p++; + s2 = s2 + s1; + s1 = s1 + *p++; + s2 = s2 + s1; + s1 = s1 + *p++; + s2 = s2 + s1; + s1 = s1 + *p++; + s2 = s2 + s1; + s1 = s1 + *p++; + s2 = s2 + s1; + } + hsz -= 5552; + s1 %= 65521; + s2 %= 65521; + } + + while (hsz >= 16) + { + /* Manually unroll loop 16 times. */ + s1 = s1 + *p++; + s2 = s2 + s1; + s1 = s1 + *p++; + s2 = s2 + s1; + s1 = s1 + *p++; + s2 = s2 + s1; + s1 = s1 + *p++; + s2 = s2 + s1; + s1 = s1 + *p++; + s2 = s2 + s1; + s1 = s1 + *p++; + s2 = s2 + s1; + s1 = s1 + *p++; + s2 = s2 + s1; + s1 = s1 + *p++; + s2 = s2 + s1; + s1 = s1 + *p++; + s2 = s2 + s1; + s1 = s1 + *p++; + s2 = s2 + s1; + s1 = s1 + *p++; + s2 = s2 + s1; + s1 = s1 + *p++; + s2 = s2 + s1; + s1 = s1 + *p++; + s2 = s2 + s1; + s1 = s1 + *p++; + s2 = s2 + s1; + s1 = s1 + *p++; + s2 = s2 + s1; + s1 = s1 + *p++; + s2 = s2 + s1; + + hsz -= 16; + } + + for (i = 0; i < hsz; ++i) + { + s1 = s1 + *p++; + s2 = s2 + s1; + } + + s1 %= 65521; + s2 %= 65521; + + if (unlikely ((s2 << 16) + s1 != cksum)) + { + elf_uncompress_failed (); + return 0; + } + + return 1; +} + +/* Inflate a zlib stream from PIN/SIN to POUT/SOUT, and verify the + checksum. Return 1 on success, 0 on error. */ + +static int +elf_zlib_inflate_and_verify (const unsigned char *pin, size_t sin, + uint16_t *zdebug_table, unsigned char *pout, + size_t sout) +{ + if (!elf_zlib_inflate (pin, sin, zdebug_table, pout, sout)) + return 0; + if (!elf_zlib_verify_checksum (pin + sin - 4, pout, sout)) + return 0; + return 1; +} + +/* For working memory during zstd compression, we need + - a literal length FSE table: 512 64-bit values == 4096 bytes + - a match length FSE table: 512 64-bit values == 4096 bytes + - a offset FSE table: 256 64-bit values == 2048 bytes + - a Huffman tree: 2048 uint16_t values == 4096 bytes + - scratch space, one of + - to build an FSE table: 512 uint16_t values == 1024 bytes + - to build a Huffman tree: 512 uint16_t + 256 uint32_t == 2048 bytes +*/ + +#define ZSTD_TABLE_SIZE \ + (2 * 512 * sizeof (struct elf_zstd_fse_baseline_entry) \ + + 256 * sizeof (struct elf_zstd_fse_baseline_entry) \ + + 2048 * sizeof (uint16_t) \ + + 512 * sizeof (uint16_t) + 256 * sizeof (uint32_t)) + +#define ZSTD_TABLE_LITERAL_FSE_OFFSET (0) + +#define ZSTD_TABLE_MATCH_FSE_OFFSET \ + (512 * sizeof (struct elf_zstd_fse_baseline_entry)) + +#define ZSTD_TABLE_OFFSET_FSE_OFFSET \ + (ZSTD_TABLE_MATCH_FSE_OFFSET \ + + 512 * sizeof (struct elf_zstd_fse_baseline_entry)) + +#define ZSTD_TABLE_HUFFMAN_OFFSET \ + (ZSTD_TABLE_OFFSET_FSE_OFFSET \ + + 256 * sizeof (struct elf_zstd_fse_baseline_entry)) + +#define ZSTD_TABLE_WORK_OFFSET \ + (ZSTD_TABLE_HUFFMAN_OFFSET + 2048 * sizeof (uint16_t)) + +/* An entry in a zstd FSE table. */ + +struct elf_zstd_fse_entry +{ + /* The value that this FSE entry represents. */ + unsigned char symbol; + /* The number of bits to read to determine the next state. */ + unsigned char bits; + /* Add the bits to this base to get the next state. */ + uint16_t base; +}; + +static int +elf_zstd_build_fse (const int16_t *, int, uint16_t *, int, + struct elf_zstd_fse_entry *); + +/* Read a zstd FSE table and build the decoding table in *TABLE, updating *PPIN + as it reads. ZDEBUG_TABLE is scratch space; it must be enough for 512 + uint16_t values (1024 bytes). MAXIDX is the maximum number of symbols + permitted. *TABLE_BITS is the maximum number of bits for symbols in the + table: the size of *TABLE is at least 1 << *TABLE_BITS. This updates + *TABLE_BITS to the actual number of bits. Returns 1 on success, 0 on + error. */ + +static int +elf_zstd_read_fse (const unsigned char **ppin, const unsigned char *pinend, + uint16_t *zdebug_table, int maxidx, + struct elf_zstd_fse_entry *table, int *table_bits) +{ + const unsigned char *pin; + int16_t *norm; + uint16_t *next; + uint64_t val; + unsigned int bits; + int accuracy_log; + uint32_t remaining; + uint32_t threshold; + int bits_needed; + int idx; + int prev0; + + pin = *ppin; + + norm = (int16_t *) zdebug_table; + next = zdebug_table + 256; + + if (unlikely (pin + 3 >= pinend)) + { + elf_uncompress_failed (); + return 0; + } + + /* Align PIN to a 32-bit boundary. */ + + val = 0; + bits = 0; + while ((((uintptr_t) pin) & 3) != 0) + { + val |= (uint64_t)*pin << bits; + bits += 8; + ++pin; + } + + if (!elf_fetch_bits (&pin, pinend, &val, &bits)) + return 0; + + accuracy_log = (val & 0xf) + 5; + if (accuracy_log > *table_bits) + { + elf_uncompress_failed (); + return 0; + } + *table_bits = accuracy_log; + val >>= 4; + bits -= 4; + + /* This code is mostly copied from the reference implementation. */ + + /* The number of remaining probabilities, plus 1. This sets the number of + bits that need to be read for the next value. */ + remaining = (1 << accuracy_log) + 1; + + /* The current difference between small and large values, which depends on + the number of remaining values. Small values use one less bit. */ + threshold = 1 << accuracy_log; + + /* The number of bits used to compute threshold. */ + bits_needed = accuracy_log + 1; + + /* The next character value. */ + idx = 0; + + /* Whether the last count was 0. */ + prev0 = 0; + + while (remaining > 1 && idx <= maxidx) + { + uint32_t max; + int32_t count; + + if (!elf_fetch_bits (&pin, pinend, &val, &bits)) + return 0; + + if (prev0) + { + int zidx; + + /* Previous count was 0, so there is a 2-bit repeat flag. If the + 2-bit flag is 0b11, it adds 3 and then there is another repeat + flag. */ + zidx = idx; + while ((val & 0xfff) == 0xfff) + { + zidx += 3 * 6; + val >>= 12; + bits -= 12; + if (!elf_fetch_bits (&pin, pinend, &val, &bits)) + return 0; + } + while ((val & 3) == 3) + { + zidx += 3; + val >>= 2; + bits -= 2; + if (!elf_fetch_bits (&pin, pinend, &val, &bits)) + return 0; + } + /* We have at least 13 bits here, don't need to fetch. */ + zidx += val & 3; + val >>= 2; + bits -= 2; + + if (unlikely (zidx > maxidx)) + { + elf_uncompress_failed (); + return 0; + } + + for (; idx < zidx; idx++) + norm[idx] = 0; + + prev0 = 0; + continue; + } + + max = (2 * threshold - 1) - remaining; + if ((val & (threshold - 1)) < max) + { + /* A small value. */ + count = (int32_t) ((uint32_t) val & (threshold - 1)); + val >>= bits_needed - 1; + bits -= bits_needed - 1; + } + else + { + /* A large value. */ + count = (int32_t) ((uint32_t) val & (2 * threshold - 1)); + if (count >= (int32_t) threshold) + count -= (int32_t) max; + val >>= bits_needed; + bits -= bits_needed; + } + + count--; + if (count >= 0) + remaining -= count; + else + remaining--; + if (unlikely (idx >= 256)) + { + elf_uncompress_failed (); + return 0; + } + norm[idx] = (int16_t) count; + ++idx; + + prev0 = count == 0; + + while (remaining < threshold) + { + bits_needed--; + threshold >>= 1; + } + } + + if (unlikely (remaining != 1)) + { + elf_uncompress_failed (); + return 0; + } + + /* If we've read ahead more than a byte, back up. */ + while (bits >= 8) + { + --pin; + bits -= 8; + } + + *ppin = pin; + + for (; idx <= maxidx; idx++) + norm[idx] = 0; + + return elf_zstd_build_fse (norm, idx, next, *table_bits, table); +} + +/* Build the FSE decoding table from a list of probabilities. This reads from + NORM of length IDX, uses NEXT as scratch space, and writes to *TABLE, whose + size is TABLE_BITS. */ + +static int +elf_zstd_build_fse (const int16_t *norm, int idx, uint16_t *next, + int table_bits, struct elf_zstd_fse_entry *table) +{ + int table_size; + int high_threshold; + int i; + int pos; + int step; + int mask; + + table_size = 1 << table_bits; + high_threshold = table_size - 1; + for (i = 0; i < idx; i++) + { + int16_t n; + + n = norm[i]; + if (n >= 0) + next[i] = (uint16_t) n; + else + { + table[high_threshold].symbol = (unsigned char) i; + high_threshold--; + next[i] = 1; + } + } + + pos = 0; + step = (table_size >> 1) + (table_size >> 3) + 3; + mask = table_size - 1; + for (i = 0; i < idx; i++) + { + int n; + int j; + + n = (int) norm[i]; + for (j = 0; j < n; j++) + { + table[pos].symbol = (unsigned char) i; + pos = (pos + step) & mask; + while (unlikely (pos > high_threshold)) + pos = (pos + step) & mask; + } + } + if (unlikely (pos != 0)) + { + elf_uncompress_failed (); + return 0; + } + + for (i = 0; i < table_size; i++) + { + unsigned char sym; + uint16_t next_state; + int high_bit; + int bits; + + sym = table[i].symbol; + next_state = next[sym]; + ++next[sym]; + + if (next_state == 0) + { + elf_uncompress_failed (); + return 0; + } + high_bit = 31 - __builtin_clz (next_state); + + bits = table_bits - high_bit; + table[i].bits = (unsigned char) bits; + table[i].base = (uint16_t) ((next_state << bits) - table_size); + } + + return 1; +} + +/* Encode the baseline and bits into a single 32-bit value. */ + +#define ZSTD_ENCODE_BASELINE_BITS(baseline, basebits) \ + ((uint32_t)(baseline) | ((uint32_t)(basebits) << 24)) + +#define ZSTD_DECODE_BASELINE(baseline_basebits) \ + ((uint32_t)(baseline_basebits) & 0xffffff) + +#define ZSTD_DECODE_BASEBITS(baseline_basebits) \ + ((uint32_t)(baseline_basebits) >> 24) + +/* Given a literal length code, we need to read a number of bits and add that + to a baseline. For states 0 to 15 the baseline is the state and the number + of bits is zero. */ + +#define ZSTD_LITERAL_LENGTH_BASELINE_OFFSET (16) + +static const uint32_t elf_zstd_literal_length_base[] = +{ + ZSTD_ENCODE_BASELINE_BITS(16, 1), + ZSTD_ENCODE_BASELINE_BITS(18, 1), + ZSTD_ENCODE_BASELINE_BITS(20, 1), + ZSTD_ENCODE_BASELINE_BITS(22, 1), + ZSTD_ENCODE_BASELINE_BITS(24, 2), + ZSTD_ENCODE_BASELINE_BITS(28, 2), + ZSTD_ENCODE_BASELINE_BITS(32, 3), + ZSTD_ENCODE_BASELINE_BITS(40, 3), + ZSTD_ENCODE_BASELINE_BITS(48, 4), + ZSTD_ENCODE_BASELINE_BITS(64, 6), + ZSTD_ENCODE_BASELINE_BITS(128, 7), + ZSTD_ENCODE_BASELINE_BITS(256, 8), + ZSTD_ENCODE_BASELINE_BITS(512, 9), + ZSTD_ENCODE_BASELINE_BITS(1024, 10), + ZSTD_ENCODE_BASELINE_BITS(2048, 11), + ZSTD_ENCODE_BASELINE_BITS(4096, 12), + ZSTD_ENCODE_BASELINE_BITS(8192, 13), + ZSTD_ENCODE_BASELINE_BITS(16384, 14), + ZSTD_ENCODE_BASELINE_BITS(32768, 15), + ZSTD_ENCODE_BASELINE_BITS(65536, 16) +}; + +/* The same applies to match length codes. For states 0 to 31 the baseline is + the state + 3 and the number of bits is zero. */ + +#define ZSTD_MATCH_LENGTH_BASELINE_OFFSET (32) + +static const uint32_t elf_zstd_match_length_base[] = +{ + ZSTD_ENCODE_BASELINE_BITS(35, 1), + ZSTD_ENCODE_BASELINE_BITS(37, 1), + ZSTD_ENCODE_BASELINE_BITS(39, 1), + ZSTD_ENCODE_BASELINE_BITS(41, 1), + ZSTD_ENCODE_BASELINE_BITS(43, 2), + ZSTD_ENCODE_BASELINE_BITS(47, 2), + ZSTD_ENCODE_BASELINE_BITS(51, 3), + ZSTD_ENCODE_BASELINE_BITS(59, 3), + ZSTD_ENCODE_BASELINE_BITS(67, 4), + ZSTD_ENCODE_BASELINE_BITS(83, 4), + ZSTD_ENCODE_BASELINE_BITS(99, 5), + ZSTD_ENCODE_BASELINE_BITS(131, 7), + ZSTD_ENCODE_BASELINE_BITS(259, 8), + ZSTD_ENCODE_BASELINE_BITS(515, 9), + ZSTD_ENCODE_BASELINE_BITS(1027, 10), + ZSTD_ENCODE_BASELINE_BITS(2051, 11), + ZSTD_ENCODE_BASELINE_BITS(4099, 12), + ZSTD_ENCODE_BASELINE_BITS(8195, 13), + ZSTD_ENCODE_BASELINE_BITS(16387, 14), + ZSTD_ENCODE_BASELINE_BITS(32771, 15), + ZSTD_ENCODE_BASELINE_BITS(65539, 16) +}; + +/* An entry in an FSE table used for literal/match/length values. For these we + have to map the symbol to a baseline value, and we have to read zero or more + bits and add that value to the baseline value. Rather than look the values + up in a separate table, we grow the FSE table so that we get better memory + caching. */ + +struct elf_zstd_fse_baseline_entry +{ + /* The baseline for the value that this FSE entry represents.. */ + uint32_t baseline; + /* The number of bits to read to add to the baseline. */ + unsigned char basebits; + /* The number of bits to read to determine the next state. */ + unsigned char bits; + /* Add the bits to this base to get the next state. */ + uint16_t base; +}; + +/* Convert the literal length FSE table FSE_TABLE to an FSE baseline table at + BASELINE_TABLE. Note that FSE_TABLE and BASELINE_TABLE will overlap. */ + +static int +elf_zstd_make_literal_baseline_fse ( + const struct elf_zstd_fse_entry *fse_table, + int table_bits, + struct elf_zstd_fse_baseline_entry *baseline_table) +{ + size_t count; + const struct elf_zstd_fse_entry *pfse; + struct elf_zstd_fse_baseline_entry *pbaseline; + + /* Convert backward to avoid overlap. */ + + count = 1U << table_bits; + pfse = fse_table + count; + pbaseline = baseline_table + count; + while (pfse > fse_table) + { + unsigned char symbol; + unsigned char bits; + uint16_t base; + + --pfse; + --pbaseline; + symbol = pfse->symbol; + bits = pfse->bits; + base = pfse->base; + if (symbol < ZSTD_LITERAL_LENGTH_BASELINE_OFFSET) + { + pbaseline->baseline = (uint32_t)symbol; + pbaseline->basebits = 0; + } + else + { + unsigned int idx; + uint32_t basebits; + + if (unlikely (symbol > 35)) + { + elf_uncompress_failed (); + return 0; + } + idx = symbol - ZSTD_LITERAL_LENGTH_BASELINE_OFFSET; + basebits = elf_zstd_literal_length_base[idx]; + pbaseline->baseline = ZSTD_DECODE_BASELINE(basebits); + pbaseline->basebits = ZSTD_DECODE_BASEBITS(basebits); + } + pbaseline->bits = bits; + pbaseline->base = base; + } + + return 1; +} + +/* Convert the offset length FSE table FSE_TABLE to an FSE baseline table at + BASELINE_TABLE. Note that FSE_TABLE and BASELINE_TABLE will overlap. */ + +static int +elf_zstd_make_offset_baseline_fse ( + const struct elf_zstd_fse_entry *fse_table, + int table_bits, + struct elf_zstd_fse_baseline_entry *baseline_table) +{ + size_t count; + const struct elf_zstd_fse_entry *pfse; + struct elf_zstd_fse_baseline_entry *pbaseline; + + /* Convert backward to avoid overlap. */ + + count = 1U << table_bits; + pfse = fse_table + count; + pbaseline = baseline_table + count; + while (pfse > fse_table) + { + unsigned char symbol; + unsigned char bits; + uint16_t base; + + --pfse; + --pbaseline; + symbol = pfse->symbol; + bits = pfse->bits; + base = pfse->base; + if (unlikely (symbol > 31)) + { + elf_uncompress_failed (); + return 0; + } + + /* The simple way to write this is + + pbaseline->baseline = (uint32_t)1 << symbol; + pbaseline->basebits = symbol; + + That will give us an offset value that corresponds to the one + described in the RFC. However, for offset values > 3, we have to + subtract 3. And for offset values 1, 2, 3 we use a repeated offset. + The baseline is always a power of 2, and is never 0, so for these low + values we will see one entry that is baseline 1, basebits 0, and one + entry that is baseline 2, basebits 1. All other entries will have + baseline >= 4 and basebits >= 2. + + So we can check for RFC offset <= 3 by checking for basebits <= 1. + And that means that we can subtract 3 here and not worry about doing + it in the hot loop. */ + + pbaseline->baseline = (uint32_t)1 << symbol; + if (symbol >= 2) + pbaseline->baseline -= 3; + pbaseline->basebits = symbol; + pbaseline->bits = bits; + pbaseline->base = base; + } + + return 1; +} + +/* Convert the match length FSE table FSE_TABLE to an FSE baseline table at + BASELINE_TABLE. Note that FSE_TABLE and BASELINE_TABLE will overlap. */ + +static int +elf_zstd_make_match_baseline_fse ( + const struct elf_zstd_fse_entry *fse_table, + int table_bits, + struct elf_zstd_fse_baseline_entry *baseline_table) +{ + size_t count; + const struct elf_zstd_fse_entry *pfse; + struct elf_zstd_fse_baseline_entry *pbaseline; + + /* Convert backward to avoid overlap. */ + + count = 1U << table_bits; + pfse = fse_table + count; + pbaseline = baseline_table + count; + while (pfse > fse_table) + { + unsigned char symbol; + unsigned char bits; + uint16_t base; + + --pfse; + --pbaseline; + symbol = pfse->symbol; + bits = pfse->bits; + base = pfse->base; + if (symbol < ZSTD_MATCH_LENGTH_BASELINE_OFFSET) + { + pbaseline->baseline = (uint32_t)symbol + 3; + pbaseline->basebits = 0; + } + else + { + unsigned int idx; + uint32_t basebits; + + if (unlikely (symbol > 52)) + { + elf_uncompress_failed (); + return 0; + } + idx = symbol - ZSTD_MATCH_LENGTH_BASELINE_OFFSET; + basebits = elf_zstd_match_length_base[idx]; + pbaseline->baseline = ZSTD_DECODE_BASELINE(basebits); + pbaseline->basebits = ZSTD_DECODE_BASEBITS(basebits); + } + pbaseline->bits = bits; + pbaseline->base = base; + } + + return 1; +} + +#ifdef BACKTRACE_GENERATE_ZSTD_FSE_TABLES + +/* Used to generate the predefined FSE decoding tables for zstd. */ + +#include + +/* These values are straight from RFC 8878. */ + +static int16_t lit[36] = +{ + 4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 1, 1, 1, 1, + -1,-1,-1,-1 +}; + +static int16_t match[53] = +{ + 1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1,-1, + -1,-1,-1,-1,-1 +}; + +static int16_t offset[29] = +{ + 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1 +}; + +static uint16_t next[256]; + +static void +print_table (const struct elf_zstd_fse_baseline_entry *table, size_t size) +{ + size_t i; + + printf ("{\n"); + for (i = 0; i < size; i += 3) + { + int j; + + printf (" "); + for (j = 0; j < 3 && i + j < size; ++j) + printf (" { %u, %d, %d, %d },", table[i + j].baseline, + table[i + j].basebits, table[i + j].bits, + table[i + j].base); + printf ("\n"); + } + printf ("};\n"); +} + +int +main () +{ + struct elf_zstd_fse_entry lit_table[64]; + struct elf_zstd_fse_baseline_entry lit_baseline[64]; + struct elf_zstd_fse_entry match_table[64]; + struct elf_zstd_fse_baseline_entry match_baseline[64]; + struct elf_zstd_fse_entry offset_table[32]; + struct elf_zstd_fse_baseline_entry offset_baseline[32]; + + if (!elf_zstd_build_fse (lit, sizeof lit / sizeof lit[0], next, + 6, lit_table)) + { + fprintf (stderr, "elf_zstd_build_fse failed\n"); + exit (EXIT_FAILURE); + } + + if (!elf_zstd_make_literal_baseline_fse (lit_table, 6, lit_baseline)) + { + fprintf (stderr, "elf_zstd_make_literal_baseline_fse failed\n"); + exit (EXIT_FAILURE); + } + + printf ("static const struct elf_zstd_fse_baseline_entry " + "elf_zstd_lit_table[64] =\n"); + print_table (lit_baseline, + sizeof lit_baseline / sizeof lit_baseline[0]); + printf ("\n"); + + if (!elf_zstd_build_fse (match, sizeof match / sizeof match[0], next, + 6, match_table)) + { + fprintf (stderr, "elf_zstd_build_fse failed\n"); + exit (EXIT_FAILURE); + } + + if (!elf_zstd_make_match_baseline_fse (match_table, 6, match_baseline)) + { + fprintf (stderr, "elf_zstd_make_match_baseline_fse failed\n"); + exit (EXIT_FAILURE); + } + + printf ("static const struct elf_zstd_fse_baseline_entry " + "elf_zstd_match_table[64] =\n"); + print_table (match_baseline, + sizeof match_baseline / sizeof match_baseline[0]); + printf ("\n"); + + if (!elf_zstd_build_fse (offset, sizeof offset / sizeof offset[0], next, + 5, offset_table)) + { + fprintf (stderr, "elf_zstd_build_fse failed\n"); + exit (EXIT_FAILURE); + } + + if (!elf_zstd_make_offset_baseline_fse (offset_table, 5, offset_baseline)) + { + fprintf (stderr, "elf_zstd_make_offset_baseline_fse failed\n"); + exit (EXIT_FAILURE); + } + + printf ("static const struct elf_zstd_fse_baseline_entry " + "elf_zstd_offset_table[32] =\n"); + print_table (offset_baseline, + sizeof offset_baseline / sizeof offset_baseline[0]); + printf ("\n"); + + return 0; +} + +#endif + +/* The fixed tables generated by the #ifdef'ed out main function + above. */ + +static const struct elf_zstd_fse_baseline_entry elf_zstd_lit_table[64] = +{ + { 0, 0, 4, 0 }, { 0, 0, 4, 16 }, { 1, 0, 5, 32 }, + { 3, 0, 5, 0 }, { 4, 0, 5, 0 }, { 6, 0, 5, 0 }, + { 7, 0, 5, 0 }, { 9, 0, 5, 0 }, { 10, 0, 5, 0 }, + { 12, 0, 5, 0 }, { 14, 0, 6, 0 }, { 16, 1, 5, 0 }, + { 20, 1, 5, 0 }, { 22, 1, 5, 0 }, { 28, 2, 5, 0 }, + { 32, 3, 5, 0 }, { 48, 4, 5, 0 }, { 64, 6, 5, 32 }, + { 128, 7, 5, 0 }, { 256, 8, 6, 0 }, { 1024, 10, 6, 0 }, + { 4096, 12, 6, 0 }, { 0, 0, 4, 32 }, { 1, 0, 4, 0 }, + { 2, 0, 5, 0 }, { 4, 0, 5, 32 }, { 5, 0, 5, 0 }, + { 7, 0, 5, 32 }, { 8, 0, 5, 0 }, { 10, 0, 5, 32 }, + { 11, 0, 5, 0 }, { 13, 0, 6, 0 }, { 16, 1, 5, 32 }, + { 18, 1, 5, 0 }, { 22, 1, 5, 32 }, { 24, 2, 5, 0 }, + { 32, 3, 5, 32 }, { 40, 3, 5, 0 }, { 64, 6, 4, 0 }, + { 64, 6, 4, 16 }, { 128, 7, 5, 32 }, { 512, 9, 6, 0 }, + { 2048, 11, 6, 0 }, { 0, 0, 4, 48 }, { 1, 0, 4, 16 }, + { 2, 0, 5, 32 }, { 3, 0, 5, 32 }, { 5, 0, 5, 32 }, + { 6, 0, 5, 32 }, { 8, 0, 5, 32 }, { 9, 0, 5, 32 }, + { 11, 0, 5, 32 }, { 12, 0, 5, 32 }, { 15, 0, 6, 0 }, + { 18, 1, 5, 32 }, { 20, 1, 5, 32 }, { 24, 2, 5, 32 }, + { 28, 2, 5, 32 }, { 40, 3, 5, 32 }, { 48, 4, 5, 32 }, + { 65536, 16, 6, 0 }, { 32768, 15, 6, 0 }, { 16384, 14, 6, 0 }, + { 8192, 13, 6, 0 }, +}; + +static const struct elf_zstd_fse_baseline_entry elf_zstd_match_table[64] = +{ + { 3, 0, 6, 0 }, { 4, 0, 4, 0 }, { 5, 0, 5, 32 }, + { 6, 0, 5, 0 }, { 8, 0, 5, 0 }, { 9, 0, 5, 0 }, + { 11, 0, 5, 0 }, { 13, 0, 6, 0 }, { 16, 0, 6, 0 }, + { 19, 0, 6, 0 }, { 22, 0, 6, 0 }, { 25, 0, 6, 0 }, + { 28, 0, 6, 0 }, { 31, 0, 6, 0 }, { 34, 0, 6, 0 }, + { 37, 1, 6, 0 }, { 41, 1, 6, 0 }, { 47, 2, 6, 0 }, + { 59, 3, 6, 0 }, { 83, 4, 6, 0 }, { 131, 7, 6, 0 }, + { 515, 9, 6, 0 }, { 4, 0, 4, 16 }, { 5, 0, 4, 0 }, + { 6, 0, 5, 32 }, { 7, 0, 5, 0 }, { 9, 0, 5, 32 }, + { 10, 0, 5, 0 }, { 12, 0, 6, 0 }, { 15, 0, 6, 0 }, + { 18, 0, 6, 0 }, { 21, 0, 6, 0 }, { 24, 0, 6, 0 }, + { 27, 0, 6, 0 }, { 30, 0, 6, 0 }, { 33, 0, 6, 0 }, + { 35, 1, 6, 0 }, { 39, 1, 6, 0 }, { 43, 2, 6, 0 }, + { 51, 3, 6, 0 }, { 67, 4, 6, 0 }, { 99, 5, 6, 0 }, + { 259, 8, 6, 0 }, { 4, 0, 4, 32 }, { 4, 0, 4, 48 }, + { 5, 0, 4, 16 }, { 7, 0, 5, 32 }, { 8, 0, 5, 32 }, + { 10, 0, 5, 32 }, { 11, 0, 5, 32 }, { 14, 0, 6, 0 }, + { 17, 0, 6, 0 }, { 20, 0, 6, 0 }, { 23, 0, 6, 0 }, + { 26, 0, 6, 0 }, { 29, 0, 6, 0 }, { 32, 0, 6, 0 }, + { 65539, 16, 6, 0 }, { 32771, 15, 6, 0 }, { 16387, 14, 6, 0 }, + { 8195, 13, 6, 0 }, { 4099, 12, 6, 0 }, { 2051, 11, 6, 0 }, + { 1027, 10, 6, 0 }, +}; + +static const struct elf_zstd_fse_baseline_entry elf_zstd_offset_table[32] = +{ + { 1, 0, 5, 0 }, { 61, 6, 4, 0 }, { 509, 9, 5, 0 }, + { 32765, 15, 5, 0 }, { 2097149, 21, 5, 0 }, { 5, 3, 5, 0 }, + { 125, 7, 4, 0 }, { 4093, 12, 5, 0 }, { 262141, 18, 5, 0 }, + { 8388605, 23, 5, 0 }, { 29, 5, 5, 0 }, { 253, 8, 4, 0 }, + { 16381, 14, 5, 0 }, { 1048573, 20, 5, 0 }, { 1, 2, 5, 0 }, + { 125, 7, 4, 16 }, { 2045, 11, 5, 0 }, { 131069, 17, 5, 0 }, + { 4194301, 22, 5, 0 }, { 13, 4, 5, 0 }, { 253, 8, 4, 16 }, + { 8189, 13, 5, 0 }, { 524285, 19, 5, 0 }, { 2, 1, 5, 0 }, + { 61, 6, 4, 16 }, { 1021, 10, 5, 0 }, { 65533, 16, 5, 0 }, + { 268435453, 28, 5, 0 }, { 134217725, 27, 5, 0 }, { 67108861, 26, 5, 0 }, + { 33554429, 25, 5, 0 }, { 16777213, 24, 5, 0 }, +}; + +/* Read a zstd Huffman table and build the decoding table in *TABLE, reading + and updating *PPIN. This sets *PTABLE_BITS to the number of bits of the + table, such that the table length is 1 << *TABLE_BITS. ZDEBUG_TABLE is + scratch space; it must be enough for 512 uint16_t values + 256 32-bit values + (2048 bytes). Returns 1 on success, 0 on error. */ + +static int +elf_zstd_read_huff (const unsigned char **ppin, const unsigned char *pinend, + uint16_t *zdebug_table, uint16_t *table, int *ptable_bits) +{ + const unsigned char *pin; + unsigned char hdr; + unsigned char *weights; + size_t count; + uint32_t *weight_mark; + size_t i; + uint32_t weight_mask; + size_t table_bits; + + pin = *ppin; + if (unlikely (pin >= pinend)) + { + elf_uncompress_failed (); + return 0; + } + hdr = *pin; + ++pin; + + weights = (unsigned char *) zdebug_table; + + if (hdr < 128) + { + /* Table is compressed using FSE. */ + + struct elf_zstd_fse_entry *fse_table; + int fse_table_bits; + uint16_t *scratch; + const unsigned char *pfse; + const unsigned char *pback; + uint64_t val; + unsigned int bits; + unsigned int state1, state2; + + /* SCRATCH is used temporarily by elf_zstd_read_fse. It overlaps + WEIGHTS. */ + scratch = zdebug_table; + fse_table = (struct elf_zstd_fse_entry *) (scratch + 512); + fse_table_bits = 6; + + pfse = pin; + if (!elf_zstd_read_fse (&pfse, pinend, scratch, 255, fse_table, + &fse_table_bits)) + return 0; + + if (unlikely (pin + hdr > pinend)) + { + elf_uncompress_failed (); + return 0; + } + + /* We no longer need SCRATCH. Start recording weights. We need up to + 256 bytes of weights and 64 bytes of rank counts, so it won't overlap + FSE_TABLE. */ + + pback = pin + hdr - 1; + + if (!elf_fetch_backward_init (&pback, pfse, &val, &bits)) + return 0; + + bits -= fse_table_bits; + state1 = (val >> bits) & ((1U << fse_table_bits) - 1); + bits -= fse_table_bits; + state2 = (val >> bits) & ((1U << fse_table_bits) - 1); + + /* There are two independent FSE streams, tracked by STATE1 and STATE2. + We decode them alternately. */ + + count = 0; + while (1) + { + struct elf_zstd_fse_entry *pt; + uint64_t v; + + pt = &fse_table[state1]; + + if (unlikely (pin < pinend) && bits < pt->bits) + { + if (unlikely (count >= 254)) + { + elf_uncompress_failed (); + return 0; + } + weights[count] = (unsigned char) pt->symbol; + weights[count + 1] = (unsigned char) fse_table[state2].symbol; + count += 2; + break; + } + + if (unlikely (pt->bits == 0)) + v = 0; + else + { + if (!elf_fetch_bits_backward (&pback, pfse, &val, &bits)) + return 0; + + bits -= pt->bits; + v = (val >> bits) & (((uint64_t)1 << pt->bits) - 1); + } + + state1 = pt->base + v; + + if (unlikely (count >= 255)) + { + elf_uncompress_failed (); + return 0; + } + + weights[count] = pt->symbol; + ++count; + + pt = &fse_table[state2]; + + if (unlikely (pin < pinend && bits < pt->bits)) + { + if (unlikely (count >= 254)) + { + elf_uncompress_failed (); + return 0; + } + weights[count] = (unsigned char) pt->symbol; + weights[count + 1] = (unsigned char) fse_table[state1].symbol; + count += 2; + break; + } + + if (unlikely (pt->bits == 0)) + v = 0; + else + { + if (!elf_fetch_bits_backward (&pback, pfse, &val, &bits)) + return 0; + + bits -= pt->bits; + v = (val >> bits) & (((uint64_t)1 << pt->bits) - 1); + } + + state2 = pt->base + v; + + if (unlikely (count >= 255)) + { + elf_uncompress_failed (); + return 0; + } + + weights[count] = pt->symbol; + ++count; + } + + pin += hdr; + } + else + { + /* Table is not compressed. Each weight is 4 bits. */ + + count = hdr - 127; + if (unlikely (pin + ((count + 1) / 2) >= pinend)) + { + elf_uncompress_failed (); + return 0; + } + for (i = 0; i < count; i += 2) + { + unsigned char b; + + b = *pin; + ++pin; + weights[i] = b >> 4; + weights[i + 1] = b & 0xf; + } + } + + weight_mark = (uint32_t *) (weights + 256); + memset (weight_mark, 0, 13 * sizeof (uint32_t)); + weight_mask = 0; + for (i = 0; i < count; ++i) + { + unsigned char w; + + w = weights[i]; + if (unlikely (w > 12)) + { + elf_uncompress_failed (); + return 0; + } + ++weight_mark[w]; + if (w > 0) + weight_mask += 1U << (w - 1); + } + if (unlikely (weight_mask == 0)) + { + elf_uncompress_failed (); + return 0; + } + + table_bits = 32 - __builtin_clz (weight_mask); + if (unlikely (table_bits > 11)) + { + elf_uncompress_failed (); + return 0; + } + + /* Work out the last weight value, which is omitted because the weights must + sum to a power of two. */ + { + uint32_t left; + uint32_t high_bit; + + left = ((uint32_t)1 << table_bits) - weight_mask; + if (left == 0) + { + elf_uncompress_failed (); + return 0; + } + high_bit = 31 - __builtin_clz (left); + if (((uint32_t)1 << high_bit) != left) + { + elf_uncompress_failed (); + return 0; + } + + if (unlikely (count >= 256)) + { + elf_uncompress_failed (); + return 0; + } + + weights[count] = high_bit + 1; + ++count; + ++weight_mark[high_bit + 1]; + } + + if (weight_mark[1] < 2 || (weight_mark[1] & 1) != 0) + { + elf_uncompress_failed (); + return 0; + } + + /* Change WEIGHT_MARK from a count of weights to the index of the first + symbol for that weight. We shift the indexes to also store how many we + have seen so far, below. */ + { + uint32_t next; + + next = 0; + for (i = 0; i < table_bits; ++i) + { + uint32_t cur; + + cur = next; + next += weight_mark[i + 1] << i; + weight_mark[i + 1] = cur; + } + } + + for (i = 0; i < count; ++i) + { + unsigned char weight; + uint32_t length; + uint16_t tval; + size_t start; + uint32_t j; + + weight = weights[i]; + if (weight == 0) + continue; + + length = 1U << (weight - 1); + tval = (i << 8) | (table_bits + 1 - weight); + start = weight_mark[weight]; + for (j = 0; j < length; ++j) + table[start + j] = tval; + weight_mark[weight] += length; + } + + *ppin = pin; + *ptable_bits = (int)table_bits; + + return 1; +} + +/* Read and decompress the literals and store them ending at POUTEND. This + works because we are going to use all the literals in the output, so they + must fit into the output buffer. HUFFMAN_TABLE, and PHUFFMAN_TABLE_BITS + store the Huffman table across calls. SCRATCH is used to read a Huffman + table. Store the start of the decompressed literals in *PPLIT. Update + *PPIN. Return 1 on success, 0 on error. */ + +static int +elf_zstd_read_literals (const unsigned char **ppin, + const unsigned char *pinend, + unsigned char *pout, + unsigned char *poutend, + uint16_t *scratch, + uint16_t *huffman_table, + int *phuffman_table_bits, + unsigned char **pplit) +{ + const unsigned char *pin; + unsigned char *plit; + unsigned char hdr; + uint32_t regenerated_size; + uint32_t compressed_size; + int streams; + uint32_t total_streams_size; + unsigned int huffman_table_bits; + uint64_t huffman_mask; + + pin = *ppin; + if (unlikely (pin >= pinend)) + { + elf_uncompress_failed (); + return 0; + } + hdr = *pin; + ++pin; + + if ((hdr & 3) == 0 || (hdr & 3) == 1) + { + int raw; + + /* Raw_Literals_Block or RLE_Literals_Block */ + + raw = (hdr & 3) == 0; + + switch ((hdr >> 2) & 3) + { + case 0: case 2: + regenerated_size = hdr >> 3; + break; + case 1: + if (unlikely (pin >= pinend)) + { + elf_uncompress_failed (); + return 0; + } + regenerated_size = (hdr >> 4) + ((uint32_t)(*pin) << 4); + ++pin; + break; + case 3: + if (unlikely (pin + 1 >= pinend)) + { + elf_uncompress_failed (); + return 0; + } + regenerated_size = ((hdr >> 4) + + ((uint32_t)*pin << 4) + + ((uint32_t)pin[1] << 12)); + pin += 2; + break; + default: + elf_uncompress_failed (); + return 0; + } + + if (unlikely ((size_t)(poutend - pout) < regenerated_size)) + { + elf_uncompress_failed (); + return 0; + } + + plit = poutend - regenerated_size; + + if (raw) + { + if (unlikely (pin + regenerated_size >= pinend)) + { + elf_uncompress_failed (); + return 0; + } + memcpy (plit, pin, regenerated_size); + pin += regenerated_size; + } + else + { + if (pin >= pinend) + { + elf_uncompress_failed (); + return 0; + } + memset (plit, *pin, regenerated_size); + ++pin; + } + + *ppin = pin; + *pplit = plit; + + return 1; + } + + /* Compressed_Literals_Block or Treeless_Literals_Block */ + + switch ((hdr >> 2) & 3) + { + case 0: case 1: + if (unlikely (pin + 1 >= pinend)) + { + elf_uncompress_failed (); + return 0; + } + regenerated_size = (hdr >> 4) | ((uint32_t)(*pin & 0x3f) << 4); + compressed_size = (uint32_t)*pin >> 6 | ((uint32_t)pin[1] << 2); + pin += 2; + streams = ((hdr >> 2) & 3) == 0 ? 1 : 4; + break; + case 2: + if (unlikely (pin + 2 >= pinend)) + { + elf_uncompress_failed (); + return 0; + } + regenerated_size = (((uint32_t)hdr >> 4) + | ((uint32_t)*pin << 4) + | (((uint32_t)pin[1] & 3) << 12)); + compressed_size = (((uint32_t)pin[1] >> 2) + | ((uint32_t)pin[2] << 6)); + pin += 3; + streams = 4; + break; + case 3: + if (unlikely (pin + 3 >= pinend)) + { + elf_uncompress_failed (); + return 0; + } + regenerated_size = (((uint32_t)hdr >> 4) + | ((uint32_t)*pin << 4) + | (((uint32_t)pin[1] & 0x3f) << 12)); + compressed_size = (((uint32_t)pin[1] >> 6) + | ((uint32_t)pin[2] << 2) + | ((uint32_t)pin[3] << 10)); + pin += 4; + streams = 4; + break; + default: + elf_uncompress_failed (); + return 0; + } + + if (unlikely (pin + compressed_size > pinend)) + { + elf_uncompress_failed (); + return 0; + } + + pinend = pin + compressed_size; + *ppin = pinend; + + if (unlikely ((size_t)(poutend - pout) < regenerated_size)) + { + elf_uncompress_failed (); + return 0; + } + + plit = poutend - regenerated_size; + + *pplit = plit; + + total_streams_size = compressed_size; + if ((hdr & 3) == 2) + { + const unsigned char *ptable; + + /* Compressed_Literals_Block. Read Huffman tree. */ + + ptable = pin; + if (!elf_zstd_read_huff (&ptable, pinend, scratch, huffman_table, + phuffman_table_bits)) + return 0; + + if (unlikely (total_streams_size < (size_t)(ptable - pin))) + { + elf_uncompress_failed (); + return 0; + } + + total_streams_size -= ptable - pin; + pin = ptable; + } + else + { + /* Treeless_Literals_Block. Reuse previous Huffman tree. */ + if (unlikely (*phuffman_table_bits == 0)) + { + elf_uncompress_failed (); + return 0; + } + } + + /* Decompress COMPRESSED_SIZE bytes of data at PIN using the huffman table, + storing REGENERATED_SIZE bytes of decompressed data at PLIT. */ + + huffman_table_bits = (unsigned int)*phuffman_table_bits; + huffman_mask = ((uint64_t)1 << huffman_table_bits) - 1; + + if (streams == 1) + { + const unsigned char *pback; + const unsigned char *pbackend; + uint64_t val; + unsigned int bits; + uint32_t i; + + pback = pin + total_streams_size - 1; + pbackend = pin; + if (!elf_fetch_backward_init (&pback, pbackend, &val, &bits)) + return 0; + + /* This is one of the inner loops of the decompression algorithm, so we + put some effort into optimization. We can't get more than 64 bytes + from a single call to elf_fetch_bits_backward, and we can't subtract + more than 11 bits at a time. */ + + if (regenerated_size >= 64) + { + unsigned char *plitstart; + unsigned char *plitstop; + + plitstart = plit; + plitstop = plit + regenerated_size - 64; + while (plit < plitstop) + { + uint16_t t; + + if (!elf_fetch_bits_backward (&pback, pbackend, &val, &bits)) + return 0; + + if (bits < 16) + break; + + while (bits >= 33) + { + t = huffman_table[(val >> (bits - huffman_table_bits)) + & huffman_mask]; + *plit = t >> 8; + ++plit; + bits -= t & 0xff; + + t = huffman_table[(val >> (bits - huffman_table_bits)) + & huffman_mask]; + *plit = t >> 8; + ++plit; + bits -= t & 0xff; + + t = huffman_table[(val >> (bits - huffman_table_bits)) + & huffman_mask]; + *plit = t >> 8; + ++plit; + bits -= t & 0xff; + } + + while (bits > 11) + { + t = huffman_table[(val >> (bits - huffman_table_bits)) + & huffman_mask]; + *plit = t >> 8; + ++plit; + bits -= t & 0xff; + } + } + + regenerated_size -= plit - plitstart; + } + + for (i = 0; i < regenerated_size; ++i) + { + uint16_t t; + + if (!elf_fetch_bits_backward (&pback, pbackend, &val, &bits)) + return 0; + + if (unlikely (bits < huffman_table_bits)) + { + t = huffman_table[(val << (huffman_table_bits - bits)) + & huffman_mask]; + if (unlikely (bits < (t & 0xff))) + { + elf_uncompress_failed (); + return 0; + } + } + else + t = huffman_table[(val >> (bits - huffman_table_bits)) + & huffman_mask]; + + *plit = t >> 8; + ++plit; + bits -= t & 0xff; + } + + return 1; + } + + { + uint32_t stream_size1, stream_size2, stream_size3, stream_size4; + uint32_t tot; + const unsigned char *pback1, *pback2, *pback3, *pback4; + const unsigned char *pbackend1, *pbackend2, *pbackend3, *pbackend4; + uint64_t val1, val2, val3, val4; + unsigned int bits1, bits2, bits3, bits4; + unsigned char *plit1, *plit2, *plit3, *plit4; + uint32_t regenerated_stream_size; + uint32_t regenerated_stream_size4; + uint16_t t1, t2, t3, t4; + uint32_t i; + uint32_t limit; + + /* Read jump table. */ + if (unlikely (pin + 5 >= pinend)) + { + elf_uncompress_failed (); + return 0; + } + stream_size1 = (uint32_t)*pin | ((uint32_t)pin[1] << 8); + pin += 2; + stream_size2 = (uint32_t)*pin | ((uint32_t)pin[1] << 8); + pin += 2; + stream_size3 = (uint32_t)*pin | ((uint32_t)pin[1] << 8); + pin += 2; + tot = stream_size1 + stream_size2 + stream_size3; + if (unlikely (tot > total_streams_size - 6)) + { + elf_uncompress_failed (); + return 0; + } + stream_size4 = total_streams_size - 6 - tot; + + pback1 = pin + stream_size1 - 1; + pbackend1 = pin; + + pback2 = pback1 + stream_size2; + pbackend2 = pback1 + 1; + + pback3 = pback2 + stream_size3; + pbackend3 = pback2 + 1; + + pback4 = pback3 + stream_size4; + pbackend4 = pback3 + 1; + + if (!elf_fetch_backward_init (&pback1, pbackend1, &val1, &bits1)) + return 0; + if (!elf_fetch_backward_init (&pback2, pbackend2, &val2, &bits2)) + return 0; + if (!elf_fetch_backward_init (&pback3, pbackend3, &val3, &bits3)) + return 0; + if (!elf_fetch_backward_init (&pback4, pbackend4, &val4, &bits4)) + return 0; + + regenerated_stream_size = (regenerated_size + 3) / 4; + + plit1 = plit; + plit2 = plit1 + regenerated_stream_size; + plit3 = plit2 + regenerated_stream_size; + plit4 = plit3 + regenerated_stream_size; + + regenerated_stream_size4 = regenerated_size - regenerated_stream_size * 3; + + /* We can't get more than 64 literal bytes from a single call to + elf_fetch_bits_backward. The fourth stream can be up to 3 bytes less, + so use as the limit. */ + + limit = regenerated_stream_size4 <= 64 ? 0 : regenerated_stream_size4 - 64; + i = 0; + while (i < limit) + { + if (!elf_fetch_bits_backward (&pback1, pbackend1, &val1, &bits1)) + return 0; + if (!elf_fetch_bits_backward (&pback2, pbackend2, &val2, &bits2)) + return 0; + if (!elf_fetch_bits_backward (&pback3, pbackend3, &val3, &bits3)) + return 0; + if (!elf_fetch_bits_backward (&pback4, pbackend4, &val4, &bits4)) + return 0; + + /* We can't subtract more than 11 bits at a time. */ + + do + { + t1 = huffman_table[(val1 >> (bits1 - huffman_table_bits)) + & huffman_mask]; + t2 = huffman_table[(val2 >> (bits2 - huffman_table_bits)) + & huffman_mask]; + t3 = huffman_table[(val3 >> (bits3 - huffman_table_bits)) + & huffman_mask]; + t4 = huffman_table[(val4 >> (bits4 - huffman_table_bits)) + & huffman_mask]; + + *plit1 = t1 >> 8; + ++plit1; + bits1 -= t1 & 0xff; + + *plit2 = t2 >> 8; + ++plit2; + bits2 -= t2 & 0xff; + + *plit3 = t3 >> 8; + ++plit3; + bits3 -= t3 & 0xff; + + *plit4 = t4 >> 8; + ++plit4; + bits4 -= t4 & 0xff; + + ++i; + } + while (bits1 > 11 && bits2 > 11 && bits3 > 11 && bits4 > 11); + } + + while (i < regenerated_stream_size) + { + int use4; + + use4 = i < regenerated_stream_size4; + + if (!elf_fetch_bits_backward (&pback1, pbackend1, &val1, &bits1)) + return 0; + if (!elf_fetch_bits_backward (&pback2, pbackend2, &val2, &bits2)) + return 0; + if (!elf_fetch_bits_backward (&pback3, pbackend3, &val3, &bits3)) + return 0; + if (use4) + { + if (!elf_fetch_bits_backward (&pback4, pbackend4, &val4, &bits4)) + return 0; + } + + if (unlikely (bits1 < huffman_table_bits)) + { + t1 = huffman_table[(val1 << (huffman_table_bits - bits1)) + & huffman_mask]; + if (unlikely (bits1 < (t1 & 0xff))) + { + elf_uncompress_failed (); + return 0; + } + } + else + t1 = huffman_table[(val1 >> (bits1 - huffman_table_bits)) + & huffman_mask]; + + if (unlikely (bits2 < huffman_table_bits)) + { + t2 = huffman_table[(val2 << (huffman_table_bits - bits2)) + & huffman_mask]; + if (unlikely (bits2 < (t2 & 0xff))) + { + elf_uncompress_failed (); + return 0; + } + } + else + t2 = huffman_table[(val2 >> (bits2 - huffman_table_bits)) + & huffman_mask]; + + if (unlikely (bits3 < huffman_table_bits)) + { + t3 = huffman_table[(val3 << (huffman_table_bits - bits3)) + & huffman_mask]; + if (unlikely (bits3 < (t3 & 0xff))) + { + elf_uncompress_failed (); + return 0; + } + } + else + t3 = huffman_table[(val3 >> (bits3 - huffman_table_bits)) + & huffman_mask]; + + if (use4) + { + if (unlikely (bits4 < huffman_table_bits)) + { + t4 = huffman_table[(val4 << (huffman_table_bits - bits4)) + & huffman_mask]; + if (unlikely (bits4 < (t4 & 0xff))) + { + elf_uncompress_failed (); + return 0; + } + } + else + t4 = huffman_table[(val4 >> (bits4 - huffman_table_bits)) + & huffman_mask]; + + *plit4 = t4 >> 8; + ++plit4; + bits4 -= t4 & 0xff; + } + + *plit1 = t1 >> 8; + ++plit1; + bits1 -= t1 & 0xff; + + *plit2 = t2 >> 8; + ++plit2; + bits2 -= t2 & 0xff; + + *plit3 = t3 >> 8; + ++plit3; + bits3 -= t3 & 0xff; + + ++i; + } + } + + return 1; +} + +/* The information used to decompress a sequence code, which can be a literal + length, an offset, or a match length. */ + +struct elf_zstd_seq_decode +{ + const struct elf_zstd_fse_baseline_entry *table; + int table_bits; +}; + +/* Unpack a sequence code compression mode. */ + +static int +elf_zstd_unpack_seq_decode (int mode, + const unsigned char **ppin, + const unsigned char *pinend, + const struct elf_zstd_fse_baseline_entry *predef, + int predef_bits, + uint16_t *scratch, + int maxidx, + struct elf_zstd_fse_baseline_entry *table, + int table_bits, + int (*conv)(const struct elf_zstd_fse_entry *, + int, + struct elf_zstd_fse_baseline_entry *), + struct elf_zstd_seq_decode *decode) +{ + switch (mode) + { + case 0: + decode->table = predef; + decode->table_bits = predef_bits; + break; + + case 1: + { + struct elf_zstd_fse_entry entry; + + if (unlikely (*ppin >= pinend)) + { + elf_uncompress_failed (); + return 0; + } + entry.symbol = **ppin; + ++*ppin; + entry.bits = 0; + entry.base = 0; + decode->table_bits = 0; + if (!conv (&entry, 0, table)) + return 0; + } + break; + + case 2: + { + struct elf_zstd_fse_entry *fse_table; + + /* We use the same space for the simple FSE table and the baseline + table. */ + fse_table = (struct elf_zstd_fse_entry *)table; + decode->table_bits = table_bits; + if (!elf_zstd_read_fse (ppin, pinend, scratch, maxidx, fse_table, + &decode->table_bits)) + return 0; + if (!conv (fse_table, decode->table_bits, table)) + return 0; + decode->table = table; + } + break; + + case 3: + if (unlikely (decode->table_bits == -1)) + { + elf_uncompress_failed (); + return 0; + } + break; + + default: + elf_uncompress_failed (); + return 0; + } + + return 1; +} + +/* Decompress a zstd stream from PIN/SIN to POUT/SOUT. Code based on RFC 8878. + Return 1 on success, 0 on error. */ + +static int +elf_zstd_decompress (const unsigned char *pin, size_t sin, + unsigned char *zdebug_table, unsigned char *pout, + size_t sout) +{ + const unsigned char *pinend; + unsigned char *poutstart; + unsigned char *poutend; + struct elf_zstd_seq_decode literal_decode; + struct elf_zstd_fse_baseline_entry *literal_fse_table; + struct elf_zstd_seq_decode match_decode; + struct elf_zstd_fse_baseline_entry *match_fse_table; + struct elf_zstd_seq_decode offset_decode; + struct elf_zstd_fse_baseline_entry *offset_fse_table; + uint16_t *huffman_table; + int huffman_table_bits; + uint32_t repeated_offset1; + uint32_t repeated_offset2; + uint32_t repeated_offset3; + uint16_t *scratch; + unsigned char hdr; + int has_checksum; + uint64_t content_size; + int last_block; + + pinend = pin + sin; + poutstart = pout; + poutend = pout + sout; + + literal_decode.table = NULL; + literal_decode.table_bits = -1; + literal_fse_table = ((struct elf_zstd_fse_baseline_entry *) + (zdebug_table + ZSTD_TABLE_LITERAL_FSE_OFFSET)); + + match_decode.table = NULL; + match_decode.table_bits = -1; + match_fse_table = ((struct elf_zstd_fse_baseline_entry *) + (zdebug_table + ZSTD_TABLE_MATCH_FSE_OFFSET)); + + offset_decode.table = NULL; + offset_decode.table_bits = -1; + offset_fse_table = ((struct elf_zstd_fse_baseline_entry *) + (zdebug_table + ZSTD_TABLE_OFFSET_FSE_OFFSET)); + huffman_table = ((uint16_t *) + (zdebug_table + ZSTD_TABLE_HUFFMAN_OFFSET)); + huffman_table_bits = 0; + scratch = ((uint16_t *) + (zdebug_table + ZSTD_TABLE_WORK_OFFSET)); + + repeated_offset1 = 1; + repeated_offset2 = 4; + repeated_offset3 = 8; + + if (unlikely (sin < 4)) + { + elf_uncompress_failed (); + return 0; + } + + /* These values are the zstd magic number. */ + if (unlikely (pin[0] != 0x28 + || pin[1] != 0xb5 + || pin[2] != 0x2f + || pin[3] != 0xfd)) + { + elf_uncompress_failed (); + return 0; + } + + pin += 4; + + if (unlikely (pin >= pinend)) + { + elf_uncompress_failed (); + return 0; + } + + hdr = *pin++; + + /* We expect a single frame. */ + if (unlikely ((hdr & (1 << 5)) == 0)) + { + elf_uncompress_failed (); + return 0; + } + /* Reserved bit must be zero. */ + if (unlikely ((hdr & (1 << 3)) != 0)) + { + elf_uncompress_failed (); + return 0; + } + /* We do not expect a dictionary. */ + if (unlikely ((hdr & 3) != 0)) + { + elf_uncompress_failed (); + return 0; + } + has_checksum = (hdr & (1 << 2)) != 0; + switch (hdr >> 6) + { + case 0: + if (unlikely (pin >= pinend)) + { + elf_uncompress_failed (); + return 0; + } + content_size = (uint64_t) *pin++; + break; + case 1: + if (unlikely (pin + 1 >= pinend)) + { + elf_uncompress_failed (); + return 0; + } + content_size = (((uint64_t) pin[0]) | (((uint64_t) pin[1]) << 8)) + 256; + pin += 2; + break; + case 2: + if (unlikely (pin + 3 >= pinend)) + { + elf_uncompress_failed (); + return 0; + } + content_size = ((uint64_t) pin[0] + | (((uint64_t) pin[1]) << 8) + | (((uint64_t) pin[2]) << 16) + | (((uint64_t) pin[3]) << 24)); + pin += 4; + break; + case 3: + if (unlikely (pin + 7 >= pinend)) + { + elf_uncompress_failed (); + return 0; + } + content_size = ((uint64_t) pin[0] + | (((uint64_t) pin[1]) << 8) + | (((uint64_t) pin[2]) << 16) + | (((uint64_t) pin[3]) << 24) + | (((uint64_t) pin[4]) << 32) + | (((uint64_t) pin[5]) << 40) + | (((uint64_t) pin[6]) << 48) + | (((uint64_t) pin[7]) << 56)); + pin += 8; + break; + default: + elf_uncompress_failed (); + return 0; + } + + if (unlikely (content_size != (size_t) content_size + || (size_t) content_size != sout)) + { + elf_uncompress_failed (); + return 0; + } + + last_block = 0; + while (!last_block) + { + uint32_t block_hdr; + int block_type; + uint32_t block_size; + + if (unlikely (pin + 2 >= pinend)) + { + elf_uncompress_failed (); + return 0; + } + block_hdr = ((uint32_t) pin[0] + | (((uint32_t) pin[1]) << 8) + | (((uint32_t) pin[2]) << 16)); + pin += 3; + + last_block = block_hdr & 1; + block_type = (block_hdr >> 1) & 3; + block_size = block_hdr >> 3; + + switch (block_type) + { + case 0: + /* Raw_Block */ + if (unlikely ((size_t) block_size > (size_t) (pinend - pin))) + { + elf_uncompress_failed (); + return 0; + } + if (unlikely ((size_t) block_size > (size_t) (poutend - pout))) + { + elf_uncompress_failed (); + return 0; + } + memcpy (pout, pin, block_size); + pout += block_size; + pin += block_size; + break; + + case 1: + /* RLE_Block */ + if (unlikely (pin >= pinend)) + { + elf_uncompress_failed (); + return 0; + } + if (unlikely ((size_t) block_size > (size_t) (poutend - pout))) + { + elf_uncompress_failed (); + return 0; + } + memset (pout, *pin, block_size); + pout += block_size; + pin++; + break; + + case 2: + { + const unsigned char *pblockend; + unsigned char *plitstack; + unsigned char *plit; + uint32_t literal_count; + unsigned char seq_hdr; + size_t seq_count; + size_t seq; + const unsigned char *pback; + uint64_t val; + unsigned int bits; + unsigned int literal_state; + unsigned int offset_state; + unsigned int match_state; + + /* Compressed_Block */ + if (unlikely ((size_t) block_size > (size_t) (pinend - pin))) + { + elf_uncompress_failed (); + return 0; + } + + pblockend = pin + block_size; + + /* Read the literals into the end of the output space, and leave + PLIT pointing at them. */ + + if (!elf_zstd_read_literals (&pin, pblockend, pout, poutend, + scratch, huffman_table, + &huffman_table_bits, + &plitstack)) + return 0; + plit = plitstack; + literal_count = poutend - plit; + + seq_hdr = *pin; + pin++; + if (seq_hdr < 128) + seq_count = seq_hdr; + else if (seq_hdr < 255) + { + if (unlikely (pin >= pinend)) + { + elf_uncompress_failed (); + return 0; + } + seq_count = ((seq_hdr - 128) << 8) + *pin; + pin++; + } + else + { + if (unlikely (pin + 1 >= pinend)) + { + elf_uncompress_failed (); + return 0; + } + seq_count = *pin + (pin[1] << 8) + 0x7f00; + pin += 2; + } + + if (seq_count > 0) + { + int (*pfn)(const struct elf_zstd_fse_entry *, + int, struct elf_zstd_fse_baseline_entry *); + + if (unlikely (pin >= pinend)) + { + elf_uncompress_failed (); + return 0; + } + seq_hdr = *pin; + ++pin; + + pfn = elf_zstd_make_literal_baseline_fse; + if (!elf_zstd_unpack_seq_decode ((seq_hdr >> 6) & 3, + &pin, pinend, + &elf_zstd_lit_table[0], 6, + scratch, 35, + literal_fse_table, 9, pfn, + &literal_decode)) + return 0; + + pfn = elf_zstd_make_offset_baseline_fse; + if (!elf_zstd_unpack_seq_decode ((seq_hdr >> 4) & 3, + &pin, pinend, + &elf_zstd_offset_table[0], 5, + scratch, 31, + offset_fse_table, 8, pfn, + &offset_decode)) + return 0; + + pfn = elf_zstd_make_match_baseline_fse; + if (!elf_zstd_unpack_seq_decode ((seq_hdr >> 2) & 3, + &pin, pinend, + &elf_zstd_match_table[0], 6, + scratch, 52, + match_fse_table, 9, pfn, + &match_decode)) + return 0; + } + + pback = pblockend - 1; + if (!elf_fetch_backward_init (&pback, pin, &val, &bits)) + return 0; + + bits -= literal_decode.table_bits; + literal_state = ((val >> bits) + & ((1U << literal_decode.table_bits) - 1)); + + if (!elf_fetch_bits_backward (&pback, pin, &val, &bits)) + return 0; + bits -= offset_decode.table_bits; + offset_state = ((val >> bits) + & ((1U << offset_decode.table_bits) - 1)); + + if (!elf_fetch_bits_backward (&pback, pin, &val, &bits)) + return 0; + bits -= match_decode.table_bits; + match_state = ((val >> bits) + & ((1U << match_decode.table_bits) - 1)); + + seq = 0; + while (1) + { + const struct elf_zstd_fse_baseline_entry *pt; + uint32_t offset_basebits; + uint32_t offset_baseline; + uint32_t offset_bits; + uint32_t offset_base; + uint32_t offset; + uint32_t match_baseline; + uint32_t match_bits; + uint32_t match_base; + uint32_t match; + uint32_t literal_baseline; + uint32_t literal_bits; + uint32_t literal_base; + uint32_t literal; + uint32_t need; + uint32_t add; + + pt = &offset_decode.table[offset_state]; + offset_basebits = pt->basebits; + offset_baseline = pt->baseline; + offset_bits = pt->bits; + offset_base = pt->base; + + /* This case can be more than 16 bits, which is all that + elf_fetch_bits_backward promises. */ + need = offset_basebits; + add = 0; + if (unlikely (need > 16)) + { + if (!elf_fetch_bits_backward (&pback, pin, &val, &bits)) + return 0; + bits -= 16; + add = (val >> bits) & ((1U << 16) - 1); + need -= 16; + add <<= need; + } + if (need > 0) + { + if (!elf_fetch_bits_backward (&pback, pin, &val, &bits)) + return 0; + bits -= need; + add += (val >> bits) & ((1U << need) - 1); + } + + offset = offset_baseline + add; + + pt = &match_decode.table[match_state]; + need = pt->basebits; + match_baseline = pt->baseline; + match_bits = pt->bits; + match_base = pt->base; + + add = 0; + if (need > 0) + { + if (!elf_fetch_bits_backward (&pback, pin, &val, &bits)) + return 0; + bits -= need; + add = (val >> bits) & ((1U << need) - 1); + } + + match = match_baseline + add; + + pt = &literal_decode.table[literal_state]; + need = pt->basebits; + literal_baseline = pt->baseline; + literal_bits = pt->bits; + literal_base = pt->base; + + add = 0; + if (need > 0) + { + if (!elf_fetch_bits_backward (&pback, pin, &val, &bits)) + return 0; + bits -= need; + add = (val >> bits) & ((1U << need) - 1); + } + + literal = literal_baseline + add; + + /* See the comment in elf_zstd_make_offset_baseline_fse. */ + if (offset_basebits > 1) + { + repeated_offset3 = repeated_offset2; + repeated_offset2 = repeated_offset1; + repeated_offset1 = offset; + } + else + { + if (unlikely (literal == 0)) + ++offset; + switch (offset) + { + case 1: + offset = repeated_offset1; + break; + case 2: + offset = repeated_offset2; + repeated_offset2 = repeated_offset1; + repeated_offset1 = offset; + break; + case 3: + offset = repeated_offset3; + repeated_offset3 = repeated_offset2; + repeated_offset2 = repeated_offset1; + repeated_offset1 = offset; + break; + case 4: + offset = repeated_offset1 - 1; + repeated_offset3 = repeated_offset2; + repeated_offset2 = repeated_offset1; + repeated_offset1 = offset; + break; + } + } + + ++seq; + if (seq < seq_count) + { + uint32_t v; + + /* Update the three states. */ + + if (!elf_fetch_bits_backward (&pback, pin, &val, &bits)) + return 0; + + need = literal_bits; + bits -= need; + v = (val >> bits) & (((uint32_t)1 << need) - 1); + + literal_state = literal_base + v; + + if (!elf_fetch_bits_backward (&pback, pin, &val, &bits)) + return 0; + + need = match_bits; + bits -= need; + v = (val >> bits) & (((uint32_t)1 << need) - 1); + + match_state = match_base + v; + + if (!elf_fetch_bits_backward (&pback, pin, &val, &bits)) + return 0; + + need = offset_bits; + bits -= need; + v = (val >> bits) & (((uint32_t)1 << need) - 1); + + offset_state = offset_base + v; + } + + /* The next sequence is now in LITERAL, OFFSET, MATCH. */ + + /* Copy LITERAL bytes from the literals. */ + + if (unlikely ((size_t)(poutend - pout) < literal)) + { + elf_uncompress_failed (); + return 0; + } + + if (unlikely (literal_count < literal)) + { + elf_uncompress_failed (); + return 0; + } + + literal_count -= literal; + + /* Often LITERAL is small, so handle small cases quickly. */ + switch (literal) + { + case 8: + *pout++ = *plit++; + /* FALLTHROUGH */ + case 7: + *pout++ = *plit++; + /* FALLTHROUGH */ + case 6: + *pout++ = *plit++; + /* FALLTHROUGH */ + case 5: + *pout++ = *plit++; + /* FALLTHROUGH */ + case 4: + *pout++ = *plit++; + /* FALLTHROUGH */ + case 3: + *pout++ = *plit++; + /* FALLTHROUGH */ + case 2: + *pout++ = *plit++; + /* FALLTHROUGH */ + case 1: + *pout++ = *plit++; + break; + + case 0: + break; + + default: + if (unlikely ((size_t)(plit - pout) < literal)) + { + uint32_t move; + + move = plit - pout; + while (literal > move) + { + memcpy (pout, plit, move); + pout += move; + plit += move; + literal -= move; + } + } + + memcpy (pout, plit, literal); + pout += literal; + plit += literal; + } + + if (match > 0) + { + /* Copy MATCH bytes from the decoded output at OFFSET. */ + + if (unlikely ((size_t)(poutend - pout) < match)) + { + elf_uncompress_failed (); + return 0; + } + + if (unlikely ((size_t)(pout - poutstart) < offset)) + { + elf_uncompress_failed (); + return 0; + } + + if (offset >= match) + { + memcpy (pout, pout - offset, match); + pout += match; + } + else + { + while (match > 0) + { + uint32_t copy; + + copy = match < offset ? match : offset; + memcpy (pout, pout - offset, copy); + match -= copy; + pout += copy; + } + } + } + + if (unlikely (seq >= seq_count)) + { + /* Copy remaining literals. */ + if (literal_count > 0 && plit != pout) + { + if (unlikely ((size_t)(poutend - pout) + < literal_count)) + { + elf_uncompress_failed (); + return 0; + } + + if ((size_t)(plit - pout) < literal_count) + { + uint32_t move; + + move = plit - pout; + while (literal_count > move) + { + memcpy (pout, plit, move); + pout += move; + plit += move; + literal_count -= move; + } + } + + memcpy (pout, plit, literal_count); + } + + pout += literal_count; + + break; + } + } + + pin = pblockend; + } + break; + + case 3: + default: + elf_uncompress_failed (); + return 0; + } + } + + if (has_checksum) + { + if (unlikely (pin + 4 > pinend)) + { + elf_uncompress_failed (); + return 0; + } + + /* We don't currently verify the checksum. Currently running GNU ld with + --compress-debug-sections=zstd does not seem to generate a + checksum. */ + + pin += 4; + } + + if (pin != pinend) + { + elf_uncompress_failed (); + return 0; + } + + return 1; +} + +#define ZDEBUG_TABLE_SIZE \ + (ZLIB_TABLE_SIZE > ZSTD_TABLE_SIZE ? ZLIB_TABLE_SIZE : ZSTD_TABLE_SIZE) + +/* Uncompress the old compressed debug format, the one emitted by + --compress-debug-sections=zlib-gnu. The compressed data is in + COMPRESSED / COMPRESSED_SIZE, and the function writes to + *UNCOMPRESSED / *UNCOMPRESSED_SIZE. ZDEBUG_TABLE is work space to + hold Huffman tables. Returns 0 on error, 1 on successful + decompression or if something goes wrong. In general we try to + carry on, by returning 1, even if we can't decompress. */ + +static int +elf_uncompress_zdebug (struct backtrace_state *state, + const unsigned char *compressed, size_t compressed_size, + uint16_t *zdebug_table, + backtrace_error_callback error_callback, void *data, + unsigned char **uncompressed, size_t *uncompressed_size) +{ + size_t sz; + size_t i; + unsigned char *po; + + *uncompressed = NULL; + *uncompressed_size = 0; + + /* The format starts with the four bytes ZLIB, followed by the 8 + byte length of the uncompressed data in big-endian order, + followed by a zlib stream. */ + + if (compressed_size < 12 || memcmp (compressed, "ZLIB", 4) != 0) + return 1; + + sz = 0; + for (i = 0; i < 8; i++) + sz = (sz << 8) | compressed[i + 4]; + + if (*uncompressed != NULL && *uncompressed_size >= sz) + po = *uncompressed; + else + { + po = (unsigned char *) backtrace_alloc (state, sz, error_callback, data); + if (po == NULL) + return 0; + } + + if (!elf_zlib_inflate_and_verify (compressed + 12, compressed_size - 12, + zdebug_table, po, sz)) + return 1; + + *uncompressed = po; + *uncompressed_size = sz; + + return 1; +} + +/* Uncompress the new compressed debug format, the official standard + ELF approach emitted by --compress-debug-sections=zlib-gabi. The + compressed data is in COMPRESSED / COMPRESSED_SIZE, and the + function writes to *UNCOMPRESSED / *UNCOMPRESSED_SIZE. + ZDEBUG_TABLE is work space as for elf_uncompress_zdebug. Returns 0 + on error, 1 on successful decompression or if something goes wrong. + In general we try to carry on, by returning 1, even if we can't + decompress. */ + +static int +elf_uncompress_chdr (struct backtrace_state *state, + const unsigned char *compressed, size_t compressed_size, + uint16_t *zdebug_table, + backtrace_error_callback error_callback, void *data, + unsigned char **uncompressed, size_t *uncompressed_size) +{ + b_elf_chdr chdr; + char *alc; + size_t alc_len; + unsigned char *po; + + *uncompressed = NULL; + *uncompressed_size = 0; + + /* The format starts with an ELF compression header. */ + if (compressed_size < sizeof (b_elf_chdr)) + return 1; + + /* The lld linker can misalign a compressed section, so we can't safely read + the fields directly as we can for other ELF sections. See + https://github.com/ianlancetaylor/libbacktrace/pull/120. */ + memcpy (&chdr, compressed, sizeof (b_elf_chdr)); + + alc = NULL; + alc_len = 0; + if (*uncompressed != NULL && *uncompressed_size >= chdr.ch_size) + po = *uncompressed; + else + { + alc_len = chdr.ch_size; + alc = (char*)backtrace_alloc (state, alc_len, error_callback, data); + if (alc == NULL) + return 0; + po = (unsigned char *) alc; + } + + switch (chdr.ch_type) + { + case ELFCOMPRESS_ZLIB: + if (!elf_zlib_inflate_and_verify (compressed + sizeof (b_elf_chdr), + compressed_size - sizeof (b_elf_chdr), + zdebug_table, po, chdr.ch_size)) + goto skip; + break; + + case ELFCOMPRESS_ZSTD: + if (!elf_zstd_decompress (compressed + sizeof (b_elf_chdr), + compressed_size - sizeof (b_elf_chdr), + (unsigned char *)zdebug_table, po, + chdr.ch_size)) + goto skip; + break; + + default: + /* Unsupported compression algorithm. */ + goto skip; + } + + *uncompressed = po; + *uncompressed_size = chdr.ch_size; + + return 1; + + skip: + if (alc != NULL && alc_len > 0) + backtrace_free (state, alc, alc_len, error_callback, data); + return 1; +} + +/* This function is a hook for testing the zlib support. It is only + used by tests. */ + +int +backtrace_uncompress_zdebug (struct backtrace_state *state, + const unsigned char *compressed, + size_t compressed_size, + backtrace_error_callback error_callback, + void *data, unsigned char **uncompressed, + size_t *uncompressed_size) +{ + uint16_t *zdebug_table; + int ret; + + zdebug_table = ((uint16_t *) backtrace_alloc (state, ZDEBUG_TABLE_SIZE, + error_callback, data)); + if (zdebug_table == NULL) + return 0; + ret = elf_uncompress_zdebug (state, compressed, compressed_size, + zdebug_table, error_callback, data, + uncompressed, uncompressed_size); + backtrace_free (state, zdebug_table, ZDEBUG_TABLE_SIZE, + error_callback, data); + return ret; +} + +/* This function is a hook for testing the zstd support. It is only used by + tests. */ + +int +backtrace_uncompress_zstd (struct backtrace_state *state, + const unsigned char *compressed, + size_t compressed_size, + backtrace_error_callback error_callback, + void *data, unsigned char *uncompressed, + size_t uncompressed_size) +{ + unsigned char *zdebug_table; + int ret; + + zdebug_table = ((unsigned char *) backtrace_alloc (state, ZDEBUG_TABLE_SIZE, + error_callback, data)); + if (zdebug_table == NULL) + return 0; + ret = elf_zstd_decompress (compressed, compressed_size, + zdebug_table, uncompressed, uncompressed_size); + backtrace_free (state, zdebug_table, ZDEBUG_TABLE_SIZE, + error_callback, data); + return ret; +} + +/* Number of LZMA states. */ +#define LZMA_STATES (12) + +/* Number of LZMA position states. The pb value of the property byte + is the number of bits to include in these states, and the maximum + value of pb is 4. */ +#define LZMA_POS_STATES (16) + +/* Number of LZMA distance states. These are used match distances + with a short match length: up to 4 bytes. */ +#define LZMA_DIST_STATES (4) + +/* Number of LZMA distance slots. LZMA uses six bits to encode larger + match lengths, so 1 << 6 possible probabilities. */ +#define LZMA_DIST_SLOTS (64) + +/* LZMA distances 0 to 3 are encoded directly, larger values use a + probability model. */ +#define LZMA_DIST_MODEL_START (4) + +/* The LZMA probability model ends at 14. */ +#define LZMA_DIST_MODEL_END (14) + +/* LZMA distance slots for distances less than 127. */ +#define LZMA_FULL_DISTANCES (128) + +/* LZMA uses four alignment bits. */ +#define LZMA_ALIGN_SIZE (16) + +/* LZMA match length is encoded with 4, 5, or 10 bits, some of which + are already known. */ +#define LZMA_LEN_LOW_SYMBOLS (8) +#define LZMA_LEN_MID_SYMBOLS (8) +#define LZMA_LEN_HIGH_SYMBOLS (256) + +/* LZMA literal encoding. */ +#define LZMA_LITERAL_CODERS_MAX (16) +#define LZMA_LITERAL_CODER_SIZE (0x300) + +/* LZMA is based on a large set of probabilities, each managed + independently. Each probability is an 11 bit number that we store + in a uint16_t. We use a single large array of probabilities. */ + +/* Lengths of entries in the LZMA probabilities array. The names used + here are copied from the Linux kernel implementation. */ + +#define LZMA_PROB_IS_MATCH_LEN (LZMA_STATES * LZMA_POS_STATES) +#define LZMA_PROB_IS_REP_LEN LZMA_STATES +#define LZMA_PROB_IS_REP0_LEN LZMA_STATES +#define LZMA_PROB_IS_REP1_LEN LZMA_STATES +#define LZMA_PROB_IS_REP2_LEN LZMA_STATES +#define LZMA_PROB_IS_REP0_LONG_LEN (LZMA_STATES * LZMA_POS_STATES) +#define LZMA_PROB_DIST_SLOT_LEN (LZMA_DIST_STATES * LZMA_DIST_SLOTS) +#define LZMA_PROB_DIST_SPECIAL_LEN (LZMA_FULL_DISTANCES - LZMA_DIST_MODEL_END) +#define LZMA_PROB_DIST_ALIGN_LEN LZMA_ALIGN_SIZE +#define LZMA_PROB_MATCH_LEN_CHOICE_LEN 1 +#define LZMA_PROB_MATCH_LEN_CHOICE2_LEN 1 +#define LZMA_PROB_MATCH_LEN_LOW_LEN (LZMA_POS_STATES * LZMA_LEN_LOW_SYMBOLS) +#define LZMA_PROB_MATCH_LEN_MID_LEN (LZMA_POS_STATES * LZMA_LEN_MID_SYMBOLS) +#define LZMA_PROB_MATCH_LEN_HIGH_LEN LZMA_LEN_HIGH_SYMBOLS +#define LZMA_PROB_REP_LEN_CHOICE_LEN 1 +#define LZMA_PROB_REP_LEN_CHOICE2_LEN 1 +#define LZMA_PROB_REP_LEN_LOW_LEN (LZMA_POS_STATES * LZMA_LEN_LOW_SYMBOLS) +#define LZMA_PROB_REP_LEN_MID_LEN (LZMA_POS_STATES * LZMA_LEN_MID_SYMBOLS) +#define LZMA_PROB_REP_LEN_HIGH_LEN LZMA_LEN_HIGH_SYMBOLS +#define LZMA_PROB_LITERAL_LEN \ + (LZMA_LITERAL_CODERS_MAX * LZMA_LITERAL_CODER_SIZE) + +/* Offsets into the LZMA probabilities array. This is mechanically + generated from the above lengths. */ + +#define LZMA_PROB_IS_MATCH_OFFSET 0 +#define LZMA_PROB_IS_REP_OFFSET \ + (LZMA_PROB_IS_MATCH_OFFSET + LZMA_PROB_IS_MATCH_LEN) +#define LZMA_PROB_IS_REP0_OFFSET \ + (LZMA_PROB_IS_REP_OFFSET + LZMA_PROB_IS_REP_LEN) +#define LZMA_PROB_IS_REP1_OFFSET \ + (LZMA_PROB_IS_REP0_OFFSET + LZMA_PROB_IS_REP0_LEN) +#define LZMA_PROB_IS_REP2_OFFSET \ + (LZMA_PROB_IS_REP1_OFFSET + LZMA_PROB_IS_REP1_LEN) +#define LZMA_PROB_IS_REP0_LONG_OFFSET \ + (LZMA_PROB_IS_REP2_OFFSET + LZMA_PROB_IS_REP2_LEN) +#define LZMA_PROB_DIST_SLOT_OFFSET \ + (LZMA_PROB_IS_REP0_LONG_OFFSET + LZMA_PROB_IS_REP0_LONG_LEN) +#define LZMA_PROB_DIST_SPECIAL_OFFSET \ + (LZMA_PROB_DIST_SLOT_OFFSET + LZMA_PROB_DIST_SLOT_LEN) +#define LZMA_PROB_DIST_ALIGN_OFFSET \ + (LZMA_PROB_DIST_SPECIAL_OFFSET + LZMA_PROB_DIST_SPECIAL_LEN) +#define LZMA_PROB_MATCH_LEN_CHOICE_OFFSET \ + (LZMA_PROB_DIST_ALIGN_OFFSET + LZMA_PROB_DIST_ALIGN_LEN) +#define LZMA_PROB_MATCH_LEN_CHOICE2_OFFSET \ + (LZMA_PROB_MATCH_LEN_CHOICE_OFFSET + LZMA_PROB_MATCH_LEN_CHOICE_LEN) +#define LZMA_PROB_MATCH_LEN_LOW_OFFSET \ + (LZMA_PROB_MATCH_LEN_CHOICE2_OFFSET + LZMA_PROB_MATCH_LEN_CHOICE2_LEN) +#define LZMA_PROB_MATCH_LEN_MID_OFFSET \ + (LZMA_PROB_MATCH_LEN_LOW_OFFSET + LZMA_PROB_MATCH_LEN_LOW_LEN) +#define LZMA_PROB_MATCH_LEN_HIGH_OFFSET \ + (LZMA_PROB_MATCH_LEN_MID_OFFSET + LZMA_PROB_MATCH_LEN_MID_LEN) +#define LZMA_PROB_REP_LEN_CHOICE_OFFSET \ + (LZMA_PROB_MATCH_LEN_HIGH_OFFSET + LZMA_PROB_MATCH_LEN_HIGH_LEN) +#define LZMA_PROB_REP_LEN_CHOICE2_OFFSET \ + (LZMA_PROB_REP_LEN_CHOICE_OFFSET + LZMA_PROB_REP_LEN_CHOICE_LEN) +#define LZMA_PROB_REP_LEN_LOW_OFFSET \ + (LZMA_PROB_REP_LEN_CHOICE2_OFFSET + LZMA_PROB_REP_LEN_CHOICE2_LEN) +#define LZMA_PROB_REP_LEN_MID_OFFSET \ + (LZMA_PROB_REP_LEN_LOW_OFFSET + LZMA_PROB_REP_LEN_LOW_LEN) +#define LZMA_PROB_REP_LEN_HIGH_OFFSET \ + (LZMA_PROB_REP_LEN_MID_OFFSET + LZMA_PROB_REP_LEN_MID_LEN) +#define LZMA_PROB_LITERAL_OFFSET \ + (LZMA_PROB_REP_LEN_HIGH_OFFSET + LZMA_PROB_REP_LEN_HIGH_LEN) + +#define LZMA_PROB_TOTAL_COUNT \ + (LZMA_PROB_LITERAL_OFFSET + LZMA_PROB_LITERAL_LEN) + +/* Check that the number of LZMA probabilities is the same as the + Linux kernel implementation. */ + +#if LZMA_PROB_TOTAL_COUNT != 1846 + (1 << 4) * 0x300 + #error Wrong number of LZMA probabilities +#endif + +/* Expressions for the offset in the LZMA probabilities array of a + specific probability. */ + +#define LZMA_IS_MATCH(state, pos) \ + (LZMA_PROB_IS_MATCH_OFFSET + (state) * LZMA_POS_STATES + (pos)) +#define LZMA_IS_REP(state) \ + (LZMA_PROB_IS_REP_OFFSET + (state)) +#define LZMA_IS_REP0(state) \ + (LZMA_PROB_IS_REP0_OFFSET + (state)) +#define LZMA_IS_REP1(state) \ + (LZMA_PROB_IS_REP1_OFFSET + (state)) +#define LZMA_IS_REP2(state) \ + (LZMA_PROB_IS_REP2_OFFSET + (state)) +#define LZMA_IS_REP0_LONG(state, pos) \ + (LZMA_PROB_IS_REP0_LONG_OFFSET + (state) * LZMA_POS_STATES + (pos)) +#define LZMA_DIST_SLOT(dist, slot) \ + (LZMA_PROB_DIST_SLOT_OFFSET + (dist) * LZMA_DIST_SLOTS + (slot)) +#define LZMA_DIST_SPECIAL(dist) \ + (LZMA_PROB_DIST_SPECIAL_OFFSET + (dist)) +#define LZMA_DIST_ALIGN(dist) \ + (LZMA_PROB_DIST_ALIGN_OFFSET + (dist)) +#define LZMA_MATCH_LEN_CHOICE \ + LZMA_PROB_MATCH_LEN_CHOICE_OFFSET +#define LZMA_MATCH_LEN_CHOICE2 \ + LZMA_PROB_MATCH_LEN_CHOICE2_OFFSET +#define LZMA_MATCH_LEN_LOW(pos, sym) \ + (LZMA_PROB_MATCH_LEN_LOW_OFFSET + (pos) * LZMA_LEN_LOW_SYMBOLS + (sym)) +#define LZMA_MATCH_LEN_MID(pos, sym) \ + (LZMA_PROB_MATCH_LEN_MID_OFFSET + (pos) * LZMA_LEN_MID_SYMBOLS + (sym)) +#define LZMA_MATCH_LEN_HIGH(sym) \ + (LZMA_PROB_MATCH_LEN_HIGH_OFFSET + (sym)) +#define LZMA_REP_LEN_CHOICE \ + LZMA_PROB_REP_LEN_CHOICE_OFFSET +#define LZMA_REP_LEN_CHOICE2 \ + LZMA_PROB_REP_LEN_CHOICE2_OFFSET +#define LZMA_REP_LEN_LOW(pos, sym) \ + (LZMA_PROB_REP_LEN_LOW_OFFSET + (pos) * LZMA_LEN_LOW_SYMBOLS + (sym)) +#define LZMA_REP_LEN_MID(pos, sym) \ + (LZMA_PROB_REP_LEN_MID_OFFSET + (pos) * LZMA_LEN_MID_SYMBOLS + (sym)) +#define LZMA_REP_LEN_HIGH(sym) \ + (LZMA_PROB_REP_LEN_HIGH_OFFSET + (sym)) +#define LZMA_LITERAL(code, size) \ + (LZMA_PROB_LITERAL_OFFSET + (code) * LZMA_LITERAL_CODER_SIZE + (size)) + +/* Read an LZMA varint from BUF, reading and updating *POFFSET, + setting *VAL. Returns 0 on error, 1 on success. */ + +static int +elf_lzma_varint (const unsigned char *compressed, size_t compressed_size, + size_t *poffset, uint64_t *val) +{ + size_t off; + int i; + uint64_t v; + unsigned char b; + + off = *poffset; + i = 0; + v = 0; + while (1) + { + if (unlikely (off >= compressed_size)) + { + elf_uncompress_failed (); + return 0; + } + b = compressed[off]; + v |= (b & 0x7f) << (i * 7); + ++off; + if ((b & 0x80) == 0) + { + *poffset = off; + *val = v; + return 1; + } + ++i; + if (unlikely (i >= 9)) + { + elf_uncompress_failed (); + return 0; + } + } +} + +/* Normalize the LZMA range decoder, pulling in an extra input byte if + needed. */ + +static void +elf_lzma_range_normalize (const unsigned char *compressed, + size_t compressed_size, size_t *poffset, + uint32_t *prange, uint32_t *pcode) +{ + if (*prange < (1U << 24)) + { + if (unlikely (*poffset >= compressed_size)) + { + /* We assume this will be caught elsewhere. */ + elf_uncompress_failed (); + return; + } + *prange <<= 8; + *pcode <<= 8; + *pcode += compressed[*poffset]; + ++*poffset; + } +} + +/* Read and return a single bit from the LZMA stream, reading and + updating *PROB. Each bit comes from the range coder. */ + +static int +elf_lzma_bit (const unsigned char *compressed, size_t compressed_size, + uint16_t *prob, size_t *poffset, uint32_t *prange, + uint32_t *pcode) +{ + uint32_t bound; + + elf_lzma_range_normalize (compressed, compressed_size, poffset, + prange, pcode); + bound = (*prange >> 11) * (uint32_t) *prob; + if (*pcode < bound) + { + *prange = bound; + *prob += ((1U << 11) - *prob) >> 5; + return 0; + } + else + { + *prange -= bound; + *pcode -= bound; + *prob -= *prob >> 5; + return 1; + } +} + +/* Read an integer of size BITS from the LZMA stream, most significant + bit first. The bits are predicted using PROBS. */ + +static uint32_t +elf_lzma_integer (const unsigned char *compressed, size_t compressed_size, + uint16_t *probs, uint32_t bits, size_t *poffset, + uint32_t *prange, uint32_t *pcode) +{ + uint32_t sym; + uint32_t i; + + sym = 1; + for (i = 0; i < bits; i++) + { + int bit; + + bit = elf_lzma_bit (compressed, compressed_size, probs + sym, poffset, + prange, pcode); + sym <<= 1; + sym += bit; + } + return sym - (1 << bits); +} + +/* Read an integer of size BITS from the LZMA stream, least + significant bit first. The bits are predicted using PROBS. */ + +static uint32_t +elf_lzma_reverse_integer (const unsigned char *compressed, + size_t compressed_size, uint16_t *probs, + uint32_t bits, size_t *poffset, uint32_t *prange, + uint32_t *pcode) +{ + uint32_t sym; + uint32_t val; + uint32_t i; + + sym = 1; + val = 0; + for (i = 0; i < bits; i++) + { + int bit; + + bit = elf_lzma_bit (compressed, compressed_size, probs + sym, poffset, + prange, pcode); + sym <<= 1; + sym += bit; + val += bit << i; + } + return val; +} + +/* Read a length from the LZMA stream. IS_REP picks either LZMA_MATCH + or LZMA_REP probabilities. */ + +static uint32_t +elf_lzma_len (const unsigned char *compressed, size_t compressed_size, + uint16_t *probs, int is_rep, unsigned int pos_state, + size_t *poffset, uint32_t *prange, uint32_t *pcode) +{ + uint16_t *probs_choice; + uint16_t *probs_sym; + uint32_t bits; + uint32_t len; + + probs_choice = probs + (is_rep + ? LZMA_REP_LEN_CHOICE + : LZMA_MATCH_LEN_CHOICE); + if (elf_lzma_bit (compressed, compressed_size, probs_choice, poffset, + prange, pcode)) + { + probs_choice = probs + (is_rep + ? LZMA_REP_LEN_CHOICE2 + : LZMA_MATCH_LEN_CHOICE2); + if (elf_lzma_bit (compressed, compressed_size, probs_choice, + poffset, prange, pcode)) + { + probs_sym = probs + (is_rep + ? LZMA_REP_LEN_HIGH (0) + : LZMA_MATCH_LEN_HIGH (0)); + bits = 8; + len = 2 + 8 + 8; + } + else + { + probs_sym = probs + (is_rep + ? LZMA_REP_LEN_MID (pos_state, 0) + : LZMA_MATCH_LEN_MID (pos_state, 0)); + bits = 3; + len = 2 + 8; + } + } + else + { + probs_sym = probs + (is_rep + ? LZMA_REP_LEN_LOW (pos_state, 0) + : LZMA_MATCH_LEN_LOW (pos_state, 0)); + bits = 3; + len = 2; + } + + len += elf_lzma_integer (compressed, compressed_size, probs_sym, bits, + poffset, prange, pcode); + return len; +} + +/* Uncompress one LZMA block from a minidebug file. The compressed + data is at COMPRESSED + *POFFSET. Update *POFFSET. Store the data + into the memory at UNCOMPRESSED, size UNCOMPRESSED_SIZE. CHECK is + the stream flag from the xz header. Return 1 on successful + decompression. */ + +static int +elf_uncompress_lzma_block (const unsigned char *compressed, + size_t compressed_size, unsigned char check, + uint16_t *probs, unsigned char *uncompressed, + size_t uncompressed_size, size_t *poffset) +{ + size_t off; + size_t block_header_offset; + size_t block_header_size; + unsigned char block_flags; + uint64_t header_compressed_size; + uint64_t header_uncompressed_size; + unsigned char lzma2_properties; + size_t crc_offset; + uint32_t computed_crc; + uint32_t stream_crc; + size_t uncompressed_offset; + size_t dict_start_offset; + unsigned int lc; + unsigned int lp; + unsigned int pb; + uint32_t range; + uint32_t code; + uint32_t lstate; + uint32_t dist[4]; + + off = *poffset; + block_header_offset = off; + + /* Block header size is a single byte. */ + if (unlikely (off >= compressed_size)) + { + elf_uncompress_failed (); + return 0; + } + block_header_size = (compressed[off] + 1) * 4; + if (unlikely (off + block_header_size > compressed_size)) + { + elf_uncompress_failed (); + return 0; + } + + /* Block flags. */ + block_flags = compressed[off + 1]; + if (unlikely ((block_flags & 0x3c) != 0)) + { + elf_uncompress_failed (); + return 0; + } + + off += 2; + + /* Optional compressed size. */ + header_compressed_size = 0; + if ((block_flags & 0x40) != 0) + { + *poffset = off; + if (!elf_lzma_varint (compressed, compressed_size, poffset, + &header_compressed_size)) + return 0; + off = *poffset; + } + + /* Optional uncompressed size. */ + header_uncompressed_size = 0; + if ((block_flags & 0x80) != 0) + { + *poffset = off; + if (!elf_lzma_varint (compressed, compressed_size, poffset, + &header_uncompressed_size)) + return 0; + off = *poffset; + } + + /* The recipe for creating a minidebug file is to run the xz program + with no arguments, so we expect exactly one filter: lzma2. */ + + if (unlikely ((block_flags & 0x3) != 0)) + { + elf_uncompress_failed (); + return 0; + } + + if (unlikely (off + 2 >= block_header_offset + block_header_size)) + { + elf_uncompress_failed (); + return 0; + } + + /* The filter ID for LZMA2 is 0x21. */ + if (unlikely (compressed[off] != 0x21)) + { + elf_uncompress_failed (); + return 0; + } + ++off; + + /* The size of the filter properties for LZMA2 is 1. */ + if (unlikely (compressed[off] != 1)) + { + elf_uncompress_failed (); + return 0; + } + ++off; + + lzma2_properties = compressed[off]; + ++off; + + if (unlikely (lzma2_properties > 40)) + { + elf_uncompress_failed (); + return 0; + } + + /* The properties describe the dictionary size, but we don't care + what that is. */ + + /* Skip to just before CRC, verifying zero bytes in between. */ + crc_offset = block_header_offset + block_header_size - 4; + if (unlikely (crc_offset + 4 > compressed_size)) + { + elf_uncompress_failed (); + return 0; + } + for (; off < crc_offset; off++) + { + if (compressed[off] != 0) + { + elf_uncompress_failed (); + return 0; + } + } + + /* Block header CRC. */ + computed_crc = elf_crc32 (0, compressed + block_header_offset, + block_header_size - 4); + stream_crc = (compressed[off] + | (compressed[off + 1] << 8) + | (compressed[off + 2] << 16) + | (compressed[off + 3] << 24)); + if (unlikely (computed_crc != stream_crc)) + { + elf_uncompress_failed (); + return 0; + } + off += 4; + + /* Read a sequence of LZMA2 packets. */ + + uncompressed_offset = 0; + dict_start_offset = 0; + lc = 0; + lp = 0; + pb = 0; + lstate = 0; + while (off < compressed_size) + { + unsigned char control; + + range = 0xffffffff; + code = 0; + + control = compressed[off]; + ++off; + if (unlikely (control == 0)) + { + /* End of packets. */ + break; + } + + if (control == 1 || control >= 0xe0) + { + /* Reset dictionary to empty. */ + dict_start_offset = uncompressed_offset; + } + + if (control < 0x80) + { + size_t chunk_size; + + /* The only valid values here are 1 or 2. A 1 means to + reset the dictionary (done above). Then we see an + uncompressed chunk. */ + + if (unlikely (control > 2)) + { + elf_uncompress_failed (); + return 0; + } + + /* An uncompressed chunk is a two byte size followed by + data. */ + + if (unlikely (off + 2 > compressed_size)) + { + elf_uncompress_failed (); + return 0; + } + + chunk_size = compressed[off] << 8; + chunk_size += compressed[off + 1]; + ++chunk_size; + + off += 2; + + if (unlikely (off + chunk_size > compressed_size)) + { + elf_uncompress_failed (); + return 0; + } + if (unlikely (uncompressed_offset + chunk_size > uncompressed_size)) + { + elf_uncompress_failed (); + return 0; + } + + memcpy (uncompressed + uncompressed_offset, compressed + off, + chunk_size); + uncompressed_offset += chunk_size; + off += chunk_size; + } + else + { + size_t uncompressed_chunk_start; + size_t uncompressed_chunk_size; + size_t compressed_chunk_size; + size_t limit; + + /* An LZMA chunk. This starts with an uncompressed size and + a compressed size. */ + + if (unlikely (off + 4 >= compressed_size)) + { + elf_uncompress_failed (); + return 0; + } + + uncompressed_chunk_start = uncompressed_offset; + + uncompressed_chunk_size = (control & 0x1f) << 16; + uncompressed_chunk_size += compressed[off] << 8; + uncompressed_chunk_size += compressed[off + 1]; + ++uncompressed_chunk_size; + + compressed_chunk_size = compressed[off + 2] << 8; + compressed_chunk_size += compressed[off + 3]; + ++compressed_chunk_size; + + off += 4; + + /* Bit 7 (0x80) is set. + Bits 6 and 5 (0x40 and 0x20) are as follows: + 0: don't reset anything + 1: reset state + 2: reset state, read properties + 3: reset state, read properties, reset dictionary (done above) */ + + if (control >= 0xc0) + { + unsigned char props; + + /* Bit 6 is set, read properties. */ + + if (unlikely (off >= compressed_size)) + { + elf_uncompress_failed (); + return 0; + } + props = compressed[off]; + ++off; + if (unlikely (props > (4 * 5 + 4) * 9 + 8)) + { + elf_uncompress_failed (); + return 0; + } + pb = 0; + while (props >= 9 * 5) + { + props -= 9 * 5; + ++pb; + } + lp = 0; + while (props > 9) + { + props -= 9; + ++lp; + } + lc = props; + if (unlikely (lc + lp > 4)) + { + elf_uncompress_failed (); + return 0; + } + } + + if (control >= 0xa0) + { + size_t i; + + /* Bit 5 or 6 is set, reset LZMA state. */ + + lstate = 0; + memset (&dist, 0, sizeof dist); + for (i = 0; i < LZMA_PROB_TOTAL_COUNT; i++) + probs[i] = 1 << 10; + range = 0xffffffff; + code = 0; + } + + /* Read the range code. */ + + if (unlikely (off + 5 > compressed_size)) + { + elf_uncompress_failed (); + return 0; + } + + /* The byte at compressed[off] is ignored for some + reason. */ + + code = ((compressed[off + 1] << 24) + + (compressed[off + 2] << 16) + + (compressed[off + 3] << 8) + + compressed[off + 4]); + off += 5; + + /* This is the main LZMA decode loop. */ + + limit = off + compressed_chunk_size; + *poffset = off; + while (*poffset < limit) + { + unsigned int pos_state; + + if (unlikely (uncompressed_offset + == (uncompressed_chunk_start + + uncompressed_chunk_size))) + { + /* We've decompressed all the expected bytes. */ + break; + } + + pos_state = ((uncompressed_offset - dict_start_offset) + & ((1 << pb) - 1)); + + if (elf_lzma_bit (compressed, compressed_size, + probs + LZMA_IS_MATCH (lstate, pos_state), + poffset, &range, &code)) + { + uint32_t len; + + if (elf_lzma_bit (compressed, compressed_size, + probs + LZMA_IS_REP (lstate), + poffset, &range, &code)) + { + int short_rep; + uint32_t next_dist; + + /* Repeated match. */ + + short_rep = 0; + if (elf_lzma_bit (compressed, compressed_size, + probs + LZMA_IS_REP0 (lstate), + poffset, &range, &code)) + { + if (elf_lzma_bit (compressed, compressed_size, + probs + LZMA_IS_REP1 (lstate), + poffset, &range, &code)) + { + if (elf_lzma_bit (compressed, compressed_size, + probs + LZMA_IS_REP2 (lstate), + poffset, &range, &code)) + { + next_dist = dist[3]; + dist[3] = dist[2]; + } + else + { + next_dist = dist[2]; + } + dist[2] = dist[1]; + } + else + { + next_dist = dist[1]; + } + + dist[1] = dist[0]; + dist[0] = next_dist; + } + else + { + if (!elf_lzma_bit (compressed, compressed_size, + (probs + + LZMA_IS_REP0_LONG (lstate, + pos_state)), + poffset, &range, &code)) + short_rep = 1; + } + + if (lstate < 7) + lstate = short_rep ? 9 : 8; + else + lstate = 11; + + if (short_rep) + len = 1; + else + len = elf_lzma_len (compressed, compressed_size, + probs, 1, pos_state, poffset, + &range, &code); + } + else + { + uint32_t dist_state; + uint32_t dist_slot; + uint16_t *probs_dist; + + /* Match. */ + + if (lstate < 7) + lstate = 7; + else + lstate = 10; + dist[3] = dist[2]; + dist[2] = dist[1]; + dist[1] = dist[0]; + len = elf_lzma_len (compressed, compressed_size, + probs, 0, pos_state, poffset, + &range, &code); + + if (len < 4 + 2) + dist_state = len - 2; + else + dist_state = 3; + probs_dist = probs + LZMA_DIST_SLOT (dist_state, 0); + dist_slot = elf_lzma_integer (compressed, + compressed_size, + probs_dist, 6, + poffset, &range, + &code); + if (dist_slot < LZMA_DIST_MODEL_START) + dist[0] = dist_slot; + else + { + uint32_t limit; + + limit = (dist_slot >> 1) - 1; + dist[0] = 2 + (dist_slot & 1); + if (dist_slot < LZMA_DIST_MODEL_END) + { + dist[0] <<= limit; + probs_dist = (probs + + LZMA_DIST_SPECIAL(dist[0] + - dist_slot + - 1)); + dist[0] += + elf_lzma_reverse_integer (compressed, + compressed_size, + probs_dist, + limit, poffset, + &range, &code); + } + else + { + uint32_t dist0; + uint32_t i; + + dist0 = dist[0]; + for (i = 0; i < limit - 4; i++) + { + uint32_t mask; + + elf_lzma_range_normalize (compressed, + compressed_size, + poffset, + &range, &code); + range >>= 1; + code -= range; + mask = -(code >> 31); + code += range & mask; + dist0 <<= 1; + dist0 += mask + 1; + } + dist0 <<= 4; + probs_dist = probs + LZMA_DIST_ALIGN (0); + dist0 += + elf_lzma_reverse_integer (compressed, + compressed_size, + probs_dist, 4, + poffset, + &range, &code); + dist[0] = dist0; + } + } + } + + if (unlikely (uncompressed_offset + - dict_start_offset < dist[0] + 1)) + { + elf_uncompress_failed (); + return 0; + } + if (unlikely (uncompressed_offset + len > uncompressed_size)) + { + elf_uncompress_failed (); + return 0; + } + + if (dist[0] == 0) + { + /* A common case, meaning repeat the last + character LEN times. */ + memset (uncompressed + uncompressed_offset, + uncompressed[uncompressed_offset - 1], + len); + uncompressed_offset += len; + } + else if (dist[0] + 1 >= len) + { + memcpy (uncompressed + uncompressed_offset, + uncompressed + uncompressed_offset - dist[0] - 1, + len); + uncompressed_offset += len; + } + else + { + while (len > 0) + { + uint32_t copy; + + copy = len < dist[0] + 1 ? len : dist[0] + 1; + memcpy (uncompressed + uncompressed_offset, + (uncompressed + uncompressed_offset + - dist[0] - 1), + copy); + len -= copy; + uncompressed_offset += copy; + } + } + } + else + { + unsigned char prev; + unsigned char low; + size_t high; + uint16_t *lit_probs; + unsigned int sym; + + /* Literal value. */ + + if (uncompressed_offset > 0) + prev = uncompressed[uncompressed_offset - 1]; + else + prev = 0; + low = prev >> (8 - lc); + high = (((uncompressed_offset - dict_start_offset) + & ((1 << lp) - 1)) + << lc); + lit_probs = probs + LZMA_LITERAL (low + high, 0); + if (lstate < 7) + sym = elf_lzma_integer (compressed, compressed_size, + lit_probs, 8, poffset, &range, + &code); + else + { + unsigned int match; + unsigned int bit; + unsigned int match_bit; + unsigned int idx; + + sym = 1; + if (uncompressed_offset >= dist[0] + 1) + match = uncompressed[uncompressed_offset - dist[0] - 1]; + else + match = 0; + match <<= 1; + bit = 0x100; + do + { + match_bit = match & bit; + match <<= 1; + idx = bit + match_bit + sym; + sym <<= 1; + if (elf_lzma_bit (compressed, compressed_size, + lit_probs + idx, poffset, + &range, &code)) + { + ++sym; + bit &= match_bit; + } + else + { + bit &= ~ match_bit; + } + } + while (sym < 0x100); + } + + if (unlikely (uncompressed_offset >= uncompressed_size)) + { + elf_uncompress_failed (); + return 0; + } + + uncompressed[uncompressed_offset] = (unsigned char) sym; + ++uncompressed_offset; + if (lstate <= 3) + lstate = 0; + else if (lstate <= 9) + lstate -= 3; + else + lstate -= 6; + } + } + + elf_lzma_range_normalize (compressed, compressed_size, poffset, + &range, &code); + + off = *poffset; + } + } + + /* We have reached the end of the block. Pad to four byte + boundary. */ + off = (off + 3) &~ (size_t) 3; + if (unlikely (off > compressed_size)) + { + elf_uncompress_failed (); + return 0; + } + + switch (check) + { + case 0: + /* No check. */ + break; + + case 1: + /* CRC32 */ + if (unlikely (off + 4 > compressed_size)) + { + elf_uncompress_failed (); + return 0; + } + computed_crc = elf_crc32 (0, uncompressed, uncompressed_offset); + stream_crc = (compressed[off] + | (compressed[off + 1] << 8) + | (compressed[off + 2] << 16) + | (compressed[off + 3] << 24)); + if (computed_crc != stream_crc) + { + elf_uncompress_failed (); + return 0; + } + off += 4; + break; + + case 4: + /* CRC64. We don't bother computing a CRC64 checksum. */ + if (unlikely (off + 8 > compressed_size)) + { + elf_uncompress_failed (); + return 0; + } + off += 8; + break; + + case 10: + /* SHA. We don't bother computing a SHA checksum. */ + if (unlikely (off + 32 > compressed_size)) + { + elf_uncompress_failed (); + return 0; + } + off += 32; + break; + + default: + elf_uncompress_failed (); + return 0; + } + + *poffset = off; + + return 1; +} + +/* Uncompress LZMA data found in a minidebug file. The minidebug + format is described at + https://sourceware.org/gdb/current/onlinedocs/gdb/MiniDebugInfo.html. + Returns 0 on error, 1 on successful decompression. For this + function we return 0 on failure to decompress, as the calling code + will carry on in that case. */ + +static int +elf_uncompress_lzma (struct backtrace_state *state, + const unsigned char *compressed, size_t compressed_size, + backtrace_error_callback error_callback, void *data, + unsigned char **uncompressed, size_t *uncompressed_size) +{ + size_t header_size; + size_t footer_size; + unsigned char check; + uint32_t computed_crc; + uint32_t stream_crc; + size_t offset; + size_t index_size; + size_t footer_offset; + size_t index_offset; + uint64_t index_compressed_size; + uint64_t index_uncompressed_size; + unsigned char *mem; + uint16_t *probs; + size_t compressed_block_size; + + /* The format starts with a stream header and ends with a stream + footer. */ + header_size = 12; + footer_size = 12; + if (unlikely (compressed_size < header_size + footer_size)) + { + elf_uncompress_failed (); + return 0; + } + + /* The stream header starts with a magic string. */ + if (unlikely (memcmp (compressed, "\375" "7zXZ\0", 6) != 0)) + { + elf_uncompress_failed (); + return 0; + } + + /* Next come stream flags. The first byte is zero, the second byte + is the check. */ + if (unlikely (compressed[6] != 0)) + { + elf_uncompress_failed (); + return 0; + } + check = compressed[7]; + if (unlikely ((check & 0xf8) != 0)) + { + elf_uncompress_failed (); + return 0; + } + + /* Next comes a CRC of the stream flags. */ + computed_crc = elf_crc32 (0, compressed + 6, 2); + stream_crc = (compressed[8] + | (compressed[9] << 8) + | (compressed[10] << 16) + | (compressed[11] << 24)); + if (unlikely (computed_crc != stream_crc)) + { + elf_uncompress_failed (); + return 0; + } + + /* Now that we've parsed the header, parse the footer, so that we + can get the uncompressed size. */ + + /* The footer ends with two magic bytes. */ + + offset = compressed_size; + if (unlikely (memcmp (compressed + offset - 2, "YZ", 2) != 0)) + { + elf_uncompress_failed (); + return 0; + } + offset -= 2; + + /* Before that are the stream flags, which should be the same as the + flags in the header. */ + if (unlikely (compressed[offset - 2] != 0 + || compressed[offset - 1] != check)) + { + elf_uncompress_failed (); + return 0; + } + offset -= 2; + + /* Before that is the size of the index field, which precedes the + footer. */ + index_size = (compressed[offset - 4] + | (compressed[offset - 3] << 8) + | (compressed[offset - 2] << 16) + | (compressed[offset - 1] << 24)); + index_size = (index_size + 1) * 4; + offset -= 4; + + /* Before that is a footer CRC. */ + computed_crc = elf_crc32 (0, compressed + offset, 6); + stream_crc = (compressed[offset - 4] + | (compressed[offset - 3] << 8) + | (compressed[offset - 2] << 16) + | (compressed[offset - 1] << 24)); + if (unlikely (computed_crc != stream_crc)) + { + elf_uncompress_failed (); + return 0; + } + offset -= 4; + + /* The index comes just before the footer. */ + if (unlikely (offset < index_size + header_size)) + { + elf_uncompress_failed (); + return 0; + } + + footer_offset = offset; + offset -= index_size; + index_offset = offset; + + /* The index starts with a zero byte. */ + if (unlikely (compressed[offset] != 0)) + { + elf_uncompress_failed (); + return 0; + } + ++offset; + + /* Next is the number of blocks. We expect zero blocks for an empty + stream, and otherwise a single block. */ + if (unlikely (compressed[offset] == 0)) + { + *uncompressed = NULL; + *uncompressed_size = 0; + return 1; + } + if (unlikely (compressed[offset] != 1)) + { + elf_uncompress_failed (); + return 0; + } + ++offset; + + /* Next is the compressed size and the uncompressed size. */ + if (!elf_lzma_varint (compressed, compressed_size, &offset, + &index_compressed_size)) + return 0; + if (!elf_lzma_varint (compressed, compressed_size, &offset, + &index_uncompressed_size)) + return 0; + + /* Pad to a four byte boundary. */ + offset = (offset + 3) &~ (size_t) 3; + + /* Next is a CRC of the index. */ + computed_crc = elf_crc32 (0, compressed + index_offset, + offset - index_offset); + stream_crc = (compressed[offset] + | (compressed[offset + 1] << 8) + | (compressed[offset + 2] << 16) + | (compressed[offset + 3] << 24)); + if (unlikely (computed_crc != stream_crc)) + { + elf_uncompress_failed (); + return 0; + } + offset += 4; + + /* We should now be back at the footer. */ + if (unlikely (offset != footer_offset)) + { + elf_uncompress_failed (); + return 0; + } + + /* Allocate space to hold the uncompressed data. If we succeed in + uncompressing the LZMA data, we never free this memory. */ + mem = (unsigned char *) backtrace_alloc (state, index_uncompressed_size, + error_callback, data); + if (unlikely (mem == NULL)) + return 0; + *uncompressed = mem; + *uncompressed_size = index_uncompressed_size; + + /* Allocate space for probabilities. */ + probs = ((uint16_t *) + backtrace_alloc (state, + LZMA_PROB_TOTAL_COUNT * sizeof (uint16_t), + error_callback, data)); + if (unlikely (probs == NULL)) + { + backtrace_free (state, mem, index_uncompressed_size, error_callback, + data); + return 0; + } + + /* Uncompress the block, which follows the header. */ + offset = 12; + if (!elf_uncompress_lzma_block (compressed, compressed_size, check, probs, + mem, index_uncompressed_size, &offset)) + { + backtrace_free (state, mem, index_uncompressed_size, error_callback, + data); + return 0; + } + + compressed_block_size = offset - 12; + if (unlikely (compressed_block_size + != ((index_compressed_size + 3) &~ (size_t) 3))) + { + elf_uncompress_failed (); + backtrace_free (state, mem, index_uncompressed_size, error_callback, + data); + return 0; + } + + offset = (offset + 3) &~ (size_t) 3; + if (unlikely (offset != index_offset)) + { + elf_uncompress_failed (); + backtrace_free (state, mem, index_uncompressed_size, error_callback, + data); + return 0; + } + + return 1; +} + +/* This function is a hook for testing the LZMA support. It is only + used by tests. */ + +int +backtrace_uncompress_lzma (struct backtrace_state *state, + const unsigned char *compressed, + size_t compressed_size, + backtrace_error_callback error_callback, + void *data, unsigned char **uncompressed, + size_t *uncompressed_size) +{ + return elf_uncompress_lzma (state, compressed, compressed_size, + error_callback, data, uncompressed, + uncompressed_size); +} + +/* Add the backtrace data for one ELF file. Returns 1 on success, + 0 on failure (in both cases descriptor is closed) or -1 if exe + is non-zero and the ELF file is ET_DYN, which tells the caller that + elf_add will need to be called on the descriptor again after + base_address is determined. */ + +static int +elf_add (struct backtrace_state *state, const char *filename, int descriptor, + const unsigned char *memory, size_t memory_size, + uintptr_t base_address, struct elf_ppc64_opd_data *caller_opd, + backtrace_error_callback error_callback, void *data, + fileline *fileline_fn, int *found_sym, int *found_dwarf, + struct dwarf_data **fileline_entry, int exe, int debuginfo, + const char *with_buildid_data, uint32_t with_buildid_size) +{ + struct elf_view ehdr_view; + b_elf_ehdr ehdr; + off_t shoff; + unsigned int shnum; + unsigned int shstrndx; + struct elf_view shdrs_view; + int shdrs_view_valid; + const b_elf_shdr *shdrs; + const b_elf_shdr *shstrhdr; + size_t shstr_size; + off_t shstr_off; + struct elf_view names_view; + int names_view_valid; + const char *names; + unsigned int symtab_shndx; + unsigned int dynsym_shndx; + unsigned int i; + struct debug_section_info sections[DEBUG_MAX]; + struct debug_section_info zsections[DEBUG_MAX]; + struct elf_view symtab_view; + int symtab_view_valid; + struct elf_view strtab_view; + int strtab_view_valid; + struct elf_view buildid_view; + int buildid_view_valid; + const char *buildid_data; + uint32_t buildid_size; + struct elf_view debuglink_view; + int debuglink_view_valid; + const char *debuglink_name; + uint32_t debuglink_crc; + struct elf_view debugaltlink_view; + int debugaltlink_view_valid; + const char *debugaltlink_name; + const char *debugaltlink_buildid_data; + uint32_t debugaltlink_buildid_size; + struct elf_view gnu_debugdata_view; + int gnu_debugdata_view_valid; + size_t gnu_debugdata_size; + unsigned char *gnu_debugdata_uncompressed; + size_t gnu_debugdata_uncompressed_size; + off_t min_offset; + off_t max_offset; + off_t debug_size; + struct elf_view debug_view; + int debug_view_valid; + unsigned int using_debug_view; + uint16_t *zdebug_table; + struct elf_view split_debug_view[DEBUG_MAX]; + unsigned char split_debug_view_valid[DEBUG_MAX]; + struct elf_ppc64_opd_data opd_data, *opd; + int opd_view_valid; + struct dwarf_sections dwarf_sections; + struct dwarf_data *fileline_altlink = NULL; + + if (!debuginfo) + { + *found_sym = 0; + *found_dwarf = 0; + } + + shdrs_view_valid = 0; + names_view_valid = 0; + symtab_view_valid = 0; + strtab_view_valid = 0; + buildid_view_valid = 0; + buildid_data = NULL; + buildid_size = 0; + debuglink_view_valid = 0; + debuglink_name = NULL; + debuglink_crc = 0; + debugaltlink_view_valid = 0; + debugaltlink_name = NULL; + debugaltlink_buildid_data = NULL; + debugaltlink_buildid_size = 0; + gnu_debugdata_view_valid = 0; + gnu_debugdata_size = 0; + debug_view_valid = 0; + memset (&split_debug_view_valid[0], 0, sizeof split_debug_view_valid); + opd = NULL; + opd_view_valid = 0; + + if (!elf_get_view (state, descriptor, memory, memory_size, 0, sizeof ehdr, + error_callback, data, &ehdr_view)) + goto fail; + + memcpy (&ehdr, ehdr_view.view.data, sizeof ehdr); + + elf_release_view (state, &ehdr_view, error_callback, data); + + if (ehdr.e_ident[EI_MAG0] != ELFMAG0 + || ehdr.e_ident[EI_MAG1] != ELFMAG1 + || ehdr.e_ident[EI_MAG2] != ELFMAG2 + || ehdr.e_ident[EI_MAG3] != ELFMAG3) + { + error_callback (data, "executable file is not ELF", 0); + goto fail; + } + if (ehdr.e_ident[EI_VERSION] != EV_CURRENT) + { + error_callback (data, "executable file is unrecognized ELF version", 0); + goto fail; + } + +#if BACKTRACE_ELF_SIZE == 32 +#define BACKTRACE_ELFCLASS ELFCLASS32 +#else +#define BACKTRACE_ELFCLASS ELFCLASS64 +#endif + + if (ehdr.e_ident[EI_CLASS] != BACKTRACE_ELFCLASS) + { + error_callback (data, "executable file is unexpected ELF class", 0); + goto fail; + } + + if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB + && ehdr.e_ident[EI_DATA] != ELFDATA2MSB) + { + error_callback (data, "executable file has unknown endianness", 0); + goto fail; + } + + /* If the executable is ET_DYN, it is either a PIE, or we are running + directly a shared library with .interp. We need to wait for + dl_iterate_phdr in that case to determine the actual base_address. */ + if (exe && ehdr.e_type == ET_DYN) + return -1; + + shoff = ehdr.e_shoff; + shnum = ehdr.e_shnum; + shstrndx = ehdr.e_shstrndx; + + if ((shnum == 0 || shstrndx == SHN_XINDEX) + && shoff != 0) + { + struct elf_view shdr_view; + const b_elf_shdr *shdr; + + if (!elf_get_view (state, descriptor, memory, memory_size, shoff, + sizeof shdr, error_callback, data, &shdr_view)) + goto fail; + + shdr = (const b_elf_shdr *) shdr_view.view.data; + + if (shnum == 0) + shnum = shdr->sh_size; + + if (shstrndx == SHN_XINDEX) + { + shstrndx = shdr->sh_link; + + /* Versions of the GNU binutils between 2.12 and 2.18 did + not handle objects with more than SHN_LORESERVE sections + correctly. All large section indexes were offset by + 0x100. There is more information at + http://sourceware.org/bugzilla/show_bug.cgi?id-5900 . + Fortunately these object files are easy to detect, as the + GNU binutils always put the section header string table + near the end of the list of sections. Thus if the + section header string table index is larger than the + number of sections, then we know we have to subtract + 0x100 to get the real section index. */ + if (shstrndx >= shnum && shstrndx >= SHN_LORESERVE + 0x100) + shstrndx -= 0x100; + } + + elf_release_view (state, &shdr_view, error_callback, data); + } + + if (shnum == 0 || shstrndx == 0) + goto fail; + + /* To translate PC to file/line when using DWARF, we need to find + the .debug_info and .debug_line sections. */ + + /* Read the section headers, skipping the first one. */ + + if (!elf_get_view (state, descriptor, memory, memory_size, + shoff + sizeof (b_elf_shdr), + (shnum - 1) * sizeof (b_elf_shdr), + error_callback, data, &shdrs_view)) + goto fail; + shdrs_view_valid = 1; + shdrs = (const b_elf_shdr *) shdrs_view.view.data; + + /* Read the section names. */ + + shstrhdr = &shdrs[shstrndx - 1]; + shstr_size = shstrhdr->sh_size; + shstr_off = shstrhdr->sh_offset; + + if (!elf_get_view (state, descriptor, memory, memory_size, shstr_off, + shstrhdr->sh_size, error_callback, data, &names_view)) + goto fail; + names_view_valid = 1; + names = (const char *) names_view.view.data; + + symtab_shndx = 0; + dynsym_shndx = 0; + + memset (sections, 0, sizeof sections); + memset (zsections, 0, sizeof zsections); + + /* Look for the symbol table. */ + for (i = 1; i < shnum; ++i) + { + const b_elf_shdr *shdr; + unsigned int sh_name; + const char *name; + int j; + + shdr = &shdrs[i - 1]; + + if (shdr->sh_type == SHT_SYMTAB) + symtab_shndx = i; + else if (shdr->sh_type == SHT_DYNSYM) + dynsym_shndx = i; + + sh_name = shdr->sh_name; + if (sh_name >= shstr_size) + { + error_callback (data, "ELF section name out of range", 0); + goto fail; + } + + name = names + sh_name; + + for (j = 0; j < (int) DEBUG_MAX; ++j) + { + if (strcmp (name, dwarf_section_names[j]) == 0) + { + sections[j].offset = shdr->sh_offset; + sections[j].size = shdr->sh_size; + sections[j].compressed = (shdr->sh_flags & SHF_COMPRESSED) != 0; + break; + } + } + + if (name[0] == '.' && name[1] == 'z') + { + for (j = 0; j < (int) DEBUG_MAX; ++j) + { + if (strcmp (name + 2, dwarf_section_names[j] + 1) == 0) + { + zsections[j].offset = shdr->sh_offset; + zsections[j].size = shdr->sh_size; + break; + } + } + } + + /* Read the build ID if present. This could check for any + SHT_NOTE section with the right note name and type, but gdb + looks for a specific section name. */ + if ((!debuginfo || with_buildid_data != NULL) + && !buildid_view_valid + && strcmp (name, ".note.gnu.build-id") == 0) + { + const b_elf_note *note; + + if (!elf_get_view (state, descriptor, memory, memory_size, + shdr->sh_offset, shdr->sh_size, error_callback, + data, &buildid_view)) + goto fail; + + buildid_view_valid = 1; + note = (const b_elf_note *) buildid_view.view.data; + if (note->type == NT_GNU_BUILD_ID + && note->namesz == 4 + && strncmp (note->name, "GNU", 4) == 0 + && shdr->sh_size <= 12 + ((note->namesz + 3) & ~ 3) + note->descsz) + { + buildid_data = ¬e->name[0] + ((note->namesz + 3) & ~ 3); + buildid_size = note->descsz; + } + + if (with_buildid_size != 0) + { + if (buildid_size != with_buildid_size) + goto fail; + + if (memcmp (buildid_data, with_buildid_data, buildid_size) != 0) + goto fail; + } + } + + /* Read the debuglink file if present. */ + if (!debuginfo + && !debuglink_view_valid + && strcmp (name, ".gnu_debuglink") == 0) + { + const char *debuglink_data; + size_t crc_offset; + + if (!elf_get_view (state, descriptor, memory, memory_size, + shdr->sh_offset, shdr->sh_size, error_callback, + data, &debuglink_view)) + goto fail; + + debuglink_view_valid = 1; + debuglink_data = (const char *) debuglink_view.view.data; + crc_offset = strnlen (debuglink_data, shdr->sh_size); + crc_offset = (crc_offset + 3) & ~3; + if (crc_offset + 4 <= shdr->sh_size) + { + debuglink_name = debuglink_data; + debuglink_crc = *(const uint32_t*)(debuglink_data + crc_offset); + } + } + + if (!debugaltlink_view_valid + && strcmp (name, ".gnu_debugaltlink") == 0) + { + const char *debugaltlink_data; + size_t debugaltlink_name_len; + + if (!elf_get_view (state, descriptor, memory, memory_size, + shdr->sh_offset, shdr->sh_size, error_callback, + data, &debugaltlink_view)) + goto fail; + + debugaltlink_view_valid = 1; + debugaltlink_data = (const char *) debugaltlink_view.view.data; + debugaltlink_name = debugaltlink_data; + debugaltlink_name_len = strnlen (debugaltlink_data, shdr->sh_size); + if (debugaltlink_name_len < shdr->sh_size) + { + /* Include terminating zero. */ + debugaltlink_name_len += 1; + + debugaltlink_buildid_data + = debugaltlink_data + debugaltlink_name_len; + debugaltlink_buildid_size = shdr->sh_size - debugaltlink_name_len; + } + } + + if (!gnu_debugdata_view_valid + && strcmp (name, ".gnu_debugdata") == 0) + { + if (!elf_get_view (state, descriptor, memory, memory_size, + shdr->sh_offset, shdr->sh_size, error_callback, + data, &gnu_debugdata_view)) + goto fail; + + gnu_debugdata_size = shdr->sh_size; + gnu_debugdata_view_valid = 1; + } + + /* Read the .opd section on PowerPC64 ELFv1. */ + if (ehdr.e_machine == EM_PPC64 + && (ehdr.e_flags & EF_PPC64_ABI) < 2 + && shdr->sh_type == SHT_PROGBITS + && strcmp (name, ".opd") == 0) + { + if (!elf_get_view (state, descriptor, memory, memory_size, + shdr->sh_offset, shdr->sh_size, error_callback, + data, &opd_data.view)) + goto fail; + + opd = &opd_data; + opd->addr = shdr->sh_addr; + opd->data = (const char *) opd_data.view.view.data; + opd->size = shdr->sh_size; + opd_view_valid = 1; + } + } + + /* A debuginfo file may not have a useful .opd section, but we can use the + one from the original executable. */ + if (opd == NULL) + opd = caller_opd; + + if (symtab_shndx == 0) + symtab_shndx = dynsym_shndx; + if (symtab_shndx != 0) + { + const b_elf_shdr *symtab_shdr; + unsigned int strtab_shndx; + const b_elf_shdr *strtab_shdr; + struct elf_syminfo_data *sdata; + + symtab_shdr = &shdrs[symtab_shndx - 1]; + strtab_shndx = symtab_shdr->sh_link; + if (strtab_shndx >= shnum) + { + error_callback (data, + "ELF symbol table strtab link out of range", 0); + goto fail; + } + strtab_shdr = &shdrs[strtab_shndx - 1]; + + if (!elf_get_view (state, descriptor, memory, memory_size, + symtab_shdr->sh_offset, symtab_shdr->sh_size, + error_callback, data, &symtab_view)) + goto fail; + symtab_view_valid = 1; + + if (!elf_get_view (state, descriptor, memory, memory_size, + strtab_shdr->sh_offset, strtab_shdr->sh_size, + error_callback, data, &strtab_view)) + goto fail; + strtab_view_valid = 1; + + sdata = ((struct elf_syminfo_data *) + backtrace_alloc (state, sizeof *sdata, error_callback, data)); + if (sdata == NULL) + goto fail; + + if (!elf_initialize_syminfo (state, base_address, + (const unsigned char*)symtab_view.view.data, symtab_shdr->sh_size, + (const unsigned char*)strtab_view.view.data, strtab_shdr->sh_size, + error_callback, data, sdata, opd)) + { + backtrace_free (state, sdata, sizeof *sdata, error_callback, data); + goto fail; + } + + /* We no longer need the symbol table, but we hold on to the + string table permanently. */ + elf_release_view (state, &symtab_view, error_callback, data); + symtab_view_valid = 0; + strtab_view_valid = 0; + + *found_sym = 1; + + elf_add_syminfo_data (state, sdata); + } + + elf_release_view (state, &shdrs_view, error_callback, data); + shdrs_view_valid = 0; + elf_release_view (state, &names_view, error_callback, data); + names_view_valid = 0; + + /* If the debug info is in a separate file, read that one instead. */ + + if (buildid_data != NULL) + { + int d; + + d = elf_open_debugfile_by_buildid (state, buildid_data, buildid_size, + filename, error_callback, data); + if (d >= 0) + { + int ret; + + elf_release_view (state, &buildid_view, error_callback, data); + if (debuglink_view_valid) + elf_release_view (state, &debuglink_view, error_callback, data); + if (debugaltlink_view_valid) + elf_release_view (state, &debugaltlink_view, error_callback, data); + ret = elf_add (state, "", d, NULL, 0, base_address, opd, + error_callback, data, fileline_fn, found_sym, + found_dwarf, NULL, 0, 1, NULL, 0); + if (ret < 0) + backtrace_close (d, error_callback, data); + else if (descriptor >= 0) + backtrace_close (descriptor, error_callback, data); + return ret; + } + } + + if (buildid_view_valid) + { + elf_release_view (state, &buildid_view, error_callback, data); + buildid_view_valid = 0; + } + + if (debuglink_name != NULL) + { + int d; + + d = elf_open_debugfile_by_debuglink (state, filename, debuglink_name, + debuglink_crc, error_callback, + data); + if (d >= 0) + { + int ret; + + elf_release_view (state, &debuglink_view, error_callback, data); + if (debugaltlink_view_valid) + elf_release_view (state, &debugaltlink_view, error_callback, data); + ret = elf_add (state, "", d, NULL, 0, base_address, opd, + error_callback, data, fileline_fn, found_sym, + found_dwarf, NULL, 0, 1, NULL, 0); + if (ret < 0) + backtrace_close (d, error_callback, data); + else if (descriptor >= 0) + backtrace_close(descriptor, error_callback, data); + return ret; + } + } + + if (debuglink_view_valid) + { + elf_release_view (state, &debuglink_view, error_callback, data); + debuglink_view_valid = 0; + } + + if (debugaltlink_name != NULL) + { + int d; + + d = elf_open_debugfile_by_debuglink (state, filename, debugaltlink_name, + 0, error_callback, data); + if (d >= 0) + { + int ret; + + ret = elf_add (state, filename, d, NULL, 0, base_address, opd, + error_callback, data, fileline_fn, found_sym, + found_dwarf, &fileline_altlink, 0, 1, + debugaltlink_buildid_data, debugaltlink_buildid_size); + elf_release_view (state, &debugaltlink_view, error_callback, data); + debugaltlink_view_valid = 0; + if (ret < 0) + { + backtrace_close (d, error_callback, data); + return ret; + } + } + } + + if (debugaltlink_view_valid) + { + elf_release_view (state, &debugaltlink_view, error_callback, data); + debugaltlink_view_valid = 0; + } + + if (gnu_debugdata_view_valid) + { + int ret; + + ret = elf_uncompress_lzma (state, + ((const unsigned char *) + gnu_debugdata_view.view.data), + gnu_debugdata_size, error_callback, data, + &gnu_debugdata_uncompressed, + &gnu_debugdata_uncompressed_size); + + elf_release_view (state, &gnu_debugdata_view, error_callback, data); + gnu_debugdata_view_valid = 0; + + if (ret) + { + ret = elf_add (state, filename, -1, gnu_debugdata_uncompressed, + gnu_debugdata_uncompressed_size, base_address, opd, + error_callback, data, fileline_fn, found_sym, + found_dwarf, NULL, 0, 0, NULL, 0); + if (ret >= 0 && descriptor >= 0) + backtrace_close(descriptor, error_callback, data); + return ret; + } + } + + if (opd_view_valid) + { + elf_release_view (state, &opd->view, error_callback, data); + opd_view_valid = 0; + opd = NULL; + } + + /* Read all the debug sections in a single view, since they are + probably adjacent in the file. If any of sections are + uncompressed, we never release this view. */ + + min_offset = 0; + max_offset = 0; + debug_size = 0; + for (i = 0; i < (int) DEBUG_MAX; ++i) + { + off_t end; + + if (sections[i].size != 0) + { + if (min_offset == 0 || sections[i].offset < min_offset) + min_offset = sections[i].offset; + end = sections[i].offset + sections[i].size; + if (end > max_offset) + max_offset = end; + debug_size += sections[i].size; + } + if (zsections[i].size != 0) + { + if (min_offset == 0 || zsections[i].offset < min_offset) + min_offset = zsections[i].offset; + end = zsections[i].offset + zsections[i].size; + if (end > max_offset) + max_offset = end; + debug_size += zsections[i].size; + } + } + if (min_offset == 0 || max_offset == 0) + { + if (descriptor >= 0) + { + if (!backtrace_close (descriptor, error_callback, data)) + goto fail; + } + return 1; + } + + /* If the total debug section size is large, assume that there are + gaps between the sections, and read them individually. */ + + if (max_offset - min_offset < 0x20000000 + || max_offset - min_offset < debug_size + 0x10000) + { + if (!elf_get_view (state, descriptor, memory, memory_size, min_offset, + max_offset - min_offset, error_callback, data, + &debug_view)) + goto fail; + debug_view_valid = 1; + } + else + { + memset (&split_debug_view[0], 0, sizeof split_debug_view); + for (i = 0; i < (int) DEBUG_MAX; ++i) + { + struct debug_section_info *dsec; + + if (sections[i].size != 0) + dsec = §ions[i]; + else if (zsections[i].size != 0) + dsec = &zsections[i]; + else + continue; + + if (!elf_get_view (state, descriptor, memory, memory_size, + dsec->offset, dsec->size, error_callback, data, + &split_debug_view[i])) + goto fail; + split_debug_view_valid[i] = 1; + + if (sections[i].size != 0) + sections[i].data = ((const unsigned char *) + split_debug_view[i].view.data); + else + zsections[i].data = ((const unsigned char *) + split_debug_view[i].view.data); + } + } + + /* We've read all we need from the executable. */ + if (descriptor >= 0) + { + if (!backtrace_close (descriptor, error_callback, data)) + goto fail; + descriptor = -1; + } + + using_debug_view = 0; + if (debug_view_valid) + { + for (i = 0; i < (int) DEBUG_MAX; ++i) + { + if (sections[i].size == 0) + sections[i].data = NULL; + else + { + sections[i].data = ((const unsigned char *) debug_view.view.data + + (sections[i].offset - min_offset)); + ++using_debug_view; + } + + if (zsections[i].size == 0) + zsections[i].data = NULL; + else + zsections[i].data = ((const unsigned char *) debug_view.view.data + + (zsections[i].offset - min_offset)); + } + } + + /* Uncompress the old format (--compress-debug-sections=zlib-gnu). */ + + zdebug_table = NULL; + for (i = 0; i < (int) DEBUG_MAX; ++i) + { + if (sections[i].size == 0 && zsections[i].size > 0) + { + unsigned char *uncompressed_data; + size_t uncompressed_size; + + if (zdebug_table == NULL) + { + zdebug_table = ((uint16_t *) + backtrace_alloc (state, ZLIB_TABLE_SIZE, + error_callback, data)); + if (zdebug_table == NULL) + goto fail; + } + + uncompressed_data = NULL; + uncompressed_size = 0; + if (!elf_uncompress_zdebug (state, zsections[i].data, + zsections[i].size, zdebug_table, + error_callback, data, + &uncompressed_data, &uncompressed_size)) + goto fail; + sections[i].data = uncompressed_data; + sections[i].size = uncompressed_size; + sections[i].compressed = 0; + + if (split_debug_view_valid[i]) + { + elf_release_view (state, &split_debug_view[i], + error_callback, data); + split_debug_view_valid[i] = 0; + } + } + } + + if (zdebug_table != NULL) + { + backtrace_free (state, zdebug_table, ZLIB_TABLE_SIZE, + error_callback, data); + zdebug_table = NULL; + } + + /* Uncompress the official ELF format + (--compress-debug-sections=zlib-gabi, --compress-debug-sections=zstd). */ + for (i = 0; i < (int) DEBUG_MAX; ++i) + { + unsigned char *uncompressed_data; + size_t uncompressed_size; + + if (sections[i].size == 0 || !sections[i].compressed) + continue; + + if (zdebug_table == NULL) + { + zdebug_table = ((uint16_t *) + backtrace_alloc (state, ZDEBUG_TABLE_SIZE, + error_callback, data)); + if (zdebug_table == NULL) + goto fail; + } + + uncompressed_data = NULL; + uncompressed_size = 0; + if (!elf_uncompress_chdr (state, sections[i].data, sections[i].size, + zdebug_table, error_callback, data, + &uncompressed_data, &uncompressed_size)) + goto fail; + sections[i].data = uncompressed_data; + sections[i].size = uncompressed_size; + sections[i].compressed = 0; + + if (debug_view_valid) + --using_debug_view; + else if (split_debug_view_valid[i]) + { + elf_release_view (state, &split_debug_view[i], error_callback, data); + split_debug_view_valid[i] = 0; + } + } + + if (zdebug_table != NULL) + backtrace_free (state, zdebug_table, ZDEBUG_TABLE_SIZE, + error_callback, data); + + if (debug_view_valid && using_debug_view == 0) + { + elf_release_view (state, &debug_view, error_callback, data); + debug_view_valid = 0; + } + + for (i = 0; i < (int) DEBUG_MAX; ++i) + { + dwarf_sections.data[i] = sections[i].data; + dwarf_sections.size[i] = sections[i].size; + } + + if (!backtrace_dwarf_add (state, base_address, &dwarf_sections, + ehdr.e_ident[EI_DATA] == ELFDATA2MSB, + fileline_altlink, + error_callback, data, fileline_fn, + fileline_entry)) + goto fail; + + *found_dwarf = 1; + + return 1; + + fail: + if (shdrs_view_valid) + elf_release_view (state, &shdrs_view, error_callback, data); + if (names_view_valid) + elf_release_view (state, &names_view, error_callback, data); + if (symtab_view_valid) + elf_release_view (state, &symtab_view, error_callback, data); + if (strtab_view_valid) + elf_release_view (state, &strtab_view, error_callback, data); + if (debuglink_view_valid) + elf_release_view (state, &debuglink_view, error_callback, data); + if (debugaltlink_view_valid) + elf_release_view (state, &debugaltlink_view, error_callback, data); + if (gnu_debugdata_view_valid) + elf_release_view (state, &gnu_debugdata_view, error_callback, data); + if (buildid_view_valid) + elf_release_view (state, &buildid_view, error_callback, data); + if (debug_view_valid) + elf_release_view (state, &debug_view, error_callback, data); + for (i = 0; i < (int) DEBUG_MAX; ++i) + { + if (split_debug_view_valid[i]) + elf_release_view (state, &split_debug_view[i], error_callback, data); + } + if (opd_view_valid) + elf_release_view (state, &opd->view, error_callback, data); + if (descriptor >= 0) + backtrace_close (descriptor, error_callback, data); + return 0; +} + +/* Data passed to phdr_callback. */ + +struct phdr_data +{ + struct backtrace_state *state; + backtrace_error_callback error_callback; + void *data; + fileline *fileline_fn; + int *found_sym; + int *found_dwarf; + const char *exe_filename; + int exe_descriptor; +}; + +/* Callback passed to dl_iterate_phdr. Load debug info from shared + libraries. */ + +struct PhdrIterate +{ + char* dlpi_name; + ElfW(Addr) dlpi_addr; + ElfW(Addr) dlpi_end_addr; +}; +FastVector s_phdrData(16); + +struct ElfAddrRange +{ + ElfW(Addr) dlpi_addr; + ElfW(Addr) dlpi_end_addr; +}; +FastVector s_sortedKnownElfRanges(16); + +static int address_in_known_elf_ranges(uintptr_t pc) +{ + auto it = std::lower_bound( s_sortedKnownElfRanges.begin(), s_sortedKnownElfRanges.end(), pc, + []( const ElfAddrRange& lhs, const uintptr_t rhs ) { return uintptr_t(lhs.dlpi_addr) > rhs; } ); + if( it != s_sortedKnownElfRanges.end() && pc <= it->dlpi_end_addr ) + { + return true; + } + return false; +} + +static int +phdr_callback_mock (struct dl_phdr_info *info, size_t size ATTRIBUTE_UNUSED, + void *pdata) +{ + if( address_in_known_elf_ranges(info->dlpi_addr) ) + { + return 0; + } + + auto ptr = s_phdrData.push_next(); + if (info->dlpi_name) + { + size_t sz = strlen (info->dlpi_name) + 1; + ptr->dlpi_name = (char*)tracy_malloc (sz); + memcpy (ptr->dlpi_name, info->dlpi_name, sz); + } + else ptr->dlpi_name = nullptr; + ptr->dlpi_addr = info->dlpi_addr; + + // calculate the end address as well, so we can quickly determine if a PC is within the range of this image + ptr->dlpi_end_addr = uintptr_t(info->dlpi_addr) + (info->dlpi_phnum ? uintptr_t( + info->dlpi_phdr[info->dlpi_phnum - 1].p_vaddr + + info->dlpi_phdr[info->dlpi_phnum - 1].p_memsz) : 0); + + return 0; +} + +static int +#ifdef __i386__ +__attribute__ ((__force_align_arg_pointer__)) +#endif +phdr_callback (struct PhdrIterate *info, void *pdata) +{ + struct phdr_data *pd = (struct phdr_data *) pdata; + const char *filename; + int descriptor; + int does_not_exist; + fileline elf_fileline_fn; + int found_dwarf; + + /* There is not much we can do if we don't have the module name, + unless executable is ET_DYN, where we expect the very first + phdr_callback to be for the PIE. */ + if (info->dlpi_name == NULL || info->dlpi_name[0] == '\0') + { + if (pd->exe_descriptor == -1) + return 0; + filename = pd->exe_filename; + descriptor = pd->exe_descriptor; + pd->exe_descriptor = -1; + } + else + { + if (pd->exe_descriptor != -1) + { + backtrace_close (pd->exe_descriptor, pd->error_callback, pd->data); + pd->exe_descriptor = -1; + } + + filename = info->dlpi_name; + descriptor = backtrace_open (info->dlpi_name, pd->error_callback, + pd->data, &does_not_exist); + if (descriptor < 0) + return 0; + } + + if (elf_add (pd->state, filename, descriptor, NULL, 0, info->dlpi_addr, NULL, + pd->error_callback, pd->data, &elf_fileline_fn, pd->found_sym, + &found_dwarf, NULL, 0, 0, NULL, 0)) + { + if (found_dwarf) + { + *pd->found_dwarf = 1; + *pd->fileline_fn = elf_fileline_fn; + } + } + + return 0; +} + +static int elf_iterate_phdr_and_add_new_files(phdr_data *pd) +{ + assert(s_phdrData.empty()); + // dl_iterate_phdr, will only add entries for elf files loaded in a previously unseen range + dl_iterate_phdr(phdr_callback_mock, nullptr); + + if(s_phdrData.size() == 0) + { + return 0; + } + + uint32_t headersAdded = 0; + for (auto &v : s_phdrData) + { + phdr_callback(&v, (void *)pd); + + auto newEntry = s_sortedKnownElfRanges.push_next(); + newEntry->dlpi_addr = v.dlpi_addr; + newEntry->dlpi_end_addr = v.dlpi_end_addr; + + tracy_free(v.dlpi_name); + + headersAdded++; + } + + s_phdrData.clear(); + + std::sort( s_sortedKnownElfRanges.begin(), s_sortedKnownElfRanges.end(), + []( const ElfAddrRange& lhs, const ElfAddrRange& rhs ) { return lhs.dlpi_addr > rhs.dlpi_addr; } ); + + return headersAdded; +} + +#ifdef TRACY_LIBBACKTRACE_ELF_DYNLOAD_SUPPORT +/* Request an elf entry update if the pc passed in is not in any of the known elf ranges. +This could mean that new images were dlopened and we need to add those new elf entries */ +static int elf_refresh_address_ranges_if_needed(struct backtrace_state *state, uintptr_t pc) +{ + if ( address_in_known_elf_ranges(pc) ) + { + return 0; + } + + struct phdr_data pd; + int found_sym = 0; + int found_dwarf = 0; + fileline fileline_fn = nullptr; + pd.state = state; + pd.error_callback = nullptr; + pd.data = nullptr; + pd.fileline_fn = &fileline_fn; + pd.found_sym = &found_sym; + pd.found_dwarf = &found_dwarf; + pd.exe_filename = nullptr; + pd.exe_descriptor = -1; + + return elf_iterate_phdr_and_add_new_files(&pd); +} +#endif //#ifdef TRACY_LIBBACKTRACE_ELF_DYNLOAD_SUPPORT + +/* Initialize the backtrace data we need from an ELF executable. At + the ELF level, all we need to do is find the debug info + sections. */ + +int +backtrace_initialize (struct backtrace_state *state, const char *filename, + int descriptor, backtrace_error_callback error_callback, + void *data, fileline *fileline_fn) +{ + int ret; + int found_sym; + int found_dwarf; + fileline elf_fileline_fn = elf_nodebug; + struct phdr_data pd; + + ret = elf_add (state, filename, descriptor, NULL, 0, 0, NULL, error_callback, + data, &elf_fileline_fn, &found_sym, &found_dwarf, NULL, 1, 0, + NULL, 0); + if (!ret) + return 0; + + pd.state = state; + pd.error_callback = error_callback; + pd.data = data; + pd.fileline_fn = &elf_fileline_fn; + pd.found_sym = &found_sym; + pd.found_dwarf = &found_dwarf; + pd.exe_filename = filename; + pd.exe_descriptor = ret < 0 ? descriptor : -1; + + elf_iterate_phdr_and_add_new_files(&pd); + + if (!state->threaded) + { + if (found_sym) + state->syminfo_fn = elf_syminfo; + else if (state->syminfo_fn == NULL) + state->syminfo_fn = elf_nosyms; + } + else + { + if (found_sym) + backtrace_atomic_store_pointer (&state->syminfo_fn, &elf_syminfo); + else + (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL, + elf_nosyms); + } + + if (!state->threaded) + *fileline_fn = state->fileline_fn; + else + *fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn); + + if (*fileline_fn == NULL || *fileline_fn == elf_nodebug) + *fileline_fn = elf_fileline_fn; + + // install an address range refresh callback so we can cope with dynamically loaded elf files +#ifdef TRACY_LIBBACKTRACE_ELF_DYNLOAD_SUPPORT + state->request_known_address_ranges_refresh_fn = elf_refresh_address_ranges_if_needed; +#else + state->request_known_address_ranges_refresh_fn = NULL; +#endif + + return 1; +} + +} diff --git a/Dependencies/tracy/libbacktrace/fileline.cpp b/Dependencies/tracy/libbacktrace/fileline.cpp new file mode 100644 index 000000000..5a37ff0c7 --- /dev/null +++ b/Dependencies/tracy/libbacktrace/fileline.cpp @@ -0,0 +1,412 @@ +/* fileline.c -- Get file and line number information in a backtrace. + Copyright (C) 2012-2021 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Google. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + (1) Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + (2) Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + (3) The name of the author may not be used to + endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#if defined (HAVE_KERN_PROC_ARGS) || defined (HAVE_KERN_PROC) +#include +#endif + +#ifdef HAVE_MACH_O_DYLD_H +#include +#endif + +#ifdef HAVE_WINDOWS_H +#ifndef WIN32_MEAN_AND_LEAN +#define WIN32_MEAN_AND_LEAN +#endif + +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#include +#endif + +#include "backtrace.hpp" +#include "internal.hpp" + +#ifndef HAVE_GETEXECNAME +#define getexecname() NULL +#endif + +namespace tracy +{ + +#if !defined (HAVE_KERN_PROC_ARGS) && !defined (HAVE_KERN_PROC) + +#define sysctl_exec_name1(state, error_callback, data) NULL +#define sysctl_exec_name2(state, error_callback, data) NULL + +#else /* defined (HAVE_KERN_PROC_ARGS) || |defined (HAVE_KERN_PROC) */ + +static char * +sysctl_exec_name (struct backtrace_state *state, + int mib0, int mib1, int mib2, int mib3, + backtrace_error_callback error_callback, void *data) +{ + int mib[4]; + size_t len; + char *name; + size_t rlen; + + mib[0] = mib0; + mib[1] = mib1; + mib[2] = mib2; + mib[3] = mib3; + + if (sysctl (mib, 4, NULL, &len, NULL, 0) < 0) + return NULL; + name = (char *) backtrace_alloc (state, len, error_callback, data); + if (name == NULL) + return NULL; + rlen = len; + if (sysctl (mib, 4, name, &rlen, NULL, 0) < 0) + { + backtrace_free (state, name, len, error_callback, data); + return NULL; + } + return name; +} + +#ifdef HAVE_KERN_PROC_ARGS + +static char * +sysctl_exec_name1 (struct backtrace_state *state, + backtrace_error_callback error_callback, void *data) +{ + /* This variant is used on NetBSD. */ + return sysctl_exec_name (state, CTL_KERN, KERN_PROC_ARGS, -1, + KERN_PROC_PATHNAME, error_callback, data); +} + +#else + +#define sysctl_exec_name1(state, error_callback, data) NULL + +#endif + +#ifdef HAVE_KERN_PROC + +static char * +sysctl_exec_name2 (struct backtrace_state *state, + backtrace_error_callback error_callback, void *data) +{ + /* This variant is used on FreeBSD. */ + return sysctl_exec_name (state, CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1, + error_callback, data); +} + +#else + +#define sysctl_exec_name2(state, error_callback, data) NULL + +#endif + +#endif /* defined (HAVE_KERN_PROC_ARGS) || |defined (HAVE_KERN_PROC) */ + +#ifdef HAVE_MACH_O_DYLD_H + +static char * +macho_get_executable_path (struct backtrace_state *state, + backtrace_error_callback error_callback, void *data) +{ + uint32_t len; + char *name; + + len = 0; + if (_NSGetExecutablePath (NULL, &len) == 0) + return NULL; + name = (char *) backtrace_alloc (state, len, error_callback, data); + if (name == NULL) + return NULL; + if (_NSGetExecutablePath (name, &len) != 0) + { + backtrace_free (state, name, len, error_callback, data); + return NULL; + } + return name; +} + +#else /* !defined (HAVE_MACH_O_DYLD_H) */ + +#define macho_get_executable_path(state, error_callback, data) NULL + +#endif /* !defined (HAVE_MACH_O_DYLD_H) */ + +#if HAVE_DECL__PGMPTR + +#define windows_executable_filename() _pgmptr + +#else /* !HAVE_DECL__PGMPTR */ + +#define windows_executable_filename() NULL + +#endif /* !HAVE_DECL__PGMPTR */ + +#ifdef HAVE_WINDOWS_H + +#define FILENAME_BUF_SIZE (MAX_PATH) + +static char * +windows_get_executable_path (char *buf, backtrace_error_callback error_callback, + void *data) +{ + size_t got; + int error; + + got = GetModuleFileNameA (NULL, buf, FILENAME_BUF_SIZE - 1); + error = GetLastError (); + if (got == 0 + || (got == FILENAME_BUF_SIZE - 1 && error == ERROR_INSUFFICIENT_BUFFER)) + { + error_callback (data, + "could not get the filename of the current executable", + error); + return NULL; + } + return buf; +} + +#else /* !defined (HAVE_WINDOWS_H) */ + +#define windows_get_executable_path(buf, error_callback, data) NULL +#define FILENAME_BUF_SIZE 64 + +#endif /* !defined (HAVE_WINDOWS_H) */ + +/* Initialize the fileline information from the executable. Returns 1 + on success, 0 on failure. */ + +static int +fileline_initialize (struct backtrace_state *state, + backtrace_error_callback error_callback, void *data) +{ + int failed; + fileline fileline_fn; + int pass; + int called_error_callback; + int descriptor; + const char *filename; + char buf[FILENAME_BUF_SIZE]; + + if (!state->threaded) + failed = state->fileline_initialization_failed; + else + failed = backtrace_atomic_load_int (&state->fileline_initialization_failed); + + if (failed) + { + error_callback (data, "failed to read executable information", -1); + return 0; + } + + if (!state->threaded) + fileline_fn = state->fileline_fn; + else + fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn); + if (fileline_fn != NULL) + return 1; + + /* We have not initialized the information. Do it now. */ + + descriptor = -1; + called_error_callback = 0; + for (pass = 0; pass < 10; ++pass) + { + int does_not_exist; + + switch (pass) + { + case 0: + filename = state->filename; + break; + case 1: + filename = getexecname (); + break; + case 2: + /* Test this before /proc/self/exe, as the latter exists but points + to the wine binary (and thus doesn't work). */ + filename = windows_executable_filename (); + break; + case 3: + filename = "/proc/self/exe"; + break; + case 4: + filename = "/proc/curproc/file"; + break; + case 5: + snprintf (buf, sizeof (buf), "/proc/%ld/object/a.out", + (long) getpid ()); + filename = buf; + break; + case 6: + filename = sysctl_exec_name1 (state, error_callback, data); + break; + case 7: + filename = sysctl_exec_name2 (state, error_callback, data); + break; + case 8: + filename = macho_get_executable_path (state, error_callback, data); + break; + case 9: + filename = windows_get_executable_path (buf, error_callback, data); + break; + default: + abort (); + } + + if (filename == NULL) + continue; + + descriptor = backtrace_open (filename, error_callback, data, + &does_not_exist); + if (descriptor < 0 && !does_not_exist) + { + called_error_callback = 1; + break; + } + if (descriptor >= 0) + break; + } + + if (descriptor < 0) + { + if (!called_error_callback) + { + if (state->filename != NULL) + error_callback (data, state->filename, ENOENT); + else + error_callback (data, + "libbacktrace could not find executable to open", + 0); + } + failed = 1; + } + + if (!failed) + { + if (!backtrace_initialize (state, filename, descriptor, error_callback, + data, &fileline_fn)) + failed = 1; + } + + if (failed) + { + if (!state->threaded) + state->fileline_initialization_failed = 1; + else + backtrace_atomic_store_int (&state->fileline_initialization_failed, 1); + return 0; + } + + if (!state->threaded) + state->fileline_fn = fileline_fn; + else + { + backtrace_atomic_store_pointer (&state->fileline_fn, fileline_fn); + + /* Note that if two threads initialize at once, one of the data + sets may be leaked. */ + } + + return 1; +} + +/* Given a PC, find the file name, line number, and function name. */ + +int +backtrace_pcinfo (struct backtrace_state *state, uintptr_t pc, + backtrace_full_callback callback, + backtrace_error_callback error_callback, void *data) +{ + if (!fileline_initialize (state, error_callback, data)) + return 0; + + if (state->fileline_initialization_failed) + return 0; + + return state->fileline_fn (state, pc, callback, error_callback, data); +} + +/* Given a PC, find the symbol for it, and its value. */ + +int +backtrace_syminfo (struct backtrace_state *state, uintptr_t pc, + backtrace_syminfo_callback callback, + backtrace_error_callback error_callback, void *data) +{ + if (!fileline_initialize (state, error_callback, data)) + return 0; + + if (state->fileline_initialization_failed) + return 0; + + state->syminfo_fn (state, pc, callback, error_callback, data); + return 1; +} + +/* A backtrace_syminfo_callback that can call into a + backtrace_full_callback, used when we have a symbol table but no + debug info. */ + +void +backtrace_syminfo_to_full_callback (void *data, uintptr_t pc, + const char *symname, + uintptr_t symval ATTRIBUTE_UNUSED, + uintptr_t symsize ATTRIBUTE_UNUSED) +{ + struct backtrace_call_full *bdata = (struct backtrace_call_full *) data; + + bdata->ret = bdata->full_callback (bdata->full_data, pc, 0, NULL, 0, symname); +} + +/* An error callback that corresponds to + backtrace_syminfo_to_full_callback. */ + +void +backtrace_syminfo_to_full_error_callback (void *data, const char *msg, + int errnum) +{ + struct backtrace_call_full *bdata = (struct backtrace_call_full *) data; + + bdata->full_error_callback (bdata->full_data, msg, errnum); +} + +} diff --git a/Dependencies/tracy/libbacktrace/filenames.hpp b/Dependencies/tracy/libbacktrace/filenames.hpp new file mode 100644 index 000000000..aa7bd7adf --- /dev/null +++ b/Dependencies/tracy/libbacktrace/filenames.hpp @@ -0,0 +1,52 @@ +/* btest.c -- Filename header for libbacktrace library + Copyright (C) 2012-2018 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Google. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + (1) Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + (2) Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + (3) The name of the author may not be used to + endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. */ + +#ifndef GCC_VERSION +# define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__) +#endif + +#if (GCC_VERSION < 2007) +# define __attribute__(x) +#endif + +#ifndef ATTRIBUTE_UNUSED +# define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) +#endif + +#if defined(__MSDOS__) || defined(_WIN32) || defined(__OS2__) || defined (__CYGWIN__) +# define IS_DIR_SEPARATOR(c) ((c) == '/' || (c) == '\\') +# define HAS_DRIVE_SPEC(f) ((f)[0] != '\0' && (f)[1] == ':') +# define IS_ABSOLUTE_PATH(f) (IS_DIR_SEPARATOR((f)[0]) || HAS_DRIVE_SPEC(f)) +#else +# define IS_DIR_SEPARATOR(c) ((c) == '/') +# define IS_ABSOLUTE_PATH(f) (IS_DIR_SEPARATOR((f)[0])) +#endif diff --git a/Dependencies/tracy/libbacktrace/internal.hpp b/Dependencies/tracy/libbacktrace/internal.hpp new file mode 100644 index 000000000..fea298fa2 --- /dev/null +++ b/Dependencies/tracy/libbacktrace/internal.hpp @@ -0,0 +1,401 @@ +/* internal.h -- Internal header file for stack backtrace library. + Copyright (C) 2012-2021 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Google. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + (1) Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + (2) Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + (3) The name of the author may not be used to + endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. */ + +#ifndef BACKTRACE_INTERNAL_H +#define BACKTRACE_INTERNAL_H + +/* We assume that and "backtrace.h" have already been + included. */ + +#ifndef GCC_VERSION +# define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__) +#endif + +#if (GCC_VERSION < 2007) +# define __attribute__(x) +#endif + +#ifndef ATTRIBUTE_UNUSED +# define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) +#endif + +#ifndef ATTRIBUTE_MALLOC +# if (GCC_VERSION >= 2096) +# define ATTRIBUTE_MALLOC __attribute__ ((__malloc__)) +# else +# define ATTRIBUTE_MALLOC +# endif +#endif + +#ifndef ATTRIBUTE_FALLTHROUGH +# if (GCC_VERSION >= 7000) +# define ATTRIBUTE_FALLTHROUGH __attribute__ ((__fallthrough__)) +# else +# define ATTRIBUTE_FALLTHROUGH +# endif +#endif + +#ifndef HAVE_SYNC_FUNCTIONS + +/* Define out the sync functions. These should never be called if + they are not available. */ + +#define __sync_bool_compare_and_swap(A, B, C) (abort(), 1) +#define __sync_lock_test_and_set(A, B) (abort(), 0) +#define __sync_lock_release(A) abort() + +#endif /* !defined (HAVE_SYNC_FUNCTIONS) */ + +#ifdef HAVE_ATOMIC_FUNCTIONS + +/* We have the atomic builtin functions. */ + +#define backtrace_atomic_load_pointer(p) \ + __atomic_load_n ((p), __ATOMIC_ACQUIRE) +#define backtrace_atomic_load_int(p) \ + __atomic_load_n ((p), __ATOMIC_ACQUIRE) +#define backtrace_atomic_store_pointer(p, v) \ + __atomic_store_n ((p), (v), __ATOMIC_RELEASE) +#define backtrace_atomic_store_size_t(p, v) \ + __atomic_store_n ((p), (v), __ATOMIC_RELEASE) +#define backtrace_atomic_store_int(p, v) \ + __atomic_store_n ((p), (v), __ATOMIC_RELEASE) + +#else /* !defined (HAVE_ATOMIC_FUNCTIONS) */ +#ifdef HAVE_SYNC_FUNCTIONS + +/* We have the sync functions but not the atomic functions. Define + the atomic ones in terms of the sync ones. */ + +extern void *backtrace_atomic_load_pointer (void *); +extern int backtrace_atomic_load_int (int *); +extern void backtrace_atomic_store_pointer (void *, void *); +extern void backtrace_atomic_store_size_t (size_t *, size_t); +extern void backtrace_atomic_store_int (int *, int); + +#else /* !defined (HAVE_SYNC_FUNCTIONS) */ + +/* We have neither the sync nor the atomic functions. These will + never be called. */ + +#define backtrace_atomic_load_pointer(p) (abort(), (void *) NULL) +#define backtrace_atomic_load_int(p) (abort(), 0) +#define backtrace_atomic_store_pointer(p, v) abort() +#define backtrace_atomic_store_size_t(p, v) abort() +#define backtrace_atomic_store_int(p, v) abort() + +#endif /* !defined (HAVE_SYNC_FUNCTIONS) */ +#endif /* !defined (HAVE_ATOMIC_FUNCTIONS) */ + +namespace tracy +{ + +/* The type of the function that collects file/line information. This + is like backtrace_pcinfo. */ + +typedef int (*fileline) (struct backtrace_state *state, uintptr_t pc, + backtrace_full_callback callback, + backtrace_error_callback error_callback, void *data); + +/* The type of the function that collects symbol information. This is + like backtrace_syminfo. */ + +typedef void (*syminfo) (struct backtrace_state *state, uintptr_t pc, + backtrace_syminfo_callback callback, + backtrace_error_callback error_callback, void *data); + +/* The type of the function that will trigger an known address range refresh + (if pc passed in is for an address whichs lies ourtisde of known ranges) */ +typedef int (*request_known_address_ranges_refresh)(struct backtrace_state *state, + uintptr_t pc); + +/* What the backtrace state pointer points to. */ + +struct backtrace_state +{ + /* The name of the executable. */ + const char *filename; + /* Non-zero if threaded. */ + int threaded; + /* The master lock for fileline_fn, fileline_data, syminfo_fn, + syminfo_data, fileline_initialization_failed and everything the + data pointers point to. */ + void *lock; + /* The function that returns file/line information. */ + fileline fileline_fn; + /* The data to pass to FILELINE_FN. */ + void *fileline_data; + /* The function that returns symbol information. */ + syminfo syminfo_fn; + /* The data to pass to SYMINFO_FN. */ + void *syminfo_data; + /* Whether initializing the file/line information failed. */ + int fileline_initialization_failed; + /* The lock for the freelist. */ + int lock_alloc; + /* The freelist when using mmap. */ + struct backtrace_freelist_struct *freelist; + /* Trigger an known address range refresh */ + request_known_address_ranges_refresh request_known_address_ranges_refresh_fn; +}; + +/* Open a file for reading. Returns -1 on error. If DOES_NOT_EXIST + is not NULL, *DOES_NOT_EXIST will be set to 0 normally and set to 1 + if the file does not exist. If the file does not exist and + DOES_NOT_EXIST is not NULL, the function will return -1 and will + not call ERROR_CALLBACK. On other errors, or if DOES_NOT_EXIST is + NULL, the function will call ERROR_CALLBACK before returning. */ +extern int backtrace_open (const char *filename, + backtrace_error_callback error_callback, + void *data, + int *does_not_exist); + +/* A view of the contents of a file. This supports mmap when + available. A view will remain in memory even after backtrace_close + is called on the file descriptor from which the view was + obtained. */ + +struct backtrace_view +{ + /* The data that the caller requested. */ + const void *data; + /* The base of the view. */ + void *base; + /* The total length of the view. */ + size_t len; +}; + +/* Create a view of SIZE bytes from DESCRIPTOR at OFFSET. Store the + result in *VIEW. Returns 1 on success, 0 on error. */ +extern int backtrace_get_view (struct backtrace_state *state, int descriptor, + off_t offset, uint64_t size, + backtrace_error_callback error_callback, + void *data, struct backtrace_view *view); + +/* Release a view created by backtrace_get_view. */ +extern void backtrace_release_view (struct backtrace_state *state, + struct backtrace_view *view, + backtrace_error_callback error_callback, + void *data); + +/* Close a file opened by backtrace_open. Returns 1 on success, 0 on + error. */ + +extern int backtrace_close (int descriptor, + backtrace_error_callback error_callback, + void *data); + +/* Sort without using memory. */ + +extern void backtrace_qsort (void *base, size_t count, size_t size, + int (*compar) (const void *, const void *)); + +/* Allocate memory. This is like malloc. If ERROR_CALLBACK is NULL, + this does not report an error, it just returns NULL. */ + +extern void *backtrace_alloc (struct backtrace_state *state, size_t size, + backtrace_error_callback error_callback, + void *data) ATTRIBUTE_MALLOC; + +/* Free memory allocated by backtrace_alloc. If ERROR_CALLBACK is + NULL, this does not report an error. */ + +extern void backtrace_free (struct backtrace_state *state, void *mem, + size_t size, + backtrace_error_callback error_callback, + void *data); + +/* A growable vector of some struct. This is used for more efficient + allocation when we don't know the final size of some group of data + that we want to represent as an array. */ + +struct backtrace_vector +{ + /* The base of the vector. */ + void *base; + /* The number of bytes in the vector. */ + size_t size; + /* The number of bytes available at the current allocation. */ + size_t alc; +}; + +/* Grow VEC by SIZE bytes. Return a pointer to the newly allocated + bytes. Note that this may move the entire vector to a new memory + location. Returns NULL on failure. */ + +extern void *backtrace_vector_grow (struct backtrace_state *state, size_t size, + backtrace_error_callback error_callback, + void *data, + struct backtrace_vector *vec); + +/* Finish the current allocation on VEC. Prepare to start a new + allocation. The finished allocation will never be freed. Returns + a pointer to the base of the finished entries, or NULL on + failure. */ + +extern void* backtrace_vector_finish (struct backtrace_state *state, + struct backtrace_vector *vec, + backtrace_error_callback error_callback, + void *data); + +/* Release any extra space allocated for VEC. This may change + VEC->base. Returns 1 on success, 0 on failure. */ + +extern int backtrace_vector_release (struct backtrace_state *state, + struct backtrace_vector *vec, + backtrace_error_callback error_callback, + void *data); + +/* Free the space managed by VEC. This will reset VEC. */ + +static inline void +backtrace_vector_free (struct backtrace_state *state, + struct backtrace_vector *vec, + backtrace_error_callback error_callback, void *data) +{ + vec->alc += vec->size; + vec->size = 0; + backtrace_vector_release (state, vec, error_callback, data); +} + +/* Read initial debug data from a descriptor, and set the + fileline_data, syminfo_fn, and syminfo_data fields of STATE. + Return the fileln_fn field in *FILELN_FN--this is done this way so + that the synchronization code is only implemented once. This is + called after the descriptor has first been opened. It will close + the descriptor if it is no longer needed. Returns 1 on success, 0 + on error. There will be multiple implementations of this function, + for different file formats. Each system will compile the + appropriate one. */ + +extern int backtrace_initialize (struct backtrace_state *state, + const char *filename, + int descriptor, + backtrace_error_callback error_callback, + void *data, + fileline *fileline_fn); + +/* An enum for the DWARF sections we care about. */ + +enum dwarf_section +{ + DEBUG_INFO, + DEBUG_LINE, + DEBUG_ABBREV, + DEBUG_RANGES, + DEBUG_STR, + DEBUG_ADDR, + DEBUG_STR_OFFSETS, + DEBUG_LINE_STR, + DEBUG_RNGLISTS, + + DEBUG_MAX +}; + +/* Data for the DWARF sections we care about. */ + +struct dwarf_sections +{ + const unsigned char *data[DEBUG_MAX]; + size_t size[DEBUG_MAX]; +}; + +/* DWARF data read from a file, used for .gnu_debugaltlink. */ + +struct dwarf_data; + +/* Add file/line information for a DWARF module. */ + +extern int backtrace_dwarf_add (struct backtrace_state *state, + uintptr_t base_address, + const struct dwarf_sections *dwarf_sections, + int is_bigendian, + struct dwarf_data *fileline_altlink, + backtrace_error_callback error_callback, + void *data, fileline *fileline_fn, + struct dwarf_data **fileline_entry); + +/* A data structure to pass to backtrace_syminfo_to_full. */ + +struct backtrace_call_full +{ + backtrace_full_callback full_callback; + backtrace_error_callback full_error_callback; + void *full_data; + int ret; +}; + +/* A backtrace_syminfo_callback that can call into a + backtrace_full_callback, used when we have a symbol table but no + debug info. */ + +extern void backtrace_syminfo_to_full_callback (void *data, uintptr_t pc, + const char *symname, + uintptr_t symval, + uintptr_t symsize); + +/* An error callback that corresponds to + backtrace_syminfo_to_full_callback. */ + +extern void backtrace_syminfo_to_full_error_callback (void *, const char *, + int); + +/* A test-only hook for elf_uncompress_zdebug. */ + +extern int backtrace_uncompress_zdebug (struct backtrace_state *, + const unsigned char *compressed, + size_t compressed_size, + backtrace_error_callback, void *data, + unsigned char **uncompressed, + size_t *uncompressed_size); + +/* A test-only hook for elf_zstd_decompress. */ + +extern int backtrace_uncompress_zstd (struct backtrace_state *, + const unsigned char *compressed, + size_t compressed_size, + backtrace_error_callback, void *data, + unsigned char *uncompressed, + size_t uncompressed_size); + +/* A test-only hook for elf_uncompress_lzma. */ + +extern int backtrace_uncompress_lzma (struct backtrace_state *, + const unsigned char *compressed, + size_t compressed_size, + backtrace_error_callback, void *data, + unsigned char **uncompressed, + size_t *uncompressed_size); + +} + +#endif diff --git a/Dependencies/tracy/libbacktrace/macho.cpp b/Dependencies/tracy/libbacktrace/macho.cpp new file mode 100644 index 000000000..6cccdabaa --- /dev/null +++ b/Dependencies/tracy/libbacktrace/macho.cpp @@ -0,0 +1,1360 @@ +/* elf.c -- Get debug data from a Mach-O file for backtraces. + Copyright (C) 2020-2021 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Google. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + (1) Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + (2) Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + (3) The name of the author may not be used to + endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. */ + +#include "config.h" + +#include +#include +#include +#include + +#ifdef HAVE_MACH_O_DYLD_H +#include +#endif + +#include "backtrace.hpp" +#include "internal.hpp" + +namespace tracy +{ + +/* Mach-O file header for a 32-bit executable. */ + +struct macho_header_32 +{ + uint32_t magic; /* Magic number (MACH_O_MAGIC_32) */ + uint32_t cputype; /* CPU type */ + uint32_t cpusubtype; /* CPU subtype */ + uint32_t filetype; /* Type of file (object, executable) */ + uint32_t ncmds; /* Number of load commands */ + uint32_t sizeofcmds; /* Total size of load commands */ + uint32_t flags; /* Flags for special features */ +}; + +/* Mach-O file header for a 64-bit executable. */ + +struct macho_header_64 +{ + uint32_t magic; /* Magic number (MACH_O_MAGIC_64) */ + uint32_t cputype; /* CPU type */ + uint32_t cpusubtype; /* CPU subtype */ + uint32_t filetype; /* Type of file (object, executable) */ + uint32_t ncmds; /* Number of load commands */ + uint32_t sizeofcmds; /* Total size of load commands */ + uint32_t flags; /* Flags for special features */ + uint32_t reserved; /* Reserved */ +}; + +/* Mach-O file header for a fat executable. */ + +struct macho_header_fat +{ + uint32_t magic; /* Magic number (MACH_O_MH_(MAGIC|CIGAM)_FAT(_64)?) */ + uint32_t nfat_arch; /* Number of components */ +}; + +/* Values for the header magic field. */ + +#define MACH_O_MH_MAGIC_32 0xfeedface +#define MACH_O_MH_MAGIC_64 0xfeedfacf +#define MACH_O_MH_MAGIC_FAT 0xcafebabe +#define MACH_O_MH_CIGAM_FAT 0xbebafeca +#define MACH_O_MH_MAGIC_FAT_64 0xcafebabf +#define MACH_O_MH_CIGAM_FAT_64 0xbfbafeca + +/* Value for the header filetype field. */ + +#define MACH_O_MH_EXECUTE 0x02 +#define MACH_O_MH_DYLIB 0x06 +#define MACH_O_MH_DSYM 0x0a + +/* A component of a fat file. A fat file starts with a + macho_header_fat followed by nfat_arch instances of this + struct. */ + +struct macho_fat_arch +{ + uint32_t cputype; /* CPU type */ + uint32_t cpusubtype; /* CPU subtype */ + uint32_t offset; /* File offset of this entry */ + uint32_t size; /* Size of this entry */ + uint32_t align; /* Alignment of this entry */ +}; + +/* A component of a 64-bit fat file. This is used if the magic field + is MAGIC_FAT_64. This is only used when some file size or file + offset is too large to represent in the 32-bit format. */ + +struct macho_fat_arch_64 +{ + uint32_t cputype; /* CPU type */ + uint32_t cpusubtype; /* CPU subtype */ + uint64_t offset; /* File offset of this entry */ + uint64_t size; /* Size of this entry */ + uint32_t align; /* Alignment of this entry */ + uint32_t reserved; /* Reserved */ +}; + +/* Values for the fat_arch cputype field (and the header cputype + field). */ + +#define MACH_O_CPU_ARCH_ABI64 0x01000000 + +#define MACH_O_CPU_TYPE_X86 7 +#define MACH_O_CPU_TYPE_ARM 12 +#define MACH_O_CPU_TYPE_PPC 18 + +#define MACH_O_CPU_TYPE_X86_64 (MACH_O_CPU_TYPE_X86 | MACH_O_CPU_ARCH_ABI64) +#define MACH_O_CPU_TYPE_ARM64 (MACH_O_CPU_TYPE_ARM | MACH_O_CPU_ARCH_ABI64) +#define MACH_O_CPU_TYPE_PPC64 (MACH_O_CPU_TYPE_PPC | MACH_O_CPU_ARCH_ABI64) + +/* The header of a load command. */ + +struct macho_load_command +{ + uint32_t cmd; /* The type of load command */ + uint32_t cmdsize; /* Size in bytes of the entire command */ +}; + +/* Values for the load_command cmd field. */ + +#define MACH_O_LC_SEGMENT 0x01 +#define MACH_O_LC_SYMTAB 0x02 +#define MACH_O_LC_SEGMENT_64 0x19 +#define MACH_O_LC_UUID 0x1b + +/* The length of a section of segment name. */ + +#define MACH_O_NAMELEN (16) + +/* LC_SEGMENT load command. */ + +struct macho_segment_command +{ + uint32_t cmd; /* The type of load command (LC_SEGMENT) */ + uint32_t cmdsize; /* Size in bytes of the entire command */ + char segname[MACH_O_NAMELEN]; /* Segment name */ + uint32_t vmaddr; /* Virtual memory address */ + uint32_t vmsize; /* Virtual memory size */ + uint32_t fileoff; /* Offset of data to be mapped */ + uint32_t filesize; /* Size of data in file */ + uint32_t maxprot; /* Maximum permitted virtual protection */ + uint32_t initprot; /* Initial virtual memory protection */ + uint32_t nsects; /* Number of sections in this segment */ + uint32_t flags; /* Flags */ +}; + +/* LC_SEGMENT_64 load command. */ + +struct macho_segment_64_command +{ + uint32_t cmd; /* The type of load command (LC_SEGMENT) */ + uint32_t cmdsize; /* Size in bytes of the entire command */ + char segname[MACH_O_NAMELEN]; /* Segment name */ + uint64_t vmaddr; /* Virtual memory address */ + uint64_t vmsize; /* Virtual memory size */ + uint64_t fileoff; /* Offset of data to be mapped */ + uint64_t filesize; /* Size of data in file */ + uint32_t maxprot; /* Maximum permitted virtual protection */ + uint32_t initprot; /* Initial virtual memory protection */ + uint32_t nsects; /* Number of sections in this segment */ + uint32_t flags; /* Flags */ +}; + +/* LC_SYMTAB load command. */ + +struct macho_symtab_command +{ + uint32_t cmd; /* The type of load command (LC_SEGMENT) */ + uint32_t cmdsize; /* Size in bytes of the entire command */ + uint32_t symoff; /* File offset of symbol table */ + uint32_t nsyms; /* Number of symbols */ + uint32_t stroff; /* File offset of string table */ + uint32_t strsize; /* String table size */ +}; + +/* The length of a Mach-O uuid. */ + +#define MACH_O_UUID_LEN (16) + +/* LC_UUID load command. */ + +struct macho_uuid_command +{ + uint32_t cmd; /* Type of load command (LC_UUID) */ + uint32_t cmdsize; /* Size in bytes of command */ + unsigned char uuid[MACH_O_UUID_LEN]; /* UUID */ +}; + +/* 32-bit section header within a LC_SEGMENT segment. */ + +struct macho_section +{ + char sectname[MACH_O_NAMELEN]; /* Section name */ + char segment[MACH_O_NAMELEN]; /* Segment of this section */ + uint32_t addr; /* Address in memory */ + uint32_t size; /* Section size */ + uint32_t offset; /* File offset */ + uint32_t align; /* Log2 of section alignment */ + uint32_t reloff; /* File offset of relocations */ + uint32_t nreloc; /* Number of relocs for this section */ + uint32_t flags; /* Flags */ + uint32_t reserved1; + uint32_t reserved2; +}; + +/* 64-bit section header within a LC_SEGMENT_64 segment. */ + +struct macho_section_64 +{ + char sectname[MACH_O_NAMELEN]; /* Section name */ + char segment[MACH_O_NAMELEN]; /* Segment of this section */ + uint64_t addr; /* Address in memory */ + uint64_t size; /* Section size */ + uint32_t offset; /* File offset */ + uint32_t align; /* Log2 of section alignment */ + uint32_t reloff; /* File offset of section relocations */ + uint32_t nreloc; /* Number of relocs for this section */ + uint32_t flags; /* Flags */ + uint32_t reserved1; + uint32_t reserved2; + uint32_t reserved3; +}; + +/* 32-bit symbol data. */ + +struct macho_nlist +{ + uint32_t n_strx; /* Index of name in string table */ + uint8_t n_type; /* Type flag */ + uint8_t n_sect; /* Section number */ + uint16_t n_desc; /* Stabs description field */ + uint32_t n_value; /* Value */ +}; + +/* 64-bit symbol data. */ + +struct macho_nlist_64 +{ + uint32_t n_strx; /* Index of name in string table */ + uint8_t n_type; /* Type flag */ + uint8_t n_sect; /* Section number */ + uint16_t n_desc; /* Stabs description field */ + uint64_t n_value; /* Value */ +}; + +/* Value found in nlist n_type field. */ + +#define MACH_O_N_EXT 0x01 /* Extern symbol */ +#define MACH_O_N_ABS 0x02 /* Absolute symbol */ +#define MACH_O_N_SECT 0x0e /* Defined in section */ + +#define MACH_O_N_TYPE 0x0e /* Mask for type bits */ +#define MACH_O_N_STAB 0xe0 /* Stabs debugging symbol */ + +/* Information we keep for a Mach-O symbol. */ + +struct macho_symbol +{ + const char *name; /* Symbol name */ + uintptr_t address; /* Symbol address */ +}; + +/* Information to pass to macho_syminfo. */ + +struct macho_syminfo_data +{ + struct macho_syminfo_data *next; /* Next module */ + struct macho_symbol *symbols; /* Symbols sorted by address */ + size_t count; /* Number of symbols */ +}; + +/* Names of sections, indexed by enum dwarf_section in internal.h. */ + +static const char * const dwarf_section_names[DEBUG_MAX] = +{ + "__debug_info", + "__debug_line", + "__debug_abbrev", + "__debug_ranges", + "__debug_str", + "", /* DEBUG_ADDR */ + "__debug_str_offs", + "", /* DEBUG_LINE_STR */ + "__debug_rnglists" +}; + +/* Forward declaration. */ + +static int macho_add (struct backtrace_state *, const char *, int, off_t, + const unsigned char *, uintptr_t, int, + backtrace_error_callback, void *, fileline *, int *); + +/* A dummy callback function used when we can't find any debug info. */ + +static int +macho_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED, + uintptr_t pc ATTRIBUTE_UNUSED, + backtrace_full_callback callback ATTRIBUTE_UNUSED, + backtrace_error_callback error_callback, void *data) +{ + error_callback (data, "no debug info in Mach-O executable", -1); + return 0; +} + +/* A dummy callback function used when we can't find a symbol + table. */ + +static void +macho_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED, + uintptr_t addr ATTRIBUTE_UNUSED, + backtrace_syminfo_callback callback ATTRIBUTE_UNUSED, + backtrace_error_callback error_callback, void *data) +{ + error_callback (data, "no symbol table in Mach-O executable", -1); +} + +/* Add a single DWARF section to DWARF_SECTIONS, if we need the + section. Returns 1 on success, 0 on failure. */ + +static int +macho_add_dwarf_section (struct backtrace_state *state, int descriptor, + const char *sectname, uint32_t offset, uint64_t size, + backtrace_error_callback error_callback, void *data, + struct dwarf_sections *dwarf_sections) +{ + int i; + + for (i = 0; i < (int) DEBUG_MAX; ++i) + { + if (dwarf_section_names[i][0] != '\0' + && strncmp (sectname, dwarf_section_names[i], MACH_O_NAMELEN) == 0) + { + struct backtrace_view section_view; + + /* FIXME: Perhaps it would be better to try to use a single + view to read all the DWARF data, as we try to do for + ELF. */ + + if (!backtrace_get_view (state, descriptor, offset, size, + error_callback, data, §ion_view)) + return 0; + dwarf_sections->data[i] = (const unsigned char *) section_view.data; + dwarf_sections->size[i] = size; + break; + } + } + return 1; +} + +/* Collect DWARF sections from a DWARF segment. Returns 1 on success, + 0 on failure. */ + +static int +macho_add_dwarf_segment (struct backtrace_state *state, int descriptor, + off_t offset, unsigned int cmd, const char *psecs, + size_t sizesecs, unsigned int nsects, + backtrace_error_callback error_callback, void *data, + struct dwarf_sections *dwarf_sections) +{ + size_t sec_header_size; + size_t secoffset; + unsigned int i; + + switch (cmd) + { + case MACH_O_LC_SEGMENT: + sec_header_size = sizeof (struct macho_section); + break; + case MACH_O_LC_SEGMENT_64: + sec_header_size = sizeof (struct macho_section_64); + break; + default: + abort (); + } + + secoffset = 0; + for (i = 0; i < nsects; ++i) + { + if (secoffset + sec_header_size > sizesecs) + { + error_callback (data, "section overflow withing segment", 0); + return 0; + } + + switch (cmd) + { + case MACH_O_LC_SEGMENT: + { + struct macho_section section; + + memcpy (§ion, psecs + secoffset, sizeof section); + macho_add_dwarf_section (state, descriptor, section.sectname, + offset + section.offset, section.size, + error_callback, data, dwarf_sections); + } + break; + + case MACH_O_LC_SEGMENT_64: + { + struct macho_section_64 section; + + memcpy (§ion, psecs + secoffset, sizeof section); + macho_add_dwarf_section (state, descriptor, section.sectname, + offset + section.offset, section.size, + error_callback, data, dwarf_sections); + } + break; + + default: + abort (); + } + + secoffset += sec_header_size; + } + + return 1; +} + +/* Compare struct macho_symbol for qsort. */ + +static int +macho_symbol_compare (const void *v1, const void *v2) +{ + const struct macho_symbol *m1 = (const struct macho_symbol *) v1; + const struct macho_symbol *m2 = (const struct macho_symbol *) v2; + + if (m1->address < m2->address) + return -1; + else if (m1->address > m2->address) + return 1; + else + return 0; +} + +/* Compare an address against a macho_symbol for bsearch. We allocate + one extra entry in the array so that this can safely look at the + next entry. */ + +static int +macho_symbol_search (const void *vkey, const void *ventry) +{ + const uintptr_t *key = (const uintptr_t *) vkey; + const struct macho_symbol *entry = (const struct macho_symbol *) ventry; + uintptr_t addr; + + addr = *key; + if (addr < entry->address) + return -1; + else if (entry->name[0] == '\0' + && entry->address == ~(uintptr_t) 0) + return -1; + else if ((entry + 1)->name[0] == '\0' + && (entry + 1)->address == ~(uintptr_t) 0) + return -1; + else if (addr >= (entry + 1)->address) + return 1; + else + return 0; +} + +/* Return whether the symbol type field indicates a symbol table entry + that we care about: a function or data symbol. */ + +static int +macho_defined_symbol (uint8_t type) +{ + if ((type & MACH_O_N_STAB) != 0) + return 0; + if ((type & MACH_O_N_EXT) != 0) + return 0; + switch (type & MACH_O_N_TYPE) + { + case MACH_O_N_ABS: + return 1; + case MACH_O_N_SECT: + return 1; + default: + return 0; + } +} + +/* Add symbol table information for a Mach-O file. */ + +static int +macho_add_symtab (struct backtrace_state *state, int descriptor, + uintptr_t base_address, int is_64, + off_t symoff, unsigned int nsyms, off_t stroff, + unsigned int strsize, + backtrace_error_callback error_callback, void *data) +{ + size_t symsize; + struct backtrace_view sym_view; + int sym_view_valid; + struct backtrace_view str_view; + int str_view_valid; + size_t ndefs; + size_t symtaboff; + unsigned int i; + size_t macho_symbol_size; + struct macho_symbol *macho_symbols; + unsigned int j; + struct macho_syminfo_data *sdata; + + sym_view_valid = 0; + str_view_valid = 0; + macho_symbol_size = 0; + macho_symbols = NULL; + + if (is_64) + symsize = sizeof (struct macho_nlist_64); + else + symsize = sizeof (struct macho_nlist); + + if (!backtrace_get_view (state, descriptor, symoff, nsyms * symsize, + error_callback, data, &sym_view)) + goto fail; + sym_view_valid = 1; + + if (!backtrace_get_view (state, descriptor, stroff, strsize, + error_callback, data, &str_view)) + return 0; + str_view_valid = 1; + + ndefs = 0; + symtaboff = 0; + for (i = 0; i < nsyms; ++i, symtaboff += symsize) + { + if (is_64) + { + struct macho_nlist_64 nlist; + + memcpy (&nlist, (const char *) sym_view.data + symtaboff, + sizeof nlist); + if (macho_defined_symbol (nlist.n_type)) + ++ndefs; + } + else + { + struct macho_nlist nlist; + + memcpy (&nlist, (const char *) sym_view.data + symtaboff, + sizeof nlist); + if (macho_defined_symbol (nlist.n_type)) + ++ndefs; + } + } + + /* Add 1 to ndefs to make room for a sentinel. */ + macho_symbol_size = (ndefs + 1) * sizeof (struct macho_symbol); + macho_symbols = ((struct macho_symbol *) + backtrace_alloc (state, macho_symbol_size, error_callback, + data)); + if (macho_symbols == NULL) + goto fail; + + j = 0; + symtaboff = 0; + for (i = 0; i < nsyms; ++i, symtaboff += symsize) + { + uint32_t strx; + uint64_t value; + const char *name; + + strx = 0; + value = 0; + if (is_64) + { + struct macho_nlist_64 nlist; + + memcpy (&nlist, (const char *) sym_view.data + symtaboff, + sizeof nlist); + if (!macho_defined_symbol (nlist.n_type)) + continue; + + strx = nlist.n_strx; + value = nlist.n_value; + } + else + { + struct macho_nlist nlist; + + memcpy (&nlist, (const char *) sym_view.data + symtaboff, + sizeof nlist); + if (!macho_defined_symbol (nlist.n_type)) + continue; + + strx = nlist.n_strx; + value = nlist.n_value; + } + + if (strx >= strsize) + { + error_callback (data, "symbol string index out of range", 0); + goto fail; + } + + name = (const char *) str_view.data + strx; + if (name[0] == '_') + ++name; + macho_symbols[j].name = name; + macho_symbols[j].address = value + base_address; + ++j; + } + + sdata = ((struct macho_syminfo_data *) + backtrace_alloc (state, sizeof *sdata, error_callback, data)); + if (sdata == NULL) + goto fail; + + /* We need to keep the string table since it holds the names, but we + can release the symbol table. */ + + backtrace_release_view (state, &sym_view, error_callback, data); + sym_view_valid = 0; + str_view_valid = 0; + + /* Add a trailing sentinel symbol. */ + macho_symbols[j].name = ""; + macho_symbols[j].address = ~(uintptr_t) 0; + + backtrace_qsort (macho_symbols, ndefs + 1, sizeof (struct macho_symbol), + macho_symbol_compare); + + sdata->next = NULL; + sdata->symbols = macho_symbols; + sdata->count = ndefs; + + if (!state->threaded) + { + struct macho_syminfo_data **pp; + + for (pp = (struct macho_syminfo_data **) (void *) &state->syminfo_data; + *pp != NULL; + pp = &(*pp)->next) + ; + *pp = sdata; + } + else + { + while (1) + { + struct macho_syminfo_data **pp; + + pp = (struct macho_syminfo_data **) (void *) &state->syminfo_data; + + while (1) + { + struct macho_syminfo_data *p; + + p = backtrace_atomic_load_pointer (pp); + + if (p == NULL) + break; + + pp = &p->next; + } + + if (__sync_bool_compare_and_swap (pp, NULL, sdata)) + break; + } + } + + return 1; + + fail: + if (macho_symbols != NULL) + backtrace_free (state, macho_symbols, macho_symbol_size, + error_callback, data); + if (sym_view_valid) + backtrace_release_view (state, &sym_view, error_callback, data); + if (str_view_valid) + backtrace_release_view (state, &str_view, error_callback, data); + return 0; +} + +/* Return the symbol name and value for an ADDR. */ + +static void +macho_syminfo (struct backtrace_state *state, uintptr_t addr, + backtrace_syminfo_callback callback, + backtrace_error_callback error_callback ATTRIBUTE_UNUSED, + void *data) +{ + struct macho_syminfo_data *sdata; + struct macho_symbol *sym; + + sym = NULL; + if (!state->threaded) + { + for (sdata = (struct macho_syminfo_data *) state->syminfo_data; + sdata != NULL; + sdata = sdata->next) + { + sym = ((struct macho_symbol *) + bsearch (&addr, sdata->symbols, sdata->count, + sizeof (struct macho_symbol), macho_symbol_search)); + if (sym != NULL) + break; + } + } + else + { + struct macho_syminfo_data **pp; + + pp = (struct macho_syminfo_data **) (void *) &state->syminfo_data; + while (1) + { + sdata = backtrace_atomic_load_pointer (pp); + if (sdata == NULL) + break; + + sym = ((struct macho_symbol *) + bsearch (&addr, sdata->symbols, sdata->count, + sizeof (struct macho_symbol), macho_symbol_search)); + if (sym != NULL) + break; + + pp = &sdata->next; + } + } + + if (sym == NULL) + callback (data, addr, NULL, 0, 0); + else + callback (data, addr, sym->name, sym->address, 0); +} + +/* Look through a fat file to find the relevant executable. Returns 1 + on success, 0 on failure (in both cases descriptor is closed). */ + +static int +macho_add_fat (struct backtrace_state *state, const char *filename, + int descriptor, int swapped, off_t offset, + const unsigned char *match_uuid, uintptr_t base_address, + int skip_symtab, uint32_t nfat_arch, int is_64, + backtrace_error_callback error_callback, void *data, + fileline *fileline_fn, int *found_sym) +{ + int arch_view_valid; + unsigned int cputype; + size_t arch_size; + struct backtrace_view arch_view; + unsigned int i; + + arch_view_valid = 0; + +#if defined (__x86_64__) + cputype = MACH_O_CPU_TYPE_X86_64; +#elif defined (__i386__) + cputype = MACH_O_CPU_TYPE_X86; +#elif defined (__aarch64__) + cputype = MACH_O_CPU_TYPE_ARM64; +#elif defined (__arm__) + cputype = MACH_O_CPU_TYPE_ARM; +#elif defined (__ppc__) + cputype = MACH_O_CPU_TYPE_PPC; +#elif defined (__ppc64__) + cputype = MACH_O_CPU_TYPE_PPC64; +#else + error_callback (data, "unknown Mach-O architecture", 0); + goto fail; +#endif + + if (is_64) + arch_size = sizeof (struct macho_fat_arch_64); + else + arch_size = sizeof (struct macho_fat_arch); + + if (!backtrace_get_view (state, descriptor, offset, + nfat_arch * arch_size, + error_callback, data, &arch_view)) + goto fail; + + for (i = 0; i < nfat_arch; ++i) + { + uint32_t fcputype; + uint64_t foffset; + + if (is_64) + { + struct macho_fat_arch_64 fat_arch_64; + + memcpy (&fat_arch_64, + (const char *) arch_view.data + i * arch_size, + arch_size); + fcputype = fat_arch_64.cputype; + foffset = fat_arch_64.offset; + if (swapped) + { + fcputype = __builtin_bswap32 (fcputype); + foffset = __builtin_bswap64 (foffset); + } + } + else + { + struct macho_fat_arch fat_arch_32; + + memcpy (&fat_arch_32, + (const char *) arch_view.data + i * arch_size, + arch_size); + fcputype = fat_arch_32.cputype; + foffset = (uint64_t) fat_arch_32.offset; + if (swapped) + { + fcputype = __builtin_bswap32 (fcputype); + foffset = (uint64_t) __builtin_bswap32 ((uint32_t) foffset); + } + } + + if (fcputype == cputype) + { + /* FIXME: What about cpusubtype? */ + backtrace_release_view (state, &arch_view, error_callback, data); + return macho_add (state, filename, descriptor, foffset, match_uuid, + base_address, skip_symtab, error_callback, data, + fileline_fn, found_sym); + } + } + + error_callback (data, "could not find executable in fat file", 0); + + fail: + if (arch_view_valid) + backtrace_release_view (state, &arch_view, error_callback, data); + if (descriptor != -1) + backtrace_close (descriptor, error_callback, data); + return 0; +} + +/* Look for the dsym file for FILENAME. This is called if FILENAME + does not have debug info or a symbol table. Returns 1 on success, + 0 on failure. */ + +static int +macho_add_dsym (struct backtrace_state *state, const char *filename, + uintptr_t base_address, const unsigned char *uuid, + backtrace_error_callback error_callback, void *data, + fileline* fileline_fn) +{ + const char *p; + const char *dirname; + char *diralc; + size_t dirnamelen; + const char *basename; + size_t basenamelen; + const char *dsymsuffixdir; + size_t dsymsuffixdirlen; + size_t dsymlen; + char *dsym; + char *ps; + int d; + int does_not_exist; + int dummy_found_sym; + + diralc = NULL; + dirnamelen = 0; + dsym = NULL; + dsymlen = 0; + + p = strrchr (filename, '/'); + if (p == NULL) + { + dirname = "."; + dirnamelen = 1; + basename = filename; + basenamelen = strlen (basename); + diralc = NULL; + } + else + { + dirnamelen = p - filename; + diralc = (char*)backtrace_alloc (state, dirnamelen + 1, error_callback, data); + if (diralc == NULL) + goto fail; + memcpy (diralc, filename, dirnamelen); + diralc[dirnamelen] = '\0'; + dirname = diralc; + basename = p + 1; + basenamelen = strlen (basename); + } + + dsymsuffixdir = ".dSYM/Contents/Resources/DWARF/"; + dsymsuffixdirlen = strlen (dsymsuffixdir); + + dsymlen = (dirnamelen + + 1 + + basenamelen + + dsymsuffixdirlen + + basenamelen + + 1); + dsym = (char*)backtrace_alloc (state, dsymlen, error_callback, data); + if (dsym == NULL) + goto fail; + + ps = dsym; + memcpy (ps, dirname, dirnamelen); + ps += dirnamelen; + *ps++ = '/'; + memcpy (ps, basename, basenamelen); + ps += basenamelen; + memcpy (ps, dsymsuffixdir, dsymsuffixdirlen); + ps += dsymsuffixdirlen; + memcpy (ps, basename, basenamelen); + ps += basenamelen; + *ps = '\0'; + + if (diralc != NULL) + { + backtrace_free (state, diralc, dirnamelen + 1, error_callback, data); + diralc = NULL; + } + + d = backtrace_open (dsym, error_callback, data, &does_not_exist); + if (d < 0) + { + /* The file does not exist, so we can't read the debug info. + Just return success. */ + backtrace_free (state, dsym, dsymlen, error_callback, data); + return 1; + } + + if (!macho_add (state, dsym, d, 0, uuid, base_address, 1, + error_callback, data, fileline_fn, &dummy_found_sym)) + goto fail; + + backtrace_free (state, dsym, dsymlen, error_callback, data); + + return 1; + + fail: + if (dsym != NULL) + backtrace_free (state, dsym, dsymlen, error_callback, data); + if (diralc != NULL) + backtrace_free (state, diralc, dirnamelen, error_callback, data); + return 0; +} + +/* Add the backtrace data for a Macho-O file. Returns 1 on success, 0 + on failure (in both cases descriptor is closed). + + FILENAME: the name of the executable. + DESCRIPTOR: an open descriptor for the executable, closed here. + OFFSET: the offset within the file of this executable, for fat files. + MATCH_UUID: if not NULL, UUID that must match. + BASE_ADDRESS: the load address of the executable. + SKIP_SYMTAB: if non-zero, ignore the symbol table; used for dSYM files. + FILELINE_FN: set to the fileline function, by backtrace_dwarf_add. + FOUND_SYM: set to non-zero if we found the symbol table. +*/ + +static int +macho_add (struct backtrace_state *state, const char *filename, int descriptor, + off_t offset, const unsigned char *match_uuid, + uintptr_t base_address, int skip_symtab, + backtrace_error_callback error_callback, void *data, + fileline *fileline_fn, int *found_sym) +{ + struct backtrace_view header_view; + struct macho_header_32 header; + off_t hdroffset; + int is_64; + struct backtrace_view cmds_view; + int cmds_view_valid; + struct dwarf_sections dwarf_sections; + int have_dwarf; + unsigned char uuid[MACH_O_UUID_LEN]; + int have_uuid; + size_t cmdoffset; + unsigned int i; + + *found_sym = 0; + + cmds_view_valid = 0; + + /* The 32-bit and 64-bit file headers start out the same, so we can + just always read the 32-bit version. A fat header is shorter but + it will always be followed by data, so it's OK to read extra. */ + + if (!backtrace_get_view (state, descriptor, offset, + sizeof (struct macho_header_32), + error_callback, data, &header_view)) + goto fail; + + memcpy (&header, header_view.data, sizeof header); + + backtrace_release_view (state, &header_view, error_callback, data); + + switch (header.magic) + { + case MACH_O_MH_MAGIC_32: + is_64 = 0; + hdroffset = offset + sizeof (struct macho_header_32); + break; + case MACH_O_MH_MAGIC_64: + is_64 = 1; + hdroffset = offset + sizeof (struct macho_header_64); + break; + case MACH_O_MH_MAGIC_FAT: + case MACH_O_MH_MAGIC_FAT_64: + { + struct macho_header_fat fat_header; + + hdroffset = offset + sizeof (struct macho_header_fat); + memcpy (&fat_header, &header, sizeof fat_header); + return macho_add_fat (state, filename, descriptor, 0, hdroffset, + match_uuid, base_address, skip_symtab, + fat_header.nfat_arch, + header.magic == MACH_O_MH_MAGIC_FAT_64, + error_callback, data, fileline_fn, found_sym); + } + case MACH_O_MH_CIGAM_FAT: + case MACH_O_MH_CIGAM_FAT_64: + { + struct macho_header_fat fat_header; + uint32_t nfat_arch; + + hdroffset = offset + sizeof (struct macho_header_fat); + memcpy (&fat_header, &header, sizeof fat_header); + nfat_arch = __builtin_bswap32 (fat_header.nfat_arch); + return macho_add_fat (state, filename, descriptor, 1, hdroffset, + match_uuid, base_address, skip_symtab, + nfat_arch, + header.magic == MACH_O_MH_CIGAM_FAT_64, + error_callback, data, fileline_fn, found_sym); + } + default: + error_callback (data, "executable file is not in Mach-O format", 0); + goto fail; + } + + switch (header.filetype) + { + case MACH_O_MH_EXECUTE: + case MACH_O_MH_DYLIB: + case MACH_O_MH_DSYM: + break; + default: + error_callback (data, "executable file is not an executable", 0); + goto fail; + } + + if (!backtrace_get_view (state, descriptor, hdroffset, header.sizeofcmds, + error_callback, data, &cmds_view)) + goto fail; + cmds_view_valid = 1; + + memset (&dwarf_sections, 0, sizeof dwarf_sections); + have_dwarf = 0; + memset (&uuid, 0, sizeof uuid); + have_uuid = 0; + + cmdoffset = 0; + for (i = 0; i < header.ncmds; ++i) + { + const char *pcmd; + struct macho_load_command load_command; + + if (cmdoffset + sizeof load_command > header.sizeofcmds) + break; + + pcmd = (const char *) cmds_view.data + cmdoffset; + memcpy (&load_command, pcmd, sizeof load_command); + + switch (load_command.cmd) + { + case MACH_O_LC_SEGMENT: + { + struct macho_segment_command segcmd; + + memcpy (&segcmd, pcmd, sizeof segcmd); + if (memcmp (segcmd.segname, + "__DWARF\0\0\0\0\0\0\0\0\0", + MACH_O_NAMELEN) == 0) + { + if (!macho_add_dwarf_segment (state, descriptor, offset, + load_command.cmd, + pcmd + sizeof segcmd, + (load_command.cmdsize + - sizeof segcmd), + segcmd.nsects, error_callback, + data, &dwarf_sections)) + goto fail; + have_dwarf = 1; + } + } + break; + + case MACH_O_LC_SEGMENT_64: + { + struct macho_segment_64_command segcmd; + + memcpy (&segcmd, pcmd, sizeof segcmd); + if (memcmp (segcmd.segname, + "__DWARF\0\0\0\0\0\0\0\0\0", + MACH_O_NAMELEN) == 0) + { + if (!macho_add_dwarf_segment (state, descriptor, offset, + load_command.cmd, + pcmd + sizeof segcmd, + (load_command.cmdsize + - sizeof segcmd), + segcmd.nsects, error_callback, + data, &dwarf_sections)) + goto fail; + have_dwarf = 1; + } + } + break; + + case MACH_O_LC_SYMTAB: + if (!skip_symtab) + { + struct macho_symtab_command symcmd; + + memcpy (&symcmd, pcmd, sizeof symcmd); + if (!macho_add_symtab (state, descriptor, base_address, is_64, + offset + symcmd.symoff, symcmd.nsyms, + offset + symcmd.stroff, symcmd.strsize, + error_callback, data)) + goto fail; + + *found_sym = 1; + } + break; + + case MACH_O_LC_UUID: + { + struct macho_uuid_command uuidcmd; + + memcpy (&uuidcmd, pcmd, sizeof uuidcmd); + memcpy (&uuid[0], &uuidcmd.uuid[0], MACH_O_UUID_LEN); + have_uuid = 1; + } + break; + + default: + break; + } + + cmdoffset += load_command.cmdsize; + } + + if (!backtrace_close (descriptor, error_callback, data)) + goto fail; + descriptor = -1; + + backtrace_release_view (state, &cmds_view, error_callback, data); + cmds_view_valid = 0; + + if (match_uuid != NULL) + { + /* If we don't have a UUID, or it doesn't match, just ignore + this file. */ + if (!have_uuid + || memcmp (match_uuid, &uuid[0], MACH_O_UUID_LEN) != 0) + return 1; + } + + if (have_dwarf) + { + int is_big_endian; + + is_big_endian = 0; +#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + is_big_endian = 1; +#endif +#endif + + if (!backtrace_dwarf_add (state, base_address, &dwarf_sections, + is_big_endian, NULL, error_callback, data, + fileline_fn, NULL)) + goto fail; + } + + if (!have_dwarf && have_uuid) + { + if (!macho_add_dsym (state, filename, base_address, &uuid[0], + error_callback, data, fileline_fn)) + goto fail; + } + + return 1; + + fail: + if (cmds_view_valid) + backtrace_release_view (state, &cmds_view, error_callback, data); + if (descriptor != -1) + backtrace_close (descriptor, error_callback, data); + return 0; +} + +#ifdef HAVE_MACH_O_DYLD_H + +/* Initialize the backtrace data we need from a Mach-O executable + using the dyld support functions. This closes descriptor. */ + +int +backtrace_initialize (struct backtrace_state *state, const char *filename, + int descriptor, backtrace_error_callback error_callback, + void *data, fileline *fileline_fn) +{ + uint32_t c; + uint32_t i; + int closed_descriptor; + int found_sym; + fileline macho_fileline_fn; + + closed_descriptor = 0; + found_sym = 0; + macho_fileline_fn = macho_nodebug; + + c = _dyld_image_count (); + for (i = 0; i < c; ++i) + { + uintptr_t base_address; + const char *name; + int d; + fileline mff; + int mfs; + + name = _dyld_get_image_name (i); + if (name == NULL) + continue; + + if (strcmp (name, filename) == 0 && !closed_descriptor) + { + d = descriptor; + closed_descriptor = 1; + } + else + { + int does_not_exist; + + d = backtrace_open (name, error_callback, data, &does_not_exist); + if (d < 0) + continue; + } + + base_address = _dyld_get_image_vmaddr_slide (i); + + mff = macho_nodebug; + if (!macho_add (state, name, d, 0, NULL, base_address, 0, + error_callback, data, &mff, &mfs)) + continue; + + if (mff != macho_nodebug) + macho_fileline_fn = mff; + if (mfs) + found_sym = 1; + } + + if (!closed_descriptor) + backtrace_close (descriptor, error_callback, data); + + if (!state->threaded) + { + if (found_sym) + state->syminfo_fn = macho_syminfo; + else if (state->syminfo_fn == NULL) + state->syminfo_fn = macho_nosyms; + } + else + { + if (found_sym) + backtrace_atomic_store_pointer (&state->syminfo_fn, &macho_syminfo); + else + (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL, + macho_nosyms); + } + + if (!state->threaded) + *fileline_fn = state->fileline_fn; + else + *fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn); + + if (*fileline_fn == NULL || *fileline_fn == macho_nodebug) + *fileline_fn = macho_fileline_fn; + + return 1; +} + +#else /* !defined (HAVE_MACH_O_DYLD_H) */ + +/* Initialize the backtrace data we need from a Mach-O executable + without using the dyld support functions. This closes + descriptor. */ + +int +backtrace_initialize (struct backtrace_state *state, const char *filename, + int descriptor, backtrace_error_callback error_callback, + void *data, fileline *fileline_fn) +{ + fileline macho_fileline_fn; + int found_sym; + + macho_fileline_fn = macho_nodebug; + if (!macho_add (state, filename, descriptor, 0, NULL, 0, 0, + error_callback, data, &macho_fileline_fn, &found_sym)) + return 0; + + if (!state->threaded) + { + if (found_sym) + state->syminfo_fn = macho_syminfo; + else if (state->syminfo_fn == NULL) + state->syminfo_fn = macho_nosyms; + } + else + { + if (found_sym) + backtrace_atomic_store_pointer (&state->syminfo_fn, &macho_syminfo); + else + (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL, + macho_nosyms); + } + + if (!state->threaded) + *fileline_fn = state->fileline_fn; + else + *fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn); + + if (*fileline_fn == NULL || *fileline_fn == macho_nodebug) + *fileline_fn = macho_fileline_fn; + + return 1; +} + +#endif /* !defined (HAVE_MACH_O_DYLD_H) */ + +} diff --git a/Dependencies/tracy/libbacktrace/mmapio.cpp b/Dependencies/tracy/libbacktrace/mmapio.cpp new file mode 100644 index 000000000..0e8f599bb --- /dev/null +++ b/Dependencies/tracy/libbacktrace/mmapio.cpp @@ -0,0 +1,115 @@ +/* mmapio.c -- File views using mmap. + Copyright (C) 2012-2021 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Google. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + (1) Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + (2) Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + (3) The name of the author may not be used to + endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. */ + +#include "config.h" + +#include +#include +#include +#include + +#include "backtrace.hpp" +#include "internal.hpp" + +#ifndef HAVE_DECL_GETPAGESIZE +extern int getpagesize (void); +#endif + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +namespace tracy +{ + +/* This file implements file views and memory allocation when mmap is + available. */ + +/* Create a view of SIZE bytes from DESCRIPTOR at OFFSET. */ + +int +backtrace_get_view (struct backtrace_state *state ATTRIBUTE_UNUSED, + int descriptor, off_t offset, uint64_t size, + backtrace_error_callback error_callback, + void *data, struct backtrace_view *view) +{ + size_t pagesize; + unsigned int inpage; + off_t pageoff; + void *map; + + if ((uint64_t) (size_t) size != size) + { + error_callback (data, "file size too large", 0); + return 0; + } + + pagesize = getpagesize (); + inpage = offset % pagesize; + pageoff = offset - inpage; + + size += inpage; + size = (size + (pagesize - 1)) & ~ (pagesize - 1); + + map = mmap (NULL, size, PROT_READ, MAP_PRIVATE, descriptor, pageoff); + if (map == MAP_FAILED) + { + error_callback (data, "mmap", errno); + return 0; + } + + view->data = (char *) map + inpage; + view->base = map; + view->len = size; + + return 1; +} + +/* Release a view read by backtrace_get_view. */ + +void +backtrace_release_view (struct backtrace_state *state ATTRIBUTE_UNUSED, + struct backtrace_view *view, + backtrace_error_callback error_callback, + void *data) +{ + union { + const void *cv; + void *v; + } cc; + + cc.cv = view->base; + if (munmap (cc.v, view->len) < 0) + error_callback (data, "munmap", errno); +} + +} diff --git a/Dependencies/tracy/libbacktrace/posix.cpp b/Dependencies/tracy/libbacktrace/posix.cpp new file mode 100644 index 000000000..8233a8ea3 --- /dev/null +++ b/Dependencies/tracy/libbacktrace/posix.cpp @@ -0,0 +1,109 @@ +/* posix.c -- POSIX file I/O routines for the backtrace library. + Copyright (C) 2012-2021 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Google. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + (1) Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + (2) Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + (3) The name of the author may not be used to + endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. */ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include "backtrace.hpp" +#include "internal.hpp" + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + +#ifndef FD_CLOEXEC +#define FD_CLOEXEC 1 +#endif + +namespace tracy +{ + +/* Open a file for reading. */ + +int +backtrace_open (const char *filename, backtrace_error_callback error_callback, + void *data, int *does_not_exist) +{ + int descriptor; + + if (does_not_exist != NULL) + *does_not_exist = 0; + + descriptor = open (filename, (int) (O_RDONLY | O_BINARY | O_CLOEXEC)); + if (descriptor < 0) + { + /* If DOES_NOT_EXIST is not NULL, then don't call ERROR_CALLBACK + if the file does not exist. We treat lacking permission to + open the file as the file not existing; this case arises when + running the libgo syscall package tests as root. */ + if (does_not_exist != NULL && (errno == ENOENT || errno == EACCES)) + *does_not_exist = 1; + else + error_callback (data, filename, errno); + return -1; + } + +#ifdef HAVE_FCNTL + /* Set FD_CLOEXEC just in case the kernel does not support + O_CLOEXEC. It doesn't matter if this fails for some reason. + FIXME: At some point it should be safe to only do this if + O_CLOEXEC == 0. */ + fcntl (descriptor, F_SETFD, FD_CLOEXEC); +#endif + + return descriptor; +} + +/* Close DESCRIPTOR. */ + +int +backtrace_close (int descriptor, backtrace_error_callback error_callback, + void *data) +{ + if (close (descriptor) < 0) + { + error_callback (data, "close", errno); + return 0; + } + return 1; +} + +} diff --git a/Dependencies/tracy/libbacktrace/sort.cpp b/Dependencies/tracy/libbacktrace/sort.cpp new file mode 100644 index 000000000..6daee0a64 --- /dev/null +++ b/Dependencies/tracy/libbacktrace/sort.cpp @@ -0,0 +1,113 @@ +/* sort.c -- Sort without allocating memory + Copyright (C) 2012-2021 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Google. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + (1) Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + (2) Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + (3) The name of the author may not be used to + endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. */ + +#include "config.h" + +#include +#include + +#include "backtrace.hpp" +#include "internal.hpp" + +namespace tracy +{ + +/* The GNU glibc version of qsort allocates memory, which we must not + do if we are invoked by a signal handler. So provide our own + sort. */ + +static void +swap (char *a, char *b, size_t size) +{ + size_t i; + + for (i = 0; i < size; i++, a++, b++) + { + char t; + + t = *a; + *a = *b; + *b = t; + } +} + +void +backtrace_qsort (void *basearg, size_t count, size_t size, + int (*compar) (const void *, const void *)) +{ + char *base = (char *) basearg; + size_t i; + size_t mid; + + tail_recurse: + if (count < 2) + return; + + /* The symbol table and DWARF tables, which is all we use this + routine for, tend to be roughly sorted. Pick the middle element + in the array as our pivot point, so that we are more likely to + cut the array in half for each recursion step. */ + swap (base, base + (count / 2) * size, size); + + mid = 0; + for (i = 1; i < count; i++) + { + if ((*compar) (base, base + i * size) > 0) + { + ++mid; + if (i != mid) + swap (base + mid * size, base + i * size, size); + } + } + + if (mid > 0) + swap (base, base + mid * size, size); + + /* Recurse with the smaller array, loop with the larger one. That + ensures that our maximum stack depth is log count. */ + if (2 * mid < count) + { + backtrace_qsort (base, mid, size, compar); + base += (mid + 1) * size; + count -= mid + 1; + goto tail_recurse; + } + else + { + backtrace_qsort (base + (mid + 1) * size, count - (mid + 1), + size, compar); + count = mid; + goto tail_recurse; + } +} + +} diff --git a/Dependencies/tracy/libbacktrace/state.cpp b/Dependencies/tracy/libbacktrace/state.cpp new file mode 100644 index 000000000..ea3c137c5 --- /dev/null +++ b/Dependencies/tracy/libbacktrace/state.cpp @@ -0,0 +1,76 @@ +/* state.c -- Create the backtrace state. + Copyright (C) 2012-2021 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Google. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + (1) Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + (2) Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + (3) The name of the author may not be used to + endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. */ + +#include "config.h" + +#include +#include + +#include "backtrace.hpp" +#include "internal.hpp" + +namespace tracy +{ + +/* Create the backtrace state. This will then be passed to all the + other routines. */ + +struct backtrace_state * +backtrace_create_state (const char *filename, int threaded, + backtrace_error_callback error_callback, + void *data) +{ + struct backtrace_state init_state; + struct backtrace_state *state; + +#ifndef HAVE_SYNC_FUNCTIONS + if (threaded) + { + error_callback (data, "backtrace library does not support threads", 0); + return NULL; + } +#endif + + memset (&init_state, 0, sizeof init_state); + init_state.filename = filename; + init_state.threaded = threaded; + + state = ((struct backtrace_state *) + backtrace_alloc (&init_state, sizeof *state, error_callback, data)); + if (state == NULL) + return NULL; + *state = init_state; + + return state; +} + +} diff --git a/Dependencies/tracy/premake5.lua b/Dependencies/tracy/premake5.lua index 34f82193f..6ae48eb37 100644 --- a/Dependencies/tracy/premake5.lua +++ b/Dependencies/tracy/premake5.lua @@ -13,6 +13,11 @@ project "tracy" "**.cpp", "**.lua" } + + -- Not needed on Windows + filter { "system:windows" } + removefiles { "libbacktrace/**" } + filter {} filter { "configurations:Debug" } defines { "DEBUG" } diff --git a/OpenInVisualStudio.bat b/OpenInVisualStudio.bat deleted file mode 100644 index bdbb9356b..000000000 --- a/OpenInVisualStudio.bat +++ /dev/null @@ -1,15 +0,0 @@ -@echo off - -REM Call the GenerateProjects script -call "%~dp0\Scripts\GenerateProjects.bat" - -REM Check if the project generation was successful -if %errorlevel% neq 0 ( - echo Project generation failed. Exiting. - exit /b %errorlevel% -) - -REM Call the OpenSolution script -call "%~dp0\Scripts\MSVC\OpenSolution.bat" - -exit /b 0 diff --git a/README.md b/README.md index b10891151..2089698c8 100644 --- a/README.md +++ b/README.md @@ -51,18 +51,49 @@ Overload pillars are: Check out our [issues](https://github.com/Overload-Technologies/Overload/issues) and [pull requests](https://github.com/Overload-Technologies/Overload/pulls) to learn more about what's coming next! -# Quick Start (TL;DR) -*Assuming you are on Windows, have Visual Studio 2022 installed, and have about 5 minutes to spare!* -1. Clone Overload -2. Inside of the repository folder, run `OpenInVisualStudio.bat` -3. Build the project, voilà! +# Documentation +Check-out Overload's [documentation](https://github.com/Overload-Technologies/Overload/wiki) to find **sample projects**, **tutorials** & the **scripting API**! -- **⭐ Bonus:** get one of Overload's [sample projects](https://github.com/Overload-Technologies/Overload/wiki/Sample-Projects)! -- **✨ Extra Bonus:** check-out the [documentation](https://github.com/Overload-Technologies/Overload/wiki). +# Getting Started -More in-depth guide on getting started available [here](#getting-started). +Before running Overload, we highly recommend [downloading one of Overload's sample projects](https://github.com/Overload-Technologies/Overload/wiki/Sample-Projects)! +## Pre-Built Binaries In a rush? [Get the latest release](https://github.com/Overload-Technologies/Overload/releases)! +> [!warning] +> Pre-built binaries are only available for Windows at the moment. + +## Building From Sources +### Windows (MSVC) +```powershell +git clone https://github.com/Overload-Technologies/Overload +cd Overload +.\gen_proj_win32.bat # generate project files for Visual Studio 2022 + +# (Optional) open the solution in Visual Studio +.\Overload.sln +``` + +### Linux (Clang) +```bash +git clone https://github.com/Overload-Technologies/Overload +cd Overload +./gen_proj_linux.sh # generate Makefiles + +# (Optional) build the project +make +``` + +### Other Platforms & IDEs +`gen_proj` scripts can be invoked with an argument to specify the the action to perform. +```bash +# Generating Makefile on Windows +.\gen_proj_win32.bat gmake + +# Generating CodeLite project on Linux +./gen_proj_linux.sh codelite +``` +*Please refer to [Premake5's documentation](https://premake.github.io/docs/Using-Premake) to find supported IDEs.* # Architecture Overload is divided into 11 modules: 9 libraries (SDK), and 2 executables (Applications). @@ -99,51 +130,6 @@ Overload depends on a few third-party libraries: - [ImGui](https://github.com/ocornut/imgui) (GUI) - [Premake5](https://github.com/premake/premake-core) (Project generation) -# Getting started -## Running Overload from a Release Build -Get started with Overload in no time by downloading one of our [release builds](https://github.com/Overload-Technologies/Overload/releases). While this is the fastest way to get started, you might miss out on some cool features we're cooking up! - -After downloading the archive, unzip it and run the `Overload.exe` executable file. - -## Building Overload from Sources - -### Quick Start (For Visual Studio 2022) -To start working with Overload quickly, clone the repository and run the `OpenInVisualStudio.bat` script. Project files will be automatically generated, and Visual Studio will open with the generated solution (`Overload/Sources/Overload.sln`). - -```powershell -# These 2 lines will clone Overload, generate project files, and open the Visual Studio solution. -git clone https://github.com/Overload-Technologies/Overload -.\Overload\OpenInVisualStudio.bat -``` - -### Generating Project Files (For Any IDE) -*Note: This step is performed automatically when using `OpenInVisualStudio.bat`* - -Overload uses Premake5 to generate project files. To generate these files, execute the `GenerateProjects.bat` located in the `Scripts/` folder. - -By default, `GenerateProjects.bat` will generate project files for Visual Studio 2022. - -If you'd like to use another IDE, you'll need to run `GenerateProjects.bat` from the command line: - -```powershell -.\Scripts\GenerateProjects.bat -``` - -*Please refer to [Premake5's documentation](https://premake.github.io/docs/Using-Premake) to find supported IDEs.* - -> ⚠️ Some Premake5-supported IDEs might still not work with Overload. - -### Building From the Command Line (MSVC Only) -*Note: Before building, make sure that you generated the Visual Studio solution.* - -If you'd like to build Overload directly from the command line (without opening Visual Studio), you can use the `BuildAll.bat` script located in `Scripts/MSVC/`. By default, `BuildAll.bat` will build the project in `Debug` mode, but you can choose the configuration you want by providing an argument: -```powershell -.\Scripts\MSVC\BuildAll.bat Release -``` - -## Tutorials & Scripting API -Learn how to create your own games using Overload by visiting our [wiki](https://github.com/Overload-Technologies/Overload/wiki). - # Contributing Overload is open to contributions of all kinds. Feel free to open issues (feature requests or bug reports) or submit pull requests. @@ -153,9 +139,9 @@ If you'd like to contribute, please refer to our [contribution guildelines](http | | | |-|-| | **RAM** | 1GB | -| **OS** | Windows 7 | +| **OS** | Windows 7 & Linux | | **GPU** | Graphics card supporting OpenGL 4.5 | -| **CPU** | x64 | +| **CPU** | x86_64 | # Screenshots ![editor](https://github.com/user-attachments/assets/b1ab6300-774a-4733-a810-4cece269aef2) diff --git a/Resources/Engine/Shaders/Common/Utils.ovfxh b/Resources/Engine/Shaders/Common/Utils.ovfxh index 82ffc679e..6e6626314 100644 --- a/Resources/Engine/Shaders/Common/Utils.ovfxh +++ b/Resources/Engine/Shaders/Common/Utils.ovfxh @@ -1,10 +1,15 @@ -vec3 UnPack(float target) +vec3 UnPack(float packedFloat) { - return vec3 ( - float((uint(target) >> 24) & 0xff) * 0.003921568627451, - float((uint(target) >> 16) & 0xff) * 0.003921568627451, - float((uint(target) >> 8) & 0xff) * 0.003921568627451 - ); + // Reinterpret the float bits as a uint + uint value = floatBitsToUint(packedFloat); + + // Extract bytes + uint c0 = (value >> 24) & 0xFFu; + uint c1 = (value >> 16) & 0xFFu; + uint c2 = (value >> 8) & 0xFFu; + + // Convert back to float in [0,1] + return vec3(c0, c1, c2) / 255.0; } vec2 TileAndOffsetTexCoords(vec2 texCoords, vec2 tiling, vec2 offset) diff --git a/Resources/Engine/Shaders/Standard.ovfx b/Resources/Engine/Shaders/Standard.ovfx index 7de07a3a6..5092a0771 100644 --- a/Resources/Engine/Shaders/Standard.ovfx +++ b/Resources/Engine/Shaders/Standard.ovfx @@ -211,8 +211,15 @@ void main() // Simple built-in tonemapping (Reinhard) and gamma correction for elements // not affected by post-processing (e.g. debug, UI, etc.), but still aiming // to approximate the final PBR look. - pbr = mix(pbr, pbr / (pbr + vec3(1.0)), u_BuiltInToneMapping); - pbr = mix(pbr, pow(pbr, vec3(1.0 / 2.2)), u_BuiltInGammaCorrection); + if (u_BuiltInToneMapping) + { + pbr = pbr / (pbr + vec3(1.0)); + } + + if (u_BuiltInGammaCorrection) + { + pbr = pow(pbr, vec3(1.0 / 2.2)); + } const vec3 emissive = texture(u_EmissiveMap, texCoords).rgb * u_EmissiveColor * u_EmissiveIntensity; pbr += emissive; diff --git a/Scripts/GenerateProjects.bat b/Scripts/GenerateProjects.bat deleted file mode 100644 index e2209fb64..000000000 --- a/Scripts/GenerateProjects.bat +++ /dev/null @@ -1,9 +0,0 @@ -@echo off -SET version=%~1% -if "%~1"=="" SET version="vs2022" - -SET premake_path="%~dp0\..\Dependencies\premake5\bin\premake5.exe" - -pushd "%~dp0\..\Sources\Overload" -call %premake_path% %version% -popd diff --git a/Scripts/Linux/BuildAll.sh b/Scripts/Linux/BuildAll.sh new file mode 100755 index 000000000..3e29f6ccf --- /dev/null +++ b/Scripts/Linux/BuildAll.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +# Get the configuration parameter (default to debug) +CONFIGURATION="${1:-debug}" + +# Convert to lowercase for make +CONFIG_LOWER=$(echo "$CONFIGURATION" | tr '[:upper:]' '[:lower:]') + +# Generate the projects +pushd "$(dirname "$0")/.." > /dev/null +./Linux/GenerateProjects.sh gmake +popd > /dev/null + +# Build the solution +echo "Building Overload in $CONFIGURATION mode..." + +pushd "$(dirname "$0")/../.." > /dev/null +make config=${CONFIG_LOWER}_x64 -j$(nproc) +BUILD_RESULT=$? +popd > /dev/null + +if [ $BUILD_RESULT -ne 0 ]; then + echo "Build failed." + exit $BUILD_RESULT +fi + +echo "Build completed successfully." diff --git a/Scripts/Linux/GenerateProjects.sh b/Scripts/Linux/GenerateProjects.sh new file mode 100755 index 000000000..33ca65d49 --- /dev/null +++ b/Scripts/Linux/GenerateProjects.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +# Get the action parameter (default to gmake) +ACTION="${1:-gmake}" + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PREMAKE_PATH="$SCRIPT_DIR/../../Dependencies/premake5/bin/premake5" + +pushd "$SCRIPT_DIR/../.." > /dev/null +"$PREMAKE_PATH" "$ACTION" +popd > /dev/null diff --git a/Scripts/Linux/MakeReleaseBuild.sh b/Scripts/Linux/MakeReleaseBuild.sh new file mode 100755 index 000000000..055e23566 --- /dev/null +++ b/Scripts/Linux/MakeReleaseBuild.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +SCRIPT_DIR="$(dirname "$0")" + +# Build Debug +"$SCRIPT_DIR/BuildAll.sh" debug +if [ $? -ne 0 ]; then + echo "Debug build failed. Exiting." + exit $? +fi + +# Build Release +"$SCRIPT_DIR/BuildAll.sh" release +if [ $? -ne 0 ]; then + echo "Release build failed. Exiting." + exit $? +fi + +# Read version from VERSION.txt +VERSION=$(cat "$SCRIPT_DIR/../../VERSION.txt") +PLATFORM="linux_x64" + +# Navigate to the build folder +pushd "$SCRIPT_DIR/../../Build/" > /dev/null + +# Delete any existing folder with the release name +if [ -d "Overload-$VERSION-$PLATFORM" ]; then + rm -rf "Overload-$VERSION-$PLATFORM" +fi + +# Create Releases folder if it doesn't exist +mkdir -p ../Releases + +# Copy the Release folder to a new folder +cp -r Release "../Releases/Overload-$VERSION-$PLATFORM" + +# Create the archive, delete any existing one first +if [ -f "../Releases/Overload-$VERSION-$PLATFORM.tar.gz" ]; then + rm "../Releases/Overload-$VERSION-$PLATFORM.tar.gz" +fi + +pushd ../Releases > /dev/null +tar -czf "Overload-$VERSION-$PLATFORM.tar.gz" "Overload-$VERSION-$PLATFORM" +echo "Archive created: Releases/Overload-$VERSION-$PLATFORM.tar.gz" +popd > /dev/null + +# Delete temporary build +if [ -d "../Releases/Overload-$VERSION-$PLATFORM" ]; then + rm -rf "../Releases/Overload-$VERSION-$PLATFORM" + echo "Temporary build deleted." +fi + +popd > /dev/null + +# Open the output folder in the file manager (if available) +if command -v xdg-open &> /dev/null; then + xdg-open "$SCRIPT_DIR/../../Releases" +fi diff --git a/Scripts/MSVC/OpenSolution.bat b/Scripts/MSVC/OpenSolution.bat deleted file mode 100644 index 5221333d7..000000000 --- a/Scripts/MSVC/OpenSolution.bat +++ /dev/null @@ -1,6 +0,0 @@ -@echo off - -pushd "%~dp0..\..\Sources\Overload\" -start Overload.sln - -exit /b 0 diff --git a/Scripts/RunEditor.bat b/Scripts/RunEditor.bat deleted file mode 100644 index 770737f13..000000000 --- a/Scripts/RunEditor.bat +++ /dev/null @@ -1,21 +0,0 @@ -@echo off -setlocal enabledelayedexpansion - -:: Get the configuration parameter -set "CONFIGURATION=%~1" - -:: Build the solution -if "%CONFIGURATION%"=="" ( - echo Launching Overload Editor in Debug mode... - start "%~dp0\..\Build\Debug\OvEditor.exe" -) else ( - echo Launching Overload Editor in %CONFIGURATION% mode... - start "%~dp0\..\Build\%CONFIGURATION%\OvEditor.exe" -) - -if %errorlevel% neq 0 ( - echo Launching the editor failed. - exit /b %errorlevel% -) - -echo Editor launched successfully. diff --git a/Scripts/MSVC/BuildAll.bat b/Scripts/Windows/BuildAll.bat similarity index 96% rename from Scripts/MSVC/BuildAll.bat rename to Scripts/Windows/BuildAll.bat index 5d9291b39..3d5cbd5f7 100644 --- a/Scripts/MSVC/BuildAll.bat +++ b/Scripts/Windows/BuildAll.bat @@ -59,7 +59,10 @@ echo msbuild.exe found at: "!MSBUILD_PATH!" echo. :: Build the solution -pushd "%~dp0..\..\Sources\Overload\" +echo Building Overload in !CONFIGURATION! mode... +echo. + +pushd "%~dp0..\..\" if "%CONFIGURATION%"=="" ( echo Building with default configuration configuration... "!MSBUILD_PATH!" Overload.sln -m -verbosity:minimal diff --git a/Scripts/Windows/GenerateProjects.bat b/Scripts/Windows/GenerateProjects.bat new file mode 100644 index 000000000..3da060b9d --- /dev/null +++ b/Scripts/Windows/GenerateProjects.bat @@ -0,0 +1,9 @@ +@echo off +SET version=%~1% +if "%~1"=="" SET version="vs2022" + +SET premake_path="%~dp0\..\..\Dependencies\premake5\bin\premake5.exe" + +pushd "%~dp0\..\.." +call %premake_path% %version% +popd diff --git a/Scripts/MSVC/MakeReleaseBuild.bat b/Scripts/Windows/MakeReleaseBuild.bat similarity index 100% rename from Scripts/MSVC/MakeReleaseBuild.bat rename to Scripts/Windows/MakeReleaseBuild.bat diff --git a/Sources/Overload/OvAudio/include/OvAudio/Core/AudioEngine.h b/Sources/OvAudio/include/OvAudio/Core/AudioEngine.h similarity index 100% rename from Sources/Overload/OvAudio/include/OvAudio/Core/AudioEngine.h rename to Sources/OvAudio/include/OvAudio/Core/AudioEngine.h diff --git a/Sources/Overload/OvAudio/include/OvAudio/Data/SoundHandle.h b/Sources/OvAudio/include/OvAudio/Data/SoundHandle.h similarity index 100% rename from Sources/Overload/OvAudio/include/OvAudio/Data/SoundHandle.h rename to Sources/OvAudio/include/OvAudio/Data/SoundHandle.h diff --git a/Sources/Overload/OvAudio/include/OvAudio/Data/SoundInstance.h b/Sources/OvAudio/include/OvAudio/Data/SoundInstance.h similarity index 100% rename from Sources/Overload/OvAudio/include/OvAudio/Data/SoundInstance.h rename to Sources/OvAudio/include/OvAudio/Data/SoundInstance.h diff --git a/Sources/Overload/OvAudio/include/OvAudio/Entities/AudioListener.h b/Sources/OvAudio/include/OvAudio/Entities/AudioListener.h similarity index 100% rename from Sources/Overload/OvAudio/include/OvAudio/Entities/AudioListener.h rename to Sources/OvAudio/include/OvAudio/Entities/AudioListener.h diff --git a/Sources/Overload/OvAudio/include/OvAudio/Entities/AudioSource.h b/Sources/OvAudio/include/OvAudio/Entities/AudioSource.h similarity index 100% rename from Sources/Overload/OvAudio/include/OvAudio/Entities/AudioSource.h rename to Sources/OvAudio/include/OvAudio/Entities/AudioSource.h diff --git a/Sources/Overload/OvAudio/include/OvAudio/Resources/Loaders/SoundLoader.h b/Sources/OvAudio/include/OvAudio/Resources/Loaders/SoundLoader.h similarity index 100% rename from Sources/Overload/OvAudio/include/OvAudio/Resources/Loaders/SoundLoader.h rename to Sources/OvAudio/include/OvAudio/Resources/Loaders/SoundLoader.h diff --git a/Sources/Overload/OvAudio/include/OvAudio/Resources/Sound.h b/Sources/OvAudio/include/OvAudio/Resources/Sound.h similarity index 100% rename from Sources/Overload/OvAudio/include/OvAudio/Resources/Sound.h rename to Sources/OvAudio/include/OvAudio/Resources/Sound.h diff --git a/Sources/Overload/OvAudio/include/OvAudio/Settings/EAttenuationModel.h b/Sources/OvAudio/include/OvAudio/Settings/EAttenuationModel.h similarity index 100% rename from Sources/Overload/OvAudio/include/OvAudio/Settings/EAttenuationModel.h rename to Sources/OvAudio/include/OvAudio/Settings/EAttenuationModel.h diff --git a/Sources/Overload/OvAudio/premake5.lua b/Sources/OvAudio/premake5.lua similarity index 79% rename from Sources/Overload/OvAudio/premake5.lua rename to Sources/OvAudio/premake5.lua index dfe641b28..6fdc70aa1 100644 --- a/Sources/Overload/OvAudio/premake5.lua +++ b/Sources/OvAudio/premake5.lua @@ -18,9 +18,9 @@ project "OvAudio" dependdir .. "soloud/include", -- Overload SDK - "%{wks.location}/OvDebug/include", - "%{wks.location}/OvMaths/include", - "%{wks.location}/OvTools/include", + "%{wks.location}/Sources/OvDebug/include", + "%{wks.location}/Sources/OvMaths/include", + "%{wks.location}/Sources/OvTools/include", -- Current Project "include" diff --git a/Sources/Overload/OvAudio/src/OvAudio/Core/AudioEngine.cpp b/Sources/OvAudio/src/OvAudio/Core/AudioEngine.cpp similarity index 100% rename from Sources/Overload/OvAudio/src/OvAudio/Core/AudioEngine.cpp rename to Sources/OvAudio/src/OvAudio/Core/AudioEngine.cpp diff --git a/Sources/Overload/OvAudio/src/OvAudio/Data/SoundInstance.cpp b/Sources/OvAudio/src/OvAudio/Data/SoundInstance.cpp similarity index 100% rename from Sources/Overload/OvAudio/src/OvAudio/Data/SoundInstance.cpp rename to Sources/OvAudio/src/OvAudio/Data/SoundInstance.cpp diff --git a/Sources/Overload/OvAudio/src/OvAudio/Entities/AudioListener.cpp b/Sources/OvAudio/src/OvAudio/Entities/AudioListener.cpp similarity index 100% rename from Sources/Overload/OvAudio/src/OvAudio/Entities/AudioListener.cpp rename to Sources/OvAudio/src/OvAudio/Entities/AudioListener.cpp diff --git a/Sources/Overload/OvAudio/src/OvAudio/Entities/AudioSource.cpp b/Sources/OvAudio/src/OvAudio/Entities/AudioSource.cpp similarity index 100% rename from Sources/Overload/OvAudio/src/OvAudio/Entities/AudioSource.cpp rename to Sources/OvAudio/src/OvAudio/Entities/AudioSource.cpp diff --git a/Sources/Overload/OvAudio/src/OvAudio/Resources/Loaders/SoundLoader.cpp b/Sources/OvAudio/src/OvAudio/Resources/Loaders/SoundLoader.cpp similarity index 100% rename from Sources/Overload/OvAudio/src/OvAudio/Resources/Loaders/SoundLoader.cpp rename to Sources/OvAudio/src/OvAudio/Resources/Loaders/SoundLoader.cpp diff --git a/Sources/Overload/OvAudio/src/OvAudio/Resources/Sound.cpp b/Sources/OvAudio/src/OvAudio/Resources/Sound.cpp similarity index 100% rename from Sources/Overload/OvAudio/src/OvAudio/Resources/Sound.cpp rename to Sources/OvAudio/src/OvAudio/Resources/Sound.cpp diff --git a/Sources/Overload/OvCore/include/OvCore/API/IInspectorItem.h b/Sources/OvCore/include/OvCore/API/IInspectorItem.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/API/IInspectorItem.h rename to Sources/OvCore/include/OvCore/API/IInspectorItem.h diff --git a/Sources/Overload/OvCore/include/OvCore/API/ISerializable.h b/Sources/OvCore/include/OvCore/API/ISerializable.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/API/ISerializable.h rename to Sources/OvCore/include/OvCore/API/ISerializable.h diff --git a/Sources/Overload/OvCore/include/OvCore/ECS/Actor.h b/Sources/OvCore/include/OvCore/ECS/Actor.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/ECS/Actor.h rename to Sources/OvCore/include/OvCore/ECS/Actor.h diff --git a/Sources/Overload/OvCore/include/OvCore/ECS/Actor.inl b/Sources/OvCore/include/OvCore/ECS/Actor.inl similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/ECS/Actor.inl rename to Sources/OvCore/include/OvCore/ECS/Actor.inl diff --git a/Sources/Overload/OvCore/include/OvCore/ECS/Components/AComponent.h b/Sources/OvCore/include/OvCore/ECS/Components/AComponent.h similarity index 93% rename from Sources/Overload/OvCore/include/OvCore/ECS/Components/AComponent.h rename to Sources/OvCore/include/OvCore/ECS/Components/AComponent.h index 3b2fd1dc1..8618d9a44 100644 --- a/Sources/Overload/OvCore/include/OvCore/ECS/Components/AComponent.h +++ b/Sources/OvCore/include/OvCore/ECS/Components/AComponent.h @@ -118,7 +118,18 @@ namespace OvCore::ECS::Components */ virtual std::string GetName() = 0; + /** + * Returns the type name of the component + */ + virtual std::string GetTypeName() = 0; + public: ECS::Actor& owner; }; + + template + struct ComponentTraits + { + static constexpr std::string_view Name = "Unknown Component Type"; + }; } \ No newline at end of file diff --git a/Sources/Overload/OvCore/include/OvCore/ECS/Components/Behaviour.h b/Sources/OvCore/include/OvCore/ECS/Components/Behaviour.h similarity index 93% rename from Sources/Overload/OvCore/include/OvCore/ECS/Components/Behaviour.h rename to Sources/OvCore/include/OvCore/ECS/Components/Behaviour.h index 7ded3953f..28277a1a0 100644 --- a/Sources/Overload/OvCore/include/OvCore/ECS/Components/Behaviour.h +++ b/Sources/OvCore/include/OvCore/ECS/Components/Behaviour.h @@ -36,6 +36,11 @@ namespace OvCore::ECS::Components * Returns the name of the component */ virtual std::string GetName() override; + + /** + * Returns the type name of the component + */ + virtual std::string GetTypeName() override; /** * Sets the script associated with this behaviour @@ -160,4 +165,10 @@ namespace OvCore::ECS::Components private: std::unique_ptr m_script; }; + + template<> + struct ComponentTraits + { + static constexpr std::string_view Name = "class OvCore::ECS::Components::Behaviour"; + }; } diff --git a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CAmbientBoxLight.h b/Sources/OvCore/include/OvCore/ECS/Components/CAmbientBoxLight.h similarity index 80% rename from Sources/Overload/OvCore/include/OvCore/ECS/Components/CAmbientBoxLight.h rename to Sources/OvCore/include/OvCore/ECS/Components/CAmbientBoxLight.h index 4e5717873..7badaa1aa 100644 --- a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CAmbientBoxLight.h +++ b/Sources/OvCore/include/OvCore/ECS/Components/CAmbientBoxLight.h @@ -29,6 +29,11 @@ namespace OvCore::ECS::Components */ std::string GetName() override; + /** + * Returns the type name of the component + */ + virtual std::string GetTypeName() override; + /** * Returns the size of the box */ @@ -60,4 +65,10 @@ namespace OvCore::ECS::Components */ virtual void OnInspector(OvUI::Internal::WidgetContainer& p_root) override; }; + + template<> + struct ComponentTraits + { + static constexpr std::string_view Name = "class OvCore::ECS::Components::CAmbientBoxLight"; + }; } \ No newline at end of file diff --git a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CAmbientSphereLight.h b/Sources/OvCore/include/OvCore/ECS/Components/CAmbientSphereLight.h similarity index 80% rename from Sources/Overload/OvCore/include/OvCore/ECS/Components/CAmbientSphereLight.h rename to Sources/OvCore/include/OvCore/ECS/Components/CAmbientSphereLight.h index 6b9efe3c6..406bebad1 100644 --- a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CAmbientSphereLight.h +++ b/Sources/OvCore/include/OvCore/ECS/Components/CAmbientSphereLight.h @@ -29,6 +29,11 @@ namespace OvCore::ECS::Components */ std::string GetName() override; + /** + * Returns the type name of the component + */ + virtual std::string GetTypeName() override; + /** * Returns the radius of the sphere */ @@ -60,4 +65,10 @@ namespace OvCore::ECS::Components */ virtual void OnInspector(OvUI::Internal::WidgetContainer& p_root) override; }; + + template<> + struct ComponentTraits + { + static constexpr std::string_view Name = "class OvCore::ECS::Components::CAmbientSphereLight"; + }; } \ No newline at end of file diff --git a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CAudioListener.h b/Sources/OvCore/include/OvCore/ECS/Components/CAudioListener.h similarity index 82% rename from Sources/Overload/OvCore/include/OvCore/ECS/Components/CAudioListener.h rename to Sources/OvCore/include/OvCore/ECS/Components/CAudioListener.h index dc6a93215..f414a52a4 100644 --- a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CAudioListener.h +++ b/Sources/OvCore/include/OvCore/ECS/Components/CAudioListener.h @@ -34,6 +34,11 @@ namespace OvCore::ECS::Components */ std::string GetName() override; + /** + * Returns the type name of the component + */ + virtual std::string GetTypeName() override; + /** * Serialize the component * @param p_doc @@ -61,4 +66,10 @@ namespace OvCore::ECS::Components private: OvAudio::Entities::AudioListener m_audioListener; }; + + template<> + struct ComponentTraits + { + static constexpr std::string_view Name = "class OvCore::ECS::Components::CAudioListener"; + }; } \ No newline at end of file diff --git a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CAudioSource.h b/Sources/OvCore/include/OvCore/ECS/Components/CAudioSource.h similarity index 92% rename from Sources/Overload/OvCore/include/OvCore/ECS/Components/CAudioSource.h rename to Sources/OvCore/include/OvCore/ECS/Components/CAudioSource.h index 206274194..1159e0365 100644 --- a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CAudioSource.h +++ b/Sources/OvCore/include/OvCore/ECS/Components/CAudioSource.h @@ -32,6 +32,11 @@ namespace OvCore::ECS::Components */ std::string GetName() override; + /** + * Returns the type name of the component + */ + virtual std::string GetTypeName() override; + /** * Defines the sound to play on the audio source * @param p_sound @@ -173,4 +178,10 @@ namespace OvCore::ECS::Components OvAudio::Entities::AudioSource m_audioSource; bool m_autoPlay = false; }; + + template<> + struct ComponentTraits + { + static constexpr std::string_view Name = "class OvCore::ECS::Components::CAudioSource"; + }; } \ No newline at end of file diff --git a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CCamera.h b/Sources/OvCore/include/OvCore/ECS/Components/CCamera.h similarity index 92% rename from Sources/Overload/OvCore/include/OvCore/ECS/Components/CCamera.h rename to Sources/OvCore/include/OvCore/ECS/Components/CCamera.h index f300cf81c..53e36e289 100644 --- a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CCamera.h +++ b/Sources/OvCore/include/OvCore/ECS/Components/CCamera.h @@ -35,6 +35,11 @@ namespace OvCore::ECS::Components */ std::string GetName() override; + /** + * Returns the type name of the component + */ + virtual std::string GetTypeName() override; + /** * Sets the fov of the camera to the given value * @param p_value @@ -151,4 +156,10 @@ namespace OvCore::ECS::Components private: OvRendering::Entities::Camera m_camera; }; + + template<> + struct ComponentTraits + { + static constexpr std::string_view Name = "class OvCore::ECS::Components::CCamera"; + }; } \ No newline at end of file diff --git a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CDirectionalLight.h b/Sources/OvCore/include/OvCore/ECS/Components/CDirectionalLight.h similarity index 87% rename from Sources/Overload/OvCore/include/OvCore/ECS/Components/CDirectionalLight.h rename to Sources/OvCore/include/OvCore/ECS/Components/CDirectionalLight.h index f7860ca9a..c1cfb11e2 100644 --- a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CDirectionalLight.h +++ b/Sources/OvCore/include/OvCore/ECS/Components/CDirectionalLight.h @@ -29,6 +29,11 @@ namespace OvCore::ECS::Components */ std::string GetName() override; + /** + * Returns the type name of the component + */ + virtual std::string GetTypeName() override; + /** * Set if the light should cast shadows * @param p_enabled @@ -94,4 +99,10 @@ namespace OvCore::ECS::Components */ virtual void OnInspector(OvUI::Internal::WidgetContainer& p_root) override; }; + + template<> + struct ComponentTraits + { + static constexpr std::string_view Name = "class OvCore::ECS::Components::CDirectionalLight"; + }; } \ No newline at end of file diff --git a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CLight.h b/Sources/OvCore/include/OvCore/ECS/Components/CLight.h similarity index 89% rename from Sources/Overload/OvCore/include/OvCore/ECS/Components/CLight.h rename to Sources/OvCore/include/OvCore/ECS/Components/CLight.h index 45b866604..004906fe7 100644 --- a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CLight.h +++ b/Sources/OvCore/include/OvCore/ECS/Components/CLight.h @@ -76,4 +76,10 @@ namespace OvCore::ECS::Components protected: OvRendering::Entities::Light m_data; }; + + template<> + struct ComponentTraits + { + static constexpr std::string_view Name = "class OvCore::ECS::Components::CLight"; + }; } \ No newline at end of file diff --git a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CMaterialRenderer.h b/Sources/OvCore/include/OvCore/ECS/Components/CMaterialRenderer.h similarity index 92% rename from Sources/Overload/OvCore/include/OvCore/ECS/Components/CMaterialRenderer.h rename to Sources/OvCore/include/OvCore/ECS/Components/CMaterialRenderer.h index 6dbf8c559..ac18d92c2 100644 --- a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CMaterialRenderer.h +++ b/Sources/OvCore/include/OvCore/ECS/Components/CMaterialRenderer.h @@ -40,6 +40,11 @@ namespace OvCore::ECS::Components */ std::string GetName() override; + /** + * Returns the type name of the component + */ + virtual std::string GetTypeName() override; + /** * Fill the material renderer with the given material * @param p_material @@ -150,4 +155,10 @@ namespace OvCore::ECS::Components OvMaths::FMatrix4 m_userMatrix; Rendering::EVisibilityFlags m_visibilityFlags = Rendering::EVisibilityFlags::ALL; }; + + template<> + struct ComponentTraits + { + static constexpr std::string_view Name = "class OvCore::ECS::Components::CMaterialRenderer"; + }; } \ No newline at end of file diff --git a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CModelRenderer.h b/Sources/OvCore/include/OvCore/ECS/Components/CModelRenderer.h similarity index 89% rename from Sources/Overload/OvCore/include/OvCore/ECS/Components/CModelRenderer.h rename to Sources/OvCore/include/OvCore/ECS/Components/CModelRenderer.h index 6b5fe8462..66af257f0 100644 --- a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CModelRenderer.h +++ b/Sources/OvCore/include/OvCore/ECS/Components/CModelRenderer.h @@ -43,6 +43,11 @@ namespace OvCore::ECS::Components */ std::string GetName() override; + /** + * Returns the type name of the component + */ + virtual std::string GetTypeName() override; + /** * Defines the model to use * @param p_model @@ -102,4 +107,10 @@ namespace OvCore::ECS::Components OvRendering::Geometry::BoundingSphere m_customBoundingSphere = { {}, 1.0f }; EFrustumBehaviour m_frustumBehaviour = EFrustumBehaviour::MESH_BOUNDS; }; + + template<> + struct ComponentTraits + { + static constexpr std::string_view Name = "class OvCore::ECS::Components::CModelRenderer"; + }; } \ No newline at end of file diff --git a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CPhysicalBox.h b/Sources/OvCore/include/OvCore/ECS/Components/CPhysicalBox.h similarity index 82% rename from Sources/Overload/OvCore/include/OvCore/ECS/Components/CPhysicalBox.h rename to Sources/OvCore/include/OvCore/ECS/Components/CPhysicalBox.h index 191ed5895..7990834e4 100644 --- a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CPhysicalBox.h +++ b/Sources/OvCore/include/OvCore/ECS/Components/CPhysicalBox.h @@ -31,6 +31,11 @@ namespace OvCore::ECS::Components */ std::string GetName() override; + /** + * Returns the type name of the component + */ + virtual std::string GetTypeName() override; + /** * Defines the size of the box shape * @param p_size @@ -62,4 +67,10 @@ namespace OvCore::ECS::Components */ virtual void OnInspector(OvUI::Internal::WidgetContainer& p_root) override; }; + + template<> + struct ComponentTraits + { + static constexpr std::string_view Name = "class OvCore::ECS::Components::CPhysicalBox"; + }; } \ No newline at end of file diff --git a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CPhysicalCapsule.h b/Sources/OvCore/include/OvCore/ECS/Components/CPhysicalCapsule.h similarity index 83% rename from Sources/Overload/OvCore/include/OvCore/ECS/Components/CPhysicalCapsule.h rename to Sources/OvCore/include/OvCore/ECS/Components/CPhysicalCapsule.h index 0019cd76b..b96257182 100644 --- a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CPhysicalCapsule.h +++ b/Sources/OvCore/include/OvCore/ECS/Components/CPhysicalCapsule.h @@ -31,6 +31,11 @@ namespace OvCore::ECS::Components */ std::string GetName() override; + /** + * Returns the type name of the component + */ + virtual std::string GetTypeName() override; + /** * Defines the radius of the capsule shape * @param p_radius @@ -73,4 +78,10 @@ namespace OvCore::ECS::Components */ virtual void OnInspector(OvUI::Internal::WidgetContainer& p_root) override; }; + + template<> + struct ComponentTraits + { + static constexpr std::string_view Name = "class OvCore::ECS::Components::CPhysicalCapsule"; + }; } \ No newline at end of file diff --git a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CPhysicalObject.h b/Sources/OvCore/include/OvCore/ECS/Components/CPhysicalObject.h similarity index 96% rename from Sources/Overload/OvCore/include/OvCore/ECS/Components/CPhysicalObject.h rename to Sources/OvCore/include/OvCore/ECS/Components/CPhysicalObject.h index 119dd09f7..1b38afa4f 100644 --- a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CPhysicalObject.h +++ b/Sources/OvCore/include/OvCore/ECS/Components/CPhysicalObject.h @@ -205,4 +205,10 @@ namespace OvCore::ECS::Components protected: std::unique_ptr m_physicalObject; }; + + template<> + struct ComponentTraits + { + static constexpr std::string_view Name = "class OvCore::ECS::Components::CPhysicalObject"; + }; } \ No newline at end of file diff --git a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CPhysicalSphere.h b/Sources/OvCore/include/OvCore/ECS/Components/CPhysicalSphere.h similarity index 81% rename from Sources/Overload/OvCore/include/OvCore/ECS/Components/CPhysicalSphere.h rename to Sources/OvCore/include/OvCore/ECS/Components/CPhysicalSphere.h index d258c4ac8..ff4f35b90 100644 --- a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CPhysicalSphere.h +++ b/Sources/OvCore/include/OvCore/ECS/Components/CPhysicalSphere.h @@ -31,6 +31,11 @@ namespace OvCore::ECS::Components */ std::string GetName() override; + /** + * Returns the type name of the component + */ + virtual std::string GetTypeName() override; + /** * Defines the radius of the sphere shape * @param p_radius @@ -62,4 +67,10 @@ namespace OvCore::ECS::Components */ virtual void OnInspector(OvUI::Internal::WidgetContainer& p_root) override; }; + + template<> + struct ComponentTraits + { + static constexpr std::string_view Name = "class OvCore::ECS::Components::CPhysicalSphere"; + }; } \ No newline at end of file diff --git a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CPointLight.h b/Sources/OvCore/include/OvCore/ECS/Components/CPointLight.h similarity index 85% rename from Sources/Overload/OvCore/include/OvCore/ECS/Components/CPointLight.h rename to Sources/OvCore/include/OvCore/ECS/Components/CPointLight.h index 5718791d3..ca7842997 100644 --- a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CPointLight.h +++ b/Sources/OvCore/include/OvCore/ECS/Components/CPointLight.h @@ -31,6 +31,11 @@ namespace OvCore::ECS::Components */ std::string GetName() override; + /** + * Returns the type name of the component + */ + virtual std::string GetTypeName() override; + /** * Returns the light constant */ @@ -84,4 +89,10 @@ namespace OvCore::ECS::Components */ virtual void OnInspector(OvUI::Internal::WidgetContainer& p_root) override; }; + + template<> + struct ComponentTraits + { + static constexpr std::string_view Name = "class OvCore::ECS::Components::CPointLight"; + }; } \ No newline at end of file diff --git a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CPostProcessStack.h b/Sources/OvCore/include/OvCore/ECS/Components/CPostProcessStack.h similarity index 90% rename from Sources/Overload/OvCore/include/OvCore/ECS/Components/CPostProcessStack.h rename to Sources/OvCore/include/OvCore/ECS/Components/CPostProcessStack.h index 778c11f52..ccf37b42c 100644 --- a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CPostProcessStack.h +++ b/Sources/OvCore/include/OvCore/ECS/Components/CPostProcessStack.h @@ -35,6 +35,11 @@ namespace OvCore::ECS::Components */ std::string GetName() override; + /** + * Returns the type name of the component + */ + virtual std::string GetTypeName() override; + /** * Serialize the component * @param p_doc @@ -107,4 +112,10 @@ namespace OvCore::ECS::Components private: OvCore::Rendering::PostProcess::PostProcessStack m_settings; }; + + template<> + struct ComponentTraits + { + static constexpr std::string_view Name = "class OvCore::ECS::Components::CPostProcessStack"; + }; } \ No newline at end of file diff --git a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CReflectionProbe.h b/Sources/OvCore/include/OvCore/ECS/Components/CReflectionProbe.h similarity index 95% rename from Sources/Overload/OvCore/include/OvCore/ECS/Components/CReflectionProbe.h rename to Sources/OvCore/include/OvCore/ECS/Components/CReflectionProbe.h index 63204ca38..7bbab2439 100644 --- a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CReflectionProbe.h +++ b/Sources/OvCore/include/OvCore/ECS/Components/CReflectionProbe.h @@ -60,6 +60,11 @@ namespace OvCore::ECS::Components */ std::string GetName() override; + /** + * Returns the type name of the component + */ + virtual std::string GetTypeName() override; + /** * Sets the refresh mode of the reflection probe * @param p_mode @@ -217,4 +222,10 @@ namespace OvCore::ECS::Components OvMaths::FVector3 m_influenceSize{ 10.0f, 10.0f, 10.0f }; bool m_boxProjection = false; }; + + template<> + struct ComponentTraits + { + static constexpr std::string_view Name = "class OvCore::ECS::Components::CReflectionProbe"; + }; } diff --git a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CSpotLight.h b/Sources/OvCore/include/OvCore/ECS/Components/CSpotLight.h similarity index 87% rename from Sources/Overload/OvCore/include/OvCore/ECS/Components/CSpotLight.h rename to Sources/OvCore/include/OvCore/ECS/Components/CSpotLight.h index 802124ac0..4a4480b22 100644 --- a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CSpotLight.h +++ b/Sources/OvCore/include/OvCore/ECS/Components/CSpotLight.h @@ -29,6 +29,11 @@ namespace OvCore::ECS::Components */ std::string GetName() override; + /** + * Returns the type name of the component + */ + virtual std::string GetTypeName() override; + /** * Returns the light constant */ @@ -104,4 +109,10 @@ namespace OvCore::ECS::Components */ virtual void OnInspector(OvUI::Internal::WidgetContainer& p_root) override; }; + + template<> + struct ComponentTraits + { + static constexpr std::string_view Name = "class OvCore::ECS::Components::CSpotLight"; + }; } \ No newline at end of file diff --git a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CTransform.h b/Sources/OvCore/include/OvCore/ECS/Components/CTransform.h similarity index 94% rename from Sources/Overload/OvCore/include/OvCore/ECS/Components/CTransform.h rename to Sources/OvCore/include/OvCore/ECS/Components/CTransform.h index 39156eda7..db6b3b850 100644 --- a/Sources/Overload/OvCore/include/OvCore/ECS/Components/CTransform.h +++ b/Sources/OvCore/include/OvCore/ECS/Components/CTransform.h @@ -37,6 +37,11 @@ namespace OvCore::ECS::Components */ std::string GetName() override; + /** + * Returns the type name of the component + */ + virtual std::string GetTypeName() override; + /** * Defines a parent to the transform * @param p_parent @@ -207,4 +212,10 @@ namespace OvCore::ECS::Components private: OvMaths::FTransform m_transform; }; + + template<> + struct ComponentTraits + { + static constexpr std::string_view Name = "class OvCore::ECS::Components::CTransform"; + }; } \ No newline at end of file diff --git a/Sources/Overload/OvCore/include/OvCore/ECS/PhysicsWrapper.h b/Sources/OvCore/include/OvCore/ECS/PhysicsWrapper.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/ECS/PhysicsWrapper.h rename to Sources/OvCore/include/OvCore/ECS/PhysicsWrapper.h diff --git a/Sources/Overload/OvCore/include/OvCore/Global/ServiceLocator.h b/Sources/OvCore/include/OvCore/Global/ServiceLocator.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/Global/ServiceLocator.h rename to Sources/OvCore/include/OvCore/Global/ServiceLocator.h diff --git a/Sources/Overload/OvCore/include/OvCore/Helpers/GUIDrawer.h b/Sources/OvCore/include/OvCore/Helpers/GUIDrawer.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/Helpers/GUIDrawer.h rename to Sources/OvCore/include/OvCore/Helpers/GUIDrawer.h diff --git a/Sources/Overload/OvCore/include/OvCore/Helpers/GUIDrawer.inl b/Sources/OvCore/include/OvCore/Helpers/GUIDrawer.inl similarity index 93% rename from Sources/Overload/OvCore/include/OvCore/Helpers/GUIDrawer.inl rename to Sources/OvCore/include/OvCore/Helpers/GUIDrawer.inl index ad1784173..eb428cc5b 100644 --- a/Sources/Overload/OvCore/include/OvCore/Helpers/GUIDrawer.inl +++ b/Sources/OvCore/include/OvCore/Helpers/GUIDrawer.inl @@ -40,7 +40,7 @@ namespace OvCore::Helpers CreateTitle(p_root, p_name); auto& widget = p_root.CreateWidget>(GetDataType(), p_min, p_max, p_data, p_step, "", GetFormat()); - auto& dispatcher = widget.AddPlugin>(); + auto& dispatcher = widget.template AddPlugin>(); dispatcher.RegisterReference(p_data); } @@ -51,7 +51,7 @@ namespace OvCore::Helpers CreateTitle(p_root, p_name); auto& widget = p_root.CreateWidget>(GetDataType(), p_min, p_max, static_cast(0), p_step, "", GetFormat()); - auto& dispatcher = widget.AddPlugin>(); + auto& dispatcher = widget.template AddPlugin>(); dispatcher.RegisterGatherer(p_gatherer); dispatcher.RegisterProvider(p_provider); } diff --git a/Sources/Overload/OvCore/include/OvCore/Helpers/Serializer.h b/Sources/OvCore/include/OvCore/Helpers/Serializer.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/Helpers/Serializer.h rename to Sources/OvCore/include/OvCore/Helpers/Serializer.h diff --git a/Sources/Overload/OvCore/include/OvCore/Rendering/EVisibilityFlags.h b/Sources/OvCore/include/OvCore/Rendering/EVisibilityFlags.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/Rendering/EVisibilityFlags.h rename to Sources/OvCore/include/OvCore/Rendering/EVisibilityFlags.h diff --git a/Sources/Overload/OvCore/include/OvCore/Rendering/EngineBufferRenderFeature.h b/Sources/OvCore/include/OvCore/Rendering/EngineBufferRenderFeature.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/Rendering/EngineBufferRenderFeature.h rename to Sources/OvCore/include/OvCore/Rendering/EngineBufferRenderFeature.h diff --git a/Sources/Overload/OvCore/include/OvCore/Rendering/EngineDrawableDescriptor.h b/Sources/OvCore/include/OvCore/Rendering/EngineDrawableDescriptor.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/Rendering/EngineDrawableDescriptor.h rename to Sources/OvCore/include/OvCore/Rendering/EngineDrawableDescriptor.h diff --git a/Sources/Overload/OvCore/include/OvCore/Rendering/FramebufferUtil.h b/Sources/OvCore/include/OvCore/Rendering/FramebufferUtil.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/Rendering/FramebufferUtil.h rename to Sources/OvCore/include/OvCore/Rendering/FramebufferUtil.h diff --git a/Sources/Overload/OvCore/include/OvCore/Rendering/PingPongFramebuffer.h b/Sources/OvCore/include/OvCore/Rendering/PingPongFramebuffer.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/Rendering/PingPongFramebuffer.h rename to Sources/OvCore/include/OvCore/Rendering/PingPongFramebuffer.h diff --git a/Sources/Overload/OvCore/include/OvCore/Rendering/PostProcess/AEffect.h b/Sources/OvCore/include/OvCore/Rendering/PostProcess/AEffect.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/Rendering/PostProcess/AEffect.h rename to Sources/OvCore/include/OvCore/Rendering/PostProcess/AEffect.h diff --git a/Sources/Overload/OvCore/include/OvCore/Rendering/PostProcess/AutoExposureEffect.h b/Sources/OvCore/include/OvCore/Rendering/PostProcess/AutoExposureEffect.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/Rendering/PostProcess/AutoExposureEffect.h rename to Sources/OvCore/include/OvCore/Rendering/PostProcess/AutoExposureEffect.h diff --git a/Sources/Overload/OvCore/include/OvCore/Rendering/PostProcess/BloomEffect.h b/Sources/OvCore/include/OvCore/Rendering/PostProcess/BloomEffect.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/Rendering/PostProcess/BloomEffect.h rename to Sources/OvCore/include/OvCore/Rendering/PostProcess/BloomEffect.h diff --git a/Sources/Overload/OvCore/include/OvCore/Rendering/PostProcess/FXAAEffect.h b/Sources/OvCore/include/OvCore/Rendering/PostProcess/FXAAEffect.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/Rendering/PostProcess/FXAAEffect.h rename to Sources/OvCore/include/OvCore/Rendering/PostProcess/FXAAEffect.h diff --git a/Sources/Overload/OvCore/include/OvCore/Rendering/PostProcess/PostProcessStack.h b/Sources/OvCore/include/OvCore/Rendering/PostProcess/PostProcessStack.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/Rendering/PostProcess/PostProcessStack.h rename to Sources/OvCore/include/OvCore/Rendering/PostProcess/PostProcessStack.h diff --git a/Sources/Overload/OvCore/include/OvCore/Rendering/PostProcess/PostProcessStack.inl b/Sources/OvCore/include/OvCore/Rendering/PostProcess/PostProcessStack.inl similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/Rendering/PostProcess/PostProcessStack.inl rename to Sources/OvCore/include/OvCore/Rendering/PostProcess/PostProcessStack.inl diff --git a/Sources/Overload/OvCore/include/OvCore/Rendering/PostProcess/TonemappingEffect.h b/Sources/OvCore/include/OvCore/Rendering/PostProcess/TonemappingEffect.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/Rendering/PostProcess/TonemappingEffect.h rename to Sources/OvCore/include/OvCore/Rendering/PostProcess/TonemappingEffect.h diff --git a/Sources/Overload/OvCore/include/OvCore/Rendering/PostProcessRenderPass.h b/Sources/OvCore/include/OvCore/Rendering/PostProcessRenderPass.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/Rendering/PostProcessRenderPass.h rename to Sources/OvCore/include/OvCore/Rendering/PostProcessRenderPass.h diff --git a/Sources/Overload/OvCore/include/OvCore/Rendering/ReflectionRenderFeature.h b/Sources/OvCore/include/OvCore/Rendering/ReflectionRenderFeature.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/Rendering/ReflectionRenderFeature.h rename to Sources/OvCore/include/OvCore/Rendering/ReflectionRenderFeature.h diff --git a/Sources/Overload/OvCore/include/OvCore/Rendering/ReflectionRenderPass.h b/Sources/OvCore/include/OvCore/Rendering/ReflectionRenderPass.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/Rendering/ReflectionRenderPass.h rename to Sources/OvCore/include/OvCore/Rendering/ReflectionRenderPass.h diff --git a/Sources/Overload/OvCore/include/OvCore/Rendering/SceneRenderer.h b/Sources/OvCore/include/OvCore/Rendering/SceneRenderer.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/Rendering/SceneRenderer.h rename to Sources/OvCore/include/OvCore/Rendering/SceneRenderer.h diff --git a/Sources/Overload/OvCore/include/OvCore/Rendering/ShadowRenderFeature.h b/Sources/OvCore/include/OvCore/Rendering/ShadowRenderFeature.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/Rendering/ShadowRenderFeature.h rename to Sources/OvCore/include/OvCore/Rendering/ShadowRenderFeature.h diff --git a/Sources/Overload/OvCore/include/OvCore/Rendering/ShadowRenderPass.h b/Sources/OvCore/include/OvCore/Rendering/ShadowRenderPass.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/Rendering/ShadowRenderPass.h rename to Sources/OvCore/include/OvCore/Rendering/ShadowRenderPass.h diff --git a/Sources/Overload/OvCore/include/OvCore/ResourceManagement/AResourceManager.h b/Sources/OvCore/include/OvCore/ResourceManagement/AResourceManager.h similarity index 69% rename from Sources/Overload/OvCore/include/OvCore/ResourceManagement/AResourceManager.h rename to Sources/OvCore/include/OvCore/ResourceManagement/AResourceManager.h index 5d073a8cd..c034722df 100644 --- a/Sources/Overload/OvCore/include/OvCore/ResourceManagement/AResourceManager.h +++ b/Sources/OvCore/include/OvCore/ResourceManagement/AResourceManager.h @@ -23,32 +23,32 @@ namespace OvCore::ResourceManagement * Handle the creation of a resource and register it * @param p_path */ - T* LoadResource(const std::string& p_path); + T* LoadResource(const std::filesystem::path& p_path); /** * Handle the destruction of a resource and unregister it * @param p_path */ - void UnloadResource(const std::string& p_path); + void UnloadResource(const std::filesystem::path& p_path); /** * Move a resource to the new given id (path) * @param p_previousPath * @param p_newPath */ - bool MoveResource(const std::string& p_previousPath, const std::string& p_newPath); + bool MoveResource(const std::filesystem::path& p_previousPath, const std::filesystem::path& p_newPath); /** * Reload a resource * @param p_path */ - void ReloadResource(const std::string& p_path); + void ReloadResource(const std::filesystem::path& p_path); /** * Return true if the resource exists (= Is registered) * @param p_path */ - bool IsResourceRegistered(const std::string& p_path); + bool IsResourceRegistered(const std::filesystem::path& p_path); /** * Destroy and unregister every resources @@ -62,14 +62,14 @@ namespace OvCore::ResourceManagement * @param p_path * @param p_instance */ - T* RegisterResource(const std::string& p_path, T* p_instance); + T* RegisterResource(const std::filesystem::path& p_path, T* p_instance); /** * Unregister a resource (You have to destroy the resource before calling this method * to prevent memory leaks) * @param p_path */ - void UnregisterResource(const std::string& p_path); + void UnregisterResource(const std::filesystem::path& p_path); /** * Return the instance linked to the given path or try to load it if not registered. @@ -77,14 +77,14 @@ namespace OvCore::ResourceManagement * @param p_path * @param p_tryToLoadIfNotFound */ - T* GetResource(const std::string& p_path, bool p_tryToLoadIfNotFound = true); + T* GetResource(const std::filesystem::path& p_path, bool p_tryToLoadIfNotFound = true); /** * Operator overload to get an instance linked to the given path. * @note See GetResource for more informations * @param p_path */ - T* operator[](const std::string& p_path); + T* operator[](const std::filesystem::path& p_path); /** * Provide asset paths for the resource managers @@ -100,19 +100,19 @@ namespace OvCore::ResourceManagement /** * Returns the resource map */ - std::unordered_map& GetResources(); + std::unordered_map& GetResources(); protected: - virtual T* CreateResource(const std::string& p_path) = 0; + virtual T* CreateResource(const std::filesystem::path& p_path) = 0; virtual void DestroyResource(T* p_resource) = 0; - virtual void ReloadResource(T* p_resource, const std::string& p_path) = 0; - std::string GetRealPath(const std::string& p_path) const; + virtual void ReloadResource(T* p_resource, const std::filesystem::path& p_path) = 0; + std::filesystem::path GetRealPath(const std::filesystem::path& p_path) const; private: inline static std::filesystem::path __PROJECT_ASSETS_PATH; inline static std::filesystem::path __ENGINE_ASSETS_PATH; - std::unordered_map m_resources; + std::unordered_map m_resources; }; } diff --git a/Sources/OvCore/include/OvCore/ResourceManagement/AResourceManager.inl b/Sources/OvCore/include/OvCore/ResourceManagement/AResourceManager.inl new file mode 100644 index 000000000..efe522d70 --- /dev/null +++ b/Sources/OvCore/include/OvCore/ResourceManagement/AResourceManager.inl @@ -0,0 +1,173 @@ +/** +* @project: Overload +* @author: Overload Tech. +* @licence: MIT +*/ + +#pragma once + +#include + +#include "OvCore/ResourceManagement/AResourceManager.h" + +namespace +{ + // Normalize a path for consistent key usage across platforms. + // - Treat backslashes as separators (important on POSIX where '\\' isn't a separator) + // - Apply lexically_normal to collapse '.' and '..' + inline std::filesystem::path NormalizeKey(const std::filesystem::path& p) + { + std::string s = p.string(); + std::replace(s.begin(), s.end(), '\\', '/'); + std::filesystem::path norm = std::filesystem::path{s}.lexically_normal(); + return norm; + } +} + +namespace OvCore::ResourceManagement +{ + template + inline T* AResourceManager::LoadResource(const std::filesystem::path & p_path) + { + if (auto resource = GetResource(p_path, false); resource) + return resource; + else + { + auto newResource = CreateResource(p_path); + if (newResource) + return RegisterResource(p_path, newResource); + else + return nullptr; + } + } + + template + inline void AResourceManager::UnloadResource(const std::filesystem::path & p_path) + { + if (auto resource = GetResource(p_path, false); resource) + { + DestroyResource(resource); + UnregisterResource(p_path); + } + } + + template + inline bool AResourceManager::MoveResource(const std::filesystem::path & p_previousPath, const std::filesystem::path & p_newPath) + { + if (auto toMove = GetResource(p_previousPath, false); toMove && !IsResourceRegistered(p_newPath)) + { + RegisterResource(p_newPath, toMove); + UnregisterResource(p_previousPath); + return true; + } + + return false; + } + + template + inline void AResourceManager::ReloadResource(const std::filesystem::path& p_path) + { + if (auto resource = GetResource(p_path, false); resource) + { + ReloadResource(resource, p_path); + } + } + + template + inline bool AResourceManager::IsResourceRegistered(const std::filesystem::path & p_path) + { + return m_resources.find(NormalizeKey(p_path)) != m_resources.end(); + } + + template + inline void AResourceManager::UnloadResources() + { + for (auto&[key, value] : m_resources) + DestroyResource(value); + + m_resources.clear(); + } + + template + inline T* AResourceManager::RegisterResource(const std::filesystem::path& p_path, T* p_instance) + { + auto key = NormalizeKey(p_path); + + if (auto resource = GetResource(p_path, false); resource) + { + DestroyResource(resource); + } + + m_resources[key] = p_instance; + + return p_instance; + } + + template + inline void AResourceManager::UnregisterResource(const std::filesystem::path & p_path) + { + m_resources.erase(NormalizeKey(p_path)); + } + + template + inline T* AResourceManager::GetResource(const std::filesystem::path& p_path, bool p_tryToLoadIfNotFound) + { + auto key = NormalizeKey(p_path); + + if (auto resource = m_resources.find(key); resource != m_resources.end()) + { + return resource->second; + } + else if (p_tryToLoadIfNotFound) + { + return LoadResource(p_path); + } + + return nullptr; + } + + template + inline T* AResourceManager::operator[](const std::filesystem::path & p_path) + { + return GetResource(p_path); + } + + template + inline void AResourceManager::ProvideAssetPaths( + const std::filesystem::path& p_projectAssetsPath, + const std::filesystem::path& p_engineAssetsPath + ) + { + __PROJECT_ASSETS_PATH = p_projectAssetsPath; + __ENGINE_ASSETS_PATH = p_engineAssetsPath; + } + + template + inline std::unordered_map& AResourceManager::GetResources() + { + return m_resources; + } + + template + inline std::filesystem::path AResourceManager::GetRealPath(const std::filesystem::path& p_path) const + { + // Keep support for the engine prefix ':' + const std::string s = p_path.string(); + std::filesystem::path path; + if (!s.empty() && s.front() == ':') + { + // Remove the ':' prefix and normalize separators + std::string sub = s.substr(1); + std::replace(sub.begin(), sub.end(), '\\', '/'); + path = __ENGINE_ASSETS_PATH / std::filesystem::path{sub}; + } + else + { + std::string sub = s; + std::replace(sub.begin(), sub.end(), '\\', '/'); + path = __PROJECT_ASSETS_PATH / std::filesystem::path{sub}; + } + + return path.lexically_normal(); + } +} \ No newline at end of file diff --git a/Sources/Overload/OvCore/include/OvCore/ResourceManagement/MaterialManager.h b/Sources/OvCore/include/OvCore/ResourceManagement/MaterialManager.h similarity index 89% rename from Sources/Overload/OvCore/include/OvCore/ResourceManagement/MaterialManager.h rename to Sources/OvCore/include/OvCore/ResourceManagement/MaterialManager.h index 7e1bfbd92..d1f142843 100644 --- a/Sources/Overload/OvCore/include/OvCore/ResourceManagement/MaterialManager.h +++ b/Sources/OvCore/include/OvCore/ResourceManagement/MaterialManager.h @@ -21,7 +21,7 @@ namespace OvCore::ResourceManagement * Create the resource identified by the given path * @param p_path */ - virtual OvCore::Resources::Material* CreateResource(const std::string & p_path) override; + virtual OvCore::Resources::Material* CreateResource(const std::filesystem::path & p_path) override; /** * Destroy the given resource @@ -34,6 +34,6 @@ namespace OvCore::ResourceManagement * @param p_resource * @param p_path */ - virtual void ReloadResource(OvCore::Resources::Material* p_resource, const std::string& p_path) override; + virtual void ReloadResource(OvCore::Resources::Material* p_resource, const std::filesystem::path& p_path) override; }; } \ No newline at end of file diff --git a/Sources/Overload/OvCore/include/OvCore/ResourceManagement/ModelManager.h b/Sources/OvCore/include/OvCore/ResourceManagement/ModelManager.h similarity index 89% rename from Sources/Overload/OvCore/include/OvCore/ResourceManagement/ModelManager.h rename to Sources/OvCore/include/OvCore/ResourceManagement/ModelManager.h index f61dc79e6..60bd6c184 100644 --- a/Sources/Overload/OvCore/include/OvCore/ResourceManagement/ModelManager.h +++ b/Sources/OvCore/include/OvCore/ResourceManagement/ModelManager.h @@ -22,7 +22,7 @@ namespace OvCore::ResourceManagement * Create the resource identified by the given path * @param p_path */ - virtual OvRendering::Resources::Model* CreateResource(const std::string & p_path) override; + virtual OvRendering::Resources::Model* CreateResource(const std::filesystem::path & p_path) override; /** * Destroy the given resource @@ -35,6 +35,6 @@ namespace OvCore::ResourceManagement * @param p_resource * @param p_path */ - virtual void ReloadResource(OvRendering::Resources::Model* p_resource, const std::string& p_path) override; + virtual void ReloadResource(OvRendering::Resources::Model* p_resource, const std::filesystem::path& p_path) override; }; } \ No newline at end of file diff --git a/Sources/Overload/OvCore/include/OvCore/ResourceManagement/ShaderManager.h b/Sources/OvCore/include/OvCore/ResourceManagement/ShaderManager.h similarity index 89% rename from Sources/Overload/OvCore/include/OvCore/ResourceManagement/ShaderManager.h rename to Sources/OvCore/include/OvCore/ResourceManagement/ShaderManager.h index 9577bcad0..076ff8a6b 100644 --- a/Sources/Overload/OvCore/include/OvCore/ResourceManagement/ShaderManager.h +++ b/Sources/OvCore/include/OvCore/ResourceManagement/ShaderManager.h @@ -22,7 +22,7 @@ namespace OvCore::ResourceManagement * Create the resource identified by the given path * @param p_path */ - virtual OvRendering::Resources::Shader* CreateResource(const std::string & p_path) override; + virtual OvRendering::Resources::Shader* CreateResource(const std::filesystem::path & p_path) override; /** * Destroy the given resource @@ -35,6 +35,6 @@ namespace OvCore::ResourceManagement * @param p_resource * @param p_path */ - virtual void ReloadResource(OvRendering::Resources::Shader* p_resource, const std::string& p_path) override; + virtual void ReloadResource(OvRendering::Resources::Shader* p_resource, const std::filesystem::path& p_path) override; }; } \ No newline at end of file diff --git a/Sources/Overload/OvCore/include/OvCore/ResourceManagement/SoundManager.h b/Sources/OvCore/include/OvCore/ResourceManagement/SoundManager.h similarity index 82% rename from Sources/Overload/OvCore/include/OvCore/ResourceManagement/SoundManager.h rename to Sources/OvCore/include/OvCore/ResourceManagement/SoundManager.h index b9ee8f75e..9241492f8 100644 --- a/Sources/Overload/OvCore/include/OvCore/ResourceManagement/SoundManager.h +++ b/Sources/OvCore/include/OvCore/ResourceManagement/SoundManager.h @@ -22,7 +22,7 @@ namespace OvCore::ResourceManagement * Create the resource identified by the given path * @param p_path */ - virtual OvAudio::Resources::Sound* CreateResource(const std::string& p_path) override; + virtual OvAudio::Resources::Sound* CreateResource(const std::filesystem::path& p_path) override; /** * Destroy the given resource @@ -35,6 +35,6 @@ namespace OvCore::ResourceManagement * @param p_resource * @param p_path */ - virtual void ReloadResource(OvAudio::Resources::Sound* p_resource, const std::string& p_path) override; + virtual void ReloadResource(OvAudio::Resources::Sound* p_resource, const std::filesystem::path& p_path) override; }; } \ No newline at end of file diff --git a/Sources/Overload/OvCore/include/OvCore/ResourceManagement/TextureManager.h b/Sources/OvCore/include/OvCore/ResourceManagement/TextureManager.h similarity index 89% rename from Sources/Overload/OvCore/include/OvCore/ResourceManagement/TextureManager.h rename to Sources/OvCore/include/OvCore/ResourceManagement/TextureManager.h index 24134d033..8a3b8069c 100644 --- a/Sources/Overload/OvCore/include/OvCore/ResourceManagement/TextureManager.h +++ b/Sources/OvCore/include/OvCore/ResourceManagement/TextureManager.h @@ -22,7 +22,7 @@ namespace OvCore::ResourceManagement * Create the resource identified by the given path * @param p_path */ - virtual OvRendering::Resources::Texture* CreateResource(const std::string & p_path) override; + virtual OvRendering::Resources::Texture* CreateResource(const std::filesystem::path & p_path) override; /** * Destroy the given resource @@ -35,6 +35,6 @@ namespace OvCore::ResourceManagement * @param p_resource * @param p_path */ - virtual void ReloadResource(OvRendering::Resources::Texture* p_resource, const std::string& p_path) override; + virtual void ReloadResource(OvRendering::Resources::Texture* p_resource, const std::filesystem::path& p_path) override; }; } \ No newline at end of file diff --git a/Sources/Overload/OvCore/include/OvCore/Resources/Loaders/MaterialLoader.h b/Sources/OvCore/include/OvCore/Resources/Loaders/MaterialLoader.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/Resources/Loaders/MaterialLoader.h rename to Sources/OvCore/include/OvCore/Resources/Loaders/MaterialLoader.h diff --git a/Sources/Overload/OvCore/include/OvCore/Resources/Material.h b/Sources/OvCore/include/OvCore/Resources/Material.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/Resources/Material.h rename to Sources/OvCore/include/OvCore/Resources/Material.h diff --git a/Sources/Overload/OvCore/include/OvCore/SceneSystem/Scene.h b/Sources/OvCore/include/OvCore/SceneSystem/Scene.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/SceneSystem/Scene.h rename to Sources/OvCore/include/OvCore/SceneSystem/Scene.h diff --git a/Sources/Overload/OvCore/include/OvCore/SceneSystem/SceneManager.h b/Sources/OvCore/include/OvCore/SceneSystem/SceneManager.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/SceneSystem/SceneManager.h rename to Sources/OvCore/include/OvCore/SceneSystem/SceneManager.h diff --git a/Sources/Overload/OvCore/include/OvCore/Scripting/Common/EScriptingLanguage.h b/Sources/OvCore/include/OvCore/Scripting/Common/EScriptingLanguage.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/Scripting/Common/EScriptingLanguage.h rename to Sources/OvCore/include/OvCore/Scripting/Common/EScriptingLanguage.h diff --git a/Sources/Overload/OvCore/include/OvCore/Scripting/Common/TScript.h b/Sources/OvCore/include/OvCore/Scripting/Common/TScript.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/Scripting/Common/TScript.h rename to Sources/OvCore/include/OvCore/Scripting/Common/TScript.h diff --git a/Sources/Overload/OvCore/include/OvCore/Scripting/Common/TScriptEngine.h b/Sources/OvCore/include/OvCore/Scripting/Common/TScriptEngine.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/Scripting/Common/TScriptEngine.h rename to Sources/OvCore/include/OvCore/Scripting/Common/TScriptEngine.h diff --git a/Sources/Overload/OvCore/include/OvCore/Scripting/Lua/LuaScript.h b/Sources/OvCore/include/OvCore/Scripting/Lua/LuaScript.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/Scripting/Lua/LuaScript.h rename to Sources/OvCore/include/OvCore/Scripting/Lua/LuaScript.h diff --git a/Sources/Overload/OvCore/include/OvCore/Scripting/Lua/LuaScriptEngine.h b/Sources/OvCore/include/OvCore/Scripting/Lua/LuaScriptEngine.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/Scripting/Lua/LuaScriptEngine.h rename to Sources/OvCore/include/OvCore/Scripting/Lua/LuaScriptEngine.h diff --git a/Sources/Overload/OvCore/include/OvCore/Scripting/Null/NullScript.h b/Sources/OvCore/include/OvCore/Scripting/Null/NullScript.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/Scripting/Null/NullScript.h rename to Sources/OvCore/include/OvCore/Scripting/Null/NullScript.h diff --git a/Sources/Overload/OvCore/include/OvCore/Scripting/Null/NullScriptEngine.h b/Sources/OvCore/include/OvCore/Scripting/Null/NullScriptEngine.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/Scripting/Null/NullScriptEngine.h rename to Sources/OvCore/include/OvCore/Scripting/Null/NullScriptEngine.h diff --git a/Sources/Overload/OvCore/include/OvCore/Scripting/ScriptEngine.h b/Sources/OvCore/include/OvCore/Scripting/ScriptEngine.h similarity index 100% rename from Sources/Overload/OvCore/include/OvCore/Scripting/ScriptEngine.h rename to Sources/OvCore/include/OvCore/Scripting/ScriptEngine.h diff --git a/Sources/Overload/OvCore/premake5.lua b/Sources/OvCore/premake5.lua similarity index 59% rename from Sources/Overload/OvCore/premake5.lua rename to Sources/OvCore/premake5.lua index 82d84f6f5..9c7b91c99 100644 --- a/Sources/Overload/OvCore/premake5.lua +++ b/Sources/OvCore/premake5.lua @@ -4,7 +4,11 @@ project "OvCore" cppdialect "C++20" targetdir (outputdir .. "%{cfg.buildcfg}/%{prj.name}") objdir (objoutdir .. "%{cfg.buildcfg}/%{prj.name}") - buildoptions { "/bigobj" } + + -- If MSVC, set big obj flag + filter { "toolset:msc" } + buildoptions { "/bigobj" } + filter {} files { "**.h", @@ -24,14 +28,14 @@ project "OvCore" dependdir .. "tracy", -- Overload SDK - "%{wks.location}/OvAudio/include", - "%{wks.location}/OvDebug/include", - "%{wks.location}/OvMaths/include", - "%{wks.location}/OvPhysics/include", - "%{wks.location}/OvRendering/include", - "%{wks.location}/OvTools/include", - "%{wks.location}/OvUI/include", - "%{wks.location}/OvWindowing/include", + "%{wks.location}/Sources/OvAudio/include", + "%{wks.location}/Sources/OvDebug/include", + "%{wks.location}/Sources/OvMaths/include", + "%{wks.location}/Sources/OvPhysics/include", + "%{wks.location}/Sources/OvRendering/include", + "%{wks.location}/Sources/OvTools/include", + "%{wks.location}/Sources/OvUI/include", + "%{wks.location}/Sources/OvWindowing/include", -- Current project "include", diff --git a/Sources/Overload/OvCore/src/OvCore/ECS/Actor.cpp b/Sources/OvCore/src/OvCore/ECS/Actor.cpp similarity index 85% rename from Sources/Overload/OvCore/src/OvCore/ECS/Actor.cpp rename to Sources/OvCore/src/OvCore/ECS/Actor.cpp index 75dc984ec..2ab0ae9b8 100644 --- a/Sources/Overload/OvCore/src/OvCore/ECS/Actor.cpp +++ b/Sources/OvCore/src/OvCore/ECS/Actor.cpp @@ -25,6 +25,17 @@ #include #include +#include + +namespace +{ + template + bool IsType(const std::string_view p_typeName) + { + return p_typeName == OvCore::ECS::Components::ComponentTraits::Name; + } +} + OvTools::Eventing::Event OvCore::ECS::Actor::DestroyedEvent; OvTools::Eventing::Event OvCore::ECS::Actor::CreatedEvent; OvTools::Eventing::Event OvCore::ECS::Actor::AttachEvent; @@ -401,7 +412,7 @@ void OvCore::ECS::Actor::OnSerialize(tinyxml2::XMLDocument & p_doc, tinyxml2::XM componentsNode->InsertEndChild(componentNode); /* Component type */ - OvCore::Helpers::Serializer::SerializeString(p_doc, componentNode, "type", typeid(*component).name()); + OvCore::Helpers::Serializer::SerializeString(p_doc, componentNode, "type", component->GetTypeName()); /* Data node (Will be passed to the component) */ tinyxml2::XMLElement* data = p_doc.NewElement("data"); @@ -448,29 +459,32 @@ void OvCore::ECS::Actor::OnDeserialize(tinyxml2::XMLDocument & p_doc, tinyxml2:: while (currentComponent) { - std::string componentType = currentComponent->FirstChildElement("type")->GetText(); + const std::string componentType = currentComponent->FirstChildElement("type")->GetText(); OvCore::ECS::Components::AComponent* component = nullptr; - // TODO: Use component name instead of typeid (unsafe) - if (componentType == typeid(Components::CTransform).name()) component = &transform; - else if (componentType == typeid(Components::CPhysicalBox).name()) component = &AddComponent(); - else if (componentType == typeid(Components::CPhysicalSphere).name()) component = &AddComponent(); - else if (componentType == typeid(Components::CPhysicalCapsule).name()) component = &AddComponent(); - else if (componentType == typeid(Components::CModelRenderer).name()) component = &AddComponent(); - else if (componentType == typeid(Components::CCamera).name()) component = &AddComponent(); - else if (componentType == typeid(Components::CMaterialRenderer).name()) component = &AddComponent(); - else if (componentType == typeid(Components::CAudioSource).name()) component = &AddComponent(); - else if (componentType == typeid(Components::CAudioListener).name()) component = &AddComponent(); - else if (componentType == typeid(Components::CPointLight).name()) component = &AddComponent(); - else if (componentType == typeid(Components::CDirectionalLight).name()) component = &AddComponent(); - else if (componentType == typeid(Components::CSpotLight).name()) component = &AddComponent(); - else if (componentType == typeid(Components::CAmbientBoxLight).name()) component = &AddComponent(); - else if (componentType == typeid(Components::CAmbientSphereLight).name()) component = &AddComponent(); - else if (componentType == typeid(Components::CPostProcessStack).name()) component = &AddComponent(); - else if (componentType == typeid(Components::CReflectionProbe).name()) component = &AddComponent(); + using namespace OvCore::ECS::Components; + + if (IsType(componentType)) component = &transform; + else if (IsType(componentType)) component = &AddComponent(); + else if (IsType(componentType)) component = &AddComponent(); + else if (IsType(componentType)) component = &AddComponent(); + else if (IsType(componentType)) component = &AddComponent(); + else if (IsType(componentType)) component = &AddComponent(); + else if (IsType(componentType)) component = &AddComponent(); + else if (IsType(componentType)) component = &AddComponent(); + else if (IsType(componentType)) component = &AddComponent(); + else if (IsType(componentType)) component = &AddComponent(); + else if (IsType(componentType)) component = &AddComponent(); + else if (IsType(componentType)) component = &AddComponent(); + else if (IsType(componentType)) component = &AddComponent(); + else if (IsType(componentType)) component = &AddComponent(); + else if (IsType(componentType)) component = &AddComponent(); + else if (IsType(componentType)) component = &AddComponent(); if (component) + { component->OnDeserialize(p_doc, currentComponent->FirstChildElement("data")); + } currentComponent = currentComponent->NextSiblingElement("component"); } diff --git a/Sources/Overload/OvCore/src/OvCore/ECS/Components/AComponent.cpp b/Sources/OvCore/src/OvCore/ECS/Components/AComponent.cpp similarity index 100% rename from Sources/Overload/OvCore/src/OvCore/ECS/Components/AComponent.cpp rename to Sources/OvCore/src/OvCore/ECS/Components/AComponent.cpp diff --git a/Sources/Overload/OvCore/src/OvCore/ECS/Components/Behaviour.cpp b/Sources/OvCore/src/OvCore/ECS/Components/Behaviour.cpp similarity index 96% rename from Sources/Overload/OvCore/src/OvCore/ECS/Components/Behaviour.cpp rename to Sources/OvCore/src/OvCore/ECS/Components/Behaviour.cpp index 03498982e..13ed67ca7 100644 --- a/Sources/Overload/OvCore/src/OvCore/ECS/Components/Behaviour.cpp +++ b/Sources/OvCore/src/OvCore/ECS/Components/Behaviour.cpp @@ -4,14 +4,15 @@ * @licence: MIT */ -#include -#include - #include #include #include #include +#include + +#include + OvCore::ECS::Components::Behaviour::Behaviour(ECS::Actor& p_owner, const std::string& p_name) : name(p_name), AComponent(p_owner) { @@ -28,7 +29,12 @@ std::string OvCore::ECS::Components::Behaviour::GetName() return "Behaviour"; } -void OvCore::ECS::Components::Behaviour::SetScript(std::unique_ptr&& p_scriptContext) +std::string OvCore::ECS::Components::Behaviour::GetTypeName() +{ + return std::string{ComponentTraits::Name}; +} + +void OvCore::ECS::Components::Behaviour::SetScript(std::unique_ptr &&p_scriptContext) { m_script = std::move(p_scriptContext); } diff --git a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CAmbientBoxLight.cpp b/Sources/OvCore/src/OvCore/ECS/Components/CAmbientBoxLight.cpp similarity index 90% rename from Sources/Overload/OvCore/src/OvCore/ECS/Components/CAmbientBoxLight.cpp rename to Sources/OvCore/src/OvCore/ECS/Components/CAmbientBoxLight.cpp index 6b9974c4c..4f7d95f19 100644 --- a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CAmbientBoxLight.cpp +++ b/Sources/OvCore/src/OvCore/ECS/Components/CAmbientBoxLight.cpp @@ -4,14 +4,13 @@ * @licence: MIT */ +#include +#include + +#include #include #include #include -#include - -#include "OvCore/ECS/Actor.h" - -#include "OvCore/ECS/Components/CAmbientBoxLight.h" OvCore::ECS::Components::CAmbientBoxLight::CAmbientBoxLight(ECS::Actor & p_owner) : CLight(p_owner) @@ -29,6 +28,11 @@ std::string OvCore::ECS::Components::CAmbientBoxLight::GetName() return "Ambient Box Light"; } +std::string OvCore::ECS::Components::CAmbientBoxLight::GetTypeName() +{ + return std::string{ComponentTraits::Name}; +} + OvMaths::FVector3 OvCore::ECS::Components::CAmbientBoxLight::GetSize() const { return { m_data.constant, m_data.linear, m_data.quadratic }; diff --git a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CAmbientSphereLight.cpp b/Sources/OvCore/src/OvCore/ECS/Components/CAmbientSphereLight.cpp similarity index 87% rename from Sources/Overload/OvCore/src/OvCore/ECS/Components/CAmbientSphereLight.cpp rename to Sources/OvCore/src/OvCore/ECS/Components/CAmbientSphereLight.cpp index 00f71124c..2fe005454 100644 --- a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CAmbientSphereLight.cpp +++ b/Sources/OvCore/src/OvCore/ECS/Components/CAmbientSphereLight.cpp @@ -4,15 +4,14 @@ * @licence: MIT */ +#include +#include + #include #include #include #include -#include "OvCore/ECS/Actor.h" - -#include "OvCore/ECS/Components/CAmbientSphereLight.h" - OvCore::ECS::Components::CAmbientSphereLight::CAmbientSphereLight(ECS::Actor & p_owner) : CLight(p_owner) { @@ -27,6 +26,11 @@ std::string OvCore::ECS::Components::CAmbientSphereLight::GetName() return "Ambient Sphere Light"; } +std::string OvCore::ECS::Components::CAmbientSphereLight::GetTypeName() +{ + return std::string{ComponentTraits::Name}; +} + float OvCore::ECS::Components::CAmbientSphereLight::GetRadius() const { return m_data.quadratic; diff --git a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CAudioListener.cpp b/Sources/OvCore/src/OvCore/ECS/Components/CAudioListener.cpp similarity index 80% rename from Sources/Overload/OvCore/src/OvCore/ECS/Components/CAudioListener.cpp rename to Sources/OvCore/src/OvCore/ECS/Components/CAudioListener.cpp index 558572299..0316f42e2 100644 --- a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CAudioListener.cpp +++ b/Sources/OvCore/src/OvCore/ECS/Components/CAudioListener.cpp @@ -4,8 +4,8 @@ * @licence: MIT */ -#include "OvCore/ECS/Components/CAudioListener.h" -#include "OvCore/ECS/Actor.h" +#include +#include OvCore::ECS::Components::CAudioListener::CAudioListener(ECS::Actor& p_owner) : AComponent(p_owner), @@ -19,6 +19,11 @@ std::string OvCore::ECS::Components::CAudioListener::GetName() return "Audio Listener"; } +std::string OvCore::ECS::Components::CAudioListener::GetTypeName() +{ + return std::string{ComponentTraits::Name}; +} + void OvCore::ECS::Components::CAudioListener::OnSerialize(tinyxml2::XMLDocument& p_doc, tinyxml2::XMLNode* p_node) { } diff --git a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CAudioSource.cpp b/Sources/OvCore/src/OvCore/ECS/Components/CAudioSource.cpp similarity index 98% rename from Sources/Overload/OvCore/src/OvCore/ECS/Components/CAudioSource.cpp rename to Sources/OvCore/src/OvCore/ECS/Components/CAudioSource.cpp index 7d01b81ec..d45f59296 100644 --- a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CAudioSource.cpp +++ b/Sources/OvCore/src/OvCore/ECS/Components/CAudioSource.cpp @@ -25,6 +25,11 @@ std::string OvCore::ECS::Components::CAudioSource::GetName() return "Audio Source"; } +std::string OvCore::ECS::Components::CAudioSource::GetTypeName() +{ + return std::string{ComponentTraits::Name}; +} + void OvCore::ECS::Components::CAudioSource::SetSound(OvAudio::Resources::Sound* p_sound) { m_sound = p_sound; diff --git a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CCamera.cpp b/Sources/OvCore/src/OvCore/ECS/Components/CCamera.cpp similarity index 98% rename from Sources/Overload/OvCore/src/OvCore/ECS/Components/CCamera.cpp rename to Sources/OvCore/src/OvCore/ECS/Components/CCamera.cpp index 380a62dc9..d0180109e 100644 --- a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CCamera.cpp +++ b/Sources/OvCore/src/OvCore/ECS/Components/CCamera.cpp @@ -25,6 +25,11 @@ std::string OvCore::ECS::Components::CCamera::GetName() return "Camera"; } +std::string OvCore::ECS::Components::CCamera::GetTypeName() +{ + return std::string{ComponentTraits::Name}; +} + void OvCore::ECS::Components::CCamera::SetFov(float p_value) { m_camera.SetFov(p_value); diff --git a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CDirectionalLight.cpp b/Sources/OvCore/src/OvCore/ECS/Components/CDirectionalLight.cpp similarity index 94% rename from Sources/Overload/OvCore/src/OvCore/ECS/Components/CDirectionalLight.cpp rename to Sources/OvCore/src/OvCore/ECS/Components/CDirectionalLight.cpp index 3bcd44ba6..d1a6d3232 100644 --- a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CDirectionalLight.cpp +++ b/Sources/OvCore/src/OvCore/ECS/Components/CDirectionalLight.cpp @@ -4,15 +4,14 @@ * @licence: MIT */ +#include +#include + #include #include #include #include -#include "OvCore/ECS/Actor.h" - -#include "OvCore/ECS/Components/CDirectionalLight.h" - OvCore::ECS::Components::CDirectionalLight::CDirectionalLight(ECS::Actor & p_owner) : CLight(p_owner) { @@ -25,6 +24,11 @@ std::string OvCore::ECS::Components::CDirectionalLight::GetName() return "Directional Light"; } +std::string OvCore::ECS::Components::CDirectionalLight::GetTypeName() +{ + return std::string{ComponentTraits::Name}; +} + void OvCore::ECS::Components::CDirectionalLight::SetCastShadows(bool p_enabled) { m_data.castShadows = p_enabled; diff --git a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CLight.cpp b/Sources/OvCore/src/OvCore/ECS/Components/CLight.cpp similarity index 96% rename from Sources/Overload/OvCore/src/OvCore/ECS/Components/CLight.cpp rename to Sources/OvCore/src/OvCore/ECS/Components/CLight.cpp index 4e0fa5cee..ee070f567 100644 --- a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CLight.cpp +++ b/Sources/OvCore/src/OvCore/ECS/Components/CLight.cpp @@ -4,16 +4,15 @@ * @licence: MIT */ +#include +#include + #include #include #include #include #include -#include "OvCore/ECS/Actor.h" - -#include "OvCore/ECS/Components/CLight.h" - OvCore::ECS::Components::CLight::CLight(ECS::Actor & p_owner) : AComponent(p_owner), m_data{ p_owner.transform.GetFTransform() } diff --git a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CMaterialRenderer.cpp b/Sources/OvCore/src/OvCore/ECS/Components/CMaterialRenderer.cpp similarity index 98% rename from Sources/Overload/OvCore/src/OvCore/ECS/Components/CMaterialRenderer.cpp rename to Sources/OvCore/src/OvCore/ECS/Components/CMaterialRenderer.cpp index 8f1a6f1df..a9f154e93 100644 --- a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CMaterialRenderer.cpp +++ b/Sources/OvCore/src/OvCore/ECS/Components/CMaterialRenderer.cpp @@ -4,6 +4,7 @@ * @licence: MIT */ +#include #include #include @@ -38,6 +39,11 @@ std::string OvCore::ECS::Components::CMaterialRenderer::GetName() return "Material Renderer"; } +std::string OvCore::ECS::Components::CMaterialRenderer::GetTypeName() +{ + return std::string{ComponentTraits::Name}; +} + void OvCore::ECS::Components::CMaterialRenderer::FillWithMaterial(OvCore::Resources::Material & p_material) { for (uint8_t i = 0; i < m_materials.size(); ++i) diff --git a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CModelRenderer.cpp b/Sources/OvCore/src/OvCore/ECS/Components/CModelRenderer.cpp similarity index 91% rename from Sources/Overload/OvCore/src/OvCore/ECS/Components/CModelRenderer.cpp rename to Sources/OvCore/src/OvCore/ECS/Components/CModelRenderer.cpp index 4c7d1b573..0c33fe22c 100644 --- a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CModelRenderer.cpp +++ b/Sources/OvCore/src/OvCore/ECS/Components/CModelRenderer.cpp @@ -4,21 +4,21 @@ * @licence: MIT */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include #include #include -#include #include -#include -#include -#include - -#include "OvCore/Global/ServiceLocator.h" -#include "OvCore/ResourceManagement/TextureManager.h" -#include "OvCore/ResourceManagement/ModelManager.h" -#include "OvCore/ResourceManagement/ShaderManager.h" -#include "OvCore/ECS/Components/CModelRenderer.h" -#include "OvCore/ECS/Components/CMaterialRenderer.h" -#include "OvCore/ECS/Actor.h" OvCore::ECS::Components::CModelRenderer::CModelRenderer(ECS::Actor& p_owner) : AComponent(p_owner) { @@ -34,6 +34,11 @@ std::string OvCore::ECS::Components::CModelRenderer::GetName() return "Model Renderer"; } +std::string OvCore::ECS::Components::CModelRenderer::GetTypeName() +{ + return std::string{ComponentTraits::Name}; +} + void OvCore::ECS::Components::CModelRenderer::SetModel(OvRendering::Resources::Model* p_model) { m_model = p_model; diff --git a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CPhysicalBox.cpp b/Sources/OvCore/src/OvCore/ECS/Components/CPhysicalBox.cpp similarity index 88% rename from Sources/Overload/OvCore/src/OvCore/ECS/Components/CPhysicalBox.cpp rename to Sources/OvCore/src/OvCore/ECS/Components/CPhysicalBox.cpp index 4228b2b31..52f3698b5 100644 --- a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CPhysicalBox.cpp +++ b/Sources/OvCore/src/OvCore/ECS/Components/CPhysicalBox.cpp @@ -4,10 +4,10 @@ * @licence: MIT */ -#include +#include +#include -#include "OvCore/ECS/Components/CPhysicalBox.h" -#include "OvCore/ECS/Actor.h" +#include using namespace OvPhysics::Entities; @@ -27,6 +27,11 @@ std::string OvCore::ECS::Components::CPhysicalBox::GetName() return "Physical Box"; } +std::string OvCore::ECS::Components::CPhysicalBox::GetTypeName() +{ + return std::string{ComponentTraits::Name}; +} + void OvCore::ECS::Components::CPhysicalBox::SetSize(const OvMaths::FVector3 & p_size) { GetPhysicalObjectAs().SetSize(p_size); diff --git a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CPhysicalCapsule.cpp b/Sources/OvCore/src/OvCore/ECS/Components/CPhysicalCapsule.cpp similarity index 91% rename from Sources/Overload/OvCore/src/OvCore/ECS/Components/CPhysicalCapsule.cpp rename to Sources/OvCore/src/OvCore/ECS/Components/CPhysicalCapsule.cpp index 83fc7a100..db415eb84 100644 --- a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CPhysicalCapsule.cpp +++ b/Sources/OvCore/src/OvCore/ECS/Components/CPhysicalCapsule.cpp @@ -4,12 +4,12 @@ * @licence: MIT */ +#include +#include + #include #include -#include "OvCore/ECS/Components/CPhysicalCapsule.h" -#include "OvCore/ECS/Actor.h" - using namespace OvPhysics::Entities; OvCore::ECS::Components::CPhysicalCapsule::CPhysicalCapsule(ECS::Actor & p_owner) : @@ -28,6 +28,11 @@ std::string OvCore::ECS::Components::CPhysicalCapsule::GetName() return "Physical Capsule"; } +std::string OvCore::ECS::Components::CPhysicalCapsule::GetTypeName() +{ + return std::string{ComponentTraits::Name}; +} + void OvCore::ECS::Components::CPhysicalCapsule::SetRadius(float p_radius) { GetPhysicalObjectAs().SetRadius(p_radius); diff --git a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CPhysicalObject.cpp b/Sources/OvCore/src/OvCore/ECS/Components/CPhysicalObject.cpp similarity index 98% rename from Sources/Overload/OvCore/src/OvCore/ECS/Components/CPhysicalObject.cpp rename to Sources/OvCore/src/OvCore/ECS/Components/CPhysicalObject.cpp index 895ea35a0..b7762f275 100644 --- a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CPhysicalObject.cpp +++ b/Sources/OvCore/src/OvCore/ECS/Components/CPhysicalObject.cpp @@ -4,15 +4,17 @@ * @licence: MIT */ -#include -#include +#include + +#include +#include #include #include -#include "OvCore/ECS/Components/CPhysicalObject.h" -#include "OvCore/ECS/Actor.h" +#include +#include OvCore::ECS::Components::CPhysicalObject::CPhysicalObject(ECS::Actor & p_owner) : AComponent(p_owner) diff --git a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CPhysicalSphere.cpp b/Sources/OvCore/src/OvCore/ECS/Components/CPhysicalSphere.cpp similarity index 88% rename from Sources/Overload/OvCore/src/OvCore/ECS/Components/CPhysicalSphere.cpp rename to Sources/OvCore/src/OvCore/ECS/Components/CPhysicalSphere.cpp index 410903f6f..f7da8cdc7 100644 --- a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CPhysicalSphere.cpp +++ b/Sources/OvCore/src/OvCore/ECS/Components/CPhysicalSphere.cpp @@ -4,12 +4,13 @@ * @licence: MIT */ + +#include +#include + #include #include -#include "OvCore/ECS/Components/CPhysicalSphere.h" -#include "OvCore/ECS/Actor.h" - using namespace OvPhysics::Entities; OvCore::ECS::Components::CPhysicalSphere::CPhysicalSphere(ECS::Actor & p_owner) : @@ -28,6 +29,11 @@ std::string OvCore::ECS::Components::CPhysicalSphere::GetName() return "Physical Sphere"; } +std::string OvCore::ECS::Components::CPhysicalSphere::GetTypeName() +{ + return std::string{ComponentTraits::Name}; +} + void OvCore::ECS::Components::CPhysicalSphere::SetRadius(float p_radius) { GetPhysicalObjectAs().SetRadius(p_radius); diff --git a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CPointLight.cpp b/Sources/OvCore/src/OvCore/ECS/Components/CPointLight.cpp similarity index 94% rename from Sources/Overload/OvCore/src/OvCore/ECS/Components/CPointLight.cpp rename to Sources/OvCore/src/OvCore/ECS/Components/CPointLight.cpp index 1b8ecd93f..6c04c6610 100644 --- a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CPointLight.cpp +++ b/Sources/OvCore/src/OvCore/ECS/Components/CPointLight.cpp @@ -4,16 +4,15 @@ * @licence: MIT */ +#include +#include + #include #include #include #include #include -#include "OvCore/ECS/Actor.h" - -#include "OvCore/ECS/Components/CPointLight.h" - OvCore::ECS::Components::CPointLight::CPointLight(ECS::Actor& p_owner) : CLight(p_owner) { @@ -25,6 +24,11 @@ std::string OvCore::ECS::Components::CPointLight::GetName() return "Point Light"; } +std::string OvCore::ECS::Components::CPointLight::GetTypeName() +{ + return std::string{ComponentTraits::Name}; +} + float OvCore::ECS::Components::CPointLight::GetConstant() const { return m_data.constant; diff --git a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CPostProcessStack.cpp b/Sources/OvCore/src/OvCore/ECS/Components/CPostProcessStack.cpp similarity index 98% rename from Sources/Overload/OvCore/src/OvCore/ECS/Components/CPostProcessStack.cpp rename to Sources/OvCore/src/OvCore/ECS/Components/CPostProcessStack.cpp index 4add93895..56046b5b4 100644 --- a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CPostProcessStack.cpp +++ b/Sources/OvCore/src/OvCore/ECS/Components/CPostProcessStack.cpp @@ -18,6 +18,11 @@ std::string OvCore::ECS::Components::CPostProcessStack::GetName() return "Post Process Stack"; } +std::string OvCore::ECS::Components::CPostProcessStack::GetTypeName() +{ + return std::string{ComponentTraits::Name}; +} + void OvCore::ECS::Components::CPostProcessStack::OnSerialize(tinyxml2::XMLDocument& p_doc, tinyxml2::XMLNode* p_node) { auto& bloomSettings = m_settings.Get(); diff --git a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CReflectionProbe.cpp b/Sources/OvCore/src/OvCore/ECS/Components/CReflectionProbe.cpp similarity index 99% rename from Sources/Overload/OvCore/src/OvCore/ECS/Components/CReflectionProbe.cpp rename to Sources/OvCore/src/OvCore/ECS/Components/CReflectionProbe.cpp index d3c885a46..813794cc6 100644 --- a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CReflectionProbe.cpp +++ b/Sources/OvCore/src/OvCore/ECS/Components/CReflectionProbe.cpp @@ -9,8 +9,11 @@ #include #include + #include + #include + #include #include #include @@ -52,6 +55,11 @@ std::string OvCore::ECS::Components::CReflectionProbe::GetName() return "Reflection Probe"; } +std::string OvCore::ECS::Components::CReflectionProbe::GetTypeName() +{ + return std::string{ComponentTraits::Name}; +} + void OvCore::ECS::Components::CReflectionProbe::SetRefreshMode(ERefreshMode p_mode) { if (p_mode != m_refreshMode) diff --git a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CSpotLight.cpp b/Sources/OvCore/src/OvCore/ECS/Components/CSpotLight.cpp similarity index 95% rename from Sources/Overload/OvCore/src/OvCore/ECS/Components/CSpotLight.cpp rename to Sources/OvCore/src/OvCore/ECS/Components/CSpotLight.cpp index 359b69e96..4ea1dd783 100644 --- a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CSpotLight.cpp +++ b/Sources/OvCore/src/OvCore/ECS/Components/CSpotLight.cpp @@ -4,15 +4,14 @@ * @licence: MIT */ -#include -#include -#include +#include +#include + #include +#include #include - -#include "OvCore/ECS/Actor.h" - -#include "OvCore/ECS/Components/CSpotLight.h" +#include +#include OvCore::ECS::Components::CSpotLight::CSpotLight(ECS::Actor & p_owner) : CLight(p_owner) @@ -25,6 +24,11 @@ std::string OvCore::ECS::Components::CSpotLight::GetName() return "Spot Light"; } +std::string OvCore::ECS::Components::CSpotLight::GetTypeName() +{ + return std::string{ComponentTraits::Name}; +} + float OvCore::ECS::Components::CSpotLight::GetConstant() const { return m_data.constant; diff --git a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CTransform.cpp b/Sources/OvCore/src/OvCore/ECS/Components/CTransform.cpp similarity index 96% rename from Sources/Overload/OvCore/src/OvCore/ECS/Components/CTransform.cpp rename to Sources/OvCore/src/OvCore/ECS/Components/CTransform.cpp index b37d1c826..79ddff68b 100644 --- a/Sources/Overload/OvCore/src/OvCore/ECS/Components/CTransform.cpp +++ b/Sources/OvCore/src/OvCore/ECS/Components/CTransform.cpp @@ -4,7 +4,7 @@ * @licence: MIT */ -#include "OvCore/ECS/Components/CTransform.h" +#include OvCore::ECS::Components::CTransform::CTransform(ECS::Actor& p_owner, OvMaths::FVector3 p_localPosition, OvMaths::FQuaternion p_localRotation, OvMaths::FVector3 p_localScale) : AComponent(p_owner) @@ -17,6 +17,11 @@ std::string OvCore::ECS::Components::CTransform::GetName() return "Transform"; } +std::string OvCore::ECS::Components::CTransform::GetTypeName() +{ + return std::string{ComponentTraits::Name}; +} + void OvCore::ECS::Components::CTransform::SetParent(CTransform& p_parent) { m_transform.SetParent(p_parent.GetFTransform()); diff --git a/Sources/Overload/OvCore/src/OvCore/ECS/PhysicsWrapper.cpp b/Sources/OvCore/src/OvCore/ECS/PhysicsWrapper.cpp similarity index 100% rename from Sources/Overload/OvCore/src/OvCore/ECS/PhysicsWrapper.cpp rename to Sources/OvCore/src/OvCore/ECS/PhysicsWrapper.cpp diff --git a/Sources/Overload/OvCore/src/OvCore/Global/ServiceLocator.cpp b/Sources/OvCore/src/OvCore/Global/ServiceLocator.cpp similarity index 100% rename from Sources/Overload/OvCore/src/OvCore/Global/ServiceLocator.cpp rename to Sources/OvCore/src/OvCore/Global/ServiceLocator.cpp diff --git a/Sources/Overload/OvCore/src/OvCore/Helpers/GUIDrawer.cpp b/Sources/OvCore/src/OvCore/Helpers/GUIDrawer.cpp similarity index 100% rename from Sources/Overload/OvCore/src/OvCore/Helpers/GUIDrawer.cpp rename to Sources/OvCore/src/OvCore/Helpers/GUIDrawer.cpp diff --git a/Sources/Overload/OvCore/src/OvCore/Helpers/Serializer.cpp b/Sources/OvCore/src/OvCore/Helpers/Serializer.cpp similarity index 100% rename from Sources/Overload/OvCore/src/OvCore/Helpers/Serializer.cpp rename to Sources/OvCore/src/OvCore/Helpers/Serializer.cpp diff --git a/Sources/Overload/OvCore/src/OvCore/Rendering/EngineBufferRenderFeature.cpp b/Sources/OvCore/src/OvCore/Rendering/EngineBufferRenderFeature.cpp similarity index 100% rename from Sources/Overload/OvCore/src/OvCore/Rendering/EngineBufferRenderFeature.cpp rename to Sources/OvCore/src/OvCore/Rendering/EngineBufferRenderFeature.cpp diff --git a/Sources/Overload/OvCore/src/OvCore/Rendering/FramebufferUtil.cpp b/Sources/OvCore/src/OvCore/Rendering/FramebufferUtil.cpp similarity index 100% rename from Sources/Overload/OvCore/src/OvCore/Rendering/FramebufferUtil.cpp rename to Sources/OvCore/src/OvCore/Rendering/FramebufferUtil.cpp diff --git a/Sources/Overload/OvCore/src/OvCore/Rendering/PingPongFramebuffer.cpp b/Sources/OvCore/src/OvCore/Rendering/PingPongFramebuffer.cpp similarity index 100% rename from Sources/Overload/OvCore/src/OvCore/Rendering/PingPongFramebuffer.cpp rename to Sources/OvCore/src/OvCore/Rendering/PingPongFramebuffer.cpp diff --git a/Sources/Overload/OvCore/src/OvCore/Rendering/PostProcess/APostProcessEffect.cpp b/Sources/OvCore/src/OvCore/Rendering/PostProcess/APostProcessEffect.cpp similarity index 100% rename from Sources/Overload/OvCore/src/OvCore/Rendering/PostProcess/APostProcessEffect.cpp rename to Sources/OvCore/src/OvCore/Rendering/PostProcess/APostProcessEffect.cpp diff --git a/Sources/Overload/OvCore/src/OvCore/Rendering/PostProcess/AutoExposureEffect.cpp b/Sources/OvCore/src/OvCore/Rendering/PostProcess/AutoExposureEffect.cpp similarity index 100% rename from Sources/Overload/OvCore/src/OvCore/Rendering/PostProcess/AutoExposureEffect.cpp rename to Sources/OvCore/src/OvCore/Rendering/PostProcess/AutoExposureEffect.cpp diff --git a/Sources/Overload/OvCore/src/OvCore/Rendering/PostProcess/BloomEffect.cpp b/Sources/OvCore/src/OvCore/Rendering/PostProcess/BloomEffect.cpp similarity index 99% rename from Sources/Overload/OvCore/src/OvCore/Rendering/PostProcess/BloomEffect.cpp rename to Sources/OvCore/src/OvCore/Rendering/PostProcess/BloomEffect.cpp index 5b8dbcf9c..c4f5f22d2 100644 --- a/Sources/Overload/OvCore/src/OvCore/Rendering/PostProcess/BloomEffect.cpp +++ b/Sources/OvCore/src/OvCore/Rendering/PostProcess/BloomEffect.cpp @@ -4,6 +4,8 @@ * @licence: MIT */ +#include + #include #include #include diff --git a/Sources/Overload/OvCore/src/OvCore/Rendering/PostProcess/FXAAEffect.cpp b/Sources/OvCore/src/OvCore/Rendering/PostProcess/FXAAEffect.cpp similarity index 100% rename from Sources/Overload/OvCore/src/OvCore/Rendering/PostProcess/FXAAEffect.cpp rename to Sources/OvCore/src/OvCore/Rendering/PostProcess/FXAAEffect.cpp diff --git a/Sources/Overload/OvCore/src/OvCore/Rendering/PostProcess/PostProcessStack.cpp b/Sources/OvCore/src/OvCore/Rendering/PostProcess/PostProcessStack.cpp similarity index 100% rename from Sources/Overload/OvCore/src/OvCore/Rendering/PostProcess/PostProcessStack.cpp rename to Sources/OvCore/src/OvCore/Rendering/PostProcess/PostProcessStack.cpp diff --git a/Sources/Overload/OvCore/src/OvCore/Rendering/PostProcess/TonemappingEffect.cpp b/Sources/OvCore/src/OvCore/Rendering/PostProcess/TonemappingEffect.cpp similarity index 100% rename from Sources/Overload/OvCore/src/OvCore/Rendering/PostProcess/TonemappingEffect.cpp rename to Sources/OvCore/src/OvCore/Rendering/PostProcess/TonemappingEffect.cpp diff --git a/Sources/Overload/OvCore/src/OvCore/Rendering/PostProcessRenderPass.cpp b/Sources/OvCore/src/OvCore/Rendering/PostProcessRenderPass.cpp similarity index 100% rename from Sources/Overload/OvCore/src/OvCore/Rendering/PostProcessRenderPass.cpp rename to Sources/OvCore/src/OvCore/Rendering/PostProcessRenderPass.cpp diff --git a/Sources/Overload/OvCore/src/OvCore/Rendering/ReflectionRenderFeature.cpp b/Sources/OvCore/src/OvCore/Rendering/ReflectionRenderFeature.cpp similarity index 100% rename from Sources/Overload/OvCore/src/OvCore/Rendering/ReflectionRenderFeature.cpp rename to Sources/OvCore/src/OvCore/Rendering/ReflectionRenderFeature.cpp diff --git a/Sources/Overload/OvCore/src/OvCore/Rendering/ReflectionRenderPass.cpp b/Sources/OvCore/src/OvCore/Rendering/ReflectionRenderPass.cpp similarity index 100% rename from Sources/Overload/OvCore/src/OvCore/Rendering/ReflectionRenderPass.cpp rename to Sources/OvCore/src/OvCore/Rendering/ReflectionRenderPass.cpp diff --git a/Sources/Overload/OvCore/src/OvCore/Rendering/SceneRenderer.cpp b/Sources/OvCore/src/OvCore/Rendering/SceneRenderer.cpp similarity index 100% rename from Sources/Overload/OvCore/src/OvCore/Rendering/SceneRenderer.cpp rename to Sources/OvCore/src/OvCore/Rendering/SceneRenderer.cpp diff --git a/Sources/Overload/OvCore/src/OvCore/Rendering/ShadowRenderFeature.cpp b/Sources/OvCore/src/OvCore/Rendering/ShadowRenderFeature.cpp similarity index 100% rename from Sources/Overload/OvCore/src/OvCore/Rendering/ShadowRenderFeature.cpp rename to Sources/OvCore/src/OvCore/Rendering/ShadowRenderFeature.cpp diff --git a/Sources/Overload/OvCore/src/OvCore/Rendering/ShadowRenderPass.cpp b/Sources/OvCore/src/OvCore/Rendering/ShadowRenderPass.cpp similarity index 100% rename from Sources/Overload/OvCore/src/OvCore/Rendering/ShadowRenderPass.cpp rename to Sources/OvCore/src/OvCore/Rendering/ShadowRenderPass.cpp diff --git a/Sources/Overload/OvCore/src/OvCore/ResourceManagement/MaterialManager.cpp b/Sources/OvCore/src/OvCore/ResourceManagement/MaterialManager.cpp similarity index 66% rename from Sources/Overload/OvCore/src/OvCore/ResourceManagement/MaterialManager.cpp rename to Sources/OvCore/src/OvCore/ResourceManagement/MaterialManager.cpp index 9bfe60b71..3f810a215 100644 --- a/Sources/Overload/OvCore/src/OvCore/ResourceManagement/MaterialManager.cpp +++ b/Sources/OvCore/src/OvCore/ResourceManagement/MaterialManager.cpp @@ -6,14 +6,14 @@ #include "OvCore/ResourceManagement/MaterialManager.h" -OvCore::Resources::Material * OvCore::ResourceManagement::MaterialManager::CreateResource(const std::string & p_path) +OvCore::Resources::Material * OvCore::ResourceManagement::MaterialManager::CreateResource(const std::filesystem::path & p_path) { - std::string realPath = GetRealPath(p_path); + std::string realPath = GetRealPath(p_path).string(); Resources::Material* material = OvCore::Resources::Loaders::MaterialLoader::Create(realPath); if (material) { - *reinterpret_cast(reinterpret_cast(material) + offsetof(Resources::Material, path)) = p_path; // Force the resource path to fit the given path + *reinterpret_cast(reinterpret_cast(material) + offsetof(Resources::Material, path)) = p_path.string(); // Force the resource path to fit the given path } return material; @@ -24,8 +24,8 @@ void OvCore::ResourceManagement::MaterialManager::DestroyResource(OvCore::Resour OvCore::Resources::Loaders::MaterialLoader::Destroy(p_resource); } -void OvCore::ResourceManagement::MaterialManager::ReloadResource(OvCore::Resources::Material* p_resource, const std::string& p_path) +void OvCore::ResourceManagement::MaterialManager::ReloadResource(OvCore::Resources::Material* p_resource, const std::filesystem::path& p_path) { - std::string realPath = GetRealPath(p_path); + std::string realPath = GetRealPath(p_path).string(); OvCore::Resources::Loaders::MaterialLoader::Reload(*p_resource, realPath); } diff --git a/Sources/Overload/OvCore/src/OvCore/ResourceManagement/ModelManager.cpp b/Sources/OvCore/src/OvCore/ResourceManagement/ModelManager.cpp similarity index 93% rename from Sources/Overload/OvCore/src/OvCore/ResourceManagement/ModelManager.cpp rename to Sources/OvCore/src/OvCore/ResourceManagement/ModelManager.cpp index d656275fd..fc6851df8 100644 --- a/Sources/Overload/OvCore/src/OvCore/ResourceManagement/ModelManager.cpp +++ b/Sources/OvCore/src/OvCore/ResourceManagement/ModelManager.cpp @@ -49,12 +49,12 @@ OvRendering::Resources::Parsers::EModelParserFlags GetAssetMetadata(const std::s return { flags }; } -OvRendering::Resources::Model* OvCore::ResourceManagement::ModelManager::CreateResource(const std::string& p_path) +OvRendering::Resources::Model* OvCore::ResourceManagement::ModelManager::CreateResource(const std::filesystem::path& p_path) { - std::string realPath = GetRealPath(p_path); + std::string realPath = GetRealPath(p_path).string(); auto model = OvRendering::Resources::Loaders::ModelLoader::Create(realPath, GetAssetMetadata(realPath)); if (model) - *reinterpret_cast(reinterpret_cast(model) + offsetof(OvRendering::Resources::Model, path)) = p_path; // Force the resource path to fit the given path + *reinterpret_cast(reinterpret_cast(model) + offsetof(OvRendering::Resources::Model, path)) = p_path.string(); // Force the resource path to fit the given path return model; } @@ -64,8 +64,8 @@ void OvCore::ResourceManagement::ModelManager::DestroyResource(OvRendering::Reso OvRendering::Resources::Loaders::ModelLoader::Destroy(p_resource); } -void OvCore::ResourceManagement::ModelManager::ReloadResource(OvRendering::Resources::Model* p_resource, const std::string& p_path) +void OvCore::ResourceManagement::ModelManager::ReloadResource(OvRendering::Resources::Model* p_resource, const std::filesystem::path& p_path) { - std::string realPath = GetRealPath(p_path); + std::string realPath = GetRealPath(p_path).string(); OvRendering::Resources::Loaders::ModelLoader::Reload(*p_resource, realPath, GetAssetMetadata(realPath)); } diff --git a/Sources/Overload/OvCore/src/OvCore/ResourceManagement/ShaderManager.cpp b/Sources/OvCore/src/OvCore/ResourceManagement/ShaderManager.cpp similarity index 55% rename from Sources/Overload/OvCore/src/OvCore/ResourceManagement/ShaderManager.cpp rename to Sources/OvCore/src/OvCore/ResourceManagement/ShaderManager.cpp index 546610a3b..79959433c 100644 --- a/Sources/Overload/OvCore/src/OvCore/ResourceManagement/ShaderManager.cpp +++ b/Sources/OvCore/src/OvCore/ResourceManagement/ShaderManager.cpp @@ -6,13 +6,13 @@ #include "OvCore/ResourceManagement/ShaderManager.h" -OvRendering::Resources::Shader* OvCore::ResourceManagement::ShaderManager::CreateResource(const std::string & p_path) +OvRendering::Resources::Shader* OvCore::ResourceManagement::ShaderManager::CreateResource(const std::filesystem::path & p_path) { - std::string realPath = GetRealPath(p_path); - auto pathParserCallback = std::bind(&OvCore::ResourceManagement::ShaderManager::GetRealPath, this, std::placeholders::_1); + std::string realPath = GetRealPath(p_path).string(); + auto pathParserCallback = [this](const std::string& s) { return GetRealPath(std::filesystem::path{s}).string(); }; OvRendering::Resources::Shader* shader = OvRendering::Resources::Loaders::ShaderLoader::Create(realPath, pathParserCallback); if (shader) - *reinterpret_cast(reinterpret_cast(shader) + offsetof(OvRendering::Resources::Shader, path)) = p_path; // Force the resource path to fit the given path + *reinterpret_cast(reinterpret_cast(shader) + offsetof(OvRendering::Resources::Shader, path)) = p_path.string(); // Force the resource path to fit the given path return shader; } @@ -22,8 +22,8 @@ void OvCore::ResourceManagement::ShaderManager::DestroyResource(OvRendering::Res OvRendering::Resources::Loaders::ShaderLoader::Destroy(p_resource); } -void OvCore::ResourceManagement::ShaderManager::ReloadResource(OvRendering::Resources::Shader* p_resource, const std::string& p_path) +void OvCore::ResourceManagement::ShaderManager::ReloadResource(OvRendering::Resources::Shader* p_resource, const std::filesystem::path& p_path) { - auto pathParserCallback = std::bind(&OvCore::ResourceManagement::ShaderManager::GetRealPath, this, std::placeholders::_1); - OvRendering::Resources::Loaders::ShaderLoader::Recompile(*p_resource, p_path, pathParserCallback); + auto pathParserCallback = [this](const std::string& s) { return GetRealPath(std::filesystem::path{s}).string(); }; + OvRendering::Resources::Loaders::ShaderLoader::Recompile(*p_resource, p_path.string(), pathParserCallback); } diff --git a/Sources/Overload/OvCore/src/OvCore/ResourceManagement/SoundManager.cpp b/Sources/OvCore/src/OvCore/ResourceManagement/SoundManager.cpp similarity index 67% rename from Sources/Overload/OvCore/src/OvCore/ResourceManagement/SoundManager.cpp rename to Sources/OvCore/src/OvCore/ResourceManagement/SoundManager.cpp index fc14380e7..2a53b6e3c 100644 --- a/Sources/Overload/OvCore/src/OvCore/ResourceManagement/SoundManager.cpp +++ b/Sources/OvCore/src/OvCore/ResourceManagement/SoundManager.cpp @@ -6,12 +6,12 @@ #include "OvCore/ResourceManagement/SoundManager.h" -OvAudio::Resources::Sound* OvCore::ResourceManagement::SoundManager::CreateResource(const std::string& p_path) +OvAudio::Resources::Sound* OvCore::ResourceManagement::SoundManager::CreateResource(const std::filesystem::path& p_path) { - std::string realPath = GetRealPath(p_path); + std::string realPath = GetRealPath(p_path).string(); OvAudio::Resources::Sound* sound = OvAudio::Resources::Loaders::SoundLoader::Create(realPath); if (sound) - *reinterpret_cast(reinterpret_cast(sound) + offsetof(OvAudio::Resources::Sound, path)) = p_path; // Force the resource path to fit the given path + *reinterpret_cast(reinterpret_cast(sound) + offsetof(OvAudio::Resources::Sound, path)) = p_path.string(); // Force the resource path to fit the given path return sound; } @@ -21,6 +21,6 @@ void OvCore::ResourceManagement::SoundManager::DestroyResource(OvAudio::Resource OvAudio::Resources::Loaders::SoundLoader::Destroy(p_resource); } -void OvCore::ResourceManagement::SoundManager::ReloadResource(OvAudio::Resources::Sound* p_resource, const std::string& p_path) +void OvCore::ResourceManagement::SoundManager::ReloadResource(OvAudio::Resources::Sound* p_resource, const std::filesystem::path& p_path) { } diff --git a/Sources/Overload/OvCore/src/OvCore/ResourceManagement/TextureManager.cpp b/Sources/OvCore/src/OvCore/ResourceManagement/TextureManager.cpp similarity index 86% rename from Sources/Overload/OvCore/src/OvCore/ResourceManagement/TextureManager.cpp rename to Sources/OvCore/src/OvCore/ResourceManagement/TextureManager.cpp index 48c6fed40..c3c088b42 100644 --- a/Sources/Overload/OvCore/src/OvCore/ResourceManagement/TextureManager.cpp +++ b/Sources/OvCore/src/OvCore/ResourceManagement/TextureManager.cpp @@ -40,9 +40,9 @@ namespace } } -OvRendering::Resources::Texture* OvCore::ResourceManagement::TextureManager::CreateResource(const std::string & p_path) +OvRendering::Resources::Texture* OvCore::ResourceManagement::TextureManager::CreateResource(const std::filesystem::path & p_path) { - std::string realPath = GetRealPath(p_path); + std::string realPath = GetRealPath(p_path).string(); const auto metaData = LoadTextureMetadata(realPath); @@ -56,7 +56,7 @@ OvRendering::Resources::Texture* OvCore::ResourceManagement::TextureManager::Cre ); if (texture) - *reinterpret_cast(reinterpret_cast(texture) + offsetof(OvRendering::Resources::Texture, path)) = p_path; // Force the resource path to fit the given path + *reinterpret_cast(reinterpret_cast(texture) + offsetof(OvRendering::Resources::Texture, path)) = p_path.string(); // Force the resource path to fit the given path return texture; } @@ -66,9 +66,9 @@ void OvCore::ResourceManagement::TextureManager::DestroyResource(OvRendering::Re OvRendering::Resources::Loaders::TextureLoader::Destroy(p_resource); } -void OvCore::ResourceManagement::TextureManager::ReloadResource(OvRendering::Resources::Texture* p_resource, const std::string& p_path) +void OvCore::ResourceManagement::TextureManager::ReloadResource(OvRendering::Resources::Texture* p_resource, const std::filesystem::path& p_path) { - std::string realPath = GetRealPath(p_path); + std::string realPath = GetRealPath(p_path).string(); const auto metaData = LoadTextureMetadata(realPath); diff --git a/Sources/Overload/OvCore/src/OvCore/Resources/Loaders/MaterialLoader.cpp b/Sources/OvCore/src/OvCore/Resources/Loaders/MaterialLoader.cpp similarity index 100% rename from Sources/Overload/OvCore/src/OvCore/Resources/Loaders/MaterialLoader.cpp rename to Sources/OvCore/src/OvCore/Resources/Loaders/MaterialLoader.cpp diff --git a/Sources/Overload/OvCore/src/OvCore/Resources/Material.cpp b/Sources/OvCore/src/OvCore/Resources/Material.cpp similarity index 100% rename from Sources/Overload/OvCore/src/OvCore/Resources/Material.cpp rename to Sources/OvCore/src/OvCore/Resources/Material.cpp diff --git a/Sources/Overload/OvCore/src/OvCore/SceneSystem/Scene.cpp b/Sources/OvCore/src/OvCore/SceneSystem/Scene.cpp similarity index 100% rename from Sources/Overload/OvCore/src/OvCore/SceneSystem/Scene.cpp rename to Sources/OvCore/src/OvCore/SceneSystem/Scene.cpp diff --git a/Sources/Overload/OvCore/src/OvCore/SceneSystem/SceneManager.cpp b/Sources/OvCore/src/OvCore/SceneSystem/SceneManager.cpp similarity index 100% rename from Sources/Overload/OvCore/src/OvCore/SceneSystem/SceneManager.cpp rename to Sources/OvCore/src/OvCore/SceneSystem/SceneManager.cpp diff --git a/Sources/Overload/OvCore/src/OvCore/Scripting/Lua/Bindings/LuaActorBindings.cpp b/Sources/OvCore/src/OvCore/Scripting/Lua/Bindings/LuaActorBindings.cpp similarity index 100% rename from Sources/Overload/OvCore/src/OvCore/Scripting/Lua/Bindings/LuaActorBindings.cpp rename to Sources/OvCore/src/OvCore/Scripting/Lua/Bindings/LuaActorBindings.cpp diff --git a/Sources/Overload/OvCore/src/OvCore/Scripting/Lua/Bindings/LuaComponentsBindings.cpp b/Sources/OvCore/src/OvCore/Scripting/Lua/Bindings/LuaComponentsBindings.cpp similarity index 100% rename from Sources/Overload/OvCore/src/OvCore/Scripting/Lua/Bindings/LuaComponentsBindings.cpp rename to Sources/OvCore/src/OvCore/Scripting/Lua/Bindings/LuaComponentsBindings.cpp diff --git a/Sources/Overload/OvCore/src/OvCore/Scripting/Lua/Bindings/LuaGlobalBindings.cpp b/Sources/OvCore/src/OvCore/Scripting/Lua/Bindings/LuaGlobalBindings.cpp similarity index 99% rename from Sources/Overload/OvCore/src/OvCore/Scripting/Lua/Bindings/LuaGlobalBindings.cpp rename to Sources/OvCore/src/OvCore/Scripting/Lua/Bindings/LuaGlobalBindings.cpp index 32f877714..89dffa033 100644 --- a/Sources/Overload/OvCore/src/OvCore/Scripting/Lua/Bindings/LuaGlobalBindings.cpp +++ b/Sources/OvCore/src/OvCore/Scripting/Lua/Bindings/LuaGlobalBindings.cpp @@ -4,6 +4,8 @@ * @licence: MIT */ +#include + #include #include diff --git a/Sources/Overload/OvCore/src/OvCore/Scripting/Lua/Bindings/LuaMathBindings.cpp b/Sources/OvCore/src/OvCore/Scripting/Lua/Bindings/LuaMathBindings.cpp similarity index 100% rename from Sources/Overload/OvCore/src/OvCore/Scripting/Lua/Bindings/LuaMathBindings.cpp rename to Sources/OvCore/src/OvCore/Scripting/Lua/Bindings/LuaMathBindings.cpp diff --git a/Sources/Overload/OvCore/src/OvCore/Scripting/Lua/Bindings/LuaProfilerBindings.cpp b/Sources/OvCore/src/OvCore/Scripting/Lua/Bindings/LuaProfilerBindings.cpp similarity index 100% rename from Sources/Overload/OvCore/src/OvCore/Scripting/Lua/Bindings/LuaProfilerBindings.cpp rename to Sources/OvCore/src/OvCore/Scripting/Lua/Bindings/LuaProfilerBindings.cpp diff --git a/Sources/Overload/OvCore/src/OvCore/Scripting/Lua/LuaScript.cpp b/Sources/OvCore/src/OvCore/Scripting/Lua/LuaScript.cpp similarity index 100% rename from Sources/Overload/OvCore/src/OvCore/Scripting/Lua/LuaScript.cpp rename to Sources/OvCore/src/OvCore/Scripting/Lua/LuaScript.cpp diff --git a/Sources/Overload/OvCore/src/OvCore/Scripting/Lua/LuaScriptEngine.cpp b/Sources/OvCore/src/OvCore/Scripting/Lua/LuaScriptEngine.cpp similarity index 100% rename from Sources/Overload/OvCore/src/OvCore/Scripting/Lua/LuaScriptEngine.cpp rename to Sources/OvCore/src/OvCore/Scripting/Lua/LuaScriptEngine.cpp index 56422d47f..1de5422dc 100644 --- a/Sources/Overload/OvCore/src/OvCore/Scripting/Lua/LuaScriptEngine.cpp +++ b/Sources/OvCore/src/OvCore/Scripting/Lua/LuaScriptEngine.cpp @@ -93,62 +93,6 @@ bool RegisterBehaviour(sol::state& p_luaState, OvCore::ECS::Components::Behaviou return false; } -OvCore::Scripting::LuaScriptEngine::LuaScriptEngine() -{ - CreateContext(); -} - -OvCore::Scripting::LuaScriptEngine::~LuaScriptEngine() -{ - DestroyContext(); -} - -void OvCore::Scripting::LuaScriptEngine::CreateContext() -{ - OVASSERT(m_context.luaState == nullptr, "A Lua context already exists!"); - - m_context.luaState = std::make_unique(); - m_context.luaState->open_libraries(sol::lib::base, sol::lib::math); - - for (auto& callback : luaBindings) - { - callback(*m_context.luaState); - } - - m_context.errorCount = 0; - - std::for_each(m_context.behaviours.begin(), m_context.behaviours.end(), - [this](std::reference_wrapper behaviour) { - const auto scriptFileName = behaviour.get().name + GetDefaultExtension(); - const auto scriptPath = m_context.scriptRootFolder / scriptFileName; - if (!RegisterBehaviour(*m_context.luaState, behaviour.get(), scriptPath.string())) - { - ++m_context.errorCount; - } - } - ); - - if (m_context.errorCount > 0) - { - const std::string message = std::to_string(m_context.errorCount) + " script(s) failed to register"; - OVLOG_ERROR(message); - } -} - -void OvCore::Scripting::LuaScriptEngine::DestroyContext() -{ - OVASSERT(m_context.luaState != nullptr, "No valid Lua context"); - - std::for_each(m_context.behaviours.begin(), m_context.behaviours.end(), - [this](std::reference_wrapper behaviour) - { - behaviour.get().RemoveScript(); - } - ); - - m_context.luaState.reset(); -} - template<> OvCore::Scripting::LuaScriptEngineBase::TScriptEngine() {} @@ -162,21 +106,21 @@ void OvCore::Scripting::LuaScriptEngineBase::SetScriptRootFolder(const std::file } template<> -std::vector OvCore::Scripting::LuaScriptEngineBase::GetValidExtensions() +std::string OvCore::Scripting::LuaScriptEngineBase::GetDefaultExtension() { - return { GetDefaultExtension() }; + return ".lua"; } template<> -std::string OvCore::Scripting::LuaScriptEngineBase::GetDefaultScriptContent(const std::string& p_name) +std::vector OvCore::Scripting::LuaScriptEngineBase::GetValidExtensions() { - return "local " + p_name + " =\n{\n}\n\nfunction " + p_name + ":OnStart()\nend\n\nfunction " + p_name + ":OnUpdate(deltaTime)\nend\n\nreturn " + p_name; + return { GetDefaultExtension() }; } template<> -std::string OvCore::Scripting::LuaScriptEngineBase::GetDefaultExtension() +std::string OvCore::Scripting::LuaScriptEngineBase::GetDefaultScriptContent(const std::string& p_name) { - return ".lua"; + return "local " + p_name + " =\n{\n}\n\nfunction " + p_name + ":OnStart()\nend\n\nfunction " + p_name + ":OnUpdate(deltaTime)\nend\n\nreturn " + p_name; } template<> @@ -195,6 +139,13 @@ void OvCore::Scripting::LuaScriptEngineBase::AddBehaviour(OvCore::ECS::Component } } +template<> +void OvCore::Scripting::LuaScriptEngineBase::Reload() +{ + static_cast(*this).DestroyContext(); + static_cast(*this).CreateContext(); +} + template<> void OvCore::Scripting::LuaScriptEngineBase::RemoveBehaviour(OvCore::ECS::Components::Behaviour& p_toRemove) { @@ -216,13 +167,6 @@ void OvCore::Scripting::LuaScriptEngineBase::RemoveBehaviour(OvCore::ECS::Compon Reload(); } -template<> -void OvCore::Scripting::LuaScriptEngineBase::Reload() -{ - static_cast(*this).DestroyContext(); - static_cast(*this).CreateContext(); -} - template<> bool OvCore::Scripting::LuaScriptEngineBase::IsOk() const { @@ -312,3 +256,59 @@ void OvCore::Scripting::LuaScriptEngineBase::OnTriggerExit(OvCore::ECS::Componen { ExecuteLuaFunction(p_target, "OnTriggerExit", p_otherObject); } + +OvCore::Scripting::LuaScriptEngine::LuaScriptEngine() +{ + CreateContext(); +} + +OvCore::Scripting::LuaScriptEngine::~LuaScriptEngine() +{ + DestroyContext(); +} + +void OvCore::Scripting::LuaScriptEngine::CreateContext() +{ + OVASSERT(m_context.luaState == nullptr, "A Lua context already exists!"); + + m_context.luaState = std::make_unique(); + m_context.luaState->open_libraries(sol::lib::base, sol::lib::math); + + for (auto& callback : luaBindings) + { + callback(*m_context.luaState); + } + + m_context.errorCount = 0; + + std::for_each(m_context.behaviours.begin(), m_context.behaviours.end(), + [this](std::reference_wrapper behaviour) { + const auto scriptFileName = behaviour.get().name + GetDefaultExtension(); + const auto scriptPath = m_context.scriptRootFolder / scriptFileName; + if (!RegisterBehaviour(*m_context.luaState, behaviour.get(), scriptPath.string())) + { + ++m_context.errorCount; + } + } + ); + + if (m_context.errorCount > 0) + { + const std::string message = std::to_string(m_context.errorCount) + " script(s) failed to register"; + OVLOG_ERROR(message); + } +} + +void OvCore::Scripting::LuaScriptEngine::DestroyContext() +{ + OVASSERT(m_context.luaState != nullptr, "No valid Lua context"); + + std::for_each(m_context.behaviours.begin(), m_context.behaviours.end(), + [this](std::reference_wrapper behaviour) + { + behaviour.get().RemoveScript(); + } + ); + + m_context.luaState.reset(); +} diff --git a/Sources/Overload/OvCore/src/OvCore/Scripting/Null/NullScript.cpp b/Sources/OvCore/src/OvCore/Scripting/Null/NullScript.cpp similarity index 100% rename from Sources/Overload/OvCore/src/OvCore/Scripting/Null/NullScript.cpp rename to Sources/OvCore/src/OvCore/Scripting/Null/NullScript.cpp diff --git a/Sources/Overload/OvCore/src/OvCore/Scripting/Null/NullScriptEngine.cpp b/Sources/OvCore/src/OvCore/Scripting/Null/NullScriptEngine.cpp similarity index 100% rename from Sources/Overload/OvCore/src/OvCore/Scripting/Null/NullScriptEngine.cpp rename to Sources/OvCore/src/OvCore/Scripting/Null/NullScriptEngine.cpp index 16f741a49..7e461874b 100644 --- a/Sources/Overload/OvCore/src/OvCore/Scripting/Null/NullScriptEngine.cpp +++ b/Sources/OvCore/src/OvCore/Scripting/Null/NullScriptEngine.cpp @@ -18,21 +18,21 @@ template<> void OvCore::Scripting::NullScriptEngineBase::SetScriptRootFolder(const std::filesystem::path& p_scriptRootFolder) {} template<> -std::vector OvCore::Scripting::NullScriptEngineBase::GetValidExtensions() +std::string OvCore::Scripting::NullScriptEngineBase::GetDefaultExtension() { - return { GetDefaultExtension() }; + return ".ovscript"; } template<> -std::string OvCore::Scripting::NullScriptEngineBase::GetDefaultScriptContent(const std::string& p_name) +std::vector OvCore::Scripting::NullScriptEngineBase::GetValidExtensions() { - return "class " + p_name + " {\n}"; + return { GetDefaultExtension() }; } template<> -std::string OvCore::Scripting::NullScriptEngineBase::GetDefaultExtension() +std::string OvCore::Scripting::NullScriptEngineBase::GetDefaultScriptContent(const std::string& p_name) { - return ".ovscript"; + return "class " + p_name + " {\n}"; } template<> diff --git a/Sources/Overload/OvDebug/include/OvDebug/Assertion.h b/Sources/OvDebug/include/OvDebug/Assertion.h similarity index 100% rename from Sources/Overload/OvDebug/include/OvDebug/Assertion.h rename to Sources/OvDebug/include/OvDebug/Assertion.h diff --git a/Sources/Overload/OvDebug/include/OvDebug/ConsoleColor.h b/Sources/OvDebug/include/OvDebug/ConsoleColor.h similarity index 73% rename from Sources/Overload/OvDebug/include/OvDebug/ConsoleColor.h rename to Sources/OvDebug/include/OvDebug/ConsoleColor.h index 1b3f41679..f915b3ae3 100644 --- a/Sources/Overload/OvDebug/include/OvDebug/ConsoleColor.h +++ b/Sources/OvDebug/include/OvDebug/ConsoleColor.h @@ -7,7 +7,10 @@ #pragma once #include + +#ifdef _WIN32 #include +#endif #define COLOR_BLUE OvDebug::blue #define COLOR_RED OvDebug::red @@ -20,56 +23,81 @@ namespace OvDebug { inline std::ostream& blue(std::ostream& s) { +#ifdef _WIN32 HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute(hStdout, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY); +#else + s << "\033[1;36m"; // Cyan (bright blue) +#endif return s; } inline std::ostream& red(std::ostream& s) { +#ifdef _WIN32 HANDLE hStdout = GetStdHandle(STD_ERROR_HANDLE); SetConsoleTextAttribute(hStdout, FOREGROUND_RED | FOREGROUND_INTENSITY); +#else + s << "\033[1;31m"; // Bright red +#endif return s; } inline std::ostream& green(std::ostream& s) { +#ifdef _WIN32 HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute(hStdout, FOREGROUND_GREEN | FOREGROUND_INTENSITY); +#else + s << "\033[1;32m"; // Bright green +#endif return s; } inline std::ostream& yellow(std::ostream& s) { +#ifdef _WIN32 HANDLE hStdout = GetStdHandle(STD_ERROR_HANDLE); SetConsoleTextAttribute(hStdout, FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY); +#else + s << "\033[1;33m"; // Bright yellow +#endif return s; } inline std::ostream& white(std::ostream& s) { +#ifdef _WIN32 HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute(hStdout, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY); +#else + s << "\033[1;37m"; // Bright white +#endif return s; } inline std::ostream& grey(std::ostream& s) { +#ifdef _WIN32 HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute(hStdout, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); +#else + s << "\033[0m"; // Reset to default +#endif return s; } +#ifdef _WIN32 struct color { color(WORD attribute) : m_color(attribute) @@ -87,4 +115,22 @@ namespace OvDebug SetConsoleTextAttribute(hStdout, c.m_color); return i; } +#else + struct color + { + color(const char* ansiCode) : m_color(ansiCode) + { + } + + const char* m_color; + }; + + template + std::basic_ostream<_Elem, _Traits>& + operator<<(std::basic_ostream<_Elem, _Traits>& i, color& c) + { + i << c.m_color; + return i; + } +#endif } \ No newline at end of file diff --git a/Sources/Overload/OvDebug/include/OvDebug/ConsoleHandler.h b/Sources/OvDebug/include/OvDebug/ConsoleHandler.h similarity index 100% rename from Sources/Overload/OvDebug/include/OvDebug/ConsoleHandler.h rename to Sources/OvDebug/include/OvDebug/ConsoleHandler.h diff --git a/Sources/Overload/OvDebug/include/OvDebug/FileHandler.h b/Sources/OvDebug/include/OvDebug/FileHandler.h similarity index 100% rename from Sources/Overload/OvDebug/include/OvDebug/FileHandler.h rename to Sources/OvDebug/include/OvDebug/FileHandler.h diff --git a/Sources/Overload/OvDebug/include/OvDebug/HistoryHandler.h b/Sources/OvDebug/include/OvDebug/HistoryHandler.h similarity index 100% rename from Sources/Overload/OvDebug/include/OvDebug/HistoryHandler.h rename to Sources/OvDebug/include/OvDebug/HistoryHandler.h diff --git a/Sources/Overload/OvDebug/include/OvDebug/ILogHandler.h b/Sources/OvDebug/include/OvDebug/ILogHandler.h similarity index 100% rename from Sources/Overload/OvDebug/include/OvDebug/ILogHandler.h rename to Sources/OvDebug/include/OvDebug/ILogHandler.h diff --git a/Sources/Overload/OvDebug/include/OvDebug/Logger.h b/Sources/OvDebug/include/OvDebug/Logger.h similarity index 100% rename from Sources/Overload/OvDebug/include/OvDebug/Logger.h rename to Sources/OvDebug/include/OvDebug/Logger.h diff --git a/Sources/Overload/OvDebug/include/OvDebug/Logger.inl b/Sources/OvDebug/include/OvDebug/Logger.inl similarity index 100% rename from Sources/Overload/OvDebug/include/OvDebug/Logger.inl rename to Sources/OvDebug/include/OvDebug/Logger.inl diff --git a/Sources/Overload/OvDebug/premake5.lua b/Sources/OvDebug/premake5.lua similarity index 91% rename from Sources/Overload/OvDebug/premake5.lua rename to Sources/OvDebug/premake5.lua index 1d1a6fcb8..083d5b2cb 100644 --- a/Sources/Overload/OvDebug/premake5.lua +++ b/Sources/OvDebug/premake5.lua @@ -15,7 +15,7 @@ project "OvDebug" includedirs { -- Overload SDK - "%{wks.location}/OvTools/include", + "%{wks.location}/Sources/OvTools/include", -- Current Project "include" diff --git a/Sources/Overload/OvDebug/src/OvDebug/Assertion.cpp b/Sources/OvDebug/src/OvDebug/Assertion.cpp similarity index 100% rename from Sources/Overload/OvDebug/src/OvDebug/Assertion.cpp rename to Sources/OvDebug/src/OvDebug/Assertion.cpp diff --git a/Sources/Overload/OvDebug/src/OvDebug/ConsoleHandler.cpp b/Sources/OvDebug/src/OvDebug/ConsoleHandler.cpp similarity index 100% rename from Sources/Overload/OvDebug/src/OvDebug/ConsoleHandler.cpp rename to Sources/OvDebug/src/OvDebug/ConsoleHandler.cpp diff --git a/Sources/Overload/OvDebug/src/OvDebug/FileHandler.cpp b/Sources/OvDebug/src/OvDebug/FileHandler.cpp similarity index 100% rename from Sources/Overload/OvDebug/src/OvDebug/FileHandler.cpp rename to Sources/OvDebug/src/OvDebug/FileHandler.cpp diff --git a/Sources/Overload/OvDebug/src/OvDebug/HistoryHandler.cpp b/Sources/OvDebug/src/OvDebug/HistoryHandler.cpp similarity index 100% rename from Sources/Overload/OvDebug/src/OvDebug/HistoryHandler.cpp rename to Sources/OvDebug/src/OvDebug/HistoryHandler.cpp diff --git a/Sources/Overload/OvDebug/src/OvDebug/Logger.cpp b/Sources/OvDebug/src/OvDebug/Logger.cpp similarity index 99% rename from Sources/Overload/OvDebug/src/OvDebug/Logger.cpp rename to Sources/OvDebug/src/OvDebug/Logger.cpp index 38029f1c1..9ea43c6fe 100644 --- a/Sources/Overload/OvDebug/src/OvDebug/Logger.cpp +++ b/Sources/OvDebug/src/OvDebug/Logger.cpp @@ -4,6 +4,8 @@ * @licence: MIT */ +#include + #include "OvDebug/Logger.h" #include "OvTools/Time/Date.h" diff --git a/Sources/Overload/OvEditor/OvEditor.rc b/Sources/OvEditor/OvEditor.rc similarity index 100% rename from Sources/Overload/OvEditor/OvEditor.rc rename to Sources/OvEditor/OvEditor.rc diff --git a/Sources/Overload/OvEditor/icon.ico b/Sources/OvEditor/icon.ico similarity index 100% rename from Sources/Overload/OvEditor/icon.ico rename to Sources/OvEditor/icon.ico diff --git a/Sources/Overload/OvEditor/include/OvEditor/Core/Application.h b/Sources/OvEditor/include/OvEditor/Core/Application.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Core/Application.h rename to Sources/OvEditor/include/OvEditor/Core/Application.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Core/CameraController.h b/Sources/OvEditor/include/OvEditor/Core/CameraController.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Core/CameraController.h rename to Sources/OvEditor/include/OvEditor/Core/CameraController.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Core/Context.h b/Sources/OvEditor/include/OvEditor/Core/Context.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Core/Context.h rename to Sources/OvEditor/include/OvEditor/Core/Context.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Core/Editor.h b/Sources/OvEditor/include/OvEditor/Core/Editor.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Core/Editor.h rename to Sources/OvEditor/include/OvEditor/Core/Editor.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Core/EditorActions.h b/Sources/OvEditor/include/OvEditor/Core/EditorActions.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Core/EditorActions.h rename to Sources/OvEditor/include/OvEditor/Core/EditorActions.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Core/EditorActions.inl b/Sources/OvEditor/include/OvEditor/Core/EditorActions.inl similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Core/EditorActions.inl rename to Sources/OvEditor/include/OvEditor/Core/EditorActions.inl diff --git a/Sources/Overload/OvEditor/include/OvEditor/Core/EditorResources.h b/Sources/OvEditor/include/OvEditor/Core/EditorResources.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Core/EditorResources.h rename to Sources/OvEditor/include/OvEditor/Core/EditorResources.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Core/GizmoBehaviour.h b/Sources/OvEditor/include/OvEditor/Core/GizmoBehaviour.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Core/GizmoBehaviour.h rename to Sources/OvEditor/include/OvEditor/Core/GizmoBehaviour.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Core/PanelsManager.h b/Sources/OvEditor/include/OvEditor/Core/PanelsManager.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Core/PanelsManager.h rename to Sources/OvEditor/include/OvEditor/Core/PanelsManager.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Core/ProjectHub.h b/Sources/OvEditor/include/OvEditor/Core/ProjectHub.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Core/ProjectHub.h rename to Sources/OvEditor/include/OvEditor/Core/ProjectHub.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Panels/AView.h b/Sources/OvEditor/include/OvEditor/Panels/AView.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Panels/AView.h rename to Sources/OvEditor/include/OvEditor/Panels/AView.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Panels/AViewControllable.h b/Sources/OvEditor/include/OvEditor/Panels/AViewControllable.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Panels/AViewControllable.h rename to Sources/OvEditor/include/OvEditor/Panels/AViewControllable.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Panels/AssetBrowser.h b/Sources/OvEditor/include/OvEditor/Panels/AssetBrowser.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Panels/AssetBrowser.h rename to Sources/OvEditor/include/OvEditor/Panels/AssetBrowser.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Panels/AssetProperties.h b/Sources/OvEditor/include/OvEditor/Panels/AssetProperties.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Panels/AssetProperties.h rename to Sources/OvEditor/include/OvEditor/Panels/AssetProperties.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Panels/AssetView.h b/Sources/OvEditor/include/OvEditor/Panels/AssetView.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Panels/AssetView.h rename to Sources/OvEditor/include/OvEditor/Panels/AssetView.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Panels/Console.h b/Sources/OvEditor/include/OvEditor/Panels/Console.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Panels/Console.h rename to Sources/OvEditor/include/OvEditor/Panels/Console.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Panels/FrameInfo.h b/Sources/OvEditor/include/OvEditor/Panels/FrameInfo.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Panels/FrameInfo.h rename to Sources/OvEditor/include/OvEditor/Panels/FrameInfo.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Panels/GameView.h b/Sources/OvEditor/include/OvEditor/Panels/GameView.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Panels/GameView.h rename to Sources/OvEditor/include/OvEditor/Panels/GameView.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Panels/HardwareInfo.h b/Sources/OvEditor/include/OvEditor/Panels/HardwareInfo.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Panels/HardwareInfo.h rename to Sources/OvEditor/include/OvEditor/Panels/HardwareInfo.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Panels/Hierarchy.h b/Sources/OvEditor/include/OvEditor/Panels/Hierarchy.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Panels/Hierarchy.h rename to Sources/OvEditor/include/OvEditor/Panels/Hierarchy.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Panels/Inspector.h b/Sources/OvEditor/include/OvEditor/Panels/Inspector.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Panels/Inspector.h rename to Sources/OvEditor/include/OvEditor/Panels/Inspector.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Panels/MaterialEditor.h b/Sources/OvEditor/include/OvEditor/Panels/MaterialEditor.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Panels/MaterialEditor.h rename to Sources/OvEditor/include/OvEditor/Panels/MaterialEditor.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Panels/MenuBar.h b/Sources/OvEditor/include/OvEditor/Panels/MenuBar.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Panels/MenuBar.h rename to Sources/OvEditor/include/OvEditor/Panels/MenuBar.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Panels/ProjectSettings.h b/Sources/OvEditor/include/OvEditor/Panels/ProjectSettings.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Panels/ProjectSettings.h rename to Sources/OvEditor/include/OvEditor/Panels/ProjectSettings.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Panels/SceneView.h b/Sources/OvEditor/include/OvEditor/Panels/SceneView.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Panels/SceneView.h rename to Sources/OvEditor/include/OvEditor/Panels/SceneView.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Panels/TextureDebugger.h b/Sources/OvEditor/include/OvEditor/Panels/TextureDebugger.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Panels/TextureDebugger.h rename to Sources/OvEditor/include/OvEditor/Panels/TextureDebugger.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Panels/Toolbar.h b/Sources/OvEditor/include/OvEditor/Panels/Toolbar.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Panels/Toolbar.h rename to Sources/OvEditor/include/OvEditor/Panels/Toolbar.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Rendering/DebugModelRenderFeature.h b/Sources/OvEditor/include/OvEditor/Rendering/DebugModelRenderFeature.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Rendering/DebugModelRenderFeature.h rename to Sources/OvEditor/include/OvEditor/Rendering/DebugModelRenderFeature.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Rendering/DebugSceneRenderer.h b/Sources/OvEditor/include/OvEditor/Rendering/DebugSceneRenderer.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Rendering/DebugSceneRenderer.h rename to Sources/OvEditor/include/OvEditor/Rendering/DebugSceneRenderer.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Rendering/GizmoRenderFeature.h b/Sources/OvEditor/include/OvEditor/Rendering/GizmoRenderFeature.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Rendering/GizmoRenderFeature.h rename to Sources/OvEditor/include/OvEditor/Rendering/GizmoRenderFeature.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Rendering/GridRenderPass.h b/Sources/OvEditor/include/OvEditor/Rendering/GridRenderPass.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Rendering/GridRenderPass.h rename to Sources/OvEditor/include/OvEditor/Rendering/GridRenderPass.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Rendering/OutlineRenderFeature.h b/Sources/OvEditor/include/OvEditor/Rendering/OutlineRenderFeature.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Rendering/OutlineRenderFeature.h rename to Sources/OvEditor/include/OvEditor/Rendering/OutlineRenderFeature.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Rendering/PickingRenderPass.h b/Sources/OvEditor/include/OvEditor/Rendering/PickingRenderPass.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Rendering/PickingRenderPass.h rename to Sources/OvEditor/include/OvEditor/Rendering/PickingRenderPass.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Settings/EFontSize.h b/Sources/OvEditor/include/OvEditor/Settings/EFontSize.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Settings/EFontSize.h rename to Sources/OvEditor/include/OvEditor/Settings/EFontSize.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Settings/EditorSettings.h b/Sources/OvEditor/include/OvEditor/Settings/EditorSettings.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Settings/EditorSettings.h rename to Sources/OvEditor/include/OvEditor/Settings/EditorSettings.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Utils/ActorCreationMenu.h b/Sources/OvEditor/include/OvEditor/Utils/ActorCreationMenu.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Utils/ActorCreationMenu.h rename to Sources/OvEditor/include/OvEditor/Utils/ActorCreationMenu.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Utils/FileSystem.h b/Sources/OvEditor/include/OvEditor/Utils/FileSystem.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Utils/FileSystem.h rename to Sources/OvEditor/include/OvEditor/Utils/FileSystem.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Utils/ProjectManagement.h b/Sources/OvEditor/include/OvEditor/Utils/ProjectManagement.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Utils/ProjectManagement.h rename to Sources/OvEditor/include/OvEditor/Utils/ProjectManagement.h diff --git a/Sources/Overload/OvEditor/include/OvEditor/Utils/TextureRegistry.h b/Sources/OvEditor/include/OvEditor/Utils/TextureRegistry.h similarity index 100% rename from Sources/Overload/OvEditor/include/OvEditor/Utils/TextureRegistry.h rename to Sources/OvEditor/include/OvEditor/Utils/TextureRegistry.h diff --git a/Sources/Overload/OvEditor/layout.ini b/Sources/OvEditor/layout.ini similarity index 100% rename from Sources/Overload/OvEditor/layout.ini rename to Sources/OvEditor/layout.ini diff --git a/Sources/OvEditor/premake5.lua b/Sources/OvEditor/premake5.lua new file mode 100644 index 000000000..d3caf81d2 --- /dev/null +++ b/Sources/OvEditor/premake5.lua @@ -0,0 +1,151 @@ +project "OvEditor" + language "C++" + cppdialect "C++20" + targetdir (outputdir .. "%{cfg.buildcfg}/%{prj.name}") + objdir (objoutdir .. "%{cfg.buildcfg}/%{prj.name}") + debugdir "%{wks.location}/Build/%{cfg.buildcfg}" + + files { + "**.h", + "**.inl", + "**.cpp", + "**.lua", + "**.ini", + } + + includedirs { + -- Dependencies + dependdir .. "glad/include", + dependdir .. "ImGui/include", + dependdir .. "tinyxml2/include", + dependdir .. "tracy", + + -- Overload SDK + "%{wks.location}/Sources/OvAudio/include", + "%{wks.location}/Sources/OvCore/include", + "%{wks.location}/Sources/OvDebug/include", + "%{wks.location}/Sources/OvMaths/include", + "%{wks.location}/Sources/OvPhysics/include", + "%{wks.location}/Sources/OvRendering/include", + "%{wks.location}/Sources/OvTools/include", + "%{wks.location}/Sources/OvUI/include", + "%{wks.location}/Sources/OvWindowing/include", + + -- Current project + "include" + } + + links { + -- Dependencies (order matters on Linux!) + "bullet3", + "glad", + "ImGui", + "lua", + "soloud", + "tinyxml2", + "tracy", + + -- Overload SDK + "OvAudio", + "OvCore", + "OvDebug", + "OvMaths", + "OvPhysics", + "OvRendering", + "OvTools", + "OvUI", + "OvWindowing", + + -- Dependencies that others depend on - must come after + "assimp", + "glfw", + } + + filter { "configurations:Debug" } + defines { "DEBUG" } + symbols "On" + kind "ConsoleApp" + + filter { "configurations:Release" } + defines { "NDEBUG" } + optimize "Speed" + kind "WindowedApp" + + filter { "system:windows" } + characterset ("MBCS") + -- forces post-build commands to trigger even if nothing changed + fastuptodate "Off" + + files { + "**.rc", + } + + links { + -- Precompiled Libraries + "dbghelp.lib", + "opengl32.lib", + } + + postbuildcommands { + "for /f \"delims=|\" %%i in ('dir /B /S \"%{dependdir}\\*.dll\"') do xcopy /Q /Y \"%%i\" \"%{outputdir}%{cfg.buildcfg}\\%{prj.name}\"", + + "rmdir /s /q \"%{builddir}%{cfg.buildcfg}\\Data\"", + + "xcopy \"%{resdir}Engine\\*\" \"%{builddir}%{cfg.buildcfg}\\Data\\Engine\" /y /i /r /e /q", + "xcopy \"%{resdir}Editor\\*\" \"%{builddir}%{cfg.buildcfg}\\Data\\Editor\" /y /i /r /e /q", + "xcopy \"%{prj.location}\\Layout.ini\" \"%{builddir}%{cfg.buildcfg}\\Config\\\" /y /i", + + "xcopy \"%{wks.location}\\Tools\\tracy-profiler.exe\" \"%{builddir}%{cfg.buildcfg}\\Tools\\\" /y /i", + + "xcopy /Y /I /Q /D \"%{outputdir}%{cfg.buildcfg}\\%{prj.name}\\*.exe\" \"%{builddir}%{cfg.buildcfg}\\\"", + "xcopy /Y /I /Q /D \"%{outputdir}%{cfg.buildcfg}\\%{prj.name}\\*.dll\" \"%{builddir}%{cfg.buildcfg}\\\"", + + "xcopy \"%{outputdir}Debug\\OvGame\\*.exe\" \"%{builddir}%{cfg.buildcfg}\\Builder\\Development\" /y /i /c", + "xcopy \"%{outputdir}Debug\\OvGame\\*.dll\" \"%{builddir}%{cfg.buildcfg}\\Builder\\Development\" /y /i /c", + "xcopy \"%{outputdir}Release\\OvGame\\*.exe\" \"%{builddir}%{cfg.buildcfg}\\Builder\\Shipping\" /y /i /c", + "xcopy \"%{outputdir}Release\\OvGame\\*.dll\" \"%{builddir}%{cfg.buildcfg}\\Builder\\Shipping\" /y /i /c", + + "EXIT /B 0" + } + + filter { "system:linux" } + links { + "dl", + "pthread", + "GL", + "X11", + } + + -- Force inclusion of all symbols from these libraries + linkoptions { + "-Wl,--whole-archive", + outputdir .. "%{cfg.buildcfg}/ImGui/libImGui.a", + outputdir .. "%{cfg.buildcfg}/bullet3/libbullet3.a", + outputdir .. "%{cfg.buildcfg}/lua/liblua.a", + outputdir .. "%{cfg.buildcfg}/soloud/libsoloud.a", + outputdir .. "%{cfg.buildcfg}/OvAudio/libOvAudio.a", + outputdir .. "%{cfg.buildcfg}/assimp/libassimp.a", + outputdir .. "%{cfg.buildcfg}/tinyxml2/libtinyxml2.a", + outputdir .. "%{cfg.buildcfg}/glad/libglad.a", + "-Wl,--no-whole-archive", + "-Wl,--allow-multiple-definition", -- Tracy and Bullet3 have some duplicate symbols + } + + postbuildcommands { + "rm -rf %{builddir}%{cfg.buildcfg}/Data", + "mkdir -p %{builddir}%{cfg.buildcfg}/Data", + "mkdir -p %{builddir}%{cfg.buildcfg}/Config", + "mkdir -p %{builddir}%{cfg.buildcfg}/Builder/Development", + "mkdir -p %{builddir}%{cfg.buildcfg}/Builder/Shipping", + + "cp -r %{resdir}Engine %{builddir}%{cfg.buildcfg}/Data/Engine", + "cp -r %{resdir}Editor %{builddir}%{cfg.buildcfg}/Data/Editor", + "cp %{prj.location}/layout.ini %{builddir}%{cfg.buildcfg}/Config/ 2>/dev/null || true", + + "cp %{outputdir}%{cfg.buildcfg}/%{prj.name}/OvEditor %{builddir}%{cfg.buildcfg}/", + + "cp %{outputdir}Debug/OvGame/OvGame %{builddir}%{cfg.buildcfg}/Builder/Development/ 2>/dev/null || true", + "cp %{outputdir}Release/OvGame/OvGame %{builddir}%{cfg.buildcfg}/Builder/Shipping/ 2>/dev/null || true", + + "true" + } diff --git a/Sources/Overload/OvEditor/resource.h b/Sources/OvEditor/resource.h similarity index 100% rename from Sources/Overload/OvEditor/resource.h rename to Sources/OvEditor/resource.h diff --git a/Sources/Overload/OvEditor/src/OvEditor/Core/Application.cpp b/Sources/OvEditor/src/OvEditor/Core/Application.cpp similarity index 100% rename from Sources/Overload/OvEditor/src/OvEditor/Core/Application.cpp rename to Sources/OvEditor/src/OvEditor/Core/Application.cpp diff --git a/Sources/Overload/OvEditor/src/OvEditor/Core/CameraController.cpp b/Sources/OvEditor/src/OvEditor/Core/CameraController.cpp similarity index 98% rename from Sources/Overload/OvEditor/src/OvEditor/Core/CameraController.cpp rename to Sources/OvEditor/src/OvEditor/Core/CameraController.cpp index 2d3fb94a8..06dc62cd7 100644 --- a/Sources/Overload/OvEditor/src/OvEditor/Core/CameraController.cpp +++ b/Sources/OvEditor/src/OvEditor/Core/CameraController.cpp @@ -188,7 +188,8 @@ void OvEditor::Core::CameraController::HandleInputs(float p_deltaTime) { if (m_middleMousePressed) { - if (m_inputManager.GetKeyState(OvWindowing::Inputs::EKey::KEY_LEFT_ALT) == OvWindowing::Inputs::EKeyState::KEY_DOWN) + if (m_inputManager.GetKeyState(OvWindowing::Inputs::EKey::KEY_LEFT_ALT) == OvWindowing::Inputs::EKeyState::KEY_DOWN || + m_inputManager.GetKeyState(OvWindowing::Inputs::EKey::KEY_LEFT_CONTROL) == OvWindowing::Inputs::EKeyState::KEY_DOWN) { if (auto target = GetTargetActor()) { diff --git a/Sources/Overload/OvEditor/src/OvEditor/Core/Context.cpp b/Sources/OvEditor/src/OvEditor/Core/Context.cpp similarity index 100% rename from Sources/Overload/OvEditor/src/OvEditor/Core/Context.cpp rename to Sources/OvEditor/src/OvEditor/Core/Context.cpp diff --git a/Sources/Overload/OvEditor/src/OvEditor/Core/Editor.cpp b/Sources/OvEditor/src/OvEditor/Core/Editor.cpp similarity index 100% rename from Sources/Overload/OvEditor/src/OvEditor/Core/Editor.cpp rename to Sources/OvEditor/src/OvEditor/Core/Editor.cpp diff --git a/Sources/Overload/OvEditor/src/OvEditor/Core/EditorActions.cpp b/Sources/OvEditor/src/OvEditor/Core/EditorActions.cpp similarity index 99% rename from Sources/Overload/OvEditor/src/OvEditor/Core/EditorActions.cpp rename to Sources/OvEditor/src/OvEditor/Core/EditorActions.cpp index 8d92a15ec..e41b8b22f 100644 --- a/Sources/Overload/OvEditor/src/OvEditor/Core/EditorActions.cpp +++ b/Sources/OvEditor/src/OvEditor/Core/EditorActions.cpp @@ -824,16 +824,18 @@ std::string OvEditor::Core::EditorActions::GetRealPath(const std::string& p_path { std::filesystem::path result; - if (p_path.starts_with(':')) // The path is an engine path + const std::string normalizedPath = OvTools::Utils::PathParser::MakeNonWindowsStyle(p_path); + + if (normalizedPath.starts_with(':')) // The path is an engine path { - result = m_context.engineAssetsPath / p_path.substr(1); + result = m_context.engineAssetsPath / normalizedPath.substr(1); } else // The path is a project path { - result = m_context.projectAssetsPath / p_path; + result = m_context.projectAssetsPath / normalizedPath; } - return result.string(); + return result.lexically_normal().string(); } std::string OvEditor::Core::EditorActions::GetResourcePath(const std::string& p_path, bool p_isFromEngine) diff --git a/Sources/Overload/OvEditor/src/OvEditor/Core/EditorResources.cpp b/Sources/OvEditor/src/OvEditor/Core/EditorResources.cpp similarity index 100% rename from Sources/Overload/OvEditor/src/OvEditor/Core/EditorResources.cpp rename to Sources/OvEditor/src/OvEditor/Core/EditorResources.cpp diff --git a/Sources/Overload/OvEditor/src/OvEditor/Core/GizmoBehaviour.cpp b/Sources/OvEditor/src/OvEditor/Core/GizmoBehaviour.cpp similarity index 99% rename from Sources/Overload/OvEditor/src/OvEditor/Core/GizmoBehaviour.cpp rename to Sources/OvEditor/src/OvEditor/Core/GizmoBehaviour.cpp index 51c19bd3e..96a7bfe86 100644 --- a/Sources/Overload/OvEditor/src/OvEditor/Core/GizmoBehaviour.cpp +++ b/Sources/OvEditor/src/OvEditor/Core/GizmoBehaviour.cpp @@ -4,6 +4,8 @@ * @licence: MIT */ +#include + #include "OvEditor/Core/GizmoBehaviour.h" #include "OvEditor/Core/EditorActions.h" #include "OvEditor/Settings/EditorSettings.h" diff --git a/Sources/Overload/OvEditor/src/OvEditor/Core/PanelsManager.cpp b/Sources/OvEditor/src/OvEditor/Core/PanelsManager.cpp similarity index 100% rename from Sources/Overload/OvEditor/src/OvEditor/Core/PanelsManager.cpp rename to Sources/OvEditor/src/OvEditor/Core/PanelsManager.cpp diff --git a/Sources/Overload/OvEditor/src/OvEditor/Core/ProjectHub.cpp b/Sources/OvEditor/src/OvEditor/Core/ProjectHub.cpp similarity index 100% rename from Sources/Overload/OvEditor/src/OvEditor/Core/ProjectHub.cpp rename to Sources/OvEditor/src/OvEditor/Core/ProjectHub.cpp diff --git a/Sources/Overload/OvEditor/src/OvEditor/Main.cpp b/Sources/OvEditor/src/OvEditor/Main.cpp similarity index 88% rename from Sources/Overload/OvEditor/src/OvEditor/Main.cpp rename to Sources/OvEditor/src/OvEditor/Main.cpp index f48fbe11b..7878ed39c 100644 --- a/Sources/Overload/OvEditor/src/OvEditor/Main.cpp +++ b/Sources/OvEditor/src/OvEditor/Main.cpp @@ -18,8 +18,12 @@ #include #include +#ifdef _WIN32 #undef APIENTRY #include "Windows.h" +#else +#include +#endif FORCE_DEDICATED_GPU @@ -32,7 +36,9 @@ namespace */ void UpdateWorkingDirectory(const std::string& p_executablePath) { +#ifdef _WIN32 if (!IsDebuggerPresent()) +#endif { std::filesystem::current_path(OvTools::Utils::PathParser::GetContainingFolder(p_executablePath)); } @@ -42,7 +48,13 @@ namespace { const auto errorEvent = [](OvWindowing::Context::EDeviceError, std::string errMsg) { errMsg = "Overload requires OpenGL 4.5 or newer.\r\n" + errMsg; +#ifdef _WIN32 MessageBox(0, errMsg.c_str(), "Overload", MB_OK | MB_ICONSTOP); +#else + // Use zenity for error message on Linux + std::string command = "zenity --error --title=\"Overload\" --text=\"" + errMsg + "\" 2>/dev/null"; + std::system(command.c_str()); +#endif }; std::unique_ptr app; @@ -67,7 +79,7 @@ namespace int main(int argc, char** argv) { - UpdateWorkingDirectory(argv[0]); + // UpdateWorkingDirectory(argv[0]); OvEditor::Settings::EditorSettings::Load(); @@ -109,9 +121,11 @@ int main(int argc, char** argv) return EXIT_SUCCESS; } +#ifdef _WIN32 #ifndef _DEBUG INT WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow) { main(__argc, __argv); } #endif +#endif diff --git a/Sources/Overload/OvEditor/src/OvEditor/Panels/AView.cpp b/Sources/OvEditor/src/OvEditor/Panels/AView.cpp similarity index 100% rename from Sources/Overload/OvEditor/src/OvEditor/Panels/AView.cpp rename to Sources/OvEditor/src/OvEditor/Panels/AView.cpp diff --git a/Sources/Overload/OvEditor/src/OvEditor/Panels/AViewControllable.cpp b/Sources/OvEditor/src/OvEditor/Panels/AViewControllable.cpp similarity index 100% rename from Sources/Overload/OvEditor/src/OvEditor/Panels/AViewControllable.cpp rename to Sources/OvEditor/src/OvEditor/Panels/AViewControllable.cpp diff --git a/Sources/Overload/OvEditor/src/OvEditor/Panels/AssetBrowser.cpp b/Sources/OvEditor/src/OvEditor/Panels/AssetBrowser.cpp similarity index 96% rename from Sources/Overload/OvEditor/src/OvEditor/Panels/AssetBrowser.cpp rename to Sources/OvEditor/src/OvEditor/Panels/AssetBrowser.cpp index bf1e30186..4a0c52615 100644 --- a/Sources/Overload/OvEditor/src/OvEditor/Panels/AssetBrowser.cpp +++ b/Sources/OvEditor/src/OvEditor/Panels/AssetBrowser.cpp @@ -988,21 +988,19 @@ void OvEditor::Panels::AssetBrowser::ConsiderItem(OvUI::Widgets::Layout::TreeNod { if (!p_isEngineItem) /* Prevent engine item from being DDTarget (Can't Drag and drop to engine folder) */ { - treeNode.AddPlugin>>("Folder").DataReceivedEvent += [this, &treeNode, path, p_isEngineItem](std::pair p_data) - { - if (!p_data.first.empty()) - { - const std::filesystem::path folderReceivedPath = EDITOR_EXEC(GetRealPath(p_data.first)); - const std::filesystem::path folderName = folderReceivedPath.filename(); - const std::filesystem::path prevPath = folderReceivedPath; - const std::filesystem::path correctPath = m_pathUpdate.contains(&treeNode) ? m_pathUpdate.at(&treeNode) : path; - const std::filesystem::path newPath = correctPath / folderName; - - if (!std::filesystem::exists(newPath)) - { - const bool isEngineFolder = p_data.first.starts_with(':'); + treeNode.AddPlugin>>("Folder").DataReceivedEvent += [this, &treeNode, path, p_isEngineItem](std::pair p_data) + { + if (!p_data.first.empty()) + { + const std::filesystem::path folderReceivedPath = EDITOR_EXEC(GetRealPath(p_data.first)); + const std::filesystem::path folderName = folderReceivedPath.filename(); + const std::filesystem::path prevPath = folderReceivedPath; + const std::filesystem::path correctPath = m_pathUpdate.find(&treeNode) != m_pathUpdate.end() ? m_pathUpdate.at(&treeNode) : std::filesystem::path(path); + const std::filesystem::path newPath = correctPath / folderName; - // Copy dd folder from Engine resources + if (!std::filesystem::exists(newPath)) + { + const bool isEngineFolder = !p_data.first.empty() && p_data.first[0] == ':'; // Copy dd folder from Engine resources if (isEngineFolder) { std::filesystem::copy(prevPath, newPath, std::filesystem::copy_options::recursive); @@ -1035,18 +1033,16 @@ void OvEditor::Panels::AssetBrowser::ConsiderItem(OvUI::Widgets::Layout::TreeNod } }; - treeNode.AddPlugin>>("File").DataReceivedEvent += [this, &treeNode, path, p_isEngineItem](std::pair p_data) + treeNode.AddPlugin>>("File").DataReceivedEvent += [this, &treeNode, path, p_isEngineItem](std::pair p_data) + { + if (!p_data.first.empty()) { - if (!p_data.first.empty()) - { - std::filesystem::path fileReceivedPath = EDITOR_EXEC(GetRealPath(p_data.first)); - - const auto fileName = fileReceivedPath.filename(); - const auto prevPath = fileReceivedPath; - const auto correctPath = m_pathUpdate.find(&treeNode) != m_pathUpdate.end() ? m_pathUpdate.at(&treeNode) : path; - const auto newPath = correctPath / fileName; + std::filesystem::path fileReceivedPath = EDITOR_EXEC(GetRealPath(p_data.first)); - if (!std::filesystem::exists(newPath)) + const auto fileName = fileReceivedPath.filename(); + const auto prevPath = fileReceivedPath; + const auto correctPath = m_pathUpdate.find(&treeNode) != m_pathUpdate.end() ? m_pathUpdate.at(&treeNode) : std::filesystem::path(path); + const auto newPath = correctPath / fileName; if (!std::filesystem::exists(newPath)) { bool isEngineFile = p_data.first.at(0) == ':'; @@ -1133,7 +1129,7 @@ void OvEditor::Panels::AssetBrowser::ConsiderItem(OvUI::Widgets::Layout::TreeNod treeNode.OpenedEvent += [this, &treeNode, path, p_isEngineItem, p_scriptFolder] { treeNode.RemoveAllWidgets(); - std::string updatedPath = OvTools::Utils::PathParser::GetContainingFolder(path) + treeNode.name; + std::filesystem::path updatedPath = std::filesystem::path{path}.parent_path() / treeNode.name; ParseFolder(treeNode, std::filesystem::directory_entry(updatedPath), p_isEngineItem, p_scriptFolder); }; diff --git a/Sources/Overload/OvEditor/src/OvEditor/Panels/AssetProperties.cpp b/Sources/OvEditor/src/OvEditor/Panels/AssetProperties.cpp similarity index 100% rename from Sources/Overload/OvEditor/src/OvEditor/Panels/AssetProperties.cpp rename to Sources/OvEditor/src/OvEditor/Panels/AssetProperties.cpp diff --git a/Sources/Overload/OvEditor/src/OvEditor/Panels/AssetView.cpp b/Sources/OvEditor/src/OvEditor/Panels/AssetView.cpp similarity index 100% rename from Sources/Overload/OvEditor/src/OvEditor/Panels/AssetView.cpp rename to Sources/OvEditor/src/OvEditor/Panels/AssetView.cpp diff --git a/Sources/Overload/OvEditor/src/OvEditor/Panels/Console.cpp b/Sources/OvEditor/src/OvEditor/Panels/Console.cpp similarity index 100% rename from Sources/Overload/OvEditor/src/OvEditor/Panels/Console.cpp rename to Sources/OvEditor/src/OvEditor/Panels/Console.cpp diff --git a/Sources/Overload/OvEditor/src/OvEditor/Panels/FrameInfo.cpp b/Sources/OvEditor/src/OvEditor/Panels/FrameInfo.cpp similarity index 99% rename from Sources/Overload/OvEditor/src/OvEditor/Panels/FrameInfo.cpp rename to Sources/OvEditor/src/OvEditor/Panels/FrameInfo.cpp index 6274a2418..fe2e02c7d 100644 --- a/Sources/Overload/OvEditor/src/OvEditor/Panels/FrameInfo.cpp +++ b/Sources/OvEditor/src/OvEditor/Panels/FrameInfo.cpp @@ -4,6 +4,8 @@ * @licence: MIT */ +#include + #include #include diff --git a/Sources/Overload/OvEditor/src/OvEditor/Panels/GameView.cpp b/Sources/OvEditor/src/OvEditor/Panels/GameView.cpp similarity index 100% rename from Sources/Overload/OvEditor/src/OvEditor/Panels/GameView.cpp rename to Sources/OvEditor/src/OvEditor/Panels/GameView.cpp diff --git a/Sources/Overload/OvEditor/src/OvEditor/Panels/HardwareInfo.cpp b/Sources/OvEditor/src/OvEditor/Panels/HardwareInfo.cpp similarity index 100% rename from Sources/Overload/OvEditor/src/OvEditor/Panels/HardwareInfo.cpp rename to Sources/OvEditor/src/OvEditor/Panels/HardwareInfo.cpp diff --git a/Sources/Overload/OvEditor/src/OvEditor/Panels/Hierarchy.cpp b/Sources/OvEditor/src/OvEditor/Panels/Hierarchy.cpp similarity index 100% rename from Sources/Overload/OvEditor/src/OvEditor/Panels/Hierarchy.cpp rename to Sources/OvEditor/src/OvEditor/Panels/Hierarchy.cpp diff --git a/Sources/Overload/OvEditor/src/OvEditor/Panels/Inspector.cpp b/Sources/OvEditor/src/OvEditor/Panels/Inspector.cpp similarity index 100% rename from Sources/Overload/OvEditor/src/OvEditor/Panels/Inspector.cpp rename to Sources/OvEditor/src/OvEditor/Panels/Inspector.cpp diff --git a/Sources/Overload/OvEditor/src/OvEditor/Panels/MaterialEditor.cpp b/Sources/OvEditor/src/OvEditor/Panels/MaterialEditor.cpp similarity index 100% rename from Sources/Overload/OvEditor/src/OvEditor/Panels/MaterialEditor.cpp rename to Sources/OvEditor/src/OvEditor/Panels/MaterialEditor.cpp diff --git a/Sources/Overload/OvEditor/src/OvEditor/Panels/MenuBar.cpp b/Sources/OvEditor/src/OvEditor/Panels/MenuBar.cpp similarity index 98% rename from Sources/Overload/OvEditor/src/OvEditor/Panels/MenuBar.cpp rename to Sources/OvEditor/src/OvEditor/Panels/MenuBar.cpp index f08b5fabf..c7c60f044 100644 --- a/Sources/Overload/OvEditor/src/OvEditor/Panels/MenuBar.cpp +++ b/Sources/OvEditor/src/OvEditor/Panels/MenuBar.cpp @@ -237,8 +237,13 @@ void OvEditor::Panels::MenuBar::CreateResourcesMenu() void OvEditor::Panels::MenuBar::CreateToolsMenu() { +// No Tracy profiler (front-end) on non-Windows platforms at the moment. +// You'll need to build it yourself if you want to use it on other platforms. +// https://github.com/Overload-Technologies/Overload/issues/614 +#ifdef _WIN32 auto& toolsMenu = CreateWidget("Tools"); toolsMenu.CreateWidget("Open Profiler").ClickedEvent += EDITOR_BIND(OpenProfiler); +#endif } void OvEditor::Panels::MenuBar::CreateSettingsMenu() diff --git a/Sources/Overload/OvEditor/src/OvEditor/Panels/ProjectSettings.cpp b/Sources/OvEditor/src/OvEditor/Panels/ProjectSettings.cpp similarity index 100% rename from Sources/Overload/OvEditor/src/OvEditor/Panels/ProjectSettings.cpp rename to Sources/OvEditor/src/OvEditor/Panels/ProjectSettings.cpp diff --git a/Sources/Overload/OvEditor/src/OvEditor/Panels/SceneView.cpp b/Sources/OvEditor/src/OvEditor/Panels/SceneView.cpp similarity index 100% rename from Sources/Overload/OvEditor/src/OvEditor/Panels/SceneView.cpp rename to Sources/OvEditor/src/OvEditor/Panels/SceneView.cpp diff --git a/Sources/Overload/OvEditor/src/OvEditor/Panels/TextureDebugger.cpp b/Sources/OvEditor/src/OvEditor/Panels/TextureDebugger.cpp similarity index 100% rename from Sources/Overload/OvEditor/src/OvEditor/Panels/TextureDebugger.cpp rename to Sources/OvEditor/src/OvEditor/Panels/TextureDebugger.cpp diff --git a/Sources/Overload/OvEditor/src/OvEditor/Panels/Toolbar.cpp b/Sources/OvEditor/src/OvEditor/Panels/Toolbar.cpp similarity index 100% rename from Sources/Overload/OvEditor/src/OvEditor/Panels/Toolbar.cpp rename to Sources/OvEditor/src/OvEditor/Panels/Toolbar.cpp diff --git a/Sources/Overload/OvEditor/src/OvEditor/Rendering/DebugModelRenderFeature.cpp b/Sources/OvEditor/src/OvEditor/Rendering/DebugModelRenderFeature.cpp similarity index 100% rename from Sources/Overload/OvEditor/src/OvEditor/Rendering/DebugModelRenderFeature.cpp rename to Sources/OvEditor/src/OvEditor/Rendering/DebugModelRenderFeature.cpp diff --git a/Sources/Overload/OvEditor/src/OvEditor/Rendering/DebugSceneRenderer.cpp b/Sources/OvEditor/src/OvEditor/Rendering/DebugSceneRenderer.cpp similarity index 100% rename from Sources/Overload/OvEditor/src/OvEditor/Rendering/DebugSceneRenderer.cpp rename to Sources/OvEditor/src/OvEditor/Rendering/DebugSceneRenderer.cpp diff --git a/Sources/Overload/OvEditor/src/OvEditor/Rendering/GizmoRenderFeature.cpp b/Sources/OvEditor/src/OvEditor/Rendering/GizmoRenderFeature.cpp similarity index 100% rename from Sources/Overload/OvEditor/src/OvEditor/Rendering/GizmoRenderFeature.cpp rename to Sources/OvEditor/src/OvEditor/Rendering/GizmoRenderFeature.cpp diff --git a/Sources/Overload/OvEditor/src/OvEditor/Rendering/GridRenderPass.cpp b/Sources/OvEditor/src/OvEditor/Rendering/GridRenderPass.cpp similarity index 100% rename from Sources/Overload/OvEditor/src/OvEditor/Rendering/GridRenderPass.cpp rename to Sources/OvEditor/src/OvEditor/Rendering/GridRenderPass.cpp diff --git a/Sources/Overload/OvEditor/src/OvEditor/Rendering/OutlineRenderFeature.cpp b/Sources/OvEditor/src/OvEditor/Rendering/OutlineRenderFeature.cpp similarity index 100% rename from Sources/Overload/OvEditor/src/OvEditor/Rendering/OutlineRenderFeature.cpp rename to Sources/OvEditor/src/OvEditor/Rendering/OutlineRenderFeature.cpp diff --git a/Sources/Overload/OvEditor/src/OvEditor/Rendering/PickingRenderPass.cpp b/Sources/OvEditor/src/OvEditor/Rendering/PickingRenderPass.cpp similarity index 98% rename from Sources/Overload/OvEditor/src/OvEditor/Rendering/PickingRenderPass.cpp rename to Sources/OvEditor/src/OvEditor/Rendering/PickingRenderPass.cpp index da614416d..ad22db4b7 100644 --- a/Sources/Overload/OvEditor/src/OvEditor/Rendering/PickingRenderPass.cpp +++ b/Sources/OvEditor/src/OvEditor/Rendering/PickingRenderPass.cpp @@ -169,7 +169,7 @@ void OvEditor::Rendering::PickingRenderPass::DrawPickableModels( drawable.material.value() : m_actorPickingFallbackMaterial; - const auto& actor = drawable.GetDescriptor().actor; + const auto& actor = drawable.template GetDescriptor().actor; PreparePickingMaterial(actor, targetMaterial); diff --git a/Sources/Overload/OvEditor/src/OvEditor/Settings/EditorSettings.cpp b/Sources/OvEditor/src/OvEditor/Settings/EditorSettings.cpp similarity index 100% rename from Sources/Overload/OvEditor/src/OvEditor/Settings/EditorSettings.cpp rename to Sources/OvEditor/src/OvEditor/Settings/EditorSettings.cpp diff --git a/Sources/Overload/OvEditor/src/OvEditor/Utils/ActorCreationMenu.cpp b/Sources/OvEditor/src/OvEditor/Utils/ActorCreationMenu.cpp similarity index 100% rename from Sources/Overload/OvEditor/src/OvEditor/Utils/ActorCreationMenu.cpp rename to Sources/OvEditor/src/OvEditor/Utils/ActorCreationMenu.cpp diff --git a/Sources/Overload/OvEditor/src/OvEditor/Utils/ProjectManagement.cpp b/Sources/OvEditor/src/OvEditor/Utils/ProjectManagement.cpp similarity index 100% rename from Sources/Overload/OvEditor/src/OvEditor/Utils/ProjectManagement.cpp rename to Sources/OvEditor/src/OvEditor/Utils/ProjectManagement.cpp diff --git a/Sources/Overload/OvEditor/src/OvEditor/Utils/TextureRegistry.cpp b/Sources/OvEditor/src/OvEditor/Utils/TextureRegistry.cpp similarity index 100% rename from Sources/Overload/OvEditor/src/OvEditor/Utils/TextureRegistry.cpp rename to Sources/OvEditor/src/OvEditor/Utils/TextureRegistry.cpp diff --git a/Sources/Overload/OvGame/OvGame.rc b/Sources/OvGame/OvGame.rc similarity index 100% rename from Sources/Overload/OvGame/OvGame.rc rename to Sources/OvGame/OvGame.rc diff --git a/Sources/Overload/OvGame/icon.ico b/Sources/OvGame/icon.ico similarity index 100% rename from Sources/Overload/OvGame/icon.ico rename to Sources/OvGame/icon.ico diff --git a/Sources/Overload/OvGame/include/OvGame/Core/Application.h b/Sources/OvGame/include/OvGame/Core/Application.h similarity index 100% rename from Sources/Overload/OvGame/include/OvGame/Core/Application.h rename to Sources/OvGame/include/OvGame/Core/Application.h diff --git a/Sources/Overload/OvGame/include/OvGame/Core/Context.h b/Sources/OvGame/include/OvGame/Core/Context.h similarity index 100% rename from Sources/Overload/OvGame/include/OvGame/Core/Context.h rename to Sources/OvGame/include/OvGame/Core/Context.h diff --git a/Sources/Overload/OvGame/include/OvGame/Core/Game.h b/Sources/OvGame/include/OvGame/Core/Game.h similarity index 100% rename from Sources/Overload/OvGame/include/OvGame/Core/Game.h rename to Sources/OvGame/include/OvGame/Core/Game.h diff --git a/Sources/Overload/OvGame/include/OvGame/Debug/DriverInfo.h b/Sources/OvGame/include/OvGame/Debug/DriverInfo.h similarity index 100% rename from Sources/Overload/OvGame/include/OvGame/Debug/DriverInfo.h rename to Sources/OvGame/include/OvGame/Debug/DriverInfo.h diff --git a/Sources/Overload/OvGame/include/OvGame/Debug/FrameInfo.h b/Sources/OvGame/include/OvGame/Debug/FrameInfo.h similarity index 100% rename from Sources/Overload/OvGame/include/OvGame/Debug/FrameInfo.h rename to Sources/OvGame/include/OvGame/Debug/FrameInfo.h diff --git a/Sources/Overload/OvGame/include/OvGame/Utils/FPSCounter.h b/Sources/OvGame/include/OvGame/Utils/FPSCounter.h similarity index 100% rename from Sources/Overload/OvGame/include/OvGame/Utils/FPSCounter.h rename to Sources/OvGame/include/OvGame/Utils/FPSCounter.h diff --git a/Sources/OvGame/premake5.lua b/Sources/OvGame/premake5.lua new file mode 100644 index 000000000..1af6029c5 --- /dev/null +++ b/Sources/OvGame/premake5.lua @@ -0,0 +1,119 @@ +project "OvGame" + language "C++" + cppdialect "C++20" + targetdir (outputdir .. "%{cfg.buildcfg}/%{prj.name}") + objdir (objoutdir .. "%{cfg.buildcfg}/%{prj.name}") + debugdir (outputdir .. "%{cfg.buildcfg}/%{prj.name}") + + files { + "**.h", + "**.inl", + "**.cpp", + "**.lua", + "**.ini", + } + + includedirs { + -- Dependencies + dependdir .. "glad/include", + dependdir .. "ImGui/include", + dependdir .. "tracy", + + -- Overload SDK + "%{wks.location}/Sources/OvAudio/include", + "%{wks.location}/Sources/OvCore/include", + "%{wks.location}/Sources/OvDebug/include", + "%{wks.location}/Sources/OvMaths/include", + "%{wks.location}/Sources/OvPhysics/include", + "%{wks.location}/Sources/OvRendering/include", + "%{wks.location}/Sources/OvTools/include", + "%{wks.location}/Sources/OvUI/include", + "%{wks.location}/Sources/OvWindowing/include", + + -- Current project + "include" + } + + links { + -- Dependencies + "assimp", + "bullet3", + "glad", + "glfw", + "ImGui", + "lua", + "soloud", + "tinyxml2", + "tracy", + + -- Overload SDK + "OvAudio", + "OvCore", + "OvDebug", + "OvMaths", + "OvPhysics", + "OvRendering", + "OvTools", + "OvUI", + "OvWindowing" + } + + filter { "configurations:Debug" } + defines { "DEBUG" } + symbols "On" + kind "ConsoleApp" + + filter { "configurations:Release" } + defines { "NDEBUG" } + optimize "Speed" + kind "WindowedApp" + + filter { "system:windows" } + -- forces post-build commands to trigger even if nothing changed + fastuptodate "Off" + + files { + "**.rc", + } + + links { + -- Precompiled Libraries + "dbghelp.lib", + "opengl32.lib", + } + + postbuildcommands { + "for /f \"delims=|\" %%i in ('dir /B /S \"%{dependdir}\\*.dll\"') do xcopy /Q /Y \"%%i\" \"%{outputdir}%{cfg.buildcfg}\\%{prj.name}\"", + "xcopy \"%{resdir}Engine\\*\" \"%{outputdir}%{cfg.buildcfg}\\%{prj.name}\\Data\\Engine\" /y /i /r /e /q", + "EXIT /B 0" + } + + filter { "system:linux" } + links { + "dl", + "pthread", + "GL", + "X11", + } + + -- Force inclusion of all symbols from these libraries + linkoptions { + "-Wl,--whole-archive", + outputdir .. "%{cfg.buildcfg}/ImGui/libImGui.a", + outputdir .. "%{cfg.buildcfg}/bullet3/libbullet3.a", + outputdir .. "%{cfg.buildcfg}/lua/liblua.a", + outputdir .. "%{cfg.buildcfg}/soloud/libsoloud.a", + outputdir .. "%{cfg.buildcfg}/OvAudio/libOvAudio.a", + outputdir .. "%{cfg.buildcfg}/assimp/libassimp.a", + outputdir .. "%{cfg.buildcfg}/tinyxml2/libtinyxml2.a", + outputdir .. "%{cfg.buildcfg}/glad/libglad.a", + "-Wl,--no-whole-archive", + "-Wl,--allow-multiple-definition", -- Tracy and Bullet3 have some duplicate symbols + } + + postbuildcommands { + "mkdir -p %{outputdir}%{cfg.buildcfg}/%{prj.name}/Data", + "cp -r %{resdir}Engine %{outputdir}%{cfg.buildcfg}/%{prj.name}/Data/Engine", + "true" + } + diff --git a/Sources/Overload/OvGame/resource.h b/Sources/OvGame/resource.h similarity index 100% rename from Sources/Overload/OvGame/resource.h rename to Sources/OvGame/resource.h diff --git a/Sources/Overload/OvGame/src/OvGame/Core/Application.cpp b/Sources/OvGame/src/OvGame/Core/Application.cpp similarity index 100% rename from Sources/Overload/OvGame/src/OvGame/Core/Application.cpp rename to Sources/OvGame/src/OvGame/Core/Application.cpp diff --git a/Sources/Overload/OvGame/src/OvGame/Core/Context.cpp b/Sources/OvGame/src/OvGame/Core/Context.cpp similarity index 100% rename from Sources/Overload/OvGame/src/OvGame/Core/Context.cpp rename to Sources/OvGame/src/OvGame/Core/Context.cpp diff --git a/Sources/Overload/OvGame/src/OvGame/Core/Game.cpp b/Sources/OvGame/src/OvGame/Core/Game.cpp similarity index 100% rename from Sources/Overload/OvGame/src/OvGame/Core/Game.cpp rename to Sources/OvGame/src/OvGame/Core/Game.cpp diff --git a/Sources/Overload/OvGame/src/OvGame/Debug/DriverInfo.cpp b/Sources/OvGame/src/OvGame/Debug/DriverInfo.cpp similarity index 100% rename from Sources/Overload/OvGame/src/OvGame/Debug/DriverInfo.cpp rename to Sources/OvGame/src/OvGame/Debug/DriverInfo.cpp diff --git a/Sources/Overload/OvGame/src/OvGame/Debug/FrameInfo.cpp b/Sources/OvGame/src/OvGame/Debug/FrameInfo.cpp similarity index 100% rename from Sources/Overload/OvGame/src/OvGame/Debug/FrameInfo.cpp rename to Sources/OvGame/src/OvGame/Debug/FrameInfo.cpp diff --git a/Sources/Overload/OvGame/src/OvGame/Main.cpp b/Sources/OvGame/src/OvGame/Main.cpp similarity index 65% rename from Sources/Overload/OvGame/src/OvGame/Main.cpp rename to Sources/OvGame/src/OvGame/Main.cpp index b03868242..3073a4754 100644 --- a/Sources/Overload/OvGame/src/OvGame/Main.cpp +++ b/Sources/OvGame/src/OvGame/Main.cpp @@ -13,9 +13,13 @@ FORCE_DEDICATED_GPU #ifdef _DEBUG int main() #else -#undef APIENTRY -#include "Windows.h" -INT WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow) + #ifdef _WIN32 + #undef APIENTRY + #include "Windows.h" + INT WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow) + #else + int main() + #endif #endif { OvGame::Core::Application app; diff --git a/Sources/Overload/OvGame/src/OvGame/Utils/FPSCounter.cpp b/Sources/OvGame/src/OvGame/Utils/FPSCounter.cpp similarity index 100% rename from Sources/Overload/OvGame/src/OvGame/Utils/FPSCounter.cpp rename to Sources/OvGame/src/OvGame/Utils/FPSCounter.cpp diff --git a/Sources/Overload/OvMaths/include/OvMaths/FMatrix3.h b/Sources/OvMaths/include/OvMaths/FMatrix3.h similarity index 99% rename from Sources/Overload/OvMaths/include/OvMaths/FMatrix3.h rename to Sources/OvMaths/include/OvMaths/FMatrix3.h index 82cd1db19..f39738c39 100644 --- a/Sources/Overload/OvMaths/include/OvMaths/FMatrix3.h +++ b/Sources/OvMaths/include/OvMaths/FMatrix3.h @@ -9,7 +9,7 @@ #include #include "OvMaths/FVector3.h" -#include "OvMAths/FVector2.h" +#include "OvMaths/FVector2.h" namespace OvMaths { diff --git a/Sources/Overload/OvMaths/include/OvMaths/FMatrix4.h b/Sources/OvMaths/include/OvMaths/FMatrix4.h similarity index 100% rename from Sources/Overload/OvMaths/include/OvMaths/FMatrix4.h rename to Sources/OvMaths/include/OvMaths/FMatrix4.h diff --git a/Sources/Overload/OvMaths/include/OvMaths/FQuaternion.h b/Sources/OvMaths/include/OvMaths/FQuaternion.h similarity index 100% rename from Sources/Overload/OvMaths/include/OvMaths/FQuaternion.h rename to Sources/OvMaths/include/OvMaths/FQuaternion.h diff --git a/Sources/Overload/OvMaths/include/OvMaths/FTransform.h b/Sources/OvMaths/include/OvMaths/FTransform.h similarity index 100% rename from Sources/Overload/OvMaths/include/OvMaths/FTransform.h rename to Sources/OvMaths/include/OvMaths/FTransform.h diff --git a/Sources/Overload/OvMaths/include/OvMaths/FVector2.h b/Sources/OvMaths/include/OvMaths/FVector2.h similarity index 100% rename from Sources/Overload/OvMaths/include/OvMaths/FVector2.h rename to Sources/OvMaths/include/OvMaths/FVector2.h diff --git a/Sources/Overload/OvMaths/include/OvMaths/FVector3.h b/Sources/OvMaths/include/OvMaths/FVector3.h similarity index 100% rename from Sources/Overload/OvMaths/include/OvMaths/FVector3.h rename to Sources/OvMaths/include/OvMaths/FVector3.h diff --git a/Sources/Overload/OvMaths/include/OvMaths/FVector4.h b/Sources/OvMaths/include/OvMaths/FVector4.h similarity index 100% rename from Sources/Overload/OvMaths/include/OvMaths/FVector4.h rename to Sources/OvMaths/include/OvMaths/FVector4.h diff --git a/Sources/Overload/OvMaths/include/OvMaths/Internal/TransformNotifier.h b/Sources/OvMaths/include/OvMaths/Internal/TransformNotifier.h similarity index 98% rename from Sources/Overload/OvMaths/include/OvMaths/Internal/TransformNotifier.h rename to Sources/OvMaths/include/OvMaths/Internal/TransformNotifier.h index 9ae76442b..9bca3a8ce 100644 --- a/Sources/Overload/OvMaths/include/OvMaths/Internal/TransformNotifier.h +++ b/Sources/OvMaths/include/OvMaths/Internal/TransformNotifier.h @@ -6,9 +6,9 @@ #pragma once +#include #include - namespace OvMaths::Internal { /** diff --git a/Sources/Overload/OvMaths/premake5.lua b/Sources/OvMaths/premake5.lua similarity index 100% rename from Sources/Overload/OvMaths/premake5.lua rename to Sources/OvMaths/premake5.lua diff --git a/Sources/Overload/OvMaths/src/OvMaths/FMatrix3.cpp b/Sources/OvMaths/src/OvMaths/FMatrix3.cpp similarity index 99% rename from Sources/Overload/OvMaths/src/OvMaths/FMatrix3.cpp rename to Sources/OvMaths/src/OvMaths/FMatrix3.cpp index f18330f61..427611e83 100644 --- a/Sources/Overload/OvMaths/src/OvMaths/FMatrix3.cpp +++ b/Sources/OvMaths/src/OvMaths/FMatrix3.cpp @@ -4,9 +4,10 @@ * @licence: MIT */ -#include -#include #include +#include +#include +#include #include "OvMaths/FMatrix3.h" diff --git a/Sources/Overload/OvMaths/src/OvMaths/FMatrix4.cpp b/Sources/OvMaths/src/OvMaths/FMatrix4.cpp similarity index 100% rename from Sources/Overload/OvMaths/src/OvMaths/FMatrix4.cpp rename to Sources/OvMaths/src/OvMaths/FMatrix4.cpp diff --git a/Sources/Overload/OvMaths/src/OvMaths/FQuaternion.cpp b/Sources/OvMaths/src/OvMaths/FQuaternion.cpp similarity index 100% rename from Sources/Overload/OvMaths/src/OvMaths/FQuaternion.cpp rename to Sources/OvMaths/src/OvMaths/FQuaternion.cpp diff --git a/Sources/Overload/OvMaths/src/OvMaths/FTransform.cpp b/Sources/OvMaths/src/OvMaths/FTransform.cpp similarity index 100% rename from Sources/Overload/OvMaths/src/OvMaths/FTransform.cpp rename to Sources/OvMaths/src/OvMaths/FTransform.cpp diff --git a/Sources/Overload/OvMaths/src/OvMaths/FVector2.cpp b/Sources/OvMaths/src/OvMaths/FVector2.cpp similarity index 99% rename from Sources/Overload/OvMaths/src/OvMaths/FVector2.cpp rename to Sources/OvMaths/src/OvMaths/FVector2.cpp index 5aad0d382..0a153ce29 100644 --- a/Sources/Overload/OvMaths/src/OvMaths/FVector2.cpp +++ b/Sources/OvMaths/src/OvMaths/FVector2.cpp @@ -4,8 +4,9 @@ * @licence: MIT */ -#include +#include #include +#include #include "OvMaths/FVector2.h" diff --git a/Sources/Overload/OvMaths/src/OvMaths/FVector3.cpp b/Sources/OvMaths/src/OvMaths/FVector3.cpp similarity index 100% rename from Sources/Overload/OvMaths/src/OvMaths/FVector3.cpp rename to Sources/OvMaths/src/OvMaths/FVector3.cpp diff --git a/Sources/Overload/OvMaths/src/OvMaths/FVector4.cpp b/Sources/OvMaths/src/OvMaths/FVector4.cpp similarity index 99% rename from Sources/Overload/OvMaths/src/OvMaths/FVector4.cpp rename to Sources/OvMaths/src/OvMaths/FVector4.cpp index 251357be5..f622b5d5c 100644 --- a/Sources/Overload/OvMaths/src/OvMaths/FVector4.cpp +++ b/Sources/OvMaths/src/OvMaths/FVector4.cpp @@ -4,8 +4,9 @@ * @licence: MIT */ -#include +#include #include +#include #include "OvMaths/FVector4.h" diff --git a/Sources/Overload/OvMaths/src/OvMaths/Internal/TransformNotifier.cpp b/Sources/OvMaths/src/OvMaths/Internal/TransformNotifier.cpp similarity index 100% rename from Sources/Overload/OvMaths/src/OvMaths/Internal/TransformNotifier.cpp rename to Sources/OvMaths/src/OvMaths/Internal/TransformNotifier.cpp diff --git a/Sources/Overload/OvPhysics/include/OvPhysics/Core/PhysicsEngine.h b/Sources/OvPhysics/include/OvPhysics/Core/PhysicsEngine.h similarity index 98% rename from Sources/Overload/OvPhysics/include/OvPhysics/Core/PhysicsEngine.h rename to Sources/OvPhysics/include/OvPhysics/Core/PhysicsEngine.h index 2a01ef1ed..3f48d6e31 100644 --- a/Sources/Overload/OvPhysics/include/OvPhysics/Core/PhysicsEngine.h +++ b/Sources/OvPhysics/include/OvPhysics/Core/PhysicsEngine.h @@ -41,7 +41,7 @@ namespace OvPhysics::Core /** * Destructor */ - virtual ~PhysicsEngine() = default; + virtual ~PhysicsEngine(); /** * Simulate the physics. This method call is decomposed in 3 things: diff --git a/Sources/Overload/OvPhysics/include/OvPhysics/Entities/PhysicalBox.h b/Sources/OvPhysics/include/OvPhysics/Entities/PhysicalBox.h similarity index 100% rename from Sources/Overload/OvPhysics/include/OvPhysics/Entities/PhysicalBox.h rename to Sources/OvPhysics/include/OvPhysics/Entities/PhysicalBox.h diff --git a/Sources/Overload/OvPhysics/include/OvPhysics/Entities/PhysicalCapsule.h b/Sources/OvPhysics/include/OvPhysics/Entities/PhysicalCapsule.h similarity index 100% rename from Sources/Overload/OvPhysics/include/OvPhysics/Entities/PhysicalCapsule.h rename to Sources/OvPhysics/include/OvPhysics/Entities/PhysicalCapsule.h diff --git a/Sources/Overload/OvPhysics/include/OvPhysics/Entities/PhysicalObject.h b/Sources/OvPhysics/include/OvPhysics/Entities/PhysicalObject.h similarity index 100% rename from Sources/Overload/OvPhysics/include/OvPhysics/Entities/PhysicalObject.h rename to Sources/OvPhysics/include/OvPhysics/Entities/PhysicalObject.h diff --git a/Sources/Overload/OvPhysics/include/OvPhysics/Entities/PhysicalSphere.h b/Sources/OvPhysics/include/OvPhysics/Entities/PhysicalSphere.h similarity index 100% rename from Sources/Overload/OvPhysics/include/OvPhysics/Entities/PhysicalSphere.h rename to Sources/OvPhysics/include/OvPhysics/Entities/PhysicalSphere.h diff --git a/Sources/Overload/OvPhysics/include/OvPhysics/Entities/RaycastHit.h b/Sources/OvPhysics/include/OvPhysics/Entities/RaycastHit.h similarity index 100% rename from Sources/Overload/OvPhysics/include/OvPhysics/Entities/RaycastHit.h rename to Sources/OvPhysics/include/OvPhysics/Entities/RaycastHit.h diff --git a/Sources/Overload/OvPhysics/include/OvPhysics/Settings/BodySettings.h b/Sources/OvPhysics/include/OvPhysics/Settings/BodySettings.h similarity index 100% rename from Sources/Overload/OvPhysics/include/OvPhysics/Settings/BodySettings.h rename to Sources/OvPhysics/include/OvPhysics/Settings/BodySettings.h diff --git a/Sources/Overload/OvPhysics/include/OvPhysics/Settings/PhysicsSettings.h b/Sources/OvPhysics/include/OvPhysics/Settings/PhysicsSettings.h similarity index 100% rename from Sources/Overload/OvPhysics/include/OvPhysics/Settings/PhysicsSettings.h rename to Sources/OvPhysics/include/OvPhysics/Settings/PhysicsSettings.h diff --git a/Sources/Overload/OvPhysics/include/OvPhysics/Tools/Conversion.h b/Sources/OvPhysics/include/OvPhysics/Tools/Conversion.h similarity index 100% rename from Sources/Overload/OvPhysics/include/OvPhysics/Tools/Conversion.h rename to Sources/OvPhysics/include/OvPhysics/Tools/Conversion.h diff --git a/Sources/Overload/OvPhysics/premake5.lua b/Sources/OvPhysics/premake5.lua similarity index 75% rename from Sources/Overload/OvPhysics/premake5.lua rename to Sources/OvPhysics/premake5.lua index 0816c462e..b465da3b8 100644 --- a/Sources/Overload/OvPhysics/premake5.lua +++ b/Sources/OvPhysics/premake5.lua @@ -16,11 +16,12 @@ project "OvPhysics" includedirs { -- Dependencies dependdir .. "bullet3/", + dependdir .. "bullet3/bullet", -- Overload SDK - "%{wks.location}/OvDebug/include", - "%{wks.location}/OvMaths/include", - "%{wks.location}/OvTools/include", + "%{wks.location}/Sources/OvDebug/include", + "%{wks.location}/Sources/OvMaths/include", + "%{wks.location}/Sources/OvTools/include", -- Current Project "include" diff --git a/Sources/Overload/OvPhysics/src/OvPhysics/Core/PhysicsEngine.cpp b/Sources/OvPhysics/src/OvPhysics/Core/PhysicsEngine.cpp similarity index 99% rename from Sources/Overload/OvPhysics/src/OvPhysics/Core/PhysicsEngine.cpp rename to Sources/OvPhysics/src/OvPhysics/Core/PhysicsEngine.cpp index 5ac42ad5a..494d0e742 100644 --- a/Sources/Overload/OvPhysics/src/OvPhysics/Core/PhysicsEngine.cpp +++ b/Sources/OvPhysics/src/OvPhysics/Core/PhysicsEngine.cpp @@ -5,6 +5,7 @@ */ #include +#include #include #include @@ -34,6 +35,11 @@ OvPhysics::Core::PhysicsEngine::PhysicsEngine(const Settings::PhysicsSettings & SetCollisionCallback(); } +OvPhysics::Core::PhysicsEngine::~PhysicsEngine() +{ + +} + void OvPhysics::Core::PhysicsEngine::PreUpdate() { std::for_each(m_physicalObjects.begin(), m_physicalObjects.end(), std::mem_fn(&PhysicalObject::UpdateBtTransform)); diff --git a/Sources/Overload/OvPhysics/src/OvPhysics/Entities/PhysicalBox.cpp b/Sources/OvPhysics/src/OvPhysics/Entities/PhysicalBox.cpp similarity index 100% rename from Sources/Overload/OvPhysics/src/OvPhysics/Entities/PhysicalBox.cpp rename to Sources/OvPhysics/src/OvPhysics/Entities/PhysicalBox.cpp diff --git a/Sources/Overload/OvPhysics/src/OvPhysics/Entities/PhysicalCapsule.cpp b/Sources/OvPhysics/src/OvPhysics/Entities/PhysicalCapsule.cpp similarity index 100% rename from Sources/Overload/OvPhysics/src/OvPhysics/Entities/PhysicalCapsule.cpp rename to Sources/OvPhysics/src/OvPhysics/Entities/PhysicalCapsule.cpp diff --git a/Sources/Overload/OvPhysics/src/OvPhysics/Entities/PhysicalObject.cpp b/Sources/OvPhysics/src/OvPhysics/Entities/PhysicalObject.cpp similarity index 99% rename from Sources/Overload/OvPhysics/src/OvPhysics/Entities/PhysicalObject.cpp rename to Sources/OvPhysics/src/OvPhysics/Entities/PhysicalObject.cpp index 77ef90316..a968aa17d 100644 --- a/Sources/Overload/OvPhysics/src/OvPhysics/Entities/PhysicalObject.cpp +++ b/Sources/OvPhysics/src/OvPhysics/Entities/PhysicalObject.cpp @@ -4,6 +4,8 @@ * @licence: MIT */ +#include + #include #include diff --git a/Sources/Overload/OvPhysics/src/OvPhysics/Entities/PhysicalSphere.cpp b/Sources/OvPhysics/src/OvPhysics/Entities/PhysicalSphere.cpp similarity index 100% rename from Sources/Overload/OvPhysics/src/OvPhysics/Entities/PhysicalSphere.cpp rename to Sources/OvPhysics/src/OvPhysics/Entities/PhysicalSphere.cpp diff --git a/Sources/Overload/OvPhysics/src/OvPhysics/Tools/Conversion.cpp b/Sources/OvPhysics/src/OvPhysics/Tools/Conversion.cpp similarity index 100% rename from Sources/Overload/OvPhysics/src/OvPhysics/Tools/Conversion.cpp rename to Sources/OvPhysics/src/OvPhysics/Tools/Conversion.cpp diff --git a/Sources/Overload/OvRendering/include/OvRendering/Context/Driver.h b/Sources/OvRendering/include/OvRendering/Context/Driver.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Context/Driver.h rename to Sources/OvRendering/include/OvRendering/Context/Driver.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Core/ABaseRenderer.h b/Sources/OvRendering/include/OvRendering/Core/ABaseRenderer.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Core/ABaseRenderer.h rename to Sources/OvRendering/include/OvRendering/Core/ABaseRenderer.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Core/ARenderPass.h b/Sources/OvRendering/include/OvRendering/Core/ARenderPass.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Core/ARenderPass.h rename to Sources/OvRendering/include/OvRendering/Core/ARenderPass.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Core/CompositeRenderer.h b/Sources/OvRendering/include/OvRendering/Core/CompositeRenderer.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Core/CompositeRenderer.h rename to Sources/OvRendering/include/OvRendering/Core/CompositeRenderer.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Core/CompositeRenderer.inl b/Sources/OvRendering/include/OvRendering/Core/CompositeRenderer.inl similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Core/CompositeRenderer.inl rename to Sources/OvRendering/include/OvRendering/Core/CompositeRenderer.inl diff --git a/Sources/Overload/OvRendering/include/OvRendering/Core/IRenderer.h b/Sources/OvRendering/include/OvRendering/Core/IRenderer.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Core/IRenderer.h rename to Sources/OvRendering/include/OvRendering/Core/IRenderer.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Data/Describable.h b/Sources/OvRendering/include/OvRendering/Data/Describable.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Data/Describable.h rename to Sources/OvRendering/include/OvRendering/Data/Describable.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Data/Describable.inl b/Sources/OvRendering/include/OvRendering/Data/Describable.inl similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Data/Describable.inl rename to Sources/OvRendering/include/OvRendering/Data/Describable.inl diff --git a/Sources/Overload/OvRendering/include/OvRendering/Data/FeatureSet.h b/Sources/OvRendering/include/OvRendering/Data/FeatureSet.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Data/FeatureSet.h rename to Sources/OvRendering/include/OvRendering/Data/FeatureSet.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Data/FrameDescriptor.h b/Sources/OvRendering/include/OvRendering/Data/FrameDescriptor.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Data/FrameDescriptor.h rename to Sources/OvRendering/include/OvRendering/Data/FrameDescriptor.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Data/FrameInfo.h b/Sources/OvRendering/include/OvRendering/Data/FrameInfo.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Data/FrameInfo.h rename to Sources/OvRendering/include/OvRendering/Data/FrameInfo.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Data/Frustum.h b/Sources/OvRendering/include/OvRendering/Data/Frustum.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Data/Frustum.h rename to Sources/OvRendering/include/OvRendering/Data/Frustum.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Data/Material.h b/Sources/OvRendering/include/OvRendering/Data/Material.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Data/Material.h rename to Sources/OvRendering/include/OvRendering/Data/Material.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Data/PipelineState.h b/Sources/OvRendering/include/OvRendering/Data/PipelineState.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Data/PipelineState.h rename to Sources/OvRendering/include/OvRendering/Data/PipelineState.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Data/StateMask.h b/Sources/OvRendering/include/OvRendering/Data/StateMask.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Data/StateMask.h rename to Sources/OvRendering/include/OvRendering/Data/StateMask.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Entities/Camera.h b/Sources/OvRendering/include/OvRendering/Entities/Camera.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Entities/Camera.h rename to Sources/OvRendering/include/OvRendering/Entities/Camera.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Entities/Drawable.h b/Sources/OvRendering/include/OvRendering/Entities/Drawable.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Entities/Drawable.h rename to Sources/OvRendering/include/OvRendering/Entities/Drawable.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Entities/Entity.h b/Sources/OvRendering/include/OvRendering/Entities/Entity.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Entities/Entity.h rename to Sources/OvRendering/include/OvRendering/Entities/Entity.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Entities/Light.h b/Sources/OvRendering/include/OvRendering/Entities/Light.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Entities/Light.h rename to Sources/OvRendering/include/OvRendering/Entities/Light.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Features/ARenderFeature.h b/Sources/OvRendering/include/OvRendering/Features/ARenderFeature.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Features/ARenderFeature.h rename to Sources/OvRendering/include/OvRendering/Features/ARenderFeature.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Features/DebugShapeRenderFeature.h b/Sources/OvRendering/include/OvRendering/Features/DebugShapeRenderFeature.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Features/DebugShapeRenderFeature.h rename to Sources/OvRendering/include/OvRendering/Features/DebugShapeRenderFeature.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Features/FrameInfoRenderFeature.h b/Sources/OvRendering/include/OvRendering/Features/FrameInfoRenderFeature.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Features/FrameInfoRenderFeature.h rename to Sources/OvRendering/include/OvRendering/Features/FrameInfoRenderFeature.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Features/LightingRenderFeature.h b/Sources/OvRendering/include/OvRendering/Features/LightingRenderFeature.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Features/LightingRenderFeature.h rename to Sources/OvRendering/include/OvRendering/Features/LightingRenderFeature.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Geometry/BoundingSphere.h b/Sources/OvRendering/include/OvRendering/Geometry/BoundingSphere.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Geometry/BoundingSphere.h rename to Sources/OvRendering/include/OvRendering/Geometry/BoundingSphere.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Geometry/Vertex.h b/Sources/OvRendering/include/OvRendering/Geometry/Vertex.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Geometry/Vertex.h rename to Sources/OvRendering/include/OvRendering/Geometry/Vertex.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/Backend.h b/Sources/OvRendering/include/OvRendering/HAL/Backend.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/Backend.h rename to Sources/OvRendering/include/OvRendering/HAL/Backend.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/Buffer.h b/Sources/OvRendering/include/OvRendering/HAL/Buffer.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/Buffer.h rename to Sources/OvRendering/include/OvRendering/HAL/Buffer.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/Common/TBackend.h b/Sources/OvRendering/include/OvRendering/HAL/Common/TBackend.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/Common/TBackend.h rename to Sources/OvRendering/include/OvRendering/HAL/Common/TBackend.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/Common/TBuffer.h b/Sources/OvRendering/include/OvRendering/HAL/Common/TBuffer.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/Common/TBuffer.h rename to Sources/OvRendering/include/OvRendering/HAL/Common/TBuffer.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/Common/TFramebuffer.h b/Sources/OvRendering/include/OvRendering/HAL/Common/TFramebuffer.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/Common/TFramebuffer.h rename to Sources/OvRendering/include/OvRendering/HAL/Common/TFramebuffer.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/Common/TIndexBuffer.h b/Sources/OvRendering/include/OvRendering/HAL/Common/TIndexBuffer.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/Common/TIndexBuffer.h rename to Sources/OvRendering/include/OvRendering/HAL/Common/TIndexBuffer.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/Common/TRenderbuffer.h b/Sources/OvRendering/include/OvRendering/HAL/Common/TRenderbuffer.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/Common/TRenderbuffer.h rename to Sources/OvRendering/include/OvRendering/HAL/Common/TRenderbuffer.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/Common/TShaderProgram.h b/Sources/OvRendering/include/OvRendering/HAL/Common/TShaderProgram.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/Common/TShaderProgram.h rename to Sources/OvRendering/include/OvRendering/HAL/Common/TShaderProgram.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/Common/TShaderStage.h b/Sources/OvRendering/include/OvRendering/HAL/Common/TShaderStage.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/Common/TShaderStage.h rename to Sources/OvRendering/include/OvRendering/HAL/Common/TShaderStage.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/Common/TShaderStorageBuffer.h b/Sources/OvRendering/include/OvRendering/HAL/Common/TShaderStorageBuffer.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/Common/TShaderStorageBuffer.h rename to Sources/OvRendering/include/OvRendering/HAL/Common/TShaderStorageBuffer.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/Common/TTexture.h b/Sources/OvRendering/include/OvRendering/HAL/Common/TTexture.h similarity index 93% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/Common/TTexture.h rename to Sources/OvRendering/include/OvRendering/HAL/Common/TTexture.h index 2b142b73f..a141daf3c 100644 --- a/Sources/Overload/OvRendering/include/OvRendering/HAL/Common/TTexture.h +++ b/Sources/OvRendering/include/OvRendering/HAL/Common/TTexture.h @@ -88,8 +88,8 @@ namespace OvRendering::HAL const std::string& GetDebugName() const; public: - static OvTools::Eventing::Event CreationEvent; - static OvTools::Eventing::Event DestructionEvent; + inline static OvTools::Eventing::Event CreationEvent; + inline static OvTools::Eventing::Event DestructionEvent; private: TextureContext m_textureContext; diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/Common/TTextureHandle.h b/Sources/OvRendering/include/OvRendering/HAL/Common/TTextureHandle.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/Common/TTextureHandle.h rename to Sources/OvRendering/include/OvRendering/HAL/Common/TTextureHandle.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/Common/TUniformBuffer.h b/Sources/OvRendering/include/OvRendering/HAL/Common/TUniformBuffer.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/Common/TUniformBuffer.h rename to Sources/OvRendering/include/OvRendering/HAL/Common/TUniformBuffer.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/Common/TVertexArray.h b/Sources/OvRendering/include/OvRendering/HAL/Common/TVertexArray.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/Common/TVertexArray.h rename to Sources/OvRendering/include/OvRendering/HAL/Common/TVertexArray.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/Common/TVertexBuffer.h b/Sources/OvRendering/include/OvRendering/HAL/Common/TVertexBuffer.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/Common/TVertexBuffer.h rename to Sources/OvRendering/include/OvRendering/HAL/Common/TVertexBuffer.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/Framebuffer.h b/Sources/OvRendering/include/OvRendering/HAL/Framebuffer.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/Framebuffer.h rename to Sources/OvRendering/include/OvRendering/HAL/Framebuffer.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/IndexBuffer.h b/Sources/OvRendering/include/OvRendering/HAL/IndexBuffer.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/IndexBuffer.h rename to Sources/OvRendering/include/OvRendering/HAL/IndexBuffer.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/None/NoneBackend.h b/Sources/OvRendering/include/OvRendering/HAL/None/NoneBackend.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/None/NoneBackend.h rename to Sources/OvRendering/include/OvRendering/HAL/None/NoneBackend.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/None/NoneBuffer.h b/Sources/OvRendering/include/OvRendering/HAL/None/NoneBuffer.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/None/NoneBuffer.h rename to Sources/OvRendering/include/OvRendering/HAL/None/NoneBuffer.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/None/NoneFramebuffer.h b/Sources/OvRendering/include/OvRendering/HAL/None/NoneFramebuffer.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/None/NoneFramebuffer.h rename to Sources/OvRendering/include/OvRendering/HAL/None/NoneFramebuffer.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/None/NoneIndexBuffer.h b/Sources/OvRendering/include/OvRendering/HAL/None/NoneIndexBuffer.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/None/NoneIndexBuffer.h rename to Sources/OvRendering/include/OvRendering/HAL/None/NoneIndexBuffer.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/None/NoneRenderbuffer.h b/Sources/OvRendering/include/OvRendering/HAL/None/NoneRenderbuffer.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/None/NoneRenderbuffer.h rename to Sources/OvRendering/include/OvRendering/HAL/None/NoneRenderbuffer.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/None/NoneShaderProgram.h b/Sources/OvRendering/include/OvRendering/HAL/None/NoneShaderProgram.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/None/NoneShaderProgram.h rename to Sources/OvRendering/include/OvRendering/HAL/None/NoneShaderProgram.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/None/NoneShaderStage.h b/Sources/OvRendering/include/OvRendering/HAL/None/NoneShaderStage.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/None/NoneShaderStage.h rename to Sources/OvRendering/include/OvRendering/HAL/None/NoneShaderStage.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/None/NoneShaderStorageBuffer.h b/Sources/OvRendering/include/OvRendering/HAL/None/NoneShaderStorageBuffer.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/None/NoneShaderStorageBuffer.h rename to Sources/OvRendering/include/OvRendering/HAL/None/NoneShaderStorageBuffer.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/None/NoneTexture.h b/Sources/OvRendering/include/OvRendering/HAL/None/NoneTexture.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/None/NoneTexture.h rename to Sources/OvRendering/include/OvRendering/HAL/None/NoneTexture.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/None/NoneTextureHandle.h b/Sources/OvRendering/include/OvRendering/HAL/None/NoneTextureHandle.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/None/NoneTextureHandle.h rename to Sources/OvRendering/include/OvRendering/HAL/None/NoneTextureHandle.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/None/NoneUniformBuffer.h b/Sources/OvRendering/include/OvRendering/HAL/None/NoneUniformBuffer.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/None/NoneUniformBuffer.h rename to Sources/OvRendering/include/OvRendering/HAL/None/NoneUniformBuffer.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/None/NoneVertexArray.h b/Sources/OvRendering/include/OvRendering/HAL/None/NoneVertexArray.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/None/NoneVertexArray.h rename to Sources/OvRendering/include/OvRendering/HAL/None/NoneVertexArray.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/None/NoneVertexBuffer.h b/Sources/OvRendering/include/OvRendering/HAL/None/NoneVertexBuffer.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/None/NoneVertexBuffer.h rename to Sources/OvRendering/include/OvRendering/HAL/None/NoneVertexBuffer.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/OpenGL/GLBackend.h b/Sources/OvRendering/include/OvRendering/HAL/OpenGL/GLBackend.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/OpenGL/GLBackend.h rename to Sources/OvRendering/include/OvRendering/HAL/OpenGL/GLBackend.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/OpenGL/GLBuffer.h b/Sources/OvRendering/include/OvRendering/HAL/OpenGL/GLBuffer.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/OpenGL/GLBuffer.h rename to Sources/OvRendering/include/OvRendering/HAL/OpenGL/GLBuffer.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/OpenGL/GLFramebuffer.h b/Sources/OvRendering/include/OvRendering/HAL/OpenGL/GLFramebuffer.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/OpenGL/GLFramebuffer.h rename to Sources/OvRendering/include/OvRendering/HAL/OpenGL/GLFramebuffer.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/OpenGL/GLIndexBuffer.h b/Sources/OvRendering/include/OvRendering/HAL/OpenGL/GLIndexBuffer.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/OpenGL/GLIndexBuffer.h rename to Sources/OvRendering/include/OvRendering/HAL/OpenGL/GLIndexBuffer.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/OpenGL/GLRenderbuffer.h b/Sources/OvRendering/include/OvRendering/HAL/OpenGL/GLRenderbuffer.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/OpenGL/GLRenderbuffer.h rename to Sources/OvRendering/include/OvRendering/HAL/OpenGL/GLRenderbuffer.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/OpenGL/GLShaderProgram.h b/Sources/OvRendering/include/OvRendering/HAL/OpenGL/GLShaderProgram.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/OpenGL/GLShaderProgram.h rename to Sources/OvRendering/include/OvRendering/HAL/OpenGL/GLShaderProgram.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/OpenGL/GLShaderStage.h b/Sources/OvRendering/include/OvRendering/HAL/OpenGL/GLShaderStage.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/OpenGL/GLShaderStage.h rename to Sources/OvRendering/include/OvRendering/HAL/OpenGL/GLShaderStage.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/OpenGL/GLShaderStorageBuffer.h b/Sources/OvRendering/include/OvRendering/HAL/OpenGL/GLShaderStorageBuffer.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/OpenGL/GLShaderStorageBuffer.h rename to Sources/OvRendering/include/OvRendering/HAL/OpenGL/GLShaderStorageBuffer.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/OpenGL/GLTexture.h b/Sources/OvRendering/include/OvRendering/HAL/OpenGL/GLTexture.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/OpenGL/GLTexture.h rename to Sources/OvRendering/include/OvRendering/HAL/OpenGL/GLTexture.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/OpenGL/GLTextureHandle.h b/Sources/OvRendering/include/OvRendering/HAL/OpenGL/GLTextureHandle.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/OpenGL/GLTextureHandle.h rename to Sources/OvRendering/include/OvRendering/HAL/OpenGL/GLTextureHandle.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/OpenGL/GLTypes.h b/Sources/OvRendering/include/OvRendering/HAL/OpenGL/GLTypes.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/OpenGL/GLTypes.h rename to Sources/OvRendering/include/OvRendering/HAL/OpenGL/GLTypes.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/OpenGL/GLUniformBuffer.h b/Sources/OvRendering/include/OvRendering/HAL/OpenGL/GLUniformBuffer.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/OpenGL/GLUniformBuffer.h rename to Sources/OvRendering/include/OvRendering/HAL/OpenGL/GLUniformBuffer.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/OpenGL/GLVertexArray.h b/Sources/OvRendering/include/OvRendering/HAL/OpenGL/GLVertexArray.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/OpenGL/GLVertexArray.h rename to Sources/OvRendering/include/OvRendering/HAL/OpenGL/GLVertexArray.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/OpenGL/GLVertexBuffer.h b/Sources/OvRendering/include/OvRendering/HAL/OpenGL/GLVertexBuffer.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/OpenGL/GLVertexBuffer.h rename to Sources/OvRendering/include/OvRendering/HAL/OpenGL/GLVertexBuffer.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/Profiling.h b/Sources/OvRendering/include/OvRendering/HAL/Profiling.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/Profiling.h rename to Sources/OvRendering/include/OvRendering/HAL/Profiling.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/Renderbuffer.h b/Sources/OvRendering/include/OvRendering/HAL/Renderbuffer.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/Renderbuffer.h rename to Sources/OvRendering/include/OvRendering/HAL/Renderbuffer.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/ShaderProgram.h b/Sources/OvRendering/include/OvRendering/HAL/ShaderProgram.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/ShaderProgram.h rename to Sources/OvRendering/include/OvRendering/HAL/ShaderProgram.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/ShaderStage.h b/Sources/OvRendering/include/OvRendering/HAL/ShaderStage.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/ShaderStage.h rename to Sources/OvRendering/include/OvRendering/HAL/ShaderStage.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/ShaderStorageBuffer.h b/Sources/OvRendering/include/OvRendering/HAL/ShaderStorageBuffer.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/ShaderStorageBuffer.h rename to Sources/OvRendering/include/OvRendering/HAL/ShaderStorageBuffer.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/Texture.h b/Sources/OvRendering/include/OvRendering/HAL/Texture.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/Texture.h rename to Sources/OvRendering/include/OvRendering/HAL/Texture.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/TextureHandle.h b/Sources/OvRendering/include/OvRendering/HAL/TextureHandle.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/TextureHandle.h rename to Sources/OvRendering/include/OvRendering/HAL/TextureHandle.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/UniformBuffer.h b/Sources/OvRendering/include/OvRendering/HAL/UniformBuffer.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/UniformBuffer.h rename to Sources/OvRendering/include/OvRendering/HAL/UniformBuffer.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/VertexArray.h b/Sources/OvRendering/include/OvRendering/HAL/VertexArray.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/VertexArray.h rename to Sources/OvRendering/include/OvRendering/HAL/VertexArray.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/HAL/VertexBuffer.h b/Sources/OvRendering/include/OvRendering/HAL/VertexBuffer.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/HAL/VertexBuffer.h rename to Sources/OvRendering/include/OvRendering/HAL/VertexBuffer.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Resources/IMesh.h b/Sources/OvRendering/include/OvRendering/Resources/IMesh.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Resources/IMesh.h rename to Sources/OvRendering/include/OvRendering/Resources/IMesh.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Resources/Loaders/ModelLoader.h b/Sources/OvRendering/include/OvRendering/Resources/Loaders/ModelLoader.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Resources/Loaders/ModelLoader.h rename to Sources/OvRendering/include/OvRendering/Resources/Loaders/ModelLoader.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Resources/Loaders/ShaderLoader.h b/Sources/OvRendering/include/OvRendering/Resources/Loaders/ShaderLoader.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Resources/Loaders/ShaderLoader.h rename to Sources/OvRendering/include/OvRendering/Resources/Loaders/ShaderLoader.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Resources/Loaders/TextureLoader.h b/Sources/OvRendering/include/OvRendering/Resources/Loaders/TextureLoader.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Resources/Loaders/TextureLoader.h rename to Sources/OvRendering/include/OvRendering/Resources/Loaders/TextureLoader.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Resources/Mesh.h b/Sources/OvRendering/include/OvRendering/Resources/Mesh.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Resources/Mesh.h rename to Sources/OvRendering/include/OvRendering/Resources/Mesh.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Resources/Model.h b/Sources/OvRendering/include/OvRendering/Resources/Model.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Resources/Model.h rename to Sources/OvRendering/include/OvRendering/Resources/Model.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Resources/Parsers/AssimpParser.h b/Sources/OvRendering/include/OvRendering/Resources/Parsers/AssimpParser.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Resources/Parsers/AssimpParser.h rename to Sources/OvRendering/include/OvRendering/Resources/Parsers/AssimpParser.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Resources/Parsers/EModelParserFlags.h b/Sources/OvRendering/include/OvRendering/Resources/Parsers/EModelParserFlags.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Resources/Parsers/EModelParserFlags.h rename to Sources/OvRendering/include/OvRendering/Resources/Parsers/EModelParserFlags.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Resources/Parsers/IModelParser.h b/Sources/OvRendering/include/OvRendering/Resources/Parsers/IModelParser.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Resources/Parsers/IModelParser.h rename to Sources/OvRendering/include/OvRendering/Resources/Parsers/IModelParser.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Resources/Shader.h b/Sources/OvRendering/include/OvRendering/Resources/Shader.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Resources/Shader.h rename to Sources/OvRendering/include/OvRendering/Resources/Shader.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Resources/Texture.h b/Sources/OvRendering/include/OvRendering/Resources/Texture.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Resources/Texture.h rename to Sources/OvRendering/include/OvRendering/Resources/Texture.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/DriverSettings.h b/Sources/OvRendering/include/OvRendering/Settings/DriverSettings.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/DriverSettings.h rename to Sources/OvRendering/include/OvRendering/Settings/DriverSettings.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/EAccessSpecifier.h b/Sources/OvRendering/include/OvRendering/Settings/EAccessSpecifier.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/EAccessSpecifier.h rename to Sources/OvRendering/include/OvRendering/Settings/EAccessSpecifier.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/EBlendingEquation.h b/Sources/OvRendering/include/OvRendering/Settings/EBlendingEquation.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/EBlendingEquation.h rename to Sources/OvRendering/include/OvRendering/Settings/EBlendingEquation.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/EBlendingFactor.h b/Sources/OvRendering/include/OvRendering/Settings/EBlendingFactor.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/EBlendingFactor.h rename to Sources/OvRendering/include/OvRendering/Settings/EBlendingFactor.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/EBlitFlags.h b/Sources/OvRendering/include/OvRendering/Settings/EBlitFlags.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/EBlitFlags.h rename to Sources/OvRendering/include/OvRendering/Settings/EBlitFlags.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/EBufferType.h b/Sources/OvRendering/include/OvRendering/Settings/EBufferType.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/EBufferType.h rename to Sources/OvRendering/include/OvRendering/Settings/EBufferType.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/EComparaisonAlgorithm.h b/Sources/OvRendering/include/OvRendering/Settings/EComparaisonAlgorithm.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/EComparaisonAlgorithm.h rename to Sources/OvRendering/include/OvRendering/Settings/EComparaisonAlgorithm.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/ECullFace.h b/Sources/OvRendering/include/OvRendering/Settings/ECullFace.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/ECullFace.h rename to Sources/OvRendering/include/OvRendering/Settings/ECullFace.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/ECullingOptions.h b/Sources/OvRendering/include/OvRendering/Settings/ECullingOptions.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/ECullingOptions.h rename to Sources/OvRendering/include/OvRendering/Settings/ECullingOptions.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/EDataType.h b/Sources/OvRendering/include/OvRendering/Settings/EDataType.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/EDataType.h rename to Sources/OvRendering/include/OvRendering/Settings/EDataType.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/EFormat.h b/Sources/OvRendering/include/OvRendering/Settings/EFormat.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/EFormat.h rename to Sources/OvRendering/include/OvRendering/Settings/EFormat.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/EFramebufferAttachment.h b/Sources/OvRendering/include/OvRendering/Settings/EFramebufferAttachment.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/EFramebufferAttachment.h rename to Sources/OvRendering/include/OvRendering/Settings/EFramebufferAttachment.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/EGraphicsBackend.h b/Sources/OvRendering/include/OvRendering/Settings/EGraphicsBackend.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/EGraphicsBackend.h rename to Sources/OvRendering/include/OvRendering/Settings/EGraphicsBackend.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/EInternalFormat.h b/Sources/OvRendering/include/OvRendering/Settings/EInternalFormat.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/EInternalFormat.h rename to Sources/OvRendering/include/OvRendering/Settings/EInternalFormat.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/ELightType.h b/Sources/OvRendering/include/OvRendering/Settings/ELightType.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/ELightType.h rename to Sources/OvRendering/include/OvRendering/Settings/ELightType.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/EOperation.h b/Sources/OvRendering/include/OvRendering/Settings/EOperation.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/EOperation.h rename to Sources/OvRendering/include/OvRendering/Settings/EOperation.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/EPixelDataFormat.h b/Sources/OvRendering/include/OvRendering/Settings/EPixelDataFormat.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/EPixelDataFormat.h rename to Sources/OvRendering/include/OvRendering/Settings/EPixelDataFormat.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/EPixelDataType.h b/Sources/OvRendering/include/OvRendering/Settings/EPixelDataType.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/EPixelDataType.h rename to Sources/OvRendering/include/OvRendering/Settings/EPixelDataType.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/EPrimitiveMode.h b/Sources/OvRendering/include/OvRendering/Settings/EPrimitiveMode.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/EPrimitiveMode.h rename to Sources/OvRendering/include/OvRendering/Settings/EPrimitiveMode.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/EProjectionMode.h b/Sources/OvRendering/include/OvRendering/Settings/EProjectionMode.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/EProjectionMode.h rename to Sources/OvRendering/include/OvRendering/Settings/EProjectionMode.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/ERasterizationMode.h b/Sources/OvRendering/include/OvRendering/Settings/ERasterizationMode.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/ERasterizationMode.h rename to Sources/OvRendering/include/OvRendering/Settings/ERasterizationMode.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/ERenderPassOrder.h b/Sources/OvRendering/include/OvRendering/Settings/ERenderPassOrder.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/ERenderPassOrder.h rename to Sources/OvRendering/include/OvRendering/Settings/ERenderPassOrder.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/ERenderingCapability.h b/Sources/OvRendering/include/OvRendering/Settings/ERenderingCapability.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/ERenderingCapability.h rename to Sources/OvRendering/include/OvRendering/Settings/ERenderingCapability.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/EShaderType.h b/Sources/OvRendering/include/OvRendering/Settings/EShaderType.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/EShaderType.h rename to Sources/OvRendering/include/OvRendering/Settings/EShaderType.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/ETextureFilteringMode.h b/Sources/OvRendering/include/OvRendering/Settings/ETextureFilteringMode.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/ETextureFilteringMode.h rename to Sources/OvRendering/include/OvRendering/Settings/ETextureFilteringMode.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/ETextureType.h b/Sources/OvRendering/include/OvRendering/Settings/ETextureType.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/ETextureType.h rename to Sources/OvRendering/include/OvRendering/Settings/ETextureType.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/ETextureWrapMode.h b/Sources/OvRendering/include/OvRendering/Settings/ETextureWrapMode.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/ETextureWrapMode.h rename to Sources/OvRendering/include/OvRendering/Settings/ETextureWrapMode.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/EUniformType.h b/Sources/OvRendering/include/OvRendering/Settings/EUniformType.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/EUniformType.h rename to Sources/OvRendering/include/OvRendering/Settings/EUniformType.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/ShaderCompilationResult.h b/Sources/OvRendering/include/OvRendering/Settings/ShaderCompilationResult.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/ShaderCompilationResult.h rename to Sources/OvRendering/include/OvRendering/Settings/ShaderCompilationResult.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/ShaderLinkingResult.h b/Sources/OvRendering/include/OvRendering/Settings/ShaderLinkingResult.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/ShaderLinkingResult.h rename to Sources/OvRendering/include/OvRendering/Settings/ShaderLinkingResult.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/TextureDesc.h b/Sources/OvRendering/include/OvRendering/Settings/TextureDesc.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/TextureDesc.h rename to Sources/OvRendering/include/OvRendering/Settings/TextureDesc.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/UniformInfo.h b/Sources/OvRendering/include/OvRendering/Settings/UniformInfo.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/UniformInfo.h rename to Sources/OvRendering/include/OvRendering/Settings/UniformInfo.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Settings/VertexAttribute.h b/Sources/OvRendering/include/OvRendering/Settings/VertexAttribute.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Settings/VertexAttribute.h rename to Sources/OvRendering/include/OvRendering/Settings/VertexAttribute.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Types/RenderFeatureType.h b/Sources/OvRendering/include/OvRendering/Types/RenderFeatureType.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Types/RenderFeatureType.h rename to Sources/OvRendering/include/OvRendering/Types/RenderFeatureType.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Types/RenderPassType.h b/Sources/OvRendering/include/OvRendering/Types/RenderPassType.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Types/RenderPassType.h rename to Sources/OvRendering/include/OvRendering/Types/RenderPassType.h diff --git a/Sources/Overload/OvRendering/include/OvRendering/Utils/Conversions.h b/Sources/OvRendering/include/OvRendering/Utils/Conversions.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Utils/Conversions.h rename to Sources/OvRendering/include/OvRendering/Utils/Conversions.h diff --git a/Sources/OvRendering/include/OvRendering/Utils/Defines.h b/Sources/OvRendering/include/OvRendering/Utils/Defines.h new file mode 100644 index 000000000..1e1315865 --- /dev/null +++ b/Sources/OvRendering/include/OvRendering/Utils/Defines.h @@ -0,0 +1,24 @@ +/** +* @project: Overload +* @author: Overload Tech. +* @licence: MIT +*/ + +#pragma once + +#ifdef _WIN32 +#define FORCE_DEDICATED_GPU \ +extern "C"\ +{\ + __declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001;\ + __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;\ +} +#else +// Linux version - use visibility attribute instead of dllexport +#define FORCE_DEDICATED_GPU \ +extern "C"\ +{\ + __attribute__((visibility("default"))) unsigned long NvOptimusEnablement = 0x00000001;\ + __attribute__((visibility("default"))) int AmdPowerXpressRequestHighPerformance = 1;\ +} +#endif diff --git a/Sources/Overload/OvRendering/include/OvRendering/Utils/ShaderUtil.h b/Sources/OvRendering/include/OvRendering/Utils/ShaderUtil.h similarity index 100% rename from Sources/Overload/OvRendering/include/OvRendering/Utils/ShaderUtil.h rename to Sources/OvRendering/include/OvRendering/Utils/ShaderUtil.h diff --git a/Sources/Overload/OvRendering/premake5.lua b/Sources/OvRendering/premake5.lua similarity index 82% rename from Sources/Overload/OvRendering/premake5.lua rename to Sources/OvRendering/premake5.lua index 77a18f8b9..7d37f6600 100644 --- a/Sources/Overload/OvRendering/premake5.lua +++ b/Sources/OvRendering/premake5.lua @@ -21,9 +21,9 @@ project "OvRendering" dependdir .. "tracy", -- Overload SDK - "%{wks.location}/OvDebug/include", - "%{wks.location}/OvMaths/include", - "%{wks.location}/OvTools/include", + "%{wks.location}/Sources/OvDebug/include", + "%{wks.location}/Sources/OvMaths/include", + "%{wks.location}/Sources/OvTools/include", -- Current Project "include" diff --git a/Sources/Overload/OvRendering/src/OvRendering/Context/Driver.cpp b/Sources/OvRendering/src/OvRendering/Context/Driver.cpp similarity index 99% rename from Sources/Overload/OvRendering/src/OvRendering/Context/Driver.cpp rename to Sources/OvRendering/src/OvRendering/Context/Driver.cpp index 417ebf478..4f233e105 100644 --- a/Sources/Overload/OvRendering/src/OvRendering/Context/Driver.cpp +++ b/Sources/OvRendering/src/OvRendering/Context/Driver.cpp @@ -4,6 +4,8 @@ * @licence: MIT */ +#include + #include #include diff --git a/Sources/Overload/OvRendering/src/OvRendering/Core/ABaseRenderer.cpp b/Sources/OvRendering/src/OvRendering/Core/ABaseRenderer.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/Core/ABaseRenderer.cpp rename to Sources/OvRendering/src/OvRendering/Core/ABaseRenderer.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/Core/ARenderPass.cpp b/Sources/OvRendering/src/OvRendering/Core/ARenderPass.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/Core/ARenderPass.cpp rename to Sources/OvRendering/src/OvRendering/Core/ARenderPass.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/Core/CompositeRenderer.cpp b/Sources/OvRendering/src/OvRendering/Core/CompositeRenderer.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/Core/CompositeRenderer.cpp rename to Sources/OvRendering/src/OvRendering/Core/CompositeRenderer.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/Data/Describable.cpp b/Sources/OvRendering/src/OvRendering/Data/Describable.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/Data/Describable.cpp rename to Sources/OvRendering/src/OvRendering/Data/Describable.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/Data/FeatureSet.cpp b/Sources/OvRendering/src/OvRendering/Data/FeatureSet.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/Data/FeatureSet.cpp rename to Sources/OvRendering/src/OvRendering/Data/FeatureSet.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/Data/Frustum.cpp b/Sources/OvRendering/src/OvRendering/Data/Frustum.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/Data/Frustum.cpp rename to Sources/OvRendering/src/OvRendering/Data/Frustum.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/Data/Material.cpp b/Sources/OvRendering/src/OvRendering/Data/Material.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/Data/Material.cpp rename to Sources/OvRendering/src/OvRendering/Data/Material.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/Data/PipelineState.cpp b/Sources/OvRendering/src/OvRendering/Data/PipelineState.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/Data/PipelineState.cpp rename to Sources/OvRendering/src/OvRendering/Data/PipelineState.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/Entities/Camera.cpp b/Sources/OvRendering/src/OvRendering/Entities/Camera.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/Entities/Camera.cpp rename to Sources/OvRendering/src/OvRendering/Entities/Camera.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/Entities/Drawable.cpp b/Sources/OvRendering/src/OvRendering/Entities/Drawable.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/Entities/Drawable.cpp rename to Sources/OvRendering/src/OvRendering/Entities/Drawable.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/Entities/Entity.cpp b/Sources/OvRendering/src/OvRendering/Entities/Entity.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/Entities/Entity.cpp rename to Sources/OvRendering/src/OvRendering/Entities/Entity.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/Entities/Light.cpp b/Sources/OvRendering/src/OvRendering/Entities/Light.cpp similarity index 95% rename from Sources/Overload/OvRendering/src/OvRendering/Entities/Light.cpp rename to Sources/OvRendering/src/OvRendering/Entities/Light.cpp index 1e22121c2..5a13eeb90 100644 --- a/Sources/Overload/OvRendering/src/OvRendering/Entities/Light.cpp +++ b/Sources/OvRendering/src/OvRendering/Entities/Light.cpp @@ -4,6 +4,7 @@ * @licence: MIT */ +#include #include #include @@ -58,6 +59,13 @@ namespace uint32_t Pack(const OvMaths::FVector3& p_toPack) { + OVASSERT( + p_toPack.x >= 0.f && p_toPack.x <= 1.f && + p_toPack.y >= 0.f && p_toPack.y <= 1.f && + p_toPack.z >= 0.f && p_toPack.z <= 1.f, + "Cannot pack color vector, one of its component is out of range [0;1]!" + ); + return Pack(static_cast(p_toPack.x * 255.f), static_cast(p_toPack.y * 255.f), static_cast(p_toPack.z * 255.f), 0); } @@ -134,7 +142,7 @@ OvMaths::FMatrix4 OvRendering::Entities::Light::GenerateMatrix() const result.data[5] = forward.y; result.data[6] = forward.z; - result.data[8] = static_cast(Pack(color)); + result.data[8] = std::bit_cast(Pack(color)); result.data[12] = static_cast(type); result.data[13] = cutoff; diff --git a/Sources/Overload/OvRendering/src/OvRendering/Features/ARenderFeature.cpp b/Sources/OvRendering/src/OvRendering/Features/ARenderFeature.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/Features/ARenderFeature.cpp rename to Sources/OvRendering/src/OvRendering/Features/ARenderFeature.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/Features/DebugShapeRenderFeature.cpp b/Sources/OvRendering/src/OvRendering/Features/DebugShapeRenderFeature.cpp similarity index 77% rename from Sources/Overload/OvRendering/src/OvRendering/Features/DebugShapeRenderFeature.cpp rename to Sources/OvRendering/src/OvRendering/Features/DebugShapeRenderFeature.cpp index 82d1fb270..b5278e987 100644 --- a/Sources/Overload/OvRendering/src/OvRendering/Features/DebugShapeRenderFeature.cpp +++ b/Sources/OvRendering/src/OvRendering/Features/DebugShapeRenderFeature.cpp @@ -4,6 +4,8 @@ * @licence: MIT */ +#include + #include #include #include @@ -146,9 +148,9 @@ void OvRendering::Features::DebugShapeRenderFeature::DrawSphere(OvRendering::Dat { for (float i = 0; i <= 360.0f; i += 10.0f) { - DrawLine(p_pso, p_position + p_rotation * (OvMaths::FVector3{ cos(i * (3.14f / 180.0f)), sin(i * (3.14f / 180.0f)), 0.f } *p_radius), p_position + p_rotation * (OvMaths::FVector3{ cos((i + 10.0f) * (3.14f / 180.0f)), sin((i + 10.0f) * (3.14f / 180.0f)), 0.f } *p_radius), p_color, p_lineWidth, p_depthTest); - DrawLine(p_pso, p_position + p_rotation * (OvMaths::FVector3{ 0.f, sin(i * (3.14f / 180.0f)), cos(i * (3.14f / 180.0f)) } *p_radius), p_position + p_rotation * (OvMaths::FVector3{ 0.f, sin((i + 10.0f) * (3.14f / 180.0f)), cos((i + 10.0f) * (3.14f / 180.0f)) } *p_radius), p_color, p_lineWidth, p_depthTest); - DrawLine(p_pso, p_position + p_rotation * (OvMaths::FVector3{ cos(i * (3.14f / 180.0f)), 0.f, sin(i * (3.14f / 180.0f)) } *p_radius), p_position + p_rotation * (OvMaths::FVector3{ cos((i + 10.0f) * (3.14f / 180.0f)), 0.f, sin((i + 10.0f) * (3.14f / 180.0f)) } *p_radius), p_color, p_lineWidth, p_depthTest); + DrawLine(p_pso, p_position + p_rotation * (OvMaths::FVector3{ cosf(i * (3.14f / 180.0f)), sinf(i * (3.14f / 180.0f)), 0.f } *p_radius), p_position + p_rotation * (OvMaths::FVector3{ cosf((i + 10.0f) * (3.14f / 180.0f)), sinf((i + 10.0f) * (3.14f / 180.0f)), 0.f } *p_radius), p_color, p_lineWidth, p_depthTest); + DrawLine(p_pso, p_position + p_rotation * (OvMaths::FVector3{ 0.f, sinf(i * (3.14f / 180.0f)), cosf(i * (3.14f / 180.0f)) } *p_radius), p_position + p_rotation * (OvMaths::FVector3{ 0.f, sinf((i + 10.0f) * (3.14f / 180.0f)), cosf((i + 10.0f) * (3.14f / 180.0f)) } *p_radius), p_color, p_lineWidth, p_depthTest); + DrawLine(p_pso, p_position + p_rotation * (OvMaths::FVector3{ cosf(i * (3.14f / 180.0f)), 0.f, sinf(i * (3.14f / 180.0f)) } *p_radius), p_position + p_rotation * (OvMaths::FVector3{ cosf((i + 10.0f) * (3.14f / 180.0f)), 0.f, sinf((i + 10.0f) * (3.14f / 180.0f)) } *p_radius), p_color, p_lineWidth, p_depthTest); } } } @@ -163,18 +165,18 @@ void OvRendering::Features::DebugShapeRenderFeature::DrawCapsule(OvRendering::Da for (float i = 0; i < 360.0f; i += 10.0f) { - DrawLine(p_pso, p_position + p_rotation * (hVec + OvMaths::FVector3{ cos(i * (3.14f / 180.0f)), 0.f, sin(i * (3.14f / 180.0f)) } *p_radius), p_position + p_rotation * (hVec + OvMaths::FVector3{ cos((i + 10.0f) * (3.14f / 180.0f)), 0.f, sin((i + 10.0f) * (3.14f / 180.0f)) } *p_radius), p_color, p_lineWidth, p_depthTest); - DrawLine(p_pso, p_position + p_rotation * (-hVec + OvMaths::FVector3{ cos(i * (3.14f / 180.0f)), 0.f, sin(i * (3.14f / 180.0f)) } *p_radius), p_position + p_rotation * (-hVec + OvMaths::FVector3{ cos((i + 10.0f) * (3.14f / 180.0f)), 0.f, sin((i + 10.0f) * (3.14f / 180.0f)) } *p_radius), p_color, p_lineWidth, p_depthTest); + DrawLine(p_pso, p_position + p_rotation * (hVec + OvMaths::FVector3{ cosf(i * (3.14f / 180.0f)), 0.f, sinf(i * (3.14f / 180.0f)) } *p_radius), p_position + p_rotation * (hVec + OvMaths::FVector3{ cosf((i + 10.0f) * (3.14f / 180.0f)), 0.f, sinf((i + 10.0f) * (3.14f / 180.0f)) } *p_radius), p_color, p_lineWidth, p_depthTest); + DrawLine(p_pso, p_position + p_rotation * (-hVec + OvMaths::FVector3{ cosf(i * (3.14f / 180.0f)), 0.f, sinf(i * (3.14f / 180.0f)) } *p_radius), p_position + p_rotation * (-hVec + OvMaths::FVector3{ cosf((i + 10.0f) * (3.14f / 180.0f)), 0.f, sinf((i + 10.0f) * (3.14f / 180.0f)) } *p_radius), p_color, p_lineWidth, p_depthTest); if (i < 180.f) { - DrawLine(p_pso, p_position + p_rotation * (hVec + OvMaths::FVector3{ cos(i * (3.14f / 180.0f)), sin(i * (3.14f / 180.0f)), 0.f } *p_radius), p_position + p_rotation * (hVec + OvMaths::FVector3{ cos((i + 10.0f) * (3.14f / 180.0f)), sin((i + 10.0f) * (3.14f / 180.0f)), 0.f } *p_radius), p_color, p_lineWidth, p_depthTest); - DrawLine(p_pso, p_position + p_rotation * (hVec + OvMaths::FVector3{ 0.f, sin(i * (3.14f / 180.0f)), cos(i * (3.14f / 180.0f)) } *p_radius), p_position + p_rotation * (hVec + OvMaths::FVector3{ 0.f, sin((i + 10.0f) * (3.14f / 180.0f)), cos((i + 10.0f) * (3.14f / 180.0f)) } *p_radius), p_color, p_lineWidth, p_depthTest); + DrawLine(p_pso, p_position + p_rotation * (hVec + OvMaths::FVector3{ cosf(i * (3.14f / 180.0f)), sinf(i * (3.14f / 180.0f)), 0.f } *p_radius), p_position + p_rotation * (hVec + OvMaths::FVector3{ cosf((i + 10.0f) * (3.14f / 180.0f)), sinf((i + 10.0f) * (3.14f / 180.0f)), 0.f } *p_radius), p_color, p_lineWidth, p_depthTest); + DrawLine(p_pso, p_position + p_rotation * (hVec + OvMaths::FVector3{ 0.f, sinf(i * (3.14f / 180.0f)), cosf(i * (3.14f / 180.0f)) } *p_radius), p_position + p_rotation * (hVec + OvMaths::FVector3{ 0.f, sinf((i + 10.0f) * (3.14f / 180.0f)), cosf((i + 10.0f) * (3.14f / 180.0f)) } *p_radius), p_color, p_lineWidth, p_depthTest); } else { - DrawLine(p_pso, p_position + p_rotation * (-hVec + OvMaths::FVector3{ cos(i * (3.14f / 180.0f)), sin(i * (3.14f / 180.0f)), 0.f } *p_radius), p_position + p_rotation * (-hVec + OvMaths::FVector3{ cos((i + 10.0f) * (3.14f / 180.0f)), sin((i + 10.0f) * (3.14f / 180.0f)), 0.f } *p_radius), p_color, p_lineWidth, p_depthTest); - DrawLine(p_pso, p_position + p_rotation * (-hVec + OvMaths::FVector3{ 0.f, sin(i * (3.14f / 180.0f)), cos(i * (3.14f / 180.0f)) } *p_radius), p_position + p_rotation * (-hVec + OvMaths::FVector3{ 0.f, sin((i + 10.0f) * (3.14f / 180.0f)), cos((i + 10.0f) * (3.14f / 180.0f)) } *p_radius), p_color, p_lineWidth, p_depthTest); + DrawLine(p_pso, p_position + p_rotation * (-hVec + OvMaths::FVector3{ cosf(i * (3.14f / 180.0f)), sinf(i * (3.14f / 180.0f)), 0.f } *p_radius), p_position + p_rotation * (-hVec + OvMaths::FVector3{ cosf((i + 10.0f) * (3.14f / 180.0f)), sinf((i + 10.0f) * (3.14f / 180.0f)), 0.f } *p_radius), p_color, p_lineWidth, p_depthTest); + DrawLine(p_pso, p_position + p_rotation * (-hVec + OvMaths::FVector3{ 0.f, sinf(i * (3.14f / 180.0f)), cosf(i * (3.14f / 180.0f)) } *p_radius), p_position + p_rotation * (-hVec + OvMaths::FVector3{ 0.f, sinf((i + 10.0f) * (3.14f / 180.0f)), cosf((i + 10.0f) * (3.14f / 180.0f)) } *p_radius), p_color, p_lineWidth, p_depthTest); } } diff --git a/Sources/Overload/OvRendering/src/OvRendering/Features/FrameInfoRenderFeature.cpp b/Sources/OvRendering/src/OvRendering/Features/FrameInfoRenderFeature.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/Features/FrameInfoRenderFeature.cpp rename to Sources/OvRendering/src/OvRendering/Features/FrameInfoRenderFeature.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/Features/LightingRenderFeature.cpp b/Sources/OvRendering/src/OvRendering/Features/LightingRenderFeature.cpp similarity index 99% rename from Sources/Overload/OvRendering/src/OvRendering/Features/LightingRenderFeature.cpp rename to Sources/OvRendering/src/OvRendering/Features/LightingRenderFeature.cpp index 1e346758b..6acbc3cfc 100644 --- a/Sources/Overload/OvRendering/src/OvRendering/Features/LightingRenderFeature.cpp +++ b/Sources/OvRendering/src/OvRendering/Features/LightingRenderFeature.cpp @@ -4,6 +4,8 @@ * @licence: MIT */ +#include + #include "OvRendering/Features/LightingRenderFeature.h" #include "OvRendering/Core/CompositeRenderer.h" diff --git a/Sources/Overload/OvRendering/src/OvRendering/HAL/None/NoneBackend.cpp b/Sources/OvRendering/src/OvRendering/HAL/None/NoneBackend.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/HAL/None/NoneBackend.cpp rename to Sources/OvRendering/src/OvRendering/HAL/None/NoneBackend.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/HAL/None/NoneBuffer.cpp b/Sources/OvRendering/src/OvRendering/HAL/None/NoneBuffer.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/HAL/None/NoneBuffer.cpp rename to Sources/OvRendering/src/OvRendering/HAL/None/NoneBuffer.cpp index 18b142674..f4049a3d3 100644 --- a/Sources/Overload/OvRendering/src/OvRendering/HAL/None/NoneBuffer.cpp +++ b/Sources/OvRendering/src/OvRendering/HAL/None/NoneBuffer.cpp @@ -26,43 +26,43 @@ uint64_t OvRendering::HAL::NoneBuffer::Allocate(size_t p_size, Settings::EAccess } template<> -void OvRendering::HAL::NoneBuffer::Upload(const void* p_data, std::optional p_range) +bool OvRendering::HAL::NoneBuffer::IsValid() const { - OVASSERT(IsValid(), "Trying to upload data to an invalid buffer"); - OVASSERT(!IsEmpty(), "Trying to upload data to an empty buffer"); + return + m_buffer.type != Settings::EBufferType::UNKNOWN && + m_buffer.allocatedBytes > 0; } template<> -void OvRendering::HAL::NoneBuffer::Bind(std::optional p_index) const +uint64_t OvRendering::HAL::NoneBuffer::GetSize() const { - OVASSERT(IsValid(), "Cannot bind an invalid buffer"); + OVASSERT(IsValid(), "Cannot get size of an invalid buffer"); + return m_buffer.allocatedBytes; } template<> -void OvRendering::HAL::NoneBuffer::Unbind() const +bool OvRendering::HAL::NoneBuffer::IsEmpty() const { - OVASSERT(IsValid(), "Cannot unbind an invalid buffer"); + return GetSize() == 0; } template<> -bool OvRendering::HAL::NoneBuffer::IsValid() const +void OvRendering::HAL::NoneBuffer::Upload(const void* p_data, std::optional p_range) { - return - m_buffer.type != Settings::EBufferType::UNKNOWN && - m_buffer.allocatedBytes > 0; + OVASSERT(IsValid(), "Trying to upload data to an invalid buffer"); + OVASSERT(!IsEmpty(), "Trying to upload data to an empty buffer"); } template<> -bool OvRendering::HAL::NoneBuffer::IsEmpty() const +void OvRendering::HAL::NoneBuffer::Bind(std::optional p_index) const { - return GetSize() == 0; + OVASSERT(IsValid(), "Cannot bind an invalid buffer"); } template<> -uint64_t OvRendering::HAL::NoneBuffer::GetSize() const +void OvRendering::HAL::NoneBuffer::Unbind() const { - OVASSERT(IsValid(), "Cannot get size of an invalid buffer"); - return m_buffer.allocatedBytes; + OVASSERT(IsValid(), "Cannot unbind an invalid buffer"); } template<> diff --git a/Sources/Overload/OvRendering/src/OvRendering/HAL/None/NoneFramebuffer.cpp b/Sources/OvRendering/src/OvRendering/HAL/None/NoneFramebuffer.cpp similarity index 99% rename from Sources/Overload/OvRendering/src/OvRendering/HAL/None/NoneFramebuffer.cpp rename to Sources/OvRendering/src/OvRendering/HAL/None/NoneFramebuffer.cpp index 3f1f6e795..f705f9679 100644 --- a/Sources/Overload/OvRendering/src/OvRendering/HAL/None/NoneFramebuffer.cpp +++ b/Sources/OvRendering/src/OvRendering/HAL/None/NoneFramebuffer.cpp @@ -48,6 +48,7 @@ void OvRendering::HAL::NoneFramebuffer::Unbind() const { } +template<> bool OvRendering::HAL::NoneFramebuffer::Validate() { return m_context.valid = true; diff --git a/Sources/Overload/OvRendering/src/OvRendering/HAL/None/NoneIndexBuffer.cpp b/Sources/OvRendering/src/OvRendering/HAL/None/NoneIndexBuffer.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/HAL/None/NoneIndexBuffer.cpp rename to Sources/OvRendering/src/OvRendering/HAL/None/NoneIndexBuffer.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/HAL/None/NoneRenderbuffer.cpp b/Sources/OvRendering/src/OvRendering/HAL/None/NoneRenderbuffer.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/HAL/None/NoneRenderbuffer.cpp rename to Sources/OvRendering/src/OvRendering/HAL/None/NoneRenderbuffer.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/HAL/None/NoneShaderProgram.cpp b/Sources/OvRendering/src/OvRendering/HAL/None/NoneShaderProgram.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/HAL/None/NoneShaderProgram.cpp rename to Sources/OvRendering/src/OvRendering/HAL/None/NoneShaderProgram.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/HAL/None/NoneShaderStage.cpp b/Sources/OvRendering/src/OvRendering/HAL/None/NoneShaderStage.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/HAL/None/NoneShaderStage.cpp rename to Sources/OvRendering/src/OvRendering/HAL/None/NoneShaderStage.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/HAL/None/NoneShaderStorageBuffer.cpp b/Sources/OvRendering/src/OvRendering/HAL/None/NoneShaderStorageBuffer.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/HAL/None/NoneShaderStorageBuffer.cpp rename to Sources/OvRendering/src/OvRendering/HAL/None/NoneShaderStorageBuffer.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/HAL/None/NoneTexture.cpp b/Sources/OvRendering/src/OvRendering/HAL/None/NoneTexture.cpp similarity index 92% rename from Sources/Overload/OvRendering/src/OvRendering/HAL/None/NoneTexture.cpp rename to Sources/OvRendering/src/OvRendering/HAL/None/NoneTexture.cpp index 79c5fe915..86c89a142 100644 --- a/Sources/Overload/OvRendering/src/OvRendering/HAL/None/NoneTexture.cpp +++ b/Sources/OvRendering/src/OvRendering/HAL/None/NoneTexture.cpp @@ -8,9 +8,6 @@ #include -OvTools::Eventing::Event OvRendering::HAL::NoneTexture::CreationEvent; -OvTools::Eventing::Event OvRendering::HAL::NoneTexture::DestructionEvent; - template<> OvRendering::HAL::NoneTexture::TTexture(Settings::ETextureType p_type, std::string_view p_debugName) : TTextureHandle{ p_type, 0 } { diff --git a/Sources/Overload/OvRendering/src/OvRendering/HAL/None/NoneTextureHandle.cpp b/Sources/OvRendering/src/OvRendering/HAL/None/NoneTextureHandle.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/HAL/None/NoneTextureHandle.cpp rename to Sources/OvRendering/src/OvRendering/HAL/None/NoneTextureHandle.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/HAL/None/NoneUniformBuffer.cpp b/Sources/OvRendering/src/OvRendering/HAL/None/NoneUniformBuffer.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/HAL/None/NoneUniformBuffer.cpp rename to Sources/OvRendering/src/OvRendering/HAL/None/NoneUniformBuffer.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/HAL/None/NoneVertexArray.cpp b/Sources/OvRendering/src/OvRendering/HAL/None/NoneVertexArray.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/HAL/None/NoneVertexArray.cpp rename to Sources/OvRendering/src/OvRendering/HAL/None/NoneVertexArray.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/HAL/None/NoneVertexBuffer.cpp b/Sources/OvRendering/src/OvRendering/HAL/None/NoneVertexBuffer.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/HAL/None/NoneVertexBuffer.cpp rename to Sources/OvRendering/src/OvRendering/HAL/None/NoneVertexBuffer.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLBackend.cpp b/Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLBackend.cpp similarity index 99% rename from Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLBackend.cpp rename to Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLBackend.cpp index b1fbd7dcc..bdb037697 100644 --- a/Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLBackend.cpp +++ b/Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLBackend.cpp @@ -4,8 +4,6 @@ * @licence: MIT */ -#pragma once - #include #include diff --git a/Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLBuffer.cpp b/Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLBuffer.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLBuffer.cpp rename to Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLBuffer.cpp index ee0391c87..3534bd65a 100644 --- a/Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLBuffer.cpp +++ b/Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLBuffer.cpp @@ -24,6 +24,27 @@ OvRendering::HAL::GLBuffer::~TBuffer() glDeleteBuffers(1, &m_buffer.id); } +template<> +bool OvRendering::HAL::GLBuffer::IsValid() const +{ + return + m_buffer.id != 0 && + m_buffer.type != Settings::EBufferType::UNKNOWN; +} + +template<> +uint64_t OvRendering::HAL::GLBuffer::GetSize() const +{ + OVASSERT(IsValid(), "Cannot get size of an invalid buffer"); + return m_buffer.allocatedBytes; +} + +template<> +bool OvRendering::HAL::GLBuffer::IsEmpty() const +{ + return GetSize() == 0; +} + template<> uint64_t OvRendering::HAL::GLBuffer::Allocate(uint64_t p_size, Settings::EAccessSpecifier p_usage) { @@ -68,27 +89,6 @@ void OvRendering::HAL::GLBuffer::Unbind() const glBindBuffer(EnumToValue(m_buffer.type), 0); } -template<> -bool OvRendering::HAL::GLBuffer::IsValid() const -{ - return - m_buffer.id != 0 && - m_buffer.type != Settings::EBufferType::UNKNOWN; -} - -template<> -bool OvRendering::HAL::GLBuffer::IsEmpty() const -{ - return GetSize() == 0; -} - -template<> -uint64_t OvRendering::HAL::GLBuffer::GetSize() const -{ - OVASSERT(IsValid(), "Cannot get size of an invalid buffer"); - return m_buffer.allocatedBytes; -} - template<> uint32_t OvRendering::HAL::GLBuffer::GetID() const { diff --git a/Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLFramebuffer.cpp b/Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLFramebuffer.cpp similarity index 99% rename from Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLFramebuffer.cpp rename to Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLFramebuffer.cpp index 014d2edbc..ae75c5a28 100644 --- a/Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLFramebuffer.cpp +++ b/Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLFramebuffer.cpp @@ -80,6 +80,7 @@ void OvRendering::HAL::GLFramebuffer::Unbind() const glBindFramebuffer(GL_FRAMEBUFFER, 0); } +template<> bool OvRendering::HAL::GLFramebuffer::Validate() { const GLenum status = glCheckNamedFramebufferStatus(m_context.id, GL_FRAMEBUFFER); diff --git a/Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLIndexBuffer.cpp b/Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLIndexBuffer.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLIndexBuffer.cpp rename to Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLIndexBuffer.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLRenderbuffer.cpp b/Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLRenderbuffer.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLRenderbuffer.cpp rename to Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLRenderbuffer.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLShaderProgram.cpp b/Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLShaderProgram.cpp similarity index 99% rename from Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLShaderProgram.cpp rename to Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLShaderProgram.cpp index 751168bf3..3185f70a1 100644 --- a/Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLShaderProgram.cpp +++ b/Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLShaderProgram.cpp @@ -5,6 +5,7 @@ */ #include +#include #include @@ -84,35 +85,6 @@ void OvRendering::HAL::GLShaderProgram::DetachAll() m_context.attachedShaders.clear(); } -template<> -OvRendering::Settings::ShaderLinkingResult OvRendering::HAL::GLShaderProgram::Link() -{ - glLinkProgram(m_context.id); - - GLint linkStatus; - glGetProgramiv(m_context.id, GL_LINK_STATUS, &linkStatus); - - if (linkStatus == GL_FALSE) - { - GLint maxLength; - glGetProgramiv(m_context.id, GL_INFO_LOG_LENGTH, &maxLength); - - std::string errorLog(maxLength, ' '); - glGetProgramInfoLog(m_context.id, maxLength, &maxLength, errorLog.data()); - - return { - .success = false, - .message = errorLog - }; - } - - QueryUniforms(); - - return { - .success = true - }; -} - #define DECLARE_GET_UNIFORM_FUNCTION(type, glType, func) \ template<> \ template<> \ @@ -217,6 +189,35 @@ void OvRendering::HAL::GLShaderProgram::QueryUniforms() } } +template<> +OvRendering::Settings::ShaderLinkingResult OvRendering::HAL::GLShaderProgram::Link() +{ + glLinkProgram(m_context.id); + + GLint linkStatus; + glGetProgramiv(m_context.id, GL_LINK_STATUS, &linkStatus); + + if (linkStatus == GL_FALSE) + { + GLint maxLength; + glGetProgramiv(m_context.id, GL_INFO_LOG_LENGTH, &maxLength); + + std::string errorLog(maxLength, ' '); + glGetProgramInfoLog(m_context.id, maxLength, &maxLength, errorLog.data()); + + return { + .success = false, + .message = errorLog + }; + } + + QueryUniforms(); + + return { + .success = true + }; +} + template<> OvTools::Utils::OptRef OvRendering::HAL::GLShaderProgram::GetUniformInfo(const std::string& p_name) const { diff --git a/Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLShaderStage.cpp b/Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLShaderStage.cpp similarity index 97% rename from Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLShaderStage.cpp rename to Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLShaderStage.cpp index 34d21cf0e..4acadf3d7 100644 --- a/Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLShaderStage.cpp +++ b/Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLShaderStage.cpp @@ -51,7 +51,7 @@ OvRendering::Settings::ShaderCompilationResult OvRendering::HAL::GLShaderStage:: glGetShaderInfoLog(m_context.id, maxLength, &maxLength, errorLog.data()); std::string shaderTypeStr = Utils::GetShaderTypeName(m_context.type); - std::transform(shaderTypeStr.begin(), shaderTypeStr.end(), shaderTypeStr.begin(), std::toupper); + std::transform(shaderTypeStr.begin(), shaderTypeStr.end(), shaderTypeStr.begin(), toupper); std::string errorHeader = "[" + shaderTypeStr + " SHADER] \""; return { diff --git a/Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLShaderStorageBuffer.cpp b/Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLShaderStorageBuffer.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLShaderStorageBuffer.cpp rename to Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLShaderStorageBuffer.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLTexture.cpp b/Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLTexture.cpp similarity index 95% rename from Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLTexture.cpp rename to Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLTexture.cpp index a9cb3a4dd..0fefb58d4 100644 --- a/Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLTexture.cpp +++ b/Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLTexture.cpp @@ -11,15 +11,20 @@ #include #include -OvTools::Eventing::Event OvRendering::HAL::GLTexture::CreationEvent; -OvTools::Eventing::Event OvRendering::HAL::GLTexture::DestructionEvent; - namespace { constexpr uint32_t CalculateMipMapLevels(uint32_t p_width, uint32_t p_height) { uint32_t maxDim = p_width > p_height ? p_width : p_height; - return maxDim ? 32u - __lzcnt(maxDim) : 1u; + + uint32_t levels = 0; + while (maxDim > 1) + { + maxDim >>= 1; + ++levels; + } + + return levels ? levels + 1 : 1u; } constexpr bool IsValidMipMapFilter(OvRendering::Settings::ETextureFilteringMode p_mode) diff --git a/Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLTextureHandle.cpp b/Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLTextureHandle.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLTextureHandle.cpp rename to Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLTextureHandle.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLUniformBuffer.cpp b/Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLUniformBuffer.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLUniformBuffer.cpp rename to Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLUniformBuffer.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLVertexArray.cpp b/Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLVertexArray.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLVertexArray.cpp rename to Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLVertexArray.cpp index 3c65edeb5..a2c70a428 100644 --- a/Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLVertexArray.cpp +++ b/Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLVertexArray.cpp @@ -59,6 +59,18 @@ bool OvRendering::HAL::GLVertexArray::IsValid() const return m_context.attributeCount > 0; } +template<> +void OvRendering::HAL::GLVertexArray::Bind() const +{ + glBindVertexArray(m_context.id); +} + +template<> +void OvRendering::HAL::GLVertexArray::Unbind() const +{ + glBindVertexArray(0); +} + template<> void OvRendering::HAL::GLVertexArray::SetLayout( Settings::VertexAttributeLayout p_attributes, @@ -118,18 +130,6 @@ void OvRendering::HAL::GLVertexArray::ResetLayout() Unbind(); } -template<> -void OvRendering::HAL::GLVertexArray::Bind() const -{ - glBindVertexArray(m_context.id); -} - -template<> -void OvRendering::HAL::GLVertexArray::Unbind() const -{ - glBindVertexArray(0); -} - template<> uint32_t OvRendering::HAL::GLVertexArray::GetID() const { diff --git a/Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLVertexBuffer.cpp b/Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLVertexBuffer.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/HAL/OpenGL/GLVertexBuffer.cpp rename to Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLVertexBuffer.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/Resources/Loaders/ModelLoader.cpp b/Sources/OvRendering/src/OvRendering/Resources/Loaders/ModelLoader.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/Resources/Loaders/ModelLoader.cpp rename to Sources/OvRendering/src/OvRendering/Resources/Loaders/ModelLoader.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/Resources/Loaders/ShaderLoader.cpp b/Sources/OvRendering/src/OvRendering/Resources/Loaders/ShaderLoader.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/Resources/Loaders/ShaderLoader.cpp rename to Sources/OvRendering/src/OvRendering/Resources/Loaders/ShaderLoader.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/Resources/Loaders/TextureLoader.cpp b/Sources/OvRendering/src/OvRendering/Resources/Loaders/TextureLoader.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/Resources/Loaders/TextureLoader.cpp rename to Sources/OvRendering/src/OvRendering/Resources/Loaders/TextureLoader.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/Resources/Mesh.cpp b/Sources/OvRendering/src/OvRendering/Resources/Mesh.cpp similarity index 98% rename from Sources/Overload/OvRendering/src/OvRendering/Resources/Mesh.cpp rename to Sources/OvRendering/src/OvRendering/Resources/Mesh.cpp index 252a0e892..6e45ddc81 100644 --- a/Sources/Overload/OvRendering/src/OvRendering/Resources/Mesh.cpp +++ b/Sources/OvRendering/src/OvRendering/Resources/Mesh.cpp @@ -5,6 +5,8 @@ */ #include +#include +#include #include #include diff --git a/Sources/Overload/OvRendering/src/OvRendering/Resources/Model.cpp b/Sources/OvRendering/src/OvRendering/Resources/Model.cpp similarity index 99% rename from Sources/Overload/OvRendering/src/OvRendering/Resources/Model.cpp rename to Sources/OvRendering/src/OvRendering/Resources/Model.cpp index 891186e6b..cc827fd0a 100644 --- a/Sources/Overload/OvRendering/src/OvRendering/Resources/Model.cpp +++ b/Sources/OvRendering/src/OvRendering/Resources/Model.cpp @@ -5,6 +5,7 @@ */ #include +#include #include "OvRendering/Resources/Model.h" diff --git a/Sources/Overload/OvRendering/src/OvRendering/Resources/Parsers/AssimpParser.cpp b/Sources/OvRendering/src/OvRendering/Resources/Parsers/AssimpParser.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/Resources/Parsers/AssimpParser.cpp rename to Sources/OvRendering/src/OvRendering/Resources/Parsers/AssimpParser.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/Resources/Shader.cpp b/Sources/OvRendering/src/OvRendering/Resources/Shader.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/Resources/Shader.cpp rename to Sources/OvRendering/src/OvRendering/Resources/Shader.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/Resources/Texture.cpp b/Sources/OvRendering/src/OvRendering/Resources/Texture.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/Resources/Texture.cpp rename to Sources/OvRendering/src/OvRendering/Resources/Texture.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/Utils/Conversions.cpp b/Sources/OvRendering/src/OvRendering/Utils/Conversions.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/Utils/Conversions.cpp rename to Sources/OvRendering/src/OvRendering/Utils/Conversions.cpp diff --git a/Sources/Overload/OvRendering/src/OvRendering/Utils/ShaderUtil.cpp b/Sources/OvRendering/src/OvRendering/Utils/ShaderUtil.cpp similarity index 100% rename from Sources/Overload/OvRendering/src/OvRendering/Utils/ShaderUtil.cpp rename to Sources/OvRendering/src/OvRendering/Utils/ShaderUtil.cpp diff --git a/Sources/Overload/OvTools/include/OvTools/Eventing/Event.h b/Sources/OvTools/include/OvTools/Eventing/Event.h similarity index 98% rename from Sources/Overload/OvTools/include/OvTools/Eventing/Event.h rename to Sources/OvTools/include/OvTools/Eventing/Event.h index 7f7f6440e..e7d41b6f8 100644 --- a/Sources/Overload/OvTools/include/OvTools/Eventing/Event.h +++ b/Sources/OvTools/include/OvTools/Eventing/Event.h @@ -6,9 +6,9 @@ #pragma once +#include #include - namespace OvTools::Eventing { /** diff --git a/Sources/Overload/OvTools/include/OvTools/Eventing/Event.inl b/Sources/OvTools/include/OvTools/Eventing/Event.inl similarity index 100% rename from Sources/Overload/OvTools/include/OvTools/Eventing/Event.inl rename to Sources/OvTools/include/OvTools/Eventing/Event.inl diff --git a/Sources/Overload/OvTools/include/OvTools/Filesystem/IniFile.h b/Sources/OvTools/include/OvTools/Filesystem/IniFile.h similarity index 100% rename from Sources/Overload/OvTools/include/OvTools/Filesystem/IniFile.h rename to Sources/OvTools/include/OvTools/Filesystem/IniFile.h diff --git a/Sources/Overload/OvTools/include/OvTools/Filesystem/IniFile.inl b/Sources/OvTools/include/OvTools/Filesystem/IniFile.inl similarity index 100% rename from Sources/Overload/OvTools/include/OvTools/Filesystem/IniFile.inl rename to Sources/OvTools/include/OvTools/Filesystem/IniFile.inl diff --git a/Sources/Overload/OvTools/include/OvTools/Profiling/TracyAllocators.h b/Sources/OvTools/include/OvTools/Profiling/TracyAllocators.h similarity index 100% rename from Sources/Overload/OvTools/include/OvTools/Profiling/TracyAllocators.h rename to Sources/OvTools/include/OvTools/Profiling/TracyAllocators.h diff --git a/Sources/Overload/OvTools/include/OvTools/Time/Clock.h b/Sources/OvTools/include/OvTools/Time/Clock.h similarity index 100% rename from Sources/Overload/OvTools/include/OvTools/Time/Clock.h rename to Sources/OvTools/include/OvTools/Time/Clock.h diff --git a/Sources/Overload/OvTools/include/OvTools/Time/Date.h b/Sources/OvTools/include/OvTools/Time/Date.h similarity index 100% rename from Sources/Overload/OvTools/include/OvTools/Time/Date.h rename to Sources/OvTools/include/OvTools/Time/Date.h diff --git a/Sources/Overload/OvTools/include/OvTools/Utils/CircularIterator.h b/Sources/OvTools/include/OvTools/Utils/CircularIterator.h similarity index 100% rename from Sources/Overload/OvTools/include/OvTools/Utils/CircularIterator.h rename to Sources/OvTools/include/OvTools/Utils/CircularIterator.h diff --git a/Sources/Overload/OvTools/include/OvTools/Utils/EnumMapper.h b/Sources/OvTools/include/OvTools/Utils/EnumMapper.h similarity index 100% rename from Sources/Overload/OvTools/include/OvTools/Utils/EnumMapper.h rename to Sources/OvTools/include/OvTools/Utils/EnumMapper.h diff --git a/Sources/Overload/OvTools/include/OvTools/Utils/OptRef.h b/Sources/OvTools/include/OvTools/Utils/OptRef.h similarity index 98% rename from Sources/Overload/OvTools/include/OvTools/Utils/OptRef.h rename to Sources/OvTools/include/OvTools/Utils/OptRef.h index eb745c434..8c2f68b56 100644 --- a/Sources/Overload/OvTools/include/OvTools/Utils/OptRef.h +++ b/Sources/OvTools/include/OvTools/Utils/OptRef.h @@ -6,6 +6,7 @@ #pragma once +#include #include namespace OvTools::Utils diff --git a/Sources/Overload/OvTools/include/OvTools/Utils/PathParser.h b/Sources/OvTools/include/OvTools/Utils/PathParser.h similarity index 100% rename from Sources/Overload/OvTools/include/OvTools/Utils/PathParser.h rename to Sources/OvTools/include/OvTools/Utils/PathParser.h diff --git a/Sources/Overload/OvTools/include/OvTools/Utils/Random.h b/Sources/OvTools/include/OvTools/Utils/Random.h similarity index 100% rename from Sources/Overload/OvTools/include/OvTools/Utils/Random.h rename to Sources/OvTools/include/OvTools/Utils/Random.h diff --git a/Sources/Overload/OvTools/include/OvTools/Utils/ReferenceOrValue.h b/Sources/OvTools/include/OvTools/Utils/ReferenceOrValue.h similarity index 100% rename from Sources/Overload/OvTools/include/OvTools/Utils/ReferenceOrValue.h rename to Sources/OvTools/include/OvTools/Utils/ReferenceOrValue.h diff --git a/Sources/Overload/OvTools/include/OvTools/Utils/SizeConverter.h b/Sources/OvTools/include/OvTools/Utils/SizeConverter.h similarity index 100% rename from Sources/Overload/OvTools/include/OvTools/Utils/SizeConverter.h rename to Sources/OvTools/include/OvTools/Utils/SizeConverter.h diff --git a/Sources/Overload/OvTools/include/OvTools/Utils/String.h b/Sources/OvTools/include/OvTools/Utils/String.h similarity index 96% rename from Sources/Overload/OvTools/include/OvTools/Utils/String.h rename to Sources/OvTools/include/OvTools/Utils/String.h index ab1e45ec0..9024f870a 100644 --- a/Sources/Overload/OvTools/include/OvTools/Utils/String.h +++ b/Sources/OvTools/include/OvTools/Utils/String.h @@ -57,6 +57,6 @@ namespace OvTools::Utils * @param p_str String to trim * @param p_trimOptions The desired trim options, default is trimming left and right */ - static void Trim(std::string& p_str, const TrimOptions p_trimOptions = {}); + static void Trim(std::string& p_str, const TrimOptions p_trimOptions = TrimOptions{.left = true, .right = true}); }; } diff --git a/Sources/Overload/OvTools/include/OvTools/Utils/SystemCalls.h b/Sources/OvTools/include/OvTools/Utils/SystemCalls.h similarity index 100% rename from Sources/Overload/OvTools/include/OvTools/Utils/SystemCalls.h rename to Sources/OvTools/include/OvTools/Utils/SystemCalls.h diff --git a/Sources/Overload/OvTools/premake5.lua b/Sources/OvTools/premake5.lua similarity index 100% rename from Sources/Overload/OvTools/premake5.lua rename to Sources/OvTools/premake5.lua diff --git a/Sources/Overload/OvTools/src/OvTools/Filesystem/IniFile.cpp b/Sources/OvTools/src/OvTools/Filesystem/IniFile.cpp similarity index 99% rename from Sources/Overload/OvTools/src/OvTools/Filesystem/IniFile.cpp rename to Sources/OvTools/src/OvTools/Filesystem/IniFile.cpp index 5727c9f60..aa556ffcf 100644 --- a/Sources/Overload/OvTools/src/OvTools/Filesystem/IniFile.cpp +++ b/Sources/OvTools/src/OvTools/Filesystem/IniFile.cpp @@ -7,6 +7,7 @@ #include #include +#include #include namespace diff --git a/Sources/Overload/OvTools/src/OvTools/Time/Clock.cpp b/Sources/OvTools/src/OvTools/Time/Clock.cpp similarity index 100% rename from Sources/Overload/OvTools/src/OvTools/Time/Clock.cpp rename to Sources/OvTools/src/OvTools/Time/Clock.cpp diff --git a/Sources/Overload/OvTools/src/OvTools/Time/Date.cpp b/Sources/OvTools/src/OvTools/Time/Date.cpp similarity index 91% rename from Sources/Overload/OvTools/src/OvTools/Time/Date.cpp rename to Sources/OvTools/src/OvTools/Time/Date.cpp index a0a4554bd..879506b4b 100644 --- a/Sources/Overload/OvTools/src/OvTools/Time/Date.cpp +++ b/Sources/OvTools/src/OvTools/Time/Date.cpp @@ -4,6 +4,7 @@ * @licence: MIT */ +#include #include #include "OvTools/Time/Date.h" @@ -14,7 +15,11 @@ std::string OvTools::Time::Date::GetDateAsString() const auto now = time(nullptr); tm ltm; +#ifdef _WIN32 localtime_s(<m, &now); +#else + localtime_r(&now, <m); +#endif std::string dateData[6] = { diff --git a/Sources/Overload/OvTools/src/OvTools/Utils/PathParser.cpp b/Sources/OvTools/src/OvTools/Utils/PathParser.cpp similarity index 100% rename from Sources/Overload/OvTools/src/OvTools/Utils/PathParser.cpp rename to Sources/OvTools/src/OvTools/Utils/PathParser.cpp diff --git a/Sources/Overload/OvTools/src/OvTools/Utils/Random.cpp b/Sources/OvTools/src/OvTools/Utils/Random.cpp similarity index 100% rename from Sources/Overload/OvTools/src/OvTools/Utils/Random.cpp rename to Sources/OvTools/src/OvTools/Utils/Random.cpp diff --git a/Sources/Overload/OvTools/src/OvTools/Utils/SizeConverter.cpp b/Sources/OvTools/src/OvTools/Utils/SizeConverter.cpp similarity index 98% rename from Sources/Overload/OvTools/src/OvTools/Utils/SizeConverter.cpp rename to Sources/OvTools/src/OvTools/Utils/SizeConverter.cpp index a15704927..3bf7e1986 100644 --- a/Sources/Overload/OvTools/src/OvTools/Utils/SizeConverter.cpp +++ b/Sources/OvTools/src/OvTools/Utils/SizeConverter.cpp @@ -4,6 +4,8 @@ * @licence: MIT */ +#include + #include "OvTools/Utils/SizeConverter.h" std::pair OvTools::Utils::SizeConverter::ConvertToOptimalUnit(float p_value, ESizeUnit p_unit) diff --git a/Sources/Overload/OvTools/src/OvTools/Utils/String.cpp b/Sources/OvTools/src/OvTools/Utils/String.cpp similarity index 98% rename from Sources/Overload/OvTools/src/OvTools/Utils/String.cpp rename to Sources/OvTools/src/OvTools/Utils/String.cpp index 06b9b5765..d5e5a9d97 100644 --- a/Sources/Overload/OvTools/src/OvTools/Utils/String.cpp +++ b/Sources/OvTools/src/OvTools/Utils/String.cpp @@ -4,6 +4,9 @@ * @licence: MIT */ +#include +#include + #include "OvTools/Utils/String.h" bool OvTools::Utils::String::Replace(std::string & p_target, const std::string & p_from, const std::string & p_to) diff --git a/Sources/Overload/OvTools/src/OvTools/Utils/SystemCalls.cpp b/Sources/OvTools/src/OvTools/Utils/SystemCalls.cpp similarity index 59% rename from Sources/Overload/OvTools/src/OvTools/Utils/SystemCalls.cpp rename to Sources/OvTools/src/OvTools/Utils/SystemCalls.cpp index d59904d7e..99203f88c 100644 --- a/Sources/Overload/OvTools/src/OvTools/Utils/SystemCalls.cpp +++ b/Sources/OvTools/src/OvTools/Utils/SystemCalls.cpp @@ -7,35 +7,68 @@ #include "OvTools/Utils/PathParser.h" #include "OvTools/Utils/SystemCalls.h" +#ifdef _WIN32 #include #include +#else +#include +#include +#include +#include +#endif + #include #include void OvTools::Utils::SystemCalls::ShowInExplorer(const std::string & p_path) { +#ifdef _WIN32 ShellExecuteA(NULL, "open", OvTools::Utils::PathParser::MakeWindowsStyle(p_path).c_str(), NULL, NULL, SW_SHOWNORMAL); +#else + std::string command = "xdg-open \"" + p_path + "\" &"; + std::system(command.c_str()); +#endif } void OvTools::Utils::SystemCalls::OpenFile(const std::string & p_file, const std::string & p_workingDir) { +#ifdef _WIN32 ShellExecuteA(NULL, "open", OvTools::Utils::PathParser::MakeWindowsStyle(p_file).c_str(), NULL, p_workingDir.empty() ? NULL : OvTools::Utils::PathParser::MakeWindowsStyle(p_workingDir).c_str(), SW_SHOWNORMAL); +#else + std::string command = "xdg-open \"" + p_file + "\" &"; + if (!p_workingDir.empty()) + { + command = "cd \"" + p_workingDir + "\" && " + command; + } + std::system(command.c_str()); +#endif } void OvTools::Utils::SystemCalls::EditFile(const std::string & p_file) { +#ifdef _WIN32 ShellExecuteW(NULL, NULL, std::wstring(p_file.begin(), p_file.end()).c_str(), NULL, NULL, SW_NORMAL); +#else + std::string command = "xdg-open \"" + p_file + "\" &"; + std::system(command.c_str()); +#endif } void OvTools::Utils::SystemCalls::OpenURL(const std::string& p_url) { +#ifdef _WIN32 ShellExecute(0, 0, p_url.c_str(), 0, 0, SW_SHOW); +#else + std::string command = "xdg-open \"" + p_url + "\" &"; + std::system(command.c_str()); +#endif } std::string OvTools::Utils::SystemCalls::GetPathToAppdata() { +#ifdef _WIN32 // Retrieve app-data path PWSTR rawPath = nullptr; const HRESULT hr = SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, nullptr, &rawPath); @@ -48,4 +81,23 @@ std::string OvTools::Utils::SystemCalls::GetPathToAppdata() std::string appDataPath(size_needed - 1, 0); WideCharToMultiByte(CP_UTF8, 0, path.get(), -1, &appDataPath[0], size_needed, nullptr, nullptr); return appDataPath; +#else + // On Linux, use the home directory or XDG_CONFIG_HOME + const char* configHome = std::getenv("XDG_CONFIG_HOME"); + if (configHome != nullptr && configHome[0] != '\0') + { + return std::string(configHome); + } + + const char* home = std::getenv("HOME"); + if (home != nullptr && home[0] != '\0') + { + return std::string(home) + "/.config"; + } + + // Fallback to pwd if HOME is not set + struct passwd* pw = getpwuid(getuid()); + assert(pw != nullptr && "Failed to get user home directory"); + return std::string(pw->pw_dir) + "/.config"; +#endif } \ No newline at end of file diff --git a/Sources/Overload/OvUI/include/OvUI/API/IDrawable.h b/Sources/OvUI/include/OvUI/API/IDrawable.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/API/IDrawable.h rename to Sources/OvUI/include/OvUI/API/IDrawable.h diff --git a/Sources/Overload/OvUI/include/OvUI/Core/UIManager.h b/Sources/OvUI/include/OvUI/Core/UIManager.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Core/UIManager.h rename to Sources/OvUI/include/OvUI/Core/UIManager.h diff --git a/Sources/Overload/OvUI/include/OvUI/Internal/Converter.h b/Sources/OvUI/include/OvUI/Internal/Converter.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Internal/Converter.h rename to Sources/OvUI/include/OvUI/Internal/Converter.h diff --git a/Sources/Overload/OvUI/include/OvUI/Internal/EMemoryMode.h b/Sources/OvUI/include/OvUI/Internal/EMemoryMode.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Internal/EMemoryMode.h rename to Sources/OvUI/include/OvUI/Internal/EMemoryMode.h diff --git a/Sources/Overload/OvUI/include/OvUI/Internal/TextureID.h b/Sources/OvUI/include/OvUI/Internal/TextureID.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Internal/TextureID.h rename to Sources/OvUI/include/OvUI/Internal/TextureID.h diff --git a/Sources/Overload/OvUI/include/OvUI/Internal/WidgetContainer.h b/Sources/OvUI/include/OvUI/Internal/WidgetContainer.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Internal/WidgetContainer.h rename to Sources/OvUI/include/OvUI/Internal/WidgetContainer.h diff --git a/Sources/Overload/OvUI/include/OvUI/Modules/Canvas.h b/Sources/OvUI/include/OvUI/Modules/Canvas.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Modules/Canvas.h rename to Sources/OvUI/include/OvUI/Modules/Canvas.h diff --git a/Sources/Overload/OvUI/include/OvUI/Panels/APanel.h b/Sources/OvUI/include/OvUI/Panels/APanel.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Panels/APanel.h rename to Sources/OvUI/include/OvUI/Panels/APanel.h diff --git a/Sources/Overload/OvUI/include/OvUI/Panels/APanelTransformable.h b/Sources/OvUI/include/OvUI/Panels/APanelTransformable.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Panels/APanelTransformable.h rename to Sources/OvUI/include/OvUI/Panels/APanelTransformable.h diff --git a/Sources/Overload/OvUI/include/OvUI/Panels/PanelMenuBar.h b/Sources/OvUI/include/OvUI/Panels/PanelMenuBar.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Panels/PanelMenuBar.h rename to Sources/OvUI/include/OvUI/Panels/PanelMenuBar.h diff --git a/Sources/Overload/OvUI/include/OvUI/Panels/PanelUndecorated.h b/Sources/OvUI/include/OvUI/Panels/PanelUndecorated.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Panels/PanelUndecorated.h rename to Sources/OvUI/include/OvUI/Panels/PanelUndecorated.h diff --git a/Sources/Overload/OvUI/include/OvUI/Panels/PanelWindow.h b/Sources/OvUI/include/OvUI/Panels/PanelWindow.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Panels/PanelWindow.h rename to Sources/OvUI/include/OvUI/Panels/PanelWindow.h diff --git a/Sources/Overload/OvUI/include/OvUI/Plugins/ContextualMenu.h b/Sources/OvUI/include/OvUI/Plugins/ContextualMenu.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Plugins/ContextualMenu.h rename to Sources/OvUI/include/OvUI/Plugins/ContextualMenu.h diff --git a/Sources/Overload/OvUI/include/OvUI/Plugins/DDSource.h b/Sources/OvUI/include/OvUI/Plugins/DDSource.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Plugins/DDSource.h rename to Sources/OvUI/include/OvUI/Plugins/DDSource.h diff --git a/Sources/Overload/OvUI/include/OvUI/Plugins/DDTarget.h b/Sources/OvUI/include/OvUI/Plugins/DDTarget.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Plugins/DDTarget.h rename to Sources/OvUI/include/OvUI/Plugins/DDTarget.h diff --git a/Sources/Overload/OvUI/include/OvUI/Plugins/DataDispatcher.h b/Sources/OvUI/include/OvUI/Plugins/DataDispatcher.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Plugins/DataDispatcher.h rename to Sources/OvUI/include/OvUI/Plugins/DataDispatcher.h diff --git a/Sources/Overload/OvUI/include/OvUI/Plugins/IPlugin.h b/Sources/OvUI/include/OvUI/Plugins/IPlugin.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Plugins/IPlugin.h rename to Sources/OvUI/include/OvUI/Plugins/IPlugin.h diff --git a/Sources/Overload/OvUI/include/OvUI/Plugins/Pluginable.h b/Sources/OvUI/include/OvUI/Plugins/Pluginable.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Plugins/Pluginable.h rename to Sources/OvUI/include/OvUI/Plugins/Pluginable.h diff --git a/Sources/Overload/OvUI/include/OvUI/Settings/Alignment.h b/Sources/OvUI/include/OvUI/Settings/Alignment.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Settings/Alignment.h rename to Sources/OvUI/include/OvUI/Settings/Alignment.h diff --git a/Sources/Overload/OvUI/include/OvUI/Settings/EDirection.h b/Sources/OvUI/include/OvUI/Settings/EDirection.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Settings/EDirection.h rename to Sources/OvUI/include/OvUI/Settings/EDirection.h diff --git a/Sources/Overload/OvUI/include/OvUI/Settings/PanelWindowSettings.h b/Sources/OvUI/include/OvUI/Settings/PanelWindowSettings.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Settings/PanelWindowSettings.h rename to Sources/OvUI/include/OvUI/Settings/PanelWindowSettings.h diff --git a/Sources/Overload/OvUI/include/OvUI/Styling/EStyle.h b/Sources/OvUI/include/OvUI/Styling/EStyle.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Styling/EStyle.h rename to Sources/OvUI/include/OvUI/Styling/EStyle.h diff --git a/Sources/Overload/OvUI/include/OvUI/Styling/TStyle.h b/Sources/OvUI/include/OvUI/Styling/TStyle.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Styling/TStyle.h rename to Sources/OvUI/include/OvUI/Styling/TStyle.h diff --git a/Sources/Overload/OvUI/include/OvUI/Types/Color.h b/Sources/OvUI/include/OvUI/Types/Color.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Types/Color.h rename to Sources/OvUI/include/OvUI/Types/Color.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/AWidget.h b/Sources/OvUI/include/OvUI/Widgets/AWidget.h similarity index 98% rename from Sources/Overload/OvUI/include/OvUI/Widgets/AWidget.h rename to Sources/OvUI/include/OvUI/Widgets/AWidget.h index edeed776b..9037ec559 100644 --- a/Sources/Overload/OvUI/include/OvUI/Widgets/AWidget.h +++ b/Sources/OvUI/include/OvUI/Widgets/AWidget.h @@ -6,6 +6,7 @@ #pragma once +#include #include #include diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Buttons/AButton.h b/Sources/OvUI/include/OvUI/Widgets/Buttons/AButton.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Buttons/AButton.h rename to Sources/OvUI/include/OvUI/Widgets/Buttons/AButton.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Buttons/Button.h b/Sources/OvUI/include/OvUI/Widgets/Buttons/Button.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Buttons/Button.h rename to Sources/OvUI/include/OvUI/Widgets/Buttons/Button.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Buttons/ButtonArrow.h b/Sources/OvUI/include/OvUI/Widgets/Buttons/ButtonArrow.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Buttons/ButtonArrow.h rename to Sources/OvUI/include/OvUI/Widgets/Buttons/ButtonArrow.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Buttons/ButtonColored.h b/Sources/OvUI/include/OvUI/Widgets/Buttons/ButtonColored.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Buttons/ButtonColored.h rename to Sources/OvUI/include/OvUI/Widgets/Buttons/ButtonColored.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Buttons/ButtonImage.h b/Sources/OvUI/include/OvUI/Widgets/Buttons/ButtonImage.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Buttons/ButtonImage.h rename to Sources/OvUI/include/OvUI/Widgets/Buttons/ButtonImage.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Buttons/ButtonSmall.h b/Sources/OvUI/include/OvUI/Widgets/Buttons/ButtonSmall.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Buttons/ButtonSmall.h rename to Sources/OvUI/include/OvUI/Widgets/Buttons/ButtonSmall.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/DataWidget.h b/Sources/OvUI/include/OvUI/Widgets/DataWidget.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/DataWidget.h rename to Sources/OvUI/include/OvUI/Widgets/DataWidget.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Drags/DragDouble.h b/Sources/OvUI/include/OvUI/Widgets/Drags/DragDouble.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Drags/DragDouble.h rename to Sources/OvUI/include/OvUI/Widgets/Drags/DragDouble.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Drags/DragFloat.h b/Sources/OvUI/include/OvUI/Widgets/Drags/DragFloat.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Drags/DragFloat.h rename to Sources/OvUI/include/OvUI/Widgets/Drags/DragFloat.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Drags/DragInt.h b/Sources/OvUI/include/OvUI/Widgets/Drags/DragInt.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Drags/DragInt.h rename to Sources/OvUI/include/OvUI/Widgets/Drags/DragInt.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Drags/DragMultipleDoubles.h b/Sources/OvUI/include/OvUI/Widgets/Drags/DragMultipleDoubles.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Drags/DragMultipleDoubles.h rename to Sources/OvUI/include/OvUI/Widgets/Drags/DragMultipleDoubles.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Drags/DragMultipleFloats.h b/Sources/OvUI/include/OvUI/Widgets/Drags/DragMultipleFloats.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Drags/DragMultipleFloats.h rename to Sources/OvUI/include/OvUI/Widgets/Drags/DragMultipleFloats.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Drags/DragMultipleInts.h b/Sources/OvUI/include/OvUI/Widgets/Drags/DragMultipleInts.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Drags/DragMultipleInts.h rename to Sources/OvUI/include/OvUI/Widgets/Drags/DragMultipleInts.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Drags/DragMultipleScalars.h b/Sources/OvUI/include/OvUI/Widgets/Drags/DragMultipleScalars.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Drags/DragMultipleScalars.h rename to Sources/OvUI/include/OvUI/Widgets/Drags/DragMultipleScalars.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Drags/DragSingleScalar.h b/Sources/OvUI/include/OvUI/Widgets/Drags/DragSingleScalar.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Drags/DragSingleScalar.h rename to Sources/OvUI/include/OvUI/Widgets/Drags/DragSingleScalar.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/InputFields/InputDouble.h b/Sources/OvUI/include/OvUI/Widgets/InputFields/InputDouble.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/InputFields/InputDouble.h rename to Sources/OvUI/include/OvUI/Widgets/InputFields/InputDouble.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/InputFields/InputFloat.h b/Sources/OvUI/include/OvUI/Widgets/InputFields/InputFloat.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/InputFields/InputFloat.h rename to Sources/OvUI/include/OvUI/Widgets/InputFields/InputFloat.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/InputFields/InputInt.h b/Sources/OvUI/include/OvUI/Widgets/InputFields/InputInt.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/InputFields/InputInt.h rename to Sources/OvUI/include/OvUI/Widgets/InputFields/InputInt.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/InputFields/InputMultipleDoubles.h b/Sources/OvUI/include/OvUI/Widgets/InputFields/InputMultipleDoubles.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/InputFields/InputMultipleDoubles.h rename to Sources/OvUI/include/OvUI/Widgets/InputFields/InputMultipleDoubles.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/InputFields/InputMultipleFloats.h b/Sources/OvUI/include/OvUI/Widgets/InputFields/InputMultipleFloats.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/InputFields/InputMultipleFloats.h rename to Sources/OvUI/include/OvUI/Widgets/InputFields/InputMultipleFloats.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/InputFields/InputMultipleInts.h b/Sources/OvUI/include/OvUI/Widgets/InputFields/InputMultipleInts.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/InputFields/InputMultipleInts.h rename to Sources/OvUI/include/OvUI/Widgets/InputFields/InputMultipleInts.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/InputFields/InputMultipleScalars.h b/Sources/OvUI/include/OvUI/Widgets/InputFields/InputMultipleScalars.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/InputFields/InputMultipleScalars.h rename to Sources/OvUI/include/OvUI/Widgets/InputFields/InputMultipleScalars.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/InputFields/InputSingleScalar.h b/Sources/OvUI/include/OvUI/Widgets/InputFields/InputSingleScalar.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/InputFields/InputSingleScalar.h rename to Sources/OvUI/include/OvUI/Widgets/InputFields/InputSingleScalar.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/InputFields/InputText.h b/Sources/OvUI/include/OvUI/Widgets/InputFields/InputText.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/InputFields/InputText.h rename to Sources/OvUI/include/OvUI/Widgets/InputFields/InputText.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Layout/Columns.h b/Sources/OvUI/include/OvUI/Widgets/Layout/Columns.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Layout/Columns.h rename to Sources/OvUI/include/OvUI/Widgets/Layout/Columns.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Layout/Dummy.h b/Sources/OvUI/include/OvUI/Widgets/Layout/Dummy.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Layout/Dummy.h rename to Sources/OvUI/include/OvUI/Widgets/Layout/Dummy.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Layout/Group.h b/Sources/OvUI/include/OvUI/Widgets/Layout/Group.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Layout/Group.h rename to Sources/OvUI/include/OvUI/Widgets/Layout/Group.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Layout/GroupCollapsable.h b/Sources/OvUI/include/OvUI/Widgets/Layout/GroupCollapsable.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Layout/GroupCollapsable.h rename to Sources/OvUI/include/OvUI/Widgets/Layout/GroupCollapsable.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Layout/NewLine.h b/Sources/OvUI/include/OvUI/Widgets/Layout/NewLine.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Layout/NewLine.h rename to Sources/OvUI/include/OvUI/Widgets/Layout/NewLine.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Layout/Spacing.h b/Sources/OvUI/include/OvUI/Widgets/Layout/Spacing.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Layout/Spacing.h rename to Sources/OvUI/include/OvUI/Widgets/Layout/Spacing.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Layout/TreeNode.h b/Sources/OvUI/include/OvUI/Widgets/Layout/TreeNode.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Layout/TreeNode.h rename to Sources/OvUI/include/OvUI/Widgets/Layout/TreeNode.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Menu/MenuItem.h b/Sources/OvUI/include/OvUI/Widgets/Menu/MenuItem.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Menu/MenuItem.h rename to Sources/OvUI/include/OvUI/Widgets/Menu/MenuItem.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Menu/MenuList.h b/Sources/OvUI/include/OvUI/Widgets/Menu/MenuList.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Menu/MenuList.h rename to Sources/OvUI/include/OvUI/Widgets/Menu/MenuList.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Plots/APlot.h b/Sources/OvUI/include/OvUI/Widgets/Plots/APlot.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Plots/APlot.h rename to Sources/OvUI/include/OvUI/Widgets/Plots/APlot.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Plots/PlotHistogram.h b/Sources/OvUI/include/OvUI/Widgets/Plots/PlotHistogram.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Plots/PlotHistogram.h rename to Sources/OvUI/include/OvUI/Widgets/Plots/PlotHistogram.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Plots/PlotLines.h b/Sources/OvUI/include/OvUI/Widgets/Plots/PlotLines.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Plots/PlotLines.h rename to Sources/OvUI/include/OvUI/Widgets/Plots/PlotLines.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Selection/CheckBox.h b/Sources/OvUI/include/OvUI/Widgets/Selection/CheckBox.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Selection/CheckBox.h rename to Sources/OvUI/include/OvUI/Widgets/Selection/CheckBox.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Selection/ColorEdit.h b/Sources/OvUI/include/OvUI/Widgets/Selection/ColorEdit.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Selection/ColorEdit.h rename to Sources/OvUI/include/OvUI/Widgets/Selection/ColorEdit.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Selection/ColorPicker.h b/Sources/OvUI/include/OvUI/Widgets/Selection/ColorPicker.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Selection/ColorPicker.h rename to Sources/OvUI/include/OvUI/Widgets/Selection/ColorPicker.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Selection/ComboBox.h b/Sources/OvUI/include/OvUI/Widgets/Selection/ComboBox.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Selection/ComboBox.h rename to Sources/OvUI/include/OvUI/Widgets/Selection/ComboBox.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Selection/RadioButton.h b/Sources/OvUI/include/OvUI/Widgets/Selection/RadioButton.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Selection/RadioButton.h rename to Sources/OvUI/include/OvUI/Widgets/Selection/RadioButton.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Selection/RadioButtonLinker.h b/Sources/OvUI/include/OvUI/Widgets/Selection/RadioButtonLinker.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Selection/RadioButtonLinker.h rename to Sources/OvUI/include/OvUI/Widgets/Selection/RadioButtonLinker.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Sliders/ESliderOrientation.h b/Sources/OvUI/include/OvUI/Widgets/Sliders/ESliderOrientation.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Sliders/ESliderOrientation.h rename to Sources/OvUI/include/OvUI/Widgets/Sliders/ESliderOrientation.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Sliders/SliderDouble.h b/Sources/OvUI/include/OvUI/Widgets/Sliders/SliderDouble.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Sliders/SliderDouble.h rename to Sources/OvUI/include/OvUI/Widgets/Sliders/SliderDouble.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Sliders/SliderFloat.h b/Sources/OvUI/include/OvUI/Widgets/Sliders/SliderFloat.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Sliders/SliderFloat.h rename to Sources/OvUI/include/OvUI/Widgets/Sliders/SliderFloat.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Sliders/SliderInt.h b/Sources/OvUI/include/OvUI/Widgets/Sliders/SliderInt.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Sliders/SliderInt.h rename to Sources/OvUI/include/OvUI/Widgets/Sliders/SliderInt.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Sliders/SliderMultipleDoubles.h b/Sources/OvUI/include/OvUI/Widgets/Sliders/SliderMultipleDoubles.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Sliders/SliderMultipleDoubles.h rename to Sources/OvUI/include/OvUI/Widgets/Sliders/SliderMultipleDoubles.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Sliders/SliderMultipleFloats.h b/Sources/OvUI/include/OvUI/Widgets/Sliders/SliderMultipleFloats.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Sliders/SliderMultipleFloats.h rename to Sources/OvUI/include/OvUI/Widgets/Sliders/SliderMultipleFloats.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Sliders/SliderMultipleInts.h b/Sources/OvUI/include/OvUI/Widgets/Sliders/SliderMultipleInts.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Sliders/SliderMultipleInts.h rename to Sources/OvUI/include/OvUI/Widgets/Sliders/SliderMultipleInts.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Sliders/SliderMultipleScalars.h b/Sources/OvUI/include/OvUI/Widgets/Sliders/SliderMultipleScalars.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Sliders/SliderMultipleScalars.h rename to Sources/OvUI/include/OvUI/Widgets/Sliders/SliderMultipleScalars.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Sliders/SliderSingleScalar.h b/Sources/OvUI/include/OvUI/Widgets/Sliders/SliderSingleScalar.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Sliders/SliderSingleScalar.h rename to Sources/OvUI/include/OvUI/Widgets/Sliders/SliderSingleScalar.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Texts/Text.h b/Sources/OvUI/include/OvUI/Widgets/Texts/Text.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Texts/Text.h rename to Sources/OvUI/include/OvUI/Widgets/Texts/Text.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Texts/TextClickable.h b/Sources/OvUI/include/OvUI/Widgets/Texts/TextClickable.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Texts/TextClickable.h rename to Sources/OvUI/include/OvUI/Widgets/Texts/TextClickable.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Texts/TextColored.h b/Sources/OvUI/include/OvUI/Widgets/Texts/TextColored.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Texts/TextColored.h rename to Sources/OvUI/include/OvUI/Widgets/Texts/TextColored.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Texts/TextDisabled.h b/Sources/OvUI/include/OvUI/Widgets/Texts/TextDisabled.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Texts/TextDisabled.h rename to Sources/OvUI/include/OvUI/Widgets/Texts/TextDisabled.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Texts/TextLabelled.h b/Sources/OvUI/include/OvUI/Widgets/Texts/TextLabelled.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Texts/TextLabelled.h rename to Sources/OvUI/include/OvUI/Widgets/Texts/TextLabelled.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Texts/TextSelectable.h b/Sources/OvUI/include/OvUI/Widgets/Texts/TextSelectable.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Texts/TextSelectable.h rename to Sources/OvUI/include/OvUI/Widgets/Texts/TextSelectable.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Texts/TextWrapped.h b/Sources/OvUI/include/OvUI/Widgets/Texts/TextWrapped.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Texts/TextWrapped.h rename to Sources/OvUI/include/OvUI/Widgets/Texts/TextWrapped.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Visual/Bullet.h b/Sources/OvUI/include/OvUI/Widgets/Visual/Bullet.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Visual/Bullet.h rename to Sources/OvUI/include/OvUI/Widgets/Visual/Bullet.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Visual/Image.h b/Sources/OvUI/include/OvUI/Widgets/Visual/Image.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Visual/Image.h rename to Sources/OvUI/include/OvUI/Widgets/Visual/Image.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Visual/ProgressBar.h b/Sources/OvUI/include/OvUI/Widgets/Visual/ProgressBar.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Visual/ProgressBar.h rename to Sources/OvUI/include/OvUI/Widgets/Visual/ProgressBar.h diff --git a/Sources/Overload/OvUI/include/OvUI/Widgets/Visual/Separator.h b/Sources/OvUI/include/OvUI/Widgets/Visual/Separator.h similarity index 100% rename from Sources/Overload/OvUI/include/OvUI/Widgets/Visual/Separator.h rename to Sources/OvUI/include/OvUI/Widgets/Visual/Separator.h diff --git a/Sources/Overload/OvUI/premake5.lua b/Sources/OvUI/premake5.lua similarity index 85% rename from Sources/Overload/OvUI/premake5.lua rename to Sources/OvUI/premake5.lua index 84d46aee3..31b9f50c3 100644 --- a/Sources/Overload/OvUI/premake5.lua +++ b/Sources/OvUI/premake5.lua @@ -18,8 +18,8 @@ project "OvUI" dependdir .. "ImGui/include", -- Overload SDK - "%{wks.location}/OvMaths/include", - "%{wks.location}/OvTools/include", + "%{wks.location}/Sources/OvMaths/include", + "%{wks.location}/Sources/OvTools/include", -- Current Project "include" diff --git a/Sources/Overload/OvUI/src/OvUI/Core/UIManager.cpp b/Sources/OvUI/src/OvUI/Core/UIManager.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Core/UIManager.cpp rename to Sources/OvUI/src/OvUI/Core/UIManager.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Internal/Converter.cpp b/Sources/OvUI/src/OvUI/Internal/Converter.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Internal/Converter.cpp rename to Sources/OvUI/src/OvUI/Internal/Converter.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Internal/WidgetContainer.cpp b/Sources/OvUI/src/OvUI/Internal/WidgetContainer.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Internal/WidgetContainer.cpp rename to Sources/OvUI/src/OvUI/Internal/WidgetContainer.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Modules/Canvas.cpp b/Sources/OvUI/src/OvUI/Modules/Canvas.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Modules/Canvas.cpp rename to Sources/OvUI/src/OvUI/Modules/Canvas.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Panels/APanel.cpp b/Sources/OvUI/src/OvUI/Panels/APanel.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Panels/APanel.cpp rename to Sources/OvUI/src/OvUI/Panels/APanel.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Panels/APanelTransformable.cpp b/Sources/OvUI/src/OvUI/Panels/APanelTransformable.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Panels/APanelTransformable.cpp rename to Sources/OvUI/src/OvUI/Panels/APanelTransformable.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Panels/PanelMenuBar.cpp b/Sources/OvUI/src/OvUI/Panels/PanelMenuBar.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Panels/PanelMenuBar.cpp rename to Sources/OvUI/src/OvUI/Panels/PanelMenuBar.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Panels/PanelUndecorated.cpp b/Sources/OvUI/src/OvUI/Panels/PanelUndecorated.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Panels/PanelUndecorated.cpp rename to Sources/OvUI/src/OvUI/Panels/PanelUndecorated.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Panels/PanelWindow.cpp b/Sources/OvUI/src/OvUI/Panels/PanelWindow.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Panels/PanelWindow.cpp rename to Sources/OvUI/src/OvUI/Panels/PanelWindow.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Plugins/ContextualMenu.cpp b/Sources/OvUI/src/OvUI/Plugins/ContextualMenu.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Plugins/ContextualMenu.cpp rename to Sources/OvUI/src/OvUI/Plugins/ContextualMenu.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Styling/DefaultDark.cpp b/Sources/OvUI/src/OvUI/Styling/DefaultDark.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Styling/DefaultDark.cpp rename to Sources/OvUI/src/OvUI/Styling/DefaultDark.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Styling/DuneDark.cpp b/Sources/OvUI/src/OvUI/Styling/DuneDark.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Styling/DuneDark.cpp rename to Sources/OvUI/src/OvUI/Styling/DuneDark.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Styling/EvenDarker.cpp b/Sources/OvUI/src/OvUI/Styling/EvenDarker.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Styling/EvenDarker.cpp rename to Sources/OvUI/src/OvUI/Styling/EvenDarker.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Styling/ImClassic.cpp b/Sources/OvUI/src/OvUI/Styling/ImClassic.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Styling/ImClassic.cpp rename to Sources/OvUI/src/OvUI/Styling/ImClassic.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Styling/ImDark.cpp b/Sources/OvUI/src/OvUI/Styling/ImDark.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Styling/ImDark.cpp rename to Sources/OvUI/src/OvUI/Styling/ImDark.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Styling/ImLight.cpp b/Sources/OvUI/src/OvUI/Styling/ImLight.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Styling/ImLight.cpp rename to Sources/OvUI/src/OvUI/Styling/ImLight.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Types/Color.cpp b/Sources/OvUI/src/OvUI/Types/Color.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Types/Color.cpp rename to Sources/OvUI/src/OvUI/Types/Color.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/AWidget.cpp b/Sources/OvUI/src/OvUI/Widgets/AWidget.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/AWidget.cpp rename to Sources/OvUI/src/OvUI/Widgets/AWidget.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Buttons/Button.cpp b/Sources/OvUI/src/OvUI/Widgets/Buttons/Button.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Buttons/Button.cpp rename to Sources/OvUI/src/OvUI/Widgets/Buttons/Button.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Buttons/ButtonArrow.cpp b/Sources/OvUI/src/OvUI/Widgets/Buttons/ButtonArrow.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Buttons/ButtonArrow.cpp rename to Sources/OvUI/src/OvUI/Widgets/Buttons/ButtonArrow.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Buttons/ButtonColored.cpp b/Sources/OvUI/src/OvUI/Widgets/Buttons/ButtonColored.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Buttons/ButtonColored.cpp rename to Sources/OvUI/src/OvUI/Widgets/Buttons/ButtonColored.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Buttons/ButtonImage.cpp b/Sources/OvUI/src/OvUI/Widgets/Buttons/ButtonImage.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Buttons/ButtonImage.cpp rename to Sources/OvUI/src/OvUI/Widgets/Buttons/ButtonImage.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Buttons/ButtonSmall.cpp b/Sources/OvUI/src/OvUI/Widgets/Buttons/ButtonSmall.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Buttons/ButtonSmall.cpp rename to Sources/OvUI/src/OvUI/Widgets/Buttons/ButtonSmall.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Drags/DragDouble.cpp b/Sources/OvUI/src/OvUI/Widgets/Drags/DragDouble.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Drags/DragDouble.cpp rename to Sources/OvUI/src/OvUI/Widgets/Drags/DragDouble.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Drags/DragFloat.cpp b/Sources/OvUI/src/OvUI/Widgets/Drags/DragFloat.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Drags/DragFloat.cpp rename to Sources/OvUI/src/OvUI/Widgets/Drags/DragFloat.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Drags/DragInt.cpp b/Sources/OvUI/src/OvUI/Widgets/Drags/DragInt.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Drags/DragInt.cpp rename to Sources/OvUI/src/OvUI/Widgets/Drags/DragInt.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/InputFields/InputDouble.cpp b/Sources/OvUI/src/OvUI/Widgets/InputFields/InputDouble.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/InputFields/InputDouble.cpp rename to Sources/OvUI/src/OvUI/Widgets/InputFields/InputDouble.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/InputFields/InputFloat.cpp b/Sources/OvUI/src/OvUI/Widgets/InputFields/InputFloat.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/InputFields/InputFloat.cpp rename to Sources/OvUI/src/OvUI/Widgets/InputFields/InputFloat.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/InputFields/InputInt.cpp b/Sources/OvUI/src/OvUI/Widgets/InputFields/InputInt.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/InputFields/InputInt.cpp rename to Sources/OvUI/src/OvUI/Widgets/InputFields/InputInt.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/InputFields/InputText.cpp b/Sources/OvUI/src/OvUI/Widgets/InputFields/InputText.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/InputFields/InputText.cpp rename to Sources/OvUI/src/OvUI/Widgets/InputFields/InputText.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Layout/Dummy.cpp b/Sources/OvUI/src/OvUI/Widgets/Layout/Dummy.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Layout/Dummy.cpp rename to Sources/OvUI/src/OvUI/Widgets/Layout/Dummy.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Layout/Group.cpp b/Sources/OvUI/src/OvUI/Widgets/Layout/Group.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Layout/Group.cpp rename to Sources/OvUI/src/OvUI/Widgets/Layout/Group.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Layout/GroupCollapsable.cpp b/Sources/OvUI/src/OvUI/Widgets/Layout/GroupCollapsable.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Layout/GroupCollapsable.cpp rename to Sources/OvUI/src/OvUI/Widgets/Layout/GroupCollapsable.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Layout/NewLine.cpp b/Sources/OvUI/src/OvUI/Widgets/Layout/NewLine.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Layout/NewLine.cpp rename to Sources/OvUI/src/OvUI/Widgets/Layout/NewLine.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Layout/Spacing.cpp b/Sources/OvUI/src/OvUI/Widgets/Layout/Spacing.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Layout/Spacing.cpp rename to Sources/OvUI/src/OvUI/Widgets/Layout/Spacing.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Layout/TreeNode.cpp b/Sources/OvUI/src/OvUI/Widgets/Layout/TreeNode.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Layout/TreeNode.cpp rename to Sources/OvUI/src/OvUI/Widgets/Layout/TreeNode.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Menu/MenuItem.cpp b/Sources/OvUI/src/OvUI/Widgets/Menu/MenuItem.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Menu/MenuItem.cpp rename to Sources/OvUI/src/OvUI/Widgets/Menu/MenuItem.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Menu/MenuList.cpp b/Sources/OvUI/src/OvUI/Widgets/Menu/MenuList.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Menu/MenuList.cpp rename to Sources/OvUI/src/OvUI/Widgets/Menu/MenuList.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Plots/APlot.cpp b/Sources/OvUI/src/OvUI/Widgets/Plots/APlot.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Plots/APlot.cpp rename to Sources/OvUI/src/OvUI/Widgets/Plots/APlot.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Plots/PlotHistogram.cpp b/Sources/OvUI/src/OvUI/Widgets/Plots/PlotHistogram.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Plots/PlotHistogram.cpp rename to Sources/OvUI/src/OvUI/Widgets/Plots/PlotHistogram.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Plots/PlotLines.cpp b/Sources/OvUI/src/OvUI/Widgets/Plots/PlotLines.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Plots/PlotLines.cpp rename to Sources/OvUI/src/OvUI/Widgets/Plots/PlotLines.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Selection/CheckBox.cpp b/Sources/OvUI/src/OvUI/Widgets/Selection/CheckBox.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Selection/CheckBox.cpp rename to Sources/OvUI/src/OvUI/Widgets/Selection/CheckBox.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Selection/ColorEdit.cpp b/Sources/OvUI/src/OvUI/Widgets/Selection/ColorEdit.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Selection/ColorEdit.cpp rename to Sources/OvUI/src/OvUI/Widgets/Selection/ColorEdit.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Selection/ColorPicker.cpp b/Sources/OvUI/src/OvUI/Widgets/Selection/ColorPicker.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Selection/ColorPicker.cpp rename to Sources/OvUI/src/OvUI/Widgets/Selection/ColorPicker.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Selection/ComboBox.cpp b/Sources/OvUI/src/OvUI/Widgets/Selection/ComboBox.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Selection/ComboBox.cpp rename to Sources/OvUI/src/OvUI/Widgets/Selection/ComboBox.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Selection/RadioButton.cpp b/Sources/OvUI/src/OvUI/Widgets/Selection/RadioButton.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Selection/RadioButton.cpp rename to Sources/OvUI/src/OvUI/Widgets/Selection/RadioButton.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Selection/RadioButtonLinker.cpp b/Sources/OvUI/src/OvUI/Widgets/Selection/RadioButtonLinker.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Selection/RadioButtonLinker.cpp rename to Sources/OvUI/src/OvUI/Widgets/Selection/RadioButtonLinker.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Sliders/SliderDouble.cpp b/Sources/OvUI/src/OvUI/Widgets/Sliders/SliderDouble.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Sliders/SliderDouble.cpp rename to Sources/OvUI/src/OvUI/Widgets/Sliders/SliderDouble.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Sliders/SliderFloat.cpp b/Sources/OvUI/src/OvUI/Widgets/Sliders/SliderFloat.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Sliders/SliderFloat.cpp rename to Sources/OvUI/src/OvUI/Widgets/Sliders/SliderFloat.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Sliders/SliderInt.cpp b/Sources/OvUI/src/OvUI/Widgets/Sliders/SliderInt.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Sliders/SliderInt.cpp rename to Sources/OvUI/src/OvUI/Widgets/Sliders/SliderInt.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Texts/Text.cpp b/Sources/OvUI/src/OvUI/Widgets/Texts/Text.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Texts/Text.cpp rename to Sources/OvUI/src/OvUI/Widgets/Texts/Text.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Texts/TextClickable.cpp b/Sources/OvUI/src/OvUI/Widgets/Texts/TextClickable.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Texts/TextClickable.cpp rename to Sources/OvUI/src/OvUI/Widgets/Texts/TextClickable.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Texts/TextColored.cpp b/Sources/OvUI/src/OvUI/Widgets/Texts/TextColored.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Texts/TextColored.cpp rename to Sources/OvUI/src/OvUI/Widgets/Texts/TextColored.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Texts/TextDisabled.cpp b/Sources/OvUI/src/OvUI/Widgets/Texts/TextDisabled.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Texts/TextDisabled.cpp rename to Sources/OvUI/src/OvUI/Widgets/Texts/TextDisabled.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Texts/TextLabelled.cpp b/Sources/OvUI/src/OvUI/Widgets/Texts/TextLabelled.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Texts/TextLabelled.cpp rename to Sources/OvUI/src/OvUI/Widgets/Texts/TextLabelled.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Texts/TextSelectable.cpp b/Sources/OvUI/src/OvUI/Widgets/Texts/TextSelectable.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Texts/TextSelectable.cpp rename to Sources/OvUI/src/OvUI/Widgets/Texts/TextSelectable.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Texts/TextWrapped.cpp b/Sources/OvUI/src/OvUI/Widgets/Texts/TextWrapped.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Texts/TextWrapped.cpp rename to Sources/OvUI/src/OvUI/Widgets/Texts/TextWrapped.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Visual/Bullet.cpp b/Sources/OvUI/src/OvUI/Widgets/Visual/Bullet.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Visual/Bullet.cpp rename to Sources/OvUI/src/OvUI/Widgets/Visual/Bullet.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Visual/Image.cpp b/Sources/OvUI/src/OvUI/Widgets/Visual/Image.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Visual/Image.cpp rename to Sources/OvUI/src/OvUI/Widgets/Visual/Image.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Visual/ProgressBar.cpp b/Sources/OvUI/src/OvUI/Widgets/Visual/ProgressBar.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Visual/ProgressBar.cpp rename to Sources/OvUI/src/OvUI/Widgets/Visual/ProgressBar.cpp diff --git a/Sources/Overload/OvUI/src/OvUI/Widgets/Visual/Separator.cpp b/Sources/OvUI/src/OvUI/Widgets/Visual/Separator.cpp similarity index 100% rename from Sources/Overload/OvUI/src/OvUI/Widgets/Visual/Separator.cpp rename to Sources/OvUI/src/OvUI/Widgets/Visual/Separator.cpp diff --git a/Sources/Overload/OvWindowing/include/OvWindowing/Context/Device.h b/Sources/OvWindowing/include/OvWindowing/Context/Device.h similarity index 100% rename from Sources/Overload/OvWindowing/include/OvWindowing/Context/Device.h rename to Sources/OvWindowing/include/OvWindowing/Context/Device.h diff --git a/Sources/Overload/OvWindowing/include/OvWindowing/Context/EDeviceError.h b/Sources/OvWindowing/include/OvWindowing/Context/EDeviceError.h similarity index 100% rename from Sources/Overload/OvWindowing/include/OvWindowing/Context/EDeviceError.h rename to Sources/OvWindowing/include/OvWindowing/Context/EDeviceError.h diff --git a/Sources/Overload/OvWindowing/include/OvWindowing/Cursor/ECursorMode.h b/Sources/OvWindowing/include/OvWindowing/Cursor/ECursorMode.h similarity index 100% rename from Sources/Overload/OvWindowing/include/OvWindowing/Cursor/ECursorMode.h rename to Sources/OvWindowing/include/OvWindowing/Cursor/ECursorMode.h diff --git a/Sources/Overload/OvWindowing/include/OvWindowing/Cursor/ECursorShape.h b/Sources/OvWindowing/include/OvWindowing/Cursor/ECursorShape.h similarity index 100% rename from Sources/Overload/OvWindowing/include/OvWindowing/Cursor/ECursorShape.h rename to Sources/OvWindowing/include/OvWindowing/Cursor/ECursorShape.h diff --git a/Sources/Overload/OvWindowing/include/OvWindowing/Dialogs/FileDialog.h b/Sources/OvWindowing/include/OvWindowing/Dialogs/FileDialog.h similarity index 99% rename from Sources/Overload/OvWindowing/include/OvWindowing/Dialogs/FileDialog.h rename to Sources/OvWindowing/include/OvWindowing/Dialogs/FileDialog.h index c0217d56f..771c3c089 100644 --- a/Sources/Overload/OvWindowing/include/OvWindowing/Dialogs/FileDialog.h +++ b/Sources/OvWindowing/include/OvWindowing/Dialogs/FileDialog.h @@ -117,5 +117,6 @@ namespace OvWindowing::Dialogs std::string m_filename; std::string m_filepath; bool m_succeeded; + bool m_isSaveDialog = false; }; } \ No newline at end of file diff --git a/Sources/Overload/OvWindowing/include/OvWindowing/Dialogs/MessageBox.h b/Sources/OvWindowing/include/OvWindowing/Dialogs/MessageBox.h similarity index 100% rename from Sources/Overload/OvWindowing/include/OvWindowing/Dialogs/MessageBox.h rename to Sources/OvWindowing/include/OvWindowing/Dialogs/MessageBox.h diff --git a/Sources/Overload/OvWindowing/include/OvWindowing/Dialogs/OpenFileDialog.h b/Sources/OvWindowing/include/OvWindowing/Dialogs/OpenFileDialog.h similarity index 100% rename from Sources/Overload/OvWindowing/include/OvWindowing/Dialogs/OpenFileDialog.h rename to Sources/OvWindowing/include/OvWindowing/Dialogs/OpenFileDialog.h diff --git a/Sources/Overload/OvWindowing/include/OvWindowing/Dialogs/SaveFileDialog.h b/Sources/OvWindowing/include/OvWindowing/Dialogs/SaveFileDialog.h similarity index 100% rename from Sources/Overload/OvWindowing/include/OvWindowing/Dialogs/SaveFileDialog.h rename to Sources/OvWindowing/include/OvWindowing/Dialogs/SaveFileDialog.h diff --git a/Sources/Overload/OvWindowing/include/OvWindowing/Inputs/EKey.h b/Sources/OvWindowing/include/OvWindowing/Inputs/EKey.h similarity index 100% rename from Sources/Overload/OvWindowing/include/OvWindowing/Inputs/EKey.h rename to Sources/OvWindowing/include/OvWindowing/Inputs/EKey.h diff --git a/Sources/Overload/OvWindowing/include/OvWindowing/Inputs/EKeyState.h b/Sources/OvWindowing/include/OvWindowing/Inputs/EKeyState.h similarity index 100% rename from Sources/Overload/OvWindowing/include/OvWindowing/Inputs/EKeyState.h rename to Sources/OvWindowing/include/OvWindowing/Inputs/EKeyState.h diff --git a/Sources/Overload/OvWindowing/include/OvWindowing/Inputs/EMouseButton.h b/Sources/OvWindowing/include/OvWindowing/Inputs/EMouseButton.h similarity index 100% rename from Sources/Overload/OvWindowing/include/OvWindowing/Inputs/EMouseButton.h rename to Sources/OvWindowing/include/OvWindowing/Inputs/EMouseButton.h diff --git a/Sources/Overload/OvWindowing/include/OvWindowing/Inputs/EMouseButtonState.h b/Sources/OvWindowing/include/OvWindowing/Inputs/EMouseButtonState.h similarity index 100% rename from Sources/Overload/OvWindowing/include/OvWindowing/Inputs/EMouseButtonState.h rename to Sources/OvWindowing/include/OvWindowing/Inputs/EMouseButtonState.h diff --git a/Sources/Overload/OvWindowing/include/OvWindowing/Inputs/InputManager.h b/Sources/OvWindowing/include/OvWindowing/Inputs/InputManager.h similarity index 100% rename from Sources/Overload/OvWindowing/include/OvWindowing/Inputs/InputManager.h rename to Sources/OvWindowing/include/OvWindowing/Inputs/InputManager.h diff --git a/Sources/Overload/OvWindowing/include/OvWindowing/Settings/DeviceSettings.h b/Sources/OvWindowing/include/OvWindowing/Settings/DeviceSettings.h similarity index 100% rename from Sources/Overload/OvWindowing/include/OvWindowing/Settings/DeviceSettings.h rename to Sources/OvWindowing/include/OvWindowing/Settings/DeviceSettings.h diff --git a/Sources/Overload/OvWindowing/include/OvWindowing/Settings/WindowSettings.h b/Sources/OvWindowing/include/OvWindowing/Settings/WindowSettings.h similarity index 100% rename from Sources/Overload/OvWindowing/include/OvWindowing/Settings/WindowSettings.h rename to Sources/OvWindowing/include/OvWindowing/Settings/WindowSettings.h diff --git a/Sources/Overload/OvWindowing/include/OvWindowing/Window.h b/Sources/OvWindowing/include/OvWindowing/Window.h similarity index 100% rename from Sources/Overload/OvWindowing/include/OvWindowing/Window.h rename to Sources/OvWindowing/include/OvWindowing/Window.h diff --git a/Sources/Overload/OvWindowing/premake5.lua b/Sources/OvWindowing/premake5.lua similarity index 93% rename from Sources/Overload/OvWindowing/premake5.lua rename to Sources/OvWindowing/premake5.lua index 8d7473a1e..073a950c5 100644 --- a/Sources/Overload/OvWindowing/premake5.lua +++ b/Sources/OvWindowing/premake5.lua @@ -19,7 +19,7 @@ project "OvWindowing" dependdir .. "stb_image/include", -- Overload SDK - "%{wks.location}/OvTools/include", + "%{wks.location}/Sources/OvTools/include", -- Current Project "include" diff --git a/Sources/Overload/OvWindowing/src/OvWindowing/Context/Device.cpp b/Sources/OvWindowing/src/OvWindowing/Context/Device.cpp similarity index 100% rename from Sources/Overload/OvWindowing/src/OvWindowing/Context/Device.cpp rename to Sources/OvWindowing/src/OvWindowing/Context/Device.cpp diff --git a/Sources/Overload/OvWindowing/src/OvWindowing/Dialogs/FileDialog.cpp b/Sources/OvWindowing/src/OvWindowing/Dialogs/FileDialog.cpp similarity index 57% rename from Sources/Overload/OvWindowing/src/OvWindowing/Dialogs/FileDialog.cpp rename to Sources/OvWindowing/src/OvWindowing/Dialogs/FileDialog.cpp index 80f3e2260..700a05201 100644 --- a/Sources/Overload/OvWindowing/src/OvWindowing/Dialogs/FileDialog.cpp +++ b/Sources/OvWindowing/src/OvWindowing/Dialogs/FileDialog.cpp @@ -6,7 +6,15 @@ #include +#ifdef _WIN32 #include +#else +#include +#include +#include +#include +#include +#endif #include "OvWindowing/Dialogs/FileDialog.h" @@ -24,6 +32,7 @@ void OvWindowing::Dialogs::FileDialog::SetInitialDirectory(const std::string & p void OvWindowing::Dialogs::FileDialog::Show(EExplorerFlags p_flags) { +#ifdef _WIN32 OPENFILENAME ofn; if (!m_initialDirectory.empty()) @@ -56,6 +65,95 @@ void OvWindowing::Dialogs::FileDialog::Show(EExplorerFlags p_flags) for (auto it = m_filepath.rbegin(); it != m_filepath.rend() && *it != '\\' && *it != '/'; ++it) m_filename += *it; std::reverse(m_filename.begin(), m_filename.end()); +#else + // Linux implementation using zenity + std::string command = "zenity --file-selection --title=\"" + m_dialogTitle + "\""; + + if (m_isSaveDialog) + command += " --save"; + + if (!m_initialDirectory.empty()) + { + // Add trailing slash to indicate directory for zenity + command += " --filename=\"" + m_initialDirectory; + if (m_initialDirectory.back() != '/') + command += "/"; + command += "\""; + } + else + { + // Even without initial directory, --filename="" helps show the filename entry + command += " --filename=\"\""; + } + + // Add file filters if present + if (!m_filter.empty()) + { + std::string filters = m_filter; + size_t pos = 0; + while (pos < filters.length()) + { + // Skip label (terminated by null) + size_t labelEnd = filters.find('\0', pos); + if (labelEnd == std::string::npos) break; + + pos = labelEnd + 1; + if (pos >= filters.length()) break; + + // Get filter pattern + size_t patternEnd = filters.find('\0', pos); + if (patternEnd == std::string::npos) patternEnd = filters.length(); + + std::string pattern = filters.substr(pos, patternEnd - pos); + if (!pattern.empty()) + { + command += " --file-filter='" + pattern + "'"; + } + + pos = patternEnd + 1; + } + } + + command += " 2>/dev/null"; // Suppress GTK warnings + + // Execute zenity and capture output + std::array buffer; + std::string result; + std::unique_ptr pipe(popen(command.c_str(), "r"), pclose); + + if (!pipe) + { + m_succeeded = false; + m_error = "Failed to open zenity"; + return; + } + + while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) + { + result += buffer.data(); + } + + // Remove trailing newline + if (!result.empty() && result.back() == '\n') + result.pop_back(); + + m_succeeded = !result.empty(); + + if (m_succeeded) + { + m_filepath = result; + + /* Extract filename from filepath */ + m_filename.clear(); + for (auto it = m_filepath.rbegin(); it != m_filepath.rend() && *it != '\\' && *it != '/'; ++it) + m_filename += *it; + std::reverse(m_filename.begin(), m_filename.end()); + } + else + { + m_error = "Dialog cancelled or zenity not available"; + } +#endif } bool OvWindowing::Dialogs::FileDialog::HasSucceeded() const @@ -85,6 +183,7 @@ bool OvWindowing::Dialogs::FileDialog::IsFileExisting() const void OvWindowing::Dialogs::FileDialog::HandleError() { +#ifdef _WIN32 switch (CommDlgExtendedError()) { case CDERR_DIALOGFAILURE: m_error = "CDERR_DIALOGFAILURE"; break; @@ -104,4 +203,7 @@ void OvWindowing::Dialogs::FileDialog::HandleError() case FNERR_SUBCLASSFAILURE: m_error = "FNERR_SUBCLASSFAILURE"; break; default: m_error = "You cancelled."; } +#else + m_error = "Dialog operation failed"; +#endif } diff --git a/Sources/OvWindowing/src/OvWindowing/Dialogs/MessageBox.cpp b/Sources/OvWindowing/src/OvWindowing/Dialogs/MessageBox.cpp new file mode 100644 index 000000000..479d2168b --- /dev/null +++ b/Sources/OvWindowing/src/OvWindowing/Dialogs/MessageBox.cpp @@ -0,0 +1,191 @@ +/** +* @project: Overload +* @author: Overload Tech. +* @licence: MIT +*/ + +#ifdef _WIN32 +#include +#else +#include +#include +#include +#endif + +#include "OvWindowing/Dialogs/MessageBox.h" + +#undef MessageBox + +OvWindowing::Dialogs::MessageBox::MessageBox(std::string p_title, std::string p_message, EMessageType p_messageType, EButtonLayout p_buttonLayout, bool p_autoSpawn) : + m_title(p_title), + m_message(p_message), + m_buttonLayout(p_buttonLayout), + m_messageType(p_messageType) +{ + if (p_autoSpawn) + Spawn(); +} + +const OvWindowing::Dialogs::MessageBox::EUserAction& OvWindowing::Dialogs::MessageBox::GetUserAction() const +{ + return m_userResult; +} + +void OvWindowing::Dialogs::MessageBox::Spawn() +{ +#ifdef _WIN32 + int msgboxID = MessageBoxA + ( + nullptr, + static_cast(m_message.c_str()), + static_cast(m_title.c_str()), + static_cast(m_messageType) | static_cast(m_buttonLayout) | MB_DEFBUTTON2 + ); + + m_userResult = static_cast(msgboxID); +#else + // Linux implementation using zenity + std::string command = "zenity --question"; // Always use question dialog for flexibility + + // Add title and message + command += " --title=\"" + m_title + "\""; + command += " --text=\"" + m_message + "\""; + command += " --no-markup"; // Prevent markup interpretation issues + + // Handle button layout + bool useExtraButtons = false; + + switch (m_buttonLayout) + { + case EButtonLayout::OK: + command += " --ok-label=\"OK\" --no-cancel"; + break; + case EButtonLayout::OK_CANCEL: + command += " --ok-label=\"OK\" --cancel-label=\"Cancel\""; + break; + case EButtonLayout::YES_NO: + command += " --ok-label=\"Yes\" --cancel-label=\"No\""; + break; + case EButtonLayout::YES_NO_CANCEL: + useExtraButtons = true; + // When using extra buttons, don't use ok-label or cancel-label + command += " --extra-button=\"Yes\" --extra-button=\"No\" --extra-button=\"Cancel\""; + break; + case EButtonLayout::RETRY_CANCEL: + command += " --ok-label=\"Retry\" --cancel-label=\"Cancel\""; + break; + case EButtonLayout::ABORT_RETRY_IGNORE: + useExtraButtons = true; + command += " --extra-button=\"Abort\" --extra-button=\"Retry\" --extra-button=\"Ignore\""; + break; + case EButtonLayout::CANCEL_TRYAGAIN_CONTINUE: + useExtraButtons = true; + command += " --extra-button=\"Cancel\" --extra-button=\"Try Again\" --extra-button=\"Continue\""; + break; + case EButtonLayout::HELP: + command += " --ok-label=\"Help\" --no-cancel"; + break; + } + + command += " 2>/dev/null"; // Suppress GTK warnings + + // Execute zenity and check exit code + int exitCode = system(command.c_str()); + int zenityResult = WEXITSTATUS(exitCode); + + // Map zenity exit codes to EUserAction + // zenity returns: 0 for OK/Yes, 1 for Cancel/No, 5 for timeout, + // -1 for error, and button text for extra buttons + + if (useExtraButtons) + { + // For extra buttons, we need to capture the output + std::string captureCommand = command.substr(0, command.find(" 2>/dev/null")); + captureCommand += " 2>/dev/null"; + + std::array buffer; + std::string result; + std::unique_ptr pipe(popen(captureCommand.c_str(), "r"), pclose); + + if (pipe) + { + while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) + { + result += buffer.data(); + } + } + + // Remove trailing newline + if (!result.empty() && result.back() == '\n') + result.pop_back(); + + // Map based on button text and layout + if (m_buttonLayout == EButtonLayout::YES_NO_CANCEL) + { + if (result == "Yes") + m_userResult = EUserAction::YES; + else if (result == "No") + m_userResult = EUserAction::NO; + else + m_userResult = EUserAction::CANCEL; + } + else if (m_buttonLayout == EButtonLayout::ABORT_RETRY_IGNORE) + { + if (result == "Abort") + m_userResult = EUserAction::CANCEL; // Map Abort to Cancel (no direct equivalent) + else if (result == "Retry") + m_userResult = EUserAction::RETRY; + else if (result == "Ignore") + m_userResult = EUserAction::IGNORE; + else + m_userResult = EUserAction::CANCEL; // Dialog closed + } + else if (m_buttonLayout == EButtonLayout::CANCEL_TRYAGAIN_CONTINUE) + { + if (result == "Try Again") + m_userResult = EUserAction::TRYAGAIN; + else if (result == "Continue") + m_userResult = EUserAction::CONTINUE; + else + m_userResult = EUserAction::CANCEL; + } + else + { + m_userResult = EUserAction::CANCEL; + } + } + else + { + // Simple OK/Cancel mapping + if (zenityResult == 0) + { + // OK/Yes/Retry button pressed + switch (m_buttonLayout) + { + case EButtonLayout::YES_NO: + m_userResult = EUserAction::YES; + break; + case EButtonLayout::RETRY_CANCEL: + m_userResult = EUserAction::RETRY; + break; + default: + m_userResult = EUserAction::OK; + break; + } + } + else + { + // Cancel/No button pressed + switch (m_buttonLayout) + { + case EButtonLayout::YES_NO: + m_userResult = EUserAction::NO; + break; + default: + m_userResult = EUserAction::CANCEL; + break; + } + } + } +#endif +} diff --git a/Sources/Overload/OvWindowing/src/OvWindowing/Dialogs/OpenFileDialog.cpp b/Sources/OvWindowing/src/OvWindowing/Dialogs/OpenFileDialog.cpp similarity index 60% rename from Sources/Overload/OvWindowing/src/OvWindowing/Dialogs/OpenFileDialog.cpp rename to Sources/OvWindowing/src/OvWindowing/Dialogs/OpenFileDialog.cpp index 9f11dcd1e..28577a44f 100644 --- a/Sources/Overload/OvWindowing/src/OvWindowing/Dialogs/OpenFileDialog.cpp +++ b/Sources/OvWindowing/src/OvWindowing/Dialogs/OpenFileDialog.cpp @@ -6,11 +6,20 @@ #include "OvWindowing/Dialogs/OpenFileDialog.h" +#ifdef _WIN32 #include OvWindowing::Dialogs::OpenFileDialog::OpenFileDialog(const std::string & p_dialogTitle) : FileDialog(GetOpenFileNameA, p_dialogTitle) { } +#else +// Dummy callback for Linux (not used, but needed for constructor) +static int DummyOpenCallback(tagOFNA*) { return 0; } + +OvWindowing::Dialogs::OpenFileDialog::OpenFileDialog(const std::string & p_dialogTitle) : FileDialog(DummyOpenCallback, p_dialogTitle) +{ +} +#endif void OvWindowing::Dialogs::OpenFileDialog::AddFileType(const std::string & p_label, const std::string & p_filter) { diff --git a/Sources/Overload/OvWindowing/src/OvWindowing/Dialogs/SaveFileDialog.cpp b/Sources/OvWindowing/src/OvWindowing/Dialogs/SaveFileDialog.cpp similarity index 77% rename from Sources/Overload/OvWindowing/src/OvWindowing/Dialogs/SaveFileDialog.cpp rename to Sources/OvWindowing/src/OvWindowing/Dialogs/SaveFileDialog.cpp index 04bc5720a..b24baa5b3 100644 --- a/Sources/Overload/OvWindowing/src/OvWindowing/Dialogs/SaveFileDialog.cpp +++ b/Sources/OvWindowing/src/OvWindowing/Dialogs/SaveFileDialog.cpp @@ -6,11 +6,21 @@ #include "OvWindowing/Dialogs/SaveFileDialog.h" +#ifdef _WIN32 #include OvWindowing::Dialogs::SaveFileDialog::SaveFileDialog(const std::string & p_dialogTitle) : FileDialog(GetSaveFileNameA, p_dialogTitle) { } +#else +// Dummy callback for Linux (not used, but needed for constructor) +static int DummySaveCallback(tagOFNA*) { return 0; } + +OvWindowing::Dialogs::SaveFileDialog::SaveFileDialog(const std::string & p_dialogTitle) : FileDialog(DummySaveCallback, p_dialogTitle) +{ + m_isSaveDialog = true; +} +#endif void OvWindowing::Dialogs::SaveFileDialog::Show(EExplorerFlags p_flags) { diff --git a/Sources/Overload/OvWindowing/src/OvWindowing/Inputs/InputManager.cpp b/Sources/OvWindowing/src/OvWindowing/Inputs/InputManager.cpp similarity index 100% rename from Sources/Overload/OvWindowing/src/OvWindowing/Inputs/InputManager.cpp rename to Sources/OvWindowing/src/OvWindowing/Inputs/InputManager.cpp diff --git a/Sources/Overload/OvWindowing/src/OvWindowing/Window.cpp b/Sources/OvWindowing/src/OvWindowing/Window.cpp similarity index 100% rename from Sources/Overload/OvWindowing/src/OvWindowing/Window.cpp rename to Sources/OvWindowing/src/OvWindowing/Window.cpp diff --git a/Sources/Overload/OvCore/include/OvCore/ResourceManagement/AResourceManager.inl b/Sources/Overload/OvCore/include/OvCore/ResourceManagement/AResourceManager.inl deleted file mode 100644 index 5acb1cffe..000000000 --- a/Sources/Overload/OvCore/include/OvCore/ResourceManagement/AResourceManager.inl +++ /dev/null @@ -1,148 +0,0 @@ -/** -* @project: Overload -* @author: Overload Tech. -* @licence: MIT -*/ - -#pragma once - -#include - -#include "OvCore/ResourceManagement/AResourceManager.h" - -namespace OvCore::ResourceManagement -{ - template - inline T* AResourceManager::LoadResource(const std::string & p_path) - { - if (auto resource = GetResource(p_path, false); resource) - return resource; - else - { - auto newResource = CreateResource(p_path); - if (newResource) - return RegisterResource(p_path, newResource); - else - return nullptr; - } - } - - template - inline void AResourceManager::UnloadResource(const std::string & p_path) - { - if (auto resource = GetResource(p_path, false); resource) - { - DestroyResource(resource); - UnregisterResource(p_path); - } - } - - template - inline bool AResourceManager::MoveResource(const std::string & p_previousPath, const std::string & p_newPath) - { - if (IsResourceRegistered(p_previousPath) && !IsResourceRegistered(p_newPath)) - { - T* toMove = m_resources.at(p_previousPath); - UnregisterResource(p_previousPath); - RegisterResource(p_newPath, toMove); - return true; - } - - return false; - } - - template - inline void AResourceManager::ReloadResource(const std::string& p_path) - { - if (auto resource = GetResource(p_path, false); resource) - { - ReloadResource(resource, p_path); - } - } - - template - inline bool AResourceManager::IsResourceRegistered(const std::string & p_path) - { - return m_resources.find(p_path) != m_resources.end(); - } - - template - inline void AResourceManager::UnloadResources() - { - for (auto&[key, value] : m_resources) - DestroyResource(value); - - m_resources.clear(); - } - - template - inline T* AResourceManager::RegisterResource(const std::string& p_path, T* p_instance) - { - if (auto resource = GetResource(p_path, false); resource) - DestroyResource(resource); - - m_resources[p_path] = p_instance; - - return p_instance; - } - - template - inline void AResourceManager::UnregisterResource(const std::string & p_path) - { - m_resources.erase(p_path); - } - - template - inline T* AResourceManager::GetResource(const std::string& p_path, bool p_tryToLoadIfNotFound) - { - if (auto resource = m_resources.find(p_path); resource != m_resources.end()) - { - return resource->second; - } - else if (p_tryToLoadIfNotFound) - { - return LoadResource(p_path); - } - - return nullptr; - } - - template - inline T* AResourceManager::operator[](const std::string & p_path) - { - return GetResource(p_path); - } - - template - inline void AResourceManager::ProvideAssetPaths( - const std::filesystem::path& p_projectAssetsPath, - const std::filesystem::path& p_engineAssetsPath - ) - { - __PROJECT_ASSETS_PATH = p_projectAssetsPath; - __ENGINE_ASSETS_PATH = p_engineAssetsPath; - } - - template - inline std::unordered_map& AResourceManager::GetResources() - { - return m_resources; - } - - template - inline std::string AResourceManager::GetRealPath(const std::string& p_path) const - { - std::filesystem::path path; - - if (p_path.starts_with(':')) // The path is an engine path - { - path = __ENGINE_ASSETS_PATH / p_path.substr(1); - } - else // The path is a project path - { - path = __PROJECT_ASSETS_PATH / p_path; - } - - return path.string(); - } -} \ No newline at end of file diff --git a/Sources/Overload/OvEditor/premake5.lua b/Sources/Overload/OvEditor/premake5.lua deleted file mode 100644 index d3737fdcd..000000000 --- a/Sources/Overload/OvEditor/premake5.lua +++ /dev/null @@ -1,103 +0,0 @@ -project "OvEditor" - language "C++" - cppdialect "C++20" - targetdir (outputdir .. "%{cfg.buildcfg}/%{prj.name}") - objdir (objoutdir .. "%{cfg.buildcfg}/%{prj.name}") - debugdir "%{wks.location}/../../Build/%{cfg.buildcfg}" - - files { - "**.h", - "**.inl", - "**.cpp", - "**.lua", - "**.ini", - "**.rc", - } - - includedirs { - -- Dependencies - dependdir .. "glad/include", - dependdir .. "ImGui/include", - dependdir .. "tinyxml2/include", - dependdir .. "tracy", - - -- Overload SDK - "%{wks.location}/OvAudio/include", - "%{wks.location}/OvCore/include", - "%{wks.location}/OvDebug/include", - "%{wks.location}/OvMaths/include", - "%{wks.location}/OvPhysics/include", - "%{wks.location}/OvRendering/include", - "%{wks.location}/OvTools/include", - "%{wks.location}/OvUI/include", - "%{wks.location}/OvWindowing/include", - - -- Current project - "include" - } - - links { - -- Precompiled Libraries - "dbghelp.lib", - "opengl32.lib", - - -- Dependencies - "assimp", - "bullet3", - "glad", - "glfw", - "ImGui", - "lua", - "soloud", - "tinyxml2", - "tracy", - - -- Overload SDK - "OvAudio", - "OvCore", - "OvDebug", - "OvMaths", - "OvPhysics", - "OvRendering", - "OvTools", - "OvUI", - "OvWindowing" - } - - postbuildcommands { - "for /f \"delims=|\" %%i in ('dir /B /S \"%{dependdir}\\*.dll\"') do xcopy /Q /Y \"%%i\" \"%{outputdir}%{cfg.buildcfg}\\%{prj.name}\"", - - "rmdir /s /q \"%{builddir}%{cfg.buildcfg}\\Data\"", - - "xcopy \"%{resdir}Engine\\*\" \"%{builddir}%{cfg.buildcfg}\\Data\\Engine\" /y /i /r /e /q", - "xcopy \"%{resdir}Editor\\*\" \"%{builddir}%{cfg.buildcfg}\\Data\\Editor\" /y /i /r /e /q", - "xcopy \"%{prj.location}\\Layout.ini\" \"%{builddir}%{cfg.buildcfg}\\Config\\\" /y /i", - - "xcopy \"%{wks.location}\\..\\..\\Tools\\tracy-profiler.exe\" \"%{builddir}%{cfg.buildcfg}\\Tools\\\" /y /i", - - "xcopy /Y /I /Q /D \"%{outputdir}%{cfg.buildcfg}\\%{prj.name}\\*.exe\" \"%{builddir}%{cfg.buildcfg}\\\"", - "xcopy /Y /I /Q /D \"%{outputdir}%{cfg.buildcfg}\\%{prj.name}\\*.dll\" \"%{builddir}%{cfg.buildcfg}\\\"", - - "xcopy \"%{outputdir}Debug\\OvGame\\*.exe\" \"%{builddir}%{cfg.buildcfg}\\Builder\\Development\" /y /i /c", - "xcopy \"%{outputdir}Debug\\OvGame\\*.dll\" \"%{builddir}%{cfg.buildcfg}\\Builder\\Development\" /y /i /c", - "xcopy \"%{outputdir}Release\\OvGame\\*.exe\" \"%{builddir}%{cfg.buildcfg}\\Builder\\Shipping\" /y /i /c", - "xcopy \"%{outputdir}Release\\OvGame\\*.dll\" \"%{builddir}%{cfg.buildcfg}\\Builder\\Shipping\" /y /i /c", - - "EXIT /B 0" - } - - filter { "configurations:Debug" } - defines { "DEBUG" } - symbols "On" - kind "ConsoleApp" - - filter { "configurations:Release" } - defines { "NDEBUG" } - optimize "Speed" - flags { "LinkTimeOptimization" } - kind "WindowedApp" - - filter { "system:windows" } - characterset ("MBCS") - -- forces post-build commands to trigger even if nothing changed - fastuptodate "Off" diff --git a/Sources/Overload/OvGame/premake5.lua b/Sources/Overload/OvGame/premake5.lua deleted file mode 100644 index 197e9a47c..000000000 --- a/Sources/Overload/OvGame/premake5.lua +++ /dev/null @@ -1,85 +0,0 @@ -project "OvGame" - language "C++" - cppdialect "C++20" - targetdir (outputdir .. "%{cfg.buildcfg}/%{prj.name}") - objdir (objoutdir .. "%{cfg.buildcfg}/%{prj.name}") - debugdir (outputdir .. "%{cfg.buildcfg}/%{prj.name}") - - files { - "**.h", - "**.inl", - "**.cpp", - "**.lua", - "**.ini", - "**.rc" - } - - includedirs { - -- Dependencies - dependdir .. "glad/include", - dependdir .. "ImGui/include", - dependdir .. "tracy", - - -- Overload SDK - "%{wks.location}/OvAudio/include", - "%{wks.location}/OvCore/include", - "%{wks.location}/OvDebug/include", - "%{wks.location}/OvMaths/include", - "%{wks.location}/OvPhysics/include", - "%{wks.location}/OvRendering/include", - "%{wks.location}/OvTools/include", - "%{wks.location}/OvUI/include", - "%{wks.location}/OvWindowing/include", - - -- Current project - "include" - } - - links { - -- Precompiled Libraries - "dbghelp.lib", - "opengl32.lib", - - -- Dependencies - "assimp", - "bullet3", - "glad", - "glfw", - "ImGui", - "lua", - "soloud", - "tinyxml2", - "tracy", - - -- Overload SDK - "OvAudio", - "OvCore", - "OvDebug", - "OvMaths", - "OvPhysics", - "OvRendering", - "OvTools", - "OvUI", - "OvWindowing" - } - - postbuildcommands { - "for /f \"delims=|\" %%i in ('dir /B /S \"%{dependdir}\\*.dll\"') do xcopy /Q /Y \"%%i\" \"%{outputdir}%{cfg.buildcfg}\\%{prj.name}\"", - "xcopy \"%{resdir}Engine\\*\" \"%{outputdir}%{cfg.buildcfg}\\%{prj.name}\\Data\\Engine\" /y /i /r /e /q", - "EXIT /B 0" - } - - filter { "configurations:Debug" } - defines { "DEBUG" } - symbols "On" - kind "ConsoleApp" - - filter { "configurations:Release" } - defines { "NDEBUG" } - optimize "Speed" - flags { "LinkTimeOptimization" } - kind "WindowedApp" - - filter { "system:windows" } - -- forces post-build commands to trigger even if nothing changed - fastuptodate "Off" diff --git a/Sources/Overload/OvRendering/include/OvRendering/Utils/Defines.h b/Sources/Overload/OvRendering/include/OvRendering/Utils/Defines.h deleted file mode 100644 index f57e3bace..000000000 --- a/Sources/Overload/OvRendering/include/OvRendering/Utils/Defines.h +++ /dev/null @@ -1,14 +0,0 @@ -/** -* @project: Overload -* @author: Overload Tech. -* @licence: MIT -*/ - -#pragma once - -#define FORCE_DEDICATED_GPU \ -extern "C"\ -{\ - __declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001;\ - __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;\ -} diff --git a/Sources/Overload/OvWindowing/src/OvWindowing/Dialogs/MessageBox.cpp b/Sources/Overload/OvWindowing/src/OvWindowing/Dialogs/MessageBox.cpp deleted file mode 100644 index 3cab687ce..000000000 --- a/Sources/Overload/OvWindowing/src/OvWindowing/Dialogs/MessageBox.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/** -* @project: Overload -* @author: Overload Tech. -* @licence: MIT -*/ - -#include - -#include "OvWindowing/Dialogs/MessageBox.h" - -#undef MessageBox - -OvWindowing::Dialogs::MessageBox::MessageBox(std::string p_title, std::string p_message, EMessageType p_messageType, EButtonLayout p_buttonLayout, bool p_autoSpawn) : - m_title(p_title), - m_message(p_message), - m_buttonLayout(p_buttonLayout), - m_messageType(p_messageType) -{ - if (p_autoSpawn) - Spawn(); -} - -const OvWindowing::Dialogs::MessageBox::EUserAction& OvWindowing::Dialogs::MessageBox::GetUserAction() const -{ - return m_userResult; -} - -void OvWindowing::Dialogs::MessageBox::Spawn() -{ - int msgboxID = MessageBoxA - ( - nullptr, - static_cast(m_message.c_str()), - static_cast(m_title.c_str()), - static_cast(m_messageType) | static_cast(m_buttonLayout) | MB_DEFBUTTON2 - ); - - m_userResult = static_cast(msgboxID); -} diff --git a/Sources/Overload/premake5.lua b/Sources/Overload/premake5.lua deleted file mode 100644 index d64ca64c5..000000000 --- a/Sources/Overload/premake5.lua +++ /dev/null @@ -1,71 +0,0 @@ --- Function to read the version number from VERSION.txt -local function readVersion() - local versionFile = io.open("../../VERSION.txt", "r") - if versionFile then - local version = versionFile:read("*l") - versionFile:close() - return version - else - error("Could not open VERSION.txt") - end -end - -local version = readVersion() - -workspace "Overload" - configurations { "Debug", "Release" } - platforms { "x64" } - startproject "OvEditor" - defines { - "LUA_SCRIPTING", - "GRAPHICS_API_OPENGL", - "OVERLOAD_VERSION=\"" .. version .. "\"", - "TRACY_ENABLE", - "TRACY_ON_DEMAND", - "TRACY_MEMORY_ENABLE" - } - - -- Disable "Hot Reload": Doesn't work with Tracy. - editandcontinue "Off" - -outputdir = "%{wks.location}/../../Bin/" -objoutdir = "%{wks.location}/../../Bin-Int/" -dependdir = "%{wks.location}/../../Dependencies/" -builddir = "%{wks.location}/../../Build/" -resdir = "%{wks.location}/../../Resources/" - -group "Dependencies" - include "../../Dependencies/ImGui" - include "../../Dependencies/tinyxml2" - include "../../Dependencies/tracy" - include "../../Dependencies/lua" - include "../../Dependencies/glad" - include "../../Dependencies/soloud" - include "../../Dependencies/assimp" - include "../../Dependencies/glfw" - include "../../Dependencies/bullet3" -group "" - -group "Dependencies/Prebuilt" - include "../../Dependencies/stb_image" - include "../../Dependencies/sol" -group "" - -group "Overload SDK" - include "OvAudio" - include "OvCore" - include "OvDebug" - include "OvMaths" - include "OvPhysics" - include "OvRendering" - include "OvTools" - include "OvUI" - include "OvWindowing" -group "" - -group "Overload Apps" - include "OvEditor" - include "OvGame" -group "" - -include "../../Resources" diff --git a/gen_proj_linux.sh b/gen_proj_linux.sh new file mode 100755 index 000000000..fd08ffee9 --- /dev/null +++ b/gen_proj_linux.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +# Call the Linux GenerateProjects script +"$(dirname "$0")/Scripts/Linux/GenerateProjects.sh" "$@" diff --git a/gen_proj_win32.bat b/gen_proj_win32.bat new file mode 100644 index 000000000..b9e53a64b --- /dev/null +++ b/gen_proj_win32.bat @@ -0,0 +1,6 @@ +@echo off + +REM Call the Windows GenerateProjects script +call "%~dp0\Scripts\Windows\GenerateProjects.bat" %* + +exit /b %errorlevel% diff --git a/premake5.lua b/premake5.lua new file mode 100644 index 000000000..e1aba572a --- /dev/null +++ b/premake5.lua @@ -0,0 +1,78 @@ +-- Function to read the version number from VERSION.txt +local function readVersion() + local versionFile = io.open("VERSION.txt", "r") + if versionFile then + local version = versionFile:read("*l") + versionFile:close() + return version + else + error("Could not open VERSION.txt") + end +end + +local version = readVersion() + +workspace "Overload" + configurations { "Debug", "Release" } + platforms { "x64" } + startproject "OvEditor" + defines { + "LUA_SCRIPTING", + "GRAPHICS_API_OPENGL", + "OVERLOAD_VERSION=\"" .. version .. "\"", + "TRACY_ENABLE", + "TRACY_ON_DEMAND", + "TRACY_MEMORY_ENABLE" + } + + -- Set toolset based on operating system + filter {"system:windows"} + toolset("msc") + filter {"system:linux"} + toolset("clang") -- Use Clang on Linux (sol2 doesn't work well with GCC) + filter {} + + -- Disable "Hot Reload": Doesn't work with Tracy. + editandcontinue "Off" + +outputdir = "%{wks.location}/Bin/" +objoutdir = "%{wks.location}/Bin-Int/" +dependdir = "%{wks.location}/Dependencies/" +builddir = "%{wks.location}/Build/" +resdir = "%{wks.location}/Resources/" + +group "Dependencies" + include "Dependencies/ImGui" + include "Dependencies/tinyxml2" + include "Dependencies/tracy" + include "Dependencies/lua" + include "Dependencies/glad" + include "Dependencies/soloud" + include "Dependencies/assimp" + include "Dependencies/glfw" + include "Dependencies/bullet3" +group "" + +group "Dependencies/Prebuilt" + include "Dependencies/stb_image" + include "Dependencies/sol" +group "" + +group "Overload SDK" + include "Sources/OvAudio" + include "Sources/OvCore" + include "Sources/OvDebug" + include "Sources/OvMaths" + include "Sources/OvPhysics" + include "Sources/OvRendering" + include "Sources/OvTools" + include "Sources/OvUI" + include "Sources/OvWindowing" +group "" + +group "Overload Apps" + include "Sources/OvEditor" + include "Sources/OvGame" +group "" + +include "Resources"