旧版から引き継いだ従来部分のページ参照に関しては,全箇所をチェックし 誤記をピックアップしました.(2017/10/28)
対象となるのは,以下の3つのファイルです.
cross-gcc494/exec/lib-aarch64-elf.S cross2-gcc494/exec/lib-aarch64-elf.S cross2-gcc494/printf/lib-aarch64-elf.S
上記3つのファイル中にスタートアップがあり,スタックポインタを初期化している 部分があります(以下).ここで _estack の値は .long で定義されており, 32ビット値になっています.しかしAArch64は64ビット・アーキテクチャで スタックポインタも64ビットのため,ここから値をロードしようとしたときに, 後続の4バイトも含めた64ビット値としてロードしてしまい,スタックポインタの 上位32ビット値が不定になってしまうようです.(スタックポインタがとんでもなく 大きな値となり,スタック操作している箇所で動作がおかしくなったりします)
.globl _start .type _start, %function _start: ldr x0, _stack_addr ... .align 4 _stack_addr: .long _estack配布している cross-gcc494-v1.0 のコンパイル済みモジュール(aarch64-elf.x)では, 上記対象となる3つとも,たまたま後続の4バイトがオールゼロになっているため 実害は起きませんが,モジュールを再生成したりすると構成が変化して問題が起きる かもしれません.
正しくは,以下のようにして .quad を使って8バイト値として定義するようにします. (アラインメントも8バイトにします)
.align 8 _stack_addr: .quad _estack
環境によって,ビルド時に以下のエラーが発生します.
../../../../toolchain/gcc-4.9.4/gcc/config/msp430/msp430.c:1632:24: error: unable to find string literal operator 'operator""N' with 'const char [10]', 'unsigned int' arguments #define CSH(N,C,X,G) { "__mspabi_"N, C, X, gen_##G }
上記箇所の #define の定義で,文字列の連結のために文字列リテラルと変数Nが 密着している点がまずいようです.
以下の修正をすることで,ビルド時のエラーを回避できます.
--- gcc/config/msp430/msp430.c.orig 2014-05-21 01:49:40.000000000 +0900 +++ gcc/config/msp430/msp430.c 2018-11-29 00:07:02.843725000 +0900 @@ -1629,7 +1629,11 @@ } const_shift_helpers[] = { +#if 0 #define CSH(N,C,X,G) { "__mspabi_"N, C, X, gen_##G } +#else +#define CSH(N,C,X,G) { "__mspabi_" N, C, X, gen_##G } +#endif CSH ("slli", 1, 1, slli_1), CSH ("slll", 1, 1, slll_1),
対象となるのは,以下の3つのファイルです.
cross-gcc494/exec/lib-msp430-elf.S cross2-gcc494/exec/lib-msp430-elf.S cross2-gcc494/printf/lib-msp430-elf.S
実行開始時にスタックポインタ設定が初期化されておらずゼロとなってしまうため, その後のスタックフレームの獲得によるスタックポインタの減算でゼロで折り返され 0xFFF.. のような値になり,その後にスタックフレームより後のアドレスに アクセスできません.(アドレスの折り返しが起きるため)
以下の修正をすることで,正常に設定されます.
@@ -16,7 +16,7 @@ .globl _start .type _start, @function _start: - mov _estack, r1 + mova #_estack, r1 calla #main
環境によって,ビルド時にエラーが発生します.
error()が未定義の場合があり,リンクエラーとなるようです.
以下の修正をすることで,ビルド時のエラーを回避できます.
--- sim/ppc/gen-idecode.c.orig 2016-08-02 00:50:21.000000000 +0900 +++ sim/ppc/gen-idecode.c 2018-12-02 20:51:40.370107000 +0900 @@ -1521,6 +1521,19 @@ lf_printf(file, "\n"); lf_printf(file, "\n"); +#if 1 + lf_printf(file, "__attribute__((weak)) void error (const char *msg, ...)\n"); + lf_printf(file, "{\n"); + lf_printf(file, " va_list ap;\n"); + lf_printf(file, " va_start(ap, msg);\n"); + lf_printf(file, " vprintf(msg, ap);\n"); + lf_printf(file, " printf(\"\\n\");\n"); + lf_printf(file, " va_end(ap);\n"); + lf_printf(file, " exit (1);\n"); + lf_printf(file, "}\n"); + lf_printf(file, "\n"); +#endif + if ((code & generate_calls)) { print_idecode_lookups(file, table, cache_rules);
対象となるのは,以下の6つのファイルです.
cross-gcc494/exec/lib-arm-elf.S cross2-gcc494/exec/lib-arm-elf.S cross2-gcc494/printf/lib-arm-elf.S cross-gcc494/exec/lib-arm16-elf.S cross2-gcc494/exec/lib-arm16-elf.S cross2-gcc494/printf/lib-arm16-elf.S
GDBシミュレータのread/writeシステムコールの処理で,戻り値が反転されており, 通常は読み込み/書き込みサイズが返るところで,残りサイズが返されています.
システムコール・ラッパーに以下の反転処理を追加することで, 戻り値として読み込み/書き込みサイズ期待を得ることができます.
(lib-arm-elf.S)
SWI(SWI_XXXX) + cmp r0, #0 + subge r0, r2, r0 mov pc, lr
(lib-arm16-elf.S)
SWI(SWI_XXXX) - bx lr + cmp r0, #0 + blt 1f + subs r0, r2, r0 +1: bx lr
対象となるのは,以下の3つのファイルです.
cross-gcc494/exec/lib-m32c-elf.S cross2-gcc494/exec/lib-m32c-elf.S cross2-gcc494/printf/lib-m32c-elf.S
GDBシミュレータのシステムコール処理に合わせて,システムコール呼び出しで0x400 というアドレスに書き込みしていますが,ワードアクセスのために後続の0x401にも 書き込みを行ってしまい,さらに0x401への書き込みは1文字出力として扱われるため, 不正な文字が出力されていました.
システムコール・ラッパーを以下のように修正することで,バイトアクセスとなり 改善されます.
- mov.w:g r0, SYSCALL_ADDR + mov.b:g r0l, SYSCALL_ADDR
対象となるのは,以下の3つのファイルです.
cross-gcc494/exec/lib-mn10300-elf.S cross2-gcc494/exec/lib-mn10300-elf.S cross2-gcc494/printf/lib-mn10300-elf.S
GDBシミュレータでは戻り値はd1レジスタ,エラーコードはd0レジスタで返されますが, 関数の返り値はd0レジスタで返されるため,システムコールの戻り値として エラーコードが返っていました.
以下のようにしてd1→d0へのコピーを追加することで,戻り値が返るようになります.
syscall + mov d1, d0 rets
対象となるのは,以下の3つのファイルです.
cross-gcc494/exec/lib-moxie-elf.S cross2-gcc494/exec/lib-moxie-elf.S cross2-gcc494/printf/lib-moxie-elf.S
GDBシミュレータのシステムコール処理で引数を受け取るレジスタが,関数呼び出しで 引数を渡すレジスタとは異なると判断してレジスタコピーを行っていましたが, GDBシミュレータのシステムコール処理の読み違いで,レジスタコピーは不要で, システムコールの引数が正常に渡されていませんでした.
以下のようにしてレジスタコピーを廃止することで,システムコールの引数が 期待通りに渡されるようになります.
- mov $r4, $r2 - mov $r3, $r1 - mov $r2, $r0 swi SYS_xxxx - mov $r0, $r2 ret
対象となるのは,以下の3つのファイルです.
cross-gcc494/exec/lib-moxie-elf.S cross2-gcc494/exec/lib-moxie-elf.S cross2-gcc494/printf/lib-moxie-elf.S
GDB付属のMoxieシミュレータのopenシステムコールの(おそらく)バグで,ファイル名の コピーとopen()の呼び出しが逆転していて,ファイル名が設定されずにopen()が呼び 出されることで,open()が不定のファイル名で実行されてエラーとなっていました.
苦肉の策として,以下のようにしてopenシステムコールを2回呼び出すことで, 1回目の呼び出しでファイル名が設定され,2回目の呼び出しではスタック上にある ファイル名がそのまま残っているため,open()が期待通りに行われるようになります.
.globl __open .type __open, @function __open: mov $r3, $r0 swi SYS_open mov $r0, $r3 swi SYS_open ret
対象となるのは,以下の3つのファイルです.
cross-gcc494/exec/lib-rx-elf.S cross2-gcc494/exec/lib-rx-elf.S cross2-gcc494/printf/lib-rx-elf.S
GDB付属のRXシミュレータのopenシステムコール処理で,openシステムコールは引数を スタック経由で渡されていたため,引数が正常に受け取れていませんでした.
以下のようにしてopenシステムコールの呼び出し時にスタックに引数を積むことで,open()の引数が期待通りに渡されるようになります.
.globl ___open .type ___open, @function ___open: sub #16, r0 mov.l r2, 4[r0] mov.l r3, 8[r0] mov #SYS_open, r5 int #255 add #16, r0 rts
対象となるのは,以下の3つのファイルです.
cross-gcc494/exec/lib-cr16-elf.S cross2-gcc494/exec/lib-cr16-elf.S cross2-gcc494/printf/lib-cr16-elf.S
スタックポインタの設定を16ビットとして行っているため,実行コードのサイズが 拡大してスタックのアドレスが16ビット範囲(64KB)を越えたときにオーバーフロー してしまい,リンク時にアドレス補填できずリンクエラーとなっていました.
以下のようにしてスタックポインタの設定を32ビットで行うことで回避できます.
.globl _start .type _start, @function _start: - movw $_estack:l, sp + movd $_estack:l, (sp) bal (ra),_main
対象となるのは,以下の1つのファイルです.
cross2-gcc494/printf/Makefile
レジスタウィンドウの利用のために,関数呼び出し時にsave/restore命令が利用されて いますが,libcのライブラリを利用すると関数呼び出しが深くなり, レジスタウィンドウの上限を越えてループしてしまうことで戻り先アドレスが破壊 され,関数呼び出しの呼び元まで戻った際に不正なアドレスにジャンプしていました. (gdb-7.12.1/sim/erc32のPSR_CWPを利用している部分を参照)
Makefileに以下を追加してコンパイル時に -mflat オプションを付加することで, save/restore命令を利用せずにスタック上にレジスタを退避する実行コードが生成 され,回避できます.
CFLAGS-sparc-elf += -mflat
対象となるのは,以下の3つのファイルです.
cross-gcc494/sample/Makefile cross-gcc494/exec/Makefile cross2-gcc494/sample/Makefile cross2-gcc494/exec/Makefile cross2-gcc494/printf/Makefile
gccのビルド環境によって,sample/sample.c:get_static_value_addr()等で アドレス設定にadrp/add命令が使われることがあります (v1.0版に付属するアセンブリ出力では,ldr命令により直後のメモリから ロードしています)
AArch64のコンパイルオプションに,以下のようにして -mcmodel=large を設定する ことでv1.0版に付属する出力相当のコードが生成されます (gcc-4.9.4/gcc/config/aarch64/aarch64-protos.h の SYMBOL_SMALL_ABSOLUTE に 関するコメントと,gcc-4.9.4/gcc/config/aarch64/aarch64.c の SYMBOL_SMALL_ABSOLUTE に関する処理を参照. なお -mcmodel=small で,adrp/add命令を利用するアセンブリが出力されます)
なお未確認ですが,手元で試したところだと, ビルド環境のgccのバージョンがgcc-4.8.x以前とgcc-4.9.x以降で, アセンブリの出力が異なるようです. (gcc-4.8.x以前だと -mcmodel=large 相当, gcc-4.9.x以降だと -mcmodel=small 相当になるようです)
CFLAGS-aarch64-elf += -mcmodel=large
https://gcc.gnu.org/gcc-10/porting_to.html
Default to -fno-common
A common mistake in C is omitting extern when declaring a global variable in a header file. If the header is included by several files it results in multiple definitions of the same variable. In previous GCC versions this error is ignored. GCC 10 defaults to -fno-common, which means a linker error will now be reported. To fix this, use extern in header files when declaring global variables, and ensure each global is defined in exactly one C file. If tentative definitions of particular variables need to be placed in a common block, __attribute__((__common__)) can be used to force that behavior even in code compiled without -fcommon. As a workaround, legacy C code where all tentative definitions should be placed into a common block can be compiled with -fcommon.
int x; // tentative definition - avoid in header files
extern int y; // correct declaration in a header file
コンパイル時のデフォルトが -fno-common になったことにより, gdbのシミュレータ関連のヘッダファイル上で定義されているグローバルシンボル間で 重複定義エラーになるというものです.(本来エラーなのですが,従来はビルドできて いたものが,エラーとなるようになりました)
コンパイル時に -fcommon を付加するか, リンク時に --allow-multiple-definition を付加することで回避できます. (-fcommon を付加するのが,従来と等価の動作になります)
以下が修正パッチです.
patch-gdb-7.12.1-gcc10-fcommon-conf.txt
patch-gdb-7.12.1-gcc10-fcommon-make.txt
https://bugzilla.redhat.com/show_bug.cgi?id=1577396
https://sourceware.org/bugzilla/show_bug.cgi?id=23252
https://sourceware.org/legacy-ml/gdb-patches/2018-05/msg00863.html
_PyImport_FixupBuiltin()という内部関数を使ってしまっていた問題です.
以下が修正パッチです.
patch-gdb-7.12.1-python37-error.txt
以下のファイルの10198,10199行目で不正な文字コードが利用されていたことが 原因でした.
gcc/config/pa/pa.c不正な文字コードを削除することで回避できます.
以下が修正パッチです.
patch-gcc-4.9.4-hppa-wrongcode.txt
src/mul.cの175行目で mpfr_fmma() という関数をstatic定義しファイル内で利用して いますが,システムが持つ /usr/include/mpfr.h が同名の関数を定義している場合に 関数の型の不一致でエラーとなります. (このため,システムにインストールされているmpfrのバージョンによって 発生するようです)
src/mul.cの mpfr_fmma() の関数名を変更することで回避できます.
以下が修正パッチです.
patch-mpc-1.0.3-conflict-mpfr.txt