first commit

This commit is contained in:
Maschell 2020-04-27 13:32:37 +02:00
commit 7ed1cee873
54 changed files with 9208 additions and 0 deletions

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
/*.elf
/*.cbp
/build
*.rpx
*.bin
*.cscope_file_list
*.layout

339
LICENSE Normal file
View File

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
{description}
Copyright (C) {year} {fullname}
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 2 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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
{signature of Ty Coon}, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

216
Makefile Normal file
View File

@ -0,0 +1,216 @@
#---------------------------------------------------------------------------------
# Clear the implicit built in rules
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITPPC)),)
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
endif
ifeq ($(strip $(DEVKITPRO)),)
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>devkitPRO")
endif
export PATH := $(DEVKITPPC)/bin:$(PORTLIBS)/bin:$(PATH)
export PORTLIBS := $(DEVKITPRO)/portlibs/ppc
GCC_VER := $(shell $(DEVKITPPC)/bin/powerpc-eabi-gcc -dumpversion)
PREFIX := powerpc-eabi-
export AS := $(PREFIX)as
export CC := $(PREFIX)gcc
export CXX := $(PREFIX)g++
export AR := $(PREFIX)ar
export OBJCOPY := $(PREFIX)objcopy
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
#---------------------------------------------------------------------------------
TARGET := payload
BUILD := build
BUILD_DBG := $(TARGET)_dbg
SOURCES := src \
src/module \
src/utils
DATA := data
INCLUDES := src
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
CFLAGS := -std=gnu11 -mcpu=750 -meabi -mhard-float -ffast-math \
-O2 -Wall -Wextra -Wno-unused-parameter -Wno-strict-aliasing $(INCLUDE)
CXXFLAGS := -std=gnu++11 -mcpu=750 -meabi -mhard-float -ffast-math \
-O2 -Wall -Wextra -Wno-unused-parameter -Wno-strict-aliasing $(INCLUDE)
ASFLAGS := -mregnames
LDFLAGS := -nostartfiles -Wl,--gc-sections
#---------------------------------------------------------------------------------
Q := @
MAKEFLAGS += --no-print-directory
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS :=
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(CURDIR) \
$(DEVKITPPC)/lib \
$(DEVKITPRO)/wut \
$(DEVKITPPC)/lib/gcc/powerpc-eabi/$(GCC_VER)
#---------------------------------------------------------------------------------
# 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)/*.*)))
#---------------------------------------------------------------------------------
# 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) -I$(LIBOGC_INC) \
-I$(PORTLIBS)/include -I$(PORTLIBS)/include/freetype2
#---------------------------------------------------------------------------------
# build a list of library paths
#---------------------------------------------------------------------------------
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \
-L$(LIBOGC_LIB) -L$(PORTLIBS)/lib
export OUTPUT := $(CURDIR)/$(TARGET)
.PHONY: $(BUILD) clean install
#---------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).bin $(BUILD_DBG).elf
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT).elf: $(OFILES)
#---------------------------------------------------------------------------------
# This rule links in binary data with the .jpg extension
#---------------------------------------------------------------------------------
%.elf: link.ld $(OFILES)
@echo "linking ... $(TARGET).elf"
$(Q)$(LD) -n -T $^ $(LDFLAGS) -o ../$(BUILD_DBG).elf $(LIBPATHS) $(LIBS)
$(Q)$(OBJCOPY) -S -R .comment -R .gnu.attributes ../$(BUILD_DBG).elf $@
$(Q)$(OBJCOPY) -O binary -R .comment -R .gnu.attributes ../$(BUILD_DBG).elf $@.bin
#---------------------------------------------------------------------------------
%.a:
#---------------------------------------------------------------------------------
@echo $(notdir $@)
@rm -f $@
@$(AR) -rc $@ $^
#---------------------------------------------------------------------------------
%.o: %.cpp
@echo $(notdir $<)
@$(CXX) -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER)
#---------------------------------------------------------------------------------
%.o: %.c
@echo $(notdir $<)
@$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d $(CFLAGS) -c $< -o $@ $(ERROR_FILTER)
#---------------------------------------------------------------------------------
%.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 $(@)
#---------------------------------------------------------------------------------
%.jpg.o : %.jpg
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
#---------------------------------------------------------------------------------
%.ttf.o : %.ttf
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
#---------------------------------------------------------------------------------
%.bin.o : %.bin
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
#---------------------------------------------------------------------------------
%.wav.o : %.wav
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
#---------------------------------------------------------------------------------
%.mp3.o : %.mp3
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
#---------------------------------------------------------------------------------
%.ogg.o : %.ogg
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
#---------------------------------------------------------------------------------
%.tga.o : %.tga
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
-include $(DEPENDS)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------

16
README.md Normal file
View File

@ -0,0 +1,16 @@
# CustomRPXLoader
This custom loader for `.rpx` files which can be used with any `payload.elf` loader. (For example [https://github.com/wiiu-env/PayloadFromRPX](https://github.com/wiiu-env/PayloadFromRPX) or [JsTypeHax](https://github.com/wiiu-env/JsTypeHax))
## Usage
Place the `payload.elf` in the `sd:/wiiu` folder of your sd card and run a exploit which loads `payload.elf`, this will load the `sd:/wiiu/payload.rpx`into memory and execute it. The maximum size of the `payload.rpx` depends on the size of this loader, but should > 7Mib.
## Building
For building you just need [wut](https://github.com/devkitPro/wut/) installed, then use the `make` command.
## Credits
- Maschell
- orboditilt
- Copy pasted the solution for using wut header in .elf files from [RetroArch](https://github.com/libretro/RetroArch)
- Copy pasted resolving the ElfRelocations from [decaf](https://github.com/decaf-emu/decaf-emu)
- Copy pasted SD mounting code + devoptabs from [libutils](https://github.com/Maschell/libutils)

158
src/ElfUtils.cpp Normal file
View File

@ -0,0 +1,158 @@
#include <stdio.h>
#include <string.h>
#include <coreinit/debug.h>
#include <coreinit/cache.h>
#include <coreinit/memdefaultheap.h>
#include <whb/sdcard.h>
#include <whb/file.h>
#include <whb/log.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) {
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.\n");
return false;
}
if (distance & 3) {
DEBUG_FUNCTION_LINE("***RELOC ERROR %d: lower 2 bits must be zero before shifting.\n", -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.\n", -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).\n");
DEBUG_FUNCTION_LINE("***value %08X - target %08X = distance %08X\n", value, target, distance);
return false;
}
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));
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.\n", -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).\n", -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).\n", -470040);
return false;
}
*(int32_t *)target = (*(int32_t *)target & 0xfc000003) | (distance & 0x03fffffc);
break;
}
default:
DEBUG_FUNCTION_LINE("***ERROR: Unsupported Relocation_Add Type (%08X):\n", type);
return false;
}
return true;
}

50
src/ElfUtils.h Normal file
View File

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

View File

@ -0,0 +1,61 @@
/****************************************************************************
* 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 <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#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_TRAMPOLIN_LIST_LENGTH DYN_LINK_FUNCTION_LIST_LENGTH
typedef struct _dyn_linking_function_t {
char functionName[DYN_LINK_FUNCTION_NAME_LENGTH+1];
void * address;
} dyn_linking_function_t;
typedef struct _dyn_linking_import_t {
char importName[DYN_LINK_IMPORT_NAME_LENGTH+1];
bool isData = false;
} dyn_linking_import_t;
typedef struct _dyn_linking_relocation_entry_t {
dyn_linking_function_t* functionEntry = NULL;
dyn_linking_import_t* importEntry = NULL;
void * destination = NULL;
char type;
size_t offset;
int32_t addend;
} dyn_linking_relocation_entry_t;
typedef struct _dyn_linking_relocation_data_t {
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;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,56 @@
/****************************************************************************
* 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;
};
#define MAXIMUM_MODULES 8
struct module_information_t {
int32_t number_used_modules = 0; // Number of used function. Maximum is MAXIMUM_MODULES
dyn_linking_relocation_data_t linking_data;
relocation_trampolin_entry_t trampolines[DYN_LINK_TRAMPOLIN_LIST_LENGTH];
module_information_single_t module_data[MAXIMUM_MODULES];
};
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,19 @@
#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 trampolin[4];
RelocationTrampolinStatus status = RELOC_TRAMP_FREE;
} relocation_trampolin_entry_t;

37
src/dynamic.c Normal file
View File

@ -0,0 +1,37 @@
#include <coreinit/dynload.h>
#include <coreinit/debug.h>
#define IMPORT(name) void* addr_##name
#define IMPORT_BEGIN(lib)
#define IMPORT_END()
#include "imports.h"
#undef IMPORT
#undef IMPORT_BEGIN
#undef IMPORT_END
#define IMPORT(name) do{if(OSDynLoad_FindExport(handle, 0, #name, &addr_##name) < 0)OSFatal("Function " # name " is NULL");} while(0)
#define IMPORT_BEGIN(lib) OSDynLoad_Acquire(#lib ".rpl", &handle)
/* #define IMPORT_END() OSDynLoad_Release(handle) */
#define IMPORT_END()
#define EXPORT_VAR(type, var) type var __attribute__((section(".data")));
EXPORT_VAR(uint32_t *, pMEMAllocFromDefaultHeapEx);
EXPORT_VAR(uint32_t *, pMEMAllocFromDefaultHeap);
EXPORT_VAR(uint32_t *, pMEMFreeToDefaultHeap);
void InitFunctionPointers(void) {
OSDynLoad_Module handle;
addr_OSDynLoad_Acquire = (void*) 0x0102A3B4;
addr_OSDynLoad_FindExport = (void*) 0x0102B828;
OSDynLoad_Acquire("coreinit.rpl", &handle);
OSDynLoad_FindExport(handle, 1, "MEMAllocFromDefaultHeapEx", (void**) &pMEMAllocFromDefaultHeapEx);
OSDynLoad_FindExport(handle, 1, "MEMAllocFromDefaultHeap", (void**) &pMEMAllocFromDefaultHeap);
OSDynLoad_FindExport(handle, 1, "MEMFreeToDefaultHeap", (void**) &pMEMFreeToDefaultHeap);
#include "imports.h"
}

11
src/dynamic.h Normal file
View File

@ -0,0 +1,11 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
void InitFunctionPointers(void);
#ifdef __cplusplus
}
#endif

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

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

955
src/elfio/elfio.hpp Normal file
View File

@ -0,0 +1,955 @@
/*
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 ); \
} \
} \
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( 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
src/elfio/elfio_dump.hpp Normal file
View File

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

257
src/elfio/elfio_dynamic.hpp Normal file
View File

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

145
src/elfio/elfio_header.hpp Normal file
View File

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

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

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

View File

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

360
src/elfio/elfio_section.hpp Normal file
View File

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

246
src/elfio/elfio_segment.hpp Normal file
View File

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

100
src/elfio/elfio_strings.hpp Normal file
View File

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

282
src/elfio/elfio_symbols.hpp Normal file
View File

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

209
src/elfio/elfio_utils.hpp Normal file
View File

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

24
src/import_stub.S Normal file
View File

@ -0,0 +1,24 @@
/*#define IMPORT(name) \
.global name; \
name: \
lis %r11, addr_##name@h; \
lwz %r11, addr_##name@l(%r11); \
mtctr %r11; \
bctr*/
#define IMPORT(name) \
.global name; \
name: \
lis %r11, addr_##name@h; \
ori %r11, %r11, addr_##name@l; \
lwz %r11, 0(%r11); \
mtctr %r11; \
bctr
#define IMPORT_BEGIN(lib)
#define IMPORT_END()
.align 2;
.section ".text";
#include "imports.h"

281
src/imports.h Normal file
View File

@ -0,0 +1,281 @@
/* coreinit */
IMPORT_BEGIN(coreinit);
IMPORT(OSScreenInit);
IMPORT(OSScreenGetBufferSizeEx);
IMPORT(OSScreenSetBufferEx);
IMPORT(OSScreenEnableEx);
IMPORT(OSScreenFlipBuffersEx);
IMPORT(OSScreenClearBufferEx);
IMPORT(OSScreenPutFontEx);
IMPORT(OSFatal);
IMPORT(OSDynLoad_Acquire);
IMPORT(OSDynLoad_FindExport);
IMPORT(OSDynLoad_Release);
IMPORT(OSSetExceptionCallback);
IMPORT(OSSavesDone_ReadyToRelease);
IMPORT(OSInitMutex);
IMPORT(OSLockMutex);
IMPORT(OSUnlockMutex);
IMPORT(OSInitCond);
IMPORT(OSWaitCond);
IMPORT(OSSignalCond);
IMPORT(OSInitSpinLock);
IMPORT(OSUninterruptibleSpinLock_Acquire);
IMPORT(OSUninterruptibleSpinLock_Release);
IMPORT(OSFastMutex_Init);
IMPORT(OSFastMutex_Lock);
IMPORT(OSFastMutex_Unlock);
IMPORT(OSSleepTicks);
IMPORT(OSGetTitleID);
IMPORT(OSIsThreadTerminated);
IMPORT(OSSetThreadPriority);
IMPORT(OSCreateThread);
IMPORT(OSSetThreadCleanupCallback);
IMPORT(OSResumeThread);
IMPORT(OSIsThreadSuspended);
IMPORT(OSSuspendThread);
IMPORT(OSGetCurrentThread);
IMPORT(OSExitThread);
IMPORT(OSJoinThread);
IMPORT(OSYieldThread);
IMPORT(OSGetCoreId);
IMPORT(OSIsMainCore);
IMPORT(OSGetSystemTime);
IMPORT(OSGetSystemTick);
IMPORT(OSGetTime);
IMPORT(OSGetSymbolName);
IMPORT(OSGetSharedData);
IMPORT(OSEffectiveToPhysical);
IMPORT(OSInitSemaphore);
IMPORT(OSInitSemaphoreEx);
IMPORT(OSGetSemaphoreCount);
IMPORT(OSSignalSemaphore);
IMPORT(OSWaitSemaphore);
IMPORT(OSTryWaitSemaphore);
IMPORT(exit);
IMPORT(_Exit);
IMPORT(__os_snprintf);
IMPORT(DisassemblePPCRange);
IMPORT(ICInvalidateRange);
IMPORT(DCInvalidateRange);
IMPORT(DCFlushRange);
IMPORT(DCStoreRange);
IMPORT(DCStoreRangeNoSync);
IMPORT(__gh_errno_ptr);
IMPORT(MEMGetBaseHeapHandle);
IMPORT(MEMCreateExpHeapEx);
IMPORT(MEMDestroyExpHeap);
IMPORT(MEMAllocFromExpHeapEx);
IMPORT(MEMFreeToExpHeap);
IMPORT(MEMGetSizeForMBlockExpHeap);
IMPORT(MEMAllocFromFrmHeapEx);
IMPORT(MEMFreeToFrmHeap);
IMPORT(MEMGetAllocatableSizeForFrmHeapEx);
IMPORT(FSInit);
IMPORT(FSShutdown);
IMPORT(FSAddClient);
IMPORT(FSAddClientEx);
IMPORT(FSDelClient);
IMPORT(FSInitCmdBlock);
IMPORT(FSChangeDir);
IMPORT(FSGetFreeSpaceSize);
IMPORT(FSGetStat);
IMPORT(FSRemove);
IMPORT(FSOpenFile);
IMPORT(FSCloseFile);
IMPORT(FSOpenDir);
IMPORT(FSMakeDir);
IMPORT(FSReadDir);
IMPORT(FSRewindDir);
IMPORT(FSCloseDir);
IMPORT(FSGetStatFile);
IMPORT(FSReadFile);
IMPORT(FSWriteFile);
IMPORT(FSSetPosFile);
IMPORT(FSFlushFile);
IMPORT(FSTruncateFile);
IMPORT(FSRename);
IMPORT(FSGetMountSource);
IMPORT(FSMount);
IMPORT(FSUnmount);
IMPORT(IOS_Open);
IMPORT(IOS_Close);
IMPORT(IOS_Ioctl);
IMPORT(IOS_IoctlAsync);
IMPORT(IMIsAPDEnabled);
IMPORT(IMIsDimEnabled);
IMPORT(IMEnableAPD);
IMPORT(IMEnableDim);
IMPORT(IMDisableAPD);
IMPORT(IMDisableDim);
IMPORT(OSGetSystemInfo);
IMPORT_END();
/* nsysnet */
IMPORT_BEGIN(nsysnet);
IMPORT(socket_lib_init);
IMPORT(getaddrinfo);
IMPORT(freeaddrinfo);
IMPORT(getnameinfo);
IMPORT(inet_ntoa);
IMPORT(inet_ntop);
IMPORT(inet_aton);
IMPORT(inet_pton);
IMPORT(ntohl);
IMPORT(ntohs);
IMPORT(htonl);
IMPORT(htons);
IMPORT(accept);
IMPORT(bind);
IMPORT(socketclose);
IMPORT(connect);
IMPORT(getpeername);
IMPORT(getsockname);
IMPORT(getsockopt);
IMPORT(listen);
IMPORT(recv);
IMPORT(recvfrom);
IMPORT(send);
IMPORT(sendto);
IMPORT(setsockopt);
IMPORT(shutdown);
IMPORT(socket);
IMPORT(select);
IMPORT(socketlasterr);
IMPORT_END();
/* gx2 */
IMPORT_BEGIN(gx2);
IMPORT(GX2Invalidate);
IMPORT(GX2Init);
IMPORT(GX2GetSystemTVScanMode);
IMPORT(GX2CalcTVSize);
IMPORT(GX2SetTVBuffer);
IMPORT(GX2CalcDRCSize);
IMPORT(GX2SetDRCBuffer);
IMPORT(GX2CalcSurfaceSizeAndAlignment);
IMPORT(GX2InitColorBufferRegs);
IMPORT(GX2SetupContextStateEx);
IMPORT(GX2SetContextState);
IMPORT(GX2SetColorBuffer);
IMPORT(GX2SetViewport);
IMPORT(GX2SetScissor);
IMPORT(GX2SetDepthOnlyControl);
IMPORT(GX2SetColorControl);
IMPORT(GX2SetBlendControl);
IMPORT(GX2SetBlendConstantColor);
IMPORT(GX2SetCullOnlyControl);
IMPORT(GX2CalcFetchShaderSizeEx);
IMPORT(GX2InitFetchShaderEx);
IMPORT(GX2SetFetchShader);
IMPORT(GX2SetVertexShader);
IMPORT(GX2SetPixelShader);
IMPORT(GX2SetGeometryShader);
IMPORT(GX2SetGeometryUniformBlock);
IMPORT(GX2SetVertexUniformBlock);
IMPORT(GX2SetPixelUniformBlock);
IMPORT(GX2CalcGeometryShaderInputRingBufferSize);
IMPORT(GX2CalcGeometryShaderOutputRingBufferSize);
IMPORT(GX2SetGeometryShaderInputRingBuffer);
IMPORT(GX2SetGeometryShaderOutputRingBuffer);
IMPORT(GX2SetShaderModeEx);
IMPORT(GX2SetAttribBuffer);
IMPORT(GX2InitTextureRegs);
IMPORT(GX2InitSampler);
IMPORT(GX2SetPixelTexture);
IMPORT(GX2SetPixelSampler);
IMPORT(GX2ClearColor);
IMPORT(GX2CopyColorBufferToScanBuffer);
IMPORT(GX2SwapScanBuffers);
IMPORT(GX2Flush);
IMPORT(GX2WaitForVsync);
IMPORT(GX2SetTVEnable);
IMPORT(GX2SetDRCEnable);
IMPORT(GX2SetSwapInterval);
IMPORT(GX2DrawDone);
IMPORT(GX2Shutdown);
IMPORT(GX2DrawEx);
IMPORT(GX2WaitForFlip);
IMPORT(GX2GetSwapStatus);
IMPORT_END();
/* nn_ac */
IMPORT_BEGIN(nn_ac);
IMPORT(ACInitialize);
IMPORT(ACFinalize);
IMPORT(ACConnect);
IMPORT(ACClose);
IMPORT(ACGetAssignedAddress);
IMPORT(ACGetAssignedSubnet);
IMPORT_END();
/* proc_ui */
IMPORT_BEGIN(proc_ui);
IMPORT(ProcUIInit);
IMPORT(ProcUIShutdown);
IMPORT(ProcUIDrawDoneRelease);
IMPORT(ProcUIProcessMessages);
IMPORT_END();
/* sndcore2 */
IMPORT_BEGIN(sndcore2);
IMPORT(AXInitWithParams);
IMPORT(AXQuit);
IMPORT(AXRegisterFrameCallback);
IMPORT(AXAcquireMultiVoice);
IMPORT(AXSetMultiVoiceDeviceMix);
IMPORT(AXSetMultiVoiceOffsets);
IMPORT(AXSetMultiVoiceCurrentOffset);
IMPORT(AXSetMultiVoiceState);
IMPORT(AXSetMultiVoiceVe);
IMPORT(AXSetMultiVoiceSrcType);
IMPORT(AXSetMultiVoiceSrcRatio);
IMPORT(AXIsMultiVoiceRunning);
IMPORT(AXFreeMultiVoice);
IMPORT_END();
/* sysapp */
IMPORT_BEGIN(sysapp);
IMPORT(SYSRelaunchTitle);
IMPORT(_SYSGetSystemApplicationTitleId);
IMPORT(SYSLaunchMenu);
IMPORT_END();
/* vpad */
IMPORT_BEGIN(vpad);
IMPORT(VPADRead);
IMPORT(VPADInit);
IMPORT(VPADGetTPCalibratedPoint);
IMPORT_END();
/* nsyskbd */
IMPORT_BEGIN(zlib125);
IMPORT(inflateInit_);
IMPORT(inflate);
IMPORT(inflateEnd);
IMPORT_END();

40
src/kernel.cpp Normal file
View File

@ -0,0 +1,40 @@
#include <stdint.h>
#include "kernel.h"
/* assembly functions */
extern "C" void Syscall_0x36(void);
extern "C" void KernelPatches(void);
void __attribute__ ((noinline)) kern_write(void *addr, uint32_t value);
void doKernelSetup(){
kern_write((void*)(KERN_SYSCALL_TBL_1 + (0x36 * 4)), (unsigned int)KernelPatches);
kern_write((void*)(KERN_SYSCALL_TBL_2 + (0x36 * 4)), (unsigned int)KernelPatches);
kern_write((void*)(KERN_SYSCALL_TBL_3 + (0x36 * 4)), (unsigned int)KernelPatches);
kern_write((void*)(KERN_SYSCALL_TBL_4 + (0x36 * 4)), (unsigned int)KernelPatches);
kern_write((void*)(KERN_SYSCALL_TBL_5 + (0x36 * 4)), (unsigned int)KernelPatches);
Syscall_0x36();
}
/* 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"
);
}

10
src/kernel.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
#define KERN_SYSCALL_TBL_1 0xFFE84C70 // unknown
#define KERN_SYSCALL_TBL_2 0xFFE85070 // works with games
#define KERN_SYSCALL_TBL_3 0xFFE85470 // works with loader
#define KERN_SYSCALL_TBL_4 0xFFEAAA60 // works with home menu
#define KERN_SYSCALL_TBL_5 0xFFEAAE60 // works with browser (previously KERN_SYSCALL_TBL)
void doKernelSetup();

210
src/kernel_asm.S Normal file
View File

@ -0,0 +1,210 @@
.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
#define BAT_SETUP_HOOK_ADDR 0xFFF1D624
# not all of those NOP address are required for every firmware
# mainly these should stop the kernel from removing our IBAT4 and DBAT5
#define BAT_SET_NOP_ADDR_1 0xFFF06B6C
#define BAT_SET_NOP_ADDR_2 0xFFF06BF8
#define BAT_SET_NOP_ADDR_3 0xFFF003C8
#define BAT_SET_NOP_ADDR_4 0xFFF003CC
#define BAT_SET_NOP_ADDR_5 0xFFF1D70C
#define BAT_SET_NOP_ADDR_6 0xFFF1D728
#define BAT_SET_NOP_ADDR_7 0xFFF1D82C
#define BAT_SET_NOP_ADDR_8 0xFFEE11C4
#define BAT_SET_NOP_ADDR_9 0xFFEE11C8
#define BAT_SETUP_HOOK_ENTRY 0x00800000
#define BAT4U_VAL 0x008000FF
#define BAT4L_VAL 0x30800012
#define SET_R4_TO_ADDR(addr) \
lis r3, addr@h ; \
ori r3, r3, addr@l ; \
stw r4, 0(r3) ; \
dcbf 0, r3 ; \
icbi 0, r3 ;
.globl Syscall_0x36
Syscall_0x36:
li r0, 0x3600
sc
blr
.globl KernelPatches
KernelPatches:
# store the old DBAT0
mfdbatu r5, 0
mfdbatl r6, 0
# memory barrier
eieio
isync
# setup DBAT0 for access to kernel code memory
lis r3, 0xFFF0
ori r3, r3, 0x0002
mtdbatu 0, r3
lis r3, 0xFFF0
ori r3, r3, 0x0032
mtdbatl 0, r3
# memory barrier
eieio
isync
# SaveAndResetDataBATs_And_SRs hook setup, but could be any BAT function though
# just chosen because its simple
lis r3, BAT_SETUP_HOOK_ADDR@h
ori r3, r3, BAT_SETUP_HOOK_ADDR@l
# make the kernel setup our section in IBAT4 and
# jump to our function to restore the replaced instructions
lis r4, 0x3ce0 # lis r7, BAT4L_VAL@h
ori r4, r4, BAT4L_VAL@h
stw r4, 0x00(r3)
lis r4, 0x60e7 # ori r7, r7, BAT4L_VAL@l
ori r4, r4, BAT4L_VAL@l
stw r4, 0x04(r3)
lis r4, 0x7cf1 # mtspr 561, r7
ori r4, r4, 0x8ba6
stw r4, 0x08(r3)
lis r4, 0x3ce0 # lis r7, BAT4U_VAL@h
ori r4, r4, BAT4U_VAL@h
stw r4, 0x0C(r3)
lis r4, 0x60e7 # ori r7, r7, BAT4U_VAL@l
ori r4, r4, BAT4U_VAL@l
stw r4, 0x10(r3)
lis r4, 0x7cf0 # mtspr 560, r7
ori r4, r4, 0x8ba6
stw r4, 0x14(r3)
lis r4, 0x7c00 # eieio
ori r4, r4, 0x06ac
stw r4, 0x18(r3)
lis r4, 0x4c00 # isync
ori r4, r4, 0x012c
stw r4, 0x1C(r3)
lis r4, 0x7ce8 # mflr r7
ori r4, r4, 0x02a6
stw r4, 0x20(r3)
lis r4, (BAT_SETUP_HOOK_ENTRY | 0x48000003)@h # bla BAT_SETUP_HOOK_ENTRY
ori r4, r4, (BAT_SETUP_HOOK_ENTRY | 0x48000003)@l
stw r4, 0x24(r3)
# flush and invalidate the replaced instructions
lis r3, (BAT_SETUP_HOOK_ADDR & ~31)@h
ori r3, r3, (BAT_SETUP_HOOK_ADDR & ~31)@l
dcbf 0, r3
icbi 0, r3
lis r3, ((BAT_SETUP_HOOK_ADDR + 0x20) & ~31)@h
ori r3, r3, ((BAT_SETUP_HOOK_ADDR + 0x20) & ~31)@l
dcbf 0, r3
icbi 0, r3
sync
# setup IBAT4 for core 1 at this position (not really required but wont hurt)
# IBATL 4
lis r3, BAT4L_VAL@h
ori r3, r3, BAT4L_VAL@l
mtspr 561, r3
# IBATU 4
lis r3, BAT4U_VAL@h
ori r3, r3, BAT4U_VAL@l
mtspr 560, r3
# memory barrier
eieio
isync
# write "nop" to some positions
lis r4, 0x6000
# nop on IBATU 4 and DBAT 5 set/reset
#ifdef BAT_SET_NOP_ADDR_1
SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_1)
#endif
#ifdef BAT_SET_NOP_ADDR_2
SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_2)
#endif
#ifdef BAT_SET_NOP_ADDR_3
SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_3)
#endif
#ifdef BAT_SET_NOP_ADDR_4
SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_4)
#endif
#ifdef BAT_SET_NOP_ADDR_5
SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_5)
#endif
#ifdef BAT_SET_NOP_ADDR_6
SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_6)
#endif
#ifdef BAT_SET_NOP_ADDR_7
SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_7)
#endif
#if (defined(BAT_SET_NOP_ADDR_8) && defined(BAT_SET_NOP_ADDR_9))
# memory barrier
eieio
isync
# setup DBAT0 for access to kernel code memory
lis r3, 0xFFEE
ori r3, r3, 0x0002
mtdbatu 0, r3
lis r3, 0xFFEE
ori r3, r3, 0x0032
mtdbatl 0, r3
# memory barrier
eieio
isync
# write "nop" to some positions
lis r4, 0x6000
SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_8)
SET_R4_TO_ADDR(BAT_SET_NOP_ADDR_9)
#endif
# memory barrier
eieio
isync
# restore DBAT 0 and return from interrupt
mtdbatu 0, r5
mtdbatl 0, r6
# memory barrier
eieio
isync
blr

26
src/link.ld Normal file
View File

@ -0,0 +1,26 @@
OUTPUT(payload.elf);
ENTRY(_start);
SECTIONS {
. = 0x00800000;
.text : {
*(.kernel_code*);
*(.text*);
/* Tell linker to not garbage collect this section as it is not referenced anywhere */
KEEP(*(.kernel_code*));
}
.data : {
*(.rodata*);
*(.data*);
*(.sdata*);
*(.bss*);
*(.sbss*);
}
__CODE_END = .;
/DISCARD/ : {
*(*);
}
}
ASSERT((SIZEOF(.text) + SIZEOF(.data)) < 0x100000, "elf is too big");

126
src/main.cpp Normal file
View File

@ -0,0 +1,126 @@
#include <stdint.h>
#include <coreinit/cache.h>
#include <coreinit/dynload.h>
#include <sysapp/launch.h>
#include <nsysnet/socket.h>
#include <proc_ui/procui.h>
#include <coreinit/foreground.h>
#include "ElfUtils.h"
#include "module/ModuleData.h"
#include "module/ModuleDataFactory.h"
#include "common/module_defines.h"
#include "main.h"
#include "kernel.h"
#include "dynamic.h"
#include "utils/logger.h"
#include "utils/utils.h"
#include "utils/sd_fat_devoptab.h"
#define gModuleData ((module_information_t *) (0x00880000))
static_assert(sizeof(module_information_t) <= 0x80000);
bool doRelocation(std::vector<RelocationData *> &relocData, relocation_trampolin_entry_t * tramp_data, uint32_t tramp_length);
bool CheckRunning() {
switch(ProcUIProcessMessages(true)) {
case PROCUI_STATUS_EXITING: {
return false;
}
case PROCUI_STATUS_RELEASE_FOREGROUND: {
ProcUIDrawDoneRelease();
break;
}
case PROCUI_STATUS_IN_FOREGROUND: {
break;
}
case PROCUI_STATUS_IN_BACKGROUND:
default:
break;
}
return true;
}
extern "C" int _start(int argc, char **argv) {
doKernelSetup();
InitFunctionPointers();
socket_lib_init();
log_init();
int res = 0;
if((res = mount_sd_fat("sd")) >= 0) {
DEBUG_FUNCTION_LINE("Mounted sd card\n");
uint32_t ApplicationMemoryEnd;
asm volatile("lis %0, __CODE_END@h; ori %0, %0, __CODE_END@l" : "=r" (ApplicationMemoryEnd));
ApplicationMemoryEnd = (ApplicationMemoryEnd + 0x10000) & 0xFFFF0000;
ModuleData * moduleData = ModuleDataFactory::load("sd:/wiiu/payload.rpx", ApplicationMemoryEnd, 0x01000000 - ApplicationMemoryEnd, gModuleData->trampolines, DYN_LINK_TRAMPOLIN_LIST_LENGTH);
if(moduleData != NULL) {
DEBUG_FUNCTION_LINE("Loaded module data\n");
std::vector<RelocationData *> relocData = moduleData->getRelocationDataList();
if(!doRelocation(relocData, gModuleData->trampolines,DYN_LINK_TRAMPOLIN_LIST_LENGTH)) {
DEBUG_FUNCTION_LINE("relocations failed\n");
}
if(moduleData->getBSSAddr() != 0) {
DEBUG_FUNCTION_LINE("memset .bss %08X (%d)\n", moduleData->getBSSAddr(), moduleData->getBSSSize());
memset((void*)moduleData->getBSSAddr(), 0, moduleData->getBSSSize());
}
if(moduleData->getSBSSAddr() != 0) {
DEBUG_FUNCTION_LINE("memset .sbss %08X (%d)\n", moduleData->getSBSSAddr(), moduleData->getSBSSSize());
memset((void*)moduleData->getSBSSAddr(), 0, moduleData->getSBSSSize());
}
DCFlushRange((void*)0x00800000, 0x00800000);
ICInvalidateRange((void*)0x00800000, 0x00800000);
DEBUG_FUNCTION_LINE("New entrypoint: %08X\n", moduleData->getEntrypoint());
((int (*)(int, char **))moduleData->getEntrypoint())(argc, argv);
delete moduleData;
} else {
DEBUG_FUNCTION_LINE("Failed to load module\n");
}
} else {
DEBUG_FUNCTION_LINE("Mounted sd card failed %d.\n", res);
}
SYSLaunchMenu();
ProcUIInit(OSSavesDone_ReadyToRelease);
DEBUG_FUNCTION_LINE("In ProcUI loop\n");
while(CheckRunning()) {
// wait.
OSSleepTicks(OSMillisecondsToTicks(100));
}
ProcUIShutdown();
return 0;
}
bool doRelocation(std::vector<RelocationData *> &relocData, relocation_trampolin_entry_t * tramp_data, uint32_t tramp_length) {
for (auto const& curReloc : relocData) {
RelocationData * cur = curReloc;
std::string functionName = cur->getName();
std::string rplName = cur->getImportRPLInformation()->getName();
int32_t isData = cur->getImportRPLInformation()->isData();
OSDynLoad_Module rplHandle = 0;
OSDynLoad_Acquire(rplName.c_str(), &rplHandle);
uint32_t functionAddress = 0;
OSDynLoad_FindExport(rplHandle, isData, functionName.c_str(), (void**) &functionAddress);
if(functionAddress == 0) {
return false;
}
if(!ElfUtils::elfLinkOne(cur->getType(), cur->getOffset(), cur->getAddend(), (uint32_t) cur->getDestination(), functionAddress, tramp_data, tramp_length, RELOC_TYPE_IMPORT)) {
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;
}

16
src/main.h Normal file
View File

@ -0,0 +1,16 @@
//Main.h
#ifndef _MAIN_H_
#define _MAIN_H_
/* Main */
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,104 @@
#include "DynamicLinkingHelper.h"
#include <stdio.h>
#include <string.h>
#include <vector>
#include <coreinit/dynload.h>
#include "utils/logger.h"
#include "common/module_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, 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, void *destination, std::string name, 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, 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 = destination;
curEntry->functionEntry = functionName;
curEntry->importEntry = importInfo;
return true;
}
return false;
}

View File

@ -0,0 +1,60 @@
#pragma once
#include "common/dynamic_linking_defines.h"
#include "utils/logger.h"
#include <string>
#include <vector>
#include "RelocationData.h"
class DynamicLinkingHelper {
public:
/**
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.
**/
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.
This will return entries for _function_ imports.
\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.
**/
static dyn_linking_import_t * getOrAddFunctionImportByName(dyn_linking_relocation_data_t * data, const char * importName);
/**
Gets the data import entry for a given data name. If the import is not present in the list, it will be added.
This will return entries for _data_ imports.
\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.
**/
static dyn_linking_import_t * getOrAddDataImportByName(dyn_linking_relocation_data_t * data, const char * importName);
/**
Gets the import entry for a given data name and type. If the import is not present in the list, it will be added.
This will return entries for _data_ and _function_ imports, depending on the isData parameter.
\param importName Name of the data
\param isData Set this to true to return a data import
\return Returns a pointer to the data import entry which contains the importName. Null on error or if the list full.
**/
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, 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, void *destination, std::string name, ImportRPLInformation * rplInfo);
static bool addReloationEntry(dyn_linking_relocation_entry_t * linking_entries, uint32_t linking_entry_length, char type, size_t offset, int32_t addend, void *destination, dyn_linking_function_t * functionName, dyn_linking_import_t * importInfo);
private:
DynamicLinkingHelper() {
}
~DynamicLinkingHelper() {
}
};

View File

@ -0,0 +1,67 @@
/****************************************************************************
* 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 <string>
#include "utils/logger.h"
class ImportRPLInformation {
public:
ImportRPLInformation(std::string name, bool isData = false) {
this->name = name;
this->_isData = isData;
}
~ImportRPLInformation() {
}
static ImportRPLInformation * createImportRPLInformation(std::string rawSectionName) {
std::string fimport = ".fimport_";
std::string dimport = ".dimport_";
bool data = false;
std::string rplName = "";
if(rawSectionName.size() < fimport.size()) {
return NULL;
} 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());
data = true;
} else {
DEBUG_FUNCTION_LINE("invalid section name\n");
return NULL;
}
return new ImportRPLInformation(rplName, data);
}
std::string getName() {
return name;
}
bool isData() {
return _isData;
}
private:
std::string name;
bool _isData = false;
};

12
src/module/ModuleData.cpp Normal file
View File

@ -0,0 +1,12 @@
#include "ModuleData.h"
#include "utils/StringTools.h"
std::string ModuleData::toString() {
std::string res = StringTools::strfmt("Entrypoint %08X, bss: %08X (%d), bss: %08X (%d)\n", getEntrypoint(), getBSSAddr(), getBSSSize(), getSBSSAddr(), getSBSSSize());
for (auto const& reloc : relocation_data_list) {
if(reloc != NULL) {
res += reloc->toString();
}
}
return res;
}

88
src/module/ModuleData.h Normal file
View File

@ -0,0 +1,88 @@
/****************************************************************************
* 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 <string>
#include <vector>
#include "RelocationData.h"
class ModuleData {
public:
ModuleData() {
}
~ModuleData() {
for (auto const& reloc : relocation_data_list) {
if(reloc != NULL) {
delete reloc;
}
}
}
void setBSSLocation(uint32_t addr, uint32_t size) {
this->bssAddr = addr;
this->bssSize = size;
}
void setSBSSLocation(uint32_t addr, uint32_t size) {
this->sbssAddr = addr;
this->sbssSize = size;
}
void setEntrypoint(uint32_t addr) {
this->entrypoint = addr;
}
void addRelocationData(RelocationData * relocation_data) {
relocation_data_list.push_back(relocation_data);
}
std::vector<RelocationData *> getRelocationDataList() {
return relocation_data_list;
}
uint32_t getBSSAddr() {
return bssAddr;
}
uint32_t getBSSSize() {
return bssSize;
}
uint32_t getSBSSAddr() {
return sbssAddr;
}
uint32_t getSBSSSize() {
return sbssSize;
}
uint32_t getEntrypoint() {
return entrypoint;
}
std::string toString();
private:
std::vector<RelocationData *> relocation_data_list;
uint32_t bssAddr = 0;
uint32_t bssSize = 0;
uint32_t sbssAddr = 0;
uint32_t sbssSize = 0;
uint32_t entrypoint = 0;
};

View File

@ -0,0 +1,247 @@
/****************************************************************************
* 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 "ModuleDataFactory.h"
#include "elfio/elfio.hpp"
#include "utils/utils.h"
#include "../ElfUtils.h"
using namespace ELFIO;
ModuleData * ModuleDataFactory::load(std::string path, uint32_t destination_address, uint32_t maximum_size, relocation_trampolin_entry_t * trampolin_data, uint32_t trampolin_data_length) {
elfio reader;
ModuleData * moduleData = new ModuleData();
if(moduleData == NULL) {
return NULL;
}
// Load ELF data
if (!reader.load(path)) {
DEBUG_FUNCTION_LINE("Can't find or process ELF file\n");
delete moduleData;
return NULL;
}
uint32_t sec_num = reader.sections.size();
uint8_t **destinations = (uint8_t **) malloc(sizeof(uint8_t *) * sec_num);
uint32_t baseOffset = destination_address;
uint32_t offset_text = baseOffset;
uint32_t offset_data = offset_text;
uint32_t entrypoint = offset_text + (uint32_t) reader.get_entry() - 0x02000000;
uint32_t totalSize = 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();
destinations[psec->get_index()] = (uint8_t *) baseOffset;
uint32_t destination = baseOffset + address;
if((address >= 0x02000000) && address < 0x10000000) {
destination -= 0x02000000;
destinations[psec->get_index()] -= 0x02000000;
baseOffset += sectionSize;
offset_data += sectionSize;
} else if((address >= 0x10000000) && address < 0xC0000000) {
destination -= 0x10000000;
destinations[psec->get_index()] -= 0x10000000;
} else if(address >= 0xC0000000) {
destination -= 0xC0000000;
destinations[psec->get_index()] -= 0xC0000000;
} else {
DEBUG_FUNCTION_LINE("Unhandled case\n");
free(destinations);
delete moduleData;
return NULL;
}
const char* p = reader.sections[i]->get_data();
if(psec->get_type() == SHT_NOBITS) {
DEBUG_FUNCTION_LINE("memset section %s %08X to 0 (%d bytes)\n", 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)\n", psec->get_name().c_str(), p, destination, sectionSize);
memcpy((void*) destination, p, sectionSize);
}
//nextAddress = ROUNDUP(destination + sectionSize,0x100);
if(psec->get_name().compare(".bss") == 0) {
moduleData->setBSSLocation(destination, sectionSize);
DEBUG_FUNCTION_LINE("Saved %s section info. Location: %08X size: %08X\n", psec->get_name().c_str(), destination, sectionSize);
} else if(psec->get_name().compare(".sbss") == 0) {
moduleData->setSBSSLocation(destination, sectionSize);
DEBUG_FUNCTION_LINE("Saved %s section info. Location: %08X size: %08X\n", 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\n",i,psec->get_name().c_str());
if (!linkSection(reader, psec->get_index(), (uint32_t) destinations[psec->get_index()], offset_text, offset_data, trampolin_data, trampolin_data_length)) {
DEBUG_FUNCTION_LINE("elfLink failed\n");
free(destinations);
delete moduleData;
return NULL;
}
}
}
std::vector<RelocationData*> relocationData = getImportRelocationData(reader, destinations);
for (auto const& reloc : relocationData) {
moduleData->addRelocationData(reloc);
}
DCFlushRange((void*)destination_address, totalSize);
ICInvalidateRange((void*)destination_address, totalSize);
free(destinations);
moduleData->setEntrypoint(entrypoint);
DEBUG_FUNCTION_LINE("Saved entrypoint as %08X\n", entrypoint);
return moduleData;
}
std::vector<RelocationData*> ModuleDataFactory::getImportRelocationData(elfio& reader, uint8_t ** destinations) {
std::vector<RelocationData*> result;
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\n",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\n");
break;
}
uint32_t adjusted_sym_value = (uint32_t) sym_value;
if(adjusted_sym_value < 0xC0000000) {
continue;
}
ImportRPLInformation * rplInfo = ImportRPLInformation::createImportRPLInformation(infoMap[sym_section_index]);
if(rplInfo == NULL) {
DEBUG_FUNCTION_LINE("Failed to create import information\n");
break;
}
uint32_t section_index = psec->get_info();
// When these relocations are performed, we don't need the 0xC0000000 offset anymore.
RelocationData * relocationData = new RelocationData(type, offset - 0x02000000, addend, (void*)(destinations[section_index] + 0x02000000), sym_name, rplInfo);
//relocationData->printInformation();
result.push_back(relocationData);
}
}
}
return result;
}
bool ModuleDataFactory::linkSection(elfio& reader, 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) {
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\n",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\n");
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) {
// Skip imports
continue;
} else if(adjusted_sym_value == 0x0) {
//
} else {
DEBUG_FUNCTION_LINE("Unhandled case %08X\n",adjusted_sym_value);
return false;
}
if(sym_section_index == SHN_ABS) {
//
} else if(sym_section_index > SHN_LORESERVE) {
DEBUG_FUNCTION_LINE("NOT IMPLEMENTED: %04X\n", sym_section_index);
return false;
}
if(!ElfUtils::elfLinkOne(type, offset, addend, destination, adjusted_sym_value, trampolin_data, trampolin_data_length, RELOC_TYPE_FIXED)) {
DEBUG_FUNCTION_LINE("Link failed\n");
return false;
}
}
}
}
return true;
}

View File

@ -0,0 +1,32 @@
/****************************************************************************
* 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 <string>
#include <vector>
#include <map>
#include "common/relocation_defines.h"
#include "ModuleData.h"
#include "elfio/elfio.hpp"
class ModuleDataFactory {
public:
static ModuleData * load(std::string path, uint32_t destination_address, uint32_t maximum_size, relocation_trampolin_entry_t * trampolin_data, uint32_t trampolin_data_length);
static bool linkSection(ELFIO::elfio& reader, 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);
static std::vector<RelocationData*> getImportRelocationData(ELFIO::elfio& reader, uint8_t ** destinations);
};

View File

@ -0,0 +1,106 @@
#include <coreinit/cache.h>
#include "ModuleDataPersistence.h"
#include "DynamicLinkingHelper.h"
#include "common/module_defines.h"
#include "ModuleData.h"
#include "RelocationData.h"
bool ModuleDataPersistence::saveModuleData(module_information_t * moduleInformation, ModuleData * module) {
int32_t module_count = moduleInformation->number_used_modules;
if(module_count >= MAXIMUM_MODULES) {
return false;
}
// Copy data to global struct.
module_information_single_t * module_data = &(moduleInformation->module_data[module_count]);
// Relocation
std::vector<RelocationData *> relocationData = module->getRelocationDataList();
for (auto const& reloc : relocationData) {
if(!DynamicLinkingHelper::addReloationEntry(&(moduleInformation->linking_data), module_data->linking_entries, DYN_LINK_RELOCATION_LIST_LENGTH, reloc)) {
return false;
}
}
module_data->bssAddr = module->getBSSAddr();
module_data->bssSize = module->getBSSSize();
module_data->sbssAddr = module->getSBSSAddr();
module_data->sbssSize = module->getSBSSSize();
module_data->entrypoint = module->getEntrypoint();
moduleInformation->number_used_modules++;
DCFlushRange((void*)moduleInformation,sizeof(module_information_t));
ICInvalidateRange((void*)moduleInformation,sizeof(module_information_t));
return true;
}
std::vector<ModuleData*> ModuleDataPersistence::loadModuleData(module_information_t * moduleInformation) {
std::vector<ModuleData*> result;
if(moduleInformation == NULL) {
DEBUG_FUNCTION_LINE("moduleInformation == NULL\n");
return result;
}
DCFlushRange((void*)moduleInformation,sizeof(module_information_t));
ICInvalidateRange((void*)moduleInformation,sizeof(module_information_t));
int32_t module_count = moduleInformation->number_used_modules;
if(module_count > MAXIMUM_MODULES) {
DEBUG_FUNCTION_LINE("moduleInformation->module_count was bigger then allowed. %d > %d. Limiting to %d\n",module_count, MAXIMUM_MODULES, MAXIMUM_MODULES);
module_count = MAXIMUM_MODULES;
}
for(int32_t i = 0; i < module_count; i++) {
// Copy data from struct.
module_information_single_t * module_data = &(moduleInformation->module_data[i]);
ModuleData * moduleData = new ModuleData();
if(moduleData == NULL){
DEBUG_FUNCTION_LINE("Failed to allocate data for ModuleData object\n");
continue;
}
moduleData->setBSSLocation(module_data->bssAddr, module_data->bssSize);
moduleData->setSBSSLocation(module_data->sbssAddr, module_data->sbssSize);
moduleData->setEntrypoint(module_data->entrypoint);
for(uint32_t j = 0; j < DYN_LINK_RELOCATION_LIST_LENGTH; j++) {
dyn_linking_relocation_entry_t * linking_entry = &(module_data->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\n");
continue;
}
if(importEntry->importName == NULL){
DEBUG_FUNCTION_LINE("importEntry->importName was NULL, skipping relocation entry\n");
continue;
}
dyn_linking_function_t* functionEntry = linking_entry->functionEntry;
if(functionEntry == NULL){
DEBUG_FUNCTION_LINE("functionEntry was NULL, skipping relocation entry\n");
continue;
}
if(functionEntry->functionName == NULL){
DEBUG_FUNCTION_LINE("functionEntry->functionName was NULL, skipping relocation entry\n");
continue;
}
ImportRPLInformation * rplInfo = new ImportRPLInformation(importEntry->importName, importEntry->isData);
if(rplInfo == NULL){
DEBUG_FUNCTION_LINE("Failed to allocate ImportRPLInformation object. Skipping relocation entry.\n");
continue;
}
RelocationData * reloc = new RelocationData(linking_entry->type, linking_entry->offset, linking_entry->addend, linking_entry->destination, functionEntry->functionName, rplInfo);
if(reloc == NULL){
DEBUG_FUNCTION_LINE("Failed to allocate RelocationData object. Skipping relocation entry.\n");
continue;
}
moduleData->addRelocationData(reloc);
}
result.push_back(moduleData);
}
return result;
}

View File

@ -0,0 +1,10 @@
#pragma once
#include "common/module_defines.h"
#include "ModuleData.h"
class ModuleDataPersistence {
public:
static bool saveModuleData(module_information_t * moduleInformation, ModuleData * module);
static std::vector<ModuleData*> loadModuleData(module_information_t * moduleInformation);
};

View File

@ -0,0 +1,6 @@
#include "RelocationData.h"
#include "utils/StringTools.h"
std::string RelocationData::toString(){
return StringTools::strfmt("%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() );
}

View File

@ -0,0 +1,73 @@
/****************************************************************************
* 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 <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() {
if(rplInfo != NULL) {
delete rplInfo;
}
}
char getType() {
return type;
}
size_t getOffset() {
return offset;
}
int32_t getAddend() {
return addend;
}
void * getDestination() {
return destination;
}
std::string getName() {
return name;
}
ImportRPLInformation * getImportRPLInformation() {
return rplInfo;
}
std::string toString();
private:
char type;
size_t offset;
int32_t addend;
void *destination;
std::string name;
ImportRPLInformation * rplInfo;
};

60
src/utils/FSOSUtils.cpp Normal file
View File

@ -0,0 +1,60 @@
#include <malloc.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <coreinit/filesystem.h>
#include "utils/logger.h"
#include "FSOSUtils.h"
#define FS_MOUNT_SOURCE_SIZE 0x300
#define FS_MAX_MOUNTPATH_SIZE 128
#define FS_SOURCETYPE_EXTERNAL 0
int32_t FSOSUtils::MountFS(FSClient *pClient, FSCmdBlock *pCmd, char **mount_path) {
int32_t result = -1;
DEBUG_FUNCTION_LINE("\n");
FSMountSource *mountSrc = (FSMountSource*) malloc(sizeof(FSMountSource));
if(!mountSrc) {
return -3;
}
DEBUG_FUNCTION_LINE("\n");
char* mountPath = (char*) malloc(FS_MAX_MOUNTPATH_SIZE);
if(!mountPath) {
free(mountSrc);
mountSrc = NULL;
return -4;
}
DEBUG_FUNCTION_LINE("\n");
memset(mountSrc, 0, FS_MOUNT_SOURCE_SIZE);
memset(mountPath, 0, FS_MAX_MOUNTPATH_SIZE);
// Mount sdcard
if (FSGetMountSource(pClient, pCmd, FS_MOUNT_SOURCE_SD, mountSrc, -1) == 0) {
DEBUG_FUNCTION_LINE("\n");
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");
free(mountPath);
free(mountSrc);
mountPath = NULL;
mountSrc = NULL;
return result;
}
int32_t FSOSUtils::UmountFS(FSClient *pClient, FSCmdBlock *pCmd, const char *mountPath) {
int32_t result = -1;
result = FSUnmount(pClient, pCmd, mountPath, -1);
return result;
}

13
src/utils/FSOSUtils.h Normal file
View File

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

290
src/utils/StringTools.cpp Normal file
View File

@ -0,0 +1,290 @@
/***************************************************************************
* 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
***************************************************************************/
#include <vector>
#include <string>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <wchar.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;
return std::equal(a.begin() + a.size() - b.size(), a.end(), b.begin());
}
const char * StringTools::byte_to_binary(int32_t x) {
static char b[9];
b[0] = '\0';
int32_t z;
for (z = 128; z > 0; z >>= 1) {
strcat(b, ((x & z) == z) ? "1" : "0");
}
return b;
}
std::string StringTools::removeCharFromString(std::string& input,char toBeRemoved) {
std::string output = input;
size_t position;
while(1) {
position = output.find(toBeRemoved);
if(position == std::string::npos)
break;
output.erase(position, 1);
}
return output;
}
const char * StringTools::fmt(const char * format, ...) {
static char strChar[512];
strChar[0] = 0;
va_list va;
va_start(va, format);
if((vsprintf(strChar, format, va) >= 0)) {
va_end(va);
return (const char *) strChar;
}
va_end(va);
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;
if(strcmp(format, "") == 0)
return (const wchar_t *) strWChar;
va_list va;
va_start(va, format);
if((vsprintf(tmp, format, va) >= 0)) {
int bt;
int32_t strlength = strlen(tmp);
bt = mbstowcs(strWChar, tmp, (strlength < 512) ? strlength : 512 );
if(bt > 0) {
strWChar[bt] = 0;
return (const wchar_t *) strWChar;
}
}
va_end(va);
return NULL;
}
int32_t StringTools::strprintf(std::string &str, const char * format, ...) {
static char tmp[512];
tmp[0] = 0;
int32_t result = 0;
va_list va;
va_start(va, format);
if((vsprintf(tmp, format, va) >= 0)) {
str = tmp;
result = str.size();
}
va_end(va);
return result;
}
std::string StringTools::strfmt(const char * format, ...) {
std::string str;
static char tmp[512];
tmp[0] = 0;
va_list va;
va_start(va, format);
if((vsprintf(tmp, format, va) >= 0)) {
str = tmp;
}
va_end(va);
return str;
}
BOOL StringTools::char2wchar_t(const char * strChar, wchar_t * dest) {
if(!strChar || !dest)
return false;
int bt;
bt = mbstowcs(dest, strChar, strlen(strChar));
if (bt > 0) {
dest[bt] = 0;
return true;
}
return false;
}
int32_t StringTools::strtokcmp(const char * string, const char * compare, const char * separator) {
if(!string || !compare)
return -1;
char TokCopy[512];
strncpy(TokCopy, compare, sizeof(TokCopy));
TokCopy[511] = '\0';
char * strTok = strtok(TokCopy, separator);
while (strTok != NULL) {
if (strcasecmp(string, strTok) == 0) {
return 0;
}
strTok = strtok(NULL,separator);
}
return -1;
}
int32_t StringTools::strextcmp(const char * string, const char * extension, char seperator) {
if(!string || !extension)
return -1;
char *ptr = strrchr(string, seperator);
if(!ptr)
return -1;
return strcasecmp(ptr + 1, extension);
}
std::vector<std::string> StringTools::stringSplit(const std::string & inValue, const std::string & splitter) {
std::string value = inValue;
std::vector<std::string> result;
while (true) {
uint32_t index = value.find(splitter);
if (index == std::string::npos) {
result.push_back(value);
break;
}
std::string first = value.substr(0, index);
result.push_back(first);
if (index + splitter.size() == value.length()) {
result.push_back("");
break;
}
if(index + splitter.size() > value.length()) {
break;
}
value = value.substr(index + splitter.size(), value.length());
}
return result;
}
const char * StringTools::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;
}
void StringTools::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--;
}
}
}
// You must free the result if result is non-NULL.
char * StringTools::str_replace(char *orig, char *rep, char *with) {
char *result; // the return string
char *ins; // the next insert point
char *tmp; // varies
int len_rep; // length of rep (the string to remove)
int len_with; // length of with (the string to replace rep with)
int len_front; // distance between rep and end of last rep
int count; // number of replacements
// sanity checks and initialization
if (!orig || !rep)
return NULL;
len_rep = strlen(rep);
if (len_rep == 0)
return NULL; // empty rep causes infinite loop during count
if (!with)
with = "";
len_with = strlen(with);
// count the number of replacements needed
ins = orig;
for (count = 0; tmp = strstr(ins, rep); ++count) {
ins = tmp + len_rep;
}
tmp = result = (char*)malloc(strlen(orig) + (len_with - len_rep) * count + 1);
if (!result)
return NULL;
// first time through the loop, all the variable are set correctly
// from here on,
// tmp points to the end of the result string
// ins points to the next occurrence of rep in orig
// orig points to the remainder of orig after "end of rep"
while (count--) {
ins = strstr(orig, rep);
len_front = ins - orig;
tmp = strncpy(tmp, orig, len_front) + len_front;
tmp = strcpy(tmp, with) + len_with;
orig += len_front + len_rep; // move to next "end of rep"
}
strcpy(tmp, orig);
return result;
}

52
src/utils/StringTools.h Normal file
View File

@ -0,0 +1,52 @@
/***************************************************************************
* 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 char *str_replace(char *orig, char *rep, char *with);
static const char * FullpathToFilename(const char *path);
static void RemoveDoubleSlashs(std::string &str);
static std::vector<std::string> stringSplit(const std::string & value, const std::string & splitter);
};
#endif /* __STRING_TOOLS_H */

82
src/utils/logger.c Normal file
View File

@ -0,0 +1,82 @@
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.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_() {
int broadcastEnable = 1;
log_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (log_socket < 0)
return;
setsockopt(log_socket, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable));
memset(&connect_addr, 0, sizeof(struct sockaddr_in));
connect_addr.sin_family = AF_INET;
connect_addr.sin_port = 4405;
connect_addr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
}
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)
OSSleepTicks(OSMicrosecondsToTicks(1000));
log_lock = 1;
int len = strlen(str);
int ret;
while (len > 0) {
int block = len < 1400 ? len : 1400; // take max 1400 bytes per UDP packet
ret = sendto(log_socket, str, block, 0, (struct sockaddr *)&connect_addr, sizeof(struct sockaddr_in));
if(ret < 0)
break;
len -= ret;
str += ret;
}
log_lock = 0;
}
void OSFatal_printf(const char *format, ...) {
char tmp[512];
tmp[0] = 0;
va_list va;
va_start(va, format);
if((vsprintf(tmp, format, va) >= 0)) {
OSFatal(tmp);
}
va_end(va);
}
void log_printf_(const char *format, ...) {
if(log_socket < 0) {
return;
}
char tmp[512];
tmp[0] = 0;
va_list va;
va_start(va, format);
if((vsprintf(tmp, format, va) >= 0)) {
log_print_(tmp);
}
va_end(va);
}

38
src/utils/logger.h Normal file
View File

@ -0,0 +1,38 @@
#ifndef __LOGGER_H_
#define __LOGGER_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <string.h>
void log_init_();
//void log_deinit_(void);
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__)
#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILENAME_X__)
#define OSFATAL_FUNCTION_LINE(FMT, ARGS...)do { \
OSFatal_printf("[%s]%s@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 "",__FILENAME__,__FUNCTION__, __LINE__, ## ARGS); \
} while (0)
#ifdef __cplusplus
}
#endif
#endif

107
src/utils/memory.c Normal file
View File

@ -0,0 +1,107 @@
/****************************************************************************
* Copyright (C) 2015 Dimok
*
* 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 <coreinit/memexpheap.h>
#include <coreinit/memdefaultheap.h>
#include <coreinit/memorymap.h>
#include <malloc.h>
#include <string.h>
#include <errno.h>
extern uint32_t * pMEMAllocFromDefaultHeapEx;
extern uint32_t * pMEMAllocFromDefaultHeap;
extern uint32_t * pMEMFreeToDefaultHeap;
//!-------------------------------------------------------------------------------------------
//! reent versions
//!-------------------------------------------------------------------------------------------
void *_malloc_r(struct _reent *r, size_t size) {
void *ptr = ((void * (*)(size_t))(*pMEMAllocFromDefaultHeap))(size);
if (!ptr) {
r->_errno = ENOMEM;
}
return ptr;
}
void *_calloc_r(struct _reent *r, size_t num, size_t size) {
void *ptr = ((void * (*)(size_t))(*pMEMAllocFromDefaultHeap))(size);
if (ptr) {
memset(ptr, 0, num * size);
} else {
r->_errno = ENOMEM;
}
return ptr;
}
void *_memalign_r(struct _reent *r, size_t align, size_t size) {
return ((void * (*)(size_t, size_t))(*pMEMAllocFromDefaultHeapEx))(size, align);
}
void _free_r(struct _reent *r, void *ptr) {
if (ptr) {
((void (*)(void *))(*pMEMFreeToDefaultHeap))(ptr);
}
}
void *_realloc_r(struct _reent *r, void *p, size_t size) {
void *new_ptr = ((void * (*)(size_t))(*pMEMAllocFromDefaultHeap))(size);
if (!new_ptr) {
r->_errno = ENOMEM;
return new_ptr;
}
if (p) {
size_t old_size = MEMGetSizeForMBlockExpHeap(p);
memcpy(new_ptr, p, old_size <= size ? old_size : size);
((void (*)(void *))(*pMEMFreeToDefaultHeap))(p);
}
return new_ptr;
}
struct mallinfo _mallinfo_r(struct _reent *r) {
struct mallinfo info = { 0 };
return info;
}
void
_malloc_stats_r(struct _reent *r) {
}
int
_mallopt_r(struct _reent *r, int param, int value) {
return 0;
}
size_t
_malloc_usable_size_r(struct _reent *r, void *ptr) {
return MEMGetSizeForMBlockExpHeap(ptr);
}
void *
_valloc_r(struct _reent *r, size_t size) {
return ((void * (*)(size_t, size_t))(*pMEMAllocFromDefaultHeapEx))(size, OS_PAGE_SIZE);
}
void *
_pvalloc_r(struct _reent *r, size_t size) {
return ((void * (*)(size_t, size_t))(*pMEMAllocFromDefaultHeapEx))((size + (OS_PAGE_SIZE - 1)) & ~(OS_PAGE_SIZE - 1), OS_PAGE_SIZE);
}
int
_malloc_trim_r(struct _reent *r, size_t pad) {
return 0;
}

42
src/utils/memory.h Normal file
View File

@ -0,0 +1,42 @@
/****************************************************************************
* Copyright (C) 2015 Dimok
*
* 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/>.
****************************************************************************/
#ifndef __MEMORY_H_
#define __MEMORY_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <malloc.h>
void memoryInitialize(void);
void memoryRelease(void);
void * MEM2_alloc(u32 size, u32 align);
void MEM2_free(void *ptr);
void * MEM1_alloc(u32 size, u32 align);
void MEM1_free(void *ptr);
void * MEMBucket_alloc(u32 size, u32 align);
void MEMBucket_free(void *ptr);
#ifdef __cplusplus
}
#endif
#endif // __MEMORY_H_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,40 @@
/***************************************************************************
* 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_

41
src/utils/utils.c Normal file
View File

@ -0,0 +1,41 @@
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <malloc.h>
#include "utils/logger.h"
// https://gist.github.com/ccbrown/9722406
void dumpHex(const void* data, size_t size) {
char ascii[17];
size_t i, j;
ascii[16] = '\0';
DEBUG_FUNCTION_LINE("0x%08X (0x0000): ", data);
for (i = 0; i < size; ++i) {
log_printf("%02X ", ((unsigned char*)data)[i]);
if (((unsigned char*)data)[i] >= ' ' && ((unsigned char*)data)[i] <= '~') {
ascii[i % 16] = ((unsigned char*)data)[i];
} else {
ascii[i % 16] = '.';
}
if ((i+1) % 8 == 0 || i+1 == size) {
log_print(" ");
if ((i+1) % 16 == 0) {
log_printf("| %s \n", ascii);
if(i + 1 < size) {
DEBUG_FUNCTION_LINE("0x%08X (0x%04X); ", data + i + 1,i+1);
}
} else if (i+1 == size) {
ascii[(i+1) % 16] = '\0';
if ((i+1) % 16 <= 8) {
log_print(" ");
}
for (j = (i+1) % 16; j < 16; ++j) {
log_print(" ");
}
log_printf("| %s \n", ascii);
}
}
}
}

35
src/utils/utils.h Normal file
View File

@ -0,0 +1,35 @@
#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)
#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_