How to CosmoNim (GCC) on Solus Linux? (segfault) - linux

What methods or tools can I use to help figure out the below issue?
I'd like to use CosmoNim on Solus Linux. It works on other linux distributions, but produces executables that segfault when built on Solus Linux. CosmoNim works for me on Ubuntu just fine.
CosmoNim is a Nim wrapper to use Cosmopolitan
Cosmopolitan is a library and method to produce universal binaries built with GCC
Nim is a transpiler to C (auto compiling with GCC)
So CosmoNim should work out of the box on many linux distros (and does indeed work on Ubuntu)
However, CosmoNim fails to make a functioning executable on Solus (the executable segfaults when run) before doing the objcopy to make the full universal executable.
But! Cosmopolitan (directly using GCC) HelloWorld does work on Solus
So Nim is either missing some compile or link flags for GCC or it's doing something it shouldn't for this process
How can I make progress on figuring this out?
Upon using GDB, it reports the main() function for the segfault:
$ gdb hello.elf ...
Program received signal SIGSEGV, Segmentation fault.
0x0000000000413005 in NimMain ()
121 N_CDECL(void, NimMain)(void) {
This is starting at that line 121 in the source file:
N_CDECL(void, NimMain)(void) {
void (*volatile inner)(void);
PreMain();
inner = NimMainInner;
initStackBottomWith((void *)&inner);
(*inner)();
}
int main(int argc, char** args, char** env) {
cmdLine = args;
cmdCount = argc;
gEnv = env;
NimMain();
return nim_program_result;
}
$ (gdb) info functions
121: void NimMain(void);
117: void NimMainInner(void);
137: void NimMainModule(void);
108: void PreMain(void);
102: void PreMainInner(void);
129: int main(int, char **, char **);
Any GDB/compiler utils wizards out there know how to introspect this?

Related

Using LD_PRELOAD on Fedora 25 causes Segmentation Fault

I have found a strange behavior while I was trying to use a library that I wrote a long time ago. The main problem is, when the program is executed on Fedora 25 and linked to my library by using LD_PRELOAD, the system raises a Segmentation Fault. I've made a small sample of my old library to easily understand the problem.
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
extern void *__libc_malloc(size_t size);
void *malloc(size_t size)
{
void *ptr = __libc_malloc(size);
fprintf(stdout, "Malloc(%d)->(%p)\n", (int) size, ptr);
return ptr;
}
This code was compiled by using these parameters:
gcc -c -fPIC -O3 -Wall -o libtest.o libtest.c
gcc -shared -o libtest.so libtest.o
The program was executed as follows:
LD_PRELOAD=./libtest.so ./progtest
I found out that the "fprintf" line was causing the Segfault problem. So I've changed the "stdout" file descriptor to "stderr", and the problem was gone.
Then I tested the same code using the "stdout" file descriptor as output for "fprintf" on another machine running CentOS 7, and it worked fine in both cases using "stdout" and "stderr".
By observing these results, I wonder what I am missing and why this is happening.
GLibc and GCC versions installed on Fedora 25:
GNU ld version 2.26.1-1.fc25
gcc (GCC) 6.3.1 20161221 (Red Hat 6.3.1-1)
GLibc and GCC versions installed on CentOS 7:
GNU ld version 2.25.1-22.base.el7
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-11)
fprintf itself may need to use malloc under some circumstances. One possible reason is that stderr is unbuffered while stdout is line buffered. fprintf(stdout) might have a buffer already, or it may try to allocate one, ending up calling your malloc, which calls into fprintf again, but it is not re-entrant on the same FILE*.
You can prevent re-entrancy with a flag, such as (C11):
#include <stdbool.h>
#include <threads.h>
thread_local bool inside_malloc = false;
void *malloc(size_t size) {
void *ptr = __libc_malloc(size);
if (!inside_malloc) {
inside_malloc = true;
fprintf(stdout, "Malloc(%zd)->(%p)\n", size, ptr);
inside_malloc = false;
}
return ptr;
}

Symbols defined with defsym give incorrect address on Ubuntu 16.10

If I define a symbol address when linking a program on Ubuntu 16.10, this doesn't seem to produce the correct address when running the program. For example taking the following program
#include <stdio.h>
extern int mem_;
int main()
{
printf("%p\n", &mem_);
}
and compiling with
gcc example.c -o example -Xlinker --defsym=mem_=0x80
then running the program prints 0x80 on older Ubuntu systems, but a random number on Ubuntu 16.10. The 0x80 symbol seems to go into the executable, as shown by the nm program, however.
Any ideas what's causing this? I'm suspecting a security feature.
Under the GCC section of the ChangeLog (found here: https://wiki.ubuntu.com/YakketyYak/ReleaseNotes)
"We have modified GCC to by-default compile programs with position independent executable support, on the amd64 and ppc64el architectures, to improve the security benefits provided by Address Space Layout Randomization."
To disable this option, simply add -no-pie to GCC's flags.

Shared Object not loading, gives segmentation fault on dlopen

I have a lot of code that was written on 32 bit machine. Now I've upgraded to 64 bit, and it won't load shared objects. The shared object is compiled for 32 bit (using -m32 flag for DMD), and so is the host application.
This is the shared library:
module lib;
export extern(C) int abcd(){
return 4;
}
it is compiled using dmd -shared -m32 lib.d, and the output is lib.so
And this is the code for the loader:
module loader;
import std.stdio;
import core.sys.posix.dlfcn;
alias func = extern(C) int function();
void main(string[] args){
writeln("reached 0, press enter");readln;
void* so = dlopen("/home/nafees/Desktop/temp/lib.so",RTLD_LAZY);
writeln("reached 1, press enter");readln;
func f = cast(func)dlsym(so,"abcd");
writeln((*f)());
}
This one is compiled using dmd -m32 loader.d. It compiles fine, but when I run it, it runs fine till the dlopen, then causes a segmentation fault(core dumped). This used to work fine on 32 bit.
What is wrong in this code, why won't it work?
P.S: I don't want to compile it for 64 bit, so if a solution requires removing -m32, I need another one.
EDIT: I have a program compiled (also written in D), that loads a shared object (which is also written in D), using dlopen. That program would run fine in 32 bit, but not on my 64 bit machine.
EDIT2: I now tried compiling the loader without -m32, it now dlerror is saying this: /home/nafees/Desktop/temp/lib.so: wrong ELF class: ELFCLASS32
Instead of dlopen try to use loadLibrary.
UPDATE:
Use -fPIC flags for compile lib.d:
dmd -m32 -fPIC -shared lib.d

How to build and run a Linux kernel module on QEMU?

My teacher gives me a linux kernel vmlinuz-3.17.2 and a rootfs.ext2 which can be loaded to qemu. And he asks me to build a simplest kernel module which prints a hello world as homework.
Firstly, I download the kernel source and run make oldconfig
Secondly, I make the config to be PREEMPT and without modversions
(according to uname -a of vmlinuz running in qemu) , then make prepare
Thirdly, I compile the kernel mod and copy hello.ko in rootfs.ext2
Finally, In qemu, I run insmod hello.ko which exit without any prompt
and echo $? returns 0.
However, I can't see anything in dmesg or /var/log/messages
Is there anything wrong? How can I do with this?
There is also nothing to be printed when I run rmmod hello.ko successfully.
My log level is 7 4 1 7
I have make my hello.c as follows:
#include <linux/init.h>
#include <linux/module.h>
static int __init hello_init(void)
{
pr_info("Hello World");
return -1;
// I changed this to -1 deliberately, Because It seems that the code is not executed.
}
static void __exit hello_exit(void)
{
printk(KERN_ERR "Goodbye, cruel world\n");
}
MODULE_LICENSE("GPL");
module_init(hello_init);
module_exit(hello_exit);
Buildroot
Buildroot is the easiest way to do it:
minimal out-of-tree example: How to add a Linux kernel driver module as a Buildroot package?
minimal in-tree example: https://github.com/cirosantilli/buildroot/tree/kernel-module-2016.05
how to debug the module with GDB: How to debug Linux kernel modules with QEMU?
Tested on Ubuntu 16.04.

Segmentation fault while running Qt Helloworld on embedded system

I cross-compiled a Helloworld executable for ARM. It worked well on my friend's development board, but failed with a " segmentation fault " on my board. The two boards are slightly different in both hardware and software.
My question is, how can I debug in my board? Is it relatively easy to debug such a simple program? Does it indicate that there's nothing wrong with the executable and the problem most probably lies in the filesystem of my board?
Below is the code:
#include <QApplication>
#include <QPushButton>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QPushButton hello("Hello world");
hello.resize(100, 30);
hello.show();
return app.exec();
}
And the executable is generated by the following commands:
qmake -project
qmake
make
most probably gdb is ported to be run on ARM target but in case lack of that or for easy debugging, you should use gdb remote debugging.
http://sourceware.org/gdb/onlinedocs/gdb/Remote-Debugging.html#Remote-Debugging
Gdbserver is the application should be run on target. the following is demonstration howto use it. (copied from wikipedia)
Target settings:
remote$ gdbserver :2345 hello_world
Process hello_world created; pid = 2509
Listening on port 2345
Host settings:
local$ gdb -q hello_world
Reading symbols from /home/user/hello_world...done.
(gdb) target remote 192.168.0.11:2345
Remote debugging using 192.168.0.11:2345
0x002f3850 in ?? () from /lib/ld-linux.so.2
(gdb) continue
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0x08048414 in main () at hello_world.c:10
10 printf("x[%d] = %g\n", i, x[i]);
(gdb)
So you mentioned after LD_LIBRARY_PATH your issue was resolved. And before setting the LD_LIBRARY_PATH if your application gives error can not find libQt then it means you do not have Qt, but your application is giving this Seg Fault that mean you have library but not the right one so we can say you have multiple installations of Qt on your filesystem.
The one to which you have pointed now is correctly compiled for your current hardware but the other one is not compiled for your hardware causing the Segfault and this installation is in your library search path.
One possible reason of this seg fault can be determined from below.
Following are some CFLAGS which if not set correctly for any particular hardware, the compiled application / library causes Seg faults at run time.
-march
-mtune
-mfpu
So if your binary / library is compiled with say -march=armv5a and you are running it on ARM9 then it will crash like this.
Also note that not all application uses these flags, usually these flags are optimization flags and are used by base system libraries (i.e Qt, Glib, bison, Gtk etc....).
Even if you write a simple C based hello world application and your glibc is not compiled for your hardware you will get the Seg fault.
Answer from Author:
What caused this "segmentation fault" is exactly the software difference of the board. Specifically, the environmenat variable LD_LIBRARY_PATH was predefined in the failed board. And I added my path by the command
export LD_LIBRARY_PATH=$LD_LIBRARAY_PATH:/my/qt/path
Thus the predefined paths caused the problem ( still don't know in what way ).
If I change the command to
export LD_LIBRARY_PATH=/my/qt/path
the executable works.
As a general rule you shouldn't create objects derived from QObject on the stack as the QMetaObject system manages the life-time of objects with a parent-child relationship, and will therefore risk free()ing memory on the stack.

Resources