mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-06-01 23:22:40 +02: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/makefile.exm -text
|
||||
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/Makefile 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
|
||||
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
|
||||
UNIXs = linux $(BSDs) solaris qnx
|
||||
LIMIT83fs = go32v2 os2 emx watcom
|
||||
@ -233,7 +233,7 @@ PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages/base $(FPCDIR)/packages/ext
|
||||
override PACKAGE_NAME=utils
|
||||
override PACKAGE_VERSION=2.0.0
|
||||
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
|
||||
ifeq ($(FULL_TARGET),i386-go32v2)
|
||||
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
||||
@ -277,11 +277,8 @@ endif
|
||||
ifeq ($(FULL_TARGET),i386-netwlibc)
|
||||
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
||||
endif
|
||||
ifeq ($(FULL_TARGET),i386-wince)
|
||||
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
||||
endif
|
||||
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
|
||||
ifeq ($(FULL_TARGET),m68k-freebsd)
|
||||
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
|
||||
endif
|
||||
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
|
||||
ifeq ($(FULL_TARGET),powerpc-netbsd)
|
||||
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
|
||||
endif
|
||||
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
|
||||
ifeq ($(FULL_TARGET),sparc-netbsd)
|
||||
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
|
||||
endif
|
||||
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
|
||||
ifeq ($(FULL_TARGET),x86_64-freebsd)
|
||||
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
||||
endif
|
||||
ifeq ($(FULL_TARGET),x86_64-win64)
|
||||
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
||||
endif
|
||||
ifeq ($(FULL_TARGET),arm-linux)
|
||||
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
||||
endif
|
||||
ifeq ($(FULL_TARGET),arm-wince)
|
||||
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc
|
||||
override TARGET_DIRS+=fpcm tply h2pas fprcp dxegen fpdoc fpcres
|
||||
endif
|
||||
ifeq ($(FULL_TARGET),i386-linux)
|
||||
override TARGET_PROGRAMS+=ppdep ptop rstconv data2inc delp bin2obj postw32
|
||||
@ -385,9 +376,6 @@ endif
|
||||
ifeq ($(FULL_TARGET),i386-netwlibc)
|
||||
override TARGET_PROGRAMS+=ppdep ptop rstconv data2inc delp bin2obj postw32
|
||||
endif
|
||||
ifeq ($(FULL_TARGET),i386-wince)
|
||||
override TARGET_PROGRAMS+=ppdep ptop rstconv data2inc delp bin2obj postw32
|
||||
endif
|
||||
ifeq ($(FULL_TARGET),m68k-linux)
|
||||
override TARGET_PROGRAMS+=ppdep ptop rstconv data2inc delp bin2obj postw32
|
||||
endif
|
||||
@ -439,15 +427,9 @@ endif
|
||||
ifeq ($(FULL_TARGET),x86_64-freebsd)
|
||||
override TARGET_PROGRAMS+=ppdep ptop rstconv data2inc delp bin2obj postw32
|
||||
endif
|
||||
ifeq ($(FULL_TARGET),x86_64-win64)
|
||||
override TARGET_PROGRAMS+=ppdep ptop rstconv data2inc delp bin2obj postw32
|
||||
endif
|
||||
ifeq ($(FULL_TARGET),arm-linux)
|
||||
override TARGET_PROGRAMS+=ppdep ptop rstconv data2inc delp bin2obj postw32
|
||||
endif
|
||||
ifeq ($(FULL_TARGET),arm-wince)
|
||||
override TARGET_PROGRAMS+=ppdep ptop rstconv data2inc delp bin2obj postw32
|
||||
endif
|
||||
ifeq ($(FULL_TARGET),i386-linux)
|
||||
override TARGET_RSTS+=rstconv
|
||||
endif
|
||||
@ -493,9 +475,6 @@ endif
|
||||
ifeq ($(FULL_TARGET),i386-netwlibc)
|
||||
override TARGET_RSTS+=rstconv
|
||||
endif
|
||||
ifeq ($(FULL_TARGET),i386-wince)
|
||||
override TARGET_RSTS+=rstconv
|
||||
endif
|
||||
ifeq ($(FULL_TARGET),m68k-linux)
|
||||
override TARGET_RSTS+=rstconv
|
||||
endif
|
||||
@ -547,15 +526,9 @@ endif
|
||||
ifeq ($(FULL_TARGET),x86_64-freebsd)
|
||||
override TARGET_RSTS+=rstconv
|
||||
endif
|
||||
ifeq ($(FULL_TARGET),x86_64-win64)
|
||||
override TARGET_RSTS+=rstconv
|
||||
endif
|
||||
ifeq ($(FULL_TARGET),arm-linux)
|
||||
override TARGET_RSTS+=rstconv
|
||||
endif
|
||||
ifeq ($(FULL_TARGET),arm-wince)
|
||||
override TARGET_RSTS+=rstconv
|
||||
endif
|
||||
ifeq ($(FULL_TARGET),i386-linux)
|
||||
override CLEAN_UNITS+=ptopu
|
||||
endif
|
||||
@ -601,9 +574,6 @@ endif
|
||||
ifeq ($(FULL_TARGET),i386-netwlibc)
|
||||
override CLEAN_UNITS+=ptopu
|
||||
endif
|
||||
ifeq ($(FULL_TARGET),i386-wince)
|
||||
override CLEAN_UNITS+=ptopu
|
||||
endif
|
||||
ifeq ($(FULL_TARGET),m68k-linux)
|
||||
override CLEAN_UNITS+=ptopu
|
||||
endif
|
||||
@ -655,15 +625,9 @@ endif
|
||||
ifeq ($(FULL_TARGET),x86_64-freebsd)
|
||||
override CLEAN_UNITS+=ptopu
|
||||
endif
|
||||
ifeq ($(FULL_TARGET),x86_64-win64)
|
||||
override CLEAN_UNITS+=ptopu
|
||||
endif
|
||||
ifeq ($(FULL_TARGET),arm-linux)
|
||||
override CLEAN_UNITS+=ptopu
|
||||
endif
|
||||
ifeq ($(FULL_TARGET),arm-wince)
|
||||
override CLEAN_UNITS+=ptopu
|
||||
endif
|
||||
override INSTALL_FPCPACKAGE=y
|
||||
ifdef REQUIRE_UNITSDIR
|
||||
override UNITSDIR+=$(REQUIRE_UNITSDIR)
|
||||
@ -1562,14 +1526,6 @@ REQUIRE_PACKAGES_PASJPEG=1
|
||||
REQUIRE_PACKAGES_NETDB=1
|
||||
REQUIRE_PACKAGES_LIBASYNC=1
|
||||
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)
|
||||
REQUIRE_PACKAGES_RTL=1
|
||||
REQUIRE_PACKAGES_PASZLIB=1
|
||||
@ -1757,14 +1713,6 @@ REQUIRE_PACKAGES_POSTGRES=1
|
||||
REQUIRE_PACKAGES_MYSQL=1
|
||||
REQUIRE_PACKAGES_SQLITE=1
|
||||
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)
|
||||
REQUIRE_PACKAGES_RTL=1
|
||||
REQUIRE_PACKAGES_PASZLIB=1
|
||||
@ -1778,14 +1726,6 @@ REQUIRE_PACKAGES_POSTGRES=1
|
||||
REQUIRE_PACKAGES_MYSQL=1
|
||||
REQUIRE_PACKAGES_SQLITE=1
|
||||
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
|
||||
PACKAGEDIR_RTL:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /rtl/Makefile.fpc,$(PACKAGESDIR))))))
|
||||
ifneq ($(PACKAGEDIR_RTL),)
|
||||
@ -2121,7 +2061,7 @@ else
|
||||
FPCCPUOPT:=
|
||||
endif
|
||||
endif
|
||||
override FPCOPT+=-Ur -Xs $(FPCCPUOPT) -n
|
||||
override FPCOPT+=-Xs $(FPCCPUOPT) -n
|
||||
override FPCOPTDEF+=RELEASE
|
||||
endif
|
||||
ifdef STRIP
|
||||
@ -2601,6 +2541,7 @@ TARGET_DIRS_H2PAS=1
|
||||
TARGET_DIRS_FPRCP=1
|
||||
TARGET_DIRS_DXEGEN=1
|
||||
TARGET_DIRS_FPDOC=1
|
||||
TARGET_DIRS_FPCRES=1
|
||||
endif
|
||||
ifeq ($(FULL_TARGET),i386-go32v2)
|
||||
TARGET_DIRS_FPCM=1
|
||||
@ -2715,14 +2656,6 @@ TARGET_DIRS_FPRCP=1
|
||||
TARGET_DIRS_DXEGEN=1
|
||||
TARGET_DIRS_FPDOC=1
|
||||
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)
|
||||
TARGET_DIRS_FPCM=1
|
||||
TARGET_DIRS_TPLY=1
|
||||
@ -2730,6 +2663,7 @@ TARGET_DIRS_H2PAS=1
|
||||
TARGET_DIRS_FPRCP=1
|
||||
TARGET_DIRS_DXEGEN=1
|
||||
TARGET_DIRS_FPDOC=1
|
||||
TARGET_DIRS_FPCRES=1
|
||||
endif
|
||||
ifeq ($(FULL_TARGET),m68k-freebsd)
|
||||
TARGET_DIRS_FPCM=1
|
||||
@ -2786,6 +2720,7 @@ TARGET_DIRS_H2PAS=1
|
||||
TARGET_DIRS_FPRCP=1
|
||||
TARGET_DIRS_DXEGEN=1
|
||||
TARGET_DIRS_FPDOC=1
|
||||
TARGET_DIRS_FPCRES=1
|
||||
endif
|
||||
ifeq ($(FULL_TARGET),powerpc-netbsd)
|
||||
TARGET_DIRS_FPCM=1
|
||||
@ -2826,6 +2761,7 @@ TARGET_DIRS_H2PAS=1
|
||||
TARGET_DIRS_FPRCP=1
|
||||
TARGET_DIRS_DXEGEN=1
|
||||
TARGET_DIRS_FPDOC=1
|
||||
TARGET_DIRS_FPCRES=1
|
||||
endif
|
||||
ifeq ($(FULL_TARGET),sparc-netbsd)
|
||||
TARGET_DIRS_FPCM=1
|
||||
@ -2850,6 +2786,7 @@ TARGET_DIRS_H2PAS=1
|
||||
TARGET_DIRS_FPRCP=1
|
||||
TARGET_DIRS_DXEGEN=1
|
||||
TARGET_DIRS_FPDOC=1
|
||||
TARGET_DIRS_FPCRES=1
|
||||
endif
|
||||
ifeq ($(FULL_TARGET),x86_64-freebsd)
|
||||
TARGET_DIRS_FPCM=1
|
||||
@ -2859,14 +2796,6 @@ TARGET_DIRS_FPRCP=1
|
||||
TARGET_DIRS_DXEGEN=1
|
||||
TARGET_DIRS_FPDOC=1
|
||||
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)
|
||||
TARGET_DIRS_FPCM=1
|
||||
TARGET_DIRS_TPLY=1
|
||||
@ -2874,14 +2803,7 @@ TARGET_DIRS_H2PAS=1
|
||||
TARGET_DIRS_FPRCP=1
|
||||
TARGET_DIRS_DXEGEN=1
|
||||
TARGET_DIRS_FPDOC=1
|
||||
endif
|
||||
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
|
||||
TARGET_DIRS_FPCRES=1
|
||||
endif
|
||||
ifdef TARGET_DIRS_FPCM
|
||||
fpcm_all:
|
||||
@ -3153,6 +3075,51 @@ fpdoc:
|
||||
$(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
|
||||
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
|
||||
fpmc_all:
|
||||
$(MAKE) -C fpmc all
|
||||
|
@ -10,6 +10,7 @@ version=2.0.0
|
||||
dirs=fpcm tply h2pas fprcp dxegen fpdoc
|
||||
programs=ppdep ptop rstconv data2inc delp bin2obj postw32
|
||||
dirs_win32=fpmc
|
||||
dirs_linux=fpcres
|
||||
rsts=rstconv
|
||||
|
||||
[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