mirror of
https://github.com/wiiu-env/WiiUPluginLoaderBackend.git
synced 2024-11-16 01:45:10 +01:00
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:
parent
a83d11379e
commit
2705a91c13
11
.gitignore
vendored
11
.gitignore
vendored
@ -1,7 +1,6 @@
|
||||
*.elf
|
||||
*.rpx
|
||||
*.bin
|
||||
hook.h
|
||||
build/
|
||||
*.cbp
|
||||
WiiUPluginLoaderBackend.layout
|
||||
*.elf
|
||||
*.layout
|
||||
*.rpx
|
||||
build/
|
||||
*.save-failed
|
||||
|
198
Makefile
198
Makefile
@ -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 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)))
|
||||
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))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# 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
|
||||
export TOPDIR := $(CURDIR)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#-------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
#-------------------------------------------------------------------------------
|
||||
export LD := $(CC)
|
||||
#-------------------------------------------------------------------------------
|
||||
else
|
||||
#-------------------------------------------------------------------------------
|
||||
export LD := $(CXX)
|
||||
#-------------------------------------------------------------------------------
|
||||
endif
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
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)))
|
||||
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
-I$(CURDIR)/$(BUILD)
|
||||
|
||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
|
||||
.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
|
||||
#---------------------------------------------------------------------------------
|
||||
#-------------------------------------------------------------------------------
|
||||
|
@ -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
|
@ -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_ */
|
58
source/common/module_defines.h
Normal file
58
source/common/module_defines.h
Normal 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
|
95
source/common/plugin_defines.h
Normal file
95
source/common/plugin_defines.h
Normal 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
|
20
source/common/relocation_defines.h
Normal file
20
source/common/relocation_defines.h
Normal 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;
|
25
source/common/replacement_defines.h
Normal file
25
source/common/replacement_defines.h
Normal 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
29
source/crt0.s
Normal 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
851
source/elfio/elf_types.hpp
Normal 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
932
source/elfio/elfio.hpp
Normal 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
976
source/elfio/elfio_dump.hpp
Normal 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
|
257
source/elfio/elfio_dynamic.hpp
Normal file
257
source/elfio/elfio_dynamic.hpp
Normal 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
|
145
source/elfio/elfio_header.hpp
Normal file
145
source/elfio/elfio_header.hpp
Normal 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
170
source/elfio/elfio_note.hpp
Normal 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
|
333
source/elfio/elfio_relocation.hpp
Normal file
333
source/elfio/elfio_relocation.hpp
Normal 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
|
360
source/elfio/elfio_section.hpp
Normal file
360
source/elfio/elfio_section.hpp
Normal 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
|
246
source/elfio/elfio_segment.hpp
Normal file
246
source/elfio/elfio_segment.hpp
Normal 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
|
100
source/elfio/elfio_strings.hpp
Normal file
100
source/elfio/elfio_strings.hpp
Normal 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
|
282
source/elfio/elfio_symbols.hpp
Normal file
282
source/elfio/elfio_symbols.hpp
Normal 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
|
209
source/elfio/elfio_utils.hpp
Normal file
209
source/elfio/elfio_utils.hpp
Normal 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
103
source/hooks.cpp
Normal 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
7
source/hooks.h
Normal 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);
|
@ -6,7 +6,7 @@ SCKernelCopyData:
|
||||
li %r7, 0x10
|
||||
andc %r6, %r6, %r7
|
||||
mtmsr %r6
|
||||
|
||||
|
||||
// Copy data
|
||||
addi %r3, %r3, -1
|
||||
addi %r4, %r4, -1
|
||||
@ -15,7 +15,7 @@ SCKernelCopyData_loop:
|
||||
lbzu %r5, 1(%r4)
|
||||
stbu %r5, 1(%r3)
|
||||
bdnz SCKernelCopyData_loop
|
||||
|
||||
|
||||
// Enable data address translation
|
||||
ori %r6, %r6, 0x10
|
||||
mtmsr %r6
|
||||
@ -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
|
||||
blr
|
@ -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;
|
91
source/kernel/kernel_utils.c
Normal file
91
source/kernel/kernel_utils.c
Normal 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
192
source/main.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
};
|
104
source/plugin/DynamicLinkingHelper.cpp
Normal file
104
source/plugin/DynamicLinkingHelper.cpp
Normal 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;
|
||||
}
|
@ -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
|
@ -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
|
@ -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
|
@ -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;
|
||||
};
|
56
source/plugin/PluginContainer.h
Normal file
56
source/plugin/PluginContainer.h
Normal 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;
|
||||
};
|
296
source/plugin/PluginContainerPersistence.cpp
Normal file
296
source/plugin/PluginContainerPersistence.cpp
Normal 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;
|
||||
}
|
10
source/plugin/PluginContainerPersistence.h
Normal file
10
source/plugin/PluginContainerPersistence.h
Normal 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);
|
||||
};
|
76
source/plugin/PluginData.cpp
Normal file
76
source/plugin/PluginData.cpp
Normal 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;
|
||||
}
|
68
source/plugin/PluginData.h
Normal file
68
source/plugin/PluginData.h
Normal 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;
|
||||
};
|
112
source/plugin/PluginDataFactory.cpp
Normal file
112
source/plugin/PluginDataFactory.cpp
Normal 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;
|
||||
}
|
@ -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);
|
||||
};
|
95
source/plugin/PluginInformation.h
Normal file
95
source/plugin/PluginInformation.h
Normal 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;
|
||||
};
|
349
source/plugin/PluginInformationFactory.cpp
Normal file
349
source/plugin/PluginInformationFactory.cpp
Normal 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;
|
||||
}
|
35
source/plugin/PluginInformationFactory.h
Normal file
35
source/plugin/PluginInformationFactory.h
Normal 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);
|
||||
};
|
96
source/plugin/PluginMetaInformation.h
Normal file
96
source/plugin/PluginMetaInformation.h
Normal 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;
|
||||
};
|
108
source/plugin/PluginMetaInformationFactory.cpp
Normal file
108
source/plugin/PluginMetaInformationFactory.cpp
Normal 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;
|
||||
}
|
@ -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
|
@ -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
|
@ -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
159
source/utils/ElfUtils.cpp
Normal 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
50
source/utils/ElfUtils.h
Normal 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);
|
||||
};
|
@ -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;
|
||||
|
80
source/utils/StringTools.h
Normal file
80
source/utils/StringTools.h
Normal 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 */
|
||||
|
@ -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
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
@ -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
40
source/utils/utils.h
Normal 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_
|
@ -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;*/
|
@ -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_
|
@ -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);
|
||||
}
|
@ -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_
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
@ -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_
|
@ -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);
|
||||
}
|
@ -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_
|
@ -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
|
@ -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();
|
||||
}
|
@ -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_
|
@ -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);
|
||||
}
|
@ -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_
|
276
src/entry.cpp
276
src/entry.cpp
@ -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");
|
||||
|
||||
}
|
174
src/fs/CFile.cpp
174
src/fs/CFile.cpp
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
@ -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;
|
||||
}
|
103
src/fs/DirList.h
103
src/fs/DirList.h
@ -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
|
@ -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;
|
||||
}
|
@ -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_
|
@ -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;
|
||||
}
|
||||
|
@ -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_
|
@ -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
@ -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_
|
@ -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);
|
||||
}
|
@ -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
|
@ -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 */
|
@ -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_ */
|
@ -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_ */
|
@ -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__) */
|
@ -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
|
||||
};
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
@ -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
Loading…
Reference in New Issue
Block a user