mirror of
https://github.com/wiiu-env/CustomRPXLoader.git
synced 2024-11-27 20:24:15 +01:00
first commit
This commit is contained in:
commit
7ed1cee873
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
/*.elf
|
||||||
|
/*.cbp
|
||||||
|
/build
|
||||||
|
*.rpx
|
||||||
|
*.bin
|
||||||
|
*.cscope_file_list
|
||||||
|
*.layout
|
339
LICENSE
Normal file
339
LICENSE
Normal 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
216
Makefile
Normal 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
16
README.md
Normal 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
158
src/ElfUtils.cpp
Normal 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
50
src/ElfUtils.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "common/relocation_defines.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int32_t LoadFileToMem(const char *relativefilepath, char **fileOut, uint32_t * sizeOut);
|
||||||
|
uint32_t load_loader_elf_from_sd(unsigned char* baseAddress, const char* relativePath);
|
||||||
|
uint32_t load_loader_elf(unsigned char* baseAddress, char * elf_data, uint32_t fileSize);
|
||||||
|
|
||||||
|
#define R_PPC_NONE 0
|
||||||
|
#define R_PPC_ADDR32 1
|
||||||
|
#define R_PPC_ADDR16_LO 4
|
||||||
|
#define R_PPC_ADDR16_HI 5
|
||||||
|
#define R_PPC_ADDR16_HA 6
|
||||||
|
#define R_PPC_REL24 10
|
||||||
|
#define R_PPC_REL14 11
|
||||||
|
#define R_PPC_DTPMOD32 68
|
||||||
|
#define R_PPC_DTPREL32 78
|
||||||
|
#define R_PPC_EMB_SDA21 109
|
||||||
|
#define R_PPC_EMB_RELSDA 116
|
||||||
|
#define R_PPC_DIAB_SDA21_LO 180
|
||||||
|
#define R_PPC_DIAB_SDA21_HI 181
|
||||||
|
#define R_PPC_DIAB_SDA21_HA 182
|
||||||
|
#define R_PPC_DIAB_RELSDA_LO 183
|
||||||
|
#define R_PPC_DIAB_RELSDA_HI 184
|
||||||
|
#define R_PPC_DIAB_RELSDA_HA 185
|
||||||
|
#define R_PPC_GHS_REL16_HA 251
|
||||||
|
#define R_PPC_GHS_REL16_HI 252
|
||||||
|
#define R_PPC_GHS_REL16_LO 253
|
||||||
|
|
||||||
|
// Masks for manipulating Power PC relocation targets
|
||||||
|
#define PPC_WORD32 0xFFFFFFFF
|
||||||
|
#define PPC_WORD30 0xFFFFFFFC
|
||||||
|
#define PPC_LOW24 0x03FFFFFC
|
||||||
|
#define PPC_LOW14 0x0020FFFC
|
||||||
|
#define PPC_HALF16 0xFFFF
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class ElfUtils {
|
||||||
|
|
||||||
|
public:
|
||||||
|
static bool elfLinkOne(char type, size_t offset, int32_t addend, uint32_t destination, uint32_t symbol_addr, relocation_trampolin_entry_t * trampolin_data, uint32_t trampolin_data_length, RelocationType reloc_type);
|
||||||
|
};
|
61
src/common/dynamic_linking_defines.h
Normal file
61
src/common/dynamic_linking_defines.h
Normal 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
|
56
src/common/module_defines.h
Normal file
56
src/common/module_defines.h
Normal 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
|
19
src/common/relocation_defines.h
Normal file
19
src/common/relocation_defines.h
Normal 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
37
src/dynamic.c
Normal 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
11
src/dynamic.h
Normal 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
851
src/elfio/elf_types.hpp
Normal file
@ -0,0 +1,851 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2001-2015 by Serge Lamikhov-Center
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ELFTYPES_H
|
||||||
|
#define ELFTYPES_H
|
||||||
|
|
||||||
|
#ifndef ELFIO_NO_OWN_TYPES
|
||||||
|
#if !defined(ELFIO_NO_CSTDINT) && !defined(ELFIO_NO_INTTYPES)
|
||||||
|
#include <stdint.h>
|
||||||
|
#else
|
||||||
|
typedef unsigned char uint8_t;
|
||||||
|
typedef signed char int8_t;
|
||||||
|
typedef unsigned short uint16_t;
|
||||||
|
typedef signed short int16_t;
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
typedef unsigned __int32 uint32_t;
|
||||||
|
typedef signed __int32 int32_t;
|
||||||
|
typedef unsigned __int64 uint64_t;
|
||||||
|
typedef signed __int64 int64_t;
|
||||||
|
#else
|
||||||
|
typedef unsigned int uint32_t;
|
||||||
|
typedef signed int int32_t;
|
||||||
|
typedef unsigned long long uint64_t;
|
||||||
|
typedef signed long long int64_t;
|
||||||
|
#endif // _MSC_VER
|
||||||
|
#endif // ELFIO_NO_CSTDINT
|
||||||
|
#endif // ELFIO_NO_OWN_TYPES
|
||||||
|
|
||||||
|
namespace ELFIO {
|
||||||
|
|
||||||
|
// Attention! Platform depended definitions.
|
||||||
|
typedef uint16_t Elf_Half;
|
||||||
|
typedef uint32_t Elf_Word;
|
||||||
|
typedef int32_t Elf_Sword;
|
||||||
|
typedef uint64_t Elf_Xword;
|
||||||
|
typedef int64_t Elf_Sxword;
|
||||||
|
|
||||||
|
typedef uint32_t Elf32_Addr;
|
||||||
|
typedef uint32_t Elf32_Off;
|
||||||
|
typedef uint64_t Elf64_Addr;
|
||||||
|
typedef uint64_t Elf64_Off;
|
||||||
|
|
||||||
|
#define Elf32_Half Elf_Half
|
||||||
|
#define Elf64_Half Elf_Half
|
||||||
|
#define Elf32_Word Elf_Word
|
||||||
|
#define Elf64_Word Elf_Word
|
||||||
|
#define Elf32_Sword Elf_Sword
|
||||||
|
#define Elf64_Sword Elf_Sword
|
||||||
|
|
||||||
|
///////////////////////
|
||||||
|
// ELF Header Constants
|
||||||
|
|
||||||
|
// File type
|
||||||
|
#define ET_NONE 0
|
||||||
|
#define ET_REL 1
|
||||||
|
#define ET_EXEC 2
|
||||||
|
#define ET_DYN 3
|
||||||
|
#define ET_CORE 4
|
||||||
|
#define ET_LOOS 0xFE00
|
||||||
|
#define ET_HIOS 0xFEFF
|
||||||
|
#define ET_LOPROC 0xFF00
|
||||||
|
#define ET_HIPROC 0xFFFF
|
||||||
|
|
||||||
|
|
||||||
|
#define EM_NONE 0 // No machine
|
||||||
|
#define EM_M32 1 // AT&T WE 32100
|
||||||
|
#define EM_SPARC 2 // SUN SPARC
|
||||||
|
#define EM_386 3 // Intel 80386
|
||||||
|
#define EM_68K 4 // Motorola m68k family
|
||||||
|
#define EM_88K 5 // Motorola m88k family
|
||||||
|
#define EM_486 6 // Intel 80486// Reserved for future use
|
||||||
|
#define EM_860 7 // Intel 80860
|
||||||
|
#define EM_MIPS 8 // MIPS R3000 (officially, big-endian only)
|
||||||
|
#define EM_S370 9 // IBM System/370
|
||||||
|
#define EM_MIPS_RS3_LE 10 // MIPS R3000 little-endian (Oct 4 1999 Draft) Deprecated
|
||||||
|
#define EM_res011 11 // Reserved
|
||||||
|
#define EM_res012 12 // Reserved
|
||||||
|
#define EM_res013 13 // Reserved
|
||||||
|
#define EM_res014 14 // Reserved
|
||||||
|
#define EM_PARISC 15 // HPPA
|
||||||
|
#define EM_res016 16 // Reserved
|
||||||
|
#define EM_VPP550 17 // Fujitsu VPP500
|
||||||
|
#define EM_SPARC32PLUS 18 // Sun's "v8plus"
|
||||||
|
#define EM_960 19 // Intel 80960
|
||||||
|
#define EM_PPC 20 // PowerPC
|
||||||
|
#define EM_PPC64 21 // 64-bit PowerPC
|
||||||
|
#define EM_S390 22 // IBM S/390
|
||||||
|
#define EM_SPU 23 // Sony/Toshiba/IBM SPU
|
||||||
|
#define EM_res024 24 // Reserved
|
||||||
|
#define EM_res025 25 // Reserved
|
||||||
|
#define EM_res026 26 // Reserved
|
||||||
|
#define EM_res027 27 // Reserved
|
||||||
|
#define EM_res028 28 // Reserved
|
||||||
|
#define EM_res029 29 // Reserved
|
||||||
|
#define EM_res030 30 // Reserved
|
||||||
|
#define EM_res031 31 // Reserved
|
||||||
|
#define EM_res032 32 // Reserved
|
||||||
|
#define EM_res033 33 // Reserved
|
||||||
|
#define EM_res034 34 // Reserved
|
||||||
|
#define EM_res035 35 // Reserved
|
||||||
|
#define EM_V800 36 // NEC V800 series
|
||||||
|
#define EM_FR20 37 // Fujitsu FR20
|
||||||
|
#define EM_RH32 38 // TRW RH32
|
||||||
|
#define EM_MCORE 39 // Motorola M*Core // May also be taken by Fujitsu MMA
|
||||||
|
#define EM_RCE 39 // Old name for MCore
|
||||||
|
#define EM_ARM 40 // ARM
|
||||||
|
#define EM_OLD_ALPHA 41 // Digital Alpha
|
||||||
|
#define EM_SH 42 // Renesas (formerly Hitachi) / SuperH SH
|
||||||
|
#define EM_SPARCV9 43 // SPARC v9 64-bit
|
||||||
|
#define EM_TRICORE 44 // Siemens Tricore embedded processor
|
||||||
|
#define EM_ARC 45 // ARC Cores
|
||||||
|
#define EM_H8_300 46 // Renesas (formerly Hitachi) H8/300
|
||||||
|
#define EM_H8_300H 47 // Renesas (formerly Hitachi) H8/300H
|
||||||
|
#define EM_H8S 48 // Renesas (formerly Hitachi) H8S
|
||||||
|
#define EM_H8_500 49 // Renesas (formerly Hitachi) H8/500
|
||||||
|
#define EM_IA_64 50 // Intel IA-64 Processor
|
||||||
|
#define EM_MIPS_X 51 // Stanford MIPS-X
|
||||||
|
#define EM_COLDFIRE 52 // Motorola Coldfire
|
||||||
|
#define EM_68HC12 53 // Motorola M68HC12
|
||||||
|
#define EM_MMA 54 // Fujitsu Multimedia Accelerator
|
||||||
|
#define EM_PCP 55 // Siemens PCP
|
||||||
|
#define EM_NCPU 56 // Sony nCPU embedded RISC processor
|
||||||
|
#define EM_NDR1 57 // Denso NDR1 microprocesspr
|
||||||
|
#define EM_STARCORE 58 // Motorola Star*Core processor
|
||||||
|
#define EM_ME16 59 // Toyota ME16 processor
|
||||||
|
#define EM_ST100 60 // STMicroelectronics ST100 processor
|
||||||
|
#define EM_TINYJ 61 // Advanced Logic Corp. TinyJ embedded processor
|
||||||
|
#define EM_X86_64 62 // Advanced Micro Devices X86-64 processor
|
||||||
|
#define EM_PDSP 63 // Sony DSP Processor
|
||||||
|
#define EM_PDP10 64 // Digital Equipment Corp. PDP-10
|
||||||
|
#define EM_PDP11 65 // Digital Equipment Corp. PDP-11
|
||||||
|
#define EM_FX66 66 // Siemens FX66 microcontroller
|
||||||
|
#define EM_ST9PLUS 67 // STMicroelectronics ST9+ 8/16 bit microcontroller
|
||||||
|
#define EM_ST7 68 // STMicroelectronics ST7 8-bit microcontroller
|
||||||
|
#define EM_68HC16 69 // Motorola MC68HC16 Microcontroller
|
||||||
|
#define EM_68HC11 70 // Motorola MC68HC11 Microcontroller
|
||||||
|
#define EM_68HC08 71 // Motorola MC68HC08 Microcontroller
|
||||||
|
#define EM_68HC05 72 // Motorola MC68HC05 Microcontroller
|
||||||
|
#define EM_SVX 73 // Silicon Graphics SVx
|
||||||
|
#define EM_ST19 74 // STMicroelectronics ST19 8-bit cpu
|
||||||
|
#define EM_VAX 75 // Digital VAX
|
||||||
|
#define EM_CRIS 76 // Axis Communications 32-bit embedded processor
|
||||||
|
#define EM_JAVELIN 77 // Infineon Technologies 32-bit embedded cpu
|
||||||
|
#define EM_FIREPATH 78 // Element 14 64-bit DSP processor
|
||||||
|
#define EM_ZSP 79 // LSI Logic's 16-bit DSP processor
|
||||||
|
#define EM_MMIX 80 // Donald Knuth's educational 64-bit processor
|
||||||
|
#define EM_HUANY 81 // Harvard's machine-independent format
|
||||||
|
#define EM_PRISM 82 // SiTera Prism
|
||||||
|
#define EM_AVR 83 // Atmel AVR 8-bit microcontroller
|
||||||
|
#define EM_FR30 84 // Fujitsu FR30
|
||||||
|
#define EM_D10V 85 // Mitsubishi D10V
|
||||||
|
#define EM_D30V 86 // Mitsubishi D30V
|
||||||
|
#define EM_V850 87 // NEC v850
|
||||||
|
#define EM_M32R 88 // Renesas M32R (formerly Mitsubishi M32R)
|
||||||
|
#define EM_MN10300 89 // Matsushita MN10300
|
||||||
|
#define EM_MN10200 90 // Matsushita MN10200
|
||||||
|
#define EM_PJ 91 // picoJava
|
||||||
|
#define EM_OPENRISC 92 // OpenRISC 32-bit embedded processor
|
||||||
|
#define EM_ARC_A5 93 // ARC Cores Tangent-A5
|
||||||
|
#define EM_XTENSA 94 // Tensilica Xtensa Architecture
|
||||||
|
#define EM_VIDEOCORE 95 // Alphamosaic VideoCore processor
|
||||||
|
#define EM_TMM_GPP 96 // Thompson Multimedia General Purpose Processor
|
||||||
|
#define EM_NS32K 97 // National Semiconductor 32000 series
|
||||||
|
#define EM_TPC 98 // Tenor Network TPC processor
|
||||||
|
#define EM_SNP1K 99 // Trebia SNP 1000 processor
|
||||||
|
#define EM_ST200 100 // STMicroelectronics ST200 microcontroller
|
||||||
|
#define EM_IP2K 101 // Ubicom IP2022 micro controller
|
||||||
|
#define EM_MAX 102 // MAX Processor
|
||||||
|
#define EM_CR 103 // National Semiconductor CompactRISC
|
||||||
|
#define EM_F2MC16 104 // Fujitsu F2MC16
|
||||||
|
#define EM_MSP430 105 // TI msp430 micro controller
|
||||||
|
#define EM_BLACKFIN 106 // ADI Blackfin
|
||||||
|
#define EM_SE_C33 107 // S1C33 Family of Seiko Epson processors
|
||||||
|
#define EM_SEP 108 // Sharp embedded microprocessor
|
||||||
|
#define EM_ARCA 109 // Arca RISC Microprocessor
|
||||||
|
#define EM_UNICORE 110 // Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University
|
||||||
|
#define EM_EXCESS 111 // eXcess: 16/32/64-bit configurable embedded CPU
|
||||||
|
#define EM_DXP 112 // Icera Semiconductor Inc. Deep Execution Processor
|
||||||
|
#define EM_ALTERA_NIOS2 113 // Altera Nios II soft-core processor
|
||||||
|
#define EM_CRX 114 // National Semiconductor CRX
|
||||||
|
#define EM_XGATE 115 // Motorola XGATE embedded processor
|
||||||
|
#define EM_C166 116 // Infineon C16x/XC16x processor
|
||||||
|
#define EM_M16C 117 // Renesas M16C series microprocessors
|
||||||
|
#define EM_DSPIC30F 118 // Microchip Technology dsPIC30F Digital Signal Controller
|
||||||
|
#define EM_CE 119 // Freescale Communication Engine RISC core
|
||||||
|
#define EM_M32C 120 // Renesas M32C series microprocessors
|
||||||
|
#define EM_res121 121 // Reserved
|
||||||
|
#define EM_res122 122 // Reserved
|
||||||
|
#define EM_res123 123 // Reserved
|
||||||
|
#define EM_res124 124 // Reserved
|
||||||
|
#define EM_res125 125 // Reserved
|
||||||
|
#define EM_res126 126 // Reserved
|
||||||
|
#define EM_res127 127 // Reserved
|
||||||
|
#define EM_res128 128 // Reserved
|
||||||
|
#define EM_res129 129 // Reserved
|
||||||
|
#define EM_res130 130 // Reserved
|
||||||
|
#define EM_TSK3000 131 // Altium TSK3000 core
|
||||||
|
#define EM_RS08 132 // Freescale RS08 embedded processor
|
||||||
|
#define EM_res133 133 // Reserved
|
||||||
|
#define EM_ECOG2 134 // Cyan Technology eCOG2 microprocessor
|
||||||
|
#define EM_SCORE 135 // Sunplus Score
|
||||||
|
#define EM_SCORE7 135 // Sunplus S+core7 RISC processor
|
||||||
|
#define EM_DSP24 136 // New Japan Radio (NJR) 24-bit DSP Processor
|
||||||
|
#define EM_VIDEOCORE3 137 // Broadcom VideoCore III processor
|
||||||
|
#define EM_LATTICEMICO32 138 // RISC processor for Lattice FPGA architecture
|
||||||
|
#define EM_SE_C17 139 // Seiko Epson C17 family
|
||||||
|
#define EM_TI_C6000 140 // Texas Instruments TMS320C6000 DSP family
|
||||||
|
#define EM_TI_C2000 141 // Texas Instruments TMS320C2000 DSP family
|
||||||
|
#define EM_TI_C5500 142 // Texas Instruments TMS320C55x DSP family
|
||||||
|
#define EM_res143 143 // Reserved
|
||||||
|
#define EM_res144 144 // Reserved
|
||||||
|
#define EM_res145 145 // Reserved
|
||||||
|
#define EM_res146 146 // Reserved
|
||||||
|
#define EM_res147 147 // Reserved
|
||||||
|
#define EM_res148 148 // Reserved
|
||||||
|
#define EM_res149 149 // Reserved
|
||||||
|
#define EM_res150 150 // Reserved
|
||||||
|
#define EM_res151 151 // Reserved
|
||||||
|
#define EM_res152 152 // Reserved
|
||||||
|
#define EM_res153 153 // Reserved
|
||||||
|
#define EM_res154 154 // Reserved
|
||||||
|
#define EM_res155 155 // Reserved
|
||||||
|
#define EM_res156 156 // Reserved
|
||||||
|
#define EM_res157 157 // Reserved
|
||||||
|
#define EM_res158 158 // Reserved
|
||||||
|
#define EM_res159 159 // Reserved
|
||||||
|
#define EM_MMDSP_PLUS 160 // STMicroelectronics 64bit VLIW Data Signal Processor
|
||||||
|
#define EM_CYPRESS_M8C 161 // Cypress M8C microprocessor
|
||||||
|
#define EM_R32C 162 // Renesas R32C series microprocessors
|
||||||
|
#define EM_TRIMEDIA 163 // NXP Semiconductors TriMedia architecture family
|
||||||
|
#define EM_QDSP6 164 // QUALCOMM DSP6 Processor
|
||||||
|
#define EM_8051 165 // Intel 8051 and variants
|
||||||
|
#define EM_STXP7X 166 // STMicroelectronics STxP7x family
|
||||||
|
#define EM_NDS32 167 // Andes Technology compact code size embedded RISC processor family
|
||||||
|
#define EM_ECOG1 168 // Cyan Technology eCOG1X family
|
||||||
|
#define EM_ECOG1X 168 // Cyan Technology eCOG1X family
|
||||||
|
#define EM_MAXQ30 169 // Dallas Semiconductor MAXQ30 Core Micro-controllers
|
||||||
|
#define EM_XIMO16 170 // New Japan Radio (NJR) 16-bit DSP Processor
|
||||||
|
#define EM_MANIK 171 // M2000 Reconfigurable RISC Microprocessor
|
||||||
|
#define EM_CRAYNV2 172 // Cray Inc. NV2 vector architecture
|
||||||
|
#define EM_RX 173 // Renesas RX family
|
||||||
|
#define EM_METAG 174 // Imagination Technologies META processor architecture
|
||||||
|
#define EM_MCST_ELBRUS 175 // MCST Elbrus general purpose hardware architecture
|
||||||
|
#define EM_ECOG16 176 // Cyan Technology eCOG16 family
|
||||||
|
#define EM_CR16 177 // National Semiconductor CompactRISC 16-bit processor
|
||||||
|
#define EM_ETPU 178 // Freescale Extended Time Processing Unit
|
||||||
|
#define EM_SLE9X 179 // Infineon Technologies SLE9X core
|
||||||
|
#define EM_L1OM 180 // Intel L1OM
|
||||||
|
#define EM_INTEL181 181 // Reserved by Intel
|
||||||
|
#define EM_INTEL182 182 // Reserved by Intel
|
||||||
|
#define EM_res183 183 // Reserved by ARM
|
||||||
|
#define EM_res184 184 // Reserved by ARM
|
||||||
|
#define EM_AVR32 185 // Atmel Corporation 32-bit microprocessor family
|
||||||
|
#define EM_STM8 186 // STMicroeletronics STM8 8-bit microcontroller
|
||||||
|
#define EM_TILE64 187 // Tilera TILE64 multicore architecture family
|
||||||
|
#define EM_TILEPRO 188 // Tilera TILEPro multicore architecture family
|
||||||
|
#define EM_MICROBLAZE 189 // Xilinx MicroBlaze 32-bit RISC soft processor core
|
||||||
|
#define EM_CUDA 190 // NVIDIA CUDA architecture
|
||||||
|
#define EM_TILEGX 191 // Tilera TILE-Gx multicore architecture family
|
||||||
|
#define EM_CLOUDSHIELD 192 // CloudShield architecture family
|
||||||
|
#define EM_COREA_1ST 193 // KIPO-KAIST Core-A 1st generation processor family
|
||||||
|
#define EM_COREA_2ND 194 // KIPO-KAIST Core-A 2nd generation processor family
|
||||||
|
#define EM_ARC_COMPACT2 195 // Synopsys ARCompact V2
|
||||||
|
#define EM_OPEN8 196 // Open8 8-bit RISC soft processor core
|
||||||
|
#define EM_RL78 197 // Renesas RL78 family
|
||||||
|
#define EM_VIDEOCORE5 198 // Broadcom VideoCore V processor
|
||||||
|
#define EM_78KOR 199 // Renesas 78KOR family
|
||||||
|
#define EM_56800EX 200 // Freescale 56800EX Digital Signal Controller (DSC)
|
||||||
|
#define EM_BA1 201 // Beyond BA1 CPU architecture
|
||||||
|
#define EM_BA2 202 // Beyond BA2 CPU architecture
|
||||||
|
#define EM_XCORE 203 // XMOS xCORE processor family
|
||||||
|
#define EM_MCHP_PIC 204 // Microchip 8-bit PIC(r) family
|
||||||
|
#define EM_INTEL205 205 // Reserved by Intel
|
||||||
|
#define EM_INTEL206 206 // Reserved by Intel
|
||||||
|
#define EM_INTEL207 207 // Reserved by Intel
|
||||||
|
#define EM_INTEL208 208 // Reserved by Intel
|
||||||
|
#define EM_INTEL209 209 // Reserved by Intel
|
||||||
|
#define EM_KM32 210 // KM211 KM32 32-bit processor
|
||||||
|
#define EM_KMX32 211 // KM211 KMX32 32-bit processor
|
||||||
|
#define EM_KMX16 212 // KM211 KMX16 16-bit processor
|
||||||
|
#define EM_KMX8 213 // KM211 KMX8 8-bit processor
|
||||||
|
#define EM_KVARC 214 // KM211 KVARC processor
|
||||||
|
#define EM_CDP 215 // Paneve CDP architecture family
|
||||||
|
#define EM_COGE 216 // Cognitive Smart Memory Processor
|
||||||
|
#define EM_COOL 217 // iCelero CoolEngine
|
||||||
|
#define EM_NORC 218 // Nanoradio Optimized RISC
|
||||||
|
#define EM_CSR_KALIMBA 219 // CSR Kalimba architecture family
|
||||||
|
#define EM_Z80 220 // Zilog Z80
|
||||||
|
#define EM_VISIUM 221 // Controls and Data Services VISIUMcore processor
|
||||||
|
#define EM_FT32 222 // FTDI Chip FT32 high performance 32-bit RISC architecture
|
||||||
|
#define EM_MOXIE 223 // Moxie processor family
|
||||||
|
#define EM_AMDGPU 224 // AMD GPU architecture
|
||||||
|
#define EM_RISCV 243 // RISC-V
|
||||||
|
#define EM_LANAI 244 // Lanai processor
|
||||||
|
#define EM_CEVA 245 // CEVA Processor Architecture Family
|
||||||
|
#define EM_CEVA_X2 246 // CEVA X2 Processor Family
|
||||||
|
#define EM_BPF 247 // Linux BPF – in-kernel virtual machine
|
||||||
|
|
||||||
|
// File version
|
||||||
|
#define EV_NONE 0
|
||||||
|
#define EV_CURRENT 1
|
||||||
|
|
||||||
|
// Identification index
|
||||||
|
#define EI_MAG0 0
|
||||||
|
#define EI_MAG1 1
|
||||||
|
#define EI_MAG2 2
|
||||||
|
#define EI_MAG3 3
|
||||||
|
#define EI_CLASS 4
|
||||||
|
#define EI_DATA 5
|
||||||
|
#define EI_VERSION 6
|
||||||
|
#define EI_OSABI 7
|
||||||
|
#define EI_ABIVERSION 8
|
||||||
|
#define EI_PAD 9
|
||||||
|
#define EI_NIDENT 16
|
||||||
|
|
||||||
|
// Magic number
|
||||||
|
#define ELFMAG0 0x7F
|
||||||
|
#define ELFMAG1 'E'
|
||||||
|
#define ELFMAG2 'L'
|
||||||
|
#define ELFMAG3 'F'
|
||||||
|
|
||||||
|
// File class
|
||||||
|
#define ELFCLASSNONE 0
|
||||||
|
#define ELFCLASS32 1
|
||||||
|
#define ELFCLASS64 2
|
||||||
|
|
||||||
|
// Encoding
|
||||||
|
#define ELFDATANONE 0
|
||||||
|
#define ELFDATA2LSB 1
|
||||||
|
#define ELFDATA2MSB 2
|
||||||
|
|
||||||
|
// OS extensions
|
||||||
|
#define ELFOSABI_NONE 0 // No extensions or unspecified
|
||||||
|
#define ELFOSABI_HPUX 1 // Hewlett-Packard HP-UX
|
||||||
|
#define ELFOSABI_NETBSD 2 // NetBSD
|
||||||
|
#define ELFOSABI_LINUX 3 // Linux
|
||||||
|
#define ELFOSABI_SOLARIS 6 // Sun Solaris
|
||||||
|
#define ELFOSABI_AIX 7 // AIX
|
||||||
|
#define ELFOSABI_IRIX 8 // IRIX
|
||||||
|
#define ELFOSABI_FREEBSD 9 // FreeBSD
|
||||||
|
#define ELFOSABI_TRU64 10 // Compaq TRU64 UNIX
|
||||||
|
#define ELFOSABI_MODESTO 11 // Novell Modesto
|
||||||
|
#define ELFOSABI_OPENBSD 12 // Open BSD
|
||||||
|
#define ELFOSABI_OPENVMS 13 // Open VMS
|
||||||
|
#define ELFOSABI_NSK 14 // Hewlett-Packard Non-Stop Kernel
|
||||||
|
#define ELFOSABI_AROS 15 // Amiga Research OS
|
||||||
|
#define ELFOSABI_FENIXOS 16 // The FenixOS highly scalable multi-core OS
|
||||||
|
// 64-255 Architecture-specific value range
|
||||||
|
#define ELFOSABI_AMDGPU_HSA 64 // AMDGPU OS for HSA compatible compute
|
||||||
|
// kernels.
|
||||||
|
#define ELFOSABI_AMDGPU_PAL 65 // AMDGPU OS for AMD PAL compatible graphics
|
||||||
|
// shaders and compute kernels.
|
||||||
|
#define ELFOSABI_AMDGPU_MESA3D 66 // AMDGPU OS for Mesa3D compatible graphics
|
||||||
|
// shaders and compute kernels.
|
||||||
|
|
||||||
|
|
||||||
|
// AMDGPU specific e_flags
|
||||||
|
#define EF_AMDGPU_MACH 0x0ff // AMDGPU processor selection mask.
|
||||||
|
#define EF_AMDGPU_XNACK 0x100 // Indicates if the XNACK target feature is
|
||||||
|
// enabled for all code contained in the ELF.
|
||||||
|
// AMDGPU processors
|
||||||
|
#define EF_AMDGPU_MACH_NONE 0x000 // Unspecified processor.
|
||||||
|
#define EF_AMDGPU_MACH_R600_R600 0x001
|
||||||
|
#define EF_AMDGPU_MACH_R600_R630 0x002
|
||||||
|
#define EF_AMDGPU_MACH_R600_RS880 0x003
|
||||||
|
#define EF_AMDGPU_MACH_R600_RV670 0x004
|
||||||
|
#define EF_AMDGPU_MACH_R600_RV710 0x005
|
||||||
|
#define EF_AMDGPU_MACH_R600_RV730 0x006
|
||||||
|
#define EF_AMDGPU_MACH_R600_RV770 0x007
|
||||||
|
#define EF_AMDGPU_MACH_R600_CEDAR 0x008
|
||||||
|
#define EF_AMDGPU_MACH_R600_CYPRESS 0x009
|
||||||
|
#define EF_AMDGPU_MACH_R600_JUNIPER 0x00a
|
||||||
|
#define EF_AMDGPU_MACH_R600_REDWOOD 0x00b
|
||||||
|
#define EF_AMDGPU_MACH_R600_SUMO 0x00c
|
||||||
|
#define EF_AMDGPU_MACH_R600_BARTS 0x00d
|
||||||
|
#define EF_AMDGPU_MACH_R600_CAICOS 0x00e
|
||||||
|
#define EF_AMDGPU_MACH_R600_CAYMAN 0x00f
|
||||||
|
#define EF_AMDGPU_MACH_R600_TURKS 0x010
|
||||||
|
#define EF_AMDGPU_MACH_R600_RESERVED_FIRST 0x011
|
||||||
|
#define EF_AMDGPU_MACH_R600_RESERVED_LAST 0x01f
|
||||||
|
#define EF_AMDGPU_MACH_R600_FIRST EF_AMDGPU_MACH_R600_R600
|
||||||
|
#define EF_AMDGPU_MACH_R600_LAST EF_AMDGPU_MACH_R600_TURKS
|
||||||
|
#define EF_AMDGPU_MACH_AMDGCN_GFX600 0x020
|
||||||
|
#define EF_AMDGPU_MACH_AMDGCN_GFX601 0x021
|
||||||
|
#define EF_AMDGPU_MACH_AMDGCN_GFX700 0x022
|
||||||
|
#define EF_AMDGPU_MACH_AMDGCN_GFX701 0x023
|
||||||
|
#define EF_AMDGPU_MACH_AMDGCN_GFX702 0x024
|
||||||
|
#define EF_AMDGPU_MACH_AMDGCN_GFX703 0x025
|
||||||
|
#define EF_AMDGPU_MACH_AMDGCN_GFX704 0x026
|
||||||
|
#define EF_AMDGPU_MACH_AMDGCN_GFX801 0x028
|
||||||
|
#define EF_AMDGPU_MACH_AMDGCN_GFX802 0x029
|
||||||
|
#define EF_AMDGPU_MACH_AMDGCN_GFX803 0x02a
|
||||||
|
#define EF_AMDGPU_MACH_AMDGCN_GFX810 0x02b
|
||||||
|
#define EF_AMDGPU_MACH_AMDGCN_GFX900 0x02c
|
||||||
|
#define EF_AMDGPU_MACH_AMDGCN_GFX902 0x02d
|
||||||
|
#define EF_AMDGPU_MACH_AMDGCN_GFX904 0x02e
|
||||||
|
#define EF_AMDGPU_MACH_AMDGCN_GFX906 0x02f
|
||||||
|
#define EF_AMDGPU_MACH_AMDGCN_RESERVED0 0x027
|
||||||
|
#define EF_AMDGPU_MACH_AMDGCN_RESERVED1 0x030
|
||||||
|
#define EF_AMDGPU_MACH_AMDGCN_FIRST EF_AMDGPU_MACH_AMDGCN_GFX600
|
||||||
|
#define EF_AMDGPU_MACH_AMDGCN_LAST EF_AMDGPU_MACH_AMDGCN_GFX906
|
||||||
|
|
||||||
|
/////////////////////
|
||||||
|
// Sections constants
|
||||||
|
|
||||||
|
// Section indexes
|
||||||
|
#define SHN_UNDEF 0
|
||||||
|
#define SHN_LORESERVE 0xFF00
|
||||||
|
#define SHN_LOPROC 0xFF00
|
||||||
|
#define SHN_HIPROC 0xFF1F
|
||||||
|
#define SHN_LOOS 0xFF20
|
||||||
|
#define SHN_HIOS 0xFF3F
|
||||||
|
#define SHN_ABS 0xFFF1
|
||||||
|
#define SHN_COMMON 0xFFF2
|
||||||
|
#define SHN_XINDEX 0xFFFF
|
||||||
|
#define SHN_HIRESERVE 0xFFFF
|
||||||
|
|
||||||
|
// Section types
|
||||||
|
#define SHT_NULL 0
|
||||||
|
#define SHT_PROGBITS 1
|
||||||
|
#define SHT_SYMTAB 2
|
||||||
|
#define SHT_STRTAB 3
|
||||||
|
#define SHT_RELA 4
|
||||||
|
#define SHT_HASH 5
|
||||||
|
#define SHT_DYNAMIC 6
|
||||||
|
#define SHT_NOTE 7
|
||||||
|
#define SHT_NOBITS 8
|
||||||
|
#define SHT_REL 9
|
||||||
|
#define SHT_SHLIB 10
|
||||||
|
#define SHT_DYNSYM 11
|
||||||
|
#define SHT_INIT_ARRAY 14
|
||||||
|
#define SHT_FINI_ARRAY 15
|
||||||
|
#define SHT_PREINIT_ARRAY 16
|
||||||
|
#define SHT_GROUP 17
|
||||||
|
#define SHT_SYMTAB_SHNDX 18
|
||||||
|
#define SHT_LOOS 0x60000000
|
||||||
|
#define SHT_HIOS 0x6fffffff
|
||||||
|
#define SHT_LOPROC 0x70000000
|
||||||
|
#define SHT_HIPROC 0x7FFFFFFF
|
||||||
|
#define SHT_LOUSER 0x80000000
|
||||||
|
#define SHT_HIUSER 0xFFFFFFFF
|
||||||
|
|
||||||
|
// Section attribute flags
|
||||||
|
#define SHF_WRITE 0x1
|
||||||
|
#define SHF_ALLOC 0x2
|
||||||
|
#define SHF_EXECINSTR 0x4
|
||||||
|
#define SHF_MERGE 0x10
|
||||||
|
#define SHF_STRINGS 0x20
|
||||||
|
#define SHF_INFO_LINK 0x40
|
||||||
|
#define SHF_LINK_ORDER 0x80
|
||||||
|
#define SHF_OS_NONCONFORMING 0x100
|
||||||
|
#define SHF_GROUP 0x200
|
||||||
|
#define SHF_TLS 0x400
|
||||||
|
#define SHF_MASKOS 0x0ff00000
|
||||||
|
#define SHF_MASKPROC 0xF0000000
|
||||||
|
|
||||||
|
// Section group flags
|
||||||
|
#define GRP_COMDAT 0x1
|
||||||
|
#define GRP_MASKOS 0x0ff00000
|
||||||
|
#define GRP_MASKPROC 0xf0000000
|
||||||
|
|
||||||
|
// Symbol binding
|
||||||
|
#define STB_LOCAL 0
|
||||||
|
#define STB_GLOBAL 1
|
||||||
|
#define STB_WEAK 2
|
||||||
|
#define STB_LOOS 10
|
||||||
|
#define STB_HIOS 12
|
||||||
|
#define STB_MULTIDEF 13
|
||||||
|
#define STB_LOPROC 13
|
||||||
|
#define STB_HIPROC 15
|
||||||
|
|
||||||
|
// Note types
|
||||||
|
#define NT_AMDGPU_METADATA 1
|
||||||
|
#define NT_AMD_AMDGPU_HSA_METADATA 10
|
||||||
|
#define NT_AMD_AMDGPU_ISA 11
|
||||||
|
#define NT_AMD_AMDGPU_PAL_METADATA 12
|
||||||
|
|
||||||
|
// Symbol types
|
||||||
|
#define STT_NOTYPE 0
|
||||||
|
#define STT_OBJECT 1
|
||||||
|
#define STT_FUNC 2
|
||||||
|
#define STT_SECTION 3
|
||||||
|
#define STT_FILE 4
|
||||||
|
#define STT_COMMON 5
|
||||||
|
#define STT_TLS 6
|
||||||
|
#define STT_LOOS 10
|
||||||
|
#define STT_AMDGPU_HSA_KERNEL 10
|
||||||
|
#define STT_HIOS 12
|
||||||
|
#define STT_LOPROC 13
|
||||||
|
#define STT_HIPROC 15
|
||||||
|
|
||||||
|
// Symbol visibility
|
||||||
|
#define STV_DEFAULT 0
|
||||||
|
#define STV_INTERNAL 1
|
||||||
|
#define STV_HIDDEN 2
|
||||||
|
#define STV_PROTECTED 3
|
||||||
|
|
||||||
|
// Undefined name
|
||||||
|
#define STN_UNDEF 0
|
||||||
|
|
||||||
|
// Relocation types
|
||||||
|
#define R_386_NONE 0
|
||||||
|
#define R_X86_64_NONE 0
|
||||||
|
#define R_AMDGPU_NONE 0
|
||||||
|
#define R_386_32 1
|
||||||
|
#define R_X86_64_64 1
|
||||||
|
#define R_AMDGPU_ABS32_LO 1
|
||||||
|
#define R_386_PC32 2
|
||||||
|
#define R_X86_64_PC32 2
|
||||||
|
#define R_AMDGPU_ABS32_HI 2
|
||||||
|
#define R_386_GOT32 3
|
||||||
|
#define R_X86_64_GOT32 3
|
||||||
|
#define R_AMDGPU_ABS64 3
|
||||||
|
#define R_386_PLT32 4
|
||||||
|
#define R_X86_64_PLT32 4
|
||||||
|
#define R_AMDGPU_REL32 4
|
||||||
|
#define R_386_COPY 5
|
||||||
|
#define R_X86_64_COPY 5
|
||||||
|
#define R_AMDGPU_REL64 5
|
||||||
|
#define R_386_GLOB_DAT 6
|
||||||
|
#define R_X86_64_GLOB_DAT 6
|
||||||
|
#define R_AMDGPU_ABS32 6
|
||||||
|
#define R_386_JMP_SLOT 7
|
||||||
|
#define R_X86_64_JUMP_SLOT 7
|
||||||
|
#define R_AMDGPU_GOTPCREL 7
|
||||||
|
#define R_386_RELATIVE 8
|
||||||
|
#define R_X86_64_RELATIVE 8
|
||||||
|
#define R_AMDGPU_GOTPCREL32_LO 8
|
||||||
|
#define R_386_GOTOFF 9
|
||||||
|
#define R_X86_64_GOTPCREL 9
|
||||||
|
#define R_AMDGPU_GOTPCREL32_HI 9
|
||||||
|
#define R_386_GOTPC 10
|
||||||
|
#define R_X86_64_32 10
|
||||||
|
#define R_AMDGPU_REL32_LO 10
|
||||||
|
#define R_386_32PLT 11
|
||||||
|
#define R_X86_64_32S 11
|
||||||
|
#define R_AMDGPU_REL32_HI 11
|
||||||
|
#define R_X86_64_16 12
|
||||||
|
#define R_X86_64_PC16 13
|
||||||
|
#define R_AMDGPU_RELATIVE64 13
|
||||||
|
#define R_386_TLS_TPOFF 14
|
||||||
|
#define R_X86_64_8 14
|
||||||
|
#define R_386_TLS_IE 15
|
||||||
|
#define R_X86_64_PC8 15
|
||||||
|
#define R_386_TLS_GOTIE 16
|
||||||
|
#define R_X86_64_DTPMOD64 16
|
||||||
|
#define R_386_TLS_LE 17
|
||||||
|
#define R_X86_64_DTPOFF64 17
|
||||||
|
#define R_386_TLS_GD 18
|
||||||
|
#define R_X86_64_TPOFF64 18
|
||||||
|
#define R_386_TLS_LDM 19
|
||||||
|
#define R_X86_64_TLSGD 19
|
||||||
|
#define R_386_16 20
|
||||||
|
#define R_X86_64_TLSLD 20
|
||||||
|
#define R_386_PC16 21
|
||||||
|
#define R_X86_64_DTPOFF32 21
|
||||||
|
#define R_386_8 22
|
||||||
|
#define R_X86_64_GOTTPOFF 22
|
||||||
|
#define R_386_PC8 23
|
||||||
|
#define R_X86_64_TPOFF32 23
|
||||||
|
#define R_386_TLS_GD_32 24
|
||||||
|
#define R_X86_64_PC64 24
|
||||||
|
#define R_386_TLS_GD_PUSH 25
|
||||||
|
#define R_X86_64_GOTOFF64 25
|
||||||
|
#define R_386_TLS_GD_CALL 26
|
||||||
|
#define R_X86_64_GOTPC32 26
|
||||||
|
#define R_386_TLS_GD_POP 27
|
||||||
|
#define R_X86_64_GOT64 27
|
||||||
|
#define R_386_TLS_LDM_32 28
|
||||||
|
#define R_X86_64_GOTPCREL64 28
|
||||||
|
#define R_386_TLS_LDM_PUSH 29
|
||||||
|
#define R_X86_64_GOTPC64 29
|
||||||
|
#define R_386_TLS_LDM_CALL 30
|
||||||
|
#define R_X86_64_GOTPLT64 30
|
||||||
|
#define R_386_TLS_LDM_POP 31
|
||||||
|
#define R_X86_64_PLTOFF64 31
|
||||||
|
#define R_386_TLS_LDO_32 32
|
||||||
|
#define R_386_TLS_IE_32 33
|
||||||
|
#define R_386_TLS_LE_32 34
|
||||||
|
#define R_X86_64_GOTPC32_TLSDESC 34
|
||||||
|
#define R_386_TLS_DTPMOD32 35
|
||||||
|
#define R_X86_64_TLSDESC_CALL 35
|
||||||
|
#define R_386_TLS_DTPOFF32 36
|
||||||
|
#define R_X86_64_TLSDESC 36
|
||||||
|
#define R_386_TLS_TPOFF32 37
|
||||||
|
#define R_X86_64_IRELATIVE 37
|
||||||
|
#define R_386_SIZE32 38
|
||||||
|
#define R_386_TLS_GOTDESC 39
|
||||||
|
#define R_386_TLS_DESC_CALL 40
|
||||||
|
#define R_386_TLS_DESC 41
|
||||||
|
#define R_386_IRELATIVE 42
|
||||||
|
#define R_386_GOT32X 43
|
||||||
|
#define R_X86_64_GNU_VTINHERIT 250
|
||||||
|
#define R_X86_64_GNU_VTENTRY 251
|
||||||
|
|
||||||
|
// Segment types
|
||||||
|
#define PT_NULL 0
|
||||||
|
#define PT_LOAD 1
|
||||||
|
#define PT_DYNAMIC 2
|
||||||
|
#define PT_INTERP 3
|
||||||
|
#define PT_NOTE 4
|
||||||
|
#define PT_SHLIB 5
|
||||||
|
#define PT_PHDR 6
|
||||||
|
#define PT_TLS 7
|
||||||
|
#define PT_LOOS 0x60000000
|
||||||
|
#define PT_HIOS 0x6fffffff
|
||||||
|
#define PT_LOPROC 0x70000000
|
||||||
|
#define PT_HIPROC 0x7FFFFFFF
|
||||||
|
|
||||||
|
// Segment flags
|
||||||
|
#define PF_X 1 // Execute
|
||||||
|
#define PF_W 2 // Write
|
||||||
|
#define PF_R 4 // Read
|
||||||
|
#define PF_MASKOS 0x0ff00000 // Unspecified
|
||||||
|
#define PF_MASKPROC 0xf0000000 // Unspecified
|
||||||
|
|
||||||
|
// Dynamic Array Tags
|
||||||
|
#define DT_NULL 0
|
||||||
|
#define DT_NEEDED 1
|
||||||
|
#define DT_PLTRELSZ 2
|
||||||
|
#define DT_PLTGOT 3
|
||||||
|
#define DT_HASH 4
|
||||||
|
#define DT_STRTAB 5
|
||||||
|
#define DT_SYMTAB 6
|
||||||
|
#define DT_RELA 7
|
||||||
|
#define DT_RELASZ 8
|
||||||
|
#define DT_RELAENT 9
|
||||||
|
#define DT_STRSZ 10
|
||||||
|
#define DT_SYMENT 11
|
||||||
|
#define DT_INIT 12
|
||||||
|
#define DT_FINI 13
|
||||||
|
#define DT_SONAME 14
|
||||||
|
#define DT_RPATH 15
|
||||||
|
#define DT_SYMBOLIC 16
|
||||||
|
#define DT_REL 17
|
||||||
|
#define DT_RELSZ 18
|
||||||
|
#define DT_RELENT 19
|
||||||
|
#define DT_PLTREL 20
|
||||||
|
#define DT_DEBUG 21
|
||||||
|
#define DT_TEXTREL 22
|
||||||
|
#define DT_JMPREL 23
|
||||||
|
#define DT_BIND_NOW 24
|
||||||
|
#define DT_INIT_ARRAY 25
|
||||||
|
#define DT_FINI_ARRAY 26
|
||||||
|
#define DT_INIT_ARRAYSZ 27
|
||||||
|
#define DT_FINI_ARRAYSZ 28
|
||||||
|
#define DT_RUNPATH 29
|
||||||
|
#define DT_FLAGS 30
|
||||||
|
#define DT_ENCODING 32
|
||||||
|
#define DT_PREINIT_ARRAY 32
|
||||||
|
#define DT_PREINIT_ARRAYSZ 33
|
||||||
|
#define DT_MAXPOSTAGS 34
|
||||||
|
#define DT_LOOS 0x6000000D
|
||||||
|
#define DT_HIOS 0x6ffff000
|
||||||
|
#define DT_LOPROC 0x70000000
|
||||||
|
#define DT_HIPROC 0x7FFFFFFF
|
||||||
|
|
||||||
|
// DT_FLAGS values
|
||||||
|
#define DF_ORIGIN 0x1
|
||||||
|
#define DF_SYMBOLIC 0x2
|
||||||
|
#define DF_TEXTREL 0x4
|
||||||
|
#define DF_BIND_NOW 0x8
|
||||||
|
#define DF_STATIC_TLS 0x10
|
||||||
|
|
||||||
|
|
||||||
|
// ELF file header
|
||||||
|
struct Elf32_Ehdr {
|
||||||
|
unsigned char e_ident[EI_NIDENT];
|
||||||
|
Elf_Half e_type;
|
||||||
|
Elf_Half e_machine;
|
||||||
|
Elf_Word e_version;
|
||||||
|
Elf32_Addr e_entry;
|
||||||
|
Elf32_Off e_phoff;
|
||||||
|
Elf32_Off e_shoff;
|
||||||
|
Elf_Word e_flags;
|
||||||
|
Elf_Half e_ehsize;
|
||||||
|
Elf_Half e_phentsize;
|
||||||
|
Elf_Half e_phnum;
|
||||||
|
Elf_Half e_shentsize;
|
||||||
|
Elf_Half e_shnum;
|
||||||
|
Elf_Half e_shstrndx;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Elf64_Ehdr {
|
||||||
|
unsigned char e_ident[EI_NIDENT];
|
||||||
|
Elf_Half e_type;
|
||||||
|
Elf_Half e_machine;
|
||||||
|
Elf_Word e_version;
|
||||||
|
Elf64_Addr e_entry;
|
||||||
|
Elf64_Off e_phoff;
|
||||||
|
Elf64_Off e_shoff;
|
||||||
|
Elf_Word e_flags;
|
||||||
|
Elf_Half e_ehsize;
|
||||||
|
Elf_Half e_phentsize;
|
||||||
|
Elf_Half e_phnum;
|
||||||
|
Elf_Half e_shentsize;
|
||||||
|
Elf_Half e_shnum;
|
||||||
|
Elf_Half e_shstrndx;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Section header
|
||||||
|
struct Elf32_Shdr {
|
||||||
|
Elf_Word sh_name;
|
||||||
|
Elf_Word sh_type;
|
||||||
|
Elf_Word sh_flags;
|
||||||
|
Elf32_Addr sh_addr;
|
||||||
|
Elf32_Off sh_offset;
|
||||||
|
Elf_Word sh_size;
|
||||||
|
Elf_Word sh_link;
|
||||||
|
Elf_Word sh_info;
|
||||||
|
Elf_Word sh_addralign;
|
||||||
|
Elf_Word sh_entsize;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Elf64_Shdr {
|
||||||
|
Elf_Word sh_name;
|
||||||
|
Elf_Word sh_type;
|
||||||
|
Elf_Xword sh_flags;
|
||||||
|
Elf64_Addr sh_addr;
|
||||||
|
Elf64_Off sh_offset;
|
||||||
|
Elf_Xword sh_size;
|
||||||
|
Elf_Word sh_link;
|
||||||
|
Elf_Word sh_info;
|
||||||
|
Elf_Xword sh_addralign;
|
||||||
|
Elf_Xword sh_entsize;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Segment header
|
||||||
|
struct Elf32_Phdr {
|
||||||
|
Elf_Word p_type;
|
||||||
|
Elf32_Off p_offset;
|
||||||
|
Elf32_Addr p_vaddr;
|
||||||
|
Elf32_Addr p_paddr;
|
||||||
|
Elf_Word p_filesz;
|
||||||
|
Elf_Word p_memsz;
|
||||||
|
Elf_Word p_flags;
|
||||||
|
Elf_Word p_align;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Elf64_Phdr {
|
||||||
|
Elf_Word p_type;
|
||||||
|
Elf_Word p_flags;
|
||||||
|
Elf64_Off p_offset;
|
||||||
|
Elf64_Addr p_vaddr;
|
||||||
|
Elf64_Addr p_paddr;
|
||||||
|
Elf_Xword p_filesz;
|
||||||
|
Elf_Xword p_memsz;
|
||||||
|
Elf_Xword p_align;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Symbol table entry
|
||||||
|
struct Elf32_Sym {
|
||||||
|
Elf_Word st_name;
|
||||||
|
Elf32_Addr st_value;
|
||||||
|
Elf_Word st_size;
|
||||||
|
unsigned char st_info;
|
||||||
|
unsigned char st_other;
|
||||||
|
Elf_Half st_shndx;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Elf64_Sym {
|
||||||
|
Elf_Word st_name;
|
||||||
|
unsigned char st_info;
|
||||||
|
unsigned char st_other;
|
||||||
|
Elf_Half st_shndx;
|
||||||
|
Elf64_Addr st_value;
|
||||||
|
Elf_Xword st_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define ELF_ST_BIND(i) ((i)>>4)
|
||||||
|
#define ELF_ST_TYPE(i) ((i)&0xf)
|
||||||
|
#define ELF_ST_INFO(b,t) (((b)<<4)+((t)&0xf))
|
||||||
|
|
||||||
|
#define ELF_ST_VISIBILITY(o) ((o)&0x3)
|
||||||
|
|
||||||
|
|
||||||
|
// Relocation entries
|
||||||
|
struct Elf32_Rel {
|
||||||
|
Elf32_Addr r_offset;
|
||||||
|
Elf_Word r_info;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Elf32_Rela {
|
||||||
|
Elf32_Addr r_offset;
|
||||||
|
Elf_Word r_info;
|
||||||
|
Elf_Sword r_addend;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Elf64_Rel {
|
||||||
|
Elf64_Addr r_offset;
|
||||||
|
Elf_Xword r_info;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Elf64_Rela {
|
||||||
|
Elf64_Addr r_offset;
|
||||||
|
Elf_Xword r_info;
|
||||||
|
Elf_Sxword r_addend;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define ELF32_R_SYM(i) ((i)>>8)
|
||||||
|
#define ELF32_R_TYPE(i) ((unsigned char)(i))
|
||||||
|
#define ELF32_R_INFO(s,t) (((s)<<8 )+(unsigned char)(t))
|
||||||
|
|
||||||
|
#define ELF64_R_SYM(i) ((i)>>32)
|
||||||
|
#define ELF64_R_TYPE(i) ((i)&0xffffffffL)
|
||||||
|
#define ELF64_R_INFO(s,t) ((((int64_t)(s))<<32)+((t)&0xffffffffL))
|
||||||
|
|
||||||
|
// Dynamic structure
|
||||||
|
struct Elf32_Dyn {
|
||||||
|
Elf_Sword d_tag;
|
||||||
|
union {
|
||||||
|
Elf_Word d_val;
|
||||||
|
Elf32_Addr d_ptr;
|
||||||
|
} d_un;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Elf64_Dyn {
|
||||||
|
Elf_Sxword d_tag;
|
||||||
|
union {
|
||||||
|
Elf_Xword d_val;
|
||||||
|
Elf64_Addr d_ptr;
|
||||||
|
} d_un;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ELFIO
|
||||||
|
|
||||||
|
#endif // ELFTYPES_H
|
955
src/elfio/elfio.hpp
Normal file
955
src/elfio/elfio.hpp
Normal 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
976
src/elfio/elfio_dump.hpp
Normal file
@ -0,0 +1,976 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2001-2015 by Serge Lamikhov-Center
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ELFIO_DUMP_HPP
|
||||||
|
#define ELFIO_DUMP_HPP
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <string>
|
||||||
|
#include <ostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <elfio/elfio.hpp>
|
||||||
|
|
||||||
|
namespace ELFIO {
|
||||||
|
|
||||||
|
|
||||||
|
static struct class_table_t {
|
||||||
|
const char key;
|
||||||
|
const char* str;
|
||||||
|
} class_table [] =
|
||||||
|
{
|
||||||
|
{ ELFCLASS32, "ELF32" },
|
||||||
|
{ ELFCLASS64, "ELF64" },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static struct endian_table_t {
|
||||||
|
const char key;
|
||||||
|
const char* str;
|
||||||
|
} endian_table [] =
|
||||||
|
{
|
||||||
|
{ ELFDATANONE, "None" },
|
||||||
|
{ ELFDATA2LSB, "Little endian" },
|
||||||
|
{ ELFDATA2MSB, "Big endian" },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static struct version_table_t {
|
||||||
|
const Elf64_Word key;
|
||||||
|
const char* str;
|
||||||
|
} version_table [] =
|
||||||
|
{
|
||||||
|
{ EV_NONE , "None" },
|
||||||
|
{ EV_CURRENT, "Current" },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static struct type_table_t {
|
||||||
|
const Elf32_Half key;
|
||||||
|
const char* str;
|
||||||
|
} type_table [] =
|
||||||
|
{
|
||||||
|
{ ET_NONE, "No file type" },
|
||||||
|
{ ET_REL , "Relocatable file" },
|
||||||
|
{ ET_EXEC, "Executable file" },
|
||||||
|
{ ET_DYN , "Shared object file" },
|
||||||
|
{ ET_CORE, "Core file" },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static struct machine_table_t {
|
||||||
|
const Elf64_Half key;
|
||||||
|
const char* str;
|
||||||
|
} machine_table [] =
|
||||||
|
{
|
||||||
|
{ EM_NONE , "No machine" },
|
||||||
|
{ EM_M32 , "AT&T WE 32100" },
|
||||||
|
{ EM_SPARC , "SUN SPARC" },
|
||||||
|
{ EM_386 , "Intel 80386" },
|
||||||
|
{ EM_68K , "Motorola m68k family" },
|
||||||
|
{ EM_88K , "Motorola m88k family" },
|
||||||
|
{ EM_486 , "Intel 80486// Reserved for future use" },
|
||||||
|
{ EM_860 , "Intel 80860" },
|
||||||
|
{ EM_MIPS , "MIPS R3000 (officially, big-endian only)" },
|
||||||
|
{ EM_S370 , "IBM System/370" },
|
||||||
|
{ EM_MIPS_RS3_LE , "MIPS R3000 little-endian (Oct 4 1999 Draft) Deprecated" },
|
||||||
|
{ EM_res011 , "Reserved" },
|
||||||
|
{ EM_res012 , "Reserved" },
|
||||||
|
{ EM_res013 , "Reserved" },
|
||||||
|
{ EM_res014 , "Reserved" },
|
||||||
|
{ EM_PARISC , "HPPA" },
|
||||||
|
{ EM_res016 , "Reserved" },
|
||||||
|
{ EM_VPP550 , "Fujitsu VPP500" },
|
||||||
|
{ EM_SPARC32PLUS , "Sun's v8plus" },
|
||||||
|
{ EM_960 , "Intel 80960" },
|
||||||
|
{ EM_PPC , "PowerPC" },
|
||||||
|
{ EM_PPC64 , "64-bit PowerPC" },
|
||||||
|
{ EM_S390 , "IBM S/390" },
|
||||||
|
{ EM_SPU , "Sony/Toshiba/IBM SPU" },
|
||||||
|
{ EM_res024 , "Reserved" },
|
||||||
|
{ EM_res025 , "Reserved" },
|
||||||
|
{ EM_res026 , "Reserved" },
|
||||||
|
{ EM_res027 , "Reserved" },
|
||||||
|
{ EM_res028 , "Reserved" },
|
||||||
|
{ EM_res029 , "Reserved" },
|
||||||
|
{ EM_res030 , "Reserved" },
|
||||||
|
{ EM_res031 , "Reserved" },
|
||||||
|
{ EM_res032 , "Reserved" },
|
||||||
|
{ EM_res033 , "Reserved" },
|
||||||
|
{ EM_res034 , "Reserved" },
|
||||||
|
{ EM_res035 , "Reserved" },
|
||||||
|
{ EM_V800 , "NEC V800 series" },
|
||||||
|
{ EM_FR20 , "Fujitsu FR20" },
|
||||||
|
{ EM_RH32 , "TRW RH32" },
|
||||||
|
{ EM_MCORE , "Motorola M*Core // May also be taken by Fujitsu MMA" },
|
||||||
|
{ EM_RCE , "Old name for MCore" },
|
||||||
|
{ EM_ARM , "ARM" },
|
||||||
|
{ EM_OLD_ALPHA , "Digital Alpha" },
|
||||||
|
{ EM_SH , "Renesas (formerly Hitachi) / SuperH SH" },
|
||||||
|
{ EM_SPARCV9 , "SPARC v9 64-bit" },
|
||||||
|
{ EM_TRICORE , "Siemens Tricore embedded processor" },
|
||||||
|
{ EM_ARC , "ARC Cores" },
|
||||||
|
{ EM_H8_300 , "Renesas (formerly Hitachi) H8/300" },
|
||||||
|
{ EM_H8_300H , "Renesas (formerly Hitachi) H8/300H" },
|
||||||
|
{ EM_H8S , "Renesas (formerly Hitachi) H8S" },
|
||||||
|
{ EM_H8_500 , "Renesas (formerly Hitachi) H8/500" },
|
||||||
|
{ EM_IA_64 , "Intel IA-64 Processor" },
|
||||||
|
{ EM_MIPS_X , "Stanford MIPS-X" },
|
||||||
|
{ EM_COLDFIRE , "Motorola Coldfire" },
|
||||||
|
{ EM_68HC12 , "Motorola M68HC12" },
|
||||||
|
{ EM_MMA , "Fujitsu Multimedia Accelerator" },
|
||||||
|
{ EM_PCP , "Siemens PCP" },
|
||||||
|
{ EM_NCPU , "Sony nCPU embedded RISC processor" },
|
||||||
|
{ EM_NDR1 , "Denso NDR1 microprocesspr" },
|
||||||
|
{ EM_STARCORE , "Motorola Star*Core processor" },
|
||||||
|
{ EM_ME16 , "Toyota ME16 processor" },
|
||||||
|
{ EM_ST100 , "STMicroelectronics ST100 processor" },
|
||||||
|
{ EM_TINYJ , "Advanced Logic Corp. TinyJ embedded processor" },
|
||||||
|
{ EM_X86_64 , "Advanced Micro Devices X86-64 processor" },
|
||||||
|
{ EM_PDSP , "Sony DSP Processor" },
|
||||||
|
{ EM_PDP10 , "Digital Equipment Corp. PDP-10" },
|
||||||
|
{ EM_PDP11 , "Digital Equipment Corp. PDP-11" },
|
||||||
|
{ EM_FX66 , "Siemens FX66 microcontroller" },
|
||||||
|
{ EM_ST9PLUS , "STMicroelectronics ST9+ 8/16 bit microcontroller" },
|
||||||
|
{ EM_ST7 , "STMicroelectronics ST7 8-bit microcontroller" },
|
||||||
|
{ EM_68HC16 , "Motorola MC68HC16 Microcontroller" },
|
||||||
|
{ EM_68HC11 , "Motorola MC68HC11 Microcontroller" },
|
||||||
|
{ EM_68HC08 , "Motorola MC68HC08 Microcontroller" },
|
||||||
|
{ EM_68HC05 , "Motorola MC68HC05 Microcontroller" },
|
||||||
|
{ EM_SVX , "Silicon Graphics SVx" },
|
||||||
|
{ EM_ST19 , "STMicroelectronics ST19 8-bit cpu" },
|
||||||
|
{ EM_VAX , "Digital VAX" },
|
||||||
|
{ EM_CRIS , "Axis Communications 32-bit embedded processor" },
|
||||||
|
{ EM_JAVELIN , "Infineon Technologies 32-bit embedded cpu" },
|
||||||
|
{ EM_FIREPATH , "Element 14 64-bit DSP processor" },
|
||||||
|
{ EM_ZSP , "LSI Logic's 16-bit DSP processor" },
|
||||||
|
{ EM_MMIX , "Donald Knuth's educational 64-bit processor" },
|
||||||
|
{ EM_HUANY , "Harvard's machine-independent format" },
|
||||||
|
{ EM_PRISM , "SiTera Prism" },
|
||||||
|
{ EM_AVR , "Atmel AVR 8-bit microcontroller" },
|
||||||
|
{ EM_FR30 , "Fujitsu FR30" },
|
||||||
|
{ EM_D10V , "Mitsubishi D10V" },
|
||||||
|
{ EM_D30V , "Mitsubishi D30V" },
|
||||||
|
{ EM_V850 , "NEC v850" },
|
||||||
|
{ EM_M32R , "Renesas M32R (formerly Mitsubishi M32R)" },
|
||||||
|
{ EM_MN10300 , "Matsushita MN10300" },
|
||||||
|
{ EM_MN10200 , "Matsushita MN10200" },
|
||||||
|
{ EM_PJ , "picoJava" },
|
||||||
|
{ EM_OPENRISC , "OpenRISC 32-bit embedded processor" },
|
||||||
|
{ EM_ARC_A5 , "ARC Cores Tangent-A5" },
|
||||||
|
{ EM_XTENSA , "Tensilica Xtensa Architecture" },
|
||||||
|
{ EM_VIDEOCORE , "Alphamosaic VideoCore processor" },
|
||||||
|
{ EM_TMM_GPP , "Thompson Multimedia General Purpose Processor" },
|
||||||
|
{ EM_NS32K , "National Semiconductor 32000 series" },
|
||||||
|
{ EM_TPC , "Tenor Network TPC processor" },
|
||||||
|
{ EM_SNP1K , "Trebia SNP 1000 processor" },
|
||||||
|
{ EM_ST200 , "STMicroelectronics ST200 microcontroller" },
|
||||||
|
{ EM_IP2K , "Ubicom IP2022 micro controller" },
|
||||||
|
{ EM_MAX , "MAX Processor" },
|
||||||
|
{ EM_CR , "National Semiconductor CompactRISC" },
|
||||||
|
{ EM_F2MC16 , "Fujitsu F2MC16" },
|
||||||
|
{ EM_MSP430 , "TI msp430 micro controller" },
|
||||||
|
{ EM_BLACKFIN , "ADI Blackfin" },
|
||||||
|
{ EM_SE_C33 , "S1C33 Family of Seiko Epson processors" },
|
||||||
|
{ EM_SEP , "Sharp embedded microprocessor" },
|
||||||
|
{ EM_ARCA , "Arca RISC Microprocessor" },
|
||||||
|
{ EM_UNICORE , "Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University" },
|
||||||
|
{ EM_EXCESS , "eXcess: 16/32/64-bit configurable embedded CPU" },
|
||||||
|
{ EM_DXP , "Icera Semiconductor Inc. Deep Execution Processor" },
|
||||||
|
{ EM_ALTERA_NIOS2 , "Altera Nios II soft-core processor" },
|
||||||
|
{ EM_CRX , "National Semiconductor CRX" },
|
||||||
|
{ EM_XGATE , "Motorola XGATE embedded processor" },
|
||||||
|
{ EM_C166 , "Infineon C16x/XC16x processor" },
|
||||||
|
{ EM_M16C , "Renesas M16C series microprocessors" },
|
||||||
|
{ EM_DSPIC30F , "Microchip Technology dsPIC30F Digital Signal Controller" },
|
||||||
|
{ EM_CE , "Freescale Communication Engine RISC core" },
|
||||||
|
{ EM_M32C , "Renesas M32C series microprocessors" },
|
||||||
|
{ EM_res121 , "Reserved" },
|
||||||
|
{ EM_res122 , "Reserved" },
|
||||||
|
{ EM_res123 , "Reserved" },
|
||||||
|
{ EM_res124 , "Reserved" },
|
||||||
|
{ EM_res125 , "Reserved" },
|
||||||
|
{ EM_res126 , "Reserved" },
|
||||||
|
{ EM_res127 , "Reserved" },
|
||||||
|
{ EM_res128 , "Reserved" },
|
||||||
|
{ EM_res129 , "Reserved" },
|
||||||
|
{ EM_res130 , "Reserved" },
|
||||||
|
{ EM_TSK3000 , "Altium TSK3000 core" },
|
||||||
|
{ EM_RS08 , "Freescale RS08 embedded processor" },
|
||||||
|
{ EM_res133 , "Reserved" },
|
||||||
|
{ EM_ECOG2 , "Cyan Technology eCOG2 microprocessor" },
|
||||||
|
{ EM_SCORE , "Sunplus Score" },
|
||||||
|
{ EM_SCORE7 , "Sunplus S+core7 RISC processor" },
|
||||||
|
{ EM_DSP24 , "New Japan Radio (NJR) 24-bit DSP Processor" },
|
||||||
|
{ EM_VIDEOCORE3 , "Broadcom VideoCore III processor" },
|
||||||
|
{ EM_LATTICEMICO32, "RISC processor for Lattice FPGA architecture" },
|
||||||
|
{ EM_SE_C17 , "Seiko Epson C17 family" },
|
||||||
|
{ EM_TI_C6000 , "Texas Instruments TMS320C6000 DSP family" },
|
||||||
|
{ EM_TI_C2000 , "Texas Instruments TMS320C2000 DSP family" },
|
||||||
|
{ EM_TI_C5500 , "Texas Instruments TMS320C55x DSP family" },
|
||||||
|
{ EM_res143 , "Reserved" },
|
||||||
|
{ EM_res144 , "Reserved" },
|
||||||
|
{ EM_res145 , "Reserved" },
|
||||||
|
{ EM_res146 , "Reserved" },
|
||||||
|
{ EM_res147 , "Reserved" },
|
||||||
|
{ EM_res148 , "Reserved" },
|
||||||
|
{ EM_res149 , "Reserved" },
|
||||||
|
{ EM_res150 , "Reserved" },
|
||||||
|
{ EM_res151 , "Reserved" },
|
||||||
|
{ EM_res152 , "Reserved" },
|
||||||
|
{ EM_res153 , "Reserved" },
|
||||||
|
{ EM_res154 , "Reserved" },
|
||||||
|
{ EM_res155 , "Reserved" },
|
||||||
|
{ EM_res156 , "Reserved" },
|
||||||
|
{ EM_res157 , "Reserved" },
|
||||||
|
{ EM_res158 , "Reserved" },
|
||||||
|
{ EM_res159 , "Reserved" },
|
||||||
|
{ EM_MMDSP_PLUS , "STMicroelectronics 64bit VLIW Data Signal Processor" },
|
||||||
|
{ EM_CYPRESS_M8C , "Cypress M8C microprocessor" },
|
||||||
|
{ EM_R32C , "Renesas R32C series microprocessors" },
|
||||||
|
{ EM_TRIMEDIA , "NXP Semiconductors TriMedia architecture family" },
|
||||||
|
{ EM_QDSP6 , "QUALCOMM DSP6 Processor" },
|
||||||
|
{ EM_8051 , "Intel 8051 and variants" },
|
||||||
|
{ EM_STXP7X , "STMicroelectronics STxP7x family" },
|
||||||
|
{ EM_NDS32 , "Andes Technology compact code size embedded RISC processor family" },
|
||||||
|
{ EM_ECOG1 , "Cyan Technology eCOG1X family" },
|
||||||
|
{ EM_ECOG1X , "Cyan Technology eCOG1X family" },
|
||||||
|
{ EM_MAXQ30 , "Dallas Semiconductor MAXQ30 Core Micro-controllers" },
|
||||||
|
{ EM_XIMO16 , "New Japan Radio (NJR) 16-bit DSP Processor" },
|
||||||
|
{ EM_MANIK , "M2000 Reconfigurable RISC Microprocessor" },
|
||||||
|
{ EM_CRAYNV2 , "Cray Inc. NV2 vector architecture" },
|
||||||
|
{ EM_RX , "Renesas RX family" },
|
||||||
|
{ EM_METAG , "Imagination Technologies META processor architecture" },
|
||||||
|
{ EM_MCST_ELBRUS , "MCST Elbrus general purpose hardware architecture" },
|
||||||
|
{ EM_ECOG16 , "Cyan Technology eCOG16 family" },
|
||||||
|
{ EM_CR16 , "National Semiconductor CompactRISC 16-bit processor" },
|
||||||
|
{ EM_ETPU , "Freescale Extended Time Processing Unit" },
|
||||||
|
{ EM_SLE9X , "Infineon Technologies SLE9X core" },
|
||||||
|
{ EM_L1OM , "Intel L1OM" },
|
||||||
|
{ EM_INTEL181 , "Reserved by Intel" },
|
||||||
|
{ EM_INTEL182 , "Reserved by Intel" },
|
||||||
|
{ EM_res183 , "Reserved by ARM" },
|
||||||
|
{ EM_res184 , "Reserved by ARM" },
|
||||||
|
{ EM_AVR32 , "Atmel Corporation 32-bit microprocessor family" },
|
||||||
|
{ EM_STM8 , "STMicroeletronics STM8 8-bit microcontroller" },
|
||||||
|
{ EM_TILE64 , "Tilera TILE64 multicore architecture family" },
|
||||||
|
{ EM_TILEPRO , "Tilera TILEPro multicore architecture family" },
|
||||||
|
{ EM_MICROBLAZE , "Xilinx MicroBlaze 32-bit RISC soft processor core" },
|
||||||
|
{ EM_CUDA , "NVIDIA CUDA architecture " },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static struct section_type_table_t {
|
||||||
|
const Elf64_Half key;
|
||||||
|
const char* str;
|
||||||
|
} section_type_table [] =
|
||||||
|
{
|
||||||
|
{ SHT_NULL , "NULL" },
|
||||||
|
{ SHT_PROGBITS , "PROGBITS" },
|
||||||
|
{ SHT_SYMTAB , "SYMTAB" },
|
||||||
|
{ SHT_STRTAB , "STRTAB" },
|
||||||
|
{ SHT_RELA , "RELA" },
|
||||||
|
{ SHT_HASH , "HASH" },
|
||||||
|
{ SHT_DYNAMIC , "DYNAMIC" },
|
||||||
|
{ SHT_NOTE , "NOTE" },
|
||||||
|
{ SHT_NOBITS , "NOBITS" },
|
||||||
|
{ SHT_REL , "REL" },
|
||||||
|
{ SHT_SHLIB , "SHLIB" },
|
||||||
|
{ SHT_DYNSYM , "DYNSYM" },
|
||||||
|
{ SHT_INIT_ARRAY , "INIT_ARRAY" },
|
||||||
|
{ SHT_FINI_ARRAY , "FINI_ARRAY" },
|
||||||
|
{ SHT_PREINIT_ARRAY, "PREINIT_ARRAY" },
|
||||||
|
{ SHT_GROUP , "GROUP" },
|
||||||
|
{ SHT_SYMTAB_SHNDX , "SYMTAB_SHNDX " },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static struct segment_type_table_t {
|
||||||
|
const Elf_Word key;
|
||||||
|
const char* str;
|
||||||
|
} segment_type_table [] =
|
||||||
|
{
|
||||||
|
{ PT_NULL , "NULL" },
|
||||||
|
{ PT_LOAD , "LOAD" },
|
||||||
|
{ PT_DYNAMIC, "DYNAMIC" },
|
||||||
|
{ PT_INTERP , "INTERP" },
|
||||||
|
{ PT_NOTE , "NOTE" },
|
||||||
|
{ PT_SHLIB , "SHLIB" },
|
||||||
|
{ PT_PHDR , "PHDR" },
|
||||||
|
{ PT_TLS , "TLS" },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static struct segment_flag_table_t {
|
||||||
|
const Elf_Word key;
|
||||||
|
const char* str;
|
||||||
|
} segment_flag_table [] =
|
||||||
|
{
|
||||||
|
{ 0, "" },
|
||||||
|
{ 1, "X" },
|
||||||
|
{ 2, "W" },
|
||||||
|
{ 3, "WX" },
|
||||||
|
{ 4, "R" },
|
||||||
|
{ 5, "RX" },
|
||||||
|
{ 6, "RW" },
|
||||||
|
{ 7, "RWX" },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static struct symbol_bind_t {
|
||||||
|
const Elf_Word key;
|
||||||
|
const char* str;
|
||||||
|
} symbol_bind_table [] =
|
||||||
|
{
|
||||||
|
{ STB_LOCAL , "LOCAL" },
|
||||||
|
{ STB_GLOBAL , "GLOBAL" },
|
||||||
|
{ STB_WEAK , "WEAK" },
|
||||||
|
{ STB_LOOS , "LOOS" },
|
||||||
|
{ STB_HIOS , "HIOS" },
|
||||||
|
{ STB_MULTIDEF, "MULTIDEF" },
|
||||||
|
{ STB_LOPROC , "LOPROC" },
|
||||||
|
{ STB_HIPROC , "HIPROC" },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static struct symbol_type_t {
|
||||||
|
const Elf_Word key;
|
||||||
|
const char* str;
|
||||||
|
} symbol_type_table [] =
|
||||||
|
{
|
||||||
|
{ STT_NOTYPE , "NOTYPE" },
|
||||||
|
{ STT_OBJECT , "OBJECT" },
|
||||||
|
{ STT_FUNC , "FUNC" },
|
||||||
|
{ STT_SECTION, "SECTION" },
|
||||||
|
{ STT_FILE , "FILE" },
|
||||||
|
{ STT_COMMON , "COMMON" },
|
||||||
|
{ STT_TLS , "TLS" },
|
||||||
|
{ STT_LOOS , "LOOS" },
|
||||||
|
{ STT_HIOS , "HIOS" },
|
||||||
|
{ STT_LOPROC , "LOPROC" },
|
||||||
|
{ STT_HIPROC , "HIPROC" },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static struct dynamic_tag_t {
|
||||||
|
const Elf_Word key;
|
||||||
|
const char* str;
|
||||||
|
} dynamic_tag_table [] =
|
||||||
|
{
|
||||||
|
{ DT_NULL , "NULL" },
|
||||||
|
{ DT_NEEDED , "NEEDED" },
|
||||||
|
{ DT_PLTRELSZ , "PLTRELSZ" },
|
||||||
|
{ DT_PLTGOT , "PLTGOT" },
|
||||||
|
{ DT_HASH , "HASH" },
|
||||||
|
{ DT_STRTAB , "STRTAB" },
|
||||||
|
{ DT_SYMTAB , "SYMTAB" },
|
||||||
|
{ DT_RELA , "RELA" },
|
||||||
|
{ DT_RELASZ , "RELASZ" },
|
||||||
|
{ DT_RELAENT , "RELAENT" },
|
||||||
|
{ DT_STRSZ , "STRSZ" },
|
||||||
|
{ DT_SYMENT , "SYMENT" },
|
||||||
|
{ DT_INIT , "INIT" },
|
||||||
|
{ DT_FINI , "FINI" },
|
||||||
|
{ DT_SONAME , "SONAME" },
|
||||||
|
{ DT_RPATH , "RPATH" },
|
||||||
|
{ DT_SYMBOLIC , "SYMBOLIC" },
|
||||||
|
{ DT_REL , "REL" },
|
||||||
|
{ DT_RELSZ , "RELSZ" },
|
||||||
|
{ DT_RELENT , "RELENT" },
|
||||||
|
{ DT_PLTREL , "PLTREL" },
|
||||||
|
{ DT_DEBUG , "DEBUG" },
|
||||||
|
{ DT_TEXTREL , "TEXTREL" },
|
||||||
|
{ DT_JMPREL , "JMPREL" },
|
||||||
|
{ DT_BIND_NOW , "BIND_NOW" },
|
||||||
|
{ DT_INIT_ARRAY , "INIT_ARRAY" },
|
||||||
|
{ DT_FINI_ARRAY , "FINI_ARRAY" },
|
||||||
|
{ DT_INIT_ARRAYSZ , "INIT_ARRAYSZ" },
|
||||||
|
{ DT_FINI_ARRAYSZ , "FINI_ARRAYSZ" },
|
||||||
|
{ DT_RUNPATH , "RUNPATH" },
|
||||||
|
{ DT_FLAGS , "FLAGS" },
|
||||||
|
{ DT_ENCODING , "ENCODING" },
|
||||||
|
{ DT_PREINIT_ARRAY , "PREINIT_ARRAY" },
|
||||||
|
{ DT_PREINIT_ARRAYSZ, "PREINIT_ARRAYSZ" },
|
||||||
|
{ DT_MAXPOSTAGS , "MAXPOSTAGS" },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const ELFIO::Elf_Xword MAX_DATA_ENTRIES = 64;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
class dump
|
||||||
|
{
|
||||||
|
#define DUMP_DEC_FORMAT( width ) std::setw(width) << std::setfill( ' ' ) << \
|
||||||
|
std::dec << std::right
|
||||||
|
#define DUMP_HEX_FORMAT( width ) std::setw(width) << std::setfill( '0' ) << \
|
||||||
|
std::hex << std::right
|
||||||
|
#define DUMP_STR_FORMAT( width ) std::setw(width) << std::setfill( ' ' ) << \
|
||||||
|
std::hex << std::left
|
||||||
|
|
||||||
|
public:
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
static void
|
||||||
|
header( std::ostream& out, const elfio& reader )
|
||||||
|
{
|
||||||
|
if (!reader.get_header_size())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
out << "ELF Header" << std::endl << std::endl
|
||||||
|
<< " Class: " << str_class( reader.get_class() ) << std::endl
|
||||||
|
<< " Encoding: " << str_endian( reader.get_encoding() ) << std::endl
|
||||||
|
<< " ELFVersion: " << str_version( reader.get_elf_version() ) << std::endl
|
||||||
|
<< " Type: " << str_type( reader.get_type() ) << std::endl
|
||||||
|
<< " Machine: " << str_machine( reader.get_machine() ) << std::endl
|
||||||
|
<< " Version: " << str_version( reader.get_version() ) << std::endl
|
||||||
|
<< " Entry: " << "0x" << std::hex << reader.get_entry() << std::endl
|
||||||
|
<< " Flags: " << "0x" << std::hex << reader.get_flags() << std::endl
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
static void
|
||||||
|
section_headers( std::ostream& out, const elfio& reader )
|
||||||
|
{
|
||||||
|
Elf_Half n = reader.sections.size();
|
||||||
|
|
||||||
|
if ( n == 0 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
out << "Section Headers:" << std::endl;
|
||||||
|
if ( reader.get_class() == ELFCLASS32 ) { // Output for 32-bit
|
||||||
|
out << "[ Nr ] Type Addr Size ES Flg Lk Inf Al Name" << std::endl;
|
||||||
|
}
|
||||||
|
else { // Output for 64-bit
|
||||||
|
out << "[ Nr ] Type Addr Size ES Flg" << std::endl
|
||||||
|
<< " Lk Inf Al Name" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( Elf_Half i = 0; i < n; ++i ) { // For all sections
|
||||||
|
section* sec = reader.sections[i];
|
||||||
|
section_header( out, i, sec, reader.get_class() );
|
||||||
|
}
|
||||||
|
|
||||||
|
out << "Key to Flags: W (write), A (alloc), X (execute)\n\n"
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
static void
|
||||||
|
section_header( std::ostream& out, Elf_Half no, const section* sec,
|
||||||
|
unsigned char elf_class )
|
||||||
|
{
|
||||||
|
std::ios_base::fmtflags original_flags = out.flags();
|
||||||
|
|
||||||
|
if ( elf_class == ELFCLASS32 ) { // Output for 32-bit
|
||||||
|
out << "["
|
||||||
|
<< DUMP_DEC_FORMAT( 5 ) << no
|
||||||
|
<< "] "
|
||||||
|
<< DUMP_STR_FORMAT( 17 ) << str_section_type( sec->get_type() ) << " "
|
||||||
|
<< DUMP_HEX_FORMAT( 8 ) << sec->get_address() << " "
|
||||||
|
<< DUMP_HEX_FORMAT( 8 ) << sec->get_size() << " "
|
||||||
|
<< DUMP_HEX_FORMAT( 2 ) << sec->get_entry_size() << " "
|
||||||
|
<< DUMP_STR_FORMAT( 3 ) << section_flags( sec->get_flags() ) << " "
|
||||||
|
<< DUMP_HEX_FORMAT( 2 ) << sec->get_link() << " "
|
||||||
|
<< DUMP_HEX_FORMAT( 3 ) << sec->get_info() << " "
|
||||||
|
<< DUMP_HEX_FORMAT( 2 ) << sec->get_addr_align() << " "
|
||||||
|
<< DUMP_STR_FORMAT( 17 ) << sec->get_name() << " "
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
else { // Output for 64-bit
|
||||||
|
out << "["
|
||||||
|
<< DUMP_DEC_FORMAT( 5 ) << no
|
||||||
|
<< "] "
|
||||||
|
<< DUMP_STR_FORMAT( 17 ) << str_section_type( sec->get_type() ) << " "
|
||||||
|
<< DUMP_HEX_FORMAT( 16 ) << sec->get_address() << " "
|
||||||
|
<< DUMP_HEX_FORMAT( 16 ) << sec->get_size() << " "
|
||||||
|
<< DUMP_HEX_FORMAT( 4 ) << sec->get_entry_size() << " "
|
||||||
|
<< DUMP_STR_FORMAT( 3 ) << section_flags( sec->get_flags() ) << " "
|
||||||
|
<< std::endl
|
||||||
|
<< " "
|
||||||
|
<< DUMP_HEX_FORMAT( 4 ) << sec->get_link() << " "
|
||||||
|
<< DUMP_HEX_FORMAT( 4 ) << sec->get_info() << " "
|
||||||
|
<< DUMP_HEX_FORMAT( 4 ) << sec->get_addr_align() << " "
|
||||||
|
<< DUMP_STR_FORMAT( 17 ) << sec->get_name() << " "
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.flags(original_flags);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
static void
|
||||||
|
segment_headers( std::ostream& out, const elfio& reader )
|
||||||
|
{
|
||||||
|
Elf_Half n = reader.segments.size();
|
||||||
|
if ( n == 0 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
out << "Segment headers:" << std::endl;
|
||||||
|
if ( reader.get_class() == ELFCLASS32 ) { // Output for 32-bit
|
||||||
|
out << "[ Nr ] Type VirtAddr PhysAddr FileSize Mem.Size Flags Align"
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
else { // Output for 64-bit
|
||||||
|
out << "[ Nr ] Type VirtAddr PhysAddr Flags" << std::endl
|
||||||
|
<< " FileSize Mem.Size Align"
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( Elf_Half i = 0; i < n; ++i ) {
|
||||||
|
segment* seg = reader.segments[i];
|
||||||
|
segment_header( out, i, seg, reader.get_class() );
|
||||||
|
}
|
||||||
|
|
||||||
|
out << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
static void
|
||||||
|
segment_header( std::ostream& out, Elf_Half no, const segment* seg,
|
||||||
|
unsigned int elf_class )
|
||||||
|
{
|
||||||
|
std::ios_base::fmtflags original_flags = out.flags();
|
||||||
|
|
||||||
|
if ( elf_class == ELFCLASS32 ) { // Output for 32-bit
|
||||||
|
out << "["
|
||||||
|
<< DUMP_DEC_FORMAT( 5 ) << no
|
||||||
|
<< "] "
|
||||||
|
<< DUMP_STR_FORMAT( 14 ) << str_segment_type( seg->get_type() ) << " "
|
||||||
|
<< DUMP_HEX_FORMAT( 8 ) << seg->get_virtual_address() << " "
|
||||||
|
<< DUMP_HEX_FORMAT( 8 ) << seg->get_physical_address() << " "
|
||||||
|
<< DUMP_HEX_FORMAT( 8 ) << seg->get_file_size() << " "
|
||||||
|
<< DUMP_HEX_FORMAT( 8 ) << seg->get_memory_size() << " "
|
||||||
|
<< DUMP_STR_FORMAT( 8 ) << str_segment_flag( seg->get_flags() ) << " "
|
||||||
|
<< DUMP_HEX_FORMAT( 8 ) << seg->get_align() << " "
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
else { // Output for 64-bit
|
||||||
|
out << "["
|
||||||
|
<< DUMP_DEC_FORMAT( 5 ) << no
|
||||||
|
<< "] "
|
||||||
|
<< DUMP_STR_FORMAT( 14 ) << str_segment_type( seg->get_type() ) << " "
|
||||||
|
<< DUMP_HEX_FORMAT( 16 ) << seg->get_virtual_address() << " "
|
||||||
|
<< DUMP_HEX_FORMAT( 16 ) << seg->get_physical_address() << " "
|
||||||
|
<< DUMP_STR_FORMAT( 16 ) << str_segment_flag( seg->get_flags() ) << " "
|
||||||
|
<< std::endl
|
||||||
|
<< " "
|
||||||
|
<< DUMP_HEX_FORMAT( 16 ) << seg->get_file_size() << " "
|
||||||
|
<< DUMP_HEX_FORMAT( 16 ) << seg->get_memory_size() << " "
|
||||||
|
<< DUMP_HEX_FORMAT( 16 ) << seg->get_align() << " "
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.flags(original_flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
static void
|
||||||
|
symbol_tables( std::ostream& out, const elfio& reader )
|
||||||
|
{
|
||||||
|
Elf_Half n = reader.sections.size();
|
||||||
|
for ( Elf_Half i = 0; i < n; ++i ) { // For all sections
|
||||||
|
section* sec = reader.sections[i];
|
||||||
|
if ( SHT_SYMTAB == sec->get_type() || SHT_DYNSYM == sec->get_type() ) {
|
||||||
|
symbol_section_accessor symbols( reader, sec );
|
||||||
|
|
||||||
|
Elf_Xword sym_no = symbols.get_symbols_num();
|
||||||
|
if ( sym_no > 0 ) {
|
||||||
|
out << "Symbol table (" << sec->get_name() << ")" << std::endl;
|
||||||
|
if ( reader.get_class() == ELFCLASS32 ) { // Output for 32-bit
|
||||||
|
out << "[ Nr ] Value Size Type Bind Sect Name"
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
else { // Output for 64-bit
|
||||||
|
out << "[ Nr ] Value Size Type Bind Sect" << std::endl
|
||||||
|
<< " Name"
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
for ( Elf_Half i = 0; i < sym_no; ++i ) {
|
||||||
|
std::string name;
|
||||||
|
Elf64_Addr value = 0;
|
||||||
|
Elf_Xword size = 0;
|
||||||
|
unsigned char bind = 0;
|
||||||
|
unsigned char type = 0;
|
||||||
|
Elf_Half section = 0;
|
||||||
|
unsigned char other = 0;
|
||||||
|
symbols.get_symbol( i, name, value, size, bind, type, section, other );
|
||||||
|
symbol_table( out, i, name, value, size, bind, type, section, reader.get_class() );
|
||||||
|
}
|
||||||
|
|
||||||
|
out << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
static void
|
||||||
|
symbol_table( std::ostream& out,
|
||||||
|
Elf_Half no,
|
||||||
|
std::string& name,
|
||||||
|
Elf64_Addr value,
|
||||||
|
Elf_Xword size,
|
||||||
|
unsigned char bind,
|
||||||
|
unsigned char type,
|
||||||
|
Elf_Half section,
|
||||||
|
unsigned int elf_class )
|
||||||
|
{
|
||||||
|
std::ios_base::fmtflags original_flags = out.flags();
|
||||||
|
|
||||||
|
if ( elf_class == ELFCLASS32 ) { // Output for 32-bit
|
||||||
|
out << "["
|
||||||
|
<< DUMP_DEC_FORMAT( 5 ) << no
|
||||||
|
<< "] "
|
||||||
|
<< DUMP_HEX_FORMAT( 8 ) << value << " "
|
||||||
|
<< DUMP_HEX_FORMAT( 8 ) << size << " "
|
||||||
|
<< DUMP_STR_FORMAT( 7 ) << str_symbol_type( type ) << " "
|
||||||
|
<< DUMP_STR_FORMAT( 8 ) << str_symbol_bind( bind ) << " "
|
||||||
|
<< DUMP_DEC_FORMAT( 5 ) << section << " "
|
||||||
|
<< DUMP_STR_FORMAT( 1 ) << name << " "
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
else { // Output for 64-bit
|
||||||
|
out << "["
|
||||||
|
<< DUMP_DEC_FORMAT( 5 ) << no
|
||||||
|
<< "] "
|
||||||
|
<< DUMP_HEX_FORMAT( 16 ) << value << " "
|
||||||
|
<< DUMP_HEX_FORMAT( 16 ) << size << " "
|
||||||
|
<< DUMP_STR_FORMAT( 7 ) << str_symbol_type( type ) << " "
|
||||||
|
<< DUMP_STR_FORMAT( 8 ) << str_symbol_bind( bind ) << " "
|
||||||
|
<< DUMP_DEC_FORMAT( 5 ) << section << " "
|
||||||
|
<< std::endl
|
||||||
|
<< " "
|
||||||
|
<< DUMP_STR_FORMAT( 1 ) << name << " "
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.flags(original_flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
static void
|
||||||
|
notes( std::ostream& out, const elfio& reader )
|
||||||
|
{
|
||||||
|
Elf_Half no = reader.sections.size();
|
||||||
|
for ( Elf_Half i = 0; i < no; ++i ) { // For all sections
|
||||||
|
section* sec = reader.sections[i];
|
||||||
|
if ( SHT_NOTE == sec->get_type() ) { // Look at notes
|
||||||
|
note_section_accessor notes( reader, sec );
|
||||||
|
int no_notes = notes.get_notes_num();
|
||||||
|
if ( no > 0 ) {
|
||||||
|
out << "Note section (" << sec->get_name() << ")" << std::endl
|
||||||
|
<< " No Type Name"
|
||||||
|
<< std::endl;
|
||||||
|
for ( int j = 0; j < no_notes; ++j ) { // For all notes
|
||||||
|
Elf_Word type;
|
||||||
|
std::string name;
|
||||||
|
void* desc;
|
||||||
|
Elf_Word descsz;
|
||||||
|
|
||||||
|
if ( notes.get_note(j, type, name, desc, descsz) ) {
|
||||||
|
// 'name' usually contains \0 at the end. Try to fix it
|
||||||
|
name = name.c_str();
|
||||||
|
note( out, j, type, name );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
static void
|
||||||
|
note( std::ostream& out,
|
||||||
|
int no,
|
||||||
|
Elf_Word type,
|
||||||
|
const std::string& name )
|
||||||
|
{
|
||||||
|
out << " ["
|
||||||
|
<< DUMP_DEC_FORMAT( 2 ) << no
|
||||||
|
<< "] "
|
||||||
|
<< DUMP_HEX_FORMAT( 8 ) << type << " "
|
||||||
|
<< DUMP_STR_FORMAT( 1 ) << name
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
static void
|
||||||
|
dynamic_tags( std::ostream& out, const elfio& reader )
|
||||||
|
{
|
||||||
|
Elf_Half n = reader.sections.size();
|
||||||
|
for ( Elf_Half i = 0; i < n; ++i ) { // For all sections
|
||||||
|
section* sec = reader.sections[i];
|
||||||
|
if ( SHT_DYNAMIC == sec->get_type() ) {
|
||||||
|
dynamic_section_accessor dynamic( reader, sec );
|
||||||
|
|
||||||
|
Elf_Xword dyn_no = dynamic.get_entries_num();
|
||||||
|
if ( dyn_no > 0 ) {
|
||||||
|
out << "Dynamic section (" << sec->get_name() << ")" << std::endl;
|
||||||
|
out << "[ Nr ] Tag Name/Value" << std::endl;
|
||||||
|
for ( Elf_Xword i = 0; i < dyn_no; ++i ) {
|
||||||
|
Elf_Xword tag = 0;
|
||||||
|
Elf_Xword value = 0;
|
||||||
|
std::string str;
|
||||||
|
dynamic.get_entry( i, tag, value, str );
|
||||||
|
dynamic_tag( out, i, tag, value, str, reader.get_class() );
|
||||||
|
if ( DT_NULL == tag ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
static void
|
||||||
|
dynamic_tag( std::ostream& out,
|
||||||
|
Elf_Xword no,
|
||||||
|
Elf_Xword tag,
|
||||||
|
Elf_Xword value,
|
||||||
|
std::string str,
|
||||||
|
unsigned int /*elf_class*/ )
|
||||||
|
{
|
||||||
|
out << "["
|
||||||
|
<< DUMP_DEC_FORMAT( 5 ) << no
|
||||||
|
<< "] "
|
||||||
|
<< DUMP_STR_FORMAT( 16 ) << str_dynamic_tag( tag ) << " ";
|
||||||
|
if ( str.empty() ) {
|
||||||
|
out << DUMP_HEX_FORMAT( 16 ) << value << " ";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
out << DUMP_STR_FORMAT( 32 ) << str << " ";
|
||||||
|
}
|
||||||
|
out << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
static void
|
||||||
|
section_data( std::ostream& out, const section* sec )
|
||||||
|
{
|
||||||
|
std::ios_base::fmtflags original_flags = out.flags();
|
||||||
|
|
||||||
|
out << sec->get_name() << std::endl;
|
||||||
|
const char* pdata = sec->get_data();
|
||||||
|
if ( pdata ){
|
||||||
|
ELFIO::Elf_Xword i;
|
||||||
|
for ( i = 0; i < std::min( sec->get_size(), MAX_DATA_ENTRIES ); ++i ) {
|
||||||
|
if ( i % 16 == 0 ) {
|
||||||
|
out << "[" << DUMP_HEX_FORMAT( 8 ) << i << "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
out << " " << DUMP_HEX_FORMAT( 2 ) << ( pdata[i] & 0x000000FF );
|
||||||
|
|
||||||
|
if ( i % 16 == 15 ) {
|
||||||
|
out << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( i % 16 != 0 ) {
|
||||||
|
out << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.flags(original_flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
static void
|
||||||
|
section_datas( std::ostream& out, const elfio& reader )
|
||||||
|
{
|
||||||
|
Elf_Half n = reader.sections.size();
|
||||||
|
|
||||||
|
if ( n == 0 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
out << "Section Data:" << std::endl;
|
||||||
|
|
||||||
|
for ( Elf_Half i = 1; i < n; ++i ) { // For all sections
|
||||||
|
section* sec = reader.sections[i];
|
||||||
|
if ( sec->get_type() == SHT_NOBITS ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
section_data( out, sec );
|
||||||
|
}
|
||||||
|
|
||||||
|
out << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
static void
|
||||||
|
segment_data( std::ostream& out, Elf_Half no, const segment* seg )
|
||||||
|
{
|
||||||
|
std::ios_base::fmtflags original_flags = out.flags();
|
||||||
|
|
||||||
|
out << "Segment # " << no << std::endl;
|
||||||
|
const char* pdata = seg->get_data();
|
||||||
|
if ( pdata ) {
|
||||||
|
ELFIO::Elf_Xword i;
|
||||||
|
for ( i = 0; i < std::min( seg->get_file_size(), MAX_DATA_ENTRIES ); ++i ) {
|
||||||
|
if ( i % 16 == 0 ) {
|
||||||
|
out << "[" << DUMP_HEX_FORMAT( 8 ) << i << "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
out << " " << DUMP_HEX_FORMAT( 2 ) << ( pdata[i] & 0x000000FF );
|
||||||
|
|
||||||
|
if ( i % 16 == 15 ) {
|
||||||
|
out << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( i % 16 != 0 ) {
|
||||||
|
out << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.flags(original_flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
static void
|
||||||
|
segment_datas( std::ostream& out, const elfio& reader )
|
||||||
|
{
|
||||||
|
Elf_Half n = reader.segments.size();
|
||||||
|
|
||||||
|
if ( n == 0 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
out << "Segment Data:" << std::endl;
|
||||||
|
|
||||||
|
for ( Elf_Half i = 0; i < n; ++i ) { // For all sections
|
||||||
|
segment* seg = reader.segments[i];
|
||||||
|
segment_data( out, i, seg );
|
||||||
|
}
|
||||||
|
|
||||||
|
out << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
template< typename T, typename K >
|
||||||
|
std::string
|
||||||
|
static
|
||||||
|
find_value_in_table( const T& table, const K& key )
|
||||||
|
{
|
||||||
|
std::string res = "?";
|
||||||
|
for ( unsigned int i = 0; i < sizeof( table )/sizeof( table[0] ); ++i ) {
|
||||||
|
if ( table[i].key == key ) {
|
||||||
|
res = table[i].str;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
template< typename T, typename K >
|
||||||
|
static
|
||||||
|
std::string
|
||||||
|
format_assoc( const T& table, const K& key )
|
||||||
|
{
|
||||||
|
std::string str = find_value_in_table( table, key );
|
||||||
|
if ( str == "?" ) {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << str << " (0x" << std::hex << key << ")";
|
||||||
|
str = oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
template< typename T >
|
||||||
|
static
|
||||||
|
std::string
|
||||||
|
format_assoc( const T& table, const char key )
|
||||||
|
{
|
||||||
|
return format_assoc( table, (const int)key );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
static
|
||||||
|
std::string
|
||||||
|
section_flags( Elf_Xword flags )
|
||||||
|
{
|
||||||
|
std::string ret = "";
|
||||||
|
if ( flags & SHF_WRITE ) {
|
||||||
|
ret += "W";
|
||||||
|
}
|
||||||
|
if ( flags & SHF_ALLOC ) {
|
||||||
|
ret += "A";
|
||||||
|
}
|
||||||
|
if ( flags & SHF_EXECINSTR ) {
|
||||||
|
ret += "X";
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
#define STR_FUNC_TABLE( name ) \
|
||||||
|
template< typename T > \
|
||||||
|
static \
|
||||||
|
std::string \
|
||||||
|
str_##name( const T key ) \
|
||||||
|
{ \
|
||||||
|
return format_assoc( name##_table, key ); \
|
||||||
|
}
|
||||||
|
|
||||||
|
STR_FUNC_TABLE( class )
|
||||||
|
STR_FUNC_TABLE( endian )
|
||||||
|
STR_FUNC_TABLE( version )
|
||||||
|
STR_FUNC_TABLE( type )
|
||||||
|
STR_FUNC_TABLE( machine )
|
||||||
|
STR_FUNC_TABLE( section_type )
|
||||||
|
STR_FUNC_TABLE( segment_type )
|
||||||
|
STR_FUNC_TABLE( segment_flag )
|
||||||
|
STR_FUNC_TABLE( symbol_bind )
|
||||||
|
STR_FUNC_TABLE( symbol_type )
|
||||||
|
STR_FUNC_TABLE( dynamic_tag )
|
||||||
|
|
||||||
|
#undef STR_FUNC_TABLE
|
||||||
|
#undef DUMP_DEC_FORMAT
|
||||||
|
#undef DUMP_HEX_FORMAT
|
||||||
|
#undef DUMP_STR_FORMAT
|
||||||
|
}; // class dump
|
||||||
|
|
||||||
|
|
||||||
|
}; // namespace ELFIO
|
||||||
|
|
||||||
|
#endif // ELFIO_DUMP_HPP
|
257
src/elfio/elfio_dynamic.hpp
Normal file
257
src/elfio/elfio_dynamic.hpp
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2001-2015 by Serge Lamikhov-Center
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ELFIO_DYNAMIC_HPP
|
||||||
|
#define ELFIO_DYNAMIC_HPP
|
||||||
|
|
||||||
|
namespace ELFIO {
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
template< class S >
|
||||||
|
class dynamic_section_accessor_template
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
dynamic_section_accessor_template( const elfio& elf_file_, S* section_ ) :
|
||||||
|
elf_file( elf_file_ ),
|
||||||
|
dynamic_section( section_ )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
Elf_Xword
|
||||||
|
get_entries_num() const
|
||||||
|
{
|
||||||
|
Elf_Xword nRet = 0;
|
||||||
|
|
||||||
|
if ( 0 != dynamic_section->get_entry_size() ) {
|
||||||
|
nRet = dynamic_section->get_size() / dynamic_section->get_entry_size();
|
||||||
|
}
|
||||||
|
|
||||||
|
return nRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
bool
|
||||||
|
get_entry( Elf_Xword index,
|
||||||
|
Elf_Xword& tag,
|
||||||
|
Elf_Xword& value,
|
||||||
|
std::string& str ) const
|
||||||
|
{
|
||||||
|
if ( index >= get_entries_num() ) { // Is index valid
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( elf_file.get_class() == ELFCLASS32 ) {
|
||||||
|
generic_get_entry_dyn< Elf32_Dyn >( index, tag, value );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
generic_get_entry_dyn< Elf64_Dyn >( index, tag, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the tag may have a string table reference, prepare the string
|
||||||
|
if ( tag == DT_NEEDED ||
|
||||||
|
tag == DT_SONAME ||
|
||||||
|
tag == DT_RPATH ||
|
||||||
|
tag == DT_RUNPATH ) {
|
||||||
|
string_section_accessor strsec =
|
||||||
|
elf_file.sections[ get_string_table_index() ];
|
||||||
|
const char* result = strsec.get_string( value );
|
||||||
|
if ( 0 == result ) {
|
||||||
|
str.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
str = result;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
str.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
add_entry( Elf_Xword tag,
|
||||||
|
Elf_Xword value )
|
||||||
|
{
|
||||||
|
if ( elf_file.get_class() == ELFCLASS32 ) {
|
||||||
|
generic_add_entry< Elf32_Dyn >( tag, value );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
generic_add_entry< Elf64_Dyn >( tag, value );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
add_entry( Elf_Xword tag,
|
||||||
|
const std::string& str )
|
||||||
|
{
|
||||||
|
string_section_accessor strsec =
|
||||||
|
elf_file.sections[ get_string_table_index() ];
|
||||||
|
Elf_Xword value = strsec.add_string( str );
|
||||||
|
add_entry( tag, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
private:
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
Elf_Half
|
||||||
|
get_string_table_index() const
|
||||||
|
{
|
||||||
|
return (Elf_Half)dynamic_section->get_link();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
template< class T >
|
||||||
|
void
|
||||||
|
generic_get_entry_dyn( Elf_Xword index,
|
||||||
|
Elf_Xword& tag,
|
||||||
|
Elf_Xword& value ) const
|
||||||
|
{
|
||||||
|
const endianess_convertor& convertor = elf_file.get_convertor();
|
||||||
|
|
||||||
|
// Check unusual case when dynamic section has no data
|
||||||
|
if( dynamic_section->get_data() == 0 ||
|
||||||
|
( index + 1 ) * dynamic_section->get_entry_size() > dynamic_section->get_size() ) {
|
||||||
|
tag = DT_NULL;
|
||||||
|
value = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const T* pEntry = reinterpret_cast<const T*>(
|
||||||
|
dynamic_section->get_data() +
|
||||||
|
index * dynamic_section->get_entry_size() );
|
||||||
|
tag = convertor( pEntry->d_tag );
|
||||||
|
switch ( tag ) {
|
||||||
|
case DT_NULL:
|
||||||
|
case DT_SYMBOLIC:
|
||||||
|
case DT_TEXTREL:
|
||||||
|
case DT_BIND_NOW:
|
||||||
|
value = 0;
|
||||||
|
break;
|
||||||
|
case DT_NEEDED:
|
||||||
|
case DT_PLTRELSZ:
|
||||||
|
case DT_RELASZ:
|
||||||
|
case DT_RELAENT:
|
||||||
|
case DT_STRSZ:
|
||||||
|
case DT_SYMENT:
|
||||||
|
case DT_SONAME:
|
||||||
|
case DT_RPATH:
|
||||||
|
case DT_RELSZ:
|
||||||
|
case DT_RELENT:
|
||||||
|
case DT_PLTREL:
|
||||||
|
case DT_INIT_ARRAYSZ:
|
||||||
|
case DT_FINI_ARRAYSZ:
|
||||||
|
case DT_RUNPATH:
|
||||||
|
case DT_FLAGS:
|
||||||
|
case DT_PREINIT_ARRAYSZ:
|
||||||
|
value = convertor( pEntry->d_un.d_val );
|
||||||
|
break;
|
||||||
|
case DT_PLTGOT:
|
||||||
|
case DT_HASH:
|
||||||
|
case DT_STRTAB:
|
||||||
|
case DT_SYMTAB:
|
||||||
|
case DT_RELA:
|
||||||
|
case DT_INIT:
|
||||||
|
case DT_FINI:
|
||||||
|
case DT_REL:
|
||||||
|
case DT_DEBUG:
|
||||||
|
case DT_JMPREL:
|
||||||
|
case DT_INIT_ARRAY:
|
||||||
|
case DT_FINI_ARRAY:
|
||||||
|
case DT_PREINIT_ARRAY:
|
||||||
|
default:
|
||||||
|
value = convertor( pEntry->d_un.d_ptr );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
template< class T >
|
||||||
|
void
|
||||||
|
generic_add_entry( Elf_Xword tag, Elf_Xword value )
|
||||||
|
{
|
||||||
|
const endianess_convertor& convertor = elf_file.get_convertor();
|
||||||
|
|
||||||
|
T entry;
|
||||||
|
|
||||||
|
switch ( tag ) {
|
||||||
|
case DT_NULL:
|
||||||
|
case DT_SYMBOLIC:
|
||||||
|
case DT_TEXTREL:
|
||||||
|
case DT_BIND_NOW:
|
||||||
|
value = 0;
|
||||||
|
case DT_NEEDED:
|
||||||
|
case DT_PLTRELSZ:
|
||||||
|
case DT_RELASZ:
|
||||||
|
case DT_RELAENT:
|
||||||
|
case DT_STRSZ:
|
||||||
|
case DT_SYMENT:
|
||||||
|
case DT_SONAME:
|
||||||
|
case DT_RPATH:
|
||||||
|
case DT_RELSZ:
|
||||||
|
case DT_RELENT:
|
||||||
|
case DT_PLTREL:
|
||||||
|
case DT_INIT_ARRAYSZ:
|
||||||
|
case DT_FINI_ARRAYSZ:
|
||||||
|
case DT_RUNPATH:
|
||||||
|
case DT_FLAGS:
|
||||||
|
case DT_PREINIT_ARRAYSZ:
|
||||||
|
entry.d_un.d_val = convertor( value );
|
||||||
|
break;
|
||||||
|
case DT_PLTGOT:
|
||||||
|
case DT_HASH:
|
||||||
|
case DT_STRTAB:
|
||||||
|
case DT_SYMTAB:
|
||||||
|
case DT_RELA:
|
||||||
|
case DT_INIT:
|
||||||
|
case DT_FINI:
|
||||||
|
case DT_REL:
|
||||||
|
case DT_DEBUG:
|
||||||
|
case DT_JMPREL:
|
||||||
|
case DT_INIT_ARRAY:
|
||||||
|
case DT_FINI_ARRAY:
|
||||||
|
case DT_PREINIT_ARRAY:
|
||||||
|
default:
|
||||||
|
entry.d_un.d_ptr = convertor( value );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.d_tag = convertor( tag );
|
||||||
|
|
||||||
|
dynamic_section->append_data( reinterpret_cast<char*>( &entry ), sizeof( entry ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
private:
|
||||||
|
const elfio& elf_file;
|
||||||
|
S* dynamic_section;
|
||||||
|
};
|
||||||
|
|
||||||
|
using dynamic_section_accessor = dynamic_section_accessor_template<section>;
|
||||||
|
using const_dynamic_section_accessor = dynamic_section_accessor_template<const section>;
|
||||||
|
|
||||||
|
} // namespace ELFIO
|
||||||
|
|
||||||
|
#endif // ELFIO_DYNAMIC_HPP
|
145
src/elfio/elfio_header.hpp
Normal file
145
src/elfio/elfio_header.hpp
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2001-2015 by Serge Lamikhov-Center
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ELF_HEADER_HPP
|
||||||
|
#define ELF_HEADER_HPP
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace ELFIO {
|
||||||
|
|
||||||
|
class elf_header
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~elf_header() {};
|
||||||
|
virtual bool load( std::istream& stream ) = 0;
|
||||||
|
virtual bool save( std::ostream& stream ) const = 0;
|
||||||
|
|
||||||
|
// ELF header functions
|
||||||
|
ELFIO_GET_ACCESS_DECL( unsigned char, class );
|
||||||
|
ELFIO_GET_ACCESS_DECL( unsigned char, elf_version );
|
||||||
|
ELFIO_GET_ACCESS_DECL( unsigned char, encoding );
|
||||||
|
ELFIO_GET_ACCESS_DECL( Elf_Half, header_size );
|
||||||
|
ELFIO_GET_ACCESS_DECL( Elf_Half, section_entry_size );
|
||||||
|
ELFIO_GET_ACCESS_DECL( Elf_Half, segment_entry_size );
|
||||||
|
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, version );
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( unsigned char, os_abi );
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( unsigned char, abi_version );
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Half, type );
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Half, machine );
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, flags );
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, entry );
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Half, sections_num );
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( Elf64_Off, sections_offset );
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Half, segments_num );
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( Elf64_Off, segments_offset );
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Half, section_name_str_index );
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template< class T > struct elf_header_impl_types;
|
||||||
|
template<> struct elf_header_impl_types<Elf32_Ehdr> {
|
||||||
|
typedef Elf32_Phdr Phdr_type;
|
||||||
|
typedef Elf32_Shdr Shdr_type;
|
||||||
|
static const unsigned char file_class = ELFCLASS32;
|
||||||
|
};
|
||||||
|
template<> struct elf_header_impl_types<Elf64_Ehdr> {
|
||||||
|
typedef Elf64_Phdr Phdr_type;
|
||||||
|
typedef Elf64_Shdr Shdr_type;
|
||||||
|
static const unsigned char file_class = ELFCLASS64;
|
||||||
|
};
|
||||||
|
|
||||||
|
template< class T > class elf_header_impl : public elf_header
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
elf_header_impl( endianess_convertor* convertor_,
|
||||||
|
unsigned char encoding )
|
||||||
|
{
|
||||||
|
convertor = convertor_;
|
||||||
|
|
||||||
|
std::fill_n( reinterpret_cast<char*>( &header ), sizeof( header ), '\0' );
|
||||||
|
|
||||||
|
header.e_ident[EI_MAG0] = ELFMAG0;
|
||||||
|
header.e_ident[EI_MAG1] = ELFMAG1;
|
||||||
|
header.e_ident[EI_MAG2] = ELFMAG2;
|
||||||
|
header.e_ident[EI_MAG3] = ELFMAG3;
|
||||||
|
header.e_ident[EI_CLASS] = elf_header_impl_types<T>::file_class;
|
||||||
|
header.e_ident[EI_DATA] = encoding;
|
||||||
|
header.e_ident[EI_VERSION] = EV_CURRENT;
|
||||||
|
header.e_version = (*convertor)( (Elf_Word)EV_CURRENT );
|
||||||
|
header.e_ehsize = ( sizeof( header ) );
|
||||||
|
header.e_ehsize = (*convertor)( header.e_ehsize );
|
||||||
|
header.e_shstrndx = (*convertor)( (Elf_Half)1 );
|
||||||
|
header.e_phentsize = sizeof( typename elf_header_impl_types<T>::Phdr_type );
|
||||||
|
header.e_shentsize = sizeof( typename elf_header_impl_types<T>::Shdr_type );
|
||||||
|
header.e_phentsize = (*convertor)( header.e_phentsize );
|
||||||
|
header.e_shentsize = (*convertor)( header.e_shentsize );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
load( std::istream& stream )
|
||||||
|
{
|
||||||
|
stream.seekg( 0 );
|
||||||
|
stream.read( reinterpret_cast<char*>( &header ), sizeof( header ) );
|
||||||
|
|
||||||
|
return (stream.gcount() == sizeof( header ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
save( std::ostream& stream ) const
|
||||||
|
{
|
||||||
|
stream.seekp( 0 );
|
||||||
|
stream.write( reinterpret_cast<const char*>( &header ), sizeof( header ) );
|
||||||
|
|
||||||
|
return stream.good();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELF header functions
|
||||||
|
ELFIO_GET_ACCESS( unsigned char, class, header.e_ident[EI_CLASS] );
|
||||||
|
ELFIO_GET_ACCESS( unsigned char, elf_version, header.e_ident[EI_VERSION] );
|
||||||
|
ELFIO_GET_ACCESS( unsigned char, encoding, header.e_ident[EI_DATA] );
|
||||||
|
ELFIO_GET_ACCESS( Elf_Half, header_size, header.e_ehsize );
|
||||||
|
ELFIO_GET_ACCESS( Elf_Half, section_entry_size, header.e_shentsize );
|
||||||
|
ELFIO_GET_ACCESS( Elf_Half, segment_entry_size, header.e_phentsize );
|
||||||
|
|
||||||
|
ELFIO_GET_SET_ACCESS( Elf_Word, version, header.e_version);
|
||||||
|
ELFIO_GET_SET_ACCESS( unsigned char, os_abi, header.e_ident[EI_OSABI] );
|
||||||
|
ELFIO_GET_SET_ACCESS( unsigned char, abi_version, header.e_ident[EI_ABIVERSION] );
|
||||||
|
ELFIO_GET_SET_ACCESS( Elf_Half, type, header.e_type );
|
||||||
|
ELFIO_GET_SET_ACCESS( Elf_Half, machine, header.e_machine );
|
||||||
|
ELFIO_GET_SET_ACCESS( Elf_Word, flags, header.e_flags );
|
||||||
|
ELFIO_GET_SET_ACCESS( Elf_Half, section_name_str_index, header.e_shstrndx );
|
||||||
|
ELFIO_GET_SET_ACCESS( Elf64_Addr, entry, header.e_entry );
|
||||||
|
ELFIO_GET_SET_ACCESS( Elf_Half, sections_num, header.e_shnum );
|
||||||
|
ELFIO_GET_SET_ACCESS( Elf64_Off, sections_offset, header.e_shoff );
|
||||||
|
ELFIO_GET_SET_ACCESS( Elf_Half, segments_num, header.e_phnum );
|
||||||
|
ELFIO_GET_SET_ACCESS( Elf64_Off, segments_offset, header.e_phoff );
|
||||||
|
|
||||||
|
private:
|
||||||
|
T header;
|
||||||
|
endianess_convertor* convertor;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ELFIO
|
||||||
|
|
||||||
|
#endif // ELF_HEADER_HPP
|
170
src/elfio/elfio_note.hpp
Normal file
170
src/elfio/elfio_note.hpp
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2001-2015 by Serge Lamikhov-Center
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ELFIO_NOTE_HPP
|
||||||
|
#define ELFIO_NOTE_HPP
|
||||||
|
|
||||||
|
namespace ELFIO {
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// There are discrepancies in documentations. SCO documentation
|
||||||
|
// (http://www.sco.com/developers/gabi/latest/ch5.pheader.html#note_section)
|
||||||
|
// requires 8 byte entries alignment for 64-bit ELF file,
|
||||||
|
// but Oracle's definition uses the same structure
|
||||||
|
// for 32-bit and 64-bit formats.
|
||||||
|
// (https://docs.oracle.com/cd/E23824_01/html/819-0690/chapter6-18048.html)
|
||||||
|
//
|
||||||
|
// It looks like EM_X86_64 Linux implementation is similar to Oracle's
|
||||||
|
// definition. Therefore, the same alignment works for both formats
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
template< class S >
|
||||||
|
class note_section_accessor_template
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
note_section_accessor_template( const elfio& elf_file_, S* section_ ) :
|
||||||
|
elf_file( elf_file_ ), note_section( section_ )
|
||||||
|
{
|
||||||
|
process_section();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
Elf_Word
|
||||||
|
get_notes_num() const
|
||||||
|
{
|
||||||
|
return (Elf_Word)note_start_positions.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
bool
|
||||||
|
get_note( Elf_Word index,
|
||||||
|
Elf_Word& type,
|
||||||
|
std::string& name,
|
||||||
|
void*& desc,
|
||||||
|
Elf_Word& descSize ) const
|
||||||
|
{
|
||||||
|
if ( index >= note_section->get_size() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* pData = note_section->get_data() + note_start_positions[index];
|
||||||
|
int align = sizeof( Elf_Word );
|
||||||
|
|
||||||
|
const endianess_convertor& convertor = elf_file.get_convertor();
|
||||||
|
type = convertor( *(const Elf_Word*)( pData + 2*align ) );
|
||||||
|
Elf_Word namesz = convertor( *(const Elf_Word*)( pData ) );
|
||||||
|
descSize = convertor( *(const Elf_Word*)( pData + sizeof( namesz ) ) );
|
||||||
|
Elf_Xword max_name_size = note_section->get_size() - note_start_positions[index];
|
||||||
|
if ( namesz > max_name_size ||
|
||||||
|
namesz + descSize > max_name_size ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
name.assign( pData + 3*align, namesz - 1);
|
||||||
|
if ( 0 == descSize ) {
|
||||||
|
desc = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
desc = const_cast<char*> ( pData + 3*align +
|
||||||
|
( ( namesz + align - 1 )/align )*align );
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void add_note( Elf_Word type,
|
||||||
|
const std::string& name,
|
||||||
|
const void* desc,
|
||||||
|
Elf_Word descSize )
|
||||||
|
{
|
||||||
|
const endianess_convertor& convertor = elf_file.get_convertor();
|
||||||
|
|
||||||
|
int align = sizeof( Elf_Word );
|
||||||
|
Elf_Word nameLen = (Elf_Word)name.size() + 1;
|
||||||
|
Elf_Word nameLenConv = convertor( nameLen );
|
||||||
|
std::string buffer( reinterpret_cast<char*>( &nameLenConv ), align );
|
||||||
|
Elf_Word descSizeConv = convertor( descSize );
|
||||||
|
buffer.append( reinterpret_cast<char*>( &descSizeConv ), align );
|
||||||
|
type = convertor( type );
|
||||||
|
buffer.append( reinterpret_cast<char*>( &type ), align );
|
||||||
|
buffer.append( name );
|
||||||
|
buffer.append( 1, '\x00' );
|
||||||
|
const char pad[] = { '\0', '\0', '\0', '\0' };
|
||||||
|
if ( nameLen % align != 0 ) {
|
||||||
|
buffer.append( pad, align - nameLen % align );
|
||||||
|
}
|
||||||
|
if ( desc != 0 && descSize != 0 ) {
|
||||||
|
buffer.append( reinterpret_cast<const char*>( desc ), descSize );
|
||||||
|
if ( descSize % align != 0 ) {
|
||||||
|
buffer.append( pad, align - descSize % align );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
note_start_positions.push_back( note_section->get_size() );
|
||||||
|
note_section->append_data( buffer );
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void process_section()
|
||||||
|
{
|
||||||
|
const endianess_convertor& convertor = elf_file.get_convertor();
|
||||||
|
const char* data = note_section->get_data();
|
||||||
|
Elf_Xword size = note_section->get_size();
|
||||||
|
Elf_Xword current = 0;
|
||||||
|
|
||||||
|
note_start_positions.clear();
|
||||||
|
|
||||||
|
// Is it empty?
|
||||||
|
if ( 0 == data || 0 == size ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int align = sizeof( Elf_Word );
|
||||||
|
while ( current + 3*align <= size ) {
|
||||||
|
note_start_positions.push_back( current );
|
||||||
|
Elf_Word namesz = convertor(
|
||||||
|
*(const Elf_Word*)( data + current ) );
|
||||||
|
Elf_Word descsz = convertor(
|
||||||
|
*(const Elf_Word*)( data + current + sizeof( namesz ) ) );
|
||||||
|
|
||||||
|
current += 3*sizeof( Elf_Word ) +
|
||||||
|
( ( namesz + align - 1 ) / align ) * align +
|
||||||
|
( ( descsz + align - 1 ) / align ) * align;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
private:
|
||||||
|
const elfio& elf_file;
|
||||||
|
S* note_section;
|
||||||
|
std::vector<Elf_Xword> note_start_positions;
|
||||||
|
};
|
||||||
|
|
||||||
|
using note_section_accessor = note_section_accessor_template<section>;
|
||||||
|
using const_note_section_accessor = note_section_accessor_template<const section>;
|
||||||
|
|
||||||
|
} // namespace ELFIO
|
||||||
|
|
||||||
|
#endif // ELFIO_NOTE_HPP
|
333
src/elfio/elfio_relocation.hpp
Normal file
333
src/elfio/elfio_relocation.hpp
Normal file
@ -0,0 +1,333 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2001-2015 by Serge Lamikhov-Center
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ELFIO_RELOCATION_HPP
|
||||||
|
#define ELFIO_RELOCATION_HPP
|
||||||
|
|
||||||
|
namespace ELFIO {
|
||||||
|
|
||||||
|
template<typename T> struct get_sym_and_type;
|
||||||
|
template<> struct get_sym_and_type< Elf32_Rel >
|
||||||
|
{
|
||||||
|
static int get_r_sym( Elf_Xword info )
|
||||||
|
{
|
||||||
|
return ELF32_R_SYM( (Elf_Word)info );
|
||||||
|
}
|
||||||
|
static int get_r_type( Elf_Xword info )
|
||||||
|
{
|
||||||
|
return ELF32_R_TYPE( (Elf_Word)info );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template<> struct get_sym_and_type< Elf32_Rela >
|
||||||
|
{
|
||||||
|
static int get_r_sym( Elf_Xword info )
|
||||||
|
{
|
||||||
|
return ELF32_R_SYM( (Elf_Word)info );
|
||||||
|
}
|
||||||
|
static int get_r_type( Elf_Xword info )
|
||||||
|
{
|
||||||
|
return ELF32_R_TYPE( (Elf_Word)info );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template<> struct get_sym_and_type< Elf64_Rel >
|
||||||
|
{
|
||||||
|
static int get_r_sym( Elf_Xword info )
|
||||||
|
{
|
||||||
|
return ELF64_R_SYM( info );
|
||||||
|
}
|
||||||
|
static int get_r_type( Elf_Xword info )
|
||||||
|
{
|
||||||
|
return ELF64_R_TYPE( info );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template<> struct get_sym_and_type< Elf64_Rela >
|
||||||
|
{
|
||||||
|
static int get_r_sym( Elf_Xword info )
|
||||||
|
{
|
||||||
|
return ELF64_R_SYM( info );
|
||||||
|
}
|
||||||
|
static int get_r_type( Elf_Xword info )
|
||||||
|
{
|
||||||
|
return ELF64_R_TYPE( info );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
template< class S >
|
||||||
|
class relocation_section_accessor_template
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
relocation_section_accessor_template( const elfio& elf_file_, S* section_ ) :
|
||||||
|
elf_file( elf_file_ ),
|
||||||
|
relocation_section( section_ )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
Elf_Xword
|
||||||
|
get_entries_num() const
|
||||||
|
{
|
||||||
|
Elf_Xword nRet = 0;
|
||||||
|
|
||||||
|
if ( 0 != relocation_section->get_entry_size() ) {
|
||||||
|
nRet = relocation_section->get_size() / relocation_section->get_entry_size();
|
||||||
|
}
|
||||||
|
|
||||||
|
return nRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
bool
|
||||||
|
get_entry( Elf_Xword index,
|
||||||
|
Elf64_Addr& offset,
|
||||||
|
Elf_Word& symbol,
|
||||||
|
Elf_Word& type,
|
||||||
|
Elf_Sxword& addend ) const
|
||||||
|
{
|
||||||
|
if ( index >= get_entries_num() ) { // Is index valid
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( elf_file.get_class() == ELFCLASS32 ) {
|
||||||
|
if ( SHT_REL == relocation_section->get_type() ) {
|
||||||
|
generic_get_entry_rel< Elf32_Rel >( index, offset, symbol,
|
||||||
|
type, addend );
|
||||||
|
}
|
||||||
|
else if ( SHT_RELA == relocation_section->get_type() ) {
|
||||||
|
generic_get_entry_rela< Elf32_Rela >( index, offset, symbol,
|
||||||
|
type, addend );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ( SHT_REL == relocation_section->get_type() ) {
|
||||||
|
generic_get_entry_rel< Elf64_Rel >( index, offset, symbol,
|
||||||
|
type, addend );
|
||||||
|
}
|
||||||
|
else if ( SHT_RELA == relocation_section->get_type() ) {
|
||||||
|
generic_get_entry_rela< Elf64_Rela >( index, offset, symbol,
|
||||||
|
type, addend );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
bool
|
||||||
|
get_entry( Elf_Xword index,
|
||||||
|
Elf64_Addr& offset,
|
||||||
|
Elf64_Addr& symbolValue,
|
||||||
|
std::string& symbolName,
|
||||||
|
Elf_Word& type,
|
||||||
|
Elf_Sxword& addend,
|
||||||
|
Elf_Half& section) const
|
||||||
|
{
|
||||||
|
// Do regular job
|
||||||
|
Elf_Word symbol;
|
||||||
|
bool ret = get_entry( index, offset, symbol, type, addend );
|
||||||
|
|
||||||
|
// Find the symbol
|
||||||
|
Elf_Xword size;
|
||||||
|
unsigned char bind;
|
||||||
|
unsigned char symbolType;
|
||||||
|
unsigned char other;
|
||||||
|
|
||||||
|
symbol_section_accessor symbols( elf_file, elf_file.sections[get_symbol_table_index()] );
|
||||||
|
ret = ret && symbols.get_symbol( symbol, symbolName, symbolValue,
|
||||||
|
size, bind, symbolType, section, other );
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
add_entry( Elf64_Addr offset, Elf_Xword info )
|
||||||
|
{
|
||||||
|
if ( elf_file.get_class() == ELFCLASS32 ) {
|
||||||
|
generic_add_entry< Elf32_Rel >( offset, info );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
generic_add_entry< Elf64_Rel >( offset, info );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
add_entry( Elf64_Addr offset, Elf_Word symbol, unsigned char type )
|
||||||
|
{
|
||||||
|
Elf_Xword info;
|
||||||
|
if ( elf_file.get_class() == ELFCLASS32 ) {
|
||||||
|
info = ELF32_R_INFO( (Elf_Xword)symbol, type );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
info = ELF64_R_INFO((Elf_Xword)symbol, type );
|
||||||
|
}
|
||||||
|
|
||||||
|
add_entry( offset, info );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend )
|
||||||
|
{
|
||||||
|
if ( elf_file.get_class() == ELFCLASS32 ) {
|
||||||
|
generic_add_entry< Elf32_Rela >( offset, info, addend );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
generic_add_entry< Elf64_Rela >( offset, info, addend );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
add_entry( Elf64_Addr offset, Elf_Word symbol, unsigned char type,
|
||||||
|
Elf_Sxword addend )
|
||||||
|
{
|
||||||
|
Elf_Xword info;
|
||||||
|
if ( elf_file.get_class() == ELFCLASS32 ) {
|
||||||
|
info = ELF32_R_INFO( (Elf_Xword)symbol, type );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
info = ELF64_R_INFO( (Elf_Xword)symbol, type );
|
||||||
|
}
|
||||||
|
|
||||||
|
add_entry( offset, info, addend );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
add_entry( string_section_accessor str_writer,
|
||||||
|
const char* str,
|
||||||
|
symbol_section_accessor sym_writer,
|
||||||
|
Elf64_Addr value,
|
||||||
|
Elf_Word size,
|
||||||
|
unsigned char sym_info,
|
||||||
|
unsigned char other,
|
||||||
|
Elf_Half shndx,
|
||||||
|
Elf64_Addr offset,
|
||||||
|
unsigned char type )
|
||||||
|
{
|
||||||
|
Elf_Word str_index = str_writer.add_string( str );
|
||||||
|
Elf_Word sym_index = sym_writer.add_symbol( str_index, value, size,
|
||||||
|
sym_info, other, shndx );
|
||||||
|
add_entry( offset, sym_index, type );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
private:
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
Elf_Half
|
||||||
|
get_symbol_table_index() const
|
||||||
|
{
|
||||||
|
return (Elf_Half)relocation_section->get_link();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
template< class T >
|
||||||
|
void
|
||||||
|
generic_get_entry_rel( Elf_Xword index,
|
||||||
|
Elf64_Addr& offset,
|
||||||
|
Elf_Word& symbol,
|
||||||
|
Elf_Word& type,
|
||||||
|
Elf_Sxword& addend ) const
|
||||||
|
{
|
||||||
|
const endianess_convertor& convertor = elf_file.get_convertor();
|
||||||
|
|
||||||
|
const T* pEntry = reinterpret_cast<const T*>(
|
||||||
|
relocation_section->get_data() +
|
||||||
|
index * relocation_section->get_entry_size() );
|
||||||
|
offset = convertor( pEntry->r_offset );
|
||||||
|
Elf_Xword tmp = convertor( pEntry->r_info );
|
||||||
|
symbol = get_sym_and_type<T>::get_r_sym( tmp );
|
||||||
|
type = get_sym_and_type<T>::get_r_type( tmp );
|
||||||
|
addend = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
template< class T >
|
||||||
|
void
|
||||||
|
generic_get_entry_rela( Elf_Xword index,
|
||||||
|
Elf64_Addr& offset,
|
||||||
|
Elf_Word& symbol,
|
||||||
|
Elf_Word& type,
|
||||||
|
Elf_Sxword& addend ) const
|
||||||
|
{
|
||||||
|
const endianess_convertor& convertor = elf_file.get_convertor();
|
||||||
|
|
||||||
|
const T* pEntry = reinterpret_cast<const T*>(
|
||||||
|
relocation_section->get_data() +
|
||||||
|
index * relocation_section->get_entry_size() );
|
||||||
|
offset = convertor( pEntry->r_offset );
|
||||||
|
Elf_Xword tmp = convertor( pEntry->r_info );
|
||||||
|
symbol = get_sym_and_type<T>::get_r_sym( tmp );
|
||||||
|
type = get_sym_and_type<T>::get_r_type( tmp );
|
||||||
|
addend = convertor( pEntry->r_addend );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
template< class T >
|
||||||
|
void
|
||||||
|
generic_add_entry( Elf64_Addr offset, Elf_Xword info )
|
||||||
|
{
|
||||||
|
const endianess_convertor& convertor = elf_file.get_convertor();
|
||||||
|
|
||||||
|
T entry;
|
||||||
|
entry.r_offset = offset;
|
||||||
|
entry.r_info = info;
|
||||||
|
entry.r_offset = convertor( entry.r_offset );
|
||||||
|
entry.r_info = convertor( entry.r_info );
|
||||||
|
|
||||||
|
relocation_section->append_data( reinterpret_cast<char*>( &entry ), sizeof( entry ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
template< class T >
|
||||||
|
void
|
||||||
|
generic_add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend )
|
||||||
|
{
|
||||||
|
const endianess_convertor& convertor = elf_file.get_convertor();
|
||||||
|
|
||||||
|
T entry;
|
||||||
|
entry.r_offset = offset;
|
||||||
|
entry.r_info = info;
|
||||||
|
entry.r_addend = addend;
|
||||||
|
entry.r_offset = convertor( entry.r_offset );
|
||||||
|
entry.r_info = convertor( entry.r_info );
|
||||||
|
entry.r_addend = convertor( entry.r_addend );
|
||||||
|
|
||||||
|
relocation_section->append_data( reinterpret_cast<char*>( &entry ), sizeof( entry ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
private:
|
||||||
|
const elfio& elf_file;
|
||||||
|
S* relocation_section;
|
||||||
|
};
|
||||||
|
|
||||||
|
using relocation_section_accessor = relocation_section_accessor_template<section>;
|
||||||
|
using const_relocation_section_accessor = relocation_section_accessor_template<const section>;
|
||||||
|
|
||||||
|
} // namespace ELFIO
|
||||||
|
|
||||||
|
#endif // ELFIO_RELOCATION_HPP
|
360
src/elfio/elfio_section.hpp
Normal file
360
src/elfio/elfio_section.hpp
Normal file
@ -0,0 +1,360 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2001-2015 by Serge Lamikhov-Center
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ELFIO_SECTION_HPP
|
||||||
|
#define ELFIO_SECTION_HPP
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
#include "utils/logger.h"
|
||||||
|
#include <zlib.h>
|
||||||
|
|
||||||
|
namespace ELFIO {
|
||||||
|
|
||||||
|
class section
|
||||||
|
{
|
||||||
|
friend class elfio;
|
||||||
|
public:
|
||||||
|
virtual ~section() {};
|
||||||
|
|
||||||
|
ELFIO_GET_ACCESS_DECL ( Elf_Half, index );
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( std::string, name );
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type );
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, flags );
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, info );
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, link );
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, addr_align );
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, entry_size );
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, address );
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, size );
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, name_string_offset );
|
||||||
|
ELFIO_GET_ACCESS_DECL ( Elf64_Off, offset );
|
||||||
|
size_t stream_size;
|
||||||
|
size_t get_stream_size() const
|
||||||
|
{
|
||||||
|
return stream_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_stream_size(size_t value)
|
||||||
|
{
|
||||||
|
stream_size = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const char* get_data() const = 0;
|
||||||
|
virtual void set_data( const char* pData, Elf_Word size ) = 0;
|
||||||
|
virtual void set_data( const std::string& data ) = 0;
|
||||||
|
virtual void append_data( const char* pData, Elf_Word size ) = 0;
|
||||||
|
virtual void append_data( const std::string& data ) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ELFIO_SET_ACCESS_DECL( Elf64_Off, offset );
|
||||||
|
ELFIO_SET_ACCESS_DECL( Elf_Half, index );
|
||||||
|
|
||||||
|
virtual void load( std::istream& stream,
|
||||||
|
std::streampos header_offset ) = 0;
|
||||||
|
virtual void save( std::ostream& stream,
|
||||||
|
std::streampos header_offset,
|
||||||
|
std::streampos data_offset ) = 0;
|
||||||
|
virtual bool is_address_initialized() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template< class T >
|
||||||
|
class section_impl : public section
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
section_impl( const endianess_convertor* convertor_ ) : convertor( convertor_ )
|
||||||
|
{
|
||||||
|
std::fill_n( reinterpret_cast<char*>( &header ), sizeof( header ), '\0' );
|
||||||
|
is_address_set = false;
|
||||||
|
data = 0;
|
||||||
|
data_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
~section_impl()
|
||||||
|
{
|
||||||
|
delete [] data;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Section info functions
|
||||||
|
ELFIO_GET_SET_ACCESS( Elf_Word, type, header.sh_type );
|
||||||
|
ELFIO_GET_SET_ACCESS( Elf_Xword, flags, header.sh_flags );
|
||||||
|
ELFIO_GET_SET_ACCESS( Elf_Xword, size, header.sh_size );
|
||||||
|
ELFIO_GET_SET_ACCESS( Elf_Word, link, header.sh_link );
|
||||||
|
ELFIO_GET_SET_ACCESS( Elf_Word, info, header.sh_info );
|
||||||
|
ELFIO_GET_SET_ACCESS( Elf_Xword, addr_align, header.sh_addralign );
|
||||||
|
ELFIO_GET_SET_ACCESS( Elf_Xword, entry_size, header.sh_entsize );
|
||||||
|
ELFIO_GET_SET_ACCESS( Elf_Word, name_string_offset, header.sh_name );
|
||||||
|
ELFIO_GET_ACCESS ( Elf64_Addr, address, header.sh_addr );
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
Elf_Half
|
||||||
|
get_index() const
|
||||||
|
{
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
std::string
|
||||||
|
get_name() const
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
set_name( std::string name_ )
|
||||||
|
{
|
||||||
|
name = name_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
set_address( Elf64_Addr value )
|
||||||
|
{
|
||||||
|
header.sh_addr = value;
|
||||||
|
header.sh_addr = (*convertor)( header.sh_addr );
|
||||||
|
is_address_set = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
bool
|
||||||
|
is_address_initialized() const
|
||||||
|
{
|
||||||
|
return is_address_set;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
const char*
|
||||||
|
get_data() const
|
||||||
|
{
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
set_data( const char* raw_data, Elf_Word size )
|
||||||
|
{
|
||||||
|
if ( get_type() != SHT_NOBITS ) {
|
||||||
|
delete [] data;
|
||||||
|
try {
|
||||||
|
data = new char[size];
|
||||||
|
} catch (const std::bad_alloc&) {
|
||||||
|
data = 0;
|
||||||
|
data_size = 0;
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
if ( 0 != data && 0 != raw_data ) {
|
||||||
|
data_size = size;
|
||||||
|
std::copy( raw_data, raw_data + size, data );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set_size( size );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
set_data( const std::string& str_data )
|
||||||
|
{
|
||||||
|
return set_data( str_data.c_str(), (Elf_Word)str_data.size() );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
append_data( const char* raw_data, Elf_Word size )
|
||||||
|
{
|
||||||
|
if ( get_type() != SHT_NOBITS ) {
|
||||||
|
if ( get_size() + size < data_size ) {
|
||||||
|
std::copy( raw_data, raw_data + size, data + get_size() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
data_size = 2*( data_size + size);
|
||||||
|
char* new_data;
|
||||||
|
try {
|
||||||
|
new_data = new char[data_size];
|
||||||
|
} catch (const std::bad_alloc&) {
|
||||||
|
new_data = 0;
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
if ( 0 != new_data ) {
|
||||||
|
std::copy( data, data + get_size(), new_data );
|
||||||
|
std::copy( raw_data, raw_data + size, new_data + get_size() );
|
||||||
|
delete [] data;
|
||||||
|
data = new_data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set_size( get_size() + size );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
append_data( const std::string& str_data )
|
||||||
|
{
|
||||||
|
return append_data( str_data.c_str(), (Elf_Word)str_data.size() );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
protected:
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
ELFIO_GET_SET_ACCESS( Elf64_Off, offset, header.sh_offset );
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
set_index( Elf_Half value )
|
||||||
|
{
|
||||||
|
index = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
load( std::istream& stream,
|
||||||
|
std::streampos header_offset )
|
||||||
|
{
|
||||||
|
std::fill_n( reinterpret_cast<char*>( &header ), sizeof( header ), '\0' );
|
||||||
|
|
||||||
|
stream.seekg ( 0, stream.end );
|
||||||
|
set_stream_size ( stream.tellg() );
|
||||||
|
|
||||||
|
stream.seekg( header_offset );
|
||||||
|
stream.read( reinterpret_cast<char*>( &header ), sizeof( header ) );
|
||||||
|
|
||||||
|
|
||||||
|
Elf_Xword size = get_size();
|
||||||
|
if ( 0 == data && SHT_NULL != get_type() && SHT_NOBITS != get_type() && size < get_stream_size()) {
|
||||||
|
try {
|
||||||
|
data = new char[size + 1];
|
||||||
|
} catch (const std::bad_alloc&) {
|
||||||
|
data = 0;
|
||||||
|
data_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ( 0 != size ) && ( 0 != data ) ) {
|
||||||
|
stream.seekg( (*convertor)( header.sh_offset ) );
|
||||||
|
if (get_flags() & 0x08000000){
|
||||||
|
uint32_t uncompressed_size = size;
|
||||||
|
stream.read( (char *) &uncompressed_size, 4);
|
||||||
|
stream.read( data, size - 4);
|
||||||
|
|
||||||
|
char* uncompressedData = new char[uncompressed_size + 1];
|
||||||
|
|
||||||
|
int ret = 0;
|
||||||
|
z_stream s;
|
||||||
|
memset(&s, 0, sizeof(s));
|
||||||
|
|
||||||
|
s.zalloc = Z_NULL;
|
||||||
|
s.zfree = Z_NULL;
|
||||||
|
s.opaque = Z_NULL;
|
||||||
|
|
||||||
|
ret = inflateInit_(&s, ZLIB_VERSION, sizeof(s));
|
||||||
|
if (ret != Z_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
s.avail_in = size - 4;
|
||||||
|
s.next_in = (Bytef *)data;
|
||||||
|
|
||||||
|
s.avail_out = uncompressed_size;
|
||||||
|
s.next_out = (Bytef *)&uncompressedData[0];
|
||||||
|
|
||||||
|
ret = inflate(&s, Z_FINISH);
|
||||||
|
if (ret != Z_OK && ret != Z_STREAM_END){
|
||||||
|
DEBUG_FUNCTION_LINE("NOOOO\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
inflateEnd(&s);
|
||||||
|
|
||||||
|
free(data);
|
||||||
|
data = uncompressedData;
|
||||||
|
data_size = uncompressed_size;
|
||||||
|
set_size(uncompressed_size);
|
||||||
|
data[data_size] = 0; // Ensure data is ended with 0 to avoid oob read
|
||||||
|
|
||||||
|
}else{
|
||||||
|
stream.read( data, size );
|
||||||
|
data[size] = 0; // Ensure data is ended with 0 to avoid oob read
|
||||||
|
data_size = size;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
set_size(0);
|
||||||
|
DEBUG_FUNCTION_LINE("Failed to allocate memory.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
save( std::ostream& stream,
|
||||||
|
std::streampos header_offset,
|
||||||
|
std::streampos data_offset )
|
||||||
|
{
|
||||||
|
if ( 0 != get_index() ) {
|
||||||
|
header.sh_offset = data_offset;
|
||||||
|
header.sh_offset = (*convertor)( header.sh_offset );
|
||||||
|
}
|
||||||
|
|
||||||
|
save_header( stream, header_offset );
|
||||||
|
if ( get_type() != SHT_NOBITS && get_type() != SHT_NULL &&
|
||||||
|
get_size() != 0 && data != 0 ) {
|
||||||
|
save_data( stream, data_offset );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
private:
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
save_header( std::ostream& stream,
|
||||||
|
std::streampos header_offset ) const
|
||||||
|
{
|
||||||
|
stream.seekp( header_offset );
|
||||||
|
stream.write( reinterpret_cast<const char*>( &header ), sizeof( header ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
save_data( std::ostream& stream,
|
||||||
|
std::streampos data_offset ) const
|
||||||
|
{
|
||||||
|
stream.seekp( data_offset );
|
||||||
|
stream.write( get_data(), get_size() );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
private:
|
||||||
|
T header;
|
||||||
|
Elf_Half index;
|
||||||
|
std::string name;
|
||||||
|
char* data;
|
||||||
|
Elf_Word data_size;
|
||||||
|
const endianess_convertor* convertor;
|
||||||
|
bool is_address_set;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ELFIO
|
||||||
|
|
||||||
|
#endif // ELFIO_SECTION_HPP
|
246
src/elfio/elfio_segment.hpp
Normal file
246
src/elfio/elfio_segment.hpp
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2001-2015 by Serge Lamikhov-Center
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ELFIO_SEGMENT_HPP
|
||||||
|
#define ELFIO_SEGMENT_HPP
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace ELFIO {
|
||||||
|
|
||||||
|
class segment
|
||||||
|
{
|
||||||
|
friend class elfio;
|
||||||
|
public:
|
||||||
|
virtual ~segment() {};
|
||||||
|
|
||||||
|
ELFIO_GET_ACCESS_DECL ( Elf_Half, index );
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type );
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, flags );
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, align );
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, virtual_address );
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, physical_address );
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, file_size );
|
||||||
|
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, memory_size );
|
||||||
|
ELFIO_GET_ACCESS_DECL( Elf64_Off, offset );
|
||||||
|
|
||||||
|
virtual const char* get_data() const = 0;
|
||||||
|
|
||||||
|
virtual Elf_Half add_section_index( Elf_Half index, Elf_Xword addr_align ) = 0;
|
||||||
|
virtual Elf_Half get_sections_num() const = 0;
|
||||||
|
virtual Elf_Half get_section_index_at( Elf_Half num ) const = 0;
|
||||||
|
virtual bool is_offset_initialized() const = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ELFIO_SET_ACCESS_DECL( Elf64_Off, offset );
|
||||||
|
ELFIO_SET_ACCESS_DECL( Elf_Half, index );
|
||||||
|
|
||||||
|
virtual const std::vector<Elf_Half>& get_sections() const = 0;
|
||||||
|
virtual void load( std::istream& stream, std::streampos header_offset ) = 0;
|
||||||
|
virtual void save( std::ostream& stream, std::streampos header_offset,
|
||||||
|
std::streampos data_offset ) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
template< class T >
|
||||||
|
class segment_impl : public segment
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
segment_impl( endianess_convertor* convertor_ ) :
|
||||||
|
stream_size( 0 ), index( 0 ), data( 0 ), convertor( convertor_ )
|
||||||
|
{
|
||||||
|
is_offset_set = false;
|
||||||
|
std::fill_n( reinterpret_cast<char*>( &ph ), sizeof( ph ), '\0' );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
virtual ~segment_impl()
|
||||||
|
{
|
||||||
|
delete [] data;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Section info functions
|
||||||
|
ELFIO_GET_SET_ACCESS( Elf_Word, type, ph.p_type );
|
||||||
|
ELFIO_GET_SET_ACCESS( Elf_Word, flags, ph.p_flags );
|
||||||
|
ELFIO_GET_SET_ACCESS( Elf_Xword, align, ph.p_align );
|
||||||
|
ELFIO_GET_SET_ACCESS( Elf64_Addr, virtual_address, ph.p_vaddr );
|
||||||
|
ELFIO_GET_SET_ACCESS( Elf64_Addr, physical_address, ph.p_paddr );
|
||||||
|
ELFIO_GET_SET_ACCESS( Elf_Xword, file_size, ph.p_filesz );
|
||||||
|
ELFIO_GET_SET_ACCESS( Elf_Xword, memory_size, ph.p_memsz );
|
||||||
|
ELFIO_GET_ACCESS( Elf64_Off, offset, ph.p_offset );
|
||||||
|
size_t stream_size;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
size_t
|
||||||
|
get_stream_size() const
|
||||||
|
{
|
||||||
|
return stream_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
set_stream_size(size_t value)
|
||||||
|
{
|
||||||
|
stream_size = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
Elf_Half
|
||||||
|
get_index() const
|
||||||
|
{
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
const char*
|
||||||
|
get_data() const
|
||||||
|
{
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
Elf_Half
|
||||||
|
add_section_index( Elf_Half sec_index, Elf_Xword addr_align )
|
||||||
|
{
|
||||||
|
sections.push_back( sec_index );
|
||||||
|
if ( addr_align > get_align() ) {
|
||||||
|
set_align( addr_align );
|
||||||
|
}
|
||||||
|
|
||||||
|
return (Elf_Half)sections.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
Elf_Half
|
||||||
|
get_sections_num() const
|
||||||
|
{
|
||||||
|
return (Elf_Half)sections.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
Elf_Half
|
||||||
|
get_section_index_at( Elf_Half num ) const
|
||||||
|
{
|
||||||
|
if ( num < sections.size() ) {
|
||||||
|
return sections[num];
|
||||||
|
}
|
||||||
|
|
||||||
|
return Elf_Half(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
protected:
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
set_offset( Elf64_Off value )
|
||||||
|
{
|
||||||
|
ph.p_offset = value;
|
||||||
|
ph.p_offset = (*convertor)( ph.p_offset );
|
||||||
|
is_offset_set = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
bool
|
||||||
|
is_offset_initialized() const
|
||||||
|
{
|
||||||
|
return is_offset_set;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
const std::vector<Elf_Half>&
|
||||||
|
get_sections() const
|
||||||
|
{
|
||||||
|
return sections;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
set_index( Elf_Half value )
|
||||||
|
{
|
||||||
|
index = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
load( std::istream& stream,
|
||||||
|
std::streampos header_offset )
|
||||||
|
{
|
||||||
|
|
||||||
|
stream.seekg ( 0, stream.end );
|
||||||
|
set_stream_size ( stream.tellg() );
|
||||||
|
|
||||||
|
stream.seekg( header_offset );
|
||||||
|
stream.read( reinterpret_cast<char*>( &ph ), sizeof( ph ) );
|
||||||
|
is_offset_set = true;
|
||||||
|
|
||||||
|
if ( PT_NULL != get_type() && 0 != get_file_size() ) {
|
||||||
|
stream.seekg( (*convertor)( ph.p_offset ) );
|
||||||
|
Elf_Xword size = get_file_size();
|
||||||
|
|
||||||
|
if ( size > get_stream_size() ) {
|
||||||
|
data = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
try {
|
||||||
|
data = new char[size + 1];
|
||||||
|
} catch (const std::bad_alloc&) {
|
||||||
|
data = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( 0 != data ) {
|
||||||
|
stream.read( data, size );
|
||||||
|
data[size] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void save( std::ostream& stream,
|
||||||
|
std::streampos header_offset,
|
||||||
|
std::streampos data_offset )
|
||||||
|
{
|
||||||
|
ph.p_offset = data_offset;
|
||||||
|
ph.p_offset = (*convertor)(ph.p_offset);
|
||||||
|
stream.seekp( header_offset );
|
||||||
|
stream.write( reinterpret_cast<const char*>( &ph ), sizeof( ph ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
private:
|
||||||
|
T ph;
|
||||||
|
Elf_Half index;
|
||||||
|
char* data;
|
||||||
|
std::vector<Elf_Half> sections;
|
||||||
|
endianess_convertor* convertor;
|
||||||
|
bool is_offset_set;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ELFIO
|
||||||
|
|
||||||
|
#endif // ELFIO_SEGMENT_HPP
|
100
src/elfio/elfio_strings.hpp
Normal file
100
src/elfio/elfio_strings.hpp
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2001-2015 by Serge Lamikhov-Center
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ELFIO_STRINGS_HPP
|
||||||
|
#define ELFIO_STRINGS_HPP
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace ELFIO {
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
template< class S >
|
||||||
|
class string_section_accessor_template
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
string_section_accessor_template( S* section_ ) :
|
||||||
|
string_section( section_ )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
const char*
|
||||||
|
get_string( Elf_Word index ) const
|
||||||
|
{
|
||||||
|
if ( string_section ) {
|
||||||
|
if ( index < string_section->get_size() ) {
|
||||||
|
const char* data = string_section->get_data();
|
||||||
|
if ( 0 != data ) {
|
||||||
|
return data + index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
Elf_Word
|
||||||
|
add_string( const char* str )
|
||||||
|
{
|
||||||
|
Elf_Word current_position = 0;
|
||||||
|
|
||||||
|
if (string_section) {
|
||||||
|
// Strings are addeded to the end of the current section data
|
||||||
|
current_position = (Elf_Word)string_section->get_size();
|
||||||
|
|
||||||
|
if ( current_position == 0 ) {
|
||||||
|
char empty_string = '\0';
|
||||||
|
string_section->append_data( &empty_string, 1 );
|
||||||
|
current_position++;
|
||||||
|
}
|
||||||
|
string_section->append_data( str, (Elf_Word)std::strlen( str ) + 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
return current_position;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
Elf_Word
|
||||||
|
add_string( const std::string& str )
|
||||||
|
{
|
||||||
|
return add_string( str.c_str() );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
private:
|
||||||
|
S* string_section;
|
||||||
|
};
|
||||||
|
|
||||||
|
using string_section_accessor = string_section_accessor_template<section>;
|
||||||
|
using const_string_section_accessor = string_section_accessor_template<const section>;
|
||||||
|
|
||||||
|
} // namespace ELFIO
|
||||||
|
|
||||||
|
#endif // ELFIO_STRINGS_HPP
|
282
src/elfio/elfio_symbols.hpp
Normal file
282
src/elfio/elfio_symbols.hpp
Normal file
@ -0,0 +1,282 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2001-2015 by Serge Lamikhov-Center
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ELFIO_SYMBOLS_HPP
|
||||||
|
#define ELFIO_SYMBOLS_HPP
|
||||||
|
|
||||||
|
namespace ELFIO {
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
template< class S >
|
||||||
|
class symbol_section_accessor_template
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
symbol_section_accessor_template( const elfio& elf_file_, S* symbol_section_ ) :
|
||||||
|
elf_file( elf_file_ ),
|
||||||
|
symbol_section( symbol_section_ )
|
||||||
|
{
|
||||||
|
find_hash_section();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
Elf_Xword
|
||||||
|
get_symbols_num() const
|
||||||
|
{
|
||||||
|
Elf_Xword nRet = 0;
|
||||||
|
if ( 0 != symbol_section->get_entry_size() ) {
|
||||||
|
nRet = symbol_section->get_size() / symbol_section->get_entry_size();
|
||||||
|
}
|
||||||
|
|
||||||
|
return nRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
bool
|
||||||
|
get_symbol( Elf_Xword index,
|
||||||
|
std::string& name,
|
||||||
|
Elf64_Addr& value,
|
||||||
|
Elf_Xword& size,
|
||||||
|
unsigned char& bind,
|
||||||
|
unsigned char& type,
|
||||||
|
Elf_Half& section_index,
|
||||||
|
unsigned char& other ) const
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
if ( elf_file.get_class() == ELFCLASS32 ) {
|
||||||
|
ret = generic_get_symbol<Elf32_Sym>( index, name, value, size, bind,
|
||||||
|
type, section_index, other );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = generic_get_symbol<Elf64_Sym>( index, name, value, size, bind,
|
||||||
|
type, section_index, other );
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
bool
|
||||||
|
get_symbol( const std::string& name,
|
||||||
|
Elf64_Addr& value,
|
||||||
|
Elf_Xword& size,
|
||||||
|
unsigned char& bind,
|
||||||
|
unsigned char& type,
|
||||||
|
Elf_Half& section_index,
|
||||||
|
unsigned char& other ) const
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
if ( 0 != get_hash_table_index() ) {
|
||||||
|
Elf_Word nbucket = *(const Elf_Word*)hash_section->get_data();
|
||||||
|
Elf_Word nchain = *(const Elf_Word*)( hash_section->get_data() +
|
||||||
|
sizeof( Elf_Word ) );
|
||||||
|
Elf_Word val = elf_hash( (const unsigned char*)name.c_str() );
|
||||||
|
|
||||||
|
Elf_Word y = *(const Elf_Word*)( hash_section->get_data() +
|
||||||
|
( 2 + val % nbucket ) * sizeof( Elf_Word ) );
|
||||||
|
std::string str;
|
||||||
|
get_symbol( y, str, value, size, bind, type, section_index, other );
|
||||||
|
while ( str != name && STN_UNDEF != y && y < nchain ) {
|
||||||
|
y = *(const Elf_Word*)( hash_section->get_data() +
|
||||||
|
( 2 + nbucket + y ) * sizeof( Elf_Word ) );
|
||||||
|
get_symbol( y, str, value, size, bind, type, section_index, other );
|
||||||
|
}
|
||||||
|
if ( str == name ) {
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
Elf_Word
|
||||||
|
add_symbol( Elf_Word name, Elf64_Addr value, Elf_Xword size,
|
||||||
|
unsigned char info, unsigned char other,
|
||||||
|
Elf_Half shndx )
|
||||||
|
{
|
||||||
|
Elf_Word nRet;
|
||||||
|
|
||||||
|
if ( symbol_section->get_size() == 0 ) {
|
||||||
|
if ( elf_file.get_class() == ELFCLASS32 ) {
|
||||||
|
nRet = generic_add_symbol<Elf32_Sym>( 0, 0, 0, 0, 0, 0 );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nRet = generic_add_symbol<Elf64_Sym>( 0, 0, 0, 0, 0, 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( elf_file.get_class() == ELFCLASS32 ) {
|
||||||
|
nRet = generic_add_symbol<Elf32_Sym>( name, value, size, info, other,
|
||||||
|
shndx );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nRet = generic_add_symbol<Elf64_Sym>( name, value, size, info, other,
|
||||||
|
shndx );
|
||||||
|
}
|
||||||
|
|
||||||
|
return nRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
Elf_Word
|
||||||
|
add_symbol( Elf_Word name, Elf64_Addr value, Elf_Xword size,
|
||||||
|
unsigned char bind, unsigned char type, unsigned char other,
|
||||||
|
Elf_Half shndx )
|
||||||
|
{
|
||||||
|
return add_symbol( name, value, size, ELF_ST_INFO( bind, type ), other, shndx );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
Elf_Word
|
||||||
|
add_symbol( string_section_accessor& pStrWriter, const char* str,
|
||||||
|
Elf64_Addr value, Elf_Xword size,
|
||||||
|
unsigned char info, unsigned char other,
|
||||||
|
Elf_Half shndx )
|
||||||
|
{
|
||||||
|
Elf_Word index = pStrWriter.add_string( str );
|
||||||
|
return add_symbol( index, value, size, info, other, shndx );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
Elf_Word
|
||||||
|
add_symbol( string_section_accessor& pStrWriter, const char* str,
|
||||||
|
Elf64_Addr value, Elf_Xword size,
|
||||||
|
unsigned char bind, unsigned char type, unsigned char other,
|
||||||
|
Elf_Half shndx )
|
||||||
|
{
|
||||||
|
return add_symbol( pStrWriter, str, value, size, ELF_ST_INFO( bind, type ), other, shndx );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
private:
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
find_hash_section()
|
||||||
|
{
|
||||||
|
hash_section = 0;
|
||||||
|
hash_section_index = 0;
|
||||||
|
Elf_Half nSecNo = elf_file.sections.size();
|
||||||
|
for ( Elf_Half i = 0; i < nSecNo && 0 == hash_section_index; ++i ) {
|
||||||
|
const section* sec = elf_file.sections[i];
|
||||||
|
if ( sec->get_link() == symbol_section->get_index() ) {
|
||||||
|
hash_section = sec;
|
||||||
|
hash_section_index = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
Elf_Half
|
||||||
|
get_string_table_index() const
|
||||||
|
{
|
||||||
|
return (Elf_Half)symbol_section->get_link();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
Elf_Half
|
||||||
|
get_hash_table_index() const
|
||||||
|
{
|
||||||
|
return hash_section_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
template< class T >
|
||||||
|
bool
|
||||||
|
generic_get_symbol( Elf_Xword index,
|
||||||
|
std::string& name, Elf64_Addr& value,
|
||||||
|
Elf_Xword& size,
|
||||||
|
unsigned char& bind, unsigned char& type,
|
||||||
|
Elf_Half& section_index,
|
||||||
|
unsigned char& other ) const
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
if ( index < get_symbols_num() ) {
|
||||||
|
const T* pSym = reinterpret_cast<const T*>(
|
||||||
|
symbol_section->get_data() +
|
||||||
|
index * symbol_section->get_entry_size() );
|
||||||
|
|
||||||
|
const endianess_convertor& convertor = elf_file.get_convertor();
|
||||||
|
|
||||||
|
section* string_section = elf_file.sections[get_string_table_index()];
|
||||||
|
string_section_accessor str_reader( string_section );
|
||||||
|
const char* pStr = str_reader.get_string( convertor( pSym->st_name ) );
|
||||||
|
if ( 0 != pStr ) {
|
||||||
|
name = pStr;
|
||||||
|
}
|
||||||
|
value = convertor( pSym->st_value );
|
||||||
|
size = convertor( pSym->st_size );
|
||||||
|
bind = ELF_ST_BIND( pSym->st_info );
|
||||||
|
type = ELF_ST_TYPE( pSym->st_info );
|
||||||
|
section_index = convertor( pSym->st_shndx );
|
||||||
|
other = pSym->st_other;
|
||||||
|
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
template< class T >
|
||||||
|
Elf_Word
|
||||||
|
generic_add_symbol( Elf_Word name, Elf64_Addr value, Elf_Xword size,
|
||||||
|
unsigned char info, unsigned char other,
|
||||||
|
Elf_Half shndx )
|
||||||
|
{
|
||||||
|
const endianess_convertor& convertor = elf_file.get_convertor();
|
||||||
|
|
||||||
|
T entry;
|
||||||
|
entry.st_name = convertor( name );
|
||||||
|
entry.st_value = value;
|
||||||
|
entry.st_value = convertor( entry.st_value );
|
||||||
|
entry.st_size = size;
|
||||||
|
entry.st_size = convertor( entry.st_size );
|
||||||
|
entry.st_info = convertor( info );
|
||||||
|
entry.st_other = convertor( other );
|
||||||
|
entry.st_shndx = convertor( shndx );
|
||||||
|
|
||||||
|
symbol_section->append_data( reinterpret_cast<char*>( &entry ),
|
||||||
|
sizeof( entry ) );
|
||||||
|
|
||||||
|
Elf_Word nRet = symbol_section->get_size() / sizeof( entry ) - 1;
|
||||||
|
|
||||||
|
return nRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
private:
|
||||||
|
const elfio& elf_file;
|
||||||
|
S* symbol_section;
|
||||||
|
Elf_Half hash_section_index;
|
||||||
|
const section* hash_section;
|
||||||
|
};
|
||||||
|
|
||||||
|
using symbol_section_accessor = symbol_section_accessor_template<section>;
|
||||||
|
using const_symbol_section_accessor = symbol_section_accessor_template<const section>;
|
||||||
|
|
||||||
|
} // namespace ELFIO
|
||||||
|
|
||||||
|
#endif // ELFIO_SYMBOLS_HPP
|
209
src/elfio/elfio_utils.hpp
Normal file
209
src/elfio/elfio_utils.hpp
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2001-2015 by Serge Lamikhov-Center
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ELFIO_UTILS_HPP
|
||||||
|
#define ELFIO_UTILS_HPP
|
||||||
|
|
||||||
|
#define ELFIO_GET_ACCESS( TYPE, NAME, FIELD ) \
|
||||||
|
TYPE get_##NAME() const \
|
||||||
|
{ \
|
||||||
|
return (*convertor)( FIELD ); \
|
||||||
|
}
|
||||||
|
#define ELFIO_SET_ACCESS( TYPE, NAME, FIELD ) \
|
||||||
|
void set_##NAME( TYPE value ) \
|
||||||
|
{ \
|
||||||
|
FIELD = value; \
|
||||||
|
FIELD = (*convertor)( FIELD ); \
|
||||||
|
}
|
||||||
|
#define ELFIO_GET_SET_ACCESS( TYPE, NAME, FIELD ) \
|
||||||
|
TYPE get_##NAME() const \
|
||||||
|
{ \
|
||||||
|
return (*convertor)( FIELD ); \
|
||||||
|
} \
|
||||||
|
void set_##NAME( TYPE value ) \
|
||||||
|
{ \
|
||||||
|
FIELD = value; \
|
||||||
|
FIELD = (*convertor)( FIELD ); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ELFIO_GET_ACCESS_DECL( TYPE, NAME ) \
|
||||||
|
virtual TYPE get_##NAME() const = 0
|
||||||
|
|
||||||
|
#define ELFIO_SET_ACCESS_DECL( TYPE, NAME ) \
|
||||||
|
virtual void set_##NAME( TYPE value ) = 0
|
||||||
|
|
||||||
|
#define ELFIO_GET_SET_ACCESS_DECL( TYPE, NAME ) \
|
||||||
|
virtual TYPE get_##NAME() const = 0; \
|
||||||
|
virtual void set_##NAME( TYPE value ) = 0
|
||||||
|
|
||||||
|
namespace ELFIO {
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
class endianess_convertor {
|
||||||
|
public:
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
endianess_convertor()
|
||||||
|
{
|
||||||
|
need_conversion = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
setup( unsigned char elf_file_encoding )
|
||||||
|
{
|
||||||
|
need_conversion = ( elf_file_encoding != get_host_encoding() );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
uint64_t
|
||||||
|
operator()( uint64_t value ) const
|
||||||
|
{
|
||||||
|
if ( !need_conversion ) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
value =
|
||||||
|
( ( value & 0x00000000000000FFull ) << 56 ) |
|
||||||
|
( ( value & 0x000000000000FF00ull ) << 40 ) |
|
||||||
|
( ( value & 0x0000000000FF0000ull ) << 24 ) |
|
||||||
|
( ( value & 0x00000000FF000000ull ) << 8 ) |
|
||||||
|
( ( value & 0x000000FF00000000ull ) >> 8 ) |
|
||||||
|
( ( value & 0x0000FF0000000000ull ) >> 24 ) |
|
||||||
|
( ( value & 0x00FF000000000000ull ) >> 40 ) |
|
||||||
|
( ( value & 0xFF00000000000000ull ) >> 56 );
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
int64_t
|
||||||
|
operator()( int64_t value ) const
|
||||||
|
{
|
||||||
|
if ( !need_conversion ) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return (int64_t)(*this)( (uint64_t)value );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
uint32_t
|
||||||
|
operator()( uint32_t value ) const
|
||||||
|
{
|
||||||
|
if ( !need_conversion ) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
value =
|
||||||
|
( ( value & 0x000000FF ) << 24 ) |
|
||||||
|
( ( value & 0x0000FF00 ) << 8 ) |
|
||||||
|
( ( value & 0x00FF0000 ) >> 8 ) |
|
||||||
|
( ( value & 0xFF000000 ) >> 24 );
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
int32_t
|
||||||
|
operator()( int32_t value ) const
|
||||||
|
{
|
||||||
|
if ( !need_conversion ) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return (int32_t)(*this)( (uint32_t)value );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
uint16_t
|
||||||
|
operator()( uint16_t value ) const
|
||||||
|
{
|
||||||
|
if ( !need_conversion ) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
value =
|
||||||
|
( ( value & 0x00FF ) << 8 ) |
|
||||||
|
( ( value & 0xFF00 ) >> 8 );
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
int16_t
|
||||||
|
operator()( int16_t value ) const
|
||||||
|
{
|
||||||
|
if ( !need_conversion ) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return (int16_t)(*this)( (uint16_t)value );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
int8_t
|
||||||
|
operator()( int8_t value ) const
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
uint8_t
|
||||||
|
operator()( uint8_t value ) const
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
private:
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
unsigned char
|
||||||
|
get_host_encoding() const
|
||||||
|
{
|
||||||
|
static const int tmp = 1;
|
||||||
|
if ( 1 == *(const char*)&tmp ) {
|
||||||
|
return ELFDATA2LSB;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return ELFDATA2MSB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
private:
|
||||||
|
bool need_conversion;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
inline
|
||||||
|
uint32_t
|
||||||
|
elf_hash( const unsigned char *name )
|
||||||
|
{
|
||||||
|
uint32_t h = 0, g;
|
||||||
|
while ( *name ) {
|
||||||
|
h = (h << 4) + *name++;
|
||||||
|
g = h & 0xf0000000;
|
||||||
|
if ( g != 0 )
|
||||||
|
h ^= g >> 24;
|
||||||
|
h &= ~g;
|
||||||
|
}
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ELFIO
|
||||||
|
|
||||||
|
#endif // ELFIO_UTILS_HPP
|
24
src/import_stub.S
Normal file
24
src/import_stub.S
Normal 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
281
src/imports.h
Normal 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
40
src/kernel.cpp
Normal 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
10
src/kernel.h
Normal 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
210
src/kernel_asm.S
Normal 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
26
src/link.ld
Normal 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
126
src/main.cpp
Normal 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
16
src/main.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
//Main.h
|
||||||
|
#ifndef _MAIN_H_
|
||||||
|
#define _MAIN_H_
|
||||||
|
|
||||||
|
|
||||||
|
/* Main */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
104
src/module/DynamicLinkingHelper.cpp
Normal file
104
src/module/DynamicLinkingHelper.cpp
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
#include "DynamicLinkingHelper.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <coreinit/dynload.h>
|
||||||
|
#include "utils/logger.h"
|
||||||
|
#include "common/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;
|
||||||
|
}
|
60
src/module/DynamicLinkingHelper.h
Normal file
60
src/module/DynamicLinkingHelper.h
Normal 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() {
|
||||||
|
}
|
||||||
|
};
|
67
src/module/ImportRPLInformation.h
Normal file
67
src/module/ImportRPLInformation.h
Normal 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
12
src/module/ModuleData.cpp
Normal 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
88
src/module/ModuleData.h
Normal 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;
|
||||||
|
};
|
247
src/module/ModuleDataFactory.cpp
Normal file
247
src/module/ModuleDataFactory.cpp
Normal 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;
|
||||||
|
}
|
32
src/module/ModuleDataFactory.h
Normal file
32
src/module/ModuleDataFactory.h
Normal 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);
|
||||||
|
};
|
106
src/module/ModuleDataPersistence.cpp
Normal file
106
src/module/ModuleDataPersistence.cpp
Normal 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;
|
||||||
|
}
|
10
src/module/ModuleDataPersistence.h
Normal file
10
src/module/ModuleDataPersistence.h
Normal 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);
|
||||||
|
};
|
6
src/module/RelocationData.cpp
Normal file
6
src/module/RelocationData.cpp
Normal 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() );
|
||||||
|
}
|
73
src/module/RelocationData.h
Normal file
73
src/module/RelocationData.h
Normal 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
60
src/utils/FSOSUtils.cpp
Normal 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
13
src/utils/FSOSUtils.h
Normal 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
290
src/utils/StringTools.cpp
Normal 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
52
src/utils/StringTools.h
Normal 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
82
src/utils/logger.c
Normal 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
38
src/utils/logger.h
Normal 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
107
src/utils/memory.c
Normal 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
42
src/utils/memory.h
Normal 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_
|
1016
src/utils/sd_fat_devoptab.cpp
Normal file
1016
src/utils/sd_fat_devoptab.cpp
Normal file
File diff suppressed because it is too large
Load Diff
40
src/utils/sd_fat_devoptab.h
Normal file
40
src/utils/sd_fat_devoptab.h
Normal 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
41
src/utils/utils.c
Normal 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
35
src/utils/utils.h
Normal 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_
|
Loading…
Reference in New Issue
Block a user