Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

segmentation fault on json-c parsing methods in cross compiled target #705

Closed
ausmauricio opened this issue May 4, 2021 · 10 comments
Closed

Comments

@ausmauricio
Copy link

Hi,

I'm trying to embed our software which uses json-c on a MIPS 32 target. Methods to build JSON such as json_object_new_object() work fine but parsing with for example json_tokener_parse() seg faults in this target. I think there is a problem with our cross-compilation because it works on other platforms, so any help here is much appreciated.

To simplify things I'm focusing on the app provided json_parse, which also seg faults, so I'm thinking if json_parse works so will our code. On the target:

[root@AONT: home]# ./json_parse jsonsample
maxrss: 304 KB
Segmentation fault (core dumped)

From what I understood running the same thing on my machine the output should be something like this:

$ ./json_parse jsonsample
maxrss: 2756 KB
Successfully parsed object from jsonsample
[ jsonsample content here ]
maxrss: 2756 KB
maxrss: 2756 KB

file utility output on the target:

$ file json_parse
json_parse: ELF 32-bit MSB executable, MIPS, MIPS32 version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, with debug_info, not stripped

I'm building for the target from the master specifying this toolchain file:

root@e318088542a9:/usr/src# cat toolchainfile.cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_C_COMPILER /opt/toolchains/crosstools-mips-gcc-4.6-linux-3.4-uclibc-0.9.32-binutils-2.21/usr/bin/mips-unknown-linux-uclibc-gcc)
set(CMAKE_CXX_COMPILER /opt/toolchains/crosstools-mips-gcc-4.6-linux-3.4-uclibc-0.9.32-binutils-2.21/usr/bin/mips-unknown-linux-uclibc-g++)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -lm -Os -pipe -Os -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64" CACHE STRING "Buildroot CFLAGS" FORCE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -lm -Os -pipe -Os -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64" CACHE STRING "Buildroot CXXFLAGS" FORCE)
set(CMAKE_INSTALL_SO_NO_EXE 0)
set(CMAKE_PROGRAM_PATH "/opt/toolchains/crosstools-mips-gcc-4.6-linux-3.4-uclibc-0.9.32-binutils-2.21/usr/bin")
set(CMAKE_FIND_ROOT_PATH "/opt/toolchains/crosstools-mips-gcc-4.6-linux-3.4-uclibc-0.9.32-binutils-2.21/usr/mips-unknown-linux-uclibc/sysroot")
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(ENV{PKG_CONFIG_SYSROOT_DIR} "/opt/toolchains/crosstools-mips-gcc-4.6-linux-3.4-uclibc-0.9.32-binutils-2.21/usr/mips-unknown-linux-uclibc/sysroot")

So basically I run:

$ cmake -DCMAKE_TOOLCHAIN_FILE="/usr/src/toolchainfile.cmake" ../json-c
on json-c-build folder, and this is the compiler I'm using:

root@e318088542a9:/usr/src# /opt/toolchains/crosstools-mips-gcc-4.6-linux-3.4-uclibc-0.9.32-binutils-2.21/usr/bin/mips-unknown-linux-uclibc-gcc --version
mips-unknown-linux-uclibc-gcc (Buildroot 2011.11) 4.6.2
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Thank you

@hawicz
Copy link
Member

hawicz commented May 4, 2021

It's going to be pretty hard to suggest anything without some more details. Can you load the core dump in a debugger and see where it crashed?

@ausmauricio
Copy link
Author

ausmauricio commented May 4, 2021

Unfortunately, that doesn't show much and I even re-compiled with the -g option.

$ gdb-multiarch -c json_parse-2021-05-04-18-38-01_pid15313_sig11.core.0 json_parse
GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
http://www.gnu.org/software/gdb/bugs/.
Find the GDB manual and other documentation resources online at:
http://www.gnu.org/software/gdb/documentation/.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
json_parse: No such file or directory.
[New LWP 15313]
Core was generated by `./json_parse jsonsample'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x77d6ecf8 in ?? ()
(gdb)

I'm thinking the toolchainfile isn't enough to make CMake find target includes and libs and it's using the systems instead.

@MarcT512
Copy link
Contributor

MarcT512 commented May 4, 2021

GDB didn't show much because it failed to load/locate your compiled json_parse executable (and hence the debug symbols). Probably best to copy the core into the same directory as the executable for now.

json_parse: No such file or directory.

Anyhow, with only one frame apparently on the stack it probably failed quite early.
You may need to re-compile json-c itself in debug mode too.

Good luck!

@ausmauricio
Copy link
Author

Hey thanks for the reply and patience.

Found gdbserver for this arch and trying to use it, still don't know what I am doing with gdb though. Changed the compilation a bit but the error is still the same. But here it is:

Remote device:

$ ./gdbserver 192.168.1.254:2500 json_parse jsonsample
Process json_parse created; pid = 28730
Listening on port 2500
Remote debugging from host 192.168.1.151
maxrss: 284 KB

Child terminated with signal = 0xb (SIGSEGV)
GDBserver exiting

My machine:

$ gdb-multiarch json_parse
GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
http://www.gnu.org/software/gdb/bugs/.
Find the GDB manual and other documentation resources online at:
http://www.gnu.org/software/gdb/documentation/.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from json_parse...done.
(gdb) target remote 192.168.1.254:2500
Remote debugging using 192.168.1.254:2500
Reading /lib/ld-uClibc.so.0 from remote target...
warning: File transfers from remote targets can be slow. Use "set sysroot" to access files locally instead.
Reading /lib/ld-uClibc.so.0 from remote target...
Reading symbols from target:/lib/ld-uClibc.so.0...(no debugging symbols found)...done.
0x779acaf0 in _start () from target:/lib/ld-uClibc.so.0
(gdb) continue
Continuing.
Reading /lib/libm.so.0 from remote target...
Reading /configs/home/newdeps/libjson-c.so.5 from remote target...
Reading /lib/libgcc_s.so.1 from remote target...
Reading /lib/libc.so.0 from remote target...

Program received signal SIGSEGV, Segmentation fault.
0x778bdcf8 in duplocale () from target:/lib/libc.so.0
(gdb) continue
Continuing.

Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.
(gdb)

Seems like the problem is actually in libc from this call?

$ ack duplocale
json_tokener.c
297: locale_t duploc = duplocale(oldlocale);

Thanks

@MarcT512
Copy link
Contributor

MarcT512 commented May 6, 2021

Looks like it crashed in duplocale() as you mentioned.

You could try the patch from FreeBSD in the issue below that should enable an alternate code path in the json-c library:
#668

If that doesn't help, you can probably modify the patch to disable HAVE_SETLOCALE as well. You'll have to be the judge of whether locale support matters for you.

@ausmauricio
Copy link
Author

ausmauricio commented May 7, 2021

Greedily for now I just removed the parts in json_tokener.c that are executed if HAVE_SETLOCALE and HAVE_USELOCALE are set, and json_parse now works and my code as well! Thx

Tbh I don't understand why they are executed in the first place, the patch seems to act on config.h which I guess is after the cmake command, but these variables aren't set here (there is 1 in CMakeCache maybe that's it?):

root@a5bc7e728a2d:/usr/src/json-c-build# ack LOCALE
config.h
30:#define HAVE_LOCALE_H
75:#define HAVE_XLOCALE_H
119:#define HAVE_SETLOCALE
138:#define HAVE_USELOCALE

CMakeCache.txt
108:CMAKE_INSTALL_LOCALEDIR:PATH=
484://ADVANCED property for variable: CMAKE_INSTALL_LOCALEDIR
485:CMAKE_INSTALL_LOCALEDIR-ADVANCED:INTERNAL=1
647:HAVE_LOCALE_H:INTERNAL=1
655:HAVE_SETLOCALE:INTERNAL=1
711:HAVE_USELOCALE:INTERNAL=1
721:HAVE_XLOCALE_H:INTERNAL=1

I'd expect a 1 to follow the define statements on config.h

Let me know if you want something from me such as running the scripts suggested in #668 to check locale behavior.

Thank you

Edit: edited out lines with LOCALE string in json-c/cmake/config.h.in and it works.

@hawicz
Copy link
Member

hawicz commented May 8, 2021

Those variables are set in config.h. It doesn't matter what value those preprocessor variables are set to, just that they're set at all, because they're checked with simple #ifdefs in the code.
It'd be nice to fix the code to work, but it seems that duplocale() is just completely broken on your system. :(
Assuming the ulibc you're using has the same code as https://github.com/ffainelli/uClibc/blob/master/libc/misc/locale/locale.c#L1322, it's pretty clear that it even intentionally crashes on what should be an entirely valid call to duplocale().

The easiest quick patch it probably to comment out the check_include_file lines in CMakeLists.txt that refer to locale.h and xlocale.h. Without the locale handling code you'll need to make sure to run your program in the "C" locale.

As for what change to commit, I think we'll need to have the cmake checks actually run a program that uses duplocale, and see if it works or crashes.

@ausmauricio
Copy link
Author

Awesome thanks! If you want me to run anything let me know.

@hawicz
Copy link
Member

hawicz commented Jul 30, 2022

Actually, we can't run a program that uses duplocale in this case, because you're cross-compiling.
Instead, I'll have cmake check the output of gcc -dumpmachine for "uclibc", and disable locale handling if found.

hawicz added a commit that referenced this issue Jul 30, 2022
… because its duplocale() function (intentionally) crashes.
@hawicz
Copy link
Member

hawicz commented Jul 30, 2022

Commit 253a5fa should address this, please re-open if it doesn't work for you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants