mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-11-01 01:15:51 +01:00
+ Added fpcres
git-svn-id: trunk@954 -
This commit is contained in:
parent
51d0c0ef2a
commit
d570eabe53
7
.gitattributes
vendored
7
.gitattributes
vendored
@ -6271,6 +6271,13 @@ utils/fpcm/fpcmpkg.pp svneol=native#text/plain
|
|||||||
utils/fpcm/fpcmwr.pp svneol=native#text/plain
|
utils/fpcm/fpcmwr.pp svneol=native#text/plain
|
||||||
utils/fpcm/makefile.exm -text
|
utils/fpcm/makefile.exm -text
|
||||||
utils/fpcm/readme.txt svneol=native#text/plain
|
utils/fpcm/readme.txt svneol=native#text/plain
|
||||||
|
utils/fpcres/Makefile svneol=native#text/plain
|
||||||
|
utils/fpcres/Makefile.fpc svneol=native#text/plain
|
||||||
|
utils/fpcres/elfbfd.pas svneol=native#text/plain
|
||||||
|
utils/fpcres/elfres.pas svneol=native#text/plain
|
||||||
|
utils/fpcres/elfresfix.pas svneol=native#text/plain
|
||||||
|
utils/fpcres/fpcres.lpi svneol=native#text/plain
|
||||||
|
utils/fpcres/fpcres.pas svneol=native#text/plain
|
||||||
utils/fpdoc/COPYING -text
|
utils/fpdoc/COPYING -text
|
||||||
utils/fpdoc/Makefile svneol=native#text/plain
|
utils/fpdoc/Makefile svneol=native#text/plain
|
||||||
utils/fpdoc/Makefile.fpc svneol=native#text/plain
|
utils/fpdoc/Makefile.fpc svneol=native#text/plain
|
||||||
|
|||||||
153
utils/Makefile
153
utils/Makefile
@ -1,8 +1,8 @@
|
|||||||
#
|
#
|
||||||
# Don't edit, this file is generated by FPCMake Version 2.0.0 [2005/08/10]
|
# Don't edit, this file is generated by FPCMake Version 1.9.8 [2005/04/10]
|
||||||
#
|
#
|
||||||
default: all
|
default: all
|
||||||
MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-emx i386-watcom i386-netwlibc i386-wince m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos powerpc-linux powerpc-netbsd powerpc-macos powerpc-darwin powerpc-morphos sparc-linux sparc-netbsd sparc-solaris x86_64-linux x86_64-freebsd x86_64-win64 arm-linux arm-wince
|
MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-emx i386-watcom i386-netwlibc m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos powerpc-linux powerpc-netbsd powerpc-macos powerpc-darwin powerpc-morphos sparc-linux sparc-netbsd sparc-solaris x86_64-linux x86_64-freebsd arm-linux
|
||||||
BSDs = freebsd netbsd openbsd darwin
|
BSDs = freebsd netbsd openbsd darwin
|
||||||
UNIXs = linux $(BSDs) solaris qnx
|
UNIXs = linux $(BSDs) solaris qnx
|
||||||
LIMIT83fs = go32v2 os2 emx watcom
|
LIMIT83fs = go32v2 os2 emx watcom
|
||||||
@ -233,7 +233,7 @@ PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages/base $(FPCDIR)/packages/ext
|
|||||||
override PACKAGE_NAME=utils
|
override PACKAGE_NAME=utils
|
||||||
override PACKAGE_VERSION=2.0.0
|
override PACKAGE_VERSION=2.0.0
|
||||||
ifeq ($(FULL_TARGET),i386-linux)
|
ifeq ($(FULL_TARGET),i386-linux)
|
||||||
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc fpcres
|
||||||
endif
|
endif
|
||||||
ifeq ($(FULL_TARGET),i386-go32v2)
|
ifeq ($(FULL_TARGET),i386-go32v2)
|
||||||
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
||||||
@ -277,11 +277,8 @@ endif
|
|||||||
ifeq ($(FULL_TARGET),i386-netwlibc)
|
ifeq ($(FULL_TARGET),i386-netwlibc)
|
||||||
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
||||||
endif
|
endif
|
||||||
ifeq ($(FULL_TARGET),i386-wince)
|
|
||||||
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
|
||||||
endif
|
|
||||||
ifeq ($(FULL_TARGET),m68k-linux)
|
ifeq ($(FULL_TARGET),m68k-linux)
|
||||||
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc fpcres
|
||||||
endif
|
endif
|
||||||
ifeq ($(FULL_TARGET),m68k-freebsd)
|
ifeq ($(FULL_TARGET),m68k-freebsd)
|
||||||
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
||||||
@ -302,7 +299,7 @@ ifeq ($(FULL_TARGET),m68k-palmos)
|
|||||||
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
||||||
endif
|
endif
|
||||||
ifeq ($(FULL_TARGET),powerpc-linux)
|
ifeq ($(FULL_TARGET),powerpc-linux)
|
||||||
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc fpcres
|
||||||
endif
|
endif
|
||||||
ifeq ($(FULL_TARGET),powerpc-netbsd)
|
ifeq ($(FULL_TARGET),powerpc-netbsd)
|
||||||
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
||||||
@ -317,7 +314,7 @@ ifeq ($(FULL_TARGET),powerpc-morphos)
|
|||||||
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
||||||
endif
|
endif
|
||||||
ifeq ($(FULL_TARGET),sparc-linux)
|
ifeq ($(FULL_TARGET),sparc-linux)
|
||||||
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc fpcres
|
||||||
endif
|
endif
|
||||||
ifeq ($(FULL_TARGET),sparc-netbsd)
|
ifeq ($(FULL_TARGET),sparc-netbsd)
|
||||||
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
||||||
@ -326,19 +323,13 @@ ifeq ($(FULL_TARGET),sparc-solaris)
|
|||||||
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
||||||
endif
|
endif
|
||||||
ifeq ($(FULL_TARGET),x86_64-linux)
|
ifeq ($(FULL_TARGET),x86_64-linux)
|
||||||
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc fpcres
|
||||||
endif
|
endif
|
||||||
ifeq ($(FULL_TARGET),x86_64-freebsd)
|
ifeq ($(FULL_TARGET),x86_64-freebsd)
|
||||||
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
||||||
endif
|
endif
|
||||||
ifeq ($(FULL_TARGET),x86_64-win64)
|
|
||||||
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
|
||||||
endif
|
|
||||||
ifeq ($(FULL_TARGET),arm-linux)
|
ifeq ($(FULL_TARGET),arm-linux)
|
||||||
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc fpcres
|
||||||
endif
|
|
||||||
ifeq ($(FULL_TARGET),arm-wince)
|
|
||||||
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
|
||||||
endif
|
endif
|
||||||
ifeq ($(FULL_TARGET),i386-linux)
|
ifeq ($(FULL_TARGET),i386-linux)
|
||||||
override TARGET_PROGRAMS+=ppdep ptop rstconv data2inc delp bin2obj postw32
|
override TARGET_PROGRAMS+=ppdep ptop rstconv data2inc delp bin2obj postw32
|
||||||
@ -385,9 +376,6 @@ endif
|
|||||||
ifeq ($(FULL_TARGET),i386-netwlibc)
|
ifeq ($(FULL_TARGET),i386-netwlibc)
|
||||||
override TARGET_PROGRAMS+=ppdep ptop rstconv data2inc delp bin2obj postw32
|
override TARGET_PROGRAMS+=ppdep ptop rstconv data2inc delp bin2obj postw32
|
||||||
endif
|
endif
|
||||||
ifeq ($(FULL_TARGET),i386-wince)
|
|
||||||
override TARGET_PROGRAMS+=ppdep ptop rstconv data2inc delp bin2obj postw32
|
|
||||||
endif
|
|
||||||
ifeq ($(FULL_TARGET),m68k-linux)
|
ifeq ($(FULL_TARGET),m68k-linux)
|
||||||
override TARGET_PROGRAMS+=ppdep ptop rstconv data2inc delp bin2obj postw32
|
override TARGET_PROGRAMS+=ppdep ptop rstconv data2inc delp bin2obj postw32
|
||||||
endif
|
endif
|
||||||
@ -439,15 +427,9 @@ endif
|
|||||||
ifeq ($(FULL_TARGET),x86_64-freebsd)
|
ifeq ($(FULL_TARGET),x86_64-freebsd)
|
||||||
override TARGET_PROGRAMS+=ppdep ptop rstconv data2inc delp bin2obj postw32
|
override TARGET_PROGRAMS+=ppdep ptop rstconv data2inc delp bin2obj postw32
|
||||||
endif
|
endif
|
||||||
ifeq ($(FULL_TARGET),x86_64-win64)
|
|
||||||
override TARGET_PROGRAMS+=ppdep ptop rstconv data2inc delp bin2obj postw32
|
|
||||||
endif
|
|
||||||
ifeq ($(FULL_TARGET),arm-linux)
|
ifeq ($(FULL_TARGET),arm-linux)
|
||||||
override TARGET_PROGRAMS+=ppdep ptop rstconv data2inc delp bin2obj postw32
|
override TARGET_PROGRAMS+=ppdep ptop rstconv data2inc delp bin2obj postw32
|
||||||
endif
|
endif
|
||||||
ifeq ($(FULL_TARGET),arm-wince)
|
|
||||||
override TARGET_PROGRAMS+=ppdep ptop rstconv data2inc delp bin2obj postw32
|
|
||||||
endif
|
|
||||||
ifeq ($(FULL_TARGET),i386-linux)
|
ifeq ($(FULL_TARGET),i386-linux)
|
||||||
override TARGET_RSTS+=rstconv
|
override TARGET_RSTS+=rstconv
|
||||||
endif
|
endif
|
||||||
@ -493,9 +475,6 @@ endif
|
|||||||
ifeq ($(FULL_TARGET),i386-netwlibc)
|
ifeq ($(FULL_TARGET),i386-netwlibc)
|
||||||
override TARGET_RSTS+=rstconv
|
override TARGET_RSTS+=rstconv
|
||||||
endif
|
endif
|
||||||
ifeq ($(FULL_TARGET),i386-wince)
|
|
||||||
override TARGET_RSTS+=rstconv
|
|
||||||
endif
|
|
||||||
ifeq ($(FULL_TARGET),m68k-linux)
|
ifeq ($(FULL_TARGET),m68k-linux)
|
||||||
override TARGET_RSTS+=rstconv
|
override TARGET_RSTS+=rstconv
|
||||||
endif
|
endif
|
||||||
@ -547,15 +526,9 @@ endif
|
|||||||
ifeq ($(FULL_TARGET),x86_64-freebsd)
|
ifeq ($(FULL_TARGET),x86_64-freebsd)
|
||||||
override TARGET_RSTS+=rstconv
|
override TARGET_RSTS+=rstconv
|
||||||
endif
|
endif
|
||||||
ifeq ($(FULL_TARGET),x86_64-win64)
|
|
||||||
override TARGET_RSTS+=rstconv
|
|
||||||
endif
|
|
||||||
ifeq ($(FULL_TARGET),arm-linux)
|
ifeq ($(FULL_TARGET),arm-linux)
|
||||||
override TARGET_RSTS+=rstconv
|
override TARGET_RSTS+=rstconv
|
||||||
endif
|
endif
|
||||||
ifeq ($(FULL_TARGET),arm-wince)
|
|
||||||
override TARGET_RSTS+=rstconv
|
|
||||||
endif
|
|
||||||
ifeq ($(FULL_TARGET),i386-linux)
|
ifeq ($(FULL_TARGET),i386-linux)
|
||||||
override CLEAN_UNITS+=ptopu
|
override CLEAN_UNITS+=ptopu
|
||||||
endif
|
endif
|
||||||
@ -601,9 +574,6 @@ endif
|
|||||||
ifeq ($(FULL_TARGET),i386-netwlibc)
|
ifeq ($(FULL_TARGET),i386-netwlibc)
|
||||||
override CLEAN_UNITS+=ptopu
|
override CLEAN_UNITS+=ptopu
|
||||||
endif
|
endif
|
||||||
ifeq ($(FULL_TARGET),i386-wince)
|
|
||||||
override CLEAN_UNITS+=ptopu
|
|
||||||
endif
|
|
||||||
ifeq ($(FULL_TARGET),m68k-linux)
|
ifeq ($(FULL_TARGET),m68k-linux)
|
||||||
override CLEAN_UNITS+=ptopu
|
override CLEAN_UNITS+=ptopu
|
||||||
endif
|
endif
|
||||||
@ -655,15 +625,9 @@ endif
|
|||||||
ifeq ($(FULL_TARGET),x86_64-freebsd)
|
ifeq ($(FULL_TARGET),x86_64-freebsd)
|
||||||
override CLEAN_UNITS+=ptopu
|
override CLEAN_UNITS+=ptopu
|
||||||
endif
|
endif
|
||||||
ifeq ($(FULL_TARGET),x86_64-win64)
|
|
||||||
override CLEAN_UNITS+=ptopu
|
|
||||||
endif
|
|
||||||
ifeq ($(FULL_TARGET),arm-linux)
|
ifeq ($(FULL_TARGET),arm-linux)
|
||||||
override CLEAN_UNITS+=ptopu
|
override CLEAN_UNITS+=ptopu
|
||||||
endif
|
endif
|
||||||
ifeq ($(FULL_TARGET),arm-wince)
|
|
||||||
override CLEAN_UNITS+=ptopu
|
|
||||||
endif
|
|
||||||
override INSTALL_FPCPACKAGE=y
|
override INSTALL_FPCPACKAGE=y
|
||||||
ifdef REQUIRE_UNITSDIR
|
ifdef REQUIRE_UNITSDIR
|
||||||
override UNITSDIR+=$(REQUIRE_UNITSDIR)
|
override UNITSDIR+=$(REQUIRE_UNITSDIR)
|
||||||
@ -1562,14 +1526,6 @@ REQUIRE_PACKAGES_PASJPEG=1
|
|||||||
REQUIRE_PACKAGES_NETDB=1
|
REQUIRE_PACKAGES_NETDB=1
|
||||||
REQUIRE_PACKAGES_LIBASYNC=1
|
REQUIRE_PACKAGES_LIBASYNC=1
|
||||||
endif
|
endif
|
||||||
ifeq ($(FULL_TARGET),i386-wince)
|
|
||||||
REQUIRE_PACKAGES_RTL=1
|
|
||||||
REQUIRE_PACKAGES_PASZLIB=1
|
|
||||||
REQUIRE_PACKAGES_FCL=1
|
|
||||||
REQUIRE_PACKAGES_PASJPEG=1
|
|
||||||
REQUIRE_PACKAGES_NETDB=1
|
|
||||||
REQUIRE_PACKAGES_LIBASYNC=1
|
|
||||||
endif
|
|
||||||
ifeq ($(FULL_TARGET),m68k-linux)
|
ifeq ($(FULL_TARGET),m68k-linux)
|
||||||
REQUIRE_PACKAGES_RTL=1
|
REQUIRE_PACKAGES_RTL=1
|
||||||
REQUIRE_PACKAGES_PASZLIB=1
|
REQUIRE_PACKAGES_PASZLIB=1
|
||||||
@ -1757,14 +1713,6 @@ REQUIRE_PACKAGES_POSTGRES=1
|
|||||||
REQUIRE_PACKAGES_MYSQL=1
|
REQUIRE_PACKAGES_MYSQL=1
|
||||||
REQUIRE_PACKAGES_SQLITE=1
|
REQUIRE_PACKAGES_SQLITE=1
|
||||||
endif
|
endif
|
||||||
ifeq ($(FULL_TARGET),x86_64-win64)
|
|
||||||
REQUIRE_PACKAGES_RTL=1
|
|
||||||
REQUIRE_PACKAGES_PASZLIB=1
|
|
||||||
REQUIRE_PACKAGES_FCL=1
|
|
||||||
REQUIRE_PACKAGES_PASJPEG=1
|
|
||||||
REQUIRE_PACKAGES_NETDB=1
|
|
||||||
REQUIRE_PACKAGES_LIBASYNC=1
|
|
||||||
endif
|
|
||||||
ifeq ($(FULL_TARGET),arm-linux)
|
ifeq ($(FULL_TARGET),arm-linux)
|
||||||
REQUIRE_PACKAGES_RTL=1
|
REQUIRE_PACKAGES_RTL=1
|
||||||
REQUIRE_PACKAGES_PASZLIB=1
|
REQUIRE_PACKAGES_PASZLIB=1
|
||||||
@ -1778,14 +1726,6 @@ REQUIRE_PACKAGES_POSTGRES=1
|
|||||||
REQUIRE_PACKAGES_MYSQL=1
|
REQUIRE_PACKAGES_MYSQL=1
|
||||||
REQUIRE_PACKAGES_SQLITE=1
|
REQUIRE_PACKAGES_SQLITE=1
|
||||||
endif
|
endif
|
||||||
ifeq ($(FULL_TARGET),arm-wince)
|
|
||||||
REQUIRE_PACKAGES_RTL=1
|
|
||||||
REQUIRE_PACKAGES_PASZLIB=1
|
|
||||||
REQUIRE_PACKAGES_FCL=1
|
|
||||||
REQUIRE_PACKAGES_PASJPEG=1
|
|
||||||
REQUIRE_PACKAGES_NETDB=1
|
|
||||||
REQUIRE_PACKAGES_LIBASYNC=1
|
|
||||||
endif
|
|
||||||
ifdef REQUIRE_PACKAGES_RTL
|
ifdef REQUIRE_PACKAGES_RTL
|
||||||
PACKAGEDIR_RTL:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /rtl/Makefile.fpc,$(PACKAGESDIR))))))
|
PACKAGEDIR_RTL:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /rtl/Makefile.fpc,$(PACKAGESDIR))))))
|
||||||
ifneq ($(PACKAGEDIR_RTL),)
|
ifneq ($(PACKAGEDIR_RTL),)
|
||||||
@ -2121,7 +2061,7 @@ else
|
|||||||
FPCCPUOPT:=
|
FPCCPUOPT:=
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
override FPCOPT+=-Ur -Xs $(FPCCPUOPT) -n
|
override FPCOPT+=-Xs $(FPCCPUOPT) -n
|
||||||
override FPCOPTDEF+=RELEASE
|
override FPCOPTDEF+=RELEASE
|
||||||
endif
|
endif
|
||||||
ifdef STRIP
|
ifdef STRIP
|
||||||
@ -2601,6 +2541,7 @@ TARGET_DIRS_H2PAS=1
|
|||||||
TARGET_DIRS_FPRCP=1
|
TARGET_DIRS_FPRCP=1
|
||||||
TARGET_DIRS_DXEGEN=1
|
TARGET_DIRS_DXEGEN=1
|
||||||
TARGET_DIRS_FPDOC=1
|
TARGET_DIRS_FPDOC=1
|
||||||
|
TARGET_DIRS_FPCRES=1
|
||||||
endif
|
endif
|
||||||
ifeq ($(FULL_TARGET),i386-go32v2)
|
ifeq ($(FULL_TARGET),i386-go32v2)
|
||||||
TARGET_DIRS_FPCM=1
|
TARGET_DIRS_FPCM=1
|
||||||
@ -2715,14 +2656,6 @@ TARGET_DIRS_FPRCP=1
|
|||||||
TARGET_DIRS_DXEGEN=1
|
TARGET_DIRS_DXEGEN=1
|
||||||
TARGET_DIRS_FPDOC=1
|
TARGET_DIRS_FPDOC=1
|
||||||
endif
|
endif
|
||||||
ifeq ($(FULL_TARGET),i386-wince)
|
|
||||||
TARGET_DIRS_FPCM=1
|
|
||||||
TARGET_DIRS_TPLY=1
|
|
||||||
TARGET_DIRS_H2PAS=1
|
|
||||||
TARGET_DIRS_FPRCP=1
|
|
||||||
TARGET_DIRS_DXEGEN=1
|
|
||||||
TARGET_DIRS_FPDOC=1
|
|
||||||
endif
|
|
||||||
ifeq ($(FULL_TARGET),m68k-linux)
|
ifeq ($(FULL_TARGET),m68k-linux)
|
||||||
TARGET_DIRS_FPCM=1
|
TARGET_DIRS_FPCM=1
|
||||||
TARGET_DIRS_TPLY=1
|
TARGET_DIRS_TPLY=1
|
||||||
@ -2730,6 +2663,7 @@ TARGET_DIRS_H2PAS=1
|
|||||||
TARGET_DIRS_FPRCP=1
|
TARGET_DIRS_FPRCP=1
|
||||||
TARGET_DIRS_DXEGEN=1
|
TARGET_DIRS_DXEGEN=1
|
||||||
TARGET_DIRS_FPDOC=1
|
TARGET_DIRS_FPDOC=1
|
||||||
|
TARGET_DIRS_FPCRES=1
|
||||||
endif
|
endif
|
||||||
ifeq ($(FULL_TARGET),m68k-freebsd)
|
ifeq ($(FULL_TARGET),m68k-freebsd)
|
||||||
TARGET_DIRS_FPCM=1
|
TARGET_DIRS_FPCM=1
|
||||||
@ -2786,6 +2720,7 @@ TARGET_DIRS_H2PAS=1
|
|||||||
TARGET_DIRS_FPRCP=1
|
TARGET_DIRS_FPRCP=1
|
||||||
TARGET_DIRS_DXEGEN=1
|
TARGET_DIRS_DXEGEN=1
|
||||||
TARGET_DIRS_FPDOC=1
|
TARGET_DIRS_FPDOC=1
|
||||||
|
TARGET_DIRS_FPCRES=1
|
||||||
endif
|
endif
|
||||||
ifeq ($(FULL_TARGET),powerpc-netbsd)
|
ifeq ($(FULL_TARGET),powerpc-netbsd)
|
||||||
TARGET_DIRS_FPCM=1
|
TARGET_DIRS_FPCM=1
|
||||||
@ -2826,6 +2761,7 @@ TARGET_DIRS_H2PAS=1
|
|||||||
TARGET_DIRS_FPRCP=1
|
TARGET_DIRS_FPRCP=1
|
||||||
TARGET_DIRS_DXEGEN=1
|
TARGET_DIRS_DXEGEN=1
|
||||||
TARGET_DIRS_FPDOC=1
|
TARGET_DIRS_FPDOC=1
|
||||||
|
TARGET_DIRS_FPCRES=1
|
||||||
endif
|
endif
|
||||||
ifeq ($(FULL_TARGET),sparc-netbsd)
|
ifeq ($(FULL_TARGET),sparc-netbsd)
|
||||||
TARGET_DIRS_FPCM=1
|
TARGET_DIRS_FPCM=1
|
||||||
@ -2850,6 +2786,7 @@ TARGET_DIRS_H2PAS=1
|
|||||||
TARGET_DIRS_FPRCP=1
|
TARGET_DIRS_FPRCP=1
|
||||||
TARGET_DIRS_DXEGEN=1
|
TARGET_DIRS_DXEGEN=1
|
||||||
TARGET_DIRS_FPDOC=1
|
TARGET_DIRS_FPDOC=1
|
||||||
|
TARGET_DIRS_FPCRES=1
|
||||||
endif
|
endif
|
||||||
ifeq ($(FULL_TARGET),x86_64-freebsd)
|
ifeq ($(FULL_TARGET),x86_64-freebsd)
|
||||||
TARGET_DIRS_FPCM=1
|
TARGET_DIRS_FPCM=1
|
||||||
@ -2859,14 +2796,6 @@ TARGET_DIRS_FPRCP=1
|
|||||||
TARGET_DIRS_DXEGEN=1
|
TARGET_DIRS_DXEGEN=1
|
||||||
TARGET_DIRS_FPDOC=1
|
TARGET_DIRS_FPDOC=1
|
||||||
endif
|
endif
|
||||||
ifeq ($(FULL_TARGET),x86_64-win64)
|
|
||||||
TARGET_DIRS_FPCM=1
|
|
||||||
TARGET_DIRS_TPLY=1
|
|
||||||
TARGET_DIRS_H2PAS=1
|
|
||||||
TARGET_DIRS_FPRCP=1
|
|
||||||
TARGET_DIRS_DXEGEN=1
|
|
||||||
TARGET_DIRS_FPDOC=1
|
|
||||||
endif
|
|
||||||
ifeq ($(FULL_TARGET),arm-linux)
|
ifeq ($(FULL_TARGET),arm-linux)
|
||||||
TARGET_DIRS_FPCM=1
|
TARGET_DIRS_FPCM=1
|
||||||
TARGET_DIRS_TPLY=1
|
TARGET_DIRS_TPLY=1
|
||||||
@ -2874,14 +2803,7 @@ TARGET_DIRS_H2PAS=1
|
|||||||
TARGET_DIRS_FPRCP=1
|
TARGET_DIRS_FPRCP=1
|
||||||
TARGET_DIRS_DXEGEN=1
|
TARGET_DIRS_DXEGEN=1
|
||||||
TARGET_DIRS_FPDOC=1
|
TARGET_DIRS_FPDOC=1
|
||||||
endif
|
TARGET_DIRS_FPCRES=1
|
||||||
ifeq ($(FULL_TARGET),arm-wince)
|
|
||||||
TARGET_DIRS_FPCM=1
|
|
||||||
TARGET_DIRS_TPLY=1
|
|
||||||
TARGET_DIRS_H2PAS=1
|
|
||||||
TARGET_DIRS_FPRCP=1
|
|
||||||
TARGET_DIRS_DXEGEN=1
|
|
||||||
TARGET_DIRS_FPDOC=1
|
|
||||||
endif
|
endif
|
||||||
ifdef TARGET_DIRS_FPCM
|
ifdef TARGET_DIRS_FPCM
|
||||||
fpcm_all:
|
fpcm_all:
|
||||||
@ -3153,6 +3075,51 @@ fpdoc:
|
|||||||
$(MAKE) -C fpdoc all
|
$(MAKE) -C fpdoc all
|
||||||
.PHONY: fpdoc_all fpdoc_debug fpdoc_smart fpdoc_release fpdoc_units fpdoc_examples fpdoc_shared fpdoc_install fpdoc_sourceinstall fpdoc_exampleinstall fpdoc_distinstall fpdoc_zipinstall fpdoc_zipsourceinstall fpdoc_zipexampleinstall fpdoc_zipdistinstall fpdoc_clean fpdoc_distclean fpdoc_cleanall fpdoc_info fpdoc_makefiles fpdoc
|
.PHONY: fpdoc_all fpdoc_debug fpdoc_smart fpdoc_release fpdoc_units fpdoc_examples fpdoc_shared fpdoc_install fpdoc_sourceinstall fpdoc_exampleinstall fpdoc_distinstall fpdoc_zipinstall fpdoc_zipsourceinstall fpdoc_zipexampleinstall fpdoc_zipdistinstall fpdoc_clean fpdoc_distclean fpdoc_cleanall fpdoc_info fpdoc_makefiles fpdoc
|
||||||
endif
|
endif
|
||||||
|
ifdef TARGET_DIRS_FPCRES
|
||||||
|
fpcres_all:
|
||||||
|
$(MAKE) -C fpcres all
|
||||||
|
fpcres_debug:
|
||||||
|
$(MAKE) -C fpcres debug
|
||||||
|
fpcres_smart:
|
||||||
|
$(MAKE) -C fpcres smart
|
||||||
|
fpcres_release:
|
||||||
|
$(MAKE) -C fpcres release
|
||||||
|
fpcres_units:
|
||||||
|
$(MAKE) -C fpcres units
|
||||||
|
fpcres_examples:
|
||||||
|
$(MAKE) -C fpcres examples
|
||||||
|
fpcres_shared:
|
||||||
|
$(MAKE) -C fpcres shared
|
||||||
|
fpcres_install:
|
||||||
|
$(MAKE) -C fpcres install
|
||||||
|
fpcres_sourceinstall:
|
||||||
|
$(MAKE) -C fpcres sourceinstall
|
||||||
|
fpcres_exampleinstall:
|
||||||
|
$(MAKE) -C fpcres exampleinstall
|
||||||
|
fpcres_distinstall:
|
||||||
|
$(MAKE) -C fpcres distinstall
|
||||||
|
fpcres_zipinstall:
|
||||||
|
$(MAKE) -C fpcres zipinstall
|
||||||
|
fpcres_zipsourceinstall:
|
||||||
|
$(MAKE) -C fpcres zipsourceinstall
|
||||||
|
fpcres_zipexampleinstall:
|
||||||
|
$(MAKE) -C fpcres zipexampleinstall
|
||||||
|
fpcres_zipdistinstall:
|
||||||
|
$(MAKE) -C fpcres zipdistinstall
|
||||||
|
fpcres_clean:
|
||||||
|
$(MAKE) -C fpcres clean
|
||||||
|
fpcres_distclean:
|
||||||
|
$(MAKE) -C fpcres distclean
|
||||||
|
fpcres_cleanall:
|
||||||
|
$(MAKE) -C fpcres cleanall
|
||||||
|
fpcres_info:
|
||||||
|
$(MAKE) -C fpcres info
|
||||||
|
fpcres_makefiles:
|
||||||
|
$(MAKE) -C fpcres makefiles
|
||||||
|
fpcres:
|
||||||
|
$(MAKE) -C fpcres all
|
||||||
|
.PHONY: fpcres_all fpcres_debug fpcres_smart fpcres_release fpcres_units fpcres_examples fpcres_shared fpcres_install fpcres_sourceinstall fpcres_exampleinstall fpcres_distinstall fpcres_zipinstall fpcres_zipsourceinstall fpcres_zipexampleinstall fpcres_zipdistinstall fpcres_clean fpcres_distclean fpcres_cleanall fpcres_info fpcres_makefiles fpcres
|
||||||
|
endif
|
||||||
ifdef TARGET_DIRS_FPMC
|
ifdef TARGET_DIRS_FPMC
|
||||||
fpmc_all:
|
fpmc_all:
|
||||||
$(MAKE) -C fpmc all
|
$(MAKE) -C fpmc all
|
||||||
|
|||||||
@ -10,6 +10,7 @@ version=2.0.0
|
|||||||
dirs=fpcm tply h2pas fprcp dxegen fpdoc
|
dirs=fpcm tply h2pas fprcp dxegen fpdoc
|
||||||
programs=ppdep ptop rstconv data2inc delp bin2obj postw32
|
programs=ppdep ptop rstconv data2inc delp bin2obj postw32
|
||||||
dirs_win32=fpmc
|
dirs_win32=fpmc
|
||||||
|
dirs_linux=fpcres
|
||||||
rsts=rstconv
|
rsts=rstconv
|
||||||
|
|
||||||
[require]
|
[require]
|
||||||
|
|||||||
1519
utils/fpcres/Makefile
Normal file
1519
utils/fpcres/Makefile
Normal file
File diff suppressed because it is too large
Load Diff
22
utils/fpcres/Makefile.fpc
Normal file
22
utils/fpcres/Makefile.fpc
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#
|
||||||
|
# Makefile.fpc for FPCMake
|
||||||
|
#
|
||||||
|
|
||||||
|
[target]
|
||||||
|
programs=fpcres
|
||||||
|
rsts=fpcres fpcresfix elfres
|
||||||
|
|
||||||
|
[clean]
|
||||||
|
units=fpcresfix elfbfd elfres
|
||||||
|
|
||||||
|
[require]
|
||||||
|
packages=rtl
|
||||||
|
|
||||||
|
[install]
|
||||||
|
fpcpackage=y
|
||||||
|
|
||||||
|
[default]
|
||||||
|
fpcdir=../..
|
||||||
|
|
||||||
|
[rules]
|
||||||
|
fpcmake$(EXEEXT): fpcresfix.pas elfbfd.pas elfres.pas fpcres.pas
|
||||||
150
utils/fpcres/elfbfd.pas
Normal file
150
utils/fpcres/elfbfd.pas
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
{$ifdef fpc}
|
||||||
|
{$mode objfpc}
|
||||||
|
{$endif}
|
||||||
|
{$H+}
|
||||||
|
unit elfbfd;
|
||||||
|
|
||||||
|
{ELF Binary Format Description. 32/64 bit definitions }
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
const
|
||||||
|
SHT_NULL = 0;
|
||||||
|
SHT_PROGBITS = 1;
|
||||||
|
SHT_SYMTAB = 2;
|
||||||
|
SHT_STRTAB = 3;
|
||||||
|
SHT_RELA = 4;
|
||||||
|
SHT_HASH = 5;
|
||||||
|
SHT_DYNAMIC = 6;
|
||||||
|
SHT_NOTE = 7;
|
||||||
|
SHT_NOBITS = 8;
|
||||||
|
SHT_REL = 9;
|
||||||
|
SHT_SHLIB = 10;
|
||||||
|
SHT_DYNSYM = 11;
|
||||||
|
SHF_WRITE = 1;
|
||||||
|
SHF_ALLOC = 2;
|
||||||
|
SHF_EXECINSTR = 4;
|
||||||
|
|
||||||
|
PT_NULL = 0;
|
||||||
|
PT_LOAD = 1;
|
||||||
|
PT_DYNAMIC = 2;
|
||||||
|
PT_INTERP = 3;
|
||||||
|
PT_NOTE = 4;
|
||||||
|
PT_SHLIB = 5;
|
||||||
|
PT_PHDR = 6;
|
||||||
|
PT_LOOS = $60000000;
|
||||||
|
PT_HIOS = $6fffffff;
|
||||||
|
PT_LOPROC = $70000000;
|
||||||
|
PT_HIPROC = $7fffffff;
|
||||||
|
|
||||||
|
Type
|
||||||
|
TElf32header = packed record
|
||||||
|
magic0123: longint;
|
||||||
|
file_class: byte;
|
||||||
|
data_encoding: byte;
|
||||||
|
file_version: byte;
|
||||||
|
padding: array[$07..$0F] of byte;
|
||||||
|
e_type: word;
|
||||||
|
e_machine: word;
|
||||||
|
e_version: longint;
|
||||||
|
e_entry: longint; { entrypoint }
|
||||||
|
e_phoff: longint; { program header offset }
|
||||||
|
e_shoff: longint; { sections header offset }
|
||||||
|
e_flags: longint;
|
||||||
|
e_ehsize: word; { elf header size in bytes }
|
||||||
|
e_phentsize: word; { size of an entry in the program header array }
|
||||||
|
e_phnum: word; { 0..e_phnum-1 of entrys }
|
||||||
|
e_shentsize: word; { size of an entry in sections header array }
|
||||||
|
e_shnum: word; { 0..e_shnum-1 of entrys }
|
||||||
|
e_shstrndx: word; { index of string section header }
|
||||||
|
end;
|
||||||
|
|
||||||
|
TElf64header = packed record
|
||||||
|
magic0123: longint;
|
||||||
|
file_class: byte;
|
||||||
|
data_encoding: byte;
|
||||||
|
file_version: byte;
|
||||||
|
padding: array[$07..$0F] of byte;
|
||||||
|
e_type: word;
|
||||||
|
e_machine: word;
|
||||||
|
e_version: longint;
|
||||||
|
e_entry: int64; { entrypoint }
|
||||||
|
e_phoff: int64; { program header offset }
|
||||||
|
e_shoff: int64; { sections header offset }
|
||||||
|
e_flags: longint;
|
||||||
|
e_ehsize: word; { elf header size in bytes }
|
||||||
|
e_phentsize: word; { size of an entry in the program header array }
|
||||||
|
e_phnum: word; { 0..e_phnum-1 of entrys }
|
||||||
|
e_shentsize: word; { size of an entry in sections header array }
|
||||||
|
e_shnum: word; { 0..e_shnum-1 of entrys }
|
||||||
|
e_shstrndx: word; { index of string section header }
|
||||||
|
end;
|
||||||
|
|
||||||
|
TElf32sechdr = packed record
|
||||||
|
sh_name: longint;
|
||||||
|
sh_type: longint;
|
||||||
|
sh_flags: longint;
|
||||||
|
sh_addr: longint;
|
||||||
|
sh_offset: longint;
|
||||||
|
sh_size: longint;
|
||||||
|
sh_link: longint;
|
||||||
|
sh_info: longint;
|
||||||
|
sh_addralign: longint;
|
||||||
|
sh_entsize: longint;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TElf64sechdr = packed record
|
||||||
|
sh_name: longint;
|
||||||
|
sh_type: longint;
|
||||||
|
sh_flags: longint;
|
||||||
|
sh_addr: int64;
|
||||||
|
sh_offset: int64;
|
||||||
|
sh_size: int64;
|
||||||
|
sh_link: longint;
|
||||||
|
sh_info: longint;
|
||||||
|
sh_addralign: int64;
|
||||||
|
sh_entsize: int64;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ FPC resources }
|
||||||
|
|
||||||
|
TELF32ResourceSectionInfo = packed record
|
||||||
|
ptr: longint;
|
||||||
|
size: longint;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TELF64ResourceSectionInfo = packed record
|
||||||
|
ptr: int64;
|
||||||
|
size: int64;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TELF32ResourceInfo = packed record
|
||||||
|
reshash: longint; // always 32bit, contains an ELF hash of the resource entries name
|
||||||
|
restype: longint; // always 32bit, contains the resource type ID compatible with Windows RES IDs
|
||||||
|
ptr: longint; // Byte offset to the resource inside the resdata section.
|
||||||
|
name: longint; // Byte offset to the the resource name inside the ressym section.
|
||||||
|
size: longint; // The size of the resource entry
|
||||||
|
end;
|
||||||
|
|
||||||
|
TELF64ResourceInfo = packed record
|
||||||
|
reshash: longint; // always 32bit, contains an ELF hash of the resource entries name
|
||||||
|
restype: longint; // always 32bit, contains the resource type ID compatible with Windows RES IDs
|
||||||
|
ptr: int64; // Byte offset to the resource inside the resdata section.
|
||||||
|
name: int64; // Byte offset to the the resource name inside the ressym section.
|
||||||
|
size: int64; // The size of the resource entry
|
||||||
|
end;
|
||||||
|
|
||||||
|
TELF32ResourceSectionTable = packed record
|
||||||
|
version: integer;
|
||||||
|
resentries: integer;
|
||||||
|
ressym: TELF32ResourceSectionInfo;
|
||||||
|
reshash: TELF32ResourceSectionInfo;
|
||||||
|
resdata: TELF32ResourceSectionInfo;
|
||||||
|
resspare: TELF32ResourceSectionInfo;
|
||||||
|
resstr: TELF32ResourceSectionInfo;
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
||||||
692
utils/fpcres/elfres.pas
Normal file
692
utils/fpcres/elfres.pas
Normal file
@ -0,0 +1,692 @@
|
|||||||
|
{ *********************************************************************** }
|
||||||
|
{ }
|
||||||
|
{ fpcres2elf - Free Pascal Resource to ELF object compiler }
|
||||||
|
{ Part of the Free Pascal and CrossFPC distributions }
|
||||||
|
{ }
|
||||||
|
{ Copyright (C) 2005 Simon Kissel }
|
||||||
|
{ }
|
||||||
|
{ See the file COPYING.FPC, included in the FPC distribution, }
|
||||||
|
{ for details about the copyright. }
|
||||||
|
{ }
|
||||||
|
{ This program is distributed in the hope that it will be useful, }
|
||||||
|
{ but WITHOUT ANY WARRANTY; without even the implied warranty of }
|
||||||
|
{ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. }
|
||||||
|
{ }
|
||||||
|
{ *********************************************************************** }
|
||||||
|
|
||||||
|
{
|
||||||
|
This unit will compile an ELF object file out of a supplied .res resource
|
||||||
|
file. Optionally, Delphi/Kylix dfm/xfm form files are also accepted as
|
||||||
|
input. These will automatically be converted into resources internally.
|
||||||
|
|
||||||
|
fpcres2elf builds with Delphi, Kylix and FPC.
|
||||||
|
|
||||||
|
Currently this only works on 32Bit targets, but support for 64Bit targets
|
||||||
|
is in the works. Support for big endian systems is completely missing,
|
||||||
|
though.
|
||||||
|
|
||||||
|
Format used for the various resource sections:
|
||||||
|
|
||||||
|
fpc.resptrs: This section is contained in resptrs.o and always linked to the executable by
|
||||||
|
FPC. It containes an exported label fpcrespointers, which is used at runtime
|
||||||
|
to find the resptrs section in memory. The resptrs contains pointers to all the
|
||||||
|
sections and their sizes. These are updated in a post-precessing step by the
|
||||||
|
compiler and by the external resource embedder when applied to an ELF file.
|
||||||
|
This section always is 128 Bytes long and initially filled with zeros.
|
||||||
|
The first integer (32/64 Bit) value in this section contains the version
|
||||||
|
number of the resource system. Currently this value is 1.
|
||||||
|
The second integer (32/64 Bit) value in this section contains the number of
|
||||||
|
resources.
|
||||||
|
After this follows a version-defined number of TFPCResourceSectionInfo entries.
|
||||||
|
fpc.ressym: Contains the resource names. This simply is a stream of zero-terminated strings.
|
||||||
|
Only textual names are supported, numeric IDs get autoconverted to #ID's.
|
||||||
|
The reshash table has got a byte index into ressym to quickly get that data if needed
|
||||||
|
fpc.reshash: n TFPCResourceInfo records. (number of entries is defined in fpc.resptrs)
|
||||||
|
fpc.resdata: Contains the plain resource data stream. A byte index into the data stream
|
||||||
|
is given for each resource entry in TResourceInfo
|
||||||
|
fpc.resspare: An empty section which is resized to make room if the size of any of the previous
|
||||||
|
sections gets changed. NOT USED IN VERSION 1 (SIZE WILL BE 0)
|
||||||
|
fpc.resstr: This section is completely seperated from the rest and contains a block of
|
||||||
|
resourcestrings in internal FPC format.
|
||||||
|
|
||||||
|
resptr TFPCResourceSectionInfo list for FPC resources version 1:
|
||||||
|
|
||||||
|
Index Pointer to
|
||||||
|
0 ressym
|
||||||
|
1 reshash
|
||||||
|
2 resdata
|
||||||
|
3 resspare
|
||||||
|
4 resstr
|
||||||
|
5 reserved for future extension (stabs)
|
||||||
|
6 reserved for future extension
|
||||||
|
}
|
||||||
|
{$ifdef fpc}
|
||||||
|
{$mode objfpc}
|
||||||
|
{$endif}
|
||||||
|
{$H+}
|
||||||
|
unit elfres;
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
elfbfd,
|
||||||
|
SysUtils,
|
||||||
|
Classes;
|
||||||
|
|
||||||
|
const fpcres2elf_version=1;
|
||||||
|
|
||||||
|
// Do not change the following consts, they are dummy tables to generate an .o that makes ld happy
|
||||||
|
const shstrtab = #0+'.symtab'+#0+'.strtab'+#0+'.shstrtab'+#0+'.text'+#0+'.data'+#0+
|
||||||
|
'.bss'+#0+'fpc.ressym'+#0+'fpc.resstr'+#0+'fpc.reshash'+#0+
|
||||||
|
'fpc.resdata'+#0+'fpc.resspare'+#0+#0;
|
||||||
|
symtab = #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+
|
||||||
|
#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$03#$00#$01#$00+
|
||||||
|
#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$03#$00#$02#$00+
|
||||||
|
#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$03#$00#$03#$00+
|
||||||
|
#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$03#$00#$04#$00+
|
||||||
|
#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$03#$00#$05#$00+
|
||||||
|
#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$03#$00#$06#$00+
|
||||||
|
#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$03#$00#$07#$00+
|
||||||
|
#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$03#$00#$08#$00;
|
||||||
|
strtab = #$00#$00; // this actually is just one byte long
|
||||||
|
zeros = #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00;
|
||||||
|
fake = 'fakefakefakefakefakefakefakefake';
|
||||||
|
|
||||||
|
// header of a windows 32 bit .res file (16 bytes)
|
||||||
|
reshdr = #$00#$00#$00#$00#$20#$00#$00#$00#$FF#$FF#$00#$00#$FF#$FF#$00#$00+
|
||||||
|
#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00;
|
||||||
|
|
||||||
|
FilerSignature: array[1..4] of Char = 'TPF0';
|
||||||
|
|
||||||
|
SDefaultExtension = '.or';
|
||||||
|
|
||||||
|
Type
|
||||||
|
{ TElfResCreator }
|
||||||
|
|
||||||
|
TElfResCreator = Class(TObject)
|
||||||
|
private
|
||||||
|
FDestFileName: String;
|
||||||
|
FExtension: string;
|
||||||
|
FSourceFileName: String;
|
||||||
|
FOverwrite: Boolean;
|
||||||
|
FVerbose: Boolean;
|
||||||
|
FVersion: Integer;
|
||||||
|
Protected
|
||||||
|
FSectionStream: TMemoryStream;
|
||||||
|
FDataStream: TMemoryStream;
|
||||||
|
FSymStream: TMemoryStream;
|
||||||
|
FHashStream: TMemoryStream;
|
||||||
|
sectionheader_ofs: integer;
|
||||||
|
shstrtab_ofs: integer;
|
||||||
|
CurrentResource:integer;
|
||||||
|
resheader: string;
|
||||||
|
Signature: byte;
|
||||||
|
Procedure AllocateData; virtual;
|
||||||
|
Procedure FreeData; virtual;
|
||||||
|
Procedure DoAlign(const a: integer);
|
||||||
|
Public
|
||||||
|
Constructor Create;
|
||||||
|
Procedure Convert(Const Source,Destination : String);
|
||||||
|
Procedure ConvertStreams(Source,Dest : TStream);
|
||||||
|
Procedure DoConvertStreams(Source,Dest : TStream); virtual;Abstract;
|
||||||
|
Property Verbose : Boolean Read FVerbose Write FVerbose;
|
||||||
|
Property SourceFileName : String Read FSourceFileName;
|
||||||
|
Property DestFileName : String Read FDestFileName;
|
||||||
|
Property Overwrite : Boolean Read FOverwrite Write FOverWrite;
|
||||||
|
Property Version : Integer Read FVersion Write FVersion;
|
||||||
|
Property Extension : string Read FExtension Write FExtension;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TElf32ResCreator }
|
||||||
|
|
||||||
|
TElf32ResCreator = Class(TElfResCreator)
|
||||||
|
Private
|
||||||
|
ResourceEntries: array of TELF32ResourceInfo;
|
||||||
|
Protected
|
||||||
|
Procedure AllocateData; override;
|
||||||
|
Procedure FreeData; override;
|
||||||
|
public
|
||||||
|
procedure LoadBinaryDFMEntry(const rs:TStream; const DataStream:TMemoryStream; const SymStream:TMemoryStream; var resinfo:TELF32ResourceInfo);
|
||||||
|
procedure LoadTextDFMEntry(const rs:TStream; const DataStream:TMemoryStream; const SymStream:TMemoryStream; var resinfo:TELF32ResourceInfo);
|
||||||
|
procedure LoadRESEntry(const rs:TStream; const DataStream:TMemoryStream; const SymStream:TMemoryStream; var resinfo:TELF32ResourceInfo);
|
||||||
|
Procedure DoConvertStreams(Source,Dest : TStream); override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TElf64Creator }
|
||||||
|
|
||||||
|
TElf64ResCreator = Class(TElfResCreator)
|
||||||
|
Procedure DoConvertStreams(Source,Dest : TStream); override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
EElfResError = Class(Exception);
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
resourcestring
|
||||||
|
SErrUnrecognizedFormat = 'Unrecognized file format for input file "%s"';
|
||||||
|
|
||||||
|
Procedure DoError (Msg : String);
|
||||||
|
|
||||||
|
begin
|
||||||
|
Raise EElfResError.Create(Msg);
|
||||||
|
end;
|
||||||
|
|
||||||
|
Procedure DoErrorFmt (Msg : String; Args : Array of const);
|
||||||
|
|
||||||
|
begin
|
||||||
|
Raise EElfResError.CreateFmt(Msg,Args);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function HashELF(const S : string) : longint;
|
||||||
|
{Note: this hash function is described in "Practical Algorithms For
|
||||||
|
Programmers" by Andrew Binstock and John Rex, Addison Wesley,
|
||||||
|
with modifications in Dr Dobbs Journal, April 1996}
|
||||||
|
var
|
||||||
|
G : longint;
|
||||||
|
i : integer;
|
||||||
|
begin
|
||||||
|
Result := 0;
|
||||||
|
for i := 1 to length(S) do begin
|
||||||
|
Result := (Result shl 4) + ord(S[i]);
|
||||||
|
G := Result and $F0000000;
|
||||||
|
if (G <> 0) then
|
||||||
|
Result := Result xor (G shr 24);
|
||||||
|
Result := Result and (not G);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TElfResCreator }
|
||||||
|
|
||||||
|
procedure TElfResCreator.AllocateData;
|
||||||
|
begin
|
||||||
|
FSectionStream:=TMemoryStream.Create;
|
||||||
|
FDataStream:=TMemoryStream.Create;
|
||||||
|
FSymStream:=TMemoryStream.Create;
|
||||||
|
FHashStream:=TMemoryStream.Create;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TElfResCreator.FreeData;
|
||||||
|
begin
|
||||||
|
FreeAndNil(FSectionStream);
|
||||||
|
FreeAndNil(FDataStream);
|
||||||
|
FreeAndNil(FSymStream);
|
||||||
|
FreeAndNil(FHashStream);
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TElfResCreator.Create;
|
||||||
|
begin
|
||||||
|
FVersion:=fpcres2elf_version;
|
||||||
|
FOverwrite:=True;
|
||||||
|
FVerbose:=False;
|
||||||
|
FExtension:=SDefaultExtension;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// fill the memorystream so it is aligned, max supported align is 16
|
||||||
|
procedure TElfResCreator.DoAlign(const a: integer);
|
||||||
|
var i: integer;
|
||||||
|
begin
|
||||||
|
i:=(4 - (FSectionStream.position MOD a)) MOD a;
|
||||||
|
if (i>0) then FSectionStream.Write(zeros,i);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TElfResCreator.Convert(const Source, Destination: String);
|
||||||
|
|
||||||
|
Var
|
||||||
|
Src,Dest : TFileStream;
|
||||||
|
|
||||||
|
begin
|
||||||
|
FSourceFileName:=Source;
|
||||||
|
FDestFileName:=Destination;
|
||||||
|
if FDestFileName='' then
|
||||||
|
FDestFileName:=ChangeFileExt(Source,FExtension);
|
||||||
|
Src:=TFileStream.Create(FSourceFileName,fmOpenRead or fmShareDenyWrite);
|
||||||
|
try
|
||||||
|
Dest:=TFileStream.Create(FDestFileName,fmCreate or fmShareDenyWrite);
|
||||||
|
Try
|
||||||
|
ConvertStreams(Src,Dest);
|
||||||
|
Finally
|
||||||
|
Dest.Free;
|
||||||
|
end;
|
||||||
|
Finally
|
||||||
|
Src.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TElfResCreator.ConvertStreams(Source, Dest: TStream);
|
||||||
|
begin
|
||||||
|
AllocateData;
|
||||||
|
Try
|
||||||
|
DoConvertStreams(Source,Dest);
|
||||||
|
Finally
|
||||||
|
FreeData;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ ---------------------------------------------------------------------
|
||||||
|
TElf32ResCreator
|
||||||
|
---------------------------------------------------------------------}
|
||||||
|
|
||||||
|
procedure TElf32ResCreator.AllocateData;
|
||||||
|
begin
|
||||||
|
inherited AllocateData;
|
||||||
|
// reserve space for 1024 resource entries for now
|
||||||
|
SetLength(ResourceEntries,1024);
|
||||||
|
CurrentResource:=0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TElf32ResCreator.FreeData;
|
||||||
|
begin
|
||||||
|
inherited FreeData;
|
||||||
|
SetLength(ResourceEntries,0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TElf32ResCreator.LoadRESEntry(const rs:TStream; const DataStream:TMemoryStream; const SymStream:TMemoryStream; var resinfo:TELF32ResourceInfo);
|
||||||
|
var l:longint;
|
||||||
|
w:word;
|
||||||
|
ws:WideString;
|
||||||
|
wc:WideChar;
|
||||||
|
name:string;
|
||||||
|
i: integer;
|
||||||
|
headersize:integer;
|
||||||
|
headerstart:integer;
|
||||||
|
begin
|
||||||
|
headerstart:=rs.Position;
|
||||||
|
resinfo.ptr:=DataStream.Position;
|
||||||
|
rs.Read(resinfo.size,4);
|
||||||
|
rs.Read(headersize,4);
|
||||||
|
rs.Read(l,4); // Type
|
||||||
|
if (l AND $0000FFFF)=$0000FFFF then
|
||||||
|
begin // Type is stored as ID
|
||||||
|
resinfo.restype:=(l AND $FFFF0000) shr 16; // kill the marker, we always use IDs
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
// we don't support text IDs for now, skip until we have reached the end
|
||||||
|
// of the widestring, and set rcdata (10) in this case.
|
||||||
|
repeat
|
||||||
|
rs.Read(w,2);
|
||||||
|
until w=0;
|
||||||
|
resinfo.restype:=10;
|
||||||
|
end;
|
||||||
|
|
||||||
|
rs.Read(l,4); // Name
|
||||||
|
if (l AND $0000FFFF)=$0000FFFF then
|
||||||
|
begin // Name is stored as ID.
|
||||||
|
l:=(l AND $FFFF0000) shr 16; // kill the marker
|
||||||
|
// We don't want to support integer names, we'll instead convert them to a #id string
|
||||||
|
// which is more common.
|
||||||
|
name:='#'+inttostr(l);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
// Ok, it's a widestring ID
|
||||||
|
ws:=widechar(l AND $0000FFFF);
|
||||||
|
ws:=ws+widechar((l AND $FFFF0000) shr 16);
|
||||||
|
// get the rest of it
|
||||||
|
repeat
|
||||||
|
rs.Read(wc,2);
|
||||||
|
if wc<>#0 then ws:=ws+wc;
|
||||||
|
until wc=#0;
|
||||||
|
// convert to ANSI
|
||||||
|
name:=ws;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// create a hash of the name
|
||||||
|
resinfo.reshash:=HashELF(name);
|
||||||
|
|
||||||
|
// save the name plus a trailing #0 to the SymStream, also save
|
||||||
|
// the position of this name in the SymStream
|
||||||
|
resinfo.name:=SymStream.Position;
|
||||||
|
name:=name+#0;
|
||||||
|
SymStream.Write(name[1],length(name));
|
||||||
|
|
||||||
|
// We don't care about the rest of the header
|
||||||
|
rs.Seek(headersize-(rs.position-headerstart),soFromCurrent);
|
||||||
|
|
||||||
|
// Now copy over the resource data into our internal memory stream
|
||||||
|
DataStream.CopyFrom(rs,resinfo.size);
|
||||||
|
|
||||||
|
// Align the resource stream on a dword boundary
|
||||||
|
i:=(4 - (rs.Position MOD 4)) MOD 4;
|
||||||
|
if (i>0) then rs.Seek(i,soFromCurrent);
|
||||||
|
|
||||||
|
|
||||||
|
// Align the data stream on a dword boundary
|
||||||
|
i:=(4 - (DataStream.Position MOD 4)) MOD 4;
|
||||||
|
if (i>0) then DataStream.Write(zeros,i);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TElf32ResCreator.LoadBinaryDFMEntry(const rs:TStream; const DataStream:TMemoryStream; const SymStream:TMemoryStream; var resinfo:TELF32ResourceInfo);
|
||||||
|
var name: string;
|
||||||
|
i: integer;
|
||||||
|
begin
|
||||||
|
resinfo.ptr:=0;
|
||||||
|
resinfo.restype:=10; // RCDATA
|
||||||
|
|
||||||
|
// Skip the header
|
||||||
|
rs.Position:=3;
|
||||||
|
|
||||||
|
// Read the name
|
||||||
|
setlength(name,64); // Component names can be 64 chars at max
|
||||||
|
rs.Read(name[1],64);
|
||||||
|
|
||||||
|
// Find end of name
|
||||||
|
i:=pos(#0,name);
|
||||||
|
name:=copy(name,1,i-1);
|
||||||
|
|
||||||
|
// Seek to after the name and skip other crap
|
||||||
|
rs.Position:=i+9;
|
||||||
|
|
||||||
|
resinfo.size:=rs.Size-rs.Position;
|
||||||
|
|
||||||
|
// ...this is followed by the data.
|
||||||
|
|
||||||
|
// create a hash of the name
|
||||||
|
resinfo.reshash:=HashELF(name);
|
||||||
|
|
||||||
|
// save the name plus a trailing #0 to the SymStream, also save
|
||||||
|
// the position of this name in the SymStream
|
||||||
|
resinfo.name:=SymStream.Position;
|
||||||
|
name:=name+#0;
|
||||||
|
SymStream.Write(name[1],length(name));
|
||||||
|
|
||||||
|
// Now copy over the resource data into our internal memory stream
|
||||||
|
DataStream.CopyFrom(rs,resinfo.size);
|
||||||
|
|
||||||
|
// Align the data stream on a dword boundary
|
||||||
|
i:=(4 - (DataStream.Position MOD 4)) MOD 4;
|
||||||
|
if (i>0) then DataStream.Write(zeros,i);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TElf32ResCreator.LoadTextDFMEntry(const rs:TStream; const DataStream:TMemoryStream; const SymStream:TMemoryStream; var resinfo:TELF32ResourceInfo);
|
||||||
|
var ms:TMemoryStream;
|
||||||
|
begin
|
||||||
|
ms:=nil;
|
||||||
|
try
|
||||||
|
ms:=TMemoryStream.Create;
|
||||||
|
ObjectTextToResource(rs,ms);
|
||||||
|
LoadBinaryDFMEntry(ms, DataStream, SymStream, resinfo);
|
||||||
|
finally
|
||||||
|
ms.free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TElf32ResCreator.DoConvertStreams(Source, Dest: TStream);
|
||||||
|
|
||||||
|
Var
|
||||||
|
I : Integer;
|
||||||
|
ElfHeader: TElf32Header;
|
||||||
|
SectionHeader: TElf32sechdr;
|
||||||
|
ressym: TELF32ResourceSectionInfo;
|
||||||
|
resstr: TELF32ResourceSectionInfo;
|
||||||
|
reshash: TELF32ResourceSectionInfo;
|
||||||
|
resdata: TELF32ResourceSectionInfo;
|
||||||
|
resspare: TELF32ResourceSectionInfo;
|
||||||
|
|
||||||
|
begin
|
||||||
|
// Read and check the header of the input file. First check if it's a 32bit resource
|
||||||
|
// file...
|
||||||
|
SetLength(resheader,32);
|
||||||
|
Source.Read(resheader[1],32);
|
||||||
|
if (resheader<>reshdr) then
|
||||||
|
begin
|
||||||
|
// ...not a 32Bit resource file. Now let's see if it's a text or binary dfm/xfm/lfm file.
|
||||||
|
Source.Position:=0;
|
||||||
|
Source.Read(Signature,1);
|
||||||
|
if (Signature=$FF) then
|
||||||
|
begin
|
||||||
|
Source.Position:=0;
|
||||||
|
LoadBinaryDFMEntry(Source, FDataStream, FSymStream, ResourceEntries[CurrentResource]);
|
||||||
|
end
|
||||||
|
else if char(Signature) in ['o','O','i','I',' ',#13,#11,#9] then
|
||||||
|
begin
|
||||||
|
Source.Position:=0;
|
||||||
|
LoadTextDFMEntry(Source, FDataStream, FSymStream, ResourceEntries[CurrentResource]);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
DoErrorFmt(SErrUnrecognizedFormat,[SourceFileName]);
|
||||||
|
inc(CurrentResource,1);
|
||||||
|
end
|
||||||
|
else // ...yes, it's a resource file.
|
||||||
|
while Source.Position<Source.Size do
|
||||||
|
begin
|
||||||
|
// Load Resource info, and copy the resource data into the DataStream
|
||||||
|
LoadRESEntry(Source, FDataStream, FSymStream, ResourceEntries[CurrentResource]);
|
||||||
|
inc(CurrentResource,1);
|
||||||
|
// if we hit the current limit of allocated ResourceEntries in the
|
||||||
|
// array, allocate some more space
|
||||||
|
if (CurrentResource>=length(ResourceEntries)) then
|
||||||
|
setlength(ResourceEntries,length(ResourceEntries)+1024);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// downsize the ResourceEntries to the really needed size
|
||||||
|
SetLength(ResourceEntries,CurrentResource);
|
||||||
|
|
||||||
|
// Write the symbol table - ressym
|
||||||
|
ressym.ptr:=FSectionStream.Position+sizeof(TElf32Header);
|
||||||
|
FSymStream.Position:=0;
|
||||||
|
FSectionStream.CopyFrom(FSymStream,FSymStream.Size);
|
||||||
|
doalign(4);
|
||||||
|
|
||||||
|
// resstr
|
||||||
|
resstr.ptr:=FSectionStream.Position+sizeof(TElf32Header);
|
||||||
|
resstr.size:=0;
|
||||||
|
// TODO: Load string data here
|
||||||
|
doalign(4);
|
||||||
|
|
||||||
|
// Now write the ResourceInfos.
|
||||||
|
reshash.ptr:=FSectionStream.Position+sizeof(TElf32Header);
|
||||||
|
for i:=0 to high(ResourceEntries) do
|
||||||
|
begin
|
||||||
|
FSectionStream.Write(ResourceEntries[i],sizeof(TELF32ResourceInfo));
|
||||||
|
end;
|
||||||
|
doalign(4);
|
||||||
|
|
||||||
|
// Next write the resource data stream
|
||||||
|
resdata.ptr:=FSectionStream.Position+sizeof(TElf32Header);
|
||||||
|
FDataStream.Position:=0;
|
||||||
|
FSectionStream.CopyFrom(FDataStream,FDataStream.Size);
|
||||||
|
doalign(4);
|
||||||
|
|
||||||
|
// resspare
|
||||||
|
resspare.ptr:=FSectionStream.Position+sizeof(TElf32Header);
|
||||||
|
// don't write anything, this is an empty section
|
||||||
|
|
||||||
|
// shstrtab - this is not aligned
|
||||||
|
shstrtab_ofs:=FSectionStream.Position+sizeof(TElf32Header);
|
||||||
|
FSectionStream.Write(shstrtab,length(shstrtab));
|
||||||
|
|
||||||
|
// Write 12 section headers. The headers itself don't need to be aligned,
|
||||||
|
// as their size can be divided by 4. As shstrtab is uneven and not aligned,
|
||||||
|
// we however need to align the start of the section header table
|
||||||
|
doalign(4);
|
||||||
|
sectionheader_ofs:=FSectionStream.Position+sizeof(TElf32Header);;
|
||||||
|
|
||||||
|
// empty one
|
||||||
|
fillchar(SectionHeader,sizeof(SectionHeader),0);
|
||||||
|
FSectionStream.Write(SectionHeader,sizeOf(SectionHeader));
|
||||||
|
|
||||||
|
// .text
|
||||||
|
SectionHeader.sh_name:=$1B;
|
||||||
|
SectionHeader.sh_type:=1; // PROGBITS
|
||||||
|
SectionHeader.sh_flags:=6; // AX
|
||||||
|
SectionHeader.sh_addr:=0;
|
||||||
|
SectionHeader.sh_offset:=sizeof(TElf32Header); // after header, dummy as size is 0
|
||||||
|
SectionHeader.sh_size:=0; // yep, pretty empty it is
|
||||||
|
SectionHeader.sh_link:=0;
|
||||||
|
SectionHeader.sh_info:=0;
|
||||||
|
SectionHeader.sh_addralign:=4; // alignment
|
||||||
|
SectionHeader.sh_entsize:=0;
|
||||||
|
FSectionStream.Write(SectionHeader,sizeOf(SectionHeader));
|
||||||
|
|
||||||
|
// .data
|
||||||
|
SectionHeader.sh_name:=$21;
|
||||||
|
SectionHeader.sh_type:=1; // PROGBITS
|
||||||
|
SectionHeader.sh_flags:=3; // WA
|
||||||
|
SectionHeader.sh_addr:=0;
|
||||||
|
SectionHeader.sh_offset:=sizeof(TElf32Header); // after header, dummy as size is 0
|
||||||
|
SectionHeader.sh_size:=0; // yep, pretty empty it is
|
||||||
|
SectionHeader.sh_link:=0;
|
||||||
|
SectionHeader.sh_info:=0;
|
||||||
|
SectionHeader.sh_addralign:=4; // alignment
|
||||||
|
SectionHeader.sh_entsize:=0;
|
||||||
|
FSectionStream.Write(SectionHeader,sizeOf(SectionHeader));
|
||||||
|
|
||||||
|
// .bss
|
||||||
|
SectionHeader.sh_name:=$27;
|
||||||
|
SectionHeader.sh_type:=8; // NOBITS
|
||||||
|
SectionHeader.sh_flags:=3; // WA
|
||||||
|
SectionHeader.sh_addr:=0;
|
||||||
|
SectionHeader.sh_offset:=sizeof(TElf32Header); // after header, dummy as size is 0
|
||||||
|
SectionHeader.sh_size:=0; // yep, pretty empty it is
|
||||||
|
SectionHeader.sh_link:=0;
|
||||||
|
SectionHeader.sh_info:=0;
|
||||||
|
SectionHeader.sh_addralign:=4; // alignment
|
||||||
|
SectionHeader.sh_entsize:=0;
|
||||||
|
FSectionStream.Write(SectionHeader,sizeOf(SectionHeader));
|
||||||
|
|
||||||
|
// fpc.ressym
|
||||||
|
SectionHeader.sh_name:=$2C;
|
||||||
|
SectionHeader.sh_type:=1; // PROGBITS
|
||||||
|
SectionHeader.sh_flags:=2; // A
|
||||||
|
SectionHeader.sh_addr:=0;
|
||||||
|
SectionHeader.sh_offset:=ressym.ptr; // directly after header
|
||||||
|
SectionHeader.sh_size:=FSymStream.Size;
|
||||||
|
SectionHeader.sh_link:=0;
|
||||||
|
SectionHeader.sh_info:=0;
|
||||||
|
SectionHeader.sh_addralign:=4; // alignment
|
||||||
|
SectionHeader.sh_entsize:=0;
|
||||||
|
FSectionStream.Write(SectionHeader,sizeOf(SectionHeader));
|
||||||
|
|
||||||
|
// fpc.resstr
|
||||||
|
SectionHeader.sh_name:=$37;
|
||||||
|
SectionHeader.sh_type:=1; // PROGBITS
|
||||||
|
SectionHeader.sh_flags:=2; // A
|
||||||
|
SectionHeader.sh_addr:=0;
|
||||||
|
SectionHeader.sh_offset:=resstr.ptr;
|
||||||
|
SectionHeader.sh_size:=0; // currently empty
|
||||||
|
SectionHeader.sh_link:=0;
|
||||||
|
SectionHeader.sh_info:=0;
|
||||||
|
SectionHeader.sh_addralign:=4; // alignment
|
||||||
|
SectionHeader.sh_entsize:=0;
|
||||||
|
FSectionStream.Write(SectionHeader,sizeOf(SectionHeader));
|
||||||
|
|
||||||
|
// fpc.reshash
|
||||||
|
SectionHeader.sh_name:=$42;
|
||||||
|
SectionHeader.sh_type:=1; // PROGBITS
|
||||||
|
SectionHeader.sh_flags:=2; // A
|
||||||
|
SectionHeader.sh_addr:=0;
|
||||||
|
SectionHeader.sh_offset:=reshash.ptr;
|
||||||
|
SectionHeader.sh_size:=length(ResourceEntries)*sizeof(TELF32ResourceInfo)+4;
|
||||||
|
SectionHeader.sh_link:=0;
|
||||||
|
SectionHeader.sh_info:=0;
|
||||||
|
SectionHeader.sh_addralign:=4; // alignment
|
||||||
|
SectionHeader.sh_entsize:=0;
|
||||||
|
FSectionStream.Write(SectionHeader,sizeOf(SectionHeader));
|
||||||
|
|
||||||
|
// fpc.resdata
|
||||||
|
SectionHeader.sh_name:=$4e;
|
||||||
|
SectionHeader.sh_type:=1; // PROGBITS
|
||||||
|
SectionHeader.sh_flags:=2; // A
|
||||||
|
SectionHeader.sh_addr:=0;
|
||||||
|
SectionHeader.sh_offset:=resdata.ptr;
|
||||||
|
SectionHeader.sh_size:=FDataStream.Size;
|
||||||
|
SectionHeader.sh_link:=0;
|
||||||
|
SectionHeader.sh_info:=0;
|
||||||
|
SectionHeader.sh_addralign:=4; // alignment
|
||||||
|
SectionHeader.sh_entsize:=0;
|
||||||
|
FSectionStream.Write(SectionHeader,sizeOf(SectionHeader));
|
||||||
|
|
||||||
|
// fpc.resspare
|
||||||
|
// Not used in V1
|
||||||
|
SectionHeader.sh_name:=$5a;
|
||||||
|
SectionHeader.sh_type:=8; // NOBITS
|
||||||
|
SectionHeader.sh_flags:=2; // A
|
||||||
|
SectionHeader.sh_addr:=0;
|
||||||
|
SectionHeader.sh_offset:=resspare.ptr; // fake, as it's empty, should be equal to shstrtab's offset
|
||||||
|
SectionHeader.sh_size:=0; //DataStream.Size; // Leave as much room as we currently have in resdata section
|
||||||
|
SectionHeader.sh_link:=0;
|
||||||
|
SectionHeader.sh_info:=0;
|
||||||
|
SectionHeader.sh_addralign:=4; // alignment
|
||||||
|
SectionHeader.sh_entsize:=0;
|
||||||
|
FSectionStream.Write(SectionHeader,sizeOf(SectionHeader));
|
||||||
|
|
||||||
|
// .shstrtab
|
||||||
|
SectionHeader.sh_name:=$11;
|
||||||
|
SectionHeader.sh_type:=3; // STRTAB
|
||||||
|
SectionHeader.sh_flags:=0;
|
||||||
|
SectionHeader.sh_addr:=0;
|
||||||
|
SectionHeader.sh_offset:=shstrtab_ofs; // $3E
|
||||||
|
SectionHeader.sh_size:=$67;
|
||||||
|
SectionHeader.sh_link:=0;
|
||||||
|
SectionHeader.sh_info:=0;
|
||||||
|
SectionHeader.sh_addralign:=1; // alignment
|
||||||
|
SectionHeader.sh_entsize:=0;
|
||||||
|
FSectionStream.Write(SectionHeader,sizeOf(SectionHeader));
|
||||||
|
|
||||||
|
// .symtab
|
||||||
|
SectionHeader.sh_name:=$01;
|
||||||
|
SectionHeader.sh_type:=2; // SYMTAB
|
||||||
|
SectionHeader.sh_flags:=0;
|
||||||
|
SectionHeader.sh_addr:=0;
|
||||||
|
SectionHeader.sh_offset:=FSectionStream.Position+sizeof(TElf32Header)+sizeOf(SectionHeader)+sizeOf(SectionHeader); // will come directly after this and the next section. $0288;
|
||||||
|
SectionHeader.sh_size:=$90;
|
||||||
|
SectionHeader.sh_link:=$0B;
|
||||||
|
SectionHeader.sh_info:=$09;
|
||||||
|
SectionHeader.sh_addralign:=4; // alignment
|
||||||
|
SectionHeader.sh_entsize:=$10;
|
||||||
|
FSectionStream.Write(SectionHeader,sizeOf(SectionHeader));
|
||||||
|
|
||||||
|
// .strtab
|
||||||
|
SectionHeader.sh_name:=$09;
|
||||||
|
SectionHeader.sh_type:=3; // STRTAB
|
||||||
|
SectionHeader.sh_flags:=0;
|
||||||
|
SectionHeader.sh_addr:=0;
|
||||||
|
SectionHeader.sh_offset:=FSectionStream.Position+sizeof(TElf32Header)+sizeOf(SectionHeader)+$90; // will come after this sectionheader and the $90 bytes symtab - $0318; end of file
|
||||||
|
SectionHeader.sh_size:=1;
|
||||||
|
SectionHeader.sh_link:=0;
|
||||||
|
SectionHeader.sh_info:=0;
|
||||||
|
SectionHeader.sh_addralign:=1; // alignment
|
||||||
|
SectionHeader.sh_entsize:=$0;
|
||||||
|
FSectionStream.Write(SectionHeader,sizeOf(SectionHeader));
|
||||||
|
|
||||||
|
// now write the symbol table
|
||||||
|
FSectionStream.Write(symtab,length(symtab));
|
||||||
|
// We don't need to align it, as it's $90 in size
|
||||||
|
|
||||||
|
// now write the string table, it's just a single byte
|
||||||
|
FSectionStream.Write(strtab,1);
|
||||||
|
|
||||||
|
// Ok, we are done, now let's really write something to disk...
|
||||||
|
|
||||||
|
// First write the ELF header
|
||||||
|
|
||||||
|
fillchar(ElfHeader,sizeof(ElfHeader),0);
|
||||||
|
ElfHeader.magic0123:=$464c457f; { = #127'ELF' }
|
||||||
|
ElfHeader.file_class:=1;
|
||||||
|
ElfHeader.data_encoding:=1;
|
||||||
|
ElfHeader.file_version:=1;
|
||||||
|
ElfHeader.e_type:=1;
|
||||||
|
ElfHeader.e_machine:=3;
|
||||||
|
ElfHeader.e_version:=1;
|
||||||
|
ElfHeader.e_shoff:=sectionheader_ofs;
|
||||||
|
ElfHeader.e_shstrndx:=9;
|
||||||
|
ElfHeader.e_shnum:=12;
|
||||||
|
ElfHeader.e_ehsize:=sizeof(TElf32header);
|
||||||
|
ElfHeader.e_shentsize:=sizeof(TElf32sechdr);
|
||||||
|
|
||||||
|
Dest.Write(ElfHeader,sizeof(TElf32header));
|
||||||
|
|
||||||
|
// And now let's dump our whole memorystream into it.
|
||||||
|
Dest.CopyFrom(FSectionStream,0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
{ TElf64Creator }
|
||||||
|
|
||||||
|
procedure TElf64ResCreator.DoConvertStreams(Source, Dest: TStream);
|
||||||
|
begin
|
||||||
|
DoError('64 bits resources not yet supported')
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
||||||
260
utils/fpcres/elfresfix.pas
Normal file
260
utils/fpcres/elfresfix.pas
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
|
||||||
|
{ *********************************************************************** }
|
||||||
|
{ }
|
||||||
|
{ elfresfix - Free Pascal Resource to ELF object compiler - fixup tool }
|
||||||
|
{ Part of the Free Pascal and CrossFPC distributions }
|
||||||
|
{ }
|
||||||
|
{ Copyright (C) 2005 Simon Kissel }
|
||||||
|
{ }
|
||||||
|
{ See the file COPYING.FPC, included in the FPC distribution, }
|
||||||
|
{ for details about the copyright. }
|
||||||
|
{ }
|
||||||
|
{ This program is distributed in the hope that it will be useful, }
|
||||||
|
{ but WITHOUT ANY WARRANTY; without even the implied warranty of }
|
||||||
|
{ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. }
|
||||||
|
{ }
|
||||||
|
{ *********************************************************************** }
|
||||||
|
|
||||||
|
{
|
||||||
|
This tool will update the fpc.resptrs section of an ELF executable to point
|
||||||
|
to the various resource sections in the file. This is done so that the FPC
|
||||||
|
RTL at runtime is able to get pointers to these sections.
|
||||||
|
|
||||||
|
This tool is automatically run on any fpc compiled ELF executable that
|
||||||
|
contains ELF resources.
|
||||||
|
|
||||||
|
fpcresfix builds with Delphi, Kylix and FPC.
|
||||||
|
|
||||||
|
Currently this only works on 32Bit targets, but support for 64Bit targets
|
||||||
|
is in the works. Support for big endian systems is completely missing,
|
||||||
|
though.
|
||||||
|
}
|
||||||
|
{$ifdef fpc}
|
||||||
|
{$mode objfpc}
|
||||||
|
{$endif}
|
||||||
|
{$h+}
|
||||||
|
|
||||||
|
unit elfresfix;
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
SysUtils, Classes, elfbfd;
|
||||||
|
|
||||||
|
Type
|
||||||
|
|
||||||
|
TLogEvent = Procedure(Const Msg : String) of object;
|
||||||
|
|
||||||
|
{ TElfResourceFixer }
|
||||||
|
|
||||||
|
TElfResourceFixer = Class(TObject)
|
||||||
|
private
|
||||||
|
FFileName: String;
|
||||||
|
FOnVerbose: TLogEvent;
|
||||||
|
FVerbose: Boolean;
|
||||||
|
Procedure DoVerbose(Msg : String);
|
||||||
|
public
|
||||||
|
Procedure FixFile(AFileName : String);
|
||||||
|
Procedure DoFixStream(Stream : TStream); virtual; abstract;
|
||||||
|
Property Verbose : Boolean read FVerbose write FVerbose;
|
||||||
|
Property FileName : String Read FFileName;
|
||||||
|
Property Onverbose : TLogEvent Read FOnVerbose Write FOnVerbose;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TElf32ResourceFixer }
|
||||||
|
|
||||||
|
TElf32ResourceFixer = Class(TElfResourceFixer)
|
||||||
|
Procedure DoFixStream(Stream : TStream); override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TElf64ResourceFixer }
|
||||||
|
|
||||||
|
TElf64ResourceFixer = Class(TElfResourceFixer)
|
||||||
|
Procedure DoFixStream(Stream : TStream); override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
EElfResFixError = Class(Exception);
|
||||||
|
|
||||||
|
Implementation
|
||||||
|
|
||||||
|
ResourceString
|
||||||
|
SCheckingHeader = 'Checking ELF Header... ';
|
||||||
|
SReadingSectionHeaders = 'Reading Section Headers...';
|
||||||
|
SHeaderOK = 'ELF Header is OK';
|
||||||
|
SCheckingHeaderTable = 'Checking Section Header table...';
|
||||||
|
SStrTabFound = 'Found strtab...';
|
||||||
|
SProcessingSection = 'Processing section: ';
|
||||||
|
SUpdatingResptrs = 'Updating resptrs section...';
|
||||||
|
SFileFixed = 'File fixed successfully!';
|
||||||
|
SNothingToFix = 'There was nothing to fix in this file.';
|
||||||
|
|
||||||
|
SErrUnsupportedHeaderSize = 'Unsupported Section Header size.';
|
||||||
|
SErrInvalidELFHeader = 'Not a valid linux ELF binary.';
|
||||||
|
SErrResPtrsNotFound = 'Unable to find resptrs section.';
|
||||||
|
|
||||||
|
Procedure DoError (Msg : String);
|
||||||
|
|
||||||
|
begin
|
||||||
|
Raise EElfResFixError.Create(Msg);
|
||||||
|
end;
|
||||||
|
|
||||||
|
Procedure DoErrorFmt (Msg : String; Args : Array of const);
|
||||||
|
|
||||||
|
begin
|
||||||
|
Raise EElfResFixError.CreateFmt(Msg,Args);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TElfResourceFixer }
|
||||||
|
|
||||||
|
procedure TElfResourceFixer.DoVerbose(Msg: String);
|
||||||
|
begin
|
||||||
|
If FVerbose and Assigned(FOnVerbose) then
|
||||||
|
FOnVerbose(Msg);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TElfResourceFixer.FixFile(AFileName: String);
|
||||||
|
|
||||||
|
Var
|
||||||
|
F : TStream;
|
||||||
|
|
||||||
|
begin
|
||||||
|
FFileName:=AFileName;
|
||||||
|
F:=TFileStream.Create(AFilename,fmOpenReadWrite or fmShareDenyWrite);
|
||||||
|
Try
|
||||||
|
DoFixStream(F);
|
||||||
|
Finally
|
||||||
|
F.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TElf32ResourceFixer }
|
||||||
|
|
||||||
|
procedure TElf32ResourceFixer.DoFixStream(Stream: TStream);
|
||||||
|
|
||||||
|
var
|
||||||
|
ElfHeader:TElf32header;
|
||||||
|
ResourceSectionTable: TElf32ResourceSectionTable;
|
||||||
|
SectionHeaders: array of TElf32sechdr;
|
||||||
|
|
||||||
|
i:integer;
|
||||||
|
sn:string;
|
||||||
|
SectionHeaderOffset:integer;
|
||||||
|
fixed: boolean;
|
||||||
|
strtab:string;
|
||||||
|
SectionName: string;
|
||||||
|
ResPtrsSection: integer;
|
||||||
|
|
||||||
|
begin
|
||||||
|
Fixed:=False;
|
||||||
|
Stream.Read(ElfHeader,sizeof(TElf32header));
|
||||||
|
DoVerbose(SCheckingHeader);
|
||||||
|
if (ElfHeader.magic0123<>$464C457F) then
|
||||||
|
DoError(SErrInvalidELFheader);
|
||||||
|
if ElfHeader.e_shentsize=sizeof(TElf32sechdr) then
|
||||||
|
DoVerbose(SHeaderOK)
|
||||||
|
else
|
||||||
|
DoError(SErrUnSupportedHeaderSize);
|
||||||
|
DoVerbose(SReadingSectionHeaders);
|
||||||
|
|
||||||
|
setlength(SectionHeaders,ElfHeader.e_shnum);
|
||||||
|
SectionHeaderOffset:=ElfHeader.e_shoff;
|
||||||
|
Stream.Position:=SectionHeaderOffset;
|
||||||
|
|
||||||
|
for i:=0 to ElfHeader.e_shnum-1 do
|
||||||
|
begin
|
||||||
|
Stream.Read(SectionHeaders[i],sizeof(TElf32sechdr));
|
||||||
|
end;
|
||||||
|
|
||||||
|
DoVerbose(SCheckingHeaderTable);
|
||||||
|
|
||||||
|
// Get the section header strtab
|
||||||
|
i:=ElfHeader.e_shstrndx;
|
||||||
|
if SectionHeaders[i].sh_type=SHT_STRTAB then
|
||||||
|
begin
|
||||||
|
DoVerbose(SStrTabFound);
|
||||||
|
// read the strtab
|
||||||
|
Stream.Position:=SectionHeaders[i].sh_offset;
|
||||||
|
setlength(strtab,SectionHeaders[i].sh_size);
|
||||||
|
Stream.Read(strtab[1],SectionHeaders[i].sh_size);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
writeln('Error: Unable to find strtab.');
|
||||||
|
halt(5);
|
||||||
|
end;
|
||||||
|
|
||||||
|
ResPtrsSection:=-1;
|
||||||
|
ResourceSectionTable.version:=66;
|
||||||
|
|
||||||
|
// Next cycle through all sections to gather pointers to all the resource
|
||||||
|
// sections, and note the index of the resptrs section
|
||||||
|
for i:=0 to ElfHeader.e_shnum-1 do
|
||||||
|
begin
|
||||||
|
SectionName:=copy(strtab,SectionHeaders[i].sh_name+1,32);
|
||||||
|
SectionName:=copy(SectionName,1,pos(#0,SectionName)-1);
|
||||||
|
DoVerbose(SProcessingSection+SectionName);
|
||||||
|
sn:=Copy(SectionName,1,4);
|
||||||
|
// FPC section ?
|
||||||
|
if (sn='fpc.') then
|
||||||
|
begin
|
||||||
|
sn:=SectionName;
|
||||||
|
Delete(SN,1,4);
|
||||||
|
if SN='resptrs' then
|
||||||
|
begin
|
||||||
|
ResPtrsSection:=i;
|
||||||
|
end
|
||||||
|
else if sn='ressym' then
|
||||||
|
begin
|
||||||
|
ResourceSectionTable.ressym.ptr:=SectionHeaders[i].sh_addr;
|
||||||
|
ResourceSectionTable.ressym.size:=SectionHeaders[i].sh_size;
|
||||||
|
end
|
||||||
|
else if sn='reshash' then
|
||||||
|
begin
|
||||||
|
ResourceSectionTable.reshash.ptr:=SectionHeaders[i].sh_addr;
|
||||||
|
ResourceSectionTable.reshash.size:=SectionHeaders[i].sh_size;
|
||||||
|
ResourceSectionTable.resentries:=SectionHeaders[i].sh_size DIV sizeof(TELF32ResourceInfo);
|
||||||
|
end
|
||||||
|
else if sn='resdata' then
|
||||||
|
begin
|
||||||
|
ResourceSectionTable.resdata.ptr:=SectionHeaders[i].sh_addr;
|
||||||
|
ResourceSectionTable.resdata.size:=SectionHeaders[i].sh_size;
|
||||||
|
end
|
||||||
|
else if sn='resspare' then
|
||||||
|
begin
|
||||||
|
ResourceSectionTable.resspare.ptr:=SectionHeaders[i].sh_addr;
|
||||||
|
ResourceSectionTable.resspare.size:=SectionHeaders[i].sh_size;
|
||||||
|
end
|
||||||
|
else if SectionName='resstr' then
|
||||||
|
begin
|
||||||
|
ResourceSectionTable.resstr.ptr:=SectionHeaders[i].sh_addr;
|
||||||
|
ResourceSectionTable.resstr.size:=SectionHeaders[i].sh_size;
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Ok, we now have pointers to all resource sections and also
|
||||||
|
// know the number of resources.
|
||||||
|
// Now update the resptrs table
|
||||||
|
if ResPtrsSection>-1 then
|
||||||
|
begin
|
||||||
|
Doverbose(SUpdatingResPtrs);
|
||||||
|
Stream.Position:=SectionHeaders[ResPtrsSection].sh_offset;
|
||||||
|
Stream.Write(ResourceSectionTable,sizeof(TELF32ResourceSectionTable));
|
||||||
|
fixed:=true;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
DoError(SErrREsptrsNotFound);
|
||||||
|
if fixed then
|
||||||
|
DoVerbose(SFileFixed)
|
||||||
|
else
|
||||||
|
writeln(SNothingToFix);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TElf64ResourceFixer }
|
||||||
|
|
||||||
|
procedure TElf64ResourceFixer.DoFixStream(Stream: TStream);
|
||||||
|
begin
|
||||||
|
DoError('64-bit resources not yet supported');
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
||||||
171
utils/fpcres/fpcres.lpi
Normal file
171
utils/fpcres/fpcres.lpi
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<CONFIG>
|
||||||
|
<ProjectOptions>
|
||||||
|
<PathDelim Value="/"/>
|
||||||
|
<Version Value="5"/>
|
||||||
|
<General>
|
||||||
|
<Flags>
|
||||||
|
<MainUnitHasUsesSectionForAllUnits Value="False"/>
|
||||||
|
<MainUnitHasCreateFormStatements Value="False"/>
|
||||||
|
<MainUnitHasTitleStatement Value="False"/>
|
||||||
|
</Flags>
|
||||||
|
<MainUnit Value="0"/>
|
||||||
|
<ActiveEditorIndexAtStart Value="0"/>
|
||||||
|
<IconPath Value="./"/>
|
||||||
|
<TargetFileExt Value=""/>
|
||||||
|
</General>
|
||||||
|
<JumpHistory Count="18" HistoryIndex="17">
|
||||||
|
<Position1>
|
||||||
|
<Filename Value="fpcres.pas"/>
|
||||||
|
<Caret Line="175" Column="14" TopLine="138"/>
|
||||||
|
</Position1>
|
||||||
|
<Position2>
|
||||||
|
<Filename Value="fpcres.pas"/>
|
||||||
|
<Caret Line="144" Column="11" TopLine="122"/>
|
||||||
|
</Position2>
|
||||||
|
<Position3>
|
||||||
|
<Filename Value="fpcres.pas"/>
|
||||||
|
<Caret Line="143" Column="5" TopLine="122"/>
|
||||||
|
</Position3>
|
||||||
|
<Position4>
|
||||||
|
<Filename Value="fpcres.pas"/>
|
||||||
|
<Caret Line="148" Column="29" TopLine="126"/>
|
||||||
|
</Position4>
|
||||||
|
<Position5>
|
||||||
|
<Filename Value="fpcres.pas"/>
|
||||||
|
<Caret Line="152" Column="5" TopLine="130"/>
|
||||||
|
</Position5>
|
||||||
|
<Position6>
|
||||||
|
<Filename Value="fpcres.pas"/>
|
||||||
|
<Caret Line="162" Column="8" TopLine="140"/>
|
||||||
|
</Position6>
|
||||||
|
<Position7>
|
||||||
|
<Filename Value="fpcres.pas"/>
|
||||||
|
<Caret Line="162" Column="8" TopLine="140"/>
|
||||||
|
</Position7>
|
||||||
|
<Position8>
|
||||||
|
<Filename Value="fpcres.pas"/>
|
||||||
|
<Caret Line="163" Column="3" TopLine="141"/>
|
||||||
|
</Position8>
|
||||||
|
<Position9>
|
||||||
|
<Filename Value="fpcres.pas"/>
|
||||||
|
<Caret Line="162" Column="34" TopLine="141"/>
|
||||||
|
</Position9>
|
||||||
|
<Position10>
|
||||||
|
<Filename Value="fpcres.pas"/>
|
||||||
|
<Caret Line="170" Column="25" TopLine="148"/>
|
||||||
|
</Position10>
|
||||||
|
<Position11>
|
||||||
|
<Filename Value="fpcres.pas"/>
|
||||||
|
<Caret Line="170" Column="25" TopLine="148"/>
|
||||||
|
</Position11>
|
||||||
|
<Position12>
|
||||||
|
<Filename Value="fpcres.pas"/>
|
||||||
|
<Caret Line="170" Column="25" TopLine="148"/>
|
||||||
|
</Position12>
|
||||||
|
<Position13>
|
||||||
|
<Filename Value="fpcres.pas"/>
|
||||||
|
<Caret Line="148" Column="17" TopLine="148"/>
|
||||||
|
</Position13>
|
||||||
|
<Position14>
|
||||||
|
<Filename Value="fpcres.pas"/>
|
||||||
|
<Caret Line="67" Column="16" TopLine="67"/>
|
||||||
|
</Position14>
|
||||||
|
<Position15>
|
||||||
|
<Filename Value="fpcres.pas"/>
|
||||||
|
<Caret Line="70" Column="1" TopLine="28"/>
|
||||||
|
</Position15>
|
||||||
|
<Position16>
|
||||||
|
<Filename Value="fpcres.pas"/>
|
||||||
|
<Caret Line="233" Column="27" TopLine="190"/>
|
||||||
|
</Position16>
|
||||||
|
<Position17>
|
||||||
|
<Filename Value="fpcres.pas"/>
|
||||||
|
<Caret Line="143" Column="5" TopLine="121"/>
|
||||||
|
</Position17>
|
||||||
|
<Position18>
|
||||||
|
<Filename Value="fpcres.pas"/>
|
||||||
|
<Caret Line="137" Column="1" TopLine="137"/>
|
||||||
|
</Position18>
|
||||||
|
</JumpHistory>
|
||||||
|
<Units Count="5">
|
||||||
|
<Unit0>
|
||||||
|
<CursorPos X="18" Y="4"/>
|
||||||
|
<EditorIndex Value="0"/>
|
||||||
|
<Filename Value="fpcres.pas"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
<Loaded Value="True"/>
|
||||||
|
<TopLine Value="1"/>
|
||||||
|
<UnitName Value="fpcres"/>
|
||||||
|
<UsageCount Value="32"/>
|
||||||
|
</Unit0>
|
||||||
|
<Unit1>
|
||||||
|
<CursorPos X="1" Y="235"/>
|
||||||
|
<EditorIndex Value="1"/>
|
||||||
|
<Filename Value="elfres.pas"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
<Loaded Value="True"/>
|
||||||
|
<TopLine Value="206"/>
|
||||||
|
<UnitName Value="elfres"/>
|
||||||
|
<UsageCount Value="32"/>
|
||||||
|
</Unit1>
|
||||||
|
<Unit2>
|
||||||
|
<CursorPos X="1" Y="1"/>
|
||||||
|
<Filename Value="/home/michael/cmdline.pp"/>
|
||||||
|
<TopLine Value="1"/>
|
||||||
|
<UsageCount Value="10"/>
|
||||||
|
</Unit2>
|
||||||
|
<Unit3>
|
||||||
|
<CursorPos X="1" Y="1"/>
|
||||||
|
<EditorIndex Value="3"/>
|
||||||
|
<Filename Value="elfbfd.pas"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
<Loaded Value="True"/>
|
||||||
|
<TopLine Value="1"/>
|
||||||
|
<UnitName Value="elfbfd"/>
|
||||||
|
<UsageCount Value="25"/>
|
||||||
|
</Unit3>
|
||||||
|
<Unit4>
|
||||||
|
<CursorPos X="1" Y="121"/>
|
||||||
|
<EditorIndex Value="2"/>
|
||||||
|
<Filename Value="elfresfix.pas"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
<Loaded Value="True"/>
|
||||||
|
<TopLine Value="109"/>
|
||||||
|
<UnitName Value="elfresfix"/>
|
||||||
|
<UsageCount Value="25"/>
|
||||||
|
</Unit4>
|
||||||
|
</Units>
|
||||||
|
<PublishOptions>
|
||||||
|
<Version Value="2"/>
|
||||||
|
<IgnoreBinaries Value="False"/>
|
||||||
|
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
|
||||||
|
<ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
|
||||||
|
</PublishOptions>
|
||||||
|
<RunParams>
|
||||||
|
<local>
|
||||||
|
<FormatVersion Value="1"/>
|
||||||
|
<LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
|
||||||
|
</local>
|
||||||
|
</RunParams>
|
||||||
|
</ProjectOptions>
|
||||||
|
<CompilerOptions>
|
||||||
|
<Version Value="5"/>
|
||||||
|
<CodeGeneration>
|
||||||
|
<Generate Value="Faster"/>
|
||||||
|
</CodeGeneration>
|
||||||
|
<Other>
|
||||||
|
<CompilerPath Value="$(CompPath)"/>
|
||||||
|
</Other>
|
||||||
|
</CompilerOptions>
|
||||||
|
<Debugging>
|
||||||
|
<Exceptions Count="2">
|
||||||
|
<Item1>
|
||||||
|
<Name Value="ECodetoolError"/>
|
||||||
|
</Item1>
|
||||||
|
<Item2>
|
||||||
|
<Name Value="EFOpenError"/>
|
||||||
|
</Item2>
|
||||||
|
</Exceptions>
|
||||||
|
</Debugging>
|
||||||
|
</CONFIG>
|
||||||
277
utils/fpcres/fpcres.pas
Normal file
277
utils/fpcres/fpcres.pas
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
{$ifdef fpc}
|
||||||
|
{$mode objfpc}
|
||||||
|
{$endif}
|
||||||
|
{$apptype console}
|
||||||
|
{$H+}
|
||||||
|
program fpcres;
|
||||||
|
|
||||||
|
uses
|
||||||
|
Classes, SysUtils, elfres, elfresfix;
|
||||||
|
|
||||||
|
resourcestring
|
||||||
|
SError = 'Error:';
|
||||||
|
SErrUnknownParam = 'Unknown command-line parameter : %s';
|
||||||
|
SErrNeedArgument = 'Option at pos %d (%s) needs an argument.';
|
||||||
|
SErrNoInputFile = 'No input filename was specified';
|
||||||
|
SErrNoOutputFile = 'Outputfile is not allowed when multiple input files are given';
|
||||||
|
SErrOutputFileIllegal = 'Outputfile not allowed when fixing headers.';
|
||||||
|
|
||||||
|
SUsage010 = 'fpcres - Free Pascal Resource to ELF object compiler';
|
||||||
|
SUsage020 = 'Part of the Free Pascal and CrossFPC distributions';
|
||||||
|
SUsage030 = 'Copyright (C) 2005 Simon Kissel';
|
||||||
|
SUsage040 = '--------------------------------------------------------';
|
||||||
|
SUsage050 = 'Usage: fpcres [options] -i inputfile [-i inputfile] [-o outputfile]';
|
||||||
|
SUsage055 = ' where options are one or more of:';
|
||||||
|
SUsage060 = ' -i --input=inputfile';
|
||||||
|
SUsage065 = ' A file in windows .res resource format, ';
|
||||||
|
SUsage070 = ' or a Delphi/Kylix form file in dfm/xfm ';
|
||||||
|
SUsage080 = ' format (binary or text).';
|
||||||
|
SUSage085 = ' More than one inputfile may be specified.';
|
||||||
|
SUsage090 = ' -o --output=outputfile';
|
||||||
|
SUsage095 = ' Name of the object file to generate. If ';
|
||||||
|
SUsage100 = ' omitted, the name of the input file will';
|
||||||
|
SUsage110 = ' be used, with .or as extension.';
|
||||||
|
SUSage115 = ' (not allowed with multiple input files.)';
|
||||||
|
SUsage116 = ' -e --extension=ext';
|
||||||
|
SUsage117 = ' use ext as the extension for output filenames';
|
||||||
|
SUsage120 = ' -h --help show this help message.';
|
||||||
|
SUsage130 = ' -f --fixheader fix resource block header.';
|
||||||
|
SUsage140 = ' -6 --64bit Use 64-bit elf resources.';
|
||||||
|
SUsage150 = ' -v --verbose be verbose.';
|
||||||
|
|
||||||
|
|
||||||
|
Type
|
||||||
|
TRunMode = (rmCreateElfRes,rmFixHeader);
|
||||||
|
|
||||||
|
Var
|
||||||
|
RunMode : TRunMode;
|
||||||
|
InputFiles : TStringList;
|
||||||
|
OutputFileName : String;
|
||||||
|
Use64bit : Boolean;
|
||||||
|
BeVerbose : Boolean;
|
||||||
|
UseExt : String;
|
||||||
|
|
||||||
|
Procedure Usage(ExitStatus : Word);
|
||||||
|
|
||||||
|
begin
|
||||||
|
Writeln(SUsage010);
|
||||||
|
Writeln(SUsage020);
|
||||||
|
Writeln(SUsage030);
|
||||||
|
Writeln(SUsage040);
|
||||||
|
Writeln(SUsage050);
|
||||||
|
Writeln(SUsage055);
|
||||||
|
Writeln(SUsage060);
|
||||||
|
Writeln(SUsage065);
|
||||||
|
Writeln(SUsage070);
|
||||||
|
Writeln(SUsage080);
|
||||||
|
Writeln(SUSage085);
|
||||||
|
Writeln(SUsage090);
|
||||||
|
Writeln(SUsage095);
|
||||||
|
Writeln(SUsage100);
|
||||||
|
Writeln(SUsage110);
|
||||||
|
Writeln(SUSage115);
|
||||||
|
Writeln(SUSage116);
|
||||||
|
Writeln(SUSage117);
|
||||||
|
Writeln(SUsage120);
|
||||||
|
Writeln(SUsage130);
|
||||||
|
Writeln(SUsage140);
|
||||||
|
Writeln(SUsage150);
|
||||||
|
Halt(ExitStatus);
|
||||||
|
end;
|
||||||
|
|
||||||
|
Procedure DoError(Msg : String; Args : Array of const);
|
||||||
|
|
||||||
|
begin
|
||||||
|
Writeln(SError,' ',Format(Msg,Args));
|
||||||
|
Usage(1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
Procedure AnalyzeParams;
|
||||||
|
|
||||||
|
Function CheckOption(Index : Integer;Short,Long : String): Boolean;
|
||||||
|
|
||||||
|
var
|
||||||
|
O : String;
|
||||||
|
|
||||||
|
begin
|
||||||
|
O:=Paramstr(Index);
|
||||||
|
Result:=(O='-'+short) or (copy(O,1,Length(Long)+3)=('--'+long+'='));
|
||||||
|
end;
|
||||||
|
|
||||||
|
Function OptionArg(Var Index : Integer) : String;
|
||||||
|
|
||||||
|
Var
|
||||||
|
P : Integer;
|
||||||
|
|
||||||
|
begin
|
||||||
|
if (Length(ParamStr(Index))>1) and (Paramstr(Index)[2]<>'-') then
|
||||||
|
begin
|
||||||
|
If Index<ParamCount then
|
||||||
|
begin
|
||||||
|
Inc(Index);
|
||||||
|
Result:=Paramstr(Index);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
DoError(SErrNeedArgument,[Index,ParamStr(Index)]);
|
||||||
|
end
|
||||||
|
else If length(ParamStr(Index))>2 then
|
||||||
|
begin
|
||||||
|
P:=Pos('=',Paramstr(Index));
|
||||||
|
If (P=0) then
|
||||||
|
DoError(SErrNeedArgument,[Index,ParamStr(Index)])
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
Result:=Paramstr(Index);
|
||||||
|
Delete(Result,1,P);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Var
|
||||||
|
I : Integer;
|
||||||
|
P : String;
|
||||||
|
|
||||||
|
begin
|
||||||
|
RunMode:=rmCreateElfres;
|
||||||
|
Use64bit:=False;
|
||||||
|
BeVerbose:=False;
|
||||||
|
I:=0;
|
||||||
|
While (I<ParamCount) do
|
||||||
|
begin
|
||||||
|
Inc(I);
|
||||||
|
// Values.
|
||||||
|
If Checkoption(I,'o','output') then
|
||||||
|
OutPutFileName:=OptionArg(I)
|
||||||
|
else if Checkoption(I,'i','input') then
|
||||||
|
InputFiles.Add(OptionArg(I))
|
||||||
|
else If Checkoption(I,'e','extension') then
|
||||||
|
UseExt:=OptionArg(I)
|
||||||
|
else if CheckOption(I,'f','fixheader') then
|
||||||
|
RunMode:=rmFixHeader
|
||||||
|
else if CheckOption(I,'6','64bit') then
|
||||||
|
Use64bit:=True
|
||||||
|
else if CheckOption(I,'h','help') then
|
||||||
|
Usage(0)
|
||||||
|
else if CheckOption(I,'v','verbose') then
|
||||||
|
BeVerbose:=True
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
P:=ParamStr(I);
|
||||||
|
if (Length(P)>0) and (P[1]<>'-') then
|
||||||
|
begin
|
||||||
|
if (I=ParamCount) then
|
||||||
|
OutputFileName:=P
|
||||||
|
else
|
||||||
|
InputFiles.Add(P)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
DoError(SErrUnknownParam,[P]);
|
||||||
|
Usage(1);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
If (InputFiles.Count=0) then
|
||||||
|
DoError(SErrNoInputFile,[]);
|
||||||
|
If (InputFiles.Count>1) and (OutputFileName<>'') then
|
||||||
|
DoError(SErrNoOutputFile,[]);
|
||||||
|
If (RunMode=rmFixHeader) and (OutputFileName<>'') then
|
||||||
|
DoError(SErrOutputFileIllegal,[])
|
||||||
|
end;
|
||||||
|
|
||||||
|
Type
|
||||||
|
TLogger = Class(TObject)
|
||||||
|
Procedure Log(Const Msg : String);
|
||||||
|
end;
|
||||||
|
|
||||||
|
Procedure TLogger.Log(Const Msg : string);
|
||||||
|
|
||||||
|
begin
|
||||||
|
Writeln(Msg);
|
||||||
|
end;
|
||||||
|
|
||||||
|
Procedure FixHeader(AFileName : String);
|
||||||
|
|
||||||
|
Var
|
||||||
|
F : TElfResourceFixer;
|
||||||
|
O : TLogger;
|
||||||
|
|
||||||
|
begin
|
||||||
|
if Use64bit then
|
||||||
|
F:=TElf64ResourceFixer.Create
|
||||||
|
else
|
||||||
|
F:=TElf32ResourceFixer.Create;
|
||||||
|
try
|
||||||
|
F.Verbose:=BeVerbose;
|
||||||
|
if BeVerbose then
|
||||||
|
begin
|
||||||
|
O:=TLogger.Create;
|
||||||
|
F.OnVerbose:={$ifdef fpc}@{$endif}O.Log;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
O:=Nil;
|
||||||
|
Try
|
||||||
|
F.FixFile(AFileName);
|
||||||
|
Finally
|
||||||
|
O.Free;
|
||||||
|
end;
|
||||||
|
Finally
|
||||||
|
F.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Procedure CreateRes(AFileName : String);
|
||||||
|
|
||||||
|
Var
|
||||||
|
C : TElfResCreator;
|
||||||
|
|
||||||
|
begin
|
||||||
|
If Use64Bit then
|
||||||
|
C:=TElf64ResCreator.Create
|
||||||
|
else
|
||||||
|
C:=TElf32ResCreator.Create;
|
||||||
|
With C do
|
||||||
|
Try
|
||||||
|
Verbose:=BeVerbose;
|
||||||
|
If (UseExt<>'') then
|
||||||
|
Extension:=UseExt;
|
||||||
|
Convert(AFileName,OutputFileName);
|
||||||
|
Finally
|
||||||
|
Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Procedure Run;
|
||||||
|
|
||||||
|
Var
|
||||||
|
I : Integer;
|
||||||
|
|
||||||
|
begin
|
||||||
|
Try
|
||||||
|
Case RunMode of
|
||||||
|
rmFixHeader:
|
||||||
|
For I:=0 to InputFiles.Count-1 do
|
||||||
|
FixHeader(InputFiles[i]);
|
||||||
|
rmCreateElfRes:
|
||||||
|
For I:=0 to InputFiles.Count-1 do
|
||||||
|
CreateRes(InputFiles[i]);
|
||||||
|
end;
|
||||||
|
except
|
||||||
|
On E : Exception do
|
||||||
|
begin
|
||||||
|
Writeln(SError,' ',E.Message);
|
||||||
|
Halt(1);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
InputFiles:=TStringList.Create;
|
||||||
|
Try
|
||||||
|
AnalyzeParams;
|
||||||
|
Run;
|
||||||
|
Finally
|
||||||
|
FreeAndNil(InputFiles);
|
||||||
|
end;
|
||||||
|
end.
|
||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user