First iteration of the WUPS-Backend as a .rpx/module for the SetupPayload

- Function replacements are not implemented yet
- Serveral features like the config menu are missing

Still WIP
This commit is contained in:
Maschell 2020-04-29 18:02:36 +02:00
parent a83d11379e
commit 2705a91c13
188 changed files with 7644 additions and 27184 deletions

11
.gitignore vendored
View File

@ -1,7 +1,6 @@
*.elf
*.rpx
*.bin
hook.h
build/
*.cbp
WiiUPluginLoaderBackend.layout
*.elf
*.layout
*.rpx
build/
*.save-failed

158
Makefile
View File

@ -3,19 +3,14 @@
#-------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITPRO)),)
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitPro")
endif
ifeq ($(strip $(DEVKITPPC)),)
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>/devkitPro/devkitPPC")
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITPPC)/base_rules
MACHDEP = -DESPRESSO -mcpu=750 -meabi -mhard-float
include $(DEVKITPRO)/wut/share/wut_rules
WUPS_ROOT := $(DEVKITPRO)/wups
#-------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
@ -23,160 +18,129 @@ MACHDEP = -DESPRESSO -mcpu=750 -meabi -mhard-float
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#-------------------------------------------------------------------------------
TARGET := hook_payload
TARGET := PluginBackend
BUILD := build
BUILD_DBG := $(TARGET)_dbg
SOURCES := src \
src/common \
src/libelf \
src/fs \
src/dynamic_libs \
src/kernel \
src/memory \
src/plugin \
src/patcher \
src/settings \
src/system \
src/utils
SOURCES := source \
source/elfio \
source/kernel \
source/patcher \
source/plugin \
source/utils
DATA := data
INCLUDES := src \
src/libelf
INCLUDES := source
#-------------------------------------------------------------------------------
# options for code generation
#-------------------------------------------------------------------------------
CFLAGS := -g -Wall -O0 -ffunction-sections \
CFLAGS := -g -Wall -O0 -ffunction-sections -std=c++17 \
$(MACHDEP)
CFLAGS += $(INCLUDE) -D__WIIU__ -D_GNU_SOURCE
CFLAGS += $(INCLUDE) -D__WIIU__ -D__WUT__
CXXFLAGS := $(CFLAGS)
ASFLAGS := -g -mregnames $(ARCH)
LDFLAGS = -g $(ARCH) -nostartfiles -Wl,-Map,$(notdir $@).map,-wrap,malloc,-wrap,free,-wrap,memalign,-wrap,calloc,-wrap,realloc,-wrap,malloc_usable_size,-wrap,_malloc_r,-wrap,_free_r,-wrap,_realloc_r,-wrap,_calloc_r,-wrap,_memalign_r,-wrap,_malloc_usable_size_r,-wrap,valloc,-wrap,_valloc_r,-wrap,_pvalloc_r,--gc-sections
ASFLAGS := -g $(ARCH)
LDFLAGS = -g $(ARCH) $(RPXSPECS) --entry=_start -Wl,-Map,$(notdir $*.map)
LIBS :=
LIBS := -lwut -lwups
#-------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level
# containing include and lib
#-------------------------------------------------------------------------------
LIBDIRS := $(DEVKITPRO)/wups
LIBDIRS := $(PORTLIBS) $(WUT_ROOT) $(WUPS_ROOT)
#---------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export PROJECTDIR := $(CURDIR)
export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET)
#-------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
#---------------------------------------------------------------------------------
# automatically build a list of object files for our project
#---------------------------------------------------------------------------------
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
TTFFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.ttf)))
PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png)))
#---------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#-------------------------------------------------------------------------------
export LD := $(CC)
#-------------------------------------------------------------------------------
else
#-------------------------------------------------------------------------------
export LD := $(CXX)
#-------------------------------------------------------------------------------
endif
#-------------------------------------------------------------------------------
export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \
$(sFILES:.s=.o) $(SFILES:.S=.o) \
$(PNGFILES:.png=.png.o) $(addsuffix .o,$(BINFILES))
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
#---------------------------------------------------------------------------------
# build a list of include paths
#---------------------------------------------------------------------------------
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
#---------------------------------------------------------------------------------
# build a list of library paths
#---------------------------------------------------------------------------------
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
export OUTPUT := $(CURDIR)/$(TARGET)
.PHONY: $(BUILD) clean install
.PHONY: $(BUILD) clean all
#-------------------------------------------------------------------------------
all: $(BUILD)
#---------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
clean:
@rm -fr $(BUILD) $(OUTPUT).elf $(BUILD_DBG).elf
@echo clean ...
@rm -fr $(BUILD) $(TARGET).rpx $(TARGET).elf
#---------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
else
.PHONY: all
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT).elf: $(OFILES)
#-------------------------------------------------------------------------------
all : $(OUTPUT).rpx
#---------------------------------------------------------------------------------
# This rule links in binary data with the .jpg extension
#---------------------------------------------------------------------------------
%.elf: link.ld $(OFILES)
@echo "linking ... $(TARGET).elf"
@$(LD) -n -T $^ $(LDFLAGS) -o ../$(BUILD_DBG).elf $(LIBPATHS) $(LIBS)
@$(OBJCOPY) -S -R .comment -R .gnu.attributes ../$(BUILD_DBG).elf $@
$(OUTPUT).rpx : $(OUTPUT).elf
$(OUTPUT).elf : $(OFILES)
#---------------------------------------------------------------------------------
%.a:
#---------------------------------------------------------------------------------
@echo $(notdir $@)
@rm -f $@
@$(AR) -rc $@ $^
$(OFILES_SRC) : $(HFILES_BIN)
#---------------------------------------------------------------------------------
%.o: %.cpp
#-------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#-------------------------------------------------------------------------------
%.bin.o %_bin.h : %.bin
#-------------------------------------------------------------------------------
@echo $(notdir $<)
@$(CXX) -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER)
@$(bin2o)
#---------------------------------------------------------------------------------
%.o: %.c
@echo $(notdir $<)
@$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d $(CFLAGS) -c $< -o $@ $(ERROR_FILTER)
#---------------------------------------------------------------------------------
%.o: %.S
%.o: %.s
@echo $(notdir $<)
@$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d -x assembler-with-cpp $(ASFLAGS) -c $< -o $@ $(ERROR_FILTER)
#---------------------------------------------------------------------------------
%.png.o : %.png
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
#---------------------------------------------------------------------------------
%.ttf.o : %.ttf
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
-include $(DEPENDS)
#---------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
#-------------------------------------------------------------------------------

View File

@ -2,7 +2,7 @@
This is the Backend for the [WiiUPluginSystem](https://github.com/Maschell/WiiUPluginSystem). Check out the readme for more information about the Plugin System.
## Usage
Put the `hook_payload.elf` in the `sd:/wiiu` folder of your sd card and load it via the [SystemMenuHook](https://github.com/wiiu-env/SystemMenuHook).
Put the `PluginBackend.rpx` in the `sd:/wiiu/modules` folder of your sd card and load it via the [SetupPayload](https://github.com/wiiu-env/SetupPayload).
Plugins needs to be placed into the following folder:
@ -35,5 +35,6 @@ DEVKITPPC=/opt/devkitpro/devkitPPC
# Credits
Maschell
orboditilt
- Maschell
- orboditilt
- https://github.com/serge1/ELFIO

View File

@ -15,33 +15,31 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef _DYNAMIC_LINKING_DEFINES_H_
#define _DYNAMIC_LINKING_DEFINES_H_
#pragma once
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <dynamic_libs/coreinit.h>
#include <wups.h>
#define DYN_LINK_FUNCTION_NAME_LENGTH 255
#define DYN_LINK_IMPORT_NAME_LENGTH 150
#define DYN_LINK_FUNCTION_NAME_LENGTH 351
#define DYN_LINK_IMPORT_NAME_LENGTH 50
#define DYN_LINK_FUNCTION_LIST_LENGTH 500
#define DYN_LINK_IMPORT_LIST_LENGTH 50
#define DYN_LINK_RELOCATION_LIST_LENGTH 5000
#define DYN_LINK_TRAMPOLIN_LIST_LENGTH DYN_LINK_FUNCTION_LIST_LENGTH
typedef struct _dyn_linking_function_t {
char functionName[DYN_LINK_FUNCTION_NAME_LENGTH+1];
void * address;
uint32_t big_jump[6];
} dyn_linking_function_t;
typedef struct _dyn_linking_import_t {
char importName[DYN_LINK_IMPORT_NAME_LENGTH+1];
bool isData = false;
uint32_t handle = 0;
} dyn_linking_import_t;
typedef struct _dyn_linking_relocation_entry_t {
@ -54,7 +52,6 @@ typedef struct _dyn_linking_relocation_entry_t {
} dyn_linking_relocation_entry_t;
typedef struct _dyn_linking_relocation_data_t {
dyn_linking_relocation_entry_t entries[DYN_LINK_RELOCATION_LIST_LENGTH];
dyn_linking_function_t functions[DYN_LINK_FUNCTION_LIST_LENGTH];
dyn_linking_import_t imports[DYN_LINK_IMPORT_LIST_LENGTH];
} dyn_linking_relocation_data_t;
@ -62,5 +59,3 @@ typedef struct _dyn_linking_relocation_data_t {
#ifdef __cplusplus
}
#endif
#endif /* _DYNAMIC_LINKING_DEFINES_H_ */

View File

@ -0,0 +1,58 @@
/****************************************************************************
* Copyright (C) 2018-2019 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#pragma once
#include <stdint.h>
#include <stddef.h>
#include "dynamic_linking_defines.h"
#include "relocation_defines.h"
#ifdef __cplusplus
extern "C" {
#endif
#define MAXIMUM_MODULE_PATH_NAME_LENGTH 256
#define MAXIMUM_MODULE_NAME_LENGTH 51
#define DYN_LINK_RELOCATION_LIST_LENGTH 500
struct module_information_single_t {
char path[MAXIMUM_MODULE_PATH_NAME_LENGTH] = ""; // Path where the module is stored
dyn_linking_relocation_entry_t linking_entries[DYN_LINK_RELOCATION_LIST_LENGTH];
int32_t priority; // Priority of this module
uint32_t bssAddr;
uint32_t bssSize;
uint32_t sbssAddr;
uint32_t sbssSize;
uint32_t entrypoint;
uint32_t startAddress;
uint32_t endAddress;
};
#define MAXIMUM_MODULES 8
struct module_information_t {
int32_t number_used_modules = 0; // Number of used function. Maximum is MAXIMUM_MODULES
dyn_linking_relocation_data_t linking_data;
relocation_trampolin_entry_t trampolines[DYN_LINK_TRAMPOLIN_LIST_LENGTH];
module_information_single_t module_data[MAXIMUM_MODULES];
};
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,95 @@
/****************************************************************************
* Copyright (C) 2018-2019 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#pragma once
#include <stdint.h>
#include <stddef.h>
#include "dynamic_linking_defines.h"
#include "relocation_defines.h"
#include "replacement_defines.h"
#ifdef __cplusplus
extern "C" {
#endif
#define MAXIMUM_PLUGIN_SECTION_LENGTH 10
#define MAXIMUM_PLUGIN_SECTION_NAME_LENGTH 20
#define MAXIMUM_PLUGIN_PATH_NAME_LENGTH 256
#define MAXIMUM_PLUGIN_NAME_LENGTH 51
#define MAXIMUM_PLUGIN_DESCRIPTION_LENGTH 255
#define MAXIMUM_PLUGIN_META_FIELD_LENGTH 51
#define DYN_LINK_RELOCATION_LIST_LENGTH 500
#define MAXIMUM_HOOKS_PER_PLUGIN 25
#define MAXIMUM_FUNCTION_PER_PLUGIN 100
struct plugin_section_info_t {
char name[MAXIMUM_PLUGIN_SECTION_NAME_LENGTH] = "";
uint32_t addr;
uint32_t size;
};
struct plugin_meta_info_t {
char name[MAXIMUM_PLUGIN_META_FIELD_LENGTH] = "";
char author[MAXIMUM_PLUGIN_META_FIELD_LENGTH] = "";
char version[MAXIMUM_PLUGIN_META_FIELD_LENGTH] = "";
char license[MAXIMUM_PLUGIN_META_FIELD_LENGTH] = "";
char buildTimestamp[MAXIMUM_PLUGIN_META_FIELD_LENGTH] = "";
char descripion[MAXIMUM_PLUGIN_DESCRIPTION_LENGTH] = "";
uint32_t size;
};
struct plugin_info_t {
dyn_linking_relocation_entry_t linking_entries[DYN_LINK_RELOCATION_LIST_LENGTH];
plugin_section_info_t sectionInfos[MAXIMUM_PLUGIN_SECTION_LENGTH];
uint32_t number_used_functions; // Number of used function. Maximum is MAXIMUM_FUNCTION_PER_PLUGIN
replacement_data_function_t functions[MAXIMUM_FUNCTION_PER_PLUGIN]; // Replacement information for each function.
uint32_t number_used_hooks; // Number of used hooks. Maximum is MAXIMUM_HOOKS_PER_PLUGIN
replacement_data_hook_t hooks[MAXIMUM_HOOKS_PER_PLUGIN]; // Replacement information for each function.
uint8_t trampolinId;
};
struct plugin_data_t {
char * buffer = NULL;
size_t bufferLength = 0;
int memoryType = 0;
int heapHandle = 0;
};
struct plugin_information_single_t {
plugin_meta_info_t meta;
plugin_info_t info;
plugin_data_t data;
int32_t priority; // Priority of this plugin
};
#define MAXIMUM_PLUGINS 32
struct plugin_information_t {
int32_t number_used_plugins = 0; // Number of used plugins. Maximum is MAXIMUM_PLUGINS
plugin_information_single_t plugin_data[MAXIMUM_PLUGINS];
relocation_trampolin_entry_t trampolines[DYN_LINK_TRAMPOLIN_LIST_LENGTH];
dyn_linking_relocation_data_t linking_data; // RPL and function name list
};
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,20 @@
#pragma once
#include <stdint.h>
typedef enum RelocationTrampolinStatus{
RELOC_TRAMP_FREE = 0,
RELOC_TRAMP_FIXED = 1,
RELOC_TRAMP_IMPORT_IN_PROGRESS = 2,
RELOC_TRAMP_IMPORT_DONE = 3,
} RelocationTrampolinStatus;
typedef enum RelocationType{
RELOC_TYPE_FIXED = 0,
RELOC_TYPE_IMPORT = 1
} RelocationType;
typedef struct relocation_trampolin_entry_t {
uint32_t id;
uint32_t trampolin[4];
RelocationTrampolinStatus status = RELOC_TRAMP_FREE;
} relocation_trampolin_entry_t;

View File

@ -0,0 +1,25 @@
#pragma once
#include <stdint.h>
#include <wups.h>
#define FUNCTION_PATCHER_METHOD_STORE_SIZE 13
#define MAXIMUM_FUNCTION_NAME_LENGTH 83
struct replacement_data_function_t {
uint32_t physicalAddr; /* [needs to be filled] */
uint32_t virtualAddr; /* [needs to be filled] */
uint32_t replaceAddr; /* [needs to be filled] Address of our replacement function */
uint32_t replaceCall; /* [needs to be filled] Address to access the real_function */
wups_loader_library_type_t library; /* [needs to be filled] rpl where the function we want to replace is. */
char function_name[MAXIMUM_FUNCTION_NAME_LENGTH]; /* [needs to be filled] name of the function we want to replace */
uint32_t realAddr; /* [will be filled] Address of the real function we want to replace. */
volatile uint32_t replace_data [FUNCTION_PATCHER_METHOD_STORE_SIZE]; /* [will be filled] Space for us to store some jump instructions */
uint32_t restoreInstruction; /* [will be filled] Copy of the instruction we replaced to jump to our code. */
uint8_t functionType; /* [will be filled] */
uint8_t alreadyPatched; /* [will be filled] */
};
struct replacement_data_hook_t {
void * func_pointer = NULL; /* [will be filled] */
wups_loader_hook_type_t type; /* [will be filled] */
};

29
source/crt0.s Normal file
View File

@ -0,0 +1,29 @@
.extern main
.extern exit
.extern __init_wut
.extern __fini_wut
.global _start
_start:
stwu 1, -0x28(1)
mflr 0
stw 0, 0x2C(1)
stw 31, 0x24(1)
or 31, 1, 1
stw 3, 0x18(31)
stw 4, 0x1C(31)
bl __init_wut
lwz 4, 0x1C(31)
lwz 3, 0x18(31)
bl main
or 9, 3, 3
stw 9, 0x8(31)
bl __fini_wut
lwz 9, 0x8(31)
or 3, 9, 9
addi 11, 31, 0x28
lwz 0, 0x4(11)
mtlr 0
lwz 31, -0x4(11)
or 1, 11, 11
blr

851
source/elfio/elf_types.hpp Normal file
View File

@ -0,0 +1,851 @@
/*
Copyright (C) 2001-2015 by Serge Lamikhov-Center
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef ELFTYPES_H
#define ELFTYPES_H
#ifndef ELFIO_NO_OWN_TYPES
#if !defined(ELFIO_NO_CSTDINT) && !defined(ELFIO_NO_INTTYPES)
#include <stdint.h>
#else
typedef unsigned char uint8_t;
typedef signed char int8_t;
typedef unsigned short uint16_t;
typedef signed short int16_t;
#ifdef _MSC_VER
typedef unsigned __int32 uint32_t;
typedef signed __int32 int32_t;
typedef unsigned __int64 uint64_t;
typedef signed __int64 int64_t;
#else
typedef unsigned int uint32_t;
typedef signed int int32_t;
typedef unsigned long long uint64_t;
typedef signed long long int64_t;
#endif // _MSC_VER
#endif // ELFIO_NO_CSTDINT
#endif // ELFIO_NO_OWN_TYPES
namespace ELFIO {
// Attention! Platform depended definitions.
typedef uint16_t Elf_Half;
typedef uint32_t Elf_Word;
typedef int32_t Elf_Sword;
typedef uint64_t Elf_Xword;
typedef int64_t Elf_Sxword;
typedef uint32_t Elf32_Addr;
typedef uint32_t Elf32_Off;
typedef uint64_t Elf64_Addr;
typedef uint64_t Elf64_Off;
#define Elf32_Half Elf_Half
#define Elf64_Half Elf_Half
#define Elf32_Word Elf_Word
#define Elf64_Word Elf_Word
#define Elf32_Sword Elf_Sword
#define Elf64_Sword Elf_Sword
///////////////////////
// ELF Header Constants
// File type
#define ET_NONE 0
#define ET_REL 1
#define ET_EXEC 2
#define ET_DYN 3
#define ET_CORE 4
#define ET_LOOS 0xFE00
#define ET_HIOS 0xFEFF
#define ET_LOPROC 0xFF00
#define ET_HIPROC 0xFFFF
#define EM_NONE 0 // No machine
#define EM_M32 1 // AT&T WE 32100
#define EM_SPARC 2 // SUN SPARC
#define EM_386 3 // Intel 80386
#define EM_68K 4 // Motorola m68k family
#define EM_88K 5 // Motorola m88k family
#define EM_486 6 // Intel 80486// Reserved for future use
#define EM_860 7 // Intel 80860
#define EM_MIPS 8 // MIPS R3000 (officially, big-endian only)
#define EM_S370 9 // IBM System/370
#define EM_MIPS_RS3_LE 10 // MIPS R3000 little-endian (Oct 4 1999 Draft) Deprecated
#define EM_res011 11 // Reserved
#define EM_res012 12 // Reserved
#define EM_res013 13 // Reserved
#define EM_res014 14 // Reserved
#define EM_PARISC 15 // HPPA
#define EM_res016 16 // Reserved
#define EM_VPP550 17 // Fujitsu VPP500
#define EM_SPARC32PLUS 18 // Sun's "v8plus"
#define EM_960 19 // Intel 80960
#define EM_PPC 20 // PowerPC
#define EM_PPC64 21 // 64-bit PowerPC
#define EM_S390 22 // IBM S/390
#define EM_SPU 23 // Sony/Toshiba/IBM SPU
#define EM_res024 24 // Reserved
#define EM_res025 25 // Reserved
#define EM_res026 26 // Reserved
#define EM_res027 27 // Reserved
#define EM_res028 28 // Reserved
#define EM_res029 29 // Reserved
#define EM_res030 30 // Reserved
#define EM_res031 31 // Reserved
#define EM_res032 32 // Reserved
#define EM_res033 33 // Reserved
#define EM_res034 34 // Reserved
#define EM_res035 35 // Reserved
#define EM_V800 36 // NEC V800 series
#define EM_FR20 37 // Fujitsu FR20
#define EM_RH32 38 // TRW RH32
#define EM_MCORE 39 // Motorola M*Core // May also be taken by Fujitsu MMA
#define EM_RCE 39 // Old name for MCore
#define EM_ARM 40 // ARM
#define EM_OLD_ALPHA 41 // Digital Alpha
#define EM_SH 42 // Renesas (formerly Hitachi) / SuperH SH
#define EM_SPARCV9 43 // SPARC v9 64-bit
#define EM_TRICORE 44 // Siemens Tricore embedded processor
#define EM_ARC 45 // ARC Cores
#define EM_H8_300 46 // Renesas (formerly Hitachi) H8/300
#define EM_H8_300H 47 // Renesas (formerly Hitachi) H8/300H
#define EM_H8S 48 // Renesas (formerly Hitachi) H8S
#define EM_H8_500 49 // Renesas (formerly Hitachi) H8/500
#define EM_IA_64 50 // Intel IA-64 Processor
#define EM_MIPS_X 51 // Stanford MIPS-X
#define EM_COLDFIRE 52 // Motorola Coldfire
#define EM_68HC12 53 // Motorola M68HC12
#define EM_MMA 54 // Fujitsu Multimedia Accelerator
#define EM_PCP 55 // Siemens PCP
#define EM_NCPU 56 // Sony nCPU embedded RISC processor
#define EM_NDR1 57 // Denso NDR1 microprocesspr
#define EM_STARCORE 58 // Motorola Star*Core processor
#define EM_ME16 59 // Toyota ME16 processor
#define EM_ST100 60 // STMicroelectronics ST100 processor
#define EM_TINYJ 61 // Advanced Logic Corp. TinyJ embedded processor
#define EM_X86_64 62 // Advanced Micro Devices X86-64 processor
#define EM_PDSP 63 // Sony DSP Processor
#define EM_PDP10 64 // Digital Equipment Corp. PDP-10
#define EM_PDP11 65 // Digital Equipment Corp. PDP-11
#define EM_FX66 66 // Siemens FX66 microcontroller
#define EM_ST9PLUS 67 // STMicroelectronics ST9+ 8/16 bit microcontroller
#define EM_ST7 68 // STMicroelectronics ST7 8-bit microcontroller
#define EM_68HC16 69 // Motorola MC68HC16 Microcontroller
#define EM_68HC11 70 // Motorola MC68HC11 Microcontroller
#define EM_68HC08 71 // Motorola MC68HC08 Microcontroller
#define EM_68HC05 72 // Motorola MC68HC05 Microcontroller
#define EM_SVX 73 // Silicon Graphics SVx
#define EM_ST19 74 // STMicroelectronics ST19 8-bit cpu
#define EM_VAX 75 // Digital VAX
#define EM_CRIS 76 // Axis Communications 32-bit embedded processor
#define EM_JAVELIN 77 // Infineon Technologies 32-bit embedded cpu
#define EM_FIREPATH 78 // Element 14 64-bit DSP processor
#define EM_ZSP 79 // LSI Logic's 16-bit DSP processor
#define EM_MMIX 80 // Donald Knuth's educational 64-bit processor
#define EM_HUANY 81 // Harvard's machine-independent format
#define EM_PRISM 82 // SiTera Prism
#define EM_AVR 83 // Atmel AVR 8-bit microcontroller
#define EM_FR30 84 // Fujitsu FR30
#define EM_D10V 85 // Mitsubishi D10V
#define EM_D30V 86 // Mitsubishi D30V
#define EM_V850 87 // NEC v850
#define EM_M32R 88 // Renesas M32R (formerly Mitsubishi M32R)
#define EM_MN10300 89 // Matsushita MN10300
#define EM_MN10200 90 // Matsushita MN10200
#define EM_PJ 91 // picoJava
#define EM_OPENRISC 92 // OpenRISC 32-bit embedded processor
#define EM_ARC_A5 93 // ARC Cores Tangent-A5
#define EM_XTENSA 94 // Tensilica Xtensa Architecture
#define EM_VIDEOCORE 95 // Alphamosaic VideoCore processor
#define EM_TMM_GPP 96 // Thompson Multimedia General Purpose Processor
#define EM_NS32K 97 // National Semiconductor 32000 series
#define EM_TPC 98 // Tenor Network TPC processor
#define EM_SNP1K 99 // Trebia SNP 1000 processor
#define EM_ST200 100 // STMicroelectronics ST200 microcontroller
#define EM_IP2K 101 // Ubicom IP2022 micro controller
#define EM_MAX 102 // MAX Processor
#define EM_CR 103 // National Semiconductor CompactRISC
#define EM_F2MC16 104 // Fujitsu F2MC16
#define EM_MSP430 105 // TI msp430 micro controller
#define EM_BLACKFIN 106 // ADI Blackfin
#define EM_SE_C33 107 // S1C33 Family of Seiko Epson processors
#define EM_SEP 108 // Sharp embedded microprocessor
#define EM_ARCA 109 // Arca RISC Microprocessor
#define EM_UNICORE 110 // Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University
#define EM_EXCESS 111 // eXcess: 16/32/64-bit configurable embedded CPU
#define EM_DXP 112 // Icera Semiconductor Inc. Deep Execution Processor
#define EM_ALTERA_NIOS2 113 // Altera Nios II soft-core processor
#define EM_CRX 114 // National Semiconductor CRX
#define EM_XGATE 115 // Motorola XGATE embedded processor
#define EM_C166 116 // Infineon C16x/XC16x processor
#define EM_M16C 117 // Renesas M16C series microprocessors
#define EM_DSPIC30F 118 // Microchip Technology dsPIC30F Digital Signal Controller
#define EM_CE 119 // Freescale Communication Engine RISC core
#define EM_M32C 120 // Renesas M32C series microprocessors
#define EM_res121 121 // Reserved
#define EM_res122 122 // Reserved
#define EM_res123 123 // Reserved
#define EM_res124 124 // Reserved
#define EM_res125 125 // Reserved
#define EM_res126 126 // Reserved
#define EM_res127 127 // Reserved
#define EM_res128 128 // Reserved
#define EM_res129 129 // Reserved
#define EM_res130 130 // Reserved
#define EM_TSK3000 131 // Altium TSK3000 core
#define EM_RS08 132 // Freescale RS08 embedded processor
#define EM_res133 133 // Reserved
#define EM_ECOG2 134 // Cyan Technology eCOG2 microprocessor
#define EM_SCORE 135 // Sunplus Score
#define EM_SCORE7 135 // Sunplus S+core7 RISC processor
#define EM_DSP24 136 // New Japan Radio (NJR) 24-bit DSP Processor
#define EM_VIDEOCORE3 137 // Broadcom VideoCore III processor
#define EM_LATTICEMICO32 138 // RISC processor for Lattice FPGA architecture
#define EM_SE_C17 139 // Seiko Epson C17 family
#define EM_TI_C6000 140 // Texas Instruments TMS320C6000 DSP family
#define EM_TI_C2000 141 // Texas Instruments TMS320C2000 DSP family
#define EM_TI_C5500 142 // Texas Instruments TMS320C55x DSP family
#define EM_res143 143 // Reserved
#define EM_res144 144 // Reserved
#define EM_res145 145 // Reserved
#define EM_res146 146 // Reserved
#define EM_res147 147 // Reserved
#define EM_res148 148 // Reserved
#define EM_res149 149 // Reserved
#define EM_res150 150 // Reserved
#define EM_res151 151 // Reserved
#define EM_res152 152 // Reserved
#define EM_res153 153 // Reserved
#define EM_res154 154 // Reserved
#define EM_res155 155 // Reserved
#define EM_res156 156 // Reserved
#define EM_res157 157 // Reserved
#define EM_res158 158 // Reserved
#define EM_res159 159 // Reserved
#define EM_MMDSP_PLUS 160 // STMicroelectronics 64bit VLIW Data Signal Processor
#define EM_CYPRESS_M8C 161 // Cypress M8C microprocessor
#define EM_R32C 162 // Renesas R32C series microprocessors
#define EM_TRIMEDIA 163 // NXP Semiconductors TriMedia architecture family
#define EM_QDSP6 164 // QUALCOMM DSP6 Processor
#define EM_8051 165 // Intel 8051 and variants
#define EM_STXP7X 166 // STMicroelectronics STxP7x family
#define EM_NDS32 167 // Andes Technology compact code size embedded RISC processor family
#define EM_ECOG1 168 // Cyan Technology eCOG1X family
#define EM_ECOG1X 168 // Cyan Technology eCOG1X family
#define EM_MAXQ30 169 // Dallas Semiconductor MAXQ30 Core Micro-controllers
#define EM_XIMO16 170 // New Japan Radio (NJR) 16-bit DSP Processor
#define EM_MANIK 171 // M2000 Reconfigurable RISC Microprocessor
#define EM_CRAYNV2 172 // Cray Inc. NV2 vector architecture
#define EM_RX 173 // Renesas RX family
#define EM_METAG 174 // Imagination Technologies META processor architecture
#define EM_MCST_ELBRUS 175 // MCST Elbrus general purpose hardware architecture
#define EM_ECOG16 176 // Cyan Technology eCOG16 family
#define EM_CR16 177 // National Semiconductor CompactRISC 16-bit processor
#define EM_ETPU 178 // Freescale Extended Time Processing Unit
#define EM_SLE9X 179 // Infineon Technologies SLE9X core
#define EM_L1OM 180 // Intel L1OM
#define EM_INTEL181 181 // Reserved by Intel
#define EM_INTEL182 182 // Reserved by Intel
#define EM_res183 183 // Reserved by ARM
#define EM_res184 184 // Reserved by ARM
#define EM_AVR32 185 // Atmel Corporation 32-bit microprocessor family
#define EM_STM8 186 // STMicroeletronics STM8 8-bit microcontroller
#define EM_TILE64 187 // Tilera TILE64 multicore architecture family
#define EM_TILEPRO 188 // Tilera TILEPro multicore architecture family
#define EM_MICROBLAZE 189 // Xilinx MicroBlaze 32-bit RISC soft processor core
#define EM_CUDA 190 // NVIDIA CUDA architecture
#define EM_TILEGX 191 // Tilera TILE-Gx multicore architecture family
#define EM_CLOUDSHIELD 192 // CloudShield architecture family
#define EM_COREA_1ST 193 // KIPO-KAIST Core-A 1st generation processor family
#define EM_COREA_2ND 194 // KIPO-KAIST Core-A 2nd generation processor family
#define EM_ARC_COMPACT2 195 // Synopsys ARCompact V2
#define EM_OPEN8 196 // Open8 8-bit RISC soft processor core
#define EM_RL78 197 // Renesas RL78 family
#define EM_VIDEOCORE5 198 // Broadcom VideoCore V processor
#define EM_78KOR 199 // Renesas 78KOR family
#define EM_56800EX 200 // Freescale 56800EX Digital Signal Controller (DSC)
#define EM_BA1 201 // Beyond BA1 CPU architecture
#define EM_BA2 202 // Beyond BA2 CPU architecture
#define EM_XCORE 203 // XMOS xCORE processor family
#define EM_MCHP_PIC 204 // Microchip 8-bit PIC(r) family
#define EM_INTEL205 205 // Reserved by Intel
#define EM_INTEL206 206 // Reserved by Intel
#define EM_INTEL207 207 // Reserved by Intel
#define EM_INTEL208 208 // Reserved by Intel
#define EM_INTEL209 209 // Reserved by Intel
#define EM_KM32 210 // KM211 KM32 32-bit processor
#define EM_KMX32 211 // KM211 KMX32 32-bit processor
#define EM_KMX16 212 // KM211 KMX16 16-bit processor
#define EM_KMX8 213 // KM211 KMX8 8-bit processor
#define EM_KVARC 214 // KM211 KVARC processor
#define EM_CDP 215 // Paneve CDP architecture family
#define EM_COGE 216 // Cognitive Smart Memory Processor
#define EM_COOL 217 // iCelero CoolEngine
#define EM_NORC 218 // Nanoradio Optimized RISC
#define EM_CSR_KALIMBA 219 // CSR Kalimba architecture family
#define EM_Z80 220 // Zilog Z80
#define EM_VISIUM 221 // Controls and Data Services VISIUMcore processor
#define EM_FT32 222 // FTDI Chip FT32 high performance 32-bit RISC architecture
#define EM_MOXIE 223 // Moxie processor family
#define EM_AMDGPU 224 // AMD GPU architecture
#define EM_RISCV 243 // RISC-V
#define EM_LANAI 244 // Lanai processor
#define EM_CEVA 245 // CEVA Processor Architecture Family
#define EM_CEVA_X2 246 // CEVA X2 Processor Family
#define EM_BPF 247 // Linux BPF in-kernel virtual machine
// File version
#define EV_NONE 0
#define EV_CURRENT 1
// Identification index
#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 EI_OSABI 7
#define EI_ABIVERSION 8
#define EI_PAD 9
#define EI_NIDENT 16
// Magic number
#define ELFMAG0 0x7F
#define ELFMAG1 'E'
#define ELFMAG2 'L'
#define ELFMAG3 'F'
// File class
#define ELFCLASSNONE 0
#define ELFCLASS32 1
#define ELFCLASS64 2
// Encoding
#define ELFDATANONE 0
#define ELFDATA2LSB 1
#define ELFDATA2MSB 2
// OS extensions
#define ELFOSABI_NONE 0 // No extensions or unspecified
#define ELFOSABI_HPUX 1 // Hewlett-Packard HP-UX
#define ELFOSABI_NETBSD 2 // NetBSD
#define ELFOSABI_LINUX 3 // Linux
#define ELFOSABI_SOLARIS 6 // Sun Solaris
#define ELFOSABI_AIX 7 // AIX
#define ELFOSABI_IRIX 8 // IRIX
#define ELFOSABI_FREEBSD 9 // FreeBSD
#define ELFOSABI_TRU64 10 // Compaq TRU64 UNIX
#define ELFOSABI_MODESTO 11 // Novell Modesto
#define ELFOSABI_OPENBSD 12 // Open BSD
#define ELFOSABI_OPENVMS 13 // Open VMS
#define ELFOSABI_NSK 14 // Hewlett-Packard Non-Stop Kernel
#define ELFOSABI_AROS 15 // Amiga Research OS
#define ELFOSABI_FENIXOS 16 // The FenixOS highly scalable multi-core OS
// 64-255 Architecture-specific value range
#define ELFOSABI_AMDGPU_HSA 64 // AMDGPU OS for HSA compatible compute
// kernels.
#define ELFOSABI_AMDGPU_PAL 65 // AMDGPU OS for AMD PAL compatible graphics
// shaders and compute kernels.
#define ELFOSABI_AMDGPU_MESA3D 66 // AMDGPU OS for Mesa3D compatible graphics
// shaders and compute kernels.
// AMDGPU specific e_flags
#define EF_AMDGPU_MACH 0x0ff // AMDGPU processor selection mask.
#define EF_AMDGPU_XNACK 0x100 // Indicates if the XNACK target feature is
// enabled for all code contained in the ELF.
// AMDGPU processors
#define EF_AMDGPU_MACH_NONE 0x000 // Unspecified processor.
#define EF_AMDGPU_MACH_R600_R600 0x001
#define EF_AMDGPU_MACH_R600_R630 0x002
#define EF_AMDGPU_MACH_R600_RS880 0x003
#define EF_AMDGPU_MACH_R600_RV670 0x004
#define EF_AMDGPU_MACH_R600_RV710 0x005
#define EF_AMDGPU_MACH_R600_RV730 0x006
#define EF_AMDGPU_MACH_R600_RV770 0x007
#define EF_AMDGPU_MACH_R600_CEDAR 0x008
#define EF_AMDGPU_MACH_R600_CYPRESS 0x009
#define EF_AMDGPU_MACH_R600_JUNIPER 0x00a
#define EF_AMDGPU_MACH_R600_REDWOOD 0x00b
#define EF_AMDGPU_MACH_R600_SUMO 0x00c
#define EF_AMDGPU_MACH_R600_BARTS 0x00d
#define EF_AMDGPU_MACH_R600_CAICOS 0x00e
#define EF_AMDGPU_MACH_R600_CAYMAN 0x00f
#define EF_AMDGPU_MACH_R600_TURKS 0x010
#define EF_AMDGPU_MACH_R600_RESERVED_FIRST 0x011
#define EF_AMDGPU_MACH_R600_RESERVED_LAST 0x01f
#define EF_AMDGPU_MACH_R600_FIRST EF_AMDGPU_MACH_R600_R600
#define EF_AMDGPU_MACH_R600_LAST EF_AMDGPU_MACH_R600_TURKS
#define EF_AMDGPU_MACH_AMDGCN_GFX600 0x020
#define EF_AMDGPU_MACH_AMDGCN_GFX601 0x021
#define EF_AMDGPU_MACH_AMDGCN_GFX700 0x022
#define EF_AMDGPU_MACH_AMDGCN_GFX701 0x023
#define EF_AMDGPU_MACH_AMDGCN_GFX702 0x024
#define EF_AMDGPU_MACH_AMDGCN_GFX703 0x025
#define EF_AMDGPU_MACH_AMDGCN_GFX704 0x026
#define EF_AMDGPU_MACH_AMDGCN_GFX801 0x028
#define EF_AMDGPU_MACH_AMDGCN_GFX802 0x029
#define EF_AMDGPU_MACH_AMDGCN_GFX803 0x02a
#define EF_AMDGPU_MACH_AMDGCN_GFX810 0x02b
#define EF_AMDGPU_MACH_AMDGCN_GFX900 0x02c
#define EF_AMDGPU_MACH_AMDGCN_GFX902 0x02d
#define EF_AMDGPU_MACH_AMDGCN_GFX904 0x02e
#define EF_AMDGPU_MACH_AMDGCN_GFX906 0x02f
#define EF_AMDGPU_MACH_AMDGCN_RESERVED0 0x027
#define EF_AMDGPU_MACH_AMDGCN_RESERVED1 0x030
#define EF_AMDGPU_MACH_AMDGCN_FIRST EF_AMDGPU_MACH_AMDGCN_GFX600
#define EF_AMDGPU_MACH_AMDGCN_LAST EF_AMDGPU_MACH_AMDGCN_GFX906
/////////////////////
// Sections constants
// Section indexes
#define SHN_UNDEF 0
#define SHN_LORESERVE 0xFF00
#define SHN_LOPROC 0xFF00
#define SHN_HIPROC 0xFF1F
#define SHN_LOOS 0xFF20
#define SHN_HIOS 0xFF3F
#define SHN_ABS 0xFFF1
#define SHN_COMMON 0xFFF2
#define SHN_XINDEX 0xFFFF
#define SHN_HIRESERVE 0xFFFF
// Section types
#define SHT_NULL 0
#define SHT_PROGBITS 1
#define SHT_SYMTAB 2
#define SHT_STRTAB 3
#define SHT_RELA 4
#define SHT_HASH 5
#define SHT_DYNAMIC 6
#define SHT_NOTE 7
#define SHT_NOBITS 8
#define SHT_REL 9
#define SHT_SHLIB 10
#define SHT_DYNSYM 11
#define SHT_INIT_ARRAY 14
#define SHT_FINI_ARRAY 15
#define SHT_PREINIT_ARRAY 16
#define SHT_GROUP 17
#define SHT_SYMTAB_SHNDX 18
#define SHT_LOOS 0x60000000
#define SHT_HIOS 0x6fffffff
#define SHT_LOPROC 0x70000000
#define SHT_HIPROC 0x7FFFFFFF
#define SHT_LOUSER 0x80000000
#define SHT_HIUSER 0xFFFFFFFF
// Section attribute flags
#define SHF_WRITE 0x1
#define SHF_ALLOC 0x2
#define SHF_EXECINSTR 0x4
#define SHF_MERGE 0x10
#define SHF_STRINGS 0x20
#define SHF_INFO_LINK 0x40
#define SHF_LINK_ORDER 0x80
#define SHF_OS_NONCONFORMING 0x100
#define SHF_GROUP 0x200
#define SHF_TLS 0x400
#define SHF_MASKOS 0x0ff00000
#define SHF_MASKPROC 0xF0000000
// Section group flags
#define GRP_COMDAT 0x1
#define GRP_MASKOS 0x0ff00000
#define GRP_MASKPROC 0xf0000000
// Symbol binding
#define STB_LOCAL 0
#define STB_GLOBAL 1
#define STB_WEAK 2
#define STB_LOOS 10
#define STB_HIOS 12
#define STB_MULTIDEF 13
#define STB_LOPROC 13
#define STB_HIPROC 15
// Note types
#define NT_AMDGPU_METADATA 1
#define NT_AMD_AMDGPU_HSA_METADATA 10
#define NT_AMD_AMDGPU_ISA 11
#define NT_AMD_AMDGPU_PAL_METADATA 12
// Symbol types
#define STT_NOTYPE 0
#define STT_OBJECT 1
#define STT_FUNC 2
#define STT_SECTION 3
#define STT_FILE 4
#define STT_COMMON 5
#define STT_TLS 6
#define STT_LOOS 10
#define STT_AMDGPU_HSA_KERNEL 10
#define STT_HIOS 12
#define STT_LOPROC 13
#define STT_HIPROC 15
// Symbol visibility
#define STV_DEFAULT 0
#define STV_INTERNAL 1
#define STV_HIDDEN 2
#define STV_PROTECTED 3
// Undefined name
#define STN_UNDEF 0
// Relocation types
#define R_386_NONE 0
#define R_X86_64_NONE 0
#define R_AMDGPU_NONE 0
#define R_386_32 1
#define R_X86_64_64 1
#define R_AMDGPU_ABS32_LO 1
#define R_386_PC32 2
#define R_X86_64_PC32 2
#define R_AMDGPU_ABS32_HI 2
#define R_386_GOT32 3
#define R_X86_64_GOT32 3
#define R_AMDGPU_ABS64 3
#define R_386_PLT32 4
#define R_X86_64_PLT32 4
#define R_AMDGPU_REL32 4
#define R_386_COPY 5
#define R_X86_64_COPY 5
#define R_AMDGPU_REL64 5
#define R_386_GLOB_DAT 6
#define R_X86_64_GLOB_DAT 6
#define R_AMDGPU_ABS32 6
#define R_386_JMP_SLOT 7
#define R_X86_64_JUMP_SLOT 7
#define R_AMDGPU_GOTPCREL 7
#define R_386_RELATIVE 8
#define R_X86_64_RELATIVE 8
#define R_AMDGPU_GOTPCREL32_LO 8
#define R_386_GOTOFF 9
#define R_X86_64_GOTPCREL 9
#define R_AMDGPU_GOTPCREL32_HI 9
#define R_386_GOTPC 10
#define R_X86_64_32 10
#define R_AMDGPU_REL32_LO 10
#define R_386_32PLT 11
#define R_X86_64_32S 11
#define R_AMDGPU_REL32_HI 11
#define R_X86_64_16 12
#define R_X86_64_PC16 13
#define R_AMDGPU_RELATIVE64 13
#define R_386_TLS_TPOFF 14
#define R_X86_64_8 14
#define R_386_TLS_IE 15
#define R_X86_64_PC8 15
#define R_386_TLS_GOTIE 16
#define R_X86_64_DTPMOD64 16
#define R_386_TLS_LE 17
#define R_X86_64_DTPOFF64 17
#define R_386_TLS_GD 18
#define R_X86_64_TPOFF64 18
#define R_386_TLS_LDM 19
#define R_X86_64_TLSGD 19
#define R_386_16 20
#define R_X86_64_TLSLD 20
#define R_386_PC16 21
#define R_X86_64_DTPOFF32 21
#define R_386_8 22
#define R_X86_64_GOTTPOFF 22
#define R_386_PC8 23
#define R_X86_64_TPOFF32 23
#define R_386_TLS_GD_32 24
#define R_X86_64_PC64 24
#define R_386_TLS_GD_PUSH 25
#define R_X86_64_GOTOFF64 25
#define R_386_TLS_GD_CALL 26
#define R_X86_64_GOTPC32 26
#define R_386_TLS_GD_POP 27
#define R_X86_64_GOT64 27
#define R_386_TLS_LDM_32 28
#define R_X86_64_GOTPCREL64 28
#define R_386_TLS_LDM_PUSH 29
#define R_X86_64_GOTPC64 29
#define R_386_TLS_LDM_CALL 30
#define R_X86_64_GOTPLT64 30
#define R_386_TLS_LDM_POP 31
#define R_X86_64_PLTOFF64 31
#define R_386_TLS_LDO_32 32
#define R_386_TLS_IE_32 33
#define R_386_TLS_LE_32 34
#define R_X86_64_GOTPC32_TLSDESC 34
#define R_386_TLS_DTPMOD32 35
#define R_X86_64_TLSDESC_CALL 35
#define R_386_TLS_DTPOFF32 36
#define R_X86_64_TLSDESC 36
#define R_386_TLS_TPOFF32 37
#define R_X86_64_IRELATIVE 37
#define R_386_SIZE32 38
#define R_386_TLS_GOTDESC 39
#define R_386_TLS_DESC_CALL 40
#define R_386_TLS_DESC 41
#define R_386_IRELATIVE 42
#define R_386_GOT32X 43
#define R_X86_64_GNU_VTINHERIT 250
#define R_X86_64_GNU_VTENTRY 251
// Segment types
#define PT_NULL 0
#define PT_LOAD 1
#define PT_DYNAMIC 2
#define PT_INTERP 3
#define PT_NOTE 4
#define PT_SHLIB 5
#define PT_PHDR 6
#define PT_TLS 7
#define PT_LOOS 0x60000000
#define PT_HIOS 0x6fffffff
#define PT_LOPROC 0x70000000
#define PT_HIPROC 0x7FFFFFFF
// Segment flags
#define PF_X 1 // Execute
#define PF_W 2 // Write
#define PF_R 4 // Read
#define PF_MASKOS 0x0ff00000 // Unspecified
#define PF_MASKPROC 0xf0000000 // Unspecified
// Dynamic Array Tags
#define DT_NULL 0
#define DT_NEEDED 1
#define DT_PLTRELSZ 2
#define DT_PLTGOT 3
#define DT_HASH 4
#define DT_STRTAB 5
#define DT_SYMTAB 6
#define DT_RELA 7
#define DT_RELASZ 8
#define DT_RELAENT 9
#define DT_STRSZ 10
#define DT_SYMENT 11
#define DT_INIT 12
#define DT_FINI 13
#define DT_SONAME 14
#define DT_RPATH 15
#define DT_SYMBOLIC 16
#define DT_REL 17
#define DT_RELSZ 18
#define DT_RELENT 19
#define DT_PLTREL 20
#define DT_DEBUG 21
#define DT_TEXTREL 22
#define DT_JMPREL 23
#define DT_BIND_NOW 24
#define DT_INIT_ARRAY 25
#define DT_FINI_ARRAY 26
#define DT_INIT_ARRAYSZ 27
#define DT_FINI_ARRAYSZ 28
#define DT_RUNPATH 29
#define DT_FLAGS 30
#define DT_ENCODING 32
#define DT_PREINIT_ARRAY 32
#define DT_PREINIT_ARRAYSZ 33
#define DT_MAXPOSTAGS 34
#define DT_LOOS 0x6000000D
#define DT_HIOS 0x6ffff000
#define DT_LOPROC 0x70000000
#define DT_HIPROC 0x7FFFFFFF
// DT_FLAGS values
#define DF_ORIGIN 0x1
#define DF_SYMBOLIC 0x2
#define DF_TEXTREL 0x4
#define DF_BIND_NOW 0x8
#define DF_STATIC_TLS 0x10
// ELF file header
struct Elf32_Ehdr {
unsigned char e_ident[EI_NIDENT];
Elf_Half e_type;
Elf_Half e_machine;
Elf_Word e_version;
Elf32_Addr e_entry;
Elf32_Off e_phoff;
Elf32_Off e_shoff;
Elf_Word e_flags;
Elf_Half e_ehsize;
Elf_Half e_phentsize;
Elf_Half e_phnum;
Elf_Half e_shentsize;
Elf_Half e_shnum;
Elf_Half e_shstrndx;
};
struct Elf64_Ehdr {
unsigned char e_ident[EI_NIDENT];
Elf_Half e_type;
Elf_Half e_machine;
Elf_Word e_version;
Elf64_Addr e_entry;
Elf64_Off e_phoff;
Elf64_Off e_shoff;
Elf_Word e_flags;
Elf_Half e_ehsize;
Elf_Half e_phentsize;
Elf_Half e_phnum;
Elf_Half e_shentsize;
Elf_Half e_shnum;
Elf_Half e_shstrndx;
};
// Section header
struct Elf32_Shdr {
Elf_Word sh_name;
Elf_Word sh_type;
Elf_Word sh_flags;
Elf32_Addr sh_addr;
Elf32_Off sh_offset;
Elf_Word sh_size;
Elf_Word sh_link;
Elf_Word sh_info;
Elf_Word sh_addralign;
Elf_Word sh_entsize;
};
struct Elf64_Shdr {
Elf_Word sh_name;
Elf_Word sh_type;
Elf_Xword sh_flags;
Elf64_Addr sh_addr;
Elf64_Off sh_offset;
Elf_Xword sh_size;
Elf_Word sh_link;
Elf_Word sh_info;
Elf_Xword sh_addralign;
Elf_Xword sh_entsize;
};
// Segment header
struct Elf32_Phdr {
Elf_Word p_type;
Elf32_Off p_offset;
Elf32_Addr p_vaddr;
Elf32_Addr p_paddr;
Elf_Word p_filesz;
Elf_Word p_memsz;
Elf_Word p_flags;
Elf_Word p_align;
};
struct Elf64_Phdr {
Elf_Word p_type;
Elf_Word p_flags;
Elf64_Off p_offset;
Elf64_Addr p_vaddr;
Elf64_Addr p_paddr;
Elf_Xword p_filesz;
Elf_Xword p_memsz;
Elf_Xword p_align;
};
// Symbol table entry
struct Elf32_Sym {
Elf_Word st_name;
Elf32_Addr st_value;
Elf_Word st_size;
unsigned char st_info;
unsigned char st_other;
Elf_Half st_shndx;
};
struct Elf64_Sym {
Elf_Word st_name;
unsigned char st_info;
unsigned char st_other;
Elf_Half st_shndx;
Elf64_Addr st_value;
Elf_Xword st_size;
};
#define ELF_ST_BIND(i) ((i)>>4)
#define ELF_ST_TYPE(i) ((i)&0xf)
#define ELF_ST_INFO(b,t) (((b)<<4)+((t)&0xf))
#define ELF_ST_VISIBILITY(o) ((o)&0x3)
// Relocation entries
struct Elf32_Rel {
Elf32_Addr r_offset;
Elf_Word r_info;
};
struct Elf32_Rela {
Elf32_Addr r_offset;
Elf_Word r_info;
Elf_Sword r_addend;
};
struct Elf64_Rel {
Elf64_Addr r_offset;
Elf_Xword r_info;
};
struct Elf64_Rela {
Elf64_Addr r_offset;
Elf_Xword r_info;
Elf_Sxword r_addend;
};
#define ELF32_R_SYM(i) ((i)>>8)
#define ELF32_R_TYPE(i) ((unsigned char)(i))
#define ELF32_R_INFO(s,t) (((s)<<8 )+(unsigned char)(t))
#define ELF64_R_SYM(i) ((i)>>32)
#define ELF64_R_TYPE(i) ((i)&0xffffffffL)
#define ELF64_R_INFO(s,t) ((((int64_t)(s))<<32)+((t)&0xffffffffL))
// Dynamic structure
struct Elf32_Dyn {
Elf_Sword d_tag;
union {
Elf_Word d_val;
Elf32_Addr d_ptr;
} d_un;
};
struct Elf64_Dyn {
Elf_Sxword d_tag;
union {
Elf_Xword d_val;
Elf64_Addr d_ptr;
} d_un;
};
} // namespace ELFIO
#endif // ELFTYPES_H

932
source/elfio/elfio.hpp Normal file
View File

@ -0,0 +1,932 @@
/*
Copyright (C) 2001-2015 by Serge Lamikhov-Center
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef ELFIO_HPP
#define ELFIO_HPP
#ifdef _MSC_VER
#pragma warning ( push )
#pragma warning(disable:4996)
#pragma warning(disable:4355)
#pragma warning(disable:4244)
#endif
#include <string>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
#include <deque>
#include <iterator>
#include <typeinfo>
#include <elfio/elf_types.hpp>
#include <elfio/elfio_utils.hpp>
#include <elfio/elfio_header.hpp>
#include <elfio/elfio_section.hpp>
#include <elfio/elfio_segment.hpp>
#include <elfio/elfio_strings.hpp>
#define ELFIO_HEADER_ACCESS_GET( TYPE, FNAME ) \
TYPE \
get_##FNAME() const \
{ \
return header? header->get_##FNAME() : 0; \
}
#define ELFIO_HEADER_ACCESS_GET_SET( TYPE, FNAME ) \
TYPE \
get_##FNAME() const \
{ \
return header? header->get_##FNAME() : 0; \
} \
void \
set_##FNAME( TYPE val ) \
{ \
if (header) { \
header->set_##FNAME( val ); \
} \
} \
struct membuf : std::streambuf {
membuf(char* begin, char* end) {
this->setg(begin, begin, end);
}
pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which = std::ios_base::in) override {
if (dir == std::ios_base::cur)
gbump(off);
else if (dir == std::ios_base::end)
setg(eback(), egptr() + off, egptr());
else if (dir == std::ios_base::beg)
setg(eback(), eback() + off, egptr());
return gptr() - eback();
}
pos_type seekpos(pos_type sp, std::ios_base::openmode which) override {
return seekoff(sp - pos_type(off_type(0)), std::ios_base::beg, which);
}
};
namespace ELFIO {
//------------------------------------------------------------------------------
class elfio {
public:
//------------------------------------------------------------------------------
elfio() : sections( this ), segments( this ) {
header = 0;
current_file_pos = 0;
create( ELFCLASS32, ELFDATA2LSB );
}
//------------------------------------------------------------------------------
~elfio() {
clean();
}
//------------------------------------------------------------------------------
void create( unsigned char file_class, unsigned char encoding ) {
clean();
convertor.setup( encoding );
header = create_header( file_class, encoding );
create_mandatory_sections();
}
//------------------------------------------------------------------------------
bool load(char * buffer, size_t length) {
membuf sbuf(buffer, buffer + length);
std::istream in(&sbuf);
return load(in);
}
//------------------------------------------------------------------------------
bool load( const std::string& file_name ) {
std::ifstream stream;
stream.open( file_name.c_str(), std::ios::in | std::ios::binary );
if ( !stream ) {
return false;
}
return load(stream);
}
//------------------------------------------------------------------------------
bool load( std::istream &stream ) {
clean();
unsigned char e_ident[EI_NIDENT];
// Read ELF file signature
stream.read( reinterpret_cast<char*>( &e_ident ), sizeof( e_ident ) );
// Is it ELF file?
if ( stream.gcount() != sizeof( e_ident ) ||
e_ident[EI_MAG0] != ELFMAG0 ||
e_ident[EI_MAG1] != ELFMAG1 ||
e_ident[EI_MAG2] != ELFMAG2 ||
e_ident[EI_MAG3] != ELFMAG3 ) {
return false;
}
if ( ( e_ident[EI_CLASS] != ELFCLASS64 ) &&
( e_ident[EI_CLASS] != ELFCLASS32 )) {
return false;
}
convertor.setup( e_ident[EI_DATA] );
header = create_header( e_ident[EI_CLASS], e_ident[EI_DATA] );
if ( 0 == header ) {
return false;
}
if ( !header->load( stream ) ) {
return false;
}
load_sections( stream );
bool is_still_good = load_segments( stream );
return is_still_good;
}
//------------------------------------------------------------------------------
bool save( const std::string& file_name ) {
std::ofstream stream;
stream.open( file_name.c_str(), std::ios::out | std::ios::binary );
if ( !stream ) {
return false;
}
return save(stream);
}
//------------------------------------------------------------------------------
bool save( std::ostream &stream ) {
if ( !stream || !header) {
return false;
}
bool is_still_good = true;
// Define layout specific header fields
// The position of the segment table is fixed after the header.
// The position of the section table is variable and needs to be fixed
// before saving.
header->set_segments_num( segments.size() );
header->set_segments_offset( segments.size() ? header->get_header_size() : 0 );
header->set_sections_num( sections.size() );
header->set_sections_offset( 0 );
// Layout the first section right after the segment table
current_file_pos = header->get_header_size() +
header->get_segment_entry_size() * header->get_segments_num();
calc_segment_alignment();
is_still_good = layout_segments_and_their_sections();
is_still_good = is_still_good && layout_sections_without_segments();
is_still_good = is_still_good && layout_section_table();
is_still_good = is_still_good && save_header( stream );
is_still_good = is_still_good && save_sections( stream );
is_still_good = is_still_good && save_segments( stream );
return is_still_good;
}
//------------------------------------------------------------------------------
// ELF header access functions
ELFIO_HEADER_ACCESS_GET( unsigned char, class );
ELFIO_HEADER_ACCESS_GET( unsigned char, elf_version );
ELFIO_HEADER_ACCESS_GET( unsigned char, encoding );
ELFIO_HEADER_ACCESS_GET( Elf_Word, version );
ELFIO_HEADER_ACCESS_GET( Elf_Half, header_size );
ELFIO_HEADER_ACCESS_GET( Elf_Half, section_entry_size );
ELFIO_HEADER_ACCESS_GET( Elf_Half, segment_entry_size );
ELFIO_HEADER_ACCESS_GET_SET( unsigned char, os_abi );
ELFIO_HEADER_ACCESS_GET_SET( unsigned char, abi_version );
ELFIO_HEADER_ACCESS_GET_SET( Elf_Half, type );
ELFIO_HEADER_ACCESS_GET_SET( Elf_Half, machine );
ELFIO_HEADER_ACCESS_GET_SET( Elf_Word, flags );
ELFIO_HEADER_ACCESS_GET_SET( Elf64_Addr, entry );
ELFIO_HEADER_ACCESS_GET_SET( Elf64_Off, sections_offset );
ELFIO_HEADER_ACCESS_GET_SET( Elf64_Off, segments_offset );
ELFIO_HEADER_ACCESS_GET_SET( Elf_Half, section_name_str_index );
//------------------------------------------------------------------------------
const endianess_convertor& get_convertor() const {
return convertor;
}
//------------------------------------------------------------------------------
Elf_Xword get_default_entry_size( Elf_Word section_type ) const {
switch( section_type ) {
case SHT_RELA:
if ( header->get_class() == ELFCLASS64 ) {
return sizeof( Elf64_Rela );
} else {
return sizeof( Elf32_Rela );
}
case SHT_REL:
if ( header->get_class() == ELFCLASS64 ) {
return sizeof( Elf64_Rel );
} else {
return sizeof( Elf32_Rel );
}
case SHT_SYMTAB:
if ( header->get_class() == ELFCLASS64 ) {
return sizeof( Elf64_Sym );
} else {
return sizeof( Elf32_Sym );
}
case SHT_DYNAMIC:
if ( header->get_class() == ELFCLASS64 ) {
return sizeof( Elf64_Dyn );
} else {
return sizeof( Elf32_Dyn );
}
default:
return 0;
}
}
//------------------------------------------------------------------------------
private:
bool is_offset_in_section( Elf64_Off offset, const section* sec ) const {
return offset >= sec->get_offset() && offset < sec->get_offset()+sec->get_size();
}
//------------------------------------------------------------------------------
public:
//! returns an empty string if no problems are detected,
//! or a string containing an error message if problems are found
std::string validate() const {
// check for overlapping sections in the file
for ( int i = 0; i < sections.size(); ++i) {
for ( int j = i+1; j < sections.size(); ++j ) {
const section* a = sections[i];
const section* b = sections[j];
if ( !(a->get_type() & SHT_NOBITS)
&& !(b->get_type() & SHT_NOBITS)
&& (a->get_size() > 0)
&& (b->get_size() > 0)
&& (a->get_offset() > 0)
&& (b->get_offset() > 0)) {
if ( is_offset_in_section( a->get_offset(), b )
|| is_offset_in_section( a->get_offset()+a->get_size()-1, b )
|| is_offset_in_section( b->get_offset(), a )
|| is_offset_in_section( b->get_offset()+b->get_size()-1, a )) {
return "Sections " + a->get_name() + " and " + b->get_name() + " overlap in file";
}
}
}
}
// more checks to be added here...
return "";
}
//------------------------------------------------------------------------------
private:
//------------------------------------------------------------------------------
void clean() {
delete header;
header = 0;
std::vector<section*>::const_iterator it;
for ( it = sections_.begin(); it != sections_.end(); ++it ) {
delete *it;
}
sections_.clear();
std::vector<segment*>::const_iterator it1;
for ( it1 = segments_.begin(); it1 != segments_.end(); ++it1 ) {
delete *it1;
}
segments_.clear();
}
//------------------------------------------------------------------------------
elf_header* create_header( unsigned char file_class, unsigned char encoding ) {
elf_header* new_header = 0;
if ( file_class == ELFCLASS64 ) {
new_header = new elf_header_impl< Elf64_Ehdr >( &convertor,
encoding );
} else if ( file_class == ELFCLASS32 ) {
new_header = new elf_header_impl< Elf32_Ehdr >( &convertor,
encoding );
} else {
return 0;
}
return new_header;
}
//------------------------------------------------------------------------------
section* create_section() {
section* new_section;
unsigned char file_class = get_class();
if ( file_class == ELFCLASS64 ) {
new_section = new section_impl<Elf64_Shdr>( &convertor );
} else if ( file_class == ELFCLASS32 ) {
new_section = new section_impl<Elf32_Shdr>( &convertor );
} else {
return 0;
}
new_section->set_index( (Elf_Half)sections_.size() );
sections_.push_back( new_section );
return new_section;
}
//------------------------------------------------------------------------------
segment* create_segment() {
segment* new_segment;
unsigned char file_class = header->get_class();
if ( file_class == ELFCLASS64 ) {
new_segment = new segment_impl<Elf64_Phdr>( &convertor );
} else if ( file_class == ELFCLASS32 ) {
new_segment = new segment_impl<Elf32_Phdr>( &convertor );
} else {
return 0;
}
new_segment->set_index( (Elf_Half)segments_.size() );
segments_.push_back( new_segment );
return new_segment;
}
//------------------------------------------------------------------------------
void create_mandatory_sections() {
// Create null section without calling to 'add_section' as no string
// section containing section names exists yet
section* sec0 = create_section();
sec0->set_index( 0 );
sec0->set_name( "" );
sec0->set_name_string_offset( 0 );
set_section_name_str_index( 1 );
section* shstrtab = sections.add( ".shstrtab" );
shstrtab->set_type( SHT_STRTAB );
shstrtab->set_addr_align( 1 );
}
//------------------------------------------------------------------------------
Elf_Half load_sections( std::istream& stream ) {
Elf_Half entry_size = header->get_section_entry_size();
Elf_Half num = header->get_sections_num();
Elf64_Off offset = header->get_sections_offset();
for ( Elf_Half i = 0; i < num; ++i ) {
section* sec = create_section();
sec->load( stream, (std::streamoff)offset + i * entry_size );
sec->set_index( i );
// To mark that the section is not permitted to reassign address
// during layout calculation
sec->set_address( sec->get_address() );
}
Elf_Half shstrndx = get_section_name_str_index();
if ( SHN_UNDEF != shstrndx ) {
string_section_accessor str_reader( sections[shstrndx] );
for ( Elf_Half i = 0; i < num; ++i ) {
Elf_Word section_offset = sections[i]->get_name_string_offset();
const char* p = str_reader.get_string( section_offset );
if ( p != 0 ) {
sections[i]->set_name( p );
}
}
}
return num;
}
//------------------------------------------------------------------------------
//! Checks whether the addresses of the section entirely fall within the given segment.
//! It doesn't matter if the addresses are memory addresses, or file offsets,
//! they just need to be in the same address space
bool is_sect_in_seg ( Elf64_Off sect_begin, Elf_Xword sect_size, Elf64_Off seg_begin, Elf64_Off seg_end ) {
return seg_begin <= sect_begin
&& sect_begin + sect_size <= seg_end
&& sect_begin < seg_end; // this is important criteria when sect_size == 0
// Example: seg_begin=10, seg_end=12 (-> covering the bytes 10 and 11)
// sect_begin=12, sect_size=0 -> shall return false!
}
//------------------------------------------------------------------------------
bool load_segments( std::istream& stream ) {
Elf_Half entry_size = header->get_segment_entry_size();
Elf_Half num = header->get_segments_num();
Elf64_Off offset = header->get_segments_offset();
for ( Elf_Half i = 0; i < num; ++i ) {
segment* seg;
unsigned char file_class = header->get_class();
if ( file_class == ELFCLASS64 ) {
seg = new segment_impl<Elf64_Phdr>( &convertor );
} else if ( file_class == ELFCLASS32 ) {
seg = new segment_impl<Elf32_Phdr>( &convertor );
} else {
return false;
}
seg->load( stream, (std::streamoff)offset + i * entry_size );
seg->set_index( i );
// Add sections to the segments (similar to readelfs algorithm)
Elf64_Off segBaseOffset = seg->get_offset();
Elf64_Off segEndOffset = segBaseOffset + seg->get_file_size();
Elf64_Off segVBaseAddr = seg->get_virtual_address();
Elf64_Off segVEndAddr = segVBaseAddr + seg->get_memory_size();
for( Elf_Half j = 0; j < sections.size(); ++j ) {
const section* psec = sections[j];
// SHF_ALLOC sections are matched based on the virtual address
// otherwise the file offset is matched
if( psec->get_flags() & SHF_ALLOC
? is_sect_in_seg( psec->get_address(), psec->get_size(), segVBaseAddr, segVEndAddr )
: is_sect_in_seg( psec->get_offset(), psec->get_size(), segBaseOffset, segEndOffset )) {
// Alignment of segment shall not be updated, to preserve original value
// It will be re-calculated on saving.
seg->add_section_index( psec->get_index(), 0 );
}
}
// Add section into the segments' container
segments_.push_back( seg );
}
return true;
}
//------------------------------------------------------------------------------
bool save_header( std::ostream& stream ) {
return header->save( stream );
}
//------------------------------------------------------------------------------
bool save_sections( std::ostream& stream ) {
for ( unsigned int i = 0; i < sections_.size(); ++i ) {
section *sec = sections_.at(i);
std::streampos headerPosition =
(std::streamoff)header->get_sections_offset() +
header->get_section_entry_size() * sec->get_index();
sec->save(stream,headerPosition,sec->get_offset());
}
return true;
}
//------------------------------------------------------------------------------
bool save_segments( std::ostream& stream ) {
for ( unsigned int i = 0; i < segments_.size(); ++i ) {
segment *seg = segments_.at(i);
std::streampos headerPosition = header->get_segments_offset() +
header->get_segment_entry_size()*seg->get_index();
seg->save( stream, headerPosition, seg->get_offset() );
}
return true;
}
//------------------------------------------------------------------------------
bool is_section_without_segment( unsigned int section_index ) {
bool found = false;
for ( unsigned int j = 0; !found && ( j < segments.size() ); ++j ) {
for ( unsigned int k = 0;
!found && ( k < segments[j]->get_sections_num() );
++k ) {
found = segments[j]->get_section_index_at( k ) == section_index;
}
}
return !found;
}
//------------------------------------------------------------------------------
bool is_subsequence_of( segment* seg1, segment* seg2 ) {
// Return 'true' if sections of seg1 are a subset of sections in seg2
const std::vector<Elf_Half>& sections1 = seg1->get_sections();
const std::vector<Elf_Half>& sections2 = seg2->get_sections();
bool found = false;
if ( sections1.size() < sections2.size() ) {
found = std::includes( sections2.begin(), sections2.end(),
sections1.begin(), sections1.end() );
}
return found;
}
//------------------------------------------------------------------------------
std::vector<segment*> get_ordered_segments( ) {
std::vector<segment*> res;
std::deque<segment*> worklist;
res.reserve(segments.size());
std::copy( segments_.begin(), segments_.end(),
std::back_inserter( worklist )) ;
// Bring the segments which start at address 0 to the front
size_t nextSlot = 0;
for( size_t i = 0; i < worklist.size(); ++i ) {
if( i != nextSlot && worklist[i]->is_offset_initialized()
&& worklist[i]->get_offset() == 0 ) {
if (worklist[nextSlot]->get_offset() == 0) {
++nextSlot;
}
std::swap(worklist[i],worklist[nextSlot]);
++nextSlot;
}
}
while ( !worklist.empty() ) {
segment *seg = worklist.front();
worklist.pop_front();
size_t i = 0;
for ( ; i < worklist.size(); ++i ) {
if ( is_subsequence_of( seg, worklist[i] ) ) {
break;
}
}
if ( i < worklist.size() )
worklist.push_back(seg);
else
res.push_back(seg);
}
return res;
}
//------------------------------------------------------------------------------
bool layout_sections_without_segments( ) {
for ( unsigned int i = 0; i < sections_.size(); ++i ) {
if ( is_section_without_segment( i ) ) {
section *sec = sections_[i];
Elf_Xword section_align = sec->get_addr_align();
if ( section_align > 1 && current_file_pos % section_align != 0 ) {
current_file_pos += section_align -
current_file_pos % section_align;
}
if ( 0 != sec->get_index() )
sec->set_offset(current_file_pos);
if ( SHT_NOBITS != sec->get_type() &&
SHT_NULL != sec->get_type() ) {
current_file_pos += sec->get_size();
}
}
}
return true;
}
//------------------------------------------------------------------------------
void calc_segment_alignment( ) {
for( std::vector<segment*>::iterator s = segments_.begin(); s != segments_.end(); ++s ) {
segment* seg = *s;
for ( int i = 0; i < seg->get_sections_num(); ++i ) {
section* sect = sections_[ seg->get_section_index_at(i) ];
if ( sect->get_addr_align() > seg->get_align() ) {
seg->set_align( sect->get_addr_align() );
}
}
}
}
//------------------------------------------------------------------------------
bool layout_segments_and_their_sections( ) {
std::vector<segment*> worklist;
std::vector<bool> section_generated(sections.size(),false);
// Get segments in a order in where segments which contain a
// sub sequence of other segments are located at the end
worklist = get_ordered_segments();
for ( unsigned int i = 0; i < worklist.size(); ++i ) {
Elf_Xword segment_memory = 0;
Elf_Xword segment_filesize = 0;
Elf_Xword seg_start_pos = current_file_pos;
segment* seg = worklist[i];
// Special case: PHDR segment
// This segment contains the program headers but no sections
if ( seg->get_type() == PT_PHDR && seg->get_sections_num() == 0 ) {
seg_start_pos = header->get_segments_offset();
segment_memory = segment_filesize =
header->get_segment_entry_size() * header->get_segments_num();
}
// Special case:
// Segments which start with the NULL section and have further sections
else if ( seg->get_sections_num() > 1
&& sections[seg->get_section_index_at( 0 )]->get_type() == SHT_NULL ) {
seg_start_pos = 0;
if ( seg->get_sections_num() ) {
segment_memory = segment_filesize = current_file_pos;
}
}
// New segments with not generated sections
// have to be aligned
else if ( seg->get_sections_num()
&& !section_generated[seg->get_section_index_at( 0 )] ) {
Elf_Xword align = seg->get_align() > 0 ? seg->get_align() : 1;
Elf64_Off cur_page_alignment = current_file_pos % align;
Elf64_Off req_page_alignment = seg->get_virtual_address() % align;
Elf64_Off error = req_page_alignment - cur_page_alignment;
current_file_pos += ( seg->get_align() + error ) % align;
seg_start_pos = current_file_pos;
} else if ( seg->get_sections_num() ) {
seg_start_pos = sections[seg->get_section_index_at( 0 )]->get_offset();
}
// Write segment's data
for ( unsigned int j = 0; j < seg->get_sections_num(); ++j ) {
Elf_Half index = seg->get_section_index_at( j );
section* sec = sections[ index ];
// The NULL section is always generated
if ( SHT_NULL == sec->get_type()) {
section_generated[index] = true;
continue;
}
Elf_Xword secAlign = 0;
// Fix up the alignment
if ( !section_generated[index] && sec->is_address_initialized()
&& SHT_NOBITS != sec->get_type()
&& SHT_NULL != sec->get_type()
&& 0 != sec->get_size() ) {
// Align the sections based on the virtual addresses
// when possible (this is what matters for execution)
Elf64_Off req_offset = sec->get_address() - seg->get_virtual_address();
Elf64_Off cur_offset = current_file_pos - seg_start_pos;
if ( req_offset < cur_offset) {
// something has gone awfully wrong, abort!
// secAlign would turn out negative, seeking backwards and overwriting previous data
return false;
}
secAlign = req_offset - cur_offset;
} else if (!section_generated[index] && !sec->is_address_initialized() ) {
// If no address has been specified then only the section
// alignment constraint has to be matched
Elf_Xword align = sec->get_addr_align();
if (align == 0) {
align = 1;
}
Elf64_Off error = current_file_pos % align;
secAlign = ( align - error ) % align;
} else if (section_generated[index] ) {
// Alignment for already generated sections
secAlign = sec->get_offset() - seg_start_pos - segment_filesize;
}
// Determine the segment file and memory sizes
// Special case .tbss section (NOBITS) in non TLS segment
if ( (sec->get_flags() & SHF_ALLOC)
&& !( (sec->get_flags() & SHF_TLS) && (seg->get_type() != PT_TLS)
&& ( SHT_NOBITS == sec->get_type())) )
segment_memory += sec->get_size() + secAlign;
if ( SHT_NOBITS != sec->get_type() && SHT_NULL != sec->get_type() )
segment_filesize += sec->get_size() + secAlign;
// Nothing to be done when generating nested segments
if(section_generated[index]) {
continue;
}
current_file_pos += secAlign;
// Set the section addresses when missing
if ( !sec->is_address_initialized() )
sec->set_address( seg->get_virtual_address()
+ current_file_pos - seg_start_pos);
if ( 0 != sec->get_index() )
sec->set_offset(current_file_pos);
if ( SHT_NOBITS != sec->get_type() && SHT_NULL != sec->get_type() )
current_file_pos += sec->get_size();
section_generated[index] = true;
}
seg->set_file_size( segment_filesize );
// If we already have a memory size from loading an elf file (value > 0),
// it must not shrink!
// Memory size may be bigger than file size and it is the loader's job to do something
// with the surplus bytes in memory, like initializing them with a defined value.
if ( seg->get_memory_size() < segment_memory ) {
seg->set_memory_size( segment_memory );
}
seg->set_offset(seg_start_pos);
}
return true;
}
//------------------------------------------------------------------------------
bool layout_section_table() {
// Simply place the section table at the end for now
Elf64_Off alignmentError = current_file_pos % 4;
current_file_pos += ( 4 - alignmentError ) % 4;
header->set_sections_offset(current_file_pos);
return true;
}
//------------------------------------------------------------------------------
public:
friend class Sections;
class Sections {
public:
//------------------------------------------------------------------------------
Sections( elfio* parent_ ) :
parent( parent_ ) {
}
//------------------------------------------------------------------------------
Elf_Half size() const {
return (Elf_Half)parent->sections_.size();
}
//------------------------------------------------------------------------------
section* operator[]( unsigned int index ) const {
section* sec = 0;
if ( index < parent->sections_.size() ) {
sec = parent->sections_[index];
}
return sec;
}
//------------------------------------------------------------------------------
section* operator[]( const std::string& name ) const {
section* sec = 0;
std::vector<section*>::const_iterator it;
for ( it = parent->sections_.begin();
it != parent->sections_.end();
++it ) {
if ( (*it)->get_name() == name ) {
sec = *it;
break;
}
}
return sec;
}
//------------------------------------------------------------------------------
section* add( const std::string& name ) {
section* new_section = parent->create_section();
new_section->set_name( name );
Elf_Half str_index = parent->get_section_name_str_index();
section* string_table( parent->sections_[str_index] );
string_section_accessor str_writer( string_table );
Elf_Word pos = str_writer.add_string( name );
new_section->set_name_string_offset( pos );
return new_section;
}
//------------------------------------------------------------------------------
std::vector<section*>::iterator begin() {
return parent->sections_.begin();
}
//------------------------------------------------------------------------------
std::vector<section*>::iterator end() {
return parent->sections_.end();
}
//------------------------------------------------------------------------------
std::vector<section*>::const_iterator begin() const {
return parent->sections_.cbegin();
}
//------------------------------------------------------------------------------
std::vector<section*>::const_iterator end() const {
return parent->sections_.cend();
}
//------------------------------------------------------------------------------
private:
elfio* parent;
} sections;
//------------------------------------------------------------------------------
public:
friend class Segments;
class Segments {
public:
//------------------------------------------------------------------------------
Segments( elfio* parent_ ) :
parent( parent_ ) {
}
//------------------------------------------------------------------------------
Elf_Half size() const {
return (Elf_Half)parent->segments_.size();
}
//------------------------------------------------------------------------------
segment* operator[]( unsigned int index ) const {
return parent->segments_[index];
}
//------------------------------------------------------------------------------
segment* add() {
return parent->create_segment();
}
//------------------------------------------------------------------------------
std::vector<segment*>::iterator begin() {
return parent->segments_.begin();
}
//------------------------------------------------------------------------------
std::vector<segment*>::iterator end() {
return parent->segments_.end();
}
//------------------------------------------------------------------------------
std::vector<segment*>::const_iterator begin() const {
return parent->segments_.cbegin();
}
//------------------------------------------------------------------------------
std::vector<segment*>::const_iterator end() const {
return parent->segments_.cend();
}
//------------------------------------------------------------------------------
private:
elfio* parent;
} segments;
//------------------------------------------------------------------------------
private:
elf_header* header;
std::vector<section*> sections_;
std::vector<segment*> segments_;
endianess_convertor convertor;
Elf_Xword current_file_pos;
};
} // namespace ELFIO
#include <elfio/elfio_symbols.hpp>
#include <elfio/elfio_note.hpp>
#include <elfio/elfio_relocation.hpp>
#include <elfio/elfio_dynamic.hpp>
#ifdef _MSC_VER
#pragma warning ( pop )
#endif
#endif // ELFIO_HPP

976
source/elfio/elfio_dump.hpp Normal file
View File

@ -0,0 +1,976 @@
/*
Copyright (C) 2001-2015 by Serge Lamikhov-Center
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef ELFIO_DUMP_HPP
#define ELFIO_DUMP_HPP
#include <algorithm>
#include <string>
#include <ostream>
#include <sstream>
#include <iomanip>
#include <elfio/elfio.hpp>
namespace ELFIO {
static struct class_table_t {
const char key;
const char* str;
} class_table [] =
{
{ ELFCLASS32, "ELF32" },
{ ELFCLASS64, "ELF64" },
};
static struct endian_table_t {
const char key;
const char* str;
} endian_table [] =
{
{ ELFDATANONE, "None" },
{ ELFDATA2LSB, "Little endian" },
{ ELFDATA2MSB, "Big endian" },
};
static struct version_table_t {
const Elf64_Word key;
const char* str;
} version_table [] =
{
{ EV_NONE , "None" },
{ EV_CURRENT, "Current" },
};
static struct type_table_t {
const Elf32_Half key;
const char* str;
} type_table [] =
{
{ ET_NONE, "No file type" },
{ ET_REL , "Relocatable file" },
{ ET_EXEC, "Executable file" },
{ ET_DYN , "Shared object file" },
{ ET_CORE, "Core file" },
};
static struct machine_table_t {
const Elf64_Half key;
const char* str;
} machine_table [] =
{
{ EM_NONE , "No machine" },
{ EM_M32 , "AT&T WE 32100" },
{ EM_SPARC , "SUN SPARC" },
{ EM_386 , "Intel 80386" },
{ EM_68K , "Motorola m68k family" },
{ EM_88K , "Motorola m88k family" },
{ EM_486 , "Intel 80486// Reserved for future use" },
{ EM_860 , "Intel 80860" },
{ EM_MIPS , "MIPS R3000 (officially, big-endian only)" },
{ EM_S370 , "IBM System/370" },
{ EM_MIPS_RS3_LE , "MIPS R3000 little-endian (Oct 4 1999 Draft) Deprecated" },
{ EM_res011 , "Reserved" },
{ EM_res012 , "Reserved" },
{ EM_res013 , "Reserved" },
{ EM_res014 , "Reserved" },
{ EM_PARISC , "HPPA" },
{ EM_res016 , "Reserved" },
{ EM_VPP550 , "Fujitsu VPP500" },
{ EM_SPARC32PLUS , "Sun's v8plus" },
{ EM_960 , "Intel 80960" },
{ EM_PPC , "PowerPC" },
{ EM_PPC64 , "64-bit PowerPC" },
{ EM_S390 , "IBM S/390" },
{ EM_SPU , "Sony/Toshiba/IBM SPU" },
{ EM_res024 , "Reserved" },
{ EM_res025 , "Reserved" },
{ EM_res026 , "Reserved" },
{ EM_res027 , "Reserved" },
{ EM_res028 , "Reserved" },
{ EM_res029 , "Reserved" },
{ EM_res030 , "Reserved" },
{ EM_res031 , "Reserved" },
{ EM_res032 , "Reserved" },
{ EM_res033 , "Reserved" },
{ EM_res034 , "Reserved" },
{ EM_res035 , "Reserved" },
{ EM_V800 , "NEC V800 series" },
{ EM_FR20 , "Fujitsu FR20" },
{ EM_RH32 , "TRW RH32" },
{ EM_MCORE , "Motorola M*Core // May also be taken by Fujitsu MMA" },
{ EM_RCE , "Old name for MCore" },
{ EM_ARM , "ARM" },
{ EM_OLD_ALPHA , "Digital Alpha" },
{ EM_SH , "Renesas (formerly Hitachi) / SuperH SH" },
{ EM_SPARCV9 , "SPARC v9 64-bit" },
{ EM_TRICORE , "Siemens Tricore embedded processor" },
{ EM_ARC , "ARC Cores" },
{ EM_H8_300 , "Renesas (formerly Hitachi) H8/300" },
{ EM_H8_300H , "Renesas (formerly Hitachi) H8/300H" },
{ EM_H8S , "Renesas (formerly Hitachi) H8S" },
{ EM_H8_500 , "Renesas (formerly Hitachi) H8/500" },
{ EM_IA_64 , "Intel IA-64 Processor" },
{ EM_MIPS_X , "Stanford MIPS-X" },
{ EM_COLDFIRE , "Motorola Coldfire" },
{ EM_68HC12 , "Motorola M68HC12" },
{ EM_MMA , "Fujitsu Multimedia Accelerator" },
{ EM_PCP , "Siemens PCP" },
{ EM_NCPU , "Sony nCPU embedded RISC processor" },
{ EM_NDR1 , "Denso NDR1 microprocesspr" },
{ EM_STARCORE , "Motorola Star*Core processor" },
{ EM_ME16 , "Toyota ME16 processor" },
{ EM_ST100 , "STMicroelectronics ST100 processor" },
{ EM_TINYJ , "Advanced Logic Corp. TinyJ embedded processor" },
{ EM_X86_64 , "Advanced Micro Devices X86-64 processor" },
{ EM_PDSP , "Sony DSP Processor" },
{ EM_PDP10 , "Digital Equipment Corp. PDP-10" },
{ EM_PDP11 , "Digital Equipment Corp. PDP-11" },
{ EM_FX66 , "Siemens FX66 microcontroller" },
{ EM_ST9PLUS , "STMicroelectronics ST9+ 8/16 bit microcontroller" },
{ EM_ST7 , "STMicroelectronics ST7 8-bit microcontroller" },
{ EM_68HC16 , "Motorola MC68HC16 Microcontroller" },
{ EM_68HC11 , "Motorola MC68HC11 Microcontroller" },
{ EM_68HC08 , "Motorola MC68HC08 Microcontroller" },
{ EM_68HC05 , "Motorola MC68HC05 Microcontroller" },
{ EM_SVX , "Silicon Graphics SVx" },
{ EM_ST19 , "STMicroelectronics ST19 8-bit cpu" },
{ EM_VAX , "Digital VAX" },
{ EM_CRIS , "Axis Communications 32-bit embedded processor" },
{ EM_JAVELIN , "Infineon Technologies 32-bit embedded cpu" },
{ EM_FIREPATH , "Element 14 64-bit DSP processor" },
{ EM_ZSP , "LSI Logic's 16-bit DSP processor" },
{ EM_MMIX , "Donald Knuth's educational 64-bit processor" },
{ EM_HUANY , "Harvard's machine-independent format" },
{ EM_PRISM , "SiTera Prism" },
{ EM_AVR , "Atmel AVR 8-bit microcontroller" },
{ EM_FR30 , "Fujitsu FR30" },
{ EM_D10V , "Mitsubishi D10V" },
{ EM_D30V , "Mitsubishi D30V" },
{ EM_V850 , "NEC v850" },
{ EM_M32R , "Renesas M32R (formerly Mitsubishi M32R)" },
{ EM_MN10300 , "Matsushita MN10300" },
{ EM_MN10200 , "Matsushita MN10200" },
{ EM_PJ , "picoJava" },
{ EM_OPENRISC , "OpenRISC 32-bit embedded processor" },
{ EM_ARC_A5 , "ARC Cores Tangent-A5" },
{ EM_XTENSA , "Tensilica Xtensa Architecture" },
{ EM_VIDEOCORE , "Alphamosaic VideoCore processor" },
{ EM_TMM_GPP , "Thompson Multimedia General Purpose Processor" },
{ EM_NS32K , "National Semiconductor 32000 series" },
{ EM_TPC , "Tenor Network TPC processor" },
{ EM_SNP1K , "Trebia SNP 1000 processor" },
{ EM_ST200 , "STMicroelectronics ST200 microcontroller" },
{ EM_IP2K , "Ubicom IP2022 micro controller" },
{ EM_MAX , "MAX Processor" },
{ EM_CR , "National Semiconductor CompactRISC" },
{ EM_F2MC16 , "Fujitsu F2MC16" },
{ EM_MSP430 , "TI msp430 micro controller" },
{ EM_BLACKFIN , "ADI Blackfin" },
{ EM_SE_C33 , "S1C33 Family of Seiko Epson processors" },
{ EM_SEP , "Sharp embedded microprocessor" },
{ EM_ARCA , "Arca RISC Microprocessor" },
{ EM_UNICORE , "Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University" },
{ EM_EXCESS , "eXcess: 16/32/64-bit configurable embedded CPU" },
{ EM_DXP , "Icera Semiconductor Inc. Deep Execution Processor" },
{ EM_ALTERA_NIOS2 , "Altera Nios II soft-core processor" },
{ EM_CRX , "National Semiconductor CRX" },
{ EM_XGATE , "Motorola XGATE embedded processor" },
{ EM_C166 , "Infineon C16x/XC16x processor" },
{ EM_M16C , "Renesas M16C series microprocessors" },
{ EM_DSPIC30F , "Microchip Technology dsPIC30F Digital Signal Controller" },
{ EM_CE , "Freescale Communication Engine RISC core" },
{ EM_M32C , "Renesas M32C series microprocessors" },
{ EM_res121 , "Reserved" },
{ EM_res122 , "Reserved" },
{ EM_res123 , "Reserved" },
{ EM_res124 , "Reserved" },
{ EM_res125 , "Reserved" },
{ EM_res126 , "Reserved" },
{ EM_res127 , "Reserved" },
{ EM_res128 , "Reserved" },
{ EM_res129 , "Reserved" },
{ EM_res130 , "Reserved" },
{ EM_TSK3000 , "Altium TSK3000 core" },
{ EM_RS08 , "Freescale RS08 embedded processor" },
{ EM_res133 , "Reserved" },
{ EM_ECOG2 , "Cyan Technology eCOG2 microprocessor" },
{ EM_SCORE , "Sunplus Score" },
{ EM_SCORE7 , "Sunplus S+core7 RISC processor" },
{ EM_DSP24 , "New Japan Radio (NJR) 24-bit DSP Processor" },
{ EM_VIDEOCORE3 , "Broadcom VideoCore III processor" },
{ EM_LATTICEMICO32, "RISC processor for Lattice FPGA architecture" },
{ EM_SE_C17 , "Seiko Epson C17 family" },
{ EM_TI_C6000 , "Texas Instruments TMS320C6000 DSP family" },
{ EM_TI_C2000 , "Texas Instruments TMS320C2000 DSP family" },
{ EM_TI_C5500 , "Texas Instruments TMS320C55x DSP family" },
{ EM_res143 , "Reserved" },
{ EM_res144 , "Reserved" },
{ EM_res145 , "Reserved" },
{ EM_res146 , "Reserved" },
{ EM_res147 , "Reserved" },
{ EM_res148 , "Reserved" },
{ EM_res149 , "Reserved" },
{ EM_res150 , "Reserved" },
{ EM_res151 , "Reserved" },
{ EM_res152 , "Reserved" },
{ EM_res153 , "Reserved" },
{ EM_res154 , "Reserved" },
{ EM_res155 , "Reserved" },
{ EM_res156 , "Reserved" },
{ EM_res157 , "Reserved" },
{ EM_res158 , "Reserved" },
{ EM_res159 , "Reserved" },
{ EM_MMDSP_PLUS , "STMicroelectronics 64bit VLIW Data Signal Processor" },
{ EM_CYPRESS_M8C , "Cypress M8C microprocessor" },
{ EM_R32C , "Renesas R32C series microprocessors" },
{ EM_TRIMEDIA , "NXP Semiconductors TriMedia architecture family" },
{ EM_QDSP6 , "QUALCOMM DSP6 Processor" },
{ EM_8051 , "Intel 8051 and variants" },
{ EM_STXP7X , "STMicroelectronics STxP7x family" },
{ EM_NDS32 , "Andes Technology compact code size embedded RISC processor family" },
{ EM_ECOG1 , "Cyan Technology eCOG1X family" },
{ EM_ECOG1X , "Cyan Technology eCOG1X family" },
{ EM_MAXQ30 , "Dallas Semiconductor MAXQ30 Core Micro-controllers" },
{ EM_XIMO16 , "New Japan Radio (NJR) 16-bit DSP Processor" },
{ EM_MANIK , "M2000 Reconfigurable RISC Microprocessor" },
{ EM_CRAYNV2 , "Cray Inc. NV2 vector architecture" },
{ EM_RX , "Renesas RX family" },
{ EM_METAG , "Imagination Technologies META processor architecture" },
{ EM_MCST_ELBRUS , "MCST Elbrus general purpose hardware architecture" },
{ EM_ECOG16 , "Cyan Technology eCOG16 family" },
{ EM_CR16 , "National Semiconductor CompactRISC 16-bit processor" },
{ EM_ETPU , "Freescale Extended Time Processing Unit" },
{ EM_SLE9X , "Infineon Technologies SLE9X core" },
{ EM_L1OM , "Intel L1OM" },
{ EM_INTEL181 , "Reserved by Intel" },
{ EM_INTEL182 , "Reserved by Intel" },
{ EM_res183 , "Reserved by ARM" },
{ EM_res184 , "Reserved by ARM" },
{ EM_AVR32 , "Atmel Corporation 32-bit microprocessor family" },
{ EM_STM8 , "STMicroeletronics STM8 8-bit microcontroller" },
{ EM_TILE64 , "Tilera TILE64 multicore architecture family" },
{ EM_TILEPRO , "Tilera TILEPro multicore architecture family" },
{ EM_MICROBLAZE , "Xilinx MicroBlaze 32-bit RISC soft processor core" },
{ EM_CUDA , "NVIDIA CUDA architecture " },
};
static struct section_type_table_t {
const Elf64_Half key;
const char* str;
} section_type_table [] =
{
{ SHT_NULL , "NULL" },
{ SHT_PROGBITS , "PROGBITS" },
{ SHT_SYMTAB , "SYMTAB" },
{ SHT_STRTAB , "STRTAB" },
{ SHT_RELA , "RELA" },
{ SHT_HASH , "HASH" },
{ SHT_DYNAMIC , "DYNAMIC" },
{ SHT_NOTE , "NOTE" },
{ SHT_NOBITS , "NOBITS" },
{ SHT_REL , "REL" },
{ SHT_SHLIB , "SHLIB" },
{ SHT_DYNSYM , "DYNSYM" },
{ SHT_INIT_ARRAY , "INIT_ARRAY" },
{ SHT_FINI_ARRAY , "FINI_ARRAY" },
{ SHT_PREINIT_ARRAY, "PREINIT_ARRAY" },
{ SHT_GROUP , "GROUP" },
{ SHT_SYMTAB_SHNDX , "SYMTAB_SHNDX " },
};
static struct segment_type_table_t {
const Elf_Word key;
const char* str;
} segment_type_table [] =
{
{ PT_NULL , "NULL" },
{ PT_LOAD , "LOAD" },
{ PT_DYNAMIC, "DYNAMIC" },
{ PT_INTERP , "INTERP" },
{ PT_NOTE , "NOTE" },
{ PT_SHLIB , "SHLIB" },
{ PT_PHDR , "PHDR" },
{ PT_TLS , "TLS" },
};
static struct segment_flag_table_t {
const Elf_Word key;
const char* str;
} segment_flag_table [] =
{
{ 0, "" },
{ 1, "X" },
{ 2, "W" },
{ 3, "WX" },
{ 4, "R" },
{ 5, "RX" },
{ 6, "RW" },
{ 7, "RWX" },
};
static struct symbol_bind_t {
const Elf_Word key;
const char* str;
} symbol_bind_table [] =
{
{ STB_LOCAL , "LOCAL" },
{ STB_GLOBAL , "GLOBAL" },
{ STB_WEAK , "WEAK" },
{ STB_LOOS , "LOOS" },
{ STB_HIOS , "HIOS" },
{ STB_MULTIDEF, "MULTIDEF" },
{ STB_LOPROC , "LOPROC" },
{ STB_HIPROC , "HIPROC" },
};
static struct symbol_type_t {
const Elf_Word key;
const char* str;
} symbol_type_table [] =
{
{ STT_NOTYPE , "NOTYPE" },
{ STT_OBJECT , "OBJECT" },
{ STT_FUNC , "FUNC" },
{ STT_SECTION, "SECTION" },
{ STT_FILE , "FILE" },
{ STT_COMMON , "COMMON" },
{ STT_TLS , "TLS" },
{ STT_LOOS , "LOOS" },
{ STT_HIOS , "HIOS" },
{ STT_LOPROC , "LOPROC" },
{ STT_HIPROC , "HIPROC" },
};
static struct dynamic_tag_t {
const Elf_Word key;
const char* str;
} dynamic_tag_table [] =
{
{ DT_NULL , "NULL" },
{ DT_NEEDED , "NEEDED" },
{ DT_PLTRELSZ , "PLTRELSZ" },
{ DT_PLTGOT , "PLTGOT" },
{ DT_HASH , "HASH" },
{ DT_STRTAB , "STRTAB" },
{ DT_SYMTAB , "SYMTAB" },
{ DT_RELA , "RELA" },
{ DT_RELASZ , "RELASZ" },
{ DT_RELAENT , "RELAENT" },
{ DT_STRSZ , "STRSZ" },
{ DT_SYMENT , "SYMENT" },
{ DT_INIT , "INIT" },
{ DT_FINI , "FINI" },
{ DT_SONAME , "SONAME" },
{ DT_RPATH , "RPATH" },
{ DT_SYMBOLIC , "SYMBOLIC" },
{ DT_REL , "REL" },
{ DT_RELSZ , "RELSZ" },
{ DT_RELENT , "RELENT" },
{ DT_PLTREL , "PLTREL" },
{ DT_DEBUG , "DEBUG" },
{ DT_TEXTREL , "TEXTREL" },
{ DT_JMPREL , "JMPREL" },
{ DT_BIND_NOW , "BIND_NOW" },
{ DT_INIT_ARRAY , "INIT_ARRAY" },
{ DT_FINI_ARRAY , "FINI_ARRAY" },
{ DT_INIT_ARRAYSZ , "INIT_ARRAYSZ" },
{ DT_FINI_ARRAYSZ , "FINI_ARRAYSZ" },
{ DT_RUNPATH , "RUNPATH" },
{ DT_FLAGS , "FLAGS" },
{ DT_ENCODING , "ENCODING" },
{ DT_PREINIT_ARRAY , "PREINIT_ARRAY" },
{ DT_PREINIT_ARRAYSZ, "PREINIT_ARRAYSZ" },
{ DT_MAXPOSTAGS , "MAXPOSTAGS" },
};
static const ELFIO::Elf_Xword MAX_DATA_ENTRIES = 64;
//------------------------------------------------------------------------------
class dump
{
#define DUMP_DEC_FORMAT( width ) std::setw(width) << std::setfill( ' ' ) << \
std::dec << std::right
#define DUMP_HEX_FORMAT( width ) std::setw(width) << std::setfill( '0' ) << \
std::hex << std::right
#define DUMP_STR_FORMAT( width ) std::setw(width) << std::setfill( ' ' ) << \
std::hex << std::left
public:
//------------------------------------------------------------------------------
static void
header( std::ostream& out, const elfio& reader )
{
if (!reader.get_header_size())
{
return;
}
out << "ELF Header" << std::endl << std::endl
<< " Class: " << str_class( reader.get_class() ) << std::endl
<< " Encoding: " << str_endian( reader.get_encoding() ) << std::endl
<< " ELFVersion: " << str_version( reader.get_elf_version() ) << std::endl
<< " Type: " << str_type( reader.get_type() ) << std::endl
<< " Machine: " << str_machine( reader.get_machine() ) << std::endl
<< " Version: " << str_version( reader.get_version() ) << std::endl
<< " Entry: " << "0x" << std::hex << reader.get_entry() << std::endl
<< " Flags: " << "0x" << std::hex << reader.get_flags() << std::endl
<< std::endl;
}
//------------------------------------------------------------------------------
static void
section_headers( std::ostream& out, const elfio& reader )
{
Elf_Half n = reader.sections.size();
if ( n == 0 ) {
return;
}
out << "Section Headers:" << std::endl;
if ( reader.get_class() == ELFCLASS32 ) { // Output for 32-bit
out << "[ Nr ] Type Addr Size ES Flg Lk Inf Al Name" << std::endl;
}
else { // Output for 64-bit
out << "[ Nr ] Type Addr Size ES Flg" << std::endl
<< " Lk Inf Al Name" << std::endl;
}
for ( Elf_Half i = 0; i < n; ++i ) { // For all sections
section* sec = reader.sections[i];
section_header( out, i, sec, reader.get_class() );
}
out << "Key to Flags: W (write), A (alloc), X (execute)\n\n"
<< std::endl;
}
//------------------------------------------------------------------------------
static void
section_header( std::ostream& out, Elf_Half no, const section* sec,
unsigned char elf_class )
{
std::ios_base::fmtflags original_flags = out.flags();
if ( elf_class == ELFCLASS32 ) { // Output for 32-bit
out << "["
<< DUMP_DEC_FORMAT( 5 ) << no
<< "] "
<< DUMP_STR_FORMAT( 17 ) << str_section_type( sec->get_type() ) << " "
<< DUMP_HEX_FORMAT( 8 ) << sec->get_address() << " "
<< DUMP_HEX_FORMAT( 8 ) << sec->get_size() << " "
<< DUMP_HEX_FORMAT( 2 ) << sec->get_entry_size() << " "
<< DUMP_STR_FORMAT( 3 ) << section_flags( sec->get_flags() ) << " "
<< DUMP_HEX_FORMAT( 2 ) << sec->get_link() << " "
<< DUMP_HEX_FORMAT( 3 ) << sec->get_info() << " "
<< DUMP_HEX_FORMAT( 2 ) << sec->get_addr_align() << " "
<< DUMP_STR_FORMAT( 17 ) << sec->get_name() << " "
<< std::endl;
}
else { // Output for 64-bit
out << "["
<< DUMP_DEC_FORMAT( 5 ) << no
<< "] "
<< DUMP_STR_FORMAT( 17 ) << str_section_type( sec->get_type() ) << " "
<< DUMP_HEX_FORMAT( 16 ) << sec->get_address() << " "
<< DUMP_HEX_FORMAT( 16 ) << sec->get_size() << " "
<< DUMP_HEX_FORMAT( 4 ) << sec->get_entry_size() << " "
<< DUMP_STR_FORMAT( 3 ) << section_flags( sec->get_flags() ) << " "
<< std::endl
<< " "
<< DUMP_HEX_FORMAT( 4 ) << sec->get_link() << " "
<< DUMP_HEX_FORMAT( 4 ) << sec->get_info() << " "
<< DUMP_HEX_FORMAT( 4 ) << sec->get_addr_align() << " "
<< DUMP_STR_FORMAT( 17 ) << sec->get_name() << " "
<< std::endl;
}
out.flags(original_flags);
return;
}
//------------------------------------------------------------------------------
static void
segment_headers( std::ostream& out, const elfio& reader )
{
Elf_Half n = reader.segments.size();
if ( n == 0 ) {
return;
}
out << "Segment headers:" << std::endl;
if ( reader.get_class() == ELFCLASS32 ) { // Output for 32-bit
out << "[ Nr ] Type VirtAddr PhysAddr FileSize Mem.Size Flags Align"
<< std::endl;
}
else { // Output for 64-bit
out << "[ Nr ] Type VirtAddr PhysAddr Flags" << std::endl
<< " FileSize Mem.Size Align"
<< std::endl;
}
for ( Elf_Half i = 0; i < n; ++i ) {
segment* seg = reader.segments[i];
segment_header( out, i, seg, reader.get_class() );
}
out << std::endl;
}
//------------------------------------------------------------------------------
static void
segment_header( std::ostream& out, Elf_Half no, const segment* seg,
unsigned int elf_class )
{
std::ios_base::fmtflags original_flags = out.flags();
if ( elf_class == ELFCLASS32 ) { // Output for 32-bit
out << "["
<< DUMP_DEC_FORMAT( 5 ) << no
<< "] "
<< DUMP_STR_FORMAT( 14 ) << str_segment_type( seg->get_type() ) << " "
<< DUMP_HEX_FORMAT( 8 ) << seg->get_virtual_address() << " "
<< DUMP_HEX_FORMAT( 8 ) << seg->get_physical_address() << " "
<< DUMP_HEX_FORMAT( 8 ) << seg->get_file_size() << " "
<< DUMP_HEX_FORMAT( 8 ) << seg->get_memory_size() << " "
<< DUMP_STR_FORMAT( 8 ) << str_segment_flag( seg->get_flags() ) << " "
<< DUMP_HEX_FORMAT( 8 ) << seg->get_align() << " "
<< std::endl;
}
else { // Output for 64-bit
out << "["
<< DUMP_DEC_FORMAT( 5 ) << no
<< "] "
<< DUMP_STR_FORMAT( 14 ) << str_segment_type( seg->get_type() ) << " "
<< DUMP_HEX_FORMAT( 16 ) << seg->get_virtual_address() << " "
<< DUMP_HEX_FORMAT( 16 ) << seg->get_physical_address() << " "
<< DUMP_STR_FORMAT( 16 ) << str_segment_flag( seg->get_flags() ) << " "
<< std::endl
<< " "
<< DUMP_HEX_FORMAT( 16 ) << seg->get_file_size() << " "
<< DUMP_HEX_FORMAT( 16 ) << seg->get_memory_size() << " "
<< DUMP_HEX_FORMAT( 16 ) << seg->get_align() << " "
<< std::endl;
}
out.flags(original_flags);
}
//------------------------------------------------------------------------------
static void
symbol_tables( std::ostream& out, const elfio& reader )
{
Elf_Half n = reader.sections.size();
for ( Elf_Half i = 0; i < n; ++i ) { // For all sections
section* sec = reader.sections[i];
if ( SHT_SYMTAB == sec->get_type() || SHT_DYNSYM == sec->get_type() ) {
symbol_section_accessor symbols( reader, sec );
Elf_Xword sym_no = symbols.get_symbols_num();
if ( sym_no > 0 ) {
out << "Symbol table (" << sec->get_name() << ")" << std::endl;
if ( reader.get_class() == ELFCLASS32 ) { // Output for 32-bit
out << "[ Nr ] Value Size Type Bind Sect Name"
<< std::endl;
}
else { // Output for 64-bit
out << "[ Nr ] Value Size Type Bind Sect" << std::endl
<< " Name"
<< std::endl;
}
for ( Elf_Half i = 0; i < sym_no; ++i ) {
std::string name;
Elf64_Addr value = 0;
Elf_Xword size = 0;
unsigned char bind = 0;
unsigned char type = 0;
Elf_Half section = 0;
unsigned char other = 0;
symbols.get_symbol( i, name, value, size, bind, type, section, other );
symbol_table( out, i, name, value, size, bind, type, section, reader.get_class() );
}
out << std::endl;
}
}
}
}
//------------------------------------------------------------------------------
static void
symbol_table( std::ostream& out,
Elf_Half no,
std::string& name,
Elf64_Addr value,
Elf_Xword size,
unsigned char bind,
unsigned char type,
Elf_Half section,
unsigned int elf_class )
{
std::ios_base::fmtflags original_flags = out.flags();
if ( elf_class == ELFCLASS32 ) { // Output for 32-bit
out << "["
<< DUMP_DEC_FORMAT( 5 ) << no
<< "] "
<< DUMP_HEX_FORMAT( 8 ) << value << " "
<< DUMP_HEX_FORMAT( 8 ) << size << " "
<< DUMP_STR_FORMAT( 7 ) << str_symbol_type( type ) << " "
<< DUMP_STR_FORMAT( 8 ) << str_symbol_bind( bind ) << " "
<< DUMP_DEC_FORMAT( 5 ) << section << " "
<< DUMP_STR_FORMAT( 1 ) << name << " "
<< std::endl;
}
else { // Output for 64-bit
out << "["
<< DUMP_DEC_FORMAT( 5 ) << no
<< "] "
<< DUMP_HEX_FORMAT( 16 ) << value << " "
<< DUMP_HEX_FORMAT( 16 ) << size << " "
<< DUMP_STR_FORMAT( 7 ) << str_symbol_type( type ) << " "
<< DUMP_STR_FORMAT( 8 ) << str_symbol_bind( bind ) << " "
<< DUMP_DEC_FORMAT( 5 ) << section << " "
<< std::endl
<< " "
<< DUMP_STR_FORMAT( 1 ) << name << " "
<< std::endl;
}
out.flags(original_flags);
}
//------------------------------------------------------------------------------
static void
notes( std::ostream& out, const elfio& reader )
{
Elf_Half no = reader.sections.size();
for ( Elf_Half i = 0; i < no; ++i ) { // For all sections
section* sec = reader.sections[i];
if ( SHT_NOTE == sec->get_type() ) { // Look at notes
note_section_accessor notes( reader, sec );
int no_notes = notes.get_notes_num();
if ( no > 0 ) {
out << "Note section (" << sec->get_name() << ")" << std::endl
<< " No Type Name"
<< std::endl;
for ( int j = 0; j < no_notes; ++j ) { // For all notes
Elf_Word type;
std::string name;
void* desc;
Elf_Word descsz;
if ( notes.get_note(j, type, name, desc, descsz) ) {
// 'name' usually contains \0 at the end. Try to fix it
name = name.c_str();
note( out, j, type, name );
}
}
out << std::endl;
}
}
}
}
//------------------------------------------------------------------------------
static void
note( std::ostream& out,
int no,
Elf_Word type,
const std::string& name )
{
out << " ["
<< DUMP_DEC_FORMAT( 2 ) << no
<< "] "
<< DUMP_HEX_FORMAT( 8 ) << type << " "
<< DUMP_STR_FORMAT( 1 ) << name
<< std::endl;
}
//------------------------------------------------------------------------------
static void
dynamic_tags( std::ostream& out, const elfio& reader )
{
Elf_Half n = reader.sections.size();
for ( Elf_Half i = 0; i < n; ++i ) { // For all sections
section* sec = reader.sections[i];
if ( SHT_DYNAMIC == sec->get_type() ) {
dynamic_section_accessor dynamic( reader, sec );
Elf_Xword dyn_no = dynamic.get_entries_num();
if ( dyn_no > 0 ) {
out << "Dynamic section (" << sec->get_name() << ")" << std::endl;
out << "[ Nr ] Tag Name/Value" << std::endl;
for ( Elf_Xword i = 0; i < dyn_no; ++i ) {
Elf_Xword tag = 0;
Elf_Xword value = 0;
std::string str;
dynamic.get_entry( i, tag, value, str );
dynamic_tag( out, i, tag, value, str, reader.get_class() );
if ( DT_NULL == tag ) {
break;
}
}
out << std::endl;
}
}
}
}
//------------------------------------------------------------------------------
static void
dynamic_tag( std::ostream& out,
Elf_Xword no,
Elf_Xword tag,
Elf_Xword value,
std::string str,
unsigned int /*elf_class*/ )
{
out << "["
<< DUMP_DEC_FORMAT( 5 ) << no
<< "] "
<< DUMP_STR_FORMAT( 16 ) << str_dynamic_tag( tag ) << " ";
if ( str.empty() ) {
out << DUMP_HEX_FORMAT( 16 ) << value << " ";
}
else {
out << DUMP_STR_FORMAT( 32 ) << str << " ";
}
out << std::endl;
}
//------------------------------------------------------------------------------
static void
section_data( std::ostream& out, const section* sec )
{
std::ios_base::fmtflags original_flags = out.flags();
out << sec->get_name() << std::endl;
const char* pdata = sec->get_data();
if ( pdata ){
ELFIO::Elf_Xword i;
for ( i = 0; i < std::min( sec->get_size(), MAX_DATA_ENTRIES ); ++i ) {
if ( i % 16 == 0 ) {
out << "[" << DUMP_HEX_FORMAT( 8 ) << i << "]";
}
out << " " << DUMP_HEX_FORMAT( 2 ) << ( pdata[i] & 0x000000FF );
if ( i % 16 == 15 ) {
out << std::endl;
}
}
if ( i % 16 != 0 ) {
out << std::endl;
}
out.flags(original_flags);
}
return;
}
//------------------------------------------------------------------------------
static void
section_datas( std::ostream& out, const elfio& reader )
{
Elf_Half n = reader.sections.size();
if ( n == 0 ) {
return;
}
out << "Section Data:" << std::endl;
for ( Elf_Half i = 1; i < n; ++i ) { // For all sections
section* sec = reader.sections[i];
if ( sec->get_type() == SHT_NOBITS ) {
continue;
}
section_data( out, sec );
}
out << std::endl;
}
//------------------------------------------------------------------------------
static void
segment_data( std::ostream& out, Elf_Half no, const segment* seg )
{
std::ios_base::fmtflags original_flags = out.flags();
out << "Segment # " << no << std::endl;
const char* pdata = seg->get_data();
if ( pdata ) {
ELFIO::Elf_Xword i;
for ( i = 0; i < std::min( seg->get_file_size(), MAX_DATA_ENTRIES ); ++i ) {
if ( i % 16 == 0 ) {
out << "[" << DUMP_HEX_FORMAT( 8 ) << i << "]";
}
out << " " << DUMP_HEX_FORMAT( 2 ) << ( pdata[i] & 0x000000FF );
if ( i % 16 == 15 ) {
out << std::endl;
}
}
if ( i % 16 != 0 ) {
out << std::endl;
}
out.flags(original_flags);
}
return;
}
//------------------------------------------------------------------------------
static void
segment_datas( std::ostream& out, const elfio& reader )
{
Elf_Half n = reader.segments.size();
if ( n == 0 ) {
return;
}
out << "Segment Data:" << std::endl;
for ( Elf_Half i = 0; i < n; ++i ) { // For all sections
segment* seg = reader.segments[i];
segment_data( out, i, seg );
}
out << std::endl;
}
private:
//------------------------------------------------------------------------------
template< typename T, typename K >
std::string
static
find_value_in_table( const T& table, const K& key )
{
std::string res = "?";
for ( unsigned int i = 0; i < sizeof( table )/sizeof( table[0] ); ++i ) {
if ( table[i].key == key ) {
res = table[i].str;
break;
}
}
return res;
}
//------------------------------------------------------------------------------
template< typename T, typename K >
static
std::string
format_assoc( const T& table, const K& key )
{
std::string str = find_value_in_table( table, key );
if ( str == "?" ) {
std::ostringstream oss;
oss << str << " (0x" << std::hex << key << ")";
str = oss.str();
}
return str;
}
//------------------------------------------------------------------------------
template< typename T >
static
std::string
format_assoc( const T& table, const char key )
{
return format_assoc( table, (const int)key );
}
//------------------------------------------------------------------------------
static
std::string
section_flags( Elf_Xword flags )
{
std::string ret = "";
if ( flags & SHF_WRITE ) {
ret += "W";
}
if ( flags & SHF_ALLOC ) {
ret += "A";
}
if ( flags & SHF_EXECINSTR ) {
ret += "X";
}
return ret;
}
//------------------------------------------------------------------------------
#define STR_FUNC_TABLE( name ) \
template< typename T > \
static \
std::string \
str_##name( const T key ) \
{ \
return format_assoc( name##_table, key ); \
}
STR_FUNC_TABLE( class )
STR_FUNC_TABLE( endian )
STR_FUNC_TABLE( version )
STR_FUNC_TABLE( type )
STR_FUNC_TABLE( machine )
STR_FUNC_TABLE( section_type )
STR_FUNC_TABLE( segment_type )
STR_FUNC_TABLE( segment_flag )
STR_FUNC_TABLE( symbol_bind )
STR_FUNC_TABLE( symbol_type )
STR_FUNC_TABLE( dynamic_tag )
#undef STR_FUNC_TABLE
#undef DUMP_DEC_FORMAT
#undef DUMP_HEX_FORMAT
#undef DUMP_STR_FORMAT
}; // class dump
}; // namespace ELFIO
#endif // ELFIO_DUMP_HPP

View File

@ -0,0 +1,257 @@
/*
Copyright (C) 2001-2015 by Serge Lamikhov-Center
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef ELFIO_DYNAMIC_HPP
#define ELFIO_DYNAMIC_HPP
namespace ELFIO {
//------------------------------------------------------------------------------
template< class S >
class dynamic_section_accessor_template
{
public:
//------------------------------------------------------------------------------
dynamic_section_accessor_template( const elfio& elf_file_, S* section_ ) :
elf_file( elf_file_ ),
dynamic_section( section_ )
{
}
//------------------------------------------------------------------------------
Elf_Xword
get_entries_num() const
{
Elf_Xword nRet = 0;
if ( 0 != dynamic_section->get_entry_size() ) {
nRet = dynamic_section->get_size() / dynamic_section->get_entry_size();
}
return nRet;
}
//------------------------------------------------------------------------------
bool
get_entry( Elf_Xword index,
Elf_Xword& tag,
Elf_Xword& value,
std::string& str ) const
{
if ( index >= get_entries_num() ) { // Is index valid
return false;
}
if ( elf_file.get_class() == ELFCLASS32 ) {
generic_get_entry_dyn< Elf32_Dyn >( index, tag, value );
}
else {
generic_get_entry_dyn< Elf64_Dyn >( index, tag, value );
}
// If the tag may have a string table reference, prepare the string
if ( tag == DT_NEEDED ||
tag == DT_SONAME ||
tag == DT_RPATH ||
tag == DT_RUNPATH ) {
string_section_accessor strsec =
elf_file.sections[ get_string_table_index() ];
const char* result = strsec.get_string( value );
if ( 0 == result ) {
str.clear();
return false;
}
str = result;
}
else {
str.clear();
}
return true;
}
//------------------------------------------------------------------------------
void
add_entry( Elf_Xword tag,
Elf_Xword value )
{
if ( elf_file.get_class() == ELFCLASS32 ) {
generic_add_entry< Elf32_Dyn >( tag, value );
}
else {
generic_add_entry< Elf64_Dyn >( tag, value );
}
}
//------------------------------------------------------------------------------
void
add_entry( Elf_Xword tag,
const std::string& str )
{
string_section_accessor strsec =
elf_file.sections[ get_string_table_index() ];
Elf_Xword value = strsec.add_string( str );
add_entry( tag, value );
}
//------------------------------------------------------------------------------
private:
//------------------------------------------------------------------------------
Elf_Half
get_string_table_index() const
{
return (Elf_Half)dynamic_section->get_link();
}
//------------------------------------------------------------------------------
template< class T >
void
generic_get_entry_dyn( Elf_Xword index,
Elf_Xword& tag,
Elf_Xword& value ) const
{
const endianess_convertor& convertor = elf_file.get_convertor();
// Check unusual case when dynamic section has no data
if( dynamic_section->get_data() == 0 ||
( index + 1 ) * dynamic_section->get_entry_size() > dynamic_section->get_size() ) {
tag = DT_NULL;
value = 0;
return;
}
const T* pEntry = reinterpret_cast<const T*>(
dynamic_section->get_data() +
index * dynamic_section->get_entry_size() );
tag = convertor( pEntry->d_tag );
switch ( tag ) {
case DT_NULL:
case DT_SYMBOLIC:
case DT_TEXTREL:
case DT_BIND_NOW:
value = 0;
break;
case DT_NEEDED:
case DT_PLTRELSZ:
case DT_RELASZ:
case DT_RELAENT:
case DT_STRSZ:
case DT_SYMENT:
case DT_SONAME:
case DT_RPATH:
case DT_RELSZ:
case DT_RELENT:
case DT_PLTREL:
case DT_INIT_ARRAYSZ:
case DT_FINI_ARRAYSZ:
case DT_RUNPATH:
case DT_FLAGS:
case DT_PREINIT_ARRAYSZ:
value = convertor( pEntry->d_un.d_val );
break;
case DT_PLTGOT:
case DT_HASH:
case DT_STRTAB:
case DT_SYMTAB:
case DT_RELA:
case DT_INIT:
case DT_FINI:
case DT_REL:
case DT_DEBUG:
case DT_JMPREL:
case DT_INIT_ARRAY:
case DT_FINI_ARRAY:
case DT_PREINIT_ARRAY:
default:
value = convertor( pEntry->d_un.d_ptr );
break;
}
}
//------------------------------------------------------------------------------
template< class T >
void
generic_add_entry( Elf_Xword tag, Elf_Xword value )
{
const endianess_convertor& convertor = elf_file.get_convertor();
T entry;
switch ( tag ) {
case DT_NULL:
case DT_SYMBOLIC:
case DT_TEXTREL:
case DT_BIND_NOW:
value = 0;
case DT_NEEDED:
case DT_PLTRELSZ:
case DT_RELASZ:
case DT_RELAENT:
case DT_STRSZ:
case DT_SYMENT:
case DT_SONAME:
case DT_RPATH:
case DT_RELSZ:
case DT_RELENT:
case DT_PLTREL:
case DT_INIT_ARRAYSZ:
case DT_FINI_ARRAYSZ:
case DT_RUNPATH:
case DT_FLAGS:
case DT_PREINIT_ARRAYSZ:
entry.d_un.d_val = convertor( value );
break;
case DT_PLTGOT:
case DT_HASH:
case DT_STRTAB:
case DT_SYMTAB:
case DT_RELA:
case DT_INIT:
case DT_FINI:
case DT_REL:
case DT_DEBUG:
case DT_JMPREL:
case DT_INIT_ARRAY:
case DT_FINI_ARRAY:
case DT_PREINIT_ARRAY:
default:
entry.d_un.d_ptr = convertor( value );
break;
}
entry.d_tag = convertor( tag );
dynamic_section->append_data( reinterpret_cast<char*>( &entry ), sizeof( entry ) );
}
//------------------------------------------------------------------------------
private:
const elfio& elf_file;
S* dynamic_section;
};
using dynamic_section_accessor = dynamic_section_accessor_template<section>;
using const_dynamic_section_accessor = dynamic_section_accessor_template<const section>;
} // namespace ELFIO
#endif // ELFIO_DYNAMIC_HPP

View File

@ -0,0 +1,145 @@
/*
Copyright (C) 2001-2015 by Serge Lamikhov-Center
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef ELF_HEADER_HPP
#define ELF_HEADER_HPP
#include <iostream>
namespace ELFIO {
class elf_header
{
public:
virtual ~elf_header() {};
virtual bool load( std::istream& stream ) = 0;
virtual bool save( std::ostream& stream ) const = 0;
// ELF header functions
ELFIO_GET_ACCESS_DECL( unsigned char, class );
ELFIO_GET_ACCESS_DECL( unsigned char, elf_version );
ELFIO_GET_ACCESS_DECL( unsigned char, encoding );
ELFIO_GET_ACCESS_DECL( Elf_Half, header_size );
ELFIO_GET_ACCESS_DECL( Elf_Half, section_entry_size );
ELFIO_GET_ACCESS_DECL( Elf_Half, segment_entry_size );
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, version );
ELFIO_GET_SET_ACCESS_DECL( unsigned char, os_abi );
ELFIO_GET_SET_ACCESS_DECL( unsigned char, abi_version );
ELFIO_GET_SET_ACCESS_DECL( Elf_Half, type );
ELFIO_GET_SET_ACCESS_DECL( Elf_Half, machine );
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, flags );
ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, entry );
ELFIO_GET_SET_ACCESS_DECL( Elf_Half, sections_num );
ELFIO_GET_SET_ACCESS_DECL( Elf64_Off, sections_offset );
ELFIO_GET_SET_ACCESS_DECL( Elf_Half, segments_num );
ELFIO_GET_SET_ACCESS_DECL( Elf64_Off, segments_offset );
ELFIO_GET_SET_ACCESS_DECL( Elf_Half, section_name_str_index );
};
template< class T > struct elf_header_impl_types;
template<> struct elf_header_impl_types<Elf32_Ehdr> {
typedef Elf32_Phdr Phdr_type;
typedef Elf32_Shdr Shdr_type;
static const unsigned char file_class = ELFCLASS32;
};
template<> struct elf_header_impl_types<Elf64_Ehdr> {
typedef Elf64_Phdr Phdr_type;
typedef Elf64_Shdr Shdr_type;
static const unsigned char file_class = ELFCLASS64;
};
template< class T > class elf_header_impl : public elf_header
{
public:
elf_header_impl( endianess_convertor* convertor_,
unsigned char encoding )
{
convertor = convertor_;
std::fill_n( reinterpret_cast<char*>( &header ), sizeof( header ), '\0' );
header.e_ident[EI_MAG0] = ELFMAG0;
header.e_ident[EI_MAG1] = ELFMAG1;
header.e_ident[EI_MAG2] = ELFMAG2;
header.e_ident[EI_MAG3] = ELFMAG3;
header.e_ident[EI_CLASS] = elf_header_impl_types<T>::file_class;
header.e_ident[EI_DATA] = encoding;
header.e_ident[EI_VERSION] = EV_CURRENT;
header.e_version = (*convertor)( (Elf_Word)EV_CURRENT );
header.e_ehsize = ( sizeof( header ) );
header.e_ehsize = (*convertor)( header.e_ehsize );
header.e_shstrndx = (*convertor)( (Elf_Half)1 );
header.e_phentsize = sizeof( typename elf_header_impl_types<T>::Phdr_type );
header.e_shentsize = sizeof( typename elf_header_impl_types<T>::Shdr_type );
header.e_phentsize = (*convertor)( header.e_phentsize );
header.e_shentsize = (*convertor)( header.e_shentsize );
}
bool
load( std::istream& stream )
{
stream.seekg( 0 );
stream.read( reinterpret_cast<char*>( &header ), sizeof( header ) );
return (stream.gcount() == sizeof( header ) );
}
bool
save( std::ostream& stream ) const
{
stream.seekp( 0 );
stream.write( reinterpret_cast<const char*>( &header ), sizeof( header ) );
return stream.good();
}
// ELF header functions
ELFIO_GET_ACCESS( unsigned char, class, header.e_ident[EI_CLASS] );
ELFIO_GET_ACCESS( unsigned char, elf_version, header.e_ident[EI_VERSION] );
ELFIO_GET_ACCESS( unsigned char, encoding, header.e_ident[EI_DATA] );
ELFIO_GET_ACCESS( Elf_Half, header_size, header.e_ehsize );
ELFIO_GET_ACCESS( Elf_Half, section_entry_size, header.e_shentsize );
ELFIO_GET_ACCESS( Elf_Half, segment_entry_size, header.e_phentsize );
ELFIO_GET_SET_ACCESS( Elf_Word, version, header.e_version);
ELFIO_GET_SET_ACCESS( unsigned char, os_abi, header.e_ident[EI_OSABI] );
ELFIO_GET_SET_ACCESS( unsigned char, abi_version, header.e_ident[EI_ABIVERSION] );
ELFIO_GET_SET_ACCESS( Elf_Half, type, header.e_type );
ELFIO_GET_SET_ACCESS( Elf_Half, machine, header.e_machine );
ELFIO_GET_SET_ACCESS( Elf_Word, flags, header.e_flags );
ELFIO_GET_SET_ACCESS( Elf_Half, section_name_str_index, header.e_shstrndx );
ELFIO_GET_SET_ACCESS( Elf64_Addr, entry, header.e_entry );
ELFIO_GET_SET_ACCESS( Elf_Half, sections_num, header.e_shnum );
ELFIO_GET_SET_ACCESS( Elf64_Off, sections_offset, header.e_shoff );
ELFIO_GET_SET_ACCESS( Elf_Half, segments_num, header.e_phnum );
ELFIO_GET_SET_ACCESS( Elf64_Off, segments_offset, header.e_phoff );
private:
T header;
endianess_convertor* convertor;
};
} // namespace ELFIO
#endif // ELF_HEADER_HPP

170
source/elfio/elfio_note.hpp Normal file
View File

@ -0,0 +1,170 @@
/*
Copyright (C) 2001-2015 by Serge Lamikhov-Center
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef ELFIO_NOTE_HPP
#define ELFIO_NOTE_HPP
namespace ELFIO {
//------------------------------------------------------------------------------
// There are discrepancies in documentations. SCO documentation
// (http://www.sco.com/developers/gabi/latest/ch5.pheader.html#note_section)
// requires 8 byte entries alignment for 64-bit ELF file,
// but Oracle's definition uses the same structure
// for 32-bit and 64-bit formats.
// (https://docs.oracle.com/cd/E23824_01/html/819-0690/chapter6-18048.html)
//
// It looks like EM_X86_64 Linux implementation is similar to Oracle's
// definition. Therefore, the same alignment works for both formats
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
template< class S >
class note_section_accessor_template
{
public:
//------------------------------------------------------------------------------
note_section_accessor_template( const elfio& elf_file_, S* section_ ) :
elf_file( elf_file_ ), note_section( section_ )
{
process_section();
}
//------------------------------------------------------------------------------
Elf_Word
get_notes_num() const
{
return (Elf_Word)note_start_positions.size();
}
//------------------------------------------------------------------------------
bool
get_note( Elf_Word index,
Elf_Word& type,
std::string& name,
void*& desc,
Elf_Word& descSize ) const
{
if ( index >= note_section->get_size() ) {
return false;
}
const char* pData = note_section->get_data() + note_start_positions[index];
int align = sizeof( Elf_Word );
const endianess_convertor& convertor = elf_file.get_convertor();
type = convertor( *(const Elf_Word*)( pData + 2*align ) );
Elf_Word namesz = convertor( *(const Elf_Word*)( pData ) );
descSize = convertor( *(const Elf_Word*)( pData + sizeof( namesz ) ) );
Elf_Xword max_name_size = note_section->get_size() - note_start_positions[index];
if ( namesz > max_name_size ||
namesz + descSize > max_name_size ) {
return false;
}
name.assign( pData + 3*align, namesz - 1);
if ( 0 == descSize ) {
desc = 0;
}
else {
desc = const_cast<char*> ( pData + 3*align +
( ( namesz + align - 1 )/align )*align );
}
return true;
}
//------------------------------------------------------------------------------
void add_note( Elf_Word type,
const std::string& name,
const void* desc,
Elf_Word descSize )
{
const endianess_convertor& convertor = elf_file.get_convertor();
int align = sizeof( Elf_Word );
Elf_Word nameLen = (Elf_Word)name.size() + 1;
Elf_Word nameLenConv = convertor( nameLen );
std::string buffer( reinterpret_cast<char*>( &nameLenConv ), align );
Elf_Word descSizeConv = convertor( descSize );
buffer.append( reinterpret_cast<char*>( &descSizeConv ), align );
type = convertor( type );
buffer.append( reinterpret_cast<char*>( &type ), align );
buffer.append( name );
buffer.append( 1, '\x00' );
const char pad[] = { '\0', '\0', '\0', '\0' };
if ( nameLen % align != 0 ) {
buffer.append( pad, align - nameLen % align );
}
if ( desc != 0 && descSize != 0 ) {
buffer.append( reinterpret_cast<const char*>( desc ), descSize );
if ( descSize % align != 0 ) {
buffer.append( pad, align - descSize % align );
}
}
note_start_positions.push_back( note_section->get_size() );
note_section->append_data( buffer );
}
private:
//------------------------------------------------------------------------------
void process_section()
{
const endianess_convertor& convertor = elf_file.get_convertor();
const char* data = note_section->get_data();
Elf_Xword size = note_section->get_size();
Elf_Xword current = 0;
note_start_positions.clear();
// Is it empty?
if ( 0 == data || 0 == size ) {
return;
}
int align = sizeof( Elf_Word );
while ( current + 3*align <= size ) {
note_start_positions.push_back( current );
Elf_Word namesz = convertor(
*(const Elf_Word*)( data + current ) );
Elf_Word descsz = convertor(
*(const Elf_Word*)( data + current + sizeof( namesz ) ) );
current += 3*sizeof( Elf_Word ) +
( ( namesz + align - 1 ) / align ) * align +
( ( descsz + align - 1 ) / align ) * align;
}
}
//------------------------------------------------------------------------------
private:
const elfio& elf_file;
S* note_section;
std::vector<Elf_Xword> note_start_positions;
};
using note_section_accessor = note_section_accessor_template<section>;
using const_note_section_accessor = note_section_accessor_template<const section>;
} // namespace ELFIO
#endif // ELFIO_NOTE_HPP

View File

@ -0,0 +1,333 @@
/*
Copyright (C) 2001-2015 by Serge Lamikhov-Center
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef ELFIO_RELOCATION_HPP
#define ELFIO_RELOCATION_HPP
namespace ELFIO {
template<typename T> struct get_sym_and_type;
template<> struct get_sym_and_type< Elf32_Rel >
{
static int get_r_sym( Elf_Xword info )
{
return ELF32_R_SYM( (Elf_Word)info );
}
static int get_r_type( Elf_Xword info )
{
return ELF32_R_TYPE( (Elf_Word)info );
}
};
template<> struct get_sym_and_type< Elf32_Rela >
{
static int get_r_sym( Elf_Xword info )
{
return ELF32_R_SYM( (Elf_Word)info );
}
static int get_r_type( Elf_Xword info )
{
return ELF32_R_TYPE( (Elf_Word)info );
}
};
template<> struct get_sym_and_type< Elf64_Rel >
{
static int get_r_sym( Elf_Xword info )
{
return ELF64_R_SYM( info );
}
static int get_r_type( Elf_Xword info )
{
return ELF64_R_TYPE( info );
}
};
template<> struct get_sym_and_type< Elf64_Rela >
{
static int get_r_sym( Elf_Xword info )
{
return ELF64_R_SYM( info );
}
static int get_r_type( Elf_Xword info )
{
return ELF64_R_TYPE( info );
}
};
//------------------------------------------------------------------------------
template< class S >
class relocation_section_accessor_template
{
public:
//------------------------------------------------------------------------------
relocation_section_accessor_template( const elfio& elf_file_, S* section_ ) :
elf_file( elf_file_ ),
relocation_section( section_ )
{
}
//------------------------------------------------------------------------------
Elf_Xword
get_entries_num() const
{
Elf_Xword nRet = 0;
if ( 0 != relocation_section->get_entry_size() ) {
nRet = relocation_section->get_size() / relocation_section->get_entry_size();
}
return nRet;
}
//------------------------------------------------------------------------------
bool
get_entry( Elf_Xword index,
Elf64_Addr& offset,
Elf_Word& symbol,
Elf_Word& type,
Elf_Sxword& addend ) const
{
if ( index >= get_entries_num() ) { // Is index valid
return false;
}
if ( elf_file.get_class() == ELFCLASS32 ) {
if ( SHT_REL == relocation_section->get_type() ) {
generic_get_entry_rel< Elf32_Rel >( index, offset, symbol,
type, addend );
}
else if ( SHT_RELA == relocation_section->get_type() ) {
generic_get_entry_rela< Elf32_Rela >( index, offset, symbol,
type, addend );
}
}
else {
if ( SHT_REL == relocation_section->get_type() ) {
generic_get_entry_rel< Elf64_Rel >( index, offset, symbol,
type, addend );
}
else if ( SHT_RELA == relocation_section->get_type() ) {
generic_get_entry_rela< Elf64_Rela >( index, offset, symbol,
type, addend );
}
}
return true;
}
//------------------------------------------------------------------------------
bool
get_entry( Elf_Xword index,
Elf64_Addr& offset,
Elf64_Addr& symbolValue,
std::string& symbolName,
Elf_Word& type,
Elf_Sxword& addend,
Elf_Half& section) const
{
// Do regular job
Elf_Word symbol;
bool ret = get_entry( index, offset, symbol, type, addend );
// Find the symbol
Elf_Xword size;
unsigned char bind;
unsigned char symbolType;
unsigned char other;
symbol_section_accessor symbols( elf_file, elf_file.sections[get_symbol_table_index()] );
ret = ret && symbols.get_symbol( symbol, symbolName, symbolValue,
size, bind, symbolType, section, other );
return ret;
}
//------------------------------------------------------------------------------
void
add_entry( Elf64_Addr offset, Elf_Xword info )
{
if ( elf_file.get_class() == ELFCLASS32 ) {
generic_add_entry< Elf32_Rel >( offset, info );
}
else {
generic_add_entry< Elf64_Rel >( offset, info );
}
}
//------------------------------------------------------------------------------
void
add_entry( Elf64_Addr offset, Elf_Word symbol, unsigned char type )
{
Elf_Xword info;
if ( elf_file.get_class() == ELFCLASS32 ) {
info = ELF32_R_INFO( (Elf_Xword)symbol, type );
}
else {
info = ELF64_R_INFO((Elf_Xword)symbol, type );
}
add_entry( offset, info );
}
//------------------------------------------------------------------------------
void
add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend )
{
if ( elf_file.get_class() == ELFCLASS32 ) {
generic_add_entry< Elf32_Rela >( offset, info, addend );
}
else {
generic_add_entry< Elf64_Rela >( offset, info, addend );
}
}
//------------------------------------------------------------------------------
void
add_entry( Elf64_Addr offset, Elf_Word symbol, unsigned char type,
Elf_Sxword addend )
{
Elf_Xword info;
if ( elf_file.get_class() == ELFCLASS32 ) {
info = ELF32_R_INFO( (Elf_Xword)symbol, type );
}
else {
info = ELF64_R_INFO( (Elf_Xword)symbol, type );
}
add_entry( offset, info, addend );
}
//------------------------------------------------------------------------------
void
add_entry( string_section_accessor str_writer,
const char* str,
symbol_section_accessor sym_writer,
Elf64_Addr value,
Elf_Word size,
unsigned char sym_info,
unsigned char other,
Elf_Half shndx,
Elf64_Addr offset,
unsigned char type )
{
Elf_Word str_index = str_writer.add_string( str );
Elf_Word sym_index = sym_writer.add_symbol( str_index, value, size,
sym_info, other, shndx );
add_entry( offset, sym_index, type );
}
//------------------------------------------------------------------------------
private:
//------------------------------------------------------------------------------
Elf_Half
get_symbol_table_index() const
{
return (Elf_Half)relocation_section->get_link();
}
//------------------------------------------------------------------------------
template< class T >
void
generic_get_entry_rel( Elf_Xword index,
Elf64_Addr& offset,
Elf_Word& symbol,
Elf_Word& type,
Elf_Sxword& addend ) const
{
const endianess_convertor& convertor = elf_file.get_convertor();
const T* pEntry = reinterpret_cast<const T*>(
relocation_section->get_data() +
index * relocation_section->get_entry_size() );
offset = convertor( pEntry->r_offset );
Elf_Xword tmp = convertor( pEntry->r_info );
symbol = get_sym_and_type<T>::get_r_sym( tmp );
type = get_sym_and_type<T>::get_r_type( tmp );
addend = 0;
}
//------------------------------------------------------------------------------
template< class T >
void
generic_get_entry_rela( Elf_Xword index,
Elf64_Addr& offset,
Elf_Word& symbol,
Elf_Word& type,
Elf_Sxword& addend ) const
{
const endianess_convertor& convertor = elf_file.get_convertor();
const T* pEntry = reinterpret_cast<const T*>(
relocation_section->get_data() +
index * relocation_section->get_entry_size() );
offset = convertor( pEntry->r_offset );
Elf_Xword tmp = convertor( pEntry->r_info );
symbol = get_sym_and_type<T>::get_r_sym( tmp );
type = get_sym_and_type<T>::get_r_type( tmp );
addend = convertor( pEntry->r_addend );
}
//------------------------------------------------------------------------------
template< class T >
void
generic_add_entry( Elf64_Addr offset, Elf_Xword info )
{
const endianess_convertor& convertor = elf_file.get_convertor();
T entry;
entry.r_offset = offset;
entry.r_info = info;
entry.r_offset = convertor( entry.r_offset );
entry.r_info = convertor( entry.r_info );
relocation_section->append_data( reinterpret_cast<char*>( &entry ), sizeof( entry ) );
}
//------------------------------------------------------------------------------
template< class T >
void
generic_add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend )
{
const endianess_convertor& convertor = elf_file.get_convertor();
T entry;
entry.r_offset = offset;
entry.r_info = info;
entry.r_addend = addend;
entry.r_offset = convertor( entry.r_offset );
entry.r_info = convertor( entry.r_info );
entry.r_addend = convertor( entry.r_addend );
relocation_section->append_data( reinterpret_cast<char*>( &entry ), sizeof( entry ) );
}
//------------------------------------------------------------------------------
private:
const elfio& elf_file;
S* relocation_section;
};
using relocation_section_accessor = relocation_section_accessor_template<section>;
using const_relocation_section_accessor = relocation_section_accessor_template<const section>;
} // namespace ELFIO
#endif // ELFIO_RELOCATION_HPP

View File

@ -0,0 +1,360 @@
/*
Copyright (C) 2001-2015 by Serge Lamikhov-Center
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef ELFIO_SECTION_HPP
#define ELFIO_SECTION_HPP
#include <string>
#include <iostream>
#include "utils/logger.h"
#include <zlib.h>
namespace ELFIO {
class section
{
friend class elfio;
public:
virtual ~section() {};
ELFIO_GET_ACCESS_DECL ( Elf_Half, index );
ELFIO_GET_SET_ACCESS_DECL( std::string, name );
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type );
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, flags );
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, info );
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, link );
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, addr_align );
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, entry_size );
ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, address );
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, size );
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, name_string_offset );
ELFIO_GET_ACCESS_DECL ( Elf64_Off, offset );
size_t stream_size;
size_t get_stream_size() const
{
return stream_size;
}
void set_stream_size(size_t value)
{
stream_size = value;
}
virtual const char* get_data() const = 0;
virtual void set_data( const char* pData, Elf_Word size ) = 0;
virtual void set_data( const std::string& data ) = 0;
virtual void append_data( const char* pData, Elf_Word size ) = 0;
virtual void append_data( const std::string& data ) = 0;
protected:
ELFIO_SET_ACCESS_DECL( Elf64_Off, offset );
ELFIO_SET_ACCESS_DECL( Elf_Half, index );
virtual void load( std::istream& stream,
std::streampos header_offset ) = 0;
virtual void save( std::ostream& stream,
std::streampos header_offset,
std::streampos data_offset ) = 0;
virtual bool is_address_initialized() const = 0;
};
template< class T >
class section_impl : public section
{
public:
//------------------------------------------------------------------------------
section_impl( const endianess_convertor* convertor_ ) : convertor( convertor_ )
{
std::fill_n( reinterpret_cast<char*>( &header ), sizeof( header ), '\0' );
is_address_set = false;
data = 0;
data_size = 0;
}
//------------------------------------------------------------------------------
~section_impl()
{
delete [] data;
}
//------------------------------------------------------------------------------
// Section info functions
ELFIO_GET_SET_ACCESS( Elf_Word, type, header.sh_type );
ELFIO_GET_SET_ACCESS( Elf_Xword, flags, header.sh_flags );
ELFIO_GET_SET_ACCESS( Elf_Xword, size, header.sh_size );
ELFIO_GET_SET_ACCESS( Elf_Word, link, header.sh_link );
ELFIO_GET_SET_ACCESS( Elf_Word, info, header.sh_info );
ELFIO_GET_SET_ACCESS( Elf_Xword, addr_align, header.sh_addralign );
ELFIO_GET_SET_ACCESS( Elf_Xword, entry_size, header.sh_entsize );
ELFIO_GET_SET_ACCESS( Elf_Word, name_string_offset, header.sh_name );
ELFIO_GET_ACCESS ( Elf64_Addr, address, header.sh_addr );
//------------------------------------------------------------------------------
Elf_Half
get_index() const
{
return index;
}
//------------------------------------------------------------------------------
std::string
get_name() const
{
return name;
}
//------------------------------------------------------------------------------
void
set_name( std::string name_ )
{
name = name_;
}
//------------------------------------------------------------------------------
void
set_address( Elf64_Addr value )
{
header.sh_addr = value;
header.sh_addr = (*convertor)( header.sh_addr );
is_address_set = true;
}
//------------------------------------------------------------------------------
bool
is_address_initialized() const
{
return is_address_set;
}
//------------------------------------------------------------------------------
const char*
get_data() const
{
return data;
}
//------------------------------------------------------------------------------
void
set_data( const char* raw_data, Elf_Word size )
{
if ( get_type() != SHT_NOBITS ) {
delete [] data;
try {
data = new char[size];
} catch (const std::bad_alloc&) {
data = 0;
data_size = 0;
size = 0;
}
if ( 0 != data && 0 != raw_data ) {
data_size = size;
std::copy( raw_data, raw_data + size, data );
}
}
set_size( size );
}
//------------------------------------------------------------------------------
void
set_data( const std::string& str_data )
{
return set_data( str_data.c_str(), (Elf_Word)str_data.size() );
}
//------------------------------------------------------------------------------
void
append_data( const char* raw_data, Elf_Word size )
{
if ( get_type() != SHT_NOBITS ) {
if ( get_size() + size < data_size ) {
std::copy( raw_data, raw_data + size, data + get_size() );
}
else {
data_size = 2*( data_size + size);
char* new_data;
try {
new_data = new char[data_size];
} catch (const std::bad_alloc&) {
new_data = 0;
size = 0;
}
if ( 0 != new_data ) {
std::copy( data, data + get_size(), new_data );
std::copy( raw_data, raw_data + size, new_data + get_size() );
delete [] data;
data = new_data;
}
}
set_size( get_size() + size );
}
}
//------------------------------------------------------------------------------
void
append_data( const std::string& str_data )
{
return append_data( str_data.c_str(), (Elf_Word)str_data.size() );
}
//------------------------------------------------------------------------------
protected:
//------------------------------------------------------------------------------
ELFIO_GET_SET_ACCESS( Elf64_Off, offset, header.sh_offset );
//------------------------------------------------------------------------------
void
set_index( Elf_Half value )
{
index = value;
}
//------------------------------------------------------------------------------
void
load( std::istream& stream,
std::streampos header_offset )
{
std::fill_n( reinterpret_cast<char*>( &header ), sizeof( header ), '\0' );
stream.seekg ( 0, stream.end );
set_stream_size ( stream.tellg() );
stream.seekg( header_offset );
stream.read( reinterpret_cast<char*>( &header ), sizeof( header ) );
Elf_Xword size = get_size();
if ( 0 == data && SHT_NULL != get_type() && SHT_NOBITS != get_type() && size < get_stream_size()) {
try {
data = new char[size + 1];
} catch (const std::bad_alloc&) {
data = 0;
data_size = 0;
}
if ( ( 0 != size ) && ( 0 != data ) ) {
stream.seekg( (*convertor)( header.sh_offset ) );
if (get_flags() & 0x08000000){
uint32_t uncompressed_size = size;
stream.read( (char *) &uncompressed_size, 4);
stream.read( data, size - 4);
char* uncompressedData = new char[uncompressed_size + 1];
int ret = 0;
z_stream s;
memset(&s, 0, sizeof(s));
s.zalloc = Z_NULL;
s.zfree = Z_NULL;
s.opaque = Z_NULL;
ret = inflateInit_(&s, ZLIB_VERSION, sizeof(s));
if (ret != Z_OK)
return;
s.avail_in = size - 4;
s.next_in = (Bytef *)data;
s.avail_out = uncompressed_size;
s.next_out = (Bytef *)&uncompressedData[0];
ret = inflate(&s, Z_FINISH);
if (ret != Z_OK && ret != Z_STREAM_END){
DEBUG_FUNCTION_LINE("NOOOO\n");
}
inflateEnd(&s);
free(data);
data = uncompressedData;
data_size = uncompressed_size;
set_size(uncompressed_size);
data[data_size] = 0; // Ensure data is ended with 0 to avoid oob read
}else{
stream.read( data, size );
data[size] = 0; // Ensure data is ended with 0 to avoid oob read
data_size = size;
}
}else{
set_size(0);
DEBUG_FUNCTION_LINE("Failed to allocate memory.\n");
}
}
}
//------------------------------------------------------------------------------
void
save( std::ostream& stream,
std::streampos header_offset,
std::streampos data_offset )
{
if ( 0 != get_index() ) {
header.sh_offset = data_offset;
header.sh_offset = (*convertor)( header.sh_offset );
}
save_header( stream, header_offset );
if ( get_type() != SHT_NOBITS && get_type() != SHT_NULL &&
get_size() != 0 && data != 0 ) {
save_data( stream, data_offset );
}
}
//------------------------------------------------------------------------------
private:
//------------------------------------------------------------------------------
void
save_header( std::ostream& stream,
std::streampos header_offset ) const
{
stream.seekp( header_offset );
stream.write( reinterpret_cast<const char*>( &header ), sizeof( header ) );
}
//------------------------------------------------------------------------------
void
save_data( std::ostream& stream,
std::streampos data_offset ) const
{
stream.seekp( data_offset );
stream.write( get_data(), get_size() );
}
//------------------------------------------------------------------------------
private:
T header;
Elf_Half index;
std::string name;
char* data;
Elf_Word data_size;
const endianess_convertor* convertor;
bool is_address_set;
};
} // namespace ELFIO
#endif // ELFIO_SECTION_HPP

View File

@ -0,0 +1,246 @@
/*
Copyright (C) 2001-2015 by Serge Lamikhov-Center
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef ELFIO_SEGMENT_HPP
#define ELFIO_SEGMENT_HPP
#include <iostream>
#include <vector>
namespace ELFIO {
class segment
{
friend class elfio;
public:
virtual ~segment() {};
ELFIO_GET_ACCESS_DECL ( Elf_Half, index );
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type );
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, flags );
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, align );
ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, virtual_address );
ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, physical_address );
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, file_size );
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, memory_size );
ELFIO_GET_ACCESS_DECL( Elf64_Off, offset );
virtual const char* get_data() const = 0;
virtual Elf_Half add_section_index( Elf_Half index, Elf_Xword addr_align ) = 0;
virtual Elf_Half get_sections_num() const = 0;
virtual Elf_Half get_section_index_at( Elf_Half num ) const = 0;
virtual bool is_offset_initialized() const = 0;
protected:
ELFIO_SET_ACCESS_DECL( Elf64_Off, offset );
ELFIO_SET_ACCESS_DECL( Elf_Half, index );
virtual const std::vector<Elf_Half>& get_sections() const = 0;
virtual void load( std::istream& stream, std::streampos header_offset ) = 0;
virtual void save( std::ostream& stream, std::streampos header_offset,
std::streampos data_offset ) = 0;
};
//------------------------------------------------------------------------------
template< class T >
class segment_impl : public segment
{
public:
//------------------------------------------------------------------------------
segment_impl( endianess_convertor* convertor_ ) :
stream_size( 0 ), index( 0 ), data( 0 ), convertor( convertor_ )
{
is_offset_set = false;
std::fill_n( reinterpret_cast<char*>( &ph ), sizeof( ph ), '\0' );
}
//------------------------------------------------------------------------------
virtual ~segment_impl()
{
delete [] data;
}
//------------------------------------------------------------------------------
// Section info functions
ELFIO_GET_SET_ACCESS( Elf_Word, type, ph.p_type );
ELFIO_GET_SET_ACCESS( Elf_Word, flags, ph.p_flags );
ELFIO_GET_SET_ACCESS( Elf_Xword, align, ph.p_align );
ELFIO_GET_SET_ACCESS( Elf64_Addr, virtual_address, ph.p_vaddr );
ELFIO_GET_SET_ACCESS( Elf64_Addr, physical_address, ph.p_paddr );
ELFIO_GET_SET_ACCESS( Elf_Xword, file_size, ph.p_filesz );
ELFIO_GET_SET_ACCESS( Elf_Xword, memory_size, ph.p_memsz );
ELFIO_GET_ACCESS( Elf64_Off, offset, ph.p_offset );
size_t stream_size;
//------------------------------------------------------------------------------
size_t
get_stream_size() const
{
return stream_size;
}
//------------------------------------------------------------------------------
void
set_stream_size(size_t value)
{
stream_size = value;
}
//------------------------------------------------------------------------------
Elf_Half
get_index() const
{
return index;
}
//------------------------------------------------------------------------------
const char*
get_data() const
{
return data;
}
//------------------------------------------------------------------------------
Elf_Half
add_section_index( Elf_Half sec_index, Elf_Xword addr_align )
{
sections.push_back( sec_index );
if ( addr_align > get_align() ) {
set_align( addr_align );
}
return (Elf_Half)sections.size();
}
//------------------------------------------------------------------------------
Elf_Half
get_sections_num() const
{
return (Elf_Half)sections.size();
}
//------------------------------------------------------------------------------
Elf_Half
get_section_index_at( Elf_Half num ) const
{
if ( num < sections.size() ) {
return sections[num];
}
return Elf_Half(-1);
}
//------------------------------------------------------------------------------
protected:
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
set_offset( Elf64_Off value )
{
ph.p_offset = value;
ph.p_offset = (*convertor)( ph.p_offset );
is_offset_set = true;
}
//------------------------------------------------------------------------------
bool
is_offset_initialized() const
{
return is_offset_set;
}
//------------------------------------------------------------------------------
const std::vector<Elf_Half>&
get_sections() const
{
return sections;
}
//------------------------------------------------------------------------------
void
set_index( Elf_Half value )
{
index = value;
}
//------------------------------------------------------------------------------
void
load( std::istream& stream,
std::streampos header_offset )
{
stream.seekg ( 0, stream.end );
set_stream_size ( stream.tellg() );
stream.seekg( header_offset );
stream.read( reinterpret_cast<char*>( &ph ), sizeof( ph ) );
is_offset_set = true;
if ( PT_NULL != get_type() && 0 != get_file_size() ) {
stream.seekg( (*convertor)( ph.p_offset ) );
Elf_Xword size = get_file_size();
if ( size > get_stream_size() ) {
data = 0;
}
else {
try {
data = new char[size + 1];
} catch (const std::bad_alloc&) {
data = 0;
}
if ( 0 != data ) {
stream.read( data, size );
data[size] = 0;
}
}
}
}
//------------------------------------------------------------------------------
void save( std::ostream& stream,
std::streampos header_offset,
std::streampos data_offset )
{
ph.p_offset = data_offset;
ph.p_offset = (*convertor)(ph.p_offset);
stream.seekp( header_offset );
stream.write( reinterpret_cast<const char*>( &ph ), sizeof( ph ) );
}
//------------------------------------------------------------------------------
private:
T ph;
Elf_Half index;
char* data;
std::vector<Elf_Half> sections;
endianess_convertor* convertor;
bool is_offset_set;
};
} // namespace ELFIO
#endif // ELFIO_SEGMENT_HPP

View File

@ -0,0 +1,100 @@
/*
Copyright (C) 2001-2015 by Serge Lamikhov-Center
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef ELFIO_STRINGS_HPP
#define ELFIO_STRINGS_HPP
#include <cstdlib>
#include <cstring>
#include <string>
namespace ELFIO {
//------------------------------------------------------------------------------
template< class S >
class string_section_accessor_template
{
public:
//------------------------------------------------------------------------------
string_section_accessor_template( S* section_ ) :
string_section( section_ )
{
}
//------------------------------------------------------------------------------
const char*
get_string( Elf_Word index ) const
{
if ( string_section ) {
if ( index < string_section->get_size() ) {
const char* data = string_section->get_data();
if ( 0 != data ) {
return data + index;
}
}
}
return 0;
}
//------------------------------------------------------------------------------
Elf_Word
add_string( const char* str )
{
Elf_Word current_position = 0;
if (string_section) {
// Strings are addeded to the end of the current section data
current_position = (Elf_Word)string_section->get_size();
if ( current_position == 0 ) {
char empty_string = '\0';
string_section->append_data( &empty_string, 1 );
current_position++;
}
string_section->append_data( str, (Elf_Word)std::strlen( str ) + 1 );
}
return current_position;
}
//------------------------------------------------------------------------------
Elf_Word
add_string( const std::string& str )
{
return add_string( str.c_str() );
}
//------------------------------------------------------------------------------
private:
S* string_section;
};
using string_section_accessor = string_section_accessor_template<section>;
using const_string_section_accessor = string_section_accessor_template<const section>;
} // namespace ELFIO
#endif // ELFIO_STRINGS_HPP

View File

@ -0,0 +1,282 @@
/*
Copyright (C) 2001-2015 by Serge Lamikhov-Center
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef ELFIO_SYMBOLS_HPP
#define ELFIO_SYMBOLS_HPP
namespace ELFIO {
//------------------------------------------------------------------------------
template< class S >
class symbol_section_accessor_template
{
public:
//------------------------------------------------------------------------------
symbol_section_accessor_template( const elfio& elf_file_, S* symbol_section_ ) :
elf_file( elf_file_ ),
symbol_section( symbol_section_ )
{
find_hash_section();
}
//------------------------------------------------------------------------------
Elf_Xword
get_symbols_num() const
{
Elf_Xword nRet = 0;
if ( 0 != symbol_section->get_entry_size() ) {
nRet = symbol_section->get_size() / symbol_section->get_entry_size();
}
return nRet;
}
//------------------------------------------------------------------------------
bool
get_symbol( Elf_Xword index,
std::string& name,
Elf64_Addr& value,
Elf_Xword& size,
unsigned char& bind,
unsigned char& type,
Elf_Half& section_index,
unsigned char& other ) const
{
bool ret = false;
if ( elf_file.get_class() == ELFCLASS32 ) {
ret = generic_get_symbol<Elf32_Sym>( index, name, value, size, bind,
type, section_index, other );
}
else {
ret = generic_get_symbol<Elf64_Sym>( index, name, value, size, bind,
type, section_index, other );
}
return ret;
}
//------------------------------------------------------------------------------
bool
get_symbol( const std::string& name,
Elf64_Addr& value,
Elf_Xword& size,
unsigned char& bind,
unsigned char& type,
Elf_Half& section_index,
unsigned char& other ) const
{
bool ret = false;
if ( 0 != get_hash_table_index() ) {
Elf_Word nbucket = *(const Elf_Word*)hash_section->get_data();
Elf_Word nchain = *(const Elf_Word*)( hash_section->get_data() +
sizeof( Elf_Word ) );
Elf_Word val = elf_hash( (const unsigned char*)name.c_str() );
Elf_Word y = *(const Elf_Word*)( hash_section->get_data() +
( 2 + val % nbucket ) * sizeof( Elf_Word ) );
std::string str;
get_symbol( y, str, value, size, bind, type, section_index, other );
while ( str != name && STN_UNDEF != y && y < nchain ) {
y = *(const Elf_Word*)( hash_section->get_data() +
( 2 + nbucket + y ) * sizeof( Elf_Word ) );
get_symbol( y, str, value, size, bind, type, section_index, other );
}
if ( str == name ) {
ret = true;
}
}
return ret;
}
//------------------------------------------------------------------------------
Elf_Word
add_symbol( Elf_Word name, Elf64_Addr value, Elf_Xword size,
unsigned char info, unsigned char other,
Elf_Half shndx )
{
Elf_Word nRet;
if ( symbol_section->get_size() == 0 ) {
if ( elf_file.get_class() == ELFCLASS32 ) {
nRet = generic_add_symbol<Elf32_Sym>( 0, 0, 0, 0, 0, 0 );
}
else {
nRet = generic_add_symbol<Elf64_Sym>( 0, 0, 0, 0, 0, 0 );
}
}
if ( elf_file.get_class() == ELFCLASS32 ) {
nRet = generic_add_symbol<Elf32_Sym>( name, value, size, info, other,
shndx );
}
else {
nRet = generic_add_symbol<Elf64_Sym>( name, value, size, info, other,
shndx );
}
return nRet;
}
//------------------------------------------------------------------------------
Elf_Word
add_symbol( Elf_Word name, Elf64_Addr value, Elf_Xword size,
unsigned char bind, unsigned char type, unsigned char other,
Elf_Half shndx )
{
return add_symbol( name, value, size, ELF_ST_INFO( bind, type ), other, shndx );
}
//------------------------------------------------------------------------------
Elf_Word
add_symbol( string_section_accessor& pStrWriter, const char* str,
Elf64_Addr value, Elf_Xword size,
unsigned char info, unsigned char other,
Elf_Half shndx )
{
Elf_Word index = pStrWriter.add_string( str );
return add_symbol( index, value, size, info, other, shndx );
}
//------------------------------------------------------------------------------
Elf_Word
add_symbol( string_section_accessor& pStrWriter, const char* str,
Elf64_Addr value, Elf_Xword size,
unsigned char bind, unsigned char type, unsigned char other,
Elf_Half shndx )
{
return add_symbol( pStrWriter, str, value, size, ELF_ST_INFO( bind, type ), other, shndx );
}
//------------------------------------------------------------------------------
private:
//------------------------------------------------------------------------------
void
find_hash_section()
{
hash_section = 0;
hash_section_index = 0;
Elf_Half nSecNo = elf_file.sections.size();
for ( Elf_Half i = 0; i < nSecNo && 0 == hash_section_index; ++i ) {
const section* sec = elf_file.sections[i];
if ( sec->get_link() == symbol_section->get_index() ) {
hash_section = sec;
hash_section_index = i;
}
}
}
//------------------------------------------------------------------------------
Elf_Half
get_string_table_index() const
{
return (Elf_Half)symbol_section->get_link();
}
//------------------------------------------------------------------------------
Elf_Half
get_hash_table_index() const
{
return hash_section_index;
}
//------------------------------------------------------------------------------
template< class T >
bool
generic_get_symbol( Elf_Xword index,
std::string& name, Elf64_Addr& value,
Elf_Xword& size,
unsigned char& bind, unsigned char& type,
Elf_Half& section_index,
unsigned char& other ) const
{
bool ret = false;
if ( index < get_symbols_num() ) {
const T* pSym = reinterpret_cast<const T*>(
symbol_section->get_data() +
index * symbol_section->get_entry_size() );
const endianess_convertor& convertor = elf_file.get_convertor();
section* string_section = elf_file.sections[get_string_table_index()];
string_section_accessor str_reader( string_section );
const char* pStr = str_reader.get_string( convertor( pSym->st_name ) );
if ( 0 != pStr ) {
name = pStr;
}
value = convertor( pSym->st_value );
size = convertor( pSym->st_size );
bind = ELF_ST_BIND( pSym->st_info );
type = ELF_ST_TYPE( pSym->st_info );
section_index = convertor( pSym->st_shndx );
other = pSym->st_other;
ret = true;
}
return ret;
}
//------------------------------------------------------------------------------
template< class T >
Elf_Word
generic_add_symbol( Elf_Word name, Elf64_Addr value, Elf_Xword size,
unsigned char info, unsigned char other,
Elf_Half shndx )
{
const endianess_convertor& convertor = elf_file.get_convertor();
T entry;
entry.st_name = convertor( name );
entry.st_value = value;
entry.st_value = convertor( entry.st_value );
entry.st_size = size;
entry.st_size = convertor( entry.st_size );
entry.st_info = convertor( info );
entry.st_other = convertor( other );
entry.st_shndx = convertor( shndx );
symbol_section->append_data( reinterpret_cast<char*>( &entry ),
sizeof( entry ) );
Elf_Word nRet = symbol_section->get_size() / sizeof( entry ) - 1;
return nRet;
}
//------------------------------------------------------------------------------
private:
const elfio& elf_file;
S* symbol_section;
Elf_Half hash_section_index;
const section* hash_section;
};
using symbol_section_accessor = symbol_section_accessor_template<section>;
using const_symbol_section_accessor = symbol_section_accessor_template<const section>;
} // namespace ELFIO
#endif // ELFIO_SYMBOLS_HPP

View File

@ -0,0 +1,209 @@
/*
Copyright (C) 2001-2015 by Serge Lamikhov-Center
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef ELFIO_UTILS_HPP
#define ELFIO_UTILS_HPP
#define ELFIO_GET_ACCESS( TYPE, NAME, FIELD ) \
TYPE get_##NAME() const \
{ \
return (*convertor)( FIELD ); \
}
#define ELFIO_SET_ACCESS( TYPE, NAME, FIELD ) \
void set_##NAME( TYPE value ) \
{ \
FIELD = value; \
FIELD = (*convertor)( FIELD ); \
}
#define ELFIO_GET_SET_ACCESS( TYPE, NAME, FIELD ) \
TYPE get_##NAME() const \
{ \
return (*convertor)( FIELD ); \
} \
void set_##NAME( TYPE value ) \
{ \
FIELD = value; \
FIELD = (*convertor)( FIELD ); \
}
#define ELFIO_GET_ACCESS_DECL( TYPE, NAME ) \
virtual TYPE get_##NAME() const = 0
#define ELFIO_SET_ACCESS_DECL( TYPE, NAME ) \
virtual void set_##NAME( TYPE value ) = 0
#define ELFIO_GET_SET_ACCESS_DECL( TYPE, NAME ) \
virtual TYPE get_##NAME() const = 0; \
virtual void set_##NAME( TYPE value ) = 0
namespace ELFIO {
//------------------------------------------------------------------------------
class endianess_convertor {
public:
//------------------------------------------------------------------------------
endianess_convertor()
{
need_conversion = false;
}
//------------------------------------------------------------------------------
void
setup( unsigned char elf_file_encoding )
{
need_conversion = ( elf_file_encoding != get_host_encoding() );
}
//------------------------------------------------------------------------------
uint64_t
operator()( uint64_t value ) const
{
if ( !need_conversion ) {
return value;
}
value =
( ( value & 0x00000000000000FFull ) << 56 ) |
( ( value & 0x000000000000FF00ull ) << 40 ) |
( ( value & 0x0000000000FF0000ull ) << 24 ) |
( ( value & 0x00000000FF000000ull ) << 8 ) |
( ( value & 0x000000FF00000000ull ) >> 8 ) |
( ( value & 0x0000FF0000000000ull ) >> 24 ) |
( ( value & 0x00FF000000000000ull ) >> 40 ) |
( ( value & 0xFF00000000000000ull ) >> 56 );
return value;
}
//------------------------------------------------------------------------------
int64_t
operator()( int64_t value ) const
{
if ( !need_conversion ) {
return value;
}
return (int64_t)(*this)( (uint64_t)value );
}
//------------------------------------------------------------------------------
uint32_t
operator()( uint32_t value ) const
{
if ( !need_conversion ) {
return value;
}
value =
( ( value & 0x000000FF ) << 24 ) |
( ( value & 0x0000FF00 ) << 8 ) |
( ( value & 0x00FF0000 ) >> 8 ) |
( ( value & 0xFF000000 ) >> 24 );
return value;
}
//------------------------------------------------------------------------------
int32_t
operator()( int32_t value ) const
{
if ( !need_conversion ) {
return value;
}
return (int32_t)(*this)( (uint32_t)value );
}
//------------------------------------------------------------------------------
uint16_t
operator()( uint16_t value ) const
{
if ( !need_conversion ) {
return value;
}
value =
( ( value & 0x00FF ) << 8 ) |
( ( value & 0xFF00 ) >> 8 );
return value;
}
//------------------------------------------------------------------------------
int16_t
operator()( int16_t value ) const
{
if ( !need_conversion ) {
return value;
}
return (int16_t)(*this)( (uint16_t)value );
}
//------------------------------------------------------------------------------
int8_t
operator()( int8_t value ) const
{
return value;
}
//------------------------------------------------------------------------------
uint8_t
operator()( uint8_t value ) const
{
return value;
}
//------------------------------------------------------------------------------
private:
//------------------------------------------------------------------------------
unsigned char
get_host_encoding() const
{
static const int tmp = 1;
if ( 1 == *(const char*)&tmp ) {
return ELFDATA2LSB;
}
else {
return ELFDATA2MSB;
}
}
//------------------------------------------------------------------------------
private:
bool need_conversion;
};
//------------------------------------------------------------------------------
inline
uint32_t
elf_hash( const unsigned char *name )
{
uint32_t h = 0, g;
while ( *name ) {
h = (h << 4) + *name++;
g = h & 0xf0000000;
if ( g != 0 )
h ^= g >> 24;
h &= ~g;
}
return h;
}
} // namespace ELFIO
#endif // ELFIO_UTILS_HPP

103
source/hooks.cpp Normal file
View File

@ -0,0 +1,103 @@
#include "hooks.h"
#include "utils/logger.h"
void CallHook(plugin_information_t * pluginInformation, wups_loader_hook_type_t hook_type) {
CallHookEx(pluginInformation, hook_type,-1);
}
bool HasHookCallHook(plugin_information_t * pluginInformation, wups_loader_hook_type_t hook_type) {
for(int32_t plugin_index=0; plugin_index<pluginInformation->number_used_plugins; plugin_index++) {
plugin_information_single_t * plugin_data = &pluginInformation->plugin_data[plugin_index];
for(uint32_t j=0; j<plugin_data->info.number_used_hooks; j++) {
replacement_data_hook_t * hook_data = &plugin_data->info.hooks[j];
if(hook_data->type == hook_type) {
return true;
}
}
}
return false;
}
static const char** hook_names = (const char *[]){
"WUPS_LOADER_HOOK_INIT_OVERLAY",
"WUPS_LOADER_HOOK_INIT_KERNEL",
"WUPS_LOADER_HOOK_INIT_VID_MEM",
"WUPS_LOADER_HOOK_INIT_WUT_MALLOC",
"WUPS_LOADER_HOOK_FINI_WUT_MALLOC",
"WUPS_LOADER_HOOK_INIT_WUT_DEVOPTAB",
"WUPS_LOADER_HOOK_FINI_WUT_DEVOPTAB",
"WUPS_LOADER_HOOK_INIT_WUT_NEWLIB",
"WUPS_LOADER_HOOK_FINI_WUT_NEWLIB",
"WUPS_LOADER_HOOK_INIT_WUT_STDCPP",
"WUPS_LOADER_HOOK_FINI_WUT_STDCPP",
"WUPS_LOADER_HOOK_INIT_PLUGIN",
"WUPS_LOADER_HOOK_DEINIT_PLUGIN",
"WUPS_LOADER_HOOK_APPLICATION_START",
"WUPS_LOADER_HOOK_FUNCTIONS_PATCHED",
"WUPS_LOADER_HOOK_RELEASE_FOREGROUND",
"WUPS_LOADER_HOOK_ACQUIRED_FOREGROUND",
"WUPS_LOADER_HOOK_APPLICATION_END",
"WUPS_LOADER_HOOK_CONFIRM_RELEASE_FOREGROUND",
"WUPS_LOADER_HOOK_SAVES_DONE_READY_TO_RELEASE",
"WUPS_LOADER_HOOK_VSYNC",
"WUPS_LOADER_HOOK_GET_CONFIG",
"WUPS_LOADER_HOOK_VID_DRC_DRAW",
"WUPS_LOADER_HOOK_VID_TV_DRAW",
"WUPS_LOADER_HOOK_APPLET_START"};
void CallHookEx(plugin_information_t * pluginInformation, wups_loader_hook_type_t hook_type, int32_t plugin_index_needed) {
for(int32_t plugin_index=0; plugin_index<pluginInformation->number_used_plugins; plugin_index++) {
plugin_information_single_t * plugin_data = &pluginInformation->plugin_data[plugin_index];
if(plugin_index_needed != -1 && plugin_index_needed != plugin_index) {
continue;
}
//DEBUG_FUNCTION_LINE("Checking hook functions for %s.\n",plugin_data->plugin_name);
//DEBUG_FUNCTION_LINE("Found hooks: %d\n",plugin_data->number_used_hooks);
for(uint32_t j=0; j<plugin_data->info.number_used_hooks; j++) {
replacement_data_hook_t * hook_data = &plugin_data->info.hooks[j];
if(hook_data->type == hook_type) {
DEBUG_FUNCTION_LINE("Calling hook of type %s for plugin %s",hook_names[hook_data->type],plugin_data->meta.name);
void * func_ptr = hook_data->func_pointer;
if(func_ptr != NULL) {
//DEBUG_FUNCTION_LINE("function pointer is %08x\n",func_ptr);
if(hook_type == WUPS_LOADER_HOOK_INIT_PLUGIN) {
((void (*)(void))((uint32_t*)func_ptr) )();
} else if(hook_type == WUPS_LOADER_HOOK_DEINIT_PLUGIN) {
((void (*)(void))((uint32_t*)func_ptr) )();
} else if(hook_type == WUPS_LOADER_HOOK_APPLICATION_START) {
wups_loader_app_started_args_t args;
((void (*)(wups_loader_app_started_args_t))((uint32_t*)func_ptr) )(args);
} else if(hook_type == WUPS_LOADER_HOOK_FUNCTIONS_PATCHED) {
((void (*)(void))((uint32_t*)func_ptr))();
} else if(hook_type == WUPS_LOADER_HOOK_APPLICATION_END) {
((void (*)(void))((uint32_t*)func_ptr))();
} if(hook_type == WUPS_LOADER_HOOK_INIT_WUT_MALLOC) {
((void (*)(void))((uint32_t*)func_ptr))();
} else if(hook_type == WUPS_LOADER_HOOK_FINI_WUT_MALLOC) {
((void (*)(void))((uint32_t*)func_ptr))();
} else if(hook_type == WUPS_LOADER_HOOK_INIT_WUT_DEVOPTAB) {
((void (*)(void))((uint32_t*)func_ptr))();
} else if(hook_type == WUPS_LOADER_HOOK_FINI_WUT_DEVOPTAB) {
((void (*)(void))((uint32_t*)func_ptr))();
} else if(hook_type == WUPS_LOADER_HOOK_INIT_WUT_NEWLIB) {
((void (*)(void))((uint32_t*)func_ptr))();
} else if(hook_type == WUPS_LOADER_HOOK_FINI_WUT_NEWLIB) {
((void (*)(void))((uint32_t*)func_ptr))();
} else if(hook_type == WUPS_LOADER_HOOK_INIT_WUT_STDCPP) {
((void (*)(void))((uint32_t*)func_ptr))();
} else if(hook_type == WUPS_LOADER_HOOK_FINI_WUT_STDCPP) {
((void (*)(void))((uint32_t*)func_ptr))();
}else{
DEBUG_FUNCTION_LINE("IMPLEMENT ME");
}
} else {
DEBUG_FUNCTION_LINE("Failed to call hook. It was not defined\n");
}
}
}
}
}

7
source/hooks.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
#include <wups.h>
#include "common/plugin_defines.h"
void CallHook(plugin_information_t * pluginInformation, wups_loader_hook_type_t hook_type);
void CallHookEx(plugin_information_t * pluginInformation, wups_loader_hook_type_t hook_type, int32_t plugin_index_needed);
bool HasHookCallHook(plugin_information_t * pluginInformation, wups_loader_hook_type_t hook_type);

View File

@ -29,12 +29,12 @@ KernelCopyData:
.globl SC0x36_KernelReadSRs
SC0x36_KernelReadSRs:
li r0, 0x3600
li %r0, 0x3600
sc
blr
.globl SC0x0A_KernelWriteSRs
SC0x0A_KernelWriteSRs:
li r0, 0x0A00
li %r0, 0x0A00
sc
blr

View File

@ -7,6 +7,13 @@
extern "C" {
#endif
#define KERN_SYSCALL_TBL1 0xFFE84C70 //Unknown
#define KERN_SYSCALL_TBL2 0xFFE85070 //Games
#define KERN_SYSCALL_TBL3 0xFFE85470 //Loader
#define KERN_SYSCALL_TBL4 0xFFEAAA60 //Home menu
#define KERN_SYSCALL_TBL5 0xFFEAAE60 //Browser
typedef struct _sr_table_t {
uint32_t value[16];
uint32_t sdr1;

View File

@ -0,0 +1,91 @@
#include "kernel_utils.h"
#include "kernel_defs.h"
#include <coreinit/cache.h>
extern void SCKernelCopyData(uint32_t dst, uint32_t src, uint32_t len);
void KernelWrite(uint32_t addr, const void *data, uint32_t length) {
uint32_t dst = (uint32_t) OSEffectiveToPhysical(addr);
uint32_t src = (uint32_t) OSEffectiveToPhysical((uint32_t)data);
KernelCopyData(dst, src, length);
DCFlushRange((void *)addr, length);
ICInvalidateRange((void *)addr, length);
}
void KernelWriteU32(uint32_t addr, uint32_t value) {
uint32_t dst = (uint32_t) OSEffectiveToPhysical(addr);
uint32_t src = (uint32_t) OSEffectiveToPhysical((uint32_t)&value);
KernelCopyData(dst, src, 4);
DCFlushRange((void *)addr, 4);
ICInvalidateRange((void *)addr, 4);
}
/* Write a 32-bit word with kernel permissions */
void __attribute__ ((noinline)) kern_write(void * addr, uint32_t value) {
asm volatile (
"li 3,1\n"
"li 4,0\n"
"mr 5,%1\n"
"li 6,0\n"
"li 7,0\n"
"lis 8,1\n"
"mr 9,%0\n"
"mr %1,1\n"
"li 0,0x3500\n"
"sc\n"
"nop\n"
"mr 1,%1\n"
:
: "r"(addr), "r"(value)
: "memory", "ctr", "lr", "0", "3", "4", "5", "6", "7", "8", "9", "10",
"11", "12"
);
}
/* Read a 32-bit word with kernel permissions */
uint32_t __attribute__ ((noinline)) kern_read(const void *addr) {
uint32_t result;
asm volatile (
"li 3,1\n"
"li 4,0\n"
"li 5,0\n"
"li 6,0\n"
"li 7,0\n"
"lis 8,1\n"
"mr 9,%1\n"
"li 0,0x3400\n"
"mr %0,1\n"
"sc\n"
"nop\n"
"mr 1,%0\n"
"mr %0,3\n"
: "=r"(result)
: "b"(addr)
: "memory", "ctr", "lr", "0", "3", "4", "5", "6", "7", "8", "9", "10",
"11", "12"
);
return result;
}
void PatchSyscall(int index, uint32_t addr) {
//DEBUG_FUNCTION_LINE("Patching Syscall 0x%02X\n",index);
kern_write((void *) (KERN_SYSCALL_TBL1 + index * 4), addr);
kern_write((void *) (KERN_SYSCALL_TBL2 + index * 4), addr);
kern_write((void *) (KERN_SYSCALL_TBL3 + index * 4), addr);
kern_write((void *) (KERN_SYSCALL_TBL4 + index * 4), addr);
kern_write((void *) (KERN_SYSCALL_TBL5 + index * 4), addr);
}
void kernelInitialize() {
static uint8_t ucSyscallsSetupRequired = 1;
if(!ucSyscallsSetupRequired)
return;
ucSyscallsSetupRequired = 0;
PatchSyscall(0x25, (uint32_t)SCKernelCopyData);
}

192
source/main.cpp Normal file
View File

@ -0,0 +1,192 @@
#include <wups.h>
#include <whb/log.h>
#include <whb/log_udp.h>
#include <exception>
#include <sysapp/launch.h>
#include <coreinit/memexpheap.h>
#include <coreinit/dynload.h>
#include <coreinit/cache.h>
#include "plugin/PluginDataFactory.h"
#include "plugin/PluginContainerPersistence.h"
#include "plugin/PluginInformationFactory.h"
#include "plugin/PluginMetaInformationFactory.h"
#include "plugin/FunctionData.h"
#include "plugin/PluginContainer.h"
#include "utils/logger.h"
#include "utils/utils.h"
#include "kernel/kernel_utils.h"
#include "patcher/hooks_patcher_static.h"
#include "patcher/hooks_patcher.h"
#include "utils/ElfUtils.h"
#include "common/relocation_defines.h"
#include "common/plugin_defines.h"
#include "common/plugin_defines.h"
#include "common/module_defines.h"
#include "hooks.h"
#include <whb/sdcard.h>
MEMHeapHandle pluginDataHeap __attribute__((section(".data"))) = 0;
plugin_information_t * gPluginInformation __attribute__((section(".data"))) = NULL;
int test();
#define gModuleData ((module_information_t *) (0x00880000))
int main(int argc, char **argv) {
test();
}
bool doRelocation(const std::vector<RelocationData> &relocData, relocation_trampolin_entry_t * tramp_data, uint32_t tramp_length, uint32_t trampolinID) {
std::map<std::string,OSDynLoad_Module> moduleHandleCache;
for (auto const& cur : relocData) {
std::string functionName = cur.getName();
std::string rplName = cur.getImportRPLInformation().getName();
int32_t isData = cur.getImportRPLInformation().isData();
OSDynLoad_Module rplHandle = 0;
if(moduleHandleCache.count(rplName) > 0) {
rplHandle = moduleHandleCache[rplName];
} else {
OSDynLoad_Acquire(rplName.c_str(), &rplHandle);
moduleHandleCache[rplName] = rplHandle;
}
uint32_t functionAddress = 0;
OSDynLoad_FindExport(rplHandle, isData, functionName.c_str(), (void**) &functionAddress);
if(functionAddress == 0) {
DEBUG_FUNCTION_LINE("Failed to find export for %s", functionName.c_str());
return false;
} else {
//DEBUG_FUNCTION_LINE("Found export for %s %s", rplName.c_str(), functionName.c_str());
}
if(!ElfUtils::elfLinkOne(cur.getType(), cur.getOffset(), cur.getAddend(), (uint32_t) cur.getDestination(), functionAddress, tramp_data, tramp_length, RELOC_TYPE_IMPORT,trampolinID)) {
DEBUG_FUNCTION_LINE("Relocation failed\n");
return false;
}
}
DCFlushRange(tramp_data, tramp_length * sizeof(relocation_trampolin_entry_t));
ICInvalidateRange(tramp_data, tramp_length * sizeof(relocation_trampolin_entry_t));
return true;
}
int test() {
WHBLogUdpInit();
log_init();
bool pluginFreshLoaded = false;
if(pluginDataHeap == NULL) {
kernelInitialize();
DEBUG_FUNCTION_LINE("Kernel init done");
DCFlushRange((void*)0x00880000, sizeof(module_information_t));
uint32_t endAddress = 0;
DEBUG_FUNCTION_LINE("Using %d modules",gModuleData->number_used_modules);
for(int i = 0; i < gModuleData->number_used_modules; i++) {
DEBUG_FUNCTION_LINE("%08x",gModuleData->module_data[i].endAddress);
uint32_t curEndAddr = gModuleData->module_data[i].endAddress;
if(curEndAddr > endAddress) {
endAddress = curEndAddr;
}
}
// If this address is 0, make sure the header common match the one
// in the SetupPayload repo. (I know thats a bad idea)
endAddress = (endAddress + 0x100) & 0xFFFFFF00;
DEBUG_FUNCTION_LINE("endAddress: %08X", endAddress);
DEBUG_FUNCTION_LINE("Create heap");
pluginDataHeap = MEMCreateExpHeapEx((void*) (endAddress), 0x00FFF000 - endAddress, 0);
if(pluginDataHeap != NULL) {
if(gPluginInformation == NULL) {
gPluginInformation = (plugin_information_t*) MEMAllocFromExpHeapEx(pluginDataHeap, sizeof(plugin_information_t), 4);
if(gPluginInformation == NULL) {
DEBUG_FUNCTION_LINE("Failed to allocate global plugin information");
return 0;
}
}
DEBUG_FUNCTION_LINE("MEMGetAllocatableSizeForExpHeapEx %d kb", MEMGetAllocatableSizeForExpHeapEx(pluginDataHeap, 4)/1024);
std::vector<PluginData> pluginList = PluginDataFactory::loadDir("fs:/vol/external01/wiiu/plugins/", pluginDataHeap);
std::vector<PluginContainer> plugins;
DEBUG_FUNCTION_LINE("Loaded %d plugin data", pluginList.size());
for(auto & pluginData : pluginList) {
DEBUG_FUNCTION_LINE("Load meta information");
auto metaInfo = PluginMetaInformationFactory::loadPlugin(pluginData);
if(metaInfo) {
PluginContainer container;
container.setMetaInformation(metaInfo.value());
container.setPluginData(pluginData);
plugins.push_back(container);
}
}
uint8_t trampolinID = 0;
for(auto & pluginContainer : plugins) {
std::optional<PluginInformation> data = PluginInformationFactory::load(pluginContainer.getPluginData(), pluginDataHeap, gPluginInformation->trampolines, DYN_LINK_TRAMPOLIN_LIST_LENGTH, trampolinID);
if(!data) {
DEBUG_FUNCTION_LINE("Failed to load Plugin %s", pluginContainer.getMetaInformation().getName().c_str());
break;
}
pluginContainer.setPluginInformation(data.value());
for (const auto& kv : data->getSectionInfoList()) {
DEBUG_FUNCTION_LINE("%s = %s %08X %d", kv.first.c_str(), kv.second.getName().c_str(), kv.second.getAddress(), kv.second.getSize());
}
trampolinID++;
PluginContainerPersistence::savePlugin(gPluginInformation, pluginContainer);
}
pluginFreshLoaded = true;
}
}
if(pluginDataHeap != NULL) {
std::vector<PluginContainer> plugins = PluginContainerPersistence::loadPlugins(gPluginInformation);
for(auto & pluginContainer : plugins) {
DEBUG_FUNCTION_LINE("Doing relocations for plugin: %s", pluginContainer.getMetaInformation().getName().c_str());
if(!doRelocation(pluginContainer.getPluginInformation().getRelocationDataList(), gPluginInformation->trampolines, DYN_LINK_TRAMPOLIN_LIST_LENGTH, pluginContainer.getPluginInformation().getTrampolinId())) {
DEBUG_FUNCTION_LINE("Relocation failed");
}
auto sbssSection = pluginContainer.getPluginInformation().getSectionInfo(".sbss");
if(sbssSection){
DEBUG_FUNCTION_LINE("memset .sbss %08X (%d)", sbssSection->getAddress(), sbssSection->getSize());
memset((void*)sbssSection->getAddress(), 0, sbssSection->getSize());
}
auto bssSection = pluginContainer.getPluginInformation().getSectionInfo(".bss");
if(bssSection) {
DEBUG_FUNCTION_LINE("memset .bss %08X (%d)", bssSection->getAddress(), bssSection->getSize());
memset((void*)bssSection->getAddress(), 0, bssSection->getSize());
}
}
DCFlushRange((void*)0x00800000, 0x00800000);
ICInvalidateRange((void*)0x00800000, 0x00800000);
if(pluginFreshLoaded) {
CallHook(gPluginInformation, WUPS_LOADER_HOOK_INIT_WUT_MALLOC);
CallHook(gPluginInformation, WUPS_LOADER_HOOK_INIT_WUT_NEWLIB);
CallHook(gPluginInformation, WUPS_LOADER_HOOK_INIT_WUT_STDCPP);
CallHook(gPluginInformation, WUPS_LOADER_HOOK_INIT_VID_MEM);
CallHook(gPluginInformation, WUPS_LOADER_HOOK_INIT_KERNEL);
CallHook(gPluginInformation, WUPS_LOADER_HOOK_INIT_OVERLAY);
CallHook(gPluginInformation, WUPS_LOADER_HOOK_INIT_PLUGIN);
pluginFreshLoaded = false;
}
PatchInvidualMethodHooks(method_hooks_hooks_static, method_hooks_size_hooks_static, method_calls_hooks_static);
PatchInvidualMethodHooks(method_hooks_hooks, method_hooks_size_hooks, method_calls_hooks);
for(int32_t plugin_index=0; plugin_index<gPluginInformation->number_used_plugins; plugin_index++) {
CallHookEx(gPluginInformation, WUPS_LOADER_HOOK_INIT_WUT_DEVOPTAB,plugin_index);
CallHookEx(gPluginInformation, WUPS_LOADER_HOOK_APPLICATION_START,plugin_index);
//new_PatchInvidualMethodHooks(&gbl_replacement_data.plugin_data[plugin_index]);
CallHookEx(gPluginInformation, WUPS_LOADER_HOOK_FUNCTIONS_PATCHED,plugin_index);
}
}
return 0;
}

View File

@ -1,80 +1,17 @@
#include "utils/logger.h"
#include "utils/function_patcher.h"
#include "common/retain_vars.h"
#include "hooks_patcher.h"
#include "utils/overlay_helper.h"
#include "utils/ConfigUtils.h"
#include <malloc.h>
#include "utils.h"
#include "memory/memory_mapping.h"
#include "utils/mem_utils.h"
#include "dynamic_libs/vpad_functions.h"
#include "dynamic_libs/coreinit.h"
#include "fs/sd_fat_devoptab.h"
//#include "utils/texture_utils.h"
#include <wups.h>
#include <vpad/input.h>
#include <coreinit/messagequeue.h>
#include <coreinit/core.h>
#include "hooks.h"
DECL_FUNCTION(uint32_t, __OSPhysicalToEffectiveCached, uint32_t phyiscalAddress) {
uint32_t result = real___OSPhysicalToEffectiveCached(phyiscalAddress);
if(result == 0) {
result = MemoryMapping::PhysicalToEffective(phyiscalAddress);
//DEBUG_FUNCTION_LINE("__OSPhysicalToEffectiveCached in %08X out %08X\n",phyiscalAddress,result);
}
return result;
}
DECL_FUNCTION(uint32_t, __OSPhysicalToEffectiveUncached, uint32_t phyiscalAddress) {
uint32_t result = real___OSPhysicalToEffectiveUncached(phyiscalAddress);
if(result == 0) {
result = MemoryMapping::PhysicalToEffective(phyiscalAddress);
//DEBUG_FUNCTION_LINE("__OSPhysicalToEffectiveUncached in %08X out %08X\n",phyiscalAddress,result);
return result;
}
return result;
}
DECL_FUNCTION(uint32_t, OSEffectiveToPhysical, uint32_t virtualAddress) {
uint32_t result = real_OSEffectiveToPhysical(virtualAddress);
if(result == 0) {
result = MemoryMapping::EffectiveToPhysical(virtualAddress);
//DEBUG_FUNCTION_LINE("OSEffectiveToPhysical in %08X out %08X\n",virtualAddress,result);
return result;
}
return result;
}
DECL_FUNCTION(int32_t, OSIsAddressValid, uint32_t virtualAddress) {
int32_t result = real_OSIsAddressValid(virtualAddress);
if(result == 0) {
result = (MemoryMapping::EffectiveToPhysical(virtualAddress) > 0);
//DEBUG_FUNCTION_LINE("OSIsAddressValid in %08X out %d\n",virtualAddress,result);
return result;
}
return result;
}
DECL(void, GX2SetTVBuffer, void *buffer, uint32_t buffer_size, int32_t tv_render_mode, int32_t format, int32_t buffering_mode) {
tv_store.buffer = buffer;
tv_store.buffer_size = buffer_size;
tv_store.mode = tv_render_mode;
tv_store.surface_format = format;
tv_store.buffering_mode = buffering_mode;
return real_GX2SetTVBuffer(buffer,buffer_size,tv_render_mode,format,buffering_mode);
}
DECL(void, GX2SetDRCBuffer, void *buffer, uint32_t buffer_size, int32_t drc_mode, int32_t surface_format, int32_t buffering_mode) {
drc_store.buffer = buffer;
drc_store.buffer_size = buffer_size;
drc_store.mode = drc_mode;
drc_store.surface_format = surface_format;
drc_store.buffering_mode = buffering_mode;
return real_GX2SetDRCBuffer(buffer,buffer_size,drc_mode,surface_format,buffering_mode);
}
extern plugin_information_t * gPluginInformation;
DECL(void, GX2WaitForVsync, void) {
CallHook(WUPS_LOADER_HOOK_VSYNC);
CallHook(gPluginInformation, WUPS_LOADER_HOOK_VSYNC);
real_GX2WaitForVsync();
}
@ -85,7 +22,7 @@ float angleX_delta = 0.0f;
float angleX_last = 0.0f;
uint8_t angleX_frameCounter = 0;
void checkMagic(VPADData *buffer) {
void checkMagic(VPADStatus *buffer) {
// buffer->angle stores the rotations per axis since the app started.
// Each full rotation add/subtracts 1.0f (depending on the direction).
@ -103,7 +40,7 @@ void checkMagic(VPADData *buffer) {
angleX_counter++;
// When the gamepad rotated ~0.16% for 6 times in a row we made a full rotation!
if(angleX_counter > 5) {
ConfigUtils::openConfigMenu();
//ConfigUtils::openConfigMenu();
// reset stuff.
angleX_counter = 0;
angleX_delta = 0.0f;
@ -120,20 +57,20 @@ void checkMagic(VPADData *buffer) {
}
}
DECL(int32_t, VPADRead, int32_t chan, VPADData *buffer, uint32_t buffer_size, int32_t *error) {
DECL(int32_t, VPADRead, int32_t chan, VPADStatus *buffer, uint32_t buffer_size, int32_t *error) {
int32_t result = real_VPADRead(chan, buffer, buffer_size, error);
if(result > 0 && (buffer[0].btns_h == (VPAD_BUTTON_PLUS | VPAD_BUTTON_R | VPAD_BUTTON_L)) && vpadPressCooldown == 0 && OSIsHomeButtonMenuEnabled()) {
if(MemoryMapping::isMemoryMapped()) {
MemoryMapping::readTestValuesFromMemory();
} else {
DEBUG_FUNCTION_LINE("Memory was not mapped. To test the memory please exit the plugin loader by pressing MINUS\n");
}
if(result > 0 && (buffer[0].hold == (VPAD_BUTTON_PLUS | VPAD_BUTTON_R | VPAD_BUTTON_L)) && vpadPressCooldown == 0 && OSIsHomeButtonMenuEnabled()) {
//if(MemoryMapping::isMemoryMapped()) {
//MemoryMapping::readTestValuesFromMemory();
//} else {
// DEBUG_FUNCTION_LINE("Memory was not mapped. To test the memory please exit the plugin loader by pressing MINUS\n");
//}
vpadPressCooldown = 0x3C;
}
if(result > 0 && (buffer[0].btns_h == (VPAD_BUTTON_L | VPAD_BUTTON_DOWN | VPAD_BUTTON_MINUS)) && vpadPressCooldown == 0 && OSIsHomeButtonMenuEnabled()) {
ConfigUtils::openConfigMenu();
if(result > 0 && (buffer[0].hold == (VPAD_BUTTON_L | VPAD_BUTTON_DOWN | VPAD_BUTTON_MINUS)) && vpadPressCooldown == 0 && OSIsHomeButtonMenuEnabled()) {
//ConfigUtils::openConfigMenu();
vpadPressCooldown = 0x3C;
} else if(result > 0 && OSIsHomeButtonMenuEnabled()) {
checkMagic(buffer);
@ -312,28 +249,28 @@ static uint32_t lastData0 = 0;
DECL(uint32_t, OSReceiveMessage, OSMessageQueue *queue, OSMessage *message, uint32_t flags) {
if(flags == 0x15154848) {
CallHook(WUPS_LOADER_HOOK_ACQUIRED_FOREGROUND);
CallHook(WUPS_LOADER_HOOK_APPLICATION_END);
CallHook(WUPS_LOADER_HOOK_FINI_WUT_DEVOPTAB);
gInBackground = false;
DCFlushRange(&gInBackground,4);
CallHook(gPluginInformation, WUPS_LOADER_HOOK_ACQUIRED_FOREGROUND);
CallHook(gPluginInformation, WUPS_LOADER_HOOK_APPLICATION_END);
CallHook(gPluginInformation, WUPS_LOADER_HOOK_FINI_WUT_DEVOPTAB);
//gInBackground = false;
//DCFlushRange(&gInBackground,4);
return false;
}
int32_t res = real_OSReceiveMessage(queue, message, flags);
if(queue == OSGetSystemMessageQueue()) {
if(message != NULL) {
if(lastData0 != message->data0) {
if(message->data0 == 0xFACEF000) {
CallHook(WUPS_LOADER_HOOK_ACQUIRED_FOREGROUND);
} else if(message->data0 == 0xD1E0D1E0) {
CallHook(WUPS_LOADER_HOOK_APPLICATION_END);
CallHook(WUPS_LOADER_HOOK_FINI_WUT_DEVOPTAB);
gInBackground = false;
DCFlushRange(&gInBackground,4);
unmount_sd_fat("sd");
if(lastData0 != message->args[0]) {
if(message->args[0] == 0xFACEF000) {
CallHook(gPluginInformation, WUPS_LOADER_HOOK_ACQUIRED_FOREGROUND);
} else if(message->args[0] == 0xD1E0D1E0) {
CallHook(gPluginInformation, WUPS_LOADER_HOOK_APPLICATION_END);
CallHook(gPluginInformation, WUPS_LOADER_HOOK_FINI_WUT_DEVOPTAB);
//gInBackground = false;
//DCFlushRange(&gInBackground,4);
//unmount_sd_fat("sd");
}
}
lastData0 = message->data0;
lastData0 = message->args[0];
}
}
return res;
@ -341,22 +278,22 @@ DECL(uint32_t, OSReceiveMessage, OSMessageQueue *queue, OSMessage *message, uint
DECL(void, OSReleaseForeground) {
if(OSGetCoreId() == 1) {
CallHook(WUPS_LOADER_HOOK_RELEASE_FOREGROUND);
CallHook(gPluginInformation, WUPS_LOADER_HOOK_RELEASE_FOREGROUND);
}
real_OSReleaseForeground();
}
hooks_magic_t method_hooks_hooks_static[] __attribute__((section(".data"))) = {
MAKE_MAGIC(GX2SetTVBuffer, LIB_GX2, STATIC_FUNCTION),
MAKE_MAGIC(GX2SetDRCBuffer, LIB_GX2, STATIC_FUNCTION),
MAKE_MAGIC(GX2WaitForVsync, LIB_GX2, STATIC_FUNCTION),
//MAKE_MAGIC(GX2SetTVBuffer, LIB_GX2, STATIC_FUNCTION),
//MAKE_MAGIC(GX2SetDRCBuffer, LIB_GX2, STATIC_FUNCTION),
//MAKE_MAGIC(GX2WaitForVsync, LIB_GX2, STATIC_FUNCTION),
//MAKE_MAGIC(GX2CopyColorBufferToScanBuffer, LIB_GX2, STATIC_FUNCTION),
//MAKE_MAGIC(GX2SetContextState, LIB_GX2, STATIC_FUNCTION),
MAKE_MAGIC(VPADRead, LIB_VPAD, STATIC_FUNCTION),
MAKE_MAGIC(OSIsAddressValid, LIB_CORE_INIT, STATIC_FUNCTION),
MAKE_MAGIC(__OSPhysicalToEffectiveUncached, LIB_CORE_INIT, STATIC_FUNCTION),
MAKE_MAGIC(__OSPhysicalToEffectiveCached, LIB_CORE_INIT, STATIC_FUNCTION),
MAKE_MAGIC(OSEffectiveToPhysical, LIB_CORE_INIT, STATIC_FUNCTION),
//MAKE_MAGIC(OSIsAddressValid, LIB_CORE_INIT, STATIC_FUNCTION),
//MAKE_MAGIC(__OSPhysicalToEffectiveUncached, LIB_CORE_INIT, STATIC_FUNCTION),
//MAKE_MAGIC(__OSPhysicalToEffectiveCached, LIB_CORE_INIT, STATIC_FUNCTION),
//MAKE_MAGIC(OSEffectiveToPhysical, LIB_CORE_INIT, STATIC_FUNCTION),
MAKE_MAGIC(OSReceiveMessage, LIB_CORE_INIT, STATIC_FUNCTION),
MAKE_MAGIC(OSReleaseForeground, LIB_CORE_INIT, STATIC_FUNCTION)
};

View File

@ -0,0 +1,104 @@
#include "DynamicLinkingHelper.h"
#include <stdio.h>
#include <string.h>
#include <vector>
#include <coreinit/dynload.h>
#include "utils/logger.h"
#include "common/plugin_defines.h"
dyn_linking_function_t * DynamicLinkingHelper::getOrAddFunctionEntryByName(dyn_linking_relocation_data_t * data, const char* functionName) {
if(data == NULL) {
return NULL;
}
if(functionName == NULL) {
return NULL;
}
dyn_linking_function_t * result = NULL;
for(int32_t i = 0; i < DYN_LINK_FUNCTION_LIST_LENGTH; i++) {
dyn_linking_function_t * curEntry = &(data->functions[i]);
if(strlen(curEntry->functionName) == 0) {
if(strlen(functionName) > DYN_LINK_FUNCTION_NAME_LENGTH) {
DEBUG_FUNCTION_LINE("Failed to add function name, it's too long.\n");
return NULL;
}
strncpy(curEntry->functionName,functionName,DYN_LINK_FUNCTION_NAME_LENGTH);
result = curEntry;
break;
}
if(strncmp(curEntry->functionName,functionName,DYN_LINK_FUNCTION_NAME_LENGTH) == 0) {
result = curEntry;
break;
}
}
return result;
}
dyn_linking_import_t * DynamicLinkingHelper::getOrAddFunctionImportByName(dyn_linking_relocation_data_t * data, const char* importName) {
return getOrAddImport(data, importName, false);
}
dyn_linking_import_t * DynamicLinkingHelper::getOrAddDataImportByName(dyn_linking_relocation_data_t * data, const char* importName) {
return getOrAddImport(data, importName, true);
}
dyn_linking_import_t * DynamicLinkingHelper::getOrAddImport(dyn_linking_relocation_data_t * data, const char* importName, bool isData) {
if(importName == NULL || data == NULL) {
return NULL;
}
dyn_linking_import_t * result = NULL;
for(int32_t i = 0; i < DYN_LINK_IMPORT_LIST_LENGTH; i++) {
dyn_linking_import_t * curEntry = &(data->imports[i]);
if(strlen(curEntry->importName) == 0) {
if(strlen(importName) > DYN_LINK_IMPORT_NAME_LENGTH) {
DEBUG_FUNCTION_LINE("Failed to add Import, it's too long.\n");
return NULL;
}
strncpy(curEntry->importName,importName,DYN_LINK_IMPORT_NAME_LENGTH);
curEntry->isData = isData;
result = curEntry;
break;
}
if(strncmp(curEntry->importName,importName,DYN_LINK_IMPORT_NAME_LENGTH) == 0 && (curEntry->isData == isData)) {
return curEntry;
}
}
return result;
}
bool DynamicLinkingHelper::addReloationEntry(dyn_linking_relocation_data_t * linking_data, dyn_linking_relocation_entry_t * linking_entries, uint32_t linking_entry_length, const RelocationData& relocationData) {
return addReloationEntry(linking_data, linking_entries, linking_entry_length, relocationData.getType(), relocationData.getOffset(), relocationData.getAddend(), relocationData.getDestination(), relocationData.getName(), relocationData.getImportRPLInformation());
}
bool DynamicLinkingHelper::addReloationEntry(dyn_linking_relocation_data_t * linking_data, dyn_linking_relocation_entry_t * linking_entries, uint32_t linking_entry_length, char type, size_t offset, int32_t addend, const void *destination, const std::string& name, const ImportRPLInformation& rplInfo) {
dyn_linking_import_t * importInfoGbl = DynamicLinkingHelper::getOrAddImport(linking_data, rplInfo.getName().c_str(),rplInfo.isData());
if(importInfoGbl == NULL) {
DEBUG_FUNCTION_LINE("Getting import info failed. Probably maximum of %d rpl files to import reached.\n",DYN_LINK_IMPORT_LIST_LENGTH);
return false;
}
dyn_linking_function_t * functionInfo = DynamicLinkingHelper::getOrAddFunctionEntryByName(linking_data, name.c_str());
if(functionInfo == NULL) {
DEBUG_FUNCTION_LINE("Getting import info failed. Probably maximum of %d function to be relocated reached.\n",DYN_LINK_FUNCTION_LIST_LENGTH);
return false;
}
return addReloationEntry(linking_entries, linking_entry_length, type, offset, addend, destination, functionInfo, importInfoGbl);
}
bool DynamicLinkingHelper::addReloationEntry(dyn_linking_relocation_entry_t * linking_entries, uint32_t linking_entry_length, char type, size_t offset, int32_t addend, const void *destination, dyn_linking_function_t * functionName, dyn_linking_import_t * importInfo) {
for(uint32_t i = 0; i < linking_entry_length; i++) {
dyn_linking_relocation_entry_t * curEntry = &(linking_entries[i]);
if(curEntry->functionEntry != NULL) {
continue;
}
curEntry->type = type;
curEntry->offset = offset;
curEntry->addend = addend;
curEntry->destination = (void*) destination;
curEntry->functionEntry = functionName;
curEntry->importEntry = importInfo;
return true;
}
return false;
}

View File

@ -1,8 +1,5 @@
#ifndef DYNAMICLINKINGHELPER_H
#define DYNAMICLINKINGHELPER_H
#include "common/retain_vars.h"
#include "dynamic_linking_defines.h"
#pragma once
#include "common/dynamic_linking_defines.h"
#include "utils/logger.h"
#include <string>
#include <vector>
@ -10,28 +7,13 @@
class DynamicLinkingHelper {
public:
static DynamicLinkingHelper *getInstance() {
if(!instance) {
instance = new DynamicLinkingHelper();
}
return instance;
}
static void destroyInstance() {
if(instance) {
delete instance;
instance = NULL;
}
}
/**
Gets the function entry for a given function name. If the function name is not present in the list, it will be added.
\param functionName Name of the function
\return Returns a pointer to the entry which contains the functionName. Null on error or if the list full.
**/
dyn_linking_function_t * getOrAddFunctionEntryByName(const char * functionName);
static dyn_linking_function_t * getOrAddFunctionEntryByName(dyn_linking_relocation_data_t * data, const char * functionName);
/**
Gets the function import entry for a given function name. If the import is not present in the list, it will be added.
@ -40,7 +22,7 @@ public:
\param importName Name of the function
\return Returns a pointer to the function import entry which contains the importName. Null on error or if the list full.
**/
dyn_linking_import_t * getOrAddFunctionImportByName(const char * importName);
static dyn_linking_import_t * getOrAddFunctionImportByName(dyn_linking_relocation_data_t * data, const char * importName);
/**
@ -50,7 +32,7 @@ public:
\param importName Name of the data
\return Returns a pointer to the data import entry which contains the importName. Null on error or if the list full.
**/
dyn_linking_import_t * getOrAddDataImportByName(const char * importName);
static dyn_linking_import_t * getOrAddDataImportByName(dyn_linking_relocation_data_t * data, const char * importName);
/**
@ -62,33 +44,17 @@ public:
\return Returns a pointer to the data import entry which contains the importName. Null on error or if the list full.
**/
dyn_linking_import_t * getOrAddImport(const char * importName, bool isData);
static dyn_linking_import_t * getOrAddImport(dyn_linking_relocation_data_t * data, const char * importName, bool isData);
static bool addReloationEntry(dyn_linking_relocation_data_t * linking_data, dyn_linking_relocation_entry_t * linking_entries, uint32_t linking_entry_length, const RelocationData& relocationData);
bool addReloationEntry(RelocationData * relocationData);
static bool addReloationEntry(dyn_linking_relocation_data_t * linking_data, dyn_linking_relocation_entry_t * linking_entries, uint32_t linking_entry_length, char type, size_t offset, int32_t addend, const void *destination, const std::string& name, const ImportRPLInformation& rplInfo);
bool addReloationEntry(char type, size_t offset, int32_t addend, void *destination, std::string name, ImportRPLInformation * rplInfo);
bool addReloationEntry(char type, size_t offset, int32_t addend, void *destination, dyn_linking_function_t * functionName, dyn_linking_import_t * importInfo);
std::vector<dyn_linking_relocation_entry_t *> getAllValidDynamicLinkingRelocations();
bool fillRelocations(std::vector<dyn_linking_relocation_entry_t *> entries );
void clearAll();
protected:
static bool addReloationEntry(dyn_linking_relocation_entry_t * linking_entries, uint32_t linking_entry_length, char type, size_t offset, int32_t addend, const void *destination, dyn_linking_function_t * functionName, dyn_linking_import_t * importInfo);
private:
DynamicLinkingHelper() {
}
~DynamicLinkingHelper() {
}
static DynamicLinkingHelper *instance;
};
#endif // DYNAMICLINKINGHELPER_H

View File

@ -1,5 +1,5 @@
/****************************************************************************
* Copyright (C) 2018 Maschell
* Copyright (C) 2018-2020 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -14,9 +14,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef _FUNCTION_DATA_H_
#define _FUNCTION_DATA_H_
#pragma once
#include <wups.h>
#include <string>
@ -24,39 +22,39 @@
class FunctionData {
public:
FunctionData(void * paddress, void * vaddress, const char * name, wups_loader_library_type_t library, void * target, void * call_addr) {
FunctionData(void * paddress, void * vaddress, const std::string& name, wups_loader_library_type_t library, void * replaceAddr, void * replaceCall) {
this->paddress = paddress;
this->vaddress = vaddress;
this->name = name;
this->library = library;
this->replaceAddr = target;
this->replaceCall = call_addr;
this->replaceAddr = replaceAddr;
this->replaceCall = replaceCall;
}
~FunctionData() {
}
std::string getName() {
const std::string& getName() const{
return this->name;
}
wups_loader_library_type_t getLibrary() {
wups_loader_library_type_t getLibrary() const{
return this->library;
}
void * getPhysicalAddress() {
const void * getPhysicalAddress() const{
return paddress;
}
void * getVirtualAddress() {
const void * getVirtualAddress() const{
return vaddress;
}
void * getReplaceAddress() {
const void * getReplaceAddress() const{
return replaceAddr;
}
void * getReplaceCall() {
const void * getReplaceCall() const{
return replaceCall;
}
@ -69,5 +67,3 @@ private:
void * replaceCall = NULL;
};
#endif

View File

@ -1,5 +1,5 @@
/****************************************************************************
* Copyright (C) 2018 Maschell
* Copyright (C) 2018-2020 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -15,8 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef _HOOK_DATA_H_
#define _HOOK_DATA_H_
#pragma once
#include <wups.h>
#include <string>
@ -33,17 +32,14 @@ public:
}
void * getFunctionPointer() {
void * getFunctionPointer() const{
return function_pointer;
}
wups_loader_hook_type_t getType() {
wups_loader_hook_type_t getType() const{
return this->type;
}
private:
void * function_pointer;
wups_loader_hook_type_t type;
};
#endif

View File

@ -1,5 +1,5 @@
/****************************************************************************
* Copyright (C) 2015 Dimok
* Copyright (C) 2018 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -14,19 +14,32 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef __MEMORY_H_
#define __MEMORY_H_
#ifdef __cplusplus
extern "C" {
#endif
#pragma once
#include <malloc.h>
#include <string>
#include "utils/logger.h"
void initMemory();
class ImportRPLInformation {
#ifdef __cplusplus
}
#endif
public:
ImportRPLInformation(std::string name, bool isData = false) {
this->name = name;
this->_isData = isData;
}
#endif // __MEMORY_H_
~ImportRPLInformation() {
}
std::string getName() const {
return name;
}
bool isData() const{
return _isData;
}
private:
std::string name;
bool _isData = false;
};

View File

@ -0,0 +1,56 @@
/****************************************************************************
* Copyright (C) 2020 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#pragma once
#include "PluginData.h"
#include "PluginMetaInformation.h"
#include "PluginInformation.h"
class PluginContainer {
public:
PluginContainer(){
}
const PluginMetaInformation& getMetaInformation() const{
return this->metaInformation;
}
void setMetaInformation(PluginMetaInformation& metaInfo){
this->metaInformation = metaInfo;
}
const PluginInformation& getPluginInformation() const{
return pluginInformation;
}
void setPluginInformation(PluginInformation& pluginInformation){
this->pluginInformation = pluginInformation;
}
const PluginData& getPluginData() const{
return pluginData;
}
void setPluginData(PluginData& pluginData){
this->pluginData = pluginData;
}
PluginData pluginData;
PluginMetaInformation metaInformation;
PluginInformation pluginInformation;
};

View File

@ -0,0 +1,296 @@
#include <coreinit/cache.h>
#include "PluginContainer.h"
#include "PluginInformationFactory.h"
#include "PluginMetaInformationFactory.h"
#include "PluginContainerPersistence.h"
#include "DynamicLinkingHelper.h"
#include "common/plugin_defines.h"
#include "PluginInformation.h"
#include "RelocationData.h"
bool PluginContainerPersistence::savePlugin(plugin_information_t * pluginInformation, PluginContainer& plugin) {
int32_t plugin_count = pluginInformation->number_used_plugins;
auto pluginName = plugin.getMetaInformation().getName();
//auto pluginPath = plugin.getMetaInformation().getPath();
if(plugin_count >= MAXIMUM_PLUGINS - 1) {
DEBUG_FUNCTION_LINE("Maximum of %d plugins reached. %s won't be loaded!\n", MAXIMUM_PLUGINS, pluginName.c_str());
return false;
}
// Copy data to global struct.
plugin_information_single_t * plugin_data = &(pluginInformation->plugin_data[plugin_count]);
DEBUG_FUNCTION_LINE("%08X", plugin_data);
// Make sure everything is reset.
//plugin_data = {};
memset((void*)plugin_data, 0, sizeof(plugin_information_single_t));
auto pluginMetaInfo = plugin.getMetaInformation();
auto plugin_meta_data = &plugin_data->meta;
if(pluginMetaInfo.getName().size() >= MAXIMUM_PLUGIN_META_FIELD_LENGTH) {
DEBUG_FUNCTION_LINE("Warning: name will be truncated.");
}
strncpy(plugin_meta_data->name, pluginMetaInfo.getName().c_str(), MAXIMUM_PLUGIN_META_FIELD_LENGTH-1);
if(pluginMetaInfo.getAuthor().size() >= MAXIMUM_PLUGIN_META_FIELD_LENGTH) {
DEBUG_FUNCTION_LINE("Warning: author will be truncated.");
}
strncpy(plugin_meta_data->author, pluginMetaInfo.getAuthor().c_str(), MAXIMUM_PLUGIN_META_FIELD_LENGTH-1);
if(pluginMetaInfo.getVersion().size() >= MAXIMUM_PLUGIN_META_FIELD_LENGTH) {
DEBUG_FUNCTION_LINE("Warning: version will be truncated.");
}
strncpy(plugin_meta_data->version, pluginMetaInfo.getVersion().c_str(), MAXIMUM_PLUGIN_META_FIELD_LENGTH-1);
if(pluginMetaInfo.getLicense().size() >= MAXIMUM_PLUGIN_META_FIELD_LENGTH) {
DEBUG_FUNCTION_LINE("Warning: license will be truncated.");
}
strncpy(plugin_meta_data->license, pluginMetaInfo.getLicense().c_str(), MAXIMUM_PLUGIN_META_FIELD_LENGTH-1);
if(pluginMetaInfo.getBuildTimestamp().size() >= MAXIMUM_PLUGIN_META_FIELD_LENGTH) {
DEBUG_FUNCTION_LINE("Warning: build timestampt will be truncated.");
}
strncpy(plugin_meta_data->buildTimestamp, pluginMetaInfo.getBuildTimestamp().c_str(), MAXIMUM_PLUGIN_META_FIELD_LENGTH-1);
if(pluginMetaInfo.getDescription().size() >= MAXIMUM_PLUGIN_DESCRIPTION_LENGTH) {
DEBUG_FUNCTION_LINE("Warning: description will be truncated.");
DEBUG_FUNCTION_LINE("%s", pluginMetaInfo.getDescription().c_str());
}
strncpy(plugin_meta_data->descripion, pluginMetaInfo.getDescription().c_str(), MAXIMUM_PLUGIN_DESCRIPTION_LENGTH-1);
plugin_meta_data->size = pluginMetaInfo.getSize();
auto pluginInfo = plugin.getPluginInformation();
// Relocation
std::vector<RelocationData> relocationData = pluginInfo.getRelocationDataList();
for (auto & reloc : relocationData) {
if(!DynamicLinkingHelper::addReloationEntry(&(pluginInformation->linking_data), plugin_data->info.linking_entries, DYN_LINK_RELOCATION_LIST_LENGTH, reloc)) {
return false;
}
}
std::vector<FunctionData> function_data_list = pluginInfo.getFunctionDataList();
std::vector<HookData> hook_data_list = pluginInfo.getHookDataList();
if(function_data_list.size() > MAXIMUM_FUNCTION_PER_PLUGIN) {
DEBUG_FUNCTION_LINE("Plugin %s would replace to many function (%d, maximum is %d). It won't be loaded.",pluginName.c_str(), function_data_list.size(), MAXIMUM_FUNCTION_PER_PLUGIN);
return false;
}
if(hook_data_list.size() > MAXIMUM_HOOKS_PER_PLUGIN) {
DEBUG_FUNCTION_LINE("Plugin %s would set too many hooks (%d, maximum is %d). It won't be loaded.", pluginName.c_str(), hook_data_list.size(), MAXIMUM_HOOKS_PER_PLUGIN);
return false;
}
if(pluginName.length() > MAXIMUM_PLUGIN_NAME_LENGTH-1) {
DEBUG_FUNCTION_LINE("Name for plugin %s was too long to be stored.", pluginName.c_str());
return false;
}
/* Store function replacement information */
uint32_t i = 0;
for(auto & curFunction : pluginInfo.getFunctionDataList()) {
replacement_data_function_t * function_data = &plugin_data->info.functions[i];
if(strlen(curFunction.getName().c_str()) > MAXIMUM_FUNCTION_NAME_LENGTH-1) {
DEBUG_FUNCTION_LINE("Could not add function \"%s\" for plugin \"%s\" function name is too long.", curFunction.getName().c_str(), pluginName.c_str());
continue;
}
DEBUG_FUNCTION_LINE("Adding function \"%s\" for plugin \"%s\"",curFunction.getName().c_str(), pluginName.c_str());
strncpy(function_data->function_name, curFunction.getName().c_str(),MAXIMUM_FUNCTION_NAME_LENGTH-1);
function_data->library = curFunction.getLibrary();
function_data->replaceAddr = (uint32_t) curFunction.getReplaceAddress();
function_data->replaceCall = (uint32_t) curFunction.getReplaceCall();
function_data->physicalAddr = (uint32_t) curFunction.getPhysicalAddress();
function_data->virtualAddr = (uint32_t) curFunction.getVirtualAddress();
plugin_data->info.number_used_functions++;
i++;
}
i = 0;
for(auto & curHook : pluginInfo.getHookDataList()) {
replacement_data_hook_t * hook_data = &plugin_data->info.hooks[i];
DEBUG_FUNCTION_LINE("Set hook for plugin \"%s\" of type %08X to target %08X",plugin_data->meta.name, curHook.getType(),(void*) curHook.getFunctionPointer());
hook_data->func_pointer = (void*) curHook.getFunctionPointer();
hook_data->type = curHook.getType();
plugin_data->info.number_used_hooks++;
i++;
}
/* Saving SectionInfos */
for(auto & curSection : pluginInfo.getSectionInfoList()) {
bool foundFreeSlot = false;
uint32_t slot = 0;
for(uint32_t i = 0; i < MAXIMUM_PLUGIN_SECTION_LENGTH; i++) {
plugin_section_info_t * sectionInfo = &(plugin_data->info.sectionInfos[i]);
if(sectionInfo->addr == 0 && sectionInfo->size == 0) {
foundFreeSlot = true;
slot = i;
break;
}
}
if(foundFreeSlot) {
plugin_section_info_t * sectionInfo = &(plugin_data->info.sectionInfos[slot]);
if(strlen(curSection.first.c_str()) > MAXIMUM_PLUGIN_SECTION_NAME_LENGTH-1) {
DEBUG_FUNCTION_LINE("Could not add section info \"%s\" for plugin \"%s\" section name is too long.",curSection.first.c_str(), pluginName.c_str());
break;
}
strncpy(sectionInfo->name, curSection.first.c_str(), MAXIMUM_PLUGIN_SECTION_NAME_LENGTH-1);
sectionInfo->addr = curSection.second.getAddress();
sectionInfo->size = curSection.second.getSize();
} else {
DEBUG_FUNCTION_LINE("Failed to store SectionInfos");
return false;
}
}
plugin_data->info.trampolinId = pluginInfo.getTrampolinId();
/* Copy plugin data */
auto pluginData = plugin.getPluginData();
auto plugin_data_data = &plugin_data->data;
plugin_data_data->buffer = (char*)pluginData.buffer;
plugin_data_data->bufferLength = pluginData.length;
plugin_data_data->memoryType = pluginData.memoryType;
plugin_data_data->heapHandle = (int)pluginData.heapHandle;
pluginInformation->number_used_plugins++;
DCFlushRange((void*)pluginInformation,sizeof(plugin_information_t));
ICInvalidateRange((void*)pluginInformation,sizeof(plugin_information_t));
return true;
}
std::vector<PluginContainer> PluginContainerPersistence::loadPlugins(plugin_information_t * pluginInformation) {
std::vector<PluginContainer> result;
if(pluginInformation == NULL) {
DEBUG_FUNCTION_LINE("pluginInformation == NULL");
return result;
}
DCFlushRange((void*)pluginInformation,sizeof(plugin_information_t));
ICInvalidateRange((void*)pluginInformation,sizeof(plugin_information_t));
int32_t plugin_count = pluginInformation->number_used_plugins;
if(plugin_count > MAXIMUM_PLUGINS) {
DEBUG_FUNCTION_LINE("pluginInformation->plugin_count was bigger then allowed. %d > %d. Limiting to %d",plugin_count, MAXIMUM_PLUGINS, MAXIMUM_PLUGINS);
plugin_count = MAXIMUM_PLUGINS;
}
for(int32_t i = 0; i < plugin_count; i++) {
// Copy data from struct.
plugin_information_single_t * plugin_data = &(pluginInformation->plugin_data[i]);
PluginMetaInformation metaInformation;
plugin_meta_info_t * meta = &(plugin_data->meta);
metaInformation.setAuthor(meta->author);
metaInformation.setVersion(meta->version);
metaInformation.setBuildTimestamp(meta->buildTimestamp);
metaInformation.setLicense(meta->license);
metaInformation.setDescription(meta->descripion);
metaInformation.setSize(meta->size);
metaInformation.setName(meta->name);
PluginData pluginData;
plugin_data_t * data = &(plugin_data->data);
pluginData.buffer = data->buffer;
pluginData.length = data->bufferLength;
pluginData.memoryType = (eMemoryTypes) data->memoryType;
pluginData.heapHandle = (MEMHeapHandle) data->heapHandle;
pluginData.loadReader();
PluginInformation pluginInformation;
pluginInformation.setTrampolinId(plugin_data->info.trampolinId);
for(uint32_t i = 0; i < MAXIMUM_PLUGIN_SECTION_LENGTH; i++) {
plugin_section_info_t * sectionInfo = &(plugin_data->info.sectionInfos[i]);
if(sectionInfo->addr == 0 && sectionInfo->size == 0) {
continue;
}
DEBUG_FUNCTION_LINE("Add SectionInfo %s", sectionInfo->name);
pluginInformation.addSectionInfo(SectionInfo(sectionInfo->name, sectionInfo->addr, sectionInfo->size));
}
/* load hook data */
uint32_t hookCount = plugin_data->info.number_used_hooks;
if(hookCount > MAXIMUM_HOOKS_PER_PLUGIN) {
DEBUG_FUNCTION_LINE("number_used_hooks was bigger then allowed. %d > %d. Limiting to %d",hookCount, MAXIMUM_HOOKS_PER_PLUGIN, MAXIMUM_HOOKS_PER_PLUGIN);
hookCount = MAXIMUM_HOOKS_PER_PLUGIN;
}
for(uint32_t j = 0; j < hookCount; j++) {
replacement_data_hook_t * hook_entry = &(plugin_data->info.hooks[j]);
HookData curHook(hook_entry->func_pointer, hook_entry->type);
pluginInformation.addHookData(curHook);
}
/* load function replacement data */
uint32_t functionReplaceCount = plugin_data->info.number_used_functions;
if(functionReplaceCount > MAXIMUM_FUNCTION_PER_PLUGIN) {
DEBUG_FUNCTION_LINE("number_used_functions was bigger then allowed. %d > %d. Limiting to %d",functionReplaceCount, MAXIMUM_FUNCTION_PER_PLUGIN, MAXIMUM_FUNCTION_PER_PLUGIN);
functionReplaceCount = MAXIMUM_FUNCTION_PER_PLUGIN;
}
for(uint32_t j = 0; j < functionReplaceCount; j++) {
replacement_data_function_t * entry = &(plugin_data->info.functions[j]);
FunctionData func((void *) entry->physicalAddr, (void *) entry->virtualAddr, entry->function_name, entry->library, (void *) entry->replaceAddr, (void *) entry->replaceCall);
pluginInformation.addFunctionData(func);
}
/* load relocation data */
for(uint32_t j = 0; j < DYN_LINK_RELOCATION_LIST_LENGTH; j++) {
dyn_linking_relocation_entry_t * linking_entry = &(plugin_data->info.linking_entries[j]);
if(linking_entry->destination == NULL) {
break;
}
dyn_linking_import_t* importEntry = linking_entry->importEntry;
if(importEntry == NULL) {
DEBUG_FUNCTION_LINE("importEntry was NULL, skipping relocation entry");
continue;
}
if(importEntry->importName == NULL) {
DEBUG_FUNCTION_LINE("importEntry->importName was NULL, skipping relocation entry");
continue;
}
dyn_linking_function_t* functionEntry = linking_entry->functionEntry;
if(functionEntry == NULL) {
DEBUG_FUNCTION_LINE("functionEntry was NULL, skipping relocation entry");
continue;
}
if(functionEntry->functionName == NULL) {
DEBUG_FUNCTION_LINE("functionEntry->functionName was NULL, skipping relocation entry");
continue;
}
ImportRPLInformation rplInfo(importEntry->importName, importEntry->isData);
RelocationData reloc(linking_entry->type, linking_entry->offset, linking_entry->addend, linking_entry->destination, functionEntry->functionName, rplInfo);
pluginInformation.addRelocationData(reloc);
}
PluginContainer container;
container.setMetaInformation(metaInformation);
container.setPluginData(pluginData);
container.setPluginInformation(pluginInformation);
result.push_back(container);
}
return result;
}

View File

@ -0,0 +1,10 @@
#pragma once
#include "common/plugin_defines.h"
#include "PluginContainer.h"
class PluginContainerPersistence {
public:
static bool savePlugin(plugin_information_t * pluginInformation, PluginContainer& plugin);
static std::vector<PluginContainer> loadPlugins(plugin_information_t * pluginInformation);
};

View File

@ -0,0 +1,76 @@
#include "PluginData.h"
void PluginData::freeMemory() {
if(buffer == NULL) {
return;
}
switch(memoryType) {
default:
case eMemTypeExpHeap:
MEMFreeToExpHeap(this->heapHandle, buffer);
this->buffer = NULL;
break;
case eMemTypeMEM2:
free(this->buffer);
this->buffer = NULL;
break;
}
}
PluginData::PluginData(std::vector<uint8_t> buffer) : PluginData(buffer, 0, eMemTypeMEM2) {
}
void PluginData::loadReader() {
if(this->buffer == NULL) {
this->reader = std::nullopt;
} else {
elfio * nReader = new elfio;
if(nReader != NULL && nReader->load((char*)this->buffer, length)) {
DEBUG_FUNCTION_LINE("Loading was okay");
this->reader = nReader;
} else {
if(nReader){
delete nReader;
nReader = NULL;
}
DEBUG_FUNCTION_LINE("Loading failed");
this->reader = std::nullopt;
}
}
}
PluginData::PluginData(std::vector<uint8_t> input, MEMHeapHandle heapHandle, eMemoryTypes memoryType):
heapHandle(heapHandle),
memoryType(memoryType),
length(input.size()) {
void * data_copy = NULL;
switch(memoryType) {
default:
case eMemTypeExpHeap:
data_copy = MEMAllocFromExpHeapEx(heapHandle, length, 4);
if(data_copy == NULL) {
DEBUG_FUNCTION_LINE("Failed to allocate space on exp heap");
} else {
memcpy(data_copy, &input[0], length);
}
this->buffer = data_copy;
DEBUG_FUNCTION_LINE("copied data to exp heap");
break;
case eMemTypeMEM2:
data_copy = memalign(length, 4);
if(data_copy == NULL) {
DEBUG_FUNCTION_LINE("Failed to allocate space on default heap");
} else {
memcpy(data_copy, &input[0], length);
}
this->buffer = data_copy;
break;
}
loadReader();
}
std::optional<PluginData> PluginData::createFromExistingData(const void* buffer, MEMHeapHandle heapHandle, eMemoryTypes memoryType, const size_t length) {
return std::nullopt;
}

View File

@ -0,0 +1,68 @@
/****************************************************************************
* Copyright (C) 2020 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#pragma once
#include <optional>
#include <vector>
#include <malloc.h>
#include <coreinit/memexpheap.h>
#include "elfio/elfio.hpp"
using namespace ELFIO;
enum eMemoryTypes {
eMemTypeMEM2,
eMemTypeExpHeap
};
class PluginData {
public:
const std::optional<elfio*>& getReader() const {
return reader;
}
~PluginData() {
if(nReader != NULL) {
delete nReader;
nReader = NULL;
}
}
void freeMemory();
private:
PluginData() {
}
PluginData(std::vector<uint8_t> buffer);
PluginData(std::vector<uint8_t> input, MEMHeapHandle heapHandle, eMemoryTypes memoryType);
void loadReader();
static std::optional<PluginData> createFromExistingData(const void* buffer, MEMHeapHandle heapHandle, eMemoryTypes memoryType, const size_t length);
std::optional<elfio*> reader;
elfio* nReader = NULL;
void* buffer;
MEMHeapHandle heapHandle;
eMemoryTypes memoryType;
size_t length;
friend class PluginDataFactory;
friend class PluginContainer;
friend class PluginContainerPersistence;
};

View File

@ -0,0 +1,112 @@
/****************************************************************************
* Copyright (C) 2018 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include "PluginDataFactory.h"
#include "utils/logger.h"
#include "utils/StringTools.h"
std::vector<PluginData> PluginDataFactory::loadDir(const std::string & path, MEMHeapHandle heapHandle) {
std::vector<PluginData> result;
struct dirent *dp;
DIR *dfd = NULL;
if(path.empty()) {
DEBUG_FUNCTION_LINE("Path was empty\n");
return result;
}
if ((dfd = opendir(path.c_str())) == NULL) {
DEBUG_FUNCTION_LINE("Couldn't open dir %s\n",path.c_str());
return result;
}
while ((dp = readdir(dfd)) != NULL) {
struct stat stbuf ;
std::string full_file_path = StringTools::strfmt("%s/%s",path.c_str(),dp->d_name);
StringTools::RemoveDoubleSlashs(full_file_path);
if( stat(full_file_path.c_str(),&stbuf ) == -1 ) {
DEBUG_FUNCTION_LINE("Unable to stat file: %s\n",full_file_path.c_str()) ;
continue;
}
if ( ( stbuf.st_mode & S_IFMT ) == S_IFDIR ) { // Skip directories
continue;
} else {
DEBUG_FUNCTION_LINE("Found file: %s\n",full_file_path.c_str()) ;
auto pluginData = load(full_file_path, heapHandle);
if(pluginData) {
result.push_back(pluginData.value());
}
}
}
if(dfd != NULL) {
closedir(dfd);
}
return result;
}
std::optional<PluginData> PluginDataFactory::load(const std::string & filename, MEMHeapHandle heapHandle) {
// open the file:
DEBUG_FUNCTION_LINE();
std::ifstream file(filename, std::ios::binary);
DEBUG_FUNCTION_LINE();
if(!file.is_open()){
DEBUG_FUNCTION_LINE("Failed to open %s", filename.c_str());
return std::nullopt;
}
// Stop eating new lines in binary mode!!!
file.unsetf(std::ios::skipws);
DEBUG_FUNCTION_LINE();
// get its size:
std::streampos fileSize;
DEBUG_FUNCTION_LINE();
file.seekg(0, std::ios::end);
fileSize = file.tellg();
file.seekg(0, std::ios::beg);
DEBUG_FUNCTION_LINE();
std::vector<uint8_t> vBuffer;
vBuffer.reserve(fileSize);
DEBUG_FUNCTION_LINE();
// read the data:
vBuffer.insert(vBuffer.begin(),
std::istream_iterator<uint8_t>(file),
std::istream_iterator<uint8_t>());
DEBUG_FUNCTION_LINE("Loaded file");
return load(vBuffer, heapHandle);
}
std::optional<PluginData> PluginDataFactory::load(std::vector<uint8_t>& buffer, MEMHeapHandle heapHandle) {
if(buffer.empty()){
return std::nullopt;
}
PluginData pluginData(buffer, heapHandle, eMemoryTypes::eMemTypeExpHeap);
return pluginData;
}

View File

@ -1,5 +1,5 @@
/****************************************************************************
* Copyright (C) 2018 Maschell
* Copyright (C) 2020 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -14,24 +14,18 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#include <utils/logger.h>
#include <wups.h>
#include <stdarg.h>
#include "dynamic_libs/coreinit.h"
#include "mem_utils.h"
#include "memory/memory_mapping.h"
#pragma once
int32_t memHandleVideo __attribute__((section(".data"))) = -1;
#include <optional>
#include <string>
#include <vector>
#include <coreinit/memexpheap.h>
#include "PluginData.h"
void MemoryUtils::init() {
memHandleVideo = MEMCreateExpHeapEx((void*)MemoryMapping::getVideoMemoryAddress(), MemoryMapping::getVideoMemorySize(), 0);
}
void* MemoryUtils::alloc(uint32_t size, int32_t align) {
return MEMAllocFromExpHeapEx(memHandleVideo,size, align);
}
void MemoryUtils::free(void * ptr) {
MEMFreeToExpHeap(memHandleVideo,ptr);
}
class PluginDataFactory {
public:
static std::vector<PluginData> loadDir(const std::string & path, MEMHeapHandle heapHandle);
static std::optional<PluginData> load(const std::string & path, MEMHeapHandle heapHandle);
static std::optional<PluginData> load(std::vector<uint8_t>& buffer, MEMHeapHandle heapHandle);
};

View File

@ -0,0 +1,95 @@
/****************************************************************************
* Copyright (C) 2018 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#pragma once
#include <map>
#include <optional>
#include <string>
#include <vector>
#include "PluginMetaInformation.h"
#include "RelocationData.h"
#include "HookData.h"
#include "FunctionData.h"
#include "SectionInfo.h"
class PluginInformation {
public:
PluginInformation(){
}
virtual ~PluginInformation() {
}
void addHookData(const HookData& hook_data) {
hook_data_list.push_back(hook_data);
}
const std::vector<HookData>& getHookDataList() const {
return hook_data_list;
}
void addFunctionData(const FunctionData &function_data) {
function_data_list.push_back(function_data);
}
const std::vector<FunctionData>& getFunctionDataList() const {
return function_data_list;
}
void addRelocationData(const RelocationData &relocation_data) {
relocation_data_list.push_back(relocation_data);
}
const std::vector<RelocationData>& getRelocationDataList() const {
return relocation_data_list;
}
void addSectionInfo(const SectionInfo& sectionInfo) {
section_info_list[sectionInfo.getName()] = sectionInfo;
}
const std::map<std::string, SectionInfo>& getSectionInfoList() const {
return section_info_list;
}
std::optional<SectionInfo> getSectionInfo(const std::string& sectionName) const {
if(getSectionInfoList().count(sectionName) > 0) {
return section_info_list.at(sectionName);
}
return std::nullopt;
}
void setTrampolinId(uint8_t trampolinId) {
this->trampolinId = trampolinId;
}
uint8_t getTrampolinId() const {
return trampolinId;
}
private:
std::vector<HookData> hook_data_list;
std::vector<FunctionData> function_data_list;
std::vector<RelocationData> relocation_data_list;
std::map<std::string, SectionInfo> section_info_list;
uint8_t trampolinId = 0;
friend class PluginInformationFactory;
friend class PluginInformationPersistence;
};

View File

@ -0,0 +1,349 @@
/****************************************************************************
* Copyright (C) 2018 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#include <string>
#include <vector>
#include <map>
#include <coreinit/cache.h>
#include <coreinit/memexpheap.h>
#include <wups.h>
#include <whb/file.h>
#include "PluginData.h"
#include "PluginInformationFactory.h"
#include "HookData.h"
#include "SectionInfo.h"
#include "elfio/elfio.hpp"
#include "utils/utils.h"
#include "utils/ElfUtils.h"
#include "utils/StringTools.h"
using namespace ELFIO;
std::optional<PluginInformation> PluginInformationFactory::load(const PluginData & pluginData, MEMHeapHandle heapHandle, relocation_trampolin_entry_t * trampolin_data, uint32_t trampolin_data_length, uint8_t trampolinId) {
auto readerOpt = pluginData.getReader();
if(!readerOpt) {
DEBUG_FUNCTION_LINE("Can't find or process ELF file");
return std::nullopt;
}
auto reader = readerOpt.value();
PluginInformation pluginInfo;
uint32_t sec_num = reader->sections.size();
uint8_t **destinations = (uint8_t **) malloc(sizeof(uint8_t *) * sec_num);
uint32_t totalSize = 0;
uint32_t text_size = 0;
uint32_t data_size = 0;
for(uint32_t i = 0; i < sec_num; ++i ) {
section* psec = reader->sections[i];
if (psec->get_type() == 0x80000002) {
continue;
}
if ((psec->get_type() == SHT_PROGBITS || psec->get_type() == SHT_NOBITS) && (psec->get_flags() & SHF_ALLOC)) {
uint32_t sectionSize = psec->get_size();
uint32_t address = (uint32_t) psec->get_address();
if((address >= 0x02000000) && address < 0x10000000) {
text_size += sectionSize;
} else if((address >= 0x10000000) && address < 0xC0000000) {
data_size += sectionSize;
}
}
}
void * text_data = MEMAllocFromExpHeapEx(heapHandle, text_size, 0x1000);
if(text_data == NULL) {
DEBUG_FUNCTION_LINE("Failed to alloc memory for the .text section (%d bytes)\n", text_size);
return std::nullopt;
}
DEBUG_FUNCTION_LINE("Allocated %d kb from ExpHeap", text_size/1024);
void * data_data = MEMAllocFromExpHeapEx(heapHandle, data_size, 0x1000);
if(data_data == NULL) {
DEBUG_FUNCTION_LINE("Failed to alloc memory for the .data section (%d bytes)\n", data_size);
MEMFreeToExpHeap(heapHandle, text_data);
return std::nullopt;
}
DEBUG_FUNCTION_LINE("Allocated %d kb from ExpHeap", data_size/1024);
uint32_t entrypoint = (uint32_t)text_data + (uint32_t) reader->get_entry() - 0x02000000;
for(uint32_t i = 0; i < sec_num; ++i ) {
section* psec = reader->sections[i];
if (psec->get_type() == 0x80000002) {
continue;
}
if ((psec->get_type() == SHT_PROGBITS || psec->get_type() == SHT_NOBITS) && (psec->get_flags() & SHF_ALLOC)) {
uint32_t sectionSize = psec->get_size();
uint32_t address = (uint32_t) psec->get_address();
uint32_t destination = address;
if((address >= 0x02000000) && address < 0x10000000) {
destination += (uint32_t) text_data;
destination -= 0x02000000;
destinations[psec->get_index()] = (uint8_t *) text_data;
} else if((address >= 0x10000000) && address < 0xC0000000) {
destination += (uint32_t) data_data;
destination -= 0x10000000;
destinations[psec->get_index()] = (uint8_t *) data_data;
} else if(address >= 0xC0000000) {
destination += (uint32_t) data_data;
destination -= 0xC0000000;
//destinations[psec->get_index()] = (uint8_t *) data_data;
//destinations[psec->get_index()] -= 0xC0000000;
} else {
DEBUG_FUNCTION_LINE("Unhandled case");
free(destinations);
MEMFreeToExpHeap(heapHandle, text_data);
MEMFreeToExpHeap(heapHandle, data_data);
return std::nullopt;
}
const char* p = psec->get_data();
if(psec->get_type() == SHT_NOBITS) {
DEBUG_FUNCTION_LINE("memset section %s %08X to 0 (%d bytes)", psec->get_name().c_str(), destination, sectionSize);
memset((void*) destination, 0, sectionSize);
} else if(psec->get_type() == SHT_PROGBITS) {
DEBUG_FUNCTION_LINE("Copy section %s %08X -> %08X (%d bytes)", psec->get_name().c_str(), p, destination, sectionSize);
memcpy((void*) destination, p, sectionSize);
}
pluginInfo.addSectionInfo(SectionInfo(psec->get_name(), destination, sectionSize));
DEBUG_FUNCTION_LINE("Saved %s section info. Location: %08X size: %08X", psec->get_name().c_str(), destination, sectionSize);
totalSize += sectionSize;
DCFlushRange((void*)destination, sectionSize);
ICInvalidateRange((void*)destination, sectionSize);
}
}
for(uint32_t i = 0; i < sec_num; ++i ) {
section* psec = reader->sections[i];
if ((psec->get_type() == SHT_PROGBITS || psec->get_type() == SHT_NOBITS) && (psec->get_flags() & SHF_ALLOC)) {
DEBUG_FUNCTION_LINE("Linking (%d)... %s at %08X",i,psec->get_name().c_str(), destinations[psec->get_index()]);
if (!linkSection(pluginData, psec->get_index(), (uint32_t) destinations[psec->get_index()], (uint32_t) text_data, (uint32_t) data_data, trampolin_data, trampolin_data_length, trampolinId)) {
DEBUG_FUNCTION_LINE("elfLink failed");
free(destinations);
MEMFreeToExpHeap(heapHandle, text_data);
MEMFreeToExpHeap(heapHandle, data_data);
return std::nullopt;
}
}
}
std::vector<RelocationData> relocationData = getImportRelocationData(pluginData, destinations);
for (auto const& reloc : relocationData) {
pluginInfo.addRelocationData(reloc);
}
DCFlushRange((void*)text_data, text_size);
ICInvalidateRange((void*)text_data, text_size);
DCFlushRange((void*)data_data, data_size);
ICInvalidateRange((void*)data_data, data_size);
free(destinations);
pluginInfo.setTrampolinId(trampolinId);
DEBUG_FUNCTION_LINE("Saved entrypoint as %08X", entrypoint);
std::optional<SectionInfo> secInfo = pluginInfo.getSectionInfo(".wups.hooks");
if(secInfo && secInfo->getSize() > 0) {
size_t entries_count = secInfo->getSize() / sizeof(wups_loader_hook_t);
wups_loader_hook_t * entries = (wups_loader_hook_t *) secInfo->getAddress();
if(entries != NULL) {
for(size_t j=0; j<entries_count; j++) {
wups_loader_hook_t * hook = &entries[j];
DEBUG_FUNCTION_LINE("Saving hook of plugin Type: %08X, target: %08X"/*,pluginData.getPluginInformation()->getName().c_str()*/,hook->type,(void*) hook->target);
HookData hook_data((void *) hook->target,hook->type);
pluginInfo.addHookData(hook_data);
}
}
}
secInfo = pluginInfo.getSectionInfo(".wups.load");
if(secInfo && secInfo->getSize() > 0) {
size_t entries_count = secInfo->getSize() / sizeof(wups_loader_entry_t);
wups_loader_entry_t * entries = (wups_loader_entry_t *) secInfo->getAddress();
if(entries != NULL) {
for(size_t j=0; j<entries_count; j++) {
wups_loader_entry_t * cur_function = &entries[j];
DEBUG_FUNCTION_LINE("Saving function \"%s\" of plugin . PA:%08X VA:%08X Library: %08X, target: %08X, call_addr: %08X",cur_function->_function.name/*,pluginData.getPluginInformation()->getName().c_str()*/,cur_function->_function.physical_address,cur_function->_function.virtual_address, cur_function->_function.library,cur_function->_function.target, (void *) cur_function->_function.call_addr);
FunctionData function_data((void *) cur_function->_function.physical_address,(void *) cur_function->_function.virtual_address, cur_function->_function.name, cur_function->_function.library, (void *) cur_function->_function.target, (void *) cur_function->_function.call_addr);
pluginInfo.addFunctionData(function_data);
}
}
}
return pluginInfo;
}
std::vector<RelocationData> PluginInformationFactory::getImportRelocationData(const PluginData &pluginData, uint8_t ** destinations) {
auto readerOpt = pluginData.getReader();
std::vector<RelocationData> result;
if(!readerOpt) {
return result;
}
auto reader = readerOpt.value();
std::map<uint32_t,std::string> infoMap;
uint32_t sec_num = reader->sections.size();
for ( uint32_t i = 0; i < sec_num; ++i ) {
section* psec = reader->sections[i];
if (psec->get_type() == 0x80000002) {
infoMap[i] = psec->get_name();
}
}
for (uint32_t i = 0; i < sec_num; ++i ) {
section* psec = reader->sections[i];
if(psec->get_type() == SHT_RELA || psec->get_type() == SHT_REL) {
DEBUG_FUNCTION_LINE("Found relocation section %s",psec->get_name().c_str());
relocation_section_accessor rel(*reader, psec);
for ( uint32_t j = 0; j < (uint32_t) rel.get_entries_num(); ++j ) {
Elf64_Addr offset;
Elf_Word type;
Elf_Sxword addend;
std::string sym_name;
Elf64_Addr sym_value;
Elf_Half sym_section_index;
if(!rel.get_entry(j, offset, sym_value, sym_name, type, addend, sym_section_index)) {
DEBUG_FUNCTION_LINE("Failed to get relocation");
break;
}
uint32_t adjusted_sym_value = (uint32_t) sym_value;
if(adjusted_sym_value < 0xC0000000) {
continue;
}
std::string fimport = ".fimport_";
std::string dimport = ".dimport_";
bool isData = false;
std::string rplName = "";
std::string rawSectionName = infoMap[sym_section_index];
if(rawSectionName.size() < fimport.size()) {
DEBUG_FUNCTION_LINE("Section name was shorter than expected, skipping this relocation");
continue;
} else if (std::equal(fimport.begin(), fimport.end(), rawSectionName.begin())) {
rplName = rawSectionName.substr(fimport.size());
} else if (std::equal(dimport.begin(), dimport.end(), rawSectionName.begin())) {
rplName = rawSectionName.substr(dimport.size());
isData = true;
} else {
DEBUG_FUNCTION_LINE("invalid section name\n");
continue;
}
ImportRPLInformation rplInfo(rplName, isData);
uint32_t section_index = psec->get_info();
result.push_back(RelocationData(type, offset - 0x02000000, addend, (void*)(destinations[section_index]), sym_name, rplInfo));
}
}
}
return result;
}
bool PluginInformationFactory::linkSection(const PluginData& pluginData, uint32_t section_index, uint32_t destination, uint32_t base_text, uint32_t base_data, relocation_trampolin_entry_t * trampolin_data, uint32_t trampolin_data_length, uint8_t trampolinId) {
auto readerOpt = pluginData.getReader();
if(!readerOpt) {
return false;
}
auto reader = readerOpt.value();
uint32_t sec_num = reader->sections.size();
for (uint32_t i = 0; i < sec_num; ++i ) {
section* psec = reader->sections[i];
if(psec->get_info() == section_index) {
DEBUG_FUNCTION_LINE("Found relocation section %s",psec->get_name().c_str());
relocation_section_accessor rel(*reader, psec);
for ( uint32_t j = 0; j < (uint32_t) rel.get_entries_num(); ++j ) {
Elf64_Addr offset;
Elf_Word type;
Elf_Sxword addend;
std::string sym_name;
Elf64_Addr sym_value;
Elf_Half sym_section_index;
if(!rel.get_entry(j, offset, sym_value, sym_name, type, addend, sym_section_index)) {
DEBUG_FUNCTION_LINE("Failed to get relocation");
break;
}
uint32_t adjusted_sym_value = (uint32_t) sym_value;
if((adjusted_sym_value >= 0x02000000) && adjusted_sym_value < 0x10000000) {
adjusted_sym_value -= 0x02000000;
adjusted_sym_value += base_text;
} else if((adjusted_sym_value >= 0x10000000) && adjusted_sym_value < 0xC0000000) {
adjusted_sym_value -= 0x10000000;
adjusted_sym_value += base_data;
} else if(adjusted_sym_value >= 0xC0000000) {
//DEBUG_FUNCTION_LINE("Skip imports");
// Skip imports
continue;
} else if(adjusted_sym_value == 0x0) {
//
} else {
DEBUG_FUNCTION_LINE("Unhandled case %08X",adjusted_sym_value);
return false;
}
uint32_t adjusted_offset = (uint32_t) offset;
if((offset >= 0x02000000) && offset < 0x10000000) {
adjusted_offset -= 0x02000000;
} else if((adjusted_offset >= 0x10000000) && adjusted_offset < 0xC0000000) {
adjusted_offset -= 0x10000000;
} else if(adjusted_offset >= 0xC0000000) {
adjusted_offset -= 0xC0000000;
}
if(sym_section_index == SHN_ABS) {
//
} else if(sym_section_index > SHN_LORESERVE) {
DEBUG_FUNCTION_LINE("NOT IMPLEMENTED: %04X", sym_section_index);
return false;
}
if(false) {
DEBUG_FUNCTION_LINE("sym_value %08X adjusted_sym_value %08X offset %08X adjusted_offset %08X", (uint32_t) sym_value, adjusted_sym_value, (uint32_t) offset, adjusted_offset);
}
if(!ElfUtils::elfLinkOne(type, adjusted_offset, addend, destination, adjusted_sym_value, trampolin_data, trampolin_data_length, RELOC_TYPE_FIXED, trampolinId)) {
DEBUG_FUNCTION_LINE("Link failed");
return false;
}
}
DEBUG_FUNCTION_LINE("done");
return true;
}
}
DEBUG_FUNCTION_LINE("Failed to find relocation section");
return true;
}

View File

@ -0,0 +1,35 @@
/****************************************************************************
* Copyright (C) 2019 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#pragma once
#include <optional>
#include <string>
#include <vector>
#include <map>
#include <coreinit/memheap.h>
#include "common/relocation_defines.h"
#include "PluginInformation.h"
#include "PluginContainer.h"
#include "elfio/elfio.hpp"
class PluginInformationFactory {
public:
static std::optional<PluginInformation> load(const PluginData & pluginData, MEMHeapHandle heaphandle, relocation_trampolin_entry_t * trampolin_data, uint32_t trampolin_data_length, uint8_t trampolinId);
static bool linkSection(const PluginData & pluginData, uint32_t section_index, uint32_t destination, uint32_t base_text, uint32_t base_data, relocation_trampolin_entry_t * trampolin_data, uint32_t trampolin_data_length, uint8_t trampolinId);
static std::vector<RelocationData> getImportRelocationData(const PluginData & pluginData, uint8_t ** destinations);
};

View File

@ -0,0 +1,96 @@
/****************************************************************************
* Copyright (C) 2019,2020 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#pragma once
#include <string>
#include <vector>
class PluginMetaInformation {
public:
const std::string getName() const {
return name;
}
const std::string getAuthor() const {
return this->author;
}
const std::string getVersion() const {
return this->version;
}
const std::string getLicense() const {
return this->license;
}
const std::string getBuildTimestamp() const {
return this->buildtimestamp;
}
const std::string getDescription() const {
return this->description;
}
const size_t getSize() const {
return this->size;
}
private:
PluginMetaInformation() {
}
void setName(const std::string& name) {
this->name = name;
}
void setAuthor(const std::string& author) {
this->author = author;
}
void setVersion(const std::string& version) {
this->version = version;
}
void setLicense(const std::string& license) {
this->license = license;
}
void setBuildTimestamp(const std::string& buildtimestamp) {
this->buildtimestamp = buildtimestamp;
}
void setDescription(const std::string& description) {
this->description = description;
}
void setSize(size_t size) {
this->size = size;
}
std::string name;
std::string author;
std::string version;
std::string license;
std::string buildtimestamp;
std::string description;
size_t size;
friend class PluginMetaInformationFactory;
friend class PluginContainerPersistence;
friend class PluginContainer;
};

View File

@ -0,0 +1,108 @@
/****************************************************************************
* Copyright (C) 2018-2020 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <whb/file.h>
#include "utils/StringTools.h"
#include "PluginMetaInformationFactory.h"
#include "PluginMetaInformation.h"
#include "elfio/elfio.hpp"
using namespace ELFIO;
std::optional<PluginMetaInformation> PluginMetaInformationFactory::loadPlugin(const PluginData& pluginData) {
auto readerOpt = pluginData.getReader();
// Load ELF data
if (!readerOpt) {
DEBUG_FUNCTION_LINE("Can't find or process ELF file");
return std::nullopt;
}
auto reader = readerOpt.value();
DEBUG_FUNCTION_LINE("Found elfio reader");
size_t pluginSize = 0;
PluginMetaInformation pluginInfo;
uint32_t sec_num = reader->sections.size();
DEBUG_FUNCTION_LINE("%d number of sections", sec_num);
for(uint32_t i = 0; i < sec_num; ++i ) {
section* psec = reader->sections[i];
// Calculate total size:
if ((psec->get_type() == SHT_PROGBITS || psec->get_type() == SHT_NOBITS) && (psec->get_flags() & SHF_ALLOC)) {
uint32_t sectionSize = psec->get_size();
uint32_t address = (uint32_t) psec->get_address();
if((address >= 0x02000000) && address < 0x10000000) {
pluginSize += sectionSize;
} else if((address >= 0x10000000) && address < 0xC0000000) {
pluginSize += sectionSize;
}
}
// Get meta information and check WUPS version:
if (psec->get_name().compare(".wups.meta") == 0) {
const void * sectionData = psec->get_data();
uint32_t sectionSize = psec->get_size();
char * curEntry = (char *) sectionData;
while((uint32_t) curEntry < (uint32_t) sectionData + sectionSize) {
if (*curEntry == '\0') {
curEntry++;
continue;
}
auto firstFound = std::string(curEntry).find_first_of("=");
if(firstFound != std::string::npos) {
curEntry[firstFound] = '\0';
std::string key(curEntry);
std::string value(curEntry + firstFound + 1);
if(key.compare("name") == 0) {
DEBUG_FUNCTION_LINE("Name = %s", value.c_str());
pluginInfo.setName(value);
} else if(key.compare("author") == 0) {
pluginInfo.setAuthor(value);
} else if(key.compare("version") == 0) {
pluginInfo.setVersion(value);
} else if(key.compare("license") == 0) {
pluginInfo.setLicense(value);
} else if(key.compare("buildtimestamp") == 0) {
pluginInfo.setBuildTimestamp(value);
} else if(key.compare("description") == 0) {
pluginInfo.setDescription(value);
} else if(key.compare("wups") == 0) {
if(value.compare("0.2") != 0) {
DEBUG_FUNCTION_LINE("Warning: Ignoring plugin - Unsupported WUPS version: %s.\n", value);
return std::nullopt;
}
}
}
curEntry += strlen(curEntry) + 1;
}
}
}
pluginInfo.setSize(pluginSize);
return pluginInfo;
}

View File

@ -1,5 +1,5 @@
/****************************************************************************
* Copyright (C) 2018 Maschell
* Copyright (C) 2019,2020 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -14,19 +14,16 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef __MEMORY_UTILS_UTILS_H_
#define __MEMORY_UTILS_UTILS_H_
class MemoryUtils {
#pragma once
#include <optional>
#include <string>
#include <vector>
#include "PluginMetaInformation.h"
#include "PluginData.h"
class PluginMetaInformationFactory {
public:
static void init();
static void* alloc(uint32_t size, int32_t align);
static void free(void * ptr);
private:
MemoryUtils() {}
~MemoryUtils() {}
static std::optional<PluginMetaInformation> loadPlugin(const PluginData& pluginData);
};
#endif

View File

@ -15,65 +15,64 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef _RELOCATION_DATA_H_
#define _RELOCATION_DATA_H_
#pragma once
#include <wups.h>
#include <string>
#include "ImportRPLInformation.h"
class RelocationData {
public:
RelocationData(char type, size_t offset, int32_t addend, void *destination, std::string name, ImportRPLInformation * rplInfo) {
this->type = type;
this->offset = offset;
this->addend = addend;
this->destination = destination;
this->name = name;
this->rplInfo = rplInfo;
RelocationData(const char type, size_t offset, int32_t addend, void *destination, std::string name, ImportRPLInformation rplInfo):
type(type),
offset(offset),
addend(addend),
destination(destination),
name(name),
rplInfo(rplInfo) {
}
~RelocationData() {
RelocationData(const RelocationData &o2):
type(o2.type),
offset(o2.offset),
addend(o2.addend),
destination(o2.destination),
name(o2.name),
rplInfo(o2.rplInfo) {
}
char getType() {
virtual ~RelocationData() {
}
const char getType() const{
return type;
}
size_t getOffset() {
const size_t getOffset() const{
return offset;
}
int32_t getAddend() {
const int32_t getAddend() const{
return addend;
}
void * getDestination() {
const void * getDestination() const{
return destination;
}
std::string getName() {
const std::string& getName() const{
return name;
}
ImportRPLInformation * getImportRPLInformation() {
const ImportRPLInformation& getImportRPLInformation() const{
return rplInfo;
}
void printInformation() {
DEBUG_FUNCTION_LINE("%s destination: %08X offset: %08X type: %02X addend: %d rplName: %s isData: %d \n",name.c_str(), destination, offset, type, addend, rplInfo->getName().c_str(), rplInfo->isData() );
}
private:
char type;
size_t offset;
int32_t addend;
void *destination;
std::string name;
ImportRPLInformation * rplInfo;
ImportRPLInformation rplInfo;
};
#endif

View File

@ -1,5 +1,5 @@
/****************************************************************************
* Copyright (C) 2015 Dimok
* Copyright (C) 2019 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -14,54 +14,48 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef _CMUTEX_H_
#define _CMUTEX_H_
#include <malloc.h>
#include <dynamic_libs/os_functions.h>
#pragma once
#include <string>
class SectionInfo {
class CMutex {
public:
CMutex() {
pMutex = malloc(OS_MUTEX_SIZE);
if(!pMutex)
return;
OSInitMutex(pMutex);
}
virtual ~CMutex() {
if(pMutex)
free(pMutex);
SectionInfo(std::string name, uint32_t address, uint32_t sectionSize):
name(name),
address(address),
sectionSize(sectionSize) {
}
void lock(void) {
if(pMutex)
OSLockMutex(pMutex);
SectionInfo(){
}
void unlock(void) {
if(pMutex)
OSUnlockMutex(pMutex);
}
bool tryLock(void) {
if(!pMutex)
return false;
return (OSTryLockMutex(pMutex) != 0);
SectionInfo(const SectionInfo &o2):
name(o2.name),
address(o2.address),
sectionSize(o2.sectionSize) {
}
virtual ~SectionInfo() {
}
const std::string& getName() const {
return name;
}
const uint32_t getAddress() const {
return address;
}
const uint32_t getSize() const {
return sectionSize;
}
private:
void *pMutex;
std::string name;
uint32_t address;
uint32_t sectionSize;
};
class CMutexLock {
public:
CMutexLock() {
mutex.lock();
}
virtual ~CMutexLock() {
mutex.unlock();
}
private:
CMutex mutex;
};
#endif // _CMUTEX_H_

159
source/utils/ElfUtils.cpp Normal file
View File

@ -0,0 +1,159 @@
#include <stdio.h>
#include <string.h>
#include <coreinit/cache.h>
#include "utils/logger.h"
#include "elfio/elfio.hpp"
#include "ElfUtils.h"
// See https://github.com/decaf-emu/decaf-emu/blob/43366a34e7b55ab9d19b2444aeb0ccd46ac77dea/src/libdecaf/src/cafe/loader/cafe_loader_reloc.cpp#L144
bool ElfUtils::elfLinkOne(char type, size_t offset, int32_t addend, uint32_t destination, uint32_t symbol_addr, relocation_trampolin_entry_t * trampolin_data, uint32_t trampolin_data_length, RelocationType reloc_type, uint8_t trampolinId) {
if(type == R_PPC_NONE) {
return true;
}
auto target = destination + offset;
auto value = symbol_addr + addend;
auto relValue = value - static_cast<uint32_t>(target);
switch (type) {
case R_PPC_NONE:
break;
case R_PPC_ADDR32:
*((uint32_t *)(target)) = value;
break;
case R_PPC_ADDR16_LO:
*((uint16_t *)(target)) = static_cast<uint16_t>(value & 0xFFFF);
break;
case R_PPC_ADDR16_HI:
*((uint16_t *)(target)) = static_cast<uint16_t>(value >> 16);
break;
case R_PPC_ADDR16_HA:
*((uint16_t *)(target)) = static_cast<uint16_t>((value + 0x8000) >> 16);
break;
case R_PPC_DTPMOD32:
DEBUG_FUNCTION_LINE("################IMPLEMENT ME\n");
//*((int32_t *)(target)) = tlsModuleIndex;
break;
case R_PPC_DTPREL32:
*((uint32_t *)(target)) = value;
break;
case R_PPC_GHS_REL16_HA:
*((uint16_t *)(target)) = static_cast<uint16_t>((relValue + 0x8000) >> 16);
break;
case R_PPC_GHS_REL16_HI:
*((uint16_t *)(target)) = static_cast<uint16_t>(relValue >> 16);
break;
case R_PPC_GHS_REL16_LO:
*((uint16_t *)(target)) = static_cast<uint16_t>(relValue & 0xFFFF);
break;
case R_PPC_REL14: {
auto distance = static_cast<int32_t>(value) - static_cast<int32_t>(target);
if (distance > 0x7FFC || distance < -0x7FFC) {
DEBUG_FUNCTION_LINE("***14-bit relative branch cannot hit target.");
return false;
}
if (distance & 3) {
DEBUG_FUNCTION_LINE("***RELOC ERROR %d: lower 2 bits must be zero before shifting.", -470040);
return false;
}
if ((distance >= 0 && (distance & 0xFFFF8000)) ||
(distance < 0 && ((distance & 0xFFFF8000) != 0xFFFF8000))) {
DEBUG_FUNCTION_LINE("***RELOC ERROR %d: upper 17 bits before shift must all be the same.", -470040);
return false;
}
*(int32_t *)target = (*(int32_t *)target & 0xFFBF0003) | (distance & 0x0000fffc);
break;
}
case R_PPC_REL24: {
// if (isWeakSymbol && !symbolValue) {
// symbolValue = static_cast<uint32_t>(target);
// value = symbolValue + addend;
// }
auto distance = static_cast<int32_t>(value) - static_cast<int32_t>(target);
if (distance > 0x1FFFFFC || distance < -0x1FFFFFC) {
if(trampolin_data == NULL) {
DEBUG_FUNCTION_LINE("***24-bit relative branch cannot hit target. Trampolin isn't provided\n");
DEBUG_FUNCTION_LINE("***value %08X - target %08X = distance %08X\n", value, target, distance);
return false;
} else {
relocation_trampolin_entry_t * freeSlot = NULL;
for(uint32_t i = 0; i < trampolin_data_length; i++) {
// We want to override "old" relocations of imports
// Pending relocations have the status RELOC_TRAMP_IMPORT_IN_PROGRESS.
// When all relocations are done successfully, they will be turned into RELOC_TRAMP_IMPORT_DONE
// so they can be overridden/updated/reused on the next application launch.
//
// Relocations that won't change will have the status RELOC_TRAMP_FIXED and are set to free when the module is unloaded.
if(trampolin_data[i].status == RELOC_TRAMP_FREE ||
trampolin_data[i].status == RELOC_TRAMP_IMPORT_DONE) {
freeSlot = &(trampolin_data[i]);
break;
}
}
if(freeSlot != NULL) {
DEBUG_FUNCTION_LINE("***24-bit relative branch cannot hit target. Trampolin data list is full\n");
DEBUG_FUNCTION_LINE("***value %08X - target %08X = distance %08X\n", value, target, distance);
return false;
}
if(target - (uint32_t)&(freeSlot->trampolin[0]) > 0x1FFFFFC) {
DEBUG_FUNCTION_LINE("**Cannot link 24-bit jump (too far to tramp buffer).");
DEBUG_FUNCTION_LINE("***value %08X - target %08X = distance %08X\n", value, target, distance);
return false;
}
DEBUG_FUNCTION_LINE("freeSlot = %08X", freeSlot);
freeSlot->trampolin[0] = 0x3D600000 | ((((uint32_t) value) >> 16) & 0x0000FFFF); // lis r11, real_addr@h
freeSlot->trampolin[1] = 0x616B0000 | (((uint32_t) value) & 0x0000ffff); // ori r11, r11, real_addr@l
freeSlot->trampolin[2] = 0x7D6903A6; // mtctr r11
freeSlot->trampolin[3] = 0x4E800420; // bctr
DCFlushRange((void*)freeSlot->trampolin, sizeof(freeSlot->trampolin));
ICInvalidateRange((unsigned char*)freeSlot->trampolin, sizeof(freeSlot->trampolin));
freeSlot->id = trampolinId;
DCFlushRange((void*)&freeSlot->id, sizeof(freeSlot->id));
ICInvalidateRange((unsigned char*)&freeSlot->id, sizeof(freeSlot->id));
if(reloc_type == RELOC_TYPE_FIXED) {
freeSlot->status = RELOC_TRAMP_FIXED;
} else {
// Relocations for the imports may be overridden
freeSlot->status = RELOC_TRAMP_IMPORT_IN_PROGRESS;
}
uint32_t symbolValue = (uint32_t)&(freeSlot->trampolin[0]);
value = symbolValue + addend;
distance = static_cast<int32_t>(value) - static_cast<int32_t>(target);
DEBUG_FUNCTION_LINE("Created tramp\n");
}
}
if (distance & 3) {
DEBUG_FUNCTION_LINE("***RELOC ERROR %d: lower 2 bits must be zero before shifting.", -470022);
return false;
}
if (distance < 0 && (distance & 0xFE000000) != 0xFE000000) {
DEBUG_FUNCTION_LINE("***RELOC ERROR %d: upper 7 bits before shift must all be the same (1).", -470040);
return false;
}
if (distance >= 0 && (distance & 0xFE000000)) {
DEBUG_FUNCTION_LINE("***RELOC ERROR %d: upper 7 bits before shift must all be the same (0).", -470040);
return false;
}
*(int32_t *)target = (*(int32_t *)target & 0xfc000003) | (distance & 0x03fffffc);
break;
}
default:
DEBUG_FUNCTION_LINE("***ERROR: Unsupported Relocation_Add Type (%08X):", type);
return false;
}
return true;
}

50
source/utils/ElfUtils.h Normal file
View File

@ -0,0 +1,50 @@
#pragma once
#include <stdint.h>
#include "common/relocation_defines.h"
#ifdef __cplusplus
extern "C" {
#endif
int32_t LoadFileToMem(const char *relativefilepath, char **fileOut, uint32_t * sizeOut);
uint32_t load_loader_elf_from_sd(unsigned char* baseAddress, const char* relativePath);
uint32_t load_loader_elf(unsigned char* baseAddress, char * elf_data, uint32_t fileSize);
#define R_PPC_NONE 0
#define R_PPC_ADDR32 1
#define R_PPC_ADDR16_LO 4
#define R_PPC_ADDR16_HI 5
#define R_PPC_ADDR16_HA 6
#define R_PPC_REL24 10
#define R_PPC_REL14 11
#define R_PPC_DTPMOD32 68
#define R_PPC_DTPREL32 78
#define R_PPC_EMB_SDA21 109
#define R_PPC_EMB_RELSDA 116
#define R_PPC_DIAB_SDA21_LO 180
#define R_PPC_DIAB_SDA21_HI 181
#define R_PPC_DIAB_SDA21_HA 182
#define R_PPC_DIAB_RELSDA_LO 183
#define R_PPC_DIAB_RELSDA_HI 184
#define R_PPC_DIAB_RELSDA_HA 185
#define R_PPC_GHS_REL16_HA 251
#define R_PPC_GHS_REL16_HI 252
#define R_PPC_GHS_REL16_LO 253
// Masks for manipulating Power PC relocation targets
#define PPC_WORD32 0xFFFFFFFF
#define PPC_WORD30 0xFFFFFFFC
#define PPC_LOW24 0x03FFFFFC
#define PPC_LOW14 0x0020FFFC
#define PPC_HALF16 0xFFFF
#ifdef __cplusplus
}
#endif
class ElfUtils {
public:
static bool elfLinkOne(char type, size_t offset, int32_t addend, uint32_t destination, uint32_t symbol_addr, relocation_trampolin_entry_t * trampolin_data, uint32_t trampolin_data_length, RelocationType reloc_type, uint8_t trampolinId);
};

View File

@ -30,10 +30,15 @@
#include <stdlib.h>
#include <stdio.h>
#include <wchar.h>
#include "StringTools.h"
#include <strings.h>
#include <wut_types.h>
#include <stdio.h>
#include <utils/StringTools.h>
bool StringTools::EndsWith(const std::string& a, const std::string& b) {
if (b.size() > a.size()) return false;
BOOL StringTools::EndsWith(const std::string& a, const std::string& b) {
if (b.size() > a.size())
return false;
return std::equal(a.begin() + a.size() - b.size(), a.end(), b.begin());
}
@ -64,27 +69,23 @@ std::string StringTools::removeCharFromString(std::string& input,char toBeRemove
const char * StringTools::fmt(const char * format, ...) {
static char strChar[512];
strChar[0] = 0;
char * tmp = NULL;
va_list va;
va_start(va, format);
if((vasprintf(&tmp, format, va) >= 0) && tmp) {
snprintf(strChar, sizeof(strChar), tmp);
free(tmp);
if((vsprintf(strChar, format, va) >= 0)) {
va_end(va);
return (const char *) strChar;
}
va_end(va);
if(tmp)
free(tmp);
return NULL;
}
const wchar_t * StringTools::wfmt(const char * format, ...) {
static char tmp[512];
static wchar_t strWChar[512];
strWChar[0] = 0;
tmp[0] = 0;
if(!format)
return (const wchar_t *) strWChar;
@ -92,16 +93,12 @@ const wchar_t * StringTools::wfmt(const char * format, ...) {
if(strcmp(format, "") == 0)
return (const wchar_t *) strWChar;
char * tmp = NULL;
va_list va;
va_start(va, format);
if((vasprintf(&tmp, format, va) >= 0) && tmp) {
if((vsprintf(tmp, format, va) >= 0)) {
int bt;
int32_t strlength = strlen(tmp);
bt = mbstowcs(strWChar, tmp, (strlength < 512) ? strlength : 512 );
free(tmp);
tmp = 0;
if(bt > 0) {
strWChar[bt] = 0;
@ -110,48 +107,41 @@ const wchar_t * StringTools::wfmt(const char * format, ...) {
}
va_end(va);
if(tmp)
free(tmp);
return NULL;
}
int32_t StringTools::strprintf(std::string &str, const char * format, ...) {
static char tmp[512];
tmp[0] = 0;
int32_t result = 0;
char * tmp = NULL;
va_list va;
va_start(va, format);
if((vasprintf(&tmp, format, va) >= 0) && tmp) {
if((vsprintf(tmp, format, va) >= 0)) {
str = tmp;
result = str.size();
}
va_end(va);
if(tmp)
free(tmp);
return result;
}
std::string StringTools::strfmt(const char * format, ...) {
std::string str;
char * tmp = NULL;
static char tmp[512];
tmp[0] = 0;
va_list va;
va_start(va, format);
if((vasprintf(&tmp, format, va) >= 0) && tmp) {
if((vsprintf(tmp, format, va) >= 0)) {
str = tmp;
}
va_end(va);
if(tmp)
free(tmp);
return str;
}
bool StringTools::char2wchar_t(const char * strChar, wchar_t * dest) {
BOOL StringTools::char2wchar_t(const char * strChar, wchar_t * dest) {
if(!strChar || !dest)
return false;

View File

@ -0,0 +1,80 @@
/***************************************************************************
* Copyright (C) 2010
* by Dimok
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any
* damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any
* purpose, including commercial applications, and to alter it and
* redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you
* must not claim that you wrote the original software. If you use
* this software in a product, an acknowledgment in the product
* documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and
* must not be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*
* for WiiXplorer 2010
***************************************************************************/
#ifndef __STRING_TOOLS_H
#define __STRING_TOOLS_H
#include <vector>
#include <string>
#include <wut_types.h>
class StringTools {
public:
static BOOL EndsWith(const std::string& a, const std::string& b);
static const char * byte_to_binary(int32_t x);
static std::string removeCharFromString(std::string& input,char toBeRemoved);
static const char * fmt(const char * format, ...);
static const wchar_t * wfmt(const char * format, ...);
static int32_t strprintf(std::string &str, const char * format, ...);
static std::string strfmt(const char * format, ...);
static BOOL char2wchar_t(const char * src, wchar_t * dest);
static int32_t strtokcmp(const char * string, const char * compare, const char * separator);
static int32_t strextcmp(const char * string, const char * extension, char seperator);
static const char * FullpathToFilename(const char *path) {
if(!path)
return path;
const char * ptr = path;
const char * Filename = ptr;
while(*ptr != '\0') {
if(ptr[0] == '/' && ptr[1] != '\0')
Filename = ptr+1;
++ptr;
}
return Filename;
}
static void RemoveDoubleSlashs(std::string &str) {
uint32_t length = str.size();
//! clear path of double slashes
for(uint32_t i = 1; i < length; ++i) {
if(str[i-1] == '/' && str[i] == '/') {
str.erase(i, 1);
i--;
length--;
}
}
}
static std::vector<std::string> stringSplit(const std::string & value, const std::string & splitter);
};
#endif /* __STRING_TOOLS_H */

View File

@ -1,5 +1,5 @@
/****************************************************************************
* Copyright (C) 2016 Maschell
* Copyright (C) 2016-2020 Maschell
* With code from chadderz and dimok
*
* This program is free software: you can redistribute it and/or modify
@ -23,7 +23,7 @@
extern "C" {
#endif
#include "dynamic_libs/coreinit.h"
#include <coreinit/dynload.h>
/* Macros for libs */
#define LIB_CORE_INIT 0

View File

@ -21,45 +21,46 @@
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <coreinit/memorymap.h>
#include <coreinit/cache.h>
#include <coreinit/dynload.h>
#include "kernel/kernel_utils.h"
#include "function_patcher.h"
#include "logger.h"
#include "kernel/kernel_defs.h"
#include "kernel/kernel_utils.h"
#define LIB_CODE_RW_BASE_OFFSET 0xC1000000
#define CODE_RW_BASE_OFFSET 0x00000000
#define DEBUG_LOG_DYN 0
uint32_t acp_handle_internal = 0;
uint32_t aoc_handle_internal = 0;
uint32_t sound_handle_internal = 0;
uint32_t sound_handle_internal_old = 0;
uint32_t libcurl_handle_internal = 0;
uint32_t gx2_handle_internal = 0;
uint32_t nfp_handle_internal = 0;
uint32_t nn_act_handle_internal = 0;
uint32_t nn_nim_handle_internal = 0;
uint32_t nn_save_handle_internal = 0;
uint32_t ntag_handle_internal = 0;
uint32_t coreinit_handle_internal = 0;
uint32_t padscore_handle_internal = 0;
uint32_t proc_ui_handle_internal = 0;
uint32_t nsysnet_handle_internal = 0;
uint32_t sysapp_handle_internal = 0;
uint32_t syshid_handle_internal = 0;
uint32_t vpad_handle_internal = 0;
uint32_t vpadbase_handle_internal = 0;
OSDynLoad_Module acp_handle_internal = 0;
OSDynLoad_Module aoc_handle_internal = 0;
OSDynLoad_Module sound_handle_internal = 0;
OSDynLoad_Module sound_handle_internal_old = 0;
OSDynLoad_Module libcurl_handle_internal = 0;
OSDynLoad_Module gx2_handle_internal = 0;
OSDynLoad_Module nfp_handle_internal = 0;
OSDynLoad_Module nn_act_handle_internal = 0;
OSDynLoad_Module nn_nim_handle_internal = 0;
OSDynLoad_Module nn_save_handle_internal = 0;
OSDynLoad_Module ntag_handle_internal = 0;
OSDynLoad_Module coreinit_handle_internal = 0;
OSDynLoad_Module padscore_handle_internal = 0;
OSDynLoad_Module proc_ui_handle_internal = 0;
OSDynLoad_Module nsysnet_handle_internal = 0;
OSDynLoad_Module sysapp_handle_internal = 0;
OSDynLoad_Module syshid_handle_internal = 0;
OSDynLoad_Module vpad_handle_internal = 0;
OSDynLoad_Module vpadbase_handle_internal = 0;
/*
* Patches a function that is loaded at the start of each application. Its not required to restore, at least when they are really dynamic.
* "normal" functions should be patch with the normal patcher. Current Code by Maschell with the help of dimok. Orignal code by Chadderz.
*/
void PatchInvidualMethodHooks(hooks_magic_t method_hooks[],int32_t hook_information_size, volatile uint32_t dynamic_method_calls[]) {
InitAcquireOS();
resetLibs();
DEBUG_FUNCTION_LINE("Patching %d given functions\n",hook_information_size);
DEBUG_FUNCTION_LINE("Patching %d given functions",hook_information_size);
/* Patch branches to it. */
volatile uint32_t *space = &dynamic_method_calls[0];
@ -70,13 +71,13 @@ void PatchInvidualMethodHooks(hooks_magic_t method_hooks[],int32_t hook_informat
uint32_t instr_len = my_instr_len + skip_instr;
uint32_t flush_len = 4*instr_len;
for(int32_t i = 0; i < method_hooks_count; i++) {
DEBUG_FUNCTION_LINE("Patching %s ...",method_hooks[i].functionName);
log_printf("Patching %s ...",method_hooks[i].functionName);
if(method_hooks[i].functionType == STATIC_FUNCTION && method_hooks[i].alreadyPatched == 1) {
if(isDynamicFunction((uint32_t)OSEffectiveToPhysical(method_hooks[i].realAddr))) {
log_printf("The function %s is a dynamic function. Please fix that <3\n", method_hooks[i].functionName);
log_printf("The function %s is a dynamic function. Please fix that <3", method_hooks[i].functionName);
method_hooks[i].functionType = DYNAMIC_FUNCTION;
} else {
log_printf("Skipping %s, its already patched\n", method_hooks[i].functionName);
log_printf("Skipping %s, its already patched", method_hooks[i].functionName);
space += instr_len;
continue;
}
@ -89,25 +90,25 @@ void PatchInvidualMethodHooks(hooks_magic_t method_hooks[],int32_t hook_informat
uint32_t real_addr = GetAddressOfFunction(method_hooks[i].functionName,method_hooks[i].library);
if(!real_addr) {
log_printf("\n");
DEBUG_FUNCTION_LINE("OSDynLoad_FindExport failed for %s\n", method_hooks[i].functionName);
log_printf("");
DEBUG_FUNCTION_LINE("OSDynLoad_FindExport failed for %s", method_hooks[i].functionName);
space += instr_len;
continue;
}
if(DEBUG_LOG_DYN) {
DEBUG_FUNCTION_LINE("%s is located at %08X!\n", method_hooks[i].functionName,real_addr);
DEBUG_FUNCTION_LINE("%s is located at %08X!", method_hooks[i].functionName,real_addr);
}
physical = (uint32_t)OSEffectiveToPhysical(real_addr);
if(!physical) {
log_printf("Error. Something is wrong with the physical address\n");
log_printf("Error. Something is wrong with the physical address");
space += instr_len;
continue;
}
if(DEBUG_LOG_DYN) {
DEBUG_FUNCTION_LINE("%s physical is located at %08X!\n", method_hooks[i].functionName,physical);
DEBUG_FUNCTION_LINE("%s physical is located at %08X!", method_hooks[i].functionName,physical);
}
*(volatile uint32_t *)(call_addr) = (uint32_t)(space) - CODE_RW_BASE_OFFSET;
@ -132,13 +133,13 @@ void PatchInvidualMethodHooks(hooks_magic_t method_hooks[],int32_t hook_informat
method_hooks[i].realAddr = real_addr;
method_hooks[i].restoreInstruction = *(space-1);
if(DEBUG_LOG_DYN) {
DEBUG_FUNCTION_LINE("method_hooks[i].realAddr = %08X!\n", method_hooks[i].realAddr);
DEBUG_FUNCTION_LINE("method_hooks[i].realAddr = %08X!", method_hooks[i].realAddr);
}
if(DEBUG_LOG_DYN) {
DEBUG_FUNCTION_LINE("method_hooks[i].restoreInstruction = %08X!\n",method_hooks[i].restoreInstruction) ;
DEBUG_FUNCTION_LINE("method_hooks[i].restoreInstruction = %08X!",method_hooks[i].restoreInstruction) ;
}
} else {
log_printf("Error. Can't save %s for restoring!\n", method_hooks[i].functionName);
log_printf("Error. Can't save %s for restoring!", method_hooks[i].functionName);
}
//adding jump to real function thx @ dimok for the assembler code
@ -175,43 +176,42 @@ void PatchInvidualMethodHooks(hooks_magic_t method_hooks[],int32_t hook_informat
log_printf("done!\n");
}
DEBUG_FUNCTION_LINE("Done with patching given functions!\n");
DEBUG_FUNCTION_LINE("Done with patching given functions!");
}
/* ****************************************************************** */
/* RESTORE ORIGINAL INSTRUCTIONS */
/* ****************************************************************** */
void RestoreInvidualInstructions(hooks_magic_t method_hooks[],int32_t hook_information_size) {
InitAcquireOS();
resetLibs();
DEBUG_FUNCTION_LINE("Restoring given functions!\n");
DEBUG_FUNCTION_LINE("Restoring given functions!");
int32_t method_hooks_count = hook_information_size;
for(int32_t i = 0; i < method_hooks_count; i++) {
DEBUG_FUNCTION_LINE("Restoring %s... ",method_hooks[i].functionName);
if(method_hooks[i].restoreInstruction == 0 || method_hooks[i].realAddr == 0) {
log_printf("I dont have the information for the restore =( skip\n");
log_printf("I dont have the information for the restore =( skip");
continue;
}
uint32_t real_addr = GetAddressOfFunction(method_hooks[i].functionName,method_hooks[i].library);
if(!real_addr) {
log_printf("OSDynLoad_FindExport failed for %s\n", method_hooks[i].functionName);
log_printf("OSDynLoad_FindExport failed for %s", method_hooks[i].functionName);
continue;
}
uint32_t physical = (uint32_t)OSEffectiveToPhysical(real_addr);
if(!physical) {
log_printf("Something is wrong with the physical address\n");
log_printf("Something is wrong with the physical address");
continue;
}
if(isDynamicFunction(physical)) {
log_printf("Its a dynamic function. We don't need to restore it!\n",method_hooks[i].functionName);
log_printf("Its a dynamic function. We don't need to restore it!",method_hooks[i].functionName);
} else {
physical = (uint32_t)OSEffectiveToPhysical(method_hooks[i].realAddr); //When its an static function, we need to use the old location
if(DEBUG_LOG_DYN) {
DEBUG_FUNCTION_LINE("Restoring %08X to %08X\n",(uint32_t)method_hooks[i].restoreInstruction,physical);
DEBUG_FUNCTION_LINE("Restoring %08X to %08X",(uint32_t)method_hooks[i].restoreInstruction,physical);
}
uint32_t targetAddr = (uint32_t)&method_hooks[i].restoreInstruction;
if(targetAddr < 0x00800000 || targetAddr >= 0x01000000) {
@ -222,15 +222,15 @@ void RestoreInvidualInstructions(hooks_magic_t method_hooks[],int32_t hook_infor
KernelCopyData(physical,targetAddr, 4);
if(DEBUG_LOG_DYN) {
DEBUG_FUNCTION_LINE("ICInvalidateRange %08X\n",(void*)method_hooks[i].realAddr);
DEBUG_FUNCTION_LINE("ICInvalidateRange %08X",(void*)method_hooks[i].realAddr);
}
ICInvalidateRange((void*)method_hooks[i].realAddr, 4);
log_printf("done\n");
log_printf("done");
}
method_hooks[i].alreadyPatched = 0; // In case a
}
DEBUG_FUNCTION_LINE("Done with restoring given functions!\n");
DEBUG_FUNCTION_LINE("Done with restoring given functions!");
}
int32_t isDynamicFunction(uint32_t physicalAddress) {
@ -261,272 +261,272 @@ uint32_t GetAddressOfFunction(const char * functionName,uint32_t library) {
}
*/
uint32_t rpl_handle = 0;
OSDynLoad_Module rpl_handle = 0;
if(library == LIB_CORE_INIT) {
if(DEBUG_LOG_DYN) {
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_CORE_INIT\n", functionName);
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_CORE_INIT", functionName);
}
if(coreinit_handle_internal == 0) {
OSDynLoad_Acquire("coreinit.rpl", &coreinit_handle_internal);
}
if(coreinit_handle_internal == 0) {
DEBUG_FUNCTION_LINE("LIB_CORE_INIT failed to acquire\n");
DEBUG_FUNCTION_LINE("LIB_CORE_INIT failed to acquire");
return 0;
}
rpl_handle = coreinit_handle_internal;
} else if(library == LIB_NSYSNET) {
if(DEBUG_LOG_DYN) {
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_NSYSNET\n", functionName);
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_NSYSNET", functionName);
}
if(nsysnet_handle_internal == 0) {
OSDynLoad_Acquire("nsysnet.rpl", &nsysnet_handle_internal);
}
if(nsysnet_handle_internal == 0) {
DEBUG_FUNCTION_LINE("LIB_NSYSNET failed to acquire\n");
DEBUG_FUNCTION_LINE("LIB_NSYSNET failed to acquire");
return 0;
}
rpl_handle = nsysnet_handle_internal;
} else if(library == LIB_GX2) {
if(DEBUG_LOG_DYN) {
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_GX2\n", functionName);
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_GX2", functionName);
}
if(gx2_handle_internal == 0) {
OSDynLoad_Acquire("gx2.rpl", &gx2_handle_internal);
}
if(gx2_handle_internal == 0) {
DEBUG_FUNCTION_LINE("LIB_GX2 failed to acquire\n");
DEBUG_FUNCTION_LINE("LIB_GX2 failed to acquire");
return 0;
}
rpl_handle = gx2_handle_internal;
} else if(library == LIB_AOC) {
if(DEBUG_LOG_DYN) {
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_AOC\n", functionName);
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_AOC", functionName);
}
if(aoc_handle_internal == 0) {
OSDynLoad_Acquire("nn_aoc.rpl", &aoc_handle_internal);
}
if(aoc_handle_internal == 0) {
DEBUG_FUNCTION_LINE("LIB_AOC failed to acquire\n");
DEBUG_FUNCTION_LINE("LIB_AOC failed to acquire");
return 0;
}
rpl_handle = aoc_handle_internal;
} else if(library == LIB_AX) {
if(DEBUG_LOG_DYN) {
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_AX\n", functionName);
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_AX", functionName);
}
if(sound_handle_internal == 0) {
OSDynLoad_Acquire("sndcore2.rpl", &sound_handle_internal);
}
if(sound_handle_internal == 0) {
DEBUG_FUNCTION_LINE("LIB_AX failed to acquire\n");
DEBUG_FUNCTION_LINE("LIB_AX failed to acquire");
return 0;
}
rpl_handle = sound_handle_internal;
} else if(library == LIB_AX_OLD) {
if(DEBUG_LOG_DYN) {
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_AX_OLD\n", functionName);
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_AX_OLD", functionName);
}
if(sound_handle_internal_old == 0) {
OSDynLoad_Acquire("snd_core.rpl", &sound_handle_internal_old);
}
if(sound_handle_internal_old == 0) {
DEBUG_FUNCTION_LINE("LIB_AX_OLD failed to acquire\n");
DEBUG_FUNCTION_LINE("LIB_AX_OLD failed to acquire");
return 0;
}
rpl_handle = sound_handle_internal_old;
} else if(library == LIB_FS) {
if(DEBUG_LOG_DYN) {
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_FS\n", functionName);
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_FS", functionName);
}
if(coreinit_handle_internal == 0) {
OSDynLoad_Acquire("coreinit.rpl", &coreinit_handle_internal);
}
if(coreinit_handle_internal == 0) {
DEBUG_FUNCTION_LINE("LIB_FS failed to acquire\n");
DEBUG_FUNCTION_LINE("LIB_FS failed to acquire");
return 0;
}
rpl_handle = coreinit_handle_internal;
} else if(library == LIB_OS) {
if(DEBUG_LOG_DYN) {
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_OS\n", functionName);
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_OS", functionName);
}
if(coreinit_handle_internal == 0) {
OSDynLoad_Acquire("coreinit.rpl", &coreinit_handle_internal);
}
if(coreinit_handle_internal == 0) {
DEBUG_FUNCTION_LINE("LIB_OS failed to acquire\n");
DEBUG_FUNCTION_LINE("LIB_OS failed to acquire");
return 0;
}
rpl_handle = coreinit_handle_internal;
} else if(library == LIB_PADSCORE) {
if(DEBUG_LOG_DYN) {
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_PADSCORE\n", functionName);
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_PADSCORE", functionName);
}
if(padscore_handle_internal == 0) {
OSDynLoad_Acquire("padscore.rpl", &padscore_handle_internal);
}
if(padscore_handle_internal == 0) {
DEBUG_FUNCTION_LINE("LIB_PADSCORE failed to acquire\n");
DEBUG_FUNCTION_LINE("LIB_PADSCORE failed to acquire");
return 0;
}
rpl_handle = padscore_handle_internal;
} else if(library == LIB_SOCKET) {
if(DEBUG_LOG_DYN) {
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_SOCKET\n", functionName);
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_SOCKET", functionName);
}
if(nsysnet_handle_internal == 0) {
OSDynLoad_Acquire("nsysnet.rpl", &nsysnet_handle_internal);
}
if(nsysnet_handle_internal == 0) {
DEBUG_FUNCTION_LINE("LIB_SOCKET failed to acquire\n");
DEBUG_FUNCTION_LINE("LIB_SOCKET failed to acquire");
return 0;
}
rpl_handle = nsysnet_handle_internal;
} else if(library == LIB_SYS) {
if(DEBUG_LOG_DYN) {
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_SYS\n", functionName);
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_SYS", functionName);
}
if(sysapp_handle_internal == 0) {
OSDynLoad_Acquire("sysapp.rpl", &sysapp_handle_internal);
}
if(sysapp_handle_internal == 0) {
DEBUG_FUNCTION_LINE("LIB_SYS failed to acquire\n");
DEBUG_FUNCTION_LINE("LIB_SYS failed to acquire");
return 0;
}
rpl_handle = sysapp_handle_internal;
} else if(library == LIB_VPAD) {
if(DEBUG_LOG_DYN) {
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_VPAD\n", functionName);
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_VPAD", functionName);
}
if(vpad_handle_internal == 0) {
OSDynLoad_Acquire("vpad.rpl", &vpad_handle_internal);
}
if(vpad_handle_internal == 0) {
DEBUG_FUNCTION_LINE("LIB_VPAD failed to acquire\n");
DEBUG_FUNCTION_LINE("LIB_VPAD failed to acquire");
return 0;
}
rpl_handle = vpad_handle_internal;
} else if(library == LIB_NN_ACP) {
if(DEBUG_LOG_DYN) {
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_NN_ACP\n", functionName);
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_NN_ACP", functionName);
}
if(acp_handle_internal == 0) {
OSDynLoad_Acquire("nn_acp.rpl", &acp_handle_internal);
}
if(acp_handle_internal == 0) {
DEBUG_FUNCTION_LINE("LIB_NN_ACP failed to acquire\n");
DEBUG_FUNCTION_LINE("LIB_NN_ACP failed to acquire");
return 0;
}
rpl_handle = acp_handle_internal;
} else if(library == LIB_SYSHID) {
if(DEBUG_LOG_DYN) {
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_SYSHID\n", functionName);
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_SYSHID", functionName);
}
if(syshid_handle_internal == 0) {
OSDynLoad_Acquire("nsyshid.rpl", &syshid_handle_internal);
}
if(syshid_handle_internal == 0) {
DEBUG_FUNCTION_LINE("LIB_SYSHID failed to acquire\n");
DEBUG_FUNCTION_LINE("LIB_SYSHID failed to acquire");
return 0;
}
rpl_handle = syshid_handle_internal;
} else if(library == LIB_VPADBASE) {
if(DEBUG_LOG_DYN) {
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_VPADBASE\n", functionName);
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_VPADBASE", functionName);
}
if(vpadbase_handle_internal == 0) {
OSDynLoad_Acquire("vpadbase.rpl", &vpadbase_handle_internal);
}
if(vpadbase_handle_internal == 0) {
DEBUG_FUNCTION_LINE("LIB_VPADBASE failed to acquire\n");
DEBUG_FUNCTION_LINE("LIB_VPADBASE failed to acquire");
return 0;
}
rpl_handle = vpadbase_handle_internal;
} else if(library == LIB_PROC_UI) {
if(DEBUG_LOG_DYN) {
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_PROC_UI\n", functionName);
DEBUG_FUNCTION_LINE("FindExport of %s! From LIB_PROC_UI", functionName);
}
if(proc_ui_handle_internal == 0) {
OSDynLoad_Acquire("proc_ui.rpl", &proc_ui_handle_internal);
}
if(proc_ui_handle_internal == 0) {
DEBUG_FUNCTION_LINE("LIB_PROC_UI failed to acquire\n");
DEBUG_FUNCTION_LINE("LIB_PROC_UI failed to acquire");
return 0;
}
rpl_handle = proc_ui_handle_internal;
} else if(library == LIB_NTAG) {
if(DEBUG_LOG_DYN) {
log_printf("FindExport of %s! From LIB_NTAG\n", functionName);
log_printf("FindExport of %s! From LIB_NTAG", functionName);
}
if(ntag_handle_internal == 0) {
OSDynLoad_Acquire("ntag.rpl", &ntag_handle_internal);
}
if(ntag_handle_internal == 0) {
log_print("LIB_NTAG failed to acquire\n");
log_print("LIB_NTAG failed to acquire");
return 0;
}
rpl_handle = ntag_handle_internal;
} else if(library == LIB_NFP) {
if(DEBUG_LOG_DYN) {
log_printf("FindExport of %s! From LIB_NFP\n", functionName);
log_printf("FindExport of %s! From LIB_NFP", functionName);
}
if(nfp_handle_internal == 0) {
OSDynLoad_Acquire("nn_nfp.rpl", &nfp_handle_internal);
}
if(nfp_handle_internal == 0) {
log_print("LIB_NFP failed to acquire\n");
log_print("LIB_NFP failed to acquire");
return 0;
}
rpl_handle = nfp_handle_internal;
} else if(library == LIB_SAVE) {
if(DEBUG_LOG_DYN) {
log_printf("FindExport of %s! From LIB_SAVE\n", functionName);
log_printf("FindExport of %s! From LIB_SAVE", functionName);
}
if(nn_save_handle_internal == 0) {
OSDynLoad_Acquire("nn_save.rpl", &nn_save_handle_internal);
}
if(nn_save_handle_internal == 0) {
log_print("LIB_SAVE failed to acquire\n");
log_print("LIB_SAVE failed to acquire");
return 0;
}
rpl_handle = nn_save_handle_internal;
} else if(library == LIB_ACT) {
if(DEBUG_LOG_DYN) {
log_printf("FindExport of %s! From LIB_ACT\n", functionName);
log_printf("FindExport of %s! From LIB_ACT", functionName);
}
if(nn_act_handle_internal == 0) {
OSDynLoad_Acquire("nn_act.rpl", &nn_act_handle_internal);
}
if(nn_act_handle_internal == 0) {
log_print("LIB_ACT failed to acquire\n");
log_print("LIB_ACT failed to acquire");
return 0;
}
rpl_handle = nn_act_handle_internal;
} else if(library == LIB_NIM) {
if(DEBUG_LOG_DYN) {
log_printf("FindExport of %s! From LIB_NIM\n", functionName);
log_printf("FindExport of %s! From LIB_NIM", functionName);
}
if(nn_nim_handle_internal == 0) {
OSDynLoad_Acquire("nn_nim.rpl", &nn_nim_handle_internal);
}
if(nn_nim_handle_internal == 0) {
log_print("LIB_NIM failed to acquire\n");
log_print("LIB_NIM failed to acquire");
return 0;
}
rpl_handle = nn_nim_handle_internal;
}
if(!rpl_handle) {
DEBUG_FUNCTION_LINE("Failed to find the RPL handle for %s\n", functionName);
DEBUG_FUNCTION_LINE("Failed to find the RPL handle for %s", functionName);
return 0;
}
OSDynLoad_FindExport(rpl_handle, 0, functionName, &real_addr);
OSDynLoad_FindExport(rpl_handle, 0, functionName, (void**) &real_addr);
if(!real_addr) {
OSDynLoad_FindExport(rpl_handle, 1, functionName, &real_addr);
OSDynLoad_FindExport(rpl_handle, 1, functionName, (void**) &real_addr);
if(!real_addr) {
DEBUG_FUNCTION_LINE("OSDynLoad_FindExport failed for %s\n", functionName);
DEBUG_FUNCTION_LINE("OSDynLoad_FindExport failed for %s", functionName);
return 0;
}
}

View File

@ -3,23 +3,22 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "logger.h"
#include "dynamic_libs/coreinit.h"
#include "dynamic_libs/socket_functions.h"
#include <utils/logger.h>
#include <nsysnet/socket.h>
#include <coreinit/debug.h>
#include <coreinit/systeminfo.h>
#include <coreinit/thread.h>
static int log_socket __attribute__((section(".data")))= -1;
static struct sockaddr_in connect_addr __attribute__((section(".data")));
static volatile int log_lock __attribute__((section(".data"))) = 0;
void log_init() {
InitOSFunctionPointers();
InitSocketFunctionPointers();
void log_init_() {
int broadcastEnable = 1;
log_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (log_socket < 0){
if (log_socket < 0)
return;
}
setsockopt(log_socket, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable));
@ -29,14 +28,14 @@ void log_init() {
connect_addr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
}
void log_print(const char *str) {
void log_print_(const char *str) {
// socket is always 0 initially as it is in the BSS
if(log_socket < 0) {
return;
}
while(log_lock)
os_usleep(1000);
OSSleepTicks(OSMicrosecondsToTicks(1000));
log_lock = 1;
int len = strlen(str);
@ -55,31 +54,29 @@ void log_print(const char *str) {
}
void OSFatal_printf(const char *format, ...) {
char * tmp = NULL;
char tmp[512];
tmp[0] = 0;
va_list va;
va_start(va, format);
if((vasprintf(&tmp, format, va) >= 0) && tmp) {
if((vsprintf(tmp, format, va) >= 0)) {
OSFatal(tmp);
}
va_end(va);
}
void log_printf(const char *format, ...) {
void log_printf_(const char *format, ...) {
if(log_socket < 0) {
return;
}
char * tmp = NULL;
char tmp[512];
tmp[0] = 0;
va_list va;
va_start(va, format);
if((vasprintf(&tmp, format, va) >= 0) && tmp) {
log_print(tmp);
if((vsprintf(tmp, format, va) >= 0)) {
log_print_(tmp);
}
va_end(va);
if(tmp)
free(tmp);
}

View File

@ -7,10 +7,10 @@ extern "C" {
#include <string.h>
void log_init();
void log_init_();
//void log_deinit_(void);
void log_print(const char *str);
void log_printf(const char *format, ...);
void log_print_(const char *str);
void log_printf_(const char *format, ...);
void OSFatal_printf(const char *format, ...);
#define __FILENAME_X__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
@ -20,11 +20,17 @@ void OSFatal_printf(const char *format, ...);
OSFatal_printf("[%s]%s@L%04d: " FMT "",__FILENAME__,__FUNCTION__, __LINE__, ## ARGS); \
} while (0)
#define DEBUG_FUNCTION_LINE(FMT, ARGS...)do { \
log_printf("[%23s]%30s@L%04d: " FMT "",__FILENAME__,__FUNCTION__, __LINE__, ## ARGS); \
} while (0)
#define log_init() log_init_()
//#define log_deinit() log_deinit_()
#define log_print(str) log_print_(str)
#define log_printf(FMT, ARGS...) log_printf_(FMT, ## ARGS);
#define DEBUG_FUNCTION_LINE(FMT, ARGS...)do { \
log_printf("[%23s]%30s@L%04d: " FMT "\n",__FILENAME__,__FUNCTION__, __LINE__, ## ARGS); \
} while (0)
#ifdef __cplusplus
}
#endif

View File

@ -4,8 +4,7 @@
#include <stddef.h>
#include <stdio.h>
#include <malloc.h>
#include "utils.h"
#include "logger.h"
#include "utils/logger.h"
// https://gist.github.com/ccbrown/9722406
void dumpHex(const void* data, size_t size) {

40
source/utils/utils.h Normal file
View File

@ -0,0 +1,40 @@
#ifndef __UTILS_H_
#define __UTILS_H_
#include <malloc.h>
#ifdef __cplusplus
extern "C" {
#endif
#define LIMIT(x, min, max) \
({ \
typeof( x ) _x = x; \
typeof( min ) _min = min; \
typeof( max ) _max = max; \
( ( ( _x ) < ( _min ) ) ? ( _min ) : ( ( _x ) > ( _max ) ) ? ( _max) : ( _x ) ); \
})
#define DegToRad(a) ( (a) * 0.01745329252f )
#define RadToDeg(a) ( (a) * 57.29577951f )
#define ALIGN4(x) (((x) + 3) & ~3)
#define ALIGN32(x) (((x) + 31) & ~31)
// those work only in powers of 2
#define ROUNDDOWN(val, align) ((val) & ~(align-1))
#define ROUNDUP(val, align) ROUNDDOWN(((val) + (align-1)), align)
#define le16(i) ((((uint16_t) ((i) & 0xFF)) << 8) | ((uint16_t) (((i) & 0xFF00) >> 8)))
#define le32(i) ((((uint32_t)le16((i) & 0xFFFF)) << 16) | ((uint32_t)le16(((i) & 0xFFFF0000) >> 16)))
#define le64(i) ((((uint64_t)le32((i) & 0xFFFFFFFFLL)) << 32) | ((uint64_t)le32(((i) & 0xFFFFFFFF00000000LL) >> 32)))
//Needs to have log_init() called beforehand.
void dumpHex(const void* data, size_t size);
#ifdef __cplusplus
}
#endif
#endif // __UTILS_H_

View File

@ -1,24 +0,0 @@
#include "retain_vars.h"
#include "utils/overlay_helper.h"
replacement_data_t gbl_replacement_data __attribute__((section(".data")));
to_link_and_load_data_t gbl_to_link_and_load_data[MAXIMUM_PLUGINS] __attribute__((section(".data")));
dyn_linking_relocation_data_t gbl_dyn_linking_data __attribute__((section(".data")));
bool gInBackground __attribute__((section(".data"))) = false;
bool g_NotInLoader __attribute__((section(".data"))) = true;
uint64_t gGameTitleID __attribute__((section(".data"))) = 0;
volatile uint8_t gSDInitDone __attribute__((section(".data"))) = 0;
struct buffer_store drc_store __attribute__((section(".data")));
struct buffer_store tv_store __attribute__((section(".data")));
char gbl_common_data[0x20000] __attribute__((section(".data")));
char * gbl_common_data_ptr __attribute__((section(".data"))) = gbl_common_data;
/*
GX2ColorBuffer g_vid_main_cbuf __attribute__((section(".data")));
GX2Texture g_vid_drcTex __attribute__((section(".data")));
GX2Sampler g_vid_sampler __attribute__((section(".data")));
GX2Texture g_vid_tvTex __attribute__((section(".data")));
GX2ContextState* g_vid_ownContextState __attribute__((section(".data")));
GX2ContextState* g_vid_originalContextSave __attribute__((section(".data")))= NULL;*/

View File

@ -1,32 +0,0 @@
#ifndef RETAINS_VARS_H_
#define RETAINS_VARS_H_
#include "patcher/function_patcher.h"
#include "plugin/dynamic_linking_defines.h"
#include "utils/overlay_helper.h"
//#include <dynamic_libs/gx2_functions.h>
extern replacement_data_t gbl_replacement_data;
extern to_link_and_load_data_t gbl_to_link_and_load_data[MAXIMUM_PLUGINS];
extern dyn_linking_relocation_data_t gbl_dyn_linking_data;
extern bool g_NotInLoader;
extern bool gInBackground;
extern uint64_t gGameTitleID;
extern volatile uint8_t gSDInitDone;
extern void * ntfs_mounts;
extern int32_t ntfs_mount_count;
extern struct buffer_store drc_store;
extern struct buffer_store tv_store;
/*
extern GX2ColorBuffer g_vid_main_cbuf;
extern GX2Texture g_vid_drcTex;
extern GX2Texture g_vid_tvTex;
extern GX2ContextState* g_vid_ownContextState;
extern GX2ContextState* g_vid_originalContextSave;
extern GX2Sampler g_vid_sampler;*/
#endif // RETAINS_VARS_H_

View File

@ -1,166 +0,0 @@
#include "coreinit.h"
uint32_t coreinit_handle __attribute__((section(".data"))) = 0;
EXPORT_DECL(void, DCInvalidateRange, void *buffer, uint32_t length);
EXPORT_DECL(void, DCFlushRange, const void *addr, uint32_t length);
EXPORT_DECL(void, DCStoreRange, const void *addr, uint32_t length);
EXPORT_DECL(void, ICInvalidateRange, const void *addr, uint32_t length);
EXPORT_DECL(void*, OSEffectiveToPhysical, uint32_t);
EXPORT_DECL(void*, OSSleepTicks, uint64_t);
EXPORT_DECL(int32_t, OSCreateThread, OSThread *thread, int32_t (*callback)(int32_t, void*), int32_t argc, void *args, uint32_t stack, uint32_t stack_size, int32_t priority, uint32_t attr);
EXPORT_DECL(int32_t, OSResumeThread, OSThread *thread);
EXPORT_DECL(int32_t, OSSuspendThread, OSThread *thread);
EXPORT_DECL(int32_t, OSIsThreadTerminated, OSThread *thread);
EXPORT_DECL(int32_t, OSIsThreadSuspended, OSThread *thread);
EXPORT_DECL(int32_t, OSSetThreadPriority, OSThread * thread, int32_t priority);
EXPORT_DECL(int32_t, OSJoinThread, OSThread * thread, int32_t * ret_val);
EXPORT_DECL(void, OSDetachThread, OSThread * thread);
EXPORT_DECL(OSThread *,OSGetCurrentThread,void);
EXPORT_DECL(const char *,OSGetThreadName,OSThread * thread);
EXPORT_DECL(void,OSGetActiveThreadLink,OSThread * thread, void* link);
EXPORT_DECL(uint32_t,OSGetThreadAffinity,OSThread * thread);
EXPORT_DECL(int32_t,OSGetThreadPriority,OSThread * thread);
EXPORT_DECL(void,OSSetThreadName,OSThread * thread, const char *name);
EXPORT_DECL(int32_t, OSGetCoreId, void);
EXPORT_DECL(int32_t, OSEnableInterrupts, void);
EXPORT_DECL(void, OSRestoreInterrupts, int32_t);
EXPORT_DECL(int32_t, MEMCreateExpHeapEx, void *heap, uint32_t size, uint16_t flags);
EXPORT_DECL(void*, MEMAllocFromExpHeapEx, int32_t heap, uint32_t size, int alignment);
EXPORT_DECL(void, MEMFreeToExpHeap, int32_t heap, void * block);
EXPORT_DECL(OSMessageQueue *, OSGetSystemMessageQueue, void);
EXPORT_DECL(void, OSEnableHomeButtonMenu, int32_t);
EXPORT_VAR(uint32_t *, pMEMAllocFromDefaultHeapEx);
EXPORT_VAR(uint32_t *, pMEMAllocFromDefaultHeap);
EXPORT_VAR(uint32_t *, pMEMFreeToDefaultHeap);
EXPORT_DECL(int32_t, OSIsHomeButtonMenuEnabled, void);
EXPORT_DECL(uint64_t, OSGetTitleID, void);
EXPORT_DECL(void,OSScreenInit,void);
EXPORT_DECL(unsigned int, OSScreenGetBufferSizeEx,unsigned int bufferNum);
EXPORT_DECL(unsigned int, OSScreenSetBufferEx,unsigned int bufferNum, void * addr);
EXPORT_DECL(unsigned int, OSScreenFlipBuffersEx,unsigned int x);
EXPORT_DECL(int32_t, OSScreenEnableEx,uint32_t bufferNum, int32_t enable);
EXPORT_DECL(int32_t, OSScreenPutFontEx,uint32_t bufferNum, uint32_t posX, uint32_t posY, const char * buffer);
EXPORT_DECL(unsigned int, OSScreenClearBufferEx,unsigned int bufferNum, unsigned int temp);
EXPORT_DECL(void, OSInitMutex, void* mutex);
EXPORT_DECL(void, OSLockMutex, void* mutex);
EXPORT_DECL(void, OSUnlockMutex, void* mutex);
EXPORT_DECL(int32_t, OSTryLockMutex, void* mutex);
EXPORT_DECL(void, OSInitEvent, OSEvent *event, int32_t value, OSEventMode mode);
EXPORT_DECL(void, OSSignalEvent, OSEvent *event);
EXPORT_DECL(void, OSWaitEvent, OSEvent *event);
EXPORT_DECL(void, OSResetEvent, OSEvent *event);
EXPORT_DECL(int32_t, OSReceiveMessage, OSMessageQueue *, OSMessage * , int32_t);
EXPORT_DECL(int32_t, OSSendMessage, OSMessageQueue *, OSMessage * , int32_t);
void _os_find_export(uint32_t handle, const char *funcName, void *funcPointer) {
OSDynLoad_FindExport(handle, 0, funcName, funcPointer);
if(!*(uint32_t *)funcPointer) {
/*
* This is effectively OSFatal("Function %s is NULL", funcName),
* but we can't rely on any library functions like snprintf or
* strcpy at this point.
*
* Buffer bounds are not checked. Beware!
*/
char buf[256], *bufp = buf;
const char a[] = "Function ", b[] = " is NULL", *p;
unsigned int i;
for (i = 0; i < sizeof(a) - 1; i++)
*bufp++ = a[i];
for (p = funcName; *p; p++)
*bufp++ = *p;
for (i = 0; i < sizeof(b) - 1; i++)
*bufp++ = b[i];
*bufp++ = '\0';
OSFatal(buf);
}
}
void InitAcquireOS() {
OSDynLoad_Acquire("coreinit.rpl", &coreinit_handle);
}
void InitOSFunctionPointers(void) {
if(coreinit_handle != 0){
return;
}
uint32_t funcPointer = 0;
InitAcquireOS();
OS_FIND_EXPORT(coreinit_handle, OSInitMutex);
OS_FIND_EXPORT(coreinit_handle, OSLockMutex);
OS_FIND_EXPORT(coreinit_handle, OSUnlockMutex);
OS_FIND_EXPORT(coreinit_handle, OSTryLockMutex);
OS_FIND_EXPORT(coreinit_handle, OSScreenInit);
OS_FIND_EXPORT(coreinit_handle, OSScreenGetBufferSizeEx);
OS_FIND_EXPORT(coreinit_handle, OSScreenSetBufferEx);
OS_FIND_EXPORT(coreinit_handle, OSScreenFlipBuffersEx);
OS_FIND_EXPORT(coreinit_handle, OSScreenEnableEx);
OS_FIND_EXPORT(coreinit_handle, OSScreenPutFontEx);
OS_FIND_EXPORT(coreinit_handle, OSScreenClearBufferEx);
OS_FIND_EXPORT(coreinit_handle, OSEnableHomeButtonMenu);
OS_FIND_EXPORT(coreinit_handle, OSGetSystemMessageQueue);
OS_FIND_EXPORT(coreinit_handle, OSIsHomeButtonMenuEnabled);
OS_FIND_EXPORT(coreinit_handle, DCInvalidateRange);
OS_FIND_EXPORT(coreinit_handle, DCFlushRange);
OS_FIND_EXPORT(coreinit_handle, DCStoreRange);
OS_FIND_EXPORT(coreinit_handle, ICInvalidateRange);
OS_FIND_EXPORT(coreinit_handle, OSEffectiveToPhysical);
OS_FIND_EXPORT(coreinit_handle, OSSleepTicks);
OS_FIND_EXPORT(coreinit_handle, MEMCreateExpHeapEx);
OS_FIND_EXPORT(coreinit_handle, MEMAllocFromExpHeapEx);
OS_FIND_EXPORT(coreinit_handle, MEMFreeToExpHeap);
OS_FIND_EXPORT(coreinit_handle, OSGetTitleID);
OS_FIND_EXPORT(coreinit_handle, OSCreateThread);
OS_FIND_EXPORT(coreinit_handle, OSResumeThread);
OS_FIND_EXPORT(coreinit_handle, OSSuspendThread);
OS_FIND_EXPORT(coreinit_handle, OSIsThreadTerminated);
OS_FIND_EXPORT(coreinit_handle, OSIsThreadSuspended);
OS_FIND_EXPORT(coreinit_handle, OSJoinThread);
OS_FIND_EXPORT(coreinit_handle, OSSetThreadPriority);
OS_FIND_EXPORT(coreinit_handle, OSDetachThread);
OS_FIND_EXPORT(coreinit_handle, OSGetCurrentThread);
OS_FIND_EXPORT(coreinit_handle, OSGetThreadName);
OS_FIND_EXPORT(coreinit_handle, OSGetActiveThreadLink);
OS_FIND_EXPORT(coreinit_handle, OSGetThreadAffinity);
OS_FIND_EXPORT(coreinit_handle, OSGetThreadPriority);
OS_FIND_EXPORT(coreinit_handle, OSSetThreadName);
OS_FIND_EXPORT(coreinit_handle, OSGetCoreId);
OS_FIND_EXPORT(coreinit_handle, OSEnableInterrupts);
OS_FIND_EXPORT(coreinit_handle, OSRestoreInterrupts);
OS_FIND_EXPORT(coreinit_handle, OSInitEvent);
OS_FIND_EXPORT(coreinit_handle, OSSignalEvent);
OS_FIND_EXPORT(coreinit_handle, OSWaitEvent);
OS_FIND_EXPORT(coreinit_handle, OSResetEvent);
OS_FIND_EXPORT(coreinit_handle, OSSendMessage);
OS_FIND_EXPORT(coreinit_handle, OSReceiveMessage);
OSDynLoad_FindExport(coreinit_handle, 1, "MEMAllocFromDefaultHeapEx", &pMEMAllocFromDefaultHeapEx);
OSDynLoad_FindExport(coreinit_handle, 1, "MEMAllocFromDefaultHeap", &pMEMAllocFromDefaultHeap);
OSDynLoad_FindExport(coreinit_handle, 1, "MEMFreeToDefaultHeap", &pMEMFreeToDefaultHeap);
}

View File

@ -1,253 +0,0 @@
#ifndef __COREINIT_H_
#define __COREINIT_H_
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define OSTimerClockSpeed ((248625000) / 4)
#define OSSecondsToTicks(val) ((uint64_t)(val) * (uint64_t)OSTimerClockSpeed)
#define OSMillisecondsToTicks(val) (((uint64_t)(val) * (uint64_t)OSTimerClockSpeed) / 1000ull)
#define OSMicrosecondsToTicks(val) (((uint64_t)(val) * (uint64_t)OSTimerClockSpeed) / 1000000ull)
#define os_usleep(usecs) OSSleepTicks(OSMicrosecondsToTicks(usecs))
#define os_sleep(secs) OSSleepTicks(OSSecondsToTicks(secs))
#define OSDynLoad_Acquire ((void (*)(const char* rpl, unsigned int *handle))0x0102A3B4)
#define OSDynLoad_FindExport ((void (*)(unsigned int handle, int isdata, const char *symbol, void *address))0x0102B828)
#define OSFatal ((void (*)(char* msg))0x01031618)
#define EXPORT_DECL(res, func, ...) res (* func)(__VA_ARGS__) __attribute__((section(".data"))) = 0;
#define EXPORT_VAR(type, var) type var __attribute__((section(".data")));
#define EXPORT_FUNC_WRITE(func, val) *(uint32_t*)(((uint32_t)&func) + 0) = (uint32_t)val
#define OS_FIND_EXPORT(handle, func) _os_find_export(handle, # func, &funcPointer); \
EXPORT_FUNC_WRITE(func, funcPointer);
#define OS_FIND_EXPORT_EX(handle, func, func_p) \
_os_find_export(handle, # func, &funcPointer); \
EXPORT_FUNC_WRITE(func_p, funcPointer);
#define OS_MUTEX_SIZE 44
extern void _os_find_export(uint32_t handle, const char *funcName, void *funcPointer);
typedef struct OSThread_ OSThread;
typedef struct OSContext_ {
char tag[8];
uint32_t gpr[32];
uint32_t cr;
uint32_t lr;
uint32_t ctr;
uint32_t xer;
uint32_t srr0;
uint32_t srr1;
uint32_t ex0;
uint32_t ex1;
uint32_t exception_type;
uint32_t reserved;
double fpscr;
double fpr[32];
uint16_t spinLockCount;
uint16_t state;
uint32_t gqr[8];
uint32_t pir;
double psf[32];
uint64_t coretime[3];
uint64_t starttime;
uint32_t error;
uint32_t attributes;
uint32_t pmc1;
uint32_t pmc2;
uint32_t pmc3;
uint32_t pmc4;
uint32_t mmcr0;
uint32_t mmcr1;
} OSContext;
typedef int (*ThreadFunc)(int argc, void *argv);
typedef struct OSThreadLink_ {
OSThread *next;
OSThread *prev;
} OSThreadLink;
struct OSThread_ {
OSContext context;
uint32_t txtTag;
uint8_t state;
uint8_t attr;
short threadId;
int suspend;
int priority;
char _[0x394 - 0x330 - sizeof(OSThreadLink)];
OSThreadLink linkActive;
void *stackBase;
void *stackEnd;
ThreadFunc entryPoint;
char _3A0[0x6A0 - 0x3A0];
};
typedef struct OSThreadQueue_ {
OSThread *head;
OSThread *tail;
void *parentStruct;
uint32_t reserved;
} OSThreadQueue;
typedef struct OSMessage_ {
uint32_t message;
uint32_t data0;
uint32_t data1;
uint32_t data2;
} OSMessage;
typedef struct OSMessageQueue_ {
uint32_t tag;
char *name;
uint32_t reserved;
OSThreadQueue sendQueue;
OSThreadQueue recvQueue;
OSMessage *messages;
int msgCount;
int firstIndex;
int usedCount;
} OSMessageQueue;
typedef struct OSEvent OSEvent;
typedef enum OSEventMode
{
//! A manual event will only reset when OSResetEvent is called.
OS_EVENT_MODE_MANUAL = 0,
//! An auto event will reset everytime a thread is woken.
OS_EVENT_MODE_AUTO = 1,
} OSEventMode;
#define OS_EVENT_TAG 0x65566E54u
struct OSEvent
{
//! Should always be set to the value OS_EVENT_TAG.
uint32_t tag;
//! Name set by OSInitEventEx.
const char *name;
char unknwn[4];
//! The current value of the event object.
int32_t value;
//! The threads currently waiting on this event object with OSWaitEvent.
OSThreadQueue queue;
//! The mode of the event object, set by OSInitEvent.
OSEventMode mode;
};
extern OSMessageQueue * (*OSGetSystemMessageQueue)(void);
extern int32_t (*OSReceiveMessage)(OSMessageQueue *, OSMessage * , int32_t);
extern int32_t (*OSSendMessage)(OSMessageQueue *, OSMessage * , int32_t);
extern void (*DCInvalidateRange)(void *buffer, uint32_t length);
extern void (* DCFlushRange)(const void *addr, uint32_t length);
extern void (* DCStoreRange)(const void *addr, uint32_t length);
extern void (* ICInvalidateRange)(const void *addr, uint32_t length);
extern void* (* OSEffectiveToPhysical)(uint32_t);
extern void* (* OSSleepTicks)(uint64_t ticks);
extern void (* OSEnableHomeButtonMenu)(int32_t);
extern void (* OSInitEvent)(OSEvent *event, int32_t value, OSEventMode mode);
extern void (* OSSignalEvent)(OSEvent *event);
extern void (* OSWaitEvent)(OSEvent *event);
extern void (* OSResetEvent)(OSEvent *event);
extern int32_t (* OSCreateThread)(OSThread *thread, int32_t (*callback)(int32_t, void*), int32_t argc, void *args, uint32_t stack, uint32_t stack_size, int32_t priority, uint32_t attr);
extern int32_t (* OSResumeThread)(OSThread *thread);
extern int32_t (* OSSuspendThread)(OSThread *thread);
extern int32_t (* OSIsThreadTerminated)(OSThread *thread);
extern int32_t (* OSIsThreadSuspended)(OSThread *thread);
extern int32_t (* OSJoinThread)(OSThread * thread, int32_t * ret_val);
extern int32_t (* OSSetThreadPriority)(OSThread * thread, int32_t priority);
extern void (* OSDetachThread)(OSThread * thread);
extern OSThread * (* OSGetCurrentThread)(void);
extern const char * (* OSGetThreadName)(OSThread * thread);
extern void (* OSGetActiveThreadLink)(OSThread * thread, void* link);
extern uint32_t (* OSGetThreadAffinity)(OSThread * thread);
extern int32_t (* OSGetThreadPriority)(OSThread * thread);
extern void (* OSSetThreadName)(OSThread * thread, const char *name);
extern int32_t (* OSEnableInterrupts)(void);
extern void (* OSRestoreInterrupts)(int32_t);
extern int32_t (* OSGetCoreId)(void);
extern uint64_t (* OSGetTitleID)(void);
extern int32_t (* OSIsHomeButtonMenuEnabled)(void);
extern int32_t (* MEMCreateExpHeapEx)(void* heap, uint32_t size, uint16_t flags);
extern void* (* MEMAllocFromExpHeapEx)( int32_t heap, uint32_t size, int alignment);
extern void (* MEMFreeToExpHeap)( int32_t heap, void * block);
extern void(*OSScreenInit)();
extern unsigned int(*OSScreenGetBufferSizeEx)(unsigned int bufferNum);
extern unsigned int(*OSScreenSetBufferEx)(unsigned int bufferNum, void * addr);
extern unsigned int(*OSScreenFlipBuffersEx)(unsigned int x);
extern int32_t (*OSScreenEnableEx)(uint32_t bufferNum, int32_t enable);
extern int32_t (*OSScreenPutFontEx)(uint32_t bufferNum, uint32_t posX, uint32_t posY, const char * buffer);
extern unsigned int(*OSScreenClearBufferEx)(unsigned int bufferNum, unsigned int temp);
extern void (* OSInitMutex)(void* mutex);
extern void (* OSLockMutex)(void* mutex);
extern void (* OSUnlockMutex)(void* mutex);
extern int32_t (* OSTryLockMutex)(void* mutex);
extern uint32_t coreinit_handle;
extern uint32_t *pMEMAllocFromDefaultHeapEx;
extern uint32_t *pMEMAllocFromDefaultHeap;
extern uint32_t *pMEMFreeToDefaultHeap;
void InitAcquireOS();
void InitOSFunctionPointers(void);
#ifdef __cplusplus
}
#endif
#endif // __COREINIT_H_

View File

@ -1,93 +0,0 @@
#ifndef FS_DEFS_H
#define FS_DEFS_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include "dynamic_libs/coreinit.h"
/* FS defines and types */
#define FS_MAX_LOCALPATH_SIZE 511
#define FS_MAX_MOUNTPATH_SIZE 128
#define FS_MAX_FULLPATH_SIZE (FS_MAX_LOCALPATH_SIZE + FS_MAX_MOUNTPATH_SIZE)
#define FS_MAX_ARGPATH_SIZE FS_MAX_FULLPATH_SIZE
#define FS_STATUS_OK 0
#define FS_STATUS_EOF -2
#define FS_STATUS_FATAL_ERROR -0x400
#define FS_RET_UNSUPPORTED_CMD 0x0400
#define FS_RET_NO_ERROR 0x0000
#define FS_RET_ALL_ERROR (uint32_t)(-1)
#define FS_IO_BUFFER_ALIGN 64
#define FS_STAT_FLAG_IS_DIRECTORY 0x80000000
/* max length of file/dir name */
#define FS_MAX_ENTNAME_SIZE 256
#define FS_SOURCETYPE_EXTERNAL 0
#define FS_SOURCETYPE_HFIO 1
#define FS_MOUNT_SOURCE_SIZE 0x300
#define FS_CLIENT_SIZE 0x1700
#define FS_CMD_BLOCK_SIZE 0xA80
typedef struct FSClient_ {
uint8_t buffer[FS_CLIENT_SIZE];
} FSClient;
typedef struct FSCmdBlock_ {
uint8_t buffer[FS_CMD_BLOCK_SIZE];
} FSCmdBlock;
typedef struct {
uint32_t flag;
uint32_t permission;
uint32_t owner_id;
uint32_t group_id;
uint32_t size;
uint32_t alloc_size;
uint64_t quota_size;
uint32_t ent_id;
uint64_t ctime;
uint64_t mtime;
uint8_t attributes[48];
} __attribute__((packed)) FSStat;
typedef struct {
FSStat stat;
char name[FS_MAX_ENTNAME_SIZE];
} FSDirEntry;
typedef void (*FSAsyncCallback)(FSClient * pClient, FSCmdBlock * pCmd, int32_t result, void *context);
typedef struct {
FSAsyncCallback userCallback;
void *userContext;
OSMessageQueue *ioMsgQueue;
} FSAsyncParams;
typedef struct {
void* data; // pointer to a FSAsyncResult;
uint32_t unkwn1;
uint32_t unkwn2;
uint32_t unkwn3; // always 0x08
} __attribute__((packed)) FSMessage;
typedef struct FSAsyncResult_ {
FSAsyncParams userParams;
FSMessage ioMsg;
FSClient * client;
FSCmdBlock * block;
uint32_t result;
} FSAsyncResult;
#ifdef __cplusplus
}
#endif
#endif /* FS_DEFS_H */

View File

@ -1,141 +0,0 @@
/****************************************************************************
* Copyright (C) 2015
* by Dimok
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any
* damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any
* purpose, including commercial applications, and to alter it and
* redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you
* must not claim that you wrote the original software. If you use
* this software in a product, an acknowledgment in the product
* documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and
* must not be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
***************************************************************************/
#include "fs_functions.h"
#include "coreinit.h"
EXPORT_DECL(int32_t, FSInit, void);
EXPORT_DECL(int32_t, FSShutdown, void);
EXPORT_DECL(int32_t, FSAddClient, void *pClient, int32_t errHandling);
EXPORT_DECL(int32_t, FSAddClientEx, void *pClient, int32_t unk_zero_param, int32_t errHandling);
EXPORT_DECL(int32_t, FSDelClient, void *pClient);
EXPORT_DECL(void, FSInitCmdBlock, void *pCmd);
EXPORT_DECL(void *, FSGetCurrentCmdBlock, void *pClient);
EXPORT_DECL(int32_t, FSGetMountSource, void *pClient, void *pCmd, int32_t type, void *source, int32_t errHandling);
EXPORT_DECL(int32_t, FSMount, void *pClient, void *pCmd, void *source, char *target, uint32_t bytes, int32_t errHandling);
EXPORT_DECL(int32_t, FSUnmount, void *pClient, void *pCmd, const char *target, int32_t errHandling);
EXPORT_DECL(int32_t, FSGetStat, void *pClient, void *pCmd, const char *path, FSStat *stats, int32_t errHandling);
EXPORT_DECL(int32_t, FSGetStatAsync, void *pClient, void *pCmd, const char *path, void *stats, int32_t error, void *asyncParams);
EXPORT_DECL(int32_t, FSRename, void *pClient, void *pCmd, const char *oldPath, const char *newPath, int32_t error);
EXPORT_DECL(int32_t, FSRenameAsync, void *pClient, void *pCmd, const char *oldPath, const char *newPath, int32_t error, void *asyncParams);
EXPORT_DECL(int32_t, FSRemove, void *pClient, void *pCmd, const char *path, int32_t error);
EXPORT_DECL(int32_t, FSRemoveAsync, void *pClient, void *pCmd, const char *path, int32_t error, void *asyncParams);
EXPORT_DECL(int32_t, FSFlushQuota, void *pClient, void *pCmd, const char* path, int32_t error);
EXPORT_DECL(int32_t, FSFlushQuotaAsync, void *pClient, void *pCmd, const char *path, int32_t error, void *asyncParams);
EXPORT_DECL(int32_t, FSGetFreeSpaceSize, void *pClient, void *pCmd, const char *path, uint64_t *returnedFreeSize, int32_t error);
EXPORT_DECL(int32_t, FSGetFreeSpaceSizeAsync, void *pClient, void *pCmd, const char *path, uint64_t *returnedFreeSize, int32_t error, void *asyncParams);
EXPORT_DECL(int32_t, FSRollbackQuota, void *pClient, void *pCmd, const char *path, int32_t error);
EXPORT_DECL(int32_t, FSRollbackQuotaAsync, void *pClient, void *pCmd, const char *path, int32_t error, void *asyncParams);
EXPORT_DECL(int32_t, FSOpenDir, void *pClient, void *pCmd, const char *path, int32_t *dh, int32_t errHandling);
EXPORT_DECL(int32_t, FSOpenDirAsync, void *pClient, void* pCmd, const char *path, int32_t *handle, int32_t error, void *asyncParams);
EXPORT_DECL(int32_t, FSReadDir, void *pClient, void *pCmd, int32_t dh, FSDirEntry *dir_entry, int32_t errHandling);
EXPORT_DECL(int32_t, FSRewindDir, void *pClient, void *pCmd, int32_t dh, int32_t errHandling);
EXPORT_DECL(int32_t, FSCloseDir, void *pClient, void *pCmd, int32_t dh, int32_t errHandling);
EXPORT_DECL(int32_t, FSChangeDir, void *pClient, void *pCmd, const char *path, int32_t errHandling);
EXPORT_DECL(int32_t, FSChangeDirAsync, void *pClient, void *pCmd, const char *path, int32_t error, void *asyncParams);
EXPORT_DECL(int32_t, FSMakeDir, void *pClient, void *pCmd, const char *path, int32_t errHandling);
EXPORT_DECL(int32_t, FSMakeDirAsync, void *pClient, void *pCmd, const char *path, int32_t error, void *asyncParams);
EXPORT_DECL(int32_t, FSOpenFile, void *pClient, void *pCmd, const char *path, const char *mode, int32_t *fd, int32_t errHandling);
EXPORT_DECL(int32_t, FSOpenFileAsync, void *pClient, void *pCmd, const char *path, const char *mode, int32_t *handle, int32_t error, const void *asyncParams);
EXPORT_DECL(int32_t, FSReadFile, void *pClient, void *pCmd, void *buffer, int32_t size, int32_t count, int32_t fd, int32_t flag, int32_t errHandling);
EXPORT_DECL(int32_t, FSCloseFile, void *pClient, void *pCmd, int32_t fd, int32_t errHandling);
EXPORT_DECL(int32_t, FSFlushFile, void *pClient, void *pCmd, int32_t fd, int32_t error);
EXPORT_DECL(int32_t, FSTruncateFile, void *pClient, void *pCmd, int32_t fd, int32_t error);
EXPORT_DECL(int32_t, FSGetStatFile, void *pClient, void *pCmd, int32_t fd, void *buffer, int32_t error);
EXPORT_DECL(int32_t, FSSetPosFile, void *pClient, void *pCmd, int32_t fd, uint32_t pos, int32_t error);
EXPORT_DECL(int32_t, FSWriteFile, void *pClient, void *pCmd, const void *source, int32_t block_size, int32_t block_count, int32_t fd, int32_t flag, int32_t error);
EXPORT_DECL(int32_t, FSBindMount, void *pClient, void *pCmd, char *source, char *target, int32_t error);
EXPORT_DECL(int32_t, FSBindUnmount, void *pClient, void *pCmd, char *target, int32_t error);
EXPORT_DECL(int32_t, FSMakeQuota, void *pClient, void *pCmd, const char *path,uint32_t mode, uint64_t size, int32_t errHandling);
EXPORT_DECL(int32_t, FSMakeQuotaAsync ,void *pClient, void *pCmd, const char *path,uint32_t mode, uint64_t size, int32_t errHandling,const void *asyncParams);
EXPORT_DECL(int32_t, FSGetCwd,void * client,void * block,char * buffer,uint32_t bufferSize,uint32_t flags);
void InitFSFunctionPointers(void) {
if(coreinit_handle == 0) {
InitAcquireOS();
};
uint32_t *funcPointer = 0;
OS_FIND_EXPORT(coreinit_handle, FSInit);
OS_FIND_EXPORT(coreinit_handle, FSShutdown);
OS_FIND_EXPORT(coreinit_handle, FSAddClient);
OS_FIND_EXPORT(coreinit_handle, FSAddClientEx);
OS_FIND_EXPORT(coreinit_handle, FSDelClient);
OS_FIND_EXPORT(coreinit_handle, FSInitCmdBlock);
OS_FIND_EXPORT(coreinit_handle, FSGetCurrentCmdBlock);
OS_FIND_EXPORT(coreinit_handle, FSGetMountSource);
OS_FIND_EXPORT(coreinit_handle, FSMount);
OS_FIND_EXPORT(coreinit_handle, FSUnmount);
OS_FIND_EXPORT(coreinit_handle, FSGetStat);
OS_FIND_EXPORT(coreinit_handle, FSGetStatAsync);
OS_FIND_EXPORT(coreinit_handle, FSRename);
OS_FIND_EXPORT(coreinit_handle, FSRenameAsync);
OS_FIND_EXPORT(coreinit_handle, FSRemove);
OS_FIND_EXPORT(coreinit_handle, FSRemoveAsync);
OS_FIND_EXPORT(coreinit_handle, FSFlushQuota);
OS_FIND_EXPORT(coreinit_handle, FSFlushQuotaAsync);
OS_FIND_EXPORT(coreinit_handle, FSGetFreeSpaceSize);
OS_FIND_EXPORT(coreinit_handle, FSGetFreeSpaceSizeAsync);
OS_FIND_EXPORT(coreinit_handle, FSRollbackQuota);
OS_FIND_EXPORT(coreinit_handle, FSRollbackQuotaAsync);
OS_FIND_EXPORT(coreinit_handle, FSOpenDir);
OS_FIND_EXPORT(coreinit_handle, FSOpenDirAsync);
OS_FIND_EXPORT(coreinit_handle, FSReadDir);
OS_FIND_EXPORT(coreinit_handle, FSRewindDir);
OS_FIND_EXPORT(coreinit_handle, FSCloseDir);
OS_FIND_EXPORT(coreinit_handle, FSChangeDir);
OS_FIND_EXPORT(coreinit_handle, FSChangeDirAsync);
OS_FIND_EXPORT(coreinit_handle, FSMakeDir);
OS_FIND_EXPORT(coreinit_handle, FSMakeDirAsync);
OS_FIND_EXPORT(coreinit_handle, FSOpenFile);
OS_FIND_EXPORT(coreinit_handle, FSOpenFileAsync);
OS_FIND_EXPORT(coreinit_handle, FSReadFile);
OS_FIND_EXPORT(coreinit_handle, FSCloseFile);
OS_FIND_EXPORT(coreinit_handle, FSFlushFile);
OS_FIND_EXPORT(coreinit_handle, FSTruncateFile);
OS_FIND_EXPORT(coreinit_handle, FSGetStatFile);
OS_FIND_EXPORT(coreinit_handle, FSSetPosFile);
OS_FIND_EXPORT(coreinit_handle, FSWriteFile);
OS_FIND_EXPORT(coreinit_handle, FSBindMount);
OS_FIND_EXPORT(coreinit_handle, FSBindUnmount);
OS_FIND_EXPORT(coreinit_handle, FSMakeQuota);
OS_FIND_EXPORT(coreinit_handle, FSMakeQuotaAsync);
OS_FIND_EXPORT(coreinit_handle, FSGetCwd);
}

View File

@ -1,99 +0,0 @@
/****************************************************************************
* Copyright (C) 2015
* by Dimok
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any
* damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any
* purpose, including commercial applications, and to alter it and
* redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you
* must not claim that you wrote the original software. If you use
* this software in a product, an acknowledgment in the product
* documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and
* must not be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
***************************************************************************/
#ifndef __FS_FUNCTIONS_H_
#define __FS_FUNCTIONS_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include "fs_defs.h"
void InitFSFunctionPointers(void);
extern int32_t (* FSInit)(void);
extern int32_t (* FSShutdown)(void);
extern int32_t (* FSAddClient)(void *pClient, int32_t errHandling);
extern int32_t (* FSAddClientEx)(void *pClient, int32_t unk_zero_param, int32_t errHandling);
extern int32_t (* FSDelClient)(void *pClient);
extern void (* FSInitCmdBlock)(void *pCmd);
extern void *(* FSGetCurrentCmdBlock)(void *pClient);
extern int32_t (* FSGetMountSource)(void *pClient, void *pCmd, int32_t type, void *source, int32_t errHandling);
extern int32_t (* FSMount)(void *pClient, void *pCmd, void *source, char *target, uint32_t bytes, int32_t errHandling);
extern int32_t (* FSUnmount)(void *pClient, void *pCmd, const char *target, int32_t errHandling);
extern int32_t (* FSRename)(void *pClient, void *pCmd, const char *oldPath, const char *newPath, int32_t error);
extern int32_t (* FSRenameAsync)(void *pClient, void *pCmd, const char *oldPath, const char *newPath, int32_t error, void *asyncParams);
extern int32_t (* FSRemove)(void *pClient, void *pCmd, const char *path, int32_t error);
extern int32_t (* FSRemoveAsync)(void *pClient, void *pCmd, const char *path, int32_t error, void *asyncParams);
extern int32_t (* FSGetStat)(void *pClient, void *pCmd, const char *path, FSStat *stats, int32_t errHandling);
extern int32_t (* FSGetStatAsync)(void *pClient, void *pCmd, const char *path, void *stats, int32_t error, void *asyncParams);
extern int32_t (* FSRename)(void *pClient, void *pCmd, const char *oldPath, const char *newPath, int32_t error);
extern int32_t (* FSRenameAsync)(void *pClient, void *pCmd, const char *oldPath, const char *newPath, int32_t error, void *asyncParams);
extern int32_t (* FSRemove)(void *pClient, void *pCmd, const char *path, int32_t error);
extern int32_t (* FSRemoveAsync)(void *pClient, void *pCmd, const char *path, int32_t error, void *asyncParams);
extern int32_t (* FSFlushQuota)(void *pClient, void *pCmd, const char* path, int32_t error);
extern int32_t (* FSFlushQuotaAsync)(void *pClient, void *pCmd, const char *path, int32_t error, void *asyncParams);
extern int32_t (* FSGetFreeSpaceSize)(void *pClient, void *pCmd, const char *path, uint64_t *returnedFreeSize, int32_t error);
extern int32_t (* FSGetFreeSpaceSizeAsync)(void *pClient, void *pCmd, const char *path, uint64_t *returnedFreeSize, int32_t error, void *asyncParams);
extern int32_t (* FSRollbackQuota)(void *pClient, void *pCmd, const char *path, int32_t error);
extern int32_t (* FSRollbackQuotaAsync)(void *pClient, void *pCmd, const char *path, int32_t error, void *asyncParams);
extern int32_t (* FSOpenDir)(void *pClient, void *pCmd, const char *path, int32_t *dh, int32_t errHandling);
extern int32_t (* FSOpenDirAsync)(void *pClient, void* pCmd, const char *path, int32_t *handle, int32_t error, void *asyncParams);
extern int32_t (* FSReadDir)(void *pClient, void *pCmd, int32_t dh, FSDirEntry *dir_entry, int32_t errHandling);
extern int32_t (* FSRewindDir)(void *pClient, void *pCmd, int32_t dh, int32_t errHandling);
extern int32_t (* FSCloseDir)(void *pClient, void *pCmd, int32_t dh, int32_t errHandling);
extern int32_t (* FSChangeDir)(void *pClient, void *pCmd, const char *path, int32_t errHandling);
extern int32_t (* FSChangeDirAsync)(void *pClient, void *pCmd, const char *path, int32_t error, void *asyncParams);
extern int32_t (* FSMakeDir)(void *pClient, void *pCmd, const char *path, int32_t errHandling);
extern int32_t (* FSMakeDirAsync)(void *pClient, void *pCmd, const char *path, int32_t error, void *asyncParams);
extern int32_t (* FSOpenFile)(void *pClient, void *pCmd, const char *path, const char *mode, int32_t *fd, int32_t errHandling);
extern int32_t (* FSOpenFileAsync)(void *pClient, void *pCmd, const char *path, const char *mode, int32_t *handle, int32_t error, const void *asyncParams);
extern int32_t (* FSReadFile)(void *pClient, void *pCmd, void *buffer, int32_t size, int32_t count, int32_t fd, int32_t flag, int32_t errHandling);
extern int32_t (* FSCloseFile)(void *pClient, void *pCmd, int32_t fd, int32_t errHandling);
extern int32_t (* FSFlushFile)(void *pClient, void *pCmd, int32_t fd, int32_t error);
extern int32_t (* FSTruncateFile)(void *pClient, void *pCmd, int32_t fd, int32_t error);
extern int32_t (* FSGetStatFile)(void *pClient, void *pCmd, int32_t fd, void *buffer, int32_t error);
extern int32_t (* FSSetPosFile)(void *pClient, void *pCmd, int32_t fd, uint32_t pos, int32_t error);
extern int32_t (* FSWriteFile)(void *pClient, void *pCmd, const void *source, int32_t block_size, int32_t block_count, int32_t fd, int32_t flag, int32_t error);
extern int32_t (* FSBindMount)(void *pClient, void *pCmd, char *source, char *target, int32_t error);
extern int32_t (* FSBindUnmount)(void *pClient, void *pCmd, char *target, int32_t error);
extern int32_t (* FSMakeQuota)( void *pClient, void *pCmd, const char *path,uint32_t mode, uint64_t size, int32_t errHandling);
extern int32_t (* FSMakeQuotaAsync)(void *pClient, void *pCmd, const char *path,uint32_t mode, uint64_t size, int32_t errHandling,const void *asyncParams);
extern int32_t (* FSGetCwd)(void * client,void * block,char * buffer,uint32_t bufferSize,uint32_t flags);
#ifdef __cplusplus
}
#endif
#endif // __FS_FUNCTIONS_H_

View File

@ -1,187 +0,0 @@
/****************************************************************************
* Copyright (C) 2015
* by Dimok
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any
* damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any
* purpose, including commercial applications, and to alter it and
* redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you
* must not claim that you wrote the original software. If you use
* this software in a product, an acknowledgment in the product
* documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and
* must not be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
***************************************************************************/
#include "coreinit.h"
#include "gx2_types.h"
uint32_t gx2_handle __attribute__((section(".data"))) = 0;
EXPORT_DECL(void, GX2Init, uint32_t * init_attribs);
EXPORT_DECL(void, GX2Shutdown, void);
EXPORT_DECL(void, GX2Flush, void);
EXPORT_DECL(int32_t, GX2GetMainCoreId, void) ;
EXPORT_DECL(int32_t, GX2DrawDone, void);
EXPORT_DECL(void, GX2ClearColor, GX2ColorBuffer *colorBuffer, float r, float g, float b, float a);
EXPORT_DECL(void, GX2SetViewport, float x, float y, float w, float h, float nearZ, float farZ);
EXPORT_DECL(void, GX2SetScissor, uint32_t x_orig, uint32_t y_orig, uint32_t wd, uint32_t ht);
EXPORT_DECL(void, GX2SetContextState, const GX2ContextState* state);
EXPORT_DECL(void, GX2DrawEx, int32_t primitive_type, uint32_t count, uint32_t first_vertex, uint32_t instances_count);
EXPORT_DECL(void, GX2DrawIndexedEx, int32_t primitive_type, uint32_t count, int32_t index_format, const void* idx, uint32_t first_vertex, uint32_t instances_count);
EXPORT_DECL(void, GX2ClearDepthStencilEx, GX2DepthBuffer *depthBuffer, float depth_value, uint8_t stencil_value, int32_t clear_mode);
EXPORT_DECL(void, GX2SetClearDepthStencil, GX2DepthBuffer *depthBuffer, float depth_value, uint8_t stencil_value);
EXPORT_DECL(void, GX2CopyColorBufferToScanBuffer, const GX2ColorBuffer *colorBuffer, int32_t scan_target);
EXPORT_DECL(void, GX2SwapScanBuffers, void);
EXPORT_DECL(void, GX2SetTVEnable, int32_t enable);
EXPORT_DECL(void, GX2SetSwapInterval, uint32_t swap_interval);
EXPORT_DECL(uint32_t, GX2GetSwapInterval, void);
EXPORT_DECL(void, GX2WaitForVsync, void);
EXPORT_DECL(void, GX2CalcTVSize, int32_t tv_render_mode, int32_t format, int32_t buffering_mode, uint32_t * size, int32_t * scale_needed);
EXPORT_DECL(void, GX2Invalidate, int32_t invalidate_type, void * ptr, uint32_t buffer_size);
EXPORT_DECL(void, GX2SetTVBuffer, void *buffer, uint32_t buffer_size, int32_t tv_render_mode, int32_t format, int32_t buffering_mode);
EXPORT_DECL(void, GX2CalcSurfaceSizeAndAlignment, GX2Surface *surface);
EXPORT_DECL(void, GX2InitDepthBufferRegs, GX2DepthBuffer *depthBuffer);
EXPORT_DECL(void, GX2InitColorBufferRegs, GX2ColorBuffer *colorBuffer);
EXPORT_DECL(void, GX2CalcColorBufferAuxInfo, GX2ColorBuffer *colorBuffer, uint32_t *size, uint32_t *align);
EXPORT_DECL(void, GX2CalcDepthBufferHiZInfo, GX2DepthBuffer *depthBuffer, uint32_t *size, uint32_t *align);
EXPORT_DECL(void, GX2InitDepthBufferHiZEnable, GX2DepthBuffer *depthBuffer, int32_t hiZ_enable);
EXPORT_DECL(void, GX2SetupContextStateEx, GX2ContextState* state, int32_t enable_profiling);
EXPORT_DECL(void, GX2SetColorBuffer, const GX2ColorBuffer *colorBuffer, int32_t target);
EXPORT_DECL(void, GX2SetDepthBuffer, const GX2DepthBuffer *depthBuffer);
EXPORT_DECL(void, GX2SetAttribBuffer, uint32_t attr_index, uint32_t attr_size, uint32_t stride, const void* attr);
EXPORT_DECL(void, GX2InitTextureRegs, GX2Texture *texture);
EXPORT_DECL(void, GX2InitSampler, GX2Sampler *sampler, int32_t tex_clamp, int32_t min_mag_filter);
EXPORT_DECL(uint32_t, GX2CalcFetchShaderSizeEx, uint32_t num_attrib, int32_t fetch_shader_type, int32_t tessellation_mode);
EXPORT_DECL(void, GX2InitFetchShaderEx, GX2FetchShader* fs, void* fs_buffer, uint32_t count, const GX2AttribStream* attribs, int32_t fetch_shader_type, int32_t tessellation_mode);
EXPORT_DECL(void, GX2SetFetchShader, const GX2FetchShader* fs);
EXPORT_DECL(void, GX2SetVertexUniformReg, uint32_t offset, uint32_t count, const void *values);
EXPORT_DECL(void, GX2SetPixelUniformReg, uint32_t offset, uint32_t count, const void *values);
EXPORT_DECL(void, GX2SetPixelTexture, const GX2Texture *texture, uint32_t texture_hw_location);
EXPORT_DECL(void, GX2SetVertexTexture, const GX2Texture *texture, uint32_t texture_hw_location);
EXPORT_DECL(void, GX2SetPixelSampler, const GX2Sampler *sampler, uint32_t sampler_hw_location);
EXPORT_DECL(void, GX2SetVertexSampler, const GX2Sampler *sampler, uint32_t sampler_hw_location);
EXPORT_DECL(void, GX2SetPixelShader, const GX2PixelShader* pixelShader);
EXPORT_DECL(void, GX2SetVertexShader, const GX2VertexShader* vertexShader);
EXPORT_DECL(void, GX2InitSamplerZMFilter, GX2Sampler *sampler, int32_t z_filter, int32_t mip_filter);
EXPORT_DECL(void, GX2SetColorControl, int32_t lop, uint8_t blend_enable_mask, int32_t enable_multi_write, int32_t enable_color_buffer);
EXPORT_DECL(void, GX2SetDepthOnlyControl, int32_t enable_depth, int32_t enable_depth_write, int32_t depth_comp_function);
EXPORT_DECL(void, GX2SetBlendControl, int32_t target, int32_t color_src_blend, int32_t color_dst_blend, int32_t color_combine, int32_t separate_alpha_blend, int32_t alpha_src_blend, int32_t alpha_dst_blend, int32_t alpha_combine);
EXPORT_DECL(void, GX2CalcDRCSize, int32_t drc_mode, int32_t format, int32_t buffering_mode, uint32_t *size, int32_t *scale_needed);
EXPORT_DECL(void, GX2SetDRCBuffer, void *buffer, uint32_t buffer_size, int32_t drc_mode, int32_t surface_format, int32_t buffering_mode);
EXPORT_DECL(void, GX2SetDRCScale, uint32_t width, uint32_t height);
EXPORT_DECL(void, GX2SetDRCEnable, int32_t enable);
EXPORT_DECL(void, GX2SetPolygonControl, int32_t front_face_mode, int32_t cull_front, int32_t cull_back, int32_t enable_mode, int32_t mode_font, int32_t mode_back, int32_t poly_offset_front, int32_t poly_offset_back, int32_t point_line_offset);
EXPORT_DECL(void, GX2SetCullOnlyControl, int32_t front_face_mode, int32_t cull_front, int32_t cull_back);
EXPORT_DECL(void, GX2SetDepthStencilControl, int32_t enable_depth_test, int32_t enable_depth_write, int32_t depth_comp_function, int32_t stencil_test_enable, int32_t back_stencil_enable,
int32_t font_stencil_func, int32_t front_stencil_z_pass, int32_t front_stencil_z_fail, int32_t front_stencil_fail,
int32_t back_stencil_func, int32_t back_stencil_z_pass, int32_t back_stencil_z_fail, int32_t back_stencil_fail);
EXPORT_DECL(void, GX2SetStencilMask, uint8_t mask_front, uint8_t write_mask_front, uint8_t ref_front, uint8_t mask_back, uint8_t write_mask_back, uint8_t ref_back);
EXPORT_DECL(void, GX2SetLineWidth, float width);
EXPORT_DECL(void, GX2SetTVGamma, float val);
EXPORT_DECL(void, GX2SetDRCGamma, float gam);
EXPORT_DECL(int32_t, GX2GetSystemTVScanMode, void);
EXPORT_DECL(int32_t, GX2GetSystemDRCScanMode, void);
EXPORT_DECL(void, GX2RSetAllocator, void * (* allocFunc)(uint32_t, uint32_t, uint32_t), void (* freeFunc)(uint32_t, void*));
EXPORT_DECL(void, GX2CopySurface, GX2Surface * srcSurface,uint32_t srcMip,uint32_t srcSlice,GX2Surface * dstSurface,uint32_t dstMip,uint32_t dstSlice );
EXPORT_DECL(int32_t, GX2GetLastFrame, int32_t target, GX2Texture * texture);
EXPORT_DECL(void, GX2BeginDisplayListEx,void * displayList,uint32_t size,int32_t unkwn);
EXPORT_DECL(uint32_t, GX2EndDisplayList, void * list);
EXPORT_DECL(void, GX2CallDisplayList, void * list, uint32_t size);
EXPORT_DECL(void, GX2ExpandAAColorBuffer,GX2ColorBuffer * buffer);
EXPORT_DECL(void, GX2ResolveAAColorBuffer, const GX2ColorBuffer * srcBuffer, GX2Surface * dstSurface,uint32_t dstMip,uint32_t dstSlice);
EXPORT_DECL(void, GX2ClearBuffersEx, GX2ColorBuffer * colorBuffer,GX2DepthBuffer * depthBuffer,float r, float g, float b, float a,float depthValue,uint8_t stencilValue,int32_t clearFlags);
void InitAcquireGX2(void) {
if(coreinit_handle == 0) {
InitAcquireOS();
};
OSDynLoad_Acquire("gx2.rpl", &gx2_handle);
}
void InitGX2FunctionPointers(void) {
uint32_t *funcPointer = 0;
InitAcquireGX2();
OS_FIND_EXPORT(gx2_handle, GX2Init);
OS_FIND_EXPORT(gx2_handle, GX2Shutdown);
OS_FIND_EXPORT(gx2_handle, GX2Flush);
OS_FIND_EXPORT(gx2_handle, GX2GetMainCoreId);
OS_FIND_EXPORT(gx2_handle, GX2DrawDone);
OS_FIND_EXPORT(gx2_handle, GX2ClearColor);
OS_FIND_EXPORT(gx2_handle, GX2SetViewport);
OS_FIND_EXPORT(gx2_handle, GX2SetScissor);
OS_FIND_EXPORT(gx2_handle, GX2SetContextState);
OS_FIND_EXPORT(gx2_handle, GX2DrawEx);
OS_FIND_EXPORT(gx2_handle, GX2DrawIndexedEx);
OS_FIND_EXPORT(gx2_handle, GX2ClearDepthStencilEx);
OS_FIND_EXPORT(gx2_handle, GX2CopyColorBufferToScanBuffer);
OS_FIND_EXPORT(gx2_handle, GX2SwapScanBuffers);
OS_FIND_EXPORT(gx2_handle, GX2SetTVEnable);
OS_FIND_EXPORT(gx2_handle, GX2SetSwapInterval);
OS_FIND_EXPORT(gx2_handle, GX2GetSwapInterval);
OS_FIND_EXPORT(gx2_handle, GX2WaitForVsync);
OS_FIND_EXPORT(gx2_handle, GX2CalcTVSize);
OS_FIND_EXPORT(gx2_handle, GX2Invalidate);
OS_FIND_EXPORT(gx2_handle, GX2SetTVBuffer);
OS_FIND_EXPORT(gx2_handle, GX2CalcSurfaceSizeAndAlignment);
OS_FIND_EXPORT(gx2_handle, GX2InitDepthBufferRegs);
OS_FIND_EXPORT(gx2_handle, GX2InitColorBufferRegs);
OS_FIND_EXPORT(gx2_handle, GX2CalcColorBufferAuxInfo);
OS_FIND_EXPORT(gx2_handle, GX2CalcDepthBufferHiZInfo);
OS_FIND_EXPORT(gx2_handle, GX2InitDepthBufferHiZEnable);
OS_FIND_EXPORT(gx2_handle, GX2SetupContextStateEx);
OS_FIND_EXPORT(gx2_handle, GX2SetColorBuffer);
OS_FIND_EXPORT(gx2_handle, GX2SetDepthBuffer);
OS_FIND_EXPORT(gx2_handle, GX2SetAttribBuffer);
OS_FIND_EXPORT(gx2_handle, GX2InitTextureRegs);
OS_FIND_EXPORT(gx2_handle, GX2InitSampler);
OS_FIND_EXPORT(gx2_handle, GX2CalcFetchShaderSizeEx);
OS_FIND_EXPORT(gx2_handle, GX2InitFetchShaderEx);
OS_FIND_EXPORT(gx2_handle, GX2SetFetchShader);
OS_FIND_EXPORT(gx2_handle, GX2SetVertexUniformReg);
OS_FIND_EXPORT(gx2_handle, GX2SetPixelUniformReg);
OS_FIND_EXPORT(gx2_handle, GX2SetPixelTexture);
OS_FIND_EXPORT(gx2_handle, GX2SetVertexTexture);
OS_FIND_EXPORT(gx2_handle, GX2SetPixelSampler);
OS_FIND_EXPORT(gx2_handle, GX2SetVertexSampler);
OS_FIND_EXPORT(gx2_handle, GX2SetPixelShader);
OS_FIND_EXPORT(gx2_handle, GX2SetVertexShader);
OS_FIND_EXPORT(gx2_handle, GX2InitSamplerZMFilter);
OS_FIND_EXPORT(gx2_handle, GX2SetColorControl);
OS_FIND_EXPORT(gx2_handle, GX2SetDepthOnlyControl);
OS_FIND_EXPORT(gx2_handle, GX2SetBlendControl);
OS_FIND_EXPORT(gx2_handle, GX2CalcDRCSize);
OS_FIND_EXPORT(gx2_handle, GX2SetDRCBuffer);
OS_FIND_EXPORT(gx2_handle, GX2SetDRCScale);
OS_FIND_EXPORT(gx2_handle, GX2SetDRCEnable);
OS_FIND_EXPORT(gx2_handle, GX2SetPolygonControl);
OS_FIND_EXPORT(gx2_handle, GX2SetCullOnlyControl);
OS_FIND_EXPORT(gx2_handle, GX2SetDepthStencilControl);
OS_FIND_EXPORT(gx2_handle, GX2SetStencilMask);
OS_FIND_EXPORT(gx2_handle, GX2SetLineWidth);
OS_FIND_EXPORT(gx2_handle, GX2SetDRCGamma);
OS_FIND_EXPORT(gx2_handle, GX2SetTVGamma);
OS_FIND_EXPORT(gx2_handle, GX2GetSystemTVScanMode);
OS_FIND_EXPORT(gx2_handle, GX2GetSystemDRCScanMode);
OS_FIND_EXPORT(gx2_handle, GX2RSetAllocator);
OS_FIND_EXPORT(gx2_handle, GX2CopySurface);
OS_FIND_EXPORT(gx2_handle, GX2GetLastFrame);
OS_FIND_EXPORT(gx2_handle, GX2ClearBuffersEx);
OS_FIND_EXPORT(gx2_handle, GX2BeginDisplayListEx);
OS_FIND_EXPORT(gx2_handle, GX2EndDisplayList);
OS_FIND_EXPORT(gx2_handle, GX2CallDisplayList);
OS_FIND_EXPORT(gx2_handle, GX2ExpandAAColorBuffer);
OS_FIND_EXPORT(gx2_handle, GX2ResolveAAColorBuffer);
OS_FIND_EXPORT(gx2_handle, GX2SetClearDepthStencil);
}

View File

@ -1,213 +0,0 @@
/****************************************************************************
* Copyright (C) 2015
* by Dimok
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any
* damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any
* purpose, including commercial applications, and to alter it and
* redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you
* must not claim that you wrote the original software. If you use
* this software in a product, an acknowledgment in the product
* documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and
* must not be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
***************************************************************************/
#ifndef __GX2_FUNCTIONS_H_
#define __GX2_FUNCTIONS_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "gx2_types.h"
extern uint32_t gx2_handle;
void InitGX2FunctionPointers(void);
void InitAcquireGX2(void);
extern void (* GX2Init)(uint32_t * init_attribs);
extern void (* GX2Shutdown)(void);
extern void (* GX2Flush)(void);
extern int32_t (* GX2GetMainCoreId)(void) ;
extern int32_t (* GX2DrawDone)(void);
extern void (* GX2ClearColor)(GX2ColorBuffer *colorBuffer, float r, float g, float b, float a);
extern void (* GX2SetViewport)(float x, float y, float w, float h, float nearZ, float farZ);
extern void (* GX2SetScissor)(uint32_t x_orig, uint32_t y_orig, uint32_t wd, uint32_t ht);
extern void (* GX2SetContextState)(const GX2ContextState* state);
extern void (* GX2DrawEx)(int32_t primitive_type, uint32_t count, uint32_t first_vertex, uint32_t instances_count);
extern void (* GX2DrawIndexedEx)(int32_t primitive_type, uint32_t count, int32_t index_format, const void* idx, uint32_t first_vertex, uint32_t instances_count);
extern void (* GX2ClearDepthStencilEx)(GX2DepthBuffer *depthBuffer, float depth_value, uint8_t stencil_value, int32_t clear_mode);
extern void (* GX2SetClearDepthStencil)(GX2DepthBuffer *depthBuffer, float depth_value, uint8_t stencil_value);
extern void (* GX2CopyColorBufferToScanBuffer)(const GX2ColorBuffer *colorBuffer, int32_t scan_target);
extern void (* GX2SwapScanBuffers)(void);
extern void (* GX2SetTVEnable)(int32_t enable);
extern void (* GX2SetSwapInterval)(uint32_t swap_interval);
extern uint32_t (* GX2GetSwapInterval)(void);
extern void (* GX2WaitForVsync)(void);
extern void (* GX2CalcTVSize)(int32_t tv_render_mode, int32_t format, int32_t buffering_mode, uint32_t * size, int32_t * scale_needed);
extern void (* GX2Invalidate)(int32_t invalidate_type, void * ptr, uint32_t buffer_size);
extern void (* GX2SetTVBuffer)(void *buffer, uint32_t buffer_size, int32_t tv_render_mode, int32_t format, int32_t buffering_mode);
extern void (* GX2CalcSurfaceSizeAndAlignment)(GX2Surface *surface);
extern void (* GX2InitDepthBufferRegs)(GX2DepthBuffer *depthBuffer);
extern void (* GX2InitColorBufferRegs)(GX2ColorBuffer *colorBuffer);
extern void (* GX2CalcColorBufferAuxInfo)(GX2ColorBuffer *colorBuffer, uint32_t *size, uint32_t *align);
extern void (* GX2CalcDepthBufferHiZInfo)(GX2DepthBuffer *depthBuffer, uint32_t *size, uint32_t *align);
extern void (* GX2InitDepthBufferHiZEnable)(GX2DepthBuffer *depthBuffer, int32_t hiZ_enable);
extern void (* GX2SetupContextStateEx)(GX2ContextState* state, int32_t enable_profiling);
extern void (* GX2SetColorBuffer)(const GX2ColorBuffer *colorBuffer, int32_t target);
extern void (* GX2SetDepthBuffer)(const GX2DepthBuffer *depthBuffer);
extern void (* GX2SetAttribBuffer)(uint32_t attr_index, uint32_t attr_size, uint32_t stride, const void* attr);
extern void (* GX2InitTextureRegs)(GX2Texture *texture);
extern void (* GX2InitSampler)(GX2Sampler *sampler, int32_t tex_clamp, int32_t min_mag_filter);
extern uint32_t (* GX2CalcFetchShaderSizeEx)(uint32_t num_attrib, int32_t fetch_shader_type, int32_t tessellation_mode);
extern void (* GX2InitFetchShaderEx)(GX2FetchShader* fs, void* fs_buffer, uint32_t count, const GX2AttribStream* attribs, int32_t fetch_shader_type, int32_t tessellation_mode);
extern void (* GX2SetFetchShader)(const GX2FetchShader* fs);
extern void (* GX2SetVertexUniformReg)(uint32_t offset, uint32_t count, const void *values);
extern void (* GX2SetPixelUniformReg)(uint32_t offset, uint32_t count, const void *values);
extern void (* GX2SetPixelTexture)(const GX2Texture *texture, uint32_t texture_hw_location);
extern void (* GX2SetVertexTexture)(const GX2Texture *texture, uint32_t texture_hw_location);
extern void (* GX2SetPixelSampler)(const GX2Sampler *sampler, uint32_t sampler_hw_location);
extern void (* GX2SetVertexSampler)(const GX2Sampler *sampler, uint32_t sampler_hw_location);
extern void (* GX2SetPixelShader)(const GX2PixelShader* pixelShader);
extern void (* GX2SetVertexShader)(const GX2VertexShader* vertexShader);
extern void (* GX2InitSamplerZMFilter)(GX2Sampler *sampler, int32_t z_filter, int32_t mip_filter);
extern void (* GX2SetColorControl)(int32_t lop, uint8_t blend_enable_mask, int32_t enable_multi_write, int32_t enable_color_buffer);
extern void (* GX2SetDepthOnlyControl)(int32_t enable_depth, int32_t enable_depth_write, int32_t depth_comp_function);
extern void (* GX2SetBlendControl)(int32_t target, int32_t color_src_blend, int32_t color_dst_blend, int32_t color_combine, int32_t separate_alpha_blend, int32_t alpha_src_blend, int32_t alpha_dst_blend, int32_t alpha_combine);
extern void (* GX2CalcDRCSize)(int32_t drc_mode, int32_t format, int32_t buffering_mode, uint32_t *size, int32_t *scale_needed);
extern void (* GX2SetDRCBuffer)(void *buffer, uint32_t buffer_size, int32_t drc_mode, int32_t surface_format, int32_t buffering_mode);
extern void (* GX2SetDRCScale)(uint32_t width, uint32_t height);
extern void (* GX2SetDRCEnable)(int32_t enable);
extern void (* GX2SetPolygonControl)(int32_t front_face_mode, int32_t cull_front, int32_t cull_back, int32_t enable_mode, int32_t mode_font, int32_t mode_back, int32_t poly_offset_front, int32_t poly_offset_back, int32_t point_line_offset);
extern void (* GX2SetCullOnlyControl)(int32_t front_face_mode, int32_t cull_front, int32_t cull_back);
extern void (* GX2SetDepthStencilControl)(int32_t enable_depth_test, int32_t enable_depth_write, int32_t depth_comp_function, int32_t stencil_test_enable, int32_t back_stencil_enable,
int32_t font_stencil_func, int32_t front_stencil_z_pass, int32_t front_stencil_z_fail, int32_t front_stencil_fail,
int32_t back_stencil_func, int32_t back_stencil_z_pass, int32_t back_stencil_z_fail, int32_t back_stencil_fail);
extern void (* GX2SetStencilMask)(uint8_t mask_front, uint8_t write_mask_front, uint8_t ref_front, uint8_t mask_back, uint8_t write_mask_back, uint8_t ref_back);
extern void (* GX2SetLineWidth)(float width);
extern void (* GX2SetTVGamma)(float val);
extern void (* GX2SetDRCGamma)(float val);
extern int32_t (* GX2GetSystemTVScanMode)(void);
extern int32_t (* GX2GetSystemDRCScanMode)(void);
extern void (* GX2RSetAllocator)(void * (*allocFunc)(uint32_t, uint32_t, uint32_t), void (*freeFunc)(uint32_t, void*));
extern void (* GX2CopySurface)(GX2Surface * srcSurface,uint32_t srcMip,uint32_t srcSlice,GX2Surface * dstSurface,uint32_t dstMip,uint32_t dstSlice );
extern void (* GX2ClearBuffersEx)(GX2ColorBuffer * colorBuffer,GX2DepthBuffer * depthBuffer,float r, float g, float b, float a,float depthValue,uint8_t stencilValue,int32_t clearFlags);
extern int32_t (* GX2GetLastFrame)(int32_t target, GX2Texture * texture);
extern void (* GX2BeginDisplayListEx)(void * displayList,uint32_t size,int32_t unkwn);
extern uint32_t (*GX2EndDisplayList)(void * list);
extern void (*GX2CallDisplayList)(void * list, uint32_t size);
extern void (*GX2ExpandAAColorBuffer)(GX2ColorBuffer * buffer);
extern void (*GX2ResolveAAColorBuffer)(const GX2ColorBuffer * srcBuffer, GX2Surface * dstSurface,uint32_t dstMip,uint32_t dstSlice);
static inline void GX2InitDepthBuffer(GX2DepthBuffer *depthBuffer, int32_t dimension, uint32_t width, uint32_t height, uint32_t depth, int32_t format, int32_t aa) {
depthBuffer->surface.dimension = dimension;
depthBuffer->surface.width = width;
depthBuffer->surface.height = height;
depthBuffer->surface.depth = depth;
depthBuffer->surface.num_mips = 1;
depthBuffer->surface.format = format;
depthBuffer->surface.aa = aa;
depthBuffer->surface.use = ((format==GX2_SURFACE_FORMAT_D_D24_S8_UNORM) || (format==GX2_SURFACE_FORMAT_D_D24_S8_FLOAT)) ? GX2_SURFACE_USE_DEPTH_BUFFER : GX2_SURFACE_USE_DEPTH_BUFFER_TEXTURE;
depthBuffer->surface.tile = GX2_TILE_MODE_DEFAULT;
depthBuffer->surface.swizzle = 0;
depthBuffer->view_mip = 0;
depthBuffer->view_first_slice = 0;
depthBuffer->view_slices_count = depth;
depthBuffer->clear_depth = 1.0f;
depthBuffer->clear_stencil = 0;
depthBuffer->hiZ_data = NULL;
depthBuffer->hiZ_size = 0;
GX2CalcSurfaceSizeAndAlignment(&depthBuffer->surface);
GX2InitDepthBufferRegs(depthBuffer);
}
static inline void GX2InitColorBuffer(GX2ColorBuffer *colorBuffer, int32_t dimension, uint32_t width, uint32_t height, uint32_t depth, int32_t format, int32_t aa) {
colorBuffer->surface.dimension = dimension;
colorBuffer->surface.width = width;
colorBuffer->surface.height = height;
colorBuffer->surface.depth = depth;
colorBuffer->surface.num_mips = 1;
colorBuffer->surface.format = format;
colorBuffer->surface.aa = aa;
colorBuffer->surface.use = GX2_SURFACE_USE_COLOR_BUFFER_TEXTURE_FTV;
colorBuffer->surface.image_size = 0;
colorBuffer->surface.image_data = NULL;
colorBuffer->surface.mip_size = 0;
colorBuffer->surface.mip_data = NULL;
colorBuffer->surface.tile = GX2_TILE_MODE_DEFAULT;
colorBuffer->surface.swizzle = 0;
colorBuffer->surface.align = 0;
colorBuffer->surface.pitch = 0;
uint32_t i;
for(i = 0; i < 13; i++)
colorBuffer->surface.mip_offset[i] = 0;
colorBuffer->view_mip = 0;
colorBuffer->view_first_slice = 0;
colorBuffer->view_slices_count = depth;
colorBuffer->aux_data = NULL;
colorBuffer->aux_size = 0;
for(i = 0; i < 5; i++)
colorBuffer->regs[i] = 0;
GX2CalcSurfaceSizeAndAlignment(&colorBuffer->surface);
GX2InitColorBufferRegs(colorBuffer);
}
static inline void GX2InitAttribStream(GX2AttribStream* attr, uint32_t location, uint32_t buffer, uint32_t offset, int32_t format) {
attr->location = location;
attr->buffer = buffer;
attr->offset = offset;
attr->format = format;
attr->index_type = 0;
attr->divisor = 0;
attr->destination_selector = attribute_dest_comp_selector[format & 0xff];
attr->endian_swap = GX2_ENDIANSWAP_DEFAULT;
}
static inline void GX2InitTexture(GX2Texture *tex, uint32_t width, uint32_t height, uint32_t depth, uint32_t num_mips, int32_t format, int32_t dimension, int32_t tile) {
tex->surface.dimension = dimension;
tex->surface.width = width;
tex->surface.height = height;
tex->surface.depth = depth;
tex->surface.num_mips = num_mips;
tex->surface.format = format;
tex->surface.aa = GX2_AA_MODE_1X;
tex->surface.use = GX2_SURFACE_USE_TEXTURE;
tex->surface.image_size = 0;
tex->surface.image_data = NULL;
tex->surface.mip_size = 0;
tex->surface.mip_data = NULL;
tex->surface.tile = tile;
tex->surface.swizzle = 0;
tex->surface.align = 0;
tex->surface.pitch = 0;
uint32_t i;
for(i = 0; i < 13; i++)
tex->surface.mip_offset[i] = 0;
tex->view_first_mip = 0;
tex->view_mips_count = num_mips;
tex->view_first_slice = 0;
tex->view_slices_count = depth;
tex->component_selector = texture_comp_selector[format & 0x3f];
for(i = 0; i < 5; i++)
tex->regs[i] = 0;
GX2CalcSurfaceSizeAndAlignment(&tex->surface);
GX2InitTextureRegs(tex);
}
#ifdef __cplusplus
}
#endif
#endif // __GX2_FUNCTIONS_H_

View File

@ -1,696 +0,0 @@
/****************************************************************************
* Copyright (C) 2015
* by Dimok
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any
* damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any
* purpose, including commercial applications, and to alter it and
* redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you
* must not claim that you wrote the original software. If you use
* this software in a product, an acknowledgment in the product
* documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and
* must not be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
***************************************************************************/
#ifndef _GX2_TYPES_H_
#define _GX2_TYPES_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
//!-----------------------------------------------------------------------------------------------------------------------
//! Constants
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_COMMAND_BUFFER_SIZE 0x400000
#define GX2_SCAN_BUFFER_ALIGNMENT 0x1000
#define GX2_SHADER_ALIGNMENT 0x100
#define GX2_CONTEXT_STATE_ALIGNMENT 0x100
#define GX2_DISPLAY_LIST_ALIGNMENT 0x20
#define GX2_VERTEX_BUFFER_ALIGNMENT 0x40
#define GX2_INDEX_BUFFER_ALIGNMENT 0x20
#define GX2_CONTEXT_STATE_SIZE 0xA100
#define GX2_AUX_BUFFER_CLEAR_VALUE 0xCC
//!-----------------------------------------------------------------------------------------------------------------------
//! Common
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_FALSE 0
#define GX2_TRUE 1
#define GX2_DISABLE 0
#define GX2_ENABLE 1
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2InitAttrib
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_INIT_ATTRIB_NULL 0
#define GX2_INIT_ATTRIB_CB_BASE 1
#define GX2_INIT_ATTRIB_CB_SIZE 2
#define GX2_INIT_ATTRIB_ARGC 7
#define GX2_INIT_ATTRIB_ARGV 8
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 compare functions
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_COMPARE_NEVER 0
#define GX2_COMPARE_LESS 1
#define GX2_COMPARE_EQUAL 2
#define GX2_COMPARE_LEQUAL 3
#define GX2_COMPARE_GREATER 4
#define GX2_COMPARE_NOTEQUAL 5
#define GX2_COMPARE_GEQUAL 6
#define GX2_COMPARE_ALWAYS 7
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 stencil functions
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_STENCIL_KEEP 0
#define GX2_STENCIL_ZERO 1
#define GX2_STENCIL_REPLACE 2
#define GX2_STENCIL_INCR 3
#define GX2_STENCIL_DECR 4
#define GX2_STENCIL_INVERT 5
#define GX2_STENCIL_INCR_WRAP 6
#define GX2_STENCIL_DECR_WRAP 7
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 logic op functions
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_LOGIC_OP_CLEAR 0x00
#define GX2_LOGIC_OP_NOR 0x11
#define GX2_LOGIC_OP_INVAND 0x22
#define GX2_LOGIC_OP_INVCOPY 0x33
#define GX2_LOGIC_OP_REVAND 0x44
#define GX2_LOGIC_OP_INV 0x55
#define GX2_LOGIC_OP_XOR 0x66
#define GX2_LOGIC_OP_NAND 0x77
#define GX2_LOGIC_OP_AND 0x88
#define GX2_LOGIC_OP_EQUIV 0x99
#define GX2_LOGIC_OP_NOOP 0xAA
#define GX2_LOGIC_OP_INVOR 0xBB
#define GX2_LOGIC_OP_COPY 0xCC
#define GX2_LOGIC_OP_REVOR 0xDD
#define GX2_LOGIC_OP_OR 0xEE
#define GX2_LOGIC_OP_SET 0xFF
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 blend combination functions
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_BLEND_COMBINE_ADD 0x00
#define GX2_BLEND_COMBINE_SRC_MINUS_DST 0x01
#define GX2_BLEND_COMBINE_MIN 0x02
#define GX2_BLEND_COMBINE_MAX 0x03
#define GX2_BLEND_COMBINE_DST_MINUS_SRC 0x04
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 blend functions
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_BLEND_ZERO 0x00
#define GX2_BLEND_ONE 0x01
#define GX2_BLEND_SRC_ALPHA 0x04
#define GX2_BLEND_ONE_MINUS_SRC_ALPHA 0x05
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 render targets
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_RENDER_TARGET_0 0
#define GX2_RENDER_TARGET_1 1
#define GX2_RENDER_TARGET_2 2
#define GX2_RENDER_TARGET_3 3
#define GX2_RENDER_TARGET_4 4
#define GX2_RENDER_TARGET_5 5
#define GX2_RENDER_TARGET_6 6
#define GX2_RENDER_TARGET_7 7
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 cull modes
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_FRONT_FACE_CCW 0
#define GX2_FRONT_FACE_CW 1
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 polygon modes
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_POLYGON_MODE_POINT 0
#define GX2_POLYGON_MODE_LINE 1
#define GX2_POLYGON_MODE_TRIANGLE 2
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 special states
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_SPECIAL_STATE_CLEAR 0
#define GX2_SPECIAL_STATE_CLEAR_HIZ 1
#define GX2_SPECIAL_STATE_COPY 2
#define GX2_SPECIAL_STATE_EXPAND_COLOR 3
#define GX2_SPECIAL_STATE_EXPAND_DEPTH 4
#define GX2_SPECIAL_STATE_CONVERT_DEPTH 5
#define GX2_SPECIAL_STATE_CONVERT_AADEPTH 6
#define GX2_SPECIAL_STATE_RESOLVE_COLOR 7
#define GX2_SPECIAL_STATE_CLEAR_COLOR_AS_DEPTH 8
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 attribute formats
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_ATTRIB_FORMAT_8_UNORM 0x00000000
#define GX2_ATTRIB_FORMAT_4_4_UNORM 0x00000001
#define GX2_ATTRIB_FORMAT_16_UNORM 0x00000002
#define GX2_ATTRIB_FORMAT_8_8_UNORM 0x00000004
#define GX2_ATTRIB_FORMAT_16_16_UNORM 0x00000007
#define GX2_ATTRIB_FORMAT_8_8_8_8_UNORM 0x0000000A
#define GX2_ATTRIB_FORMAT_10_10_10_2_UNORM 0x0000000B
#define GX2_ATTRIB_FORMAT_16_16_16_16_UNORM 0x0000000E
#define GX2_ATTRIB_FORMAT_8_UINT 0x00000100
#define GX2_ATTRIB_FORMAT_16_UINT 0x00000102
#define GX2_ATTRIB_FORMAT_8_8_UINT 0x00000104
#define GX2_ATTRIB_FORMAT_32_UINT 0x00000105
#define GX2_ATTRIB_FORMAT_16_16_UINT 0x00000107
#define GX2_ATTRIB_FORMAT_8_8_8_8_UINT 0x0000010A
#define GX2_ATTRIB_FORMAT_10_10_10_2_UINT 0x0000010B
#define GX2_ATTRIB_FORMAT_32_32_UINT 0x0000010C
#define GX2_ATTRIB_FORMAT_16_16_16_16_UINT 0x0000010E
#define GX2_ATTRIB_FORMAT_32_32_32_UINT 0x00000110
#define GX2_ATTRIB_FORMAT_32_32_32_32_UINT 0x00000112
#define GX2_ATTRIB_FORMAT_8_SNORM 0x00000200
#define GX2_ATTRIB_FORMAT_16_SNORM 0x00000202
#define GX2_ATTRIB_FORMAT_8_8_SNORM 0x00000204
#define GX2_ATTRIB_FORMAT_16_16_SNORM 0x00000207
#define GX2_ATTRIB_FORMAT_8_8_8_8_SNORM 0x0000020A
#define GX2_ATTRIB_FORMAT_10_10_10_2_SNORM 0x0000020B
#define GX2_ATTRIB_FORMAT_16_16_16_16_SNORM 0x0000020E
#define GX2_ATTRIB_FORMAT_8_SINT 0x00000300
#define GX2_ATTRIB_FORMAT_16_SINT 0x00000303
#define GX2_ATTRIB_FORMAT_8_8_SINT 0x00000304
#define GX2_ATTRIB_FORMAT_32_SINT 0x00000305
#define GX2_ATTRIB_FORMAT_16_16_SINT 0x00000307
#define GX2_ATTRIB_FORMAT_8_8_8_8_SINT 0x0000030A
#define GX2_ATTRIB_FORMAT_10_10_10_2_SINT 0x0000030B
#define GX2_ATTRIB_FORMAT_32_32_SINT 0x0000030C
#define GX2_ATTRIB_FORMAT_16_16_16_16_SINT 0x0000030E
#define GX2_ATTRIB_FORMAT_32_32_32_SINT 0x00000310
#define GX2_ATTRIB_FORMAT_32_32_32_32_SINT 0x00000312
#define GX2_ATTRIB_FORMAT_8_UINT_TO_FLOAT 0x00000800
#define GX2_ATTRIB_FORMAT_16_UINT_TO_FLOAT 0x00000802
#define GX2_ATTRIB_FORMAT_16_FLOAT 0x00000803
#define GX2_ATTRIB_FORMAT_8_8_UINT_TO_FLOAT 0x00000804
#define GX2_ATTRIB_FORMAT_32_FLOAT 0x00000806
#define GX2_ATTRIB_FORMAT_16_16_UINT_TO_FLOAT 0x00000807
#define GX2_ATTRIB_FORMAT_16_16_FLOAT 0x00000808
#define GX2_ATTRIB_FORMAT_10_11_11_FLOAT 0x00000809
#define GX2_ATTRIB_FORMAT_8_8_8_8_UINT_TO_FLOAT 0x0000080A
#define GX2_ATTRIB_FORMAT_32_32_FLOAT 0x0000080D
#define GX2_ATTRIB_FORMAT_16_16_16_16_UINT_TO_FLOAT 0x0000080E
#define GX2_ATTRIB_FORMAT_16_16_16_16_FLOAT 0x0000080F
#define GX2_ATTRIB_FORMAT_32_32_32_FLOAT 0x00000811
#define GX2_ATTRIB_FORMAT_32_32_32_32_FLOAT 0x00000813
#define GX2_ATTRIB_FORMAT_8_SINT_TO_FLOAT 0x00000A00
#define GX2_ATTRIB_FORMAT_16_SINT_TO_FLOAT 0x00000A02
#define GX2_ATTRIB_FORMAT_8_8_SINT_TO_FLOAT 0x00000A04
#define GX2_ATTRIB_FORMAT_16_16_SINT_TO_FLOAT 0x00000A07
#define GX2_ATTRIB_FORMAT_8_8_8_8_SINT_TO_FLOAT 0x00000A0A
#define GX2_ATTRIB_FORMAT_16_16_16_16_SINT_TO_FLOAT 0x00000A0E
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 shader modes
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_SHADER_MODE_UNIFORM_REGISTER 0
#define GX2_SHADER_MODE_UNIFORM_BLOCK 1
#define GX2_SHADER_MODE_GEOMETRY_SHADER 2
#define GX2_SHADER_MODE_COMPUTE_SHADER 3
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 shader modes
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_COMP_SEL_NONE 0x04040405
#define GX2_COMP_SEL_X001 0x00040405
#define GX2_COMP_SEL_XY01 0x00010405
#define GX2_COMP_SEL_XYZ1 0x00010205
#define GX2_COMP_SEL_XYZW 0x00010203
#define GX2_COMP_SEL_XXXX 0x00000000
#define GX2_COMP_SEL_YYYY 0x01010101
#define GX2_COMP_SEL_ZZZZ 0x02020202
#define GX2_COMP_SEL_WWWW 0x03030303
#define GX2_COMP_SEL_WZYX 0x03020100
#define GX2_COMP_SEL_WXYZ 0x03000102
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 variable types
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_VAR_TYPE_VOID 0
#define GX2_VAR_TYPE_BOOL 1
#define GX2_VAR_TYPE_INT 2
#define GX2_VAR_TYPE_UINT 3
#define GX2_VAR_TYPE_FLOAT 4
#define GX2_VAR_TYPE_DOUBLE 5
#define GX2_VAR_TYPE_VEC2 9
#define GX2_VAR_TYPE_VEC3 10
#define GX2_VAR_TYPE_VEC4 11
#define GX2_VAR_TYPE_MAT2 21
#define GX2_VAR_TYPE_MAT3 25
#define GX2_VAR_TYPE_MAT4 29
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 sample types
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_SAMPLER_TYPE_2D 1
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 index formats
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_INDEX_FORMAT_U16 4
#define GX2_INDEX_FORMAT_uint32_t 9
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 primitive types
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_PRIMITIVE_POINTS 0x01
#define GX2_PRIMITIVE_LINES 0x02
#define GX2_PRIMITIVE_LINE_STRIP 0x03
#define GX2_PRIMITIVE_TRIANGLES 0x04
#define GX2_PRIMITIVE_TRIANGLE_FAN 0x05
#define GX2_PRIMITIVE_TRIANGLE_STRIP 0x06
#define GX2_PRIMITIVE_RECTS 0x11
#define GX2_PRIMITIVE_QUADS 0x13
#define GX2_PRIMITIVE_QUAD_STRIP 0x14
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 clear modes
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_CLEAR_DEPTH 0x01
#define GX2_CLEAR_STENCIL 0x02
#define GX2_CLEAR_BOTH (GX2_CLEAR_DEPTH | GX2_CLEAR_STENCIL)
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 surface formats
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_SURFACE_FORMAT_TC_R8_UNORM 0x00000001
#define GX2_SURFACE_FORMAT_T_R4_G4_UNORM 0x00000002
#define GX2_SURFACE_FORMAT_TCD_R16_UNORM 0x00000005
#define GX2_SURFACE_FORMAT_TC_R8_G8_UNORM 0x00000007
#define GX2_SURFACE_FORMAT_TCS_R5_G6_B5_UNORM 0x00000008
#define GX2_SURFACE_FORMAT_TC_R5_G5_B5_A1_UNORM 0x0000000a
#define GX2_SURFACE_FORMAT_TC_R4_G4_B4_A4_UNORM 0x0000000b
#define GX2_SURFACE_FORMAT_TC_A1_B5_G5_R5_UNORM 0x0000000c
#define GX2_SURFACE_FORMAT_TC_R16_G16_UNORM 0x0000000f
#define GX2_SURFACE_FORMAT_D_D24_S8_UNORM 0x00000011
#define GX2_SURFACE_FORMAT_T_R24_UNORM_X8 0x00000011
#define GX2_SURFACE_FORMAT_TCS_R10_G10_B10_A2_UNORM 0x00000019
#define GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM 0x0000001a
#define GX2_SURFACE_FORMAT_TCS_A2_B10_G10_R10_UNORM 0x0000001b
#define GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_UNORM 0x0000001f
#define GX2_SURFACE_FORMAT_T_BC1_UNORM 0x00000031
#define GX2_SURFACE_FORMAT_T_BC2_UNORM 0x00000032
#define GX2_SURFACE_FORMAT_T_BC3_UNORM 0x00000033
#define GX2_SURFACE_FORMAT_T_BC4_UNORM 0x00000034
#define GX2_SURFACE_FORMAT_T_BC5_UNORM 0x00000035
#define GX2_SURFACE_FORMAT_T_NV12_UNORM 0x00000081
#define GX2_SURFACE_FORMAT_TC_R8_UINT 0x00000101
#define GX2_SURFACE_FORMAT_TC_R16_UINT 0x00000105
#define GX2_SURFACE_FORMAT_TC_R8_G8_UINT 0x00000107
#define GX2_SURFACE_FORMAT_TC_R32_UINT 0x0000010d
#define GX2_SURFACE_FORMAT_TC_R16_G16_UINT 0x0000010f
#define GX2_SURFACE_FORMAT_T_X24_G8_UINT 0x00000111
#define GX2_SURFACE_FORMAT_TC_R10_G10_B10_A2_UINT 0x00000119
#define GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_UINT 0x0000011a
#define GX2_SURFACE_FORMAT_TC_A2_B10_G10_R10_UINT 0x0000011b
#define GX2_SURFACE_FORMAT_T_X32_G8_UINT_X24 0x0000011c
#define GX2_SURFACE_FORMAT_TC_R32_G32_UINT 0x0000011d
#define GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_UINT 0x0000011f
#define GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_UINT 0x00000122
#define GX2_SURFACE_FORMAT_TC_R8_SNORM 0x00000201
#define GX2_SURFACE_FORMAT_TC_R16_SNORM 0x00000205
#define GX2_SURFACE_FORMAT_TC_R8_G8_SNORM 0x00000207
#define GX2_SURFACE_FORMAT_TC_R16_G16_SNORM 0x0000020f
#define GX2_SURFACE_FORMAT_T_R10_G10_B10_A2_SNORM 0x00000219
#define GX2_SURFACE_FORMAT_TC_R10_G10_B10_A2_SNORM 0x00000219
#define GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_SNORM 0x0000021a
#define GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_SNORM 0x0000021f
#define GX2_SURFACE_FORMAT_T_BC4_SNORM 0x00000234
#define GX2_SURFACE_FORMAT_T_BC5_SNORM 0x00000235
#define GX2_SURFACE_FORMAT_TC_R8_SINT 0x00000301
#define GX2_SURFACE_FORMAT_TC_R16_SINT 0x00000305
#define GX2_SURFACE_FORMAT_TC_R8_G8_SINT 0x00000307
#define GX2_SURFACE_FORMAT_TC_R32_SINT 0x0000030d
#define GX2_SURFACE_FORMAT_TC_R16_G16_SINT 0x0000030f
#define GX2_SURFACE_FORMAT_TC_R10_G10_B10_A2_SINT 0x00000319
#define GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_SINT 0x0000031a
#define GX2_SURFACE_FORMAT_TC_R32_G32_SINT 0x0000031d
#define GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_SINT 0x0000031f
#define GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_SINT 0x00000322
#define GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_SRGB 0x0000041a
#define GX2_SURFACE_FORMAT_T_BC1_SRGB 0x00000431
#define GX2_SURFACE_FORMAT_T_BC2_SRGB 0x00000432
#define GX2_SURFACE_FORMAT_T_BC3_SRGB 0x00000433
#define GX2_SURFACE_FORMAT_TC_R16_FLOAT 0x00000806
#define GX2_SURFACE_FORMAT_TCD_R32_FLOAT 0x0000080e
#define GX2_SURFACE_FORMAT_TC_R16_G16_FLOAT 0x00000810
#define GX2_SURFACE_FORMAT_D_D24_S8_FLOAT 0x00000811
#define GX2_SURFACE_FORMAT_TC_R11_G11_B10_FLOAT 0x00000816
#define GX2_SURFACE_FORMAT_D_D32_FLOAT_S8_UINT_X24 0x0000081c
#define GX2_SURFACE_FORMAT_T_R32_FLOAT_X8_X24 0x0000081c
#define GX2_SURFACE_FORMAT_TC_R32_G32_FLOAT 0x0000081e
#define GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_FLOAT 0x00000820
#define GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_FLOAT 0x00000823
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 tile modes
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_TILE_MODE_DEFAULT 0x00000000
#define GX2_TILE_MODE_LINEAR_ALIGNED 0x00000001
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 surface use
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_SURFACE_USE_TEXTURE 0x00000001
#define GX2_SURFACE_USE_COLOR_BUFFER 0x00000002
#define GX2_SURFACE_USE_DEPTH_BUFFER 0x00000004
#define GX2_SURFACE_USE_SCAN_BUFFER 0x00000008
#define GX2_SURFACE_USE_FTV 0x80000000
#define GX2_SURFACE_USE_COLOR_BUFFER_TEXTURE (GX2_SURFACE_USE_COLOR_BUFFER | GX2_SURFACE_USE_TEXTURE)
#define GX2_SURFACE_USE_DEPTH_BUFFER_TEXTURE (GX2_SURFACE_USE_DEPTH_BUFFER | GX2_SURFACE_USE_TEXTURE)
#define GX2_SURFACE_USE_COLOR_BUFFER_FTV (GX2_SURFACE_USE_COLOR_BUFFER | GX2_SURFACE_USE_FTV)
#define GX2_SURFACE_USE_COLOR_BUFFER_TEXTURE_FTV (GX2_SURFACE_USE_COLOR_BUFFER_TEXTURE | GX2_SURFACE_USE_FTV)
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 surface dim
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_SURFACE_DIM_1D 0x00000000
#define GX2_SURFACE_DIM_2D 0x00000001
#define GX2_SURFACE_DIM_3D 0x00000002
#define GX2_SURFACE_DIM_CUBE 0x00000003
#define GX2_SURFACE_DIM_1D_ARRAY 0x00000004
#define GX2_SURFACE_DIM_2D_ARRAY 0x00000005
#define GX2_SURFACE_DIM_2D_MSAA 0x00000006
#define GX2_SURFACE_DIM_2D_MSAA_ARRAY 0x00000007
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 AA modes
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_AA_MODE_1X 0x00000000
#define GX2_AA_MODE_2X 0x00000001
#define GX2_AA_MODE_4X 0x00000002
#define GX2_AA_MODE_8X 0x00000003
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 texture clamp
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_TEX_CLAMP_WRAP 0x00000000
#define GX2_TEX_CLAMP_MIRROR 0x00000001
#define GX2_TEX_CLAMP_CLAMP 0x00000002
#define GX2_TEX_CLAMP_MIRROR_ONCE 0x00000003
#define GX2_TEX_CLAMP_CLAMP_HALF_BORDER 0x00000004
#define GX2_TEX_CLAMP_MIRROR_ONCE_HALF_BORDER 0x00000005
#define GX2_TEX_CLAMP_CLAMP_BORDER 0x00000006
#define GX2_TEX_CLAMP_MIRROR_ONCE_BORDER 0x00000007
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 texture filter
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_TEX_XY_FILTER_POINT 0x00000000
#define GX2_TEX_XY_FILTER_BILINEAR 0x00000001
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 TV scan modes
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_TV_SCAN_MODE_NONE 0x00000000
#define GX2_TV_SCAN_MODE_576I 0x00000001
#define GX2_TV_SCAN_MODE_480I 0x00000002
#define GX2_TV_SCAN_MODE_480P 0x00000003
#define GX2_TV_SCAN_MODE_720P 0x00000004
#define GX2_TV_SCAN_MODE_1080I 0x00000006
#define GX2_TV_SCAN_MODE_1080P 0x00000007
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 TV render modes
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_TV_RENDER_480_NARROW 0x00000001
#define GX2_TV_RENDER_480_WIDE 0x00000002
#define GX2_TV_RENDER_720 0x00000003
#define GX2_TV_RENDER_1080 0x00000005
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 DRC render modes
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_DRC_NONE 0x00000000
#define GX2_DRC_SINGLE 0x00000001
#define GX2_DRC_DOUBLE 0x00000002
#define GX2_DRC_SINGLE_30HZ 0x00000004
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 buffering mode
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_BUFFERING_SINGLE 0x00000001
#define GX2_BUFFERING_DOUBLE 0x00000002
#define GX2_BUFFERING_TRIPLE 0x00000003
#define GX2_BUFFERING_QUAD
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 scan targets
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_SCAN_TARGET_TV 0x00000001
#define GX2_SCAN_TARGET_DRC_FIRST 0x00000004
#define GX2_SCAN_TARGET_DRC_SECOND 0x00000008
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 invalidate types
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_INVALIDATE_ATTRIB_BUFFER 0x00000001
#define GX2_INVALIDATE_TEXTURE 0x00000002
#define GX2_INVALIDATE_UNIFORM_BLOCK 0x00000004
#define GX2_INVALIDATE_SHADER 0x00000008
#define GX2_INVALIDATE_COLOR_BUFFER 0x00000010
#define GX2_INVALIDATE_DEPTH_BUFFER 0x00000020
#define GX2_INVALIDATE_CPU 0x00000040
#define GX2_INVALIDATE_CPU_ATTRIB_BUFFER (GX2_INVALIDATE_CPU | GX2_INVALIDATE_ATTRIB_BUFFER)
#define GX2_INVALIDATE_CPU_TEXTURE (GX2_INVALIDATE_CPU | GX2_INVALIDATE_TEXTURE)
#define GX2_INVALIDATE_CPU_UNIFORM_BLOCK (GX2_INVALIDATE_CPU | GX2_INVALIDATE_UNIFORM_BLOCK)
#define GX2_INVALIDATE_CPU_SHADER (GX2_INVALIDATE_CPU | GX2_INVALIDATE_SHADER)
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 swap modes
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_ENDIANSWAP_DEFAULT 0x00000003
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 tessellation modes
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_TESSELLATION_MODE_DISCRETE 0x00000000
#define GX2_TESSELLATION_MODE_CONTINUOUS 0x00000001
#define GX2_TESSELLATION_MODE_ADAPTIVE 0x00000002
//!-----------------------------------------------------------------------------------------------------------------------
//! GX2 fetch shader types
//!-----------------------------------------------------------------------------------------------------------------------
#define GX2_FETCH_SHADER_TESSELATION_NONE 0x00000000
#define GX2_FETCH_SHADER_TESSELATION_LINES 0x00000001
#define GX2_FETCH_SHADER_TESSELATION_TRIANGLES 0x00000002
#define GX2_FETCH_SHADER_TESSELATION_QUADS 0x00000003
typedef struct _GX2ContextState {
uint8_t data[GX2_CONTEXT_STATE_SIZE];
} GX2ContextState;
typedef struct _GX2Surface {
int32_t dimension;
uint32_t width;
uint32_t height;
uint32_t depth;
uint32_t num_mips;
int32_t format;
int32_t aa;
int32_t use;
uint32_t image_size;
void *image_data;
uint32_t mip_size;
void *mip_data;
int32_t tile;
uint32_t swizzle;
uint32_t align;
uint32_t pitch;
uint32_t mip_offset[13];
} GX2Surface;
typedef struct _GX2ColorBuffer {
GX2Surface surface;
uint32_t view_mip;
uint32_t view_first_slice;
uint32_t view_slices_count;
void *aux_data;
uint32_t aux_size;
uint32_t regs[5];
} GX2ColorBuffer;
typedef struct _GX2DepthBuffer {
GX2Surface surface;
uint32_t view_mip;
uint32_t view_first_slice;
uint32_t view_slices_count;
void *hiZ_data;
uint32_t hiZ_size;
float clear_depth;
uint32_t clear_stencil;
uint32_t regs[7];
} GX2DepthBuffer;
typedef struct _GX2Texture {
GX2Surface surface;
uint32_t view_first_mip;
uint32_t view_mips_count;
uint32_t view_first_slice;
uint32_t view_slices_count;
uint32_t component_selector;
uint32_t regs[5];
} GX2Texture;
typedef struct _GX2Sampler {
uint32_t regs[3];
} GX2Sampler;
typedef struct _GX2AttribStream {
uint32_t location;
uint32_t buffer;
uint32_t offset;
int32_t format;
int32_t index_type;
uint32_t divisor;
uint32_t destination_selector;
int32_t endian_swap;
} GX2AttribStream;
typedef struct _GX2FetchShader {
int32_t type;
uint32_t reg;
uint32_t shader_size;
void *shader_program;
uint32_t attributes_count;
uint32_t divisor[3];
} GX2FetchShader;
typedef struct _GX2AttribVar {
const char *name;
int32_t var_type;
uint32_t array_count;
uint32_t location;
} GX2AttribVar;
typedef struct _GX2UniformBlock {
const char *name;
uint32_t location;
uint32_t block_size;
} GX2UniformBlock;
typedef struct _GX2UniformInitialValue {
float value[4];
uint32_t offset;
} GX2UniformInitialValue;
typedef struct _GX2SamplerVar {
const char *name;
int32_t sampler_type;
uint32_t location;
} GX2SamplerVar;
typedef struct _GX2UniformVar {
const char *name;
int32_t var_type;
uint32_t array_count;
uint32_t offset;
uint32_t block_index;
} GX2UniformVar;
typedef struct _GX2VertexShader {
uint32_t regs[52];
uint32_t shader_size;
void *shader_data;
int32_t shader_mode;
uint32_t uniform_blocks_count;
GX2UniformBlock *uniform_block;
uint32_t uniform_vars_count;
GX2UniformVar *uniform_var;
uint32_t initial_values_count;
GX2UniformInitialValue *initial_value;
uint32_t loops_count;
void *loops_data;
uint32_t sampler_vars_count;
GX2SamplerVar *sampler_var;
uint32_t attribute_vars_count;
GX2AttribVar *attribute_var;
uint32_t data[6];
uint32_t shader_program_buffer[16];
} GX2VertexShader;
typedef struct _GX2PixelShader {
uint32_t regs[41];
uint32_t shader_size;
void *shader_data;
int32_t shader_mode;
uint32_t uniform_blocks_count;
GX2UniformBlock *uniform_block;
uint32_t uniform_vars_count;
GX2UniformVar *uniform_var;
uint32_t initial_values_count;
GX2UniformInitialValue *initial_value;
uint32_t loops_count;
void *loops_data;
uint32_t sampler_vars_count;
GX2SamplerVar *sampler_var;
uint32_t shader_program_buffer[16];
} GX2PixelShader;
static const uint32_t attribute_dest_comp_selector[20] = {
GX2_COMP_SEL_X001, GX2_COMP_SEL_XY01, GX2_COMP_SEL_X001, GX2_COMP_SEL_X001, GX2_COMP_SEL_XY01, GX2_COMP_SEL_X001,
GX2_COMP_SEL_X001, GX2_COMP_SEL_XY01, GX2_COMP_SEL_XY01, GX2_COMP_SEL_XYZ1, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_XYZW,
GX2_COMP_SEL_XY01, GX2_COMP_SEL_XY01, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_XYZ1, GX2_COMP_SEL_XYZ1,
GX2_COMP_SEL_XYZW, GX2_COMP_SEL_XYZW
};
static const uint32_t texture_comp_selector[54] = {
GX2_COMP_SEL_NONE, GX2_COMP_SEL_X001, GX2_COMP_SEL_XY01, GX2_COMP_SEL_NONE, GX2_COMP_SEL_NONE, GX2_COMP_SEL_X001,
GX2_COMP_SEL_X001, GX2_COMP_SEL_XY01, GX2_COMP_SEL_XYZ1, GX2_COMP_SEL_XYZ1, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_XYZW,
GX2_COMP_SEL_WZYX, GX2_COMP_SEL_X001, GX2_COMP_SEL_X001, GX2_COMP_SEL_XY01, GX2_COMP_SEL_XY01, GX2_COMP_SEL_NONE,
GX2_COMP_SEL_NONE, GX2_COMP_SEL_NONE, GX2_COMP_SEL_NONE, GX2_COMP_SEL_NONE, GX2_COMP_SEL_XYZ1, GX2_COMP_SEL_NONE,
GX2_COMP_SEL_NONE, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_WZYX, GX2_COMP_SEL_XY01, GX2_COMP_SEL_XY01,
GX2_COMP_SEL_XY01, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_NONE, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_XYZW,
GX2_COMP_SEL_NONE, GX2_COMP_SEL_NONE, GX2_COMP_SEL_NONE, GX2_COMP_SEL_XYZ1, GX2_COMP_SEL_XYZ1, GX2_COMP_SEL_X001,
GX2_COMP_SEL_XY01, GX2_COMP_SEL_XYZ1, GX2_COMP_SEL_NONE, GX2_COMP_SEL_NONE, GX2_COMP_SEL_NONE, GX2_COMP_SEL_XYZ1,
GX2_COMP_SEL_XYZ1, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_XYZW, GX2_COMP_SEL_X001, GX2_COMP_SEL_XY01
};
typedef struct _GX2Color {
uint8_t r, g, b, a;
} GX2Color;
typedef struct _GX2Colorfloat {
float r, g, b, a;
} GX2Colorfloat;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,118 +0,0 @@
/****************************************************************************
* Copyright (C) 2015
* by Dimok
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any
* damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any
* purpose, including commercial applications, and to alter it and
* redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you
* must not claim that you wrote the original software. If you use
* this software in a product, an acknowledgment in the product
* documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and
* must not be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
***************************************************************************/
#include "coreinit.h"
#include "socket_functions.h"
uint32_t hostIpAddress = 0;
uint32_t nsysnet_handle __attribute__((section(".data"))) = 0;
EXPORT_DECL(int32_t, socket_lib_init, void);
EXPORT_DECL(int32_t, socket_lib_finish, void);
EXPORT_DECL(int32_t, socket, int32_t domain, int32_t type, int32_t protocol);
EXPORT_DECL(int32_t, socketclose, int32_t s);
EXPORT_DECL(int32_t, shutdown, int32_t s, int32_t how);
EXPORT_DECL(int32_t, connect, int32_t s, void *addr, int32_t addrlen);
EXPORT_DECL(int32_t, bind, int32_t s,struct sockaddr *name,int32_t namelen);
EXPORT_DECL(int32_t, listen, int32_t s,uint32_t backlog);
EXPORT_DECL(int32_t, accept, int32_t s,struct sockaddr *addr,int32_t *addrlen);
EXPORT_DECL(int32_t, send, int32_t s, const void *buffer, int32_t size, int32_t flags);
EXPORT_DECL(int32_t, recv, int32_t s, void *buffer, int32_t size, int32_t flags);
EXPORT_DECL(int32_t, recvfrom,int32_t sockfd, void *buf, int32_t len, int32_t flags,struct sockaddr *src_addr, int32_t *addrlen);
EXPORT_DECL(int32_t, sendto, int32_t s, const void *buffer, int32_t size, int32_t flags, const struct sockaddr *dest, int32_t dest_len);
EXPORT_DECL(int32_t, setsockopt, int32_t s, int32_t level, int32_t optname, void *optval, int32_t optlen);
EXPORT_DECL(char *, inet_ntoa, struct in_addr in);
EXPORT_DECL(int32_t, inet_aton, const char *cp, struct in_addr *inp);
EXPORT_DECL(const char *, inet_ntop, int32_t af, const void *src, char *dst, int32_t size);
EXPORT_DECL(int32_t, inet_pton, int32_t af, const char *src, void *dst);
EXPORT_DECL(int32_t, socketlasterr, void);
EXPORT_DECL(int32_t, NSSLInit, void);
EXPORT_DECL(int32_t, NSSLFinish, void);
EXPORT_DECL(int32_t, NSSLCreateContext, int32_t unkwn);
EXPORT_DECL(int32_t, NSSLDestroyContext, int32_t context);
EXPORT_DECL(int32_t, NSSLAddServerPKI, int32_t context, int32_t pki);
EXPORT_DECL(int32_t, NSSLAddServerPKIExternal, int32_t context, const uint8_t* cert, int32_t length, int32_t unkwn);
EXPORT_DECL(int32_t, NSSLWrite, int32_t connection, const void* buf, int32_t len,int32_t * written);
EXPORT_DECL(int32_t, NSSLRead, int32_t connection, const void* buf, int32_t len,int32_t * read);
EXPORT_DECL(int32_t, NSSLCreateConnection, int32_t context, const char* host, int32_t hotlen,int32_t options,int32_t sock,int32_t block);
void InitAcquireSocket(void) {
OSDynLoad_Acquire("nsysnet.rpl", &nsysnet_handle);
}
void InitSocketFunctionPointers(void) {
uint32_t *funcPointer = 0;
InitAcquireSocket();
uint32_t nn_ac_handle;
int32_t(*ACInitialize)();
int32_t(*ACGetStartupId) (uint32_t *id);
int32_t(*ACConnectWithConfigId) (uint32_t id);
int32_t(*ACGetAssignedAddress) (uint32_t * ip);
OSDynLoad_Acquire("nn_ac.rpl", &nn_ac_handle);
OSDynLoad_FindExport(nn_ac_handle, 0, "ACInitialize", &ACInitialize);
OSDynLoad_FindExport(nn_ac_handle, 0, "ACGetStartupId", &ACGetStartupId);
OSDynLoad_FindExport(nn_ac_handle, 0, "ACConnectWithConfigId",&ACConnectWithConfigId);
OSDynLoad_FindExport(nn_ac_handle, 0, "ACGetAssignedAddress",&ACGetAssignedAddress);
OS_FIND_EXPORT(nsysnet_handle, socket_lib_init);
OS_FIND_EXPORT(nsysnet_handle, socket_lib_finish);
OS_FIND_EXPORT(nsysnet_handle, socketlasterr);
OS_FIND_EXPORT(nsysnet_handle, socket);
OS_FIND_EXPORT(nsysnet_handle, socketclose);
OS_FIND_EXPORT(nsysnet_handle, shutdown);
OS_FIND_EXPORT(nsysnet_handle, connect);
OS_FIND_EXPORT(nsysnet_handle, bind);
OS_FIND_EXPORT(nsysnet_handle, listen);
OS_FIND_EXPORT(nsysnet_handle, accept);
OS_FIND_EXPORT(nsysnet_handle, send);
OS_FIND_EXPORT(nsysnet_handle, recv);
OS_FIND_EXPORT(nsysnet_handle, recvfrom);
OS_FIND_EXPORT(nsysnet_handle, sendto);
OS_FIND_EXPORT(nsysnet_handle, setsockopt);
OS_FIND_EXPORT(nsysnet_handle, inet_ntoa);
OS_FIND_EXPORT(nsysnet_handle, inet_aton);
OS_FIND_EXPORT(nsysnet_handle, inet_ntop);
OS_FIND_EXPORT(nsysnet_handle, inet_pton);
OS_FIND_EXPORT(nsysnet_handle, NSSLInit);
OS_FIND_EXPORT(nsysnet_handle, NSSLFinish);
OS_FIND_EXPORT(nsysnet_handle, NSSLCreateContext);
OS_FIND_EXPORT(nsysnet_handle, NSSLDestroyContext);
OS_FIND_EXPORT(nsysnet_handle, NSSLAddServerPKI);
OS_FIND_EXPORT(nsysnet_handle, NSSLAddServerPKIExternal);
OS_FIND_EXPORT(nsysnet_handle, NSSLWrite);
OS_FIND_EXPORT(nsysnet_handle, NSSLRead);
OS_FIND_EXPORT(nsysnet_handle, NSSLCreateConnection);
uint32_t nn_startupid;
ACInitialize();
ACGetStartupId(&nn_startupid);
ACConnectWithConfigId(nn_startupid);
ACGetAssignedAddress(&hostIpAddress);
socket_lib_init();
}

View File

@ -1,124 +0,0 @@
/****************************************************************************
* Copyright (C) 2015
* by Dimok
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any
* damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any
* purpose, including commercial applications, and to alter it and
* redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you
* must not claim that you wrote the original software. If you use
* this software in a product, an acknowledgment in the product
* documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and
* must not be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
***************************************************************************/
#ifndef __SOCKET_FUNCTIONS_H_
#define __SOCKET_FUNCTIONS_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
extern uint32_t nsysnet_handle;
extern uint32_t hostIpAddress;
#define INADDR_ANY 0
#define INADDR_BROADCAST 0xFFFFFFFF
#define AF_INET 2
#define SHUT_RD 0
#define SHUT_WR 1
#define SHUT_RDWR 2
#define SOCK_STREAM 1
#define SOCK_DGRAM 2
#define IPPROTO_IP 0
#define IPPROTO_TCP 6
#define IPPROTO_UDP 17
#define TCP_NODELAY 0x2004
#define SOL_SOCKET -1
#define SO_REUSEADDR 0x0004
#define SO_BROADCAST 0x0020 // broadcast
#define SO_NONBLOCK 0x1016
#define SO_MYADDR 0x1013
#define SO_RCVTIMEO 0x1006
#define SOL_SOCKET -1
#define MSG_DONTWAIT 32
#define htonl(x) x
#define htons(x) x
#define ntohl(x) x
#define ntohs(x) x
struct in_addr {
uint32_t s_addr;
};
struct sockaddr_in {
short sin_family;
unsigned short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
struct sockaddr {
unsigned short sa_family;
char sa_data[14];
};
void InitSocketFunctionPointers(void);
void InitAcquireSocket(void);
extern int32_t (*socket_lib_init)(void);
extern int32_t (*socket_lib_finish)(void);
extern int32_t (*socket)(int32_t domain, int32_t type, int32_t protocol);
extern int32_t (*socketclose)(int32_t s);
extern int32_t (*shutdown)(int32_t s, int32_t how);
extern int32_t (*connect)(int32_t s, void *addr, int32_t addrlen);
extern int32_t (*bind)(int32_t s,struct sockaddr *name,int32_t namelen);
extern int32_t (*listen)(int32_t s,uint32_t backlog);
extern int32_t (*accept)(int32_t s,struct sockaddr *addr,int32_t *addrlen);
extern int32_t (*send)(int32_t s, const void *buffer, int32_t size, int32_t flags);
extern int32_t (*recv)(int32_t s, void *buffer, int32_t size, int32_t flags);
extern int32_t (*recvfrom)(int32_t sockfd, void *buf, int32_t len, int32_t flags,struct sockaddr *src_addr, int32_t *addrlen);
extern int32_t (*socketlasterr)(void);
extern int32_t (*sendto)(int32_t s, const void *buffer, int32_t size, int32_t flags, const struct sockaddr *dest, int32_t dest_len);
extern int32_t (*setsockopt)(int32_t s, int32_t level, int32_t optname, void *optval, int32_t optlen);
extern int32_t (* NSSLInit)(void);
extern int32_t (* NSSLFinish)(void);
extern int32_t (* NSSLCreateContext)(int32_t unkwn);
extern int32_t (* NSSLDestroyContext)(int32_t context);
extern int32_t (* NSSLAddServerPKIExternal)(int32_t context, const uint8_t* cert, int32_t length, int32_t unkwn);
extern int32_t (* NSSLAddServerPKI)(int32_t context, int32_t pki);
extern int32_t (* NSSLWrite)(int32_t connection, const void* buf, int32_t len,int32_t * written);
extern int32_t (* NSSLRead)(int32_t connection, const void* buf, int32_t len,int32_t * read);
extern int32_t (* NSSLCreateConnection)(int32_t context, const char* host, int32_t hotlen,int32_t options,int32_t sock,int32_t block);
extern char * (*inet_ntoa)(struct in_addr in);
extern int32_t (*inet_aton)(const char *cp, struct in_addr *inp);
extern const char * (*inet_ntop)(int32_t af, const void *src, char *dst, int32_t size);
extern int32_t (*inet_pton)(int32_t af, const char *src, void *dst);
#ifdef __cplusplus
}
#endif
#endif // __SOCKET_FUNCTIONS_H_

View File

@ -1,170 +0,0 @@
/****************************************************************************
* Copyright (C) 2015
* by Dimok
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any
* damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any
* purpose, including commercial applications, and to alter it and
* redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you
* must not claim that you wrote the original software. If you use
* this software in a product, an acknowledgment in the product
* documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and
* must not be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
***************************************************************************/
#include "coreinit.h"
#include "vpad_functions.h"
uint32_t vpad_handle __attribute__((section(".data"))) = 0;
uint32_t vpadbase_handle __attribute__((section(".data"))) = 0;
EXPORT_DECL(void, VPADInit, void);
EXPORT_DECL(void, VPADShutdown, void);
EXPORT_DECL(int32_t, VPADRead, int32_t chan, VPADData *buffer, uint32_t buffer_size, int32_t *error);
EXPORT_DECL(void, VPADSetAccParam, int32_t chan, float play_radius, float sensitivity);
EXPORT_DECL(void, VPADGetAccParam, int32_t chan, float *play_radius, float *sensitivity);
EXPORT_DECL(void, VPADSetBtnRepeat, int32_t chan, float delay_sec, float pulse_sec);
EXPORT_DECL(void, VPADEnableStickCrossClamp, int32_t chan);
EXPORT_DECL(void, VPADDisableStickCrossClamp, int32_t chan);
EXPORT_DECL(void, VPADSetLStickClampThreshold, int32_t chan, int32_t max, int32_t min);
EXPORT_DECL(void, VPADSetRStickClampThreshold, int32_t chan, int32_t max, int32_t min);
EXPORT_DECL(void, VPADGetLStickClampThreshold, int32_t chan, int32_t* max, int32_t* min);
EXPORT_DECL(void, VPADGetRStickClampThreshold, int32_t chan, int32_t* max, int32_t* min);
EXPORT_DECL(void, VPADSetStickOrigin, int32_t chan);
EXPORT_DECL(void, VPADDisableLStickZeroClamp, int32_t chan);
EXPORT_DECL(void, VPADDisableRStickZeroClamp, int32_t chan);
EXPORT_DECL(void, VPADEnableLStickZeroClamp, int32_t chan);
EXPORT_DECL(void, VPADEnableRStickZeroClamp, int32_t chan);
EXPORT_DECL(void, VPADSetCrossStickEmulationParamsL, int32_t chan, float rot_deg, float xy_deg, float radius);
EXPORT_DECL(void, VPADSetCrossStickEmulationParamsR, int32_t chan, float rot_deg, float xy_deg, float radius);
EXPORT_DECL(void, VPADGetCrossStickEmulationParamsL, int32_t chan, float* rot_deg, float* xy_deg, float* radius);
EXPORT_DECL(void, VPADGetCrossStickEmulationParamsR, int32_t chan, float* rot_deg, float* xy_deg, float* radius);
EXPORT_DECL(void, VPADSetGyroAngle, int32_t chan, float ax, float ay, float az);
EXPORT_DECL(void, VPADSetGyroDirection, int32_t chan, VPADDir *dir);
EXPORT_DECL(void, VPADSetGyroDirectionMag, int32_t chan, float mag);
EXPORT_DECL(void, VPADSetGyroMagnification, int32_t chan, float pitch, float yaw, float roll);
EXPORT_DECL(void, VPADEnableGyroZeroPlay, int32_t chan);
EXPORT_DECL(void, VPADEnableGyroDirRevise, int32_t chan);
EXPORT_DECL(void, VPADEnableGyroAccRevise, int32_t chan);
EXPORT_DECL(void, VPADDisableGyroZeroPlay, int32_t chan);
EXPORT_DECL(void, VPADDisableGyroDirRevise, int32_t chan);
EXPORT_DECL(void, VPADDisableGyroAccRevise, int32_t chan);
EXPORT_DECL(float, VPADIsEnableGyroZeroPlay, int32_t chan);
EXPORT_DECL(float, VPADIsEnableGyroZeroDrift, int32_t chan);
EXPORT_DECL(float, VPADIsEnableGyroDirRevise, int32_t chan);
EXPORT_DECL(float, VPADIsEnableGyroAccRevise, int32_t chan);
EXPORT_DECL(void, VPADSetGyroZeroPlayParam, int32_t chan, float radius);
EXPORT_DECL(void, VPADSetGyroDirReviseParam, int32_t chan, float revis_pw);
EXPORT_DECL(void, VPADSetGyroAccReviseParam, int32_t chan, float revise_pw, float revise_range);
EXPORT_DECL(void, VPADSetGyroDirReviseBase, int32_t chan, VPADDir *base);
EXPORT_DECL(void, VPADGetGyroZeroPlayParam, int32_t chan, float *radius);
EXPORT_DECL(void, VPADGetGyroDirReviseParam, int32_t chan, float *revise_pw);
EXPORT_DECL(void, VPADGetGyroAccReviseParam, int32_t chan, float *revise_pw, float *revise_range);
EXPORT_DECL(void, VPADInitGyroZeroPlayParam, int32_t chan);
EXPORT_DECL(void, VPADInitGyroDirReviseParam, int32_t chan);
EXPORT_DECL(void, VPADInitGyroAccReviseParam, int32_t chan);
EXPORT_DECL(void, VPADInitGyroZeroDriftMode, int32_t chan);
EXPORT_DECL(void, VPADSetGyroZeroDriftMode, int32_t chan, VPADGyroZeroDriftMode mode);
EXPORT_DECL(void, VPADGetGyroZeroDriftMode, int32_t chan, VPADGyroZeroDriftMode *mode);
EXPORT_DECL(int16_t, VPADCalcTPCalibrationParam, VPADTPCalibrationParam* param, uint16_t rawX1, uint16_t rawY1, uint16_t x1, uint16_t y1, uint16_t rawX2, uint16_t rawY2, uint16_t x2, uint16_t y2);
EXPORT_DECL(void, VPADSetTPCalibrationParam, int32_t chan, const VPADTPCalibrationParam param);
EXPORT_DECL(void, VPADGetTPCalibrationParam, int32_t chan, VPADTPCalibrationParam* param);
EXPORT_DECL(void, VPADGetTPCalibratedPoint, int32_t chan, VPADTPData *disp, const VPADTPData *raw);
EXPORT_DECL(void, VPADGetTPCalibratedPointEx, int32_t chan, VPADTPResolution tpReso, VPADTPData *disp, const VPADTPData *raw);
EXPORT_DECL(int32_t, VPADControlMotor, int32_t chan, uint8_t* pattern, uint8_t length);
EXPORT_DECL(void, VPADStopMotor, int32_t chan);
EXPORT_DECL(int32_t, VPADSetLcdMode, int32_t chan, int32_t lcdmode);
EXPORT_DECL(int32_t, VPADGetLcdMode, int32_t chan, int32_t *lcdmode);
EXPORT_DECL(int32_t, VPADBASEGetMotorOnRemainingCount, int32_t lcdmode);
EXPORT_DECL(int32_t, VPADBASESetMotorOnRemainingCount, int32_t lcdmode, int32_t counter);
EXPORT_DECL(void, VPADBASESetSensorBarSetting, int32_t chan, char setting);
EXPORT_DECL(void, VPADBASEGetSensorBarSetting, int32_t chan, char *setting);
EXPORT_DECL(int32_t, VPADSetSensorBar, int32_t chan, int32_t on);
EXPORT_DECL(samplingCallback, VPADSetSamplingCallback, int32_t chan, samplingCallback callbackn);
void InitAcquireVPad(void) {
if(coreinit_handle == 0) {
InitAcquireOS();
};
OSDynLoad_Acquire("vpad.rpl", &vpad_handle);
OSDynLoad_Acquire("vpadbase.rpl", &vpadbase_handle);
}
void InitVPadFunctionPointers(void) {
uint32_t *funcPointer = 0;
InitAcquireVPad();
OS_FIND_EXPORT(vpad_handle, VPADInit);
OS_FIND_EXPORT(vpad_handle, VPADShutdown);
OS_FIND_EXPORT(vpad_handle, VPADRead);
OS_FIND_EXPORT(vpad_handle, VPADSetAccParam);
OS_FIND_EXPORT(vpad_handle, VPADGetAccParam);
OS_FIND_EXPORT(vpad_handle, VPADSetBtnRepeat);
OS_FIND_EXPORT(vpad_handle, VPADEnableStickCrossClamp);
OS_FIND_EXPORT(vpad_handle, VPADDisableStickCrossClamp);
OS_FIND_EXPORT(vpad_handle, VPADSetLStickClampThreshold);
OS_FIND_EXPORT(vpad_handle, VPADSetRStickClampThreshold);
OS_FIND_EXPORT(vpad_handle, VPADGetLStickClampThreshold);
OS_FIND_EXPORT(vpad_handle, VPADGetRStickClampThreshold);
OS_FIND_EXPORT(vpad_handle, VPADSetStickOrigin);
OS_FIND_EXPORT(vpad_handle, VPADDisableLStickZeroClamp);
OS_FIND_EXPORT(vpad_handle, VPADDisableRStickZeroClamp);
OS_FIND_EXPORT(vpad_handle, VPADEnableLStickZeroClamp);
OS_FIND_EXPORT(vpad_handle, VPADEnableRStickZeroClamp);
OS_FIND_EXPORT(vpad_handle, VPADSetCrossStickEmulationParamsL);
OS_FIND_EXPORT(vpad_handle, VPADSetCrossStickEmulationParamsR);
OS_FIND_EXPORT(vpad_handle, VPADGetCrossStickEmulationParamsL);
OS_FIND_EXPORT(vpad_handle, VPADGetCrossStickEmulationParamsR);
OS_FIND_EXPORT(vpad_handle, VPADSetGyroAngle);
OS_FIND_EXPORT(vpad_handle, VPADSetGyroDirection);
OS_FIND_EXPORT(vpad_handle, VPADSetGyroDirectionMag);
OS_FIND_EXPORT(vpad_handle, VPADSetGyroMagnification);
OS_FIND_EXPORT(vpad_handle, VPADEnableGyroZeroPlay);
OS_FIND_EXPORT(vpad_handle, VPADEnableGyroDirRevise);
OS_FIND_EXPORT(vpad_handle, VPADEnableGyroAccRevise);
OS_FIND_EXPORT(vpad_handle, VPADDisableGyroZeroPlay);
OS_FIND_EXPORT(vpad_handle, VPADDisableGyroDirRevise);
OS_FIND_EXPORT(vpad_handle, VPADDisableGyroAccRevise);
OS_FIND_EXPORT(vpad_handle, VPADIsEnableGyroZeroPlay);
OS_FIND_EXPORT(vpad_handle, VPADIsEnableGyroZeroDrift);
OS_FIND_EXPORT(vpad_handle, VPADIsEnableGyroDirRevise);
OS_FIND_EXPORT(vpad_handle, VPADIsEnableGyroAccRevise);
OS_FIND_EXPORT(vpad_handle, VPADSetGyroZeroPlayParam);
OS_FIND_EXPORT(vpad_handle, VPADSetGyroDirReviseParam);
OS_FIND_EXPORT(vpad_handle, VPADSetGyroAccReviseParam);
OS_FIND_EXPORT(vpad_handle, VPADSetGyroDirReviseBase);
OS_FIND_EXPORT(vpad_handle, VPADGetGyroZeroPlayParam);
OS_FIND_EXPORT(vpad_handle, VPADGetGyroDirReviseParam);
OS_FIND_EXPORT(vpad_handle, VPADGetGyroAccReviseParam);
OS_FIND_EXPORT(vpad_handle, VPADInitGyroZeroPlayParam);
OS_FIND_EXPORT(vpad_handle, VPADInitGyroDirReviseParam);
OS_FIND_EXPORT(vpad_handle, VPADInitGyroAccReviseParam);
OS_FIND_EXPORT(vpad_handle, VPADInitGyroZeroDriftMode);
OS_FIND_EXPORT(vpad_handle, VPADSetGyroZeroDriftMode);
OS_FIND_EXPORT(vpad_handle, VPADGetGyroZeroDriftMode);
OS_FIND_EXPORT(vpad_handle, VPADCalcTPCalibrationParam);
OS_FIND_EXPORT(vpad_handle, VPADSetTPCalibrationParam);
OS_FIND_EXPORT(vpad_handle, VPADGetTPCalibrationParam);
OS_FIND_EXPORT(vpad_handle, VPADGetTPCalibratedPoint);
OS_FIND_EXPORT(vpad_handle, VPADGetTPCalibratedPointEx);
OS_FIND_EXPORT(vpad_handle, VPADControlMotor);
OS_FIND_EXPORT(vpad_handle, VPADStopMotor);
OS_FIND_EXPORT(vpad_handle, VPADSetLcdMode);
OS_FIND_EXPORT(vpad_handle, VPADGetLcdMode);
OS_FIND_EXPORT(vpad_handle, VPADSetSensorBar);
OS_FIND_EXPORT(vpad_handle, VPADSetSamplingCallback);
OS_FIND_EXPORT(vpadbase_handle, VPADBASEGetMotorOnRemainingCount);
OS_FIND_EXPORT(vpadbase_handle, VPADBASESetMotorOnRemainingCount);
OS_FIND_EXPORT(vpadbase_handle, VPADBASESetSensorBarSetting);
OS_FIND_EXPORT(vpadbase_handle, VPADBASEGetSensorBarSetting);
}

View File

@ -1,207 +0,0 @@
/****************************************************************************
* Copyright (C) 2015
* by Dimok
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any
* damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any
* purpose, including commercial applications, and to alter it and
* redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you
* must not claim that you wrote the original software. If you use
* this software in a product, an acknowledgment in the product
* documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and
* must not be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
***************************************************************************/
#ifndef __VPAD_FUNCTIONS_H_
#define __VPAD_FUNCTIONS_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
extern uint32_t vpad_handle;
extern uint32_t vpadbase_handle;
#define VPAD_BUTTON_A 0x8000
#define VPAD_BUTTON_B 0x4000
#define VPAD_BUTTON_X 0x2000
#define VPAD_BUTTON_Y 0x1000
#define VPAD_BUTTON_LEFT 0x0800
#define VPAD_BUTTON_RIGHT 0x0400
#define VPAD_BUTTON_UP 0x0200
#define VPAD_BUTTON_DOWN 0x0100
#define VPAD_BUTTON_ZL 0x0080
#define VPAD_BUTTON_ZR 0x0040
#define VPAD_BUTTON_L 0x0020
#define VPAD_BUTTON_R 0x0010
#define VPAD_BUTTON_PLUS 0x0008
#define VPAD_BUTTON_MINUS 0x0004
#define VPAD_BUTTON_HOME 0x0002
#define VPAD_BUTTON_SYNC 0x0001
#define VPAD_BUTTON_STICK_R 0x00020000
#define VPAD_BUTTON_STICK_L 0x00040000
#define VPAD_BUTTON_TV 0x00010000
#define VPAD_STICK_R_EMULATION_LEFT 0x04000000
#define VPAD_STICK_R_EMULATION_RIGHT 0x02000000
#define VPAD_STICK_R_EMULATION_UP 0x01000000
#define VPAD_STICK_R_EMULATION_DOWN 0x00800000
#define VPAD_STICK_L_EMULATION_LEFT 0x40000000
#define VPAD_STICK_L_EMULATION_RIGHT 0x20000000
#define VPAD_STICK_L_EMULATION_UP 0x10000000
#define VPAD_STICK_L_EMULATION_DOWN 0x08000000
//! Own definitions
#define VPAD_BUTTON_TOUCH 0x00080000
#define VPAD_MASK_EMULATED_STICKS 0x7F800000
#define VPAD_MASK_BUTTONS ~VPAD_MASK_EMULATED_STICKS
typedef enum VPADTPResolution {
VPAD_TP_1920x1080,
VPAD_TP_1280x720,
VPAD_TP_854x480
} VPADTPResolution;
typedef enum VPADGyroZeroDriftMode {
VPAD_GYRO_ZERODRIFT_LOOSE,
VPAD_GYRO_ZERODRIFT_STANDARD,
VPAD_GYRO_ZERODRIFT_TIGHT
} VPADGyroZeroDriftMode;
typedef struct {
float x,y;
} Vec2D;
typedef struct {
float x,y,z;
} Vec3D;
typedef struct {
Vec3D X,Y,Z;
} VPADDir;
typedef struct {
uint16_t x, y; /* Touch coordinates */
uint16_t touched; /* 1 = Touched, 0 = Not touched */
uint16_t invalid; /* 0 = All valid, 1 = X invalid, 2 = Y invalid, 3 = Both invalid? */
} VPADTPData;
typedef struct {
int16_t offsetX;
int16_t offsetY;
float scaleX;
float scaleY;
} VPADTPCalibrationParam;
typedef struct {
uint32_t btns_h; /* Held buttons */
uint32_t btns_d; /* Buttons that are pressed at that instant */
uint32_t btns_r; /* Released buttons */
Vec2D lstick, rstick; /* Each contains 4-byte X and Y components */
Vec3D acc; /* Status of DRC accelerometer */
float acc_magnitude; /* Accelerometer magnitude */
float acc_variation; /* Accelerometer variation */
Vec2D acc_vertical; /* Vertical */
Vec3D gyro; /* Gyro data */
Vec3D angle; /* Angle data */
char error; /* Error */
VPADTPData tpdata; /* Normal touchscreen data */
VPADTPData tpdata1; /* Modified touchscreen data 1 */
VPADTPData tpdata2; /* Modified touchscreen data 2 */
VPADDir dir; /* Orientation in three-dimensional space */
int32_t headphone; /* Set to TRUE if headphones are plugged in, FALSE otherwise */
Vec3D mag; /* Magnetometer data */
uint8_t volume; /* 0 to 255 */
uint8_t battery; /* 0 to 6 */
uint8_t mic; /* Microphone status */
uint8_t unk_volume; /* One less than volume */
uint8_t paddings[7];
} VPADData;
void InitVPadFunctionPointers(void);
void InitAcquireVPad(void);
extern void (* VPADInit)(void);
extern void (* VPADShutdown)(void);
extern int32_t (* VPADRead)(int32_t chan, VPADData *buffer, uint32_t buffer_size, int32_t *error);
extern void (* VPADSetAccParam)(int32_t chan, float play_radius, float sensitivity);
extern void (* VPADGetAccParam)(int32_t chan, float *play_radius, float *sensitivity);
extern void (* VPADSetBtnRepeat)(int32_t chan, float delay_sec, float pulse_sec);
extern void (* VPADEnableStickCrossClamp)(int32_t chan);
extern void (* VPADDisableStickCrossClamp)(int32_t chan);
extern void (* VPADSetLStickClampThreshold)(int32_t chan, int32_t max, int32_t min);
extern void (* VPADSetRStickClampThreshold)(int32_t chan, int32_t max, int32_t min);
extern void (* VPADGetLStickClampThreshold)(int32_t chan, int32_t* max, int32_t* min);
extern void (* VPADGetRStickClampThreshold)(int32_t chan, int32_t* max, int32_t* min);
extern void (* VPADSetStickOrigin)(int32_t chan);
extern void (* VPADDisableLStickZeroClamp)(int32_t chan);
extern void (* VPADDisableRStickZeroClamp)(int32_t chan);
extern void (* VPADEnableLStickZeroClamp)(int32_t chan);
extern void (* VPADEnableRStickZeroClamp)(int32_t chan);
extern void (* VPADSetCrossStickEmulationParamsL)(int32_t chan, float rot_deg, float xy_deg, float radius);
extern void (* VPADSetCrossStickEmulationParamsR)(int32_t chan, float rot_deg, float xy_deg, float radius);
extern void (* VPADGetCrossStickEmulationParamsL)(int32_t chan, float* rot_deg, float* xy_deg, float* radius);
extern void (* VPADGetCrossStickEmulationParamsR)(int32_t chan, float* rot_deg, float* xy_deg, float* radius);
extern void (* VPADSetGyroAngle)(int32_t chan, float ax, float ay, float az);
extern void (* VPADSetGyroDirection)(int32_t chan, VPADDir *dir);
extern void (* VPADSetGyroDirectionMag)(int32_t chan, float mag);
extern void (* VPADSetGyroMagnification)(int32_t chan, float pitch, float yaw, float roll);
extern void (* VPADEnableGyroZeroPlay)(int32_t chan);
extern void (* VPADEnableGyroDirRevise)(int32_t chan);
extern void (* VPADEnableGyroAccRevise)(int32_t chan);
extern void (* VPADDisableGyroZeroPlay)(int32_t chan);
extern void (* VPADDisableGyroDirRevise)(int32_t chan);
extern void (* VPADDisableGyroAccRevise)(int32_t chan);
extern float (* VPADIsEnableGyroZeroPlay)(int32_t chan);
extern float (* VPADIsEnableGyroZeroDrift)(int32_t chan);
extern float (* VPADIsEnableGyroDirRevise)(int32_t chan);
extern float (* VPADIsEnableGyroAccRevise)(int32_t chan);
extern void (* VPADSetGyroZeroPlayParam)(int32_t chan, float radius);
extern void (* VPADSetGyroDirReviseParam)(int32_t chan, float revis_pw);
extern void (* VPADSetGyroAccReviseParam)(int32_t chan, float revise_pw, float revise_range);
extern void (* VPADSetGyroDirReviseBase)(int32_t chan, VPADDir *base);
extern void (* VPADGetGyroZeroPlayParam)(int32_t chan, float *radius);
extern void (* VPADGetGyroDirReviseParam)(int32_t chan, float *revise_pw);
extern void (* VPADGetGyroAccReviseParam)(int32_t chan, float *revise_pw, float *revise_range);
extern void (* VPADInitGyroZeroPlayParam)(int32_t chan);
extern void (* VPADInitGyroDirReviseParam)(int32_t chan);
extern void (* VPADInitGyroAccReviseParam)(int32_t chan);
extern void (* VPADInitGyroZeroDriftMode)(int32_t chan);
extern void (* VPADSetGyroZeroDriftMode)(int32_t chan, VPADGyroZeroDriftMode mode);
extern void (* VPADGetGyroZeroDriftMode)(int32_t chan, VPADGyroZeroDriftMode *mode);
extern int16_t (* VPADCalcTPCalibrationParam)(VPADTPCalibrationParam* param, uint16_t rawX1, uint16_t rawY1, uint16_t x1, uint16_t y1, uint16_t rawX2, uint16_t rawY2, uint16_t x2, uint16_t y2);
extern void (* VPADSetTPCalibrationParam)(int32_t chan, const VPADTPCalibrationParam param);
extern void (* VPADGetTPCalibrationParam)(int32_t chan, VPADTPCalibrationParam* param);
extern void (* VPADGetTPCalibratedPoint)(int32_t chan, VPADTPData *disp, const VPADTPData *raw);
extern void (* VPADGetTPCalibratedPointEx)(int32_t chan, VPADTPResolution tpReso, VPADTPData *disp, const VPADTPData *raw);
extern int32_t (* VPADControlMotor)(int32_t chan, uint8_t* pattern, uint8_t length);
extern void (* VPADStopMotor)(int32_t chan);
extern int32_t (* VPADSetLcdMode)(int32_t chan, int32_t lcdmode);
extern int32_t (* VPADGetLcdMode)(int32_t chan, int32_t *lcdmode);
extern int32_t (* VPADBASEGetMotorOnRemainingCount)(int32_t lcdmode);
extern int32_t (* VPADBASESetMotorOnRemainingCount)(int32_t lcdmode, int32_t counter);
extern void (* VPADBASESetSensorBarSetting)(int32_t chan, char setting);
extern void (* VPADBASEGetSensorBarSetting)(int32_t chan, char *setting);
extern int32_t (*VPADSetSensorBar)(int32_t chan, int32_t on);
typedef void(*samplingCallback)(int32_t chan);
extern samplingCallback ( *VPADSetSamplingCallback)(int32_t chan, samplingCallback callback);
#ifdef __cplusplus
}
#endif
#endif // __VPAD_FUNCTIONS_H_

View File

@ -1,276 +0,0 @@
#include <string.h>
#include <stdint.h>
#include "dynamic_libs/coreinit.h"
#include "dynamic_libs/socket_functions.h"
#include "dynamic_libs/fs_functions.h"
#include "dynamic_libs/gx2_functions.h"
#include "dynamic_libs/vpad_functions.h"
#include "kernel/kernel_utils.h"
#include "memory/memory_mapping.h"
#include "memory/memory.h"
#include "utils/ConfigUtils.h"
#include "utils/function_patcher.h"
#include "utils/logger.h"
#include "utils/mem_utils.h"
#include "utils/ipc.h"
#include "utils.h"
#include "system/CThread.h"
#include "common/retain_vars.h"
#include "plugin/PluginLoader.h"
#include "plugin/DynamicLinkingHelper.h"
#include <fs/sd_fat_devoptab.h>
#include "patcher/function_patcher.h"
#include "patcher/hooks_patcher.h"
#include "patcher/hooks_patcher_static.h"
int SplashScreen(int32_t time,const char * message,uint8_t pos,uint32_t button) {
//Call the Screen initilzation function.
OSScreenInit();
int result = 0;
// Prepare screen
int32_t screen_buf0_size = 0;
// Init screen and screen buffers
OSScreenInit();
screen_buf0_size = OSScreenGetBufferSizeEx(0);
OSScreenSetBufferEx(0, (void *)0xF4000000);
OSScreenSetBufferEx(1, (void *)(0xF4000000 + screen_buf0_size));
OSScreenEnableEx(0, 1);
OSScreenEnableEx(1, 1);
// Clear screens
OSScreenClearBufferEx(0, 0);
OSScreenClearBufferEx(1, 0);
// Flip buffers
OSScreenFlipBuffersEx(0);
OSScreenFlipBuffersEx(1);
OSScreenPutFontEx(0, 0, pos, message);
OSScreenPutFontEx(1, 0, pos, message);
OSScreenFlipBuffersEx(0);
OSScreenFlipBuffersEx(1);
int32_t tickswait = time * 1000*1000;
int32_t times = 1000;
int32_t sleepingtime = tickswait / 1000;
int32_t i=0;
void(*OSSleepTicks)(uint64_t x);
OSDynLoad_FindExport(coreinit_handle, 0, "OSSleepTicks", &OSSleepTicks);
while(i<times) {
i++;
OSSleepTicks(OSMicrosecondsToTicks(sleepingtime));
}
return 1;
}
void readAndPrintSegmentRegister(CThread *thread, void *arg);
void ApplyPatchesAndCallHookStartingApp() {
PatchInvidualMethodHooks(method_hooks_hooks_static, method_hooks_size_hooks_static, method_calls_hooks_static);
PatchInvidualMethodHooks(method_hooks_hooks, method_hooks_size_hooks, method_calls_hooks);
for(int32_t plugin_index=0; plugin_index<gbl_replacement_data.number_used_plugins; plugin_index++) {
CallHookEx(WUPS_LOADER_HOOK_INIT_WUT_DEVOPTAB,plugin_index);
CallHookEx(WUPS_LOADER_HOOK_APPLICATION_START,plugin_index);
new_PatchInvidualMethodHooks(&gbl_replacement_data.plugin_data[plugin_index]);
CallHookEx(WUPS_LOADER_HOOK_FUNCTIONS_PATCHED,plugin_index);
}
}
void RestorePatches() {
for(int32_t plugin_index=gbl_replacement_data.number_used_plugins-1; plugin_index>=0; plugin_index--) {
new_RestoreInvidualInstructions(&gbl_replacement_data.plugin_data[plugin_index]);
}
RestoreInvidualInstructions(method_hooks_hooks, method_hooks_size_hooks);
RestoreInvidualInstructions(method_hooks_hooks_static, method_hooks_size_hooks_static);
}
void RestoreEverything() {
CallHook(WUPS_LOADER_HOOK_RELEASE_FOREGROUND);
CallHook(WUPS_LOADER_HOOK_APPLICATION_END);
CallHook(WUPS_LOADER_HOOK_DEINIT_PLUGIN);
CallHook(WUPS_LOADER_HOOK_FINI_WUT_DEVOPTAB);
CallHook(WUPS_LOADER_HOOK_FINI_WUT_STDCPP);
CallHook(WUPS_LOADER_HOOK_FINI_WUT_NEWLIB);
CallHook(WUPS_LOADER_HOOK_FINI_WUT_MALLOC);
// Restore patches as the patched functions could change.
RestorePatches();
DynamicLinkingHelper::getInstance()->clearAll();
gInBackground = false;
}
void ResolveRelocations() {
std::vector<dyn_linking_relocation_entry_t *> relocations = DynamicLinkingHelper::getInstance()->getAllValidDynamicLinkingRelocations();
DEBUG_FUNCTION_LINE("Found relocation information for %d functions\n",relocations.size());
if(!DynamicLinkingHelper::getInstance()->fillRelocations(relocations)) {
OSFatal("fillRelocations failed.");
}
}
void clearBSS(){
for(int32_t plugin_index=0; plugin_index<gbl_replacement_data.number_used_plugins; plugin_index++) {
replacement_data_plugin_t * curData = &gbl_replacement_data.plugin_data[plugin_index];
if(curData->bssAddr != 0){
DEBUG_FUNCTION_LINE("Clearing .bss section for %s. Addr: %08X size: %08X\n", curData->plugin_name, curData->bssAddr, curData->bssSize);
memset((void*)curData->bssAddr, 0, curData->bssSize);
}
if(curData->bssAddr != 0){
DEBUG_FUNCTION_LINE("Clearin .sbss section for %s. Addr: %08X size: %08X\n", curData->plugin_name, curData->sbssAddr, curData->sbssSize);
memset((void*)curData->sbssAddr, 0, curData->sbssSize);
}
}
}
void afterLoadAndLink() {
ResolveRelocations();
CallHook(WUPS_LOADER_HOOK_INIT_WUT_MALLOC);
CallHook(WUPS_LOADER_HOOK_INIT_WUT_NEWLIB);
CallHook(WUPS_LOADER_HOOK_INIT_WUT_STDCPP);
CallHook(WUPS_LOADER_HOOK_INIT_VID_MEM);
CallHook(WUPS_LOADER_HOOK_INIT_KERNEL);
CallHook(WUPS_LOADER_HOOK_INIT_OVERLAY);
ConfigUtils::loadConfigFromSD();
CallHook(WUPS_LOADER_HOOK_INIT_PLUGIN);
}
extern "C" void doStart(int argc, char **argv);
// We need to wrap it to make sure the main function is called AFTER our code.
// The compiler tries to optimize this otherwise and calling the main function earlier
extern "C" int _start(int argc, char **argv) {
doStart(argc,argv);
return ( (int (*)(int, char **))(*(unsigned int*)0x1005E040) )(argc, argv);
}
extern "C" void doStart(int argc, char **argv) {
coreinit_handle = 0;
InitOSFunctionPointers();
if(gInBackground) {
CallHook(WUPS_LOADER_HOOK_APPLET_START);
return;
}
gInBackground = true;
coreinit_handle = 0;
InitOSFunctionPointers();
InitSocketFunctionPointers();
InitFSFunctionPointers();
InitVPadFunctionPointers();
InitGX2FunctionPointers();
// is called once.
kernelInitialize();
gGameTitleID = OSGetTitleID();
memset(&tv_store,0,sizeof(tv_store));
memset(&drc_store,0,sizeof(drc_store));
log_init();
if(!MemoryMapping::isMemoryMapped()) {
MemoryMapping::setupMemoryMapping();
memset((void*)&gbl_replacement_data,0,sizeof(gbl_replacement_data));
DCFlushRange((void*)&gbl_replacement_data,sizeof(gbl_replacement_data));
ICInvalidateRange((void*)&gbl_replacement_data,sizeof(gbl_replacement_data));
memset((void*)&gbl_dyn_linking_data,0,sizeof(gbl_dyn_linking_data));
DCFlushRange((void*)&gbl_dyn_linking_data,sizeof(gbl_dyn_linking_data));
ICInvalidateRange((void*)&gbl_dyn_linking_data,sizeof(gbl_dyn_linking_data));
// Switch to custom heap
//Does not work =(
//initMemory();
//SplashScreen(1, "Memory mapping was completed!", 0,0);
memset(gbl_to_link_and_load_data,0, sizeof(gbl_to_link_and_load_data));
// Init space
DynamicLinkingHelper::getInstance()->clearAll();
// Init IPC
uint32_t* ipcFunction = (uint32_t*)(MEMORY_START_PLUGIN_SPACE);
*ipcFunction = (uint32_t) &ipc_ioctl;
DCFlushRange(ipcFunction,4);
ICInvalidateRange(ipcFunction,4);
// Do patches so memory mapping works fine with some functions.
PatchInvidualMethodHooks(method_hooks_hooks_static, method_hooks_size_hooks_static, method_calls_hooks_static);
// mount sd card.
mount_sd_fat("sd");
DEBUG_FUNCTION_LINE("Mounted SD\n");
PluginLoader * pluginLoader = new PluginLoader((void*)PLUGIN_LOCATION_START_ADDRESS, (void*)PLUGIN_LOCATION_END_ADDRESS);
std::vector<PluginInformation *> pluginList = pluginLoader->getPluginInformation("sd:/wiiu/autoboot_plugins/");
pluginLoader->loadAndLinkPlugins(pluginList);
pluginLoader->clearPluginInformation(pluginList);
delete pluginLoader;
clearBSS();
afterLoadAndLink();
} else {
DEBUG_FUNCTION_LINE("Mapping was already done\n");
//unmount_sd_fat("sd");
mount_sd_fat("sd");
//SplashScreen(5, "Memory mapping was already done!!", 0,0);
//readAndPrintSegmentRegister(NULL,NULL);
//MemoryMapping::writeTestValuesToMemory();
//MemoryMapping::readTestValuesFromMemory();
}
clearBSS();
if(gbl_to_link_and_load_data[0].name[0] != 0) {
ResolveRelocations();
CallHook(WUPS_LOADER_HOOK_DEINIT_PLUGIN);
// Restore patches as the patched functions could change.
RestorePatches();
DynamicLinkingHelper::getInstance()->clearAll();
PluginLoader * pluginLoader = new PluginLoader((void*)PLUGIN_LOCATION_START_ADDRESS, (void*)PLUGIN_LOCATION_END_ADDRESS);
std::vector<PluginInformation *> pluginList;
for(int i = 0; gbl_to_link_and_load_data[i].name[0] != 0; i++) {
PluginInformation * info = PluginInformation::loadPluginInformation(gbl_to_link_and_load_data[i].name);
if(info != NULL) {
pluginList.push_back(info);
}
}
pluginLoader->loadAndLinkPlugins(pluginList);
pluginLoader->clearPluginInformation(pluginList);
delete pluginLoader;
clearBSS();
afterLoadAndLink();
memset(gbl_to_link_and_load_data,0, sizeof(gbl_to_link_and_load_data));
}
ResolveRelocations();
MemoryUtils::init();
DEBUG_FUNCTION_LINE("Apply patches.\n");
ApplyPatchesAndCallHookStartingApp();
DEBUG_FUNCTION_LINE("Patches applied. Running application.\n");
}

View File

@ -1,174 +0,0 @@
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include "CFile.hpp"
CFile::CFile() {
iFd = -1;
mem_file = NULL;
filesize = 0;
pos = 0;
}
CFile::CFile(const std::string & filepath, eOpenTypes mode) {
iFd = -1;
this->open(filepath, mode);
}
CFile::CFile(const uint8_t * mem, int32_t size) {
iFd = -1;
this->open(mem, size);
}
CFile::~CFile() {
this->close();
}
int32_t CFile::open(const std::string & filepath, eOpenTypes mode) {
this->close();
int32_t openMode = 0;
switch(mode) {
default:
case ReadOnly:
openMode = O_RDONLY;
break;
case WriteOnly:
openMode = O_WRONLY;
break;
case ReadWrite:
openMode = O_RDWR;
break;
case Append:
openMode = O_APPEND | O_WRONLY;
break;
}
//! Using fopen works only on the first launch as expected
//! on the second launch it causes issues because we don't overwrite
//! the .data sections which is needed for a normal application to re-init
//! this will be added with launching as RPX
iFd = ::open(filepath.c_str(), openMode);
if(iFd < 0)
return iFd;
filesize = ::lseek(iFd, 0, SEEK_END);
::lseek(iFd, 0, SEEK_SET);
return 0;
}
int32_t CFile::open(const uint8_t * mem, int32_t size) {
this->close();
mem_file = mem;
filesize = size;
return 0;
}
void CFile::close() {
if(iFd >= 0)
::close(iFd);
iFd = -1;
mem_file = NULL;
filesize = 0;
pos = 0;
}
int32_t CFile::read(uint8_t * ptr, size_t size) {
if(iFd >= 0) {
int32_t ret = ::read(iFd, ptr,size);
if(ret > 0)
pos += ret;
return ret;
}
int32_t readsize = size;
if(readsize > (int64_t) (filesize-pos))
readsize = filesize-pos;
if(readsize <= 0)
return readsize;
if(mem_file != NULL) {
memcpy(ptr, mem_file+pos, readsize);
pos += readsize;
return readsize;
}
return -1;
}
int32_t CFile::write(const uint8_t * ptr, size_t size) {
if(iFd >= 0) {
size_t done = 0;
while(done < size) {
int32_t ret = ::write(iFd, ptr, size - done);
if(ret <= 0)
return ret;
ptr += ret;
done += ret;
pos += ret;
}
return done;
}
return -1;
}
int32_t CFile::seek(long int offset, int32_t origin) {
int32_t ret = 0;
int64_t newPos = pos;
if(origin == SEEK_SET) {
newPos = offset;
} else if(origin == SEEK_CUR) {
newPos += offset;
} else if(origin == SEEK_END) {
newPos = filesize+offset;
}
if(newPos < 0) {
pos = 0;
} else {
pos = newPos;
}
if(iFd >= 0)
ret = ::lseek(iFd, pos, SEEK_SET);
if(mem_file != NULL) {
if(pos > filesize) {
pos = filesize;
}
}
return ret;
}
int32_t CFile::fwrite(const char *format, ...) {
int32_t result = -1;
char * tmp = NULL;
va_list va;
va_start(va, format);
if((vasprintf(&tmp, format, va) >= 0) && tmp) {
result = this->write((uint8_t *)tmp, strlen(tmp));
}
va_end(va);
if(tmp) {
free(tmp);
tmp = NULL;
}
return result;
}

View File

@ -1,61 +0,0 @@
#ifndef CFILE_HPP_
#define CFILE_HPP_
#include <stdio.h>
#include <string>
#include <string.h>
#include <fcntl.h>
#include <stdint.h>
#include <unistd.h>
class CFile {
public:
enum eOpenTypes {
ReadOnly,
WriteOnly,
ReadWrite,
Append
};
CFile();
CFile(const std::string & filepath, eOpenTypes mode);
CFile(const uint8_t * memory, int32_t memsize);
virtual ~CFile();
int32_t open(const std::string & filepath, eOpenTypes mode);
int32_t open(const uint8_t * memory, int32_t memsize);
bool isOpen() const {
if(iFd >= 0)
return true;
if(mem_file)
return true;
return false;
}
void close();
int32_t read(uint8_t * ptr, size_t size);
int32_t write(const uint8_t * ptr, size_t size);
int32_t fwrite(const char *format, ...);
int32_t seek(long int offset, int32_t origin);
uint64_t tell() {
return pos;
};
uint64_t size() {
return filesize;
};
void rewind() {
this->seek(0, SEEK_SET);
};
protected:
int32_t iFd;
const uint8_t * mem_file;
uint64_t filesize;
uint64_t pos;
};
#endif

View File

@ -1,212 +0,0 @@
/****************************************************************************
* Copyright (C) 2010
* by Dimok
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any
* damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any
* purpose, including commercial applications, and to alter it and
* redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you
* must not claim that you wrote the original software. If you use
* this software in a product, an acknowledgment in the product
* documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and
* must not be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*
* DirList Class
* for WiiXplorer 2010
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <algorithm>
#include <sys/stat.h>
#include <sys/dirent.h>
#include "DirList.h"
#include "utils/StringTools.h"
DirList::DirList() {
Flags = 0;
Filter = 0;
Depth = 0;
}
DirList::DirList(const std::string & path, const char *filter, uint32_t flags, uint32_t maxDepth) {
this->LoadPath(path, filter, flags, maxDepth);
this->SortList();
}
DirList::~DirList() {
ClearList();
}
bool DirList::LoadPath(const std::string & folder, const char *filter, uint32_t flags, uint32_t maxDepth) {
if(folder.empty()) return false;
Flags = flags;
Filter = filter;
Depth = maxDepth;
std::string folderpath(folder);
uint32_t length = folderpath.size();
//! clear path of double slashes
StringTools::RemoveDoubleSlashs(folderpath);
//! remove last slash if exists
if(length > 0 && folderpath[length-1] == '/')
folderpath.erase(length-1);
//! add root slash if missing
if(folderpath.find('/') == std::string::npos) {
folderpath += '/';
}
return InternalLoadPath(folderpath);
}
bool DirList::InternalLoadPath(std::string &folderpath) {
if(folderpath.size() < 3)
return false;
struct dirent *dirent = NULL;
DIR *dir = NULL;
dir = opendir(folderpath.c_str());
if (dir == NULL)
return false;
while ((dirent = readdir(dir)) != 0) {
bool isDir = dirent->d_type & DT_DIR;
const char *filename = dirent->d_name;
if(isDir) {
if(strcmp(filename,".") == 0 || strcmp(filename,"..") == 0)
continue;
if((Flags & CheckSubfolders) && (Depth > 0)) {
int32_t length = folderpath.size();
if(length > 2 && folderpath[length-1] != '/') {
folderpath += '/';
}
folderpath += filename;
Depth--;
InternalLoadPath(folderpath);
folderpath.erase(length);
Depth++;
}
if(!(Flags & Dirs))
continue;
} else if(!(Flags & Files)) {
continue;
}
if(Filter) {
char * fileext = strrchr(filename, '.');
if(!fileext)
continue;
if(StringTools::strtokcmp(fileext, Filter, ",") == 0)
AddEntrie(folderpath, filename, isDir);
} else {
AddEntrie(folderpath, filename, isDir);
}
}
closedir(dir);
return true;
}
void DirList::AddEntrie(const std::string &filepath, const char * filename, bool isDir) {
if(!filename)
return;
int32_t pos = FileInfo.size();
FileInfo.resize(pos+1);
FileInfo[pos].FilePath = (char *) malloc(filepath.size()+strlen(filename)+2);
if(!FileInfo[pos].FilePath) {
FileInfo.resize(pos);
return;
}
sprintf(FileInfo[pos].FilePath, "%s/%s", filepath.c_str(), filename);
FileInfo[pos].isDir = isDir;
}
void DirList::ClearList() {
for(uint32_t i = 0; i < FileInfo.size(); ++i) {
if(FileInfo[i].FilePath) {
free(FileInfo[i].FilePath);
FileInfo[i].FilePath = NULL;
}
}
FileInfo.clear();
std::vector<DirEntry>().swap(FileInfo);
}
const char * DirList::GetFilename(int32_t ind) const {
if (!valid(ind))
return "";
return StringTools::FullpathToFilename(FileInfo[ind].FilePath);
}
static bool SortCallback(const DirEntry & f1, const DirEntry & f2) {
if(f1.isDir && !(f2.isDir)) return true;
if(!(f1.isDir) && f2.isDir) return false;
if(f1.FilePath && !f2.FilePath) return true;
if(!f1.FilePath) return false;
if(strcasecmp(f1.FilePath, f2.FilePath) > 0)
return false;
return true;
}
void DirList::SortList() {
if(FileInfo.size() > 1)
std::sort(FileInfo.begin(), FileInfo.end(), SortCallback);
}
void DirList::SortList(bool (*SortFunc)(const DirEntry &a, const DirEntry &b)) {
if(FileInfo.size() > 1)
std::sort(FileInfo.begin(), FileInfo.end(), SortFunc);
}
uint64_t DirList::GetFilesize(int32_t index) const {
struct stat st;
const char *path = GetFilepath(index);
if(!path || stat(path, &st) != 0)
return 0;
return st.st_size;
}
int32_t DirList::GetFileIndex(const char *filename) const {
if(!filename)
return -1;
for (uint32_t i = 0; i < FileInfo.size(); ++i) {
if (strcasecmp(GetFilename(i), filename) == 0)
return i;
}
return -1;
}

View File

@ -1,103 +0,0 @@
/****************************************************************************
* Copyright (C) 2010
* by Dimok
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any
* damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any
* purpose, including commercial applications, and to alter it and
* redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you
* must not claim that you wrote the original software. If you use
* this software in a product, an acknowledgment in the product
* documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and
* must not be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*
* DirList Class
* for WiiXplorer 2010
***************************************************************************/
#ifndef ___DIRLIST_H_
#define ___DIRLIST_H_
#include <vector>
#include <string>
#include <stdint.h>
typedef struct {
char * FilePath;
bool isDir;
} DirEntry;
class DirList {
public:
//!Constructor
DirList(void);
//!\param path Path from where to load the filelist of all files
//!\param filter A fileext that needs to be filtered
//!\param flags search/filter flags from the enum
DirList(const std::string & path, const char *filter = NULL, uint32_t flags = Files | Dirs, uint32_t maxDepth = 0xffffffff);
//!Destructor
virtual ~DirList();
//! Load all the files from a directory
bool LoadPath(const std::string & path, const char *filter = NULL, uint32_t flags = Files | Dirs, uint32_t maxDepth = 0xffffffff);
//! Get a filename of the list
//!\param list index
const char * GetFilename(int32_t index) const;
//! Get the a filepath of the list
//!\param list index
const char *GetFilepath(int32_t index) const {
if (!valid(index)) return "";
else return FileInfo[index].FilePath;
}
//! Get the a filesize of the list
//!\param list index
uint64_t GetFilesize(int32_t index) const;
//! Is index a dir or a file
//!\param list index
bool IsDir(int32_t index) const {
if(!valid(index)) return false;
return FileInfo[index].isDir;
};
//! Get the filecount of the whole list
int32_t GetFilecount() const {
return FileInfo.size();
};
//! Sort list by filepath
void SortList();
//! Custom sort command for custom sort functions definitions
void SortList(bool (*SortFunc)(const DirEntry &a, const DirEntry &b));
//! Get the index of the specified filename
int32_t GetFileIndex(const char *filename) const;
//! Enum for search/filter flags
enum {
Files = 0x01,
Dirs = 0x02,
CheckSubfolders = 0x08,
};
protected:
// Internal parser
bool InternalLoadPath(std::string &path);
//!Add a list entrie
void AddEntrie(const std::string &filepath, const char * filename, bool isDir);
//! Clear the list
void ClearList();
//! Check if valid pos is requested
inline bool valid(uint32_t pos) const {
return (pos < FileInfo.size());
};
uint32_t Flags;
uint32_t Depth;
const char *Filter;
std::vector<DirEntry> FileInfo;
};
#endif

View File

@ -1,56 +0,0 @@
#include <malloc.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include "FSOSUtils.h"
#include "dynamic_libs/coreinit.h"
#include "dynamic_libs/fs_defs.h"
#include "dynamic_libs/fs_functions.h"
#include "utils/logger.h"
int32_t FSOSUtils::MountFS(void *pClient, void *pCmd, char **mount_path) {
InitOSFunctionPointers();
int32_t result = -1;
void *mountSrc = ((void * (*)(size_t))(*pMEMAllocFromDefaultHeap))(FS_MOUNT_SOURCE_SIZE);
if(!mountSrc) {
return -3;
}
char* mountPath = (char*) ((void * (*)(size_t))(*pMEMAllocFromDefaultHeap))(FS_MAX_MOUNTPATH_SIZE);
if(!mountPath) {
free(mountSrc);
mountSrc = NULL;
return -4;
}
memset(mountSrc, 0, FS_MOUNT_SOURCE_SIZE);
memset(mountPath, 0, FS_MAX_MOUNTPATH_SIZE);
// Mount sdcard
if (FSGetMountSource(pClient, pCmd, FS_SOURCETYPE_EXTERNAL, mountSrc, -1) == 0) {
result = FSMount(pClient, pCmd, mountSrc, mountPath, FS_MAX_MOUNTPATH_SIZE, -1);
if((result == 0) && mount_path) {
*mount_path = (char*)malloc(strlen(mountPath) + 1);
if(*mount_path)
strcpy(*mount_path, mountPath);
}
}
DEBUG_FUNCTION_LINE(".\n");
((void (*)(void *))(*pMEMFreeToDefaultHeap))(mountPath);
((void (*)(void *))(*pMEMFreeToDefaultHeap))(mountSrc);
//free(mountPath);
//free(mountSrc);
mountPath = NULL;
mountSrc = NULL;
return result;
}
int32_t FSOSUtils::UmountFS(void *pClient, void *pCmd, const char *mountPath) {
int32_t result = -1;
result = FSUnmount(pClient, pCmd, mountPath, -1);
return result;
}

View File

@ -1,13 +0,0 @@
#ifndef __FS_OS_UTILS_H_
#define __FS_OS_UTILS_H_
#include <stdint.h>
class FSOSUtils {
public:
static int32_t MountFS(void *pClient, void *pCmd, char **mount_path);
static int32_t UmountFS(void *pClient, void *pCmd, const char *mountPath);
};
#endif // __FS_OS_UTILS_H_

View File

@ -1,144 +0,0 @@
#include <malloc.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include "FSUtils.h"
#include "CFile.hpp"
#include "utils/logger.h"
int32_t FSUtils::LoadFileToMem(const char *filepath, uint8_t **inbuffer, uint32_t *size) {
//! always initialze input
*inbuffer = NULL;
if(size)
*size = 0;
int32_t iFd = open(filepath, O_RDONLY);
if (iFd < 0)
return -1;
uint32_t filesize = lseek(iFd, 0, SEEK_END);
lseek(iFd, 0, SEEK_SET);
uint8_t *buffer = (uint8_t *) malloc(filesize);
if (buffer == NULL) {
close(iFd);
return -2;
}
uint32_t blocksize = 0x4000;
uint32_t done = 0;
int32_t readBytes = 0;
while(done < filesize) {
if(done + blocksize > filesize) {
blocksize = filesize - done;
}
readBytes = read(iFd, buffer + done, blocksize);
if(readBytes <= 0)
break;
done += readBytes;
}
close(iFd);
if (done != filesize) {
free(buffer);
buffer = NULL;
return -3;
}
*inbuffer = buffer;
//! sign is optional input
if(size) {
*size = filesize;
}
return filesize;
}
int32_t FSUtils::CheckFile(const char * filepath) {
if(!filepath)
return 0;
struct stat filestat;
char dirnoslash[strlen(filepath)+2];
snprintf(dirnoslash, sizeof(dirnoslash), "%s", filepath);
while(dirnoslash[strlen(dirnoslash)-1] == '/')
dirnoslash[strlen(dirnoslash)-1] = '\0';
char * notRoot = strrchr(dirnoslash, '/');
if(!notRoot) {
strcat(dirnoslash, "/");
}
if (stat(dirnoslash, &filestat) == 0)
return 1;
return 0;
}
int32_t FSUtils::CreateSubfolder(const char * fullpath) {
if(!fullpath)
return 0;
int32_t result = 0;
char dirnoslash[strlen(fullpath)+1];
strcpy(dirnoslash, fullpath);
int32_t pos = strlen(dirnoslash)-1;
while(dirnoslash[pos] == '/') {
dirnoslash[pos] = '\0';
pos--;
}
if(CheckFile(dirnoslash)) {
return 1;
} else {
char parentpath[strlen(dirnoslash)+2];
strcpy(parentpath, dirnoslash);
char * ptr = strrchr(parentpath, '/');
if(!ptr) {
//!Device root directory (must be with '/')
strcat(parentpath, "/");
struct stat filestat;
if (stat(parentpath, &filestat) == 0)
return 1;
return 0;
}
ptr++;
ptr[0] = '\0';
result = CreateSubfolder(parentpath);
}
if(!result)
return 0;
if (mkdir(dirnoslash, 0777) == -1) {
return 0;
}
return 1;
}
bool FSUtils::saveBufferToFile(const char * path, void * buffer, uint32_t size) {
int32_t res = open(path, O_CREAT | O_TRUNC | O_WRONLY);
close(res);
CFile file(path, CFile::WriteOnly);
if (!file.isOpen()) {
DEBUG_FUNCTION_LINE("Failed to open %s\n",path);
return false;
}
file.write((const uint8_t*) buffer,size);
file.close();
return true;
}

View File

@ -1,15 +0,0 @@
#ifndef __FS_UTILS_H_
#define __FS_UTILS_H_
#include <stdint.h>
class FSUtils {
public:
static int32_t LoadFileToMem(const char *filepath, uint8_t **inbuffer, uint32_t *size);
//! todo: C++ class
static int32_t CreateSubfolder(const char * fullpath);
static int32_t CheckFile(const char * filepath);
static bool saveBufferToFile(const char * path, void * buffer, uint32_t size);
};
#endif // __FS_UTILS_H_

View File

@ -1,67 +0,0 @@
/*
disc_io.h
Interface template for low level disc functions.
Copyright (c) 2006 Michael "Chishm" Chisholm
Based on code originally written by MightyMax
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 OGC_DISC_IO_INCLUDE
#define OGC_DISC_IO_INCLUDE
#include <stdint.h>
#define FEATURE_MEDIUM_CANREAD 0x00000001
#define FEATURE_MEDIUM_CANWRITE 0x00000002
#define FEATURE_GAMECUBE_SLOTA 0x00000010
#define FEATURE_GAMECUBE_SLOTB 0x00000020
#define FEATURE_GAMECUBE_DVD 0x00000040
#define FEATURE_WII_SD 0x00000100
#define FEATURE_WII_USB 0x00000200
#define FEATURE_WII_DVD 0x00000400
typedef uint32_t sec_t;
typedef bool (* FN_MEDIUM_STARTUP)(void) ;
typedef bool (* FN_MEDIUM_ISINSERTED)(void) ;
typedef bool (* FN_MEDIUM_READSECTORS)(sec_t sector, sec_t numSectors, void* buffer) ;
typedef bool (* FN_MEDIUM_WRITESECTORS)(sec_t sector, sec_t numSectors, const void* buffer) ;
typedef bool (* FN_MEDIUM_CLEARSTATUS)(void) ;
typedef bool (* FN_MEDIUM_SHUTDOWN)(void) ;
struct DISC_INTERFACE_STRUCT {
unsigned long ioType ;
unsigned long features ;
FN_MEDIUM_STARTUP startup ;
FN_MEDIUM_ISINSERTED isInserted ;
FN_MEDIUM_READSECTORS readSectors ;
FN_MEDIUM_WRITESECTORS writeSectors ;
FN_MEDIUM_CLEARSTATUS clearStatus ;
FN_MEDIUM_SHUTDOWN shutdown ;
} ;
typedef struct DISC_INTERFACE_STRUCT DISC_INTERFACE ;
#endif // define OGC_DISC_IO_INCLUDE

File diff suppressed because it is too large Load Diff

View File

@ -1,40 +0,0 @@
/***************************************************************************
* Copyright (C) 2015
* by Dimok
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any
* damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any
* purpose, including commercial applications, and to alter it and
* redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you
* must not claim that you wrote the original software. If you use
* this software in a product, an acknowledgment in the product
* documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and
* must not be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
***************************************************************************/
#ifndef __SD_FAT_DEVOPTAB_H_
#define __SD_FAT_DEVOPTAB_H_
#ifdef __cplusplus
extern "C" {
#endif
int32_t mount_sd_fat(const char *path);
int32_t unmount_sd_fat(const char *path);
int32_t mount_fake();
int32_t unmount_fake();
void deleteDevTabsNames();
#ifdef __cplusplus
}
#endif
#endif // __SD_FAT_DEVOPTAB_H_

View File

@ -1,204 +0,0 @@
#include "kernel_utils.h"
#include "kernel_defs.h"
#include "dynamic_libs/coreinit.h"
#define KERN_SYSCALL_TBL1 0xFFE84C70 //Unknown
#define KERN_SYSCALL_TBL2 0xFFE85070 //Games
#define KERN_SYSCALL_TBL3 0xFFE85470 //Loader
#define KERN_SYSCALL_TBL4 0xFFEAAA60 //Home menu
#define KERN_SYSCALL_TBL5 0xFFEAAE60 //Browser
extern void SCKernelCopyData(uint32_t dst, uint32_t src, uint32_t len);
static void KernelReadSRs(sr_table_t * table) {
uint32_t i = 0;
// calculate PT_size ((end-start)*8/4096)*4 or (end-start)/128
// Minimum page table size is 64Kbytes.
asm volatile("eieio; isync");
asm volatile("mfspr %0, 25" : "=r" (table->sdr1));
asm volatile("mfsr %0, 0" : "=r" (table->value[i]));
i++;
asm volatile("mfsr %0, 1" : "=r" (table->value[i]));
i++;
asm volatile("mfsr %0, 2" : "=r" (table->value[i]));
i++;
asm volatile("mfsr %0, 3" : "=r" (table->value[i]));
i++;
asm volatile("mfsr %0, 4" : "=r" (table->value[i]));
i++;
asm volatile("mfsr %0, 5" : "=r" (table->value[i]));
i++;
asm volatile("mfsr %0, 6" : "=r" (table->value[i]));
i++;
asm volatile("mfsr %0, 7" : "=r" (table->value[i]));
i++;
asm volatile("mfsr %0, 8" : "=r" (table->value[i]));
i++;
asm volatile("mfsr %0, 9" : "=r" (table->value[i]));
i++;
asm volatile("mfsr %0, 10" : "=r" (table->value[i]));
i++;
asm volatile("mfsr %0, 11" : "=r" (table->value[i]));
i++;
asm volatile("mfsr %0, 12" : "=r" (table->value[i]));
i++;
asm volatile("mfsr %0, 13" : "=r" (table->value[i]));
i++;
asm volatile("mfsr %0, 14" : "=r" (table->value[i]));
i++;
asm volatile("mfsr %0, 15" : "=r" (table->value[i]));
i++;
asm volatile("eieio; isync");
}
static void KernelWriteSRs(sr_table_t * table) {
uint32_t i = 0;
asm volatile("eieio; isync");
// Writing didn't work for all at once so we only write number 8.
// TODO: fix this and change it if required.
/*asm volatile("mtsr 0, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 1, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 2, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 3, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 4, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 5, %0" : : "r" (table->value[i])); i++;*/
//asm volatile("mtsr 6, %0" : : "r" (table->value[6])); i++;
/*asm volatile("mtsr 7, %0" : : "r" (table->value[i])); i++;*/
asm volatile("mtsr 8, %0" : : "r" (table->value[8]));
//i++;
/*asm volatile("mtsr 9, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 10, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 11, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 12, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 13, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 14, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 15, %0" : : "r" (table->value[i])); i++;*/
asm volatile("isync");
}
void KernelWrite(uint32_t addr, const void *data, uint32_t length) {
uint32_t dst = (uint32_t) OSEffectiveToPhysical(addr);
uint32_t src = (uint32_t) OSEffectiveToPhysical((uint32_t)data);
KernelCopyData(dst, src, length);
DCFlushRange((void *)addr, length);
ICInvalidateRange((void *)addr, length);
}
void KernelWriteU32(uint32_t addr, uint32_t value) {
uint32_t dst = (uint32_t) OSEffectiveToPhysical(addr);
uint32_t src = (uint32_t) OSEffectiveToPhysical((uint32_t)&value);
KernelCopyData(dst, src, 4);
DCFlushRange((void *)addr, 4);
ICInvalidateRange((void *)addr, 4);
}
/* Write a 32-bit word with kernel permissions */
void __attribute__ ((noinline)) kern_write(void * addr, uint32_t value) {
asm volatile (
"li 3,1\n"
"li 4,0\n"
"mr 5,%1\n"
"li 6,0\n"
"li 7,0\n"
"lis 8,1\n"
"mr 9,%0\n"
"mr %1,1\n"
"li 0,0x3500\n"
"sc\n"
"nop\n"
"mr 1,%1\n"
:
: "r"(addr), "r"(value)
: "memory", "ctr", "lr", "0", "3", "4", "5", "6", "7", "8", "9", "10",
"11", "12"
);
}
/* Read a 32-bit word with kernel permissions */
uint32_t __attribute__ ((noinline)) kern_read(const void *addr)
{
uint32_t result;
asm volatile (
"li 3,1\n"
"li 4,0\n"
"li 5,0\n"
"li 6,0\n"
"li 7,0\n"
"lis 8,1\n"
"mr 9,%1\n"
"li 0,0x3400\n"
"mr %0,1\n"
"sc\n"
"nop\n"
"mr 1,%0\n"
"mr %0,3\n"
: "=r"(result)
: "b"(addr)
: "memory", "ctr", "lr", "0", "3", "4", "5", "6", "7", "8", "9", "10",
"11", "12"
);
return result;
}
void PatchSyscall(int index, uint32_t addr) {
//DEBUG_FUNCTION_LINE("Patching Syscall 0x%02X\n",index);
kern_write((void *) (KERN_SYSCALL_TBL1 + index * 4), addr);
kern_write((void *) (KERN_SYSCALL_TBL2 + index * 4), addr);
kern_write((void *) (KERN_SYSCALL_TBL3 + index * 4), addr);
kern_write((void *) (KERN_SYSCALL_TBL4 + index * 4), addr);
kern_write((void *) (KERN_SYSCALL_TBL5 + index * 4), addr);
}
void KernelReadPTE(uint32_t outputAddr, int32_t length) {
uint32_t dst = (uint32_t) OSEffectiveToPhysical(outputAddr);
uint32_t src = 0xFFE20000;
ICInvalidateRange(&dst, 4);
DCFlushRange(&dst, 4);
DCFlushRange(&src, 4);
KernelCopyData(dst, src, length);
DCFlushRange((void *)outputAddr, length);
ICInvalidateRange((void *)outputAddr, length);
}
void KernelWritePTE(uint32_t inputAddr, int32_t length) {
uint32_t dst = 0xFFE20000;
uint32_t src = (uint32_t) OSEffectiveToPhysical(inputAddr);
ICInvalidateRange(&src, 4);
DCFlushRange(&src, 4);
KernelCopyData(dst, src, length);
}
static void NOPAtPhysicalAddress(uint32_t addr) {
uint32_t dst = 0x60000000;
ICInvalidateRange(&dst, 4);
DCFlushRange(&dst, 4);
KernelCopyData(addr,(uint32_t)OSEffectiveToPhysical((uint32_t)&dst),4);
}
void kernelInitialize() {
static uint8_t ucSyscallsSetupRequired = 1;
if(!ucSyscallsSetupRequired)
return;
ucSyscallsSetupRequired = 0;
PatchSyscall(0x25, (uint32_t)SCKernelCopyData);
PatchSyscall(0x36, (uint32_t)KernelReadSRs);
PatchSyscall(0x0A, (uint32_t)KernelWriteSRs);
// Override all writes to SR8 with nops.
NOPAtPhysicalAddress(0xFFF1D754);
NOPAtPhysicalAddress(0xFFF1D64C);
NOPAtPhysicalAddress(0xFFE00638);
}

View File

@ -1,29 +0,0 @@
# This stuff may need a change in different kernel versions
# This is only needed when launched directly through browser and not SD card.
.section ".kernel_code"
.globl SaveAndResetDataBATs_And_SRs_hook
SaveAndResetDataBATs_And_SRs_hook:
# setup CTR to the position we need to return to
mflr r5
mtctr r5
# set link register to its original value
mtlr r7
# setup us a nice DBAT for our code data with same region as our code
mfspr r5, 560
mtspr 570, r5
mfspr r5, 561
mtspr 571, r5
# restore the original kernel instructions that we replaced
lwz r5, 0x34(r3)
lwz r6, 0x38(r3)
lwz r7, 0x3C(r3)
lwz r8, 0x40(r3)
lwz r9, 0x44(r3)
lwz r10, 0x48(r3)
lwz r11, 0x4C(r3)
lwz r3, 0x50(r3)
isync
mtsr 7, r5
# jump back to the position in kernel after our patch (from LR)
bctr

View File

@ -1,430 +0,0 @@
/*-
* Copyright (c) 2009 Joseph Koshy
* All rights reserved.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
*
* $Id: _elftc.h 2495 2012-04-23 05:31:56Z jkoshy $
*/
/**
** Miscellanous definitions needed by multiple components.
**/
#ifndef _ELFTC_H
#define _ELFTC_H
#ifndef NULL
#define NULL ((void *) 0)
#endif
#ifndef offsetof
#define offsetof(T, M) ((int) &((T*) 0) -> M)
#endif
/* --QUEUE-MACROS-- [[ */
/*
* Supply macros missing from <sys/queue.h>
*/
/*
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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 STAILQ_CONCAT
#define STAILQ_CONCAT(head1, head2) do { \
if (!STAILQ_EMPTY((head2))) { \
*(head1)->stqh_last = (head2)->stqh_first; \
(head1)->stqh_last = (head2)->stqh_last; \
STAILQ_INIT((head2)); \
} \
} while (/*CONSTCOND*/0)
#endif
#ifndef STAILQ_EMPTY
#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
#endif
#ifndef STAILQ_ENTRY
#define STAILQ_ENTRY(type) \
struct { \
struct type *stqe_next; /* next element */ \
}
#endif
#ifndef STAILQ_FIRST
#define STAILQ_FIRST(head) ((head)->stqh_first)
#endif
#ifndef STAILQ_HEAD
#define STAILQ_HEAD(name, type) \
struct name { \
struct type *stqh_first; /* first element */ \
struct type **stqh_last; /* addr of last next element */ \
}
#endif
#ifndef STAILQ_HEAD_INITIALIZER
#define STAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).stqh_first }
#endif
#ifndef STAILQ_FOREACH
#define STAILQ_FOREACH(var, head, field) \
for ((var) = ((head)->stqh_first); \
(var); \
(var) = ((var)->field.stqe_next))
#endif
#ifndef STAILQ_FOREACH_SAFE
#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = STAILQ_FIRST((head)); \
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
(var) = (tvar))
#endif
#ifndef STAILQ_INIT
#define STAILQ_INIT(head) do { \
(head)->stqh_first = NULL; \
(head)->stqh_last = &(head)->stqh_first; \
} while (/*CONSTCOND*/0)
#endif
#ifndef STAILQ_INSERT_HEAD
#define STAILQ_INSERT_HEAD(head, elm, field) do { \
if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \
(head)->stqh_last = &(elm)->field.stqe_next; \
(head)->stqh_first = (elm); \
} while (/*CONSTCOND*/0)
#endif
#ifndef STAILQ_INSERT_TAIL
#define STAILQ_INSERT_TAIL(head, elm, field) do { \
(elm)->field.stqe_next = NULL; \
*(head)->stqh_last = (elm); \
(head)->stqh_last = &(elm)->field.stqe_next; \
} while (/*CONSTCOND*/0)
#endif
#ifndef STAILQ_INSERT_AFTER
#define STAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
if (((elm)->field.stqe_next = (listelm)->field.stqe_next) == NULL)\
(head)->stqh_last = &(elm)->field.stqe_next; \
(listelm)->field.stqe_next = (elm); \
} while (/*CONSTCOND*/0)
#endif
#ifndef STAILQ_LAST
#define STAILQ_LAST(head, type, field) \
(STAILQ_EMPTY((head)) ? \
NULL : ((struct type *)(void *) \
((char *)((head)->stqh_last) - offsetof(struct type, field))))
#endif
#ifndef STAILQ_NEXT
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
#endif
#ifndef STAILQ_REMOVE
#define STAILQ_REMOVE(head, elm, type, field) do { \
if ((head)->stqh_first == (elm)) { \
STAILQ_REMOVE_HEAD((head), field); \
} else { \
struct type *curelm = (head)->stqh_first; \
while (curelm->field.stqe_next != (elm)) \
curelm = curelm->field.stqe_next; \
if ((curelm->field.stqe_next = \
curelm->field.stqe_next->field.stqe_next) == NULL) \
(head)->stqh_last = &(curelm)->field.stqe_next; \
} \
} while (/*CONSTCOND*/0)
#endif
#ifndef STAILQ_REMOVE_HEAD
#define STAILQ_REMOVE_HEAD(head, field) do { \
if (((head)->stqh_first = (head)->stqh_first->field.stqe_next) == \
NULL) \
(head)->stqh_last = &(head)->stqh_first; \
} while (/*CONSTCOND*/0)
#endif
#ifndef TAILQ_FOREACH_SAFE
#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = TAILQ_FIRST((head)); \
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
(var) = (tvar))
#endif
/* ]] --QUEUE-MACROS-- */
/*
* VCS Ids.
*/
#ifndef ELFTC_VCSID
#if defined(GEKKO)
#define ELFTC_VCSID(ID) /**/
#endif
#if defined(__WIIU__)
#define ELFTC_VCSID(ID) /**/
#endif
#if defined(__DragonFly__)
#define ELFTC_VCSID(ID) __RCSID(ID)
#endif
#if defined(__FreeBSD__)
#define ELFTC_VCSID(ID) __FBSDID(ID)
#endif
#if defined(__linux__) || defined(__GNU__) || defined(__GLIBC__)
#if defined(__GNUC__)
#define ELFTC_VCSID(ID) __asm__(".ident\t\"" ID "\"")
#else
#define ELFTC_VCSID(ID) /**/
#endif
#endif
#if defined(__minix)
#if defined(__GNUC__)
#define ELFTC_VCSID(ID) __asm__(".ident\t\"" ID "\"")
#else
#define ELFTC_VCSID(ID) /**/
#endif /* __GNU__ */
#endif
#if defined(__NetBSD__)
#define ELFTC_VCSID(ID) __RCSID(ID)
#endif
#if defined(__OpenBSD__)
#if defined(__GNUC__)
#define ELFTC_VCSID(ID) __asm__(".ident\t\"" ID "\"")
#else
#define ELFTC_VCSID(ID) /**/
#endif /* __GNUC__ */
#endif
#endif /* ELFTC_VCSID */
/*
* Provide an equivalent for getprogname(3).
*/
#ifndef ELFTC_GETPROGNAME
#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__minix) || \
defined(__NetBSD__)
#include <stdlib.h>
#define ELFTC_GETPROGNAME() getprogname()
#endif /* __DragonFly__ || __FreeBSD__ || __minix || __NetBSD__ */
#if defined(__GLIBC__)
/*
* GLIBC based systems have a global 'char *' pointer referencing
* the executable's name.
*/
extern const char *program_invocation_short_name;
#define ELFTC_GETPROGNAME() program_invocation_short_name
#endif /* __GLIBC__ */
#if defined(__OpenBSD__)
extern const char *__progname;
#define ELFTC_GETPROGNAME() __progname
#endif /* __OpenBSD__ */
#endif /* ELFTC_GETPROGNAME */
/**
** Per-OS configuration.
**/
#if defined(GEKKO)
#include <sys/param.h>
#define ELFTC_BYTE_ORDER BYTE_ORDER
#define ELFTC_BYTE_ORDER_LITTLE_ENDIAN LITTLE_ENDIAN
#define ELFTC_BYTE_ORDER_BIG_ENDIAN BIG_ENDIAN
#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
#define roundup2 roundup
#define ELFTC_HAVE_MMAP 0
#define ELFTC_HAVE_STRMODE 0/
#define ELFTC_NEED_BYTEORDER_EXTENSIONS 1
#endif
#if defined(__WIIU__)
#include <sys/param.h>
#define ELFTC_BYTE_ORDER BYTE_ORDER
#define ELFTC_BYTE_ORDER_LITTLE_ENDIAN LITTLE_ENDIAN
#define ELFTC_BYTE_ORDER_BIG_ENDIAN BIG_ENDIAN
#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
#define roundup2 roundup
#define ELFTC_HAVE_MMAP 0
#define ELFTC_HAVE_STRMODE 0/
#define ELFTC_NEED_BYTEORDER_EXTENSIONS 1
#endif
#if defined(__DragonFly__)
#include <osreldate.h>
#include <sys/endian.h>
#define ELFTC_BYTE_ORDER _BYTE_ORDER
#define ELFTC_BYTE_ORDER_LITTLE_ENDIAN _LITTLE_ENDIAN
#define ELFTC_BYTE_ORDER_BIG_ENDIAN _BIG_ENDIAN
#define ELFTC_HAVE_MMAP 1
#endif
#if defined(__GLIBC__)
#include <endian.h>
#define ELFTC_BYTE_ORDER __BYTE_ORDER
#define ELFTC_BYTE_ORDER_LITTLE_ENDIAN __LITTLE_ENDIAN
#define ELFTC_BYTE_ORDER_BIG_ENDIAN __BIG_ENDIAN
#define ELFTC_HAVE_MMAP 1
/*
* Debian GNU/Linux and Debian GNU/kFreeBSD do not have strmode(3).
*/
#define ELFTC_HAVE_STRMODE 0
/* Whether we need to supply {be,le}32dec. */
#define ELFTC_NEED_BYTEORDER_EXTENSIONS 1
#define roundup2 roundup
#endif /* __GLIBC__ */
#if defined(__FreeBSD__)
#include <osreldate.h>
#include <sys/endian.h>
#define ELFTC_BYTE_ORDER _BYTE_ORDER
#define ELFTC_BYTE_ORDER_LITTLE_ENDIAN _LITTLE_ENDIAN
#define ELFTC_BYTE_ORDER_BIG_ENDIAN _BIG_ENDIAN
#define ELFTC_HAVE_MMAP 1
#define ELFTC_HAVE_STRMODE 1
#if __FreeBSD_version <= 900000
#define ELFTC_BROKEN_YY_NO_INPUT 1
#endif
#endif /* __FreeBSD__ */
#if defined(__minix)
#define ELFTC_HAVE_MMAP 0
#endif /* __minix */
#if defined(__NetBSD__)
#include <sys/param.h>
#include <sys/endian.h>
#define ELFTC_BYTE_ORDER _BYTE_ORDER
#define ELFTC_BYTE_ORDER_LITTLE_ENDIAN _LITTLE_ENDIAN
#define ELFTC_BYTE_ORDER_BIG_ENDIAN _BIG_ENDIAN
#define ELFTC_HAVE_MMAP 1
#define ELFTC_HAVE_STRMODE 1
#if __NetBSD_Version__ <= 599002100
/* from src/doc/CHANGES: flex(1): Import flex-2.5.35 [christos 20091025] */
/* and 5.99.21 was from Wed Oct 21 21:28:36 2009 UTC */
# define ELFTC_BROKEN_YY_NO_INPUT 1
#endif
#endif /* __NetBSD __ */
#if defined(__OpenBSD__)
#include <sys/param.h>
#include <sys/endian.h>
#define ELFTC_BYTE_ORDER _BYTE_ORDER
#define ELFTC_BYTE_ORDER_LITTLE_ENDIAN _LITTLE_ENDIAN
#define ELFTC_BYTE_ORDER_BIG_ENDIAN _BIG_ENDIAN
#define ELFTC_HAVE_MMAP 1
#define ELFTC_HAVE_STRMODE 1
#define ELFTC_NEED_BYTEORDER_EXTENSIONS 1
#define roundup2 roundup
#endif /* __OpenBSD__ */
#endif /* _ELFTC_H */

View File

@ -1,223 +0,0 @@
/*-
* Copyright (c) 2006,2008-2011 Joseph Koshy
* All rights reserved.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
*
* $Id: _libelf.h 2365 2011-12-29 04:36:44Z jkoshy $
*/
#ifndef __LIBELF_H_
#define __LIBELF_H_
#include <sys/queue.h>
#include "_libelf_config.h"
#include "_elftc.h"
/*
* Library-private data structures.
*/
#define LIBELF_MSG_SIZE 256
struct _libelf_globals {
int libelf_arch;
unsigned int libelf_byteorder;
int libelf_class;
int libelf_error;
int libelf_fillchar;
unsigned int libelf_version;
char libelf_msg[LIBELF_MSG_SIZE];
};
extern struct _libelf_globals _libelf;
#define LIBELF_PRIVATE(N) (_libelf.libelf_##N)
#define LIBELF_ELF_ERROR_MASK 0xFF
#define LIBELF_OS_ERROR_SHIFT 8
#define LIBELF_ERROR(E, O) (((E) & LIBELF_ELF_ERROR_MASK) | \
((O) << LIBELF_OS_ERROR_SHIFT))
#define LIBELF_SET_ERROR(E, O) do { \
LIBELF_PRIVATE(error) = LIBELF_ERROR(ELF_E_##E, (O)); \
} while (0)
#define LIBELF_ADJUST_AR_SIZE(S) (((S) + 1U) & ~1U)
/*
* Flags for library internal use. These use the upper 16 bits of the
* `e_flags' field.
*/
#define LIBELF_F_API_MASK 0x00FFFF /* Flags defined by the API. */
#define LIBELF_F_AR_HEADER 0x010000 /* translated header available */
#define LIBELF_F_AR_VARIANT_SVR4 0x020000 /* BSD style ar(1) archive */
#define LIBELF_F_DATA_MALLOCED 0x040000 /* whether data was malloc'ed */
#define LIBELF_F_RAWFILE_MALLOC 0x080000 /* whether e_rawfile was malloc'ed */
#define LIBELF_F_RAWFILE_MMAP 0x100000 /* whether e_rawfile was mmap'ed */
#define LIBELF_F_SHDRS_LOADED 0x200000 /* whether all shdrs were read in */
#define LIBELF_F_SPECIAL_FILE 0x400000 /* non-regular file */
struct _Elf {
int e_activations; /* activation count */
unsigned int e_byteorder; /* ELFDATA* */
int e_class; /* ELFCLASS* */
Elf_Cmd e_cmd; /* ELF_C_* used at creation time */
int e_fd; /* associated file descriptor */
unsigned int e_flags; /* ELF_F_* & LIBELF_F_* flags */
Elf_Kind e_kind; /* ELF_K_* */
Elf *e_parent; /* non-NULL for archive members */
char *e_rawfile; /* uninterpreted bytes */
size_t e_rawsize; /* size of uninterpreted bytes */
unsigned int e_version; /* file version */
/*
* Header information for archive members. See the
* LIBELF_F_AR_HEADER flag.
*/
union {
Elf_Arhdr *e_arhdr; /* translated header */
char *e_rawhdr; /* untranslated header */
} e_hdr;
union {
struct { /* ar(1) archives */
off_t e_next; /* set by elf_rand()/elf_next() */
int e_nchildren;
char *e_rawstrtab; /* file name strings */
size_t e_rawstrtabsz;
char *e_rawsymtab; /* symbol table */
size_t e_rawsymtabsz;
Elf_Arsym *e_symtab;
size_t e_symtabsz;
} e_ar;
struct { /* regular ELF files */
union {
Elf32_Ehdr *e_ehdr32;
Elf64_Ehdr *e_ehdr64;
} e_ehdr;
union {
Elf32_Phdr *e_phdr32;
Elf64_Phdr *e_phdr64;
} e_phdr;
STAILQ_HEAD(, _Elf_Scn) e_scn; /* section list */
size_t e_nphdr; /* number of Phdr entries */
size_t e_nscn; /* number of sections */
size_t e_strndx; /* string table section index */
} e_elf;
} e_u;
};
/*
* The internal descriptor wrapping the "Elf_Data" type.
*/
struct _Libelf_Data {
Elf_Data d_data; /* The exported descriptor. */
Elf_Scn *d_scn; /* The containing section */
unsigned int d_flags;
STAILQ_ENTRY(_Libelf_Data) d_next;
};
struct _Elf_Scn {
union {
Elf32_Shdr s_shdr32;
Elf64_Shdr s_shdr64;
} s_shdr;
STAILQ_HEAD(, _Libelf_Data) s_data; /* translated data */
STAILQ_HEAD(, _Libelf_Data) s_rawdata; /* raw data */
STAILQ_ENTRY(_Elf_Scn) s_next;
struct _Elf *s_elf; /* parent ELF descriptor */
unsigned int s_flags; /* flags for the section as a whole */
size_t s_ndx; /* index# for this section */
uint64_t s_offset; /* managed by elf_update() */
uint64_t s_rawoff; /* original offset in the file */
uint64_t s_size; /* managed by elf_update() */
};
enum {
ELF_TOFILE,
ELF_TOMEMORY
};
#define LIBELF_COPY_U32(DST,SRC,NAME) do { \
if ((SRC)->NAME > UINT_MAX) { \
LIBELF_SET_ERROR(RANGE, 0); \
return (0); \
} \
(DST)->NAME = (SRC)->NAME; \
} while (0)
#define LIBELF_COPY_S32(DST,SRC,NAME) do { \
if ((SRC)->NAME > INT_MAX || \
(SRC)->NAME < INT_MIN) { \
LIBELF_SET_ERROR(RANGE, 0); \
return (0); \
} \
(DST)->NAME = (SRC)->NAME; \
} while (0)
/*
* Function Prototypes.
*/
struct _Libelf_Data *_libelf_allocate_data(Elf_Scn *_s);
Elf *_libelf_allocate_elf(void);
Elf_Scn *_libelf_allocate_scn(Elf *_e, size_t _ndx);
Elf_Arhdr *_libelf_ar_gethdr(Elf *_e);
Elf *_libelf_ar_open(Elf *_e, int _reporterror);
Elf *_libelf_ar_open_member(int _fd, Elf_Cmd _c, Elf *_ar);
int _libelf_ar_get_member(char *_s, size_t _sz, int _base, size_t *_ret);
Elf_Arsym *_libelf_ar_process_bsd_symtab(Elf *_ar, size_t *_dst);
Elf_Arsym *_libelf_ar_process_svr4_symtab(Elf *_ar, size_t *_dst);
unsigned long _libelf_checksum(Elf *_e, int _elfclass);
void *_libelf_ehdr(Elf *_e, int _elfclass, int _allocate);
int _libelf_falign(Elf_Type _t, int _elfclass);
size_t _libelf_fsize(Elf_Type _t, int _elfclass, unsigned int _version,
size_t count);
int (*_libelf_get_translator(Elf_Type _t, int _direction, int _elfclass))
(char *_dst, size_t dsz, char *_src, size_t _cnt, int _byteswap);
void *_libelf_getphdr(Elf *_e, int _elfclass);
void *_libelf_getshdr(Elf_Scn *_scn, int _elfclass);
void _libelf_init_elf(Elf *_e, Elf_Kind _kind);
int _libelf_load_section_headers(Elf *e, void *ehdr);
int _libelf_malign(Elf_Type _t, int _elfclass);
Elf *_libelf_memory(char *_image, size_t _sz, int _reporterror);
size_t _libelf_msize(Elf_Type _t, int _elfclass, unsigned int _version);
void *_libelf_newphdr(Elf *_e, int _elfclass, size_t _count);
Elf *_libelf_open_object(int _fd, Elf_Cmd _c, int _reporterror);
struct _Libelf_Data *_libelf_release_data(struct _Libelf_Data *_d);
Elf *_libelf_release_elf(Elf *_e);
Elf_Scn *_libelf_release_scn(Elf_Scn *_s);
int _libelf_setphnum(Elf *_e, void *_eh, int _elfclass, size_t _phnum);
int _libelf_setshnum(Elf *_e, void *_eh, int _elfclass, size_t _shnum);
int _libelf_setshstrndx(Elf *_e, void *_eh, int _elfclass,
size_t _shstrndx);
Elf_Data *_libelf_xlate(Elf_Data *_d, const Elf_Data *_s,
unsigned int _encoding, int _elfclass, int _direction);
int _libelf_xlate_shtype(uint32_t _sht);
#endif /* __LIBELF_H_ */

View File

@ -1,56 +0,0 @@
/*-
* Copyright (c) 2010 Joseph Koshy
* All rights reserved.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS `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 OR CONTRIBUTORS 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.
*
* $Id: _libelf_ar.h 2032 2011-10-23 09:07:00Z jkoshy $
*/
#ifndef __LIBELF_AR_H_
#define __LIBELF_AR_H_
/*
* Prototypes and declarations needed by libelf's ar(1) archive
* handling code.
*/
#include <ar.h>
#define LIBELF_AR_BSD_EXTENDED_NAME_PREFIX "#1/"
#define LIBELF_AR_BSD_SYMTAB_NAME "__.SYMDEF"
#define LIBELF_AR_BSD_EXTENDED_NAME_PREFIX_SIZE \
(sizeof(LIBELF_AR_BSD_EXTENDED_NAME_PREFIX) - 1)
#define IS_EXTENDED_BSD_NAME(NAME) \
(strncmp((NAME), LIBELF_AR_BSD_EXTENDED_NAME_PREFIX, \
LIBELF_AR_BSD_EXTENDED_NAME_PREFIX_SIZE) == 0)
char *_libelf_ar_get_string(const char *_buf, size_t _sz, int _rawname,
int _svr4names);
char *_libelf_ar_get_raw_name(const struct ar_hdr *_arh);
char *_libelf_ar_get_translated_name(const struct ar_hdr *_arh, Elf *_ar);
int _libelf_ar_get_number(const char *_buf, size_t _sz, int _base,
size_t *_ret);
#endif /* __LIBELF_AR_H_ */

View File

@ -1,193 +0,0 @@
/*-
* Copyright (c) 2008-2011 Joseph Koshy
* All rights reserved.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
*
* $Id: _libelf_config.h 2287 2011-12-04 06:45:47Z jkoshy $
*/
#ifdef GEKKO
#define LIBELF_ARCH EM_PPC
#define LIBELF_BYTEORDER ELFDATA2MSB
#define LIBELF_CLASS ELFCLASS32
#endif /* GEKKO */
#ifdef __WIIU__
#define LIBELF_ARCH EM_PPC
#define LIBELF_BYTEORDER ELFDATA2MSB
#define LIBELF_CLASS ELFCLASS32
#endif /* __WIIU__ */
#ifdef __DragonFly__
#if defined(__amd64__)
#define LIBELF_ARCH EM_X86_64
#define LIBELF_BYTEORDER ELFDATA2LSB
#define LIBELF_CLASS ELFCLASS64
#elif defined(__i386__)
#define LIBELF_ARCH EM_386
#define LIBELF_BYTEORDER ELFDATA2LSB
#define LIBELF_CLASS ELFCLASS32
#endif
#endif /* __DragonFly__ */
#ifdef __FreeBSD__
/*
* Define LIBELF_{ARCH,BYTEORDER,CLASS} based on the machine architecture.
* See also: <machine/elf.h>.
*/
#if defined(__amd64__)
#define LIBELF_ARCH EM_X86_64
#define LIBELF_BYTEORDER ELFDATA2LSB
#define LIBELF_CLASS ELFCLASS64
#elif defined(__arm__)
#define LIBELF_ARCH EM_ARM
#if defined(__ARMEB__) /* Big-endian ARM. */
#define LIBELF_BYTEORDER ELFDATA2MSB
#else
#define LIBELF_BYTEORDER ELFDATA2LSB
#endif
#define LIBELF_CLASS ELFCLASS32
#elif defined(__i386__)
#define LIBELF_ARCH EM_386
#define LIBELF_BYTEORDER ELFDATA2LSB
#define LIBELF_CLASS ELFCLASS32
#elif defined(__ia64__)
#define LIBELF_ARCH EM_IA_64
#define LIBELF_BYTEORDER ELFDATA2LSB
#define LIBELF_CLASS ELFCLASS64
#elif defined(__mips__)
#define LIBELF_ARCH EM_MIPS
#if defined(__MIPSEB__)
#define LIBELF_BYTEORDER ELFDATA2MSB
#else
#define LIBELF_BYTEORDER ELFDATA2LSB
#endif
#define LIBELF_CLASS ELFCLASS32
#elif defined(__powerpc__)
#define LIBELF_ARCH EM_PPC
#define LIBELF_BYTEORDER ELFDATA2MSB
#define LIBELF_CLASS ELFCLASS32
#elif defined(__sparc__)
#define LIBELF_ARCH EM_SPARCV9
#define LIBELF_BYTEORDER ELFDATA2MSB
#define LIBELF_CLASS ELFCLASS64
#else
#error Unknown FreeBSD architecture.
#endif
#endif /* __FreeBSD__ */
/*
* Definitions for Minix3.
*/
#ifdef __minix
#define LIBELF_ARCH EM_386
#define LIBELF_BYTEORDER ELFDATA2LSB
#define LIBELF_CLASS ELFCLASS32
#endif /* __minix */
#ifdef __NetBSD__
#include <machine/elf_machdep.h>
#if !defined(ARCH_ELFSIZE)
#error ARCH_ELFSIZE is not defined.
#endif
#if ARCH_ELFSIZE == 32
#define LIBELF_ARCH ELF32_MACHDEP_ID
#define LIBELF_BYTEORDER ELF32_MACHDEP_ENDIANNESS
#define LIBELF_CLASS ELFCLASS32
#define Elf_Note Elf32_Nhdr
#else
#define LIBELF_ARCH ELF64_MACHDEP_ID
#define LIBELF_BYTEORDER ELF64_MACHDEP_ENDIANNESS
#define LIBELF_CLASS ELFCLASS64
#define Elf_Note Elf64_Nhdr
#endif
#endif /* __NetBSD__ */
#if defined(__OpenBSD__)
#include <machine/exec.h>
#define LIBELF_ARCH ELF_TARG_MACH
#define LIBELF_BYTEORDER ELF_TARG_DATA
#define LIBELF_CLASS ELF_TARG_CLASS
#endif
/*
* GNU & Linux compatibility.
*
* `__linux__' is defined in an environment runs the Linux kernel and glibc.
* `__GNU__' is defined in an environment runs a GNU kernel (Hurd) and glibc.
* `__GLIBC__' is defined for an environment that runs glibc over a non-GNU
* kernel such as GNU/kFreeBSD.
*/
#if defined(__linux__) || defined(__GNU__) || defined(__GLIBC__)
#if defined(__linux__)
#include "native-elf-format.h"
#define LIBELF_CLASS ELFTC_CLASS
#define LIBELF_ARCH ELFTC_ARCH
#define LIBELF_BYTEORDER ELFTC_BYTEORDER
#endif /* defined(__linux__) */
#if LIBELF_CLASS == ELFCLASS32
#define Elf_Note Elf32_Nhdr
#elif LIBELF_CLASS == ELFCLASS64
#define Elf_Note Elf64_Nhdr
#else
#error LIBELF_CLASS needs to be one of ELFCLASS32 or ELFCLASS64
#endif
#endif /* defined(__linux__) || defined(__GNU__) || defined(__GLIBC__) */

View File

@ -1,40 +0,0 @@
/*-
* Copyright (c) 2006,2008,2011 Joseph Koshy
* All rights reserved.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 <libelf.h>
#include "_libelf.h"
ELFTC_VCSID("$Id: elf.c 2225 2011-11-26 18:55:54Z jkoshy $");
struct _libelf_globals _libelf = {
.libelf_arch = LIBELF_ARCH,
.libelf_byteorder = LIBELF_BYTEORDER,
.libelf_class = LIBELF_CLASS,
.libelf_error = 0,
.libelf_fillchar = 0,
.libelf_version = EV_NONE
};

View File

@ -1,91 +0,0 @@
/*-
* Copyright (c) 2006,2008-2011 Joseph Koshy
* All rights reserved.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 <libelf.h>
#include "_libelf.h"
ELFTC_VCSID("$Id: elf_begin.c 2364 2011-12-28 17:55:25Z jkoshy $");
Elf *
elf_begin(int fd, Elf_Cmd c, Elf *a)
{
Elf *e;
e = NULL;
if (LIBELF_PRIVATE(version) == EV_NONE) {
LIBELF_SET_ERROR(SEQUENCE, 0);
return (NULL);
}
switch (c) {
case ELF_C_NULL:
return (NULL);
case ELF_C_WRITE:
/*
* The ELF_C_WRITE command is required to ignore the
* descriptor passed in.
*/
a = NULL;
break;
case ELF_C_RDWR:
if (a != NULL) { /* not allowed for ar(1) archives. */
LIBELF_SET_ERROR(ARGUMENT, 0);
return (NULL);
}
/*FALLTHROUGH*/
case ELF_C_READ:
/*
* Descriptor `a' could be for a regular ELF file, or
* for an ar(1) archive. If descriptor `a' was opened
* using a valid file descriptor, we need to check if
* the passed in `fd' value matches the original one.
*/
if (a &&
((a->e_fd != -1 && a->e_fd != fd) || c != a->e_cmd)) {
LIBELF_SET_ERROR(ARGUMENT, 0);
return (NULL);
}
break;
default:
LIBELF_SET_ERROR(ARGUMENT, 0);
return (NULL);
}
if (a == NULL)
e = _libelf_open_object(fd, c, 1);
else if (a->e_kind == ELF_K_AR)
e = _libelf_ar_open_member(a->e_fd, c, a);
else
(e = a)->e_activations++;
return (e);
}

View File

@ -1,58 +0,0 @@
/*-
* Copyright (c) 2006,2008 Joseph Koshy
* All rights reserved.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 <libelf.h>
#include "_libelf.h"
ELFTC_VCSID("$Id: elf_cntl.c 2225 2011-11-26 18:55:54Z jkoshy $");
int
elf_cntl(Elf *e, Elf_Cmd c)
{
if (e == NULL ||
(c != ELF_C_FDDONE && c != ELF_C_FDREAD)) {
LIBELF_SET_ERROR(ARGUMENT, 0);
return (-1);
}
if (e->e_parent) {
LIBELF_SET_ERROR(ARCHIVE, 0);
return (-1);
}
if (c == ELF_C_FDREAD) {
if (e->e_cmd == ELF_C_WRITE) {
LIBELF_SET_ERROR(MODE, 0);
return (-1);
}
else
return (0);
}
e->e_fd = -1;
return 0;
}

View File

@ -1,254 +0,0 @@
/*-
* Copyright (c) 2006,2008,2011 Joseph Koshy
* All rights reserved.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 <assert.h>
#include <errno.h>
#include <libelf.h>
#include <stdlib.h>
#include "_libelf.h"
ELFTC_VCSID("$Id: elf_data.c 2272 2011-12-03 17:07:31Z jkoshy $");
Elf_Data *
elf_getdata(Elf_Scn *s, Elf_Data *ed)
{
Elf *e;
unsigned int sh_type;
int elfclass, elftype;
size_t fsz, msz, count;
struct _Libelf_Data *d;
uint64_t sh_align, sh_offset, sh_size;
int (*xlate)(char *_d, size_t _dsz, char *_s, size_t _c, int _swap);
d = (struct _Libelf_Data *) ed;
if (s == NULL || (e = s->s_elf) == NULL ||
(d != NULL && s != d->d_scn)) {
LIBELF_SET_ERROR(ARGUMENT, 0);
return (NULL);
}
assert(e->e_kind == ELF_K_ELF);
if (d == NULL && (d = STAILQ_FIRST(&s->s_data)) != NULL)
return (&d->d_data);
if (d != NULL)
return (&STAILQ_NEXT(d, d_next)->d_data);
if (e->e_rawfile == NULL) {
/*
* In the ELF_C_WRITE case, there is no source that
* can provide data for the section.
*/
LIBELF_SET_ERROR(ARGUMENT, 0);
return (NULL);
}
elfclass = e->e_class;
assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64);
if (elfclass == ELFCLASS32) {
sh_type = s->s_shdr.s_shdr32.sh_type;
sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset;
sh_size = (uint64_t) s->s_shdr.s_shdr32.sh_size;
sh_align = (uint64_t) s->s_shdr.s_shdr32.sh_addralign;
} else {
sh_type = s->s_shdr.s_shdr64.sh_type;
sh_offset = s->s_shdr.s_shdr64.sh_offset;
sh_size = s->s_shdr.s_shdr64.sh_size;
sh_align = s->s_shdr.s_shdr64.sh_addralign;
}
if (sh_type == SHT_NULL) {
LIBELF_SET_ERROR(SECTION, 0);
return (NULL);
}
if ((elftype = _libelf_xlate_shtype(sh_type)) < ELF_T_FIRST ||
elftype > ELF_T_LAST || (sh_type != SHT_NOBITS &&
sh_offset + sh_size > (uint64_t) e->e_rawsize)) {
LIBELF_SET_ERROR(SECTION, 0);
return (NULL);
}
if ((fsz = (elfclass == ELFCLASS32 ? elf32_fsize : elf64_fsize)
(elftype, (size_t) 1, e->e_version)) == 0) {
LIBELF_SET_ERROR(UNIMPL, 0);
return (NULL);
}
if (sh_size % fsz) {
LIBELF_SET_ERROR(SECTION, 0);
return (NULL);
}
count = sh_size / fsz;
msz = _libelf_msize(elftype, elfclass, e->e_version);
assert(msz > 0);
if ((d = _libelf_allocate_data(s)) == NULL)
return (NULL);
d->d_data.d_buf = NULL;
d->d_data.d_off = 0;
d->d_data.d_align = sh_align;
d->d_data.d_size = msz * count;
d->d_data.d_type = elftype;
d->d_data.d_version = e->e_version;
if (sh_type == SHT_NOBITS || sh_size == 0) {
STAILQ_INSERT_TAIL(&s->s_data, d, d_next);
return (&d->d_data);
}
if ((d->d_data.d_buf = malloc(msz*count)) == NULL) {
(void) _libelf_release_data(d);
LIBELF_SET_ERROR(RESOURCE, 0);
return (NULL);
}
d->d_flags |= LIBELF_F_DATA_MALLOCED;
xlate = _libelf_get_translator(elftype, ELF_TOMEMORY, elfclass);
if (!(*xlate)(d->d_data.d_buf, d->d_data.d_size,
e->e_rawfile + sh_offset, count,
e->e_byteorder != LIBELF_PRIVATE(byteorder))) {
_libelf_release_data(d);
LIBELF_SET_ERROR(DATA, 0);
return (NULL);
}
STAILQ_INSERT_TAIL(&s->s_data, d, d_next);
return (&d->d_data);
}
Elf_Data *
elf_newdata(Elf_Scn *s)
{
Elf *e;
struct _Libelf_Data *d;
if (s == NULL || (e = s->s_elf) == NULL) {
LIBELF_SET_ERROR(ARGUMENT, 0);
return (NULL);
}
assert(e->e_kind == ELF_K_ELF);
/*
* elf_newdata() has to append a data descriptor, so
* bring in existing section data if not already present.
*/
if (e->e_rawfile && s->s_size > 0 && STAILQ_EMPTY(&s->s_data))
if (elf_getdata(s, NULL) == NULL)
return (NULL);
if ((d = _libelf_allocate_data(s)) == NULL)
return (NULL);
STAILQ_INSERT_TAIL(&s->s_data, d, d_next);
d->d_data.d_align = 1;
d->d_data.d_buf = NULL;
d->d_data.d_off = (uint64_t) ~0;
d->d_data.d_size = 0;
d->d_data.d_type = ELF_T_BYTE;
d->d_data.d_version = LIBELF_PRIVATE(version);
(void) elf_flagscn(s, ELF_C_SET, ELF_F_DIRTY);
return (&d->d_data);
}
/*
* Retrieve a data descriptor for raw (untranslated) data for section
* `s'.
*/
Elf_Data *
elf_rawdata(Elf_Scn *s, Elf_Data *ed)
{
Elf *e;
int elf_class;
uint32_t sh_type;
struct _Libelf_Data *d;
uint64_t sh_align, sh_offset, sh_size;
if (s == NULL || (e = s->s_elf) == NULL || e->e_rawfile == NULL) {
LIBELF_SET_ERROR(ARGUMENT, 0);
return (NULL);
}
assert(e->e_kind == ELF_K_ELF);
d = (struct _Libelf_Data *) ed;
if (d == NULL && (d = STAILQ_FIRST(&s->s_rawdata)) != NULL)
return (&d->d_data);
if (d != NULL)
return (&STAILQ_NEXT(d, d_next)->d_data);
elf_class = e->e_class;
assert(elf_class == ELFCLASS32 || elf_class == ELFCLASS64);
if (elf_class == ELFCLASS32) {
sh_type = s->s_shdr.s_shdr32.sh_type;
sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset;
sh_size = (uint64_t) s->s_shdr.s_shdr32.sh_size;
sh_align = (uint64_t) s->s_shdr.s_shdr32.sh_addralign;
} else {
sh_type = s->s_shdr.s_shdr64.sh_type;
sh_offset = s->s_shdr.s_shdr64.sh_offset;
sh_size = s->s_shdr.s_shdr64.sh_size;
sh_align = s->s_shdr.s_shdr64.sh_addralign;
}
if (sh_type == SHT_NULL)
return (NULL);
if ((d = _libelf_allocate_data(s)) == NULL)
return (NULL);
d->d_data.d_buf = (sh_type == SHT_NOBITS || sh_size == 0) ? NULL :
e->e_rawfile + sh_offset;
d->d_data.d_off = 0;
d->d_data.d_align = sh_align;
d->d_data.d_size = sh_size;
d->d_data.d_type = ELF_T_BYTE;
d->d_data.d_version = e->e_version;
STAILQ_INSERT_TAIL(&s->s_rawdata, d, d_next);
return (&d->d_data);
}

View File

@ -1,97 +0,0 @@
/*-
* Copyright (c) 2006,2008-2009,2011 Joseph Koshy
* All rights reserved.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 <sys/cdefs.h>
#include <assert.h>
#include <libelf.h>
#include <stdlib.h>
#include "_libelf.h"
#if ELFTC_HAVE_MMAP
#include <sys/mman.h>
#endif
ELFTC_VCSID("$Id: elf_end.c 2240 2011-11-28 06:36:48Z jkoshy $");
int
elf_end(Elf *e)
{
Elf *sv;
Elf_Scn *scn, *tscn;
if (e == NULL || e->e_activations == 0)
return (0);
if (--e->e_activations > 0)
return (e->e_activations);
assert(e->e_activations == 0);
while (e && e->e_activations == 0) {
switch (e->e_kind) {
case ELF_K_AR:
/*
* If we still have open child descriptors, we
* need to defer reclaiming resources till all
* the child descriptors for the archive are
* closed.
*/
if (e->e_u.e_ar.e_nchildren > 0)
return (0);
break;
case ELF_K_ELF:
/*
* Reclaim all section descriptors.
*/
STAILQ_FOREACH_SAFE(scn, &e->e_u.e_elf.e_scn, s_next,
tscn)
scn = _libelf_release_scn(scn);
break;
case ELF_K_NUM:
assert(0);
default:
break;
}
if (e->e_rawfile) {
if (e->e_flags & LIBELF_F_RAWFILE_MALLOC)
free(e->e_rawfile);
#if ELFTC_HAVE_MMAP
else if (e->e_flags & LIBELF_F_RAWFILE_MMAP)
(void) munmap(e->e_rawfile, e->e_rawsize);
#endif
}
sv = e;
if ((e = e->e_parent) != NULL)
e->e_u.e_ar.e_nchildren--;
sv = _libelf_release_elf(sv);
}
return (0);
}

View File

@ -1,85 +0,0 @@
/*-
* Copyright (c) 2006,2008,2011 Joseph Koshy
* All rights reserved.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 <sys/cdefs.h>
#include <libelf.h>
#include <stdio.h>
#include <string.h>
#include "_libelf.h"
ELFTC_VCSID("$Id: elf_errmsg.c 2225 2011-11-26 18:55:54Z jkoshy $");
/*
* Retrieve a human readable translation for an error message.
*/
const char *_libelf_errors[] = {
#define DEFINE_ERROR(N,S) [ELF_E_##N] = S
DEFINE_ERROR(NONE, "No Error"),
DEFINE_ERROR(ARCHIVE, "Malformed ar(1) archive"),
DEFINE_ERROR(ARGUMENT, "Invalid argument"),
DEFINE_ERROR(CLASS, "ELF class mismatch"),
DEFINE_ERROR(DATA, "Invalid data buffer descriptor"),
DEFINE_ERROR(HEADER, "Missing or malformed ELF header"),
DEFINE_ERROR(IO, "I/O error"),
DEFINE_ERROR(LAYOUT, "Layout constraint violation"),
DEFINE_ERROR(MODE, "Incorrect ELF descriptor mode"),
DEFINE_ERROR(RANGE, "Value out of range of target"),
DEFINE_ERROR(RESOURCE, "Resource exhaustion"),
DEFINE_ERROR(SECTION, "Invalid section descriptor"),
DEFINE_ERROR(SEQUENCE, "API calls out of sequence"),
DEFINE_ERROR(UNIMPL, "Unimplemented feature"),
DEFINE_ERROR(VERSION, "Unknown ELF API version"),
DEFINE_ERROR(NUM, "Unknown error")
#undef DEFINE_ERROR
};
const char *
elf_errmsg(int error)
{
int oserr;
if (error == ELF_E_NONE &&
(error = LIBELF_PRIVATE(error)) == 0)
return NULL;
else if (error == -1)
error = LIBELF_PRIVATE(error);
oserr = error >> LIBELF_OS_ERROR_SHIFT;
error &= LIBELF_ELF_ERROR_MASK;
if (error < ELF_E_NONE || error >= ELF_E_NUM)
return _libelf_errors[ELF_E_NUM];
if (oserr) {
(void) snprintf(LIBELF_PRIVATE(msg),
sizeof(LIBELF_PRIVATE(msg)), "%s: %s",
_libelf_errors[error], strerror(oserr));
return (const char *)&LIBELF_PRIVATE(msg);
}
return _libelf_errors[error];
}

Some files were not shown because too many files have changed in this diff Show More