在smartphone上通过了测试.
sha1.c来自于Christophe Devine, 我把sha1_file包围在ifdef KOL_MCK里面了, 这样我是自己实现Sha1Stream, 对文件流式操作, 而不必使用gcc的stdio.
makefile如下
CC = arm-wince-mingw32ce-gcc
CCOPTS = -c -O3 -s -Os -fomit-frame-pointer -DKOL
all: gcc
gcc: sha1_gcc_coff.o
%_gcc_coff.o: %.c
$(CC) $(CCOPTS) -o $@ $^
.PHONY: all clean
clean:
@rm -f *.o
编译后, 得到sha1_gcc_coff.o, 并编写对应的链接单元sha1obj.pas.
有个诡异的现象是cegcc编译出来的obj, 其名称修饰并没有遵循cdecl的惯例来, 而是默认去掉了一切decoration.
不过按照经验, 还是将exerenal声明为cdecl, 同时实现了sha1stream, 和撰写了给sha1_gcc_coff.o使用的memcpy, memset.
Freepascal for ce的版本有2个,我用的是lazarus的2.2.1, 而FP的是2.2.0.
唯一区别的是因为我需要经常用到Freepascal的x86版, 所以默认的fpc.cfg懒得修改, 就拿lazarus的另放目录来用了.
fpc.cfg的修改, 按照ceport和我所使用的KOLCE的声明判断, 内容如下
-Twince
#Library path
-FuF:/lazarus/fpc/2.2.1/units/arm-wince
-FuF:/lazarus/fpc/2.2.1/units/arm-wince/*
-FuF:/lazarus/fpc/2.2.1/units/arm-wince/rtl
-FuF:/lazarus/fpc/2.2.1/units/arm-wince/kol
-FiF:/lazarus/fpc/2.2.1/units/arm-wince/*
-FiF:/lazarus/fpc/2.2.1/units/arm-wince/kol
-FlF:/lazarus/fpc/2.2.1/units/arm-wince/3rdwork
-FuF:/KOL/3rdWork/MHXP
-FuF:/KOL/3rdWork/Misc
-XParm-wince-
-FDF:/lazarus/fpc/2.2.1/bin/i386-win32
# For a release compile with optimizes and strip debuginfo
#IFDEF RELEASE
-Og1p2
-Xs
#KOL
-Mdelphi
-CX
-Sg
#WRITE Compiling Release Version
#ENDIF
# For a debug version compile with debuginfo and all codegeneration checks on
#IFDEF DEBUG
-gcl
-Crtoi
-Sg
#KOL
-Sa
-Mdelphi
#WRITE Compiling Debug Version
#ENDIF
-l
-viwh
为了不占版面, 删掉了块状注释.
代码是顺便加在PQVGen里面的, 其工程的makefile很短,
CC = ppcrossarm
CCOPTS = -dKOL_MCK -dF_P
all: clean release
debug: Debug/PQVGen.exe
release: Release/PQVGen.exe
RELEASE/PQVGen.exe: PQVGen.dpr
$(CC) $(CCOPTS) -dRELEASE -FERelease $^
clean:
rm -f Release/*.o
rm -f Release/*.ppu
rm -f Release/*.exe
make一下, link不过, 报告找不到memcpy和memset外部符号, 用IDA查看了编译出的sha1obj.pas, 发现其生成的memcpy导出名称被加上了单元名前缀和参数类型作为修饰, 给声明增加名称限定符失败, 在单元内增加exports的重命名失败. 直观的感觉应该单独写一个单元, 设法使用强制不修饰名称的方式link, 再{$LINK}到sha1obj.pas里面, 不过开源项目的缺点又来了, 这个CE版木得文档, 连主分支的文档都没有提到名称修饰的任何信息. 于是使用{$LINKLIB libcoredll.a}的方式, 无耻的将gcc的lib直接拿来加入链接, 一阵咯吱咯吱后, 过鸟.
最在mainunt.pas里面增加了一个点击事件,执行了一条邪恶代码
var
dige: SHA1_DIGEST;
azsd: String;
begin
azsd := 'azsd';
sha1(@azsd[1], Length(azsd), dige);
ShowMessage(Dump2Hex(@dige[0], SizeOf(dige)));
end;
dige: SHA1_DIGEST;
azsd: String;
begin
azsd := 'azsd';
sha1(@azsd[1], Length(azsd), dige);
ShowMessage(Dump2Hex(@dige[0], SizeOf(dige)));
end;
这样如果调用约定的声明错了的话, 点击就会爆掉鸟.
链接后, 拷贝到windows mobile 6的smartphone上, 点击, 华丽的弹出了计算后的熟悉hash, 成功了.
明天得去freepascal的maillist里面询问一下了, 为啥再兼容delphi编译指示字的模式下, 同单元内补充外部引用和dcc的编译器处理方式不一样, 因为问题的表面现象是在整个工程编译时候sha1_gcc_coff.o才加入编译, 导致找不到sha1obj里面的memcpy函数, 其实是在编译sha1obj单元的时候, 没有将sha1_gcc_coff.o静态链接到sha1obj.o里面去, 自然也没有将sha1obj.pas里面为sha1_gcc_coff.o所需要的外部引用添加的实现作内部连接.