2

当社の Android ソフトウェアは、正常に動作している SQLite 用の仮想ファイル システム (VFS) を使用しています。Android 6 (Marshmallow) で使用を開始すると、ftruncate() に渡される大きな負のオフセット、スタック オーバーフロー、データの破損など、あらゆる種類の奇妙なエラーが発生し始めました。readelf(他のツールの中でも)使用して、最終的に問題を追跡しました。によって使用されるインポートの変更libsqlite.so: Lollipop と以前のインポートftruncatemmap、最新のライブラリのインポートftruncate64mmap64。API のバージョンに応じて使用する関数を変更することで、問題を「解決」しました (Marshmallow はバージョン 23 です)。

/*
 * Empirical testing of Tab S2 running Marshmallow revealed the SQLite
 * unix_syscall table uses "ftruncate" and "mmap" as connection points,
 * but the actual functions linked against are the *64 versions.  This
 * leads to stack corruption and all sorts of nasty errors as a result.
 */
if (getApiVersion() >= 23)  // for Marshmallow
{   setUnixSystemCall(NULL, "ftruncate", our_ftruncate64);
    setUnixSystemCall(NULL, "mmap", our_mmap64);
}
else                        // for Lollipop & older
{   setUnixSystemCall(NULL, "ftruncate", our_ftruncate);
    setUnixSystemCall(NULL, "mmap", our_mmap);
}

http://www.sqlite.org/2015/sqlite-amalgamation-3081002.ziphttps://github.com/android/platform_external_sqlite/blob/master/dist/sqlite3.cの両方のソースコードを見ると、Cソース呼び出しは、私たちの方法論ftruncatemmapせいぜい「疑わしい」ものにします。

libsqlite.soimport と useはどのようftruncate64mmap64行われ、ソース コードはftruncateとのみを呼び出しmmapますか? 正しいソース コード リポジトリを参照していませんか? リンクステップで何かが起こっていますか?Marshmallow は、これらの関数の非 64 ビット バージョンのサポートを削除しましたか?

4

1 に答える 1

1

NDK のヘッダーが、OS のビルドに使用されている対応するヘッダーと正確に一致しないことが判明しました。

バイオニック: https://android.googlesource.com/platform/bionic.git/+/marshmallow-release/libc/include

NDK をビルドする方法は次のとおりです: https://android.googlesource.com/platform/ndk/+/marshmallow-release

特に、

https://android.googlesource.com/platform/bionic.git/+/marshmallow-release/libc/include/unistd.h

#if defined(__USE_FILE_OFFSET64)
extern int truncate(const char *, off_t) __RENAME(truncate64);
extern off_t lseek(int, off_t, int) __RENAME(lseek64);
extern ssize_t pread(int, void *, size_t, off_t) __RENAME(pread64);
extern ssize_t pwrite(int, const void *, size_t, off_t) __RENAME(pwrite64);
extern int ftruncate(int, off_t) __RENAME(ftruncate64);

https://android.googlesource.com/platform/bionic.git/+/marshmallow-release/libc/include/sys/mman.hにも同様のマクロがありますmmap- システム ヘッダーの__RENAME() は、システム ヘッダーを使用してビルドされたコードを意味します(例: libc.so) は のみをエクスポートftruncate64し、 はエクスポートしませんftruncate。また、 を呼び出すアプリがftruncateに対してリンクされている場合は、ソース コードが記述された呼び出しではlibc.soなくインポートします。ftruncate64

この魔法がどのように発生するかを調査するためにマクロに飛び込むことはしません__RENAME()でした.製品をドアの外に出そうとするという現実は、ウサギの穴をどれだけ深く掘り下げることができないかを示しています. ただし、これをさらに調査したい場合は、ここから始めてください。

于 2016-08-04T21:42:36.013 に答える