Compare commits

..
22 Commits
Author SHA1 Message Date
belliash 91ff09f7d2 Make GCC 10 relocatable as well. 2020-08-24 08:11:03 +02:00
belliash 4a042370b0 Bump GCC version to 10.2.0 2020-08-23 01:32:09 +02:00
belliash afa9926f6c Correct XTchain banner. 2020-08-17 18:09:16 +02:00
belliash 71cde519cb Disable X support in Wine. 2020-08-17 17:36:13 +02:00
belliash 85aacf9adf Update MinGW-W64 and switch from msvcrt to ucrt. 2020-08-17 15:16:21 +02:00
belliash 8ed69629c0 Several changes to GNU toolchain based XTchain:
* Fix binutils patch
* Add make and wine tools
* Do not hardcode MinGW library and NT version
* Add licensing information
* General synchronization with LLVM-based XTchain
2020-08-17 13:59:31 +02:00
belliash a2c597b1bc Remove useless patch. 2020-08-17 08:36:28 +02:00
belliash 7c0e0b3a53 Rename Binutils patchdir. 2020-08-16 21:04:40 +02:00
belliash 6a44f74ff8 Rename GCC patchdir. 2020-08-16 19:58:49 +02:00
belliash bbb5a07443 Update binutils patch. 2020-08-16 18:59:29 +02:00
belliash 2ee332e437 Add COFF/PE XT subsystem support for GNU linker. 2020-08-16 13:29:20 +02:00
belliash 2ba34cbee2 Set some CFLAGS, to make binaries more portable and lower size. 2020-08-04 14:55:39 +02:00
belliash 8395dd7e9c Make GCC relocatable. 2020-08-04 08:08:23 +02:00
belliash 464cc8b090 Enable GOLD linker. 2020-08-04 07:26:53 +02:00
belliash b3c8f93cb1 Add easy way to apply patch on top of any package used. 2020-08-03 18:33:22 +02:00
belliash a04ae78d23 Preserve attributes. 2020-08-03 16:58:17 +02:00
belliash 55519d72e9 Make sure user .bashrc will not overwrite fancy prompt. 2020-08-03 16:23:13 +02:00
belliash ef78d173cb Correct typo. 2020-08-03 16:21:56 +02:00
belliash 4ab8beba6d Inherit user .bashrc file and identify FBE in prompt. 2020-08-03 16:21:12 +02:00
belliash 1cc7c79339 Add readme. 2020-08-02 14:33:18 +02:00
belliash a8ad222100 Increase compression level. 2020-08-02 00:49:50 +02:00
belliash 251f48ec88 Import FBE build scripts. 2020-08-01 23:01:33 +02:00
26 changed files with 3159 additions and 65080 deletions
-29
View File
@@ -1,29 +0,0 @@
name: Builds
run-name: ${{ github.actor }} runs Gitea Actions
on: [push]
jobs:
XTchain:
strategy:
matrix:
target: [linux, windows]
build: [full, minimal]
runs-on: oscw
container:
image: codingworkshop/oscw-runner:latest
steps:
- name: Clone repository
uses: actions/checkout@v3
- name: Build XTchain
run: |
if [ "${{ matrix.build }}" == "minimal" ]; then
./build.sh --jobs=10 --target=${{ matrix.target }} --minimal
else
./build.sh --jobs=10 --target=${{ matrix.target }}
fi
- name: Publish binaries
if: startsWith(github.ref, 'refs/tags/')
env:
OSCW_GITHUB_USERNAME: ${{ secrets.OSCW_GITHUB_USERNAME }}
OSCW_GITHUB_PASSWORD: ${{ secrets.OSCW_GITHUB_PASSWORD }}
run: github_publish $OSCW_GITHUB_USERNAME $OSCW_GITHUB_PASSWORD $(ls xtchain-*-${{ matrix.target }}.*)
-3
View File
@@ -1,3 +0,0 @@
binaries/*
sources/*
xtchain-*.zst
+15 -42
View File
@@ -1,49 +1,22 @@
<p align=center>
<a href="https://git.codingworkshop.eu.org/xt-sys/xtchain">
<img alt="GIT Repository" src="https://img.shields.io/badge/Source-GIT-purple">
</a>
<a href="https://git.codingworkshop.eu.org/xt-sys/xtchain/actions">
<img alt="Build Status" src="https://codingworkshop.eu.org/actions.php?project=xt-sys/xtchain">
</a>
<a href="https://github.com/xt-sys/xtchain/releases">
<img alt="Releases" src="https://img.shields.io/github/v/release/xt-sys/xtchain?label=Release&amp;color=blueviolet">
</a>
<a href="https://git.codingworkshop.eu.org/xt-sys/xtchain/src/branch/master/COPYING.md">
<img alt="License" src="https://img.shields.io/badge/License-GPLv3-blue.svg">
</a>
<a href="https://github.com/sponsors/xt-sys/">
<img alt="Sponsors" src="https://img.shields.io/badge/Sponsor-%E2%9D%A4-red?logo=GitHub">
</a>
<a href="https://discord.com/invite/zBzJ5qMGX7">
<img alt="Discord" src="https://img.shields.io/badge/Chat-Join%20Discord-success">
</a>
</p>
---
## XT Toolchain
The XT Toolchain is a build environment based on LLVM/Clang/LLD. It currently supports C and C++, and includes
a variety of auxiliary tools such as IDL, message, and resource compilers. The XT Toolchain is the official
build system for compiling XT software, including the XT OS. It is currently available for Linux and Windows
host systems.
This is a GNU-based mingw-w64 toolchain. It currently supports C and C++, and provides a variety of
tools including IDL, message and resource compilers. The XT Toolchain is also the official build
environment for compiling XT software, including the FerretOS. Currently, it is targeted at Linux
host only, however it should be possible to build it in MSYS2 as well.
Key Benefits of using an LLVM-based Toolchain:
* Unified toolchain for multiple target architectures: i686, x86_64, armv7, and aarch64
* Support for generating debug information in PDB format
* Ability to target ARM/AArch64 architectures and produce ARM binaries
This toolchain includes the following software:
This software includes:
* Binutils
* CMake
* LLVM
* GCC
* Make
* Mingw-w64
* Ninja
* Wine
**Note:** This toolchain is based on the [LLVM MinGW Toolchain](https://github.com/mstorsjo/llvm-mingw).
## Licensing
The XTchain project includes scripts for building and assembling the toolchain, as well as the environment
shell. These components are licensed under the GNU GPLv3 license. This license applies only to the parts
provided directly by XTchain. For detailed information, please refer to the COPYING.md file.
The final pre-built toolchain is subject to the licenses of the individual third-party projects it includes.
A complete list of the external software used in this toolchain can be found in the README.md file.
The XTchain project includes the scripts for building and assembling a toolchain as well as
environmental shell. These are licensed under the GPLv3 license. It covers only mentioned
components that are provided by XTchain directly. For more information on that, refer to the
COPYING.md file. The final pre-built toolchain is covered by the licenses of the individual,
external projects. The full list of software incorporated into this toolchain is available in the
README.md file.
Executable
+535
View File
@@ -0,0 +1,535 @@
#!/bin/bash
# PROJECT: XTchain
# LICENSE: See the COPYING.md in the top level directory
# FILE: build-linux.sh
# DESCRIPTION: Toolchain building and assembly script
# DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
# Working Directories
BINDIR="$(pwd)/binaries"
PCHDIR="$(pwd)/patches"
SRCDIR="$(pwd)/sources"
WRKDIR="$(pwd)"
# Architecture Settings
ARCHS="i686 x86_64"
GENERIC="generic-w64-mingw32"
# Compiler Flags
CFLAGS="-march=x86-64 -mtune=generic -O2 -s -pipe"
CXXFLAGS="${CFLAGS}"
# Binutils Settings
BINUTILSDIR="${SRCDIR}/binutils"
BINUTILSTAG="binutils-2_35"
BINUTILSVCS="git://sourceware.org/git/binutils-gdb.git"
# CMake Settings
CMAKEDIR="${SRCDIR}/cmake"
CMAKETAG="v3.18.1"
CMAKEVCS="https://gitlab.kitware.com/cmake/cmake.git"
# GCC Settings
GCCDIR="${SRCDIR}/gcc"
GCCTAG="releases/gcc-10.2.0"
GCCVCS="git://gcc.gnu.org/git/gcc.git"
# Make Settings
MAKEDIR="${SRCDIR}/make"
MAKETAG="4.3"
MAKEVCS="git://git.savannah.gnu.org/make"
# Mingw-w64 Settings
MINGWDIR="${SRCDIR}/mingw-w64"
MINGWLIB="ucrt"
MINGWTAG="v7.0.0"
MINGWNTV="0x601"
MINGWVCS="https://github.com/mirror/mingw-w64.git"
# Ninja Settings
NINJADIR="${SRCDIR}/ninja"
NINJATAG="v1.10.0"
NINJAVCS="https://github.com/ninja-build/ninja.git"
# Wine Settings
WINEDIR="${SRCDIR}/wine"
WINETAG="wine-5.15"
WINEVCS="git://source.winehq.org/git/wine.git"
# This function applies a patches to the 3rd party project
apply_patches()
{
local PACKAGE="${1}"
local VERSION="${2}"
if [ -d "${PCHDIR}/${PACKAGE}/${VERSION}" ]; then
PATCHES="$(find ${PCHDIR}/${PACKAGE}/${VERSION} -name '*.diff' -o -name '*.patch' | sort -n)"
echo ">>> Applying custom patches ..."
for PATCH in ${PATCHES}; do
if [ -f "${PATCH}" ] && [ -r "${PATCH}" ]; then
for PREFIX in {0..5}; do
if patch -i${PATCH} -p${PREFIX} --silent --dry-run >/dev/null; then
patch -i${PATCH} -p${PREFIX} --silent
echo ">>> Patch ${PATCH} applied ..."
break;
elif [ ${PREFIX} -ge 5 ]; then
echo "Patch ${PATCH} does not fit. Failed applying patch ..."
return 1
fi
done
fi
done
fi
}
# This function compiles and installs BINUTILS
binutils_build()
{
for ARCH in ${ARCHS}; do
echo ">>> Building BINUTILS for ${ARCH} ..."
[ -z ${CLEAN} ] || rm -rf ${BINUTILSDIR}/build-${ARCH}
mkdir -p ${BINUTILSDIR}/build-${ARCH}
cd ${BINUTILSDIR}/build-${ARCH}
../configure \
--target=${ARCH}-w64-mingw32 \
--prefix=${BINDIR} \
--with-sysroot=${BINDIR} \
--with-zlib=yes \
--disable-multilib \
--disable-nls \
--disable-werror \
--enable-gold \
--enable-lto \
--enable-plugins
make -j${CORES}
make install
done
cd ${WRKDIR}
}
# This function downloads BINUTILS from VCS
binutils_fetch()
{
if [ ! -d ${BINUTILSDIR} ]; then
echo ">>> Downloading BINUTILS ..."
git clone ${BINUTILSVCS} ${BINUTILSDIR}
cd ${BINUTILSDIR}
git checkout tags/${BINUTILSTAG}
apply_patches ${BINUTILSDIR##*/} ${BINUTILSTAG##*-}
cd ${WRKDIR}
fi
}
# This function compiles and installs CMAKE
cmake_build()
{
echo ">>> Building CMAKE ..."
[ -z ${CLEAN} ] || rm -rf ${CMAKEDIR}/build-${GENERIC}
mkdir -p ${CMAKEDIR}/build-${GENERIC}
cd ${CMAKEDIR}/build-${GENERIC}
../bootstrap \
--prefix=${BINDIR} \
--parallel=${CORES} \
-- -DCMAKE_USE_OPENSSL=OFF
make -j${CORES}
make install
cd ${WRKDIR}
}
# This function downloads CMAKE from VCS
cmake_fetch()
{
if [ ! -d ${CMAKEDIR} ]; then
echo ">>> Downloading CMAKE ..."
git clone ${CMAKEVCS} ${CMAKEDIR}
cd ${CMAKEDIR}
git checkout tags/${CMAKETAG}
apply_patches ${CMAKEDIR##*/} ${CMAKETAG}
cd ${WRKDIR}
fi
}
# This function compiles and install GCC (phase 1)
gcc_build_phase1()
{
for ARCH in ${ARCHS}; do
echo ">>> Building GCC (phase1) for ${ARCH} ..."
[ -z ${CLEAN} ] || rm -rf ${GCCDIR}/build-${ARCH}
mkdir -p ${GCCDIR}/build-${ARCH}
cd ${GCCDIR}/build-${ARCH}
../configure \
--target=${ARCH}-w64-mingw32 \
--prefix=${BINDIR} \
--with-sysroot=${BINDIR} \
--with-pkgversion="FerretOS Build Environment" \
--without-zstd \
--disable-libstdcxx-verbose \
--disable-multilib \
--disable-nls \
--disable-shared \
--disable-werror \
--disable-win32-registry \
--enable-fully-dynamic-string \
--enable-languages=c,c++ \
--enable-lto \
--enable-sjlj-exceptions \
--enable-version-specific-runtime-libs
make -j${CORES} all-gcc
make install-gcc
make install-lto-plugin
done
cd ${WRKDIR}
}
# This function compiles and install GCC (phase 2)
gcc_build_phase2()
{
for ARCH in ${ARCHS}; do
echo ">>> Building GCC (phase2) for ${ARCH} ..."
cd ${GCCDIR}/build-${ARCH}
make -j${CORES}
make install
done
cd ${WRKDIR}
}
# This function downloads GCC from VCS
gcc_fetch()
{
if [ ! -d ${GCCDIR} ]; then
echo ">>> Downloading GCC ..."
git clone ${GCCVCS} ${GCCDIR}
cd ${GCCDIR}
git checkout tags/${GCCTAG}
apply_patches ${GCCDIR##*/} ${GCCTAG##*-}
./contrib/download_prerequisites
cd ${WRKDIR}
fi
}
# This function compiles and install MAKE
make_build()
{
echo ">>> Building Make ..."
[ -z ${CLEAN} ] || rm -rf ${MAKEDIR}/build
cd ${MAKEDIR}
./bootstrap
sed -i "s/-Werror//" maintMakefile
mkdir -p ${MAKEDIR}/build
cd ${MAKEDIR}/build
../configure \
--prefix=${BINDIR} \
--disable-dependency-tracking \
--disable-silent-rules \
--program-prefix=g \
--without-guile
make -j${CORES}
make install
if [ ! -e ${BINDIR}/bin/make ]; then
ln -sf gmake ${BINDIR}/bin/make
fi
cd ${WRKDIR}
}
# This function downloads MAKE from VCS
make_fetch()
{
if [ ! -d ${MAKEDIR} ]; then
echo ">>> Downloading Make ..."
git clone ${MAKEVCS} ${MAKEDIR}
cd ${MAKEDIR}
git checkout tags/${MAKETAG}
apply_patches ${MAKEDIR##*/} ${MAKETAG}
cd ${WRKDIR}
fi
}
# This function compiles and installs MINGW CRT
mingw_build_crt()
{
for ARCH in ${ARCHS}; do
echo ">>> Building Mingw-w64 (CRT) for ${ARCH} ..."
[ -z ${CLEAN} ] || rm -rf ${MINGWDIR}/mingw-w64-crt/build-${ARCH}
mkdir -p ${MINGWDIR}/mingw-w64-crt/build-${ARCH}
cd ${MINGWDIR}/mingw-w64-crt/build-${ARCH}
case ${ARCH} in
i686)
FLAGS="--enable-lib32 --disable-lib64"
;;
x86_64)
FLAGS="--disable-lib32 --enable-lib64"
;;
esac
ORIGPATH="${PATH}"
PATH="${BINDIR}/bin:${PATH}"
../configure \
--host=${ARCH}-w64-mingw32 \
--prefix=${BINDIR}/${ARCH}-w64-mingw32 \
--with-sysroot=${BINDIR} \
--with-default-msvcrt=${MINGWLIB} \
${FLAGS}
make -j${CORES}
make install
PATH="${ORIGPATH}"
done
cd ${WRKDIR}
}
# This function compiles and installs MINGW headers
mingw_build_headers()
{
echo ">>> Building Mingw-w64 (headers) ..."
[ -z ${CLEAN} ] || rm -rf ${MINGWDIR}/mingw-w64-headers/build-${GENERIC}
mkdir -p ${MINGWDIR}/mingw-w64-headers/build-${GENERIC}
cd ${MINGWDIR}/mingw-w64-headers/build-${GENERIC}
../configure \
--prefix=${BINDIR}/${GENERIC} \
--enable-idl \
--with-default-msvcrt=${MINGWLIB} \
--with-default-win32-winnt=${MINGWNTV}
make -j${CORES}
make install
mkdir -p ${BINDIR}/mingw
if [ ! -e ${BINDIR}/mingw/include ]; then
ln -sfn ../${GENERIC}/include ${BINDIR}/mingw/include
fi
for ARCH in ${ARCHS}; do
mkdir -p ${BINDIR}/${ARCH}-w64-mingw32
if [ ! -e ${BINDIR}/${ARCH}-w64-mingw32/include ]; then
ln -sfn ../${GENERIC}/include ${BINDIR}/${ARCH}-w64-mingw32/include
fi
done
cd ${WRKDIR}
}
# This function compiles and install MINGW libraries
mingw_build_libs()
{
for LIB in libmangle winstorecompat; do
echo ">>> Building Mingw-w64 (libs) for ${ARCH} ..."
for ARCH in ${ARCHS}; do
[ -z ${CLEAN} ] || rm -rf ${MINGWDIR}/mingw-w64-libraries/${LIB}/build-${ARCH}
mkdir -p ${MINGWDIR}/mingw-w64-libraries/${LIB}/build-${ARCH}
cd ${MINGWDIR}/mingw-w64-libraries/${LIB}/build-${ARCH}
ORIGPATH="${PATH}"
PATH="${BINDIR}/bin:${PATH}"
../configure \
--host=${ARCH}-w64-mingw32 \
--prefix=${BINDIR}/${ARCH}-w64-mingw32 \
--libdir=${BINDIR}/${ARCH}-w64-mingw32/lib
make -j${CORES}
make install
PATH="${ORIGPATH}"
done
done
cd ${WRKDIR}
}
# This function compiles and installs MINGW tools
mingw_build_tools()
{
for TOOL in gendef genidl genlib genpeimg widl; do
for ARCH in ${ARCHS}; do
echo ">>> Building Mingw-w64 (tools) for ${ARCH} ..."
[ -z ${CLEAN} ] || rm -rf ${MINGWDIR}/mingw-w64-tools/${TOOL}/build-${ARCH}
mkdir -p ${MINGWDIR}/mingw-w64-tools/${TOOL}/build-${ARCH}
cd ${MINGWDIR}/mingw-w64-tools/${TOOL}/build-${ARCH}
../configure \
--target=${ARCH}-w64-mingw32 \
--prefix=${BINDIR}
make -j${CORES}
make install
if [ -e ${BINDIR}/bin/${TOOL} ]; then
mv ${BINDIR}/bin/${TOOL} ${BINDIR}/bin/${ARCH}-w64-mingw32-${TOOL}
fi
done
done
cd ${WRKDIR}
}
# This function downloads MINGW from VCS
mingw_fetch()
{
if [ ! -d ${MINGWDIR} ]; then
echo ">>> Downloading Mingw-w64 ..."
git clone ${MINGWVCS} ${MINGWDIR}
cd ${MINGWDIR}
git checkout tags/${MINGWTAG}
apply_patches ${MINGWDIR##*/} ${MINGWTAG}
cd ${WRKDIR}
fi
}
# This function compiles and installs NINJA
ninja_build()
{
echo ">>> Building NINJA ..."
[ -z ${CLEAN} ] || rm -rf ${NINJADIR}/build-${GENERIC}
mkdir -p ${NINJADIR}/build-${GENERIC}
cd ${NINJADIR}/build-${GENERIC}
../configure.py --bootstrap
install ninja ${BINDIR}/bin/
cd ${WRKDIR}
}
# This function downloads NINJA from VCS
ninja_fetch()
{
if [ ! -d ${NINJADIR} ]; then
echo ">>> Downloading NINJA ..."
git clone ${NINJAVCS} ${NINJADIR}
cd ${NINJADIR}
git checkout tags/${NINJATAG}
apply_patches ${NINJADIR##*/} ${NINJATAG}
cd ${WRKDIR}
fi
}
# This function compiles and install WINE tools
wine_build()
{
echo ">>> Building Wine ..."
mkdir -p ${WINEDIR}/build
cd ${WINEDIR}/build
../configure \
-enable-win64 \
--without-x
for TOOL in winedump wmc wrc; do
make -j${CORES} tools/${TOOL}
cp tools/${TOOL}/${TOOL} ${BINDIR}/bin/
for ARCH in ${ARCHS}; do
if [ ! -e ${BINDIR}/bin/${ARCH}-w64-mingw32-${TOOL} ]; then
ln -sf ${TOOL} ${BINDIR}/bin/${ARCH}-w64-mingw32-${TOOL}
fi
done
done
cd ${WRKDIR}
}
# This function downloads WINE from VCS
wine_fetch()
{
if [ ! -d ${WINEDIR} ]; then
echo ">>> Downloading WINE ..."
git clone ${WINEVCS} ${WINEDIR}
cd ${WINEDIR}
git checkout tags/${WINETAG}
apply_patches ${WINEDIR##*/} ${WINETAG##*-}
cd ${WRKDIR}
fi
}
# This function installs XTCHAIN scripts, wrappers and symlinks
xtchain_build()
{
echo ">>> Building XTchain ..."
mkdir -p ${BINDIR}/bin
mkdir -p ${BINDIR}/lib/xtchain
mkdir -p ${BINDIR}/${GENERIC}/bin
for ARCH in ${ARCHS}; do
for EXEC in xtcspecc; do
if [ ! -e ${BINDIR}/bin/${EXEC} ]; then
gcc ${WRKDIR}/tools/${EXEC}.c -o ${BINDIR}/bin/${EXEC}
fi
ln -sf ${EXEC} ${BINDIR}/bin/${ARCH}-w64-mingw32-${EXEC}
done
done
cp ${WRKDIR}/scripts/xtclib ${BINDIR}/lib/xtchain/
cp ${WRKDIR}/scripts/xtchain ${BINDIR}/
cd ${WRKDIR}
}
# Exit immediately on any failure
set -e
# Check if script launched as root
if [ "$(whoami)" = "root" ]; then
echo "This script cannot be run as root!"
exit 1
fi
# Check number of CPU cores available
: ${CORES:=$(sysctl -n hw.ncpu 2>/dev/null)}
: ${CORES:=$(nproc 2>/dev/null)}
: ${CORES:=1}
# Create working directories
mkdir -p ${BINDIR}
mkdir -p ${SRCDIR}
# Export compiler flags
export CFLAGS
export CXXFLAGS
# XTchain
xtchain_build
# Download Mingw-W64
mingw_fetch
# Build and install Mingw-W64 headers
mingw_build_headers
# Download Binutils
binutils_fetch
# Build and install Binutils
binutils_build
# Download GCC
gcc_fetch
# Build and install minimal GCC
gcc_build_phase1
# Build and install MSVCRT
mingw_build_crt
# Build and install GCC
gcc_build_phase2
# Build and install Mingw-W64 libraries
mingw_build_libs
# Build and install Mingw-W64 tools
mingw_build_tools
# Download Wine
wine_fetch
# Build and install Wine tools
wine_build
# Download Make
make_fetch
# Build and install Make
make_build
# Download CMake
cmake_fetch
# Build and install CMake
cmake_build
# Download Ninja
ninja_fetch
# Build and install Ninja
ninja_build
# Remove unneeded files to save disk space
echo ">>> Removing unneeded files to save disk space ..."
rm -rf ${BINDIR}/{doc,include,mingw,share/{bash-completion,emacs,gcc*,info,man,vim}}
# Save XT Toolchain version
cd ${WRKDIR}
: ${XTCVER:=$(git describe --exact-match --tags 2>/dev/null)}
: ${XTCVER:=DEV}
echo "${XTCVER}" > ${BINDIR}/Version
# Prepare archive
echo ">>> Creating toolchain archive ..."
tar -I 'zstd -19' -cpf xtchain-${XTCVER}-linux.tar.zst -C ${BINDIR} .
-548
View File
@@ -1,548 +0,0 @@
#!/bin/bash
# PROJECT: XTchain
# LICENSE: See the COPYING.md in the top level directory
# FILE: build.sh
# DESCRIPTION: Toolchain crosscompilation and assembly script
# DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
# Aiken Harris <harraiken91@gmail.com>
# Working Directories
BINDIR="$(pwd)/binaries"
PCHDIR="$(pwd)/patches"
SRCDIR="$(pwd)/sources"
WRKDIR="$(pwd)"
# Architecture Settings
ARCHS="aarch64 armv7 i686 x86_64"
# Default Configuration
BUILD_JOBS=0
BUILD_MINIMAL=0
CLEAN_BUILD=0
ENABLE_LLVM_ASSEMBLY=0
LLVM_DYNAMIC_LINK=ON
SYSTEM_NAME=Linux
TARGET_SYSTEM=linux
# CMake Settings
CMAKEDIR="${SRCDIR}/cmake"
CMAKETAG="v4.4.3"
CMAKEVCS="https://gitlab.kitware.com/cmake/cmake.git"
# LLVM Settings
LLVMDIR="${SRCDIR}/llvm"
LLVMTAG="llvmorg-23.1.2"
LLVMVCS="https://github.com/llvm/llvm-project.git"
# Mtools Settings
MTOOLSDIR="${SRCDIR}/mtools"
MTOOLSTAG="v4.0.49"
MTOOLSVCS="https://github.com/xt-sys/mtools.git"
# Ninja Settings
NINJADIR="${SRCDIR}/ninja"
NINJATAG="v1.13.2"
NINJAVCS="https://github.com/ninja-build/ninja.git"
# Wine Settings
WINEDIR="${SRCDIR}/wine"
WINETAG="wine-10.19"
WINEVCS="https://github.com/wine-mirror/wine.git"
# This function applies a patches to the 3rd party project
apply_patches()
{
local PACKAGE="${1}"
local VERSION="${2}"
if [ -d "${PCHDIR}/${PACKAGE}/${VERSION}" ]; then
PATCHES="$(find ${PCHDIR}/${PACKAGE}/${VERSION} -name '*.diff' -o -name '*.patch' | sort -n)"
echo ">>> Applying custom patches ..."
for PATCH in ${PATCHES}; do
if [ -f "${PATCH}" ] && [ -r "${PATCH}" ]; then
for PREFIX in {0..5}; do
if patch -i${PATCH} -p${PREFIX} --silent --dry-run >/dev/null; then
patch -i${PATCH} -p${PREFIX} --silent
echo ">>> Patch ${PATCH} applied ..."
break;
elif [ ${PREFIX} -ge 5 ]; then
echo "Patch ${PATCH} does not fit. Failed applying patch ..."
return 1
fi
done
fi
done
fi
}
# This function compiles and installs CMAKE
cmake_build()
{
local CMAKE_PARAMETERS=""
# Clean old build if necessary
[ "${CLEAN_BUILD}" -eq 1 ] && rm -rf ${WINEDIR}/build-${SYSTEM_NAME}
# Additional, target-specific configuration options
case "${SYSTEM_NAME}" in
Windows)
CMAKE_PARAMETERS="${CMAKE_PARAMETERS} -DCMAKE_C_COMPILER=${SYSTEM_HOST}-gcc -DCMAKE_CXX_COMPILER=${SYSTEM_HOST}-g++"
CMAKE_PARAMETERS="${CMAKE_PARAMETERS} -DCMAKE_RC_COMPILER=${SYSTEM_HOST}-windres"
;;
esac
# Build CMake
echo ">>> Building CMAKE ..."
mkdir -p ${CMAKEDIR}/build-${SYSTEM_NAME}
cd ${CMAKEDIR}/build-${SYSTEM_NAME}
cmake \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY \
-DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY \
-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER \
-DCMAKE_INSTALL_PREFIX=${BINDIR} \
-DCMAKE_SYSTEM_NAME=${SYSTEM_NAME} \
-DCMAKE_USE_OPENSSL=OFF \
${CMAKE_PARAMETERS} \
..
cmake --build . --parallel ${BUILD_JOBS}
cmake --install .
cd ${WRKDIR}
}
# This function downloads CMAKE from VCS
cmake_fetch()
{
if [ ! -d ${CMAKEDIR} ]; then
echo ">>> Downloading CMAKE ..."
git clone --depth 1 --branch ${CMAKETAG} ${CMAKEVCS} ${CMAKEDIR}
cd ${CMAKEDIR}
apply_patches ${CMAKEDIR##*/} ${CMAKETAG}
cd ${WRKDIR}
fi
}
# This function compiles and install LLVM
llvm_build()
{
local CMAKE_PARAMETERS=""
local LLVM_ARCHS=()
# Clean old build if necessary
[ "${CLEAN_BUILD}" -eq 1 ] && rm -rf ${LLVMDIR}/llvm/build-${SYSTEM_NAME}
# Set supported architectures
for ARCH in ${ARCHS}; do
case ${ARCH} in
"aarch64")
LLVM_ARCHS+=( "AArch64" )
;;
"armv7")
LLVM_ARCHS+=( "ARM" )
;;
"i686"|"x86_64")
LLVM_ARCHS+=( "X86" )
;;
esac
done
LLVM_ARCHS=( $(for ARCH in ${LLVM_ARCHS[@]}; do echo ${ARCH}; done | sort -u) )
# Disable LLVM assembly files (like BLAKE3 support) if not specified otherwise
if [ "${ENABLE_LLVM_ASSEMBLY}" -ne 1 ]; then
CMAKE_PARAMETERS="${CMAKE_PARAMETERS} -DLLVM_DISABLE_ASSEMBLY_FILES=ON"
fi
# Additional, target-specific configuration options
case "${SYSTEM_NAME}" in
Windows)
CMAKE_PARAMETERS="${CMAKE_PARAMETERS} -DCMAKE_EXE_LINKER_FLAGS=-lpthread -DCMAKE_SHARED_LINKER_FLAGS=-lpthread"
CMAKE_PARAMETERS="${CMAKE_PARAMETERS} -DCMAKE_C_COMPILER_TARGET=${SYSTEM_HOST} -DCMAKE_CXX_COMPILER_TARGET=${SYSTEM_HOST}"
CMAKE_PARAMETERS="${CMAKE_PARAMETERS} -DCMAKE_RC_COMPILER=${SYSTEM_HOST}-windres -DLLVM_HOST_TRIPLE=${SYSTEM_HOST}"
CMAKE_PARAMETERS="${CMAKE_PARAMETERS} -DCMAKE_FIND_ROOT=$(dirname $(readlink -f $(command -v ${SYSTEM_HOST}-windres)))/../${SYSTEM_HOST}"
CMAKE_PARAMETERS="${CMAKE_PARAMETERS} -DCMAKE_CXX_FLAGS=-femulated-tls"
;;
esac
# Build LLVM
echo ">>> Building LLVM ..."
cd ${LLVMDIR}/llvm/tools
for UTIL in clang lld; do
if [ ! -e ${UTIL} ]; then
ln -sf ../../${UTIL} .
fi
done
mkdir -p ${LLVMDIR}/llvm/build-${SYSTEM_NAME}
cd ${LLVMDIR}/llvm/build-${SYSTEM_NAME}
cmake -G Ninja \
-DCMAKE_BUILD_TYPE="Release" \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_CXX_COMPILER=clang++ \
-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY \
-DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY \
-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ONLY \
-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER \
-DCMAKE_INSTALL_PREFIX=${BINDIR} \
-DCMAKE_SYSTEM_NAME="${SYSTEM_NAME}" \
-DLLDB_INCLUDE_TESTS=OFF \
-DLLVM_ENABLE_ASSERTIONS=OFF \
-DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;lld;lldb" \
-DLLVM_INSTALL_TOOLCHAIN_ONLY=ON \
-DLLVM_BUILD_INSTRUMENTED=OFF \
-DLLVM_LINK_LLVM_DYLIB=${LLVM_DYNAMIC_LINK} \
-DLLVM_TARGETS_TO_BUILD="$(echo ${LLVM_ARCHS[@]} | tr ' ' ';')" \
-DLLVM_TOOLCHAIN_TOOLS="llvm-addr2line;llvm-ar;llvm-as;llvm-cov;llvm-cvtres;llvm-cxxfilt;llvm-dlltool;llvm-lib;llvm-ml;llvm-nm;llvm-objdump;llvm-objcopy;llvm-pdbutil;llvm-profdata;llvm-ranlib;llvm-rc;llvm-readelf;llvm-readobj;llvm-size;llvm-strings;llvm-strip;llvm-symbolizer;llvm-windres" \
-DLLVM_USE_LINKER=lld \
-DLLDB_ENABLE_PYTHON=OFF \
${CMAKE_PARAMETERS} \
..
ninja -j ${BUILD_JOBS} install/strip
cd ${WRKDIR}
}
# This function downloads LLVM from VCS
llvm_fetch()
{
if [ ! -d ${LLVMDIR} ]; then
echo ">>> Downloading LLVM ..."
git clone --depth 1 --branch ${LLVMTAG} ${LLVMVCS} ${LLVMDIR}
cd ${LLVMDIR}
apply_patches ${LLVMDIR##*/} ${LLVMTAG##*-}
cd ${WRKDIR}
fi
}
# This function compiles and installs MTOOLS
mtools_build()
{
local CONFIGURE_PARAMETERS=""
local EXTENSION=""
# Clean old build if necessary
[ "${CLEAN_BUILD}" -eq 1 ] && rm -rf ${MTOOLSDIR}/build-${SYSTEM_NAME}
# Additional, target-specific configuration options
case "${SYSTEM_NAME}" in
Windows)
CONFIGURE_PARAMETERS="${CONFIGURE_PARAMETERS} --host=${SYSTEM_HOST}"
EXTENSION=".exe"
;;
esac
# Build Mtools
echo ">>> Building MTOOLS ..."
mkdir -p ${MTOOLSDIR}/build-${SYSTEM_NAME}
cd ${MTOOLSDIR}/build-${SYSTEM_NAME}
../configure ${CONFIGURE_PARAMETERS}
make -j ${BUILD_JOBS}
cp mtools${EXTENSION} ${BINDIR}/bin/
for TOOL in mcat mcd mcopy mdel mdir mformat minfo mlabel mmd mmove mpartition mrd mren mshowfat mtype mzip; do
cp mtools${EXTENSION} ${BINDIR}/bin/${TOOL}${EXTENSION}
done
cd ${WRKDIR}
}
# This function downloads MTOOLS from VCS
mtools_fetch()
{
if [ ! -d ${MTOOLSDIR} ]; then
echo ">>> Downloading MTOOLS ..."
git clone --depth 1 --branch ${MTOOLSTAG} ${MTOOLSVCS} ${MTOOLSDIR}
cd ${MTOOLSDIR}
apply_patches ${MTOOLSDIR##*/} ${MTOOLSTAG}
cd ${WRKDIR}
fi
}
# This function compiles and installs NINJA
ninja_build()
{
local EXTENSION=""
local NINJA_CXX_COMPILER=""
local NINJA_PLATFORM=""
# Clean old build if necessary
[ "${CLEAN_BUILD}" -eq 1 ] && rm -rf ${NINJADIR}/build-${SYSTEM_NAME}
# Additional, target-specific configuration options
case "${SYSTEM_NAME}" in
Windows)
EXTENSION=".exe"
NINJA_CXX_COMPILER="${SYSTEM_HOST}-g++"
NINJA_PLATFORM="mingw"
;;
*)
NINJA_CXX_COMPILER="clang++"
NINJA_PLATFORM="linux"
;;
esac
# Build Ninja
echo ">>> Building NINJA ..."
mkdir -p ${NINJADIR}/build-${SYSTEM_NAME}
cd ${NINJADIR}/build-${SYSTEM_NAME}
CXX=${NINJA_CXX_COMPILER} ../configure.py --platform=${NINJA_PLATFORM}
ninja -j ${BUILD_JOBS}
install ninja${EXTENSION} ${BINDIR}/bin/
cd ${WRKDIR}
}
# This function downloads NINJA from VCS
ninja_fetch()
{
if [ ! -d ${NINJADIR} ]; then
echo ">>> Downloading NINJA ..."
git clone --depth 1 --branch ${NINJATAG} ${NINJAVCS} ${NINJADIR}
cd ${NINJADIR}
apply_patches ${NINJADIR##*/} ${NINJATAG}
cd ${WRKDIR}
fi
}
# Performs requirements check and prepares environment
prepare_environment()
{
# Verify that the number of build jobs is a positive integer
if [ -z "${BUILD_JOBS##*[!0-9]*}" ]; then
echo "ERROR: Invalid number of jobs provided. Please enter a positive integer."
exit 1
fi
# Verify that all required tools are installed
for APP in {clang,clang++,cmake,lld,ninja,x86_64-w64-mingw32-windres}; do
which ${APP} &> /dev/null
if [ $? -ne 0 ]; then
echo "ERROR: ${APP} not found. Please install the required tool."
exit 2
fi
done
# Set target-specific options
case "${TARGET_SYSTEM}" in
windows|*-mingw32)
SYSTEM_NAME="Windows"
SYSTEM_HOST="x86_64-w64-mingw32"
;;
linux|*-linux-*)
SYSTEM_NAME="Linux"
;;
*)
echo "ERROR: Invalid target system specified. Please choose a valid target system."
exit 3
;;
esac
}
# Prints usage help
print_usage()
{
echo "USAGE: ${0} [--clean] [--enable-llvm-assembly] [--jobs=N] [--minimal] [--static-llvm] [--target={linux,windows}]"
exit 1
}
# This function compiles and install WINE tools
wine_build()
{
local CONFIGURE_PARAMETERS=""
local EXTENSION=""
# Clean old build if necessary
[ "${CLEAN_BUILD}" -eq 1 ] && rm -rf ${WINEDIR}/{build-${SYSTEM_NAME},build-tools}
# Additional, target-specific configuration options
case "${SYSTEM_NAME}" in
Windows)
CONFIGURE_PARAMETERS="${CONFIGURE_PARAMETERS} --host=${SYSTEM_HOST}"
EXTENSION=".exe"
;;
esac
# Build Wine (first configuration builds makedep)
echo ">>> Building Wine ..."
mkdir -p ${WINEDIR}/{build-${SYSTEM_NAME},build-tools}
cd ${WINEDIR}/build-tools
../configure \
--enable-win64 \
--without-freetype \
--without-x
cd ${WINEDIR}/build-${SYSTEM_NAME}
../configure \
--enable-tools \
--enable-win64 \
--with-wine-tools=${WINEDIR}/build-tools \
--without-freetype \
--without-x \
${CONFIGURE_PARAMETERS}
for TOOL in widl wmc wrc; do
make -j ${BUILD_JOBS} tools/${TOOL}/all
cp tools/${TOOL}/${TOOL}${EXTENSION} ${BINDIR}/bin/
done
cd ${WRKDIR}
}
# This function downloads WINE from VCS
wine_fetch()
{
if [ ! -d ${WINEDIR} ]; then
echo ">>> Downloading WINE ..."
git clone --depth 1 --branch ${WINETAG} ${WINEVCS} ${WINEDIR}
cd ${WINEDIR}
apply_patches ${WINEDIR##*/} ${WINETAG##*-}
cd ${WRKDIR}
fi
}
# This function installs XTCHAIN tools and scripts
xtchain_build()
{
# Target-specific configuration options
case "${SYSTEM_NAME}" in
Windows)
CCOMPILER="${SYSTEM_HOST}-gcc"
;;
*)
CCOMPILER="clang"
esac
# Build XTchain tools
echo ">>> Building XTchain tools ..."
mkdir -p ${BINDIR}/bin
mkdir -p ${BINDIR}/lib/xtchain
for EXEC in bin2c diskimg exetool mkxthv xtadkgen xtcspecc xtnlsc; do
if [ ! -e ${BINDIR}/bin/${EXEC} ]; then
${CCOMPILER} -I${WRKDIR}/tools/includes ${WRKDIR}/tools/${EXEC}.c -o ${BINDIR}/bin/${EXEC}
fi
done
cp ${WRKDIR}/scripts/xtclib* ${BINDIR}/lib/xtchain/
cp ${WRKDIR}/scripts/xtchain* ${BINDIR}/
}
# This function generates XTCHAIN version file and produces tarball archive
xtchain_tarball()
{
local EXTENSION=""
local LIBDIR=""
# Additional, target-specific configuration options
case "${SYSTEM_NAME}" in
Windows)
EXTENSION=".exe"
;;
esac
# Remove unneeded files to save disk space
echo ">>> Removing unneeded files to save disk space ..."
rm -rf ${BINDIR}/{doc,include,share/{bash-completion,emacs,info,locale,man,vim}}
for EXEC in amdgpu-arch clang-check clang-exdef-mapping clang-import-test clang-offload-* clang-rename clang-scan-deps diagtool hmaptool ld64.lld modularize nxptx-arch wasm-ld; do
rm -f ${BINDIR}/bin/${EXEC}${EXTENSION}
done
# Generate version file
cd ${WRKDIR}
: ${XTCVER:=$(git describe --exact-match --tags 2>/dev/null)}
: ${XTCVER:=DEVEL}
[ ${BUILD_MINIMAL} -eq 1 ] && XTCVER="${XTCVER}-lite"
echo "${XTCVER}" > ${BINDIR}/Version
# Windows target specific actions
if [ "${SYSTEM_NAME}" == "Windows" ]; then
# Replace symlinks with original files
for LINK in $(find ${BINDIR}/bin -maxdepth 1 -type l); do
cp -f --remove-destination $(readlink -e ${LINK}) ${LINK}
done
# Copy dynamic libraries
if [ ${BUILD_MINIMAL} -eq 0 ]; then
LIBDIR="$(dirname $(readlink -f $(command -v ${SYSTEM_HOST}-windres)))/../${SYSTEM_HOST}"
for DLL in $(${SYSTEM_HOST}-objdump --private-headers ${BINDIR}/bin/cmake.exe | grep "DLL Name:" | cut -d' ' -f3 | grep "lib.*.dll"); do
find ${LIBDIR} -type f -name ${DLL} -exec cp {} ${BINDIR}/bin \;
done
fi
fi
# Build tarball
echo ">>> Creating toolchain archive ..."
tar -I 'zstd -19' -cpf xtchain-${XTCVER}-${TARGET_SYSTEM}.tar.zst -C ${BINDIR} .
}
# Parse all arguments provided to the script
while [ $# -gt 0 ]; do
case "$1" in
--clean)
# Performs clean build
CLEAN_BUILD=1
;;
--enable-llvm-assembly)
# Enables LLVM asembly files compilation (like BLAKE3)
ENABLE_LLVM_ASSEMBLY=1
;;
--jobs=*)
# Sets number of CPU cores used for compilation
BUILD_JOBS="${1#*=}"
;;
--minimal)
BUILD_MINIMAL=1
;;
--static-llvm)
# Compiles LLVM statically
LLVM_DYNAMIC_LINK=OFF
;;
--target=*)
# Sets the target system for built toolchain (Linux or Windows)
TARGET_SYSTEM="${1#*=}"
;;
*)
# Prints help if any other parameter given
print_usage
;;
esac
shift
done
# Prepare environment
prepare_environment
# Exit immediately on any failure
set -e
# Check number of CPU cores available
if [ ${BUILD_JOBS} -eq 0 ]; then
unset BUILD_JOBS
: ${BUILD_JOBS:=$(sysctl -n hw.ncpu 2>/dev/null)}
: ${BUILD_JOBS:=$(nproc 2>/dev/null)}
: ${BUILD_JOBS:=1}
fi
# Create working directories
mkdir -p ${BINDIR}
mkdir -p ${SRCDIR}
# Build XTchain tools
xtchain_build
# Download and build Wine tools
wine_fetch
wine_build
# Download and build GNU Mtools
mtools_fetch
mtools_build
if [ ${BUILD_MINIMAL} -eq 0 ]; then
# Download and build LLVM
llvm_fetch
llvm_build
# Download and build CMake
cmake_fetch
cmake_build
# Download and build Ninja
ninja_fetch
ninja_build
fi
# Generate tarball archive
xtchain_tarball
@@ -0,0 +1,126 @@
diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c
index 5149ef582b..f09e4b7382 100644
--- a/bfd/peXXigen.c
+++ b/bfd/peXXigen.c
@@ -2952,6 +2952,25 @@ _bfd_XX_print_private_bfd_data_common (bfd * abfd, void * vfile)
case IMAGE_SUBSYSTEM_XBOX:
subsystem_name = "XBOX";
break;
+ /* These are the XT specific subsystems */
+ case IMAGE_SUBSYSTEM_XT_DRIVER:
+ subsystem_name = "XT driver";
+ break;
+ case IMAGE_SUBSYSTEM_XT_NATIVE:
+ subsystem_name = "XT native";
+ break;
+ case IMAGE_SUBSYSTEM_XT_GDIAPP:
+ subsystem_name = "XT GDI application";
+ break;
+ case IMAGE_SUBSYSTEM_XT_CLIAPP:
+ subsystem_name = "XT CLI application";
+ break;
+ case IMAGE_SUBSYSTEM_XT_PSXAPP:
+ subsystem_name = "XT PSX application";
+ break;
+ case IMAGE_SUBSYSTEM_XT_DYNLIB:
+ subsystem_name = "XT dynamic library";
+ break;
/* Added default case for clarity - subsystem_name is NULL anyway. */
default:
subsystem_name = NULL;
diff --git a/binutils/objcopy.c b/binutils/objcopy.c
index 3866c7f458..55e069831b 100644
--- a/binutils/objcopy.c
+++ b/binutils/objcopy.c
@@ -4860,7 +4860,13 @@ set_pe_subsystem (const char *s)
{ "efi-bsd", 1, IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER },
{ "efi-rtd", 1, IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER },
{ "sal-rtd", 1, IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER },
- { "xbox", 0, IMAGE_SUBSYSTEM_XBOX }
+ { "xbox", 0, IMAGE_SUBSYSTEM_XBOX },
+ { "xt-driver", 0, IMAGE_SUBSYSTEM_XT_DRIVER },
+ { "xt-native", 0, IMAGE_SUBSYSTEM_XT_NATIVE },
+ { "xt-gdiapp", 0, IMAGE_SUBSYSTEM_XT_GDIAPP },
+ { "xt-cliapp", 0, IMAGE_SUBSYSTEM_XT_CLIAPP },
+ { "xt-psxapp", 0, IMAGE_SUBSYSTEM_XT_PSXAPP },
+ { "xt-dynlib", 0, IMAGE_SUBSYSTEM_XT_DYNLIB }
};
short value;
char *copy;
diff --git a/include/coff/pe.h b/include/coff/pe.h
index c83a958eee..deeea6b49a 100644
--- a/include/coff/pe.h
+++ b/include/coff/pe.h
@@ -169,6 +169,12 @@
#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12
#define IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER 13
#define IMAGE_SUBSYSTEM_XBOX 14
+#define IMAGE_SUBSYSTEM_XT_DRIVER 21
+#define IMAGE_SUBSYSTEM_XT_NATIVE 22
+#define IMAGE_SUBSYSTEM_XT_GDIAPP 23
+#define IMAGE_SUBSYSTEM_XT_CLIAPP 24
+#define IMAGE_SUBSYSTEM_XT_PSXAPP 25
+#define IMAGE_SUBSYSTEM_XT_DYNLIB 26
/* NT allows long filenames, we want to accommodate this.
This may break some of the bfd functions. */
diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em
index 3899c9d92c..c9277ded20 100644
--- a/ld/emultempl/pe.em
+++ b/ld/emultempl/pe.em
@@ -539,6 +539,12 @@ set_entry_point (void)
{ 7, "__PosixProcessStartup"},
{ 9, "WinMainCRTStartup" },
{14, "mainCRTStartup" },
+ {21, "XtDriverStartup" },
+ {22, "XtProcessStartup" },
+ {23, "XtgMainProcessStartup" },
+ {24, "XtcMainProcessStartup" },
+ {25, "XtpMainProcessStartup" },
+ {26, "XtlMainLibraryStartup" },
{ 0, NULL }
};
@@ -606,6 +611,12 @@ set_pe_subsystem (void)
{ "posix", 7},
{ "wince", 9},
{ "xbox", 14},
+ { "xt-driver", 21},
+ { "xt-native", 22},
+ { "xt-gdiapp", 23},
+ { "xt-cliapp", 24},
+ { "xt-psxapp", 25},
+ { "xt-dynlib", 26},
{ NULL, 0 }
};
diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em
index a0a7023e70..001aa34769 100644
--- a/ld/emultempl/pep.em
+++ b/ld/emultempl/pep.em
@@ -504,6 +504,12 @@ set_entry_point (void)
{ 7, "__PosixProcessStartup" },
{ 9, "WinMainCRTStartup" },
{14, "mainCRTStartup" },
+ {21, "XtDriverStartup" },
+ {22, "XtProcessStartup" },
+ {23, "XtgMainProcessStartup" },
+ {24, "XtcMainProcessStartup" },
+ {25, "XtpMainProcessStartup" },
+ {26, "XtlMainLibraryStartup" },
{ 0, NULL }
};
@@ -568,6 +573,12 @@ set_pep_subsystem (void)
{ "posix", 7 },
{ "wince", 9 },
{ "xbox", 14 },
+ { "xt-driver", 21},
+ { "xt-native", 22},
+ { "xt-gdiapp", 23},
+ { "xt-cliapp", 24},
+ { "xt-psxapp", 25},
+ { "xt-dynlib", 26},
{ NULL, 0 }
};
@@ -0,0 +1,36 @@
Though GOLD is not yet enabled for TDM-GCC, this patch will help
From: J.M. Eubank <john@thesnappy.net>
From
<https://github.com/msys2/MINGW-packages/blob/master/mingw-w64-binutils/0001-enable-gold-on.mingw32.patch>
---
0 files changed
diff --git a/configure b/configure
index 6a9719f6..f07a3b7f 100755
--- a/configure
+++ b/configure
@@ -3001,6 +3001,7 @@ case "${ENABLE_GOLD}" in
yes|default)
# Check for ELF target.
is_elf=no
+ is_pe=no
case "${target}" in
*-*-elf* | *-*-sysv4* | *-*-unixware* | *-*-eabi* | hppa*64*-*-hpux* \
| *-*-linux* | *-*-gnu* | frv-*-uclinux* | *-*-irix5* | *-*-irix6* \
@@ -3012,10 +3013,12 @@ case "${ENABLE_GOLD}" in
*)
is_elf=yes
;;
- esac
+ esac;;
+ *-*-mingw*)
+ is_pe=yes;;
esac
- if test "$is_elf" = "yes"; then
+ if test "$is_elf" = "yes" -o "$is_pe" = "yes"; then
# Check for target supported by gold.
case "${target}" in
i?86-*-* | x86_64-*-* | sparc*-*-* | powerpc*-*-* | arm*-*-* \
@@ -0,0 +1,57 @@
Make GCC fully relocatable, not searching any fixed paths
From: J.M. Eubank <john@thesnappy.net>
that aren't relative to the current installation path
# HG changeset patch
# Parent 2a1167ee4ed20c6ff3558a104218585837e9963f
---
0 files changed
diff --git a/gcc/config/i386/mingw32.h b/gcc/config/i386/mingw32.h
index 086c0e460..f0ceca42b 100644
--- a/gcc/config/i386/mingw32.h
+++ b/gcc/config/i386/mingw32.h
@@ -78,7 +78,7 @@ along with GCC; see the file COPYING3. If not see
#endif
#undef NATIVE_SYSTEM_HEADER_COMPONENT
-#define NATIVE_SYSTEM_HEADER_COMPONENT "MINGW"
+#undef NATIVE_SYSTEM_HEADER_DIR
#undef CPP_SPEC
#define CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{mthreads:-D_MT} " \
@@ -183,17 +183,12 @@ along with GCC; see the file COPYING3. If not see
/* Override startfile prefix defaults. */
#ifndef STANDARD_STARTFILE_PREFIX_1
-#define STANDARD_STARTFILE_PREFIX_1 "/mingw/lib/"
+#define STANDARD_STARTFILE_PREFIX_1 ""
#endif
#ifndef STANDARD_STARTFILE_PREFIX_2
#define STANDARD_STARTFILE_PREFIX_2 ""
#endif
-/* For native mingw-version we need to take care that NATIVE_SYSTEM_HEADER_DIR
- macro contains POSIX-style path. See bug 52947. */
-#undef NATIVE_SYSTEM_HEADER_DIR
-#define NATIVE_SYSTEM_HEADER_DIR "/mingw/include"
-
/* Output STRING, a string representing a filename, to FILE.
We canonicalize it to be in Unix format (backslashes are replaced
forward slashes. */
diff --git a/gcc/incpath.c b/gcc/incpath.c
index bcbe20829..c5d4453d8 100644
--- a/gcc/incpath.c
+++ b/gcc/incpath.c
@@ -183,8 +183,7 @@ add_standard_paths (const char *sysroot, const char *iprefix,
str = concat (sysroot_no_trailing_dir_separator, p->fname, NULL);
free (sysroot_no_trailing_dir_separator);
}
- else if (!p->add_sysroot && relocated
- && !filename_ncmp (p->fname, cpp_PREFIX, cpp_PREFIX_len))
+ if (relocated && !filename_ncmp (p->fname, cpp_PREFIX, cpp_PREFIX_len))
{
static const char *relocated_prefix;
char *ostr;
@@ -1,13 +0,0 @@
diff --git a/lldb/source/Host/windows/MainLoopWindows.cpp b/lldb/source/Host/windows/MainLoopWindows.cpp
index c0b10797e..e971b8cfd 100644
--- a/lldb/source/Host/windows/MainLoopWindows.cpp
+++ b/lldb/source/Host/windows/MainLoopWindows.cpp
@@ -58,7 +58,7 @@ public:
// Keep trying to cancel ReadFile() until the thread exits.
do {
CancelIoEx(m_handle, /*lpOverlapped=*/NULL);
- } while (WaitForSingleObject(m_monitor_thread.native_handle(), 1) ==
+ } while (WaitForSingleObject((HANDLE)m_monitor_thread.native_handle(), 1) ==
WAIT_TIMEOUT);
m_monitor_thread.join();
}
@@ -1,13 +0,0 @@
diff --git a/lldb/source/Host/windows/MainLoopWindows.cpp b/lldb/source/Host/windows/MainLoopWindows.cpp
index c0b10797e..e971b8cfd 100644
--- a/lldb/source/Host/windows/MainLoopWindows.cpp
+++ b/lldb/source/Host/windows/MainLoopWindows.cpp
@@ -58,7 +58,7 @@ public:
// Keep trying to cancel ReadFile() until the thread exits.
do {
CancelIoEx(m_handle, /*lpOverlapped=*/NULL);
- } while (WaitForSingleObject(m_monitor_thread.native_handle(), 1) ==
+ } while (WaitForSingleObject((HANDLE)m_monitor_thread.native_handle(), 1) ==
WAIT_TIMEOUT);
m_monitor_thread.join();
}
File diff suppressed because it is too large Load Diff
+10 -4
View File
@@ -6,14 +6,20 @@
# DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
# Check if script launched as root
if [ "$(whoami)" = "root" ]; then
echo "This script cannot be run as root!"
exit 1
fi
# Get the absolute path to the XTchain
export XTCDIR="$(realpath $(dirname "${0}"))"
export XTCDIR="$(realpath $(dirname ${0}))"
# Read the XTchain version
export XTCVER="$(cat "${XTCDIR}/Version")"
export XTCVER="$(cat ${XTCDIR}/Version)"
# Load the library
source "${XTCDIR}/lib/xtchain/xtclib"
source ${XTCDIR}/lib/xtchain/xtclib
# Set the target architecture
: ${TARGET:=${1}}
@@ -41,4 +47,4 @@ export PFMAT3="\[\033[0;1;97;104m\]"
export PFMAT4="\[\033[0;94;49m\]"
export PFMAT5="\[\033[1;38;5;74m\]"
export PROMPT="\n${PFMAT1} XT Toolchain ${PFMAT2}${PFMAT3} \w ${PFMAT4}${PFMAT5} "
bash --rcfile <(echo 'export PS1="${PROMPT}" && cd "${SRCDIR}"')
bash --rcfile <(echo 'source ~/.bashrc && export PS1="${PROMPT}" && cd ${SRCDIR}')
-2
View File
@@ -1,2 +0,0 @@
@echo off
powershell.exe -ExecutionPolicy Bypass -NoExit -File "%~dp0xtchain.ps1"
-57
View File
@@ -1,57 +0,0 @@
# PROJECT: XTchain
# LICENSE: See the COPYING.md in the top level directory
# FILE: scripts/xtchain.ps1
# DESCRIPTION: XTchain Entry Script
# DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
# Get the absolute path to the XTchain
$XTCDIR = Split-Path -Parent $MyInvocation.MyCommand.Definition
# Read the XTchain version
$env:XTCVER = Get-Content "${XTCDIR}\Version"
# Load the library (Make sure the xtclib.ps1 file is PowerShell compatible)
. "${XTCDIR}\lib\xtchain\xtclib.ps1"
# Set the target architecture
$env:TARGET = $args[0]
if (-not $env:TARGET) { $env:TARGET = "amd64" }
# Save the source directory
$SRCDIR = $args[1]
if (-not $SRCDIR) { $SRCDIR = (Get-Location).Path }
# Make sure the compiler flags are clean
$env:HOST = $null
$env:CFLAGS = $null
$env:CXXFLAGS = $null
$env:LDFLAGS = $null
# Update PATH
$env:PATH = "${XTCDIR}\bin;" + $env:PATH
# Display banner
version
# Invoke shell with fancy prompt
function global:prompt {
$PROMPT = " XT Toolchain "
$CWD = (Get-Location).Path
$CHEVRON = [char]0xE0B0
$SEGMENTS = @(
@{ TEXT = $PROMPT; BGCOLOR = "Blue"; FGCOLOR = "White" },
@{ TEXT = " $CWD "; BGCOLOR = "DarkCyan"; FGCOLOR = "White" }
)
for ($INDEX = 0; $INDEX -lt $SEGMENTS.Count; $INDEX++) {
$SEGMENT = $SEGMENTS[$INDEX]
$NEXTBG = if ($INDEX + 1 -lt $SEGMENTS.Count) { $SEGMENTS[$INDEX + 1].BGCOLOR } else { "Default" }
Write-Host $SEGMENT.TEXT -NoNewLine -ForegroundColor $SEGMENT.FGCOLOR -BackgroundColor $SEGMENT.BGCOLOR
if ($NEXTBG -ne "Default") {
Write-Host $CHEVRON -NoNewLine -ForegroundColor $SEGMENT.BGCOLOR -BackgroundColor $NEXTBG
} else {
Write-Host $CHEVRON -NoNewLine -ForegroundColor $SEGMENT.BGCOLOR
}
}
return " "
}
Set-Location -Path $SRCDIR
+16 -98
View File
@@ -4,20 +4,8 @@
# FILE: scripts/xtclib
# DESCRIPTION: XTchain library
# DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
# Aiken Harris <harraiken91@gmail.com>
# Prints XTChain banner
banner()
{
local XTC_BANNER="XT Toolchain v${XTCVER} for Linux"
printf "###############################################################################\n\n"
printf "\033[33m%*s\033[00m\n\n" $(( (${#XTC_BANNER} + 80) / 2)) "${XTC_BANNER}"
printf "###############################################################################\n\n"
}
export -f banner
# Sets the target architecture
charch()
{
@@ -26,14 +14,8 @@ charch()
return
fi
case ${1} in
"aarch64"|"arm64")
export TARGET="aarch64"
;;
"arm"|"armv7")
export TARGET="armv7"
;;
"i386"|"i486"|"i586"|"i686"|"x86")
export TARGET="i686"
export TARGET="i386"
;;
"amd64"|"x64"|"x86_64")
export TARGET="amd64"
@@ -45,87 +27,23 @@ charch()
}
export -f charch
# Sets the build type
chbuild()
{
if [ "x${1}" == "x" ]; then
echo "Syntax: chbuild [DEBUG|RELEASE]"
return
fi
case ${1} in
[Rr][Ee][Ll][Ee][Aa][Ss][Ee])
export BUILD_TYPE="RELEASE"
;;
*)
export BUILD_TYPE="DEBUG"
esac
echo "Target build type: ${BUILD_TYPE}"
}
export -f chbuild
# Prints help
help()
{
banner
echo "XTChain defines an internal list of commands:"
echo " * banner - prints XTChain banner"
echo " * charch [arch] - sets the target CPU architecture [aarch64/armv7/i686/amd64]"
echo " * chbuild [type] - sets build type [debug/release]"
echo " * help - prints this message"
echo " * version - prints XTChain and its components version"
echo " * xbuild - builds an application with a Ninja build system"
}
export -f help
# Displays version banner
version()
{
local XTCHAIN_EXTTOOLS=false
if [ ! -f "${XTCDIR}/bin/clang" ] || [ "$(which clang)" != "${XTCDIR}/bin/clang" ] || [ $(echo ${XTCVER} | grep "min") ]; then
XTCHAIN_EXTTOOLS=true
for TOOL in {clang,clang++,cmake,lld-link,ninja}; do
which ${TOOL} &> /dev/null
if [ $? -ne 0 ]; then
echo "ERROR: You are using minimal version of XTChain and '${TOOL}' has been not found in your system!"
echo "ERROR: Please install all required tools."
exit 1
fi
done
fi
banner
echo -en "\nLLVM/Clang Compiler: $(clang --version | grep 'clang version' | cut -d' ' -f3) ($(which clang))"
echo -en "\nLLVM/LLD Linker: $(lld-link --version | cut -d' ' -f2) ($(which lld-link))"
echo -en "\nWine IDL Compiler: $(widl -V | grep 'version' | cut -d' ' -f5) ($(which widl))"
echo -en "\nWine Message Compiler: $(wmc -V | grep 'version' | cut -d' ' -f5) ($(which wmc))"
echo -en "\nWine Resource Compiler: $(wrc --version | grep 'version' | cut -d' ' -f5) ($(which wrc))"
echo -en "\nXT SPEC Compiler: $(xtcspecc --help | grep Version | cut -d' ' -f5) ($(which xtcspecc))"
echo -en "\nCMake Build System: $(cmake --version | grep 'cmake version' | cut -d' ' -f3) ($(which cmake))"
echo -en "\nNinja Build System: $(ninja --version) ($(which ninja))"
echo -en "\n\n"
charch ${TARGET:-amd64}
chbuild ${BUILD_TYPE:-DEBUG}
echo -en "\n\nFor a list of all supported commands, type 'help'"
echo -en "\n-------------------------------------------------\n\n\n"
echo "###############################################################################"
echo "# XT Toolchain v${XTCVER} for Linux #"
echo "# by Rafal Kupiec <belliash@codingworkshop.eu.org> #"
echo "###############################################################################"
echo
echo
echo "Binutils Version: $(${XTCDIR}/bin/i686-w64-mingw32-ld -v | cut -d' ' -f5)"
echo "GCC Version: $(${XTCDIR}/bin/i686-w64-mingw32-gcc -v 2>&1| grep 'gcc version' | cut -d' ' -f3)"
echo "IDL Compiler Version: $(${XTCDIR}/bin/i686-w64-mingw32-widl -V | grep 'version' | cut -d' ' -f5)"
echo "Wine Message Compiler Version: $(${XTCDIR}/bin/wmc -V | grep 'version' | cut -d' ' -f5)"
echo "Wine Resource Compiler Version: $(${XTCDIR}/bin/wrc --version | grep 'version' | cut -d' ' -f5)"
echo
charch ${TARGET}
echo
echo
}
export -f version
# Builds application (wrapper to Ninja)
xbuild()
{
if [ ! -f build.arch ]; then
ninja "$@"
else
ARCH=$(cat build.arch)
if [ x"${ARCH}" != x"${TARGET}" ]; then
echo "Build is configured for '${ARCH}' while current target set to '${TARGET}'!"
echo "Cannot continue until conflict is resolved ..."
return 1
fi
ninja "$@"
fi
}
export -f xbuild
-143
View File
@@ -1,143 +0,0 @@
# PROJECT: XTchain
# LICENSE: See the COPYING.md in the top level directory
# FILE: scripts/xtclib.ps1
# DESCRIPTION: XTchain library
# DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
# Prints XTChain banner
function banner {
param()
$XTC_BANNER = "XT Toolchain v${Env:XTCVER} for Windows"
Write-Host "################################################################################"
Write-Host
Write-Host (' ' * [math]::Floor((80 - $XTC_BANNER.Length) / 2) + $XTC_BANNER) -ForegroundColor Yellow
Write-Host
Write-Host "################################################################################"
Write-Host
}
# Sets the target architecture
function charch {
param (
[string]$arch
)
if ([string]::IsNullOrWhiteSpace($arch)) {
Write-Host "Syntax: charch [architecture]"
return
}
switch -Regex ($arch) {
"aarch64|arm64" {
$Env:TARGET = "aarch64"
}
"arm|armv7" {
$Env:TARGET = "armv7"
}
"i386|i486|i586|i686|x86" {
$Env:TARGET = "i686"
}
"amd64|x64|x86_64" {
$Env:TARGET = "amd64"
}
default {
$Env:TARGET = "UNKNOWN"
}
}
Write-Host "Target Architecture: $($Env:TARGET)"
}
# Sets the build type
function chbuild {
param (
[string]$buildType
)
if ([string]::IsNullOrWhiteSpace($buildType)) {
Write-Host "Syntax: chbuild [DEBUG|RELEASE]"
return
}
switch -Regex ($buildType.ToUpper()) {
"RELEASE" {
$Env:BUILD_TYPE = "RELEASE"
}
default {
$Env:BUILD_TYPE = "DEBUG"
}
}
Write-Host "Target build type: $($Env:BUILD_TYPE)"
}
# Prints help
function help {
banner
Write-Host "XTChain defines an internal list of commands:"
Write-Host " * banner - prints XTChain banner"
Write-Host " * charch [arch] - sets the target CPU architecture [aarch64/armv7/i686/amd64]"
Write-Host " * chbuild [type] - sets build type [debug/release]"
Write-Host " * help - prints this message"
Write-Host " * version - prints XTChain and its components version"
Write-Host " * xbuild - builds an application with a Ninja build system"
}
# Displays version banner
function version {
param()
[bool]$XTCHAIN_EXTTOOLS = $false
if ((Test-Path "${Env:XTCDIR}/bin/clang") -and
((Get-Command clang).Source -eq "${Env:XTCDIR}/bin/clang") -and
($Env:XTCVER -match "min")) {
$XTCHAIN_EXTTOOLS = $true
foreach ($TOOL in @("clang", "clang++", "cmake", "lld-link", "ninja")) {
if (!(Get-Command $TOOL -ErrorAction SilentlyContinue)) {
Write-Error "You are using minimal version of XTChain and '${TOOL}' has been not found in your system!"
Write-Error "Please install all required tools."
return
}
}
}
banner
Write-Host
Write-Host "LLVM/Clang Compiler: $(clang --version | Select-String -Pattern "version (\d+\.\d+\.\d+)" | ForEach-Object { $_.Matches.Groups[1].Value }) ($($(Get-Command clang).Source))"
Write-Host "LLVM/LLD Linker: $(lld-link --version | Select-String -Pattern "(\d+\.\d+\.\d+)" | ForEach-Object { $_.Matches.Groups[1].Value }) ($($(Get-Command lld-link).Source))"
Write-Host "Wine IDL Compiler: $(widl -V | Select-String -Pattern "version (\d+\.\d+)" | ForEach-Object { $_.Matches.Groups[1].Value }) ($($(Get-Command widl).Source))"
Write-Host "Wine Message Compiler: $(wmc -V | Select-String -Pattern "version (\d+\.\d+)" | ForEach-Object { $_.Matches.Groups[1].Value }) ($($(Get-Command wmc).Source))"
Write-Host "Wine Resource Compiler: $(wrc --version | Select-String -Pattern "version (\d+\.\d+)" | ForEach-Object { $_.Matches.Groups[1].Value }) ($($(Get-Command wrc).Source))"
Write-Host "XT SPEC Compiler: $(xtcspecc --help | Select-String -Pattern "Version (\d+\.\d+)" | ForEach-Object { $_.Matches.Groups[1].Value }) ($($(Get-Command xtcspecc).Source))"
Write-Host "CMake Build System: $(cmake --version | Select-String -Pattern "version (\d+\.\d+\.\d+)" | ForEach-Object { $_.Matches.Groups[1].Value }) ($($(Get-Command cmake).Source))"
Write-Host "Ninja Build System: $(ninja --version) ($($(Get-Command ninja).Source))"
Write-Host
$BUILD_TYPE = if ($null -eq $env:BUILD_TYPE -or $env:BUILD_TYPE -eq '') { 'DEBUG' } else { $env:BUILD_TYPE }
$TARGET = if ($null -eq $env:TARGET -or $env:TARGET -eq '') { 'amd64' } else { $env:TARGET }
charch $TARGET
chbuild $BUILD_TYPE
Write-Host
Write-Host
Write-Host "For a list of all supported commands, type 'help'"
Write-Host "-------------------------------------------------"
Write-Host
Write-Host
Write-Host
}
# Builds application (wrapper to Ninja)
function xbuild {
if (-not (Test-Path build.arch)) {
& ninja @args
} else {
$ARCH = Get-Content build.arch
if ($ARCH -ne $Env:TARGET) {
Write-Host "Build is configured for '$ARCH' while current target set to '$($Env:TARGET)'!"
Write-Host "Cannot continue until conflict is resolved ..."
return 1
}
& ninja @args
}
}
-74
View File
@@ -1,74 +0,0 @@
/**
* PROJECT: XTchain
* LICENSE: See COPYING.md in the top level directory
* FILE: tools/bin2c.c
* DESCRIPTION: Binary to C converter
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#include "xtchain.h"
int main(int argc, char *argv[])
{
/* Check for proper number of arguments */
if(argc != 4)
{
printf("Usage: %s <input binary> <output file> <structure name>\n", argv[0]);
return 1;
}
/* Open the input binary file in binary mode */
FILE *inputFile = fopen(argv[1], "rb");
if(inputFile == NULL)
{
printf("Error: unable to open file %s\n", argv[1]);
return 1;
}
/* Open the destination source code file in text mode */
FILE *outputFile = fopen(argv[2], "w");
if(outputFile == NULL)
{
printf("Error: unable to open file %s\n", argv[2]);
fclose(inputFile);
return 1;
}
/* Get the size of the binary file */
fseek(inputFile, 0, SEEK_END);
long binSize = ftell(inputFile);
rewind(inputFile);
/* Allocate memory for the binary data */
unsigned char *binData = (unsigned char *)malloc(binSize);
if(binData == NULL)
{
printf("Error: unable to allocate memory for binary data\n");
fclose(inputFile);
fclose(outputFile);
return 1;
}
/* Read the binary data into memory */
fread(binData, sizeof(unsigned char), binSize, inputFile);
/* Write the C structure to the header file */
fprintf(outputFile, "unsigned char %s[] = {", argv[3]);
for(int i = 0; i < binSize; i++)
{
fprintf(outputFile, "0x%02X", binData[i]);
if(i < binSize - 1)
{
fprintf(outputFile, ",");
}
}
fprintf(outputFile, "};\nunsigned int %s_size = %ld;\n", argv[3], binSize);
free(binData);
/* Close all open files */
fclose(inputFile);
fclose(outputFile);
printf("Binary data converted to C structure successfully.\n");
return 0;
}
-759
View File
@@ -1,759 +0,0 @@
/**
* PROJECT: XTchain
* LICENSE: See COPYING.md in the top level directory
* FILE: tools/diskimg.c
* DESCRIPTION: Disk Image manipulation tool
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
* Aiken Harris <harraiken91@gmail.com>
*/
#include "xtchain.h"
static RESERVED_SECTOR_INFO Fat32ReservedMap[] =
{
{0, "Main VBR"},
{1, "FSInfo Sector"},
{6, "Backup VBR"},
{7, "Backup FSInfo Sector"},
{-1, NULL}
};
/* Forward references */
static void CopyData(const char *Image, long Offset, const char *SourceDir, const char *Relative);
static void CopyImageFile(const char *Image, long Offset, const char *SourceFile, const char *Relative);
static long DetermineExtraSector(long sectors_to_write);
long GetSectorFileSize(const char *FileName);
int LoadSectors(const char *FileName, uint8_t *Buffer, int SectorCount);
static void MakeDirectory(const char *Image, long Offset, const char *Relative);
/* Copies a directory recursively to the image */
static void CopyData(const char *Image, long Offset, const char *SourceDir, const char *Relative)
{
char Path[2048];
struct dirent *Entry;
DIR *Directory;
struct stat Stat;
char new_rel[2048];
/* Create the directory in the image */
if(Relative[0] != '\0')
{
MakeDirectory(Image, Offset, Relative);
}
/* Open the source directory */
Directory = opendir(SourceDir);
if(!Directory)
{
/* Failed to open directory */
perror("Failed to open source directory");
return;
}
/* Read all entries in the directory */
while((Entry = readdir(Directory)))
{
/* Skip . and .. entries */
if(strcmp(Entry->d_name, ".") == 0 || strcmp(Entry->d_name, "..") == 0)
{
continue;
}
/* Build the full path to the entry */
snprintf(Path, sizeof(Path), "%s%c%s", SourceDir, PATH_SEP, Entry->d_name);
/* Stat the entry */
if(stat(Path, &Stat) == -1)
{
/* Failed to stat entry */
perror("Failed to stat file or directory");
continue;
}
/* Build the relative path to the entry */
if(Relative[0] != '\0')
{
snprintf(new_rel, sizeof(new_rel), "%s/%s", Relative, Entry->d_name);
}
else
{
snprintf(new_rel, sizeof(new_rel), "%s", Entry->d_name);
}
/* Copy the entry to the image */
if(S_ISDIR(Stat.st_mode))
{
/* Entry is a directory, copy it recursively */
CopyData(Image, Offset, Path, new_rel);
}
else if(S_ISREG(Stat.st_mode))
{
/* Entry is a file, copy it */
CopyImageFile(Image, Offset, Path, new_rel);
}
}
/* Close the directory */
closedir(Directory);
}
/* Copies a file to the image */
static void CopyImageFile(const char *Image, long Offset, const char *SourceFile, const char *Relative)
{
char Command[4096];
/* Copy the file to the image */
snprintf(Command, sizeof(Command), "mcopy -i \"%s@@%ld\" \"%s\" \"::/%s\"", Image, Offset, SourceFile, Relative);
if(system(Command) != 0)
{
/* Failed to copy file */
fprintf(stderr, "Faile to copy file '%s' to image\n", SourceFile);
}
}
/* Determines a safe sector to write extra VBR data to */
static long DetermineExtraSector(long sectors_to_write)
{
long Candidate;
long Conflict;
long Index;
long LastSector;
/* Start search from sector 1 (sector 0 is the main VBR) */
for(Candidate = 1; Candidate < 32; Candidate++)
{
/* Calculate the last sector to write */
LastSector = Candidate + sectors_to_write - 1;
Conflict = 0;
/* Check if it fits within the reserved region (32 sectors) */
if(LastSector >= 32)
{
/* The remaining space is not large enough */
break;
}
/* Check for conflicts with critical sectors */
for(Index = 0; Fat32ReservedMap[Index].SectorNumber != -1; Index++)
{
if(Candidate <= Fat32ReservedMap[Index].SectorNumber && LastSector >= Fat32ReservedMap[Index].SectorNumber)
{
/* Found a conflict */
Conflict = 1;
break;
}
}
/* Make sure there are no conflicts */
if(!Conflict)
{
/* Found a suitable slot */
return Candidate;
}
}
/* No suitable slot found */
return -1;
}
/* Gets the size of a file */
long GetSectorFileSize(const char *FileName)
{
FILE *File;
long Size;
/* Open the file in binary mode */
File = fopen(FileName, "rb");
if(!File)
{
/* Failed to open file */
perror("Failed to open file for size check");
return -1;
}
/* Get the file size */
fseek(File, 0, SEEK_END);
Size = ftell(File);
/* Close the file and return the size */
fclose(File);
return Size;
}
/* Loads one or more sectors from a file */
int LoadSectors(const char *FileName, uint8_t *Buffer, int SectorCount)
{
FILE *File;
long FileSize;
long BytesToRead = SectorCount * SECTOR_SIZE;
/* Get and validate file size */
FileSize = GetSectorFileSize(FileName);
if(FileSize < 0)
{
/* Failed to get file size */
perror("Failed to get file size");
return -1;
}
if(FileSize != BytesToRead)
{
fprintf(stderr, "Error: file '%s' must be exactly %ld bytes, but is %ld bytes.\n", FileName, BytesToRead, FileSize);
return -1;
}
/* Open the file in binary mode for reading */
File = fopen(FileName, "rb");
if(!File) {
/* Failed to open file */
perror("Failed to open sector file for reading");
return -1;
}
/* Read sectors to buffer */
if(fread(Buffer, 1, BytesToRead, File) != BytesToRead)
{
/* Failed to read sectors */
perror("Failed to read sectors from file");
fclose(File);
return -1;
}
/* Close the file */
fclose(File);
return 0;
}
/* Creates a directory in the image */
static void MakeDirectory(const char *Image, long Offset, const char *Relative)
{
char Command[4096];
/* Create the directory in the image */
snprintf(Command, sizeof(Command), "mmd -i \"%s@@%ld\" \"::/%s\"", Image, Offset, Relative);
system(Command);
}
/* Main function */
int main(int argc, char **argv)
{
FILE *File;
long Index;
long FatFormat = 32;
char FormatCommand[512];
long FormatPartition = 0;
long DiskSizeBytes = 0;
long DiskSizeMB = 0;
long MergedSize = 0;
long PreloaderSize = 0;
long SectorsToWrite = 0;
long VbrExtraSector = -1;
long VbrFileSize = -1;
long VbrTotalSectors = 0;
long VbrLastSector = 99;
char VbrInfo[128] = "";
MBR_PARTITION Partition = {0};
char Zero[SECTOR_SIZE] = {0};
uint8_t Mbr[SECTOR_SIZE] = {0};
uint8_t ImageVbr[SECTOR_SIZE * 2] = {0};
uint8_t *MergedData = NULL;
uint8_t *PreloaderData = NULL;
uint8_t *FullVbrData = NULL;
const char *FileName = NULL;
const char *MbrFile = NULL;
const char *PreloadFile = NULL;
const char *VbrFile = NULL;
const char *CopyDir = NULL;
/* Parse command line arguments */
for(Index = 1; Index < argc; Index++)
{
if(strcmp(argv[Index], "-c") == 0 && Index + 1 < argc)
{
/* Copy directory */
CopyDir = argv[++Index];
}
else if(strcmp(argv[Index], "-e") == 0 && Index + 1 < argc)
{
/* VBR extra data sector */
VbrExtraSector = atol(argv[++Index]);
}
else if(strcmp(argv[Index], "-f") == 0 && Index + 1 < argc)
{
/* Format partition */
FormatPartition = 1;
FatFormat = atoi(argv[++Index]);
if(FatFormat != 16 && FatFormat != 32)
{
fprintf(stderr, "Error: FAT format (-f) must be 16 or 32\n");
return 1;
}
}
else if(strcmp(argv[Index], "-m") == 0 && Index + 1 < argc)
{
/* MBR file */
MbrFile = argv[++Index];
}
else if(strcmp(argv[Index], "-o") == 0 && Index + 1 < argc)
{
/* Output file */
FileName = argv[++Index];
}
else if(strcmp(argv[Index], "-p") == 0 && Index + 1 < argc)
{
/* Preloader file */
PreloadFile = argv[++Index];
}
else if(strcmp(argv[Index], "-s") == 0 && Index + 1 < argc)
{
/* Disk size */
DiskSizeMB = atol(argv[++Index]);
}
else if(strcmp(argv[Index], "-v") == 0 && Index + 1 < argc)
{
/* VBR file */
VbrFile = argv[++Index];
}
else
{
/* Unknown argument */
fprintf(stderr, "Unknown argument: %s\n", argv[Index]);
return 1;
}
}
/* Check for required arguments */
if(DiskSizeMB <= 0 || FileName == NULL)
{
/* Missing required arguments, print usage */
fprintf(stderr, "Usage: %s -o <output.img> -s <size_MB> [-b <sector>] [-c <dir>] [-f 16|32] [-m <mbr.img>] [-p <preload.bin>] [-v <vbr.img>]\n", argv[0]);
return 1;
}
/* Validate preload usage */
if(PreloadFile && !VbrFile)
{
/* Preloader code specified without VBR */
fprintf(stderr, "Error: Option -p (PRELOADER code) requires -v (VBR code) to be specified as well.\n");
return 1;
}
/* Calculate disk size in bytes */
DiskSizeBytes = DiskSizeMB * 1024 * 1024;
/* Open the output file in binary mode */
File = fopen(FileName, "wb");
if(!File) {
/* Failed to open file */
perror("Failed to open disk image file");
return 1;
}
/* Write zeros to the disk image file */
for(Index = 0; Index < DiskSizeBytes / SECTOR_SIZE; Index++)
{
if(fwrite(Zero, 1, SECTOR_SIZE, File) != SECTOR_SIZE)
{
/* Failed to write to disk image file */
perror("Failed to write to disk image file");
fclose(File);
return 1;
}
}
/* Load MBR if provided */
if(MbrFile)
{
if(LoadSectors(MbrFile, Mbr, 1) != 0)
{
/* Failed to load MBR from file */
perror("Failed to load MBR from file");
fclose(File);
return 1;
}
}
/* Setup MBR partition as W95 FAT16 or FAT32 */
Partition.BootFlag = 0x80;
Partition.Type = (FatFormat == 16) ? 0x06 : 0x0B;
Partition.StartLBA = 2048;
Partition.Size = (DiskSizeBytes / SECTOR_SIZE) - Partition.StartLBA;
/* Write MBR */
memcpy(&Mbr[446], &Partition, sizeof(MBR_PARTITION));
Mbr[510] = 0x55;
Mbr[511] = 0xAA;
/* Write the MBR to the beginning of the disk image */
fseek(File, 0, SEEK_SET);
if(fwrite(Mbr, 1, SECTOR_SIZE, File) != SECTOR_SIZE)
{
/* Failed to write MBR to disk image */
perror("Failed to write MBR to disk image");
fclose(File);
return 1;
}
/* Check if we need to format the partition */
if(FormatPartition)
{
/* Close file before calling external formatter */
fclose(File);
/* Build mformat command */
if(FatFormat == 16)
{
/* Format partition as FAT16 */
snprintf(FormatCommand, sizeof(FormatCommand),
"mformat -i %s@@%ld",
FileName, (long)(Partition.StartLBA * SECTOR_SIZE));
}
else
{
/* Format partition as FAT32 */
snprintf(FormatCommand, sizeof(FormatCommand),
"mformat -i %s@@%ld -F",
FileName, (long)(Partition.StartLBA * SECTOR_SIZE));
}
/* Format the partition */
if(system(FormatCommand) != 0)
{
/* Failed to format partition */
perror("Failed to format partition");
return 1;
}
/* Reopen disk image */
File = fopen(FileName, "r+b");
if(!File) {
/* Failed to open file */
perror("Failed to reopen disk image");
return 1;
}
/* Read the VBR created by mformat */
fseek(File, Partition.StartLBA * SECTOR_SIZE, SEEK_SET);
if(fread(ImageVbr, 1, SECTOR_SIZE, File) != SECTOR_SIZE)
{
/* Failed to read VBR */
perror("Failed to read VBR from disk image");
fclose(File);
return 1;
}
/* Set the number of hidden sectors, as mformat sets it to 0 */
if(*(uint32_t*)&ImageVbr[0x1C] == 0)
{
memcpy(&ImageVbr[0x1C], &Partition.StartLBA, sizeof(uint32_t));
}
/* Check FAT format */
if(FatFormat == 32)
{
/* For FAT32, TotalSectors32 must be set */
*(uint16_t*)&ImageVbr[0x13] = 0;
if(*(uint32_t*)&ImageVbr[0x20] == 0)
{
/* Mformat did not set the field, update it */
memcpy(&ImageVbr[0x20], &Partition.Size, sizeof(uint32_t));
}
}
else
{
/* For FAT16, check if parition size exceeds 65535 sectors */
if(Partition.Size < 65536)
{
/* Partition smaller than 32MB (65536 sectors), use 16-bit field TotalSectors16 */
if(*(uint16_t*)&ImageVbr[0x13] == 0)
{
/* Mformat did not set the field, update it */
memcpy(&ImageVbr[0x13], &((uint16_t){Partition.Size}), sizeof(uint16_t));
}
}
else
{
/* Partition larger than 32MB (65536 sectors), use 32-bit field TotalSectors32 */
*(uint16_t*)&ImageVbr[0x13] = 0;
if(*(uint32_t*)&ImageVbr[0x20] == 0)
{
/* Mformat did not set the field, update it */
memcpy(&ImageVbr[0x20], &Partition.Size, sizeof(uint32_t));
}
}
}
/* Set DriveNumber to emulate hard disk */
ImageVbr[0x40] = 0x80;
/* Write the corrected VBR back to the disk image */
fseek(File, Partition.StartLBA * SECTOR_SIZE, SEEK_SET);
if(fwrite(ImageVbr, 1, SECTOR_SIZE, File) != SECTOR_SIZE)
{
/* Failed to write VBR */
perror("Failed to write VBR to disk image");
fclose(File);
return 1;
}
}
/* Write VBR to the start of the partition, if provided */
if(VbrFile)
{
VbrFileSize = GetSectorFileSize(VbrFile);
if(VbrFileSize < 0)
{
/* Unable to determine VBR file size */
perror("Could not get size of VBR file\n");
return 1;
}
/* Check if VBR file size is a multiple of sector size */
if(VbrFileSize % SECTOR_SIZE != 0)
{
/* Unable to determine VBR file size */
perror("VBR file size is not a multiple of sector size\n");
return 1;
}
/* Calculate number of VBR sectors */
VbrTotalSectors = VbrFileSize / SECTOR_SIZE;
/* Allocate memory for the entire VBR file */
FullVbrData = malloc(VbrFileSize);
if(!FullVbrData)
{
/* Memory allocation failed */
perror("Failed to allocate memory for VBR file\n");
return 1;
}
/* Read the entire VBR file into the buffer */
if(LoadSectors(VbrFile, FullVbrData, VbrTotalSectors) != 0)
{
/* Failed to load VBR from file */
perror("Failed to load VBR from file\n");
free(FullVbrData);
return 1;
}
/* Read the existing VBR from the formatted partition to get the correct BPB */
fseek(File, Partition.StartLBA * SECTOR_SIZE, SEEK_SET);
if(fread(ImageVbr, 1, SECTOR_SIZE, File) != SECTOR_SIZE)
{
/* Failed to read VBR from disk image */
perror("Failed to read BPB from disk image\n");
free(FullVbrData);
fclose(File);
return 1;
}
/* Copy the BPB from the image's VBR to VBR buffer */
if(FatFormat == 32)
{
/* For FAT32, BPB is larger (up to offset 89) */
memcpy(&FullVbrData[3], &ImageVbr[3], 87);
}
else
{
/* For FAT16, BPB is smaller (up to offset 61) */
memcpy(&FullVbrData[3], &ImageVbr[3], 59);
}
/* Write the first 512 bytes of the final, merged VBR to the start of the partition */
fseek(File, Partition.StartLBA * SECTOR_SIZE, SEEK_SET);
if(fwrite(FullVbrData, 1, SECTOR_SIZE, File) != SECTOR_SIZE)
{
/* Failed to write VBR to disk image */
perror("Failed to write VBR to disk image\n");
free(FullVbrData);
fclose(File);
return 1;
}
/* Handle extra VBR data if it exists */
if(FatFormat == 32)
{
/* Check if a preloader file was provided */
if(PreloadFile)
{
/* Get the size of the preloader file */
PreloaderSize = GetSectorFileSize(PreloadFile);
if(PreloaderSize < 0)
{
/* Unable to determine preloader file size */
perror("Could not get size of preloader file.\n");
free(FullVbrData);
return 1;
}
/* Check if preloader size is multiple of 512 bytes */
if(PreloaderSize % SECTOR_SIZE != 0)
{
/* Preloader file size is not a multiple of 512 bytes */
perror("Preloader file size is not a multiple of sector size\n");
free(FullVbrData);
return 1;
}
/* Allocate buffer for preloader */
PreloaderData = malloc((size_t)PreloaderSize);
if(!PreloaderData)
{
/* Memory allocation failed */
perror("Failed to allocate memory for preloader");
free(FullVbrData);
return 1;
}
/* Load preloader data */
if(LoadSectors(PreloadFile, PreloaderData, PreloaderSize / SECTOR_SIZE) != 0)
{
/* Failed to load preloader data */
perror("Failed to load Preloader code from file\n");
free(FullVbrData);
return 1;
}
/* Allocate new buffer for the first 512 bytes of VBR and preloader */
MergedSize = SECTOR_SIZE + PreloaderSize;
MergedData = malloc(MergedSize);
if(!MergedData)
{
/* Memory allocation failed */
perror("Failed to allocate memory for Preloader file\n");
free(PreloaderData);
free(FullVbrData);
return 1;
}
/* Merge VBR and preloader data */
memcpy(MergedData, FullVbrData, SECTOR_SIZE);
memcpy(MergedData + SECTOR_SIZE, PreloaderData, PreloaderSize);
/* Free old buffers and replace with merged data */
free(FullVbrData);
free(PreloaderData);
FullVbrData = MergedData;
/* Update VBR sectors count */
VbrTotalSectors = (MergedSize + SECTOR_SIZE - 1) / SECTOR_SIZE;
}
/* Check if there is extra VBR data to write */
if(VbrTotalSectors > 1)
{
/* Check if extra sector has been provided by the user */
if(VbrExtraSector == -1)
{
/* Determine a safe sector to write extra VBR data to */
long sectors_to_write = VbrTotalSectors - 1;
VbrExtraSector = DetermineExtraSector(sectors_to_write);
if(VbrExtraSector == -1)
{
/* Failed to find a safe sector */
fprintf(stderr, "Error: Could not automatically find a safe space in the FAT32 reserved region for %ld extra VBR sectors.\n",
sectors_to_write);
free(FullVbrData);
return 1;
}
}
/* Calculate number of sectors and last sector to write */
SectorsToWrite = VbrTotalSectors - 1;
VbrLastSector = VbrExtraSector + SectorsToWrite - 1;
/* Ensure VBR will not be writen outside the reserved region (32 sectors for FAT32) */
if(VbrLastSector >= 32)
{
/* The remaining space is not large enough to fit the extra VBR data */
fprintf(stderr, "Error: VBR file is too large. Writing to sector %ld would exceed the FAT32 reserved region (32 sectors).\n", VbrLastSector);
free(FullVbrData);
return 1;
}
/* Safety check: ensure we do not overwrite critical sectors */
for(Index = 0; Fat32ReservedMap[Index].SectorNumber != -1; Index++)
{
/* Check if we are about to overwrite a critical sector */
if(VbrExtraSector <= Fat32ReservedMap[Index].SectorNumber && VbrLastSector >= Fat32ReservedMap[Index].SectorNumber)
{
/* We are about to overwrite a critical sector */
fprintf(stderr, "Error: Writing VBR extra data would overwrite critical sector %d (%s).\n",
Fat32ReservedMap[Index].SectorNumber, Fat32ReservedMap[Index].Description);
free(FullVbrData);
return 1;
}
}
/* Write the rest of the VBR data */
fseek(File, (Partition.StartLBA + VbrExtraSector) * SECTOR_SIZE, SEEK_SET);
if(fwrite(FullVbrData + SECTOR_SIZE, 1, SectorsToWrite * SECTOR_SIZE, File) != (size_t)(SectorsToWrite * SECTOR_SIZE))
{
/* Failed to write extra VBR data to disk image */
perror("Failed to write extra VBR data to disk image");
free(FullVbrData);
fclose(File);
return 1;
}
}
}
else /* FatFormat == 16 */
{
/* Check if there is extra VBR data to write */
if(VbrTotalSectors > 1 || PreloadFile)
{
/* FAT16 only supports a 1-sector VBR */
fprintf(stderr, "Error: FAT16 does not support multi-sector VBR or preloader data.\n");
free(FullVbrData);
return 1;
}
}
/* Free allocated memory */
free(FullVbrData);
}
/* Close file */
fclose(File);
/* Copy files if requested */
if(CopyDir)
{
CopyData(FileName, (long)(Partition.StartLBA * SECTOR_SIZE), CopyDir, "");
}
/* Check if VBR was written */
if(VbrFile)
{
/* Compose VBR info string */
if(VbrExtraSector != -1)
{
if(PreloadFile)
{
/* Preloader written */
snprintf(VbrInfo, sizeof(VbrInfo), ", VBR written (preloader at sector %ld)", VbrExtraSector);
}
else
{
/* VBR with extra data */
snprintf(VbrInfo, sizeof(VbrInfo), ", VBR written (extra data at sector %ld)", VbrExtraSector);
}
}
else
{
/* Standard VBR */
snprintf(VbrInfo, sizeof(VbrInfo), ", VBR written");
}
}
/* Print success message */
printf("Successfully created disk image '%s' (%ld MB) with bootable W95 FAT-%ld partition%s%s%s.\n",
FileName,
DiskSizeMB,
FatFormat,
MbrFile ? ", MBR written" : "",
VbrInfo,
CopyDir ? ", files copied" : "");
return 0;
}
-182
View File
@@ -1,182 +0,0 @@
/**
* PROJECT: XTchain
* LICENSE: See COPYING.md in the top level directory
* FILE: tools/exetool.c
* DESCRIPTION: Portable Executable (PE) utility for changing its signature and subsystem
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#include "xtchain.h"
typedef struct _PE_SUBSYSTEM
{
int Identifier;
char *Name;
} PE_SUBSYSTEM, *PPE_SUBSYSTEM;
static PE_SUBSYSTEM SubSystems[] = {
{0x00, "INVALID_SUBSYSTEM"},
{0x01, "NT_NATIVE"},
{0x02, "WINDOWS_GUI"},
{0x03, "WINDOWS_CLI"},
{0x04, "WINDOWS_CE_OLD"},
{0x05, "OS2_CUI"},
{0x07, "POSIX_CUI"},
{0x08, "NATIVE_WINDOWS"},
{0x09, "WINDOWS_CE_GUI"},
{0x0A, "EFI_APPLICATION"},
{0x0B, "EFI_BOOT_SERVICE_DRIVER"},
{0x0C, "EFI_RUNTIME_DRIVER"},
{0x0D, "EFI_ROM"},
{0x0E, "XBOX"},
{0x10, "WINDOWS_BOOT_APPLICATION"},
{0x14, "XT_NATIVE_KERNEL"},
{0x15, "XT_NATIVE_APPLICATION"},
{0x16, "XT_NATIVE_DRIVER"},
{0x17, "XT_DYNAMIC_LIBRARY"},
{0x18, "XT_APPLICATION_CLI"},
{0x19, "XT_APPLICATION_GDI"}
};
PPE_SUBSYSTEM getSubSystem(char *Name)
{
int Index;
int SubSystemsCount;
PPE_SUBSYSTEM SubSystem;
/* Count number of subsystems avaialble */
SubSystemsCount = sizeof(SubSystems) / sizeof(PE_SUBSYSTEM);
/* Find subsystem */
for(Index = 0; Index < SubSystemsCount; Index++)
{
SubSystem = &SubSystems[Index];
if(strcasecmp(SubSystem->Name, Name) == 0)
{
/* Subsystem found, return its ID */
return SubSystem;
}
}
/* No valid subsystem found */
return &SubSystems[0];
}
char *getSubSystemName(int Identifier)
{
int Index;
int SubSystemsCount;
PPE_SUBSYSTEM SubSystem;
/* Count number of subsystems avaialble */
SubSystemsCount = sizeof(SubSystems) / sizeof(PE_SUBSYSTEM);
/* Find subsystem */
for(Index = 0; Index < SubSystemsCount; Index++)
{
SubSystem = &SubSystems[Index];
if(SubSystem->Identifier == Identifier)
{
/* Subsystem found, return its ID */
return SubSystem->Name;
}
}
/* No valid subsystem found */
return SubSystems[0].Name;
}
int main(int argc, char *argv[])
{
FILE *ExeFile;
unsigned char Signature[4];
unsigned int HeaderOffset;
unsigned int ImageSignature;
unsigned short SubSystem;
PPE_SUBSYSTEM NewSubSystem;
/* Check for proper number of arguments */
if(argc != 3)
{
printf("Usage: %s <filename> <new SubSystem>\n", argv[0]);
return 1;
}
/* Parse the new SubSystem value from the command line argument */
NewSubSystem = getSubSystem(argv[2]);
if(NewSubSystem->Identifier == 0)
{
/* Invalid SubSystem provided */
printf("Error: %s is not a valid PE SubSystem\n", argv[2]);
return 1;
}
/* Open the EXE file in binary mode */
ExeFile = fopen(argv[1], "r+b");
if(ExeFile == NULL)
{
/* Failed to open PE file */
printf("ERROR: Unable to open file %s\n", argv[1]);
return 2;
}
/* Verify that the input file has a valid DOS header */
fread(Signature, sizeof(unsigned char), 4, ExeFile);
if(Signature[0] != 'M' || Signature[1] != 'Z')
{
/* Invalid DOS header */
printf("ERROR: %s is not a valid EXE file\n", argv[1]);
fclose(ExeFile);
return 3;
}
/* Verify that the input file has a valid PE header */
fseek(ExeFile, 0x3C, SEEK_SET);
fread(&HeaderOffset, sizeof(unsigned int), 1, ExeFile);
fseek(ExeFile, HeaderOffset, SEEK_SET);
fread(Signature, sizeof(unsigned char), 4, ExeFile);
if((Signature[0] != 'P' || Signature[1] != 'E' || Signature[2] != 0 || Signature[3] != 0) &&
(Signature[0] != 'P' || Signature[1] != 'E' || Signature[2] != 'X' || Signature[3] != 'T'))
{
/* Invalid PE header */
printf("Error: %s is not a valid PE file\n", argv[1]);
fclose(ExeFile);
return 3;
}
/* Check if setting XT subsystem */
if(NewSubSystem->Identifier >= 0x14 && NewSubSystem->Identifier <= 0x19)
{
/* Write PEXT signature */
ImageSignature = 0x54584550;
}
else
{
/* Write PE00 signature */
ImageSignature = 0x00004550;
}
/* Seek back to header offset and write new signature */
fseek(ExeFile, HeaderOffset, SEEK_SET);
fwrite(&ImageSignature, sizeof(ImageSignature), 1, ExeFile);
/* Seek to the offset of the SubSystem field in the optional header */
fseek(ExeFile, HeaderOffset + 0x5C, SEEK_SET);
/* Read the current SubSystem value */
fread(&SubSystem, sizeof(unsigned short), 1, ExeFile);
/* Seek back to the SubSystem field in the optional header */
fseek(ExeFile, -(long)sizeof(unsigned short), SEEK_CUR);
/* Write the new SubSystem value */
fwrite(&NewSubSystem->Identifier, sizeof(unsigned short), 1, ExeFile);
/* Close the file */
fclose(ExeFile);
/* Finished successfully */
printf("PE SubSystem modified: 0x%02X <%s> to 0x%02X <%s>\n",
SubSystem, getSubSystemName(SubSystem), NewSubSystem->Identifier, NewSubSystem->Name);
return 0;
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-2069
View File
File diff suppressed because it is too large Load Diff
-167
View File
@@ -1,167 +0,0 @@
/**
* PROJECT: XTchain
* LICENSE: See COPYING.md in the top level directory
* FILE: tools/xtadkgen.c
* DESCRIPTION: XT Assembly Development Kit generator
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#include "xtchain.h"
#define MAX_LINE_LEN 1024
#define MAGIC_MARKER "==> "
/* Prints usage */
void PrintUsage(const char* ProgramName)
{
/* Output usage instructions to stderr */
fprintf(stderr, "Usage: %s <input1.S> [input2.S ...] -o <output.h>\n", ProgramName);
}
/* Processes single .S file */
void ProcessSourceFile(FILE* InFile, FILE* OutFile)
{
char LineBuffer[MAX_LINE_LEN];
char SymbolName[256];
char ValueString[256];
char *ValuePointer;
char *Marker;
/* Iterate through the input stream until the end of the file */
while(fgets(LineBuffer, sizeof(LineBuffer), InFile))
{
Marker = strstr(LineBuffer, MAGIC_MARKER);
/* Search for the predefined translation marker */
if(Marker)
{
/* Extract the symbol identifier and its associated value */
if(sscanf(Marker, "==> %255s %255s", SymbolName, ValueString) == 2)
{
/* Initialize pointer for character-level cleanup */
ValuePointer = ValueString;
/* Strip architecture-specific immediate prefixes such as '$' (AT&T) or '#' (ARM) */
while(*ValuePointer == '$' || *ValuePointer == '#')
{
/* Advance pointer to the first alpha-numeric character */
ValuePointer++;
}
/* Generate the corresponding C-preprocessor macro definition */
fprintf(OutFile, "#undef %s\n", SymbolName);
fprintf(OutFile, "#define %s %s\n\n", SymbolName, ValuePointer);
}
}
}
}
/* Main function */
int main(int Argc, char* Argv[])
{
FILE* InFile;
FILE* OutFile = stdout;
const char* OutputName = NULL;
int FirstInputIndex = -1;
int InputCount = 0;
/* Validate that a minimum set of command-line arguments is present */
if(Argc < 2)
{
/* Display usage information and terminate on insufficient arguments */
PrintUsage(Argv[0]);
return 1;
}
/* Parse command-line arguments */
for(int Index = 1; Index < Argc; Index++)
{
/* Identify the output file switch */
if((strcmp(Argv[Index], "-o") == 0 || strcmp(Argv[Index], "-O") == 0) && Index + 1 < Argc)
{
/* Assign the designated output path and skip the next argument */
OutputName = Argv[++Index];
}
else
{
/* Track the first occurrence of an input file for the processing loop */
if(FirstInputIndex == -1)
{
/* Store the argument index for the subsequent file operations */
FirstInputIndex = Index;
}
/* Increment the total count of input files */
InputCount++;
}
}
/* Ensure at least one input source is available for processing */
if(InputCount == 0 || (OutputName == NULL && FirstInputIndex == -1))
{
/* Print usage and exit */
PrintUsage(Argv[0]);
return 1;
}
/* Initialize the output stream either to a file or default to stdout */
if(OutputName)
{
/* Attempt to open the specified output header for write access */
OutFile = fopen(OutputName, "w");
if(!OutFile)
{
/* Emit fatal error if the destination file cannot be accessed */
fprintf(stderr, "%s: Failed to open output file '%s'\n", Argv[0], OutputName);
return 1;
}
}
/* Write the auto-generation warning and inclusion guard */
fprintf(OutFile, "// FILE GENERATED AUTOMATICALLY BY '%s'. DO NOT EDIT!\n\n", Argv[0]);
fprintf(OutFile, "#ifndef __XTADK_H_\n");
fprintf(OutFile, "#define __XTADK_H_\n\n");
/* Loop through the arguments again to process each input file */
for(int Index = 1; Index < Argc; Index++)
{
/* Skip the output switch and its associated parameter */
if(strcmp(Argv[Index], "-o") == 0 || strcmp(Argv[Index], "-O") == 0)
{
/* Advance the loop counter and continue */
Index++;
continue;
}
/* Open the current assembly source file */
InFile = fopen(Argv[Index], "r");
if(!InFile)
{
/* Report error for the missing file and proceed to the next input file */
fprintf(stderr, "%s: Failed to open file '%s', skipping.\n", Argv[0], Argv[Index]);
continue;
}
/* Add source file data to the generated header */
fprintf(OutFile, "/* Source: %s */\n", Argv[Index]);
ProcessSourceFile(InFile, OutFile);
fprintf(OutFile, "\n");
/* Close the input file handle */
fclose(InFile);
}
/* Close the inclusion guard in the output */
fprintf(OutFile, "#endif /* __XTADK_H_ */\n");
/* Check if a file handle was utilized */
if(OutFile != stdout)
{
/* Commit buffered data and close the output file */
fclose(OutFile);
}
/* Return success */
return 0;
}
+162
View File
@@ -0,0 +1,162 @@
/**
* PROJECT: XTchain
* LICENSE: See COPYING.md in the top level directory
* FILE: tools/xtchain.h
* DESCRIPTION: Common header for XTchain tools
* DEVELOPERS: Martin Storsjo <martin@martin.st>
* Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#ifdef UNICODE
#define _UNICODE
#endif
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define _T(x) x
#ifdef _UNICODE
#define TS "%ls"
#else
#define TS "%s"
#endif
static
inline
int
_tcsicmp(const char *a,
const char *b)
{
while(*a && tolower(*a) == tolower(*b))
{
a++;
b++;
}
return *a - *b;
}
static
inline
char *
concat(const char *prefix,
const char *suffix)
{
int prefixlen = strlen(prefix);
int suffixlen = strlen(suffix);
char *buf = malloc((prefixlen + suffixlen + 1) * sizeof(*buf));
strcpy(buf, prefix);
strcpy(buf + prefixlen, suffix);
return buf;
}
static
inline
char *
_tcsrchrs(const char *str,
char char1,
char char2)
{
char *ptr1 = strrchr(str, char1);
char *ptr2 = strrchr(str, char2);
if(!ptr1)
{
return ptr2;
}
if(!ptr2)
{
return ptr1;
}
if(ptr1 < ptr2)
{
return ptr2;
}
return ptr1;
}
static
inline
void
split_argv(const char *argv0,
char **dir_ptr,
char **basename_ptr,
char **target_ptr,
char **exe_ptr)
{
const char *sep = _tcsrchrs(argv0, '/', '\\');
char *dir = strdup(_T(""));
const char *basename = argv0;
if(sep)
{
dir = strdup(argv0);
dir[sep + 1 - argv0] = '\0';
basename = sep + 1;
}
basename = strdup(basename);
char *period = strchr(basename, '.');
if(period)
{
*period = '\0';
}
char *target = strdup(basename);
char *dash = strrchr(target, '-');
const char *exe = basename;
if(dash)
{
*dash = '\0';
exe = dash + 1;
}
else
{
target = NULL;
}
if(dir_ptr)
{
*dir_ptr = dir;
}
if(basename_ptr)
{
*basename_ptr = basename;
}
if(target_ptr)
{
*target_ptr = target;
}
if(exe_ptr)
{
*exe_ptr = exe;
}
}
static
inline
int
run_final(const char *executable,
const char *const *argv)
{
execvp(executable, (char **) argv);
perror(executable);
return 1;
}
+182 -37
View File
@@ -14,9 +14,10 @@
#include "xtchain.h"
#define XTCSPECC_VERSION "1.2"
#define ARRAYSIZE(a) (sizeof(a) / sizeof((a)[0]))
typedef struct _STRING
{
const char *buf;
@@ -48,6 +49,7 @@ enum _ARCH
};
typedef int (*PFNOUTLINE)(FILE *, EXPORT *);
int gbMSComp = 0;
int gbImportLib = 0;
int gbNotPrivateNoWarn = 0;
int gbTracing = 0;
@@ -76,12 +78,12 @@ enum
enum
{
CCONV_STDCALL,
CCONV_CDECL,
CCONV_FASTCALL,
CCONV_THISCALL,
CCONV_EXTERN,
CCONV_STUB,
CC_STDCALL,
CC_CDECL,
CC_FASTCALL,
CC_THISCALL,
CC_EXTERN,
CC_STUB,
};
enum
@@ -256,11 +258,11 @@ OutputLine_stub(FILE *file,
int bRelay = 0;
int bInPrototype = 0;
if(pexp->nCallingConvention != CCONV_STUB &&
if(pexp->nCallingConvention != CC_STUB &&
(pexp->uFlags & FL_STUB) == 0)
{
/* Only relay trace stdcall C functions */
if(!gbTracing || (pexp->nCallingConvention != CCONV_STDCALL) ||
if(!gbTracing || (pexp->nCallingConvention != CC_STDCALL) ||
(pexp->uFlags & FL_NORELAY) ||
(pexp->strName.buf[0] == '?'))
{
@@ -293,7 +295,7 @@ OutputLine_stub(FILE *file,
}
if((giArch == ARCH_X86) &&
pexp->nCallingConvention == CCONV_STDCALL)
pexp->nCallingConvention == CC_STDCALL)
{
fprintf(file, "__stdcall ");
}
@@ -397,7 +399,7 @@ OutputLine_stub(FILE *file,
}
fprintf(file, ");\n");
if(pexp->nCallingConvention == CCONV_STUB)
if(pexp->nCallingConvention == CC_STUB)
{
fprintf(file, "\t__wine_spec_unimplemented_stub(\"%s\", __FUNCTION__);\n", pszDllName);
}
@@ -509,8 +511,8 @@ PrintName(FILE *fileDest,
fprintf(fileDest, "%.*s", nNameLength, pcName);
}
else if(fDeco &&
((pexp->nCallingConvention == CCONV_STDCALL) ||
(pexp->nCallingConvention == CCONV_FASTCALL)))
((pexp->nCallingConvention == CC_STDCALL) ||
(pexp->nCallingConvention == CC_FASTCALL)))
{
/* Scan for a dll forwarding dot */
pcDot = ScanToken(pcName, '.');
@@ -529,15 +531,22 @@ PrintName(FILE *fileDest,
pcAt = ScanToken(pcName, '@');
if(pcAt && (pcAt < (pcName + nNameLength)))
{
/* On GCC, we need to remove the leading stdcall underscore */
if(!gbMSComp && (pexp->nCallingConvention == CC_STDCALL))
{
pcName++;
nNameLength--;
}
/* Print the already decorated function name */
fprintf(fileDest, "%.*s", nNameLength, pcName);
}
else
{
/* Print the prefix, but skip it for stdcall */
if(pexp->nCallingConvention != CCONV_STDCALL)
/* Print the prefix, but skip it for (GCC && stdcall) */
if(gbMSComp || (pexp->nCallingConvention != CC_STDCALL))
{
fprintf(fileDest, "%c", pexp->nCallingConvention == CCONV_FASTCALL ? '@' : '_');
fprintf(fileDest, "%c", pexp->nCallingConvention == CC_FASTCALL ? '@' : '_');
}
/* Print the name with trailing decoration */
@@ -551,13 +560,10 @@ PrintName(FILE *fileDest,
}
}
int
OutputLine_def(FILE *fileDest,
EXPORT *pexp)
void
OutputLine_def_MS(FILE *fileDest,
EXPORT *pexp)
{
DbgPrint("OutputLine_def: '%.*s'...\n", pexp->strName.len, pexp->strName.buf);
fprintf(fileDest, " ");
PrintName(fileDest, pexp, &pexp->strName, 0);
if(gbImportLib)
@@ -580,8 +586,8 @@ OutputLine_def(FILE *fileDest,
/* If the original name was decorated, use decoration in the forwarder as well */
if((giArch == ARCH_X86) && ScanToken(pexp->strName.buf, '@') &&
!ScanToken(pexp->strTarget.buf, '@') &&
((pexp->nCallingConvention == CCONV_STDCALL) ||
(pexp->nCallingConvention == CCONV_FASTCALL)) )
((pexp->nCallingConvention == CC_STDCALL) ||
(pexp->nCallingConvention == CC_FASTCALL)) )
{
PrintName(fileDest, pexp, &pexp->strTarget, 1);
}
@@ -592,18 +598,104 @@ OutputLine_def(FILE *fileDest,
}
}
}
else if(((pexp->uFlags & FL_STUB) || (pexp->nCallingConvention == CCONV_STUB)) &&
else if(((pexp->uFlags & FL_STUB) || (pexp->nCallingConvention == CC_STUB)) &&
(pexp->strName.buf[0] == '?'))
{
/* C++ stubs are forwarded to C stubs */
fprintf(fileDest, "=stub_function%d", pexp->nNumber);
}
else if(gbTracing && ((pexp->uFlags & FL_NORELAY) == 0) && (pexp->nCallingConvention == CCONV_STDCALL) &&
else if(gbTracing && ((pexp->uFlags & FL_NORELAY) == 0) && (pexp->nCallingConvention == CC_STDCALL) &&
(pexp->strName.buf[0] != '?'))
{
/* Redirect it to the relay-tracing trampoline */
fprintf(fileDest, "=$relaytrace$%.*s", pexp->strName.len, pexp->strName.buf);
}
}
void
OutputLine_def_GCC(FILE *fileDest,
EXPORT *pexp)
{
int bTracing = 0;
/* Print the function name, with decoration for export libs */
PrintName(fileDest, pexp, &pexp->strName, gbImportLib);
DbgPrint("Generating def line for '%.*s'\n", pexp->strName.len, pexp->strName.buf);
/* Check if this is a forwarded export */
if(pexp->strTarget.buf)
{
int fIsExternal = !!ScanToken(pexp->strTarget.buf, '.');
DbgPrint("Got redirect '%.*s'\n", pexp->strTarget.len, pexp->strTarget.buf);
/* print the target name, don't decorate if it is external */
fprintf(fileDest, "=");
PrintName(fileDest, pexp, &pexp->strTarget, !fIsExternal);
}
else if(((pexp->uFlags & FL_STUB) || (pexp->nCallingConvention == CC_STUB)) &&
(pexp->strName.buf[0] == '?'))
{
/* C++ stubs are forwarded to C stubs */
fprintf(fileDest, "=stub_function%d", pexp->nNumber);
}
else if(gbTracing && ((pexp->uFlags & FL_NORELAY) == 0) &&
(pexp->nCallingConvention == CC_STDCALL) &&
(pexp->strName.buf[0] != '?'))
{
/* Redirect it to the relay-tracing trampoline */
char buf[256];
STRING strTarget;
fprintf(fileDest, "=");
sprintf(buf, "$relaytrace$%.*s", pexp->strName.len, pexp->strName.buf);
strTarget.buf = buf;
strTarget.len = pexp->strName.len + 12;
PrintName(fileDest, pexp, &strTarget, 1);
bTracing = 1;
}
/* Special handling for stdcall and fastcall */
if((giArch == ARCH_X86) &&
((pexp->nCallingConvention == CC_STDCALL) ||
(pexp->nCallingConvention == CC_FASTCALL)))
{
/* Is this the import lib? */
if(gbImportLib)
{
/* Is the name in the spec file decorated? */
const char* pcDeco = ScanToken(pexp->strName.buf, '@');
if(pcDeco &&
(pexp->strName.len > 1) &&
(pcDeco < pexp->strName.buf + pexp->strName.len))
{
/* Write the name including the leading @ */
fprintf(fileDest, "==%.*s", pexp->strName.len, pexp->strName.buf);
}
}
else if((!pexp->strTarget.buf) && !(bTracing))
{
/* Write a forwarder to the actual decorated symbol */
fprintf(fileDest, "=");
PrintName(fileDest, pexp, &pexp->strName, 1);
}
}
}
int
OutputLine_def(FILE *fileDest,
EXPORT *pexp)
{
DbgPrint("OutputLine_def: '%.*s'...\n", pexp->strName.len, pexp->strName.buf);
fprintf(fileDest, " ");
if(gbMSComp)
OutputLine_def_MS(fileDest, pexp);
else
OutputLine_def_GCC(fileDest, pexp);
/* On GCC builds we force ordinals */
if((pexp->uFlags & FL_ORDINAL) || (!gbMSComp && !gbImportLib))
{
fprintf(fileDest, " @%d", pexp->nOrdinal);
}
if(pexp->uFlags & FL_NONAME)
{
@@ -615,7 +707,7 @@ OutputLine_def(FILE *fileDest,
{
fprintf(fileDest, " PRIVATE");
}
else if(pexp->nCallingConvention == CCONV_EXTERN)
else if(pexp->nCallingConvention == CC_EXTERN)
{
fprintf(fileDest, " DATA");
}
@@ -797,28 +889,28 @@ ParseFile(char* pcStart,
/* Now we should get the type */
if(CompareToken(pc, "stdcall"))
{
exp.nCallingConvention = CCONV_STDCALL;
exp.nCallingConvention = CC_STDCALL;
}
else if(CompareToken(pc, "cdecl") ||
CompareToken(pc, "varargs"))
{
exp.nCallingConvention = CCONV_CDECL;
exp.nCallingConvention = CC_CDECL;
}
else if(CompareToken(pc, "fastcall"))
{
exp.nCallingConvention = CCONV_FASTCALL;
exp.nCallingConvention = CC_FASTCALL;
}
else if(CompareToken(pc, "thiscall"))
{
exp.nCallingConvention = CCONV_THISCALL;
exp.nCallingConvention = CC_THISCALL;
}
else if(CompareToken(pc, "extern"))
{
exp.nCallingConvention = CCONV_EXTERN;
exp.nCallingConvention = CC_EXTERN;
}
else if(CompareToken(pc, "stub"))
{
exp.nCallingConvention = CCONV_STUB;
exp.nCallingConvention = CC_STUB;
}
else
{
@@ -936,6 +1028,10 @@ ParseFile(char* pcStart,
else if(CompareToken(pc, "-ordinal"))
{
exp.uFlags |= FL_ORDINAL;
/* GCC doesn't automatically import by ordinal if an ordinal
* is found in the def file. Force it. */
if(gbImportLib && !gbMSComp)
exp.uFlags |= FL_NONAME;
}
else if(CompareToken(pc, "-stub"))
{
@@ -985,8 +1081,8 @@ ParseFile(char* pcStart,
/* Handle parameters */
exp.nStackBytes = 0;
if(exp.nCallingConvention != CCONV_EXTERN &&
exp.nCallingConvention != CCONV_STUB)
if(exp.nCallingConvention != CC_EXTERN &&
exp.nCallingConvention != CC_STUB)
{
/* Go to next token */
if(!(pc = NextToken(pc)))
@@ -1068,7 +1164,7 @@ ParseFile(char* pcStart,
}
/* Handle special stub cases */
if(exp.nCallingConvention == CCONV_STUB)
if(exp.nCallingConvention == CC_STUB)
{
/* Check for c++ mangled name */
if(pc[0] == '?')
@@ -1092,7 +1188,7 @@ ParseFile(char* pcStart,
}
exp.nStackBytes = atoi(p + 1);
exp.nArgCount = exp.nStackBytes / 4;
exp.nCallingConvention = CCONV_STDCALL;
exp.nCallingConvention = CC_STDCALL;
exp.uFlags |= FL_STUB;
for(i = 0; i < exp.nArgCount; i++)
{
@@ -1130,6 +1226,41 @@ ParseFile(char* pcStart,
Fatal(pszSourceFileName, nLine, pcLine, pc, 0, "Ordinal export without ordinal");
}
/*
* Check for special handling of OLE exports, only when MSVC
* is not used, since otherwise this is handled by MS LINK.EXE.
*/
if(!gbMSComp)
{
/* Check whether the current export is not PRIVATE, or has an ordinal */
int bIsNotPrivate = (!gbNotPrivateNoWarn && /*gbImportLib &&*/ !(exp.uFlags & FL_PRIVATE));
int bHasOrdinal = (exp.uFlags & FL_ORDINAL);
/* Check whether the current export is an OLE export, in case any of these tests pass */
if(bIsNotPrivate || bHasOrdinal)
{
for(i = 0; i < ARRAYSIZE(astrOlePrivateExports); ++i)
{
if(strlen(astrOlePrivateExports[i]) == exp.strName.len &&
strncmp(exp.strName.buf, astrOlePrivateExports[i], exp.strName.len) == 0)
{
/* The current export is an OLE export: display the corresponding warning */
if(bIsNotPrivate)
{
fprintf(stderr, "WARNING: %s line %d: Exported symbol '%.*s' should be PRIVATE\n",
pszSourceFileName, nLine, exp.strName.len, exp.strName.buf);
}
if(bHasOrdinal)
{
fprintf(stderr, "WARNING: %s line %d: exported symbol '%.*s' should not be assigned an ordinal\n",
pszSourceFileName, nLine, exp.strName.len, exp.strName.buf);
}
break;
}
}
}
}
pexports[*cExports] = exp;
(*cExports)++;
gbDebug = 0;
@@ -1198,6 +1329,7 @@ void usage(void)
" -n=<name> name of the dll\n"
" -a=<arch> set architecture to one of: aarch64, armv7, i686, x86_64\n"
" --implib generate a def file for an import library\n"
" --msvc MSVC compatibility\n"
" --no-private-warnings suppress warnings about symbols that should be private\n"
" --with-tracing generate wine-like \"+relay\" trace trampolines (needs -s)\n",
XTCSPECC_VERSION,
@@ -1261,6 +1393,10 @@ int main(int argc,
{
gbImportLib = 1;
}
else if(strcasecmp(argv[i], "--msvc") == 0)
{
gbMSComp = 1;
}
else if(strcasecmp(argv[i], "--no-private-warnings") == 0)
{
gbNotPrivateNoWarn = 1;
@@ -1380,6 +1516,15 @@ int main(int argc,
return -1;
}
if(!gbMSComp)
{
if(ApplyOrdinals(pexports, cExports) < 0)
{
fprintf(stderr, "error: could not apply ordinals!\n");
return -1;
}
}
if(pszDefFileName)
{
/* Open output file */
-3416
View File
File diff suppressed because it is too large Load Diff