objc protocol: invalid pointer in property of protocol list inside binary with gnustep runtime (with lto)

Hello,

I faced with issue when while loading module and registering classes/categories/protocols, some protocol has corrupted fields, and gnustep-libobjc2 doesn’t recognize it.

I’ve used clang 3.9.1 compiler and libobjc2 is based on https://github.com/gnustep/libobjc2.
target is arm-linux-gnueabi

During protocol initialization, initiated from .objc_load_function

I found following protocol in some of our compiled modules:

it’s in isEmptyProtocol

p *p2
$1 = {isa = 0xb1f9ef88 <_OBJC_CLASS_Protocol2>, name = 0xb6e95115 “AVPlayerItemOutputPushDelegate”, protocol_list = 0xb86cf000, instance_methods = 0xb86cf008,
class_methods = 0xb86cf008, optional_instance_methods = 0xb86cf008, optional_class_methods = 0xb86cf008, properties = 0x2, optional_properties = 0xb6f5d65e}

As you can see field properties has value 0x2, sometimes it’s 0xe, sometime 0x1.

To exclude probability of runtime corruption I checked binary disassembler and found 0xe on the
referenced offset.

.data:023B2538 unk_23B2538 DCB 3 ; DATA XREF: .data:023B2528o
.data:023B2539 DCB 0
.data:023B253A DCB 0
.data:023B253B DCB 0
.data:023B253C DCD aAvplayeritemou ; “AVPlayerItemOutputPushDelegate”
.data:023B2540 DCD unk_34B2F70
.data:023B2544 DCD unk_34B2F78
.data:023B2548 DCD unk_34B2F78
.data:023B254C DCD unk_34B2F78
.data:023B2550 DCD unk_34B2F78
.data:023B2554 unk_23B2554 DCB 0xE ; DATA XREF: .data:023B06F0o
.data:023B2555 DCB 0
.data:023B2556 DCB 0
.data:023B2557 DCB 0

So looks like it’s compiler issue, but it appears in that case after applying -flto optimization.
Before that I faced with issue when optional_properties was 0x1, as I know both properties and optional_properties is pointers.

Unfortunately, I don’t have minimal compiled sample for that issue. I tried to search the same issue in bugzilla, but didn’t find something about it.

Hello,

Please can you let me know the precise compiler flags that you specified? This looks as if you have a mixture of GCC and GNUstep ABIs. You said that you’re using LTO: did you ensure that you compiled all Objective-C compilation units with the same ABI?

David

We’re using clang as compiler and ld.gold (from binutils 2.27) as linker.

Compiler options for library side where protocol declared are following:

/usr/bin/clang -O2 -pipe -Wall -fexceptions -fstack-protector --param=ssp-buffer-size=4 -Wformat -Wformat-security -fmessage-length=0 -march=armv7-a -mtune=cortex-a8 -mfpu=vfpv3 -mfloat-abi=softfp -D__SOFTFP__ -mthumb -flto -O2 -ffixed-r9 -pthread -D_REENTRANT -DGST_EXT_EXIF_MODIFICATION -D__MMFILE_DYN_LOADING__ -Wall -fPIC -fconstant-string-class=NSConstantString -Wimplicit-function-declaration -fobjc-runtime=gnustep -fobjc-arc -fblocks -mfpu=neon-vfpv3 -mfloat-abi=softfp -fvisibility=hidden -Os -D _GNU_SOURCE -D LINUX -D GCC_RUNTIME_3 -D LITTLE_ENDIAN -D FORTIFY_SOURCE -D OPENSSL_NO_SSL2 -D BLOCKS -D OS_OBJECT_USE_OBJC __ -Wno-nullability-completeness -Wall -Werror -o CMakeFiles/AVFoundation.dir/Sources/AVPlayerItemOutput.m.o -c /home/abuild/rpmbuild/BUILD/motte-1.0.0/Frameworks/AVFoundation/Sources/AVPlayerItemOutput.m

for application part.

-D__IPHONE_OS_VERSION_MIN_REQUIRED=__IPHONE_7_0
-integrated-as
-fconstant-string-class=NSConstantString
-fobjc-runtime=gnustep
-ObjC
-D_DEFAULT_SOURCE
-DLIBBSD_OVERLAY
-D__extern_always_inline=inline
-D_XOPEN_SOURCE=700
-Dtypeof=typeof
-DNS_BLOCKS_AVAILABLE
-DTARGET_OS_IPHONE
-D_GCC_NEXT_LIMITS_H
-DOS_OBJECT_HAVE_OBJC_SUPPORT=1
-fdata-sections
-ffunction-sections
-fstack-protector
–param=ssp-buffer-size=8
-Wno-nullability-completeness
-Wall
-fstrict-aliasing
-std=c99
-fasm-blocks
-Wnon-modular-include-in-framework-module
-Werror=non-modular-include-in-framework-module
-fmodules
-fno-autolink
-fobjc-exceptions
-fno-objc-arc
-fblocks
-Wswitch
-Wdeprecated-declarations
-fmessage-length=0
-ferror-limit=0
-target arm-linux-gnueabi
-gcc-toolchain /Users/sdk/tools/smart-build-interface/…/arm-linux-gnueabi-gcc-4.9/
-ccc-gcc-name arm-linux-gnueabi-g++
-march=armv7-a
-mfloat-abi=softfp
-mfpu=vfpv3-d16
-mtune=cortex-a8
-Wno-gnu
–sysroot=“/Users/sdk/tools/smart-build-interface/…/…/platforms/mobile/rootstraps/mobile-2.4-device.core”
-mthumb
-fPIC
-Os
-ffixed-r9
-fvisibility=hidden
-flto

and linker options:

-Xlinker -lstdc++ -Xlinker -ObjC -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -mtune=cortex-a8 -Xlinker --as-needed -lpthread
-Werror-implicit-function-declaration
-Wl,–gc-sections
-Xlinker -rpath=“/opt/usr/apps/XY/lib”
-march=armv7-a
-mfloat-abi=softfp
-mfpu=vfpv3-d16
-mtune=cortex-a8
-Xlinker --as-needed
-Wl,-wrap=sysctl

I omitted -L and -I as no important here;

I link objects of libraries and application into one binary. I don’t use static library for cocotron/chameleon parts,

due to issue with categories which are missed if they’r alone in linkage module.

and before link I’ve checked:

find Distribution\ -\ Production/ -name “*.o” -exec file {} +

and all objects are

LLVM IR bitcode

But in general you’re right I have 2 kind of object (IR BC) files, one part was compiled in chroot (x86 i586) and

another part was compiled in MacOS X. But it’s the same version of the same compiler, given by the same commit id and built (not downloaded from public domain).

BR,

Alexey

It’s probably worth specifying a version, otherwise it will default to the most compatible version. For ARM, you’ll probably want to use -fobjc-runtime=gnustep-1.8. Let me know if that makes a difference.

Does this only occur when you’re using LTO? I seem to recall that we were not emitting sufficient alignment information on some of the structs, which occasionally meant that the linker would align them incorrectly, but I thought that was fixed...

David