Big update!
- Source code added - Readme, gitignore, banner and the license are updated
30
.gitignore
vendored
@@ -1,4 +1,30 @@
|
|||||||
/target
|
/target
|
||||||
/.vscode
|
|
||||||
/tests
|
|
||||||
Cargo.lock
|
Cargo.lock
|
||||||
|
|
||||||
|
# This part is taken from GitHub's macOS gitignore template
|
||||||
|
# General
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# Icon must end with two \r
|
||||||
|
Icon
|
||||||
|
|
||||||
|
# Thumbnails
|
||||||
|
._*
|
||||||
|
|
||||||
|
# Files that might appear in the root of a volume
|
||||||
|
.DocumentRevisions-V100
|
||||||
|
.fseventsd
|
||||||
|
.Spotlight-V100
|
||||||
|
.TemporaryItems
|
||||||
|
.Trashes
|
||||||
|
.VolumeIcon.icns
|
||||||
|
.com.apple.timemachine.donotpresent
|
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
.apdisk
|
||||||
|
|||||||
8
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
8
.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/unildd.iml" filepath="$PROJECT_DIR$/.idea/unildd.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
11
.idea/unildd.iml
generated
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="EMPTY_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
26
Cargo.toml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
[package]
|
||||||
|
name = "unildd"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
authors = ["nix-enthusiast"]
|
||||||
|
license = "BSD-3"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
# Object parsing library
|
||||||
|
goblin = { version = "0.8.2"}
|
||||||
|
|
||||||
|
# For creating static HashMaps
|
||||||
|
phf = { version = "0.11.2", features = ["macros"] }
|
||||||
|
|
||||||
|
# Coloring
|
||||||
|
owo-colors = "4.1.0"
|
||||||
|
|
||||||
|
# For old Windows CMD
|
||||||
|
anstream = "0.6.15"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "unildd"
|
||||||
|
crate-type = ["cdylib", "staticlib"]
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
strip = true
|
||||||
532
LICENSE
@@ -1,504 +1,28 @@
|
|||||||
GNU LESSER GENERAL PUBLIC LICENSE
|
BSD 3-Clause License
|
||||||
Version 2.1, February 1999
|
|
||||||
|
Copyright (c) 2024, nix-enthusiast
|
||||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
Redistribution and use in source and binary forms, with or without
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
modification, are permitted provided that the following conditions are met:
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
[This is the first released version of the Lesser GPL. It also counts
|
list of conditions and the following disclaimer.
|
||||||
as the successor of the GNU Library Public License, version 2, hence
|
|
||||||
the version number 2.1.]
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
Preamble
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
The licenses for most software are designed to take away your
|
3. Neither the name of the copyright holder nor the names of its
|
||||||
freedom to share and change it. By contrast, the GNU General Public
|
contributors may be used to endorse or promote products derived from
|
||||||
Licenses are intended to guarantee your freedom to share and change
|
this software without specific prior written permission.
|
||||||
free software--to make sure the software is free for all its users.
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
This license, the Lesser General Public License, applies to some
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
specially designated software packages--typically libraries--of the
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
Free Software Foundation and other authors who decide to use it. You
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
can use it too, but we suggest you first think carefully about whether
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
this license or the ordinary General Public License is the better
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
strategy to use in any particular case, based on the explanations below.
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
When we speak of free software, we are referring to freedom of use,
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
not price. Our General Public Licenses are designed to make sure that
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
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 and use pieces of
|
|
||||||
it in new free programs; and that you are informed that you can do
|
|
||||||
these things.
|
|
||||||
|
|
||||||
To protect your rights, we need to make restrictions that forbid
|
|
||||||
distributors to deny you these rights or to ask you to surrender these
|
|
||||||
rights. These restrictions translate to certain responsibilities for
|
|
||||||
you if you distribute copies of the library or if you modify it.
|
|
||||||
|
|
||||||
For example, if you distribute copies of the library, whether gratis
|
|
||||||
or for a fee, you must give the recipients all the rights that we gave
|
|
||||||
you. You must make sure that they, too, receive or can get the source
|
|
||||||
code. If you link other code with the library, you must provide
|
|
||||||
complete object files to the recipients, so that they can relink them
|
|
||||||
with the library after making changes to the library and recompiling
|
|
||||||
it. And you must show them these terms so they know their rights.
|
|
||||||
|
|
||||||
We protect your rights with a two-step method: (1) we copyright the
|
|
||||||
library, and (2) we offer you this license, which gives you legal
|
|
||||||
permission to copy, distribute and/or modify the library.
|
|
||||||
|
|
||||||
To protect each distributor, we want to make it very clear that
|
|
||||||
there is no warranty for the free library. Also, if the library is
|
|
||||||
modified by someone else and passed on, the recipients should know
|
|
||||||
that what they have is not the original version, so that the original
|
|
||||||
author's reputation will not be affected by problems that might be
|
|
||||||
introduced by others.
|
|
||||||
|
|
||||||
Finally, software patents pose a constant threat to the existence of
|
|
||||||
any free program. We wish to make sure that a company cannot
|
|
||||||
effectively restrict the users of a free program by obtaining a
|
|
||||||
restrictive license from a patent holder. Therefore, we insist that
|
|
||||||
any patent license obtained for a version of the library must be
|
|
||||||
consistent with the full freedom of use specified in this license.
|
|
||||||
|
|
||||||
Most GNU software, including some libraries, is covered by the
|
|
||||||
ordinary GNU General Public License. This license, the GNU Lesser
|
|
||||||
General Public License, applies to certain designated libraries, and
|
|
||||||
is quite different from the ordinary General Public License. We use
|
|
||||||
this license for certain libraries in order to permit linking those
|
|
||||||
libraries into non-free programs.
|
|
||||||
|
|
||||||
When a program is linked with a library, whether statically or using
|
|
||||||
a shared library, the combination of the two is legally speaking a
|
|
||||||
combined work, a derivative of the original library. The ordinary
|
|
||||||
General Public License therefore permits such linking only if the
|
|
||||||
entire combination fits its criteria of freedom. The Lesser General
|
|
||||||
Public License permits more lax criteria for linking other code with
|
|
||||||
the library.
|
|
||||||
|
|
||||||
We call this license the "Lesser" General Public License because it
|
|
||||||
does Less to protect the user's freedom than the ordinary General
|
|
||||||
Public License. It also provides other free software developers Less
|
|
||||||
of an advantage over competing non-free programs. These disadvantages
|
|
||||||
are the reason we use the ordinary General Public License for many
|
|
||||||
libraries. However, the Lesser license provides advantages in certain
|
|
||||||
special circumstances.
|
|
||||||
|
|
||||||
For example, on rare occasions, there may be a special need to
|
|
||||||
encourage the widest possible use of a certain library, so that it becomes
|
|
||||||
a de-facto standard. To achieve this, non-free programs must be
|
|
||||||
allowed to use the library. A more frequent case is that a free
|
|
||||||
library does the same job as widely used non-free libraries. In this
|
|
||||||
case, there is little to gain by limiting the free library to free
|
|
||||||
software only, so we use the Lesser General Public License.
|
|
||||||
|
|
||||||
In other cases, permission to use a particular library in non-free
|
|
||||||
programs enables a greater number of people to use a large body of
|
|
||||||
free software. For example, permission to use the GNU C Library in
|
|
||||||
non-free programs enables many more people to use the whole GNU
|
|
||||||
operating system, as well as its variant, the GNU/Linux operating
|
|
||||||
system.
|
|
||||||
|
|
||||||
Although the Lesser General Public License is Less protective of the
|
|
||||||
users' freedom, it does ensure that the user of a program that is
|
|
||||||
linked with the Library has the freedom and the wherewithal to run
|
|
||||||
that program using a modified version of the Library.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
|
||||||
modification follow. Pay close attention to the difference between a
|
|
||||||
"work based on the library" and a "work that uses the library". The
|
|
||||||
former contains code derived from the library, whereas the latter must
|
|
||||||
be combined with the library in order to run.
|
|
||||||
|
|
||||||
GNU LESSER GENERAL PUBLIC LICENSE
|
|
||||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
||||||
|
|
||||||
0. This License Agreement applies to any software library or other
|
|
||||||
program which contains a notice placed by the copyright holder or
|
|
||||||
other authorized party saying it may be distributed under the terms of
|
|
||||||
this Lesser General Public License (also called "this License").
|
|
||||||
Each licensee is addressed as "you".
|
|
||||||
|
|
||||||
A "library" means a collection of software functions and/or data
|
|
||||||
prepared so as to be conveniently linked with application programs
|
|
||||||
(which use some of those functions and data) to form executables.
|
|
||||||
|
|
||||||
The "Library", below, refers to any such software library or work
|
|
||||||
which has been distributed under these terms. A "work based on the
|
|
||||||
Library" means either the Library or any derivative work under
|
|
||||||
copyright law: that is to say, a work containing the Library or a
|
|
||||||
portion of it, either verbatim or with modifications and/or translated
|
|
||||||
straightforwardly into another language. (Hereinafter, translation is
|
|
||||||
included without limitation in the term "modification".)
|
|
||||||
|
|
||||||
"Source code" for a work means the preferred form of the work for
|
|
||||||
making modifications to it. For a library, 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 library.
|
|
||||||
|
|
||||||
Activities other than copying, distribution and modification are not
|
|
||||||
covered by this License; they are outside its scope. The act of
|
|
||||||
running a program using the Library is not restricted, and output from
|
|
||||||
such a program is covered only if its contents constitute a work based
|
|
||||||
on the Library (independent of the use of the Library in a tool for
|
|
||||||
writing it). Whether that is true depends on what the Library does
|
|
||||||
and what the program that uses the Library does.
|
|
||||||
|
|
||||||
1. You may copy and distribute verbatim copies of the Library's
|
|
||||||
complete 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 distribute a copy of this License along with the
|
|
||||||
Library.
|
|
||||||
|
|
||||||
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 Library or any portion
|
|
||||||
of it, thus forming a work based on the Library, 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) The modified work must itself be a software library.
|
|
||||||
|
|
||||||
b) You must cause the files modified to carry prominent notices
|
|
||||||
stating that you changed the files and the date of any change.
|
|
||||||
|
|
||||||
c) You must cause the whole of the work to be licensed at no
|
|
||||||
charge to all third parties under the terms of this License.
|
|
||||||
|
|
||||||
d) If a facility in the modified Library refers to a function or a
|
|
||||||
table of data to be supplied by an application program that uses
|
|
||||||
the facility, other than as an argument passed when the facility
|
|
||||||
is invoked, then you must make a good faith effort to ensure that,
|
|
||||||
in the event an application does not supply such function or
|
|
||||||
table, the facility still operates, and performs whatever part of
|
|
||||||
its purpose remains meaningful.
|
|
||||||
|
|
||||||
(For example, a function in a library to compute square roots has
|
|
||||||
a purpose that is entirely well-defined independent of the
|
|
||||||
application. Therefore, Subsection 2d requires that any
|
|
||||||
application-supplied function or table used by this function must
|
|
||||||
be optional: if the application does not supply it, the square
|
|
||||||
root function must still compute square roots.)
|
|
||||||
|
|
||||||
These requirements apply to the modified work as a whole. If
|
|
||||||
identifiable sections of that work are not derived from the Library,
|
|
||||||
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 Library, 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 Library.
|
|
||||||
|
|
||||||
In addition, mere aggregation of another work not based on the Library
|
|
||||||
with the Library (or with a work based on the Library) on a volume of
|
|
||||||
a storage or distribution medium does not bring the other work under
|
|
||||||
the scope of this License.
|
|
||||||
|
|
||||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
|
||||||
License instead of this License to a given copy of the Library. To do
|
|
||||||
this, you must alter all the notices that refer to this License, so
|
|
||||||
that they refer to the ordinary GNU General Public License, version 2,
|
|
||||||
instead of to this License. (If a newer version than version 2 of the
|
|
||||||
ordinary GNU General Public License has appeared, then you can specify
|
|
||||||
that version instead if you wish.) Do not make any other change in
|
|
||||||
these notices.
|
|
||||||
|
|
||||||
Once this change is made in a given copy, it is irreversible for
|
|
||||||
that copy, so the ordinary GNU General Public License applies to all
|
|
||||||
subsequent copies and derivative works made from that copy.
|
|
||||||
|
|
||||||
This option is useful when you wish to copy part of the code of
|
|
||||||
the Library into a program that is not a library.
|
|
||||||
|
|
||||||
4. You may copy and distribute the Library (or a portion or
|
|
||||||
derivative of it, under Section 2) in object code or executable form
|
|
||||||
under the terms of Sections 1 and 2 above provided that you 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.
|
|
||||||
|
|
||||||
If distribution of 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 satisfies the requirement to
|
|
||||||
distribute the source code, even though third parties are not
|
|
||||||
compelled to copy the source along with the object code.
|
|
||||||
|
|
||||||
5. A program that contains no derivative of any portion of the
|
|
||||||
Library, but is designed to work with the Library by being compiled or
|
|
||||||
linked with it, is called a "work that uses the Library". Such a
|
|
||||||
work, in isolation, is not a derivative work of the Library, and
|
|
||||||
therefore falls outside the scope of this License.
|
|
||||||
|
|
||||||
However, linking a "work that uses the Library" with the Library
|
|
||||||
creates an executable that is a derivative of the Library (because it
|
|
||||||
contains portions of the Library), rather than a "work that uses the
|
|
||||||
library". The executable is therefore covered by this License.
|
|
||||||
Section 6 states terms for distribution of such executables.
|
|
||||||
|
|
||||||
When a "work that uses the Library" uses material from a header file
|
|
||||||
that is part of the Library, the object code for the work may be a
|
|
||||||
derivative work of the Library even though the source code is not.
|
|
||||||
Whether this is true is especially significant if the work can be
|
|
||||||
linked without the Library, or if the work is itself a library. The
|
|
||||||
threshold for this to be true is not precisely defined by law.
|
|
||||||
|
|
||||||
If such an object file uses only numerical parameters, data
|
|
||||||
structure layouts and accessors, and small macros and small inline
|
|
||||||
functions (ten lines or less in length), then the use of the object
|
|
||||||
file is unrestricted, regardless of whether it is legally a derivative
|
|
||||||
work. (Executables containing this object code plus portions of the
|
|
||||||
Library will still fall under Section 6.)
|
|
||||||
|
|
||||||
Otherwise, if the work is a derivative of the Library, you may
|
|
||||||
distribute the object code for the work under the terms of Section 6.
|
|
||||||
Any executables containing that work also fall under Section 6,
|
|
||||||
whether or not they are linked directly with the Library itself.
|
|
||||||
|
|
||||||
6. As an exception to the Sections above, you may also combine or
|
|
||||||
link a "work that uses the Library" with the Library to produce a
|
|
||||||
work containing portions of the Library, and distribute that work
|
|
||||||
under terms of your choice, provided that the terms permit
|
|
||||||
modification of the work for the customer's own use and reverse
|
|
||||||
engineering for debugging such modifications.
|
|
||||||
|
|
||||||
You must give prominent notice with each copy of the work that the
|
|
||||||
Library is used in it and that the Library and its use are covered by
|
|
||||||
this License. You must supply a copy of this License. If the work
|
|
||||||
during execution displays copyright notices, you must include the
|
|
||||||
copyright notice for the Library among them, as well as a reference
|
|
||||||
directing the user to the copy of this License. Also, you must do one
|
|
||||||
of these things:
|
|
||||||
|
|
||||||
a) Accompany the work with the complete corresponding
|
|
||||||
machine-readable source code for the Library including whatever
|
|
||||||
changes were used in the work (which must be distributed under
|
|
||||||
Sections 1 and 2 above); and, if the work is an executable linked
|
|
||||||
with the Library, with the complete machine-readable "work that
|
|
||||||
uses the Library", as object code and/or source code, so that the
|
|
||||||
user can modify the Library and then relink to produce a modified
|
|
||||||
executable containing the modified Library. (It is understood
|
|
||||||
that the user who changes the contents of definitions files in the
|
|
||||||
Library will not necessarily be able to recompile the application
|
|
||||||
to use the modified definitions.)
|
|
||||||
|
|
||||||
b) Use a suitable shared library mechanism for linking with the
|
|
||||||
Library. A suitable mechanism is one that (1) uses at run time a
|
|
||||||
copy of the library already present on the user's computer system,
|
|
||||||
rather than copying library functions into the executable, and (2)
|
|
||||||
will operate properly with a modified version of the library, if
|
|
||||||
the user installs one, as long as the modified version is
|
|
||||||
interface-compatible with the version that the work was made with.
|
|
||||||
|
|
||||||
c) Accompany the work with a written offer, valid for at
|
|
||||||
least three years, to give the same user the materials
|
|
||||||
specified in Subsection 6a, above, for a charge no more
|
|
||||||
than the cost of performing this distribution.
|
|
||||||
|
|
||||||
d) If distribution of the work is made by offering access to copy
|
|
||||||
from a designated place, offer equivalent access to copy the above
|
|
||||||
specified materials from the same place.
|
|
||||||
|
|
||||||
e) Verify that the user has already received a copy of these
|
|
||||||
materials or that you have already sent this user a copy.
|
|
||||||
|
|
||||||
For an executable, the required form of the "work that uses the
|
|
||||||
Library" must include any data and utility programs needed for
|
|
||||||
reproducing the executable from it. However, as a special exception,
|
|
||||||
the materials to be 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.
|
|
||||||
|
|
||||||
It may happen that this requirement contradicts the license
|
|
||||||
restrictions of other proprietary libraries that do not normally
|
|
||||||
accompany the operating system. Such a contradiction means you cannot
|
|
||||||
use both them and the Library together in an executable that you
|
|
||||||
distribute.
|
|
||||||
|
|
||||||
7. You may place library facilities that are a work based on the
|
|
||||||
Library side-by-side in a single library together with other library
|
|
||||||
facilities not covered by this License, and distribute such a combined
|
|
||||||
library, provided that the separate distribution of the work based on
|
|
||||||
the Library and of the other library facilities is otherwise
|
|
||||||
permitted, and provided that you do these two things:
|
|
||||||
|
|
||||||
a) Accompany the combined library with a copy of the same work
|
|
||||||
based on the Library, uncombined with any other library
|
|
||||||
facilities. This must be distributed under the terms of the
|
|
||||||
Sections above.
|
|
||||||
|
|
||||||
b) Give prominent notice with the combined library of the fact
|
|
||||||
that part of it is a work based on the Library, and explaining
|
|
||||||
where to find the accompanying uncombined form of the same work.
|
|
||||||
|
|
||||||
8. You may not copy, modify, sublicense, link with, or distribute
|
|
||||||
the Library except as expressly provided under this License. Any
|
|
||||||
attempt otherwise to copy, modify, sublicense, link with, or
|
|
||||||
distribute the Library 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.
|
|
||||||
|
|
||||||
9. 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 Library or its derivative works. These actions are
|
|
||||||
prohibited by law if you do not accept this License. Therefore, by
|
|
||||||
modifying or distributing the Library (or any work based on the
|
|
||||||
Library), you indicate your acceptance of this License to do so, and
|
|
||||||
all its terms and conditions for copying, distributing or modifying
|
|
||||||
the Library or works based on it.
|
|
||||||
|
|
||||||
10. Each time you redistribute the Library (or any work based on the
|
|
||||||
Library), the recipient automatically receives a license from the
|
|
||||||
original licensor to copy, distribute, link with or modify the Library
|
|
||||||
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 with
|
|
||||||
this License.
|
|
||||||
|
|
||||||
11. 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 Library at all. For example, if a patent
|
|
||||||
license would not permit royalty-free redistribution of the Library 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 Library.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
12. If the distribution and/or use of the Library is restricted in
|
|
||||||
certain countries either by patents or by copyrighted interfaces, the
|
|
||||||
original copyright holder who places the Library 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.
|
|
||||||
|
|
||||||
13. The Free Software Foundation may publish revised and/or new
|
|
||||||
versions of the Lesser 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 Library
|
|
||||||
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 Library does not specify a
|
|
||||||
license version number, you may choose any version ever published by
|
|
||||||
the Free Software Foundation.
|
|
||||||
|
|
||||||
14. If you wish to incorporate parts of the Library into other free
|
|
||||||
programs whose distribution conditions are incompatible with these,
|
|
||||||
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
|
|
||||||
|
|
||||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
|
||||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
|
||||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
|
||||||
OTHER PARTIES PROVIDE THE LIBRARY "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
|
|
||||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
|
||||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
|
||||||
|
|
||||||
16. 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 LIBRARY 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
|
|
||||||
LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries
|
|
||||||
|
|
||||||
If you develop a new library, and you want it to be of the greatest
|
|
||||||
possible use to the public, we recommend making it free software that
|
|
||||||
everyone can redistribute and change. You can do so by permitting
|
|
||||||
redistribution under these terms (or, alternatively, under the terms of the
|
|
||||||
ordinary General Public License).
|
|
||||||
|
|
||||||
To apply these terms, attach the following notices to the library. 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.
|
|
||||||
|
|
||||||
<one line to give the library's name and a brief idea of what it does.>
|
|
||||||
Copyright (C) <year> <name of author>
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library 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
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; 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.
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or your
|
|
||||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
|
||||||
necessary. Here is a sample; alter the names:
|
|
||||||
|
|
||||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
|
||||||
library `Frob' (a library for tweaking knobs) written by James Random
|
|
||||||
Hacker.
|
|
||||||
|
|
||||||
<signature of Ty Coon>, 1 April 1990
|
|
||||||
Ty Coon, President of Vice
|
|
||||||
|
|
||||||
That's all there is to it!
|
|
||||||
53
README.md
@@ -1,4 +1,51 @@
|
|||||||
# unildd
|

|
||||||
UniLDD - A Portable Object Parsing Library
|
|
||||||
|
|
||||||
Currently Work In Progress
|
### UniLDD is designed to bring parsing objects to any language (has a C FFI library).
|
||||||
|
|
||||||
|
### ⭐️ Features:
|
||||||
|
- Detailed information! Some of them are:
|
||||||
|
- Name of the OS (Windows, macOS, Linux, etc.)
|
||||||
|
- File type (Core dump, shared library, executable, etc.)
|
||||||
|
- ISA type (X86_64, ARM64, RISC-V, etc.)
|
||||||
|
- CPU Subtype[^1]
|
||||||
|
- Name of the linker[^2]
|
||||||
|
- Which libraries are linked against
|
||||||
|
- Parses without loading objects. Therefore, you can even parse shady objects like malwares![^3]
|
||||||
|
- Error codes and explanations to make error handling easier.
|
||||||
|
- A Basic and built-in logger to get real-time information.
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
Basically:
|
||||||
|
- Clone the git repository:
|
||||||
|
|
||||||
|
`git clone https://github.com/nix-enthusiast/unildd.git`
|
||||||
|
|
||||||
|
- Go into the git repository:
|
||||||
|
|
||||||
|
`cd unildd`
|
||||||
|
|
||||||
|
- Compile build with cargo:
|
||||||
|
|
||||||
|
`cargo build --release`
|
||||||
|
|
||||||
|
- Put the output files to desired destination:
|
||||||
|
|
||||||
|
`cp target/release/{libunildd.so,libunildd.a} /my/amazing/project/`
|
||||||
|
|
||||||
|
- Also do not forget to copy the header file:
|
||||||
|
|
||||||
|
`cp header/unildd.h /my/amazing/project/`
|
||||||
|
|
||||||
|
### License
|
||||||
|
This library is licensed with [BSD-3 Clause License](https://choosealicense.com/licenses/bsd-3-clause/)
|
||||||
|
|
||||||
|
The resources used to make this library are cited as comments in the respective source files which they were used.
|
||||||
|
|
||||||
|
### 🎉 Thanks to:
|
||||||
|
- [m4b](https://github.com/m4b) for the [goblin](https://github.com/m4b/goblin) crate which this library gets its power by!
|
||||||
|
|
||||||
|
[^1]: CPU subtype is a macOS-only feature which tells what kind of CPU model the code is optimized for.
|
||||||
|
|
||||||
|
[^2]: It has some caveats. See the wiki (currently work-in-progress) for further details.
|
||||||
|
|
||||||
|
[^3]: That doesn't mean I am liable for any damages done by this project and files you parsed. Take your own risk!
|
||||||
|
|||||||
162
header/unildd.h
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* An error struct for making error handling easy.
|
||||||
|
*
|
||||||
|
* ## Error Codes
|
||||||
|
* - \>0: Magic number of the unknown object (as `i64` (or `ìnt64_t))
|
||||||
|
* - -1: Binary is corrupted
|
||||||
|
* - -2: Unknown/Bad magic number
|
||||||
|
* - -3: Error at reading and interpreting bytes
|
||||||
|
* - -4: I/O Error at parsing the object
|
||||||
|
* - -5: Buffer is too short to hold
|
||||||
|
* - -6: Unknown error[^1]
|
||||||
|
* - -7: Unimplemented executable format
|
||||||
|
*
|
||||||
|
* [^1]: All errors thrown by goblin crate and my code are covered. Because of matching goblin's [`Error`](goblin::error::Error) is non-exhaustive, I included non-exhaustive path too.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef struct ParsingError {
|
||||||
|
int64_t code;
|
||||||
|
char *explanation;
|
||||||
|
} ParsingError;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A C-compatible vector for `Vec<String>`.
|
||||||
|
*/
|
||||||
|
typedef struct CharVec {
|
||||||
|
uintptr_t capacity;
|
||||||
|
uintptr_t length;
|
||||||
|
char **vec;
|
||||||
|
} CharVec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* A struct contains detailed information about the object.
|
||||||
|
*
|
||||||
|
* It contains some information even the object is an erroneous one to make error handling more verbose.
|
||||||
|
*
|
||||||
|
* If the error occurs on parsing:
|
||||||
|
* - A file: `file_name` and `member_name`
|
||||||
|
* - A Muti Architecture Mach-O file: `file_name`, `member_name` and `executable_format`
|
||||||
|
* - An archive: `file_name`, `member_name` and `file_type`
|
||||||
|
*
|
||||||
|
* fields will be filled correctly and the rest will be:
|
||||||
|
* - null (the fields which are string)
|
||||||
|
* - blank (`member_name` and `libraries`)
|
||||||
|
* - `false` (`is_64` and `is_stripped`).
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef struct ULDDObj {
|
||||||
|
/**
|
||||||
|
* The name of the object.
|
||||||
|
*
|
||||||
|
* Objects inside Muti Architecture Mach-O files will be named as "n. file" due to they don't have file names.
|
||||||
|
*/
|
||||||
|
char *file_name;
|
||||||
|
/**
|
||||||
|
* The location of objects in recursive files.
|
||||||
|
*
|
||||||
|
* This field is empty if the object is not in a recursive file (Like: Archives and Muti Architecture Mach-O files).
|
||||||
|
*
|
||||||
|
* The names in the vector is sorted as outer to inner.
|
||||||
|
*/
|
||||||
|
struct CharVec member_name;
|
||||||
|
/**
|
||||||
|
* The type of the executable format of the object.
|
||||||
|
*/
|
||||||
|
char *executable_format;
|
||||||
|
/**
|
||||||
|
* The field is true if the object is 64 bit otherwise it is 32 bit or the object is an erroneous one.
|
||||||
|
*/
|
||||||
|
bool is_64;
|
||||||
|
/**
|
||||||
|
* The name of the OS it was compiled for.
|
||||||
|
*/
|
||||||
|
char *os_type;
|
||||||
|
/**
|
||||||
|
* The type of the object.
|
||||||
|
*/
|
||||||
|
char *file_type;
|
||||||
|
/**
|
||||||
|
* The field is true if the object was stripped from debug symbols otherwise it is not stripped or the object is an erroneous one .
|
||||||
|
*/
|
||||||
|
bool is_stripped;
|
||||||
|
/**
|
||||||
|
* The ISA (CPU Architecture) the object compiled for.
|
||||||
|
*/
|
||||||
|
char *cpu_type;
|
||||||
|
/**
|
||||||
|
* The specific CPU model the object compiled for.
|
||||||
|
*
|
||||||
|
* macOS only field. It is null pointer in other executable formats.
|
||||||
|
*/
|
||||||
|
char *cpu_subtype;
|
||||||
|
/**
|
||||||
|
* The name/version of the linker.
|
||||||
|
*
|
||||||
|
* ELF/PE only field. It is null pointer in other executable formats.
|
||||||
|
*
|
||||||
|
* It returns the version of the linker in PE files.
|
||||||
|
*/
|
||||||
|
char *interpreter;
|
||||||
|
/**
|
||||||
|
* A vector of libraries linked against the object.
|
||||||
|
*
|
||||||
|
* It is blank in COFF files because they are mostly PE object files therefore they don't have linked libraries against them.
|
||||||
|
*/
|
||||||
|
struct CharVec libraries;
|
||||||
|
} ULDDObj;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A struct packs (empty or filled) error and (successfully or not) read object.
|
||||||
|
*/
|
||||||
|
typedef struct ULDDObjResult {
|
||||||
|
struct ParsingError error;
|
||||||
|
struct ULDDObj obj;
|
||||||
|
} ULDDObjResult;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A C-compatible vector for [`ULDDObjResult`].
|
||||||
|
*/
|
||||||
|
typedef struct ULDDObjResultVec {
|
||||||
|
uintptr_t capacity;
|
||||||
|
uintptr_t length;
|
||||||
|
struct ULDDObjResult *vec;
|
||||||
|
} ULDDObjResultVec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Parses the given buffer and returns a vector of parsed binaries.
|
||||||
|
*
|
||||||
|
* # Safety
|
||||||
|
*
|
||||||
|
* This function is null pointer-safe. If the file name is an invalid UTF-8 string and/or buffer pointer is a null pointer it will panic.
|
||||||
|
*
|
||||||
|
* Since the function returns a [`ULDDObjResultVec`] created by rust it has to be [deallocated](free_obj) by rust if it is done by other languages errors may occur.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct ULDDObjResultVec read_obj(const char *file_name,
|
||||||
|
const uint8_t *buffer,
|
||||||
|
uintptr_t buffer_size,
|
||||||
|
bool debugging);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* # Safety
|
||||||
|
*
|
||||||
|
* This function is designed for deallocating [`ULDDObjResultVec`] created by rust. Trying to deallocating [`ULDDObjResultVec`] created by other languages may result with errors.
|
||||||
|
*
|
||||||
|
* It is null pointer-safe.
|
||||||
|
*
|
||||||
|
* ## Error codes:
|
||||||
|
* - 0: No errors
|
||||||
|
* - 1: `vec` field of [`ULDDObjResultVec`] is a null pointer
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint8_t free_obj(struct ULDDObjResultVec obj,
|
||||||
|
bool debugging);
|
||||||
BIN
media/banner/UniLDD Banner.png
Normal file → Executable file
|
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 120 KiB |
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
0
media/emblems/UniLDD-%100.png
Normal file → Executable file
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
0
media/emblems/UniLDD-%400.png
Normal file → Executable file
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 3.0 KiB |
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
43
src/archive.rs
Executable file
@@ -0,0 +1,43 @@
|
|||||||
|
use crate::{
|
||||||
|
debug::{debug_objects, find_error_type, merge_members},
|
||||||
|
parse_objects,
|
||||||
|
structs::{CharVec, Debugging, ParsingError, StringPtr, ULDDObj, ULDDObjResult},
|
||||||
|
};
|
||||||
|
use goblin::archive::Archive;
|
||||||
|
|
||||||
|
pub(crate) fn parse_archive<'a>(
|
||||||
|
file_name: &'a str,
|
||||||
|
buffer: &'a [u8],
|
||||||
|
archive: Archive<'a>,
|
||||||
|
member_names: &mut Vec<&'a str>,
|
||||||
|
objects: &mut Vec<ULDDObjResult>,
|
||||||
|
debugging: bool,
|
||||||
|
) {
|
||||||
|
for member in archive.members() {
|
||||||
|
member_names.push(file_name);
|
||||||
|
let member_buffer = match archive.extract(member, buffer) {
|
||||||
|
Ok(buf) => buf,
|
||||||
|
Err(error) => {
|
||||||
|
Debugging::Error(format!("Error while extracting the bytes of the member named '{}' from buffer of the file named '{}'{}\nDetails:\n{}",
|
||||||
|
member,
|
||||||
|
file_name,
|
||||||
|
merge_members(member_names),
|
||||||
|
error)).print(debugging);
|
||||||
|
return objects.push(ULDDObjResult {
|
||||||
|
error: ParsingError {
|
||||||
|
code: find_error_type(&error),
|
||||||
|
explanation: StringPtr::from(error.to_string()).0,
|
||||||
|
},
|
||||||
|
obj: ULDDObj {
|
||||||
|
file_name: StringPtr::from(file_name).0,
|
||||||
|
member_name: CharVec::from(member_names),
|
||||||
|
file_type: StringPtr::from("Archive").0,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
debug_objects(file_name, member_names, "an archive file", debugging);
|
||||||
|
parse_objects(member, member_buffer, member_names, objects, debugging);
|
||||||
|
}
|
||||||
|
}
|
||||||
40
src/coff.rs
Executable file
@@ -0,0 +1,40 @@
|
|||||||
|
use crate::{
|
||||||
|
debug::debug_objects,
|
||||||
|
structs::{CharVec, ParsingError, StringPtr, ULDDObj, ULDDObjResult},
|
||||||
|
types::PE_ARCH,
|
||||||
|
};
|
||||||
|
use goblin::pe::{
|
||||||
|
characteristic::{IMAGE_FILE_32BIT_MACHINE, IMAGE_FILE_DEBUG_STRIPPED},
|
||||||
|
Coff,
|
||||||
|
};
|
||||||
|
use std::ptr::null_mut;
|
||||||
|
|
||||||
|
pub(crate) fn parse_coff(
|
||||||
|
file_name: &str,
|
||||||
|
coff: Coff,
|
||||||
|
member_names: &mut Vec<&str>,
|
||||||
|
debugging: bool,
|
||||||
|
) -> ULDDObjResult {
|
||||||
|
// Thanks to developers of goblin for making me to find out that I can "bitwise and" characteristics and wanted characteristics to find out if the COFF file has the one we want
|
||||||
|
let is_64 = coff.header.characteristics & IMAGE_FILE_32BIT_MACHINE != IMAGE_FILE_32BIT_MACHINE;
|
||||||
|
let is_stripped =
|
||||||
|
coff.header.characteristics & IMAGE_FILE_DEBUG_STRIPPED == IMAGE_FILE_DEBUG_STRIPPED;
|
||||||
|
let cpu_type = StringPtr::from(PE_ARCH.get(&coff.header.machine)).0;
|
||||||
|
debug_objects(file_name, member_names, "a COFF binary", debugging);
|
||||||
|
ULDDObjResult {
|
||||||
|
error: ParsingError::default(),
|
||||||
|
obj: ULDDObj {
|
||||||
|
file_name: StringPtr::from(file_name).0,
|
||||||
|
member_name: CharVec::from(member_names),
|
||||||
|
executable_format: StringPtr::from("COFF").0,
|
||||||
|
is_64,
|
||||||
|
os_type: StringPtr::from("Windows").0,
|
||||||
|
file_type: StringPtr::from("Windows object file").0,
|
||||||
|
is_stripped,
|
||||||
|
cpu_type,
|
||||||
|
cpu_subtype: null_mut(),
|
||||||
|
interpreter: null_mut(),
|
||||||
|
libraries: CharVec::default(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
37
src/debug.rs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
use goblin::error::Error as ObjectError;
|
||||||
|
|
||||||
|
use crate::structs::Debugging;
|
||||||
|
|
||||||
|
pub(crate) fn find_error_type(error: &ObjectError) -> i64 {
|
||||||
|
match error {
|
||||||
|
ObjectError::Malformed(_) => -1,
|
||||||
|
ObjectError::BadMagic(_) => -2,
|
||||||
|
ObjectError::Scroll(_) => -3,
|
||||||
|
ObjectError::BufferTooShort(_, _) => -4,
|
||||||
|
ObjectError::IO(_) => -5,
|
||||||
|
_ => -6,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn merge_members(member_names: &mut [&str]) -> String {
|
||||||
|
if !member_names.is_empty() {
|
||||||
|
format!(" (Member of: {})", member_names.join(" -> "))
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn debug_objects(
|
||||||
|
file_name: &str,
|
||||||
|
member_names: &mut [&str],
|
||||||
|
object_name: &str,
|
||||||
|
debugging: bool,
|
||||||
|
) {
|
||||||
|
Debugging::Info(format!(
|
||||||
|
"The binary named '{}'{} is {}",
|
||||||
|
file_name,
|
||||||
|
merge_members(member_names),
|
||||||
|
object_name
|
||||||
|
))
|
||||||
|
.print(debugging)
|
||||||
|
}
|
||||||
133
src/elf.rs
Executable file
@@ -0,0 +1,133 @@
|
|||||||
|
use std::ptr::null_mut;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
debug::debug_objects,
|
||||||
|
structs::{CharVec, ParsingError, StringPtr, ULDDObj, ULDDObjResult},
|
||||||
|
types::{ElfFileType, ElfOS, E_MACHINE, E_TYPE},
|
||||||
|
};
|
||||||
|
use goblin::elf::Elf;
|
||||||
|
|
||||||
|
fn find_os_from_strtab_elf(elf: &Elf<'_>, pat: &[&str]) -> bool {
|
||||||
|
[
|
||||||
|
elf.strtab.to_vec().unwrap_or(vec![""]),
|
||||||
|
elf.shdr_strtab.to_vec().unwrap_or(vec![""]),
|
||||||
|
elf.dynstrtab.to_vec().unwrap_or(vec![""]),
|
||||||
|
]
|
||||||
|
.iter()
|
||||||
|
.flatten()
|
||||||
|
.any(|s| pat.iter().any(|i| s.to_lowercase().contains(i)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_os_elf(elf: &Elf<'_>, os_abi: u8) -> (ElfOS, *mut i8) {
|
||||||
|
let os = {
|
||||||
|
match os_abi {
|
||||||
|
0x00 => match true {
|
||||||
|
_ if find_os_from_strtab_elf(elf, &["fbsd"]) => ElfOS::FreeBSD,
|
||||||
|
_ if find_os_from_strtab_elf(elf, &["openbsd"]) => ElfOS::OpenBSD,
|
||||||
|
_ if find_os_from_strtab_elf(elf, &["musl", "glibc", "linux"]) => ElfOS::Linux,
|
||||||
|
_ if find_os_from_strtab_elf(elf, &["android"]) => ElfOS::Android,
|
||||||
|
_ if find_os_from_strtab_elf(elf, &["netbsd"]) => ElfOS::NetBSD,
|
||||||
|
_ if find_os_from_strtab_elf(elf, &["solaris"]) => ElfOS::Solaris,
|
||||||
|
_ if find_os_from_strtab_elf(elf, &["illumos"]) => ElfOS::Illumos,
|
||||||
|
_ if elf.interpreter.is_some_and(|v| v.contains("Loader.so")) => ElfOS::SerenityOS,
|
||||||
|
_ => return (ElfOS::Undefined, null_mut()),
|
||||||
|
},
|
||||||
|
0x01 => ElfOS::HPUX,
|
||||||
|
0x02 => ElfOS::NetBSD,
|
||||||
|
0x03 => ElfOS::Linux,
|
||||||
|
0x04 => ElfOS::GNUHurd,
|
||||||
|
0x06 => {
|
||||||
|
if find_os_from_strtab_elf(elf, &["illumos"]) {
|
||||||
|
ElfOS::Illumos
|
||||||
|
} else {
|
||||||
|
ElfOS::Solaris
|
||||||
|
}
|
||||||
|
}
|
||||||
|
0x07 => ElfOS::AIXMonterey,
|
||||||
|
0x08 => ElfOS::IRIX,
|
||||||
|
0x09 => ElfOS::FreeBSD,
|
||||||
|
0x10 => ElfOS::FenixOS,
|
||||||
|
0x11 => ElfOS::CloudABI,
|
||||||
|
0x12 => ElfOS::OpenVOS,
|
||||||
|
0x0A => ElfOS::Tru64,
|
||||||
|
0x0B => ElfOS::NovellModesto,
|
||||||
|
0x0C => ElfOS::OpenBSD,
|
||||||
|
0x0D => ElfOS::OpenVMS,
|
||||||
|
0x0E => ElfOS::NonStopKernel,
|
||||||
|
0x0F => ElfOS::AROS,
|
||||||
|
_ => return (ElfOS::Undefined, null_mut()),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
(os, StringPtr::from(os.to_string()).0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_linux_vdso(e_machine: u16, bit_type: bool) -> Option<&'static str> {
|
||||||
|
match e_machine {
|
||||||
|
0x3E => Some("linux-vdso.so.1"),
|
||||||
|
0x03 => Some("linux-vdso.so.1"),
|
||||||
|
0x2A => Some("linux-gate.so.1"),
|
||||||
|
0x16 => {
|
||||||
|
if bit_type {
|
||||||
|
Some("linux-vdso64.so.1")
|
||||||
|
} else {
|
||||||
|
Some("linux-vdso32.so.1")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
0xF3 => Some("linux-vdso.so.1"),
|
||||||
|
0x15 => Some("linux-vdso64.so.1"),
|
||||||
|
0x14 => Some("linux-vdso32.so.1"),
|
||||||
|
0x08 => Some("linux-vdso.so.1"),
|
||||||
|
0x32 => Some("linux-gate.so.1"),
|
||||||
|
0x28 => Some("linux-vdso.so.1"),
|
||||||
|
0xB7 => Some("linux-vdso.so.1"),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_libraries_into_char_vec(elf: &mut Elf, os_abi: u8) -> CharVec {
|
||||||
|
let mut vector = std::mem::take(&mut elf.libraries);
|
||||||
|
if let (Some(vdso), ElfOS::Linux) = (
|
||||||
|
find_linux_vdso(elf.header.e_machine, elf.is_64),
|
||||||
|
find_os_elf(elf, os_abi).0,
|
||||||
|
) {
|
||||||
|
vector.push(vdso)
|
||||||
|
}
|
||||||
|
|
||||||
|
CharVec::from(vector)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn parse_elf(
|
||||||
|
file_name: &str,
|
||||||
|
elf: Elf,
|
||||||
|
os_abi: u8,
|
||||||
|
member_names: &mut Vec<&str>,
|
||||||
|
debugging: bool,
|
||||||
|
) -> ULDDObjResult {
|
||||||
|
let mut elf = elf;
|
||||||
|
let cpu_type = StringPtr::from(E_MACHINE.get(&elf.header.e_machine)).0;
|
||||||
|
let file_type = match E_TYPE.get(&elf.header.e_type) {
|
||||||
|
_ if elf.header.e_type == 0x03 && elf.interpreter.is_some() => {
|
||||||
|
StringPtr::from(ElfFileType::Executable.to_string()).0
|
||||||
|
}
|
||||||
|
rest => StringPtr::from(rest).0,
|
||||||
|
};
|
||||||
|
let interpreter = StringPtr::from(elf.interpreter).0;
|
||||||
|
debug_objects(file_name, member_names, "an ELF binary", debugging);
|
||||||
|
ULDDObjResult {
|
||||||
|
error: ParsingError::default(),
|
||||||
|
obj: ULDDObj {
|
||||||
|
file_name: StringPtr::from(file_name).0,
|
||||||
|
member_name: CharVec::from(member_names),
|
||||||
|
executable_format: StringPtr::from("ELF").0,
|
||||||
|
is_64: elf.is_64,
|
||||||
|
os_type: find_os_elf(&elf, os_abi).1,
|
||||||
|
file_type,
|
||||||
|
is_stripped: elf.syms.is_empty(),
|
||||||
|
cpu_type,
|
||||||
|
cpu_subtype: null_mut(),
|
||||||
|
interpreter,
|
||||||
|
libraries: convert_libraries_into_char_vec(&mut elf, os_abi),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
152
src/impls.rs
Executable file
@@ -0,0 +1,152 @@
|
|||||||
|
use crate::{
|
||||||
|
structs::{CharVec, Debugging, ParsingError, StringPtr, ULDDObj},
|
||||||
|
ULDDObjResult, ULDDObjResultVec,
|
||||||
|
};
|
||||||
|
use anstream::{eprintln as a_eprintln, println as a_println};
|
||||||
|
use owo_colors::OwoColorize;
|
||||||
|
use std::{fmt::Display, mem::ManuallyDrop, ptr::null_mut, ffi::{c_char, CString}};
|
||||||
|
|
||||||
|
impl From<Vec<*mut c_char>> for CharVec {
|
||||||
|
fn from(value: Vec<*mut c_char>) -> Self {
|
||||||
|
CharVec {
|
||||||
|
capacity: value.capacity(),
|
||||||
|
length: value.len(),
|
||||||
|
vec: if value.is_empty() {
|
||||||
|
null_mut()
|
||||||
|
} else {
|
||||||
|
ManuallyDrop::new(value).as_mut_ptr()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Vec<ULDDObjResult>> for ULDDObjResultVec {
|
||||||
|
fn from(value: Vec<ULDDObjResult>) -> Self {
|
||||||
|
ULDDObjResultVec {
|
||||||
|
capacity: value.capacity(),
|
||||||
|
length: value.len(),
|
||||||
|
vec: if value.is_empty() {
|
||||||
|
null_mut()
|
||||||
|
} else {
|
||||||
|
ManuallyDrop::new(value).as_mut_ptr()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for CharVec {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
capacity: 0,
|
||||||
|
length: 0,
|
||||||
|
vec: null_mut(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Vec<&str>> for CharVec {
|
||||||
|
fn from(val: Vec<&str>) -> Self {
|
||||||
|
let vector: Vec<*mut c_char> = val
|
||||||
|
.into_iter()
|
||||||
|
.map(|item| unsafe {
|
||||||
|
CString::from_vec_unchecked(item.to_string().into_bytes()).into_raw()
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
CharVec::from(vector)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&mut Vec<&str>> for CharVec {
|
||||||
|
fn from(val: &mut Vec<&str>) -> Self {
|
||||||
|
let vector: Vec<*mut c_char> = std::mem::take(val)
|
||||||
|
.into_iter()
|
||||||
|
.map(|item| unsafe {
|
||||||
|
CString::from_vec_unchecked(item.to_string().into_bytes()).into_raw()
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
CharVec::from(vector)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<String> for StringPtr {
|
||||||
|
fn from(value: String) -> Self {
|
||||||
|
let mut value = value;
|
||||||
|
value.push('\0');
|
||||||
|
let c_string = match CString::from_vec_with_nul(value.into_bytes()) {
|
||||||
|
Ok(string) => string,
|
||||||
|
Err(error) => {
|
||||||
|
Debugging::Fatal("converting the string into a C string".to_owned()).print(true);
|
||||||
|
panic!("{}", error)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
StringPtr(c_string.into_raw())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&str> for StringPtr {
|
||||||
|
fn from(value: &str) -> Self {
|
||||||
|
StringPtr::from(value.to_owned())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> From<Option<T>> for StringPtr
|
||||||
|
where
|
||||||
|
T: Display,
|
||||||
|
{
|
||||||
|
fn from(value: Option<T>) -> Self {
|
||||||
|
let Some(t) = value else {
|
||||||
|
return StringPtr(null_mut());
|
||||||
|
};
|
||||||
|
StringPtr::from(t.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ParsingError {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
code: 0,
|
||||||
|
explanation: null_mut(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ULDDObj {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
file_name: null_mut(),
|
||||||
|
member_name: Default::default(),
|
||||||
|
executable_format: null_mut(),
|
||||||
|
is_64: false,
|
||||||
|
os_type: null_mut(),
|
||||||
|
file_type: null_mut(),
|
||||||
|
is_stripped: false,
|
||||||
|
cpu_type: null_mut(),
|
||||||
|
cpu_subtype: null_mut(),
|
||||||
|
interpreter: null_mut(),
|
||||||
|
libraries: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debugging {
|
||||||
|
pub(crate) fn print(self, debugging: bool) {
|
||||||
|
if debugging {
|
||||||
|
match self {
|
||||||
|
Debugging::Info(msg) => {
|
||||||
|
a_println!("{} {}", "[INFO]".yellow().bold(), msg);
|
||||||
|
}
|
||||||
|
Debugging::Affirmative(msg) => {
|
||||||
|
a_println!("{} {}", "[OK]".green().bold(), msg);
|
||||||
|
}
|
||||||
|
Debugging::Error(msg) => {
|
||||||
|
a_eprintln!("{} {}", "[ERROR]".red().bold(), msg);
|
||||||
|
}
|
||||||
|
Debugging::Fatal(msg) => {
|
||||||
|
a_eprintln!("{} Library got a fatal error while {}. Panic function will halt the library and provide a stacktrace.", "[FATAL]".red().bold(), msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
286
src/lib.rs
Executable file
@@ -0,0 +1,286 @@
|
|||||||
|
#![doc(
|
||||||
|
html_favicon_url = "https://github.com/nix-enthusiast/unildd/blob/main/media/emblems/UniLDD-%25100.png?raw=true"
|
||||||
|
)]
|
||||||
|
#![doc(
|
||||||
|
html_logo_url = "https://github.com/nix-enthusiast/unildd/blob/main/media/emblems/UniLDD-%25400.png?raw=true"
|
||||||
|
)]
|
||||||
|
#![doc(html_playground_url = "https://play.rust-lang.org/")]
|
||||||
|
//!
|
||||||
|
//! 
|
||||||
|
//!
|
||||||
|
//! ### UniLDD is designed for bringing parsing objects to any language (has a C FFI library).
|
||||||
|
//!
|
||||||
|
//! ### ⭐️ Features:
|
||||||
|
//! - Detailed information! Some of them are:
|
||||||
|
//! - Name of the OS
|
||||||
|
//! - File type (Core dump, shared library, executable, etc.)
|
||||||
|
//! - ISA type (X86_64, Aarch64, RISC-V, etc.)
|
||||||
|
//! - CPU Subtype[^1]
|
||||||
|
//! - Name of the linker[^2]
|
||||||
|
//! - Which libraries are linked
|
||||||
|
//! - Parses without loading objects. Therefore, you can even parse shady objects like malwares![^3]
|
||||||
|
//! - Error codes and explanations to make error handling easier.
|
||||||
|
//! - A Basic and built-in logger to get real-time information.
|
||||||
|
//!
|
||||||
|
//! [^1]: CPU subtype is a macOS-only feature which tells what kind of CPU model the code is optimized for.
|
||||||
|
//!
|
||||||
|
//! [^2]: It has some caveats. See [`ULDDObj`] for further details.
|
||||||
|
//!
|
||||||
|
//! [^3]: That doesn't mean I am liable for any damages done by this project and files you parsed. Take your own risk!
|
||||||
|
//!
|
||||||
|
use archive::parse_archive;
|
||||||
|
use coff::parse_coff;
|
||||||
|
use debug::{find_error_type, merge_members};
|
||||||
|
use elf::parse_elf;
|
||||||
|
use goblin::Object;
|
||||||
|
use mach::parse_mach;
|
||||||
|
use owo_colors::OwoColorize;
|
||||||
|
use pe::parse_pe;
|
||||||
|
use std::ffi::{c_char, CStr, CString};
|
||||||
|
use structs::{
|
||||||
|
CharVec, Debugging, ParsingError, StringPtr, ULDDObj, ULDDObjResult, ULDDObjResultVec,
|
||||||
|
};
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub mod archive;
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub mod coff;
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub mod debug;
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub mod elf;
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub mod impls;
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub mod mach;
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub mod pe;
|
||||||
|
|
||||||
|
pub mod structs;
|
||||||
|
pub mod types;
|
||||||
|
|
||||||
|
fn parse_objects<'a>(
|
||||||
|
file_name: &'a str,
|
||||||
|
buffer: &'a [u8],
|
||||||
|
member_names: &mut Vec<&'a str>,
|
||||||
|
objects: &mut Vec<ULDDObjResult>,
|
||||||
|
debugging: bool,
|
||||||
|
) {
|
||||||
|
match Object::parse(buffer) {
|
||||||
|
Ok(Object::Archive(archive)) => {
|
||||||
|
parse_archive(file_name, buffer, archive, member_names, objects, debugging)
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Object::Mach(mach)) => {
|
||||||
|
parse_mach(file_name, buffer, mach, member_names, objects, debugging)
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Object::Elf(elf)) => {
|
||||||
|
objects.push(parse_elf(
|
||||||
|
file_name,
|
||||||
|
elf,
|
||||||
|
buffer[0x7],
|
||||||
|
member_names,
|
||||||
|
debugging,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Object::PE(pe)) => objects.push(parse_pe(file_name, pe, member_names, debugging)),
|
||||||
|
|
||||||
|
Ok(Object::COFF(coff)) => {
|
||||||
|
objects.push(parse_coff(file_name, coff, member_names, debugging));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Object::Unknown(magic_number)) => {
|
||||||
|
let msg = format!(
|
||||||
|
"The binary named '{}'{} has a unknown magic number (in big-endian): {}",
|
||||||
|
file_name,
|
||||||
|
merge_members(member_names),
|
||||||
|
format!("{:02X?}", magic_number.to_be_bytes()).replace(['[', ']', ','], "")
|
||||||
|
);
|
||||||
|
Debugging::Error(msg.to_owned()).print(debugging);
|
||||||
|
objects.push(ULDDObjResult {
|
||||||
|
error: ParsingError {
|
||||||
|
code: magic_number as i64,
|
||||||
|
explanation: StringPtr::from(msg).0,
|
||||||
|
},
|
||||||
|
obj: ULDDObj {
|
||||||
|
file_name: StringPtr::from(file_name).0,
|
||||||
|
member_name: CharVec::from(member_names),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(_) => {
|
||||||
|
let msg = format!(
|
||||||
|
"The executable format of the file named '{}'{} is not yet implemented",
|
||||||
|
file_name,
|
||||||
|
merge_members(member_names),
|
||||||
|
);
|
||||||
|
Debugging::Error(msg.to_string()).print(debugging);
|
||||||
|
Debugging::Info(format!(
|
||||||
|
"First 16 bytes of the file named '{}' are {}",
|
||||||
|
file_name,
|
||||||
|
format!("{:02X?}", &buffer[0..17]).replace(['[', ']', ','], "")
|
||||||
|
))
|
||||||
|
.print(debugging);
|
||||||
|
|
||||||
|
objects.push(ULDDObjResult {
|
||||||
|
error: ParsingError {
|
||||||
|
code: -7,
|
||||||
|
explanation: StringPtr::from(msg).0,
|
||||||
|
},
|
||||||
|
obj: ULDDObj {
|
||||||
|
file_name: StringPtr::from(file_name).0,
|
||||||
|
member_name: CharVec::from(member_names),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(error) => {
|
||||||
|
Debugging::Error(format!(
|
||||||
|
"Error while parsing the bytes of the given file named '{}'{}\nDetails:\n{}",
|
||||||
|
file_name,
|
||||||
|
merge_members(member_names),
|
||||||
|
error
|
||||||
|
))
|
||||||
|
.print(debugging);
|
||||||
|
|
||||||
|
objects.push(ULDDObjResult {
|
||||||
|
error: ParsingError {
|
||||||
|
code: find_error_type(&error),
|
||||||
|
explanation: StringPtr::from(error.to_string()).0,
|
||||||
|
},
|
||||||
|
obj: ULDDObj {
|
||||||
|
file_name: StringPtr::from(file_name).0,
|
||||||
|
member_name: CharVec::from(member_names),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Parses the given buffer and returns a vector of parsed binaries.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// This function is null pointer-safe. If the file name is an invalid UTF-8 string and/or buffer pointer is a null pointer it will panic.
|
||||||
|
///
|
||||||
|
/// Since the function returns a [`ULDDObjResultVec`] created by rust it has to be [deallocated](free_obj) by rust if it is done by other languages errors may occur.
|
||||||
|
///
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn read_obj(
|
||||||
|
file_name: *const c_char,
|
||||||
|
buffer: *const u8,
|
||||||
|
buffer_size: usize,
|
||||||
|
debugging: bool,
|
||||||
|
) -> ULDDObjResultVec {
|
||||||
|
let (buf, f_name) = unsafe {
|
||||||
|
let s = match CStr::from_ptr(file_name).to_str() {
|
||||||
|
Ok(string_slice) => string_slice,
|
||||||
|
Err(error) => {
|
||||||
|
Debugging::Fatal("converting the C string to a &str".to_owned()).print(true);
|
||||||
|
panic!("{}", error)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let b = std::slice::from_raw_parts(buffer, buffer_size);
|
||||||
|
(b, s)
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut objects = vec![];
|
||||||
|
parse_objects(f_name, buf, &mut vec![], &mut objects, debugging);
|
||||||
|
let (total, success, failed): (usize, usize, usize) = {
|
||||||
|
let t = objects.len();
|
||||||
|
let (mut s, mut f) = (0, 0);
|
||||||
|
objects.iter().for_each(|o| {
|
||||||
|
if o.error.code != 0 {
|
||||||
|
f += 1;
|
||||||
|
} else {
|
||||||
|
s += 1
|
||||||
|
}
|
||||||
|
});
|
||||||
|
(t, s, f)
|
||||||
|
};
|
||||||
|
|
||||||
|
Debugging::Affirmative(format!(
|
||||||
|
"{} binaries from the file(s) are parsed. Success/Fail rate of parsing(s) is {}/{}",
|
||||||
|
total,
|
||||||
|
success.green(),
|
||||||
|
failed.red()
|
||||||
|
))
|
||||||
|
.print(debugging);
|
||||||
|
|
||||||
|
ULDDObjResultVec::from(objects)
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn drop_c_string(ptr: *mut i8) {
|
||||||
|
if !ptr.is_null() {
|
||||||
|
let _ = CString::from_raw(ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// This function is designed for deallocating [`ULDDObjResultVec`] created by rust. Trying to deallocating [`ULDDObjResultVec`] created by other languages may result with errors.
|
||||||
|
///
|
||||||
|
/// It is null pointer-safe.
|
||||||
|
///
|
||||||
|
/// ## Error codes:
|
||||||
|
/// - 0: No errors
|
||||||
|
/// - 1: `vec` field of [`ULDDObjResultVec`] is a null pointer
|
||||||
|
///
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn free_obj(obj: ULDDObjResultVec, debugging: bool) -> u8 {
|
||||||
|
if obj.vec.is_null() {
|
||||||
|
Debugging::Error("Given object vector is invalid".to_owned()).print(debugging);
|
||||||
|
|
||||||
|
Debugging::Error("Deallocation(s) is failed".to_owned()).print(debugging);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
let object_vector = Vec::from_raw_parts(obj.vec, obj.length, obj.capacity);
|
||||||
|
for (index, object) in object_vector.into_iter().enumerate() {
|
||||||
|
Debugging::Info(format!("{}. object is being deallocated", index + 1)).print(debugging);
|
||||||
|
|
||||||
|
let o = object.obj;
|
||||||
|
drop_c_string(object.error.explanation);
|
||||||
|
drop_c_string(o.file_name);
|
||||||
|
drop_c_string(o.executable_format);
|
||||||
|
drop_c_string(o.os_type);
|
||||||
|
drop_c_string(o.file_type);
|
||||||
|
drop_c_string(o.cpu_type);
|
||||||
|
drop_c_string(o.cpu_subtype);
|
||||||
|
drop_c_string(o.interpreter);
|
||||||
|
if !o.member_name.vec.is_null() {
|
||||||
|
let member_names = Vec::from_raw_parts(
|
||||||
|
o.member_name.vec,
|
||||||
|
o.member_name.length,
|
||||||
|
o.member_name.capacity,
|
||||||
|
);
|
||||||
|
for name in member_names {
|
||||||
|
drop_c_string(name)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if !o.libraries.vec.is_null() {
|
||||||
|
let libraries =
|
||||||
|
Vec::from_raw_parts(o.libraries.vec, o.libraries.length, o.libraries.capacity);
|
||||||
|
for library in libraries {
|
||||||
|
drop_c_string(library)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Debugging::Affirmative(format!("{}. object is deallocated", index + 1)).print(debugging);
|
||||||
|
}
|
||||||
|
|
||||||
|
Debugging::Affirmative(format!(
|
||||||
|
"Deallocation(s) is successful. {} object(s) is freed.",
|
||||||
|
obj.length
|
||||||
|
))
|
||||||
|
.print(debugging);
|
||||||
|
|
||||||
|
0
|
||||||
|
}
|
||||||
206
src/mach.rs
Executable file
@@ -0,0 +1,206 @@
|
|||||||
|
use crate::{
|
||||||
|
debug::{debug_objects, find_error_type, merge_members},
|
||||||
|
structs::{CharVec, Debugging, ParsingError, StringPtr, ULDDObj, ULDDObjResult},
|
||||||
|
types::{
|
||||||
|
MachOCpuType, MachOOs, MACH_O_ARM_CPU_SUBTYPE, MACH_O_CPUTYPE, MACH_O_FILE_TYPE,
|
||||||
|
MACH_O_X86_CPU_SUBTYPE,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use goblin::mach::{load_command::CommandVariant::BuildVersion, Mach, MachO};
|
||||||
|
use std::ptr::null_mut;
|
||||||
|
|
||||||
|
fn find_os_mach(mach: &MachO<'_>) -> *mut i8 {
|
||||||
|
for lc in &mach.load_commands {
|
||||||
|
if let BuildVersion(build_version) = lc.command {
|
||||||
|
let os = match build_version.platform {
|
||||||
|
0x01 => MachOOs::MacOS,
|
||||||
|
0x02 => MachOOs::IOS,
|
||||||
|
0x03 => MachOOs::AppleTVBox,
|
||||||
|
0x04 => MachOOs::AppleWatch,
|
||||||
|
0x05 => MachOOs::BridgeOS,
|
||||||
|
0x06 => MachOOs::MacCatalyst,
|
||||||
|
0x07 => MachOOs::IOSSimulator,
|
||||||
|
0x08 => MachOOs::AppleTVSimulator,
|
||||||
|
0x09 => MachOOs::AppleWatchSimulator,
|
||||||
|
0x0A => MachOOs::DriverKit,
|
||||||
|
0x0B => MachOOs::AppleVisionPro,
|
||||||
|
0x0C => MachOOs::AppleVisionProSimulator,
|
||||||
|
_ => return null_mut(),
|
||||||
|
};
|
||||||
|
return StringPtr::from(os.to_string()).0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
I will leave it there because I may use later
|
||||||
|
|
||||||
|
fn decode_further(mach: &MachO<'_>) {
|
||||||
|
for lc in &mach.load_commands {
|
||||||
|
if let BuildVersion(build_version) = lc.command {
|
||||||
|
let os = match build_version.platform {
|
||||||
|
0x01 => MachOOs::MacOS,
|
||||||
|
0x02 => MachOOs::IOS,
|
||||||
|
0x03 => MachOOs::AppleTVBox,
|
||||||
|
0x04 => MachOOs::AppleWatch,
|
||||||
|
0x05 => MachOOs::BridgeOS,
|
||||||
|
0x06 => MachOOs::MacCatalyst,
|
||||||
|
0x07 => MachOOs::IOSSimulator,
|
||||||
|
0x08 => MachOOs::AppleTVSimulator,
|
||||||
|
0x09 => MachOOs::AppleWatchSimulator,
|
||||||
|
0x0A => MachOOs::DriverKit,
|
||||||
|
0x0B => MachOOs::AppleVisionPro,
|
||||||
|
0x0C => MachOOs::AppleVisionProSimulator,
|
||||||
|
_ => MachOOs::Undefined,
|
||||||
|
};
|
||||||
|
let os_ver = {
|
||||||
|
let [_, x, y, z] = build_version.minos.to_be_bytes();
|
||||||
|
format!("{x}.{y}.{z}")
|
||||||
|
};
|
||||||
|
let sdk_ver = {
|
||||||
|
let [_, x, y, z] = build_version.sdk.to_be_bytes();
|
||||||
|
format!("{x}.{y}.{z}")
|
||||||
|
};
|
||||||
|
let tool_type = match build_version.ntools {
|
||||||
|
0x1 => "Clang",
|
||||||
|
0x2 => "Swift",
|
||||||
|
0x3 => "Linked with ld",
|
||||||
|
_ => "Unknown"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
pub(crate) fn parse_mach<'a>(
|
||||||
|
file_name: &'a str,
|
||||||
|
buffer: &[u8],
|
||||||
|
mach: Mach,
|
||||||
|
member_names: &mut Vec<&'a str>,
|
||||||
|
objects: &mut Vec<ULDDObjResult>,
|
||||||
|
debugging: bool,
|
||||||
|
) {
|
||||||
|
match mach {
|
||||||
|
Mach::Fat(fat) => {
|
||||||
|
debug_objects(
|
||||||
|
file_name,
|
||||||
|
member_names,
|
||||||
|
"a multi architecture Mach-O",
|
||||||
|
debugging,
|
||||||
|
);
|
||||||
|
let fat_arches = match fat.arches() {
|
||||||
|
Ok(arches) => arches,
|
||||||
|
Err(error) => {
|
||||||
|
Debugging::Error(format!("Error while reading the multi architecture Mach-O binary named '{}'{}\nDetails:\n{}",
|
||||||
|
file_name,
|
||||||
|
merge_members(member_names),
|
||||||
|
error)).print(debugging);
|
||||||
|
|
||||||
|
return objects.push(ULDDObjResult {
|
||||||
|
error: ParsingError {
|
||||||
|
code: find_error_type(&error),
|
||||||
|
explanation: StringPtr::from(error.to_string()).0,
|
||||||
|
},
|
||||||
|
obj: ULDDObj {
|
||||||
|
file_name: StringPtr::from(file_name).0,
|
||||||
|
member_name: CharVec::from(member_names),
|
||||||
|
executable_format: StringPtr::from("Mach-O").0,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (index, arch) in fat_arches.iter().enumerate() {
|
||||||
|
match MachO::parse(buffer, arch.offset as usize) {
|
||||||
|
Ok(mach_o) => {
|
||||||
|
member_names.push(file_name);
|
||||||
|
objects.push(parse_mach_o(
|
||||||
|
&format!("{}. file", index + 1),
|
||||||
|
member_names,
|
||||||
|
mach_o,
|
||||||
|
debugging,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
Err(error) => {
|
||||||
|
Debugging::Error(format!("Error while processing the multi architecture Mach-O binary named '{}'{}\nDetails:\n{}", file_name, merge_members(member_names),
|
||||||
|
error)).print(debugging);
|
||||||
|
objects.push(ULDDObjResult {
|
||||||
|
error: ParsingError {
|
||||||
|
code: find_error_type(&error),
|
||||||
|
explanation: StringPtr::from(error.to_string()).0,
|
||||||
|
},
|
||||||
|
obj: ULDDObj {
|
||||||
|
file_name: StringPtr::from(file_name).0,
|
||||||
|
member_name: CharVec::from(member_names.clone()),
|
||||||
|
executable_format: StringPtr::from("Mach-O").0,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Mach::Binary(binary) => {
|
||||||
|
objects.push(parse_mach_o(file_name, member_names, binary, debugging))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_mach_o(
|
||||||
|
file_name: &str,
|
||||||
|
member_names: &mut Vec<&str>,
|
||||||
|
mach_o: MachO,
|
||||||
|
debugging: bool,
|
||||||
|
) -> ULDDObjResult {
|
||||||
|
let mut mach_o = mach_o;
|
||||||
|
let file_type = StringPtr::from(MACH_O_FILE_TYPE.get(&mach_o.header.filetype)).0;
|
||||||
|
let (cpu_type, cpu_subtype) = {
|
||||||
|
if let Some(mach_o_cpu_type) = MACH_O_CPUTYPE.get(&mach_o.header.cputype) {
|
||||||
|
let mach_o_cpu_subtype = {
|
||||||
|
match mach_o_cpu_type {
|
||||||
|
MachOCpuType::ARM | MachOCpuType::ARM64 => {
|
||||||
|
StringPtr::from(MACH_O_ARM_CPU_SUBTYPE.get(&mach_o.header.cpusubtype)).0
|
||||||
|
}
|
||||||
|
MachOCpuType::X86 | MachOCpuType::X86_64 => {
|
||||||
|
StringPtr::from(MACH_O_X86_CPU_SUBTYPE.get(&mach_o.header.cpusubtype)).0
|
||||||
|
}
|
||||||
|
_ => null_mut(),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
(
|
||||||
|
StringPtr::from(mach_o_cpu_type.to_string()).0,
|
||||||
|
mach_o_cpu_subtype,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(null_mut(), null_mut())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let is_stripped = !mach_o
|
||||||
|
.symbols
|
||||||
|
.as_ref()
|
||||||
|
.is_some_and(|v| v.iter().any(|s| s.is_ok_and(|(x, _)| x.contains("debug"))));
|
||||||
|
|
||||||
|
mach_o.libs.retain(|lib| lib != &"self");
|
||||||
|
debug_objects(file_name, member_names, "a Mach-O binary", debugging);
|
||||||
|
|
||||||
|
ULDDObjResult {
|
||||||
|
error: ParsingError::default(),
|
||||||
|
obj: ULDDObj {
|
||||||
|
file_name: StringPtr::from(file_name).0,
|
||||||
|
member_name: CharVec::from(member_names),
|
||||||
|
executable_format: StringPtr::from("Mach-O").0,
|
||||||
|
is_64: mach_o.is_64,
|
||||||
|
os_type: find_os_mach(&mach_o),
|
||||||
|
file_type,
|
||||||
|
is_stripped,
|
||||||
|
cpu_type,
|
||||||
|
cpu_subtype,
|
||||||
|
interpreter: null_mut(),
|
||||||
|
libraries: CharVec::from(mach_o.libs),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
88
src/pe.rs
Executable file
@@ -0,0 +1,88 @@
|
|||||||
|
use crate::{
|
||||||
|
debug::debug_objects,
|
||||||
|
structs::{CharVec, ParsingError, StringPtr, ULDDObj, ULDDObjResult},
|
||||||
|
types::{PeOS, PeSubsystem, PE_ARCH, PE_SUBSYSTEM},
|
||||||
|
};
|
||||||
|
use goblin::pe::{characteristic::IMAGE_FILE_DEBUG_STRIPPED, PE};
|
||||||
|
use std::ptr::null_mut;
|
||||||
|
|
||||||
|
fn find_os_pe(pe: &PE<'_>) -> *mut i8 {
|
||||||
|
let Some(optional_header) = pe
|
||||||
|
.header
|
||||||
|
.optional_header
|
||||||
|
.and_then(|h| PE_SUBSYSTEM.get(&h.windows_fields.subsystem))
|
||||||
|
else {
|
||||||
|
return null_mut();
|
||||||
|
};
|
||||||
|
|
||||||
|
let os = match optional_header {
|
||||||
|
PeSubsystem::Xbox => PeOS::Xbox,
|
||||||
|
PeSubsystem::EFIApplication
|
||||||
|
| PeSubsystem::EFIBootServiceDriver
|
||||||
|
| PeSubsystem::EFIRom
|
||||||
|
| PeSubsystem::EFIRuntimeDriver => PeOS::UEFI,
|
||||||
|
PeSubsystem::WindowsCUI
|
||||||
|
| PeSubsystem::WindowsGUI
|
||||||
|
| PeSubsystem::Native
|
||||||
|
| PeSubsystem::OS2CUI
|
||||||
|
| PeSubsystem::PosixCUI
|
||||||
|
| PeSubsystem::NativeWindows
|
||||||
|
| PeSubsystem::WindowsCEGUI
|
||||||
|
| PeSubsystem::WindowsBootApplication => PeOS::Windows,
|
||||||
|
PeSubsystem::Unknown => return null_mut(),
|
||||||
|
};
|
||||||
|
|
||||||
|
StringPtr::from(os.to_string()).0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn parse_pe(
|
||||||
|
file_name: &str,
|
||||||
|
pe: PE,
|
||||||
|
member_names: &mut Vec<&str>,
|
||||||
|
debugging: bool,
|
||||||
|
) -> ULDDObjResult {
|
||||||
|
let is_stripped = pe.header.coff_header.characteristics & IMAGE_FILE_DEBUG_STRIPPED
|
||||||
|
== IMAGE_FILE_DEBUG_STRIPPED;
|
||||||
|
let cpu_type = StringPtr::from(PE_ARCH.get(&pe.header.coff_header.machine)).0;
|
||||||
|
let file_type = pe
|
||||||
|
.header
|
||||||
|
.optional_header
|
||||||
|
.and_then(|h| PE_SUBSYSTEM.get(&h.windows_fields.subsystem));
|
||||||
|
let interpreter = {
|
||||||
|
if let Some(optional_header) = pe.header.optional_header {
|
||||||
|
let linker_major_version = optional_header
|
||||||
|
.windows_fields
|
||||||
|
.major_operating_system_version;
|
||||||
|
let linker_minor_version = optional_header
|
||||||
|
.windows_fields
|
||||||
|
.minor_operating_system_version;
|
||||||
|
let linker_version = format!("{}.{}", linker_major_version, linker_minor_version);
|
||||||
|
StringPtr::from(linker_version).0
|
||||||
|
} else {
|
||||||
|
null_mut()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let executable_format = if pe.is_64 {
|
||||||
|
debug_objects(file_name, member_names, "a PE32+ binary", debugging);
|
||||||
|
StringPtr::from("PE32+").0
|
||||||
|
} else {
|
||||||
|
debug_objects(file_name, member_names, "a PE32 binary", debugging);
|
||||||
|
StringPtr::from("PE32").0
|
||||||
|
};
|
||||||
|
ULDDObjResult {
|
||||||
|
error: ParsingError::default(),
|
||||||
|
obj: ULDDObj {
|
||||||
|
file_name: StringPtr::from(file_name).0,
|
||||||
|
member_name: CharVec::from(member_names),
|
||||||
|
executable_format,
|
||||||
|
is_64: pe.is_64,
|
||||||
|
os_type: find_os_pe(&pe),
|
||||||
|
file_type: StringPtr::from(file_type).0,
|
||||||
|
is_stripped,
|
||||||
|
cpu_type,
|
||||||
|
cpu_subtype: null_mut(),
|
||||||
|
interpreter,
|
||||||
|
libraries: CharVec::from(pe.libraries),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
111
src/structs.rs
Executable file
@@ -0,0 +1,111 @@
|
|||||||
|
use std::ffi::c_char;
|
||||||
|
|
||||||
|
/// A C-compatible vector for `Vec<String>`.
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct CharVec {
|
||||||
|
pub capacity: usize,
|
||||||
|
pub length: usize,
|
||||||
|
pub vec: *mut *mut c_char,
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// An error struct for making error handling easy.
|
||||||
|
///
|
||||||
|
/// ## Error Codes
|
||||||
|
/// - \>0: Magic number of the unknown object (as `i64` (or `ìnt64_t))
|
||||||
|
/// - -1: Binary is corrupted
|
||||||
|
/// - -2: Unknown/Bad magic number
|
||||||
|
/// - -3: Error at reading and interpreting bytes
|
||||||
|
/// - -4: I/O Error at parsing the object
|
||||||
|
/// - -5: Buffer is too short to hold
|
||||||
|
/// - -6: Unknown error[^1]
|
||||||
|
/// - -7: Unimplemented executable format
|
||||||
|
///
|
||||||
|
/// [^1]: All errors thrown by goblin crate and my code are covered. Because of matching goblin's [`Error`](goblin::error::Error) is non-exhaustive, I included non-exhaustive path too.
|
||||||
|
///
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct ParsingError {
|
||||||
|
pub code: i64,
|
||||||
|
pub explanation: *mut c_char,
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// A struct contains detailed information about the object.
|
||||||
|
///
|
||||||
|
/// It contains some information even the object is an erroneous one to make error handling more verbose.
|
||||||
|
///
|
||||||
|
/// If the error occurs on parsing:
|
||||||
|
/// - A file: `file_name` and `member_name`
|
||||||
|
/// - A Muti Architecture Mach-O file: `file_name`, `member_name` and `executable_format`
|
||||||
|
/// - An archive: `file_name`, `member_name` and `file_type`
|
||||||
|
///
|
||||||
|
/// fields will be filled correctly and the rest will be:
|
||||||
|
/// - null (the fields which are string)
|
||||||
|
/// - blank (`member_name` and `libraries`)
|
||||||
|
/// - `false` (`is_64` and `is_stripped`).
|
||||||
|
///
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct ULDDObj {
|
||||||
|
/// The name of the object.
|
||||||
|
///
|
||||||
|
/// Objects inside Muti Architecture Mach-O files will be named as "n. file" due to they don't have file names.
|
||||||
|
pub file_name: *mut c_char,
|
||||||
|
/// The location of objects in recursive files.
|
||||||
|
///
|
||||||
|
/// This field is empty if the object is not in a recursive file (Like: Archives and Muti Architecture Mach-O files).
|
||||||
|
///
|
||||||
|
/// The names in the vector is sorted as outer to inner.
|
||||||
|
pub member_name: CharVec,
|
||||||
|
/// The type of the executable format of the object.
|
||||||
|
pub executable_format: *mut c_char,
|
||||||
|
/// The field is true if the object is 64 bit otherwise it is 32 bit or the object is an erroneous one.
|
||||||
|
pub is_64: bool,
|
||||||
|
/// The name of the OS it was compiled for.
|
||||||
|
pub os_type: *mut c_char,
|
||||||
|
/// The type of the object.
|
||||||
|
pub file_type: *mut c_char,
|
||||||
|
/// The field is true if the object was stripped from debug symbols otherwise it is not stripped or the object is an erroneous one .
|
||||||
|
pub is_stripped: bool,
|
||||||
|
/// The ISA (CPU Architecture) the object compiled for.
|
||||||
|
pub cpu_type: *mut c_char,
|
||||||
|
/// The specific CPU model the object compiled for.
|
||||||
|
///
|
||||||
|
/// macOS only field. It is null pointer in other executable formats.
|
||||||
|
pub cpu_subtype: *mut c_char,
|
||||||
|
/// The name/version of the linker.
|
||||||
|
///
|
||||||
|
/// ELF/PE only field. It is null pointer in other executable formats.
|
||||||
|
///
|
||||||
|
/// It returns the version of the linker in PE files.
|
||||||
|
pub interpreter: *mut c_char,
|
||||||
|
/// A vector of libraries linked against the object.
|
||||||
|
///
|
||||||
|
/// It is blank in COFF files because they are mostly PE object files therefore they don't have linked libraries against them.
|
||||||
|
pub libraries: CharVec,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A struct packs (empty or filled) error and (successfully or not) read object.
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct ULDDObjResult {
|
||||||
|
pub error: ParsingError,
|
||||||
|
pub obj: ULDDObj,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A C-compatible vector for [`ULDDObjResult`].
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct ULDDObjResultVec {
|
||||||
|
pub capacity: usize,
|
||||||
|
pub length: usize,
|
||||||
|
pub vec: *mut ULDDObjResult,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub struct StringPtr(pub *mut i8);
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub(crate) enum Debugging {
|
||||||
|
Info(String),
|
||||||
|
Affirmative(String),
|
||||||
|
Error(String),
|
||||||
|
Fatal(String),
|
||||||
|
}
|
||||||
897
src/types.rs
Executable file
@@ -0,0 +1,897 @@
|
|||||||
|
use phf::phf_map;
|
||||||
|
use std::fmt::{Display, Formatter, Result as FmtResult};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Source:
|
||||||
|
https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
|
||||||
|
https://en.wikipedia.org/wiki/Cell_(processor)
|
||||||
|
https://en.wikipedia.org/wiki/ETRAX_CRIS
|
||||||
|
https://developer.fedoraproject.org/deployment/secondary_architectures/s390.html#:~:text=s390%20is%2031%2Dbit%2Daddress,known%20as%20IBM%20System%20z.
|
||||||
|
https://www.infineon.com/cms/en/product/microcontroller/
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// MP Stands for Microprocessor
|
||||||
|
/// BPF Stands for Berkeley Packet Filter
|
||||||
|
#[allow(clippy::upper_case_acronyms)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ElfInstructionSet {
|
||||||
|
Undefined,
|
||||||
|
WE32100,
|
||||||
|
SPARC,
|
||||||
|
X86,
|
||||||
|
M68k,
|
||||||
|
M88k,
|
||||||
|
IntelMCU,
|
||||||
|
I860,
|
||||||
|
MIPS,
|
||||||
|
IBMSystem370,
|
||||||
|
MIPSRS3000Le,
|
||||||
|
FutureUse,
|
||||||
|
HPPPRISC,
|
||||||
|
I960,
|
||||||
|
PPC,
|
||||||
|
PPC64,
|
||||||
|
S390,
|
||||||
|
S390x,
|
||||||
|
// Wikipedia or Google doesn't provide healthy info about what IBM SPU/SPC is
|
||||||
|
IBMSPUSPC,
|
||||||
|
NECV800,
|
||||||
|
FR20,
|
||||||
|
RH32,
|
||||||
|
MotorolaRCE,
|
||||||
|
Arm32,
|
||||||
|
DigitalAlpha,
|
||||||
|
SuperH,
|
||||||
|
SPARCVersion9,
|
||||||
|
SiemensTriCore,
|
||||||
|
ArgonautRISCCore,
|
||||||
|
H8300,
|
||||||
|
H8300H,
|
||||||
|
H8S,
|
||||||
|
H8500,
|
||||||
|
IA64,
|
||||||
|
StanfordMIPSX,
|
||||||
|
MotorolaColdFire,
|
||||||
|
MotorolaM68HC12,
|
||||||
|
FujitsuMMA,
|
||||||
|
SiemensPCP,
|
||||||
|
SonyCellCPU,
|
||||||
|
DensoNDR1,
|
||||||
|
MotorolaStarCore,
|
||||||
|
ToyotaME16,
|
||||||
|
STMicroelectronicsST100,
|
||||||
|
AdvancedLogicCorpTinyJ,
|
||||||
|
X86_64,
|
||||||
|
SonyDSP,
|
||||||
|
PDP10,
|
||||||
|
PDP11,
|
||||||
|
SiemensFX66,
|
||||||
|
STMicroelectronicsST9Plus,
|
||||||
|
STMicroelectronicsST7,
|
||||||
|
MC68HC16,
|
||||||
|
MC68HC11,
|
||||||
|
MC68HC08,
|
||||||
|
MC68HC05,
|
||||||
|
SiliconGraphicsSVx,
|
||||||
|
STMicroelectronicsST19,
|
||||||
|
DigitalVAX,
|
||||||
|
ETRAXCRIS,
|
||||||
|
InfineonTechnologiesMP32,
|
||||||
|
Element14DSP64,
|
||||||
|
LSILogicDSP16,
|
||||||
|
TMS320C6000,
|
||||||
|
MCSTElbrusE2k,
|
||||||
|
Arm64,
|
||||||
|
ZilogZ80,
|
||||||
|
RISCV,
|
||||||
|
BPF,
|
||||||
|
WDC65C816,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
|
||||||
|
pub const E_MACHINE: phf::Map<u16, ElfInstructionSet> = phf_map! {
|
||||||
|
0x00_u16 => ElfInstructionSet::Undefined,
|
||||||
|
0x01_u16 => ElfInstructionSet::WE32100,
|
||||||
|
0x02_u16 => ElfInstructionSet::SPARC,
|
||||||
|
0x03_u16 => ElfInstructionSet::X86,
|
||||||
|
0x04_u16 => ElfInstructionSet::M68k,
|
||||||
|
0x05_u16 => ElfInstructionSet::M88k,
|
||||||
|
0x06_u16 => ElfInstructionSet::IntelMCU,
|
||||||
|
0x07_u16 => ElfInstructionSet::I860,
|
||||||
|
0x08_u16 => ElfInstructionSet::MIPS,
|
||||||
|
0x09_u16 => ElfInstructionSet::IBMSystem370,
|
||||||
|
0x0A_u16 => ElfInstructionSet::MIPSRS3000Le,
|
||||||
|
0x0B_u16 => ElfInstructionSet::FutureUse,
|
||||||
|
0x0C_u16 => ElfInstructionSet::FutureUse,
|
||||||
|
0x0D_u16 => ElfInstructionSet::FutureUse,
|
||||||
|
0x0E_u16 => ElfInstructionSet::FutureUse,
|
||||||
|
0x0F_u16 => ElfInstructionSet::HPPPRISC,
|
||||||
|
0x13_u16 => ElfInstructionSet::I960,
|
||||||
|
0x14_u16 => ElfInstructionSet::PPC,
|
||||||
|
0x15_u16 => ElfInstructionSet::PPC64,
|
||||||
|
0x16_u16 => ElfInstructionSet::S390,
|
||||||
|
0x17_u16 => ElfInstructionSet::S390x,
|
||||||
|
0x18_u16 => ElfInstructionSet::FutureUse,
|
||||||
|
0x19_u16 => ElfInstructionSet::FutureUse,
|
||||||
|
0x20_u16 => ElfInstructionSet::FutureUse,
|
||||||
|
0x21_u16 => ElfInstructionSet::FutureUse,
|
||||||
|
0x22_u16 => ElfInstructionSet::FutureUse,
|
||||||
|
0x23_u16 => ElfInstructionSet::FutureUse,
|
||||||
|
0x24_u16 => ElfInstructionSet::NECV800,
|
||||||
|
0x25_u16 => ElfInstructionSet::FR20,
|
||||||
|
0x26_u16 => ElfInstructionSet::RH32,
|
||||||
|
0x27_u16 => ElfInstructionSet::MotorolaRCE,
|
||||||
|
0x28_u16 => ElfInstructionSet::Arm32,
|
||||||
|
0x29_u16 => ElfInstructionSet::DigitalAlpha,
|
||||||
|
0x2A_u16 => ElfInstructionSet::SuperH,
|
||||||
|
0x2B_u16 => ElfInstructionSet::SPARCVersion9,
|
||||||
|
0x2C_u16 => ElfInstructionSet::SiemensTriCore,
|
||||||
|
0x2D_u16 => ElfInstructionSet::ArgonautRISCCore,
|
||||||
|
0x2E_u16 => ElfInstructionSet::H8300,
|
||||||
|
0x2F_u16 => ElfInstructionSet::H8300H,
|
||||||
|
0x30_u16 => ElfInstructionSet::H8S,
|
||||||
|
0x31_u16 => ElfInstructionSet::H8500,
|
||||||
|
0x32_u16 => ElfInstructionSet::IA64,
|
||||||
|
0x33_u16 => ElfInstructionSet::StanfordMIPSX,
|
||||||
|
0x34_u16 => ElfInstructionSet::MotorolaColdFire,
|
||||||
|
0x35_u16 => ElfInstructionSet::MotorolaM68HC12,
|
||||||
|
0x36_u16 => ElfInstructionSet::FujitsuMMA,
|
||||||
|
0x37_u16 => ElfInstructionSet::SiemensPCP,
|
||||||
|
0x38_u16 => ElfInstructionSet::SonyCellCPU,
|
||||||
|
0x39_u16 => ElfInstructionSet::DensoNDR1,
|
||||||
|
0x3A_u16 => ElfInstructionSet::MotorolaStarCore,
|
||||||
|
0x3B_u16 => ElfInstructionSet::ToyotaME16,
|
||||||
|
0x3C_u16 => ElfInstructionSet::STMicroelectronicsST100,
|
||||||
|
0x3D_u16 => ElfInstructionSet::AdvancedLogicCorpTinyJ,
|
||||||
|
0x3E_u16 => ElfInstructionSet::X86_64,
|
||||||
|
0x3F_u16 => ElfInstructionSet::SonyDSP,
|
||||||
|
0x40_u16 => ElfInstructionSet::PDP10,
|
||||||
|
0x41_u16 => ElfInstructionSet::PDP11,
|
||||||
|
0x42_u16 => ElfInstructionSet::SiemensFX66,
|
||||||
|
0x43_u16 => ElfInstructionSet::STMicroelectronicsST9Plus,
|
||||||
|
0x44_u16 => ElfInstructionSet::STMicroelectronicsST7,
|
||||||
|
0x45_u16 => ElfInstructionSet::MC68HC16,
|
||||||
|
0x46_u16 => ElfInstructionSet::MC68HC11,
|
||||||
|
0x47_u16 => ElfInstructionSet::MC68HC08,
|
||||||
|
0x48_u16 => ElfInstructionSet::MC68HC05,
|
||||||
|
0x49_u16 => ElfInstructionSet::SiliconGraphicsSVx,
|
||||||
|
0x4A_u16 => ElfInstructionSet::STMicroelectronicsST19,
|
||||||
|
0x4B_u16 => ElfInstructionSet::DigitalVAX,
|
||||||
|
0x4C_u16 => ElfInstructionSet::ETRAXCRIS,
|
||||||
|
0x4D_u16 => ElfInstructionSet::InfineonTechnologiesMP32,
|
||||||
|
0x4E_u16 => ElfInstructionSet::Element14DSP64,
|
||||||
|
0x4F_u16 => ElfInstructionSet::LSILogicDSP16,
|
||||||
|
0x8C_u16 => ElfInstructionSet::TMS320C6000,
|
||||||
|
0xAF_u16 => ElfInstructionSet::MCSTElbrusE2k,
|
||||||
|
0xB7_u16 => ElfInstructionSet::Arm64,
|
||||||
|
0xDC_u16 => ElfInstructionSet::ZilogZ80,
|
||||||
|
0xF3_u16 => ElfInstructionSet::RISCV,
|
||||||
|
0xF7_u16 => ElfInstructionSet::BPF,
|
||||||
|
0x101_u16 => ElfInstructionSet::WDC65C816,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Source: https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
|
||||||
|
#[allow(clippy::upper_case_acronyms)]
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub enum ElfOS {
|
||||||
|
SystemV,
|
||||||
|
HPUX,
|
||||||
|
NetBSD,
|
||||||
|
Linux,
|
||||||
|
GNUHurd,
|
||||||
|
Solaris,
|
||||||
|
AIXMonterey,
|
||||||
|
IRIX,
|
||||||
|
FreeBSD,
|
||||||
|
Tru64,
|
||||||
|
NovellModesto,
|
||||||
|
OpenBSD,
|
||||||
|
OpenVMS,
|
||||||
|
NonStopKernel,
|
||||||
|
AROS,
|
||||||
|
FenixOS,
|
||||||
|
CloudABI,
|
||||||
|
OpenVOS,
|
||||||
|
Illumos,
|
||||||
|
SerenityOS,
|
||||||
|
Android,
|
||||||
|
Undefined,
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Source:
|
||||||
|
https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
|
||||||
|
https://stackoverflow.com/a/49248689
|
||||||
|
*/
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ElfFileType {
|
||||||
|
Undefined,
|
||||||
|
Relocatable,
|
||||||
|
Executable,
|
||||||
|
SharedObject,
|
||||||
|
CoreFile,
|
||||||
|
OsSpecific,
|
||||||
|
ProcessorSpecific,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
|
||||||
|
pub const E_TYPE: phf::Map<u16, ElfFileType> = phf_map! {
|
||||||
|
0x00_u16 => ElfFileType::Undefined,
|
||||||
|
0x01_u16 => ElfFileType::Relocatable,
|
||||||
|
0x02_u16 => ElfFileType::Executable,
|
||||||
|
0x03_u16 => ElfFileType::SharedObject,
|
||||||
|
0x04_u16 => ElfFileType::CoreFile,
|
||||||
|
0xFE00_u16 => ElfFileType::OsSpecific,
|
||||||
|
0xFEFF_u16 => ElfFileType::OsSpecific,
|
||||||
|
0xFF00_u16 => ElfFileType::ProcessorSpecific,
|
||||||
|
0xFFFF_u16 => ElfFileType::ProcessorSpecific,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Source: https://en.wikipedia.org/wiki/Mach-O
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum MachOCpuType {
|
||||||
|
VAX,
|
||||||
|
ROMP,
|
||||||
|
NS32032,
|
||||||
|
NS32332,
|
||||||
|
MC680x0,
|
||||||
|
X86,
|
||||||
|
MIPS,
|
||||||
|
NS32352,
|
||||||
|
MC98000,
|
||||||
|
HPPA,
|
||||||
|
ARM,
|
||||||
|
MC88000,
|
||||||
|
SPARC,
|
||||||
|
I860Be,
|
||||||
|
I860Le,
|
||||||
|
RS6000,
|
||||||
|
PPC,
|
||||||
|
ARM64,
|
||||||
|
X86_64,
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Source:
|
||||||
|
https://en.wikipedia.org/wiki/Mach-O
|
||||||
|
https://www.jviotti.com/2021/07/23/a-deep-dive-on-macos-universal-binaries.html
|
||||||
|
*/
|
||||||
|
pub const MACH_O_CPUTYPE: phf::Map<u32, MachOCpuType> = phf_map! {
|
||||||
|
0x01_u32 => MachOCpuType::VAX,
|
||||||
|
0x02_u32 => MachOCpuType::ROMP,
|
||||||
|
0x04_u32 => MachOCpuType::NS32032,
|
||||||
|
0x05_u32 => MachOCpuType::NS32332,
|
||||||
|
0x06_u32 => MachOCpuType::MC680x0,
|
||||||
|
0x07_u32 => MachOCpuType::X86,
|
||||||
|
0x08_u32 => MachOCpuType::MIPS,
|
||||||
|
0x09_u32 => MachOCpuType::NS32352,
|
||||||
|
0x0A_u32 => MachOCpuType::MC98000,
|
||||||
|
0x0B_u32 => MachOCpuType::HPPA,
|
||||||
|
0x0C_u32 => MachOCpuType::ARM,
|
||||||
|
0x0D_u32 => MachOCpuType::MC88000,
|
||||||
|
0x0E_u32 => MachOCpuType::SPARC,
|
||||||
|
0x0F_u32 => MachOCpuType::I860Be,
|
||||||
|
0x10_u32 => MachOCpuType::I860Le,
|
||||||
|
0x11_u32 => MachOCpuType::RS6000,
|
||||||
|
0x12_u32 => MachOCpuType::PPC,
|
||||||
|
0x1000007_u32 => MachOCpuType::X86_64,
|
||||||
|
0x100000C_u32 => MachOCpuType::ARM64,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Source: https://en.wikipedia.org/wiki/Mach-O
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum MachOArmSubType {
|
||||||
|
All,
|
||||||
|
A500ArchOrNewer,
|
||||||
|
A500OrNewer,
|
||||||
|
A440OrNewer,
|
||||||
|
M4OrNewer,
|
||||||
|
V4TOrNewer,
|
||||||
|
V6OrNewer,
|
||||||
|
V5TEJOrNewer,
|
||||||
|
XScaleOrNewer,
|
||||||
|
V7OrNewer,
|
||||||
|
V7FCortexA9OrNewer,
|
||||||
|
V7SSwiftOrNewer,
|
||||||
|
V7KKirkwood40OrNewer,
|
||||||
|
V8OrNewer,
|
||||||
|
V6MOrNewer,
|
||||||
|
V7MOrNewer,
|
||||||
|
V7EMOrNewer,
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: https://en.wikipedia.org/wiki/Mach-O
|
||||||
|
pub const MACH_O_ARM_CPU_SUBTYPE: phf::Map<u32, MachOArmSubType> = phf_map! {
|
||||||
|
0x00_u32 => MachOArmSubType::All,
|
||||||
|
0x01_u32 => MachOArmSubType::A500ArchOrNewer,
|
||||||
|
0x02_u32 => MachOArmSubType::A500OrNewer,
|
||||||
|
0x03_u32 => MachOArmSubType::A440OrNewer,
|
||||||
|
0x04_u32 => MachOArmSubType::M4OrNewer,
|
||||||
|
0x05_u32 => MachOArmSubType::V4TOrNewer,
|
||||||
|
0x06_u32 => MachOArmSubType::V6OrNewer,
|
||||||
|
0x07_u32 => MachOArmSubType::V5TEJOrNewer,
|
||||||
|
0x08_u32 => MachOArmSubType::XScaleOrNewer,
|
||||||
|
0x09_u32 => MachOArmSubType::V7OrNewer,
|
||||||
|
0x0A_u32 => MachOArmSubType::V7FCortexA9OrNewer,
|
||||||
|
0x0B_u32 => MachOArmSubType::V7SSwiftOrNewer,
|
||||||
|
0x0C_u32 => MachOArmSubType::V7KKirkwood40OrNewer,
|
||||||
|
0x0D_u32 => MachOArmSubType::V8OrNewer,
|
||||||
|
0x0E_u32 => MachOArmSubType::V6MOrNewer,
|
||||||
|
0x0F_u32 => MachOArmSubType::V7MOrNewer,
|
||||||
|
0x10_u32 => MachOArmSubType::V7EMOrNewer,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Source: https://en.wikipedia.org/wiki/Mach-O
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum MachOX86SubType {
|
||||||
|
All,
|
||||||
|
I486OrNewer,
|
||||||
|
I486SXOrNewer,
|
||||||
|
PentiumM5OrNewer,
|
||||||
|
CeleronOrNewer,
|
||||||
|
CeleronMobile,
|
||||||
|
Pentium3OrNewer,
|
||||||
|
Pentium3MOrNewer,
|
||||||
|
Pentium3XeonOrNewer,
|
||||||
|
Pentium4OrNewer,
|
||||||
|
ItaniumOrNewer,
|
||||||
|
Itanium2OrNewer,
|
||||||
|
XeonOrNewer,
|
||||||
|
XeonMPOrNewer,
|
||||||
|
Undefined,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: https://en.wikipedia.org/wiki/Mach-O
|
||||||
|
pub const MACH_O_X86_CPU_SUBTYPE: phf::Map<u32, MachOX86SubType> = phf_map! {
|
||||||
|
0x03_u32 => MachOX86SubType::All,
|
||||||
|
0x04_u32 => MachOX86SubType::I486OrNewer,
|
||||||
|
0x84_u32 => MachOX86SubType::I486SXOrNewer,
|
||||||
|
0x56_u32 => MachOX86SubType::PentiumM5OrNewer,
|
||||||
|
0x67_u32 => MachOX86SubType::CeleronOrNewer,
|
||||||
|
0x77_u32 => MachOX86SubType::CeleronMobile,
|
||||||
|
0x08_u32 => MachOX86SubType::Pentium3OrNewer,
|
||||||
|
0x18_u32 => MachOX86SubType::Pentium3MOrNewer,
|
||||||
|
0x28_u32 => MachOX86SubType::Pentium3XeonOrNewer,
|
||||||
|
0x0A_u32 => MachOX86SubType::Pentium4OrNewer,
|
||||||
|
0x0B_u32 => MachOX86SubType::ItaniumOrNewer,
|
||||||
|
0x1B_u32 => MachOX86SubType::Itanium2OrNewer,
|
||||||
|
0x0C_u32 => MachOX86SubType::XeonOrNewer,
|
||||||
|
0x1C_u32 => MachOX86SubType::XeonMPOrNewer,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum MachOCpuSubType {
|
||||||
|
Arm(MachOArmSubType),
|
||||||
|
X86(MachOX86SubType),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: https://en.wikipedia.org/wiki/Mach-O
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum MachOOs {
|
||||||
|
MacOS,
|
||||||
|
IOS,
|
||||||
|
AppleTVBox,
|
||||||
|
AppleWatch,
|
||||||
|
BridgeOS,
|
||||||
|
MacCatalyst,
|
||||||
|
IOSSimulator,
|
||||||
|
AppleTVSimulator,
|
||||||
|
AppleWatchSimulator,
|
||||||
|
DriverKit,
|
||||||
|
AppleVisionPro,
|
||||||
|
AppleVisionProSimulator,
|
||||||
|
Undefined,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: https://en.wikipedia.org/wiki/Mach-O
|
||||||
|
pub const MACH_O_OS: phf::Map<u32, MachOOs> = phf_map! {
|
||||||
|
0x1_u32 => MachOOs::MacOS,
|
||||||
|
0x2_u32 => MachOOs::IOS,
|
||||||
|
0x3_u32 => MachOOs::AppleTVBox,
|
||||||
|
0x4_u32 => MachOOs::AppleWatch,
|
||||||
|
0x5_u32 => MachOOs::BridgeOS,
|
||||||
|
0x6_u32 => MachOOs::MacCatalyst,
|
||||||
|
0x7_u32 => MachOOs::IOSSimulator,
|
||||||
|
0x8_u32 => MachOOs::AppleTVSimulator,
|
||||||
|
0x9_u32 => MachOOs::AppleWatchSimulator,
|
||||||
|
0xA_u32 => MachOOs::DriverKit,
|
||||||
|
0xB_u32 => MachOOs::AppleVisionPro,
|
||||||
|
0xC_u32 => MachOOs::AppleVisionProSimulator,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Source: https://en.wikipedia.org/wiki/Mach-O
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum MachOFileType {
|
||||||
|
RelocatableObjectFile,
|
||||||
|
DemandPagedExecutableFile,
|
||||||
|
FixedVMSharedLibraryFile,
|
||||||
|
CoreFile,
|
||||||
|
PreloadedExecutableFile,
|
||||||
|
DynamicallyBoundSharedLibraryFile,
|
||||||
|
DynamicLinkEditor,
|
||||||
|
DynamicallyBoundBundleFile,
|
||||||
|
SharedLibraryStub,
|
||||||
|
CompanionFileWithDebugSections,
|
||||||
|
X86_64Kexts,
|
||||||
|
ComposedFile,
|
||||||
|
Undefined,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: https://en.wikipedia.org/wiki/Mach-O
|
||||||
|
pub const MACH_O_FILE_TYPE: phf::Map<u32, MachOFileType> = phf_map! {
|
||||||
|
0x1_u32 => MachOFileType::RelocatableObjectFile,
|
||||||
|
0x2_u32 => MachOFileType::DemandPagedExecutableFile,
|
||||||
|
0x3_u32 => MachOFileType::FixedVMSharedLibraryFile,
|
||||||
|
0x4_u32 => MachOFileType::CoreFile,
|
||||||
|
0x5_u32 => MachOFileType::PreloadedExecutableFile,
|
||||||
|
0x6_u32 => MachOFileType::DynamicallyBoundSharedLibraryFile,
|
||||||
|
0x7_u32 => MachOFileType::DynamicLinkEditor,
|
||||||
|
0x8_u32 => MachOFileType::DynamicallyBoundBundleFile,
|
||||||
|
0x9_u32 => MachOFileType::SharedLibraryStub,
|
||||||
|
0xA_u32 => MachOFileType::CompanionFileWithDebugSections,
|
||||||
|
0xB_u32 => MachOFileType::X86_64Kexts,
|
||||||
|
0xC_u32 => MachOFileType::ComposedFile,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Source: https://learn.microsoft.com/en-us/windows/win32/debug/pe-format
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum PeArch {
|
||||||
|
Unknown,
|
||||||
|
AlphaAXP32,
|
||||||
|
AlphaAXP64,
|
||||||
|
MatsushitaAM33,
|
||||||
|
X64,
|
||||||
|
ARM,
|
||||||
|
ARM64,
|
||||||
|
ARMNT,
|
||||||
|
AXP64,
|
||||||
|
EBC,
|
||||||
|
I386,
|
||||||
|
IA64,
|
||||||
|
LoongArch32,
|
||||||
|
LoongArch64,
|
||||||
|
MitsubishiM32R,
|
||||||
|
MIPS16,
|
||||||
|
MIPSFPU,
|
||||||
|
MIPSFPU16,
|
||||||
|
PowerPC,
|
||||||
|
PowerPCFP,
|
||||||
|
MIPS,
|
||||||
|
RISCV32,
|
||||||
|
RISCV64,
|
||||||
|
RISCV128,
|
||||||
|
HitachiSH3,
|
||||||
|
HitachiSH3DSP,
|
||||||
|
HitachiSH4,
|
||||||
|
HitachiSH5,
|
||||||
|
Thumb,
|
||||||
|
MIPSWCE,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: https://learn.microsoft.com/en-us/windows/win32/debug/pe-format
|
||||||
|
pub const PE_ARCH: phf::Map<u16, PeArch> = phf_map! {
|
||||||
|
0x0000_u16 => PeArch::Unknown,
|
||||||
|
0x0184_u16 => PeArch::AlphaAXP32,
|
||||||
|
0x0284_u16 => PeArch::AlphaAXP64,
|
||||||
|
0x01d3_u16 => PeArch::MatsushitaAM33,
|
||||||
|
0x8664_u16 => PeArch::X64,
|
||||||
|
0x01c0_u16 => PeArch::ARM,
|
||||||
|
0xaa64_u16 => PeArch::ARM64,
|
||||||
|
0x01c4_u16 => PeArch::ARMNT,
|
||||||
|
// Look at source to learn why there is a duplicate value
|
||||||
|
//0x0284_u16 => PeArch::AXP64,
|
||||||
|
0xebc_u16 => PeArch::EBC,
|
||||||
|
0x014c_u16 => PeArch::I386,
|
||||||
|
0x0200_u16 => PeArch::IA64,
|
||||||
|
0x6232_u16 => PeArch::LoongArch32,
|
||||||
|
0x6264_u16 => PeArch::LoongArch64,
|
||||||
|
0x9041_u16 => PeArch::MitsubishiM32R,
|
||||||
|
0x0266_u16 => PeArch::MIPS16,
|
||||||
|
0x0366_u16 => PeArch::MIPSFPU,
|
||||||
|
0x0466_u16 => PeArch::MIPSFPU16,
|
||||||
|
0x01f0_u16 => PeArch::PowerPC,
|
||||||
|
0x01f1_u16 => PeArch::PowerPCFP,
|
||||||
|
0x0166_u16 => PeArch::MIPS,
|
||||||
|
0x5032_u16 => PeArch::RISCV32,
|
||||||
|
0x5064_u16 => PeArch::RISCV64,
|
||||||
|
0x5128_u16 => PeArch::RISCV128,
|
||||||
|
0x01a2_u16 => PeArch::HitachiSH3,
|
||||||
|
0x01a3_u16 => PeArch::HitachiSH3DSP,
|
||||||
|
0x01a6_u16 => PeArch::HitachiSH4,
|
||||||
|
0x01a8_u16 => PeArch::HitachiSH5,
|
||||||
|
0x01c2_u16 => PeArch::Thumb,
|
||||||
|
0x0169_u16 => PeArch::MIPSWCE,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Source: https://learn.microsoft.com/en-us/windows/win32/debug/pe-format
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum PeSubsystem {
|
||||||
|
Unknown,
|
||||||
|
Native,
|
||||||
|
WindowsGUI,
|
||||||
|
WindowsCUI,
|
||||||
|
OS2CUI,
|
||||||
|
PosixCUI,
|
||||||
|
NativeWindows,
|
||||||
|
WindowsCEGUI,
|
||||||
|
EFIApplication,
|
||||||
|
EFIBootServiceDriver,
|
||||||
|
EFIRuntimeDriver,
|
||||||
|
EFIRom,
|
||||||
|
Xbox,
|
||||||
|
WindowsBootApplication,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: https://learn.microsoft.com/en-us/windows/win32/debug/pe-format
|
||||||
|
pub const PE_SUBSYSTEM: phf::Map<u16, PeSubsystem> = phf_map! {
|
||||||
|
0x0000_u16 => PeSubsystem::Unknown,
|
||||||
|
0x0001_u16 => PeSubsystem::Native,
|
||||||
|
0x0002_u16 => PeSubsystem::WindowsGUI,
|
||||||
|
0x0003_u16 => PeSubsystem::WindowsCUI,
|
||||||
|
0x0005_u16 => PeSubsystem::OS2CUI,
|
||||||
|
0x0007_u16 => PeSubsystem::PosixCUI,
|
||||||
|
0x0008_u16 => PeSubsystem::NativeWindows,
|
||||||
|
0x0009_u16 => PeSubsystem::WindowsCEGUI,
|
||||||
|
0x000A_u16 => PeSubsystem::EFIApplication,
|
||||||
|
0x000B_u16 => PeSubsystem::EFIBootServiceDriver,
|
||||||
|
0x000C_u16 => PeSubsystem::EFIRuntimeDriver,
|
||||||
|
0x000D_u16 => PeSubsystem::EFIRom,
|
||||||
|
0x000E_u16 => PeSubsystem::Xbox,
|
||||||
|
0x0010_u16 => PeSubsystem::WindowsBootApplication,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum PeOS {
|
||||||
|
Xbox,
|
||||||
|
Windows,
|
||||||
|
UEFI,
|
||||||
|
Undefined,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source of the names: https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
|
||||||
|
impl Display for ElfOS {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||||
|
match self {
|
||||||
|
ElfOS::SystemV => write!(f, "System V"),
|
||||||
|
ElfOS::HPUX => write!(f, "HP-UX"),
|
||||||
|
ElfOS::NetBSD => write!(f, "NetBSD"),
|
||||||
|
ElfOS::Linux => write!(f, "Linux"),
|
||||||
|
ElfOS::GNUHurd => write!(f, "GNU Hurd"),
|
||||||
|
ElfOS::Solaris => write!(f, "Solaris"),
|
||||||
|
ElfOS::AIXMonterey => write!(f, "AIX (Monterey)"),
|
||||||
|
ElfOS::IRIX => write!(f, "IRIX"),
|
||||||
|
ElfOS::FreeBSD => write!(f, "FreeBSD"),
|
||||||
|
ElfOS::Tru64 => write!(f, "Tru64"),
|
||||||
|
ElfOS::NovellModesto => write!(f, "Novell Modesto"),
|
||||||
|
ElfOS::OpenBSD => write!(f, "OpenBSD"),
|
||||||
|
ElfOS::OpenVMS => write!(f, "OpenVMS"),
|
||||||
|
ElfOS::NonStopKernel => write!(f, "NonStop Kernel"),
|
||||||
|
ElfOS::AROS => write!(f, "AROS"),
|
||||||
|
ElfOS::FenixOS => write!(f, "FenixOS"),
|
||||||
|
ElfOS::CloudABI => write!(f, "Nuxi CloudABI"),
|
||||||
|
ElfOS::OpenVOS => write!(f, "OpenVOS"),
|
||||||
|
ElfOS::Illumos => write!(f, "Illumos"),
|
||||||
|
ElfOS::SerenityOS => write!(f, "SerenityOS"),
|
||||||
|
ElfOS::Android => write!(f, "Android"),
|
||||||
|
ElfOS::Undefined => write!(f, "Undefined"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source of the names: https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
|
||||||
|
impl Display for ElfInstructionSet {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||||
|
match self {
|
||||||
|
ElfInstructionSet::Undefined => write!(f, "Undefined"), //0x00 no specific instruction set is defined
|
||||||
|
ElfInstructionSet::WE32100 => write!(f, "AT&T WE 32100"),
|
||||||
|
ElfInstructionSet::SPARC => write!(f, "SPARC"),
|
||||||
|
ElfInstructionSet::X86 => write!(f, "x86"),
|
||||||
|
ElfInstructionSet::M68k => write!(f, "Motorola 68000 (M68k)"),
|
||||||
|
ElfInstructionSet::M88k => write!(f, "Motorola 88000 (M88k)"),
|
||||||
|
ElfInstructionSet::IntelMCU => write!(f, "Intel MCU"),
|
||||||
|
ElfInstructionSet::I860 => write!(f, "Intel 80860"),
|
||||||
|
ElfInstructionSet::MIPS => write!(f, "MIPS"),
|
||||||
|
ElfInstructionSet::IBMSystem370 => write!(f, "IBM System/370"),
|
||||||
|
ElfInstructionSet::MIPSRS3000Le => write!(f, "MIPS RS3000 (Little-endian)"),
|
||||||
|
ElfInstructionSet::FutureUse => write!(f, "Reserved for future use"),
|
||||||
|
ElfInstructionSet::HPPPRISC => write!(f, "HP PA-RISC"),
|
||||||
|
ElfInstructionSet::I960 => write!(f, "Intel 80960"),
|
||||||
|
ElfInstructionSet::PPC => write!(f, "PowerPC"),
|
||||||
|
ElfInstructionSet::PPC64 => write!(f, "PowerPC (64-Bit)"),
|
||||||
|
ElfInstructionSet::S390 => write!(f, "S390"),
|
||||||
|
ElfInstructionSet::S390x => write!(f, "S390x"),
|
||||||
|
ElfInstructionSet::NECV800 => write!(f, "NEC V800"),
|
||||||
|
ElfInstructionSet::FR20 => write!(f, "Fujitsu FR20"),
|
||||||
|
ElfInstructionSet::RH32 => write!(f, "TRW RH-32"),
|
||||||
|
ElfInstructionSet::MotorolaRCE => write!(f, "Motorola RCE"),
|
||||||
|
ElfInstructionSet::Arm32 => write!(f, "Arm (32-Bit)"),
|
||||||
|
ElfInstructionSet::DigitalAlpha => write!(f, "Digital Alpha"),
|
||||||
|
ElfInstructionSet::SuperH => write!(f, "SuperH"),
|
||||||
|
ElfInstructionSet::SPARCVersion9 => write!(f, "SPARC version 9"),
|
||||||
|
ElfInstructionSet::SiemensTriCore => write!(f, "Siemens TriCore"),
|
||||||
|
ElfInstructionSet::ArgonautRISCCore => write!(f, "Argonaut RISC Core"),
|
||||||
|
ElfInstructionSet::H8300 => write!(f, "Hitachi H8/300"),
|
||||||
|
ElfInstructionSet::H8300H => write!(f, "Hitachi H8/300H"),
|
||||||
|
ElfInstructionSet::H8S => write!(f, "Hitachi H8S"),
|
||||||
|
ElfInstructionSet::H8500 => write!(f, "Hitachi H8/500"),
|
||||||
|
ElfInstructionSet::IA64 => write!(f, "Intel Itanium"),
|
||||||
|
ElfInstructionSet::StanfordMIPSX => write!(f, "Stanford MIPS-X"),
|
||||||
|
ElfInstructionSet::MotorolaColdFire => write!(f, "Motorola ColdFire"),
|
||||||
|
ElfInstructionSet::MotorolaM68HC12 => write!(f, "Motorola M68HC12"),
|
||||||
|
ElfInstructionSet::FujitsuMMA => write!(f, "Fujitsu MMA multimedia accelerator"),
|
||||||
|
ElfInstructionSet::SiemensPCP => write!(f, "Siemens PCP"),
|
||||||
|
ElfInstructionSet::SonyCellCPU => write!(f, "Sony nCPU Embedded RISC"),
|
||||||
|
ElfInstructionSet::DensoNDR1 => write!(f, "Denso NDR1"),
|
||||||
|
ElfInstructionSet::MotorolaStarCore => write!(f, "Motorola Star*Core"),
|
||||||
|
ElfInstructionSet::ToyotaME16 => write!(f, "Toyota ME16"),
|
||||||
|
ElfInstructionSet::STMicroelectronicsST100 => {
|
||||||
|
write!(f, "STMicroelectronics ST100")
|
||||||
|
}
|
||||||
|
ElfInstructionSet::AdvancedLogicCorpTinyJ => {
|
||||||
|
write!(f, "Advanced Logic Corp. TinyJ")
|
||||||
|
}
|
||||||
|
ElfInstructionSet::X86_64 => write!(f, "x86-64"),
|
||||||
|
ElfInstructionSet::SonyDSP => write!(f, "Sony DSP processor"),
|
||||||
|
ElfInstructionSet::PDP10 => write!(f, "Digital Equipment Corp. PDP-10"),
|
||||||
|
ElfInstructionSet::PDP11 => write!(f, "Digital Equipment Corp. PDP-11"),
|
||||||
|
ElfInstructionSet::SiemensFX66 => write!(f, "Siemens FX66 microcontroller"),
|
||||||
|
ElfInstructionSet::STMicroelectronicsST9Plus => {
|
||||||
|
write!(f, "STMicroelectronics ST9+ 8/16-Bit microcontroller")
|
||||||
|
}
|
||||||
|
ElfInstructionSet::STMicroelectronicsST7 => {
|
||||||
|
write!(f, "STMicroelectronics ST7 8-Bit microcontroller")
|
||||||
|
}
|
||||||
|
ElfInstructionSet::MC68HC16 => write!(f, "Motorola MC68HC16 microcontroller"),
|
||||||
|
ElfInstructionSet::MC68HC11 => write!(f, "Motorola MC68HC11 microcontroller"),
|
||||||
|
ElfInstructionSet::MC68HC08 => write!(f, "Motorola MC68HC08 microcontroller"),
|
||||||
|
ElfInstructionSet::MC68HC05 => write!(f, "Motorola MC68HC05 microcontroller"),
|
||||||
|
ElfInstructionSet::SiliconGraphicsSVx => write!(f, "Silicon Graphics SVx"),
|
||||||
|
ElfInstructionSet::STMicroelectronicsST19 => {
|
||||||
|
write!(f, "STMicroelectronics ST19 8-Bit microcontroller")
|
||||||
|
}
|
||||||
|
ElfInstructionSet::DigitalVAX => write!(f, "Digital VAX"),
|
||||||
|
ElfInstructionSet::ETRAXCRIS => {
|
||||||
|
write!(f, "Axis Communications (32-Bit) embedded processor")
|
||||||
|
}
|
||||||
|
ElfInstructionSet::InfineonTechnologiesMP32 => {
|
||||||
|
write!(f, "Infineon Technologies (32-Bit) embedded processor")
|
||||||
|
}
|
||||||
|
ElfInstructionSet::Element14DSP64 => write!(f, "Element 14 (64-Bit) DSP processor"),
|
||||||
|
ElfInstructionSet::LSILogicDSP16 => write!(f, "LSI Logic 16-Bit DSP processor"),
|
||||||
|
ElfInstructionSet::TMS320C6000 => write!(f, "TMS320C6000 family"),
|
||||||
|
ElfInstructionSet::MCSTElbrusE2k => write!(f, "MCST Elbrus e2k"),
|
||||||
|
ElfInstructionSet::Arm64 => write!(f, "Arm (64-Bit)"),
|
||||||
|
ElfInstructionSet::ZilogZ80 => write!(f, "Zilog Z80"),
|
||||||
|
ElfInstructionSet::RISCV => write!(f, "RISC-V"),
|
||||||
|
ElfInstructionSet::BPF => write!(f, "Berkeley packet filter"),
|
||||||
|
ElfInstructionSet::IBMSPUSPC => write!(f, "IBM SPU/SPC"),
|
||||||
|
ElfInstructionSet::WDC65C816 => write!(f, "WDC 65C816"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Sources:
|
||||||
|
https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
|
||||||
|
https://refspecs.linuxbase.org/elf/gabi4+/ch4.intro.html
|
||||||
|
*/
|
||||||
|
impl Display for ElfFileType {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||||
|
match self {
|
||||||
|
ElfFileType::Undefined => write!(f, "Undefined"),
|
||||||
|
ElfFileType::Relocatable => write!(f, "Object file"),
|
||||||
|
ElfFileType::Executable => write!(f, "Executable"),
|
||||||
|
ElfFileType::SharedObject => write!(f, "Shared object"),
|
||||||
|
ElfFileType::CoreFile => write!(f, "Core file"),
|
||||||
|
// I couldn't get healthy info. about "OS/CPU specific"
|
||||||
|
ElfFileType::OsSpecific => write!(f, "OS-specific"),
|
||||||
|
ElfFileType::ProcessorSpecific => write!(f, "CPU-specific"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: https://learn.microsoft.com/en-us/windows/win32/debug/pe-format
|
||||||
|
impl Display for PeArch {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||||
|
match self {
|
||||||
|
PeArch::Unknown => write!(f, "Unknown"),
|
||||||
|
PeArch::AlphaAXP32 => write!(f, "Alpha AXP (32-Bit)"),
|
||||||
|
PeArch::AlphaAXP64 | PeArch::AXP64 => write!(f, "Alpha 64 (64-Bit)"),
|
||||||
|
PeArch::MatsushitaAM33 => write!(f, "Matsushita AM33"),
|
||||||
|
PeArch::X64 => write!(f, "x64"),
|
||||||
|
PeArch::ARM => write!(f, "Arm"),
|
||||||
|
PeArch::ARM64 => write!(f, "Arm (64-Bit)"),
|
||||||
|
PeArch::ARMNT => write!(f, "ARM Thumb-2"),
|
||||||
|
PeArch::EBC => write!(f, "EFI bytecode"),
|
||||||
|
PeArch::I386 => write!(f, "Intel 386"),
|
||||||
|
PeArch::IA64 => write!(f, "Intel Itanium"),
|
||||||
|
PeArch::LoongArch32 => write!(f, "LoongArch (32-Bit)"),
|
||||||
|
PeArch::LoongArch64 => write!(f, "LoongArch (64-Bit)"),
|
||||||
|
PeArch::MitsubishiM32R => write!(f, "Mitsubishi M32R"),
|
||||||
|
PeArch::MIPS16 => write!(f, "MIPS16"),
|
||||||
|
PeArch::MIPSFPU => write!(f, "MIPS with FPU"),
|
||||||
|
PeArch::MIPSFPU16 => write!(f, "MIPS16 with FPU"),
|
||||||
|
PeArch::PowerPC => write!(f, "PowerPC"),
|
||||||
|
PeArch::PowerPCFP => write!(f, "PowerPC with floating point support"),
|
||||||
|
PeArch::MIPS => write!(f, "MIPS"),
|
||||||
|
PeArch::RISCV32 => write!(f, "RISC-V (32-Bit)"),
|
||||||
|
PeArch::RISCV64 => write!(f, "RISC-V (64-Bit)"),
|
||||||
|
PeArch::RISCV128 => write!(f, "RISC-V 128-Bit"),
|
||||||
|
PeArch::HitachiSH3 => write!(f, "Hitachi SH3"),
|
||||||
|
PeArch::HitachiSH3DSP => write!(f, "Hitachi SH3 DSP"),
|
||||||
|
PeArch::HitachiSH4 => write!(f, "Hitachi SH4"),
|
||||||
|
PeArch::HitachiSH5 => write!(f, "Hitachi SH5"),
|
||||||
|
PeArch::Thumb => write!(f, "Thumb"),
|
||||||
|
PeArch::MIPSWCE => write!(f, "MIPS (Little-endian) WCE v2"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Sources:
|
||||||
|
https://learn.microsoft.com/en-us/windows/win32/debug/pe-format
|
||||||
|
CLI != CUI: https://github.com/avelino/awesome-go/issues/282#issuecomment-73395067
|
||||||
|
*/
|
||||||
|
impl Display for PeSubsystem {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||||
|
match self {
|
||||||
|
PeSubsystem::Unknown => write!(f, "Undefined"),
|
||||||
|
PeSubsystem::Native => write!(f, "Device drivers and native windows processes"),
|
||||||
|
PeSubsystem::WindowsGUI => write!(f, "GUI application"),
|
||||||
|
PeSubsystem::WindowsCUI => write!(f, "Windows CUI application"),
|
||||||
|
PeSubsystem::OS2CUI => write!(f, "OS/2 CUI application"),
|
||||||
|
PeSubsystem::PosixCUI => write!(f, "Posix CUI application"),
|
||||||
|
PeSubsystem::NativeWindows => write!(f, "Native Win9x driver"),
|
||||||
|
PeSubsystem::WindowsCEGUI => write!(f, "Windows CE application"),
|
||||||
|
PeSubsystem::EFIApplication => write!(f, "EFI application"),
|
||||||
|
PeSubsystem::EFIBootServiceDriver => write!(f, "EFI driver with boot services"),
|
||||||
|
PeSubsystem::EFIRuntimeDriver => write!(f, "EFI driver with runtime services"),
|
||||||
|
PeSubsystem::EFIRom => write!(f, "EFI ROM image"),
|
||||||
|
PeSubsystem::Xbox => write!(f, "XBOX"),
|
||||||
|
PeSubsystem::WindowsBootApplication => write!(f, "Windows boot application."),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: https://learn.microsoft.com/en-us/windows/win32/debug/pe-format
|
||||||
|
impl Display for PeOS {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||||
|
match self {
|
||||||
|
PeOS::Xbox => write!(f, "Xbox"),
|
||||||
|
PeOS::Windows => write!(f, "Windows"),
|
||||||
|
PeOS::UEFI => write!(f, "UEFI"),
|
||||||
|
PeOS::Undefined => write!(f, "Undefined"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: https://en.wikipedia.org/wiki/Mach-O
|
||||||
|
impl Display for MachOArmSubType {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||||
|
match self {
|
||||||
|
MachOArmSubType::All => write!(f, "All ARM processors"),
|
||||||
|
MachOArmSubType::A500ArchOrNewer => write!(f, "ARM-A500 ARCH or newer"),
|
||||||
|
MachOArmSubType::A500OrNewer => write!(f, "ARM-A500 or newer"),
|
||||||
|
MachOArmSubType::A440OrNewer => write!(f, "ARM-A440 or newer"),
|
||||||
|
MachOArmSubType::M4OrNewer => write!(f, "ARM-M4 or newer"),
|
||||||
|
MachOArmSubType::V4TOrNewer => write!(f, "ARM-V4T or newer"),
|
||||||
|
MachOArmSubType::V6OrNewer => write!(f, "ARM-V6 or newer"),
|
||||||
|
MachOArmSubType::V5TEJOrNewer => write!(f, "ARM-V5TEJ or newer"),
|
||||||
|
MachOArmSubType::XScaleOrNewer => write!(f, "ARM-XSCALE or newer"),
|
||||||
|
MachOArmSubType::V7OrNewer => write!(f, "ARM-V7 or newer"),
|
||||||
|
MachOArmSubType::V7FCortexA9OrNewer => write!(f, "ARM-V7F (Cortex A9) or newer"),
|
||||||
|
MachOArmSubType::V7SSwiftOrNewer => write!(f, "ARM-V7S (Swift) or newer"),
|
||||||
|
MachOArmSubType::V7KKirkwood40OrNewer => write!(f, "ARM-V7K (Kirkwood40) or newer"),
|
||||||
|
MachOArmSubType::V8OrNewer => write!(f, "ARM-V8 or newer"),
|
||||||
|
MachOArmSubType::V6MOrNewer => write!(f, "ARM-V6M or newer"),
|
||||||
|
MachOArmSubType::V7MOrNewer => write!(f, "ARM-V7M or newer"),
|
||||||
|
MachOArmSubType::V7EMOrNewer => write!(f, "ARM-V7EM or newer"),
|
||||||
|
MachOArmSubType::Unknown => write!(f, "Unknown"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: https://en.wikipedia.org/wiki/Mach-O
|
||||||
|
impl Display for MachOX86SubType {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||||
|
match self {
|
||||||
|
MachOX86SubType::All => write!(f, "All x86 processors"),
|
||||||
|
MachOX86SubType::I486OrNewer => write!(f, "486 or newer"),
|
||||||
|
MachOX86SubType::I486SXOrNewer => write!(f, "486SX or newer"),
|
||||||
|
MachOX86SubType::PentiumM5OrNewer => write!(f, "Pentium M5 or newer"),
|
||||||
|
MachOX86SubType::CeleronOrNewer => write!(f, "Celeron or newer"),
|
||||||
|
MachOX86SubType::CeleronMobile => write!(f, "Celeron Mobile"),
|
||||||
|
MachOX86SubType::Pentium3OrNewer => write!(f, "Pentium 3 or newer"),
|
||||||
|
MachOX86SubType::Pentium3MOrNewer => write!(f, "Pentium 3-M or newer"),
|
||||||
|
MachOX86SubType::Pentium3XeonOrNewer => write!(f, "Pentium 3-XEON or newer"),
|
||||||
|
MachOX86SubType::Pentium4OrNewer => write!(f, "Pentium-4 or newer"),
|
||||||
|
MachOX86SubType::ItaniumOrNewer => write!(f, "Itanium or newer"),
|
||||||
|
MachOX86SubType::Itanium2OrNewer => write!(f, "Itanium-2 or newer"),
|
||||||
|
MachOX86SubType::XeonOrNewer => write!(f, "XEON or newer"),
|
||||||
|
MachOX86SubType::XeonMPOrNewer => write!(f, "XEON-MP or newer"),
|
||||||
|
MachOX86SubType::Undefined => write!(f, "Undefined"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: https://en.wikipedia.org/wiki/Mach-O
|
||||||
|
impl Display for MachOCpuSubType {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||||
|
match self {
|
||||||
|
MachOCpuSubType::Arm(arm) => write!(f, "{}", arm),
|
||||||
|
MachOCpuSubType::X86(x86) => write!(f, "{}", x86),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: https://en.wikipedia.org/wiki/Mach-O
|
||||||
|
impl Display for MachOCpuType {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||||
|
match self {
|
||||||
|
MachOCpuType::VAX => write!(f, "VAX"),
|
||||||
|
MachOCpuType::ROMP => write!(f, "ROMP"),
|
||||||
|
MachOCpuType::NS32032 => write!(f, "NS32032"),
|
||||||
|
MachOCpuType::NS32332 => write!(f, "NS32332"),
|
||||||
|
MachOCpuType::MC680x0 => write!(f, "MC680x0"),
|
||||||
|
MachOCpuType::X86 => write!(f, "x86"),
|
||||||
|
MachOCpuType::MIPS => write!(f, "MIPS"),
|
||||||
|
MachOCpuType::NS32352 => write!(f, "NS32352"),
|
||||||
|
MachOCpuType::MC98000 => write!(f, "MC98000"),
|
||||||
|
MachOCpuType::HPPA => write!(f, "HP-PA"),
|
||||||
|
MachOCpuType::ARM => write!(f, "ARM"),
|
||||||
|
MachOCpuType::MC88000 => write!(f, "MC88000"),
|
||||||
|
MachOCpuType::SPARC => write!(f, "SPARC"),
|
||||||
|
MachOCpuType::I860Be => write!(f, "i860 (Big-endian)"),
|
||||||
|
MachOCpuType::I860Le => write!(f, "i860 (Little-endian)"),
|
||||||
|
MachOCpuType::RS6000 => write!(f, "RS/6000"),
|
||||||
|
MachOCpuType::PPC => write!(f, "PowerPC"),
|
||||||
|
MachOCpuType::ARM64 => write!(f, "ARM64"),
|
||||||
|
MachOCpuType::X86_64 => write!(f, "x86_64"),
|
||||||
|
MachOCpuType::Unknown => write!(f, "Unknown"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: https://en.wikipedia.org/wiki/Mach-O
|
||||||
|
impl Display for MachOFileType {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||||
|
match self {
|
||||||
|
MachOFileType::RelocatableObjectFile => write!(f, "Object file"),
|
||||||
|
MachOFileType::DemandPagedExecutableFile => write!(f, "Executable"),
|
||||||
|
MachOFileType::FixedVMSharedLibraryFile => write!(f, "Fixed VM shared library file"),
|
||||||
|
MachOFileType::CoreFile => write!(f, "Core file"),
|
||||||
|
MachOFileType::PreloadedExecutableFile => write!(f, "Preloaded executable file"),
|
||||||
|
MachOFileType::DynamicallyBoundSharedLibraryFile => write!(f, "Shared object"),
|
||||||
|
MachOFileType::DynamicLinkEditor => write!(f, "Dynamic link editor"),
|
||||||
|
MachOFileType::DynamicallyBoundBundleFile => write!(f, "Dynamically bound bundle file"),
|
||||||
|
MachOFileType::SharedLibraryStub => write!(f, "Shared library stub for static linking only, no section contents"),
|
||||||
|
MachOFileType::CompanionFileWithDebugSections => write!(f, "Companion file with only debug sections"),
|
||||||
|
MachOFileType::X86_64Kexts => write!(f, "x86_64 kext"),
|
||||||
|
MachOFileType::ComposedFile => write!(f, "File composed of other Mach-Os to be run in the same userspace sharing a single linkedit"),
|
||||||
|
MachOFileType::Undefined => write!(f, "Undefined"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source: https://en.wikipedia.org/wiki/Mach-O
|
||||||
|
impl Display for MachOOs {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||||
|
match self {
|
||||||
|
MachOOs::MacOS => write!(f, "MacOS"),
|
||||||
|
MachOOs::IOS => write!(f, "IOS"),
|
||||||
|
MachOOs::AppleTVBox => write!(f, "Apple TV Box"),
|
||||||
|
MachOOs::AppleWatch => write!(f, "Apple Watch"),
|
||||||
|
MachOOs::BridgeOS => write!(f, "Bridge OS"),
|
||||||
|
MachOOs::MacCatalyst => write!(f, "Mac Catalyst"),
|
||||||
|
MachOOs::IOSSimulator => write!(f, "IOS simulator"),
|
||||||
|
MachOOs::AppleTVSimulator => write!(f, "Apple TV simulator"),
|
||||||
|
MachOOs::AppleWatchSimulator => write!(f, "Apple watch simulator"),
|
||||||
|
MachOOs::DriverKit => write!(f, "Driver KIT"),
|
||||||
|
MachOOs::AppleVisionPro => write!(f, "Apple Vision Pro"),
|
||||||
|
MachOOs::AppleVisionProSimulator => write!(f, "Apple Vision Pro simulator"),
|
||||||
|
MachOOs::Undefined => write!(f, "Undefined"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||