- Old Android version (4.4 on my side) didn’t look for shared library by SONAME inside. It only checks file name. For example, in recent Android version (7 or 8), one file named
libcrypto.sowhose SONAME is
libcrypto.so.1.0.0can be loaded by dependents successfully. But in old versions the system reported “dlopen failed to load libcrypto.so.1.0.0”.
- In Linux’s programming conventions, a shared library usually has name like
libxxxx.so.x.y.zand a symbolic link named
libxxxx.sowould also be created pointing to the former. That’s OK in a normal Linux system, but has problems with Android’s app. The android apk’s zip format didn’t recognize symbolic link, and as I described in 1. it also didn’t load shared library by SONAME.
- Android Studio integrated CMake to build native libraries and it also packs what generated by CMake
libsdirectory inside the apk. That’s good. But! But it packs only files with .so extension. So, files like
libxxxx.so.x.y.zwould be packed into the apk, and we don’t have any configurable option on both
CMakefile.txtto add them manually.
Long in short, after upgraded to Android Studio 3.0, symbols from aar binary modules cannot be resolved in IDE, although the building/make is successful. Clean or Rebuild project is useless.
Two steps solution:
- Change line
- Select ‘Invalidate Caches / Restart‘ from File menu.
That is, if a 32bit DLL was loaded by
CreateRemoteThread(), the DLL would be unloaded silently without
DLL_PROCESS_DETACH invocation sent to
DLLMain() of the DLL. There are indeed 2 weird issues, one is silent unloading, the other is no
This occurs on WOW64 environment of Windows 2008 Server R2 only. Windows 2012 and 2016 don’t have this issue, while x64 environment of 2008 also doesn’t have the issue.
To fix it, we can make the DLL depend on another DLL. The 2nd DLL can receive all notification callbacks of
DLLMain(). This way can fix the callback issue. And by adding an extra
LoadLibrary() call of 2nd DLL in 1st DLL’s
DLL_PROCESS_ATTACH notification, we can keep the 2nd DLL in memory even if 1st DLL unloaded silently.
If you happen see a lot of port failed to build and error is about clock_gettime or even u_int, it is because some definition are in platform SDK instead /usr/**/*.h
Here is the trick:
Maybe /opt/local/etc/macports.conf is the right place to config it, but I have not found the key yet.
In short, ffmpeg changes its API in recent versions. One of them is marking
AVStream.codec as deprecated. On other side, a AVCodecParameters
* AVStream.codecpar was added for codec information described in the stream. To decode data read from stream correctly, we must create a
avcodec_alloc_context3(), copy codec information from
AVStream.codecpar to this allocated
AVCodecContext, and call
avcodec_open2() to assign this
AVCodec found by
Here is the point. We must call
avcodec_parameters_to_context() to copy codec information to
AVCodecContext before we call
avcodec_open2() to assign
AVCodec. If we incorrectly reversed this order, say, called
avcodec_parameters_to_context(), we can still decode many videos correctly, but we will encounter strange behavior when we try to play back .mkv or .mp4 files – Each call to decoding function will fail.
if [ "$CONFIGURATION" == "Debug" ]; then LIBFFMPEG_DIR="$PROJECT_DIR/../../ffmpeg/ios/universal/debug" else LIBFFMPEG_DIR="$PROJECT_DIR/../../ffmpeg/ios/universal/release" fi for a in $ARCHS; do EXTRACT_ARCHS="$EXTRACT_ARCHS -extract $a" done lipo "$LIBFFMPEG_DIR/lib/libffmpeg.dylib" $EXTRACT_ARCHS -output "$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/libffmpeg.dylib" if [ "$CODE_SIGNING_REQUIRED" == "YES" ]; then codesign -s "$EXPANDED_CODE_SIGN_IDENTITY" "$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/libffmpeg.dylib" fi install_name_tool -change "libffmpeg.dylib" "@executable_path/libffmpeg.dylib" "$BUILT_PRODUCTS_DIR/$EXECUTABLE_PATH"
Simply, clang has an option
'--no-integrated-as' so that the compiler invokes apple’s standalone
'as' assembler instead of using clang’s built-in. But, either has its own lost pieces.
'--no-integrated-as', clang would use its internal assembler. Unfortunately it doesn’t recognize the mnemonic
'as’ assembler reports an error in pesudo instruction
'.ios_version_min', which was apparently generated by clang itself.
Therefore I have no choice except for changing
'ldmltfd' to two simple instructions…
Passing file descriptors through unix domain socket is well-known. But there still have some tricks in implementation. I spent one day to deal with it in Mac OS X by digging into xnu source.
- How to pass multiple file descriptors in one
Simple. Put all file descriptors one by one after
- Can I put multiple
structcmsghdrs with data? I noticed there are
No. In xnu sources it checks
cmsghdr.cmsg_len. If they are not equal, a
-EINVALreturned in sendmsg
()call. That means only one cmsghdr can be put into msghdr.
The limitation is in OS X only. I haven’t check Linux and would do it soon or later.
Session 406 of WWDC 2016 is great! It explains clearly how the iOS application is settled in memory before running, with ASLR and code-signing. The key point is the indirect pointers in __DATA avoid patching the __TEXT, which is required by ASLR but impossible because of code-signing.
There is this one point confusing me, __TEXT still needs to encode address pointing to __DATA segment, though __DATA page address is randomised now.
The answer is quite simple indeed: the offset between __TEXT and __DATA is not changing between runs, the offset is encoded in __TEXT.
In 64bit Mac OS X, it implements as:
movl 0xae(%rip), %edi
iOS ARMv7 generates:
0000bf9c f240037c movw r3, #0x7c 0000bfa0 f2c00300 movt r3, #0x0 0000bfa4 447b add r3, pc ;$pc(0xbfa8) + 0x7c -> global_var in __DATA
iOS ARMv8 (64) generates:
0000000100007f2c adrp x8, 1 ; 0x100007000 + 4k*1 0000000100007f30 add x8, x8, #64 ; +0x40 -> 0x100008040 ;-> global_var in __DATA * adrp xd label mask out lower 12bits of pc then add label<<12 to generate an address.
Mac OS X El Capitan, MacPorts, it goes well for so long. And one day, git complains:
curl: (77) error setting certificate verify locations: CAfile: /opt/local/share/curl/curl-ca-bundle.crt CApath: none
Easy, update git config system to use ca-bundle.crt found by searching.
[http] sslcainfo = /opt/local/share/apps/kssl/ca-bundle.crt
But, curl itself still complains:
curl --cacert /opt/local/share/apps/kssl/ca-bundle.crt ...
Problem solved again.
But, it is hard to bear the burden of adding such a long argument!
Why did curl ask for the damn file not existed?
curl-config --ca /opt/local/share/curl/curl-ca-bundle.crt
OK, it seems that’s the value coded in the source. Fortunately, the command will check CURL_CA_BUNDLE environment variable.
Patch the ~/.profile (or .bashrc for bash, .zshrc for zsh…)
The problem is really resolved.