この質問が以前に提起された場合は、ご容赦ください。同様の質問への回答を探しましたが、まだ自分の問題に戸惑っています。だから私はとにかく質問を撃ちます。画像データにはlibexifという C ライブラリを使用しています。Linux デスクトップと MIPS ボードの両方でアプリケーション (このライブラリを使用) を実行しています。特定の画像ファイルの作成時間を取得しようとすると、エラーまたは無効な値が返されました。さらにデバッグすると、この特定の画像ファイルについて、期待どおりにタグ (EXIF_TAG_DATE_TIME) を取得していないことがわかりました。
このライブラリには、いくつかのユーティリティ関数があります。ほとんどの関数は次のように構成されています
int16_t
exif_get_sshort (const unsigned char *buf, ExifByteOrder order)
{
if (!buf) return 0;
switch (order) {
case EXIF_BYTE_ORDER_MOTOROLA:
return ((buf[0] << 8) | buf[1]);
case EXIF_BYTE_ORDER_INTEL:
return ((buf[1] << 8) | buf[0]);
}
/* Won't be reached */
return (0);
}
uint16_t
exif_get_short (const unsigned char *buf, ExifByteOrder order)
{
return (exif_get_sshort (buf, order) & 0xffff);
}
ライブラリは、生データ内のタグの存在を調査しようとすると、呼び出しexif_get_short()
て、返された値を列挙型 (int) の変数に割り当てます。
exif_get_short()
符号なし値 (34687) を返すはずのエラーの場合、負の数 (-30871) が返され、画像データからのタグ抽出全体が台無しになります。
34687 は int16_t の表現可能な最大値の範囲外です。したがって、オーバーフローにつながります。コードにこのわずかな変更を加えると、すべて正常に動作するように見えます
uint16_t
exif_get_short (const unsigned char *buf, ExifByteOrder order)
{
int temp = (exif_get_sshort (buf, order) & 0xffff);
return temp;
}
しかし、これは非常に安定したライブラリであり、かなり長い間使用されているため、ここに何かが欠けているのではないかと思いました。さらに、これはコードが他のユーティリティ関数に対しても構造化される一般的な方法です。例:exif_get_long()
呼び出しますexif_get_slong()
。次に、すべてのユーティリティ関数を変更する必要があります。
私を混乱させているのは、Linuxデスクトップでエラーファイルに対してこのコードを実行すると、問題がなく、元のライブラリコードで問題なく動作することです。これにより、私のデスクトップと MIPS ボードでは、おそらく UINT16_MAX マクロと INT16_MAX マクロの値が異なるのではないかと思いました。しかし、残念ながらそうではありません。どちらも、ボードとデスクトップに同じ値を出力します。このコードが失敗した場合、私のデスクトップでも失敗するはずです。
ここで何が欠けていますか?どんなヒントでも大歓迎です。
編集: exif_get_short() を呼び出すコードは次のようになります。
ExifTag tag;
...
tag = exif_get_short (d + offset + 12 * i, data->priv->order);
switch (tag) {
...
...
タイプ ExifTag は次のとおりです。
typedef enum {
EXIF_TAG_GPS_VERSION_ID = 0x0000,
EXIF_TAG_INTEROPERABILITY_INDEX = 0x0001,
...
...
}ExifTag ;
使用されているクロス コンパイラは mipsisa32r2el-timesys-linux-gnu-gcc です。
CFLAGS = -pipe -mips32r2 -mtune=74kc -mdspr2 -Werror -O3 -Wall -W -D_REENTRANT -fPIC $(DEFINES)
Qt内でlibexifを使用しています-Qt Mediaハブ(実際にはlibexifはQt Mediaハブに付属しています)
EDIT2:いくつかの追加の観察:私は何か奇妙なことを観察しています。印刷ステートメントを exif_get_short() に入れました。帰国直前
printf("return_value %d\n %u\n",exif_get_sshort (buf, order) & 0xffff, exif_get_sshort (buf, order) & 0xffff);
return (exif_get_sshort (buf, order) & 0xffff);
次の o/p が表示されます: return_value 34665 34665
次に、exif_get_short() を呼び出すコードに print ステートメントも挿入しました。
....
tag = exif_get_short (d + offset + 12 * i, data->priv->order);
printf("TAG %d %u\n",tag,tag);
次の o/p が表示されます: TAG -30871 4294936425
EDIT3 : MIPS ボードで撮影した exif_get_short() および exif_get_sshort() のアセンブリ コードの投稿
.file 1 "exif-utils.c"
.section .mdebug.abi32
.previous
.gnu_attribute 4, 1
.abicalls
.text
.align 2
.globl exif_get_sshort
.ent exif_get_sshort
.type exif_get_sshort, @function
exif_get_sshort:
.set nomips16
.frame $sp,0,$31 # vars= 0, regs= 0/0, args= 0, gp= 0
.mask 0x00000000,0
.fmask 0x00000000,0
.set noreorder
.set nomacro
beq $4,$0,$L2
nop
beq $5,$0,$L3
nop
li $2,1 # 0x1
beq $5,$2,$L8
nop
$L2:
j $31
move $2,$0
$L3:
lbu $2,0($4)
lbu $3,1($4)
sll $2,$2,8
or $2,$2,$3
j $31
seh $2,$2
$L8:
lbu $2,1($4)
lbu $3,0($4)
sll $2,$2,8
or $2,$2,$3
j $31
seh $2,$2
.set macro
.set reorder
.end exif_get_sshort
.align 2
.globl exif_get_short
.ent exif_get_short
.type exif_get_short, @function
exif_get_short:
.set nomips16
.frame $sp,0,$31 # vars= 0, regs= 0/0, args= 0, gp= 0
.mask 0x00000000,0
.fmask 0x00000000,0
.set noreorder
.cpload $25
.set nomacro
lw $25,%call16(exif_get_sshort)($28)
jr $25
nop
.set macro
.set reorder
.end exif_get_short
完全を期すために、私の Linux マシンから取得した ASM コード
.file "exif-utils.c"
.text
.p2align 4,,15
.globl exif_get_sshort
.type exif_get_sshort, @function
exif_get_sshort:
.LFB1:
.cfi_startproc
xorl %eax, %eax
testq %rdi, %rdi
je .L2
testl %esi, %esi
jne .L8
movzbl (%rdi), %edx
movzbl 1(%rdi), %eax
sall $8, %edx
orl %edx, %eax
ret
.p2align 4,,10
.p2align 3
.L8:
cmpl $1, %esi
jne .L2
movzbl 1(%rdi), %edx
movzbl (%rdi), %eax
sall $8, %edx
orl %edx, %eax
.L2:
rep
ret
.cfi_endproc
.LFE1:
.size exif_get_sshort, .-exif_get_sshort
.p2align 4,,15
.globl exif_get_short
.type exif_get_short, @function
exif_get_short:
.LFB2:
.cfi_startproc
jmp exif_get_sshort@PLT
.cfi_endproc
.LFE2:
.size exif_get_short, .-exif_get_short
EDIT4:私の最後の更新を願っています:-)コンパイラオプションが-O1に設定されたASMコード
exif_get_short:
.set nomips16
.frame $sp,32,$31 # vars= 0, regs= 1/0, args= 16, gp= 8
.mask 0x80000000,-4
.fmask 0x00000000,0
.set noreorder
.cpload $25
.set nomacro
addiu $sp,$sp,-32
sw $31,28($sp)
.cprestore 16
lw $25,%call16(exif_get_sshort)($28)
jalr $25
nop
lw $28,16($sp)
andi $2,$2,0xffff
lw $31,28($sp)
j $31
addiu $sp,$sp,32
.set macro
.set reorder
.end exif_get_short